summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rwxr-xr-xFunnyQuestion.conf.php.sh25
-rw-r--r--extensions/ArchInterWiki.sql109
-rw-r--r--extensions/FluxBBAuthPlugin.php153
-rw-r--r--extensions/TimedMediaHandler/.gitignore6
-rw-r--r--extensions/TimedMediaHandler/.gitreview5
-rw-r--r--extensions/TimedMediaHandler/.jscsrc3
-rw-r--r--extensions/TimedMediaHandler/.jshintignore1
-rw-r--r--extensions/TimedMediaHandler/.jshintrc44
-rw-r--r--extensions/TimedMediaHandler/ApiQueryVideoInfo.php268
-rw-r--r--extensions/TimedMediaHandler/ApiTranscodeReset.php184
-rw-r--r--extensions/TimedMediaHandler/ApiTranscodeStatus.php79
-rw-r--r--extensions/TimedMediaHandler/COPYING342
-rw-r--r--extensions/TimedMediaHandler/Gruntfile.js34
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.config.php194
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.loader.js69
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.php103
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/LightDoodleskin.swfbin0 -> 190545 bytes
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/README20
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/config.xml9
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/expressInstall.swfbin0 -> 727 bytes
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/kdp3.3.5.27.swfbin0 -> 272405 bytes
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/kdp3.swfbin0 -> 256262 bytes
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/skin.swfbin0 -> 67435 bytes
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING21
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-ogg.txt28
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-opus.txt44
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-theora.txt28
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-vorbis.txt28
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/dynamicaudio.swfbin0 -> 1865 bytes
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-decoder-audio-opus.js24
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-decoder-audio-vorbis.js23
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-decoder-video-theora.js22
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-demuxer-ogg.js23
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-support.js201
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-version.js1
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-worker-audio.js317
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-worker-video.js317
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv.js3966
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/readme.md237
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/af.json23
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/aln.json34
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ar.json59
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/arc.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ast.json89
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/az.json10
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ba.json16
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/be-tarask.json86
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bg.json12
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bho.json13
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bn.json74
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/br.json76
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bs.json12
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ca.json46
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ce.json15
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/cs.json68
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/cu.json9
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/de.json98
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/diq.json70
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/dsb.json83
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/el.json77
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/en-gb.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/en.json95
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/eo.json27
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/es.json99
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/et.json48
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/eu.json17
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fa.json87
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fi.json41
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fr.json97
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/frp.json76
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fy.json9
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ga.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/gl.json96
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/grc.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/gsw.json80
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/he.json83
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/hsb.json83
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/hu.json75
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ia.json79
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/id.json76
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ilo.json16
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/is.json64
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/it.json92
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ja.json84
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ka.json73
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ko.json83
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ksh.json84
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ku-latn.json10
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ky.json9
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/lb.json55
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/lt.json90
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/lv.json60
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/mk.json95
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ml.json96
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ms.json82
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/mt.json23
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nb.json92
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nds-nl.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nl.json85
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nn.json84
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/oc.json50
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pam.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pdc.json9
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pl.json81
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pms.json80
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ps.json21
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pt-br.json86
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pt.json101
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/qqq.json50
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/qu.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ro.json83
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/roa-tara.json33
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ru.json100
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/rue.json9
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/si.json78
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sk.json6
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sr-ec.json78
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sr-el.json77
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sv.json96
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ta.json40
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/te.json17
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tet.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tl.json83
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tr.json85
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tzm.json11
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/uk.json92
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ur.json12
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/vec.json38
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/vep.json12
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/vi.json77
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/yi.json10
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/zh-hans.json102
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/zh-hant.json86
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/blackvideo.mp4bin0 -> 4575 bytes
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayer.js2760
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerGeneric.js36
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerIEWebMPrompt.css18
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerIEWebMPrompt.js46
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerImageOverlay.js307
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerKplayer.js485
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerNative.js1088
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerOgvJs.js222
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerVLCApp.js101
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerVlc.js358
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedTypes.js360
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaElement.js491
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaPlayer.js85
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaPlayers.js195
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaSource.js490
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.processEmbedPlayers.js353
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/EmbedPlayer.css166
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/PlayerSkinKskin.css484
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/images/kaltura_open_source_video_platform.gifbin0 -> 3368 bytes
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/images/kaltura_open_source_video_platform.pngbin0 -> 302 bytes
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/images/ksprite.pngbin0 -> 13520 bytes
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/mw.PlayerSkinKskin.js394
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mvpcf/PlayerSkinMvpcf.css194
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mvpcf/images/player_big_play_button.pngbin0 -> 2935 bytes
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mvpcf/mw.PlayerSkinMvpcf.js7
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mw.PlayerControlBuilder.js2721
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Audio.html16
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_DynamicEmbed.html24
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_IncludeJQuery.html27
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Native_Bindings.html129
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Seek.html35
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_ServerSeek.html35
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_ServerSideSeek.html14
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Sources.html24
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Themable.html71
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.config.php31
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.loader.js52
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.php21
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/af.json10
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ar.json14
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ast.json26
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/be-tarask.json28
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bg.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bn.json15
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/br.json26
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bs.json10
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ca.json9
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ce.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/cs.json16
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/cy.json26
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/de-formal.json7
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/de.json28
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/diq.json13
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/dsb.json27
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/el.json24
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/en.json25
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/eo.json7
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/es.json30
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/et.json18
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/eu.json10
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fa.json30
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fi.json16
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fr.json29
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/frp.json26
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fy.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/gl.json26
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/gsw.json27
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/he.json28
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/hsb.json26
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/hu.json23
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ia.json26
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/id.json27
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/it.json29
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ja.json29
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ka.json24
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ko.json26
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ksh.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lb.json23
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lt.json9
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lv.json9
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/mk.json26
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ml.json26
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ms.json26
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nb.json25
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nl.json26
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nn.json14
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pdc.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pfl.json7
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pl.json29
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pms.json27
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ps.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pt-br.json30
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pt.json30
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/qqq.json19
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ro.json27
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/roa-tara.json14
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ru.json29
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/rue.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/si.json25
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sl.json8
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/so.json7
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sr-ec.json15
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sr-el.json14
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sv.json27
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ta.json16
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/te.json9
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/tl.json27
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/tr.json11
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/uk.json27
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ur.json9
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/vi.json18
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/wa.json15
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/yi.json9
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/zh-hans.json30
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/zh-hant.json29
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.TextSource.js504
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.TimedText.js1313
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.style.TimedText.css18
-rw-r--r--extensions/TimedMediaHandler/README127
-rw-r--r--extensions/TimedMediaHandler/SpecialOrphanedTimedText.php258
-rw-r--r--extensions/TimedMediaHandler/SpecialTimedMediaHandler.php235
-rw-r--r--extensions/TimedMediaHandler/TimedMediaHandler.hooks.php485
-rw-r--r--extensions/TimedMediaHandler/TimedMediaHandler.i18n.alias.php76
-rw-r--r--extensions/TimedMediaHandler/TimedMediaHandler.i18n.magic.php86
-rw-r--r--extensions/TimedMediaHandler/TimedMediaHandler.php306
-rw-r--r--extensions/TimedMediaHandler/TimedMediaHandler.sql19
-rw-r--r--extensions/TimedMediaHandler/TimedMediaHandler_body.php483
-rw-r--r--extensions/TimedMediaHandler/TimedMediaIframeOutput.php152
-rw-r--r--extensions/TimedMediaHandler/TimedMediaThumbnail.php240
-rw-r--r--extensions/TimedMediaHandler/TimedMediaTransformOutput.php486
-rw-r--r--extensions/TimedMediaHandler/TimedTextPage.php187
-rw-r--r--extensions/TimedMediaHandler/TranscodeStatusTable.php236
-rw-r--r--extensions/TimedMediaHandler/WebVideoTranscode/WebVideoTranscode.php1192
-rw-r--r--extensions/TimedMediaHandler/WebVideoTranscode/WebVideoTranscodeJob.php965
-rw-r--r--extensions/TimedMediaHandler/archives/transcode_name_key.sql3
-rw-r--r--extensions/TimedMediaHandler/composer.json10
-rw-r--r--extensions/TimedMediaHandler/gitinfo.json1
-rw-r--r--extensions/TimedMediaHandler/handlers/FLACHandler/FLACHandler.php74
-rw-r--r--extensions/TimedMediaHandler/handlers/ID3Handler/ID3Handler.php107
-rw-r--r--extensions/TimedMediaHandler/handlers/Mp4Handler/Mp4Handler.php139
-rw-r--r--extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg.php631
-rw-r--r--extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Bitstream.php125
-rw-r--r--extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Flac.php133
-rw-r--r--extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Media.php262
-rw-r--r--extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Opus.php126
-rw-r--r--extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Speex.php122
-rw-r--r--extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Theora.php240
-rw-r--r--extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Vorbis.php790
-rw-r--r--extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/README2
-rw-r--r--extensions/TimedMediaHandler/handlers/OggHandler/OggException.php4
-rw-r--r--extensions/TimedMediaHandler/handlers/OggHandler/OggHandler.php379
-rw-r--r--extensions/TimedMediaHandler/handlers/TextHandler/TextHandler.php305
-rw-r--r--extensions/TimedMediaHandler/handlers/WAVHandler/WAVHandler.php87
-rw-r--r--extensions/TimedMediaHandler/handlers/WebMHandler/WebMHandler.php175
-rw-r--r--extensions/TimedMediaHandler/i18n/ady-cyrl.json11
-rw-r--r--extensions/TimedMediaHandler/i18n/aeb-latn.json9
-rw-r--r--extensions/TimedMediaHandler/i18n/af.json25
-rw-r--r--extensions/TimedMediaHandler/i18n/akz.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/aln.json23
-rw-r--r--extensions/TimedMediaHandler/i18n/an.json20
-rw-r--r--extensions/TimedMediaHandler/i18n/ang.json9
-rw-r--r--extensions/TimedMediaHandler/i18n/ar.json67
-rw-r--r--extensions/TimedMediaHandler/i18n/arc.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/arq.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/arz.json24
-rw-r--r--extensions/TimedMediaHandler/i18n/as.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/ast.json122
-rw-r--r--extensions/TimedMediaHandler/i18n/av.json9
-rw-r--r--extensions/TimedMediaHandler/i18n/avk.json9
-rw-r--r--extensions/TimedMediaHandler/i18n/awa.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/az.json13
-rw-r--r--extensions/TimedMediaHandler/i18n/azb.json11
-rw-r--r--extensions/TimedMediaHandler/i18n/ba.json14
-rw-r--r--extensions/TimedMediaHandler/i18n/bcc.json24
-rw-r--r--extensions/TimedMediaHandler/i18n/bcl.json90
-rw-r--r--extensions/TimedMediaHandler/i18n/be-tarask.json71
-rw-r--r--extensions/TimedMediaHandler/i18n/be.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/bg.json24
-rw-r--r--extensions/TimedMediaHandler/i18n/bgn.json11
-rw-r--r--extensions/TimedMediaHandler/i18n/bho.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/bn.json48
-rw-r--r--extensions/TimedMediaHandler/i18n/br.json51
-rw-r--r--extensions/TimedMediaHandler/i18n/bs.json31
-rw-r--r--extensions/TimedMediaHandler/i18n/ca.json44
-rw-r--r--extensions/TimedMediaHandler/i18n/ce.json85
-rw-r--r--extensions/TimedMediaHandler/i18n/ckb.json14
-rw-r--r--extensions/TimedMediaHandler/i18n/cs.json75
-rw-r--r--extensions/TimedMediaHandler/i18n/cu.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/cv.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/cy.json50
-rw-r--r--extensions/TimedMediaHandler/i18n/da.json100
-rw-r--r--extensions/TimedMediaHandler/i18n/de-formal.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/de.json130
-rw-r--r--extensions/TimedMediaHandler/i18n/din.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/diq.json41
-rw-r--r--extensions/TimedMediaHandler/i18n/dsb.json30
-rw-r--r--extensions/TimedMediaHandler/i18n/dty.json12
-rw-r--r--extensions/TimedMediaHandler/i18n/ee.json9
-rw-r--r--extensions/TimedMediaHandler/i18n/el.json28
-rw-r--r--extensions/TimedMediaHandler/i18n/en-gb.json12
-rw-r--r--extensions/TimedMediaHandler/i18n/en.json154
-rw-r--r--extensions/TimedMediaHandler/i18n/eo.json26
-rw-r--r--extensions/TimedMediaHandler/i18n/es.json117
-rw-r--r--extensions/TimedMediaHandler/i18n/et.json122
-rw-r--r--extensions/TimedMediaHandler/i18n/eu.json29
-rw-r--r--extensions/TimedMediaHandler/i18n/fa.json123
-rw-r--r--extensions/TimedMediaHandler/i18n/fi.json78
-rw-r--r--extensions/TimedMediaHandler/i18n/fo.json12
-rw-r--r--extensions/TimedMediaHandler/i18n/fr.json150
-rw-r--r--extensions/TimedMediaHandler/i18n/frp.json38
-rw-r--r--extensions/TimedMediaHandler/i18n/frr.json11
-rw-r--r--extensions/TimedMediaHandler/i18n/fur.json23
-rw-r--r--extensions/TimedMediaHandler/i18n/fy.json16
-rw-r--r--extensions/TimedMediaHandler/i18n/ga.json13
-rw-r--r--extensions/TimedMediaHandler/i18n/gl.json125
-rw-r--r--extensions/TimedMediaHandler/i18n/gom-deva.json12
-rw-r--r--extensions/TimedMediaHandler/i18n/gom-latn.json11
-rw-r--r--extensions/TimedMediaHandler/i18n/grc.json13
-rw-r--r--extensions/TimedMediaHandler/i18n/gsw.json62
-rw-r--r--extensions/TimedMediaHandler/i18n/gu.json23
-rw-r--r--extensions/TimedMediaHandler/i18n/gv.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/he.json125
-rw-r--r--extensions/TimedMediaHandler/i18n/hi.json39
-rw-r--r--extensions/TimedMediaHandler/i18n/hr.json31
-rw-r--r--extensions/TimedMediaHandler/i18n/hrx.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/hsb.json83
-rw-r--r--extensions/TimedMediaHandler/i18n/ht.json9
-rw-r--r--extensions/TimedMediaHandler/i18n/hu.json37
-rw-r--r--extensions/TimedMediaHandler/i18n/hy.json11
-rw-r--r--extensions/TimedMediaHandler/i18n/ia.json92
-rw-r--r--extensions/TimedMediaHandler/i18n/id.json97
-rw-r--r--extensions/TimedMediaHandler/i18n/ilo.json89
-rw-r--r--extensions/TimedMediaHandler/i18n/io.json11
-rw-r--r--extensions/TimedMediaHandler/i18n/is.json60
-rw-r--r--extensions/TimedMediaHandler/i18n/it.json108
-rw-r--r--extensions/TimedMediaHandler/i18n/ja.json91
-rw-r--r--extensions/TimedMediaHandler/i18n/jut.json21
-rw-r--r--extensions/TimedMediaHandler/i18n/jv.json65
-rw-r--r--extensions/TimedMediaHandler/i18n/ka.json89
-rw-r--r--extensions/TimedMediaHandler/i18n/khw.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/kk-arab.json15
-rw-r--r--extensions/TimedMediaHandler/i18n/kk-cyrl.json56
-rw-r--r--extensions/TimedMediaHandler/i18n/kk-latn.json15
-rw-r--r--extensions/TimedMediaHandler/i18n/km.json24
-rw-r--r--extensions/TimedMediaHandler/i18n/kn.json17
-rw-r--r--extensions/TimedMediaHandler/i18n/ko.json104
-rw-r--r--extensions/TimedMediaHandler/i18n/krc.json11
-rw-r--r--extensions/TimedMediaHandler/i18n/krj.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/ksh.json81
-rw-r--r--extensions/TimedMediaHandler/i18n/ku-latn.json14
-rw-r--r--extensions/TimedMediaHandler/i18n/ky.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/la.json9
-rw-r--r--extensions/TimedMediaHandler/i18n/lad.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/lb.json73
-rw-r--r--extensions/TimedMediaHandler/i18n/lfn.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/li.json21
-rw-r--r--extensions/TimedMediaHandler/i18n/lrc.json44
-rw-r--r--extensions/TimedMediaHandler/i18n/lt.json123
-rw-r--r--extensions/TimedMediaHandler/i18n/luz.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/lv.json22
-rw-r--r--extensions/TimedMediaHandler/i18n/mai.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/mg.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/min.json30
-rw-r--r--extensions/TimedMediaHandler/i18n/mk.json144
-rw-r--r--extensions/TimedMediaHandler/i18n/ml.json124
-rw-r--r--extensions/TimedMediaHandler/i18n/mr.json28
-rw-r--r--extensions/TimedMediaHandler/i18n/ms.json97
-rw-r--r--extensions/TimedMediaHandler/i18n/mt.json11
-rw-r--r--extensions/TimedMediaHandler/i18n/myv.json13
-rw-r--r--extensions/TimedMediaHandler/i18n/mzn.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/nah.json12
-rw-r--r--extensions/TimedMediaHandler/i18n/nap.json122
-rw-r--r--extensions/TimedMediaHandler/i18n/nb.json105
-rw-r--r--extensions/TimedMediaHandler/i18n/nds-nl.json24
-rw-r--r--extensions/TimedMediaHandler/i18n/nds.json20
-rw-r--r--extensions/TimedMediaHandler/i18n/ne.json25
-rw-r--r--extensions/TimedMediaHandler/i18n/nl.json108
-rw-r--r--extensions/TimedMediaHandler/i18n/nn.json41
-rw-r--r--extensions/TimedMediaHandler/i18n/oc.json31
-rw-r--r--extensions/TimedMediaHandler/i18n/olo.json18
-rw-r--r--extensions/TimedMediaHandler/i18n/or.json85
-rw-r--r--extensions/TimedMediaHandler/i18n/os.json9
-rw-r--r--extensions/TimedMediaHandler/i18n/pa.json13
-rw-r--r--extensions/TimedMediaHandler/i18n/pdc.json9
-rw-r--r--extensions/TimedMediaHandler/i18n/pfl.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/pl.json101
-rw-r--r--extensions/TimedMediaHandler/i18n/pms.json96
-rw-r--r--extensions/TimedMediaHandler/i18n/pnb.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/ps.json29
-rw-r--r--extensions/TimedMediaHandler/i18n/pt-br.json40
-rw-r--r--extensions/TimedMediaHandler/i18n/pt.json102
-rw-r--r--extensions/TimedMediaHandler/i18n/qqq.json172
-rw-r--r--extensions/TimedMediaHandler/i18n/qu.json14
-rw-r--r--extensions/TimedMediaHandler/i18n/ro.json93
-rw-r--r--extensions/TimedMediaHandler/i18n/roa-tara.json91
-rw-r--r--extensions/TimedMediaHandler/i18n/ru.json111
-rw-r--r--extensions/TimedMediaHandler/i18n/rue.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/sa.json19
-rw-r--r--extensions/TimedMediaHandler/i18n/sah.json23
-rw-r--r--extensions/TimedMediaHandler/i18n/scn.json11
-rw-r--r--extensions/TimedMediaHandler/i18n/sco.json16
-rw-r--r--extensions/TimedMediaHandler/i18n/sdh.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/sgs.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/shn.json9
-rw-r--r--extensions/TimedMediaHandler/i18n/shy-latn.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/si.json85
-rw-r--r--extensions/TimedMediaHandler/i18n/sk.json25
-rw-r--r--extensions/TimedMediaHandler/i18n/sl.json96
-rw-r--r--extensions/TimedMediaHandler/i18n/sq.json20
-rw-r--r--extensions/TimedMediaHandler/i18n/sr-ec.json55
-rw-r--r--extensions/TimedMediaHandler/i18n/sr-el.json53
-rw-r--r--extensions/TimedMediaHandler/i18n/stq.json20
-rw-r--r--extensions/TimedMediaHandler/i18n/su.json19
-rw-r--r--extensions/TimedMediaHandler/i18n/sv.json125
-rw-r--r--extensions/TimedMediaHandler/i18n/sw.json14
-rw-r--r--extensions/TimedMediaHandler/i18n/szl.json9
-rw-r--r--extensions/TimedMediaHandler/i18n/ta.json32
-rw-r--r--extensions/TimedMediaHandler/i18n/tcy.json9
-rw-r--r--extensions/TimedMediaHandler/i18n/te.json37
-rw-r--r--extensions/TimedMediaHandler/i18n/tg-cyrl.json20
-rw-r--r--extensions/TimedMediaHandler/i18n/tg-latn.json20
-rw-r--r--extensions/TimedMediaHandler/i18n/tk.json20
-rw-r--r--extensions/TimedMediaHandler/i18n/tl.json84
-rw-r--r--extensions/TimedMediaHandler/i18n/tly.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/tr.json80
-rw-r--r--extensions/TimedMediaHandler/i18n/ts.json9
-rw-r--r--extensions/TimedMediaHandler/i18n/tt-cyrl.json17
-rw-r--r--extensions/TimedMediaHandler/i18n/tzm.json8
-rw-r--r--extensions/TimedMediaHandler/i18n/ug-arab.json13
-rw-r--r--extensions/TimedMediaHandler/i18n/uk.json134
-rw-r--r--extensions/TimedMediaHandler/i18n/ur.json21
-rw-r--r--extensions/TimedMediaHandler/i18n/vec.json85
-rw-r--r--extensions/TimedMediaHandler/i18n/vep.json11
-rw-r--r--extensions/TimedMediaHandler/i18n/vi.json130
-rw-r--r--extensions/TimedMediaHandler/i18n/vo.json14
-rw-r--r--extensions/TimedMediaHandler/i18n/vro.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/wa.json4
-rw-r--r--extensions/TimedMediaHandler/i18n/war.json9
-rw-r--r--extensions/TimedMediaHandler/i18n/wuu.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/xmf.json10
-rw-r--r--extensions/TimedMediaHandler/i18n/yi.json15
-rw-r--r--extensions/TimedMediaHandler/i18n/yue.json24
-rw-r--r--extensions/TimedMediaHandler/i18n/zh-hans.json137
-rw-r--r--extensions/TimedMediaHandler/i18n/zh-hant.json119
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/getid3.lib.php1346
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/getid3.php1776
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/license.txt340
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/module.audio-video.matroska.php1771
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/module.audio-video.mpeg.php296
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/module.audio-video.quicktime.php2192
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/module.audio-video.riff.php2435
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/module.audio.ac3.php473
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/module.audio.dts.php291
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/module.audio.flac.php442
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/module.audio.mp3.php2009
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/module.audio.ogg.php671
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/module.tag.id3v1.php359
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/module.tag.id3v2.php3414
-rw-r--r--extensions/TimedMediaHandler/libs/getid3/readme.txt591
-rw-r--r--extensions/TimedMediaHandler/maintenance/cleanupTranscodes.php46
-rw-r--r--extensions/TimedMediaHandler/maintenance/moveTranscoded.php56
-rw-r--r--extensions/TimedMediaHandler/maintenance/resetTranscodes.php41
-rw-r--r--extensions/TimedMediaHandler/maintenance/retryTranscodes.php55
-rw-r--r--extensions/TimedMediaHandler/mwEmbedLoader.php24
-rw-r--r--extensions/TimedMediaHandler/package.json14
-rw-r--r--extensions/TimedMediaHandler/resources/PopUpThumbVideo.css29
-rw-r--r--extensions/TimedMediaHandler/resources/download_sprite.pngbin0 -> 806 bytes
-rw-r--r--extensions/TimedMediaHandler/resources/embedPlayerIframe.css7
-rw-r--r--extensions/TimedMediaHandler/resources/ext.tmh.OgvJsSupport.js67
-rw-r--r--extensions/TimedMediaHandler/resources/ext.tmh.TimedTextSelector.js8
-rw-r--r--extensions/TimedMediaHandler/resources/ext.tmh.transcodetable.js90
-rw-r--r--extensions/TimedMediaHandler/resources/mw.MediaWikiPlayer.loader.js8
-rw-r--r--extensions/TimedMediaHandler/resources/mw.MediaWikiPlayerSupport.js380
-rw-r--r--extensions/TimedMediaHandler/resources/mw.PopUpThumbVideo.js44
-rw-r--r--extensions/TimedMediaHandler/resources/mw.TMHGalleryHook.js46
-rw-r--r--extensions/TimedMediaHandler/resources/player_big_play_button.pngbin0 -> 987 bytes
-rw-r--r--extensions/TimedMediaHandler/resources/player_big_play_button_hover.pngbin0 -> 1022 bytes
-rw-r--r--extensions/TimedMediaHandler/resources/transcodeTable.css14
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/ApiTestCaseVideoUpload.php130
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/README11
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/TestApiUploadVideo.php34
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/TestOggHandler.php67
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/TestTimeParsing.php42
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/TestTimedMediaHandler.php47
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/TestTimedMediaTransformOutput.php142
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/TestVideoThumbnail.php80
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/TestVideoTranscode.php121
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/TestWebMHandler.php52
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/media/README38
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/media/VP9-tractor.webmbin0 -> 179277 bytes
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/media/bear-vp9-opus.webmbin0 -> 101414 bytes
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/media/broken-file.oggbin0 -> 11424 bytes
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/media/doubleTag.ogabin0 -> 11423 bytes
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/media/shuttle10seconds.1080x608.webmbin0 -> 699018 bytes
-rw-r--r--extensions/TimedMediaHandler/tests/phpunit/media/test5seconds.electricsheep.300x400.ogvbin0 -> 299761 bytes
-rw-r--r--extensions/TimedMediaHandler/version5
-rw-r--r--robots.txt8
-rw-r--r--skins/ArchLinux/ArchLinuxTemplate.php31
-rw-r--r--skins/ArchLinux/archlogo.pngbin3254 -> 5282 bytes
-rw-r--r--skins/ArchLinux/archnavbar.css9
-rw-r--r--skins/ArchLinux/favicon.icobin501 -> 1150 bytes
-rw-r--r--skins/ArchLinux/skin.json4
537 files changed, 64465 insertions, 289 deletions
diff --git a/.gitignore b/.gitignore
index cd8c3aed..e5012ef6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,3 +33,7 @@ images/*.*
images/cache
cache/html/*
cache/*.lesscache
+
+.error.log
+/FunnyQuestion.conf.php
+/tmp
diff --git a/FunnyQuestion.conf.php.sh b/FunnyQuestion.conf.php.sh
new file mode 100755
index 00000000..1ca39d1a
--- /dev/null
+++ b/FunnyQuestion.conf.php.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+
+IP=$(realpath "$(dirname "$0")")
+
+cmd="date -u +%V\`uname\`|sha256sum|sed 's/\W//g'"
+answer="$(eval "$cmd")"
+
+declare -A prompts
+prompts[en]='What is the output of the command <tt>%s</tt>?'
+
+{
+ echo '<?php'
+ echo -n '$wgFunnyQuestions = array('
+
+ nl='\n'
+ for lang in "${!prompts[@]}"; do
+ printf "${nl}\t\"${lang}\" => array(\"${prompts[$lang]}\" => \"%s\")" "$cmd" "$answer"
+ nl=',\n'
+ done
+
+ echo
+ echo ');'
+} > "$IP/FunnyQuestion.conf.php"
+
+touch "$IP/extensions/FunnyQuestion/FunnyQuestion.i18n.php"
diff --git a/extensions/ArchInterWiki.sql b/extensions/ArchInterWiki.sql
deleted file mode 100644
index 908e5bbe..00000000
--- a/extensions/ArchInterWiki.sql
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * This script is intended to populate the interwiki table with entries useful
- * for ArchWiki.
- *
- * Before deleting interwiki links, remove them from the articles.
- *
- * In order to find all the interlanguage links of a particular language, you
- * need to do an API search, e.g.
- * https://wiki.archlinux.org/api.php?action=query&list=langbacklinks&lbllimit=max&lblprop=lltitle&lbllang=de
- * This example uses German ('de'), but for the other languages it is enough to
- * change the value of 'lbllang' to the needed language tag.
- *
- * Interwiki links using a specific prefix can be found similarly, for example:
- * https://wiki.archlinux.org/api.php?action=query&list=iwbacklinks&iwbllimit=max&iwblprop=iwtitle&iwblprefix=wikipedia
- * This example uses 'wikipedia', but for other interwiki prefixes it is enough
- * to change the value of 'iwblprefix' accordingly.
- *
- * Note that API queries are always limited, so if given interwiki prefix has
- * more than 500 (or 5000 if you have the 'apihighlimits' right) backlinks, it
- * will be necessary to continue the search as described in
- * https://www.mediawiki.org/wiki/API:Query#Continuing_queries
- *
- * Also note that such queries do not find (all) interwiki redirects, if
- * present. A search like this should do the job instead:
- * https://wiki.archlinux.org/index.php?title=Special%3ASearch&profile=advanced&limit=500&offset=0&search=%22redirect%20%5B%5Bde%3A%22&fulltext=Search&ns0=1&ns1=1&ns2=1&ns3=1&ns4=1&ns5=1&ns6=1&ns7=1&ns8=1&ns9=1&ns10=1&ns11=1&ns12=1&ns13=1&ns14=1&ns15=1&redirs=1&profile=advanced
- */
-
--- Clear the table, we don't want the entries from maintenance/interwiki.sql
-DELETE FROM interwiki;
-
--- Arch's interlanguage prefixes
-INSERT INTO
- interwiki (iw_prefix, iw_url, iw_local, iw_trans)
-VALUES
- ('ar', 'https://wiki.archlinux.org/index.php/$1_(%D8%A7%D9%84%D8%B9%D8%B1%D8%A8%D9%8A%D8%A9)', 1, 0),
- ('bg', 'https://wiki.archlinux.org/index.php/$1_(%D0%91%D1%8A%D0%BB%D0%B3%D0%B0%D1%80%D1%81%D0%BA%D0%B8)', 1, 0),
- ('cs', 'https://wiki.archlinux.org/index.php/$1_(%C4%8Cesky)', 1, 0),
- ('da', 'https://wiki.archlinux.org/index.php/$1_(Dansk)', 1, 0),
- ('de', 'https://wiki.archlinux.de/title/$1', 1, 0),
- ('el', 'https://wiki.archlinux.org/index.php/$1_(%CE%95%CE%BB%CE%BB%CE%B7%CE%BD%CE%B9%CE%BA%CE%AC)', 1, 0),
- ('en', 'https://wiki.archlinux.org/index.php/$1', 1, 0),
- ('es', 'https://wiki.archlinux.org/index.php/$1_(Espa%C3%B1ol)', 1, 0),
- ('fa', 'http://wiki.archusers.ir/index.php/$1', 1, 0),
- ('fi', 'http://www.archlinux.fi/wiki/$1', 1, 0),
- ('fr', 'http://wiki.archlinux.fr/$1', 1, 0),
- ('he', 'https://wiki.archlinux.org/index.php/$1_(%D7%A2%D7%91%D7%A8%D7%99%D7%AA)', 1, 0),
- ('hr', 'https://wiki.archlinux.org/index.php/$1_(Hrvatski)', 1, 0),
- ('hu', 'https://wiki.archlinux.org/index.php/$1_(Magyar)', 1, 0),
- ('id', 'https://wiki.archlinux.org/index.php/$1_(Indonesia)', 1, 0),
- ('it', 'https://wiki.archlinux.org/index.php/$1_(Italiano)', 1, 0),
- ('ja', 'https://wiki.archlinuxjp.org/index.php/$1', 1, 0),
- ('ko', 'https://wiki.archlinux.org/index.php/$1_(%ED%95%9C%EA%B5%AD%EC%96%B4)', 1, 0),
- ('lt', 'https://wiki.archlinux.org/index.php/$1_(Lietuvi%C5%A1kai)', 1, 0),
- ('nl', 'https://wiki.archlinux.org/index.php/$1_(Nederlands)', 1, 0),
- ('pl', 'https://wiki.archlinux.org/index.php/$1_(Polski)', 1, 0),
- ('pt', 'https://wiki.archlinux.org/index.php/$1_(Portugu%C3%AAs)', 1, 0),
- ('ro', 'http://wiki.archlinux.ro/index.php/$1', 1, 0),
- ('ru', 'https://wiki.archlinux.org/index.php/$1_(%D0%A0%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9)', 1, 0),
- ('sk', 'https://wiki.archlinux.org/index.php/$1_(Slovensk%C3%BD)', 1, 0),
- ('sr', 'https://wiki.archlinux.org/index.php/$1_(%D0%A1%D1%80%D0%BF%D1%81%D0%BA%D0%B8)', 1, 0),
- ('sv', 'http://wiki.archlinux.se/index.php?title=$1', 1, 0),
- ('th', 'https://wiki.archlinux.org/index.php/$1_(%E0%B9%84%E0%B8%97%E0%B8%A2)', 1, 0),
- ('tr', 'http://archtr.org/wiki/index.php?title=$1', 1, 0),
- ('uk', 'https://wiki.archlinux.org/index.php/$1_(%D0%A3%D0%BA%D1%80%D0%B0%D1%97%D0%BD%D1%81%D1%8C%D0%BA%D0%B0)', 1, 0),
- ('zh-cn', 'https://wiki.archlinux.org/index.php/$1_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)', 1, 0),
- ('zh-tw', 'https://wiki.archlinux.org/index.php/$1_(%E6%AD%A3%E9%AB%94%E4%B8%AD%E6%96%87)', 1, 0);
-
--- Other interwiki prefixes
-INSERT INTO interwiki (iw_prefix,iw_url,iw_local,iw_api) VALUES
-('arxiv','http://www.arxiv.org/abs/$1',0,''),
-('debian','https://wiki.debian.org/$1',0,''),
-('doi','http://dx.doi.org/$1',0,''),
-('emacswiki','http://www.emacswiki.org/cgi-bin/wiki.pl?$1',0,''),
-('foldoc','http://foldoc.org/?$1',0,''),
-('freebsdman','http://www.freebsd.org/cgi/man.cgi?query=$1',0,''),
-('funtoo','http://www.funtoo.org/$1',0,'http://www.funtoo.org/api.php'),
-('gentoo','https://wiki.gentoo.org/wiki/$1',0,'https://wiki.gentoo.org/api.php'),
-('gregswiki','http://mywiki.wooledge.org/$1',0,''),
-('linuxwiki','http://linuxwiki.de/$1',0,''),
-('lqwiki','http://wiki.linuxquestions.org/wiki/$1',0,''),
-('mozillawiki','http://wiki.mozilla.org/$1',0,'https://wiki.mozilla.org/api.php'),
-('rfc','http://www.rfc-editor.org/rfc/rfc$1.txt',0,''),
-('sourceforge','http://sourceforge.net/$1',0,''),
-('wikia','http://www.wikia.com/wiki/$1',0,'')
-;
-
--- Wikimedia Foundation projects and related
--- based on this table: https://meta.wikimedia.org/wiki/Help:Interwiki_linking#Project_titles_and_shortcuts
-INSERT INTO interwiki (iw_prefix,iw_url,iw_local,iw_api) VALUES
-('wikipedia','https://en.wikipedia.org/wiki/$1',0,'https://en.wikipedia.org/w/api.php'),
-('w','https://en.wikipedia.org/wiki/$1',0,'https://en.wikipedia.org/w/api.php'),
-('wiktionary','https://en.wiktionary.org/wiki/$1',0,'https://en.wiktionary.org/w/api.php'),
-('wikt','https://en.wiktionary.org/wiki/$1',0,'https://en.wiktionary.org/w/api.php'),
-('wikinews','https://en.wikinews.org/wiki/$1',0,'https://en.wikinews.org/w/api.php'),
-('wikibooks','https://en.wikibooks.org/wiki/$1',0,'https://en.wikibooks.org/w/api.php'),
-('wikiquote','https://en.wikiquote.org/wiki/$1',0,'https://en.wikiquote.org/w/api.php'),
-('wikisource','https://wikisource.org/wiki/$1',0,'https://wikisource.org/w/api.php'),
-('wikispecies','https://species.wikimedia.org/wiki/$1',0,'https://species.wikimedia.org/w/api.php'),
-('wikiversity','https://en.wikiversity.org/wiki/$1',0,'https://en.wikiversity.org/w/api.php'),
-('wikivoyage','https://en.wikivoyage.org/wiki/$1',0,'https://en.wikivoyage.org/w/api.php'),
-('wikimedia','https://wikimediafoundation.org/wiki/$1',0,'https://wikimediafoundation.org/w/api.php'),
-('wmf','https://wikimediafoundation.org/wiki/$1',0,'https://wikimediafoundation.org/w/api.php'),
-('commons','https://commons.wikimedia.org/wiki/$1',0,'https://commons.wikimedia.org/w/api.php'),
-('metawikimedia','https://meta.wikimedia.org/wiki/$1',0,'https://meta.wikimedia.org/w/api.php'),
-('meta','https://meta.wikimedia.org/wiki/$1',0,'https://meta.wikimedia.org/w/api.php'),
-('mw','https://www.mediawiki.org/wiki/$1',0,'https://www.mediawiki.org/w/api.php'),
-('phabricator','https://phabricator.wikimedia.org/$1',0,''),
-('phab','https://phabricator.wikimedia.org/$1',0,'')
-;
diff --git a/extensions/FluxBBAuthPlugin.php b/extensions/FluxBBAuthPlugin.php
deleted file mode 100644
index 32d4b145..00000000
--- a/extensions/FluxBBAuthPlugin.php
+++ /dev/null
@@ -1,153 +0,0 @@
-<?php
-
-$wgExtensionCredits['other'][] = array(
- 'name' => 'FluxBBAuthPlugin',
- 'version' => '1.6',
- 'description' => 'Use FluxBB accounts in MediaWiki',
- 'author' => 'Pierre Schmitz',
- 'url' => 'https://pierre-schmitz.com/'
-);
-
-require_once(__DIR__.'/../includes/AuthPlugin.php');
-
-global $FluxBBDatabase;
-$FluxBBDatabase = 'fluxbb';
-
-class FluxBBAuthPlugin extends AuthPlugin {
-
- public static function isValidPassword($password) {
- $length = strlen($password);
- return $length >= 4;
- }
-
- private function getUserData($username) {
- global $FluxBBDatabase;
- $dbr = wfGetDB( DB_SLAVE );
-
- return $dbr->selectRow($FluxBBDatabase.'.users', array('username', 'email', 'realname'), array('username' => $username));
- }
-
- public function userExists( $username ) {
- global $FluxBBDatabase;
- $dbr = wfGetDB( DB_SLAVE );
-
- try {
- $result = $dbr->select($FluxBBDatabase.'.users', 'id', array('username' => $username));
- $exists = ($result->numRows() > 0 ? true : false);
- $result->free();
- } catch (DBQueryError $e) {
- $exists = false;
- }
-
- return $exists;
- }
-
- public function authenticate( $username, $password ) {
- global $FluxBBDatabase;
- $dbr = wfGetDB( DB_SLAVE );
-
- try {
- $result = $dbr->select($FluxBBDatabase.'.users', 'id', array('username' => $username, 'password' => sha1($password)));
- $authenticated = ($result->numRows() > 0 ? true : false);
- $result->free();
- } catch (DBQueryError $e) {
- $authenticated = false;
- }
-
- return $authenticated;
- }
-
- public function modifyUITemplate( &$template, &$type ) {
- $template->set( 'usedomain', false );
- }
-
- public function updateUser( &$user ) {
- return $this->initUser($user);
- }
-
- public function autoCreate() {
- return true;
- }
-
- protected function allowRealNameChange() {
- return false;
- }
-
- protected function allowEmailChange() {
- return false;
- }
-
- protected function allowNickChange() {
- return false;
- }
-
- public function allowPasswordChange() {
- return false;
- }
-
- public function allowSetLocalPassword() {
- return false;
- }
-
- public function setPassword( $user, $password ) {
- return false;
- }
-
- public function updateExternalDB( $user ) {
- return false;
- }
-
- public function updateExternalDBGroups( $user, $addgroups, $delgroups = array() ) {
- return false;
- }
-
- public function canCreateAccounts() {
- return false;
- }
-
- public function addUser( $user, $password, $email = '', $realname = '' ) {
- return false;
- }
-
- public function strict() {
- return true;
- }
-
- public function strictUserAuth( $username ) {
- return true;
- }
-
- public function initUser( &$user, $autocreate = false ) {
- try {
- $data = $this->getUserData($user->getName());
- if (!$data) {
- return false;
- }
- $user->setEmail($data->email);
- $user->confirmEmail();
- $user->setRealName($data->realname);
- $user->saveSettings();
- } catch (Exception $e) {
- return false;
- }
- return true;
- }
-
- public function getCanonicalName( $username ) {
- try {
- $data = $this->getUserData($username);
- if ($data !== false) {
- return strtoupper(substr($data->username, 0, 1)).substr($data->username, 1);
- }
- } catch (Exception $e) {
- }
- return $username;
- }
-
-}
-
-$wgAuth = new FluxBBAuthPlugin();
-$wgHiddenPrefs[] = 'realname';
-$wgHooks['isValidPassword'][] = 'FluxBBAuthPlugin::isValidPassword';
-
-?>
diff --git a/extensions/TimedMediaHandler/.gitignore b/extensions/TimedMediaHandler/.gitignore
new file mode 100644
index 00000000..0172e092
--- /dev/null
+++ b/extensions/TimedMediaHandler/.gitignore
@@ -0,0 +1,6 @@
+.svn
+*~
+*.kate-swp
+.*.swp
+.project
+node_modules/
diff --git a/extensions/TimedMediaHandler/.gitreview b/extensions/TimedMediaHandler/.gitreview
new file mode 100644
index 00000000..39e4aad6
--- /dev/null
+++ b/extensions/TimedMediaHandler/.gitreview
@@ -0,0 +1,5 @@
+[gerrit]
+host=gerrit.wikimedia.org
+port=29418
+project=mediawiki/extensions/TimedMediaHandler.git
+defaultbranch=REL1_26
diff --git a/extensions/TimedMediaHandler/.jscsrc b/extensions/TimedMediaHandler/.jscsrc
new file mode 100644
index 00000000..9d22e3f2
--- /dev/null
+++ b/extensions/TimedMediaHandler/.jscsrc
@@ -0,0 +1,3 @@
+{
+ "preset": "wikimedia"
+}
diff --git a/extensions/TimedMediaHandler/.jshintignore b/extensions/TimedMediaHandler/.jshintignore
new file mode 100644
index 00000000..0f77f29d
--- /dev/null
+++ b/extensions/TimedMediaHandler/.jshintignore
@@ -0,0 +1 @@
+MwEmbedModules
diff --git a/extensions/TimedMediaHandler/.jshintrc b/extensions/TimedMediaHandler/.jshintrc
new file mode 100644
index 00000000..ef363f81
--- /dev/null
+++ b/extensions/TimedMediaHandler/.jshintrc
@@ -0,0 +1,44 @@
+{
+ /* Common */
+
+ // Enforcing
+ "camelcase": true,
+ "curly": true,
+ "eqeqeq": true,
+ "immed": true,
+ "latedef": true,
+ "newcap": true,
+ "noarg": true,
+ "noempty": true,
+ "nonew": true,
+ "quotmark": "single",
+ "trailing": true,
+ "undef": true,
+ "unused": true,
+ // Legacy
+ "onevar": true,
+
+ /* Local */
+
+ // Enforcing
+ "bitwise": true,
+ "es3": true,
+ // Relaxing
+ "laxbreak": true,
+ "smarttabs": true,
+ "multistr": true,
+ // Environment
+ "browser": true,
+ // Legacy
+ "nomen": true,
+
+ "predef": [
+ "mediaWiki",
+ "mw",
+ "jQuery",
+ "OGVVersion",
+ "OGVSupport",
+ "OGVPlayer",
+ "OGVLoader"
+ ]
+}
diff --git a/extensions/TimedMediaHandler/ApiQueryVideoInfo.php b/extensions/TimedMediaHandler/ApiQueryVideoInfo.php
new file mode 100644
index 00000000..65239166
--- /dev/null
+++ b/extensions/TimedMediaHandler/ApiQueryVideoInfo.php
@@ -0,0 +1,268 @@
+<?php
+/**
+ * Extends imageinfo with support for videoinfo sources property.
+ *
+ * Alternatively core ApiQueryImageInfo could support being extended in some straightforward ways.
+ * see: http://www.mediawiki.org/wiki/User:Catrope/Extension_review/TimedMediaHandler#ApiQueryVideoInfo.php
+ *
+ */
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+ // Eclipse helper - will be ignored in production
+ require_once( "ApiBase.php" );
+}
+
+class ApiQueryVideoInfo extends ApiQueryImageInfo {
+
+ public function __construct( $query, $moduleName, $prefix = 'vi' ) {
+ // We allow a subclass to override the prefix, to create a related API module.
+ // Some other parts of MediaWiki construct this with a null $prefix, which used to be ignored when this only took two arguments
+ if ( is_null( $prefix ) ) {
+ $prefix = 'vi';
+ }
+ parent::__construct( $query, $moduleName, $prefix );
+ }
+
+ /**
+ * @deprecated since MediaWiki core 1.25
+ */
+ public function getDescription() {
+ return 'Extends imageinfo to include video source (derivatives) information';
+ }
+
+ static function getInfo( $file, $prop, $result, $thumbParams = null, $version = 'latest' ) {
+ $vals = parent::getInfo( $file, $prop, $result, $thumbParams );
+ if( isset( $prop['derivatives'] ) ) {
+ if ( $file->getHandler() && $file->getHandler() instanceof TimedMediaHandler ) {
+ $vals['derivatives'] = WebVideoTranscode::getSources( $file, array( 'fullurl') );
+ $result->setIndexedTagName( $vals['derivatives'], "derivative" );
+ } else {
+ // Non-TMH file, no derivatives.
+ $vals['derivatives'] = array();
+ }
+ }
+ return $vals;
+ }
+
+ public static function getPropertyNames( $filter = array() ) {
+ $prop = parent::getPropertyNames();
+ $prop[] = 'derivatives';
+ return $prop;
+ }
+
+ public static function getPropertyDescriptions( $filter = array(), $modulePrefix = '' ) {
+ $s = parent::getPropertyDescriptions( $filter, $modulePrefix );
+ $s[] = ' derivatives - Adds an array of the different format and quality versions of an audio or video file that are available.';
+ return $s;
+ }
+
+ /**
+ * @deprecated since MediaWiki core 1.25
+ */
+ public function getExamples() {
+ return array(
+ 'api.php?action=query&titles=File:Folgers.ogv&prop=videoinfo',
+ );
+ }
+
+ /**
+ * @see ApiBase::getExamplesMessages()
+ */
+ protected function getExamplesMessages() {
+ return array(
+ 'action=query&titles=File:Folgers.ogv&prop=videoinfo'
+ => 'apihelp-query+videoinfo-example-1',
+ );
+ }
+
+ /**
+ * Execute and getAllowedprops have to be copied verbatim because of static self:: references
+ *
+ * With late static binding this would be avoidable:
+ * http://php.net/manual/en/language.oop5.late-static-bindings.php
+ */
+ public function execute() {
+ $params = $this->extractRequestParams();
+
+ $prop = array_flip( $params['prop'] );
+
+ $scale = $this->getScale( $params );
+
+ $pageIds = $this->getPageSet()->getAllTitlesByNamespace();
+ if ( !empty( $pageIds[NS_FILE] ) ) {
+ $titles = array_keys( $pageIds[NS_FILE] );
+ asort( $titles ); // Ensure the order is always the same
+
+ $skip = false;
+ if ( !is_null( $params['continue'] ) ) {
+ $skip = true;
+ $cont = explode( '|', $params['continue'] );
+ if ( count( $cont ) != 2 ) {
+ $this->dieUsage( 'Invalid continue param. You should pass the original ' .
+ 'value returned by the previous query', '_badcontinue' );
+ }
+ $fromTitle = strval( $cont[0] );
+ $fromTimestamp = $cont[1];
+ // Filter out any titles before $fromTitle
+ foreach ( $titles as $key => $title ) {
+ if ( $title < $fromTitle ) {
+ unset( $titles[$key] );
+ } else {
+ break;
+ }
+ }
+ }
+
+ $result = $this->getResult();
+ $images = RepoGroup::singleton()->findFiles( $titles );
+ foreach ( $images as $img ) {
+ // Skip redirects
+ if ( $img->getOriginalTitle()->isRedirect() ) {
+ continue;
+ }
+
+ $start = $skip ? $fromTimestamp : $params['start'];
+ $pageId = $pageIds[NS_IMAGE][ $img->getOriginalTitle()->getDBkey() ];
+
+ $fit = $result->addValue(
+ array( 'query', 'pages', intval( $pageId ) ),
+ 'imagerepository', $img->getRepoName()
+ );
+ if ( !$fit ) {
+ if ( count( $pageIds[NS_IMAGE] ) == 1 ) {
+ // The user is screwed. imageinfo can't be solely
+ // responsible for exceeding the limit in this case,
+ // so set a query-continue that just returns the same
+ // thing again. When the violating queries have been
+ // out-continued, the result will get through
+ $this->setContinueEnumParameter( 'start',
+ wfTimestamp( TS_ISO_8601, $img->getTimestamp() ) );
+ } else {
+ $this->setContinueEnumParameter( 'continue',
+ $this->getContinueStr( $img ) );
+ }
+ break;
+ }
+
+ // Check if we can make the requested thumbnail, and get transform parameters.
+ $finalThumbParams = $this->mergeThumbParams( $img, $scale, $params['urlparam'] );
+
+ // Get information about the current version first
+ // Check that the current version is within the start-end boundaries
+ $gotOne = false;
+ if (
+ ( is_null( $start ) || $img->getTimestamp() <= $start ) &&
+ ( is_null( $params['end'] ) || $img->getTimestamp() >= $params['end'] )
+ ) {
+ $gotOne = true;
+
+ $fit = $this->addPageSubItem( $pageId,
+ self::getInfo( $img, $prop, $result, $finalThumbParams ) );
+ if ( !$fit ) {
+ if ( count( $pageIds[NS_IMAGE] ) == 1 ) {
+ // See the 'the user is screwed' comment above
+ $this->setContinueEnumParameter( 'start',
+ wfTimestamp( TS_ISO_8601, $img->getTimestamp() ) );
+ } else {
+ $this->setContinueEnumParameter( 'continue',
+ $this->getContinueStr( $img ) );
+ }
+ break;
+ }
+ }
+
+ // Now get the old revisions
+ // Get one more to facilitate query-continue functionality
+ $count = ( $gotOne ? 1 : 0 );
+ $oldies = $img->getHistory( $params['limit'] - $count + 1, $start, $params['end'] );
+ foreach ( $oldies as $oldie ) {
+ if ( ++$count > $params['limit'] ) {
+ // We've reached the extra one which shows that there are additional pages to be had. Stop here...
+ // Only set a query-continue if there was only one title
+ if ( count( $pageIds[NS_FILE] ) == 1 ) {
+ $this->setContinueEnumParameter( 'start',
+ wfTimestamp( TS_ISO_8601, $oldie->getTimestamp() ) );
+ }
+ break;
+ }
+ $fit = $this->addPageSubItem( $pageId,
+ self::getInfo( $oldie, $prop, $result, $finalThumbParams ) );
+ if ( !$fit ) {
+ if ( count( $pageIds[NS_IMAGE] ) == 1 ) {
+ $this->setContinueEnumParameter( 'start',
+ wfTimestamp( TS_ISO_8601, $oldie->getTimestamp() ) );
+ } else {
+ $this->setContinueEnumParameter( 'continue',
+ $this->getContinueStr( $oldie ) );
+ }
+ break;
+ }
+ }
+ if ( !$fit ) {
+ break;
+ }
+ $skip = false;
+ }
+
+ if ( defined( 'ApiResult::META_CONTENT' ) ) {
+ $pages = (array)$this->getResult()->getResultData( array( 'query', 'pages' ), array( 'Strip' => 'base' ) );
+ } else {
+ $data = $this->getResultData();
+ $pages = $data['query']['pages'];
+ }
+ foreach ( $pages as $pageid => $arr ) {
+ if ( !isset( $arr['imagerepository'] ) ) {
+ $result->addValue(
+ array( 'query', 'pages', intval( $pageid ) ),
+ 'imagerepository', ''
+ );
+ }
+ // The above can't fail because it doesn't increase the result size
+ }
+ }
+ }
+
+ public function getAllowedParams() {
+ // Get imageinfo params
+ $params = array_intersect_key(
+ parent::getAllowedParams(),
+ array_flip( array(
+ 'limit', 'start', 'end', 'urlwidth', 'urlheight', 'urlparam', 'continue'
+ ) )
+ );
+ if ( defined( 'ApiBase::PARAM_HELP_MSG' ) ) {
+ foreach ( $params as $k => $v ) {
+ if ( !isset( $params[$k][ApiBase::PARAM_HELP_MSG] ) ) {
+ $params[$k][ApiBase::PARAM_HELP_MSG] = "apihelp-query+imageinfo-param-$k";
+ }
+ }
+ }
+
+ // Add our param
+ $params = array(
+ 'prop' => array(
+ ApiBase::PARAM_ISMULTI => true,
+ ApiBase::PARAM_DFLT => 'timestamp|user',
+ ApiBase::PARAM_TYPE => self::getPropertyNames(),
+ ),
+ ) + $params;
+
+ return $params;
+ }
+
+ /**
+ * Get API self-documentation.
+ *
+ * Needed since core calls self::getPropertyDescriptions(),
+ * (and not static::getPropertyDescriptions() ) which binds
+ * to the static method in that class instead of the static
+ * method of the same name in this class.
+ * @deprecated since MediaWiki core 1.25
+ */
+ public function getParamDescription() {
+ $params = parent::getParamDescription();
+ $p = $this->getModulePrefix();
+ $params['prop'] = self::getPropertyDescriptions( array(), $p );
+ return $params;
+ }
+}
diff --git a/extensions/TimedMediaHandler/ApiTranscodeReset.php b/extensions/TimedMediaHandler/ApiTranscodeReset.php
new file mode 100644
index 00000000..597d17e1
--- /dev/null
+++ b/extensions/TimedMediaHandler/ApiTranscodeReset.php
@@ -0,0 +1,184 @@
+<?php
+if ( !defined( 'MEDIAWIKI' ) ) {
+ // Eclipse helper - will be ignored in production
+ require_once( 'ApiBase.php' );
+}
+
+/**
+ * Allows users with the 'transcode-reset' right to reset / re-run a transcode job.
+ *
+ * You can specify must specify a media asset title. You optionally can specify
+ * a transcode key, to only reset a single transcode job for a particular media asset.
+ * @ingroup API
+ */
+class ApiTranscodeReset extends ApiBase {
+ public function execute() {
+ global $wgUser, $wgEnableTranscode, $wgWaitTimeForTranscodeReset;
+ // Check if transcoding is enabled on this wiki at all:
+ if( !$wgEnableTranscode ){
+ $this->dieUsage( 'Transcode is disabled on this wiki', 'disabledtranscode' );
+ }
+
+ // Confirm the user has the transcode-reset right
+ if( !$wgUser->isAllowed( 'transcode-reset' ) ){
+ $this->dieUsage( 'You don\'t have permission to reset transcodes', 'missingpermission' );
+ }
+ $params = $this->extractRequestParams();
+
+ // Make sure we have a valid Title
+ $titleObj = Title::newFromText( $params['title'] );
+ if ( !$titleObj || $titleObj->isExternal() ) {
+ $this->dieUsageMsg( array( 'invalidtitle', $params['title'] ) );
+ }
+ // Make sure the title can be transcoded
+ if( !TimedMediaHandlerHooks::isTranscodableTitle( $titleObj ) ){
+ $this->dieUsageMsg( array( 'invalidtranscodetitle', $params['title'] ) );
+ }
+ $transcodeKey = false;
+ // Make sure its a enabled transcode key we are trying to remove:
+ // ( if you update your transcode keys the api is not how you purge the database of expired keys )
+ if( isset( $params['transcodekey'] ) ){
+ global $wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet;
+ $transcodeSet = array_merge($wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet);
+ if( !in_array( $params['transcodekey'], $transcodeSet ) ){
+ $this->dieUsage( 'Invalid or disabled transcode key: ' . htmlspecialchars( $params['transcodekey'] ) , 'badtranscodekey' );
+ } else {
+ $transcodeKey = $params['transcodekey'];
+ }
+ }
+
+ // Don't reset if less than 1 hour has passed and we have no error )
+ $file = wfFindFile( $titleObj );
+ $timeSinceLastReset = self::checkTimeSinceLastRest( $file, $transcodeKey );
+ if( $timeSinceLastReset < $wgWaitTimeForTranscodeReset){
+ $this->dieUsage( 'Not enough time has passed since the last reset of this transcode. ' .
+ TimedMediaHandler::getTimePassedMsg( $wgWaitTimeForTranscodeReset - $timeSinceLastReset ) .
+ ' until this transcode can be reset', 'notenoughtimereset');
+ }
+
+ // All good do the transcode removal:
+ WebVideoTranscode::removeTranscodes( $file, $transcodeKey );
+
+ // Oh and we wanted to reset it, right? Trigger again.
+ WebVideoTranscode::updateJobQueue( $file, $transcodeKey );
+
+ $this->getResult()->addValue(null, 'success', 'removed transcode');
+ }
+
+ /**
+ * @param $file
+ * @param $transcodeKey
+ * @return int|string
+ */
+ static public function checkTimeSinceLastRest( $file, $transcodeKey ){
+ global $wgWaitTimeForTranscodeReset;
+ $transcodeStates = WebVideoTranscode::getTranscodeState( $file );
+ if( $transcodeKey ){
+ if( ! $transcodeStates[$transcodeKey] ){
+ // transcode key not found
+ return $wgWaitTimeForTranscodeReset + 1;
+ }
+ return self::getStateResetTime( $transcodeStates[$transcodeKey] );
+ }
+ // least wait is set to reset time:
+ $leastWait = $wgWaitTimeForTranscodeReset + 1;
+ // else check for lowest reset time
+ foreach($transcodeStates as $state ){
+ $ctime = self::getStateResetTime( $state );
+ if( $ctime < $leastWait){
+ $leastWait = $ctime;
+ }
+ }
+ return $leastWait;
+ }
+
+ /**
+ * @param $state
+ * @return int|string
+ */
+ static public function getStateResetTime( $state ){
+ global $wgWaitTimeForTranscodeReset;
+ $db = wfGetDB( DB_SLAVE );
+ // if an error return waitTime +1
+ if( !is_null( $state['time_error']) ){
+ return $wgWaitTimeForTranscodeReset + 1;
+ }
+ // return wait time from most recent event
+ foreach( array( 'time_success', 'time_startwork', 'time_addjob' ) as $timeField ){
+ if( !is_null( $state[ $timeField ] )){
+ return $db->timestamp() - $db->timestamp( $state[ $timeField ] );
+ }
+ }
+ // No time info, return resetWaitTime
+ return $wgWaitTimeForTranscodeReset + 1;
+ }
+
+ public function mustBePosted() {
+ return true;
+ }
+
+ public function isWriteMode() {
+ return true;
+ }
+
+ /**
+ * @deprecated since MediaWiki core 1.25
+ */
+ protected function getDescription() {
+ return 'Users with the \'transcode-reset\' right can reset and re-run a transcode job';
+ }
+
+ protected function getAllowedParams() {
+ return array(
+ 'title' => array(
+ ApiBase::PARAM_TYPE => 'string',
+ ApiBase::PARAM_REQUIRED => true
+ ),
+ 'transcodekey' => null,
+ 'token' => null,
+ );
+ }
+
+ /**
+ * @deprecated since MediaWiki core 1.25
+ */
+ protected function getParamDescription() {
+ return array(
+ 'title' => 'The media file title',
+ 'transcodekey' => 'The transcode key you wish to reset',
+ 'token' => 'An edit token obtained via action=tokens',
+ );
+ }
+
+ public function needsToken() {
+ return 'csrf';
+ }
+
+ public function getTokenSalt() {
+ return '';
+ }
+
+ /**
+ * @deprecated since MediaWiki core 1.25
+ */
+ protected function getExamples() {
+ return array(
+ 'Reset all transcodes for Clip.webm :',
+ ' api.php?action=transcodereset&title=File:Clip.webm&token=%2B\\',
+ 'Reset the \'360_560kbs.webm\' transcode key for clip.webm. Get a list of transcode keys via a \'transcodestatus\' query',
+ ' api.php?action=transcodereset&title=File:Clip.webm&transcodekey=360_560kbs.webm&token=%2B\\',
+ );
+ }
+
+ /**
+ * @see ApiBase::getExamplesMessages()
+ */
+ protected function getExamplesMessages() {
+ return array(
+ 'action=transcodereset&title=File:Clip.webm&token=123ABC'
+ => 'apihelp-transcodereset-example-1',
+ 'action=transcodereset&title=File:Clip.webm&transcodekey=360_560kbs.webm&token=123ABC'
+ => 'apihelp-transcodereset-example-2',
+ );
+ }
+}
diff --git a/extensions/TimedMediaHandler/ApiTranscodeStatus.php b/extensions/TimedMediaHandler/ApiTranscodeStatus.php
new file mode 100644
index 00000000..38dcccc6
--- /dev/null
+++ b/extensions/TimedMediaHandler/ApiTranscodeStatus.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Allows for api queries to get detailed information about the transcode state of a particular
+ * media asset. ( basically directly returns the transcode status table )
+ *
+ * This information can be used to generate status tables similar to the one seen
+ * on the image page.
+ */
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+ // Eclipse helper - will be ignored in production
+ require_once( "ApiBase.php" );
+}
+
+class ApiTranscodeStatus extends ApiQueryBase {
+ public function execute() {
+ $pageIds = $this->getPageSet()->getAllTitlesByNamespace();
+ // Make sure we have files in the title set:
+ if ( !empty( $pageIds[NS_FILE] ) ) {
+ $titles = array_keys( $pageIds[NS_FILE] );
+ asort( $titles ); // Ensure the order is always the same
+
+ $result = $this->getResult();
+ $images = RepoGroup::singleton()->findFiles( $titles );
+ /**
+ * @var $img File
+ */
+ foreach ( $images as $img ) {
+ // if its a "transcode" add the transcode status table output
+ if( TimedMediaHandlerHooks::isTranscodableTitle( $img->getTitle() ) ){
+ $transcodeStatus = WebVideoTranscode::getTranscodeState( $img );
+ // remove useless properties
+ foreach($transcodeStatus as $key=>&$val ){
+ unset( $val['id'] );
+ unset( $val['image_name']);
+ unset( $val['key'] );
+ }
+ $result->addValue( array( 'query', 'pages', $img->getTitle()->getArticleID() ), 'transcodestatus', $transcodeStatus );
+ }
+ }
+ }
+ }
+
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
+ public function getAllowedParams() {
+ return array();
+ }
+
+ /**
+ * @deprecated since MediaWiki core 1.25
+ */
+ public function getDescription() {
+ return array(
+ 'Get transcode status for a given file page'
+ );
+ }
+
+ /**
+ * @deprecated since MediaWiki core 1.25
+ */
+ protected function getExamples() {
+ return array (
+ 'api.php?action=query&prop=transcodestatus&titles=File:Clip.webm',
+ );
+ }
+
+ /**
+ * @see ApiBase::getExamplesMessages()
+ */
+ protected function getExamplesMessages() {
+ return array(
+ 'action=query&prop=transcodestatus&titles=File:Clip.webm'
+ => 'apihelp-query+transcodestatus-example-1',
+ );
+ }
+}
diff --git a/extensions/TimedMediaHandler/COPYING b/extensions/TimedMediaHandler/COPYING
new file mode 100644
index 00000000..019694a9
--- /dev/null
+++ b/extensions/TimedMediaHandler/COPYING
@@ -0,0 +1,342 @@
+== GNU GENERAL PUBLIC LICENSE ==
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+=== Preamble ===
+
+The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and
+modification follow.
+
+== TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ==
+
+'''0.''' This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+'''1.''' You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+'''2.''' You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ '''a)''' You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ '''b)''' You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ '''c)''' If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+'''3.''' You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ '''a)''' Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ '''b)''' Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ '''c)''' Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+'''4.''' You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+'''5.''' You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+'''6.''' Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+'''7.''' If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+'''8.''' If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+'''9.''' The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+'''10.''' If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+=== NO WARRANTY ===
+
+'''11.''' BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+'''12.''' IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ '''END OF TERMS AND CONDITIONS'''
+
+== How to Apply These Terms to Your New Programs ==
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/extensions/TimedMediaHandler/Gruntfile.js b/extensions/TimedMediaHandler/Gruntfile.js
new file mode 100644
index 00000000..45380710
--- /dev/null
+++ b/extensions/TimedMediaHandler/Gruntfile.js
@@ -0,0 +1,34 @@
+/*jshint node:true */
+module.exports = function ( grunt ) {
+ grunt.loadNpmTasks( 'grunt-contrib-jshint' );
+ grunt.loadNpmTasks( 'grunt-jsonlint' );
+ grunt.loadNpmTasks( 'grunt-banana-checker' );
+ grunt.loadNpmTasks( 'grunt-jscs' );
+
+ grunt.initConfig( {
+ jshint: {
+ options: {
+ jshintrc: true
+ },
+ all: [
+ '*.js'
+ ]
+ },
+ jscs: {
+ src: '<%= jshint.all %>'
+ },
+ banana: {
+ all: 'i18n/'
+ },
+ jsonlint: {
+ all: [
+ '*.json',
+ '**/*.json',
+ '!node_modules/**'
+ ]
+ }
+ } );
+
+ grunt.registerTask( 'test', [ 'jshint', 'jscs', 'jsonlint', 'banana' ] );
+ grunt.registerTask( 'default', 'test' );
+};
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.config.php b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.config.php
new file mode 100644
index 00000000..af32b4d7
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.config.php
@@ -0,0 +1,194 @@
+<?php
+ /**
+ * Do not edit this file instead use LocalSettings.php and
+ * $wgMwEmbedModuleConfig[ {configuration name} ] = value; format
+ */
+ return array (
+ // If the player controls should be overlaid on top of the video ( if supported by playback method)
+ // can be set to false per embed player via overlayControls attribute
+ 'EmbedPlayer.OverlayControls' => true,
+
+ // The preferred media codec preference
+ // Note user selected format order
+ 'EmbedPlayer.CodecPreference' => array( 'vp9', 'webm', 'h264', 'ogg' ),
+
+ // If video tag support should be disabled all-together, used to test
+ // fallback decoding methods and direct file links
+ 'EmbedPlayer.DisableVideoTagSupport' => false,
+
+ // If detected browser flash support should be ignored, and flash support,
+ // set to false. This will eliminate support for flash based playback.
+ 'EmbedPlayer.DisableHTML5FlashFallback'=> false,
+
+ // Can be used to set player sources via configuration, useful in cases,
+ // where metadata is loaded from an api, but actual sources need to be pointed
+ // to another location at runtime via config
+ 'EmbedPlayer.ReplaceSources' => null,
+
+ // If the flavor selector menu option should be displayed:
+ // This will be enabled by default in some future release of the library
+ 'EmbedPlayer.EnableFlavorSelector' => false,
+
+ // If the iPad should use html controls
+ // With html controls you can't access native fullscreen
+ // With html controls you can support html themed controls, overlays, ads etc. )
+ 'EmbedPlayer.EnableIpadHTMLControls' => true,
+
+ // If the webkit-playsinline attribute should be added to the video tag. Will cause the player
+ // to play inline on iPhone
+ 'EmbedPlayer.WebKitPlaysInline'=> false,
+
+ // If we should use the native device fullscreen call,
+ // this gives you hybrid player, where controls are in HTML for in browser playback,
+ // and native controls when the fullscreen button is pressed.
+ // its not the default since often users want playback control if using html controls,
+ // ( i.e no add skip etc )
+ 'EmbedPlayer.EnableIpadNativeFullscreen' => false,
+
+ // By default we display an html play screen, image thumb and play button.
+ // even though this is still a 'native' player.
+ // If you are not using ad plugins you may want to set this to false
+ // and display the native play button:
+ 'EmbedPlayer.iPhoneShowHTMLPlayScreen' => true,
+
+ // If the large play button should be disabled on replay:
+ 'EmbedPlayer.ForceLargeReplayButton' => false,
+
+ // The attribution library page
+ 'EmbedPlayer.LibraryPage' => 'http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library',
+
+ // What tags will be re-written to video player by default
+ // Set to empty string or null to avoid automatic video tag rewrites to embedPlayer
+ "EmbedPlayer.RewriteSelector" => "video,audio,playlist",
+
+ // Default video size ( if no size provided )
+ "EmbedPlayer.DefaultSize" => "400x300",
+
+ // Default player controls size:
+ 'EmbedPlayer.ControlsHeight' => 31,
+
+ // Default time display size:
+ 'EmbedPlayer.TimeDisplayWidth' => 85,
+
+ // If the video player should attribute kaltura
+ "EmbedPlayer.KalturaAttribution" => true,
+
+ // The attribution button
+ 'EmbedPlayer.AttributionButton' => array(
+ 'title' => 'Kaltura html5 video library',
+ 'href' => 'http://www.kaltura.com',
+ // Style icon to be applied
+ 'class' => 'kaltura-icon',
+ // Style to be applied to the outer attribution button container div
+ 'style' => array(),
+ // An icon image url 16x16 image url or data url )
+ 'iconurl' => false
+ ),
+
+ // If the options control bar menu item should be enabled:
+ 'EmbedPlayer.EnableOptionsMenu' => false,
+
+ // If users can right click on the player
+ 'EmbedPlayer.EnableRightClick' => true,
+
+ // Default supported menu items is merged with skin menu items
+ 'EmbedPlayer.EnabledOptionsMenuItems' => array(
+ // Player Select
+ 'playerSelect',
+
+ // Download the file menu
+ 'download',
+
+ // Share the video menu
+ 'share',
+
+ // Player library link
+ 'aboutPlayerLibrary'
+ ),
+
+ // If the player should wait for metadata like video size and duration, before trying to draw
+ // the player interface.
+ 'EmbedPlayer.WaitForMeta' => true,
+
+ // Set the browser player warning flag displays warning for non optimal playback
+ "EmbedPlayer.ShowNativeWarning" => true,
+
+ // If player errors / alerts should be displayed:
+ "EmbedPlayer.ShowPlayerAlerts" => true,
+
+ // If fullscreen is global enabled.
+ "EmbedPlayer.EnableFullscreen" => true,
+
+ // If the embed player time display should be shown
+ 'EmbedPlayer.EnableTimeDisplay' => true,
+
+ // If the embed player volume control should be displayed
+ 'EmbedPlayer.EnableVolumeControl' => true,
+
+ // If fullscreen should pop-open a new window
+ //( instead of trying to expand the video player to browser fullscreen )
+ "EmbedPlayer.NewWindowFullscreen" => false,
+
+ // If a fullscreen tip to press f11 should be displayed when entering fullscreen
+ "EmbedPlayer.FullscreenTip" => true,
+
+ // if the browser should display a warning for direct file links:
+ "EmbedPlayer.DirectFileLinkWarning" => false,
+
+ "EmbedPlayer.FirefoxLink" => 'http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed',
+
+ // If mwEmbed should use the Native player controls
+ // this will prevent video tag rewriting and skinning
+ // useful for devices such as iPad / iPod that
+ // don't fully support DOM overlays or don't expose full-screen
+ // functionality to javascript
+ "EmbedPlayer.NativeControls" => false,
+
+ // If mwEmbed should use native controls on mobile safari
+ "EmbedPlayer.NativeControlsMobileSafari" => true,
+
+ // The z-index given to the player interface during full screen ( high z-index )
+ "EmbedPlayer.FullScreenZIndex" => 999998,
+
+ // The default share embed mode ( can be "iframe" or "xssVideo" )
+ //
+ // "iframe" will provide a <iframe tag pointing to mwEmbedFrame.php
+ // Object embedding should be much more compatible with sites that
+ // let users embed flash applets
+ // "xssVideo" will include the source javascript and video tag to
+ // rewrite the player on the remote page DOM
+ // Video tag embedding is much more mash-up friendly but exposes
+ // the remote site to the mwEmbed javascript and can be a xss issue.
+ "EmbedPlayer.ShareEmbedMode" => 'iframe',
+
+ // The skin framework list:
+ "EmbedPlayer.SkinList" => array( 'mvpcf', 'kskin' ),
+
+ // Default player skin name
+ "EmbedPlayer.DefaultSkin" => "mvpcf",
+
+ // Number of milliseconds between interface updates
+ 'EmbedPlayer.MonitorRate' => 250,
+
+ // If on Android should use html5 ( even if flash is installed on the machine )
+ 'EmbedPlayer.UseFlashOnAndroid' => false,
+
+ // If embedPlayer should support server side temporal urls for seeking options are
+ // flash|always|none default is support for flash only.
+ 'EmbedPlayer.EnableURLTimeEncoding' => 'flash',
+
+ // The domains which can read and send events to the video player
+ 'EmbedPLayer.IFramePlayer.DomainWhiteList' => '*',
+
+ // If the iframe should send and receive javascript events across domains via postMessage
+ 'EmbedPlayer.EnableIframeApi' => true,
+
+ // If set to true will output the iframe as inline contents on the same domain as page contents
+ 'EmbedPlayer.PageDomainIframe' => true,
+
+ // When there is no in-browser playback mechanism provide a download link for the play button
+ 'EmbedPlayer.NotPlayableDownloadLink' => true,
+
+ // A black pixel for source switching
+ 'EmbedPlayer.BlackPixel' => "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%01%00%00%00%01%08%02%00%00%00%90wS%DE%00%00%00%01sRGB%00%AE%CE%1C%E9%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%07tIME%07%DB%0B%0A%17%041%80%9B%E7%F2%00%00%00%19tEXtComment%00Created%20with%20GIMPW%81%0E%17%00%00%00%0CIDAT%08%D7c%60%60%60%00%00%00%04%00%01'4'%0A%00%00%00%00IEND%AEB%60%82"
+ );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.loader.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.loader.js
new file mode 100644
index 00000000..f63a9393
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.loader.js
@@ -0,0 +1,69 @@
+/**
+* EmbedPlayer loader
+*/
+( function( mw, $ ) {
+ /**
+ * Add a DOM ready check for player tags
+ */
+ $( function() {
+ var $selected = $( mw.config.get( 'EmbedPlayer.RewriteSelector' ) );
+ if ( $selected.length ) {
+ var inx = 0;
+ var checkSetDone = function() {
+ if ( inx < $selected.length ) {
+ // put in timeout to avoid browser lockup, and function stack
+ $selected.slice( inx, inx + 1 ).embedPlayer( function() {
+ setTimeout( function() {
+ checkSetDone();
+ }, 5 );
+ } );
+ }
+ inx++;
+ };
+
+ checkSetDone();
+ }
+ } );
+
+ /**
+ * Add the mwEmbed jQuery loader wrapper
+ */
+ $.fn.embedPlayer = function( readyCallback ) {
+ var playerSet = this;
+ mw.log( 'jQuery.fn.embedPlayer :: ' + $( playerSet ).length );
+
+ // Set up the embed video player class request: (include the skin js as well)
+ var dependencySet = [
+ 'mw.EmbedPlayer'
+ ];
+
+ mw.loader.using( [ 'jquery.client', 'jquery.mwEmbedUtil', 'mw.MwEmbedSupport' ], function() {
+ $( playerSet ).each( function( inx, playerElement ) {
+ // we have javascript ( disable controls )
+ $( playerElement ).removeAttr( 'controls' );
+ // Add an overlay loader ( firefox has its own native loading spinner )
+
+ if ( $.client.profile().name !== 'firefox' ) {
+ $( playerElement )
+ .parent()
+ .getAbsoluteOverlaySpinner()
+ .attr('id', 'loadingSpinner_' + $( playerElement ).attr('id') );
+ }
+ // Allow other modules update the dependencies
+ $( mw ).trigger( 'EmbedPlayerUpdateDependencies',
+ [ playerElement, dependencySet ] );
+ } );
+
+ // Remove any duplicates in the dependencySet:
+ dependencySet = $.uniqueArray( dependencySet );
+
+ // Do the request and process the playerElements with updated dependency set
+ mw.loader.using( dependencySet, function() {
+ // Setup the enhanced language:
+ mw.processEmbedPlayers( playerSet, readyCallback );
+ }, function( e ) {
+ throw new Error( 'Error loading EmbedPlayer dependency set: ' + e.message );
+ } );
+ } );
+ };
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.php b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.php
new file mode 100644
index 00000000..a813c8d0
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.php
@@ -0,0 +1,103 @@
+<?php
+ global $wgVideoPlayerSkinModule;
+ // Register all the EmbedPlayer modules
+ return array(
+ "mw.MediaElement" => array(
+ 'scripts' => 'resources/mw.MediaElement.js',
+ 'dependencies' => array(
+ 'ext.tmh.OgvJsSupport',
+ )
+ ),
+ "mw.MediaPlayer" => array( 'scripts' => 'resources/mw.MediaPlayer.js' ),
+ "mw.MediaPlayers" => array(
+ 'scripts' => 'resources/mw.MediaPlayers.js',
+ 'dependencies' => 'mw.MediaPlayer'
+ ),
+ "mw.MediaSource" => array( 'scripts' => 'resources/mw.MediaSource.js' ),
+ "mw.EmbedTypes" => array(
+ 'scripts' => 'resources/mw.EmbedTypes.js',
+ 'dependencies' => array(
+ 'mw.MediaPlayers',
+ 'mediawiki.Uri',
+ 'jquery.client',
+ )
+ ),
+ "mw.EmbedPlayer" => array(
+ 'scripts' => array(
+ "resources/mw.processEmbedPlayers.js",
+ "resources/mw.EmbedPlayer.js",
+ "resources/skins/mw.PlayerControlBuilder.js",
+ ),
+ 'dependencies' => array(
+ // mwEmbed support module
+ 'mediawiki.client',
+ 'mediawiki.UtilitiesTime',
+ 'mediawiki.Uri',
+ 'mediawiki.absoluteUrl',
+ 'mediawiki.jqueryMsg',
+
+ // Browser fullscreen api support:
+ 'fullScreenApi',
+
+ // Kinda need this
+ 'mw.MwEmbedSupport',
+
+ // We always end up loading native player
+ 'mw.EmbedPlayerNative',
+
+ // Sub classes:
+ 'mw.MediaElement',
+ 'mw.MediaPlayers',
+ 'mw.MediaSource',
+ 'mw.EmbedTypes',
+
+ // jQuery dependencies:
+ 'jquery.client',
+ 'jquery.hoverIntent',
+ 'jquery.cookie',
+ 'jquery.ui.mouse',
+ 'jquery.debouncedresize',
+ 'jquery.embedMenu',
+ 'jquery.ui.slider',
+ 'jquery.ui.touchPunch',
+
+ // Set to mw.PlayerSkinKskin or mw.PlayerSkinMvpcf in config
+ $wgVideoPlayerSkinModule
+ ),
+ 'styles' => "resources/skins/EmbedPlayer.css",
+ 'messageDir' => 'i18n',
+ ),
+
+ "mw.EmbedPlayerKplayer" => array( 'scripts'=> "resources/mw.EmbedPlayerKplayer.js" ),
+ "mw.EmbedPlayerGeneric" => array( 'scripts'=> "resources/mw.EmbedPlayerGeneric.js" ),
+ "mw.EmbedPlayerNative" => array( 'scripts'=> "resources/mw.EmbedPlayerNative.js" ),
+ "mw.EmbedPlayerVLCApp" => array(
+ 'scripts'=> "resources/mw.EmbedPlayerVLCApp.js",
+ 'dependencies' => array( 'mediawiki.Uri' )
+ ),
+ "mw.EmbedPlayerIEWebMPrompt" => array(
+ 'scripts' => 'resources/mw.EmbedPlayerIEWebMPrompt.js',
+ 'styles' => 'resources/mw.EmbedPlayerIEWebMPrompt.css',
+ ),
+ "mw.EmbedPlayerOgvJs" => array(
+ 'scripts' => 'resources/mw.EmbedPlayerOgvJs.js',
+ 'dependencies' => array(
+ 'jquery.spinner',
+ 'ext.tmh.OgvJsSupport',
+ ),
+ ),
+ "mw.EmbedPlayerImageOverlay" => array( 'scripts'=> "resources/mw.EmbedPlayerImageOverlay.js" ),
+
+ "mw.EmbedPlayerVlc" => array( 'scripts'=> "resources/mw.EmbedPlayerVlc.js" ),
+
+ "mw.PlayerSkinKskin" => array(
+ 'scripts' => "resources/skins/kskin/mw.PlayerSkinKskin.js",
+ 'styles' => "resources/skins/kskin/PlayerSkinKskin.css"
+ ),
+
+ "mw.PlayerSkinMvpcf" => array(
+ 'scripts'=> "resources/skins/mvpcf/mw.PlayerSkinMvpcf.js",
+ 'styles'=> "resources/skins/mvpcf/PlayerSkinMvpcf.css"
+ ),
+ );
+?>
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/LightDoodleskin.swf b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/LightDoodleskin.swf
new file mode 100644
index 00000000..5f25450e
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/LightDoodleskin.swf
Binary files differ
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/README b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/README
new file mode 100644
index 00000000..7b11a51b
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/README
@@ -0,0 +1,20 @@
+
+File: kdp3.swf
+
+This Kaltura Dynamic Player +Playlist (KDP) is a sub package of the taken Kaltura Community Edition (CE) Built from Kaltura.org source.
+
+The full Kaltura Community Edition is licensed under the ( GNU Affero General Public License v3 )
+
+And the source code is available on the kaltura.org site:
+http://www.kaltura.org/project/kalturaCE
+
+More info about the KDP:
+http://www.kaltura.org/kdp-dynamic-player-and-playlist-widget
+
+
+
+File: expressInstall.swf
+is part of SWFObject v2.2 <http://code.google.com/p/swfobject/>
+ and is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
+
+
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/config.xml b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/config.xml
new file mode 100644
index 00000000..a4c4e9c8
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/config.xml
@@ -0,0 +1,9 @@
+<layout id="full" skinPath="assets/skin.swf">
+ <HBox id="topLevel" width="100%" height="100%">
+ <VBox id="player" width="100%" height="100%" styleName="black">
+ <Canvas height="100%" width="100%" id="PlayerHolder" styleName="black">
+ <Video id="video" width="100%" height="100%" />
+ </Canvas>
+ </VBox>
+ </HBox>
+</layout> \ No newline at end of file
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/expressInstall.swf b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/expressInstall.swf
new file mode 100644
index 00000000..0fbf8fca
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/expressInstall.swf
Binary files differ
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/kdp3.3.5.27.swf b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/kdp3.3.5.27.swf
new file mode 100644
index 00000000..b400fa68
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/kdp3.3.5.27.swf
Binary files differ
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/kdp3.swf b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/kdp3.swf
new file mode 100644
index 00000000..c2f3891c
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/kdp3.swf
Binary files differ
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/skin.swf b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/skin.swf
new file mode 100644
index 00000000..3c8bf053
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/kaltura-player/skin.swf
Binary files differ
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING
new file mode 100644
index 00000000..96498a60
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING
@@ -0,0 +1,21 @@
+ogv.js & ogv.swf wrapper and player code
+
+Copyright (c) 2013-2014 Brion Vibber and other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-ogg.txt b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-ogg.txt
new file mode 100644
index 00000000..6111c6c5
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-ogg.txt
@@ -0,0 +1,28 @@
+Copyright (c) 2002, Xiph.org Foundation
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Xiph.org Foundation nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-opus.txt b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-opus.txt
new file mode 100644
index 00000000..9c739c34
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-opus.txt
@@ -0,0 +1,44 @@
+Copyright 2001-2011 Xiph.Org, Skype Limited, Octasic,
+ Jean-Marc Valin, Timothy B. Terriberry,
+ CSIRO, Gregory Maxwell, Mark Borgerding,
+ Erik de Castro Lopo
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Opus is subject to the royalty-free patent licenses which are
+specified at:
+
+Xiph.Org Foundation:
+https://datatracker.ietf.org/ipr/1524/
+
+Microsoft Corporation:
+https://datatracker.ietf.org/ipr/1914/
+
+Broadcom Corporation:
+https://datatracker.ietf.org/ipr/1526/
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-theora.txt b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-theora.txt
new file mode 100644
index 00000000..c8ccce4f
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-theora.txt
@@ -0,0 +1,28 @@
+Copyright (C) 2002-2009 Xiph.org Foundation
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Xiph.org Foundation nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-vorbis.txt b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-vorbis.txt
new file mode 100644
index 00000000..28de72a9
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/COPYING-vorbis.txt
@@ -0,0 +1,28 @@
+Copyright (c) 2002-2008 Xiph.org Foundation
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Xiph.org Foundation nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/dynamicaudio.swf b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/dynamicaudio.swf
new file mode 100644
index 00000000..2e3ce4e4
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/dynamicaudio.swf
Binary files differ
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-decoder-audio-opus.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-decoder-audio-opus.js
new file mode 100644
index 00000000..4e73c95a
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-decoder-audio-opus.js
@@ -0,0 +1,24 @@
+var OGVDecoderAudioOpus = function(Module) {
+ Module = Module || {};
+
+var options=Module;Module={print:(function(str){console.log(str)})};var Module;if(!Module)Module=(typeof OGVDecoderAudioOpus!=="undefined"?OGVDecoderAudioOpus:null)||{};var moduleOverrides={};for(var key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var ENVIRONMENT_IS_WEB=typeof window==="object";var ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof require==="function"&&!ENVIRONMENT_IS_WEB;var ENVIRONMENT_IS_WORKER=typeof importScripts==="function";var ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){if(!Module["print"])Module["print"]=function print(x){process["stdout"].write(x+"\n")};if(!Module["printErr"])Module["printErr"]=function printErr(x){process["stderr"].write(x+"\n")};var nodeFS=require("fs");var nodePath=require("path");Module["read"]=function read(filename,binary){filename=nodePath["normalize"](filename);var ret=nodeFS["readFileSync"](filename);if(!ret&&filename!=nodePath["resolve"](filename)){filename=path.join(__dirname,"..","src",filename);ret=nodeFS["readFileSync"](filename)}if(ret&&!binary)ret=ret.toString();return ret};Module["readBinary"]=function readBinary(filename){return Module["read"](filename,true)};Module["load"]=function load(f){globalEval(read(f))};if(!Module["thisProgram"]){if(process["argv"].length>1){Module["thisProgram"]=process["argv"][1].replace(/\\/g,"/")}else{Module["thisProgram"]="unknown-program"}}Module["arguments"]=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",(function(ex){if(!(ex instanceof ExitStatus)){throw ex}}));Module["inspect"]=(function(){return"[Emscripten Module object]"})}else if(ENVIRONMENT_IS_SHELL){if(!Module["print"])Module["print"]=print;if(typeof printErr!="undefined")Module["printErr"]=printErr;if(typeof read!="undefined"){Module["read"]=read}else{Module["read"]=function read(){throw"no read() available (jsc?)"}}Module["readBinary"]=function readBinary(f){if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}var data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){Module["arguments"]=scriptArgs}else if(typeof arguments!="undefined"){Module["arguments"]=arguments}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){Module["read"]=function read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(typeof arguments!="undefined"){Module["arguments"]=arguments}if(typeof console!=="undefined"){if(!Module["print"])Module["print"]=function print(x){console.log(x)};if(!Module["printErr"])Module["printErr"]=function printErr(x){console.log(x)}}else{var TRY_USE_DUMP=false;if(!Module["print"])Module["print"]=TRY_USE_DUMP&&typeof dump!=="undefined"?(function(x){dump(x)}):(function(x){})}if(ENVIRONMENT_IS_WORKER){Module["load"]=importScripts}if(typeof Module["setWindowTitle"]==="undefined"){Module["setWindowTitle"]=(function(title){document.title=title})}}else{throw"Unknown runtime environment. Where are we?"}function globalEval(x){eval.call(null,x)}if(!Module["load"]&&Module["read"]){Module["load"]=function load(f){globalEval(Module["read"](f))}}if(!Module["print"]){Module["print"]=(function(){})}if(!Module["printErr"]){Module["printErr"]=Module["print"]}if(!Module["arguments"]){Module["arguments"]=[]}if(!Module["thisProgram"]){Module["thisProgram"]="./this.program"}Module.print=Module["print"];Module.printErr=Module["printErr"];Module["preRun"]=[];Module["postRun"]=[];for(var key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}var Runtime={setTempRet0:(function(value){tempRet0=value}),getTempRet0:(function(){return tempRet0}),stackSave:(function(){return STACKTOP}),stackRestore:(function(stackTop){STACKTOP=stackTop}),getNativeTypeSize:(function(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return Runtime.QUANTUM_SIZE}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0);return bits/8}else{return 0}}}}),getNativeFieldSize:(function(type){return Math.max(Runtime.getNativeTypeSize(type),Runtime.QUANTUM_SIZE)}),STACK_ALIGN:16,prepVararg:(function(ptr,type){if(type==="double"||type==="i64"){if(ptr&7){assert((ptr&7)===4);ptr+=4}}else{assert((ptr&3)===0)}return ptr}),getAlignSize:(function(type,size,vararg){if(!vararg&&(type=="i64"||type=="double"))return 8;if(!type)return Math.min(size,8);return Math.min(size||(type?Runtime.getNativeFieldSize(type):0),Runtime.QUANTUM_SIZE)}),dynCall:(function(sig,ptr,args){if(args&&args.length){if(!args.splice)args=Array.prototype.slice.call(args);args.splice(0,0,ptr);return Module["dynCall_"+sig].apply(null,args)}else{return Module["dynCall_"+sig].call(null,ptr)}}),functionPointers:[],addFunction:(function(func){for(var i=0;i<Runtime.functionPointers.length;i++){if(!Runtime.functionPointers[i]){Runtime.functionPointers[i]=func;return 2*(1+i)}}throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS."}),removeFunction:(function(index){Runtime.functionPointers[(index-2)/2]=null}),warnOnce:(function(text){if(!Runtime.warnOnce.shown)Runtime.warnOnce.shown={};if(!Runtime.warnOnce.shown[text]){Runtime.warnOnce.shown[text]=1;Module.printErr(text)}}),funcWrappers:{},getFuncWrapper:(function(func,sig){assert(sig);if(!Runtime.funcWrappers[sig]){Runtime.funcWrappers[sig]={}}var sigCache=Runtime.funcWrappers[sig];if(!sigCache[func]){sigCache[func]=function dynCall_wrapper(){return Runtime.dynCall(sig,func,arguments)}}return sigCache[func]}),getCompilerSetting:(function(name){throw"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work"}),stackAlloc:(function(size){var ret=STACKTOP;STACKTOP=STACKTOP+size|0;STACKTOP=STACKTOP+15&-16;return ret}),staticAlloc:(function(size){var ret=STATICTOP;STATICTOP=STATICTOP+size|0;STATICTOP=STATICTOP+15&-16;return ret}),dynamicAlloc:(function(size){var ret=DYNAMICTOP;DYNAMICTOP=DYNAMICTOP+size|0;DYNAMICTOP=DYNAMICTOP+15&-16;if(DYNAMICTOP>=TOTAL_MEMORY){var success=enlargeMemory();if(!success){DYNAMICTOP=ret;return 0}}return ret}),alignMemory:(function(size,quantum){var ret=size=Math.ceil(size/(quantum?quantum:16))*(quantum?quantum:16);return ret}),makeBigInt:(function(low,high,unsigned){var ret=unsigned?+(low>>>0)+ +(high>>>0)*+4294967296:+(low>>>0)+ +(high|0)*+4294967296;return ret}),GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module["Runtime"]=Runtime;var __THREW__=0;var ABORT=false;var EXITSTATUS=0;var undef=0;var tempValue,tempInt,tempBigInt,tempInt2,tempBigInt2,tempPair,tempBigIntI,tempBigIntR,tempBigIntS,tempBigIntP,tempBigIntD,tempDouble,tempFloat;var tempI64,tempI64b;var tempRet0,tempRet1,tempRet2,tempRet3,tempRet4,tempRet5,tempRet6,tempRet7,tempRet8,tempRet9;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var globalScope=this;function getCFunc(ident){var func=Module["_"+ident];if(!func){try{func=eval("_"+ident)}catch(e){}}assert(func,"Cannot call unknown function "+ident+" (perhaps LLVM optimizations or closure removed it?)");return func}var cwrap,ccall;((function(){var JSfuncs={"stackSave":(function(){Runtime.stackSave()}),"stackRestore":(function(){Runtime.stackRestore()}),"arrayToC":(function(arr){var ret=Runtime.stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}),"stringToC":(function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=Runtime.stackAlloc((str.length<<2)+1);writeStringToMemory(str,ret)}return ret})};var toC={"string":JSfuncs["stringToC"],"array":JSfuncs["arrayToC"]};ccall=function ccallFunc(ident,returnType,argTypes,args,opts){var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=Runtime.stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func.apply(null,cArgs);if(returnType==="string")ret=Pointer_stringify(ret);if(stack!==0){if(opts&&opts.async){EmterpreterAsync.asyncFinalizers.push((function(){Runtime.stackRestore(stack)}));return}Runtime.stackRestore(stack)}return ret};var sourceRegex=/^function\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/;function parseJSFunc(jsfunc){var parsed=jsfunc.toString().match(sourceRegex).slice(1);return{arguments:parsed[0],body:parsed[1],returnValue:parsed[2]}}var JSsource={};for(var fun in JSfuncs){if(JSfuncs.hasOwnProperty(fun)){JSsource[fun]=parseJSFunc(JSfuncs[fun])}}cwrap=function cwrap(ident,returnType,argTypes){argTypes=argTypes||[];var cfunc=getCFunc(ident);var numericArgs=argTypes.every((function(type){return type==="number"}));var numericRet=returnType!=="string";if(numericRet&&numericArgs){return cfunc}var argNames=argTypes.map((function(x,i){return"$"+i}));var funcstr="(function("+argNames.join(",")+") {";var nargs=argTypes.length;if(!numericArgs){funcstr+="var stack = "+JSsource["stackSave"].body+";";for(var i=0;i<nargs;i++){var arg=argNames[i],type=argTypes[i];if(type==="number")continue;var convertCode=JSsource[type+"ToC"];funcstr+="var "+convertCode.arguments+" = "+arg+";";funcstr+=convertCode.body+";";funcstr+=arg+"="+convertCode.returnValue+";"}}var cfuncname=parseJSFunc((function(){return cfunc})).returnValue;funcstr+="var ret = "+cfuncname+"("+argNames.join(",")+");";if(!numericRet){var strgfy=parseJSFunc((function(){return Pointer_stringify})).returnValue;funcstr+="ret = "+strgfy+"(ret);"}if(!numericArgs){funcstr+=JSsource["stackRestore"].body.replace("()","(stack)")+";"}funcstr+="return ret})";return eval(funcstr)}}))();Module["cwrap"]=cwrap;Module["ccall"]=ccall;function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble- +(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}Module["setValue"]=setValue;function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for setValue: "+type)}return null}Module["getValue"]=getValue;var ALLOC_NORMAL=0;var ALLOC_STACK=1;var ALLOC_STATIC=2;var ALLOC_DYNAMIC=3;var ALLOC_NONE=4;Module["ALLOC_NORMAL"]=ALLOC_NORMAL;Module["ALLOC_STACK"]=ALLOC_STACK;Module["ALLOC_STATIC"]=ALLOC_STATIC;Module["ALLOC_DYNAMIC"]=ALLOC_DYNAMIC;Module["ALLOC_NONE"]=ALLOC_NONE;function allocate(slab,types,allocator,ptr){var zeroinit,size;if(typeof slab==="number"){zeroinit=true;size=slab}else{zeroinit=false;size=slab.length}var singleType=typeof types==="string"?types:null;var ret;if(allocator==ALLOC_NONE){ret=ptr}else{ret=[_malloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][allocator===undefined?ALLOC_STATIC:allocator](Math.max(size,singleType?1:types.length))}if(zeroinit){var ptr=ret,stop;assert((ret&3)==0);stop=ret+(size&~3);for(;ptr<stop;ptr+=4){HEAP32[ptr>>2]=0}stop=ret+size;while(ptr<stop){HEAP8[ptr++>>0]=0}return ret}if(singleType==="i8"){if(slab.subarray||slab.slice){HEAPU8.set(slab,ret)}else{HEAPU8.set(new Uint8Array(slab),ret)}return ret}var i=0,type,typeSize,previousType;while(i<size){var curr=slab[i];if(typeof curr==="function"){curr=Runtime.getFunctionIndex(curr)}type=singleType||types[i];if(type===0){i++;continue}if(type=="i64")type="i32";setValue(ret+i,curr,type);if(previousType!==type){typeSize=Runtime.getNativeTypeSize(type);previousType=type}i+=typeSize}return ret}Module["allocate"]=allocate;function getMemory(size){if(!staticSealed)return Runtime.staticAlloc(size);if(typeof _sbrk!=="undefined"&&!_sbrk.called||!runtimeInitialized)return Runtime.dynamicAlloc(size);return _malloc(size)}Module["getMemory"]=getMemory;function Pointer_stringify(ptr,length){if(length===0||!ptr)return"";var hasUtf=0;var t;var i=0;while(1){t=HEAPU8[ptr+i>>0];hasUtf|=t;if(t==0&&!length)break;i++;if(length&&i==length)break}if(!length)length=i;var ret="";if(hasUtf<128){var MAX_CHUNK=1024;var curr;while(length>0){curr=String.fromCharCode.apply(String,HEAPU8.subarray(ptr,ptr+Math.min(length,MAX_CHUNK)));ret=ret?ret+curr:curr;ptr+=MAX_CHUNK;length-=MAX_CHUNK}return ret}return Module["UTF8ToString"](ptr)}Module["Pointer_stringify"]=Pointer_stringify;function AsciiToString(ptr){var str="";while(1){var ch=HEAP8[ptr++>>0];if(!ch)return str;str+=String.fromCharCode(ch)}}Module["AsciiToString"]=AsciiToString;function stringToAscii(str,outPtr){return writeAsciiToMemory(str,outPtr,false)}Module["stringToAscii"]=stringToAscii;function UTF8ArrayToString(u8Array,idx){var u0,u1,u2,u3,u4,u5;var str="";while(1){u0=u8Array[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}u1=u8Array[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}u2=u8Array[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u3=u8Array[idx++]&63;if((u0&248)==240){u0=(u0&7)<<18|u1<<12|u2<<6|u3}else{u4=u8Array[idx++]&63;if((u0&252)==248){u0=(u0&3)<<24|u1<<18|u2<<12|u3<<6|u4}else{u5=u8Array[idx++]&63;u0=(u0&1)<<30|u1<<24|u2<<18|u3<<12|u4<<6|u5}}}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}Module["UTF8ArrayToString"]=UTF8ArrayToString;function UTF8ToString(ptr){return UTF8ArrayToString(HEAPU8,ptr)}Module["UTF8ToString"]=UTF8ToString;function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=2097151){if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=67108863){if(outIdx+4>=endIdx)break;outU8Array[outIdx++]=248|u>>24;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+5>=endIdx)break;outU8Array[outIdx++]=252|u>>30;outU8Array[outIdx++]=128|u>>24&63;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}Module["stringToUTF8Array"]=stringToUTF8Array;function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}Module["stringToUTF8"]=stringToUTF8;function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){++len}else if(u<=2047){len+=2}else if(u<=65535){len+=3}else if(u<=2097151){len+=4}else if(u<=67108863){len+=5}else{len+=6}}return len}Module["lengthBytesUTF8"]=lengthBytesUTF8;function UTF16ToString(ptr){var i=0;var str="";while(1){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)return str;++i;str+=String.fromCharCode(codeUnit)}}Module["UTF16ToString"]=UTF16ToString;function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite<str.length*2?maxBytesToWrite/2:str.length;for(var i=0;i<numCharsToWrite;++i){var codeUnit=str.charCodeAt(i);HEAP16[outPtr>>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}Module["stringToUTF16"]=stringToUTF16;function lengthBytesUTF16(str){return str.length*2}Module["lengthBytesUTF16"]=lengthBytesUTF16;function UTF32ToString(ptr){var i=0;var str="";while(1){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)return str;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}}Module["UTF32ToString"]=UTF32ToString;function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);if(codeUnit>=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}Module["stringToUTF32"]=stringToUTF32;function lengthBytesUTF32(str){var len=0;for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);if(codeUnit>=55296&&codeUnit<=57343)++i;len+=4}return len}Module["lengthBytesUTF32"]=lengthBytesUTF32;function demangle(func){var hasLibcxxabi=!!Module["___cxa_demangle"];if(hasLibcxxabi){try{var buf=_malloc(func.length);writeStringToMemory(func.substr(1),buf);var status=_malloc(4);var ret=Module["___cxa_demangle"](buf,0,0,status);if(getValue(status,"i32")===0&&ret){return Pointer_stringify(ret)}}catch(e){}finally{if(buf)_free(buf);if(status)_free(status);if(ret)_free(ret)}}var i=3;var basicTypes={"v":"void","b":"bool","c":"char","s":"short","i":"int","l":"long","f":"float","d":"double","w":"wchar_t","a":"signed char","h":"unsigned char","t":"unsigned short","j":"unsigned int","m":"unsigned long","x":"long long","y":"unsigned long long","z":"..."};var subs=[];var first=true;function dump(x){if(x)Module.print(x);Module.print(func);var pre="";for(var a=0;a<i;a++)pre+=" ";Module.print(pre+"^")}function parseNested(){i++;if(func[i]==="K")i++;var parts=[];while(func[i]!=="E"){if(func[i]==="S"){i++;var next=func.indexOf("_",i);var num=func.substring(i,next)||0;parts.push(subs[num]||"?");i=next+1;continue}if(func[i]==="C"){parts.push(parts[parts.length-1]);i+=2;continue}var size=parseInt(func.substr(i));var pre=size.toString().length;if(!size||!pre){i--;break}var curr=func.substr(i+pre,size);parts.push(curr);subs.push(curr);i+=pre+size}i++;return parts}function parse(rawList,limit,allowVoid){limit=limit||Infinity;var ret="",list=[];function flushList(){return"("+list.join(", ")+")"}var name;if(func[i]==="N"){name=parseNested().join("::");limit--;if(limit===0)return rawList?[name]:name}else{if(func[i]==="K"||first&&func[i]==="L")i++;var size=parseInt(func.substr(i));if(size){var pre=size.toString().length;name=func.substr(i+pre,size);i+=pre+size}}first=false;if(func[i]==="I"){i++;var iList=parse(true);var iRet=parse(true,1,true);ret+=iRet[0]+" "+name+"<"+iList.join(", ")+">"}else{ret=name}paramLoop:while(i<func.length&&limit-->0){var c=func[i++];if(c in basicTypes){list.push(basicTypes[c])}else{switch(c){case"P":list.push(parse(true,1,true)[0]+"*");break;case"R":list.push(parse(true,1,true)[0]+"&");break;case"L":{i++;var end=func.indexOf("E",i);var size=end-i;list.push(func.substr(i,size));i+=size+2;break};case"A":{var size=parseInt(func.substr(i));i+=size.toString().length;if(func[i]!=="_")throw"?";i++;list.push(parse(true,1,true)[0]+" ["+size+"]");break};case"E":break paramLoop;default:ret+="?"+c;break paramLoop}}}if(!allowVoid&&list.length===1&&list[0]==="void")list=[];if(rawList){if(ret){list.push(ret+"?")}return list}else{return ret+flushList()}}var parsed=func;try{if(func=="Object._main"||func=="_main"){return"main()"}if(typeof func==="number")func=Pointer_stringify(func);if(func[0]!=="_")return func;if(func[1]!=="_")return func;if(func[2]!=="Z")return func;switch(func[3]){case"n":return"operator new()";case"d":return"operator delete()"}parsed=parse()}catch(e){parsed+="?"}if(parsed.indexOf("?")>=0&&!hasLibcxxabi){Runtime.warnOnce("warning: a problem occurred in builtin C++ name demangling; build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling")}return parsed}function demangleAll(text){return text.replace(/__Z[\w\d_]+/g,(function(x){var y=demangle(x);return x===y?x:x+" ["+y+"]"}))}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){return demangleAll(jsStackTrace())}Module["stackTrace"]=stackTrace;var PAGE_SIZE=4096;function alignMemoryPage(x){if(x%4096>0){x+=4096-x%4096}return x}var HEAP;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var STATIC_BASE=0,STATICTOP=0,staticSealed=false;var STACK_BASE=0,STACKTOP=0,STACK_MAX=0;var DYNAMIC_BASE=0,DYNAMICTOP=0;function enlargeMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.")}var TOTAL_STACK=Module["TOTAL_STACK"]||5242880;var TOTAL_MEMORY=Module["TOTAL_MEMORY"]||16777216;var totalMemory=64*1024;while(totalMemory<TOTAL_MEMORY||totalMemory<2*TOTAL_STACK){if(totalMemory<16*1024*1024){totalMemory*=2}else{totalMemory+=16*1024*1024}}if(totalMemory!==TOTAL_MEMORY){Module.printErr("increasing TOTAL_MEMORY to "+totalMemory+" to be compliant with the asm.js spec (and given that TOTAL_STACK="+TOTAL_STACK+")");TOTAL_MEMORY=totalMemory}assert(typeof Int32Array!=="undefined"&&typeof Float64Array!=="undefined"&&!!(new Int32Array(1))["subarray"]&&!!(new Int32Array(1))["set"],"JS engine does not provide full typed array support");var buffer;buffer=new ArrayBuffer(TOTAL_MEMORY);HEAP8=new Int8Array(buffer);HEAP16=new Int16Array(buffer);HEAP32=new Int32Array(buffer);HEAPU8=new Uint8Array(buffer);HEAPU16=new Uint16Array(buffer);HEAPU32=new Uint32Array(buffer);HEAPF32=new Float32Array(buffer);HEAPF64=new Float64Array(buffer);HEAP32[0]=255;assert(HEAPU8[0]===255&&HEAPU8[3]===0,"Typed arrays 2 must be run on a little-endian system");Module["HEAP"]=HEAP;Module["buffer"]=buffer;Module["HEAP8"]=HEAP8;Module["HEAP16"]=HEAP16;Module["HEAP32"]=HEAP32;Module["HEAPU8"]=HEAPU8;Module["HEAPU16"]=HEAPU16;Module["HEAPU32"]=HEAPU32;Module["HEAPF32"]=HEAPF32;Module["HEAPF64"]=HEAPF64;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Runtime.dynCall("v",func)}else{Runtime.dynCall("vi",func,[callback.arg])}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){if(runtimeInitialized)return;runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__);runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}Module["addOnPreRun"]=Module.addOnPreRun=addOnPreRun;function addOnInit(cb){__ATINIT__.unshift(cb)}Module["addOnInit"]=Module.addOnInit=addOnInit;function addOnPreMain(cb){__ATMAIN__.unshift(cb)}Module["addOnPreMain"]=Module.addOnPreMain=addOnPreMain;function addOnExit(cb){__ATEXIT__.unshift(cb)}Module["addOnExit"]=Module.addOnExit=addOnExit;function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}Module["addOnPostRun"]=Module.addOnPostRun=addOnPostRun;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}Module["intArrayFromString"]=intArrayFromString;function intArrayToString(array){var ret=[];for(var i=0;i<array.length;i++){var chr=array[i];if(chr>255){chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}Module["intArrayToString"]=intArrayToString;function writeStringToMemory(string,buffer,dontAddNull){var array=intArrayFromString(string,dontAddNull);var i=0;while(i<array.length){var chr=array[i];HEAP8[buffer+i>>0]=chr;i=i+1}}Module["writeStringToMemory"]=writeStringToMemory;function writeArrayToMemory(array,buffer){for(var i=0;i<array.length;i++){HEAP8[buffer++>>0]=array[i]}}Module["writeArrayToMemory"]=writeArrayToMemory;function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i<str.length;++i){HEAP8[buffer++>>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}Module["writeAsciiToMemory"]=writeAsciiToMemory;function unSign(value,bits,ignore){if(value>=0){return value}return bits<=32?2*Math.abs(1<<bits-1)+value:Math.pow(2,bits)+value}function reSign(value,bits,ignore){if(value<=0){return value}var half=bits<=32?Math.abs(1<<bits-1):Math.pow(2,bits-1);if(value>=half&&(bits<=32||value>half)){value=-2*half+value}return value}if(!Math["imul"]||Math["imul"](4294967295,5)!==-5)Math["imul"]=function imul(a,b){var ah=a>>>16;var al=a&65535;var bh=b>>>16;var bl=b&65535;return al*bl+(ah*bl+al*bh<<16)|0};Math.imul=Math["imul"];if(!Math["clz32"])Math["clz32"]=(function(x){x=x>>>0;for(var i=0;i<32;i++){if(x&1<<31-i)return i}return 32});Math.clz32=Math["clz32"];var Math_abs=Math.abs;var Math_cos=Math.cos;var Math_sin=Math.sin;var Math_tan=Math.tan;var Math_acos=Math.acos;var Math_asin=Math.asin;var Math_atan=Math.atan;var Math_atan2=Math.atan2;var Math_exp=Math.exp;var Math_log=Math.log;var Math_sqrt=Math.sqrt;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_pow=Math.pow;var Math_imul=Math.imul;var Math_fround=Math.fround;var Math_min=Math.min;var Math_clz32=Math.clz32;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}Module["addRunDependency"]=addRunDependency;function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["removeRunDependency"]=removeRunDependency;Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var ASM_CONSTS=[];STATIC_BASE=8;STATICTOP=STATIC_BASE+25856;__ATINIT__.push();allocate([0,255,0,255,0,255,0,255,0,255,0,254,1,0,1,255,0,254,0,253,2,0,1,255,0,254,0,253,3,0,1,255,0,0,206,64,0,0,200,64,0,0,184,64,0,0,170,64,0,0,162,64,0,0,154,64,0,0,144,64,0,0,140,64,0,0,156,64,0,0,150,64,0,0,146,64,0,0,142,64,0,0,156,64,0,0,148,64,0,0,138,64,0,0,144,64,0,0,140,64,0,0,148,64,0,0,152,64,0,0,142,64,0,0,112,64,0,0,112,64,0,0,112,64,0,0,112,64,0,0,112,64,0,0,0,0,224,112,44,15,3,2,1,0,254,237,192,132,70,23,4,0,255,252,226,155,61,11,2,0,250,245,234,203,71,50,42,38,35,33,31,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,179,99,0,0,0,0,0,0,232,11,0,0,240,11,0,0,0,12,0,0,0,0,0,0,32,12,0,0,72,12,0,0,152,12,0,0,0,0,0,0,32,0,10,0,20,46,100,1,56,13,0,0,120,14,0,0,184,14,0,0,208,14,0,0,112,15,0,0,184,15,0,0,0,16,0,0,0,0,0,0,32,0,16,0,102,38,171,1,24,16,0,0,24,18,0,0,88,18,0,0,120,18,0,0,120,19,0,0,192,19,0,0,8,20,0,0,0,0,0,0,92,202,190,216,182,223,154,226,156,230,120,236,122,244,204,252,52,3,134,11,136,19,100,25,102,29,74,32,66,39,164,53,249,247,246,245,244,234,210,202,201,200,197,174,82,59,56,55,54,46,22,12,11,10,9,7,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,48,20,0,0,56,20,0,0,120,0,0,0,0,0,0,0,128,64,0,0,0,0,0,0,232,158,10,0,0,0,0,0,230,0,0,0,0,0,0,0,243,221,192,181,0,0,0,0,100,0,240,0,32,0,100,0,205,60,0,48,0,32,0,0,171,85,0,0,0,0,0,0,192,128,64,0,0,0,0,0,205,154,102,51,0,0,0,0,213,171,128,85,43,0,0,0,224,192,160,128,96,64,32,0,100,40,16,7,3,1,0,0,253,250,244,233,212,182,150,131,120,110,98,85,72,60,49,40,32,25,19,15,13,11,9,8,7,6,5,4,3,2,1,0,210,208,206,203,199,193,183,168,142,104,74,52,37,27,20,14,10,6,4,2,0,0,0,0,223,201,183,167,152,138,124,111,98,88,79,70,62,56,50,44,39,35,31,27,24,21,18,16,14,12,10,8,6,4,3,2,1,0,0,0,0,0,0,0,188,176,155,138,119,97,67,43,26,10,0,0,0,0,0,0,165,119,80,61,47,35,27,20,14,9,4,0,0,0,0,0,113,63,0,0,0,0,0,0,125,51,26,18,15,12,11,10,9,8,7,6,5,4,3,2,1,0,198,105,45,22,15,12,11,10,9,8,7,6,5,4,3,2,1,0,213,162,116,83,59,43,32,24,18,15,12,9,7,6,5,3,2,0,239,187,116,59,28,16,11,10,9,8,7,6,5,4,3,2,1,0,250,229,188,135,86,51,30,19,13,10,8,6,5,4,3,2,1,0,249,235,213,185,156,128,103,83,66,53,42,33,26,21,17,13,10,0,254,249,235,206,164,118,77,46,27,16,10,7,5,4,3,2,1,0,255,253,249,239,220,191,156,119,85,57,37,23,15,10,6,4,2,0,255,253,251,246,237,223,203,179,152,124,98,75,55,40,29,21,15,0,255,254,253,247,220,162,106,67,42,28,18,12,9,6,4,3,2,0,0,0,0,0,241,190,178,132,87,74,41,14,0,223,193,157,140,106,57,39,18,0,0,0,0,0,0,0,128,0,214,42,0,235,128,21,0,244,184,72,11,0,248,214,128,42,7,0,248,225,170,80,25,5,0,251,236,198,126,54,18,3,0,250,238,211,159,82,35,15,5,0,250,231,203,168,128,88,53,25,6,0,252,238,216,185,148,108,71,40,18,4,0,253,243,225,199,166,128,90,57,31,13,3,0,254,246,233,212,183,147,109,73,44,23,10,2,0,255,250,240,223,198,166,128,90,58,33,16,6,1,0,255,251,244,231,210,181,146,110,75,46,25,12,5,1,0,255,253,248,238,221,196,164,128,92,60,35,18,8,3,1,0,255,253,249,242,229,208,180,146,110,76,48,27,14,7,3,1,0,129,0,207,50,0,236,129,20,0,245,185,72,10,0,249,213,129,42,6,0,250,226,169,87,27,4,0,251,233,194,130,62,20,4,0,250,236,207,160,99,47,17,3,0,255,240,217,182,131,81,41,11,1,0,255,254,233,201,159,107,61,20,2,1,0,255,249,233,206,170,128,86,50,23,7,1,0,255,250,238,217,186,148,108,70,39,18,6,1,0,255,252,243,226,200,166,128,90,56,30,13,4,1,0,255,252,245,231,209,180,146,110,76,47,25,11,4,1,0,255,253,248,237,219,194,163,128,93,62,37,19,8,3,1,0,255,254,250,241,226,205,177,145,111,79,51,30,15,6,2,1,0,129,0,203,54,0,234,129,23,0,245,184,73,10,0,250,215,129,41,5,0,252,232,173,86,24,3,0,253,240,200,129,56,15,2,0,253,244,217,164,94,38,10,1,0,253,245,226,189,132,71,27,7,1,0,253,246,231,203,159,105,56,23,6,1,0,255,248,235,213,179,133,85,47,19,5,1,0,255,254,243,221,194,159,117,70,37,12,2,1,0,255,254,248,234,208,171,128,85,48,22,8,2,1,0,255,254,250,240,220,189,149,107,67,36,16,6,2,1,0,255,254,251,243,227,201,166,128,90,55,29,13,5,2,1,0,255,254,252,246,234,213,183,147,109,73,43,22,10,4,2,1,0,130,0,200,58,0,231,130,26,0,244,184,76,12,0,249,214,130,43,6,0,252,232,173,87,24,3,0,253,241,203,131,56,14,2,0,254,246,221,167,94,35,8,1,0,254,249,232,193,130,65,23,5,1,0,255,251,239,211,162,99,45,15,4,1,0,255,251,243,223,186,131,74,33,11,3,1,0,255,252,245,230,202,158,105,57,24,8,2,1,0,255,253,247,235,214,179,132,84,44,19,7,2,1,0,255,254,250,240,223,196,159,112,69,36,15,6,2,1,0,255,254,253,245,231,209,176,136,93,55,27,11,3,2,1,0,255,254,253,252,239,221,194,158,117,76,42,18,4,3,2,1,0,0,0,2,5,9,14,20,27,35,44,54,65,77,90,104,119,135,0,0,0,0,0,0,0,254,49,67,77,82,93,99,198,11,18,24,31,36,45,255,46,66,78,87,94,104,208,14,21,32,42,51,66,255,94,104,109,112,115,118,248,53,69,80,88,95,102,0,0,0,0,0,0,0,32,254,31,246,31,234,31,216,31,194,31,168,31,136,31,98,31,58,31,10,31,216,30,160,30,98,30,34,30,220,29,144,29,66,29,238,28,150,28,58,28,216,27,114,27,10,27,156,26,42,26,180,25,58,25,188,24,60,24,182,23,46,23,160,22,16,22,126,21,232,20,78,20,176,19,16,19,110,18,200,17,30,17,116,16,198,15,22,15,100,14,174,13,248,12,64,12,132,11,200,10,10,10,74,9,138,8,198,7,2,7,62,6,120,5,178,4,234,3,34,3,90,2,146,1,202,0,0,0,54,255,110,254,166,253,222,252,22,252,78,251,136,250,194,249,254,248,58,248,118,247,182,246,246,245,56,245,124,244,192,243,8,243,82,242,156,241,234,240,58,240,140,239,226,238,56,238,146,237,240,236,80,236,178,235,24,235,130,234,240,233,96,233,210,232,74,232,196,231,68,231,198,230,76,230,214,229,100,229,246,228,142,228,40,228,198,227,106,227,18,227,190,226,112,226,36,226,222,225,158,225,96,225,40,225,246,224,198,224,158,224,120,224,88,224,62,224,40,224,22,224,10,224,2,224,0,224,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,255,1,255,2,254,2,254,3,253,0,1,0,1,255,2,255,2,254,3,254,3,0,2,255,255,255,0,0,1,1,0,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,255,2,1,0,1,1,0,0,255,255,0,0,0,0,0,0,1,255,0,1,255,0,255,1,254,2,254,254,2,253,2,3,253,252,3,252,4,4,251,5,250,251,6,249,6,5,8,247,0,0,1,0,0,0,0,0,0,0,255,1,0,0,1,255,0,1,255,255,1,255,2,1,255,2,254,254,2,254,2,2,3,253,0,1,0,0,0,0,0,0,1,0,1,0,0,1,255,1,0,0,2,1,255,2,255,255,2,255,2,2,255,3,254,254,254,3,0,1,0,0,1,0,1,255,2,255,2,255,2,3,254,3,254,254,4,4,253,5,253,252,6,252,6,5,251,8,250,251,249,9,42,175,213,201,207,255,64,0,17,0,99,255,97,1,16,254,163,0,39,43,189,86,217,255,6,0,91,0,86,255,186,0,23,0,128,252,192,24,216,77,237,255,220,255,102,0,167,255,232,255,72,1,73,252,8,10,37,62,0,0,0,0,0,0,135,199,61,201,64,0,128,0,134,255,36,0,54,1,0,253,72,2,51,36,69,69,12,0,128,0,18,0,114,255,32,1,139,255,159,252,27,16,123,56,104,2,13,200,246,255,39,0,58,0,210,255,172,255,120,0,184,0,197,254,227,253,4,5,4,21,64,35,0,0,0,0,230,62,198,196,243,255,0,0,20,0,26,0,5,0,225,255,213,255,252,255,65,0,90,0,7,0,99,255,8,255,212,255,81,2,47,6,52,10,199,12,228,87,5,197,3,0,242,255,236,255,241,255,2,0,25,0,37,0,25,0,240,255,185,255,149,255,177,255,50,0,36,1,111,2,214,3,8,5,184,5,148,107,103,196,17,0,12,0,8,0,1,0,246,255,234,255,226,255,224,255,234,255,3,0,44,0,100,0,168,0,243,0,61,1,125,1,173,1,199,1,189,0,168,253,105,2,103,119,117,0,97,255,210,251,8,116,52,0,221,0,168,246,116,110,252,255,17,2,234,242,229,102,208,255,246,2,140,240,165,93,176,255,137,3,117,239,6,83,157,255,204,3,130,239,102,71,149,255,199,3,139,240,39,59,153,255,128,3,97,242,174,46,165,255,5,3,207,244,94,34,185,255,99,2,161,247,152,22,210,255,169,1,161,250,180,11,0,0,157,62,0,64,94,62,0,192,4,62,0,128,237,62,0,64,137,62,0,0,0,0,0,192,76,63,0,0,205,61,0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,25,23,2,0,0,0,0,0,126,124,119,109,87,41,19,9,4,2,0,0,0,0,0,0,24,78,0,0,216,80,0,0,148,83,0,0,76,86,0,0,0,89,0,0,176,91,0,0,92,94,0,0,196,95,0,0,128,96,0,0,244,96,0,0,64,97,0,0,120,97,0,0,152,97,0,0,176,97,0,0,188,97,0,0,0,0,0,0,149,139,0,0,55,152,0,0,255,165,0,0,4,181,0,0,103,197,0,0,69,215,0,0,193,234,0,0,255,255,0,0,112,20,0,0,0,0,0,0,72,127,65,129,66,128,65,128,64,128,62,128,64,128,64,128,92,78,92,79,92,78,90,79,116,41,115,40,114,40,132,26,132,26,145,17,161,12,176,10,177,11,24,179,48,138,54,135,54,132,53,134,56,133,55,132,55,132,61,114,70,96,74,88,75,88,87,74,89,66,91,67,100,59,108,50,120,40,122,37,97,43,78,50,83,78,84,81,88,75,86,74,87,71,90,73,93,74,93,74,109,40,114,36,117,34,117,34,143,17,145,18,146,19,162,12,165,10,178,7,189,6,190,8,177,9,23,178,54,115,63,102,66,98,69,99,74,89,71,91,73,91,78,89,86,80,92,66,93,64,102,59,103,60,104,60,117,52,123,44,138,35,133,31,97,38,77,45,61,90,93,60,105,42,107,41,110,45,116,38,113,38,112,38,124,26,132,27,136,19,140,20,155,14,159,16,158,18,170,13,177,10,187,8,192,6,175,9,159,10,21,178,59,110,71,86,75,85,84,83,91,66,88,73,87,72,92,75,98,72,105,58,107,54,115,52,114,55,112,56,129,51,132,40,150,33,140,29,98,35,77,42,42,121,96,66,108,43,111,40,117,44,123,32,120,36,119,33,127,33,134,34,139,21,147,23,152,20,158,25,154,26,166,21,173,16,184,13,184,10,150,13,139,15,22,178,63,114,74,82,84,83,92,82,103,62,96,72,96,67,101,73,107,72,113,55,118,52,125,52,118,52,117,55,135,49,137,39,157,32,145,29,97,33,77,40,0,0,102,63,0,0,76,63,0,0,38,63,0,0,0,63,0,134,107,63,0,20,46,63,0,112,189,62,0,208,76,62,2,1,0,0,0,0,0,0,0,8,13,16,19,21,23,24,26,27,28,29,30,31,32,32,33,34,34,35,36,36,37,37,6,0,0,0,4,0,0,0,3,0,0,0,0,0,0,0,0,15,8,7,4,11,12,3,2,13,10,5,6,9,14,1,0,9,6,3,4,5,8,1,2,7,0,0,0,0,0,0,6,0,3,0,7,3,0,1,10,0,2,6,18,10,12,0,4,0,2,0,0,0,9,4,7,4,0,3,12,7,7,0,210,6,138,58,171,152,0,0,198,26,169,100,246,216,0,0,71,56,43,30,21,12,6,0,199,165,144,124,109,96,84,71,61,51,42,32,23,15,8,0,241,225,211,199,187,175,164,153,142,132,123,114,105,96,88,80,72,64,57,50,44,38,33,29,24,20,16,12,9,5,2,0,4,6,24,7,5,0,0,2,0,0,12,28,41,13,252,247,15,42,25,14,1,254,62,41,247,246,37,65,252,3,250,4,66,7,248,16,14,38,253,33,13,22,39,23,12,255,36,64,27,250,249,10,55,43,17,1,1,8,1,1,6,245,74,53,247,244,55,76,244,8,253,3,93,27,252,26,39,59,3,248,2,0,77,11,9,248,22,44,250,7,40,9,26,3,9,249,20,101,249,4,3,248,42,26,0,241,33,68,2,23,254,55,46,254,15,3,255,21,16,41,250,27,61,39,5,245,42,88,4,1,254,60,65,6,252,255,251,73,56,1,247,19,94,29,247,0,12,99,6,4,8,237,102,46,243,3,2,13,3,2,9,235,84,72,238,245,46,104,234,8,18,38,48,23,0,240,70,83,235,11,5,245,117,22,248,250,23,117,244,3,3,248,95,28,4,246,15,77,60,241,255,4,124,2,252,3,38,84,24,231,2,13,42,13,31,21,252,56,46,255,255,35,79,243,19,249,65,88,247,242,20,4,81,49,227,20,0,75,3,239,5,247,44,92,248,1,253,22,69,31,250,95,41,244,5,39,67,16,252,1,0,250,120,55,220,243,44,122,4,232,81,5,11,3,7,2,0,9,10,88,12,35,60,83,108,132,157,180,206,228,15,32,55,77,101,125,151,175,201,225,19,42,66,89,114,137,162,184,209,230,12,25,50,72,97,120,147,172,200,223,26,44,69,90,114,135,159,180,205,225,13,22,53,80,106,130,156,180,205,228,15,25,44,64,90,115,142,168,196,222,19,24,62,82,100,120,145,168,190,214,22,31,50,79,103,120,151,170,203,227,21,29,45,65,106,124,150,171,196,224,30,49,75,97,121,142,165,186,209,229,19,25,52,70,93,116,143,166,192,219,26,34,62,75,97,118,145,167,194,217,25,33,56,70,91,113,143,165,196,223,21,34,51,72,97,117,145,171,196,222,20,29,50,67,90,117,144,168,197,221,22,31,48,66,95,117,146,168,196,222,24,33,51,77,116,134,158,180,200,224,21,28,70,87,106,124,149,170,194,217,26,33,53,64,83,117,152,173,204,225,27,34,65,95,108,129,155,174,210,225,20,26,72,99,113,131,154,176,200,219,34,43,61,78,93,114,155,177,205,229,23,29,54,97,124,138,163,179,209,229,30,38,56,89,118,129,158,178,200,231,21,29,49,63,85,111,142,163,193,222,27,48,77,103,133,158,179,196,215,232,29,47,74,99,124,151,176,198,220,237,33,42,61,76,93,121,155,174,207,225,29,53,87,112,136,154,170,188,208,227,24,30,52,84,131,150,166,186,203,229,37,48,64,84,104,118,156,177,201,230,212,178,148,129,108,96,85,82,79,77,61,59,57,56,51,49,48,45,42,41,40,38,36,34,31,30,21,12,10,3,1,0,255,245,244,236,233,225,217,203,190,176,175,161,149,136,125,114,102,91,81,71,60,52,43,35,28,20,19,18,12,11,5,0,179,138,140,148,151,149,153,151,163,116,67,82,59,92,72,100,89,92,0,0,0,0,0,0,16,0,0,0,0,99,66,36,36,34,36,34,34,34,34,83,69,36,52,34,116,102,70,68,68,176,102,68,68,34,65,85,68,84,36,116,141,152,139,170,132,187,184,216,137,132,249,168,185,139,104,102,100,68,68,178,218,185,185,170,244,216,187,187,170,244,187,187,219,138,103,155,184,185,137,116,183,155,152,136,132,217,184,184,170,164,217,171,155,139,244,169,184,185,170,164,216,223,218,138,214,143,188,218,168,244,141,136,155,170,168,138,220,219,139,164,219,202,216,137,168,186,246,185,139,116,185,219,185,138,100,100,134,100,102,34,68,68,100,68,168,203,221,218,168,167,154,136,104,70,164,246,171,137,139,137,155,218,219,139,255,254,253,238,14,3,2,1,0,255,254,252,218,35,3,2,1,0,255,254,250,208,59,4,2,1,0,255,254,246,194,71,10,2,1,0,255,252,236,183,82,8,2,1,0,255,252,235,180,90,17,2,1,0,255,248,224,171,97,30,4,1,0,255,254,236,173,95,37,7,1,0,255,255,255,131,6,145,255,255,255,255,255,236,93,15,96,255,255,255,255,255,194,83,25,71,221,255,255,255,255,162,73,34,66,162,255,255,255,210,126,73,43,57,173,255,255,255,201,125,71,48,58,130,255,255,255,166,110,73,57,62,104,210,255,255,251,123,65,55,68,100,171,255,250,0,3,0,6,0,3,0,3,0,3,0,4,0,3,0,3,0,3,0,205,1,0,0,7,23,38,54,69,85,100,116,131,147,162,178,193,208,223,239,13,25,41,55,69,83,98,112,127,142,157,171,187,203,220,236,15,21,34,51,61,78,92,106,126,136,152,167,185,205,225,240,10,21,36,50,63,79,95,110,126,141,157,173,189,205,221,237,17,20,37,51,59,78,89,107,123,134,150,164,184,205,224,240,10,15,32,51,67,81,96,112,129,142,158,173,189,204,220,236,8,21,37,51,65,79,98,113,126,138,155,168,179,192,209,218,12,15,34,55,63,78,87,108,118,131,148,167,185,203,219,236,16,19,32,36,56,79,91,108,118,136,154,171,186,204,220,237,11,28,43,58,74,89,105,120,135,150,165,180,196,211,226,241,6,16,33,46,60,75,92,107,123,137,156,169,185,199,214,225,11,19,30,44,57,74,89,105,121,135,152,169,186,202,218,234,12,19,29,46,57,71,88,100,120,132,148,165,182,199,216,233,17,23,35,46,56,77,92,106,123,134,152,167,185,204,222,237,14,17,45,53,63,75,89,107,115,132,151,171,188,206,221,240,9,16,29,40,56,71,88,103,119,137,154,171,189,205,222,237,16,19,36,48,57,76,87,105,118,132,150,167,185,202,218,236,12,17,29,54,71,81,94,104,126,136,149,164,182,201,221,237,15,28,47,62,79,97,115,129,142,155,168,180,194,208,223,238,8,14,30,45,62,78,94,111,127,143,159,175,192,207,223,239,17,30,49,62,79,92,107,119,132,145,160,174,190,204,220,235,14,19,36,45,61,76,91,108,121,138,154,172,189,205,222,238,12,18,31,45,60,76,91,107,123,138,154,171,187,204,221,236,13,17,31,43,53,70,83,103,114,131,149,167,185,203,220,237,17,22,35,42,58,78,93,110,125,139,155,170,188,206,224,240,8,15,34,50,67,83,99,115,131,146,162,178,193,209,224,239,13,16,41,66,73,86,95,111,128,137,150,163,183,206,225,241,17,25,37,52,63,75,92,102,119,132,144,160,175,191,212,231,19,31,49,65,83,100,117,133,147,161,174,187,200,213,227,242,18,31,52,68,88,103,117,126,138,149,163,177,192,207,223,239,16,29,47,61,76,90,106,119,133,147,161,176,193,209,224,240,15,21,35,50,61,73,86,97,110,119,129,141,175,198,218,237,225,204,201,184,183,175,158,154,153,135,119,115,113,110,109,99,98,95,79,68,52,50,48,45,43,32,31,27,18,10,3,0,255,251,235,230,212,201,196,182,167,166,163,151,138,124,110,104,90,78,76,70,69,57,45,34,24,21,11,6,5,4,3,0,175,148,160,176,178,173,174,164,177,174,196,182,198,192,182,68,62,66,60,72,117,85,90,118,136,151,142,160,142,155,0,0,0,0,0,0,0,0,0,1,100,102,102,68,68,36,34,96,164,107,158,185,180,185,139,102,64,66,36,34,34,0,1,32,208,139,141,191,152,185,155,104,96,171,104,166,102,102,102,132,1,0,0,0,0,16,16,0,80,109,78,107,185,139,103,101,208,212,141,139,173,153,123,103,36,0,0,0,0,0,0,1,48,0,0,0,0,0,0,32,68,135,123,119,119,103,69,98,68,103,120,118,118,102,71,98,134,136,157,184,182,153,139,134,208,168,248,75,189,143,121,107,32,49,34,34,34,0,17,2,210,235,139,123,185,137,105,134,98,135,104,182,100,183,171,134,100,70,68,70,66,66,34,131,64,166,102,68,36,2,1,0,134,166,102,68,34,34,66,132,212,246,158,139,107,107,87,102,100,219,125,122,137,118,103,132,114,135,137,105,171,106,50,34,164,214,141,143,185,151,121,103,192,34,0,0,0,0,0,1,208,109,74,187,134,249,159,137,102,110,154,118,87,101,119,101,0,2,0,36,36,66,68,35,96,164,102,100,36,0,2,33,167,138,174,102,100,84,2,2,100,107,120,119,36,197,24,0,255,254,253,244,12,3,2,1,0,255,254,252,224,38,3,2,1,0,255,254,251,209,57,4,2,1,0,255,254,244,195,69,4,2,1,0,255,251,232,184,84,7,2,1,0,255,254,240,186,86,14,2,1,0,255,254,239,178,91,30,5,1,0,255,248,227,177,100,19,2,1,0,255,255,255,156,4,154,255,255,255,255,255,227,102,15,92,255,255,255,255,255,213,83,24,72,236,255,255,255,255,150,76,33,63,214,255,255,255,190,121,77,43,55,185,255,255,255,245,137,71,43,59,139,255,255,255,255,131,66,50,66,107,194,255,255,166,116,76,55,53,125,255,255,100,0,3,0,40,0,3,0,3,0,3,0,5,0,14,0,14,0,10,0,11,0,3,0,8,0,9,0,7,0,3,0,91,1,0,0,0,0,0,0,203,150,0,0,0,0,0,0,215,195,166,125,110,82,0,0,255,255,0,0,0,0,0,0,184,126,154,121,0,0,0,0,154,121,102,102,0,0,0,0,184,126,51,115,0,0,0,0,15,0,0,0,10,0,0,0,5,0,0,0,0,0,0,0,128,187,0,0,120,0,0,0,21,0,0,0,21,0,0,0,0,154,89,63,0,0,0,0,0,0,128,63,0,0,128,63,224,20,0,0,3,0,0,0,8,0,0,0,120,0,0,0,11,0,0,0,16,21,0,0,248,21,0,0,40,22,0,0,128,7,0,0,3,0,0,0,8,24,0,0,64,24,0,0,120,24,0,0,176,24,0,0,232,24,0,0,136,1,0,0,8,53,0,0,224,53,0,0,104,55,0,0,0,0,0,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,10,0,12,0,14,0,16,0,20,0,24,0,28,0,34,0,40,0,48,0,60,0,78,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,90,80,75,69,63,56,49,40,34,29,20,18,10,0,0,0,0,0,0,0,0,110,100,90,84,78,71,65,58,51,45,39,32,26,20,12,0,0,0,0,0,0,118,110,103,93,86,80,75,70,65,59,53,47,40,31,23,15,4,0,0,0,0,126,119,112,104,95,89,83,78,72,66,60,54,47,39,32,25,17,12,1,0,0,134,127,120,114,103,97,91,85,78,72,66,60,54,47,41,35,29,23,16,10,1,144,137,130,124,113,107,101,95,88,82,76,70,64,57,51,45,39,33,26,15,1,152,145,138,132,123,117,111,105,98,92,86,80,74,67,61,55,49,43,36,20,1,162,155,148,142,133,127,121,115,108,102,96,90,84,77,71,65,59,53,46,30,1,172,165,158,152,143,137,131,125,118,112,106,100,94,87,81,75,69,63,56,45,20,200,200,200,200,200,200,200,200,198,193,188,183,178,173,168,163,158,153,148,129,104,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,8,0,8,0,8,0,16,0,16,0,16,0,21,0,21,0,24,0,29,0,34,0,36,0,0,0,0,0,0,0,106,28,141,56,82,187,30,58,8,105,220,58,130,237,87,59,137,99,178,59,3,42,5,60,48,220,57,60,180,62,119,60,28,163,158,60,209,242,197,60,254,134,241,60,155,171,16,61,5,173,42,61,132,194,70,61,83,230,100,61,17,137,130,61,135,159,147,61,203,178,165,61,209,190,184,61,58,191,204,61,84,175,225,61,20,138,247,61,14,37,7,62,217,244,18,62,95,49,31,62,104,215,43,62,138,227,56,62,48,82,70,62,148,31,84,62,191,71,98,62,142,198,112,62,176,151,127,62,82,91,135,62,96,15,143,62,152,229,150,62,121,219,158,62,112,238,166,62,216,27,175,62,251,96,183,62,17,187,191,62,70,39,200,62,183,162,208,62,120,42,217,62,148,187,225,62,12,83,234,62,222,237,242,62,6,137,251,62,190,16,2,63,31,90,6,63,36,159,10,63,80,222,14,63,43,22,19,63,65,69,23,63,37,106,27,63,115,131,31,63,206,143,35,63,230,141,39,63,116,124,43,63,63,90,47,63,25,38,51,63,231,222,54,63,153,131,58,63,51,19,62,63,197,140,65,63,119,239,68,63,127,58,72,63,39,109,75,63,206,134,78,63,229,134,81,63,241,108,84,63,142,56,87,63,105,233,89,63,69,127,92,63,250,249,94,63,115,89,97,63,175,157,99,63,193,198,101,63,207,212,103,63,17,200,105,63,210,160,107,63,110,95,109,63,80,4,111,63,244,143,112,63,230,2,114,63,189,93,115,63,31,161,116,63,191,205,117,63,87,228,118,63,176,229,119,63,151,210,120,63,227,171,121,63,115,114,122,63,39,39,123,63,231,202,123,63,157,94,124,63,53,227,124,63,156,89,125,63,189,194,125,63,134,31,126,63,222,112,126,63,171,183,126,63,207,244,126,63,38,41,127,63,134,85,127,63,190,122,127,63,150,153,127,63,204,178,127,63,20,199,127,63,28,215,127,63,130,227,127,63,221,236,127,63,182,243,127,63,138,248,127,63,200,251,127,63,214,253,127,63,7,255,127,63,165,255,127,63,232,255,127,63,253,255,127,63,0,0,128,63,224,1,0,0,135,136,8,59,255,255,255,255,5,0,96,0,3,0,32,0,4,0,8,0,2,0,4,0,4,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,88,74,0,0,136,56,0,0,0,0,0,0,240,0,0,0,137,136,136,59,1,0,0,0,5,0,48,0,3,0,16,0,4,0,4,0,4,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,120,72,0,0,136,56,0,0,0,0,0,0,120,0,0,0,136,136,8,60,2,0,0,0,5,0,24,0,3,0,8,0,2,0,4,0,4,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,136,71,0,0,136,56,0,0,0,0,0,0,60,0,0,0,137,136,136,60,3,0,0,0,5,0,12,0,3,0,4,0,4,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,56,0,0,136,56,0,0,0,0,0,0,255,255,127,63,142,255,127,63,106,254,127,63,147,252,127,63,7,250,127,63,200,246,127,63,214,242,127,63,48,238,127,63,214,232,127,63,200,226,127,63,7,220,127,63,147,212,127,63,107,204,127,63,143,195,127,63,0,186,127,63,189,175,127,63,199,164,127,63,29,153,127,63,192,140,127,63,176,127,127,63,236,113,127,63,118,99,127,63,75,84,127,63,110,68,127,63,222,51,127,63,154,34,127,63,163,16,127,63,250,253,126,63,157,234,126,63,141,214,126,63,203,193,126,63,86,172,126,63,46,150,126,63,83,127,126,63,198,103,126,63,134,79,126,63,148,54,126,63,239,28,126,63,152,2,126,63,143,231,125,63,211,203,125,63,102,175,125,63,70,146,125,63,116,116,125,63,241,85,125,63,188,54,125,63,213,22,125,63,60,246,124,63,242,212,124,63,246,178,124,63,73,144,124,63,235,108,124,63,219,72,124,63,27,36,124,63,169,254,123,63,135,216,123,63,180,177,123,63,48,138,123,63,252,97,123,63,23,57,123,63,130,15,123,63,61,229,122,63,72,186,122,63,162,142,122,63,77,98,122,63,72,53,122,63,148,7,122,63,48,217,121,63,29,170,121,63,90,122,121,63,233,73,121,63,200,24,121,63,249,230,120,63,123,180,120,63,78,129,120,63,115,77,120,63,234,24,120,63,178,227,119,63,205,173,119,63,58,119,119,63,249,63,119,63,10,8,119,63,110,207,118,63,37,150,118,63,47,92,118,63,140,33,118,63,60,230,117,63,64,170,117,63,151,109,117,63,66,48,117,63,65,242,116,63,148,179,116,63,59,116,116,63,55,52,116,63,135,243,115,63,44,178,115,63,38,112,115,63,118,45,115,63,26,234,114,63,20,166,114,63,100,97,114,63,10,28,114,63,5,214,113,63,87,143,113,63,0,72,113,63,255,255,112,63,85,183,112,63,2,110,112,63,6,36,112,63,98,217,111,63,21,142,111,63,32,66,111,63,132,245,110,63,63,168,110,63,83,90,110,63,192,11,110,63,134,188,109,63,165,108,109,63,29,28,109,63,239,202,108,63,27,121,108,63,161,38,108,63,128,211,107,63,187,127,107,63,80,43,107,63,64,214,106,63,140,128,106,63,50,42,106,63,53,211,105,63,147,123,105,63,77,35,105,63,100,202,104,63,216,112,104,63,168,22,104,63,213,187,103,63,96,96,103,63,72,4,103,63,143,167,102,63,51,74,102,63,54,236,101,63,151,141,101,63,87,46,101,63,119,206,100,63,245,109,100,63,212,12,100,63,18,171,99,63,177,72,99,63,176,229,98,63,16,130,98,63,209,29,98,63,243,184,97,63,119,83,97,63,92,237,96,63,164,134,96,63,78,31,96,63,91,183,95,63,203,78,95,63,158,229,94,63,213,123,94,63,112,17,94,63,110,166,93,63,210,58,93,63,154,206,92,63,198,97,92,63,89,244,91,63,81,134,91,63,174,23,91,63,114,168,90,63,157,56,90,63,46,200,89,63,39,87,89,63,135,229,88,63,79,115,88,63,127,0,88,63,23,141,87,63,24,25,87,63,130,164,86,63,86,47,86,63,147,185,85,63,58,67,85,63,75,204,84,63,199,84,84,63,174,220,83,63,1,100,83,63,191,234,82,63,233,112,82,63,127,246,81,63,130,123,81,63,242,255,80,63,207,131,80,63,26,7,80,63,210,137,79,63,250,11,79,63,144,141,78,63,148,14,78,63,9,143,77,63,237,14,77,63,65,142,76,63,5,13,76,63,59,139,75,63,225,8,75,63,249,133,74,63,131,2,74,63,127,126,73,63,238,249,72,63,207,116,72,63,36,239,71,63,237,104,71,63,41,226,70,63,218,90,70,63,0,211,69,63,155,74,69,63,172,193,68,63,50,56,68,63,47,174,67,63,162,35,67,63,141,152,66,63,239,12,66,63,200,128,65,63,26,244,64,63,229,102,64,63,40,217,63,63,229,74,63,63,27,188,62,63,204,44,62,63,247,156,61,63,157,12,61,63,190,123,60,63,92,234,59,63,117,88,59,63,10,198,58,63,29,51,58,63,173,159,57,63,187,11,57,63,71,119,56,63,81,226,55,63,218,76,55,63,227,182,54,63,107,32,54,63,116,137,53,63,253,241,52,63,7,90,52,63,147,193,51,63,160,40,51,63,48,143,50,63,66,245,49,63,216,90,49,63,241,191,48,63,142,36,48,63,175,136,47,63,85,236,46,63,129,79,46,63,50,178,45,63,105,20,45,63,39,118,44,63,107,215,43,63,55,56,43,63,139,152,42,63,103,248,41,63,204,87,41,63,186,182,40,63,50,21,40,63,51,115,39,63,191,208,38,63,214,45,38,63,121,138,37,63,167,230,36,63,97,66,36,63,169,157,35,63,125,248,34,63,223,82,34,63,207,172,33,63,77,6,33,63,91,95,32,63,248,183,31,63,37,16,31,63,226,103,30,63,48,191,29,63,16,22,29,63,129,108,28,63,132,194,27,63,26,24,27,63,67,109,26,63,0,194,25,63,81,22,25,63,54,106,24,63,177,189,23,63,193,16,23,63,103,99,22,63,163,181,21,63,118,7,21,63,225,88,20,63,228,169,19,63,127,250,18,63,179,74,18,63,128,154,17,63,231,233,16,63,232,56,16,63,132,135,15,63,187,213,14,63,142,35,14,63,254,112,13,63,10,190,12,63,179,10,12,63,250,86,11,63,223,162,10,63,99,238,9,63,134,57,9,63,73,132,8,63,172,206,7,63,175,24,7,63,84,98,6,63,155,171,5,63,131,244,4,63,15,61,4,63,61,133,3,63,15,205,2,63,134,20,2,63,161,91,1,63,97,162,0,63,143,209,255,62,167,93,254,62,14,233,252,62,194,115,251,62,198,253,249,62,27,135,248,62,193,15,247,62,186,151,245,62,6,31,244,62,168,165,242,62,158,43,241,62,236,176,239,62,145,53,238,62,144,185,236,62,232,60,235,62,154,191,233,62,169,65,232,62,21,195,230,62,223,67,229,62,8,196,227,62,145,67,226,62,124,194,224,62,200,64,223,62,120,190,221,62,140,59,220,62,6,184,218,62,230,51,217,62,46,175,215,62,223,41,214,62,249,163,212,62,125,29,211,62,110,150,209,62,204,14,208,62,151,134,206,62,210,253,204,62,125,116,203,62,153,234,201,62,39,96,200,62,40,213,198,62,159,73,197,62,138,189,195,62,236,48,194,62,198,163,192,62,25,22,191,62,230,135,189,62,45,249,187,62,241,105,186,62,50,218,184,62,241,73,183,62,47,185,181,62,238,39,180,62,47,150,178,62,242,3,177,62,57,113,175,62,4,222,173,62,86,74,172,62,47,182,170,62,144,33,169,62,122,140,167,62,239,246,165,62,239,96,164,62,124,202,162,62,151,51,161,62,64,156,159,62,122,4,158,62,68,108,156,62,161,211,154,62,145,58,153,62,22,161,151,62,48,7,150,62,225,108,148,62,41,210,146,62,11,55,145,62,135,155,143,62,158,255,141,62,81,99,140,62,162,198,138,62,145,41,137,62,32,140,135,62,80,238,133,62,34,80,132,62,151,177,130,62,176,18,129,62,222,230,126,62,169,167,123,62,195,103,120,62,47,39,117,62,238,229,113,62,4,164,110,62,115,97,107,62,60,30,104,62,98,218,100,62,232,149,97,62,207,80,94,62,26,11,91,62,204,196,87,62,230,125,84,62,107,54,81,62,93,238,77,62,191,165,74,62,146,92,71,62,218,18,68,62,151,200,64,62,206,125,61,62,128,50,58,62,174,230,54,62,93,154,51,62,141,77,48,62,66,0,45,62,125,178,41,62,66,100,38,62,145,21,35,62,110,198,31,62,219,118,28,62,218,38,25,62,109,214,21,62,152,133,18,62,91,52,15,62,186,226,11,62,183,144,8,62,84,62,5,62,148,235,1,62,240,48,253,61,6,138,246,61,113,226,239,61,51,58,233,61,79,145,226,61,207,231,219,61,181,61,213,61,3,147,206,61,192,231,199,61,242,59,193,61,156,143,186,61,195,226,179,61,108,53,173,61,155,135,166,61,85,217,159,61,159,42,153,61,126,123,146,61,246,203,139,61,11,28,133,61,135,215,124,61,70,118,111,61,93,20,98,61,214,177,84,61,185,78,71,61,16,235,57,61,229,134,44,61,64,34,31,61,44,189,17,61,178,87,4,61,181,227,237,60,96,23,211,60,118,74,184,60,11,125,157,60,50,175,130,60,250,193,79,60,254,36,26,60,42,15,201,59,153,167,59,59,46,125,214,185,210,70,113,187,171,222,227,187,166,140,39,188,129,41,93,188,225,98,137,188,160,48,164,188,236,253,190,188,179,202,217,188,224,150,244,188,49,177,7,189,147,22,21,189,140,123,34,189,19,224,47,189,30,68,61,189,165,167,74,189,157,10,88,189,254,108,101,189,190,206,114,189,234,23,128,189,27,200,134,189,237,119,141,189,92,39,148,189,99,214,154,189,253,132,161,189,38,51,168,189,217,224,174,189,17,142,181,189,202,58,188,189,254,230,194,189,170,146,201,189,200,61,208,189,84,232,214,189,74,146,221,189,164,59,228,189,93,228,234,189,114,140,241,189,221,51,248,189,154,218,254,189,82,192,2,190,252,18,6,190,71,101,9,190,50,183,12,190,186,8,16,190,221,89,19,190,152,170,22,190,234,250,25,190,208,74,29,190,71,154,32,190,78,233,35,190,225,55,39,190,0,134,42,190,166,211,45,190,211,32,49,190,131,109,52,190,181,185,55,190,101,5,59,190,147,80,62,190,58,155,65,190,90,229,68,190,240,46,72,190,249,119,75,190,116,192,78,190,93,8,82,190,179,79,85,190,115,150,88,190,156,220,91,190,42,34,95,190,27,103,98,190,109,171,101,190,31,239,104,190,44,50,108,190,148,116,111,190,84,182,114,190,106,247,117,190,211,55,121,190,141,119,124,190,150,182,127,190,117,122,129,190,69,25,131,190,185,183,132,190,208,85,134,190,136,243,135,190,225,144,137,190,218,45,139,190,112,202,140,190,164,102,142,190,116,2,144,190,223,157,145,190,228,56,147,190,129,211,148,190,182,109,150,190,129,7,152,190,226,160,153,190,215,57,155,190,95,210,156,190,121,106,158,190,35,2,160,190,94,153,161,190,38,48,163,190,125,198,164,190,96,92,166,190,206,241,167,190,198,134,169,190,71,27,171,190,80,175,172,190,224,66,174,190,245,213,175,190,143,104,177,190,173,250,178,190,77,140,180,190,110,29,182,190,16,174,183,190,48,62,185,190,207,205,186,190,234,92,188,190,130,235,189,190,148,121,191,190,31,7,193,190,35,148,194,190,159,32,196,190,145,172,197,190,248,55,199,190,211,194,200,190,34,77,202,190,226,214,203,190,19,96,205,190,181,232,206,190,197,112,208,190,66,248,209,190,45,127,211,190,131,5,213,190,67,139,214,190,109,16,216,190,255,148,217,190,249,24,219,190,89,156,220,190,29,31,222,190,70,161,223,190,211,34,225,190,193,163,226,190,16,36,228,190,190,163,229,190,204,34,231,190,56,161,232,190,0,31,234,190,36,156,235,190,162,24,237,190,122,148,238,190,171,15,240,190,51,138,241,190,18,4,243,190,70,125,244,190,207,245,245,190,170,109,247,190,217,228,248,190,88,91,250,190,40,209,251,190,71,70,253,190,181,186,254,190,56,23,0,191,187,208,0,191,228,137,1,191,178,66,2,191,37,251,2,191,59,179,3,191,246,106,4,191,83,34,5,191,83,217,5,191,245,143,6,191,56,70,7,191,29,252,7,191,162,177,8,191,199,102,9,191,140,27,10,191,240,207,10,191,243,131,11,191,147,55,12,191,209,234,12,191,172,157,13,191,36,80,14,191,56,2,15,191,232,179,15,191,50,101,16,191,24,22,17,191,151,198,17,191,176,118,18,191,99,38,19,191,174,213,19,191,145,132,20,191,13,51,21,191,31,225,21,191,200,142,22,191,8,60,23,191,221,232,23,191,72,149,24,191,72,65,25,191,220,236,25,191,4,152,26,191,192,66,27,191,15,237,27,191,240,150,28,191,99,64,29,191,104,233,29,191,254,145,30,191,37,58,31,191,220,225,31,191,35,137,32,191,250,47,33,191,95,214,33,191,82,124,34,191,212,33,35,191,227,198,35,191,127,107,36,191,167,15,37,191,92,179,37,191,157,86,38,191,104,249,38,191,191,155,39,191,160,61,40,191,11,223,40,191,255,127,41,191,125,32,42,191,131,192,42,191,17,96,43,191,39,255,43,191,196,157,44,191,232,59,45,191,146,217,45,191,195,118,46,191,121,19,47,191,180,175,47,191,115,75,48,191,183,230,48,191,127,129,49,191,203,27,50,191,153,181,50,191,234,78,51,191,189,231,51,191,18,128,52,191,232,23,53,191,63,175,53,191,22,70,54,191,110,220,54,191,69,114,55,191,156,7,56,191,113,156,56,191,197,48,57,191,150,196,57,191,230,87,58,191,178,234,58,191,252,124,59,191,194,14,60,191,3,160,60,191,193,48,61,191,250,192,61,191,173,80,62,191,219,223,62,191,131,110,63,191,165,252,63,191,64,138,64,191,83,23,65,191,224,163,65,191,228,47,66,191,96,187,66,191,83,70,67,191,190,208,67,191,158,90,68,191,246,227,68,191,194,108,69,191,5,245,69,191,188,124,70,191,232,3,71,191,137,138,71,191,157,16,72,191,37,150,72,191,32,27,73,191,142,159,73,191,111,35,74,191,193,166,74,191,134,41,75,191,188,171,75,191,99,45,76,191,122,174,76,191,2,47,77,191,250,174,77,191,98,46,78,191,57,173,78,191,126,43,79,191,51,169,79,191,85,38,80,191,230,162,80,191,228,30,81,191,80,154,81,191,40,21,82,191,109,143,82,191,30,9,83,191,59,130,83,191,195,250,83,191,183,114,84,191,22,234,84,191,223,96,85,191,18,215,85,191,176,76,86,191,183,193,86,191,39,54,87,191,0,170,87,191,66,29,88,191,236,143,88,191,254,1,89,191,120,115,89,191,89,228,89,191,162,84,90,191,81,196,90,191,102,51,91,191,226,161,91,191,195,15,92,191,10,125,92,191,183,233,92,191,200,85,93,191,62,193,93,191,24,44,94,191,87,150,94,191,249,255,94,191,255,104,95,191,104,209,95,191,51,57,96,191,98,160,96,191,243,6,97,191,229,108,97,191,58,210,97,191,240,54,98,191,8,155,98,191,128,254,98,191,89,97,99,191,146,195,99,191,44,37,100,191,37,134,100,191,126,230,100,191,55,70,101,191,78,165,101,191,197,3,102,191,154,97,102,191,205,190,102,191,94,27,103,191,77,119,103,191,154,210,103,191,68,45,104,191,75,135,104,191,174,224,104,191,111,57,105,191,139,145,105,191,4,233,105,191,217,63,106,191,9,150,106,191,148,235,106,191,123,64,107,191,188,148,107,191,89,232,107,191,79,59,108,191,160,141,108,191,75,223,108,191,79,48,109,191,173,128,109,191,101,208,109,191,117,31,110,191,223,109,110,191,161,187,110,191,187,8,111,191,46,85,111,191,248,160,111,191,27,236,111,191,149,54,112,191,103,128,112,191,144,201,112,191,15,18,113,191,230,89,113,191,19,161,113,191,151,231,113,191,113,45,114,191,160,114,114,191,38,183,114,191,1,251,114,191,50,62,115,191,184,128,115,191,148,194,115,191,196,3,116,191,73,68,116,191,34,132,116,191,80,195,116,191,210,1,117,191,168,63,117,191,210,124,117,191,80,185,117,191,33,245,117,191,69,48,118,191,189,106,118,191,136,164,118,191,166,221,118,191,22,22,119,191,217,77,119,191,239,132,119,191,87,187,119,191,17,241,119,191,29,38,120,191,122,90,120,191,42,142,120,191,43,193,120,191,125,243,120,191,33,37,121,191,22,86,121,191,92,134,121,191,242,181,121,191,218,228,121,191,18,19,122,191,154,64,122,191,115,109,122,191,157,153,122,191,22,197,122,191,223,239,122,191,248,25,123,191,97,67,123,191,26,108,123,191,34,148,123,191,122,187,123,191,32,226,123,191,23,8,124,191,92,45,124,191,240,81,124,191,211,117,124,191,5,153,124,191,134,187,124,191,85,221,124,191,115,254,124,191,223,30,125,191,154,62,125,191,163,93,125,191,250,123,125,191,159,153,125,191,146,182,125,191,211,210,125,191,98,238,125,191,63,9,126,191,105,35,126,191,225,60,126,191,167,85,126,191,186,109,126,191,27,133,126,191,201,155,126,191,196,177,126,191,13,199,126,191,162,219,126,191,133,239,126,191,181,2,127,191,50,21,127,191,252,38,127,191,19,56,127,191,118,72,127,191,39,88,127,191,36,103,127,191,110,117,127,191,5,131,127,191,232,143,127,191,25,156,127,191,149,167,127,191,95,178,127,191,116,188,127,191,215,197,127,191,133,206,127,191,129,214,127,191,200,221,127,191,93,228,127,191,61,234,127,191,106,239,127,191,227,243,127,191,169,247,127,191,187,250,127,191,25,253,127,191,196,254,127,191,187,255,127,191,250,255,127,63,57,254,127,63,169,249,127,63,75,242,127,63,30,232,127,63,35,219,127,63,89,203,127,63,193,184,127,63],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE);allocate([91,163,127,63,40,139,127,63,39,112,127,63,90,82,127,63,191,49,127,63,88,14,127,63,37,232,126,63,38,191,126,63,92,147,126,63,200,100,126,63,105,51,126,63,65,255,125,63,79,200,125,63,150,142,125,63,20,82,125,63,203,18,125,63,188,208,124,63,231,139,124,63,77,68,124,63,239,249,123,63,205,172,123,63,233,92,123,63,67,10,123,63,221,180,122,63,182,92,122,63,209,1,122,63,46,164,121,63,206,67,121,63,178,224,120,63,220,122,120,63,76,18,120,63,4,167,119,63,4,57,119,63,79,200,118,63,228,84,118,63,198,222,117,63,246,101,117,63,117,234,116,63,68,108,116,63,101,235,115,63,218,103,115,63,163,225,114,63,194,88,114,63,57,205,113,63,9,63,113,63,52,174,112,63,187,26,112,63,160,132,111,63,228,235,110,63,138,80,110,63,147,178,109,63,1,18,109,63,213,110,108,63,17,201,107,63,183,32,107,63,201,117,106,63,73,200,105,63,57,24,105,63,155,101,104,63,111,176,103,63,186,248,102,63,124,62,102,63,184,129,101,63,111,194,100,63,164,0,100,63,90,60,99,63,145,117,98,63,76,172,97,63,142,224,96,63,89,18,96,63,174,65,95,63,145,110,94,63,3,153,93,63,8,193,92,63,160,230,91,63,207,9,91,63,152,42,90,63,251,72,89,63,253,100,88,63,159,126,87,63,229,149,86,63,208,170,85,63,99,189,84,63,161,205,83,63,140,219,82,63,39,231,81,63,117,240,80,63,121,247,79,63,52,252,78,63,171,254,77,63,223,254,76,63,212,252,75,63,140,248,74,63,10,242,73,63,82,233,72,63,101,222,71,63,71,209,70,63,251,193,69,63,132,176,68,63,229,156,67,63,32,135,66,63,58,111,65,63,52,85,64,63,19,57,63,63,216,26,62,63,136,250,60,63,38,216,59,63,180,179,58,63,54,141,57,63,175,100,56,63,34,58,55,63,147,13,54,63,5,223,52,63,124,174,51,63,249,123,50,63,130,71,49,63,25,17,48,63,194,216,46,63,127,158,45,63,86,98,44,63,72,36,43,63,90,228,41,63,144,162,40,63,235,94,39,63,113,25,38,63,37,210,36,63,9,137,35,63,35,62,34,63,117,241,32,63,4,163,31,63,210,82,30,63,228,0,29,63,61,173,27,63,225,87,26,63,211,0,25,63,25,168,23,63,180,77,22,63,170,241,20,63,253,147,19,63,178,52,18,63,204,211,16,63,80,113,15,63,66,13,14,63,164,167,12,63,124,64,11,63,205,215,9,63,154,109,8,63,233,1,7,63,189,148,5,63,25,38,4,63,3,182,2,63,126,68,1,63,28,163,255,62,110,186,252,62,250,206,249,62,202,224,246,62,228,239,243,62,81,252,240,62,26,6,238,62,71,13,235,62,224,17,232,62,237,19,229,62,119,19,226,62,135,16,223,62,36,11,220,62,88,3,217,62,42,249,213,62,164,236,210,62,205,221,207,62,175,204,204,62,82,185,201,62,191,163,198,62,254,139,195,62,24,114,192,62,22,86,189,62,0,56,186,62,224,23,183,62,189,245,179,62,161,209,176,62,149,171,173,62,162,131,170,62,207,89,167,62,39,46,164,62,178,0,161,62,121,209,157,62,133,160,154,62,223,109,151,62,143,57,148,62,160,3,145,62,26,204,141,62,5,147,138,62,107,88,135,62,86,28,132,62,205,222,128,62,182,63,123,62,16,191,116,62,187,59,110,62,201,181,103,62,77,45,97,62,89,162,90,62,255,20,84,62,81,133,77,62,99,243,70,62,70,95,64,62,13,201,57,62,202,48,51,62,144,150,44,62,114,250,37,62,130,92,31,62,210,188,24,62,118,27,18,62,127,120,11,62,1,212,4,62,29,92,252,61,114,13,239,61,41,188,225,61,102,104,212,61,78,18,199,61,8,186,185,61,184,95,172,61,132,3,159,61,146,165,145,61,7,70,132,61,18,202,109,61,122,5,83,61,145,62,56,61,164,117,29,61,252,170,2,61,202,189,207,60,86,35,154,60,97,14,73,60,197,167,187,59,61,122,86,186,9,70,241,187,18,221,99,188,80,138,167,188,65,36,221,188,227,93,9,189,35,40,36,189,150,240,62,189,242,182,89,189,234,122,116,189,26,158,135,189,66,253,148,189,200,90,162,189,134,182,175,189,87,16,189,189,22,104,202,189,155,189,215,189,195,16,229,189,105,97,242,189,101,175,255,189,74,125,6,190,104,33,13,190,250,195,19,190,237,100,26,190,46,4,33,190,172,161,39,190,83,61,46,190,16,215,52,190,210,110,59,190,134,4,66,190,25,152,72,190,121,41,79,190,148,184,85,190,86,69,92,190,174,207,98,190,137,87,105,190,214,220,111,190,128,95,118,190,120,223,124,190,84,174,129,190,129,235,132,190,56,39,136,190,114,97,139,190,36,154,142,190,69,209,145,190,205,6,149,190,179,58,152,190,238,108,155,190,116,157,158,190,61,204,161,190,64,249,164,190,115,36,168,190,207,77,171,190,73,117,174,190,218,154,177,190,120,190,180,190,27,224,183,190,186,255,186,190,75,29,190,190,199,56,193,190,37,82,196,190,91,105,199,190,97,126,202,190,48,145,205,190,188,161,208,190,0,176,211,190,241,187,214,190,135,197,217,190,186,204,220,190,129,209,223,190,211,211,226,190,169,211,229,190,250,208,232,190,189,203,235,190,234,195,238,190,120,185,241,190,96,172,244,190,154,156,247,190,28,138,250,190,223,116,253,190,109,46,0,191,3,161,1,191,45,18,3,191,230,129,4,191,44,240,5,191,250,92,7,191,76,200,8,191,30,50,10,191,108,154,11,191,50,1,13,191,108,102,14,191,23,202,15,191,45,44,17,191,172,140,18,191,144,235,19,191,213,72,21,191,118,164,22,191,113,254,23,191,192,86,25,191,98,173,26,191,81,2,28,191,138,85,29,191,9,167,30,191,203,246,31,191,204,68,33,191,9,145,34,191,124,219,35,191,36,36,37,191,253,106,38,191,2,176,39,191,48,243,40,191,132,52,42,191,250,115,43,191,143,177,44,191,63,237,45,191,7,39,47,191,227,94,48,191,208,148,49,191,202,200,50,191,206,250,51,191,218,42,53,191,232,88,54,191,247,132,55,191,2,175,56,191,7,215,57,191,3,253,58,191,241,32,60,191,207,66,61,191,154,98,62,191,79,128,63,191,233,155,64,191,104,181,65,191,198,204,66,191,1,226,67,191,23,245,68,191,3,6,70,191,196,20,71,191,86,33,72,191,182,43,73,191,225,51,74,191,212,57,75,191,141,61,76,191,9,63,77,191,68,62,78,191,61,59,79,191,240,53,80,191,90,46,81,191,121,36,82,191,74,24,83,191,202,9,84,191,247,248,84,191,206,229,85,191,77,208,86,191,112,184,87,191,55,158,88,191,156,129,89,191,160,98,90,191,62,65,91,191,117,29,92,191,65,247,92,191,162,206,93,191,148,163,94,191,20,118,95,191,34,70,96,191,186,19,97,191,217,222,97,191,127,167,98,191,169,109,99,191,84,49,100,191,126,242,100,191,38,177,101,191,73,109,102,191,229,38,103,191,248,221,103,191,128,146,104,191,123,68,105,191,232,243,105,191,195,160,106,191,12,75,107,191,192,242,107,191,222,151,108,191,100,58,109,191,80,218,109,191,160,119,110,191,83,18,111,191,102,170,111,191,217,63,112,191,169,210,112,191,213,98,113,191,91,240,113,191,58,123,114,191,113,3,115,191,253,136,115,191,222,11,116,191,17,140,116,191,150,9,117,191,107,132,117,191,143,252,117,191,0,114,118,191,189,228,118,191,198,84,119,191,24,194,119,191,178,44,120,191,147,148,120,191,187,249,120,191,40,92,121,191,217,187,121,191,205,24,122,191,2,115,122,191,121,202,122,191,47,31,123,191,36,113,123,191,88,192,123,191,201,12,124,191,118,86,124,191,95,157,124,191,130,225,124,191,224,34,125,191,119,97,125,191,71,157,125,191,79,214,125,191,142,12,126,191,4,64,126,191,176,112,126,191,146,158,126,191,169,201,126,191,245,241,126,191,117,23,127,191,41,58,127,191,16,90,127,191,43,119,127,191,120,145,127,191,248,168,127,191,170,189,127,191,143,207,127,191,165,222,127,191,237,234,127,191,102,244,127,191,17,251,127,191,237,254,127,191,234,255,127,63,229,248,127,63,166,230,127,63,45,201,127,63,124,160,127,63,149,108,127,63,121,45,127,63,44,227,126,63,177,141,126,63,11,45,126,63,63,193,125,63,82,74,125,63,72,200,124,63,40,59,124,63,247,162,123,63,189,255,122,63,128,81,122,63,72,152,121,63,30,212,120,63,9,5,120,63,19,43,119,63,70,70,118,63,172,86,117,63,78,92,116,63,56,87,115,63,118,71,114,63,19,45,113,63,28,8,112,63,158,216,110,63,165,158,109,63,64,90,108,63,126,11,107,63,107,178,105,63,25,79,104,63,150,225,102,63,242,105,101,63,62,232,99,63,139,92,98,63,234,198,96,63,109,39,95,63,38,126,93,63,40,203,91,63,133,14,90,63,83,72,88,63,163,120,86,63,139,159,84,63,32,189,82,63,118,209,80,63,163,220,78,63,189,222,76,63,219,215,74,63,19,200,72,63,124,175,70,63,46,142,68,63,65,100,66,63,206,49,64,63,236,246,61,63,180,179,59,63,66,104,57,63,173,20,55,63,16,185,52,63,134,85,50,63,41,234,47,63,21,119,45,63,101,252,42,63,53,122,40,63,161,240,37,63,198,95,35,63,192,199,32,63,172,40,30,63,169,130,27,63,212,213,24,63,74,34,22,63,42,104,19,63,147,167,16,63,164,224,13,63,123,19,11,63,57,64,8,63,253,102,5,63,231,135,2,63,45,70,255,62,91,113,249,62,151,145,243,62,36,167,237,62,69,178,231,62,60,179,225,62,76,170,219,62,186,151,213,62,201,123,207,62,190,86,201,62,223,40,195,62,112,242,188,62,183,179,182,62,251,108,176,62,129,30,170,62,146,200,163,62,115,107,157,62,108,7,151,62,197,156,144,62,199,43,138,62,185,180,131,62,199,111,122,62,33,107,109,62,17,92,96,62,41,67,83,62,253,32,70,62,32,246,56,62,38,195,43,62,164,136,30,62,45,71,17,62,87,255,3,62,110,99,237,61,194,189,210,61,218,14,184,61,222,87,157,61,251,153,130,61,188,172,79,61,101,28,26,61,153,10,201,60,42,167,59,60,193,120,214,186,45,68,113,188,87,215,227,188,76,129,39,189,148,15,93,189,21,74,137,189,90,6,164,189,109,187,190,189,34,104,217,189,78,11,244,189,227,81,7,190,47,152,20,190,247,215,33,190,165,16,47,190,166,65,60,190,100,106,73,190,77,138,86,190,205,160,99,190,80,173,112,190,69,175,125,190,13,83,133,190,158,200,139,190,13,56,146,190,18,161,152,190,102,3,159,190,191,94,165,190,216,178,171,190,105,255,177,190,43,68,184,190,216,128,190,190,42,181,196,190,219,224,202,190,165,3,209,190,69,29,215,190,117,45,221,190,241,51,227,190,118,48,233,190,192,34,239,190,141,10,245,190,155,231,250,190,211,92,0,191,56,64,3,191,219,29,6,191,155,245,8,191,90,199,11,191,247,146,14,191,84,88,17,191,80,23,20,191,205,207,22,191,172,129,25,191,208,44,28,191,26,209,30,191,109,110,33,191,171,4,36,191,183,147,38,191,116,27,41,191,199,155,43,191,147,20,46,191,187,133,48,191,38,239,50,191,183,80,53,191,85,170,55,191,227,251,57,191,74,69,60,191,110,134,62,191,55,191,64,191,139,239,66,191,83,23,69,191,117,54,71,191,218,76,73,191,107,90,75,191,16,95,77,191,179,90,79,191,62,77,81,191,154,54,83,191,179,22,85,191,114,237,86,191,197,186,88,191,149,126,90,191,208,56,92,191,98,233,93,191,56,144,95,191,64,45,97,191,103,192,98,191,156,73,100,191,206,200,101,191,235,61,103,191,227,168,104,191,167,9,106,191,39,96,107,191,84,172,108,191,31,238,109,191,122,37,111,191,88,82,112,191,171,116,113,191,103,140,114,191,127,153,115,191,231,155,116,191,149,147,117,191,126,128,118,191,150,98,119,191,212,57,120,191,47,6,121,191,158,199,121,191,23,126,122,191,148,41,123,191,13,202,123,191,122,95,124,191,213,233,124,191,24,105,125,191,62,221,125,191,64,70,126,191,28,164,126,191,204,246,126,191,77,62,127,191,156,122,127,191,182,171,127,191,153,209,127,191,67,236,127,191,180,251,127,191,166,255,127,63,148,227,127,63,156,154,127,63,204,36,127,63,56,130,126,63,253,178,125,63,63,183,124,63,42,143,123,63,243,58,122,63,212,186,120,63,17,15,119,63,246,55,117,63,213,53,115,63,8,9,113,63,241,177,110,63,249,48,108,63,144,134,105,63,47,179,102,63,83,183,99,63,132,147,96,63,78,72,93,63,69,214,89,63,3,62,86,63,43,128,82,63,101,157,78,63,94,150,74,63,204,107,70,63,106,30,66,63,249,174,61,63,64,30,57,63,13,109,52,63,50,156,47,63,135,172,42,63,235,158,37,63,63,116,32,63,109,45,27,63,97,203,21,63,13,79,16,63,104,185,10,63,107,11,5,63,46,140,254,62,221,212,242,62,241,242,230,62,127,232,218,62,166,183,206,62,136,98,194,62,78,235,181,62,42,84,169,62,81,159,156,62,253,206,143,62,109,229,130,62,206,201,107,62,98,159,81,62,48,80,55,62,211,224,28,62,241,85,2,62,98,104,207,61,124,0,154,61,36,251,72,61,27,164,187,60,243,119,86,187,100,61,241,188,187,192,99,189,103,93,167,189,20,189,220,189,3,251,8,190,115,127,35,190,52,231,61,190,164,45,88,190,38,78,114,190,18,34,134,190,137,5,147,190,52,207,159,190,213,124,172,190,51,12,185,190,26,123,197,190,91,199,209,190,205,238,221,190,80,239,233,190,199,198,245,190,144,185,0,191,38,121,6,191,36,33,12,191,141,176,17,191,102,38,23,191,186,129,28,191,152,193,33,191,21,229,38,191,74,235,43,191,86,211,48,191,91,156,53,191,131,69,58,191,253,205,62,191,252,52,67,191,188,121,71,191,125,155,75,191,132,153,79,191,31,115,83,191,161,39,87,191,99,182,90,191,198,30,94,191,48,96,97,191,15,122,100,191,216,107,103,191,7,53,106,191,31,213,108,191,169,75,111,191,55,152,113,191,98,186,115,191,201,177,117,191,22,126,119,191,246,30,121,191,33,148,122,191,85,221,123,191,89,250,124,191,250,234,125,191,14,175,126,191,116,70,127,191,15,177,127,191,206,238,127,191,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,41,0,41,0,41,0,82,0,82,0,123,0,164,0,200,0,222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,0,41,0,41,0,41,0,123,0,123,0,123,0,164,0,164,0,240,0,10,1,27,1,39,1,41,0,41,0,41,0,41,0,41,0,41,0,41,0,41,0,123,0,123,0,123,0,123,0,240,0,240,0,240,0,10,1,10,1,49,1,62,1,72,1,80,1,123,0,123,0,123,0,123,0,123,0,123,0,123,0,123,0,240,0,240,0,240,0,240,0,49,1,49,1,49,1,62,1,62,1,87,1,95,1,102,1,108,1,240,0,240,0,240,0,240,0,240,0,240,0,240,0,240,0,49,1,49,1,49,1,49,1,87,1,87,1,87,1,95,1,95,1,114,1,120,1,126,1,131,1,0,0,0,0,0,0,40,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,40,15,23,28,31,34,36,38,39,41,42,43,44,45,46,47,47,49,50,51,52,53,54,55,55,57,58,59,60,61,62,63,63,65,66,67,68,69,70,71,71,40,20,33,41,48,53,57,61,64,66,69,71,73,75,76,78,80,82,85,87,89,91,92,94,96,98,101,103,105,107,108,110,112,114,117,119,121,123,124,126,128,40,23,39,51,60,67,73,79,83,87,91,94,97,100,102,105,107,111,115,118,121,124,126,129,131,135,139,142,145,148,150,153,155,159,163,166,169,172,174,177,179,35,28,49,65,78,89,99,107,114,120,126,132,136,141,145,149,153,159,165,171,176,180,185,189,192,199,205,211,216,220,225,229,232,239,245,251,21,33,58,79,97,112,125,137,148,157,166,174,182,189,195,201,207,217,227,235,243,251,17,35,63,86,106,123,139,152,165,177,187,197,206,214,222,230,237,250,25,31,55,75,91,105,117,128,138,146,154,161,168,174,180,185,190,200,208,215,222,229,235,240,245,255,16,36,65,89,110,128,144,159,173,185,196,207,217,226,234,242,250,11,41,74,103,128,151,172,191,209,225,241,255,9,43,79,110,138,163,186,207,227,246,12,39,71,99,123,144,164,182,198,214,228,241,253,9,44,81,113,142,168,192,214,235,255,7,49,90,127,160,191,220,247,6,51,95,134,170,203,234,7,47,87,123,155,184,212,237,6,52,97,137,174,208,240,5,57,106,151,192,231,5,59,111,158,202,243,5,55,103,147,187,224,5,60,113,161,206,248,4,65,122,175,224,4,67,127,182,234,224,224,224,224,224,224,224,224,160,160,160,160,185,185,185,178,178,168,134,61,37,224,224,224,224,224,224,224,224,240,240,240,240,207,207,207,198,198,183,144,66,40,160,160,160,160,160,160,160,160,185,185,185,185,193,193,193,183,183,172,138,64,38,240,240,240,240,240,240,240,240,207,207,207,207,204,204,204,193,193,180,143,66,40,185,185,185,185,185,185,185,185,193,193,193,193,193,193,193,183,183,172,138,65,39,207,207,207,207,207,207,207,207,204,204,204,204,201,201,201,188,188,176,141,66,40,193,193,193,193,193,193,193,193,193,193,193,193,194,194,194,184,184,173,139,65,39,204,204,204,204,204,204,204,204,201,201,201,201,198,198,198,187,187,175,140,66,40,0,0,12,0,24,0,36,0,48,0,4,0,16,0,28,0,40,0,52,0,8,0,20,0,32,0,44,0,56,0,1,0,13,0,25,0,37,0,49,0,5,0,17,0,29,0,41,0,53,0,9,0,21,0,33,0,45,0,57,0,2,0,14,0,26,0,38,0,50,0,6,0,18,0,30,0,42,0,54,0,10,0,22,0,34,0,46,0,58,0,3,0,15,0,27,0,39,0,51,0,7,0,19,0,31,0,43,0,55,0,11,0,23,0,35,0,47,0,59,0,0,0,128,63,0,0,0,128,99,250,127,63,191,117,86,188,139,233,127,63,10,113,214,188,121,205,127,63,231,206,32,189,47,166,127,63,58,94,86,189,175,115,127,63,19,242,133,189,249,53,127,63,42,175,160,189,18,237,126,63,51,101,187,189,253,152,126,63,4,19,214,189,188,57,126,63,115,183,240,189,85,207,125,63,168,168,5,190,203,89,125,63,187,239,18,190,37,217,124,63,92,48,32,190,103,77,124,63,245,105,45,190,152,182,123,63,243,155,58,190,190,20,123,63,194,197,71,190,226,103,122,63,205,230,84,190,9,176,121,63,130,254,97,190,60,237,120,63,77,12,111,190,132,31,120,63,156,15,124,190,234,70,119,63,238,131,132,190,119,99,118,63,62,250,138,190,54,117,117,63,117,106,145,190,48,124,116,63,76,212,151,190,113,120,115,63,122,55,158,190,3,106,114,63,183,147,164,190,244,80,113,63,188,232,170,190,79,45,112,63,65,54,177,190,33,255,110,63,1,124,183,190,118,198,109,63,180,185,189,190,94,131,108,63,21,239,195,190,231,53,107,63,222,27,202,190,30,222,105,63,201,63,208,190,18,124,104,63,146,90,214,190,212,15,103,63,243,107,220,190,116,153,101,63,170,115,226,190,1,25,100,63,113,113,232,190,141,142,98,63,7,101,238,190,40,250,96,63,39,78,244,190,230,91,95,63,144,44,250,190,215,179,93,63,0,0,0,191,15,2,92,63,27,228,2,191,160,70,90,63,119,194,5,191,158,129,88,63,246,154,8,191,29,179,86,63,119,109,11,191,49,219,84,63,218,57,14,191,239,249,82,63,0,0,17,191,108,15,81,63,202,191,19,191,189,27,79,63,24,121,22,191,248,30,77,63,205,43,25,191,52,25,75,63,202,215,27,191,136,10,73,63,241,124,30,191,10,243,70,63,36,27,33,191,209,210,68,63,70,178,35,191,247,169,66,63,58,66,38,191,147,120,64,63,227,202,40,191,189,62,62,63,37,76,43,191,143,252,59,63,227,197,45,191,34,178,57,63,1,56,48,191,144,95,55,63,101,162,50,191,243,4,53,63,243,4,53,191,101,162,50,63,144,95,55,191,1,56,48,63,34,178,57,191,227,197,45,63,143,252,59,191,37,76,43,63,189,62,62,191,227,202,40,63,147,120,64,191,58,66,38,63,247,169,66,191,70,178,35,63,209,210,68,191,36,27,33,63,10,243,70,191,241,124,30,63,136,10,73,191,202,215,27,63,52,25,75,191,205,43,25,63,248,30,77,191,24,121,22,63,189,27,79,191,202,191,19,63,108,15,81,191,0,0,17,63,239,249,82,191,218,57,14,63,49,219,84,191,119,109,11,63,29,179,86,191,246,154,8,63,158,129,88,191,119,194,5,63,160,70,90,191,27,228,2,63,15,2,92,191,0,0,0,63,215,179,93,191,144,44,250,62,230,91,95,191,39,78,244,62,40,250,96,191,7,101,238,62,141,142,98,191,113,113,232,62,1,25,100,191,170,115,226,62,116,153,101,191,243,107,220,62,212,15,103,191,146,90,214,62,18,124,104,191,201,63,208,62,30,222,105,191,222,27,202,62,231,53,107,191,21,239,195,62,94,131,108,191,180,185,189,62,118,198,109,191,1,124,183,62,33,255,110,191,65,54,177,62,79,45,112,191,188,232,170,62,244,80,113,191,183,147,164,62,3,106,114,191,122,55,158,62,113,120,115,191,76,212,151,62,48,124,116,191,117,106,145,62,54,117,117,191,62,250,138,62,119,99,118,191,238,131,132,62,234,70,119,191,156,15,124,62,132,31,120,191,77,12,111,62,60,237,120,191,130,254,97,62,9,176,121,191,205,230,84,62,226,103,122,191,194,197,71,62,190,20,123,191,243,155,58,62,152,182,123,191,245,105,45,62,103,77,124,191,92,48,32,62,37,217,124,191,187,239,18,62,203,89,125,191,168,168,5,62,85,207,125,191,115,183,240,61,188,57,126,191,4,19,214,61,253,152,126,191,51,101,187,61,18,237,126,191,42,175,160,61,249,53,127,191,19,242,133,61,175,115,127,191,58,94,86,61,47,166,127,191,231,206,32,61,121,205,127,191,10,113,214,60,139,233,127,191,191,117,86,60,99,250,127,191,0,48,141,36,0,0,128,191,191,117,86,188,99,250,127,191,10,113,214,188,139,233,127,191,231,206,32,189,121,205,127,191,58,94,86,189,47,166,127,191,19,242,133,189,175,115,127,191,42,175,160,189,249,53,127,191,51,101,187,189,18,237,126,191,4,19,214,189,253,152,126,191,115,183,240,189,188,57,126,191,168,168,5,190,85,207,125,191,187,239,18,190,203,89,125,191,92,48,32,190,37,217,124,191,245,105,45,190,103,77,124,191,243,155,58,190,152,182,123,191,194,197,71,190,190,20,123,191,205,230,84,190,226,103,122,191,130,254,97,190,9,176,121,191,77,12,111,190,60,237,120,191,156,15,124,190,132,31,120,191,238,131,132,190,234,70,119,191,62,250,138,190,119,99,118,191,117,106,145,190,54,117,117,191,76,212,151,190,48,124,116,191,122,55,158,190,113,120,115,191,183,147,164,190,3,106,114,191,188,232,170,190,244,80,113,191,65,54,177,190,79,45,112,191,1,124,183,190,33,255,110,191,180,185,189,190,118,198,109,191,21,239,195,190,94,131,108,191,222,27,202,190,231,53,107,191,201,63,208,190,30,222,105,191,146,90,214,190,18,124,104,191,243,107,220,190,212,15,103,191,170,115,226,190,116,153,101,191,113,113,232,190,1,25,100,191,7,101,238,190,141,142,98,191,39,78,244,190,40,250,96,191,144,44,250,190,230,91,95,191,0,0,0,191,215,179,93,191,27,228,2,191,15,2,92,191,119,194,5,191,160,70,90,191,246,154,8,191,158,129,88,191,119,109,11,191,29,179,86,191,218,57,14,191,49,219,84,191,0,0,17,191,239,249,82,191,202,191,19,191,108,15,81,191,24,121,22,191,189,27,79,191,205,43,25,191,248,30,77,191,202,215,27,191,52,25,75,191,241,124,30,191,136,10,73,191,36,27,33,191,10,243,70,191,70,178,35,191,209,210,68,191,58,66,38,191,247,169,66,191,227,202,40,191,147,120,64,191,37,76,43,191,189,62,62,191,227,197,45,191,143,252,59,191,1,56,48,191,34,178,57,191,101,162,50,191,144,95,55,191,243,4,53,191,243,4,53,191,144,95,55,191,101,162,50,191,34,178,57,191,1,56,48,191,143,252,59,191,227,197,45,191,189,62,62,191,37,76,43,191,147,120,64,191,227,202,40,191,247,169,66,191,58,66,38,191,209,210,68,191,70,178,35,191,10,243,70,191,36,27,33,191,136,10,73,191,241,124,30,191,52,25,75,191,202,215,27,191,248,30,77,191,205,43,25,191,189,27,79,191,24,121,22,191,108,15,81,191,202,191,19,191,239,249,82,191,0,0,17,191,49,219,84,191,218,57,14,191,29,179,86,191,119,109,11,191,158,129,88,191,246,154,8,191,160,70,90,191,119,194,5,191,15,2,92,191,27,228,2,191,215,179,93,191,0,0,0,191,230,91,95,191,144,44,250,190,40,250,96,191,39,78,244,190,141,142,98,191,7,101,238,190,1,25,100,191,113,113,232,190,116,153,101,191,170,115,226,190,212,15,103,191,243,107,220,190,18,124,104,191,146,90,214,190,30,222,105,191,201,63,208,190,231,53,107,191,222,27,202,190,94,131,108,191,21,239,195,190,118,198,109,191,180,185,189,190,33,255,110,191,1,124,183,190,79,45,112,191,65,54,177,190,244,80,113,191,188,232,170,190,3,106,114,191,183,147,164,190,113,120,115,191,122,55,158,190,48,124,116,191,76,212,151,190,54,117,117,191,117,106,145,190,119,99,118,191,62,250,138,190,234,70,119,191,238,131,132,190,132,31,120,191,156,15,124,190,60,237,120,191,77,12,111,190,9,176,121,191,130,254,97,190,226,103,122,191,205,230,84,190,190,20,123,191,194,197,71,190,152,182,123,191,243,155,58,190,103,77,124,191,245,105,45,190,37,217,124,191,92,48,32,190,203,89,125,191,187,239,18,190,85,207,125,191,168,168,5,190,188,57,126,191,115,183,240,189,253,152,126,191,4,19,214,189,18,237,126,191,51,101,187,189,249,53,127,191,42,175,160,189,175,115,127,191,19,242,133,189,47,166,127,191,58,94,86,189,121,205,127,191,231,206,32,189,139,233,127,191,10,113,214,188,99,250,127,191,191,117,86,188,0,0,128,191,0,48,13,165,99,250,127,191,191,117,86,60,139,233,127,191,10,113,214,60,121,205,127,191,231,206,32,61,47,166,127,191,58,94,86,61,175,115,127,191,19,242,133,61,249,53,127,191,42,175,160,61,18,237,126,191,51,101,187,61,253,152,126,191,4,19,214,61,188,57,126,191,115,183,240,61,85,207,125,191,168,168,5,62,203,89,125,191,187,239,18,62,37,217,124,191,92,48,32,62,103,77,124,191,245,105,45,62,152,182,123,191,243,155,58,62,190,20,123,191,194,197,71,62,226,103,122,191,205,230,84,62,9,176,121,191,130,254,97,62,60,237,120,191,77,12,111,62,132,31,120,191,156,15,124,62,234,70,119,191,238,131,132,62,119,99,118,191,62,250,138,62,54,117,117,191,117,106,145,62,48,124,116,191,76,212,151,62,113,120,115,191,122,55,158,62,3,106,114,191,183,147,164,62,244,80,113,191,188,232,170,62,79,45,112,191,65,54,177,62,33,255,110,191,1,124,183,62,118,198,109,191,180,185,189,62,94,131,108,191,21,239,195,62,231,53,107,191,222,27,202,62,30,222,105,191,201,63,208,62,18,124,104,191,146,90,214,62,212,15,103,191,243,107,220,62,116,153,101,191,170,115,226,62,1,25,100,191,113,113,232,62,141,142,98,191,7,101,238,62,40,250,96,191,39,78,244,62,230,91,95,191,144,44,250,62,215,179,93,191,0,0,0,63,15,2,92,191,27,228,2,63,160,70,90,191,119,194,5,63,158,129,88,191,246,154,8,63,29,179,86,191,119,109,11,63,49,219,84,191,218,57,14,63,239,249,82,191,0,0,17,63,108,15,81,191,202,191,19,63,189,27,79,191,24,121,22,63,248,30,77,191,205,43,25,63,52,25,75,191,202,215,27,63,136,10,73,191,241,124,30,63,10,243,70,191,36,27,33,63,209,210,68,191,70,178,35,63,247,169,66,191,58,66,38,63,147,120,64,191,227,202,40,63,189,62,62,191,37,76,43,63,143,252,59,191,227,197,45,63,34,178,57,191,1,56,48,63,144,95,55,191,101,162,50,63,243,4,53,191,243,4,53,63,101,162,50,191,144,95,55,63,1,56,48,191,34,178,57,63,227,197,45,191,143,252,59,63,37,76,43,191,189,62,62,63,227,202,40,191,147,120,64,63,58,66,38,191,247,169,66,63,70,178,35,191,209,210,68,63,36,27,33,191,10,243,70,63,241,124,30,191,136,10,73,63,202,215,27,191,52,25,75,63,205,43,25,191,248,30,77,63,24,121,22,191,189,27,79,63,202,191,19,191,108,15,81,63,0,0,17,191,239,249,82,63,218,57,14,191,49,219,84,63,119,109,11,191,29,179,86,63,246,154,8,191,158,129,88,63,119,194,5,191,160,70,90,63,27,228,2,191,15,2,92,63,0,0,0,191,215,179,93,63,144,44,250,190,230,91,95,63,39,78,244,190,40,250,96,63,7,101,238,190,141,142,98,63,113,113,232,190,1,25,100,63,170,115,226,190,116,153,101,63,243,107,220,190,212,15,103,63,146,90,214,190,18,124,104,63,201,63,208,190,30,222,105,63,222,27,202,190,231,53,107,63,21,239,195,190,94,131,108,63,180,185,189,190,118,198,109,63,1,124,183,190,33,255,110,63,65,54,177,190,79,45,112,63,188,232,170,190,244,80,113,63,183,147,164,190,3,106,114,63,122,55,158,190,113,120,115,63,76,212,151,190,48,124,116,63,117,106,145,190,54,117,117,63,62,250,138,190,119,99,118,63,238,131,132,190,234,70,119,63,156,15,124,190,132,31,120,63,77,12,111,190,60,237,120,63,130,254,97,190,9,176,121,63,205,230,84,190,226,103,122,63,194,197,71,190,190,20,123,63,243,155,58,190,152,182,123,63,245,105,45,190,103,77,124,63,92,48,32,190,37,217,124,63,187,239,18,190,203,89,125,63,168,168,5,190,85,207,125,63,115,183,240,189,188,57,126,63,4,19,214,189,253,152,126,63,51,101,187,189,18,237,126,63,42,175,160,189,249,53,127,63,19,242,133,189,175,115,127,63,58,94,86,189,47,166,127,63,231,206,32,189,121,205,127,63,10,113,214,188,139,233,127,63,191,117,86,188,99,250,127,63,0,200,83,165,0,0,128,63,191,117,86,60,99,250,127,63,10,113,214,60,139,233,127,63,231,206,32,61,121,205,127,63,58,94,86,61,47,166,127,63,19,242,133,61,175,115,127,63,42,175,160,61,249,53,127,63,51,101,187,61,18,237,126,63,4,19,214,61,253,152,126,63,115,183,240,61,188,57,126,63,168,168,5,62,85,207,125,63,187,239,18,62,203,89,125,63,92,48,32,62,37,217,124,63,245,105,45,62,103,77,124,63,243,155,58,62,152,182,123,63,194,197,71,62,190,20,123,63,205,230,84,62,226,103,122,63,130,254,97,62,9,176,121,63,77,12,111,62,60,237,120,63,156,15,124,62,132,31,120,63,238,131,132,62,234,70,119,63,62,250,138,62,119,99,118,63,117,106,145,62,54,117,117,63,76,212,151,62,48,124,116,63,122,55,158,62,113,120,115,63,183,147,164,62,3,106,114,63,188,232,170,62,244,80,113,63,65,54,177,62,79,45,112,63,1,124,183,62,33,255,110,63,180,185,189,62,118,198,109,63,21,239,195,62,94,131,108,63,222,27,202,62,231,53,107,63,201,63,208,62,30,222,105,63,146,90,214,62,18,124,104,63,243,107,220,62,212,15,103,63,170,115,226,62,116,153,101,63,113,113,232,62,1,25,100,63,7,101,238,62,141,142,98,63,39,78,244,62,40,250,96,63,144,44,250,62,230,91,95,63,0,0,0,63,215,179,93,63,27,228,2,63,15,2,92,63,119,194,5,63,160,70,90,63,246,154,8,63,158,129,88,63,119,109,11,63,29,179,86,63,218,57,14,63,49,219,84,63,0,0,17,63,239,249,82,63,202,191,19,63,108,15,81,63,24,121,22,63,189,27,79,63,205,43,25,63,248,30,77,63,202,215,27,63,52,25,75,63,241,124,30,63,136,10,73,63,36,27,33,63,10,243,70,63,70,178,35,63,209,210,68,63,58,66,38,63,247,169,66,63,227,202,40,63,147,120,64,63,37,76,43,63,189,62,62,63,227,197,45,63,143,252,59,63,1,56,48,63,34,178,57,63,101,162,50,63,144,95,55,63,243,4,53,63,243,4,53,63,144,95,55,63,101,162,50,63,34,178,57,63,1,56,48,63,143,252,59,63,227,197,45,63,189,62,62,63,37,76,43,63,147,120,64,63,227,202,40,63,247,169,66,63,58,66,38,63,209,210,68,63,70,178,35,63,10,243,70,63,36,27,33,63,136,10,73,63,241,124,30,63,52,25,75,63,202,215,27,63,248,30,77,63,205,43,25,63,189,27,79,63,24,121,22,63,108,15,81,63,202,191,19,63,239,249,82,63,0,0,17,63,49,219,84,63,218,57,14,63,29,179,86,63,119,109,11,63,158,129,88,63,246,154,8,63,160,70,90,63,119,194,5,63,15,2,92,63,27,228,2,63,215,179,93,63,0,0,0,63,230,91,95,63,144,44,250,62,40,250,96,63,39,78,244,62,141,142,98,63,7,101,238,62,1,25,100,63,113,113,232,62,116,153,101,63,170,115,226,62,212,15,103,63,243,107,220,62,18,124,104,63,146,90,214,62,30,222,105,63,201,63,208,62,231,53,107,63,222,27,202,62,94,131,108,63,21,239,195,62,118,198,109,63,180,185,189,62,33,255,110,63,1,124,183,62,79,45,112,63,65,54,177,62,244,80,113,63,188,232,170,62,3,106,114,63,183,147,164,62,113,120,115,63,122,55,158,62,48,124,116,63,76,212,151,62,54,117,117,63,117,106,145,62,119,99,118,63,62,250,138,62,234,70,119,63,238,131,132,62,132,31,120,63,156,15,124,62,60,237,120,63,77,12,111,62,9,176,121,63,130,254,97,62,226,103,122,63,205,230,84,62,190,20,123,63,194,197,71,62,152,182,123,63,243,155,58,62,103,77,124,63,245,105,45,62,37,217,124,63,92,48,32,62,203,89,125,63,187,239,18,62,85,207,125,63,168,168,5,62,188,57,126,63,115,183,240,61,253,152,126,63,4,19,214,61,18,237,126,63,51,101,187,61,249,53,127,63,42,175,160,61,175,115,127,63,19,242,133,61,47,166,127,63,58,94,86,61,121,205,127,63,231,206,32,61,139,233,127,63,10,113,214,60,99,250,127,63,191,117,86,60,0,0,24,0,48,0,72,0,96,0,8,0,32,0,56,0,80,0,104,0,16,0,40,0,64,0,88,0,112,0,4,0,28,0,52,0,76,0,100,0,12,0,36,0,60,0,84,0,108,0,20,0,44,0,68,0,92,0,116,0,1,0,25,0,49,0,73,0,97,0,9,0,33,0,57,0,81,0,105,0,17,0,41,0,65,0,89,0,113,0,5,0,29,0,53,0,77,0,101,0,13,0,37,0,61,0,85,0,109,0,21,0,45,0,69,0,93,0,117,0,2,0,26,0,50,0,74,0,98,0,10,0,34,0,58,0,82,0,106,0,18,0,42,0,66,0,90,0,114,0,6,0,30,0,54,0,78,0,102,0,14,0,38,0,62,0,86,0,110,0,22,0,46,0,70,0,94,0,118,0,3,0,27,0,51,0,75,0,99,0,11,0,35,0,59,0,83,0,107,0,19,0,43,0,67,0,91,0,115,0,7,0,31,0,55,0,79,0,103,0,15,0,39,0,63,0,87,0,111,0,23,0,47,0,71,0,95,0,119,0,0,0,48,0,96,0,144,0,192,0,16,0,64,0,112,0,160,0,208,0,32,0,80,0,128,0,176,0,224,0,4,0,52,0,100,0,148,0,196,0,20,0,68,0,116,0,164,0,212,0,36,0,84,0,132,0,180,0,228,0,8,0,56,0,104,0,152,0,200,0,24,0,72,0,120,0,168,0,216,0,40,0,88,0,136,0,184,0,232,0,12,0,60,0,108,0,156,0,204,0,28,0,76,0,124,0,172,0,220,0,44,0,92,0,140,0,188,0,236,0,1,0,49,0,97,0,145,0,193,0,17,0,65,0,113,0,161,0,209,0,33,0,81,0,129,0,177,0,225,0,5,0,53,0,101,0,149,0,197,0,21,0,69,0,117,0,165,0,213,0,37,0,85,0,133,0,181,0,229,0,9,0,57,0,105,0,153,0,201,0,25,0,73,0,121,0,169,0,217,0,41,0,89,0,137,0,185,0,233,0,13,0,61,0,109,0,157,0,205,0,29,0,77,0,125,0,173,0,221,0,45,0,93,0,141,0,189,0,237,0,2,0,50,0,98,0,146,0,194,0,18,0,66,0,114,0,162,0,210,0,34,0,82,0,130,0,178,0,226,0,6,0,54,0,102,0,150,0,198,0,22,0,70,0,118,0,166,0,214,0,38,0,86,0,134,0,182,0,230,0,10,0,58,0,106,0,154,0,202,0,26,0,74,0,122,0,170,0,218,0,42,0,90,0,138,0,186,0,234,0,14,0,62,0,110,0,158,0,206,0,30,0,78,0,126,0,174,0,222,0,46,0,94,0,142,0,190,0,238,0,3,0,51,0,99,0,147,0,195,0,19,0,67,0,115,0,163,0,211,0,35,0,83,0,131,0,179,0,227,0,7,0,55,0,103,0,151,0,199,0,23,0,71,0,119,0,167,0,215,0,39,0,87,0,135,0,183,0,231,0,11,0,59,0,107,0,155,0,203,0,27,0,75,0,123,0,171,0,219,0,43,0,91,0,139,0,187,0,235,0,15,0,63,0,111,0,159,0,207,0,31,0,79,0,127,0,175,0,223,0,47,0,95,0,143,0,191,0,239,0,0,0,96,0,192,0,32,1,128,1,32,0,128,0,224,0,64,1,160,1,64,0,160,0,0,1,96,1,192,1,8,0,104,0,200,0,40,1,136,1,40,0,136,0,232,0,72,1,168,1,72,0,168,0,8,1,104,1,200,1,16,0,112,0,208,0,48,1,144,1,48,0,144,0,240,0,80,1,176,1,80,0,176,0,16,1,112,1,208,1,24,0,120,0,216,0,56,1,152,1,56,0,152,0,248,0,88,1,184,1,88,0,184,0,24,1,120,1,216,1,4,0,100,0,196,0,36,1,132,1,36,0,132,0,228,0,68,1,164,1,68,0,164,0,4,1,100,1,196,1,12,0,108,0,204,0,44,1,140,1,44,0,140,0,236,0,76,1,172,1,76,0,172,0,12,1,108,1,204,1,20,0,116,0,212,0,52,1,148,1,52,0,148,0,244,0,84,1,180,1,84,0,180,0,20,1,116,1,212,1,28,0,124,0,220,0,60,1,156,1,60,0,156,0,252,0,92,1,188,1,92,0,188,0,28,1,124,1,220,1,1,0,97,0,193,0,33,1,129,1,33,0,129,0,225,0,65,1,161,1,65,0,161,0,1,1,97,1,193,1,9,0,105,0,201,0,41,1,137,1,41,0,137,0,233,0,73,1,169,1,73,0,169,0,9,1,105,1,201,1,17,0,113,0,209,0,49,1,145,1,49,0,145,0,241,0,81,1,177,1,81,0,177,0,17,1,113,1,209,1,25,0,121,0,217,0,57,1,153,1,57,0,153,0,249,0,89,1,185,1,89,0,185,0,25,1,121,1,217,1,5,0,101,0,197,0,37,1,133,1,37,0,133,0,229,0,69,1,165,1,69,0,165,0,5,1,101,1,197,1,13,0,109,0,205,0,45,1,141,1,45,0,141,0,237,0,77,1,173,1,77,0,173,0,13,1,109,1,205,1,21,0,117,0,213,0,53,1,149,1,53,0,149,0,245,0,85,1,181,1,85,0,181,0,21,1,117,1,213,1,29,0,125,0,221,0,61,1,157,1,61,0,157,0,253,0,93,1,189,1,93,0,189,0,29,1,125,1,221,1,2,0,98,0,194,0,34,1,130,1,34,0,130,0,226,0,66,1,162,1,66,0,162,0,2,1,98,1,194,1,10,0,106,0,202,0,42,1,138,1,42,0,138,0,234,0,74,1,170,1,74,0,170,0,10,1,106,1,202,1,18,0,114,0,210,0,50,1,146,1,50,0,146,0,242,0,82,1,178,1,82,0,178,0,18,1,114,1,210,1,26,0,122,0,218,0,58,1,154,1,58,0,154,0,250,0,90,1,186,1,90,0,186,0,26,1,122,1,218,1,6,0,102,0,198,0,38,1,134,1,38,0,134,0,230,0,70,1,166,1,70,0,166,0,6,1,102,1,198,1,14,0,110,0,206,0,46,1,142,1,46,0,142,0,238,0,78,1,174,1,78,0,174,0,14,1,110,1,206,1,22,0,118,0,214,0,54,1,150,1,54,0,150,0,246,0,86,1,182,1,86,0,182,0,22,1,118,1,214,1,30,0,126,0,222,0,62,1,158,1,62,0,158,0,254,0,94,1,190,1,94,0,190,0,30,1,126,1,222,1,3,0,99,0,195,0,35,1,131,1,35,0,131,0,227,0,67,1,163,1,67,0,163,0,3,1,99,1,195,1,11,0,107,0,203,0,43,1,139,1,43,0,139,0,235,0,75,1,171,1,75,0,171,0,11,1,107,1,203,1,19,0,115,0,211,0,51,1,147,1,51,0,147,0,243,0,83,1,179,1,83,0,179,0,19,1,115,1,211,1,27,0,123,0,219,0,59,1,155,1,59,0,155,0,251,0,91,1,187,1,91,0,187,0,27,1,123,1,219,1,7,0,103,0,199,0,39,1,135,1,39,0,135,0,231,0,71,1,167,1,71,0,167,0,7,1,103,1,199,1,15,0,111,0,207,0,47,1,143,1,47,0,143,0,239,0,79,1,175,1,79,0,175,0,15,1,111,1,207,1,23,0,119,0,215,0,55,1,151,1,55,0,151,0,247,0,87,1,183,1,87,0,183,0,23,1,119,1,215,1,31,0,127,0,223,0,63,1,159,1,63,0,159,0,255,0,95,1,191,1,95,0,191,0,31,1,127,1,223,1,1],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE+10240);allocate([1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,3,0,0,0,5,0,0,0,7,0,0,0,9,0,0,0,11,0,0,0,13,0,0,0,15,0,0,0,17,0,0,0,19,0,0,0,21,0,0,0,23,0,0,0,25,0,0,0,27,0,0,0,29,0,0,0,31,0,0,0,33,0,0,0,35,0,0,0,37,0,0,0,39,0,0,0,41,0,0,0,43,0,0,0,45,0,0,0,47,0,0,0,49,0,0,0,51,0,0,0,53,0,0,0,55,0,0,0,57,0,0,0,59,0,0,0,61,0,0,0,63,0,0,0,65,0,0,0,67,0,0,0,69,0,0,0,71,0,0,0,73,0,0,0,75,0,0,0,77,0,0,0,79,0,0,0,81,0,0,0,83,0,0,0,85,0,0,0,87,0,0,0,89,0,0,0,91,0,0,0,93,0,0,0,95,0,0,0,97,0,0,0,99,0,0,0,101,0,0,0,103,0,0,0,105,0,0,0,107,0,0,0,109,0,0,0,111,0,0,0,113,0,0,0,115,0,0,0,117,0,0,0,119,0,0,0,121,0,0,0,123,0,0,0,125,0,0,0,127,0,0,0,129,0,0,0,131,0,0,0,133,0,0,0,135,0,0,0,137,0,0,0,139,0,0,0,141,0,0,0,143,0,0,0,145,0,0,0,147,0,0,0,149,0,0,0,151,0,0,0,153,0,0,0,155,0,0,0,157,0,0,0,159,0,0,0,161,0,0,0,163,0,0,0,165,0,0,0,167,0,0,0,169,0,0,0,171,0,0,0,173,0,0,0,175,0,0,0,177,0,0,0,179,0,0,0,181,0,0,0,183,0,0,0,185,0,0,0,187,0,0,0,189,0,0,0,191,0,0,0,193,0,0,0,195,0,0,0,197,0,0,0,199,0,0,0,201,0,0,0,203,0,0,0,205,0,0,0,207,0,0,0,209,0,0,0,211,0,0,0,213,0,0,0,215,0,0,0,217,0,0,0,219,0,0,0,221,0,0,0,223,0,0,0,225,0,0,0,227,0,0,0,229,0,0,0,231,0,0,0,233,0,0,0,235,0,0,0,237,0,0,0,239,0,0,0,241,0,0,0,243,0,0,0,245,0,0,0,247,0,0,0,249,0,0,0,251,0,0,0,253,0,0,0,255,0,0,0,1,1,0,0,3,1,0,0,5,1,0,0,7,1,0,0,9,1,0,0,11,1,0,0,13,1,0,0,15,1,0,0,17,1,0,0,19,1,0,0,21,1,0,0,23,1,0,0,25,1,0,0,27,1,0,0,29,1,0,0,31,1,0,0,33,1,0,0,35,1,0,0,37,1,0,0,39,1,0,0,41,1,0,0,43,1,0,0,45,1,0,0,47,1,0,0,49,1,0,0,51,1,0,0,53,1,0,0,55,1,0,0,57,1,0,0,59,1,0,0,61,1,0,0,63,1,0,0,65,1,0,0,67,1,0,0,69,1,0,0,71,1,0,0,73,1,0,0,75,1,0,0,77,1,0,0,79,1,0,0,81,1,0,0,83,1,0,0,85,1,0,0,87,1,0,0,89,1,0,0,91,1,0,0,93,1,0,0,95,1,0,0,13,0,0,0,25,0,0,0,41,0,0,0,61,0,0,0,85,0,0,0,113,0,0,0,145,0,0,0,181,0,0,0,221,0,0,0,9,1,0,0,57,1,0,0,109,1,0,0,165,1,0,0,225,1,0,0,33,2,0,0,101,2,0,0,173,2,0,0,249,2,0,0,73,3,0,0,157,3,0,0,245,3,0,0,81,4,0,0,177,4,0,0,21,5,0,0,125,5,0,0,233,5,0,0,89,6,0,0,205,6,0,0,69,7,0,0,193,7,0,0,65,8,0,0,197,8,0,0,77,9,0,0,217,9,0,0,105,10,0,0,253,10,0,0,149,11,0,0,49,12,0,0,209,12,0,0,117,13,0,0,29,14,0,0,201,14,0,0,121,15,0,0,45,16,0,0,229,16,0,0,161,17,0,0,97,18,0,0,37,19,0,0,237,19,0,0,185,20,0,0,137,21,0,0,93,22,0,0,53,23,0,0,17,24,0,0,241,24,0,0,213,25,0,0,189,26,0,0,169,27,0,0,153,28,0,0,141,29,0,0,133,30,0,0,129,31,0,0,129,32,0,0,133,33,0,0,141,34,0,0,153,35,0,0,169,36,0,0,189,37,0,0,213,38,0,0,241,39,0,0,17,41,0,0,53,42,0,0,93,43,0,0,137,44,0,0,185,45,0,0,237,46,0,0,37,48,0,0,97,49,0,0,161,50,0,0,229,51,0,0,45,53,0,0,121,54,0,0,201,55,0,0,29,57,0,0,117,58,0,0,209,59,0,0,49,61,0,0,149,62,0,0,253,63,0,0,105,65,0,0,217,66,0,0,77,68,0,0,197,69,0,0,65,71,0,0,193,72,0,0,69,74,0,0,205,75,0,0,89,77,0,0,233,78,0,0,125,80,0,0,21,82,0,0,177,83,0,0,81,85,0,0,245,86,0,0,157,88,0,0,73,90,0,0,249,91,0,0,173,93,0,0,101,95,0,0,33,97,0,0,225,98,0,0,165,100,0,0,109,102,0,0,57,104,0,0,9,106,0,0,221,107,0,0,181,109,0,0,145,111,0,0,113,113,0,0,85,115,0,0,61,117,0,0,41,119,0,0,25,121,0,0,13,123,0,0,5,125,0,0,1,127,0,0,1,129,0,0,5,131,0,0,13,133,0,0,25,135,0,0,41,137,0,0,61,139,0,0,85,141,0,0,113,143,0,0,145,145,0,0,181,147,0,0,221,149,0,0,9,152,0,0,57,154,0,0,109,156,0,0,165,158,0,0,225,160,0,0,33,163,0,0,101,165,0,0,173,167,0,0,249,169,0,0,73,172,0,0,157,174,0,0,245,176,0,0,81,179,0,0,177,181,0,0,21,184,0,0,125,186,0,0,233,188,0,0,89,191,0,0,205,193,0,0,69,196,0,0,193,198,0,0,65,201,0,0,197,203,0,0,77,206,0,0,217,208,0,0,105,211,0,0,253,213,0,0,149,216,0,0,49,219,0,0,209,221,0,0,117,224,0,0,29,227,0,0,201,229,0,0,121,232,0,0,45,235,0,0,229,237,0,0,161,240,0,0,63,0,0,0,129,0,0,0,231,0,0,0,121,1,0,0,63,2,0,0,65,3,0,0,135,4,0,0,25,6,0,0,255,7,0,0,65,10,0,0,231,12,0,0,249,15,0,0,127,19,0,0,129,23,0,0,7,28,0,0,25,33,0,0,191,38,0,0,1,45,0,0,231,51,0,0,121,59,0,0,191,67,0,0,193,76,0,0,135,86,0,0,25,97,0,0,127,108,0,0,193,120,0,0,231,133,0,0,249,147,0,0,255,162,0,0,1,179,0,0,7,196,0,0,25,214,0,0,63,233,0,0,129,253,0,0,231,18,1,0,121,41,1,0,63,65,1,0,65,90,1,0,135,116,1,0,25,144,1,0,255,172,1,0,65,203,1,0,231,234,1,0,249,11,2,0,127,46,2,0,129,82,2,0,7,120,2,0,25,159,2,0,191,199,2,0,1,242,2,0,231,29,3,0,121,75,3,0,191,122,3,0,193,171,3,0,135,222,3,0,25,19,4,0,127,73,4,0,193,129,4,0,231,187,4,0,249,247,4,0,255,53,5,0,1,118,5,0,7,184,5,0,25,252,5,0,63,66,6,0,129,138,6,0,231,212,6,0,121,33,7,0,63,112,7,0,65,193,7,0,135,20,8,0,25,106,8,0,255,193,8,0,65,28,9,0,231,120,9,0,249,215,9,0,127,57,10,0,129,157,10,0,7,4,11,0,25,109,11,0,191,216,11,0,1,71,12,0,231,183,12,0,121,43,13,0,191,161,13,0,193,26,14,0,135,150,14,0,25,21,15,0,127,150,15,0,193,26,16,0,231,161,16,0,249,43,17,0,255,184,17,0,1,73,18,0,7,220,18,0,25,114,19,0,63,11,20,0,129,167,20,0,231,70,21,0,121,233,21,0,63,143,22,0,65,56,23,0,135,228,23,0,25,148,24,0,255,70,25,0,65,253,25,0,231,182,26,0,249,115,27,0,127,52,28,0,129,248,28,0,7,192,29,0,25,139,30,0,191,89,31,0,1,44,32,0,231,1,33,0,121,219,33,0,191,184,34,0,193,153,35,0,135,126,36,0,25,103,37,0,127,83,38,0,193,67,39,0,231,55,40,0,249,47,41,0,255,43,42,0,1,44,43,0,7,48,44,0,25,56,45,0,63,68,46,0,129,84,47,0,231,104,48,0,121,129,49,0,63,158,50,0,65,191,51,0,135,228,52,0,25,14,54,0,255,59,55,0,65,110,56,0,231,164,57,0,249,223,58,0,127,31,60,0,129,99,61,0,7,172,62,0,25,249,63,0,191,74,65,0,1,161,66,0,231,251,67,0,121,91,69,0,191,191,70,0,193,40,72,0,135,150,73,0,25,9,75,0,127,128,76,0,193,252,77,0,231,125,79,0,249,3,81,0,255,142,82,0,1,31,84,0,7,180,85,0,25,78,87,0,63,237,88,0,129,145,90,0,231,58,92,0,121,233,93,0,63,157,95,0,65,86,97,0,135,20,99,0,25,216,100,0,255,160,102,0,65,111,104,0,231,66,106,0,249,27,108,0,127,250,109,0,65,1,0,0,169,2,0,0,9,5,0,0,193,8,0,0,65,14,0,0,9,22,0,0,169,32,0,0,193,46,0,0,1,65,0,0,41,88,0,0,9,117,0,0,129,152,0,0,129,195,0,0,9,247,0,0,41,52,1,0,1,124,1,0,193,207,1,0,169,48,2,0,9,160,2,0,65,31,3,0,193,175,3,0,9,83,4,0,169,10,5,0,65,216,5,0,129,189,6,0,41,188,7,0,9,214,8,0,1,13,10,0,1,99,11,0,9,218,12,0,41,116,14,0,129,51,16,0,65,26,18,0,169,42,20,0,9,103,22,0,193,209,24,0,65,109,27,0,9,60,30,0,169,64,33,0,193,125,36,0,1,246,39,0,41,172,43,0,9,163,47,0,129,221,51,0,129,94,56,0,9,41,61,0,41,64,66,0,1,167,71,0,193,96,77,0,169,112,83,0,9,218,89,0,65,160,96,0,193,198,103,0,9,81,111,0,169,66,119,0,65,159,127,0,129,106,136,0,41,168,145,0,9,92,155,0,1,138,165,0,1,54,176,0,9,100,187,0,41,24,199,0,129,86,211,0,65,35,224,0,169,130,237,0,9,121,251,0,193,10,10,1,65,60,25,1,9,18,41,1,169,144,57,1,193,188,74,1,1,155,92,1,41,48,111,1,9,129,130,1,129,146,150,1,129,105,171,1,9,11,193,1,41,124,215,1,1,194,238,1,193,225,6,2,169,224,31,2,9,196,57,2,65,145,84,2,193,77,112,2,9,255,140,2,169,170,170,2,65,86,201,2,129,7,233,2,41,196,9,3,9,146,43,3,1,119,78,3,1,121,114,3,9,158,151,3,41,236,189,3,129,105,229,3,65,28,14,4,169,10,56,4,9,59,99,4,193,179,143,4,65,123,189,4,9,152,236,4,169,16,29,5,193,235,78,5,1,48,130,5,41,228,182,5,9,15,237,5,129,183,36,6,129,228,93,6,9,157,152,6,41,232,212,6,1,205,18,7,193,82,82,7,169,128,147,7,9,94,214,7,65,242,26,8,193,68,97,8,9,93,169,8,169,66,243,8,65,253,62,9,129,148,140,9,41,16,220,9,9,120,45,10,1,212,128,10,1,44,214,10,9,136,45,11,41,240,134,11,129,108,226,11,65,5,64,12,169,194,159,12,9,173,1,13,193,204,101,13,65,42,204,13,9,206,52,14,169,192,159,14,193,10,13,15,1,181,124,15,41,200,238,15,9,77,99,16,129,76,218,16,129,207,83,17,9,223,207,17,41,132,78,18,1,200,207,18,193,179,83,19,169,80,218,19,9,168,99,20,65,195,239,20,193,171,126,21,9,107,16,22,169,10,165,22,65,148,60,23,129,17,215,23,41,140,116,24,9,14,21,25,1,161,184,25,1,79,95,26,9,34,9,27,41,36,182,27,129,95,102,28,65,222,25,29,169,170,208,29,9,207,138,30,193,85,72,31,65,73,9,32,9,180,205,32,169,160,149,33,193,25,97,34,1,42,48,35,41,220,2,36,9,59,217,36,129,81,179,37,147,6,0,0,69,14,0,0,15,28,0,0,17,51,0,0,91,87,0,0,13,142,0,0,119,221,0,0,57,77,1,0,99,230,1,0,149,179,2,0,31,193,3,0,33,29,5,0,171,215,6,0,221,2,9,0,7,179,11,0,201,254,14,0,51,255,18,0,229,207,23,0,47,143,29,0,49,94,36,0,251,96,44,0,173,190,53,0,151,161,64,0,89,55,77,0,3,177,91,0,53,67,108,0,63,38,127,0,65,150,148,0,75,211,172,0,125,33,200,0,39,201,230,0,233,22,9,1,211,91,47,1,133,237,89,1,79,38,137,1,81,101,189,1,155,14,247,1,77,139,54,2,183,73,124,2,121,189,200,2,163,95,28,3,213,174,119,3,95,47,219,3,97,107,71,4,235,242,188,4,29,92,60,5,71,67,198,5,9,75,91,6,115,28,252,6,37,103,169,7,111,225,99,8,113,72,44,9,59,96,3,10,237,243,233,10,215,213,224,11,153,223,232,12,67,242,2,14,117,246,47,15,127,220,112,16,129,156,198,17,139,54,50,19,189,178,180,20,103,33,79,22,41,155,2,24,19,65,208,25,197,60,185,27,143,192,190,29,145,7,226,31,219,85,36,34,141,248,134,36,247,69,11,39,185,157,178,41,227,104,126,44,21,26,112,47,159,45,137,50,161,41,203,53,43,158,55,57,93,37,208,60,135,99,150,64,73,7,140,68,179,201,178,72,101,110,12,77,175,195,154,81,177,162,95,86,123,239,92,91,45,153,148,96,23,154,8,102,217,247,186,107,131,195,173,113,181,25,227,119,191,34,93,126,29,35,0,0,113,77,0,0,145,156,0,0,253,38,1,0,101,12,2,0,233,119,3,0,153,162,5,0,53,214,8,0,45,112,13,0,225,228,19,0,33,195,28,0,237,183,40,0,117,146,56,0,89,72,77,0,41,250,103,0,37,248,137,0,61,199,180,0,81,38,234,0,177,19,44,1,221,210,124,1,133,242,222,1,201,82,85,2,185,43,227,2,21,20,140,3,77,8,84,4,193,113,63,5,65,46,83,6,205,151,148,7,149,140,9,9,57,119,184,10,73,87,168,12,5,202,224,14,93,19,106,17,49,39,77,20,209,178,147,23,189,38,72,27,165,192,117,31,169,149,40,36,217,156,109,41,245,185,82,47,109,200,230,53,161,166,57,61,97,65,92,69,173,159,96,78,181,238,89,88,25,142,92,99,105,28,126,111,229,131,213,124,255,189,0,0,1,168,1,0,143,107,3,0,241,158,6,0,63,35,12,0,193,61,21,0,143,182,35,0,241,252,57,0,255,81,91,0,1,250,139,0,15,117,209,0,113,191,50,1,63,154,184,1,193,220,109,2,15,207,95,3,113,142,158,4,255,123,61,6,1,182,83,8,143,156,252,10,241,97,88,14,63,167,140,18,193,37,197,23,143,101,52,30,241,129,20,38,255,251,167,47,1,156,58,59,15,98,34,73,113,134,192,89,63,138,130,109,193,88,227,132,1,14,4,0,145,33,9,0,17,44,19,0,65,238,37,0,65,79,71,0,145,67,128,0,17,247,221,0,1,70,115,1,1,146,90,2,17,1,184,3,145,53,188,5,65,143,167,8,65,6,206,12,17,178,155,18,145,15,154,26,1,26,118,37,1,76,7,52,145,158,87,71,17,157,172,96,65,166,145,129,35,81,22,0,197,158,50,0,23,185,107,0,153,246,216,0,107,137,160,1,13,196,254,2,31,1,80,5,33,217,29,9,51,108,48,15,213,162,164,24,167,103,8,39,41,253,125,60,123,181,231,91,29,119,29,137,175,160,45,201,173,142,123,0,137,230,25,1,57,150,94,2,61,22,216,4,181,99,119,9,225,40,198,17,33,3,52,32,117,72,130,56,125,87,87,96,191,91,175,2,129,216,39,6,247,132,94,13,233,254,173,27,127,139,235,54,129,183,229,104,23,3,156,193,193,12,255,14,57,106,133,34,25,238,145,75,129,120,43,158,51,225,9,84,0,64,202,69,27,76,255,82,130,90,179,98,162,107,96,117,0,1,1,1,2,3,3,3,2,3,3,3,2,3,3,3,0,3,12,15,48,51,60,63,192,195,204,207,240,243,252,255,1,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,3,0,0,0,6,0,0,0,1,0,0,0,5,0,0,0,2,0,0,0,15,0,0,0,0,0,0,0,8,0,0,0,7,0,0,0,12,0,0,0,3,0,0,0,11,0,0,0,4,0,0,0,14,0,0,0,1,0,0,0,9,0,0,0,6,0,0,0,13,0,0,0,2,0,0,0,10,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,79,112,117,115,32,100,101,99,111,100,105,110,103,32,101,114,114,111,114,44,32,99,111,100,101,32,37,100,10,0,0,0,79,112,117,115,72,101,97,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE+20692);var tempDoublePtr=Runtime.alignMemory(allocate(12,"i8",ALLOC_STATIC),8);assert(tempDoublePtr%8==0);function copyTempFloat(ptr){HEAP8[tempDoublePtr]=HEAP8[ptr];HEAP8[tempDoublePtr+1]=HEAP8[ptr+1];HEAP8[tempDoublePtr+2]=HEAP8[ptr+2];HEAP8[tempDoublePtr+3]=HEAP8[ptr+3]}function copyTempDouble(ptr){HEAP8[tempDoublePtr]=HEAP8[ptr];HEAP8[tempDoublePtr+1]=HEAP8[ptr+1];HEAP8[tempDoublePtr+2]=HEAP8[ptr+2];HEAP8[tempDoublePtr+3]=HEAP8[ptr+3];HEAP8[tempDoublePtr+4]=HEAP8[ptr+4];HEAP8[tempDoublePtr+5]=HEAP8[ptr+5];HEAP8[tempDoublePtr+6]=HEAP8[ptr+6];HEAP8[tempDoublePtr+7]=HEAP8[ptr+7]}Module["_bitshift64Ashr"]=_bitshift64Ashr;function _time(ptr){var ret=Date.now()/1e3|0;if(ptr){HEAP32[ptr>>2]=ret}return ret}var ___errno_state=0;function ___setErrNo(value){HEAP32[___errno_state>>2]=value;return value}var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};function _sysconf(name){switch(name){case 30:return PAGE_SIZE;case 85:return totalMemory/PAGE_SIZE;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:return 200809;case 79:return 0;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return-1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}___setErrNo(ERRNO_CODES.EINVAL);return-1}var _llvm_ctlz_i32=true;function ___errno_location(){return ___errno_state}Module["_memset"]=_memset;function _ogvjs_callback_audio(buffers,channels,sampleCount){var HEAPU32=Module.HEAPU32;var HEAPF32=Module.HEAPF32;var outputBuffers=[];if(buffers!==0){var inPtr,inArray,outArray,i;for(var channel=0;channel<channels;channel++){inPtr=HEAPU32[buffers/4+channel];inArray=HEAPF32.subarray(inPtr/4,inPtr/4+sampleCount);outArray=new Float32Array(inArray);outputBuffers.push(outArray)}}Module.audioBuffer=outputBuffers}function _abort(){Module["abort"]()}var FS=undefined;var SOCKFS=undefined;function _send(fd,buf,len,flags){var sock=SOCKFS.getSocket(fd);if(!sock){___setErrNo(ERRNO_CODES.EBADF);return-1}return _write(fd,buf,len)}function _pwrite(fildes,buf,nbyte,offset){var stream=FS.getStream(fildes);if(!stream){___setErrNo(ERRNO_CODES.EBADF);return-1}try{var slab=HEAP8;return FS.write(stream,slab,buf,nbyte,offset)}catch(e){FS.handleFSError(e);return-1}}function _write(fildes,buf,nbyte){var stream=FS.getStream(fildes);if(!stream){___setErrNo(ERRNO_CODES.EBADF);return-1}try{var slab=HEAP8;return FS.write(stream,slab,buf,nbyte)}catch(e){FS.handleFSError(e);return-1}}function _fileno(stream){stream=FS.getStreamFromPtr(stream);if(!stream)return-1;return stream.fd}function _fwrite(ptr,size,nitems,stream){var bytesToWrite=nitems*size;if(bytesToWrite==0)return 0;var fd=_fileno(stream);var bytesWritten=_write(fd,ptr,bytesToWrite);if(bytesWritten==-1){var streamObj=FS.getStreamFromPtr(stream);if(streamObj)streamObj.error=true;return 0}else{return bytesWritten/size|0}}Module["_strlen"]=_strlen;function __reallyNegative(x){return x<0||x===0&&1/x===-Infinity}function __formatString(format,varargs){assert((varargs&3)===0);var textIndex=format;var argIndex=0;function getNextArg(type){var ret;argIndex=Runtime.prepVararg(argIndex,type);if(type==="double"){ret=(HEAP32[tempDoublePtr>>2]=HEAP32[varargs+argIndex>>2],HEAP32[tempDoublePtr+4>>2]=HEAP32[varargs+(argIndex+4)>>2],+HEAPF64[tempDoublePtr>>3]);argIndex+=8}else if(type=="i64"){ret=[HEAP32[varargs+argIndex>>2],HEAP32[varargs+(argIndex+4)>>2]];argIndex+=8}else{assert((argIndex&3)===0);type="i32";ret=HEAP32[varargs+argIndex>>2];argIndex+=4}return ret}var ret=[];var curr,next,currArg;while(1){var startTextIndex=textIndex;curr=HEAP8[textIndex>>0];if(curr===0)break;next=HEAP8[textIndex+1>>0];if(curr==37){var flagAlwaysSigned=false;var flagLeftAlign=false;var flagAlternative=false;var flagZeroPad=false;var flagPadSign=false;flagsLoop:while(1){switch(next){case 43:flagAlwaysSigned=true;break;case 45:flagLeftAlign=true;break;case 35:flagAlternative=true;break;case 48:if(flagZeroPad){break flagsLoop}else{flagZeroPad=true;break};case 32:flagPadSign=true;break;default:break flagsLoop}textIndex++;next=HEAP8[textIndex+1>>0]}var width=0;if(next==42){width=getNextArg("i32");textIndex++;next=HEAP8[textIndex+1>>0]}else{while(next>=48&&next<=57){width=width*10+(next-48);textIndex++;next=HEAP8[textIndex+1>>0]}}var precisionSet=false,precision=-1;if(next==46){precision=0;precisionSet=true;textIndex++;next=HEAP8[textIndex+1>>0];if(next==42){precision=getNextArg("i32");textIndex++}else{while(1){var precisionChr=HEAP8[textIndex+1>>0];if(precisionChr<48||precisionChr>57)break;precision=precision*10+(precisionChr-48);textIndex++}}next=HEAP8[textIndex+1>>0]}if(precision<0){precision=6;precisionSet=false}var argSize;switch(String.fromCharCode(next)){case"h":var nextNext=HEAP8[textIndex+2>>0];if(nextNext==104){textIndex++;argSize=1}else{argSize=2}break;case"l":var nextNext=HEAP8[textIndex+2>>0];if(nextNext==108){textIndex++;argSize=8}else{argSize=4}break;case"L":case"q":case"j":argSize=8;break;case"z":case"t":case"I":argSize=4;break;default:argSize=null}if(argSize)textIndex++;next=HEAP8[textIndex+1>>0];switch(String.fromCharCode(next)){case"d":case"i":case"u":case"o":case"x":case"X":case"p":{var signed=next==100||next==105;argSize=argSize||4;var currArg=getNextArg("i"+argSize*8);var origArg=currArg;var argText;if(argSize==8){currArg=Runtime.makeBigInt(currArg[0],currArg[1],next==117)}if(argSize<=4){var limit=Math.pow(256,argSize)-1;currArg=(signed?reSign:unSign)(currArg&limit,argSize*8)}var currAbsArg=Math.abs(currArg);var prefix="";if(next==100||next==105){if(argSize==8&&i64Math)argText=i64Math.stringify(origArg[0],origArg[1],null);else argText=reSign(currArg,8*argSize,1).toString(10)}else if(next==117){if(argSize==8&&i64Math)argText=i64Math.stringify(origArg[0],origArg[1],true);else argText=unSign(currArg,8*argSize,1).toString(10);currArg=Math.abs(currArg)}else if(next==111){argText=(flagAlternative?"0":"")+currAbsArg.toString(8)}else if(next==120||next==88){prefix=flagAlternative&&currArg!=0?"0x":"";if(argSize==8&&i64Math){if(origArg[1]){argText=(origArg[1]>>>0).toString(16);var lower=(origArg[0]>>>0).toString(16);while(lower.length<8)lower="0"+lower;argText+=lower}else{argText=(origArg[0]>>>0).toString(16)}}else if(currArg<0){currArg=-currArg;argText=(currAbsArg-1).toString(16);var buffer=[];for(var i=0;i<argText.length;i++){buffer.push((15-parseInt(argText[i],16)).toString(16))}argText=buffer.join("");while(argText.length<argSize*2)argText="f"+argText}else{argText=currAbsArg.toString(16)}if(next==88){prefix=prefix.toUpperCase();argText=argText.toUpperCase()}}else if(next==112){if(currAbsArg===0){argText="(nil)"}else{prefix="0x";argText=currAbsArg.toString(16)}}if(precisionSet){while(argText.length<precision){argText="0"+argText}}if(currArg>=0){if(flagAlwaysSigned){prefix="+"+prefix}else if(flagPadSign){prefix=" "+prefix}}if(argText.charAt(0)=="-"){prefix="-"+prefix;argText=argText.substr(1)}while(prefix.length+argText.length<width){if(flagLeftAlign){argText+=" "}else{if(flagZeroPad){argText="0"+argText}else{prefix=" "+prefix}}}argText=prefix+argText;argText.split("").forEach((function(chr){ret.push(chr.charCodeAt(0))}));break};case"f":case"F":case"e":case"E":case"g":case"G":{var currArg=getNextArg("double");var argText;if(isNaN(currArg)){argText="nan";flagZeroPad=false}else if(!isFinite(currArg)){argText=(currArg<0?"-":"")+"inf";flagZeroPad=false}else{var isGeneral=false;var effectivePrecision=Math.min(precision,20);if(next==103||next==71){isGeneral=true;precision=precision||1;var exponent=parseInt(currArg.toExponential(effectivePrecision).split("e")[1],10);if(precision>exponent&&exponent>=-4){next=(next==103?"f":"F").charCodeAt(0);precision-=exponent+1}else{next=(next==103?"e":"E").charCodeAt(0);precision--}effectivePrecision=Math.min(precision,20)}if(next==101||next==69){argText=currArg.toExponential(effectivePrecision);if(/[eE][-+]\d$/.test(argText)){argText=argText.slice(0,-1)+"0"+argText.slice(-1)}}else if(next==102||next==70){argText=currArg.toFixed(effectivePrecision);if(currArg===0&&__reallyNegative(currArg)){argText="-"+argText}}var parts=argText.split("e");if(isGeneral&&!flagAlternative){while(parts[0].length>1&&parts[0].indexOf(".")!=-1&&(parts[0].slice(-1)=="0"||parts[0].slice(-1)==".")){parts[0]=parts[0].slice(0,-1)}}else{if(flagAlternative&&argText.indexOf(".")==-1)parts[0]+=".";while(precision>effectivePrecision++)parts[0]+="0"}argText=parts[0]+(parts.length>1?"e"+parts[1]:"");if(next==69)argText=argText.toUpperCase();if(currArg>=0){if(flagAlwaysSigned){argText="+"+argText}else if(flagPadSign){argText=" "+argText}}}while(argText.length<width){if(flagLeftAlign){argText+=" "}else{if(flagZeroPad&&(argText[0]=="-"||argText[0]=="+")){argText=argText[0]+"0"+argText.slice(1)}else{argText=(flagZeroPad?"0":" ")+argText}}}if(next<97)argText=argText.toUpperCase();argText.split("").forEach((function(chr){ret.push(chr.charCodeAt(0))}));break};case"s":{var arg=getNextArg("i8*");var argLength=arg?_strlen(arg):"(null)".length;if(precisionSet)argLength=Math.min(argLength,precision);if(!flagLeftAlign){while(argLength<width--){ret.push(32)}}if(arg){for(var i=0;i<argLength;i++){ret.push(HEAPU8[arg++>>0])}}else{ret=ret.concat(intArrayFromString("(null)".substr(0,argLength),true))}if(flagLeftAlign){while(argLength<width--){ret.push(32)}}break};case"c":{if(flagLeftAlign)ret.push(getNextArg("i8"));while(--width>0){ret.push(32)}if(!flagLeftAlign)ret.push(getNextArg("i8"));break};case"n":{var ptr=getNextArg("i32*");HEAP32[ptr>>2]=ret.length;break};case"%":{ret.push(curr);break};default:{for(var i=startTextIndex;i<textIndex+2;i++){ret.push(HEAP8[i>>0])}}}textIndex+=2}else{ret.push(curr);textIndex+=1}}return ret}function _fprintf(stream,format,varargs){var result=__formatString(format,varargs);var stack=Runtime.stackSave();var ret=_fwrite(allocate(result,"i8",ALLOC_STACK),1,result.length,stream);Runtime.stackRestore(stack);return ret}function _printf(format,varargs){var result=__formatString(format,varargs);var string=intArrayToString(result);if(string[string.length-1]==="\n")string=string.substr(0,string.length-1);Module.print(string);return result.length}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest);return dest}Module["_memcpy"]=_memcpy;function _llvm_stackrestore(p){var self=_llvm_stacksave;var ret=self.LLVM_SAVEDSTACKS[p];self.LLVM_SAVEDSTACKS.splice(p,1);Runtime.stackRestore(ret)}var _cos=Math_cos;Module["_i64Add"]=_i64Add;var _fabs=Math_abs;var _floor=Math_floor;function _llvm_stacksave(){var self=_llvm_stacksave;if(!self.LLVM_SAVEDSTACKS){self.LLVM_SAVEDSTACKS=[]}self.LLVM_SAVEDSTACKS.push(Runtime.stackSave());return self.LLVM_SAVEDSTACKS.length-1}function _ogvjs_callback_init_audio(channels,rate){Module.audioFormat={channels:channels,rate:rate};Module.loadedMetadata=true}var _sqrt=Math_sqrt;var _atan2=Math_atan2;var _abs=Math_abs;function _sbrk(bytes){var self=_sbrk;if(!self.called){DYNAMICTOP=alignMemoryPage(DYNAMICTOP);self.called=true;assert(Runtime.dynamicAlloc);self.alloc=Runtime.dynamicAlloc;Runtime.dynamicAlloc=(function(){abort("cannot dynamically allocate, sbrk now has control")})}var ret=DYNAMICTOP;if(bytes!=0){var success=self.alloc(bytes);if(!success)return-1>>>0}return ret}var _exp=Math_exp;var _llvm_pow_f64=Math_pow;Module["_memmove"]=_memmove;___errno_state=Runtime.staticAlloc(4);HEAP32[___errno_state>>2]=0;STACK_BASE=STACKTOP=Runtime.alignMemory(STATICTOP);staticSealed=true;STACK_MAX=STACK_BASE+TOTAL_STACK;DYNAMIC_BASE=DYNAMICTOP=Runtime.alignMemory(STACK_MAX);assert(DYNAMIC_BASE<TOTAL_MEMORY,"TOTAL_MEMORY not big enough for stack");var cttz_i8=allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0],"i8",ALLOC_DYNAMIC);function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){try{Module["dynCall_viiiiii"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}Module.asmGlobalArg={"Math":Math,"Int8Array":Int8Array,"Int16Array":Int16Array,"Int32Array":Int32Array,"Uint8Array":Uint8Array,"Uint16Array":Uint16Array,"Uint32Array":Uint32Array,"Float32Array":Float32Array,"Float64Array":Float64Array,"NaN":NaN,"Infinity":Infinity};Module.asmLibraryArg={"abort":abort,"assert":assert,"invoke_viiiiii":invoke_viiiiii,"_fabs":_fabs,"_exp":_exp,"_llvm_pow_f64":_llvm_pow_f64,"_send":_send,"_atan2":_atan2,"___setErrNo":___setErrNo,"_llvm_stackrestore":_llvm_stackrestore,"_floor":_floor,"_pwrite":_pwrite,"__reallyNegative":__reallyNegative,"_sbrk":_sbrk,"_ogvjs_callback_init_audio":_ogvjs_callback_init_audio,"_fileno":_fileno,"_sysconf":_sysconf,"_emscripten_memcpy_big":_emscripten_memcpy_big,"_cos":_cos,"_llvm_stacksave":_llvm_stacksave,"_printf":_printf,"_ogvjs_callback_audio":_ogvjs_callback_audio,"_write":_write,"___errno_location":___errno_location,"_abort":_abort,"_fwrite":_fwrite,"_time":_time,"_fprintf":_fprintf,"_abs":_abs,"__formatString":__formatString,"_sqrt":_sqrt,"STACKTOP":STACKTOP,"STACK_MAX":STACK_MAX,"tempDoublePtr":tempDoublePtr,"ABORT":ABORT,"cttz_i8":cttz_i8};// EMSCRIPTEN_START_ASM
+var asm=(function(global,env,buffer) {
+"use asm";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.tempDoublePtr|0;var l=env.ABORT|0;var m=env.cttz_i8|0;var n=0;var o=0;var p=0;var q=0;var r=global.NaN,s=global.Infinity;var t=0,u=0,v=0,w=0,x=0.0,y=0,z=0,A=0,B=0.0;var C=0;var D=0;var E=0;var F=0;var G=0;var H=0;var I=0;var J=0;var K=0;var L=0;var M=global.Math.floor;var N=global.Math.abs;var O=global.Math.sqrt;var P=global.Math.pow;var Q=global.Math.cos;var R=global.Math.sin;var S=global.Math.tan;var T=global.Math.acos;var U=global.Math.asin;var V=global.Math.atan;var W=global.Math.atan2;var X=global.Math.exp;var Y=global.Math.log;var Z=global.Math.ceil;var _=global.Math.imul;var $=global.Math.min;var aa=global.Math.clz32;var ba=env.abort;var ca=env.assert;var da=env.invoke_viiiiii;var ea=env._fabs;var fa=env._exp;var ga=env._llvm_pow_f64;var ha=env._send;var ia=env._atan2;var ja=env.___setErrNo;var ka=env._llvm_stackrestore;var la=env._floor;var ma=env._pwrite;var na=env.__reallyNegative;var oa=env._sbrk;var pa=env._ogvjs_callback_init_audio;var qa=env._fileno;var ra=env._sysconf;var sa=env._emscripten_memcpy_big;var ta=env._cos;var ua=env._llvm_stacksave;var va=env._printf;var wa=env._ogvjs_callback_audio;var xa=env._write;var ya=env.___errno_location;var za=env._abort;var Aa=env._fwrite;var Ba=env._time;var Ca=env._fprintf;var Da=env._abs;var Ea=env.__formatString;var Fa=env._sqrt;var Ga=0.0;
+// EMSCRIPTEN_START_FUNCS
+function kc(a,d,e){a=a|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;f=i;i=i+48|0;g=f+12|0;h=f+16|0;j=f+28|0;k=f+4|0;l=f+32|0;m=f+36|0;n=f+40|0;o=f+44|0;p=f+20|0;q=f+8|0;r=f;s=f+24|0;c[g>>2]=a;c[h>>2]=d;c[j>>2]=e;c[l>>2]=0;c[n>>2]=0;while(1){if((c[n>>2]|0)>=20)break;c[q>>2]=(b[c[g>>2]>>1]|0)-(b[c[h>>2]>>1]|0);c[l>>2]=0;c[k>>2]=1;while(1){if((c[k>>2]|0)>((c[j>>2]|0)-1|0))break;c[p>>2]=(b[(c[g>>2]|0)+(c[k>>2]<<1)>>1]|0)-((b[(c[g>>2]|0)+((c[k>>2]|0)-1<<1)>>1]|0)+(b[(c[h>>2]|0)+(c[k>>2]<<1)>>1]|0));if((c[p>>2]|0)<(c[q>>2]|0)){c[q>>2]=c[p>>2];c[l>>2]=c[k>>2]}c[k>>2]=(c[k>>2]|0)+1}c[p>>2]=32768-((b[(c[g>>2]|0)+((c[j>>2]|0)-1<<1)>>1]|0)+(b[(c[h>>2]|0)+(c[j>>2]<<1)>>1]|0));if((c[p>>2]|0)<(c[q>>2]|0)){c[q>>2]=c[p>>2];c[l>>2]=c[j>>2]}if((c[q>>2]|0)>=0){t=41;break}do if(!(c[l>>2]|0))b[c[g>>2]>>1]=b[c[h>>2]>>1]|0;else{if((c[l>>2]|0)==(c[j>>2]|0)){b[(c[g>>2]|0)+((c[j>>2]|0)-1<<1)>>1]=32768-(b[(c[h>>2]|0)+(c[j>>2]<<1)>>1]|0);break}c[r>>2]=0;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[l>>2]|0))break;c[r>>2]=(c[r>>2]|0)+(b[(c[h>>2]|0)+(c[m>>2]<<1)>>1]|0);c[m>>2]=(c[m>>2]|0)+1}c[r>>2]=(c[r>>2]|0)+(b[(c[h>>2]|0)+(c[l>>2]<<1)>>1]>>1);c[s>>2]=32768;c[m>>2]=c[j>>2];while(1){if((c[m>>2]|0)<=(c[l>>2]|0))break;c[s>>2]=(c[s>>2]|0)-(b[(c[h>>2]|0)+(c[m>>2]<<1)>>1]|0);c[m>>2]=(c[m>>2]|0)+-1}c[s>>2]=(c[s>>2]|0)-(b[(c[h>>2]|0)+(c[l>>2]<<1)>>1]>>1);e=((b[(c[g>>2]|0)+((c[l>>2]|0)-1<<1)>>1]|0)+(b[(c[g>>2]|0)+(c[l>>2]<<1)>>1]|0)>>1)+((b[(c[g>>2]|0)+((c[l>>2]|0)-1<<1)>>1]|0)+(b[(c[g>>2]|0)+(c[l>>2]<<1)>>1]|0)&1)|0;do if((c[r>>2]|0)>(c[s>>2]|0)){if((e|0)>(c[r>>2]|0)){u=c[r>>2]|0;break}if((((b[(c[g>>2]|0)+((c[l>>2]|0)-1<<1)>>1]|0)+(b[(c[g>>2]|0)+(c[l>>2]<<1)>>1]|0)>>1)+((b[(c[g>>2]|0)+((c[l>>2]|0)-1<<1)>>1]|0)+(b[(c[g>>2]|0)+(c[l>>2]<<1)>>1]|0)&1)|0)<(c[s>>2]|0)){u=c[s>>2]|0;break}else{u=((b[(c[g>>2]|0)+((c[l>>2]|0)-1<<1)>>1]|0)+(b[(c[g>>2]|0)+(c[l>>2]<<1)>>1]|0)>>1)+((b[(c[g>>2]|0)+((c[l>>2]|0)-1<<1)>>1]|0)+(b[(c[g>>2]|0)+(c[l>>2]<<1)>>1]|0)&1)|0;break}}else{if((e|0)>(c[s>>2]|0)){u=c[s>>2]|0;break}if((((b[(c[g>>2]|0)+((c[l>>2]|0)-1<<1)>>1]|0)+(b[(c[g>>2]|0)+(c[l>>2]<<1)>>1]|0)>>1)+((b[(c[g>>2]|0)+((c[l>>2]|0)-1<<1)>>1]|0)+(b[(c[g>>2]|0)+(c[l>>2]<<1)>>1]|0)&1)|0)<(c[r>>2]|0)){u=c[r>>2]|0;break}else{u=((b[(c[g>>2]|0)+((c[l>>2]|0)-1<<1)>>1]|0)+(b[(c[g>>2]|0)+(c[l>>2]<<1)>>1]|0)>>1)+((b[(c[g>>2]|0)+((c[l>>2]|0)-1<<1)>>1]|0)+(b[(c[g>>2]|0)+(c[l>>2]<<1)>>1]|0)&1)|0;break}}while(0);b[o>>1]=u;b[(c[g>>2]|0)+((c[l>>2]|0)-1<<1)>>1]=(b[o>>1]|0)-(b[(c[h>>2]|0)+(c[l>>2]<<1)>>1]>>1);b[(c[g>>2]|0)+(c[l>>2]<<1)>>1]=(b[(c[g>>2]|0)+((c[l>>2]|0)-1<<1)>>1]|0)+(b[(c[h>>2]|0)+(c[l>>2]<<1)>>1]|0)}while(0);c[n>>2]=(c[n>>2]|0)+1}if((t|0)==41){i=f;return}if((c[n>>2]|0)!=20){i=f;return}tc(c[g>>2]|0,c[j>>2]|0);n=(Rd(b[c[g>>2]>>1]|0,b[c[h>>2]>>1]|0)|0)&65535;b[c[g>>2]>>1]=n;c[k>>2]=1;while(1){if((c[k>>2]|0)>=(c[j>>2]|0))break;n=(Rd(b[(c[g>>2]|0)+(c[k>>2]<<1)>>1]|0,(b[(c[g>>2]|0)+((c[k>>2]|0)-1<<1)>>1]|0)+(b[(c[h>>2]|0)+(c[k>>2]<<1)>>1]|0)|0)|0)&65535;b[(c[g>>2]|0)+(c[k>>2]<<1)>>1]=n;c[k>>2]=(c[k>>2]|0)+1}n=(Sd(b[(c[g>>2]|0)+((c[j>>2]|0)-1<<1)>>1]|0,32768-(b[(c[h>>2]|0)+(c[j>>2]<<1)>>1]|0)|0)|0)&65535;b[(c[g>>2]|0)+((c[j>>2]|0)-1<<1)>>1]=n;c[k>>2]=(c[j>>2]|0)-2;while(1){if((c[k>>2]|0)<0)break;j=(Sd(b[(c[g>>2]|0)+(c[k>>2]<<1)>>1]|0,(b[(c[g>>2]|0)+((c[k>>2]|0)+1<<1)>>1]|0)-(b[(c[h>>2]|0)+((c[k>>2]|0)+1<<1)>>1]|0)|0)|0)&65535;b[(c[g>>2]|0)+(c[k>>2]<<1)>>1]=j;c[k>>2]=(c[k>>2]|0)+-1}i=f;return}function lc(a,d,e){a=a|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+32|0;g=f+20|0;h=f+16|0;j=f+12|0;k=f+8|0;l=f+4|0;m=f;c[g>>2]=a;c[h>>2]=d;c[j>>2]=e;c[l>>2]=Td(b[c[h>>2]>>1]|0,1)|0;c[l>>2]=131072/(c[l>>2]|0)|0;c[m>>2]=Td((b[(c[h>>2]|0)+2>>1]|0)-(b[c[h>>2]>>1]|0)|0,1)|0;c[m>>2]=131072/(c[m>>2]|0)|0;e=(Ud((c[l>>2]|0)+(c[m>>2]|0)|0,32767)|0)&65535;b[c[g>>2]>>1]=e;c[k>>2]=1;while(1){if((c[k>>2]|0)>=((c[j>>2]|0)-1|0))break;c[l>>2]=Td((b[(c[h>>2]|0)+((c[k>>2]|0)+1<<1)>>1]|0)-(b[(c[h>>2]|0)+(c[k>>2]<<1)>>1]|0)|0,1)|0;c[l>>2]=131072/(c[l>>2]|0)|0;e=(Ud((c[l>>2]|0)+(c[m>>2]|0)|0,32767)|0)&65535;b[(c[g>>2]|0)+(c[k>>2]<<1)>>1]=e;c[m>>2]=Td((b[(c[h>>2]|0)+((c[k>>2]|0)+2<<1)>>1]|0)-(b[(c[h>>2]|0)+((c[k>>2]|0)+1<<1)>>1]|0)|0,1)|0;c[m>>2]=131072/(c[m>>2]|0)|0;e=(Ud((c[l>>2]|0)+(c[m>>2]|0)|0,32767)|0)&65535;b[(c[g>>2]|0)+((c[k>>2]|0)+1<<1)>>1]=e;c[k>>2]=(c[k>>2]|0)+2}c[l>>2]=Td(32768-(b[(c[h>>2]|0)+((c[j>>2]|0)-1<<1)>>1]|0)|0,1)|0;c[l>>2]=131072/(c[l>>2]|0)|0;h=(Ud((c[l>>2]|0)+(c[m>>2]|0)|0,32767)|0)&65535;b[(c[g>>2]|0)+((c[j>>2]|0)-1<<1)>>1]=h;i=f;return}function mc(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;g=i;i=i+32|0;h=g+20|0;j=g+16|0;k=g+12|0;l=g+8|0;m=g+4|0;n=g;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;c[m>>2]=f;bf(c[j>>2]|0,0,300)|0;f=(c[k>>2]|0)!=8e3&(c[k>>2]|0)!=12e3&(c[k>>2]|0)!=16e3;do if(c[m>>2]|0){if(!(f&(c[k>>2]|0)!=24e3&(c[k>>2]|0)!=48e3)?!((c[l>>2]|0)!=8e3&(c[l>>2]|0)!=12e3&(c[l>>2]|0)!=16e3):0){c[(c[j>>2]|0)+292>>2]=a[3e3+((((c[k>>2]>>12)-((c[k>>2]|0)>16e3&1)>>((c[k>>2]|0)>24e3&1))-1|0)*3|0)+(((c[l>>2]>>12)-((c[l>>2]|0)>16e3&1)>>((c[l>>2]|0)>24e3&1))-1)>>0];break}c[h>>2]=-1;o=c[h>>2]|0;i=g;return o|0}else{if(!f?!((c[l>>2]|0)!=8e3&(c[l>>2]|0)!=12e3&(c[l>>2]|0)!=16e3&(c[l>>2]|0)!=24e3&(c[l>>2]|0)!=48e3):0){c[(c[j>>2]|0)+292>>2]=a[3016+((((c[k>>2]>>12)-((c[k>>2]|0)>16e3&1)>>((c[k>>2]|0)>24e3&1))-1|0)*5|0)+(((c[l>>2]>>12)-((c[l>>2]|0)>16e3&1)>>((c[l>>2]|0)>24e3&1))-1)>>0];break}c[h>>2]=-1;o=c[h>>2]|0;i=g;return o|0}while(0);c[(c[j>>2]|0)+284>>2]=(c[k>>2]|0)/1e3|0;c[(c[j>>2]|0)+288>>2]=(c[l>>2]|0)/1e3|0;c[(c[j>>2]|0)+268>>2]=(c[(c[j>>2]|0)+284>>2]|0)*10;c[n>>2]=0;f=c[l>>2]|0;m=c[k>>2]|0;do if((c[l>>2]|0)>(c[k>>2]|0)){e=(c[j>>2]|0)+264|0;if((f|0)==(m<<1|0)){c[e>>2]=1;break}else{c[e>>2]=2;c[n>>2]=1;break}}else{e=(c[j>>2]|0)+264|0;if((f|0)>=(m|0)){c[e>>2]=0;break}c[e>>2]=3;if((c[l>>2]<<2|0)==((c[k>>2]|0)*3|0)){c[(c[j>>2]|0)+280>>2]=3;c[(c[j>>2]|0)+276>>2]=18;c[(c[j>>2]|0)+296>>2]=2024;break}if(((c[l>>2]|0)*3|0)==(c[k>>2]<<1|0)){c[(c[j>>2]|0)+280>>2]=2;c[(c[j>>2]|0)+276>>2]=18;c[(c[j>>2]|0)+296>>2]=2088;break}if((c[l>>2]<<1|0)==(c[k>>2]|0)){c[(c[j>>2]|0)+280>>2]=1;c[(c[j>>2]|0)+276>>2]=24;c[(c[j>>2]|0)+296>>2]=2128;break}if(((c[l>>2]|0)*3|0)==(c[k>>2]|0)){c[(c[j>>2]|0)+280>>2]=1;c[(c[j>>2]|0)+276>>2]=36;c[(c[j>>2]|0)+296>>2]=2160;break}if((c[l>>2]<<2|0)==(c[k>>2]|0)){c[(c[j>>2]|0)+280>>2]=1;c[(c[j>>2]|0)+276>>2]=36;c[(c[j>>2]|0)+296>>2]=2200;break}if(((c[l>>2]|0)*6|0)==(c[k>>2]|0)){c[(c[j>>2]|0)+280>>2]=1;c[(c[j>>2]|0)+276>>2]=36;c[(c[j>>2]|0)+296>>2]=2240;break}c[h>>2]=-1;o=c[h>>2]|0;i=g;return o|0}while(0);c[(c[j>>2]|0)+272>>2]=((c[k>>2]<<14+(c[n>>2]|0)|0)/(c[l>>2]|0)|0)<<2;while(1){m=_(c[(c[j>>2]|0)+272>>2]>>16,(c[l>>2]&65535)<<16>>16)|0;f=m+((_(c[(c[j>>2]|0)+272>>2]&65535,(c[l>>2]&65535)<<16>>16)|0)>>16)|0;m=f+(_(c[(c[j>>2]|0)+272>>2]|0,(c[l>>2]>>15)+1>>1)|0)|0;if((m|0)>=(c[k>>2]<<c[n>>2]|0))break;m=(c[j>>2]|0)+272|0;c[m>>2]=(c[m>>2]|0)+1}c[h>>2]=0;o=c[h>>2]|0;i=g;return o|0}function nc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0;f=i;i=i+32|0;g=f+16|0;h=f+12|0;j=f+8|0;k=f+4|0;l=f;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[k>>2]=e;c[l>>2]=(c[(c[g>>2]|0)+284>>2]|0)-(c[(c[g>>2]|0)+292>>2]|0);df((c[g>>2]|0)+168+(c[(c[g>>2]|0)+292>>2]<<1)|0,c[j>>2]|0,c[l>>2]<<1|0)|0;e=c[(c[g>>2]|0)+264>>2]|0;if((e|0)==1){sc(c[g>>2]|0,c[h>>2]|0,(c[g>>2]|0)+168|0,c[(c[g>>2]|0)+284>>2]|0);sc(c[g>>2]|0,(c[h>>2]|0)+(c[(c[g>>2]|0)+288>>2]<<1)|0,(c[j>>2]|0)+(c[l>>2]<<1)|0,(c[k>>2]|0)-(c[(c[g>>2]|0)+284>>2]|0)|0)}else if((e|0)==2){qc(c[g>>2]|0,c[h>>2]|0,(c[g>>2]|0)+168|0,c[(c[g>>2]|0)+284>>2]|0);qc(c[g>>2]|0,(c[h>>2]|0)+(c[(c[g>>2]|0)+288>>2]<<1)|0,(c[j>>2]|0)+(c[l>>2]<<1)|0,(c[k>>2]|0)-(c[(c[g>>2]|0)+284>>2]|0)|0)}else if((e|0)==3){pc(c[g>>2]|0,c[h>>2]|0,(c[g>>2]|0)+168|0,c[(c[g>>2]|0)+284>>2]|0);pc(c[g>>2]|0,(c[h>>2]|0)+(c[(c[g>>2]|0)+288>>2]<<1)|0,(c[j>>2]|0)+(c[l>>2]<<1)|0,(c[k>>2]|0)-(c[(c[g>>2]|0)+284>>2]|0)|0)}else{df(c[h>>2]|0,(c[g>>2]|0)+168|0,c[(c[g>>2]|0)+284>>2]<<1|0)|0;df((c[h>>2]|0)+(c[(c[g>>2]|0)+288>>2]<<1)|0,(c[j>>2]|0)+(c[l>>2]<<1)|0,(c[k>>2]|0)-(c[(c[g>>2]|0)+284>>2]|0)<<1|0)|0}df((c[g>>2]|0)+168|0,(c[j>>2]|0)+((c[k>>2]|0)-(c[(c[g>>2]|0)+292>>2]|0)<<1)|0,c[(c[g>>2]|0)+292>>2]<<1|0)|0;i=f;return 0}function oc(a,d,e,f,g){a=a|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;h=i;i=i+32|0;j=h+8|0;k=h+16|0;l=h+20|0;m=h+24|0;n=h+4|0;o=h;p=h+12|0;c[j>>2]=a;c[k>>2]=d;c[l>>2]=e;c[m>>2]=f;c[n>>2]=g;c[o>>2]=0;while(1){if((c[o>>2]|0)>=(c[n>>2]|0))break;c[p>>2]=(c[c[j>>2]>>2]|0)+(b[(c[l>>2]|0)+(c[o>>2]<<1)>>1]<<8);c[(c[k>>2]|0)+(c[o>>2]<<2)>>2]=c[p>>2];c[p>>2]=c[p>>2]<<2;g=_(c[p>>2]>>16,b[c[m>>2]>>1]|0)|0;f=(c[(c[j>>2]|0)+4>>2]|0)+(g+((_(c[p>>2]&65535,b[c[m>>2]>>1]|0)|0)>>16))|0;c[c[j>>2]>>2]=f;f=_(c[p>>2]>>16,b[(c[m>>2]|0)+2>>1]|0)|0;g=f+((_(c[p>>2]&65535,b[(c[m>>2]|0)+2>>1]|0)|0)>>16)|0;c[(c[j>>2]|0)+4>>2]=g;c[o>>2]=(c[o>>2]|0)+1}i=h;return}function pc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;f=i;i=i+48|0;g=f;h=f+16|0;j=f+28|0;k=f+4|0;l=f+32|0;m=f+36|0;n=f+12|0;o=f+24|0;p=f+20|0;q=f+8|0;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[k>>2]=e;c[l>>2]=c[g>>2];g=(c[(c[l>>2]|0)+268>>2]|0)+(c[(c[l>>2]|0)+276>>2]|0)|0;c[q>>2]=ua()|0;e=i;i=i+((1*(g<<2)|0)+15&-16)|0;df(e|0,(c[l>>2]|0)+24|0,c[(c[l>>2]|0)+276>>2]<<2|0)|0;c[p>>2]=(c[(c[l>>2]|0)+296>>2]|0)+4;c[o>>2]=c[(c[l>>2]|0)+272>>2];while(1){if((c[k>>2]|0)<(c[(c[l>>2]|0)+268>>2]|0))r=c[k>>2]|0;else r=c[(c[l>>2]|0)+268>>2]|0;c[m>>2]=r;oc(c[l>>2]|0,e+(c[(c[l>>2]|0)+276>>2]<<2)|0,c[j>>2]|0,c[(c[l>>2]|0)+296>>2]|0,c[m>>2]|0);c[n>>2]=c[m>>2]<<16;c[h>>2]=Vd(c[h>>2]|0,e,c[p>>2]|0,c[(c[l>>2]|0)+276>>2]|0,c[(c[l>>2]|0)+280>>2]|0,c[n>>2]|0,c[o>>2]|0)|0;c[j>>2]=(c[j>>2]|0)+(c[m>>2]<<1);c[k>>2]=(c[k>>2]|0)-(c[m>>2]|0);if((c[k>>2]|0)<=1)break;df(e|0,e+(c[m>>2]<<2)|0,c[(c[l>>2]|0)+276>>2]<<2|0)|0}df((c[l>>2]|0)+24|0,e+(c[m>>2]<<2)|0,c[(c[l>>2]|0)+276>>2]<<2|0)|0;ka(c[q>>2]|0);i=f;return}function qc(a,d,e,f){a=a|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;g=i;i=i+48|0;h=g+28|0;j=g+16|0;k=g+4|0;l=g+8|0;m=g+32|0;n=g;o=g+12|0;p=g+24|0;q=g+20|0;c[h>>2]=a;c[j>>2]=d;c[k>>2]=e;c[l>>2]=f;c[m>>2]=c[h>>2];h=(c[(c[m>>2]|0)+268>>2]<<1)+8|0;c[q>>2]=ua()|0;f=i;i=i+((1*(h<<1)|0)+15&-16)|0;h=(c[m>>2]|0)+24|0;b[f>>1]=b[h>>1]|0;b[f+2>>1]=b[h+2>>1]|0;b[f+4>>1]=b[h+4>>1]|0;b[f+6>>1]=b[h+6>>1]|0;b[f+8>>1]=b[h+8>>1]|0;b[f+10>>1]=b[h+10>>1]|0;b[f+12>>1]=b[h+12>>1]|0;b[f+14>>1]=b[h+14>>1]|0;c[p>>2]=c[(c[m>>2]|0)+272>>2];while(1){if((c[l>>2]|0)<(c[(c[m>>2]|0)+268>>2]|0))r=c[l>>2]|0;else r=c[(c[m>>2]|0)+268>>2]|0;c[n>>2]=r;rc(c[m>>2]|0,f+16|0,c[k>>2]|0,c[n>>2]|0);c[o>>2]=c[n>>2]<<17;c[j>>2]=Wd(c[j>>2]|0,f,c[o>>2]|0,c[p>>2]|0)|0;c[k>>2]=(c[k>>2]|0)+(c[n>>2]<<1);c[l>>2]=(c[l>>2]|0)-(c[n>>2]|0);if((c[l>>2]|0)<=0)break;h=f+(c[n>>2]<<1<<1)|0;b[f>>1]=b[h>>1]|0;b[f+2>>1]=b[h+2>>1]|0;b[f+4>>1]=b[h+4>>1]|0;b[f+6>>1]=b[h+6>>1]|0;b[f+8>>1]=b[h+8>>1]|0;b[f+10>>1]=b[h+10>>1]|0;b[f+12>>1]=b[h+12>>1]|0;b[f+14>>1]=b[h+14>>1]|0}l=(c[m>>2]|0)+24|0;m=f+(c[n>>2]<<1<<1)|0;b[l>>1]=b[m>>1]|0;b[l+2>>1]=b[m+2>>1]|0;b[l+4>>1]=b[m+4>>1]|0;b[l+6>>1]=b[m+6>>1]|0;b[l+8>>1]=b[m+8>>1]|0;b[l+10>>1]=b[m+10>>1]|0;b[l+12>>1]=b[m+12>>1]|0;b[l+14>>1]=b[m+14>>1]|0;ka(c[q>>2]|0);i=g;return}function rc(a,d,e,f){a=a|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;g=i;i=i+48|0;h=g;j=g+16|0;k=g+28|0;l=g+4|0;m=g+32|0;n=g+36|0;o=g+12|0;p=g+24|0;q=g+20|0;r=g+8|0;c[h>>2]=a;c[j>>2]=d;c[k>>2]=e;c[l>>2]=f;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[l>>2]|0))break;c[n>>2]=b[(c[k>>2]|0)+(c[m>>2]<<1)>>1]<<10;c[q>>2]=(c[n>>2]|0)-(c[c[h>>2]>>2]|0);f=_(c[q>>2]>>16,b[1516]|0)|0;c[r>>2]=f+((_(c[q>>2]&65535,b[1516]|0)|0)>>16);c[o>>2]=(c[c[h>>2]>>2]|0)+(c[r>>2]|0);c[c[h>>2]>>2]=(c[n>>2]|0)+(c[r>>2]|0);c[q>>2]=(c[o>>2]|0)-(c[(c[h>>2]|0)+4>>2]|0);f=_(c[q>>2]>>16,b[1517]|0)|0;c[r>>2]=f+((_(c[q>>2]&65535,b[1517]|0)|0)>>16);c[p>>2]=(c[(c[h>>2]|0)+4>>2]|0)+(c[r>>2]|0);c[(c[h>>2]|0)+4>>2]=(c[o>>2]|0)+(c[r>>2]|0);c[q>>2]=(c[p>>2]|0)-(c[(c[h>>2]|0)+8>>2]|0);f=_(c[q>>2]>>16,b[1518]|0)|0;c[r>>2]=(c[q>>2]|0)+(f+((_(c[q>>2]&65535,b[1518]|0)|0)>>16));c[o>>2]=(c[(c[h>>2]|0)+8>>2]|0)+(c[r>>2]|0);c[(c[h>>2]|0)+8>>2]=(c[p>>2]|0)+(c[r>>2]|0);if(((c[o>>2]>>9)+1>>1|0)<=32767)if(((c[o>>2]>>9)+1>>1|0)<-32768)s=-32768;else s=(c[o>>2]>>9)+1>>1;else s=32767;b[(c[j>>2]|0)+(c[m>>2]<<1<<1)>>1]=s;c[q>>2]=(c[n>>2]|0)-(c[(c[h>>2]|0)+12>>2]|0);f=_(c[q>>2]>>16,b[1520]|0)|0;c[r>>2]=f+((_(c[q>>2]&65535,b[1520]|0)|0)>>16);c[o>>2]=(c[(c[h>>2]|0)+12>>2]|0)+(c[r>>2]|0);c[(c[h>>2]|0)+12>>2]=(c[n>>2]|0)+(c[r>>2]|0);c[q>>2]=(c[o>>2]|0)-(c[(c[h>>2]|0)+16>>2]|0);f=_(c[q>>2]>>16,b[1521]|0)|0;c[r>>2]=f+((_(c[q>>2]&65535,b[1521]|0)|0)>>16);c[p>>2]=(c[(c[h>>2]|0)+16>>2]|0)+(c[r>>2]|0);c[(c[h>>2]|0)+16>>2]=(c[o>>2]|0)+(c[r>>2]|0);c[q>>2]=(c[p>>2]|0)-(c[(c[h>>2]|0)+20>>2]|0);f=_(c[q>>2]>>16,b[1522]|0)|0;c[r>>2]=(c[q>>2]|0)+(f+((_(c[q>>2]&65535,b[1522]|0)|0)>>16));c[o>>2]=(c[(c[h>>2]|0)+20>>2]|0)+(c[r>>2]|0);c[(c[h>>2]|0)+20>>2]=(c[p>>2]|0)+(c[r>>2]|0);if(((c[o>>2]>>9)+1>>1|0)<=32767)if(((c[o>>2]>>9)+1>>1|0)<-32768)t=-32768;else t=(c[o>>2]>>9)+1>>1;else t=32767;b[(c[j>>2]|0)+((c[m>>2]<<1)+1<<1)>>1]=t;c[m>>2]=(c[m>>2]|0)+1}i=g;return}function sc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0;f=i;i=i+32|0;g=f+16|0;h=f+12|0;j=f+8|0;k=f+4|0;l=f;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[k>>2]=e;c[l>>2]=c[g>>2];rc(c[l>>2]|0,c[h>>2]|0,c[j>>2]|0,c[k>>2]|0);i=f;return}function tc(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e+4|0;k=e;c[f>>2]=a;c[g>>2]=d;c[j>>2]=1;while(1){if((c[j>>2]|0)>=(c[g>>2]|0))break;c[h>>2]=b[(c[f>>2]|0)+(c[j>>2]<<1)>>1];c[k>>2]=(c[j>>2]|0)-1;while(1){if((c[k>>2]|0)<0)break;if((c[h>>2]|0)>=(b[(c[f>>2]|0)+(c[k>>2]<<1)>>1]|0))break;b[(c[f>>2]|0)+((c[k>>2]|0)+1<<1)>>1]=b[(c[f>>2]|0)+(c[k>>2]<<1)>>1]|0;c[k>>2]=(c[k>>2]|0)+-1}b[(c[f>>2]|0)+((c[k>>2]|0)+1<<1)>>1]=c[h>>2];c[j>>2]=(c[j>>2]|0)+1}i=e;return}function uc(a,d,e,f){a=a|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;g=i;i=i+32|0;h=g+4|0;j=g+16|0;k=g+8|0;l=g+20|0;m=g+28|0;n=g;o=g+12|0;p=g+24|0;c[h>>2]=a;c[j>>2]=d;c[k>>2]=e;c[l>>2]=f;c[p>>2]=0;c[n>>2]=0;c[l>>2]=(c[l>>2]|0)+-1;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[l>>2]|0))break;c[p>>2]=(c[p>>2]|0)+(_(b[(c[k>>2]|0)+(c[m>>2]<<1)>>1]|0,b[(c[k>>2]|0)+(c[m>>2]<<1)>>1]|0)|0);c[p>>2]=(c[p>>2]|0)+(_(b[(c[k>>2]|0)+((c[m>>2]|0)+1<<1)>>1]|0,b[(c[k>>2]|0)+((c[m>>2]|0)+1<<1)>>1]|0)|0);if((c[p>>2]|0)<0){q=4;break}c[m>>2]=(c[m>>2]|0)+2}if((q|0)==4){c[p>>2]=(c[p>>2]|0)>>>2;c[n>>2]=2}while(1){r=c[m>>2]|0;if((c[m>>2]|0)>=(c[l>>2]|0))break;c[o>>2]=_(b[(c[k>>2]|0)+(r<<1)>>1]|0,b[(c[k>>2]|0)+(c[m>>2]<<1)>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(_(b[(c[k>>2]|0)+((c[m>>2]|0)+1<<1)>>1]|0,b[(c[k>>2]|0)+((c[m>>2]|0)+1<<1)>>1]|0)|0);c[p>>2]=(c[p>>2]|0)+((c[o>>2]|0)>>>(c[n>>2]|0));if((c[p>>2]|0)<0){c[p>>2]=(c[p>>2]|0)>>>2;c[n>>2]=(c[n>>2]|0)+2}c[m>>2]=(c[m>>2]|0)+2}if((r|0)==(c[l>>2]|0)){c[o>>2]=_(b[(c[k>>2]|0)+(c[m>>2]<<1)>>1]|0,b[(c[k>>2]|0)+(c[m>>2]<<1)>>1]|0)|0;c[p>>2]=(c[p>>2]|0)+(c[o>>2]>>c[n>>2])}if(!(c[p>>2]&-1073741824)){s=c[n>>2]|0;t=c[j>>2]|0;c[t>>2]=s;u=c[p>>2]|0;v=c[h>>2]|0;c[v>>2]=u;i=g;return}c[p>>2]=(c[p>>2]|0)>>>2;c[n>>2]=(c[n>>2]|0)+2;s=c[n>>2]|0;t=c[j>>2]|0;c[t>>2]=s;u=c[p>>2]|0;v=c[h>>2]|0;c[v>>2]=u;i=g;return}function vc(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;i=i+48|0;f=e+40|0;g=e+36|0;h=e+32|0;j=e+8|0;k=e+4|0;l=e;c[f>>2]=a;c[g>>2]=d;c[h>>2]=jb(c[f>>2]|0,368,8)|0;c[j+8>>2]=(c[h>>2]|0)/5|0;c[j+12+8>>2]=(c[h>>2]|0)-((c[j+8>>2]|0)*5|0);c[h>>2]=0;while(1){if((c[h>>2]|0)>=2)break;d=jb(c[f>>2]|0,472,8)|0;c[j+((c[h>>2]|0)*12|0)>>2]=d;d=jb(c[f>>2]|0,488,8)|0;c[j+((c[h>>2]|0)*12|0)+4>>2]=d;c[h>>2]=(c[h>>2]|0)+1}c[h>>2]=0;while(1){if((c[h>>2]|0)>=2)break;f=j+((c[h>>2]|0)*12|0)|0;c[f>>2]=(c[f>>2]|0)+((c[j+((c[h>>2]|0)*12|0)+8>>2]|0)*3|0);c[k>>2]=b[336+(c[j+((c[h>>2]|0)*12|0)>>2]<<1)>>1];c[l>>2]=(((b[336+((c[j+((c[h>>2]|0)*12|0)>>2]|0)+1<<1)>>1]|0)-(c[k>>2]|0)>>16)*6554|0)+(((b[336+((c[j+((c[h>>2]|0)*12|0)>>2]|0)+1<<1)>>1]|0)-(c[k>>2]|0)&65535)*6554>>16);f=(c[k>>2]|0)+(_((c[l>>2]&65535)<<16>>16,((c[j+((c[h>>2]|0)*12|0)+4>>2]<<1)+1&65535)<<16>>16)|0)|0;c[(c[g>>2]|0)+(c[h>>2]<<2)>>2]=f;c[h>>2]=(c[h>>2]|0)+1}h=c[g>>2]|0;c[h>>2]=(c[h>>2]|0)-(c[(c[g>>2]|0)+4>>2]|0);i=e;return}function wc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;b=jb(c[e>>2]|0,400,8)|0;c[c[f>>2]>>2]=b;i=d;return}function xc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0.0,B=0,C=0,D=0.0,E=0.0;f=i;i=i+80|0;h=f+60|0;j=f+44|0;k=f+24|0;l=f+28|0;m=f+12|0;n=f+40|0;o=f+48|0;p=f+56|0;q=f+64|0;r=f+8|0;s=f+4|0;t=f+32|0;u=f;v=f+16|0;w=f+36|0;x=f+20|0;y=f+52|0;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;if(!((((c[k>>2]|0)<1|(c[j>>2]|0)<1)^1)&(c[h>>2]|0)!=0&(c[l>>2]|0)!=0)){i=f;return}c[n>>2]=0;while(1){if((c[n>>2]|0)>=(_(c[j>>2]|0,c[k>>2]|0)|0))break;if(2.0<+g[(c[h>>2]|0)+(c[n>>2]<<2)>>2])z=2.0;else z=+g[(c[h>>2]|0)+(c[n>>2]<<2)>>2];if(!(-2.0>z))if(2.0<+g[(c[h>>2]|0)+(c[n>>2]<<2)>>2])A=2.0;else A=+g[(c[h>>2]|0)+(c[n>>2]<<2)>>2];else A=-2.0;g[(c[h>>2]|0)+(c[n>>2]<<2)>>2]=A;c[n>>2]=(c[n>>2]|0)+1}c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[k>>2]|0))break;c[o>>2]=(c[h>>2]|0)+(c[m>>2]<<2);g[p>>2]=+g[(c[l>>2]|0)+(c[m>>2]<<2)>>2];c[n>>2]=0;while(1){if((c[n>>2]|0)>=(c[j>>2]|0))break;e=_(c[n>>2]|0,c[k>>2]|0)|0;if(+g[(c[o>>2]|0)+(e<<2)>>2]*+g[p>>2]>=0.0)break;e=_(c[n>>2]|0,c[k>>2]|0)|0;d=_(c[n>>2]|0,c[k>>2]|0)|0;b=_(c[n>>2]|0,c[k>>2]|0)|0;a=_(c[n>>2]|0,c[k>>2]|0)|0;g[(c[o>>2]|0)+(a<<2)>>2]=+g[(c[o>>2]|0)+(e<<2)>>2]+ +g[p>>2]*+g[(c[o>>2]|0)+(d<<2)>>2]*+g[(c[o>>2]|0)+(b<<2)>>2];c[n>>2]=(c[n>>2]|0)+1}c[r>>2]=0;g[q>>2]=+g[c[o>>2]>>2];do{c[v>>2]=0;c[n>>2]=c[r>>2];while(1){if((c[n>>2]|0)>=(c[j>>2]|0))break;b=_(c[n>>2]|0,c[k>>2]|0)|0;if(+g[(c[o>>2]|0)+(b<<2)>>2]>1.0)break;b=_(c[n>>2]|0,c[k>>2]|0)|0;if(+g[(c[o>>2]|0)+(b<<2)>>2]<-1.0)break;c[n>>2]=(c[n>>2]|0)+1}if((c[n>>2]|0)==(c[j>>2]|0)){B=23;break}c[w>>2]=c[n>>2];b=c[n>>2]|0;c[t>>2]=b;c[s>>2]=b;b=_(c[n>>2]|0,c[k>>2]|0)|0;g[u>>2]=+N(+(+g[(c[o>>2]|0)+(b<<2)>>2]));while(1){if((c[s>>2]|0)<=0)break;b=_(c[n>>2]|0,c[k>>2]|0)|0;d=_((c[s>>2]|0)-1|0,c[k>>2]|0)|0;if(!(+g[(c[o>>2]|0)+(b<<2)>>2]*+g[(c[o>>2]|0)+(d<<2)>>2]>=0.0))break;c[s>>2]=(c[s>>2]|0)+-1}while(1){if((c[t>>2]|0)>=(c[j>>2]|0))break;d=_(c[n>>2]|0,c[k>>2]|0)|0;b=_(c[t>>2]|0,c[k>>2]|0)|0;if(!(+g[(c[o>>2]|0)+(d<<2)>>2]*+g[(c[o>>2]|0)+(b<<2)>>2]>=0.0))break;b=_(c[t>>2]|0,c[k>>2]|0)|0;A=+N(+(+g[(c[o>>2]|0)+(b<<2)>>2]));if(A>+g[u>>2]){b=_(c[t>>2]|0,c[k>>2]|0)|0;g[u>>2]=+N(+(+g[(c[o>>2]|0)+(b<<2)>>2]));c[w>>2]=c[t>>2]}c[t>>2]=(c[t>>2]|0)+1}if(!(c[s>>2]|0)){b=_(c[n>>2]|0,c[k>>2]|0)|0;C=+g[(c[o>>2]|0)+(b<<2)>>2]*+g[c[o>>2]>>2]>=0.0}else C=0;c[v>>2]=C&1;g[p>>2]=(+g[u>>2]-1.0)/(+g[u>>2]*+g[u>>2]);b=_(c[n>>2]|0,c[k>>2]|0)|0;if(+g[(c[o>>2]|0)+(b<<2)>>2]>0.0)g[p>>2]=-+g[p>>2];c[n>>2]=c[s>>2];while(1){if((c[n>>2]|0)>=(c[t>>2]|0))break;b=_(c[n>>2]|0,c[k>>2]|0)|0;d=_(c[n>>2]|0,c[k>>2]|0)|0;e=_(c[n>>2]|0,c[k>>2]|0)|0;a=_(c[n>>2]|0,c[k>>2]|0)|0;g[(c[o>>2]|0)+(a<<2)>>2]=+g[(c[o>>2]|0)+(b<<2)>>2]+ +g[p>>2]*+g[(c[o>>2]|0)+(d<<2)>>2]*+g[(c[o>>2]|0)+(e<<2)>>2];c[n>>2]=(c[n>>2]|0)+1}a:do if((c[v>>2]|0)!=0&(c[w>>2]|0)>=2){g[y>>2]=+g[q>>2]-+g[c[o>>2]>>2];g[x>>2]=+g[y>>2]/+(c[w>>2]|0);c[n>>2]=c[r>>2];while(1){if((c[n>>2]|0)>=(c[w>>2]|0))break a;g[y>>2]=+g[y>>2]-+g[x>>2];e=_(c[n>>2]|0,c[k>>2]|0)|0;d=(c[o>>2]|0)+(e<<2)|0;g[d>>2]=+g[d>>2]+ +g[y>>2];d=_(c[n>>2]|0,c[k>>2]|0)|0;if(1.0<+g[(c[o>>2]|0)+(d<<2)>>2])D=1.0;else{d=_(c[n>>2]|0,c[k>>2]|0)|0;D=+g[(c[o>>2]|0)+(d<<2)>>2]}if(!(-1.0>D)){d=_(c[n>>2]|0,c[k>>2]|0)|0;if(1.0<+g[(c[o>>2]|0)+(d<<2)>>2])E=1.0;else{d=_(c[n>>2]|0,c[k>>2]|0)|0;E=+g[(c[o>>2]|0)+(d<<2)>>2]}}else E=-1.0;d=_(c[n>>2]|0,c[k>>2]|0)|0;g[(c[o>>2]|0)+(d<<2)>>2]=E;c[n>>2]=(c[n>>2]|0)+1}}while(0);c[r>>2]=c[t>>2]}while((c[r>>2]|0)!=(c[j>>2]|0));if((B|0)==23){B=0;g[p>>2]=0.0}g[(c[l>>2]|0)+(c[m>>2]<<2)>>2]=+g[p>>2];c[m>>2]=(c[m>>2]|0)+1}i=f;return}function yc(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0;e=i;i=i+16|0;f=e+8|0;g=e+4|0;h=e;c[f>>2]=a;c[g>>2]=b;b=d[c[f>>2]>>0]|0;if((d[c[f>>2]>>0]|0)&128){c[h>>2]=b>>3&3;c[h>>2]=(c[g>>2]<<c[h>>2]|0)/400|0;j=c[h>>2]|0;i=e;return j|0}a=d[c[f>>2]>>0]|0;if((b&96|0)==96){b=c[g>>2]|0;c[h>>2]=(a&8|0)!=0?(b|0)/50|0:(b|0)/100|0;j=c[h>>2]|0;i=e;return j|0}c[h>>2]=a>>3&3;a=c[g>>2]|0;if((c[h>>2]|0)==3){c[h>>2]=(a*60|0)/1e3|0;j=c[h>>2]|0;i=e;return j|0}else{c[h>>2]=(a<<c[h>>2]|0)/100|0;j=c[h>>2]|0;i=e;return j|0}return 0}function zc(e,f,g,h,j,k,l,m){e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0;n=i;i=i+80|0;o=n+36|0;p=n+24|0;q=n+44|0;r=n+60|0;s=n+12|0;t=n+16|0;u=n+48|0;v=n+56|0;w=n+64|0;x=n+68|0;y=n+72|0;z=n+8|0;A=n;B=n+76|0;C=n+77|0;D=n+20|0;E=n+52|0;F=n+28|0;G=n+32|0;H=n+40|0;I=n+4|0;c[p>>2]=e;c[q>>2]=f;c[r>>2]=g;c[s>>2]=h;c[t>>2]=j;c[u>>2]=k;c[v>>2]=l;c[w>>2]=m;c[F>>2]=0;c[G>>2]=c[p>>2];if(!(c[u>>2]|0)){c[o>>2]=-1;J=c[o>>2]|0;i=n;return J|0}c[D>>2]=yc(c[p>>2]|0,48e3)|0;c[A>>2]=0;m=c[p>>2]|0;c[p>>2]=m+1;a[C>>0]=a[m>>0]|0;c[q>>2]=(c[q>>2]|0)+-1;c[E>>2]=c[q>>2];m=d[C>>0]&3;a:do if(!m)c[z>>2]=1;else if((m|0)==1){c[z>>2]=2;c[A>>2]=1;if(!(c[r>>2]|0)){if(!(c[q>>2]&1)){c[E>>2]=(c[q>>2]|0)/2|0;b[c[u>>2]>>1]=c[E>>2];break}c[o>>2]=-4;J=c[o>>2]|0;i=n;return J|0}}else if((m|0)==2){c[z>>2]=2;c[y>>2]=Xd(c[p>>2]|0,c[q>>2]|0,c[u>>2]|0)|0;c[q>>2]=(c[q>>2]|0)-(c[y>>2]|0);if((b[c[u>>2]>>1]|0)>=0?(b[c[u>>2]>>1]|0)<=(c[q>>2]|0):0){c[p>>2]=(c[p>>2]|0)+(c[y>>2]|0);c[E>>2]=(c[q>>2]|0)-(b[c[u>>2]>>1]|0);break}c[o>>2]=-4;J=c[o>>2]|0;i=n;return J|0}else{if((c[q>>2]|0)<1){c[o>>2]=-4;J=c[o>>2]|0;i=n;return J|0}l=c[p>>2]|0;c[p>>2]=l+1;a[B>>0]=a[l>>0]|0;c[z>>2]=d[B>>0]&63;if((c[z>>2]|0)>0?(_(c[D>>2]|0,c[z>>2]|0)|0)<=5760:0){c[q>>2]=(c[q>>2]|0)+-1;b:do if(d[B>>0]&64){while(1){if((c[q>>2]|0)<=0)break;l=c[p>>2]|0;c[p>>2]=l+1;c[H>>2]=d[l>>0];c[q>>2]=(c[q>>2]|0)+-1;c[I>>2]=(c[H>>2]|0)==255?254:c[H>>2]|0;c[q>>2]=(c[q>>2]|0)-(c[I>>2]|0);c[F>>2]=(c[F>>2]|0)+(c[I>>2]|0);if((c[H>>2]|0)!=255)break b}c[o>>2]=-4;J=c[o>>2]|0;i=n;return J|0}while(0);if((c[q>>2]|0)<0){c[o>>2]=-4;J=c[o>>2]|0;i=n;return J|0}c[A>>2]=((d[B>>0]&128|0)!=0^1)&1;if(c[A>>2]|0){if(c[r>>2]|0)break;c[E>>2]=(c[q>>2]|0)/(c[z>>2]|0)|0;l=_(c[E>>2]|0,c[z>>2]|0)|0;if((l|0)!=(c[q>>2]|0)){c[o>>2]=-4;J=c[o>>2]|0;i=n;return J|0}c[x>>2]=0;while(1){if((c[x>>2]|0)>=((c[z>>2]|0)-1|0))break a;b[(c[u>>2]|0)+(c[x>>2]<<1)>>1]=c[E>>2];c[x>>2]=(c[x>>2]|0)+1}}c[E>>2]=c[q>>2];c[x>>2]=0;while(1){if((c[x>>2]|0)>=((c[z>>2]|0)-1|0))break;c[y>>2]=Xd(c[p>>2]|0,c[q>>2]|0,(c[u>>2]|0)+(c[x>>2]<<1)|0)|0;c[q>>2]=(c[q>>2]|0)-(c[y>>2]|0);if((b[(c[u>>2]|0)+(c[x>>2]<<1)>>1]|0)<0){K=29;break}if((b[(c[u>>2]|0)+(c[x>>2]<<1)>>1]|0)>(c[q>>2]|0)){K=29;break}c[p>>2]=(c[p>>2]|0)+(c[y>>2]|0);c[E>>2]=(c[E>>2]|0)-((c[y>>2]|0)+(b[(c[u>>2]|0)+(c[x>>2]<<1)>>1]|0));c[x>>2]=(c[x>>2]|0)+1}if((K|0)==29){c[o>>2]=-4;J=c[o>>2]|0;i=n;return J|0}if((c[E>>2]|0)>=0)break;c[o>>2]=-4;J=c[o>>2]|0;i=n;return J|0}c[o>>2]=-4;J=c[o>>2]|0;i=n;return J|0}while(0);c:do if(c[r>>2]|0){c[y>>2]=Xd(c[p>>2]|0,c[q>>2]|0,(c[u>>2]|0)+(c[z>>2]<<1)+-2|0)|0;c[q>>2]=(c[q>>2]|0)-(c[y>>2]|0);if((b[(c[u>>2]|0)+((c[z>>2]|0)-1<<1)>>1]|0)>=0?(b[(c[u>>2]|0)+((c[z>>2]|0)-1<<1)>>1]|0)<=(c[q>>2]|0):0){c[p>>2]=(c[p>>2]|0)+(c[y>>2]|0);if(!(c[A>>2]|0)){if(((c[y>>2]|0)+(b[(c[u>>2]|0)+((c[z>>2]|0)-1<<1)>>1]|0)|0)<=(c[E>>2]|0))break;c[o>>2]=-4;J=c[o>>2]|0;i=n;return J|0}K=_(b[(c[u>>2]|0)+((c[z>>2]|0)-1<<1)>>1]|0,c[z>>2]|0)|0;if((K|0)>(c[q>>2]|0)){c[o>>2]=-4;J=c[o>>2]|0;i=n;return J|0}c[x>>2]=0;while(1){if((c[x>>2]|0)>=((c[z>>2]|0)-1|0))break c;b[(c[u>>2]|0)+(c[x>>2]<<1)>>1]=b[(c[u>>2]|0)+((c[z>>2]|0)-1<<1)>>1]|0;c[x>>2]=(c[x>>2]|0)+1}}c[o>>2]=-4;J=c[o>>2]|0;i=n;return J|0}else{if((c[E>>2]|0)<=1275){b[(c[u>>2]|0)+((c[z>>2]|0)-1<<1)>>1]=c[E>>2];break}c[o>>2]=-4;J=c[o>>2]|0;i=n;return J|0}while(0);if(c[v>>2]|0)c[c[v>>2]>>2]=(c[p>>2]|0)-(c[G>>2]|0);c[x>>2]=0;while(1){if((c[x>>2]|0)>=(c[z>>2]|0))break;if(c[t>>2]|0)c[(c[t>>2]|0)+(c[x>>2]<<2)>>2]=c[p>>2];c[p>>2]=(c[p>>2]|0)+(b[(c[u>>2]|0)+(c[x>>2]<<1)>>1]|0);c[x>>2]=(c[x>>2]|0)+1}if(c[w>>2]|0)c[c[w>>2]>>2]=(c[F>>2]|0)+((c[p>>2]|0)-(c[G>>2]|0));if(c[s>>2]|0)a[c[s>>2]>>0]=a[C>>0]|0;c[o>>2]=c[z>>2];J=c[o>>2]|0;i=n;return J|0}function Ac(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0;b=i;i=i+32|0;d=b+16|0;e=b+12|0;f=b+8|0;g=b+4|0;h=b;c[e>>2]=a;if((c[e>>2]|0)<1|(c[e>>2]|0)>2){c[d>>2]=0;j=c[d>>2]|0;i=b;return j|0}c[h>>2]=Ub(f)|0;if(c[h>>2]|0){c[d>>2]=0;j=c[d>>2]|0;i=b;return j|0}else{c[f>>2]=Yd(c[f>>2]|0)|0;c[g>>2]=Za(c[e>>2]|0)|0;e=Yd(84)|0;c[d>>2]=e+(c[f>>2]|0)+(c[g>>2]|0);j=c[d>>2]|0;i=b;return j|0}return 0}function Bc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;e=i;i=i+48|0;f=e;g=e+24|0;h=e+20|0;j=e+8|0;k=e+16|0;l=e+4|0;m=e+12|0;n=e+28|0;o=e+32|0;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;if(!((c[j>>2]|0)!=48e3&(c[j>>2]|0)!=24e3&(c[j>>2]|0)!=16e3&(c[j>>2]|0)!=12e3&(c[j>>2]|0)!=8e3)?!((c[k>>2]|0)!=1&(c[k>>2]|0)!=2):0){d=c[h>>2]|0;bf(d|0,0,Ac(c[k>>2]|0)|0)|0;c[n>>2]=Ub(o)|0;if(c[n>>2]|0){c[g>>2]=-3;p=c[g>>2]|0;i=e;return p|0}c[o>>2]=Yd(c[o>>2]|0)|0;d=Yd(84)|0;c[(c[h>>2]|0)+4>>2]=d;c[c[h>>2]>>2]=(c[(c[h>>2]|0)+4>>2]|0)+(c[o>>2]|0);c[l>>2]=(c[h>>2]|0)+(c[(c[h>>2]|0)+4>>2]|0);c[m>>2]=(c[h>>2]|0)+(c[c[h>>2]>>2]|0);o=c[k>>2]|0;c[(c[h>>2]|0)+8>>2]=o;c[(c[h>>2]|0)+44>>2]=o;c[(c[h>>2]|0)+12>>2]=c[j>>2];c[(c[h>>2]|0)+16+8>>2]=c[(c[h>>2]|0)+12>>2];c[(c[h>>2]|0)+16>>2]=c[(c[h>>2]|0)+8>>2];c[n>>2]=Vb(c[l>>2]|0)|0;if(c[n>>2]|0){c[g>>2]=-3;p=c[g>>2]|0;i=e;return p|0}c[n>>2]=_a(c[m>>2]|0,c[j>>2]|0,c[k>>2]|0)|0;if(c[n>>2]|0){c[g>>2]=-3;p=c[g>>2]|0;i=e;return p|0}else{n=c[m>>2]|0;c[f>>2]=0;ab(n,10016,f)|0;c[(c[h>>2]|0)+56>>2]=0;c[(c[h>>2]|0)+60>>2]=(c[j>>2]|0)/400|0;c[g>>2]=0;p=c[g>>2]|0;i=e;return p|0}}c[g>>2]=-1;p=c[g>>2]|0;i=e;return p|0}function Cc(a,d,e,f,h,j,k,l,m){a=a|0;d=d|0;e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0;n=i;i=i+208|0;o=n+44|0;p=n+4|0;q=n;r=n+76|0;s=n+36|0;t=n+16|0;u=n+20|0;v=n+24|0;w=n+64|0;x=n+72|0;y=n+80|0;z=n+84|0;A=n+88|0;B=n+48|0;C=n+192|0;D=n+8|0;E=n+56|0;F=n+28|0;G=n+60|0;H=n+96|0;I=n+32|0;J=n+68|0;K=n+40|0;L=n+12|0;M=n+52|0;c[p>>2]=a;c[q>>2]=d;c[r>>2]=e;c[s>>2]=f;c[t>>2]=h;c[u>>2]=j;c[v>>2]=k;c[w>>2]=l;c[x>>2]=m;if((c[u>>2]|0)<0|(c[u>>2]|0)>1){c[o>>2]=-1;N=c[o>>2]|0;i=n;return N|0}if((c[u>>2]|0)!=0|(c[r>>2]|0)==0|(c[q>>2]|0)==0?((c[t>>2]|0)%((c[(c[p>>2]|0)+12>>2]|0)/400|0|0)|0|0)!=0:0){c[o>>2]=-1;N=c[o>>2]|0;i=n;return N|0}if((c[r>>2]|0)==0|(c[q>>2]|0)==0){c[I>>2]=0;while(1){m=(c[s>>2]|0)+((_(c[I>>2]|0,c[(c[p>>2]|0)+8>>2]|0)|0)<<2)|0;c[J>>2]=Zd(c[p>>2]|0,0,0,m,(c[t>>2]|0)-(c[I>>2]|0)|0,0)|0;O=c[J>>2]|0;if((c[J>>2]|0)<0){P=9;break}c[I>>2]=(c[I>>2]|0)+O;if((c[I>>2]|0)>=(c[t>>2]|0)){P=11;break}}if((P|0)==9){c[o>>2]=O;N=c[o>>2]|0;i=n;return N|0}else if((P|0)==11){_d()|0;c[(c[p>>2]|0)+68>>2]=c[I>>2];c[o>>2]=c[I>>2];N=c[o>>2]|0;i=n;return N|0}}if((c[r>>2]|0)<0){c[o>>2]=-1;N=c[o>>2]|0;i=n;return N|0}c[F>>2]=$d(c[q>>2]|0)|0;c[E>>2]=Dc(c[q>>2]|0)|0;c[D>>2]=yc(c[q>>2]|0,c[(c[p>>2]|0)+12>>2]|0)|0;c[G>>2]=Ec(c[q>>2]|0)|0;c[A>>2]=zc(c[q>>2]|0,c[r>>2]|0,c[v>>2]|0,C,0,H,B,c[w>>2]|0)|0;if((c[A>>2]|0)<0){c[o>>2]=c[A>>2];N=c[o>>2]|0;i=n;return N|0}c[q>>2]=(c[q>>2]|0)+(c[B>>2]|0);if(c[u>>2]|0){if(!((c[F>>2]|0)==1002?1:(c[t>>2]|0)<(c[D>>2]|0))?(c[(c[p>>2]|0)+52>>2]|0)!=1002:0){c[K>>2]=c[(c[p>>2]|0)+68>>2];if(((c[t>>2]|0)-(c[D>>2]|0)|0)!=0?(c[L>>2]=Cc(c[p>>2]|0,0,0,c[s>>2]|0,(c[t>>2]|0)-(c[D>>2]|0)|0,0,0,0,c[x>>2]|0)|0,(c[L>>2]|0)<0):0){c[(c[p>>2]|0)+68>>2]=c[K>>2];c[o>>2]=c[L>>2];N=c[o>>2]|0;i=n;return N|0}c[(c[p>>2]|0)+52>>2]=c[F>>2];c[(c[p>>2]|0)+48>>2]=c[E>>2];c[(c[p>>2]|0)+60>>2]=c[D>>2];c[(c[p>>2]|0)+44>>2]=c[G>>2];K=(c[s>>2]|0)+((_(c[(c[p>>2]|0)+8>>2]|0,(c[t>>2]|0)-(c[D>>2]|0)|0)|0)<<2)|0;c[L>>2]=Zd(c[p>>2]|0,c[q>>2]|0,b[H>>1]|0,K,c[D>>2]|0,1)|0;if((c[L>>2]|0)<0){c[o>>2]=c[L>>2];N=c[o>>2]|0;i=n;return N|0}else{_d()|0;c[(c[p>>2]|0)+68>>2]=c[t>>2];c[o>>2]=c[t>>2];N=c[o>>2]|0;i=n;return N|0}}c[o>>2]=Cc(c[p>>2]|0,0,0,c[s>>2]|0,c[t>>2]|0,0,0,0,c[x>>2]|0)|0;N=c[o>>2]|0;i=n;return N|0}L=_(c[A>>2]|0,c[D>>2]|0)|0;if((L|0)>(c[t>>2]|0)){c[o>>2]=-2;N=c[o>>2]|0;i=n;return N|0}c[(c[p>>2]|0)+52>>2]=c[F>>2];c[(c[p>>2]|0)+48>>2]=c[E>>2];c[(c[p>>2]|0)+60>>2]=c[D>>2];c[(c[p>>2]|0)+44>>2]=c[G>>2];c[z>>2]=0;c[y>>2]=0;while(1){if((c[y>>2]|0)>=(c[A>>2]|0))break;G=(c[s>>2]|0)+((_(c[z>>2]|0,c[(c[p>>2]|0)+8>>2]|0)|0)<<2)|0;c[M>>2]=Zd(c[p>>2]|0,c[q>>2]|0,b[H+(c[y>>2]<<1)>>1]|0,G,(c[t>>2]|0)-(c[z>>2]|0)|0,0)|0;if((c[M>>2]|0)<0){P=31;break}c[q>>2]=(c[q>>2]|0)+(b[H+(c[y>>2]<<1)>>1]|0);c[z>>2]=(c[z>>2]|0)+(c[M>>2]|0);c[y>>2]=(c[y>>2]|0)+1}if((P|0)==31){c[o>>2]=c[M>>2];N=c[o>>2]|0;i=n;return N|0}c[(c[p>>2]|0)+68>>2]=c[z>>2];_d()|0;if(c[x>>2]|0)xc(c[s>>2]|0,c[z>>2]|0,c[(c[p>>2]|0)+8>>2]|0,(c[p>>2]|0)+72|0);else{g[(c[p>>2]|0)+72+4>>2]=0.0;g[(c[p>>2]|0)+72>>2]=0.0}c[o>>2]=c[z>>2];N=c[o>>2]|0;i=n;return N|0}function Dc(a){a=a|0;var b=0,e=0,f=0,g=0,h=0;b=i;i=i+16|0;e=b+4|0;f=b;c[e>>2]=a;a=d[c[e>>2]>>0]|0;if((d[c[e>>2]>>0]|0)&128){g=1102+(a>>5&3)|0;c[f>>2]=g;c[f>>2]=(c[f>>2]|0)==1102?1101:g;h=c[f>>2]|0;i=b;return h|0}g=d[c[e>>2]>>0]|0;if((a&96|0)==96){c[f>>2]=(g&16|0)!=0?1105:1104;h=c[f>>2]|0;i=b;return h|0}else{c[f>>2]=1101+(g>>5&3);h=c[f>>2]|0;i=b;return h|0}return 0}function Ec(a){a=a|0;var b=0,e=0;b=i;i=i+16|0;e=b;c[e>>2]=a;i=b;return (((d[c[e>>2]>>0]|0)&4|0)!=0?2:1)|0}function Fc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;e=i;i=i+80|0;f=e+8|0;g=e;h=e+12|0;j=e+16|0;k=e+20|0;l=e+44|0;m=e+24|0;n=e+40|0;o=e+48|0;p=e+52|0;q=e+56|0;r=e+60|0;s=e+64|0;t=e+68|0;u=e+72|0;v=e+76|0;c[j>>2]=a;c[k>>2]=b;c[l>>2]=0;c[n>>2]=(c[j>>2]|0)+(c[(c[j>>2]|0)+4>>2]|0);c[o>>2]=(c[j>>2]|0)+(c[c[j>>2]>>2]|0);c[m>>2]=d;a:do switch(c[k>>2]|0){case 4029:{d=(c[m>>2]|0)+(4-1)&~(4-1);b=c[d>>2]|0;c[m>>2]=d+4;c[r>>2]=b;if(c[r>>2]|0){c[c[r>>2]>>2]=c[(c[j>>2]|0)+12>>2];w=20}else w=21;break}case 4033:{b=(c[m>>2]|0)+(4-1)&~(4-1);d=c[b>>2]|0;c[m>>2]=b+4;c[s>>2]=d;if(c[s>>2]|0)if((c[(c[j>>2]|0)+56>>2]|0)==1002){d=c[o>>2]|0;c[f>>2]=(c[s>>2]|0)+((((c[s>>2]|0)-(c[s>>2]|0)|0)/4|0)<<2);ab(d,4033,f)|0;w=20;break a}else{c[c[s>>2]>>2]=c[(c[j>>2]|0)+16+20>>2];w=20;break a}else w=21;break}case 4045:{d=(c[m>>2]|0)+(4-1)&~(4-1);b=c[d>>2]|0;c[m>>2]=d+4;c[t>>2]=b;if(c[t>>2]|0){c[c[t>>2]>>2]=c[(c[j>>2]|0)+40>>2];w=20}else w=21;break}case 4034:{b=(c[m>>2]|0)+(4-1)&~(4-1);d=c[b>>2]|0;c[m>>2]=b+4;c[u>>2]=d;if((c[u>>2]|0)<-32768|(c[u>>2]|0)>32767)w=21;else{c[(c[j>>2]|0)+40>>2]=c[u>>2];w=20}break}case 4039:{d=(c[m>>2]|0)+(4-1)&~(4-1);b=c[d>>2]|0;c[m>>2]=d+4;c[v>>2]=b;if(c[v>>2]|0){c[c[v>>2]>>2]=c[(c[j>>2]|0)+68>>2];w=20}else w=21;break}case 4009:{b=(c[m>>2]|0)+(4-1)&~(4-1);d=c[b>>2]|0;c[m>>2]=b+4;c[p>>2]=d;if(c[p>>2]|0){c[c[p>>2]>>2]=c[(c[j>>2]|0)+48>>2];w=20}else w=21;break}case 4031:{d=(c[m>>2]|0)+(4-1)&~(4-1);b=c[d>>2]|0;c[m>>2]=d+4;c[q>>2]=b;if(c[q>>2]|0){c[c[q>>2]>>2]=c[(c[j>>2]|0)+80>>2];w=20}else w=21;break}case 4028:{bf((c[j>>2]|0)+44|0,0,84-((c[j>>2]|0)+44-(c[j>>2]|0))|0)|0;ab(c[o>>2]|0,4028,g)|0;Vb(c[n>>2]|0)|0;c[(c[j>>2]|0)+44>>2]=c[(c[j>>2]|0)+8>>2];c[(c[j>>2]|0)+60>>2]=(c[(c[j>>2]|0)+12>>2]|0)/400|0;w=20;break}default:{c[l>>2]=-5;w=20}}while(0);if((w|0)==20){c[h>>2]=c[l>>2];x=c[h>>2]|0;i=e;return x|0}else if((w|0)==21){c[h>>2]=-1;x=c[h>>2]|0;i=e;return x|0}return 0}function Gc(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0;e=i;i=i+16|0;f=e+12|0;g=e+8|0;h=e+4|0;j=e;c[g>>2]=a;c[h>>2]=b;do if((c[h>>2]|0)>=1){c[j>>2]=(d[c[g>>2]>>0]|0)&3;if(!(c[j>>2]|0)){c[f>>2]=1;break}if((c[j>>2]|0)!=3){c[f>>2]=2;break}if((c[h>>2]|0)<2){c[f>>2]=-4;break}else{c[f>>2]=(d[(c[g>>2]|0)+1>>0]|0)&63;break}}else c[f>>2]=-1;while(0);i=e;return c[f>>2]|0}function Hc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;e=i;i=i+32|0;f=e+20|0;g=e+16|0;h=e+12|0;j=e+8|0;k=e+4|0;l=e;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[l>>2]=Gc(c[g>>2]|0,c[h>>2]|0)|0;h=c[l>>2]|0;if((c[l>>2]|0)<0){c[f>>2]=h;m=c[f>>2]|0;i=e;return m|0}c[k>>2]=_(h,yc(c[g>>2]|0,c[j>>2]|0)|0)|0;if(((c[k>>2]|0)*25|0)>((c[j>>2]|0)*3|0)){c[f>>2]=-4;m=c[f>>2]|0;i=e;return m|0}else{c[f>>2]=c[k>>2];m=c[f>>2]|0;i=e;return m|0}return 0}function Ic(a){a=a|0;var b=0,e=0,f=0,g=0,h=0,j=0,k=0;b=i;i=i+16|0;e=b+12|0;f=b+8|0;g=b+4|0;h=b;c[f>>2]=a;c[h>>2]=(c[(c[f>>2]|0)+4>>2]|0)+(c[(c[f>>2]|0)+8>>2]|0);if((c[h>>2]|0)>255){c[e>>2]=0;j=c[e>>2]|0;i=b;return j|0}c[g>>2]=0;while(1){if((c[g>>2]|0)>=(c[c[f>>2]>>2]|0)){k=9;break}if((d[(c[f>>2]|0)+12+(c[g>>2]|0)>>0]|0|0)>=(c[h>>2]|0)?(d[(c[f>>2]|0)+12+(c[g>>2]|0)>>0]|0|0)!=255:0){k=7;break}c[g>>2]=(c[g>>2]|0)+1}if((k|0)==7){c[e>>2]=0;j=c[e>>2]|0;i=b;return j|0}else if((k|0)==9){c[e>>2]=1;j=c[e>>2]|0;i=b;return j|0}return 0}function Jc(a,b,e){a=a|0;b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;f=i;i=i+32|0;g=f+16|0;h=f+12|0;j=f+8|0;k=f+4|0;l=f;c[h>>2]=a;c[j>>2]=b;c[k>>2]=e;c[l>>2]=(c[k>>2]|0)<0?0:(c[k>>2]|0)+1|0;while(1){if((c[l>>2]|0)>=(c[c[h>>2]>>2]|0)){m=6;break}n=c[l>>2]|0;if((d[(c[h>>2]|0)+12+(c[l>>2]|0)>>0]|0|0)==(c[j>>2]<<1|0)){m=4;break}c[l>>2]=n+1}if((m|0)==4){c[g>>2]=n;o=c[g>>2]|0;i=f;return o|0}else if((m|0)==6){c[g>>2]=-1;o=c[g>>2]|0;i=f;return o|0}return 0}function Kc(a,b,e){a=a|0;b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;f=i;i=i+32|0;g=f+16|0;h=f+12|0;j=f+8|0;k=f+4|0;l=f;c[h>>2]=a;c[j>>2]=b;c[k>>2]=e;c[l>>2]=(c[k>>2]|0)<0?0:(c[k>>2]|0)+1|0;while(1){if((c[l>>2]|0)>=(c[c[h>>2]>>2]|0)){m=6;break}n=c[l>>2]|0;if((d[(c[h>>2]|0)+12+(c[l>>2]|0)>>0]|0|0)==((c[j>>2]<<1)+1|0)){m=4;break}c[l>>2]=n+1}if((m|0)==4){c[g>>2]=n;o=c[g>>2]|0;i=f;return o|0}else if((m|0)==6){c[g>>2]=-1;o=c[g>>2]|0;i=f;return o|0}return 0}function Lc(a,b,e){a=a|0;b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;f=i;i=i+32|0;g=f+16|0;h=f+12|0;j=f+8|0;k=f+4|0;l=f;c[h>>2]=a;c[j>>2]=b;c[k>>2]=e;c[l>>2]=(c[k>>2]|0)<0?0:(c[k>>2]|0)+1|0;while(1){if((c[l>>2]|0)>=(c[c[h>>2]>>2]|0)){m=6;break}n=c[l>>2]|0;if((d[(c[h>>2]|0)+12+(c[l>>2]|0)>>0]|0|0)==((c[j>>2]|0)+(c[(c[h>>2]|0)+8>>2]|0)|0)){m=4;break}c[l>>2]=n+1}if((m|0)==4){c[g>>2]=n;o=c[g>>2]|0;i=f;return o|0}else if((m|0)==6){c[g>>2]=-1;o=c[g>>2]|0;i=f;return o|0}return 0}function Mc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;i=i+32|0;e=d+16|0;f=d+12|0;g=d+8|0;h=d+4|0;j=d;c[f>>2]=a;c[g>>2]=b;if((c[f>>2]|0)>=1?!((c[g>>2]|0)<0?1:(c[g>>2]|0)>(c[f>>2]|0)):0){c[h>>2]=Ac(2)|0;c[j>>2]=Ac(1)|0;b=ae(268)|0;a=c[g>>2]|0;k=b+(_(a,ae(c[h>>2]|0)|0)|0)|0;h=(c[f>>2]|0)-(c[g>>2]|0)|0;c[e>>2]=k+(_(h,ae(c[j>>2]|0)|0)|0);l=c[e>>2]|0;i=d;return l|0}c[e>>2]=0;l=c[e>>2]|0;i=d;return l|0}function Nc(b,d,e,f,g,h){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;j=i;i=i+48|0;k=j+4|0;l=j+16|0;m=j+36|0;n=j;o=j+32|0;p=j+40|0;q=j+44|0;r=j+24|0;s=j+20|0;t=j+8|0;u=j+12|0;v=j+28|0;c[l>>2]=b;c[m>>2]=d;c[n>>2]=e;c[o>>2]=f;c[p>>2]=g;c[q>>2]=h;if((!((c[n>>2]|0)>255|(c[n>>2]|0)<1)?(c[p>>2]|0)<=(c[o>>2]|0):0)?!(((c[o>>2]|0)<1?1:((c[p>>2]|0)+(c[o>>2]|0)|0)>255)|(c[p>>2]|0)<0):0){c[c[l>>2]>>2]=c[n>>2];c[(c[l>>2]|0)+4>>2]=c[o>>2];c[(c[l>>2]|0)+8>>2]=c[p>>2];c[t>>2]=0;while(1){if((c[t>>2]|0)>=(c[c[l>>2]>>2]|0))break;a[(c[l>>2]|0)+12+(c[t>>2]|0)>>0]=a[(c[q>>2]|0)+(c[t>>2]|0)>>0]|0;c[t>>2]=(c[t>>2]|0)+1}if(!(Ic(c[l>>2]|0)|0)){c[k>>2]=-1;w=c[k>>2]|0;i=j;return w|0}q=c[l>>2]|0;c[v>>2]=q+(ae(268)|0);c[r>>2]=Ac(2)|0;c[s>>2]=Ac(1)|0;c[t>>2]=0;while(1){if((c[t>>2]|0)>=(c[(c[l>>2]|0)+8>>2]|0))break;c[u>>2]=Bc(c[v>>2]|0,c[m>>2]|0,2)|0;if(c[u>>2]|0){x=13;break}q=ae(c[r>>2]|0)|0;c[v>>2]=(c[v>>2]|0)+q;c[t>>2]=(c[t>>2]|0)+1}if((x|0)==13){c[k>>2]=c[u>>2];w=c[k>>2]|0;i=j;return w|0}while(1){if((c[t>>2]|0)>=(c[(c[l>>2]|0)+4>>2]|0)){x=19;break}c[u>>2]=Bc(c[v>>2]|0,c[m>>2]|0,1)|0;if(c[u>>2]|0){x=17;break}r=ae(c[s>>2]|0)|0;c[v>>2]=(c[v>>2]|0)+r;c[t>>2]=(c[t>>2]|0)+1}if((x|0)==17){c[k>>2]=c[u>>2];w=c[k>>2]|0;i=j;return w|0}else if((x|0)==19){c[k>>2]=0;w=c[k>>2]|0;i=j;return w|0}}c[k>>2]=-1;w=c[k>>2]|0;i=j;return w|0}function Oc(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;h=i;i=i+48|0;j=h+28|0;k=h+16|0;l=h+4|0;m=h+8|0;n=h+32|0;o=h;p=h+12|0;q=h+24|0;r=h+20|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=d;c[n>>2]=e;c[o>>2]=f;c[p>>2]=g;if((!((c[l>>2]|0)>255|(c[l>>2]|0)<1)?(c[n>>2]|0)<=(c[m>>2]|0):0)?!(((c[m>>2]|0)<1?1:((c[n>>2]|0)+(c[m>>2]|0)|0)>255)|(c[n>>2]|0)<0):0){c[r>>2]=be(Mc(c[m>>2]|0,c[n>>2]|0)|0)|0;if(!(c[r>>2]|0)){if(c[p>>2]|0)c[c[p>>2]>>2]=-7;c[j>>2]=0;s=c[j>>2]|0;i=h;return s|0}c[q>>2]=Nc(c[r>>2]|0,c[k>>2]|0,c[l>>2]|0,c[m>>2]|0,c[n>>2]|0,c[o>>2]|0)|0;if(c[p>>2]|0)c[c[p>>2]>>2]=c[q>>2];if(c[q>>2]|0){ce(c[r>>2]|0);c[r>>2]=0}c[j>>2]=c[r>>2];s=c[j>>2]|0;i=h;return s|0}if(c[p>>2]|0)c[c[p>>2]>>2]=-1;c[j>>2]=0;s=c[j>>2]|0;i=h;return s|0}function Pc(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0;h=i;i=i+32|0;j=h+20|0;k=h+16|0;l=h+12|0;m=h+8|0;n=h+4|0;o=h;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[n>>2]=f;c[o>>2]=g;g=de(c[j>>2]|0,c[k>>2]|0,c[l>>2]|0,c[m>>2]|0,1,c[n>>2]|0,c[o>>2]|0,0)|0;i=h;return g|0}function Qc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;e=i;i=i+128|0;f=e+8|0;g=e;h=e+24|0;j=e+16|0;k=e+44|0;l=e+36|0;m=e+32|0;n=e+80|0;o=e+52|0;p=e+40|0;q=e+48|0;r=e+28|0;s=e+56|0;t=e+60|0;u=e+64|0;v=e+72|0;w=e+68|0;x=e+76|0;y=e+96|0;z=e+100|0;A=e+104|0;B=e+108|0;C=e+112|0;D=e+116|0;E=e+120|0;F=e+124|0;c[l>>2]=a;c[m>>2]=b;c[r>>2]=0;c[n>>2]=d;c[o>>2]=Ac(2)|0;c[p>>2]=Ac(1)|0;d=c[l>>2]|0;c[q>>2]=d+(ae(268)|0);a:do switch(c[m>>2]|0){case 4031:{d=(c[n>>2]|0)+(4-1)&~(4-1);b=c[d>>2]|0;c[n>>2]=d+4;c[v>>2]=b;if(c[v>>2]|0){c[c[v>>2]>>2]=0;c[u>>2]=0;while(1){if((c[u>>2]|0)>=(c[(c[l>>2]|0)+4>>2]|0)){G=37;break a}c[x>>2]=c[q>>2];if((c[u>>2]|0)<(c[(c[l>>2]|0)+8>>2]|0)){b=ae(c[o>>2]|0)|0;c[q>>2]=(c[q>>2]|0)+b}else{b=ae(c[p>>2]|0)|0;c[q>>2]=(c[q>>2]|0)+b}b=c[x>>2]|0;d=c[m>>2]|0;c[h>>2]=w;c[r>>2]=Fc(b,d,h)|0;if(c[r>>2]|0){G=37;break a}d=c[v>>2]|0;c[d>>2]=c[d>>2]^c[w>>2];c[u>>2]=(c[u>>2]|0)+1}}else G=38;break}case 4028:{c[y>>2]=0;while(1){if((c[y>>2]|0)>=(c[(c[l>>2]|0)+4>>2]|0)){G=37;break a}c[z>>2]=c[q>>2];if((c[y>>2]|0)<(c[(c[l>>2]|0)+8>>2]|0)){d=ae(c[o>>2]|0)|0;c[q>>2]=(c[q>>2]|0)+d}else{d=ae(c[p>>2]|0)|0;c[q>>2]=(c[q>>2]|0)+d}c[r>>2]=Fc(c[z>>2]|0,4028,g)|0;if(c[r>>2]|0){G=37;break a}c[y>>2]=(c[y>>2]|0)+1}break}case 5122:{d=(c[n>>2]|0)+(4-1)&~(4-1);b=c[d>>2]|0;c[n>>2]=d+4;c[B>>2]=b;if(!((c[B>>2]|0)>=0?(c[B>>2]|0)<(c[(c[l>>2]|0)+4>>2]|0):0))c[r>>2]=-1;b=(c[n>>2]|0)+(4-1)&~(4-1);d=c[b>>2]|0;c[n>>2]=b+4;c[C>>2]=d;if(c[C>>2]|0){c[A>>2]=0;while(1){if((c[A>>2]|0)>=(c[B>>2]|0))break;if((c[A>>2]|0)<(c[(c[l>>2]|0)+8>>2]|0)){d=ae(c[o>>2]|0)|0;c[q>>2]=(c[q>>2]|0)+d}else{d=ae(c[p>>2]|0)|0;c[q>>2]=(c[q>>2]|0)+d}c[A>>2]=(c[A>>2]|0)+1}c[c[C>>2]>>2]=c[q>>2];G=37}else G=38;break}case 4034:{d=(c[n>>2]|0)+(4-1)&~(4-1);b=c[d>>2]|0;c[n>>2]=d+4;c[E>>2]=b;c[D>>2]=0;while(1){if((c[D>>2]|0)>=(c[(c[l>>2]|0)+4>>2]|0)){G=37;break a}c[F>>2]=c[q>>2];if((c[D>>2]|0)<(c[(c[l>>2]|0)+8>>2]|0)){b=ae(c[o>>2]|0)|0;c[q>>2]=(c[q>>2]|0)+b}else{b=ae(c[p>>2]|0)|0;c[q>>2]=(c[q>>2]|0)+b}b=c[F>>2]|0;d=c[m>>2]|0;c[f>>2]=c[E>>2];c[r>>2]=Fc(b,d,f)|0;if(c[r>>2]|0){G=37;break a}c[D>>2]=(c[D>>2]|0)+1}break}case 4039:case 4045:case 4029:case 4009:{d=(c[n>>2]|0)+(4-1)&~(4-1);b=c[d>>2]|0;c[n>>2]=d+4;c[t>>2]=b;c[s>>2]=c[q>>2];b=c[s>>2]|0;d=c[m>>2]|0;c[j>>2]=c[t>>2];c[r>>2]=Fc(b,d,j)|0;G=37;break}default:{c[r>>2]=-5;G=37}}while(0);if((G|0)==37){c[k>>2]=c[r>>2];H=c[k>>2]|0;i=e;return H|0}else if((G|0)==38){c[k>>2]=-1;H=c[k>>2]|0;i=e;return H|0}return 0}function Rc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)>>>0)/((c[f>>2]|0)>>>0)|0|0}function Sc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return (c[e>>2]|0)/(c[f>>2]|0)|0|0}function Tc(a,b,e,f,h,j,k,l,m,n,o){a=a|0;b=b|0;e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;l=l|0;m=+m;n=n|0;o=o|0;var p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,P=0,Q=0,R=0;p=i;i=i+112|0;q=p+48|0;r=p+44|0;s=p+84|0;t=p+92|0;u=p+40|0;v=p+16|0;w=p+20|0;x=p+24|0;y=p+28|0;z=p+72|0;A=p+80|0;B=p+88|0;C=p+96|0;D=p+100|0;E=p+52|0;F=p+56|0;G=p+60|0;H=p+64|0;I=p+8|0;J=p+12|0;K=p+68|0;L=p+32|0;M=p+36|0;N=p+76|0;P=p;Q=p+4|0;c[r>>2]=a;c[s>>2]=b;c[t>>2]=e;c[u>>2]=f;c[v>>2]=h;c[w>>2]=j;c[x>>2]=k;c[y>>2]=l;g[z>>2]=m;c[A>>2]=n;c[B>>2]=o;c[C>>2]=c[t>>2];c[D>>2]=c[t>>2];c[F>>2]=c[v>>2];c[G>>2]=0;c[H>>2]=0;c[J>>2]=0;c[K>>2]=((c[c[r>>2]>>2]|0)!=0^1)&1;c[M>>2]=c[c[r>>2]>>2];c[N>>2]=c[(c[r>>2]|0)+20>>2];c[I>>2]=(c[F>>2]|0)==1&1;c[D>>2]=Rc(c[D>>2]|0,c[v>>2]|0)|0;if((c[t>>2]|0)==1){c[q>>2]=Ce(c[r>>2]|0,c[s>>2]|0,0,c[u>>2]|0,c[y>>2]|0)|0;R=c[q>>2]|0;i=p;return R|0}if((c[N>>2]|0)>0)c[H>>2]=c[N>>2];do if((c[A>>2]|0)!=0&(c[w>>2]|0)!=0){if((c[H>>2]|0)==0?!((c[D>>2]&1|0)==0&(c[N>>2]|0)<0|(c[F>>2]|0)>1):0)break;df(c[A>>2]|0,c[w>>2]|0,(c[t>>2]<<2)+0|0)|0;c[w>>2]=c[A>>2]}while(0);c[L>>2]=0;while(1){if((c[L>>2]|0)>=(c[H>>2]|0))break;if(c[M>>2]|0)Ua(c[s>>2]|0,c[t>>2]>>c[L>>2],1<<c[L>>2]);if(c[w>>2]|0)Ua(c[w>>2]|0,c[t>>2]>>c[L>>2],1<<c[L>>2]);c[B>>2]=d[25096+(c[B>>2]&15)>>0]|0|(d[25096+(c[B>>2]>>4)>>0]|0)<<2;c[L>>2]=(c[L>>2]|0)+1}c[v>>2]=c[v>>2]>>c[H>>2];c[D>>2]=c[D>>2]<<c[H>>2];while(1){if(!((c[D>>2]&1|0)==0?(c[N>>2]|0)<0:0))break;if(c[M>>2]|0)Ua(c[s>>2]|0,c[D>>2]|0,c[v>>2]|0);if(c[w>>2]|0)Ua(c[w>>2]|0,c[D>>2]|0,c[v>>2]|0);c[B>>2]=c[B>>2]|c[B>>2]<<c[v>>2];c[v>>2]=c[v>>2]<<1;c[D>>2]=c[D>>2]>>1;c[G>>2]=(c[G>>2]|0)+1;c[N>>2]=(c[N>>2]|0)+1}c[F>>2]=c[v>>2];c[E>>2]=c[D>>2];if((c[F>>2]|0)>1){if(c[M>>2]|0)Le(c[s>>2]|0,c[D>>2]>>c[H>>2],c[F>>2]<<c[H>>2],c[I>>2]|0);if(c[w>>2]|0)Le(c[w>>2]|0,c[D>>2]>>c[H>>2],c[F>>2]<<c[H>>2],c[I>>2]|0)}c[J>>2]=Me(c[r>>2]|0,c[s>>2]|0,c[t>>2]|0,c[u>>2]|0,c[v>>2]|0,c[w>>2]|0,c[x>>2]|0,+g[z>>2],c[B>>2]|0)|0;if(c[K>>2]|0){if((c[F>>2]|0)>1)Ne(c[s>>2]|0,c[D>>2]>>c[H>>2],c[F>>2]<<c[H>>2],c[I>>2]|0);c[D>>2]=c[E>>2];c[v>>2]=c[F>>2];c[L>>2]=0;while(1){if((c[L>>2]|0)>=(c[G>>2]|0))break;c[v>>2]=c[v>>2]>>1;c[D>>2]=c[D>>2]<<1;c[J>>2]=c[J>>2]|(c[J>>2]|0)>>>(c[v>>2]|0);Ua(c[s>>2]|0,c[D>>2]|0,c[v>>2]|0);c[L>>2]=(c[L>>2]|0)+1}c[L>>2]=0;while(1){if((c[L>>2]|0)>=(c[H>>2]|0))break;c[J>>2]=d[25112+(c[J>>2]|0)>>0];Ua(c[s>>2]|0,c[C>>2]>>c[L>>2],1<<c[L>>2]);c[L>>2]=(c[L>>2]|0)+1}c[v>>2]=c[v>>2]<<c[H>>2];a:do if(c[y>>2]|0){g[Q>>2]=+O(+(+(c[C>>2]|0)));c[P>>2]=0;while(1){if((c[P>>2]|0)>=(c[C>>2]|0))break a;g[(c[y>>2]|0)+(c[P>>2]<<2)>>2]=+g[Q>>2]*+g[(c[s>>2]|0)+(c[P>>2]<<2)>>2];c[P>>2]=(c[P>>2]|0)+1}}while(0);c[J>>2]=c[J>>2]&(1<<c[v>>2])-1}c[q>>2]=c[J>>2];R=c[q>>2]|0;i=p;return R|0}function Uc(a,b,d,e,f,h,j,k,l,m,n){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;var o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0;o=i;i=i+176|0;p=o+156|0;q=o+132|0;r=o+8|0;s=o+56|0;t=o+64|0;u=o+16|0;v=o+20|0;w=o+24|0;x=o+28|0;y=o+32|0;z=o+36|0;A=o+40|0;B=o+44|0;C=o+128|0;D=o+136|0;E=o+144|0;F=o+152|0;G=o+160|0;H=o+68|0;I=o+72|0;J=o+76|0;K=o+80|0;L=o+84|0;M=o+88|0;N=o+96|0;O=o+12|0;P=o+4|0;Q=o;R=o+120|0;S=o+48|0;T=o+124|0;U=o+52|0;V=o+140|0;W=o+60|0;X=o+148|0;c[q>>2]=a;c[r>>2]=b;c[s>>2]=d;c[t>>2]=e;c[u>>2]=f;c[v>>2]=h;c[w>>2]=j;c[x>>2]=k;c[y>>2]=l;c[z>>2]=m;c[A>>2]=n;c[B>>2]=0;c[C>>2]=0;c[D>>2]=0;g[E>>2]=0.0;g[F>>2]=0.0;c[G>>2]=0;c[H>>2]=((c[c[q>>2]>>2]|0)!=0^1)&1;c[P>>2]=c[c[q>>2]>>2];c[Q>>2]=c[(c[q>>2]|0)+24>>2];if((c[t>>2]|0)==1){c[p>>2]=Ce(c[q>>2]|0,c[r>>2]|0,c[s>>2]|0,c[u>>2]|0,c[y>>2]|0)|0;Y=c[p>>2]|0;i=o;return Y|0}c[O>>2]=c[A>>2];De(c[q>>2]|0,N,c[r>>2]|0,c[s>>2]|0,c[t>>2]|0,u,c[v>>2]|0,c[v>>2]|0,c[x>>2]|0,1,A);c[D>>2]=c[N>>2];c[B>>2]=c[N+4>>2];c[C>>2]=c[N+8>>2];c[K>>2]=c[N+12>>2];c[L>>2]=c[N+16>>2];c[M>>2]=c[N+20>>2];g[E>>2]=+(c[B>>2]|0)*.000030517578125;g[F>>2]=+(c[C>>2]|0)*.000030517578125;do if((c[t>>2]|0)==2){c[S>>2]=0;c[I>>2]=c[u>>2];c[J>>2]=0;c[J>>2]=(c[L>>2]|0)!=0&(c[L>>2]|0)!=16384?8:0;c[I>>2]=(c[I>>2]|0)-(c[J>>2]|0);c[R>>2]=(c[L>>2]|0)>8192&1;C=(c[q>>2]|0)+28|0;c[C>>2]=(c[C>>2]|0)-((c[M>>2]|0)+(c[J>>2]|0));c[T>>2]=(c[R>>2]|0)!=0?c[s>>2]|0:c[r>>2]|0;c[U>>2]=(c[R>>2]|0)!=0?c[r>>2]|0:c[s>>2]|0;do if(c[J>>2]|0)if(c[P>>2]|0){c[S>>2]=+g[c[T>>2]>>2]*+g[(c[U>>2]|0)+4>>2]-+g[(c[T>>2]|0)+4>>2]*+g[c[U>>2]>>2]<0.0&1;pb(c[Q>>2]|0,c[S>>2]|0,1);break}else{c[S>>2]=lb(c[Q>>2]|0,1)|0;break}while(0);c[S>>2]=1-(c[S>>2]<<1);c[G>>2]=Tc(c[q>>2]|0,c[T>>2]|0,c[t>>2]|0,c[I>>2]|0,c[v>>2]|0,c[w>>2]|0,c[x>>2]|0,c[y>>2]|0,1.0,c[z>>2]|0,c[O>>2]|0)|0;g[c[U>>2]>>2]=+(0-(c[S>>2]|0)|0)*+g[(c[T>>2]|0)+4>>2];g[(c[U>>2]|0)+4>>2]=+(c[S>>2]|0)*+g[c[T>>2]>>2];if(c[H>>2]|0){g[c[r>>2]>>2]=+g[E>>2]*+g[c[r>>2]>>2];g[(c[r>>2]|0)+4>>2]=+g[E>>2]*+g[(c[r>>2]|0)+4>>2];g[c[s>>2]>>2]=+g[F>>2]*+g[c[s>>2]>>2];g[(c[s>>2]|0)+4>>2]=+g[F>>2]*+g[(c[s>>2]|0)+4>>2];g[V>>2]=+g[c[r>>2]>>2];g[c[r>>2]>>2]=+g[V>>2]-+g[c[s>>2]>>2];g[c[s>>2]>>2]=+g[V>>2]+ +g[c[s>>2]>>2];g[V>>2]=+g[(c[r>>2]|0)+4>>2];g[(c[r>>2]|0)+4>>2]=+g[V>>2]-+g[(c[s>>2]|0)+4>>2];g[(c[s>>2]|0)+4>>2]=+g[V>>2]+ +g[(c[s>>2]|0)+4>>2]}}else{C=c[u>>2]|0;if((c[u>>2]|0)<(((c[u>>2]|0)-(c[K>>2]|0)|0)/2|0|0))Z=C;else Z=(C-(c[K>>2]|0)|0)/2|0;if(0<=(Z|0)){C=c[u>>2]|0;if((c[u>>2]|0)<(((c[u>>2]|0)-(c[K>>2]|0)|0)/2|0|0))_=C;else _=(C-(c[K>>2]|0)|0)/2|0}else _=0;c[I>>2]=_;c[J>>2]=(c[u>>2]|0)-(c[I>>2]|0);C=(c[q>>2]|0)+28|0;c[C>>2]=(c[C>>2]|0)-(c[M>>2]|0);c[W>>2]=c[(c[q>>2]|0)+28>>2];C=c[q>>2]|0;if((c[I>>2]|0)>=(c[J>>2]|0)){c[G>>2]=Tc(C,c[r>>2]|0,c[t>>2]|0,c[I>>2]|0,c[v>>2]|0,c[w>>2]|0,c[x>>2]|0,c[y>>2]|0,1.0,c[z>>2]|0,c[A>>2]|0)|0;c[W>>2]=(c[I>>2]|0)-((c[W>>2]|0)-(c[(c[q>>2]|0)+28>>2]|0));if((c[W>>2]|0)>24&(c[L>>2]|0)!=0)c[J>>2]=(c[J>>2]|0)+((c[W>>2]|0)-24);B=Tc(c[q>>2]|0,c[s>>2]|0,c[t>>2]|0,c[J>>2]|0,c[v>>2]|0,0,c[x>>2]|0,0,+g[F>>2],0,c[A>>2]>>c[v>>2])|0;c[G>>2]=c[G>>2]|B;break}else{c[G>>2]=Tc(C,c[s>>2]|0,c[t>>2]|0,c[J>>2]|0,c[v>>2]|0,0,c[x>>2]|0,0,+g[F>>2],0,c[A>>2]>>c[v>>2])|0;c[W>>2]=(c[J>>2]|0)-((c[W>>2]|0)-(c[(c[q>>2]|0)+28>>2]|0));if((c[W>>2]|0)>24&(c[L>>2]|0)!=16384)c[I>>2]=(c[I>>2]|0)+((c[W>>2]|0)-24);C=Tc(c[q>>2]|0,c[r>>2]|0,c[t>>2]|0,c[I>>2]|0,c[v>>2]|0,c[w>>2]|0,c[x>>2]|0,c[y>>2]|0,1.0,c[z>>2]|0,c[A>>2]|0)|0;c[G>>2]=c[G>>2]|C;break}}while(0);a:do if(c[H>>2]|0){if((c[t>>2]|0)!=2)Ee(c[r>>2]|0,c[s>>2]|0,+g[E>>2],c[t>>2]|0);if(c[D>>2]|0){c[X>>2]=0;while(1){if((c[X>>2]|0)>=(c[t>>2]|0))break a;g[(c[s>>2]|0)+(c[X>>2]<<2)>>2]=-+g[(c[s>>2]|0)+(c[X>>2]<<2)>>2];c[X>>2]=(c[X>>2]|0)+1}}}while(0);c[p>>2]=c[G>>2];Y=c[p>>2]|0;i=o;return Y|0}function Vc(a,b,d,e,f,h,j){a=a|0;b=b|0;d=d|0;e=e|0;f=+f;h=+h;j=+j;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;k=i;i=i+64|0;l=k+44|0;m=k+36|0;n=k+20|0;o=k+16|0;p=k+32|0;q=k+40|0;r=k+48|0;s=k+8|0;t=k+4|0;u=k+24|0;v=k+12|0;w=k+28|0;x=k;c[l>>2]=a;c[m>>2]=b;c[n>>2]=d;c[o>>2]=e;g[p>>2]=f;g[q>>2]=h;g[r>>2]=j;g[w>>2]=+g[(c[m>>2]|0)+(0-(c[n>>2]|0)-2<<2)>>2];g[v>>2]=+g[(c[m>>2]|0)+(0-(c[n>>2]|0)-1<<2)>>2];g[u>>2]=+g[(c[m>>2]|0)+(0-(c[n>>2]|0)<<2)>>2];g[t>>2]=+g[(c[m>>2]|0)+(0-(c[n>>2]|0)+1<<2)>>2];c[x>>2]=0;while(1){if((c[x>>2]|0)>=(c[o>>2]|0))break;g[s>>2]=+g[(c[m>>2]|0)+((c[x>>2]|0)-(c[n>>2]|0)+2<<2)>>2];g[(c[l>>2]|0)+(c[x>>2]<<2)>>2]=+g[(c[m>>2]|0)+(c[x>>2]<<2)>>2]+ +g[p>>2]*+g[u>>2]+ +g[q>>2]*(+g[t>>2]+ +g[v>>2])+ +g[r>>2]*(+g[s>>2]+ +g[w>>2]);g[w>>2]=+g[v>>2];g[v>>2]=+g[u>>2];g[u>>2]=+g[t>>2];g[t>>2]=+g[s>>2];c[x>>2]=(c[x>>2]|0)+1}i=k;return}function Wc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;i=i+16|0;e=d+8|0;f=d+4|0;g=d;c[e>>2]=a;c[f>>2]=b;b=88+((_(c[f>>2]|0,2048+(c[(c[e>>2]|0)+4>>2]|0)|0)|0)-1<<2)|0;c[g>>2]=b+((c[f>>2]|0)*24<<2)+(c[(c[e>>2]|0)+8>>2]<<3<<2);i=d;return c[g>>2]|0}function Xc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e+4|0;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;if((c[j>>2]|0)<0|(c[j>>2]|0)>2){c[f>>2]=-1;k=c[f>>2]|0;i=e;return k|0}if(!(c[g>>2]|0)){c[f>>2]=-7;k=c[f>>2]|0;i=e;return k|0}else{d=c[g>>2]|0;bf(d|0,0,Wc(c[h>>2]|0,c[j>>2]|0)|0)|0;c[c[g>>2]>>2]=c[h>>2];c[(c[g>>2]|0)+4>>2]=c[(c[h>>2]|0)+4>>2];h=c[j>>2]|0;c[(c[g>>2]|0)+8>>2]=h;c[(c[g>>2]|0)+12>>2]=h;c[(c[g>>2]|0)+16>>2]=1;c[(c[g>>2]|0)+20>>2]=0;c[(c[g>>2]|0)+24>>2]=c[(c[c[g>>2]>>2]|0)+12>>2];c[(c[g>>2]|0)+28>>2]=1;h=Be()|0;c[(c[g>>2]|0)+32>>2]=h;c[(c[g>>2]|0)+48>>2]=0;ab(c[g>>2]|0,4028,e)|0;c[f>>2]=0;k=c[f>>2]|0;i=e;return k|0}return 0}function Yc(a,d,e){a=a|0;d=d|0;e=e|0;var f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0;f=i;i=i+4624|0;h=f+212|0;j=f+204|0;k=f+4568|0;l=f+12|0;m=f+4584|0;n=f+4600|0;o=f+24|0;p=f+32|0;q=f+40|0;r=f+44|0;s=f+48|0;t=f+52|0;u=f+56|0;v=f+60|0;w=f+64|0;x=f+68|0;y=f+72|0;z=f+76|0;A=f+80|0;B=f+84|0;C=f+88|0;D=f+92|0;E=f+4572|0;F=f+4580|0;G=f+4588|0;H=f+4596|0;I=f+4604|0;J=f+4608|0;K=f+216|0;L=f+220|0;M=f+224|0;N=f+228|0;P=f+232|0;Q=f+240|0;R=f+4336|0;S=f+4340|0;T=f+4344|0;U=f+4348|0;V=f+4352|0;W=f+4356|0;X=f+4360|0;Y=f+4364|0;Z=f+4368|0;$=f+4472|0;aa=f+16|0;ba=f+4|0;ca=f+8|0;da=f;ea=f+96|0;fa=f+104|0;ga=f+4576|0;ha=f+200|0;ia=f+4592|0;ja=f+208|0;c[h>>2]=a;c[j>>2]=d;c[k>>2]=e;c[n>>2]=c[(c[h>>2]|0)+8>>2];c[v>>2]=c[c[h>>2]>>2];c[w>>2]=c[(c[v>>2]|0)+8>>2];c[x>>2]=c[(c[v>>2]|0)+4>>2];c[B>>2]=c[(c[v>>2]|0)+32>>2];c[l>>2]=0;do{e=(c[h>>2]|0)+84+((_(c[l>>2]|0,2048+(c[x>>2]|0)|0)|0)<<2)|0;c[o+(c[l>>2]<<2)>>2]=e;c[p+(c[l>>2]<<2)>>2]=(c[o+(c[l>>2]<<2)>>2]|0)+8192+(0-(c[j>>2]|0)<<2);e=(c[l>>2]|0)+1|0;c[l>>2]=e}while((e|0)<(c[n>>2]|0));c[q>>2]=(c[h>>2]|0)+84+((_(2048+(c[x>>2]|0)|0,c[n>>2]|0)|0)<<2);c[r>>2]=(c[q>>2]|0)+((c[n>>2]|0)*24<<2);c[s>>2]=(c[r>>2]|0)+(c[w>>2]<<1<<2);c[t>>2]=(c[s>>2]|0)+(c[w>>2]<<1<<2);c[u>>2]=(c[t>>2]|0)+(c[w>>2]<<1<<2);c[z>>2]=c[(c[h>>2]|0)+48>>2];c[y>>2]=c[(c[h>>2]|0)+20>>2];c[A>>2]=((c[z>>2]|0)>=5?1:(c[y>>2]|0)!=0)&1;if(c[A>>2]|0){c[E>>2]=c[(c[h>>2]|0)+24>>2];if((c[E>>2]|0)<(c[(c[v>>2]|0)+12>>2]|0))la=c[E>>2]|0;else la=c[(c[v>>2]|0)+12>>2]|0;do if((c[y>>2]|0)<=(la|0))if((c[E>>2]|0)<(c[(c[v>>2]|0)+12>>2]|0)){ma=c[E>>2]|0;break}else{ma=c[(c[v>>2]|0)+12>>2]|0;break}else ma=c[y>>2]|0;while(0);c[F>>2]=ma;ma=_(c[n>>2]|0,c[j>>2]|0)|0;c[G>>2]=ua()|0;la=i;i=i+((1*(ma<<2)|0)+15&-16)|0;if((c[z>>2]|0)>=5)c[D>>2]=c[u>>2];else{g[H>>2]=(c[z>>2]|0)==0?1.5:.5;c[l>>2]=0;do{c[m>>2]=c[y>>2];while(1){if((c[m>>2]|0)>=(c[E>>2]|0))break;u=_(c[l>>2]|0,c[w>>2]|0)|0;ma=(c[r>>2]|0)+(u+(c[m>>2]|0)<<2)|0;g[ma>>2]=+g[ma>>2]-+g[H>>2];c[m>>2]=(c[m>>2]|0)+1}ma=(c[l>>2]|0)+1|0;c[l>>2]=ma}while((ma|0)<(c[n>>2]|0));c[D>>2]=c[r>>2]}c[C>>2]=c[(c[h>>2]|0)+36>>2];c[l>>2]=0;while(1){if((c[l>>2]|0)>=(c[n>>2]|0))break;c[m>>2]=c[y>>2];while(1){if((c[m>>2]|0)>=(c[F>>2]|0))break;r=_(c[j>>2]|0,c[l>>2]|0)|0;c[J>>2]=r+(b[(c[B>>2]|0)+(c[m>>2]<<1)>>1]<<c[k>>2]);c[K>>2]=(b[(c[B>>2]|0)+((c[m>>2]|0)+1<<1)>>1]|0)-(b[(c[B>>2]|0)+(c[m>>2]<<1)>>1]|0)<<c[k>>2];c[I>>2]=0;while(1){if((c[I>>2]|0)>=(c[K>>2]|0))break;c[C>>2]=Ra(c[C>>2]|0)|0;g[la+((c[J>>2]|0)+(c[I>>2]|0)<<2)>>2]=+(c[C>>2]>>20|0);c[I>>2]=(c[I>>2]|0)+1}Ib(la+(c[J>>2]<<2)|0,c[K>>2]|0,1.0);c[m>>2]=(c[m>>2]|0)+1}c[l>>2]=(c[l>>2]|0)+1}c[(c[h>>2]|0)+36>>2]=c[C>>2];c[l>>2]=0;do{ff(c[o+(c[l>>2]<<2)>>2]|0,(c[o+(c[l>>2]<<2)>>2]|0)+(c[j>>2]<<2)|0,(2048-(c[j>>2]|0)+(c[x>>2]>>1)<<2)+0|0)|0;C=(c[l>>2]|0)+1|0;c[l>>2]=C}while((C|0)<(c[n>>2]|0));ad(c[v>>2]|0,la,p,c[D>>2]|0,c[y>>2]|0,c[F>>2]|0,c[n>>2]|0,c[n>>2]|0,0,c[k>>2]|0,c[(c[h>>2]|0)+16>>2]|0,0);ka(c[G>>2]|0);na=c[z>>2]|0;oa=na+1|0;pa=c[h>>2]|0;qa=pa+48|0;c[qa>>2]=oa;i=f;return}g[M>>2]=1.0;if(!(c[z>>2]|0)){G=Ae(o,c[n>>2]|0,c[(c[h>>2]|0)+32>>2]|0)|0;c[N>>2]=G;c[(c[h>>2]|0)+44>>2]=G}else{c[N>>2]=c[(c[h>>2]|0)+44>>2];g[M>>2]=.800000011920929}G=c[x>>2]|0;c[P>>2]=ua()|0;k=i;i=i+((1*(G<<2)|0)+15&-16)|0;c[L>>2]=c[(c[v>>2]|0)+60>>2];c[l>>2]=0;do{g[T>>2]=0.0;c[U>>2]=c[o+(c[l>>2]<<2)>>2];c[m>>2]=0;while(1){if((c[m>>2]|0)>=1024)break;g[Q+(c[m>>2]<<2)>>2]=+g[(c[U>>2]|0)+(1024+(c[m>>2]|0)<<2)>>2];c[m>>2]=(c[m>>2]|0)+1}if(!(c[z>>2]|0)){Bb(Q,Z,c[L>>2]|0,c[x>>2]|0,24,1024,c[(c[h>>2]|0)+32>>2]|0)|0;g[Z>>2]=+g[Z>>2]*1.000100016593933;c[m>>2]=1;while(1){if((c[m>>2]|0)>24)break;v=Z+(c[m>>2]<<2)|0;g[v>>2]=+g[v>>2]-+g[Z+(c[m>>2]<<2)>>2]*6.400000711437315e-05*+(c[m>>2]|0)*+(c[m>>2]|0);c[m>>2]=(c[m>>2]|0)+1}yb((c[q>>2]|0)+((c[l>>2]|0)*24<<2)|0,Z,24)}c[X>>2]=(c[N>>2]<<1|0)<1024?c[N>>2]<<1:1024;c[m>>2]=0;while(1){if((c[m>>2]|0)>=24)break;g[$+(c[m>>2]<<2)>>2]=+g[(c[U>>2]|0)+(2048-(c[X>>2]|0)-1-(c[m>>2]|0)<<2)>>2];c[m>>2]=(c[m>>2]|0)+1}zb(Q+4096+(0-(c[X>>2]|0)<<2)|0,(c[q>>2]|0)+((c[l>>2]|0)*24<<2)|0,Q+4096+(0-(c[X>>2]|0)<<2)|0,c[X>>2]|0,24,$);g[aa>>2]=1.0;g[ba>>2]=1.0;c[ca>>2]=c[X>>2]>>1;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[ca>>2]|0))break;g[da>>2]=+g[Q+(1024-(c[ca>>2]|0)+(c[m>>2]|0)<<2)>>2];g[aa>>2]=+g[aa>>2]+ +g[da>>2]*+g[da>>2];g[da>>2]=+g[Q+(1024-(c[ca>>2]<<1)+(c[m>>2]|0)<<2)>>2];g[ba>>2]=+g[ba>>2]+ +g[da>>2]*+g[da>>2];c[m>>2]=(c[m>>2]|0)+1}g[aa>>2]=+g[aa>>2]<+g[ba>>2]?+g[aa>>2]:+g[ba>>2];g[R>>2]=+O(+(+g[aa>>2]/+g[ba>>2]));ff(c[U>>2]|0,(c[U>>2]|0)+(c[j>>2]<<2)|0,(2048-(c[j>>2]|0)<<2)+0|0)|0;c[V>>2]=1024-(c[N>>2]|0);c[W>>2]=(c[j>>2]|0)+(c[x>>2]|0);g[S>>2]=+g[M>>2]*+g[R>>2];c[Y>>2]=0;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[W>>2]|0))break;if((c[Y>>2]|0)>=(c[N>>2]|0)){c[Y>>2]=(c[Y>>2]|0)-(c[N>>2]|0);g[S>>2]=+g[S>>2]*+g[R>>2]}g[(c[U>>2]|0)+(2048-(c[j>>2]|0)+(c[m>>2]|0)<<2)>>2]=+g[S>>2]*+g[Q+((c[V>>2]|0)+(c[Y>>2]|0)<<2)>>2];g[ea>>2]=+g[(c[U>>2]|0)+(1024-(c[j>>2]|0)+(c[V>>2]|0)+(c[Y>>2]|0)<<2)>>2];g[T>>2]=+g[T>>2]+ +g[ea>>2]*+g[ea>>2];c[m>>2]=(c[m>>2]|0)+1;c[Y>>2]=(c[Y>>2]|0)+1}c[m>>2]=0;while(1){if((c[m>>2]|0)>=24)break;g[fa+(c[m>>2]<<2)>>2]=+g[(c[U>>2]|0)+(2048-(c[j>>2]|0)-1-(c[m>>2]|0)<<2)>>2];c[m>>2]=(c[m>>2]|0)+1}Ab((c[U>>2]|0)+8192+(0-(c[j>>2]|0)<<2)|0,(c[q>>2]|0)+((c[l>>2]|0)*24<<2)|0,(c[U>>2]|0)+8192+(0-(c[j>>2]|0)<<2)|0,c[W>>2]|0,24,fa);g[ga>>2]=0.0;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[W>>2]|0))break;g[ha>>2]=+g[(c[U>>2]|0)+(2048-(c[j>>2]|0)+(c[m>>2]|0)<<2)>>2];g[ga>>2]=+g[ga>>2]+ +g[ha>>2]*+g[ha>>2];c[m>>2]=(c[m>>2]|0)+1}a:do if(+g[T>>2]>+g[ga>>2]*.20000000298023224){if(+g[T>>2]<+g[ga>>2]){g[ia>>2]=+O(+((+g[T>>2]+1.0)/(+g[ga>>2]+1.0)));c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[x>>2]|0))break;g[ja>>2]=1.0-+g[(c[L>>2]|0)+(c[m>>2]<<2)>>2]*(1.0-+g[ia>>2]);g[(c[U>>2]|0)+(2048-(c[j>>2]|0)+(c[m>>2]|0)<<2)>>2]=+g[ja>>2]*+g[(c[U>>2]|0)+(2048-(c[j>>2]|0)+(c[m>>2]|0)<<2)>>2];c[m>>2]=(c[m>>2]|0)+1}c[m>>2]=c[x>>2];while(1){if((c[m>>2]|0)>=(c[W>>2]|0))break a;g[(c[U>>2]|0)+(2048-(c[j>>2]|0)+(c[m>>2]|0)<<2)>>2]=+g[ia>>2]*+g[(c[U>>2]|0)+(2048-(c[j>>2]|0)+(c[m>>2]|0)<<2)>>2];c[m>>2]=(c[m>>2]|0)+1}}}else{c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[W>>2]|0))break a;g[(c[U>>2]|0)+(2048-(c[j>>2]|0)+(c[m>>2]|0)<<2)>>2]=0.0;c[m>>2]=(c[m>>2]|0)+1}}while(0);Xa(k,(c[U>>2]|0)+8192|0,c[(c[h>>2]|0)+52>>2]|0,c[(c[h>>2]|0)+52>>2]|0,c[x>>2]|0,-+g[(c[h>>2]|0)+60>>2],-+g[(c[h>>2]|0)+60>>2],c[(c[h>>2]|0)+68>>2]|0,c[(c[h>>2]|0)+68>>2]|0,0,0);c[m>>2]=0;while(1){if((c[m>>2]|0)>=((c[x>>2]|0)/2|0|0))break;g[(c[U>>2]|0)+(2048+(c[m>>2]|0)<<2)>>2]=+g[(c[L>>2]|0)+(c[m>>2]<<2)>>2]*+g[k+((c[x>>2]|0)-1-(c[m>>2]|0)<<2)>>2]+ +g[(c[L>>2]|0)+((c[x>>2]|0)-(c[m>>2]|0)-1<<2)>>2]*+g[k+(c[m>>2]<<2)>>2];c[m>>2]=(c[m>>2]|0)+1}v=(c[l>>2]|0)+1|0;c[l>>2]=v}while((v|0)<(c[n>>2]|0));ka(c[P>>2]|0);na=c[z>>2]|0;oa=na+1|0;pa=c[h>>2]|0;qa=pa+48|0;c[qa>>2]=oa;i=f;return}function Zc(a,b,d,e,f,h,j,k){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0.0;l=i;i=i+80|0;m=l+68|0;n=l+44|0;o=l+24|0;p=l+32|0;q=l+12|0;r=l+16|0;s=l+48|0;t=l+64|0;u=l+72|0;v=l+36|0;w=l+8|0;x=l;y=l+4|0;z=l+40|0;A=l+20|0;B=l+52|0;C=l+28|0;D=l+60|0;c[m>>2]=a;c[n>>2]=b;c[o>>2]=d;c[p>>2]=e;c[q>>2]=f;c[r>>2]=h;c[s>>2]=j;c[l+56>>2]=k;c[v>>2]=0;k=c[o>>2]|0;c[x>>2]=ua()|0;j=i;i=i+((1*(k<<2)|0)+15&-16)|0;g[w>>2]=+g[c[r>>2]>>2];c[u>>2]=(c[o>>2]|0)/(c[q>>2]|0)|0;c[t>>2]=0;do{g[B>>2]=+g[(c[s>>2]|0)+(c[t>>2]<<2)>>2];c[z>>2]=c[(c[m>>2]|0)+(c[t>>2]<<2)>>2];c[A>>2]=(c[n>>2]|0)+(c[t>>2]<<2);r=(c[q>>2]|0)>1;c[y>>2]=0;a:do if(r){while(1){if((c[y>>2]|0)>=(c[o>>2]|0))break;g[C>>2]=+g[(c[z>>2]|0)+(c[y>>2]<<2)>>2]+ +g[B>>2]+1.0000000031710769e-30;g[B>>2]=+g[w>>2]*+g[C>>2];g[j+(c[y>>2]<<2)>>2]=+g[C>>2];c[y>>2]=(c[y>>2]|0)+1}c[v>>2]=1}else while(1){if((c[y>>2]|0)>=(c[o>>2]|0))break a;g[D>>2]=+g[(c[z>>2]|0)+(c[y>>2]<<2)>>2]+ +g[B>>2]+1.0000000031710769e-30;g[B>>2]=+g[w>>2]*+g[D>>2];k=_(c[y>>2]|0,c[p>>2]|0)|0;g[(c[A>>2]|0)+(k<<2)>>2]=+g[D>>2]*.000030517578125;c[y>>2]=(c[y>>2]|0)+1}while(0);g[(c[s>>2]|0)+(c[t>>2]<<2)>>2]=+g[B>>2];b:do if(c[v>>2]|0){c[y>>2]=0;while(1){if((c[y>>2]|0)>=(c[u>>2]|0))break b;E=+g[j+((_(c[y>>2]|0,c[q>>2]|0)|0)<<2)>>2]*.000030517578125;r=_(c[y>>2]|0,c[p>>2]|0)|0;g[(c[A>>2]|0)+(r<<2)>>2]=E;c[y>>2]=(c[y>>2]|0)+1}}while(0);r=(c[t>>2]|0)+1|0;c[t>>2]=r}while((r|0)<(c[p>>2]|0));ka(c[x>>2]|0);i=l;return}function _c(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;a=(c[(c[d>>2]|0)+20>>2]|0)-(32-(aa(c[(c[d>>2]|0)+28>>2]|0)|0))|0;i=b;return a|0}function $c(b,d,e,f,g,h){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;j=i;i=i+64|0;k=j+24|0;l=j+20|0;m=j+44|0;n=j+36|0;o=j+32|0;p=j+40|0;q=j+48|0;r=j+52|0;s=j+8|0;t=j+4|0;u=j+28|0;v=j+12|0;w=j;x=j+16|0;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[n>>2]=f;c[o>>2]=g;c[p>>2]=h;c[w>>2]=c[(c[p>>2]|0)+4>>2]<<3;c[x>>2]=_c(c[p>>2]|0)|0;c[v>>2]=(c[m>>2]|0)!=0?2:4;if((c[o>>2]|0)>0)y=((c[x>>2]|0)+(c[v>>2]|0)+1|0)>>>0<=(c[w>>2]|0)>>>0;else y=0;c[t>>2]=y&1;c[w>>2]=(c[w>>2]|0)-(c[t>>2]|0);c[r>>2]=0;c[u>>2]=0;c[q>>2]=c[k>>2];while(1){if((c[q>>2]|0)>=(c[l>>2]|0))break;if(((c[x>>2]|0)+(c[v>>2]|0)|0)>>>0<=(c[w>>2]|0)>>>0){y=ib(c[p>>2]|0,c[v>>2]|0)|0;c[r>>2]=c[r>>2]^y;c[x>>2]=_c(c[p>>2]|0)|0;c[u>>2]=c[u>>2]|c[r>>2]}c[(c[n>>2]|0)+(c[q>>2]<<2)>>2]=c[r>>2];c[v>>2]=(c[m>>2]|0)!=0?4:5;c[q>>2]=(c[q>>2]|0)+1}c[s>>2]=0;if((c[t>>2]|0)!=0?(a[8+(c[o>>2]<<3)+((c[m>>2]<<2)+0+(c[u>>2]|0))>>0]|0)!=(a[8+(c[o>>2]<<3)+((c[m>>2]<<2)+2+(c[u>>2]|0))>>0]|0):0)c[s>>2]=ib(c[p>>2]|0,1)|0;c[q>>2]=c[k>>2];while(1){if((c[q>>2]|0)>=(c[l>>2]|0))break;c[(c[n>>2]|0)+(c[q>>2]<<2)>>2]=a[8+(c[o>>2]<<3)+((c[m>>2]<<2)+(c[s>>2]<<1)+(c[(c[n>>2]|0)+(c[q>>2]<<2)>>2]|0))>>0];c[q>>2]=(c[q>>2]|0)+1}i=j;return}function ad(a,b,d,e,f,h,j,k,l,m,n,o){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;var p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0;p=i;i=i+112|0;q=p+92|0;r=p+84|0;s=p+40|0;t=p+44|0;u=p;v=p+16|0;w=p+20|0;x=p+24|0;y=p+28|0;z=p+72|0;A=p+80|0;B=p+88|0;C=p+96|0;D=p+48|0;E=p+52|0;F=p+56|0;G=p+60|0;H=p+8|0;I=p+64|0;J=p+12|0;K=p+32|0;L=p+68|0;M=p+36|0;N=p+76|0;O=p+4|0;c[q>>2]=a;c[r>>2]=b;c[s>>2]=d;c[t>>2]=e;c[u>>2]=f;c[v>>2]=h;c[w>>2]=j;c[x>>2]=k;c[y>>2]=l;c[z>>2]=m;c[A>>2]=n;c[B>>2]=o;c[L>>2]=c[(c[q>>2]|0)+4>>2];c[K>>2]=c[(c[q>>2]|0)+8>>2];c[H>>2]=c[(c[q>>2]|0)+44>>2]<<c[z>>2];o=c[H>>2]|0;c[M>>2]=ua()|0;n=i;i=i+((1*(o<<2)|0)+15&-16)|0;c[E>>2]=1<<c[z>>2];if(c[y>>2]|0){c[G>>2]=c[E>>2];c[I>>2]=c[(c[q>>2]|0)+44>>2];c[J>>2]=c[(c[q>>2]|0)+36>>2]}else{c[G>>2]=1;c[I>>2]=c[(c[q>>2]|0)+44>>2]<<c[z>>2];c[J>>2]=(c[(c[q>>2]|0)+36>>2]|0)-(c[z>>2]|0)}if((c[x>>2]|0)==2&(c[w>>2]|0)==1){Sa(c[q>>2]|0,c[r>>2]|0,n,c[t>>2]|0,c[u>>2]|0,c[v>>2]|0,c[E>>2]|0,c[A>>2]|0,c[B>>2]|0);c[N>>2]=(c[(c[s>>2]|0)+4>>2]|0)+(((c[L>>2]|0)/2|0)<<2);df(c[N>>2]|0,n|0,(c[H>>2]<<2)+0|0)|0;c[F>>2]=0;while(1){if((c[F>>2]|0)>=(c[G>>2]|0))break;z=(c[c[s>>2]>>2]|0)+((_(c[I>>2]|0,c[F>>2]|0)|0)<<2)|0;tb((c[q>>2]|0)+64|0,(c[N>>2]|0)+(c[F>>2]<<2)|0,z,c[(c[q>>2]|0)+60>>2]|0,c[L>>2]|0,c[J>>2]|0,c[G>>2]|0);c[F>>2]=(c[F>>2]|0)+1}c[F>>2]=0;while(1){if((c[F>>2]|0)>=(c[G>>2]|0))break;N=(c[(c[s>>2]|0)+4>>2]|0)+((_(c[I>>2]|0,c[F>>2]|0)|0)<<2)|0;tb((c[q>>2]|0)+64|0,n+(c[F>>2]<<2)|0,N,c[(c[q>>2]|0)+60>>2]|0,c[L>>2]|0,c[J>>2]|0,c[G>>2]|0);c[F>>2]=(c[F>>2]|0)+1}P=c[M>>2]|0;ka(P|0);i=p;return}if(!((c[x>>2]|0)==1&(c[w>>2]|0)==2)){c[C>>2]=0;do{w=(c[r>>2]|0)+((_(c[C>>2]|0,c[H>>2]|0)|0)<<2)|0;N=(c[t>>2]|0)+((_(c[C>>2]|0,c[K>>2]|0)|0)<<2)|0;Sa(c[q>>2]|0,w,n,N,c[u>>2]|0,c[v>>2]|0,c[E>>2]|0,c[A>>2]|0,c[B>>2]|0);c[F>>2]=0;while(1){if((c[F>>2]|0)>=(c[G>>2]|0))break;N=(c[(c[s>>2]|0)+(c[C>>2]<<2)>>2]|0)+((_(c[I>>2]|0,c[F>>2]|0)|0)<<2)|0;tb((c[q>>2]|0)+64|0,n+(c[F>>2]<<2)|0,N,c[(c[q>>2]|0)+60>>2]|0,c[L>>2]|0,c[J>>2]|0,c[G>>2]|0);c[F>>2]=(c[F>>2]|0)+1}N=(c[C>>2]|0)+1|0;c[C>>2]=N}while((N|0)<(c[x>>2]|0));P=c[M>>2]|0;ka(P|0);i=p;return}c[O>>2]=(c[c[s>>2]>>2]|0)+(((c[L>>2]|0)/2|0)<<2);Sa(c[q>>2]|0,c[r>>2]|0,n,c[t>>2]|0,c[u>>2]|0,c[v>>2]|0,c[E>>2]|0,c[A>>2]|0,c[B>>2]|0);Sa(c[q>>2]|0,(c[r>>2]|0)+(c[H>>2]<<2)|0,c[O>>2]|0,(c[t>>2]|0)+(c[K>>2]<<2)|0,c[u>>2]|0,c[v>>2]|0,c[E>>2]|0,c[A>>2]|0,c[B>>2]|0);c[D>>2]=0;while(1){if((c[D>>2]|0)>=(c[H>>2]|0))break;g[n+(c[D>>2]<<2)>>2]=(+g[n+(c[D>>2]<<2)>>2]+ +g[(c[O>>2]|0)+(c[D>>2]<<2)>>2])*.5;c[D>>2]=(c[D>>2]|0)+1}c[F>>2]=0;while(1){if((c[F>>2]|0)>=(c[G>>2]|0))break;D=(c[c[s>>2]>>2]|0)+((_(c[I>>2]|0,c[F>>2]|0)|0)<<2)|0;tb((c[q>>2]|0)+64|0,n+(c[F>>2]<<2)|0,D,c[(c[q>>2]|0)+60>>2]|0,c[L>>2]|0,c[J>>2]|0,c[G>>2]|0);c[F>>2]=(c[F>>2]|0)+1}P=c[M>>2]|0;ka(P|0);i=p;return}function bd(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;i=b;return c[(c[d>>2]|0)+44>>2]|0}function cd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;d=i;i=i+32|0;e=d+16|0;f=d+12|0;g=d+8|0;h=d+4|0;j=d;c[e>>2]=a;c[f>>2]=b;c[h>>2]=(c[e>>2]|0)-1;c[g>>2]=(c[(c[f>>2]|0)+(c[h>>2]<<2)>>2]|0)<0&1;c[j>>2]=N(c[(c[f>>2]|0)+(c[h>>2]<<2)>>2]|0)|0;do{c[h>>2]=(c[h>>2]|0)+-1;if(((c[e>>2]|0)-(c[h>>2]|0)|0)>(c[j>>2]|0))k=(c[e>>2]|0)-(c[h>>2]|0)|0;else k=c[j>>2]|0;if(((c[e>>2]|0)-(c[h>>2]|0)|0)<(c[j>>2]|0))l=(c[e>>2]|0)-(c[h>>2]|0)|0;else l=c[j>>2]|0;c[g>>2]=(c[g>>2]|0)+(c[(c[2448+(l<<2)>>2]|0)+(k<<2)>>2]|0);b=N(c[(c[f>>2]|0)+(c[h>>2]<<2)>>2]|0)|0;c[j>>2]=(c[j>>2]|0)+b;if((c[(c[f>>2]|0)+(c[h>>2]<<2)>>2]|0)<0){if(((c[e>>2]|0)-(c[h>>2]|0)|0)>((c[j>>2]|0)+1|0))m=(c[e>>2]|0)-(c[h>>2]|0)|0;else m=(c[j>>2]|0)+1|0;if(((c[e>>2]|0)-(c[h>>2]|0)|0)<((c[j>>2]|0)+1|0))n=(c[e>>2]|0)-(c[h>>2]|0)|0;else n=(c[j>>2]|0)+1|0;c[g>>2]=(c[g>>2]|0)+(c[(c[2448+(n<<2)>>2]|0)+(m<<2)>>2]|0)}}while((c[h>>2]|0)>0);i=d;return c[g>>2]|0}function dd(a,d,e,f){a=a|0;d=d|0;e=e|0;f=f|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0.0,I=0,J=0.0,K=0,L=0.0,M=0.0,N=0.0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0.0,_=0,$=0.0,aa=0,ba=0.0,ca=0.0,da=0.0,ea=0.0;h=i;i=i+48|0;j=h;k=h+16|0;l=h+4|0;m=h+8|0;n=h+32|0;o=h+36|0;p=h+12|0;q=h+40|0;r=h+20|0;s=h+28|0;t=h+24|0;c[j>>2]=a;c[k>>2]=d;c[l>>2]=e;c[m>>2]=f;g[r>>2]=0.0;while(1){u=c[k>>2]|0;if((c[j>>2]|0)<=2)break;f=c[j>>2]|0;do if((u|0)>=(c[j>>2]|0)){c[t>>2]=c[2448+(f<<2)>>2];c[n>>2]=c[(c[t>>2]|0)+((c[k>>2]|0)+1<<2)>>2];c[o>>2]=0-((c[l>>2]|0)>>>0>=(c[n>>2]|0)>>>0&1);c[l>>2]=(c[l>>2]|0)-(c[n>>2]&c[o>>2]);c[p>>2]=c[k>>2];c[s>>2]=c[(c[t>>2]|0)+(c[j>>2]<<2)>>2];a:do if((c[s>>2]|0)>>>0>(c[l>>2]|0)>>>0){c[k>>2]=c[j>>2];do{e=c[j>>2]|0;d=(c[k>>2]|0)+-1|0;c[k>>2]=d;c[n>>2]=c[(c[2448+(d<<2)>>2]|0)+(e<<2)>>2]}while((c[n>>2]|0)>>>0>(c[l>>2]|0)>>>0)}else{c[n>>2]=c[(c[t>>2]|0)+(c[k>>2]<<2)>>2];while(1){if((c[n>>2]|0)>>>0<=(c[l>>2]|0)>>>0)break a;c[k>>2]=(c[k>>2]|0)+-1;c[n>>2]=c[(c[t>>2]|0)+(c[k>>2]<<2)>>2]}}while(0);c[l>>2]=(c[l>>2]|0)-(c[n>>2]|0);b[q>>1]=(c[p>>2]|0)-(c[k>>2]|0)+(c[o>>2]|0)^c[o>>2];e=b[q>>1]|0;d=c[m>>2]|0;c[m>>2]=d+4;c[d>>2]=e;g[r>>2]=+g[r>>2]+ +(b[q>>1]|0)*+(b[q>>1]|0)}else{c[n>>2]=c[(c[2448+(c[k>>2]<<2)>>2]|0)+(f<<2)>>2];c[s>>2]=c[(c[2448+((c[k>>2]|0)+1<<2)>>2]|0)+(c[j>>2]<<2)>>2];if((c[n>>2]|0)>>>0<=(c[l>>2]|0)>>>0?(c[l>>2]|0)>>>0<(c[s>>2]|0)>>>0:0){c[l>>2]=(c[l>>2]|0)-(c[n>>2]|0);e=c[m>>2]|0;c[m>>2]=e+4;c[e>>2]=0;break}c[o>>2]=0-((c[l>>2]|0)>>>0>=(c[s>>2]|0)>>>0&1);c[l>>2]=(c[l>>2]|0)-(c[s>>2]&c[o>>2]);c[p>>2]=c[k>>2];do{e=c[j>>2]|0;d=(c[k>>2]|0)+-1|0;c[k>>2]=d;c[n>>2]=c[(c[2448+(d<<2)>>2]|0)+(e<<2)>>2]}while((c[n>>2]|0)>>>0>(c[l>>2]|0)>>>0);c[l>>2]=(c[l>>2]|0)-(c[n>>2]|0);b[q>>1]=(c[p>>2]|0)-(c[k>>2]|0)+(c[o>>2]|0)^c[o>>2];e=b[q>>1]|0;d=c[m>>2]|0;c[m>>2]=d+4;c[d>>2]=e;g[r>>2]=+g[r>>2]+ +(b[q>>1]|0)*+(b[q>>1]|0)}while(0);c[j>>2]=(c[j>>2]|0)+-1}c[n>>2]=(u<<1)+1;c[o>>2]=0-((c[l>>2]|0)>>>0>=(c[n>>2]|0)>>>0&1);c[l>>2]=(c[l>>2]|0)-(c[n>>2]&c[o>>2]);c[p>>2]=c[k>>2];c[k>>2]=((c[l>>2]|0)+1|0)>>>1;if(!(c[k>>2]|0)){v=c[p>>2]|0;w=c[k>>2]|0;x=v-w|0;y=c[o>>2]|0;z=x+y|0;A=c[o>>2]|0;B=z^A;C=B&65535;b[q>>1]=C;D=b[q>>1]|0;E=D<<16>>16;F=c[m>>2]|0;G=F+4|0;c[m>>2]=G;c[F>>2]=E;H=+g[r>>2];I=b[q>>1]|0;J=+(I<<16>>16);K=b[q>>1]|0;L=+(K<<16>>16);M=J*L;N=H+M;g[r>>2]=N;O=c[l>>2]|0;P=0-O|0;c[o>>2]=P;Q=c[k>>2]|0;R=c[o>>2]|0;S=Q+R|0;T=c[o>>2]|0;U=S^T;V=U&65535;b[q>>1]=V;W=b[q>>1]|0;X=W<<16>>16;Y=c[m>>2]|0;c[Y>>2]=X;Z=+g[r>>2];_=b[q>>1]|0;$=+(_<<16>>16);aa=b[q>>1]|0;ba=+(aa<<16>>16);ca=$*ba;da=Z+ca;g[r>>2]=da;ea=+g[r>>2];i=h;return +ea}c[l>>2]=(c[l>>2]|0)-((c[k>>2]<<1)-1);v=c[p>>2]|0;w=c[k>>2]|0;x=v-w|0;y=c[o>>2]|0;z=x+y|0;A=c[o>>2]|0;B=z^A;C=B&65535;b[q>>1]=C;D=b[q>>1]|0;E=D<<16>>16;F=c[m>>2]|0;G=F+4|0;c[m>>2]=G;c[F>>2]=E;H=+g[r>>2];I=b[q>>1]|0;J=+(I<<16>>16);K=b[q>>1]|0;L=+(K<<16>>16);M=J*L;N=H+M;g[r>>2]=N;O=c[l>>2]|0;P=0-O|0;c[o>>2]=P;Q=c[k>>2]|0;R=c[o>>2]|0;S=Q+R|0;T=c[o>>2]|0;U=S^T;V=U&65535;b[q>>1]=V;W=b[q>>1]|0;X=W<<16>>16;Y=c[m>>2]|0;c[Y>>2]=X;Z=+g[r>>2];_=b[q>>1]|0;$=+(_<<16>>16);aa=b[q>>1]|0;ba=+(aa<<16>>16);ca=$*ba;da=Z+ca;g[r>>2]=da;ea=+g[r>>2];i=h;return +ea}function ed(a){a=a|0;var b=0,e=0,f=0,g=0;b=i;i=i+16|0;e=b;c[e>>2]=a;if((c[(c[e>>2]|0)+24>>2]|0)>>>0>=(c[(c[e>>2]|0)+4>>2]|0)>>>0){f=0;i=b;return f|0}a=(c[e>>2]|0)+24|0;g=c[a>>2]|0;c[a>>2]=g+1;f=d[(c[c[e>>2]>>2]|0)+g>>0]|0;i=b;return f|0}function fd(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b+4|0;e=b;c[d>>2]=a;while(1){if((c[(c[d>>2]|0)+28>>2]|0)>>>0>8388608)break;a=(c[d>>2]|0)+20|0;c[a>>2]=(c[a>>2]|0)+8;a=(c[d>>2]|0)+28|0;c[a>>2]=c[a>>2]<<8;c[e>>2]=c[(c[d>>2]|0)+40>>2];a=ed(c[d>>2]|0)|0;c[(c[d>>2]|0)+40>>2]=a;c[e>>2]=(c[e>>2]<<8|c[(c[d>>2]|0)+40>>2])>>1;c[(c[d>>2]|0)+32>>2]=(c[(c[d>>2]|0)+32>>2]<<8)+(255&~c[e>>2])&2147483647}i=b;return}function gd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)>>>0)/((c[f>>2]|0)>>>0)|0|0}function hd(a){a=a|0;var b=0,e=0,f=0,g=0,h=0;b=i;i=i+16|0;e=b;c[e>>2]=a;if((c[(c[e>>2]|0)+8>>2]|0)>>>0>=(c[(c[e>>2]|0)+4>>2]|0)>>>0){f=0;i=b;return f|0}a=c[(c[e>>2]|0)+4>>2]|0;g=(c[e>>2]|0)+8|0;h=(c[g>>2]|0)+1|0;c[g>>2]=h;f=d[(c[c[e>>2]>>2]|0)+(a-h)>>0]|0;i=b;return f|0}function id(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)>>>0)/((c[f>>2]|0)>>>0)|0|0}function jd(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;while(1){if((c[(c[d>>2]|0)+28>>2]|0)>>>0>8388608)break;ld(c[d>>2]|0,(c[(c[d>>2]|0)+32>>2]|0)>>>23);c[(c[d>>2]|0)+32>>2]=c[(c[d>>2]|0)+32>>2]<<8&2147483647;a=(c[d>>2]|0)+28|0;c[a>>2]=c[a>>2]<<8;a=(c[d>>2]|0)+20|0;c[a>>2]=(c[a>>2]|0)+8}i=b;return}function kd(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;i=i+16|0;f=e+8|0;g=e+4|0;h=e;c[g>>2]=b;c[h>>2]=d;if(((c[(c[g>>2]|0)+24>>2]|0)+(c[(c[g>>2]|0)+8>>2]|0)|0)>>>0>=(c[(c[g>>2]|0)+4>>2]|0)>>>0){c[f>>2]=-1;j=c[f>>2]|0;i=e;return j|0}else{d=c[h>>2]&255;h=c[(c[g>>2]|0)+4>>2]|0;b=(c[g>>2]|0)+8|0;k=(c[b>>2]|0)+1|0;c[b>>2]=k;a[(c[c[g>>2]>>2]|0)+(h-k)>>0]=d;c[f>>2]=0;j=c[f>>2]|0;i=e;return j|0}return 0}function ld(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[e>>2]=a;c[f>>2]=b;if((c[f>>2]|0)==255){b=(c[e>>2]|0)+36|0;c[b>>2]=(c[b>>2]|0)+1;i=d;return}c[g>>2]=c[f>>2]>>8;if((c[(c[e>>2]|0)+40>>2]|0)>=0){b=ze(c[e>>2]|0,(c[(c[e>>2]|0)+40>>2]|0)+(c[g>>2]|0)|0)|0;a=(c[e>>2]|0)+44|0;c[a>>2]=c[a>>2]|b}if((c[(c[e>>2]|0)+36>>2]|0)>>>0>0){c[h>>2]=255+(c[g>>2]|0)&255;do{g=ze(c[e>>2]|0,c[h>>2]|0)|0;b=(c[e>>2]|0)+44|0;c[b>>2]=c[b>>2]|g;g=(c[e>>2]|0)+36|0;b=(c[g>>2]|0)+-1|0;c[g>>2]=b}while(b>>>0>0)}c[(c[e>>2]|0)+40>>2]=c[f>>2]&255;i=d;return}function md(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,h=0,j=0,k=0,l=0,m=0;e=i;i=i+48|0;f=e+8|0;h=e+28|0;j=e+32|0;k=e+4|0;l=e;m=e+16|0;c[f>>2]=a;c[e+24>>2]=b;c[h>>2]=d;g[l>>2]=.7071067690849304;c[k>>2]=0;while(1){if((c[k>>2]|0)>=(c[h>>2]|0))break;c[j>>2]=(c[f>>2]|0)+32;d=c[j>>2]|0;c[m>>2]=c[d>>2];c[m+4>>2]=c[d+4>>2];g[c[j>>2]>>2]=+g[c[f>>2]>>2]-+g[m>>2];g[(c[j>>2]|0)+4>>2]=+g[(c[f>>2]|0)+4>>2]-+g[m+4>>2];d=c[f>>2]|0;g[d>>2]=+g[d>>2]+ +g[m>>2];d=(c[f>>2]|0)+4|0;g[d>>2]=+g[d>>2]+ +g[m+4>>2];g[m>>2]=(+g[(c[j>>2]|0)+8>>2]+ +g[(c[j>>2]|0)+8+4>>2])*+g[l>>2];g[m+4>>2]=(+g[(c[j>>2]|0)+8+4>>2]-+g[(c[j>>2]|0)+8>>2])*+g[l>>2];g[(c[j>>2]|0)+8>>2]=+g[(c[f>>2]|0)+8>>2]-+g[m>>2];g[(c[j>>2]|0)+8+4>>2]=+g[(c[f>>2]|0)+8+4>>2]-+g[m+4>>2];d=(c[f>>2]|0)+8|0;g[d>>2]=+g[d>>2]+ +g[m>>2];d=(c[f>>2]|0)+8+4|0;g[d>>2]=+g[d>>2]+ +g[m+4>>2];g[m>>2]=+g[(c[j>>2]|0)+16+4>>2];g[m+4>>2]=-+g[(c[j>>2]|0)+16>>2];g[(c[j>>2]|0)+16>>2]=+g[(c[f>>2]|0)+16>>2]-+g[m>>2];g[(c[j>>2]|0)+16+4>>2]=+g[(c[f>>2]|0)+16+4>>2]-+g[m+4>>2];d=(c[f>>2]|0)+16|0;g[d>>2]=+g[d>>2]+ +g[m>>2];d=(c[f>>2]|0)+16+4|0;g[d>>2]=+g[d>>2]+ +g[m+4>>2];g[m>>2]=(+g[(c[j>>2]|0)+24+4>>2]-+g[(c[j>>2]|0)+24>>2])*+g[l>>2];g[m+4>>2]=(-+g[(c[j>>2]|0)+24+4>>2]-+g[(c[j>>2]|0)+24>>2])*+g[l>>2];g[(c[j>>2]|0)+24>>2]=+g[(c[f>>2]|0)+24>>2]-+g[m>>2];g[(c[j>>2]|0)+24+4>>2]=+g[(c[f>>2]|0)+24+4>>2]-+g[m+4>>2];d=(c[f>>2]|0)+24|0;g[d>>2]=+g[d>>2]+ +g[m>>2];d=(c[f>>2]|0)+24+4|0;g[d>>2]=+g[d>>2]+ +g[m+4>>2];c[f>>2]=(c[f>>2]|0)+64;c[k>>2]=(c[k>>2]|0)+1}i=e;return}function nd(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;j=i;i=i+128|0;k=j+112|0;l=j+88|0;m=j+64|0;n=j+60|0;o=j+48|0;p=j+84|0;q=j+92|0;r=j+104|0;s=j+120|0;t=j+68|0;u=j;v=j+76|0;w=j+72|0;x=j+52|0;y=j+80|0;z=j+56|0;A=j+96|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=d;c[n>>2]=e;c[o>>2]=f;c[p>>2]=h;if((c[n>>2]|0)==1){c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[o>>2]|0))break;g[r>>2]=+g[c[k>>2]>>2]-+g[(c[k>>2]|0)+16>>2];g[r+4>>2]=+g[(c[k>>2]|0)+4>>2]-+g[(c[k>>2]|0)+16+4>>2];h=c[k>>2]|0;g[h>>2]=+g[h>>2]+ +g[(c[k>>2]|0)+16>>2];h=(c[k>>2]|0)+4|0;g[h>>2]=+g[h>>2]+ +g[(c[k>>2]|0)+16+4>>2];g[s>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[(c[k>>2]|0)+24>>2];g[s+4>>2]=+g[(c[k>>2]|0)+8+4>>2]+ +g[(c[k>>2]|0)+24+4>>2];g[(c[k>>2]|0)+16>>2]=+g[c[k>>2]>>2]-+g[s>>2];g[(c[k>>2]|0)+16+4>>2]=+g[(c[k>>2]|0)+4>>2]-+g[s+4>>2];h=c[k>>2]|0;g[h>>2]=+g[h>>2]+ +g[s>>2];h=(c[k>>2]|0)+4|0;g[h>>2]=+g[h>>2]+ +g[s+4>>2];g[s>>2]=+g[(c[k>>2]|0)+8>>2]-+g[(c[k>>2]|0)+24>>2];g[s+4>>2]=+g[(c[k>>2]|0)+8+4>>2]-+g[(c[k>>2]|0)+24+4>>2];g[(c[k>>2]|0)+8>>2]=+g[r>>2]+ +g[s+4>>2];g[(c[k>>2]|0)+8+4>>2]=+g[r+4>>2]-+g[s>>2];g[(c[k>>2]|0)+24>>2]=+g[r>>2]-+g[s+4>>2];g[(c[k>>2]|0)+24+4>>2]=+g[r+4>>2]+ +g[s>>2];c[k>>2]=(c[k>>2]|0)+32;c[q>>2]=(c[q>>2]|0)+1}i=j;return}c[y>>2]=c[n>>2]<<1;c[z>>2]=(c[n>>2]|0)*3;c[A>>2]=c[k>>2];c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[o>>2]|0))break;c[k>>2]=(c[A>>2]|0)+((_(c[q>>2]|0,c[p>>2]|0)|0)<<3);s=c[(c[m>>2]|0)+48>>2]|0;c[v>>2]=s;c[w>>2]=s;c[x>>2]=s;c[t>>2]=0;while(1){if((c[t>>2]|0)>=(c[n>>2]|0))break;g[u>>2]=+g[(c[k>>2]|0)+(c[n>>2]<<3)>>2]*+g[c[v>>2]>>2]-+g[(c[k>>2]|0)+(c[n>>2]<<3)+4>>2]*+g[(c[v>>2]|0)+4>>2];g[u+4>>2]=+g[(c[k>>2]|0)+(c[n>>2]<<3)>>2]*+g[(c[v>>2]|0)+4>>2]+ +g[(c[k>>2]|0)+(c[n>>2]<<3)+4>>2]*+g[c[v>>2]>>2];g[u+8>>2]=+g[(c[k>>2]|0)+(c[y>>2]<<3)>>2]*+g[c[w>>2]>>2]-+g[(c[k>>2]|0)+(c[y>>2]<<3)+4>>2]*+g[(c[w>>2]|0)+4>>2];g[u+8+4>>2]=+g[(c[k>>2]|0)+(c[y>>2]<<3)>>2]*+g[(c[w>>2]|0)+4>>2]+ +g[(c[k>>2]|0)+(c[y>>2]<<3)+4>>2]*+g[c[w>>2]>>2];g[u+16>>2]=+g[(c[k>>2]|0)+(c[z>>2]<<3)>>2]*+g[c[x>>2]>>2]-+g[(c[k>>2]|0)+(c[z>>2]<<3)+4>>2]*+g[(c[x>>2]|0)+4>>2];g[u+16+4>>2]=+g[(c[k>>2]|0)+(c[z>>2]<<3)>>2]*+g[(c[x>>2]|0)+4>>2]+ +g[(c[k>>2]|0)+(c[z>>2]<<3)+4>>2]*+g[c[x>>2]>>2];g[u+40>>2]=+g[c[k>>2]>>2]-+g[u+8>>2];g[u+40+4>>2]=+g[(c[k>>2]|0)+4>>2]-+g[u+8+4>>2];s=c[k>>2]|0;g[s>>2]=+g[s>>2]+ +g[u+8>>2];s=(c[k>>2]|0)+4|0;g[s>>2]=+g[s>>2]+ +g[u+8+4>>2];g[u+24>>2]=+g[u>>2]+ +g[u+16>>2];g[u+24+4>>2]=+g[u+4>>2]+ +g[u+16+4>>2];g[u+32>>2]=+g[u>>2]-+g[u+16>>2];g[u+32+4>>2]=+g[u+4>>2]-+g[u+16+4>>2];g[(c[k>>2]|0)+(c[y>>2]<<3)>>2]=+g[c[k>>2]>>2]-+g[u+24>>2];g[(c[k>>2]|0)+(c[y>>2]<<3)+4>>2]=+g[(c[k>>2]|0)+4>>2]-+g[u+24+4>>2];c[v>>2]=(c[v>>2]|0)+(c[l>>2]<<3);c[w>>2]=(c[w>>2]|0)+(c[l>>2]<<1<<3);c[x>>2]=(c[x>>2]|0)+((c[l>>2]|0)*3<<3);s=c[k>>2]|0;g[s>>2]=+g[s>>2]+ +g[u+24>>2];s=(c[k>>2]|0)+4|0;g[s>>2]=+g[s>>2]+ +g[u+24+4>>2];g[(c[k>>2]|0)+(c[n>>2]<<3)>>2]=+g[u+40>>2]+ +g[u+32+4>>2];g[(c[k>>2]|0)+(c[n>>2]<<3)+4>>2]=+g[u+40+4>>2]-+g[u+32>>2];g[(c[k>>2]|0)+(c[z>>2]<<3)>>2]=+g[u+40>>2]-+g[u+32+4>>2];g[(c[k>>2]|0)+(c[z>>2]<<3)+4>>2]=+g[u+40+4>>2]+ +g[u+32>>2];c[k>>2]=(c[k>>2]|0)+8;c[t>>2]=(c[t>>2]|0)+1}c[q>>2]=(c[q>>2]|0)+1}i=j;return}function od(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;j=i;i=i+112|0;k=j+56|0;l=j+52|0;m=j+88|0;n=j+80|0;o=j+76|0;p=j+84|0;q=j+92|0;r=j+96|0;s=j+60|0;t=j;u=j+72|0;v=j+8|0;w=j+64|0;x=j+48|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=d;c[n>>2]=e;c[o>>2]=f;c[p>>2]=h;c[s>>2]=c[n>>2]<<1;c[x>>2]=c[k>>2];h=_(c[l>>2]|0,c[n>>2]|0)|0;f=(c[(c[m>>2]|0)+48>>2]|0)+(h<<3)|0;c[w>>2]=c[f>>2];c[w+4>>2]=c[f+4>>2];c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[o>>2]|0))break;c[k>>2]=(c[x>>2]|0)+((_(c[q>>2]|0,c[p>>2]|0)|0)<<3);f=c[(c[m>>2]|0)+48>>2]|0;c[u>>2]=f;c[t>>2]=f;c[r>>2]=c[n>>2];do{g[v+8>>2]=+g[(c[k>>2]|0)+(c[n>>2]<<3)>>2]*+g[c[t>>2]>>2]-+g[(c[k>>2]|0)+(c[n>>2]<<3)+4>>2]*+g[(c[t>>2]|0)+4>>2];g[v+8+4>>2]=+g[(c[k>>2]|0)+(c[n>>2]<<3)>>2]*+g[(c[t>>2]|0)+4>>2]+ +g[(c[k>>2]|0)+(c[n>>2]<<3)+4>>2]*+g[c[t>>2]>>2];g[v+16>>2]=+g[(c[k>>2]|0)+(c[s>>2]<<3)>>2]*+g[c[u>>2]>>2]-+g[(c[k>>2]|0)+(c[s>>2]<<3)+4>>2]*+g[(c[u>>2]|0)+4>>2];g[v+16+4>>2]=+g[(c[k>>2]|0)+(c[s>>2]<<3)>>2]*+g[(c[u>>2]|0)+4>>2]+ +g[(c[k>>2]|0)+(c[s>>2]<<3)+4>>2]*+g[c[u>>2]>>2];g[v+24>>2]=+g[v+8>>2]+ +g[v+16>>2];g[v+24+4>>2]=+g[v+8+4>>2]+ +g[v+16+4>>2];g[v>>2]=+g[v+8>>2]-+g[v+16>>2];g[v+4>>2]=+g[v+8+4>>2]-+g[v+16+4>>2];c[t>>2]=(c[t>>2]|0)+(c[l>>2]<<3);c[u>>2]=(c[u>>2]|0)+(c[l>>2]<<1<<3);g[(c[k>>2]|0)+(c[n>>2]<<3)>>2]=+g[c[k>>2]>>2]-+g[v+24>>2]*.5;g[(c[k>>2]|0)+(c[n>>2]<<3)+4>>2]=+g[(c[k>>2]|0)+4>>2]-+g[v+24+4>>2]*.5;g[v>>2]=+g[v>>2]*+g[w+4>>2];f=v+4|0;g[f>>2]=+g[f>>2]*+g[w+4>>2];f=c[k>>2]|0;g[f>>2]=+g[f>>2]+ +g[v+24>>2];f=(c[k>>2]|0)+4|0;g[f>>2]=+g[f>>2]+ +g[v+24+4>>2];g[(c[k>>2]|0)+(c[s>>2]<<3)>>2]=+g[(c[k>>2]|0)+(c[n>>2]<<3)>>2]+ +g[v+4>>2];g[(c[k>>2]|0)+(c[s>>2]<<3)+4>>2]=+g[(c[k>>2]|0)+(c[n>>2]<<3)+4>>2]-+g[v>>2];f=(c[k>>2]|0)+(c[n>>2]<<3)|0;g[f>>2]=+g[f>>2]-+g[v+4>>2];f=(c[k>>2]|0)+(c[n>>2]<<3)+4|0;g[f>>2]=+g[f>>2]+ +g[v>>2];c[k>>2]=(c[k>>2]|0)+8;f=(c[r>>2]|0)+-1|0;c[r>>2]=f}while((f|0)!=0);c[q>>2]=(c[q>>2]|0)+1}i=j;return}function pd(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;j=i;i=i+192|0;k=j+28|0;l=j+32|0;m=j+156|0;n=j+180|0;o=j+4|0;p=j+152|0;q=j+160|0;r=j+176|0;s=j+184|0;t=j+188|0;u=j+36|0;v=j;w=j+40|0;x=j+48|0;y=j+8|0;z=j+16|0;A=j+168|0;B=j+24|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=d;c[n>>2]=e;c[o>>2]=f;c[p>>2]=h;c[B>>2]=c[k>>2];h=_(c[l>>2]|0,c[n>>2]|0)|0;f=(c[(c[m>>2]|0)+48>>2]|0)+(h<<3)|0;c[z>>2]=c[f>>2];c[z+4>>2]=c[f+4>>2];f=_(c[l>>2]<<1,c[n>>2]|0)|0;h=(c[(c[m>>2]|0)+48>>2]|0)+(f<<3)|0;c[A>>2]=c[h>>2];c[A+4>>2]=c[h+4>>2];c[y>>2]=c[(c[m>>2]|0)+48>>2];c[v>>2]=0;while(1){if((c[v>>2]|0)>=(c[o>>2]|0))break;c[k>>2]=(c[B>>2]|0)+((_(c[v>>2]|0,c[p>>2]|0)|0)<<3);c[q>>2]=c[k>>2];c[r>>2]=(c[q>>2]|0)+(c[n>>2]<<3);c[s>>2]=(c[q>>2]|0)+(c[n>>2]<<1<<3);c[t>>2]=(c[q>>2]|0)+((c[n>>2]|0)*3<<3);c[u>>2]=(c[q>>2]|0)+(c[n>>2]<<2<<3);c[w>>2]=0;while(1){if((c[w>>2]|0)>=(c[n>>2]|0))break;m=c[q>>2]|0;c[x>>2]=c[m>>2];c[x+4>>2]=c[m+4>>2];m=_(c[w>>2]|0,c[l>>2]|0)|0;h=_(c[w>>2]|0,c[l>>2]|0)|0;g[x+8>>2]=+g[c[r>>2]>>2]*+g[(c[y>>2]|0)+(m<<3)>>2]-+g[(c[r>>2]|0)+4>>2]*+g[(c[y>>2]|0)+(h<<3)+4>>2];h=_(c[w>>2]|0,c[l>>2]|0)|0;m=_(c[w>>2]|0,c[l>>2]|0)|0;g[x+8+4>>2]=+g[c[r>>2]>>2]*+g[(c[y>>2]|0)+(h<<3)+4>>2]+ +g[(c[r>>2]|0)+4>>2]*+g[(c[y>>2]|0)+(m<<3)>>2];m=_(c[w>>2]<<1,c[l>>2]|0)|0;h=_(c[w>>2]<<1,c[l>>2]|0)|0;g[x+16>>2]=+g[c[s>>2]>>2]*+g[(c[y>>2]|0)+(m<<3)>>2]-+g[(c[s>>2]|0)+4>>2]*+g[(c[y>>2]|0)+(h<<3)+4>>2];h=_(c[w>>2]<<1,c[l>>2]|0)|0;m=_(c[w>>2]<<1,c[l>>2]|0)|0;g[x+16+4>>2]=+g[c[s>>2]>>2]*+g[(c[y>>2]|0)+(h<<3)+4>>2]+ +g[(c[s>>2]|0)+4>>2]*+g[(c[y>>2]|0)+(m<<3)>>2];m=_((c[w>>2]|0)*3|0,c[l>>2]|0)|0;h=_((c[w>>2]|0)*3|0,c[l>>2]|0)|0;g[x+24>>2]=+g[c[t>>2]>>2]*+g[(c[y>>2]|0)+(m<<3)>>2]-+g[(c[t>>2]|0)+4>>2]*+g[(c[y>>2]|0)+(h<<3)+4>>2];h=_((c[w>>2]|0)*3|0,c[l>>2]|0)|0;m=_((c[w>>2]|0)*3|0,c[l>>2]|0)|0;g[x+24+4>>2]=+g[c[t>>2]>>2]*+g[(c[y>>2]|0)+(h<<3)+4>>2]+ +g[(c[t>>2]|0)+4>>2]*+g[(c[y>>2]|0)+(m<<3)>>2];m=_(c[w>>2]<<2,c[l>>2]|0)|0;h=_(c[w>>2]<<2,c[l>>2]|0)|0;g[x+32>>2]=+g[c[u>>2]>>2]*+g[(c[y>>2]|0)+(m<<3)>>2]-+g[(c[u>>2]|0)+4>>2]*+g[(c[y>>2]|0)+(h<<3)+4>>2];h=_(c[w>>2]<<2,c[l>>2]|0)|0;m=_(c[w>>2]<<2,c[l>>2]|0)|0;g[x+32+4>>2]=+g[c[u>>2]>>2]*+g[(c[y>>2]|0)+(h<<3)+4>>2]+ +g[(c[u>>2]|0)+4>>2]*+g[(c[y>>2]|0)+(m<<3)>>2];g[x+56>>2]=+g[x+8>>2]+ +g[x+32>>2];g[x+56+4>>2]=+g[x+8+4>>2]+ +g[x+32+4>>2];g[x+80>>2]=+g[x+8>>2]-+g[x+32>>2];g[x+80+4>>2]=+g[x+8+4>>2]-+g[x+32+4>>2];g[x+64>>2]=+g[x+16>>2]+ +g[x+24>>2];g[x+64+4>>2]=+g[x+16+4>>2]+ +g[x+24+4>>2];g[x+72>>2]=+g[x+16>>2]-+g[x+24>>2];g[x+72+4>>2]=+g[x+16+4>>2]-+g[x+24+4>>2];m=c[q>>2]|0;g[m>>2]=+g[m>>2]+(+g[x+56>>2]+ +g[x+64>>2]);m=(c[q>>2]|0)+4|0;g[m>>2]=+g[m>>2]+(+g[x+56+4>>2]+ +g[x+64+4>>2]);g[x+40>>2]=+g[x>>2]+ +g[x+56>>2]*+g[z>>2]+ +g[x+64>>2]*+g[A>>2];g[x+40+4>>2]=+g[x+4>>2]+ +g[x+56+4>>2]*+g[z>>2]+ +g[x+64+4>>2]*+g[A>>2];g[x+48>>2]=+g[x+80+4>>2]*+g[z+4>>2]+ +g[x+72+4>>2]*+g[A+4>>2];g[x+48+4>>2]=-(+g[x+80>>2]*+g[z+4>>2])-+g[x+72>>2]*+g[A+4>>2];g[c[r>>2]>>2]=+g[x+40>>2]-+g[x+48>>2];g[(c[r>>2]|0)+4>>2]=+g[x+40+4>>2]-+g[x+48+4>>2];g[c[u>>2]>>2]=+g[x+40>>2]+ +g[x+48>>2];g[(c[u>>2]|0)+4>>2]=+g[x+40+4>>2]+ +g[x+48+4>>2];g[x+88>>2]=+g[x>>2]+ +g[x+56>>2]*+g[A>>2]+ +g[x+64>>2]*+g[z>>2];g[x+88+4>>2]=+g[x+4>>2]+ +g[x+56+4>>2]*+g[A>>2]+ +g[x+64+4>>2]*+g[z>>2];g[x+96>>2]=-(+g[x+80+4>>2]*+g[A+4>>2])+ +g[x+72+4>>2]*+g[z+4>>2];g[x+96+4>>2]=+g[x+80>>2]*+g[A+4>>2]-+g[x+72>>2]*+g[z+4>>2];g[c[s>>2]>>2]=+g[x+88>>2]+ +g[x+96>>2];g[(c[s>>2]|0)+4>>2]=+g[x+88+4>>2]+ +g[x+96+4>>2];g[c[t>>2]>>2]=+g[x+88>>2]-+g[x+96>>2];g[(c[t>>2]|0)+4>>2]=+g[x+88+4>>2]-+g[x+96+4>>2];c[q>>2]=(c[q>>2]|0)+8;c[r>>2]=(c[r>>2]|0)+8;c[s>>2]=(c[s>>2]|0)+8;c[t>>2]=(c[t>>2]|0)+8;c[u>>2]=(c[u>>2]|0)+8;c[w>>2]=(c[w>>2]|0)+1}c[v>>2]=(c[v>>2]|0)+1}i=j;return}function qd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;i=i+16|0;e=d+8|0;f=d+4|0;g=d;c[e>>2]=a;c[f>>2]=b;c[g>>2]=32736-(c[e>>2]|0);e=(_(c[g>>2]|0,16384-(c[f>>2]|0)|0)|0)>>>15;i=d;return e|0}function rd(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;h=i;i=i+80|0;j=h+60|0;k=h+44|0;l=h+20|0;m=h+16|0;n=h+4|0;o=h+40|0;p=h+48|0;q=h+56|0;r=h+64|0;s=h+24|0;t=h;u=h+32|0;v=h+28|0;w=h+8|0;x=h+36|0;y=h+12|0;z=h+52|0;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[n>>2]=f;g[p>>2]=+g[c[k>>2]>>2];g[q>>2]=+g[(c[k>>2]|0)+4>>2];g[r>>2]=+g[(c[k>>2]|0)+8>>2];g[s>>2]=+g[(c[k>>2]|0)+12>>2];g[t>>2]=+g[(c[k>>2]|0)+16>>2];g[u>>2]=+g[c[n>>2]>>2];g[v>>2]=+g[(c[n>>2]|0)+4>>2];g[w>>2]=+g[(c[n>>2]|0)+8>>2];g[x>>2]=+g[(c[n>>2]|0)+12>>2];g[y>>2]=+g[(c[n>>2]|0)+16>>2];c[o>>2]=0;while(1){if((c[o>>2]|0)>=(c[m>>2]|0))break;g[z>>2]=+g[(c[j>>2]|0)+(c[o>>2]<<2)>>2];g[z>>2]=+g[z>>2]+ +g[p>>2]*+g[u>>2];g[z>>2]=+g[z>>2]+ +g[q>>2]*+g[v>>2];g[z>>2]=+g[z>>2]+ +g[r>>2]*+g[w>>2];g[z>>2]=+g[z>>2]+ +g[s>>2]*+g[x>>2];g[z>>2]=+g[z>>2]+ +g[t>>2]*+g[y>>2];g[y>>2]=+g[x>>2];g[x>>2]=+g[w>>2];g[w>>2]=+g[v>>2];g[v>>2]=+g[u>>2];g[u>>2]=+g[(c[j>>2]|0)+(c[o>>2]<<2)>>2];g[(c[l>>2]|0)+(c[o>>2]<<2)>>2]=+g[z>>2];c[o>>2]=(c[o>>2]|0)+1}g[c[n>>2]>>2]=+g[u>>2];g[(c[n>>2]|0)+4>>2]=+g[v>>2];g[(c[n>>2]|0)+8>>2]=+g[w>>2];g[(c[n>>2]|0)+12>>2]=+g[x>>2];g[(c[n>>2]|0)+16>>2]=+g[y>>2];i=h;return}function sd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;f=i;i=i+64|0;h=f+44|0;j=f+36|0;k=f+12|0;l=f+8|0;m=f+32|0;n=f+40|0;o=f+48|0;p=f+16|0;q=f;r=f+24|0;s=f+4|0;t=f+28|0;u=f+20|0;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;g[q>>2]=0.0;e=c[j>>2]|0;c[j>>2]=e+4;g[n>>2]=+g[e>>2];e=c[j>>2]|0;c[j>>2]=e+4;g[o>>2]=+g[e>>2];e=c[j>>2]|0;c[j>>2]=e+4;g[p>>2]=+g[e>>2];c[m>>2]=0;while(1){if((c[m>>2]|0)>=((c[l>>2]|0)-3|0))break;e=c[h>>2]|0;c[h>>2]=e+4;g[r>>2]=+g[e>>2];e=c[j>>2]|0;c[j>>2]=e+4;g[q>>2]=+g[e>>2];g[c[k>>2]>>2]=+g[c[k>>2]>>2]+ +g[r>>2]*+g[n>>2];g[(c[k>>2]|0)+4>>2]=+g[(c[k>>2]|0)+4>>2]+ +g[r>>2]*+g[o>>2];g[(c[k>>2]|0)+8>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[r>>2]*+g[p>>2];g[(c[k>>2]|0)+12>>2]=+g[(c[k>>2]|0)+12>>2]+ +g[r>>2]*+g[q>>2];e=c[h>>2]|0;c[h>>2]=e+4;g[r>>2]=+g[e>>2];e=c[j>>2]|0;c[j>>2]=e+4;g[n>>2]=+g[e>>2];g[c[k>>2]>>2]=+g[c[k>>2]>>2]+ +g[r>>2]*+g[o>>2];g[(c[k>>2]|0)+4>>2]=+g[(c[k>>2]|0)+4>>2]+ +g[r>>2]*+g[p>>2];g[(c[k>>2]|0)+8>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[r>>2]*+g[q>>2];g[(c[k>>2]|0)+12>>2]=+g[(c[k>>2]|0)+12>>2]+ +g[r>>2]*+g[n>>2];e=c[h>>2]|0;c[h>>2]=e+4;g[r>>2]=+g[e>>2];e=c[j>>2]|0;c[j>>2]=e+4;g[o>>2]=+g[e>>2];g[c[k>>2]>>2]=+g[c[k>>2]>>2]+ +g[r>>2]*+g[p>>2];g[(c[k>>2]|0)+4>>2]=+g[(c[k>>2]|0)+4>>2]+ +g[r>>2]*+g[q>>2];g[(c[k>>2]|0)+8>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[r>>2]*+g[n>>2];g[(c[k>>2]|0)+12>>2]=+g[(c[k>>2]|0)+12>>2]+ +g[r>>2]*+g[o>>2];e=c[h>>2]|0;c[h>>2]=e+4;g[r>>2]=+g[e>>2];e=c[j>>2]|0;c[j>>2]=e+4;g[p>>2]=+g[e>>2];g[c[k>>2]>>2]=+g[c[k>>2]>>2]+ +g[r>>2]*+g[q>>2];g[(c[k>>2]|0)+4>>2]=+g[(c[k>>2]|0)+4>>2]+ +g[r>>2]*+g[n>>2];g[(c[k>>2]|0)+8>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[r>>2]*+g[o>>2];g[(c[k>>2]|0)+12>>2]=+g[(c[k>>2]|0)+12>>2]+ +g[r>>2]*+g[p>>2];c[m>>2]=(c[m>>2]|0)+4}r=c[m>>2]|0;c[m>>2]=r+1;if((r|0)<(c[l>>2]|0)){r=c[h>>2]|0;c[h>>2]=r+4;g[s>>2]=+g[r>>2];r=c[j>>2]|0;c[j>>2]=r+4;g[q>>2]=+g[r>>2];g[c[k>>2]>>2]=+g[c[k>>2]>>2]+ +g[s>>2]*+g[n>>2];g[(c[k>>2]|0)+4>>2]=+g[(c[k>>2]|0)+4>>2]+ +g[s>>2]*+g[o>>2];g[(c[k>>2]|0)+8>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[s>>2]*+g[p>>2];g[(c[k>>2]|0)+12>>2]=+g[(c[k>>2]|0)+12>>2]+ +g[s>>2]*+g[q>>2]}s=c[m>>2]|0;c[m>>2]=s+1;if((s|0)<(c[l>>2]|0)){s=c[h>>2]|0;c[h>>2]=s+4;g[t>>2]=+g[s>>2];s=c[j>>2]|0;c[j>>2]=s+4;g[n>>2]=+g[s>>2];g[c[k>>2]>>2]=+g[c[k>>2]>>2]+ +g[t>>2]*+g[o>>2];g[(c[k>>2]|0)+4>>2]=+g[(c[k>>2]|0)+4>>2]+ +g[t>>2]*+g[p>>2];g[(c[k>>2]|0)+8>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[t>>2]*+g[q>>2];g[(c[k>>2]|0)+12>>2]=+g[(c[k>>2]|0)+12>>2]+ +g[t>>2]*+g[n>>2]}if((c[m>>2]|0)>=(c[l>>2]|0)){i=f;return}l=c[h>>2]|0;c[h>>2]=l+4;g[u>>2]=+g[l>>2];l=c[j>>2]|0;c[j>>2]=l+4;g[o>>2]=+g[l>>2];g[c[k>>2]>>2]=+g[c[k>>2]>>2]+ +g[u>>2]*+g[p>>2];g[(c[k>>2]|0)+4>>2]=+g[(c[k>>2]|0)+4>>2]+ +g[u>>2]*+g[q>>2];g[(c[k>>2]|0)+8>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[u>>2]*+g[n>>2];g[(c[k>>2]|0)+12>>2]=+g[(c[k>>2]|0)+12>>2]+ +g[u>>2]*+g[o>>2];i=f;return}function td(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,h=0,j=0,k=0,l=0,m=0.0;e=i;i=i+32|0;f=e+16|0;h=e+12|0;j=e+8|0;k=e+4|0;l=e;c[f>>2]=a;c[h>>2]=b;c[j>>2]=d;g[l>>2]=0.0;c[k>>2]=0;while(1){m=+g[l>>2];if((c[k>>2]|0)>=(c[j>>2]|0))break;g[l>>2]=m+ +g[(c[f>>2]|0)+(c[k>>2]<<2)>>2]*+g[(c[h>>2]|0)+(c[k>>2]<<2)>>2];c[k>>2]=(c[k>>2]|0)+1}i=e;return +m}function ud(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;h=i;i=i+64|0;j=h;k=h+8|0;l=h+52|0;m=h+24|0;n=h+48|0;o=h+56|0;p=h+60|0;q=h+40|0;r=h+32|0;s=h+16|0;t=h+4|0;u=h+44|0;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[n>>2]=f;g[q>>2]=1.0;g[r>>2]=-1.0;g[r+4>>2]=-1.0;g[s>>2]=0.0;g[s+4>>2]=0.0;c[c[n>>2]>>2]=0;c[(c[n>>2]|0)+4>>2]=1;c[p>>2]=0;while(1){if((c[p>>2]|0)>=(c[l>>2]|0))break;g[q>>2]=+g[q>>2]+ +g[(c[k>>2]|0)+(c[p>>2]<<2)>>2]*+g[(c[k>>2]|0)+(c[p>>2]<<2)>>2];c[p>>2]=(c[p>>2]|0)+1}c[o>>2]=0;while(1){if((c[o>>2]|0)>=(c[m>>2]|0))break;do if(+g[(c[j>>2]|0)+(c[o>>2]<<2)>>2]>0.0?(g[u>>2]=+g[(c[j>>2]|0)+(c[o>>2]<<2)>>2],g[u>>2]=+g[u>>2]*9.999999960041972e-13,g[t>>2]=+g[u>>2]*+g[u>>2],+g[t>>2]*+g[s+4>>2]>+g[r+4>>2]*+g[q>>2]):0)if(+g[t>>2]*+g[s>>2]>+g[r>>2]*+g[q>>2]){g[r+4>>2]=+g[r>>2];g[s+4>>2]=+g[s>>2];c[(c[n>>2]|0)+4>>2]=c[c[n>>2]>>2];g[r>>2]=+g[t>>2];g[s>>2]=+g[q>>2];c[c[n>>2]>>2]=c[o>>2];break}else{g[r+4>>2]=+g[t>>2];g[s+4>>2]=+g[q>>2];c[(c[n>>2]|0)+4>>2]=c[o>>2];break}while(0);g[q>>2]=+g[q>>2]+(+g[(c[k>>2]|0)+((c[o>>2]|0)+(c[l>>2]|0)<<2)>>2]*+g[(c[k>>2]|0)+((c[o>>2]|0)+(c[l>>2]|0)<<2)>>2]-+g[(c[k>>2]|0)+(c[o>>2]<<2)>>2]*+g[(c[k>>2]|0)+(c[o>>2]<<2)>>2]);g[q>>2]=1.0>+g[q>>2]?1.0:+g[q>>2];c[o>>2]=(c[o>>2]|0)+1}i=h;return}function vd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;f=i;i=i+64|0;h=f+44|0;j=f+36|0;k=f+12|0;l=f+8|0;m=f+32|0;n=f+40|0;o=f+48|0;p=f+16|0;q=f;r=f+24|0;s=f+4|0;t=f+28|0;u=f+20|0;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;g[q>>2]=0.0;e=c[j>>2]|0;c[j>>2]=e+4;g[n>>2]=+g[e>>2];e=c[j>>2]|0;c[j>>2]=e+4;g[o>>2]=+g[e>>2];e=c[j>>2]|0;c[j>>2]=e+4;g[p>>2]=+g[e>>2];c[m>>2]=0;while(1){if((c[m>>2]|0)>=((c[l>>2]|0)-3|0))break;e=c[h>>2]|0;c[h>>2]=e+4;g[r>>2]=+g[e>>2];e=c[j>>2]|0;c[j>>2]=e+4;g[q>>2]=+g[e>>2];g[c[k>>2]>>2]=+g[c[k>>2]>>2]+ +g[r>>2]*+g[n>>2];g[(c[k>>2]|0)+4>>2]=+g[(c[k>>2]|0)+4>>2]+ +g[r>>2]*+g[o>>2];g[(c[k>>2]|0)+8>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[r>>2]*+g[p>>2];g[(c[k>>2]|0)+12>>2]=+g[(c[k>>2]|0)+12>>2]+ +g[r>>2]*+g[q>>2];e=c[h>>2]|0;c[h>>2]=e+4;g[r>>2]=+g[e>>2];e=c[j>>2]|0;c[j>>2]=e+4;g[n>>2]=+g[e>>2];g[c[k>>2]>>2]=+g[c[k>>2]>>2]+ +g[r>>2]*+g[o>>2];g[(c[k>>2]|0)+4>>2]=+g[(c[k>>2]|0)+4>>2]+ +g[r>>2]*+g[p>>2];g[(c[k>>2]|0)+8>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[r>>2]*+g[q>>2];g[(c[k>>2]|0)+12>>2]=+g[(c[k>>2]|0)+12>>2]+ +g[r>>2]*+g[n>>2];e=c[h>>2]|0;c[h>>2]=e+4;g[r>>2]=+g[e>>2];e=c[j>>2]|0;c[j>>2]=e+4;g[o>>2]=+g[e>>2];g[c[k>>2]>>2]=+g[c[k>>2]>>2]+ +g[r>>2]*+g[p>>2];g[(c[k>>2]|0)+4>>2]=+g[(c[k>>2]|0)+4>>2]+ +g[r>>2]*+g[q>>2];g[(c[k>>2]|0)+8>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[r>>2]*+g[n>>2];g[(c[k>>2]|0)+12>>2]=+g[(c[k>>2]|0)+12>>2]+ +g[r>>2]*+g[o>>2];e=c[h>>2]|0;c[h>>2]=e+4;g[r>>2]=+g[e>>2];e=c[j>>2]|0;c[j>>2]=e+4;g[p>>2]=+g[e>>2];g[c[k>>2]>>2]=+g[c[k>>2]>>2]+ +g[r>>2]*+g[q>>2];g[(c[k>>2]|0)+4>>2]=+g[(c[k>>2]|0)+4>>2]+ +g[r>>2]*+g[n>>2];g[(c[k>>2]|0)+8>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[r>>2]*+g[o>>2];g[(c[k>>2]|0)+12>>2]=+g[(c[k>>2]|0)+12>>2]+ +g[r>>2]*+g[p>>2];c[m>>2]=(c[m>>2]|0)+4}r=c[m>>2]|0;c[m>>2]=r+1;if((r|0)<(c[l>>2]|0)){r=c[h>>2]|0;c[h>>2]=r+4;g[s>>2]=+g[r>>2];r=c[j>>2]|0;c[j>>2]=r+4;g[q>>2]=+g[r>>2];g[c[k>>2]>>2]=+g[c[k>>2]>>2]+ +g[s>>2]*+g[n>>2];g[(c[k>>2]|0)+4>>2]=+g[(c[k>>2]|0)+4>>2]+ +g[s>>2]*+g[o>>2];g[(c[k>>2]|0)+8>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[s>>2]*+g[p>>2];g[(c[k>>2]|0)+12>>2]=+g[(c[k>>2]|0)+12>>2]+ +g[s>>2]*+g[q>>2]}s=c[m>>2]|0;c[m>>2]=s+1;if((s|0)<(c[l>>2]|0)){s=c[h>>2]|0;c[h>>2]=s+4;g[t>>2]=+g[s>>2];s=c[j>>2]|0;c[j>>2]=s+4;g[n>>2]=+g[s>>2];g[c[k>>2]>>2]=+g[c[k>>2]>>2]+ +g[t>>2]*+g[o>>2];g[(c[k>>2]|0)+4>>2]=+g[(c[k>>2]|0)+4>>2]+ +g[t>>2]*+g[p>>2];g[(c[k>>2]|0)+8>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[t>>2]*+g[q>>2];g[(c[k>>2]|0)+12>>2]=+g[(c[k>>2]|0)+12>>2]+ +g[t>>2]*+g[n>>2]}if((c[m>>2]|0)>=(c[l>>2]|0)){i=f;return}l=c[h>>2]|0;c[h>>2]=l+4;g[u>>2]=+g[l>>2];l=c[j>>2]|0;c[j>>2]=l+4;g[o>>2]=+g[l>>2];g[c[k>>2]>>2]=+g[c[k>>2]>>2]+ +g[u>>2]*+g[p>>2];g[(c[k>>2]|0)+4>>2]=+g[(c[k>>2]|0)+4>>2]+ +g[u>>2]*+g[q>>2];g[(c[k>>2]|0)+8>>2]=+g[(c[k>>2]|0)+8>>2]+ +g[u>>2]*+g[n>>2];g[(c[k>>2]|0)+12>>2]=+g[(c[k>>2]|0)+12>>2]+ +g[u>>2]*+g[o>>2];i=f;return}function wd(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;a=(c[(c[d>>2]|0)+20>>2]|0)-(32-(aa(c[(c[d>>2]|0)+28>>2]|0)|0))|0;i=b;return a|0}function xd(a,e,f,g,h,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B){a=a|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0;q=q|0;r=r|0;s=s|0;t=t|0;u=u|0;v=v|0;w=w|0;x=x|0;y=y|0;z=z|0;A=A|0;B=B|0;var C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0;C=i;i=i+224|0;D=C+204|0;E=C+188|0;F=C+168|0;G=C+68|0;H=C+80|0;I=C+84|0;J=C+12|0;K=C+156|0;L=C+16|0;M=C+20|0;N=C+24|0;O=C+28|0;P=C+32|0;Q=C+36|0;R=C+40|0;S=C+152|0;T=C+44|0;U=C+48|0;V=C+52|0;W=C+56|0;X=C+60|0;Y=C+64|0;Z=C+176|0;$=C+184|0;aa=C+192|0;ba=C+200|0;ca=C+208|0;da=C+88|0;ea=C+92|0;fa=C+96|0;ga=C+100|0;ha=C+148|0;ia=C+104|0;ja=C+108|0;ka=C+112|0;la=C+116|0;ma=C+120|0;na=C+124|0;oa=C+128|0;pa=C+132|0;qa=C+136|0;ra=C+140|0;sa=C+144|0;ta=C+8|0;ua=C;va=C+160|0;wa=C+164|0;xa=C+4|0;ya=C+172|0;za=C+72|0;Aa=C+180|0;Ba=C+76|0;Ca=C+196|0;c[D>>2]=a;c[E>>2]=e;c[F>>2]=f;c[G>>2]=g;c[H>>2]=h;c[I>>2]=j;c[J>>2]=k;c[K>>2]=l;c[L>>2]=m;c[M>>2]=n;c[N>>2]=o;c[O>>2]=p;c[P>>2]=q;c[Q>>2]=r;c[R>>2]=s;c[S>>2]=t;c[T>>2]=u;c[U>>2]=v;c[V>>2]=w;c[W>>2]=x;c[X>>2]=y;c[Y>>2]=z;c[Z>>2]=A;c[$>>2]=B;c[ha>>2]=-1;c[ia>>2]=c[V>>2]<<3;c[ga>>2]=(c[V>>2]|0)>1&1;c[fa>>2]=c[W>>2]<<3;c[ba>>2]=0;c[ca>>2]=64;c[da>>2]=0;while(1){if((c[da>>2]|0)>=6)break;c[na>>2]=(c[ba>>2]|0)+(c[ca>>2]|0)>>1;c[aa>>2]=0;c[la>>2]=0;c[ea>>2]=c[F>>2];while(1){B=c[ea>>2]|0;c[ea>>2]=B+-1;if((B|0)<=(c[E>>2]|0))break;c[oa>>2]=(c[(c[H>>2]|0)+(c[ea>>2]<<2)>>2]|0)+((_(c[na>>2]|0,c[(c[I>>2]|0)+(c[ea>>2]<<2)>>2]|0)|0)>>6);if(!((c[la>>2]|0)!=0?1:(c[oa>>2]|0)>=(c[(c[J>>2]|0)+(c[ea>>2]<<2)>>2]|0))){if((c[oa>>2]|0)<(c[ia>>2]|0))continue;c[aa>>2]=(c[aa>>2]|0)+(c[ia>>2]|0);continue}c[la>>2]=1;if((c[oa>>2]|0)<(c[(c[K>>2]|0)+(c[ea>>2]<<2)>>2]|0))Da=c[oa>>2]|0;else Da=c[(c[K>>2]|0)+(c[ea>>2]<<2)>>2]|0;c[aa>>2]=(c[aa>>2]|0)+Da}B=c[na>>2]|0;if((c[aa>>2]|0)>(c[L>>2]|0))c[ca>>2]=B;else c[ba>>2]=B;c[da>>2]=(c[da>>2]|0)+1}c[aa>>2]=0;c[la>>2]=0;c[ea>>2]=c[F>>2];while(1){da=c[ea>>2]|0;c[ea>>2]=da+-1;if((da|0)<=(c[E>>2]|0))break;c[pa>>2]=(c[(c[H>>2]|0)+(c[ea>>2]<<2)>>2]|0)+((_(c[ba>>2]|0,c[(c[I>>2]|0)+(c[ea>>2]<<2)>>2]|0)|0)>>6);do if(!((c[la>>2]|0)!=0?1:(c[pa>>2]|0)>=(c[(c[J>>2]|0)+(c[ea>>2]<<2)>>2]|0)))if((c[pa>>2]|0)>=(c[ia>>2]|0)){c[pa>>2]=c[ia>>2];break}else{c[pa>>2]=0;break}else c[la>>2]=1;while(0);if((c[pa>>2]|0)<(c[(c[K>>2]|0)+(c[ea>>2]<<2)>>2]|0))Ea=c[pa>>2]|0;else Ea=c[(c[K>>2]|0)+(c[ea>>2]<<2)>>2]|0;c[pa>>2]=Ea;c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]=c[pa>>2];c[aa>>2]=(c[aa>>2]|0)+(c[pa>>2]|0)}c[ha>>2]=c[F>>2];while(1){c[ea>>2]=(c[ha>>2]|0)-1;if((c[ea>>2]|0)<=(c[G>>2]|0)){Fa=29;break}c[ja>>2]=(c[L>>2]|0)-(c[aa>>2]|0);c[ka>>2]=ye(c[ja>>2]|0,(b[(c[(c[D>>2]|0)+32>>2]|0)+(c[ha>>2]<<1)>>1]|0)-(b[(c[(c[D>>2]|0)+32>>2]|0)+(c[E>>2]<<1)>>1]|0)|0)|0;pa=_((b[(c[(c[D>>2]|0)+32>>2]|0)+(c[ha>>2]<<1)>>1]|0)-(b[(c[(c[D>>2]|0)+32>>2]|0)+(c[E>>2]<<1)>>1]|0)|0,c[ka>>2]|0)|0;c[ja>>2]=(c[ja>>2]|0)-pa;if(((c[ja>>2]|0)-((b[(c[(c[D>>2]|0)+32>>2]|0)+(c[ea>>2]<<1)>>1]|0)-(b[(c[(c[D>>2]|0)+32>>2]|0)+(c[E>>2]<<1)>>1]|0))|0)>0)Ga=(c[ja>>2]|0)-((b[(c[(c[D>>2]|0)+32>>2]|0)+(c[ea>>2]<<1)>>1]|0)-(b[(c[(c[D>>2]|0)+32>>2]|0)+(c[E>>2]<<1)>>1]|0))|0;else Ga=0;c[sa>>2]=Ga;c[qa>>2]=(b[(c[(c[D>>2]|0)+32>>2]|0)+(c[ha>>2]<<1)>>1]|0)-(b[(c[(c[D>>2]|0)+32>>2]|0)+(c[ea>>2]<<1)>>1]|0);pa=(c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]|0)+(_(c[ka>>2]|0,c[qa>>2]|0)|0)|0;c[ra>>2]=pa+(c[sa>>2]|0);if((c[(c[J>>2]|0)+(c[ea>>2]<<2)>>2]|0)>((c[ia>>2]|0)+8|0))Ha=c[(c[J>>2]|0)+(c[ea>>2]<<2)>>2]|0;else Ha=(c[ia>>2]|0)+8|0;if((c[ra>>2]|0)>=(Ha|0)){if(!(c[Y>>2]|0)){if(ib(c[X>>2]|0,1)|0)break}else{if((c[ha>>2]|0)<=((c[E>>2]|0)+2|0)){Fa=40;break}pa=_((c[ea>>2]|0)<(c[Z>>2]|0)?7:9,c[qa>>2]|0)|0;if((c[ra>>2]|0)>(pa<<c[W>>2]<<3>>4|0)?(c[ea>>2]|0)<=(c[$>>2]|0):0){Fa=40;break}nb(c[X>>2]|0,0,1)}c[aa>>2]=(c[aa>>2]|0)+8;c[ra>>2]=(c[ra>>2]|0)-8}c[aa>>2]=(c[aa>>2]|0)-((c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]|0)+(c[P>>2]|0));if((c[P>>2]|0)>0)c[P>>2]=d[2928+((c[ea>>2]|0)-(c[E>>2]|0))>>0];c[aa>>2]=(c[aa>>2]|0)+(c[P>>2]|0);if((c[ra>>2]|0)>=(c[ia>>2]|0)){c[aa>>2]=(c[aa>>2]|0)+(c[ia>>2]|0);c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]=c[ia>>2]}else c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]=0;c[ha>>2]=(c[ha>>2]|0)+-1}if((Fa|0)==29)c[L>>2]=(c[L>>2]|0)+(c[N>>2]|0);else if((Fa|0)==40)nb(c[X>>2]|0,1,1);do if((c[P>>2]|0)>0){if(!(c[Y>>2]|0)){Fa=c[E>>2]|0;N=Fa+(kb(c[X>>2]|0,(c[ha>>2]|0)+1-(c[E>>2]|0)|0)|0)|0;c[c[O>>2]>>2]=N;break}if((c[c[O>>2]>>2]|0)<(c[ha>>2]|0))Ia=c[c[O>>2]>>2]|0;else Ia=c[ha>>2]|0;c[c[O>>2]>>2]=Ia;ob(c[X>>2]|0,(c[c[O>>2]>>2]|0)-(c[E>>2]|0)|0,(c[ha>>2]|0)+1-(c[E>>2]|0)|0)}else c[c[O>>2]>>2]=0;while(0);if((c[c[O>>2]>>2]|0)<=(c[E>>2]|0)){c[L>>2]=(c[L>>2]|0)+(c[R>>2]|0);c[R>>2]=0}do if((c[R>>2]|0)>0){Ia=c[X>>2]|0;if(c[Y>>2]|0){nb(Ia,c[c[Q>>2]>>2]|0,1);break}else{P=ib(Ia,1)|0;c[c[Q>>2]>>2]=P;break}}else c[c[Q>>2]>>2]=0;while(0);c[ja>>2]=(c[L>>2]|0)-(c[aa>>2]|0);c[ka>>2]=ye(c[ja>>2]|0,(b[(c[(c[D>>2]|0)+32>>2]|0)+(c[ha>>2]<<1)>>1]|0)-(b[(c[(c[D>>2]|0)+32>>2]|0)+(c[E>>2]<<1)>>1]|0)|0)|0;aa=_((b[(c[(c[D>>2]|0)+32>>2]|0)+(c[ha>>2]<<1)>>1]|0)-(b[(c[(c[D>>2]|0)+32>>2]|0)+(c[E>>2]<<1)>>1]|0)|0,c[ka>>2]|0)|0;c[ja>>2]=(c[ja>>2]|0)-aa;c[ea>>2]=c[E>>2];while(1){if((c[ea>>2]|0)>=(c[ha>>2]|0))break;aa=_(c[ka>>2]|0,(b[(c[(c[D>>2]|0)+32>>2]|0)+((c[ea>>2]|0)+1<<1)>>1]|0)-(b[(c[(c[D>>2]|0)+32>>2]|0)+(c[ea>>2]<<1)>>1]|0)|0)|0;L=(c[S>>2]|0)+(c[ea>>2]<<2)|0;c[L>>2]=(c[L>>2]|0)+aa;c[ea>>2]=(c[ea>>2]|0)+1}c[ea>>2]=c[E>>2];while(1){if((c[ea>>2]|0)>=(c[ha>>2]|0))break;if((c[ja>>2]|0)<((b[(c[(c[D>>2]|0)+32>>2]|0)+((c[ea>>2]|0)+1<<1)>>1]|0)-(b[(c[(c[D>>2]|0)+32>>2]|0)+(c[ea>>2]<<1)>>1]|0)|0))Ja=c[ja>>2]|0;else Ja=(b[(c[(c[D>>2]|0)+32>>2]|0)+((c[ea>>2]|0)+1<<1)>>1]|0)-(b[(c[(c[D>>2]|0)+32>>2]|0)+(c[ea>>2]<<1)>>1]|0)|0;c[ta>>2]=Ja;ka=(c[S>>2]|0)+(c[ea>>2]<<2)|0;c[ka>>2]=(c[ka>>2]|0)+(c[ta>>2]|0);c[ja>>2]=(c[ja>>2]|0)-(c[ta>>2]|0);c[ea>>2]=(c[ea>>2]|0)+1}c[ma>>2]=0;c[ea>>2]=c[E>>2];while(1){if((c[ea>>2]|0)>=(c[ha>>2]|0))break;c[ua>>2]=(b[(c[(c[D>>2]|0)+32>>2]|0)+((c[ea>>2]|0)+1<<1)>>1]|0)-(b[(c[(c[D>>2]|0)+32>>2]|0)+(c[ea>>2]<<1)>>1]|0);c[va>>2]=c[ua>>2]<<c[W>>2];c[Aa>>2]=(c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]|0)+(c[ma>>2]|0);E=c[Aa>>2]|0;if((c[va>>2]|0)>1){if((E-(c[(c[K>>2]|0)+(c[ea>>2]<<2)>>2]|0)|0)>0)Ka=(c[Aa>>2]|0)-(c[(c[K>>2]|0)+(c[ea>>2]<<2)>>2]|0)|0;else Ka=0;c[za>>2]=Ka;c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]=(c[Aa>>2]|0)-(c[za>>2]|0);ta=_(c[V>>2]|0,c[va>>2]|0)|0;if((c[V>>2]|0)==2&(c[va>>2]|0)>2?(c[c[Q>>2]>>2]|0)==0:0)La=(c[ea>>2]|0)<(c[c[O>>2]>>2]|0);else La=0;c[wa>>2]=ta+(La?1:0);c[ya>>2]=_(c[wa>>2]|0,(b[(c[(c[D>>2]|0)+56>>2]|0)+(c[ea>>2]<<1)>>1]|0)+(c[fa>>2]|0)|0)|0;c[xa>>2]=(c[ya>>2]>>1)-((c[wa>>2]|0)*21|0);if((c[va>>2]|0)==2)c[xa>>2]=(c[xa>>2]|0)+(c[wa>>2]<<3>>2);if(((c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]|0)+(c[xa>>2]|0)|0)>=(c[wa>>2]<<1<<3|0)){if(((c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]|0)+(c[xa>>2]|0)|0)<((c[wa>>2]|0)*3<<3|0))c[xa>>2]=(c[xa>>2]|0)+(c[ya>>2]>>3)}else c[xa>>2]=(c[xa>>2]|0)+(c[ya>>2]>>2);if(0>((c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]|0)+(c[xa>>2]|0)+(c[wa>>2]<<2)|0))Ma=0;else Ma=(c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]|0)+(c[xa>>2]|0)+(c[wa>>2]<<2)|0;c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]=Ma;ta=(ye(c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]|0,c[wa>>2]|0)|0)>>>3;c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]=ta;ta=_(c[V>>2]|0,c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]|0)|0;if((ta|0)>(c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]>>3|0))c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]=c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]>>c[ga>>2]>>3;if((c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]|0)<8)Na=c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]|0;else Na=8;c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]=Na;ta=_(c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]|0,c[wa>>2]<<3)|0;c[(c[U>>2]|0)+(c[ea>>2]<<2)>>2]=(ta|0)>=((c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]|0)+(c[xa>>2]|0)|0)&1;ta=(_(c[V>>2]|0,c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]|0)|0)<<3;ja=(c[S>>2]|0)+(c[ea>>2]<<2)|0;c[ja>>2]=(c[ja>>2]|0)-ta}else{if(0>(E-(c[V>>2]<<3)|0))Oa=0;else Oa=(c[Aa>>2]|0)-(c[V>>2]<<3)|0;c[za>>2]=Oa;c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]=(c[Aa>>2]|0)-(c[za>>2]|0);c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]=0;c[(c[U>>2]|0)+(c[ea>>2]<<2)>>2]=1}if((c[za>>2]|0)>0){if((c[za>>2]>>(c[ga>>2]|0)+3|0)<(8-(c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]|0)|0))Pa=c[za>>2]>>(c[ga>>2]|0)+3;else Pa=8-(c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]|0)|0;c[Ba>>2]=Pa;E=(c[T>>2]|0)+(c[ea>>2]<<2)|0;c[E>>2]=(c[E>>2]|0)+(c[Ba>>2]|0);c[Ca>>2]=(_(c[Ba>>2]|0,c[V>>2]|0)|0)<<3;c[(c[U>>2]|0)+(c[ea>>2]<<2)>>2]=(c[Ca>>2]|0)>=((c[za>>2]|0)-(c[ma>>2]|0)|0)&1;c[za>>2]=(c[za>>2]|0)-(c[Ca>>2]|0)}c[ma>>2]=c[za>>2];c[ea>>2]=(c[ea>>2]|0)+1}c[c[M>>2]>>2]=c[ma>>2];while(1){if((c[ea>>2]|0)>=(c[F>>2]|0))break;c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]=c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]>>c[ga>>2]>>3;c[(c[S>>2]|0)+(c[ea>>2]<<2)>>2]=0;c[(c[U>>2]|0)+(c[ea>>2]<<2)>>2]=(c[(c[T>>2]|0)+(c[ea>>2]<<2)>>2]|0)<1&1;c[ea>>2]=(c[ea>>2]|0)+1}i=C;return c[ha>>2]|0}function yd(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;j=i;i=i+64|0;k=j+44|0;l=j+36|0;m=j+12|0;n=j+8|0;o=j+32|0;p=j+40|0;q=j+48|0;r=j+16|0;s=j;t=j+24|0;u=j+4|0;v=j+28|0;w=j+20|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=d;c[n>>2]=e;c[o>>2]=f;c[p>>2]=h;c[v>>2]=0;if((c[p>>2]|0)==0?1:(c[o>>2]<<1|0)>=(c[l>>2]|0)){i=j;return}c[w>>2]=c[5216+((c[p>>2]|0)-1<<2)>>2];g[t>>2]=+(c[l>>2]|0)*1.0/+((c[l>>2]|0)+(_(c[w>>2]|0,c[o>>2]|0)|0)|0);g[u>>2]=+g[t>>2]*+g[t>>2]*.5;g[r>>2]=+Q(+(+g[u>>2]*1.5707963705062866));g[s>>2]=+Q(+((1.0-+g[u>>2])*1.5707963705062866));a:do if((c[l>>2]|0)>=(c[n>>2]<<3|0)){c[v>>2]=1;while(1){u=_(c[v>>2]|0,c[v>>2]|0)|0;t=_(u+(c[v>>2]|0)|0,c[n>>2]|0)|0;if((t+(c[n>>2]>>2)|0)>=(c[l>>2]|0))break a;c[v>>2]=(c[v>>2]|0)+1}}while(0);c[l>>2]=we(c[l>>2]|0,c[n>>2]|0)|0;c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[n>>2]|0))break;if((c[m>>2]|0)>=0){t=(c[k>>2]|0)+((_(c[q>>2]|0,c[l>>2]|0)|0)<<2)|0;xe(t,c[l>>2]|0,1,+g[r>>2],-+g[s>>2]);if(c[v>>2]|0){t=(c[k>>2]|0)+((_(c[q>>2]|0,c[l>>2]|0)|0)<<2)|0;xe(t,c[l>>2]|0,c[v>>2]|0,+g[s>>2],-+g[r>>2])}}else{if(c[v>>2]|0){t=(c[k>>2]|0)+((_(c[q>>2]|0,c[l>>2]|0)|0)<<2)|0;xe(t,c[l>>2]|0,c[v>>2]|0,+g[s>>2],+g[r>>2])}t=(c[k>>2]|0)+((_(c[q>>2]|0,c[l>>2]|0)|0)<<2)|0;xe(t,c[l>>2]|0,1,+g[r>>2],+g[s>>2])}c[q>>2]=(c[q>>2]|0)+1}i=j;return}function zd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;e=i;i=i+48|0;f=e+28|0;g=e+16|0;h=e+4|0;j=e+8|0;k=e+32|0;l=e;m=e+12|0;n=e+24|0;o=e+20|0;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;if((c[j>>2]|0)<=1){c[f>>2]=1;p=c[f>>2]|0;i=e;return p|0}c[l>>2]=we(c[h>>2]|0,c[j>>2]|0)|0;c[k>>2]=0;c[m>>2]=0;do{c[o>>2]=0;c[n>>2]=0;do{h=_(c[m>>2]|0,c[l>>2]|0)|0;c[o>>2]=c[o>>2]|c[(c[g>>2]|0)+(h+(c[n>>2]|0)<<2)>>2];h=(c[n>>2]|0)+1|0;c[n>>2]=h}while((h|0)<(c[l>>2]|0));c[k>>2]=c[k>>2]|((c[o>>2]|0)!=0&1)<<c[m>>2];h=(c[m>>2]|0)+1|0;c[m>>2]=h}while((h|0)<(c[j>>2]|0));c[f>>2]=c[k>>2];p=c[f>>2]|0;i=e;return p|0}function Ad(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=+e;f=+f;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;h=i;i=i+32|0;j=h+4|0;k=h+16|0;l=h+8|0;m=h+20|0;n=h+28|0;o=h;p=h+12|0;q=h+24|0;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;g[m>>2]=e;g[n>>2]=f;g[p>>2]=+g[m>>2];f=1.0/+O(+(+g[p>>2]));g[q>>2]=f*+g[n>>2];c[o>>2]=0;do{g[(c[k>>2]|0)+(c[o>>2]<<2)>>2]=+g[q>>2]*+(c[(c[j>>2]|0)+(c[o>>2]<<2)>>2]|0);n=(c[o>>2]|0)+1|0;c[o>>2]=n}while((n|0)<(c[l>>2]|0));i=h;return}function Bd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,h=0,j=0,k=0,l=0,m=0.0;e=i;i=i+32|0;f=e+16|0;h=e+12|0;j=e+8|0;k=e+4|0;l=e;c[f>>2]=a;c[h>>2]=b;c[j>>2]=d;g[l>>2]=0.0;c[k>>2]=0;while(1){m=+g[l>>2];if((c[k>>2]|0)>=(c[j>>2]|0))break;g[l>>2]=m+ +g[(c[f>>2]|0)+(c[k>>2]<<2)>>2]*+g[(c[h>>2]|0)+(c[k>>2]<<2)>>2];c[k>>2]=(c[k>>2]|0)+1}i=e;return +m}function Cd(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;g=i;i=i+48|0;h=g+28|0;j=g+16|0;k=g+4|0;l=g+8|0;m=g+32|0;n=g;o=g+12|0;p=g+24|0;q=g+20|0;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;c[m>>2]=f;c[q>>2]=255;while(1){if((c[q>>2]|0)<=(c[l>>2]|0))break;c[q>>2]=c[q>>2]>>1}c[n>>2]=c[c[m>>2]>>2];c[o>>2]=0;while(1){r=c[n>>2]|0;if((c[o>>2]|0)>=(c[l>>2]|0))break;c[n>>2]=907633515+(_(r,196314165)|0);c[p>>2]=c[n>>2]>>24&c[q>>2];f=_(c[(c[j>>2]|0)+(c[p>>2]<<2)>>2]>>16,(c[k>>2]>>4&65535)<<16>>16)|0;e=f+((_(c[(c[j>>2]|0)+(c[p>>2]<<2)>>2]&65535,(c[k>>2]>>4&65535)<<16>>16)|0)>>16)|0;if((e+(_(c[(c[j>>2]|0)+(c[p>>2]<<2)>>2]|0,(c[k>>2]>>4>>15)+1>>1)|0)|0)<=32767){e=_(c[(c[j>>2]|0)+(c[p>>2]<<2)>>2]>>16,(c[k>>2]>>4&65535)<<16>>16)|0;f=e+((_(c[(c[j>>2]|0)+(c[p>>2]<<2)>>2]&65535,(c[k>>2]>>4&65535)<<16>>16)|0)>>16)|0;if((f+(_(c[(c[j>>2]|0)+(c[p>>2]<<2)>>2]|0,(c[k>>2]>>4>>15)+1>>1)|0)|0)<-32768)s=-32768;else{f=_(c[(c[j>>2]|0)+(c[p>>2]<<2)>>2]>>16,(c[k>>2]>>4&65535)<<16>>16)|0;e=f+((_(c[(c[j>>2]|0)+(c[p>>2]<<2)>>2]&65535,(c[k>>2]>>4&65535)<<16>>16)|0)>>16)|0;s=e+(_(c[(c[j>>2]|0)+(c[p>>2]<<2)>>2]|0,(c[k>>2]>>4>>15)+1>>1)|0)|0}}else s=32767;c[(c[h>>2]|0)+(c[o>>2]<<2)>>2]=(s&65535)<<16>>16;c[o>>2]=(c[o>>2]|0)+1}c[c[m>>2]>>2]=r;i=g;return}function Dd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;d=i;i=i+48|0;e=d+28|0;f=d+16|0;g=d+4|0;h=d+8|0;j=d+32|0;k=d;l=d+12|0;m=d+24|0;n=d+20|0;c[f>>2]=a;c[g>>2]=b;b=c[f>>2]|0;c[h>>2]=(ve((c[f>>2]|0)>0?b:0-b|0)|0)-1;c[l>>2]=c[f>>2]<<c[h>>2];c[k>>2]=536870911/(c[l>>2]>>16|0)|0;c[n>>2]=c[k>>2]<<16;f=_(c[l>>2]>>16,(c[k>>2]&65535)<<16>>16)|0;c[m>>2]=536870912-(f+((_(c[l>>2]&65535,(c[k>>2]&65535)<<16>>16)|0)>>16))<<3;l=_(c[m>>2]>>16,(c[k>>2]&65535)<<16>>16)|0;f=(c[n>>2]|0)+(l+((_(c[m>>2]&65535,(c[k>>2]&65535)<<16>>16)|0)>>16))|0;c[n>>2]=f+(_(c[m>>2]|0,(c[k>>2]>>15)+1>>1)|0);c[j>>2]=61-(c[h>>2]|0)-(c[g>>2]|0);g=c[j>>2]|0;if((c[j>>2]|0)>0)if((g|0)<32){c[e>>2]=c[n>>2]>>c[j>>2];o=c[e>>2]|0;i=d;return o|0}else{c[e>>2]=0;o=c[e>>2]|0;i=d;return o|0}h=c[n>>2]|0;k=0-(c[j>>2]|0)|0;do if((-2147483648>>0-g|0)>(2147483647>>0-(c[j>>2]|0)|0)){if((h|0)>(-2147483648>>k|0)){p=-2147483648>>0-(c[j>>2]|0);break}if((c[n>>2]|0)<(2147483647>>0-(c[j>>2]|0)|0)){p=2147483647>>0-(c[j>>2]|0);break}else{p=c[n>>2]|0;break}}else{if((h|0)>(2147483647>>k|0)){p=2147483647>>0-(c[j>>2]|0);break}if((c[n>>2]|0)<(-2147483648>>0-(c[j>>2]|0)|0)){p=-2147483648>>0-(c[j>>2]|0);break}else{p=c[n>>2]|0;break}}while(0);c[e>>2]=p<<0-(c[j>>2]|0);o=c[e>>2]|0;i=d;return o|0}function Ed(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;e=i;i=i+48|0;f=e+36|0;g=e+16|0;h=e;j=e+28|0;k=e+32|0;l=e+40|0;m=e+12|0;n=e+24|0;o=e+20|0;p=e+8|0;q=e+4|0;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;d=c[g>>2]|0;c[k>>2]=(ve((c[g>>2]|0)>0?d:0-d|0)|0)-1;c[o>>2]=c[g>>2]<<c[k>>2];g=c[h>>2]|0;c[l>>2]=(ve((c[h>>2]|0)>0?g:0-g|0)|0)-1;c[p>>2]=c[h>>2]<<c[l>>2];c[n>>2]=536870911/(c[p>>2]>>16|0)|0;h=_(c[o>>2]>>16,(c[n>>2]&65535)<<16>>16)|0;c[q>>2]=h+((_(c[o>>2]&65535,(c[n>>2]&65535)<<16>>16)|0)>>16);h=c[o>>2]|0;g=c[p>>2]|0;p=c[q>>2]|0;d=of(g|0,((g|0)<0)<<31>>31|0,p|0,((p|0)<0)<<31>>31|0)|0;p=af(d|0,C|0,32)|0;c[o>>2]=h-(p<<3);p=_(c[o>>2]>>16,(c[n>>2]&65535)<<16>>16)|0;c[q>>2]=(c[q>>2]|0)+(p+((_(c[o>>2]&65535,(c[n>>2]&65535)<<16>>16)|0)>>16));c[m>>2]=29+(c[k>>2]|0)-(c[l>>2]|0)-(c[j>>2]|0);j=c[m>>2]|0;if((c[m>>2]|0)>=0)if((j|0)<32){c[f>>2]=c[q>>2]>>c[m>>2];r=c[f>>2]|0;i=e;return r|0}else{c[f>>2]=0;r=c[f>>2]|0;i=e;return r|0}l=c[q>>2]|0;k=0-(c[m>>2]|0)|0;do if((-2147483648>>0-j|0)>(2147483647>>0-(c[m>>2]|0)|0)){if((l|0)>(-2147483648>>k|0)){s=-2147483648>>0-(c[m>>2]|0);break}if((c[q>>2]|0)<(2147483647>>0-(c[m>>2]|0)|0)){s=2147483647>>0-(c[m>>2]|0);break}else{s=c[q>>2]|0;break}}else{if((l|0)>(2147483647>>k|0)){s=2147483647>>0-(c[m>>2]|0);break}if((c[q>>2]|0)<(-2147483648>>0-(c[m>>2]|0)|0)){s=-2147483648>>0-(c[m>>2]|0);break}else{s=c[q>>2]|0;break}}while(0);c[f>>2]=s<<0-(c[m>>2]|0);r=c[f>>2]|0;i=e;return r|0}function Fd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)<(c[f>>2]|0)?c[e>>2]|0:c[f>>2]|0)|0}function Gd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)>(c[f>>2]|0)?c[e>>2]|0:c[f>>2]|0)|0}function Hd(e,f,g,h,j){e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;k=i;i=i+32|0;l=k+24|0;m=k+16|0;n=k+12|0;o=k+8|0;p=k+28|0;q=k;r=k+20|0;s=k+4|0;c[l>>2]=e;c[m>>2]=f;c[n>>2]=g;c[o>>2]=h;b[p>>1]=j;c[r>>2]=0;c[q>>2]=(b[p>>1]|0)-1;while(1){if((c[q>>2]|0)<0)break;c[s>>2]=(_((c[r>>2]&65535)<<16>>16,d[(c[n>>2]|0)+(c[q>>2]|0)>>0]|0)|0)>>8;c[r>>2]=a[(c[m>>2]|0)+(c[q>>2]|0)>>0]<<10;p=c[r>>2]|0;if((c[r>>2]|0)<=0){if((p|0)<0)c[r>>2]=(c[r>>2]|0)+102}else c[r>>2]=p-102;p=_(c[r>>2]>>16,(c[o>>2]&65535)<<16>>16)|0;c[r>>2]=(c[s>>2]|0)+(p+((_(c[r>>2]&65535,(c[o>>2]&65535)<<16>>16)|0)>>16));b[(c[l>>2]|0)+(c[q>>2]<<1)>>1]=c[r>>2];c[q>>2]=(c[q>>2]|0)+-1}i=k;return}function Id(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0;b=i;i=i+32|0;d=b+16|0;e=b+12|0;f=b+8|0;g=b+4|0;h=b;c[e>>2]=a;if((c[e>>2]|0)<=0){c[d>>2]=0;j=c[d>>2]|0;i=b;return j|0}se(c[e>>2]|0,g,h);if(c[g>>2]&1)c[f>>2]=32768;else c[f>>2]=46214;c[f>>2]=c[f>>2]>>(c[g>>2]>>1);g=_(c[f>>2]>>16,(((c[h>>2]&65535)<<16>>16)*213&65535)<<16>>16)|0;c[f>>2]=(c[f>>2]|0)+(g+((_(c[f>>2]&65535,(((c[h>>2]&65535)<<16>>16)*213&65535)<<16>>16)|0)>>16));c[d>>2]=c[f>>2];j=c[d>>2]|0;i=b;return j|0}function Jd(a,d,e){a=a|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0;f=i;i=i+160|0;g=f+68|0;h=f+100|0;j=f+40|0;k=f+44|0;l=f+92|0;m=f+8|0;n=f+12|0;o=f+72|0;p=f+16|0;q=f+20|0;r=f+88|0;s=f+96|0;t=f+104|0;u=f+112|0;v=f+48|0;w=f+116|0;x=f+52|0;y=f+56|0;z=f+60|0;A=f+64|0;B=f+4|0;C=f+120|0;D=f+84|0;E=f+24|0;F=f+128|0;G=f;H=f+32|0;I=f+108|0;J=f+80|0;K=f+76|0;c[g>>2]=a;c[h>>2]=d;c[j>>2]=e;c[G>>2]=(c[g>>2]|0)+4168;e=(c[(c[g>>2]|0)+2336>>2]|0)+(c[(c[g>>2]|0)+2328>>2]|0)|0;c[I>>2]=ua()|0;d=i;i=i+((1*(e<<2)|0)+15&-16)|0;e=i;i=i+((1*(c[(c[g>>2]|0)+2336>>2]<<1)|0)+15&-16)|0;c[H>>2]=c[(c[G>>2]|0)+72>>2]>>6;c[H+4>>2]=c[(c[G>>2]|0)+72+4>>2]>>6;if(c[(c[g>>2]|0)+2376>>2]|0){L=(c[G>>2]|0)+14|0;M=L+32|0;do{b[L>>1]=0;L=L+2|0}while((L|0)<(M|0))}me(w,q,x,r,(c[g>>2]|0)+4|0,H,c[(c[g>>2]|0)+2332>>2]|0,c[(c[g>>2]|0)+2324>>2]|0);a=c[(c[G>>2]|0)+84>>2]|0;if((c[w>>2]>>c[r>>2]|0)<(c[x>>2]>>c[q>>2]|0)){q=ne(0,(_(a-1|0,c[(c[G>>2]|0)+88>>2]|0)|0)-128|0)|0;c[y>>2]=(c[g>>2]|0)+4+(q<<2)}else{q=ne(0,(_(a,c[(c[G>>2]|0)+88>>2]|0)|0)-128|0)|0;c[y>>2]=(c[g>>2]|0)+4+(q<<2)}c[D>>2]=(c[G>>2]|0)+4;b[C>>1]=b[(c[G>>2]|0)+56>>1]|0;c[t>>2]=b[5192+((oe(1,c[(c[g>>2]|0)+4160>>2]|0)|0)<<1)>>1];q=(c[(c[g>>2]|0)+4164>>2]|0)==2;a=oe(1,c[(c[g>>2]|0)+4160>>2]|0)|0;if(q)c[u>>2]=b[5200+(a<<1)>>1];else c[u>>2]=b[5208+(a<<1)>>1];ec((c[G>>2]|0)+14|0,c[(c[g>>2]|0)+2340>>2]|0,64881);df(F|0,(c[G>>2]|0)+14|0,c[(c[g>>2]|0)+2340>>2]<<1|0)|0;do if(!(c[(c[g>>2]|0)+4160>>2]|0)){b[C>>1]=16384;if((c[(c[g>>2]|0)+4164>>2]|0)!=2){c[J>>2]=ic((c[G>>2]|0)+14|0,c[(c[g>>2]|0)+2340>>2]|0)|0;c[K>>2]=qe(134217728,c[J>>2]|0)|0;c[K>>2]=Md(4194304,c[K>>2]|0)|0;c[K>>2]=c[K>>2]<<3;a=_(c[K>>2]>>16,(c[u>>2]&65535)<<16>>16)|0;c[u>>2]=a+((_(c[K>>2]&65535,(c[u>>2]&65535)<<16>>16)|0)>>16)>>14;break}c[k>>2]=0;while(1){if((c[k>>2]|0)>=5)break;b[C>>1]=(b[C>>1]|0)-(b[(c[D>>2]|0)+(c[k>>2]<<1)>>1]|0);c[k>>2]=(c[k>>2]|0)+1}b[C>>1]=pe(3277,b[C>>1]|0)|0;b[C>>1]=(_(b[C>>1]|0,b[(c[G>>2]|0)+68>>1]|0)|0)>>14}while(0);c[s>>2]=c[(c[G>>2]|0)+52>>2];c[n>>2]=(c[c[G>>2]>>2]>>7)+1>>1;c[p>>2]=c[(c[g>>2]|0)+2336>>2];c[o>>2]=(c[(c[g>>2]|0)+2336>>2]|0)-(c[n>>2]|0)-(c[(c[g>>2]|0)+2340>>2]|0)-2;hc(e+(c[o>>2]<<1)|0,(c[g>>2]|0)+1348+(c[o>>2]<<1)|0,F,(c[(c[g>>2]|0)+2336>>2]|0)-(c[o>>2]|0)|0,c[(c[g>>2]|0)+2340>>2]|0);c[v>>2]=re(c[(c[G>>2]|0)+72+4>>2]|0,46)|0;c[v>>2]=(c[v>>2]|0)<1073741823?c[v>>2]|0:1073741823;c[k>>2]=(c[o>>2]|0)+(c[(c[g>>2]|0)+2340>>2]|0);while(1){if((c[k>>2]|0)>=(c[(c[g>>2]|0)+2336>>2]|0))break;K=_(c[v>>2]>>16,b[e+(c[k>>2]<<1)>>1]|0)|0;J=K+((_(c[v>>2]&65535,b[e+(c[k>>2]<<1)>>1]|0)|0)>>16)|0;c[d+(c[k>>2]<<2)>>2]=J;c[k>>2]=(c[k>>2]|0)+1}c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[(c[g>>2]|0)+2324>>2]|0))break;c[z>>2]=d+((c[p>>2]|0)-(c[n>>2]|0)+2<<2);c[k>>2]=0;while(1){if((c[k>>2]|0)>=(c[(c[g>>2]|0)+2332>>2]|0))break;c[B>>2]=2;e=_(c[c[z>>2]>>2]>>16,b[c[D>>2]>>1]|0)|0;c[B>>2]=(c[B>>2]|0)+(e+((_(c[c[z>>2]>>2]&65535,b[c[D>>2]>>1]|0)|0)>>16));e=_(c[(c[z>>2]|0)+-4>>2]>>16,b[(c[D>>2]|0)+2>>1]|0)|0;c[B>>2]=(c[B>>2]|0)+(e+((_(c[(c[z>>2]|0)+-4>>2]&65535,b[(c[D>>2]|0)+2>>1]|0)|0)>>16));e=_(c[(c[z>>2]|0)+-8>>2]>>16,b[(c[D>>2]|0)+4>>1]|0)|0;c[B>>2]=(c[B>>2]|0)+(e+((_(c[(c[z>>2]|0)+-8>>2]&65535,b[(c[D>>2]|0)+4>>1]|0)|0)>>16));e=_(c[(c[z>>2]|0)+-12>>2]>>16,b[(c[D>>2]|0)+6>>1]|0)|0;c[B>>2]=(c[B>>2]|0)+(e+((_(c[(c[z>>2]|0)+-12>>2]&65535,b[(c[D>>2]|0)+6>>1]|0)|0)>>16));e=_(c[(c[z>>2]|0)+-16>>2]>>16,b[(c[D>>2]|0)+8>>1]|0)|0;c[B>>2]=(c[B>>2]|0)+(e+((_(c[(c[z>>2]|0)+-16>>2]&65535,b[(c[D>>2]|0)+8>>1]|0)|0)>>16));c[z>>2]=(c[z>>2]|0)+4;c[s>>2]=907633515+(_(c[s>>2]|0,196314165)|0);c[o>>2]=c[s>>2]>>25&127;e=_(c[(c[y>>2]|0)+(c[o>>2]<<2)>>2]>>16,b[C>>1]|0)|0;v=(c[B>>2]|0)+(e+((_(c[(c[y>>2]|0)+(c[o>>2]<<2)>>2]&65535,b[C>>1]|0)|0)>>16))<<2;c[d+(c[p>>2]<<2)>>2]=v;c[p>>2]=(c[p>>2]|0)+1;c[k>>2]=(c[k>>2]|0)+1}c[l>>2]=0;while(1){if((c[l>>2]|0)>=5)break;v=(_((c[t>>2]&65535)<<16>>16,b[(c[D>>2]|0)+(c[l>>2]<<1)>>1]|0)|0)>>15&65535;b[(c[D>>2]|0)+(c[l>>2]<<1)>>1]=v;c[l>>2]=(c[l>>2]|0)+1}b[C>>1]=(_(b[C>>1]|0,(c[u>>2]&65535)<<16>>16)|0)>>15;c[c[G>>2]>>2]=(c[c[G>>2]>>2]|0)+(((c[c[G>>2]>>2]>>16)*655|0)+((c[c[G>>2]>>2]&65535)*655>>16));v=qe(c[c[G>>2]>>2]|0,((c[(c[g>>2]|0)+2316>>2]&65535)<<16>>16)*18<<8)|0;c[c[G>>2]>>2]=v;c[n>>2]=(c[c[G>>2]>>2]>>7)+1>>1;c[m>>2]=(c[m>>2]|0)+1}c[E>>2]=d+((c[(c[g>>2]|0)+2336>>2]|0)-16<<2);L=c[E>>2]|0;d=(c[g>>2]|0)+1284|0;M=L+64|0;do{c[L>>2]=c[d>>2];L=L+4|0;d=d+4|0}while((L|0)<(M|0));c[k>>2]=0;while(1){N=c[g>>2]|0;if((c[k>>2]|0)>=(c[(c[g>>2]|0)+2328>>2]|0))break;c[A>>2]=c[N+2340>>2]>>1;m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-1<<2)>>2]>>16,b[F>>1]|0)|0;c[A>>2]=(c[A>>2]|0)+(m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-1<<2)>>2]&65535,b[F>>1]|0)|0)>>16));m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-2<<2)>>2]>>16,b[F+2>>1]|0)|0;c[A>>2]=(c[A>>2]|0)+(m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-2<<2)>>2]&65535,b[F+2>>1]|0)|0)>>16));m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-3<<2)>>2]>>16,b[F+4>>1]|0)|0;c[A>>2]=(c[A>>2]|0)+(m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-3<<2)>>2]&65535,b[F+4>>1]|0)|0)>>16));m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-4<<2)>>2]>>16,b[F+6>>1]|0)|0;c[A>>2]=(c[A>>2]|0)+(m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-4<<2)>>2]&65535,b[F+6>>1]|0)|0)>>16));m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-5<<2)>>2]>>16,b[F+8>>1]|0)|0;c[A>>2]=(c[A>>2]|0)+(m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-5<<2)>>2]&65535,b[F+8>>1]|0)|0)>>16));m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-6<<2)>>2]>>16,b[F+10>>1]|0)|0;c[A>>2]=(c[A>>2]|0)+(m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-6<<2)>>2]&65535,b[F+10>>1]|0)|0)>>16));m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-7<<2)>>2]>>16,b[F+12>>1]|0)|0;c[A>>2]=(c[A>>2]|0)+(m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-7<<2)>>2]&65535,b[F+12>>1]|0)|0)>>16));m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-8<<2)>>2]>>16,b[F+14>>1]|0)|0;c[A>>2]=(c[A>>2]|0)+(m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-8<<2)>>2]&65535,b[F+14>>1]|0)|0)>>16));m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-9<<2)>>2]>>16,b[F+16>>1]|0)|0;c[A>>2]=(c[A>>2]|0)+(m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-9<<2)>>2]&65535,b[F+16>>1]|0)|0)>>16));m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-10<<2)>>2]>>16,b[F+18>>1]|0)|0;c[A>>2]=(c[A>>2]|0)+(m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-10<<2)>>2]&65535,b[F+18>>1]|0)|0)>>16));c[l>>2]=10;while(1){if((c[l>>2]|0)>=(c[(c[g>>2]|0)+2340>>2]|0))break;m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-(c[l>>2]|0)-1<<2)>>2]>>16,b[F+(c[l>>2]<<1)>>1]|0)|0;c[A>>2]=(c[A>>2]|0)+(m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)-(c[l>>2]|0)-1<<2)>>2]&65535,b[F+(c[l>>2]<<1)>>1]|0)|0)>>16));c[l>>2]=(c[l>>2]|0)+1}c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]=(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]|0)+(c[A>>2]<<4);m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]>>16,(c[H+4>>2]&65535)<<16>>16)|0;u=m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]&65535,(c[H+4>>2]&65535)<<16>>16)|0)>>16)|0;if(((u+(_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]|0,(c[H+4>>2]>>15)+1>>1)|0)>>7)+1>>1|0)<=32767){u=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]>>16,(c[H+4>>2]&65535)<<16>>16)|0;m=u+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]&65535,(c[H+4>>2]&65535)<<16>>16)|0)>>16)|0;if(((m+(_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]|0,(c[H+4>>2]>>15)+1>>1)|0)>>7)+1>>1|0)<-32768)O=-32768;else{m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]>>16,(c[H+4>>2]&65535)<<16>>16)|0;u=m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]&65535,(c[H+4>>2]&65535)<<16>>16)|0)>>16)|0;O=(u+(_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]|0,(c[H+4>>2]>>15)+1>>1)|0)>>7)+1>>1}}else O=32767;if((O|0)<=32767){u=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]>>16,(c[H+4>>2]&65535)<<16>>16)|0;m=u+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]&65535,(c[H+4>>2]&65535)<<16>>16)|0)>>16)|0;if(((m+(_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]|0,(c[H+4>>2]>>15)+1>>1)|0)>>7)+1>>1|0)<=32767){m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]>>16,(c[H+4>>2]&65535)<<16>>16)|0;u=m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]&65535,(c[H+4>>2]&65535)<<16>>16)|0)>>16)|0;if(((u+(_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]|0,(c[H+4>>2]>>15)+1>>1)|0)>>7)+1>>1|0)<-32768)P=-32768;else{u=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]>>16,(c[H+4>>2]&65535)<<16>>16)|0;m=u+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]&65535,(c[H+4>>2]&65535)<<16>>16)|0)>>16)|0;P=(m+(_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]|0,(c[H+4>>2]>>15)+1>>1)|0)>>7)+1>>1}}else P=32767;if((P|0)>=-32768){m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]>>16,(c[H+4>>2]&65535)<<16>>16)|0;u=m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]&65535,(c[H+4>>2]&65535)<<16>>16)|0)>>16)|0;if(((u+(_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]|0,(c[H+4>>2]>>15)+1>>1)|0)>>7)+1>>1|0)<=32767){u=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]>>16,(c[H+4>>2]&65535)<<16>>16)|0;m=u+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]&65535,(c[H+4>>2]&65535)<<16>>16)|0)>>16)|0;if(((m+(_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]|0,(c[H+4>>2]>>15)+1>>1)|0)>>7)+1>>1|0)<-32768)Q=-32768;else{m=_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]>>16,(c[H+4>>2]&65535)<<16>>16)|0;u=m+((_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]&65535,(c[H+4>>2]&65535)<<16>>16)|0)>>16)|0;Q=(u+(_(c[(c[E>>2]|0)+(16+(c[k>>2]|0)<<2)>>2]|0,(c[H+4>>2]>>15)+1>>1)|0)>>7)+1>>1}}else Q=32767}else Q=-32768}else Q=32767;b[(c[j>>2]|0)+(c[k>>2]<<1)>>1]=Q;c[k>>2]=(c[k>>2]|0)+1}L=N+1284|0;d=(c[E>>2]|0)+(c[(c[g>>2]|0)+2328>>2]<<2)|0;M=L+64|0;do{c[L>>2]=c[d>>2];L=L+4|0;d=d+4|0}while((L|0)<(M|0));c[(c[G>>2]|0)+52>>2]=c[s>>2];b[(c[G>>2]|0)+56>>1]=b[C>>1]|0;c[k>>2]=0;while(1){if((c[k>>2]|0)>=4)break;c[(c[h>>2]|0)+(c[k>>2]<<2)>>2]=c[n>>2];c[k>>2]=(c[k>>2]|0)+1}ka(c[I>>2]|0);i=f;return}function Kd(d,e){d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;f=i;i=i+48|0;g=f+36|0;h=f+16|0;j=f;k=f+28|0;l=f+32|0;m=f+40|0;n=f+12|0;o=f+24|0;p=f+20|0;q=f+8|0;r=f+4|0;c[g>>2]=d;c[h>>2]=e;c[n>>2]=(c[g>>2]|0)+4168;c[(c[g>>2]|0)+4164>>2]=a[(c[g>>2]|0)+2736+29>>0];c[j>>2]=0;a:do if((a[(c[g>>2]|0)+2736+29>>0]|0)==2){c[m>>2]=0;while(1){e=_(c[m>>2]|0,c[(c[g>>2]|0)+2332>>2]|0)|0;if((e|0)>=(c[(c[h>>2]|0)+((c[(c[g>>2]|0)+2324>>2]|0)-1<<2)>>2]|0))break;if((c[m>>2]|0)==(c[(c[g>>2]|0)+2324>>2]|0))break;c[k>>2]=0;c[l>>2]=0;while(1){if((c[l>>2]|0)>=5)break;c[k>>2]=(c[k>>2]|0)+(b[(c[h>>2]|0)+96+((((c[(c[g>>2]|0)+2324>>2]|0)-1-(c[m>>2]|0)|0)*5|0)+(c[l>>2]|0)<<1)>>1]|0);c[l>>2]=(c[l>>2]|0)+1}if((c[k>>2]|0)>(c[j>>2]|0)){c[j>>2]=c[k>>2];e=(c[n>>2]|0)+4|0;d=(c[h>>2]|0)+96+((((c[(c[g>>2]|0)+2324>>2]|0)-1-(c[m>>2]|0)&65535)<<16>>16)*5<<1)|0;b[e>>1]=b[d>>1]|0;b[e+2>>1]=b[d+2>>1]|0;b[e+4>>1]=b[d+4>>1]|0;b[e+6>>1]=b[d+6>>1]|0;b[e+8>>1]=b[d+8>>1]|0;c[c[n>>2]>>2]=c[(c[h>>2]|0)+((c[(c[g>>2]|0)+2324>>2]|0)-1-(c[m>>2]|0)<<2)>>2]<<8}c[m>>2]=(c[m>>2]|0)+1}d=(c[n>>2]|0)+4|0;b[d>>1]=0;b[d+2>>1]=0;b[d+4>>1]=0;b[d+6>>1]=0;b[d+8>>1]=0;b[(c[n>>2]|0)+4+4>>1]=c[j>>2];if((c[j>>2]|0)<11469){c[p>>2]=11744256;c[o>>2]=(c[p>>2]|0)/(((c[j>>2]|0)>1?c[j>>2]|0:1)|0)|0;c[l>>2]=0;while(1){if((c[l>>2]|0)>=5)break a;d=(_(b[(c[n>>2]|0)+4+(c[l>>2]<<1)>>1]|0,(c[o>>2]&65535)<<16>>16)|0)>>10&65535;b[(c[n>>2]|0)+4+(c[l>>2]<<1)>>1]=d;c[l>>2]=(c[l>>2]|0)+1}}if((c[j>>2]|0)>15565){c[r>>2]=255016960;c[q>>2]=(c[r>>2]|0)/(((c[j>>2]|0)>1?c[j>>2]|0:1)|0)|0;c[l>>2]=0;while(1){if((c[l>>2]|0)>=5)break a;d=(_(b[(c[n>>2]|0)+4+(c[l>>2]<<1)>>1]|0,(c[q>>2]&65535)<<16>>16)|0)>>14&65535;b[(c[n>>2]|0)+4+(c[l>>2]<<1)>>1]=d;c[l>>2]=(c[l>>2]|0)+1}}}else{c[c[n>>2]>>2]=((c[(c[g>>2]|0)+2316>>2]&65535)<<16>>16)*18<<8;d=(c[n>>2]|0)+4|0;b[d>>1]=0;b[d+2>>1]=0;b[d+4>>1]=0;b[d+6>>1]=0;b[d+8>>1]=0}while(0);df((c[n>>2]|0)+14|0,(c[h>>2]|0)+32+32|0,c[(c[g>>2]|0)+2340>>2]<<1|0)|0;b[(c[n>>2]|0)+68>>1]=c[(c[h>>2]|0)+136>>2];l=(c[n>>2]|0)+72|0;q=(c[h>>2]|0)+16+((c[(c[g>>2]|0)+2324>>2]|0)-2<<2)|0;c[l>>2]=c[q>>2];c[l+4>>2]=c[q+4>>2];c[(c[n>>2]|0)+88>>2]=c[(c[g>>2]|0)+2332>>2];c[(c[n>>2]|0)+84>>2]=c[(c[g>>2]|0)+2324>>2];i=f;return}function Ld(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b;c[d>>2]=a;if(!(c[d>>2]|0)){e=32;i=b;return e|0}e=32-(32-(aa(c[d>>2]|0)|0))|0;i=b;return e|0}function Md(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)>(c[f>>2]|0)?c[e>>2]|0:c[f>>2]|0)|0}function Nd(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0;b=i;i=i+32|0;d=b+16|0;e=b+12|0;f=b+8|0;g=b+4|0;h=b;c[e>>2]=a;if((c[e>>2]|0)<=0){c[d>>2]=0;j=c[d>>2]|0;i=b;return j|0}ke(c[e>>2]|0,g,h);if(c[g>>2]&1)c[f>>2]=32768;else c[f>>2]=46214;c[f>>2]=c[f>>2]>>(c[g>>2]>>1);g=_(c[f>>2]>>16,(((c[h>>2]&65535)<<16>>16)*213&65535)<<16>>16)|0;c[f>>2]=(c[f>>2]|0)+(g+((_(c[f>>2]&65535,(((c[h>>2]&65535)<<16>>16)*213&65535)<<16>>16)|0)>>16));c[d>>2]=c[f>>2];j=c[d>>2]|0;i=b;return j|0}function Od(a,e,f,g,h){a=a|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0;j=i;i=i+32|0;k=j+16|0;l=j+12|0;m=j+8|0;n=j+4|0;o=j;c[k>>2]=a;c[l>>2]=e;c[m>>2]=f;c[n>>2]=g;c[o>>2]=h;if((c[n>>2]|0)>0){h=(jb(c[m>>2]|0,(c[o>>2]|0)+(d[1472+(c[n>>2]|0)>>0]|0)|0,8)|0)&65535;b[c[k>>2]>>1]=h;b[c[l>>2]>>1]=(c[n>>2]|0)-(b[c[k>>2]>>1]|0);i=j;return}else{b[c[k>>2]>>1]=0;b[c[l>>2]>>1]=0;i=j;return}}function Pd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;d=i;i=i+64|0;e=d+44|0;f=d+36|0;g=d+12|0;h=d+8|0;j=d+32|0;k=d+40|0;l=d+48|0;m=d+16|0;n=d;o=d+24|0;p=d+4|0;q=d+28|0;r=d+20|0;c[f>>2]=a;c[g>>2]=b;c[r>>2]=(c[f>>2]|0)+((c[g>>2]&1)<<6);c[l>>2]=1073741824;c[h>>2]=(c[g>>2]|0)-1;while(1){if((c[h>>2]|0)<=0)break;if((c[(c[r>>2]|0)+(c[h>>2]<<2)>>2]|0)>16773022){s=5;break}if((c[(c[r>>2]|0)+(c[h>>2]<<2)>>2]|0)<-16773022){s=5;break}c[m>>2]=0-(c[(c[r>>2]|0)+(c[h>>2]<<2)>>2]<<7);g=c[m>>2]|0;b=c[m>>2]|0;a=of(g|0,((g|0)<0)<<31>>31|0,b|0,((b|0)<0)<<31>>31|0)|0;b=af(a|0,C|0,32)|0;c[n>>2]=1073741824-b;b=c[n>>2]|0;c[k>>2]=32-(ie((c[n>>2]|0)>0?b:0-b|0)|0);c[o>>2]=je(c[n>>2]|0,(c[k>>2]|0)+30|0)|0;b=c[l>>2]|0;a=c[n>>2]|0;g=of(b|0,((b|0)<0)<<31>>31|0,a|0,((a|0)<0)<<31>>31|0)|0;a=af(g|0,C|0,32)|0;c[l>>2]=a<<2;c[q>>2]=c[r>>2];c[r>>2]=(c[f>>2]|0)+((c[h>>2]&1)<<6);c[j>>2]=0;while(1){if((c[j>>2]|0)>=(c[h>>2]|0))break;a=c[(c[q>>2]|0)+(c[j>>2]<<2)>>2]|0;g=c[(c[q>>2]|0)+((c[h>>2]|0)-(c[j>>2]|0)-1<<2)>>2]|0;b=c[m>>2]|0;t=of(g|0,((g|0)<0)<<31>>31|0,b|0,((b|0)<0)<<31>>31|0)|0;b=af(t|0,C|0,30)|0;t=ef(b|0,C|0,1,0)|0;b=af(t|0,C|0,1)|0;c[p>>2]=a-b;b=(c[k>>2]|0)==1;a=c[p>>2]|0;t=c[o>>2]|0;g=of(a|0,((a|0)<0)<<31>>31|0,t|0,((t|0)<0)<<31>>31|0)|0;t=C;if(b){b=af(g|0,t|0,1)|0;a=C;u=c[p>>2]|0;v=c[o>>2]|0;w=of(u|0,((u|0)<0)<<31>>31|0,v|0,((v|0)<0)<<31>>31|0)|0;v=ef(b|0,a|0,w&1|0,0)|0;x=v;y=C}else{v=af(g|0,t|0,(c[k>>2]|0)-1|0)|0;t=ef(v|0,C|0,1,0)|0;v=af(t|0,C|0,1)|0;x=v;y=C}c[(c[r>>2]|0)+(c[j>>2]<<2)>>2]=x;c[j>>2]=(c[j>>2]|0)+1}c[h>>2]=(c[h>>2]|0)+-1}if((s|0)==5){c[e>>2]=0;z=c[e>>2]|0;i=d;return z|0}if((c[c[r>>2]>>2]|0)<=16773022?(c[c[r>>2]>>2]|0)>=-16773022:0){c[m>>2]=0-(c[c[r>>2]>>2]<<7);r=c[m>>2]|0;s=c[m>>2]|0;m=of(r|0,((r|0)<0)<<31>>31|0,s|0,((s|0)<0)<<31>>31|0)|0;s=af(m|0,C|0,32)|0;c[n>>2]=1073741824-s;s=c[l>>2]|0;m=c[n>>2]|0;n=of(s|0,((s|0)<0)<<31>>31|0,m|0,((m|0)<0)<<31>>31|0)|0;m=af(n|0,C|0,32)|0;c[l>>2]=m<<2;c[e>>2]=c[l>>2];z=c[e>>2]|0;i=d;return z|0}c[e>>2]=0;z=c[e>>2]|0;i=d;return z|0}function Qd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;e=i;i=i+32|0;f=e+20|0;g=e+16|0;h=e+12|0;j=e+8|0;k=e+4|0;l=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;c[c[f>>2]>>2]=65536;c[(c[f>>2]|0)+4>>2]=0-(c[c[g>>2]>>2]|0);c[j>>2]=1;while(1){if((c[j>>2]|0)>=(c[h>>2]|0))break;c[l>>2]=c[(c[g>>2]|0)+(c[j>>2]<<1<<2)>>2];d=c[(c[f>>2]|0)+((c[j>>2]|0)-1<<2)>>2]<<1;b=c[l>>2]|0;a=c[(c[f>>2]|0)+(c[j>>2]<<2)>>2]|0;m=of(b|0,((b|0)<0)<<31>>31|0,a|0,((a|0)<0)<<31>>31|0)|0;a=af(m|0,C|0,15)|0;m=ef(a|0,C|0,1,0)|0;a=af(m|0,C|0,1)|0;c[(c[f>>2]|0)+((c[j>>2]|0)+1<<2)>>2]=d-a;c[k>>2]=c[j>>2];while(1){if((c[k>>2]|0)<=1)break;a=c[(c[f>>2]|0)+((c[k>>2]|0)-2<<2)>>2]|0;d=c[l>>2]|0;m=c[(c[f>>2]|0)+((c[k>>2]|0)-1<<2)>>2]|0;b=of(d|0,((d|0)<0)<<31>>31|0,m|0,((m|0)<0)<<31>>31|0)|0;m=af(b|0,C|0,15)|0;b=ef(m|0,C|0,1,0)|0;m=af(b|0,C|0,1)|0;b=(c[f>>2]|0)+(c[k>>2]<<2)|0;c[b>>2]=(c[b>>2]|0)+(a-m);c[k>>2]=(c[k>>2]|0)+-1}m=(c[f>>2]|0)+4|0;c[m>>2]=(c[m>>2]|0)-(c[l>>2]|0);c[j>>2]=(c[j>>2]|0)+1}i=e;return}function Rd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)>(c[f>>2]|0)?c[e>>2]|0:c[f>>2]|0)|0}function Sd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)<(c[f>>2]|0)?c[e>>2]|0:c[f>>2]|0)|0}
+function Ia(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+15&-16;return b|0}function Ja(){return i|0}function Ka(a){a=a|0;i=a}function La(a,b){a=a|0;b=b|0;i=a;j=b}function Ma(a,b){a=a|0;b=b|0;if(!n){n=a;o=b}}function Na(b){b=b|0;a[k>>0]=a[b>>0];a[k+1>>0]=a[b+1>>0];a[k+2>>0]=a[b+2>>0];a[k+3>>0]=a[b+3>>0]}function Oa(b){b=b|0;a[k>>0]=a[b>>0];a[k+1>>0]=a[b+1>>0];a[k+2>>0]=a[b+2>>0];a[k+3>>0]=a[b+3>>0];a[k+4>>0]=a[b+4>>0];a[k+5>>0]=a[b+5>>0];a[k+6>>0]=a[b+6>>0];a[k+7>>0]=a[b+7>>0]}function Pa(a){a=a|0;C=a}function Qa(){return C|0}function Ra(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;a=(_(1664525,c[d>>2]|0)|0)+1013904223|0;i=b;return a|0}function Sa(a,d,e,f,h,j,k,l,m){a=a|0;d=d|0;e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0.0;n=i;i=i+80|0;o=n+68|0;p=n+44|0;q=n+24|0;r=n+32|0;s=n+12|0;t=n+16|0;u=n+48|0;v=n+56|0;w=n+64|0;x=n+72|0;y=n+36|0;z=n+8|0;A=n;B=n+4|0;C=n+40|0;D=n+20|0;E=n+52|0;F=n+28|0;G=n+60|0;c[o>>2]=a;c[p>>2]=d;c[q>>2]=e;c[r>>2]=f;c[s>>2]=h;c[t>>2]=j;c[u>>2]=k;c[v>>2]=l;c[w>>2]=m;c[C>>2]=c[(c[o>>2]|0)+32>>2];c[y>>2]=_(c[u>>2]|0,c[(c[o>>2]|0)+44>>2]|0)|0;c[z>>2]=_(c[u>>2]|0,b[(c[C>>2]|0)+(c[t>>2]<<1)>>1]|0)|0;if((c[v>>2]|0)!=1){if((c[z>>2]|0)<((c[y>>2]|0)/(c[v>>2]|0)|0|0))H=c[z>>2]|0;else H=(c[y>>2]|0)/(c[v>>2]|0)|0;c[z>>2]=H}if(c[w>>2]|0){c[z>>2]=0;c[t>>2]=0;c[s>>2]=0}c[A>>2]=c[q>>2];c[B>>2]=(c[p>>2]|0)+((_(c[u>>2]|0,b[(c[C>>2]|0)+(c[s>>2]<<1)>>1]|0)|0)<<2);c[x>>2]=0;while(1){if((c[x>>2]|0)>=(_(c[u>>2]|0,b[(c[C>>2]|0)+(c[s>>2]<<1)>>1]|0)|0))break;p=c[A>>2]|0;c[A>>2]=p+4;g[p>>2]=0.0;c[x>>2]=(c[x>>2]|0)+1}c[x>>2]=c[s>>2];while(1){if((c[x>>2]|0)>=(c[t>>2]|0))break;c[D>>2]=_(c[u>>2]|0,b[(c[C>>2]|0)+(c[x>>2]<<1)>>1]|0)|0;c[E>>2]=_(c[u>>2]|0,b[(c[C>>2]|0)+((c[x>>2]|0)+1<<1)>>1]|0)|0;g[G>>2]=+g[(c[r>>2]|0)+(c[x>>2]<<2)>>2]+ +g[40+(c[x>>2]<<2)>>2];g[F>>2]=+X(+(+g[G>>2]*.6931471805599453));do{s=c[B>>2]|0;c[B>>2]=s+4;I=+g[s>>2]*+g[F>>2];s=c[A>>2]|0;c[A>>2]=s+4;g[s>>2]=I;s=(c[D>>2]|0)+1|0;c[D>>2]=s}while((s|0)<(c[E>>2]|0));c[x>>2]=(c[x>>2]|0)+1}bf((c[q>>2]|0)+(c[z>>2]<<2)|0,0,(c[y>>2]|0)-(c[z>>2]|0)<<2|0)|0;i=n;return}function Ta(a,e,f,h,j,k,l,m,n,o,p,q,r){a=a|0;e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0;q=q|0;r=r|0;var s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0.0,W=0.0,Y=0.0;s=i;i=i+112|0;t=s+100|0;u=s+92|0;v=s+44|0;w=s+48|0;x=s+84|0;y=s+16|0;z=s+20|0;A=s+24|0;B=s+28|0;C=s+32|0;D=s+80|0;E=s+88|0;F=s+96|0;G=s+104|0;H=s+52|0;I=s+56|0;J=s+60|0;K=s+64|0;L=s+68|0;M=s+12|0;N=s+8|0;P=s+72|0;Q=s+36|0;R=s+76|0;S=s+4|0;T=s;U=s+40|0;c[t>>2]=a;c[u>>2]=e;c[v>>2]=f;c[w>>2]=h;c[x>>2]=j;c[y>>2]=k;c[z>>2]=l;c[A>>2]=m;c[B>>2]=n;c[C>>2]=o;c[D>>2]=p;c[E>>2]=q;c[F>>2]=r;c[H>>2]=c[z>>2];while(1){if((c[H>>2]|0)>=(c[A>>2]|0))break;c[K>>2]=(b[(c[(c[t>>2]|0)+32>>2]|0)+((c[H>>2]|0)+1<<1)>>1]|0)-(b[(c[(c[t>>2]|0)+32>>2]|0)+(c[H>>2]<<1)>>1]|0);z=Rc(1+(c[(c[E>>2]|0)+(c[H>>2]<<2)>>2]|0)|0,(b[(c[(c[t>>2]|0)+32>>2]|0)+((c[H>>2]|0)+1<<1)>>1]|0)-(b[(c[(c[t>>2]|0)+32>>2]|0)+(c[H>>2]<<1)>>1]|0)|0)|0;c[N>>2]=z>>>(c[w>>2]|0);g[L>>2]=+X(+(+(c[N>>2]|0)*-.125*.6931471805599453))*.5;g[M>>2]=1.0/+O(+(+(c[K>>2]<<c[w>>2]|0)));c[G>>2]=0;do{c[U>>2]=0;z=_(c[G>>2]|0,c[(c[t>>2]|0)+8>>2]|0)|0;g[Q>>2]=+g[(c[C>>2]|0)+(z+(c[H>>2]|0)<<2)>>2];z=_(c[G>>2]|0,c[(c[t>>2]|0)+8>>2]|0)|0;g[R>>2]=+g[(c[D>>2]|0)+(z+(c[H>>2]|0)<<2)>>2];if((c[x>>2]|0)==1){if(+g[Q>>2]>+g[(c[C>>2]|0)+((c[(c[t>>2]|0)+8>>2]|0)+(c[H>>2]|0)<<2)>>2])V=+g[Q>>2];else V=+g[(c[C>>2]|0)+((c[(c[t>>2]|0)+8>>2]|0)+(c[H>>2]|0)<<2)>>2];g[Q>>2]=V;if(+g[R>>2]>+g[(c[D>>2]|0)+((c[(c[t>>2]|0)+8>>2]|0)+(c[H>>2]|0)<<2)>>2])W=+g[R>>2];else W=+g[(c[D>>2]|0)+((c[(c[t>>2]|0)+8>>2]|0)+(c[H>>2]|0)<<2)>>2];g[R>>2]=W}z=_(c[G>>2]|0,c[(c[t>>2]|0)+8>>2]|0)|0;g[S>>2]=+g[(c[B>>2]|0)+(z+(c[H>>2]|0)<<2)>>2]-(+g[Q>>2]<+g[R>>2]?+g[Q>>2]:+g[R>>2]);g[S>>2]=0.0>+g[S>>2]?0.0:+g[S>>2];g[T>>2]=+X(+(-+g[S>>2]*.6931471805599453))*2.0;if((c[w>>2]|0)==3)g[T>>2]=+g[T>>2]*1.4142135381698608;g[T>>2]=+g[L>>2]<+g[T>>2]?+g[L>>2]:+g[T>>2];g[T>>2]=+g[T>>2]*+g[M>>2];z=(c[u>>2]|0)+((_(c[G>>2]|0,c[y>>2]|0)|0)<<2)|0;c[P>>2]=z+(b[(c[(c[t>>2]|0)+32>>2]|0)+(c[H>>2]<<1)>>1]<<c[w>>2]<<2);c[J>>2]=0;while(1){if((c[J>>2]|0)>=(1<<c[w>>2]|0))break;z=_(c[H>>2]|0,c[x>>2]|0)|0;if(!(d[(c[v>>2]|0)+(z+(c[G>>2]|0))>>0]&1<<c[J>>2])){c[I>>2]=0;while(1){if((c[I>>2]|0)>=(c[K>>2]|0))break;c[F>>2]=Ra(c[F>>2]|0)|0;Y=+g[T>>2];g[(c[P>>2]|0)+((c[I>>2]<<c[w>>2])+(c[J>>2]|0)<<2)>>2]=(c[F>>2]&32768|0)!=0?Y:-Y;c[I>>2]=(c[I>>2]|0)+1}c[U>>2]=1}c[J>>2]=(c[J>>2]|0)+1}if(c[U>>2]|0)Ib(c[P>>2]|0,c[K>>2]<<c[w>>2],1.0);z=(c[G>>2]|0)+1|0;c[G>>2]=z}while((z|0)<(c[x>>2]|0));c[H>>2]=(c[H>>2]|0)+1}i=s;return}function Ua(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;i=i+32|0;f=e+8|0;h=e+16|0;j=e+20|0;k=e+24|0;l=e+4|0;m=e;n=e+12|0;c[f>>2]=a;c[h>>2]=b;c[j>>2]=d;c[h>>2]=c[h>>2]>>1;c[k>>2]=0;while(1){if((c[k>>2]|0)>=(c[j>>2]|0))break;c[l>>2]=0;while(1){if((c[l>>2]|0)>=(c[h>>2]|0))break;d=_(c[j>>2]<<1,c[l>>2]|0)|0;g[m>>2]=+g[(c[f>>2]|0)+(d+(c[k>>2]|0)<<2)>>2]*.7071067690849304;d=_(c[j>>2]|0,(c[l>>2]<<1)+1|0)|0;g[n>>2]=+g[(c[f>>2]|0)+(d+(c[k>>2]|0)<<2)>>2]*.7071067690849304;d=_(c[j>>2]<<1,c[l>>2]|0)|0;g[(c[f>>2]|0)+(d+(c[k>>2]|0)<<2)>>2]=+g[m>>2]+ +g[n>>2];d=_(c[j>>2]|0,(c[l>>2]<<1)+1|0)|0;g[(c[f>>2]|0)+(d+(c[k>>2]|0)<<2)>>2]=+g[m>>2]-+g[n>>2];c[l>>2]=(c[l>>2]|0)+1}c[k>>2]=(c[k>>2]|0)+1}i=e;return}function Va(e,f,h,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z){e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0;q=q|0;r=r|0;s=s|0;t=t|0;u=u|0;v=v|0;w=w|0;x=x|0;y=y|0;z=z|0;var A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0;A=i;i=i+240|0;B=A+96|0;C=A+92|0;D=A+84|0;E=A+200|0;F=A+224|0;G=A+216|0;H=A+20|0;I=A+24|0;J=A+28|0;K=A+32|0;L=A+36|0;M=A+40|0;N=A+44|0;O=A+48|0;P=A+52|0;Q=A+56|0;R=A+60|0;S=A+64|0;T=A+68|0;U=A+72|0;V=A+196|0;W=A+204|0;X=A+212|0;Y=A+220|0;Z=A+228|0;$=A+232|0;aa=A+100|0;ba=A+104|0;ca=A+108|0;da=A+112|0;ea=A+116|0;fa=A+120|0;ga=A+124|0;ha=A+128|0;ia=A+168|0;ja=A+172|0;la=A+176|0;ma=A+180|0;na=A+184|0;oa=A+188|0;pa=A+16|0;qa=A+8|0;ra=A;sa=A+12|0;ta=A+4|0;va=A+192|0;wa=A+76|0;xa=A+80|0;ya=A+208|0;za=A+88|0;c[B>>2]=e;c[C>>2]=f;c[D>>2]=h;c[E>>2]=j;c[F>>2]=k;c[G>>2]=l;c[H>>2]=m;c[I>>2]=n;c[J>>2]=o;c[K>>2]=p;c[L>>2]=q;c[M>>2]=r;c[N>>2]=s;c[O>>2]=t;c[P>>2]=u;c[Q>>2]=v;c[R>>2]=w;c[S>>2]=x;c[T>>2]=y;c[U>>2]=z;c[X>>2]=c[(c[C>>2]|0)+32>>2];c[da>>2]=1;c[ea>>2]=(c[G>>2]|0)!=0?2:1;c[ga>>2]=((c[B>>2]|0)!=0^1)&1;c[ba>>2]=1<<c[S>>2];c[aa>>2]=(c[K>>2]|0)!=0?c[ba>>2]|0:1;c[fa>>2]=_(c[ba>>2]|0,b[(c[X>>2]|0)+(c[D>>2]<<1)>>1]|0)|0;K=_(c[ba>>2]|0,b[(c[X>>2]|0)+((c[(c[C>>2]|0)+8>>2]|0)-1<<1)>>1]|0)|0;z=_(c[ea>>2]|0,K-(c[fa>>2]|0)|0)|0;c[ia>>2]=ua()|0;K=i;i=i+((1*(z<<2)|0)+15&-16)|0;c[Y>>2]=K;K=(c[Y>>2]|0)+((_(c[ba>>2]|0,b[(c[X>>2]|0)+((c[(c[C>>2]|0)+8>>2]|0)-1<<1)>>1]|0)|0)<<2)|0;c[Z>>2]=K+(0-(c[fa>>2]|0)<<2);c[$>>2]=(c[F>>2]|0)+((_(c[ba>>2]|0,b[(c[X>>2]|0)+((c[(c[C>>2]|0)+8>>2]|0)-1<<1)>>1]|0)|0)<<2);c[ca>>2]=0;c[ha+32>>2]=c[I>>2];c[ha+24>>2]=c[R>>2];c[ha>>2]=c[B>>2];c[ha+12>>2]=c[N>>2];c[ha+4>>2]=c[C>>2];c[ha+36>>2]=c[c[U>>2]>>2];c[ha+16>>2]=c[L>>2];c[V>>2]=c[D>>2];while(1){if((c[V>>2]|0)>=(c[E>>2]|0))break;c[oa>>2]=-1;c[ra>>2]=0;c[ha+8>>2]=c[V>>2];c[va>>2]=(c[V>>2]|0)==((c[E>>2]|0)-1|0)&1;c[pa>>2]=(c[F>>2]|0)+((_(c[ba>>2]|0,b[(c[X>>2]|0)+(c[V>>2]<<1)>>1]|0)|0)<<2);if(c[G>>2]|0)c[qa>>2]=(c[G>>2]|0)+((_(c[ba>>2]|0,b[(c[X>>2]|0)+(c[V>>2]<<1)>>1]|0)|0)<<2);else c[qa>>2]=0;B=_(c[ba>>2]|0,b[(c[X>>2]|0)+((c[V>>2]|0)+1<<1)>>1]|0)|0;c[ma>>2]=B-(_(c[ba>>2]|0,b[(c[X>>2]|0)+(c[V>>2]<<1)>>1]|0)|0);c[ja>>2]=db(c[R>>2]|0)|0;if((c[V>>2]|0)!=(c[D>>2]|0))c[Q>>2]=(c[Q>>2]|0)-(c[ja>>2]|0);c[W>>2]=(c[P>>2]|0)-(c[ja>>2]|0)-1;c[ha+28>>2]=c[W>>2];if((c[V>>2]|0)<=((c[T>>2]|0)-1|0)){if(3<((c[T>>2]|0)-(c[V>>2]|0)|0))Aa=3;else Aa=(c[T>>2]|0)-(c[V>>2]|0)|0;c[na>>2]=Sc(c[Q>>2]|0,Aa)|0;if(((c[W>>2]|0)+1|0)<((c[(c[J>>2]|0)+(c[V>>2]<<2)>>2]|0)+(c[na>>2]|0)|0))Ba=(c[W>>2]|0)+1|0;else Ba=(c[(c[J>>2]|0)+(c[V>>2]<<2)>>2]|0)+(c[na>>2]|0)|0;do if(16383>=(Ba|0))if(((c[W>>2]|0)+1|0)<((c[(c[J>>2]|0)+(c[V>>2]<<2)>>2]|0)+(c[na>>2]|0)|0)){Ca=(c[W>>2]|0)+1|0;break}else{Ca=(c[(c[J>>2]|0)+(c[V>>2]<<2)>>2]|0)+(c[na>>2]|0)|0;break}else Ca=16383;while(0);do if(0<=(Ca|0)){if(((c[W>>2]|0)+1|0)<((c[(c[J>>2]|0)+(c[V>>2]<<2)>>2]|0)+(c[na>>2]|0)|0))Da=(c[W>>2]|0)+1|0;else Da=(c[(c[J>>2]|0)+(c[V>>2]<<2)>>2]|0)+(c[na>>2]|0)|0;if(16383>=(Da|0))if(((c[W>>2]|0)+1|0)<((c[(c[J>>2]|0)+(c[V>>2]<<2)>>2]|0)+(c[na>>2]|0)|0)){Ea=(c[W>>2]|0)+1|0;break}else{Ea=(c[(c[J>>2]|0)+(c[V>>2]<<2)>>2]|0)+(c[na>>2]|0)|0;break}else Ea=16383}else Ea=0;while(0);c[la>>2]=Ea}else c[la>>2]=0;if(((c[ga>>2]|0)!=0?(B=_(c[ba>>2]|0,b[(c[X>>2]|0)+(c[V>>2]<<1)>>1]|0)|0,(B-(c[ma>>2]|0)|0)>=(_(c[ba>>2]|0,b[(c[X>>2]|0)+(c[D>>2]<<1)>>1]|0)|0)):0)?(c[da>>2]|0)!=0|(c[ca>>2]|0)==0:0)c[ca>>2]=c[V>>2];c[ra>>2]=c[(c[O>>2]|0)+(c[V>>2]<<2)>>2];c[ha+20>>2]=c[ra>>2];if((c[V>>2]|0)>=(c[(c[C>>2]|0)+12>>2]|0)){c[pa>>2]=c[Y>>2];if(c[G>>2]|0)c[qa>>2]=c[Y>>2];c[$>>2]=0}if((c[V>>2]|0)==((c[E>>2]|0)-1|0))c[$>>2]=0;if((c[ca>>2]|0)!=0?(c[L>>2]|0)!=3|(c[aa>>2]|0)>1|(c[ra>>2]|0)<0:0){B=_(c[ba>>2]|0,b[(c[X>>2]|0)+(c[ca>>2]<<1)>>1]|0)|0;if(0>(B-(c[fa>>2]|0)-(c[ma>>2]|0)|0))Fa=0;else{B=_(c[ba>>2]|0,b[(c[X>>2]|0)+(c[ca>>2]<<1)>>1]|0)|0;Fa=B-(c[fa>>2]|0)-(c[ma>>2]|0)|0}c[oa>>2]=Fa;c[wa>>2]=c[ca>>2];do{B=c[ba>>2]|0;I=(c[wa>>2]|0)+-1|0;c[wa>>2]=I;K=_(B,b[(c[X>>2]|0)+(I<<1)>>1]|0)|0}while((K|0)>((c[oa>>2]|0)+(c[fa>>2]|0)|0));c[xa>>2]=(c[ca>>2]|0)-1;do{K=c[ba>>2]|0;I=(c[xa>>2]|0)+1|0;c[xa>>2]=I;B=_(K,b[(c[X>>2]|0)+(I<<1)>>1]|0)|0}while((B|0)<((c[oa>>2]|0)+(c[fa>>2]|0)+(c[ma>>2]|0)|0));c[ta>>2]=0;c[sa>>2]=0;c[ya>>2]=c[wa>>2];do{B=(_(c[ya>>2]|0,c[ea>>2]|0)|0)+0|0;c[sa>>2]=c[sa>>2]|d[(c[H>>2]|0)+B>>0];B=_(c[ya>>2]|0,c[ea>>2]|0)|0;c[ta>>2]=c[ta>>2]|d[(c[H>>2]|0)+(B+(c[ea>>2]|0)-1)>>0];B=(c[ya>>2]|0)+1|0;c[ya>>2]=B}while((B|0)<(c[xa>>2]|0))}else{B=(1<<c[aa>>2])-1|0;c[ta>>2]=B;c[sa>>2]=B}a:do if(((c[M>>2]|0)!=0?(c[V>>2]|0)==(c[N>>2]|0):0)?(c[M>>2]=0,(c[ga>>2]|0)!=0):0){c[za>>2]=0;while(1){B=_(c[ba>>2]|0,b[(c[X>>2]|0)+(c[V>>2]<<1)>>1]|0)|0;if((c[za>>2]|0)>=(B-(c[fa>>2]|0)|0))break a;g[(c[Y>>2]|0)+(c[za>>2]<<2)>>2]=(+g[(c[Y>>2]|0)+(c[za>>2]<<2)>>2]+ +g[(c[Z>>2]|0)+(c[za>>2]<<2)>>2])*.5;c[za>>2]=(c[za>>2]|0)+1}}while(0);if(c[M>>2]|0){if((c[oa>>2]|0)!=-1)Ga=(c[Y>>2]|0)+(c[oa>>2]<<2)|0;else Ga=0;if(c[va>>2]|0)Ha=0;else{B=(c[Y>>2]|0)+((_(c[ba>>2]|0,b[(c[X>>2]|0)+(c[V>>2]<<1)>>1]|0)|0)<<2)|0;Ha=B+(0-(c[fa>>2]|0)<<2)|0}c[sa>>2]=Tc(ha,c[pa>>2]|0,c[ma>>2]|0,(c[la>>2]|0)/2|0,c[aa>>2]|0,Ga,c[S>>2]|0,Ha,1.0,c[$>>2]|0,c[sa>>2]|0)|0;if((c[oa>>2]|0)!=-1)Ia=(c[Z>>2]|0)+(c[oa>>2]<<2)|0;else Ia=0;if(c[va>>2]|0)Ja=0;else{B=(c[Z>>2]|0)+((_(c[ba>>2]|0,b[(c[X>>2]|0)+(c[V>>2]<<1)>>1]|0)|0)<<2)|0;Ja=B+(0-(c[fa>>2]|0)<<2)|0}c[ta>>2]=Tc(ha,c[qa>>2]|0,c[ma>>2]|0,(c[la>>2]|0)/2|0,c[aa>>2]|0,Ia,c[S>>2]|0,Ja,1.0,c[$>>2]|0,c[ta>>2]|0)|0}else{B=c[pa>>2]|0;if(c[qa>>2]|0){if((c[oa>>2]|0)!=-1)Ka=(c[Y>>2]|0)+(c[oa>>2]<<2)|0;else Ka=0;if(c[va>>2]|0)La=0;else{I=(c[Y>>2]|0)+((_(c[ba>>2]|0,b[(c[X>>2]|0)+(c[V>>2]<<1)>>1]|0)|0)<<2)|0;La=I+(0-(c[fa>>2]|0)<<2)|0}c[sa>>2]=Uc(ha,B,c[qa>>2]|0,c[ma>>2]|0,c[la>>2]|0,c[aa>>2]|0,Ka,c[S>>2]|0,La,c[$>>2]|0,c[sa>>2]|c[ta>>2])|0}else{if((c[oa>>2]|0)!=-1)Ma=(c[Y>>2]|0)+(c[oa>>2]<<2)|0;else Ma=0;if(c[va>>2]|0)Na=0;else{I=(c[Y>>2]|0)+((_(c[ba>>2]|0,b[(c[X>>2]|0)+(c[V>>2]<<1)>>1]|0)|0)<<2)|0;Na=I+(0-(c[fa>>2]|0)<<2)|0}c[sa>>2]=Tc(ha,B,c[ma>>2]|0,c[la>>2]|0,c[aa>>2]|0,Ma,c[S>>2]|0,Na,1.0,c[$>>2]|0,c[sa>>2]|c[ta>>2])|0}c[ta>>2]=c[sa>>2]}B=(_(c[V>>2]|0,c[ea>>2]|0)|0)+0|0;a[(c[H>>2]|0)+B>>0]=c[sa>>2];B=_(c[V>>2]|0,c[ea>>2]|0)|0;a[(c[H>>2]|0)+(B+(c[ea>>2]|0)-1)>>0]=c[ta>>2];c[Q>>2]=(c[Q>>2]|0)+((c[(c[J>>2]|0)+(c[V>>2]<<2)>>2]|0)+(c[ja>>2]|0));c[da>>2]=(c[la>>2]|0)>(c[ma>>2]<<3|0)&1;c[V>>2]=(c[V>>2]|0)+1}c[c[U>>2]>>2]=c[ha+36>>2];ka(c[ia>>2]|0);i=A;return}function Wa(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b+4|0;e=b;c[d>>2]=a;a=c[d>>2]|0;if((a|0)==8e3)c[e>>2]=6;else if((a|0)==48e3)c[e>>2]=1;else if((a|0)==24e3)c[e>>2]=2;else if((a|0)==16e3)c[e>>2]=3;else if((a|0)==12e3)c[e>>2]=4;else c[e>>2]=0;i=b;return c[e>>2]|0}function Xa(a,b,d,e,f,h,j,k,l,m,n){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=+h;j=+j;k=k|0;l=l|0;m=m|0;n=n|0;var o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;o=i;i=i+96|0;p=o+44|0;q=o+40|0;r=o+4|0;s=o+84|0;t=o;u=o+16|0;v=o+20|0;w=o+24|0;x=o+64|0;y=o+72|0;z=o+80|0;A=o+88|0;B=o+92|0;C=o+48|0;D=o+52|0;E=o+56|0;F=o+8|0;G=o+60|0;H=o+28|0;I=o+12|0;J=o+32|0;K=o+68|0;L=o+36|0;M=o+76|0;c[p>>2]=a;c[q>>2]=b;c[r>>2]=d;c[s>>2]=e;c[t>>2]=f;g[u>>2]=h;g[v>>2]=j;c[w>>2]=k;c[x>>2]=l;c[y>>2]=m;c[z>>2]=n;if(+g[u>>2]==0.0&+g[v>>2]==0.0){if((c[q>>2]|0)==(c[p>>2]|0)){i=o;return}ff(c[p>>2]|0,c[q>>2]|0,(c[t>>2]<<2)+0|0)|0;i=o;return}g[B>>2]=+g[u>>2]*+g[2376+((c[w>>2]|0)*12|0)>>2];g[C>>2]=+g[u>>2]*+g[2376+((c[w>>2]|0)*12|0)+4>>2];g[D>>2]=+g[u>>2]*+g[2376+((c[w>>2]|0)*12|0)+8>>2];g[E>>2]=+g[v>>2]*+g[2376+((c[x>>2]|0)*12|0)>>2];g[F>>2]=+g[v>>2]*+g[2376+((c[x>>2]|0)*12|0)+4>>2];g[G>>2]=+g[v>>2]*+g[2376+((c[x>>2]|0)*12|0)+8>>2];g[I>>2]=+g[(c[q>>2]|0)+(0-(c[s>>2]|0)+1<<2)>>2];g[J>>2]=+g[(c[q>>2]|0)+(0-(c[s>>2]|0)<<2)>>2];g[K>>2]=+g[(c[q>>2]|0)+(0-(c[s>>2]|0)-1<<2)>>2];g[L>>2]=+g[(c[q>>2]|0)+(0-(c[s>>2]|0)-2<<2)>>2];if((+g[u>>2]==+g[v>>2]?(c[r>>2]|0)==(c[s>>2]|0):0)?(c[w>>2]|0)==(c[x>>2]|0):0)c[z>>2]=0;c[A>>2]=0;while(1){if((c[A>>2]|0)>=(c[z>>2]|0))break;g[H>>2]=+g[(c[q>>2]|0)+((c[A>>2]|0)-(c[s>>2]|0)+2<<2)>>2];g[M>>2]=+g[(c[y>>2]|0)+(c[A>>2]<<2)>>2]*+g[(c[y>>2]|0)+(c[A>>2]<<2)>>2];g[(c[p>>2]|0)+(c[A>>2]<<2)>>2]=+g[(c[q>>2]|0)+(c[A>>2]<<2)>>2]+(1.0-+g[M>>2])*+g[B>>2]*+g[(c[q>>2]|0)+((c[A>>2]|0)-(c[r>>2]|0)<<2)>>2]+(1.0-+g[M>>2])*+g[C>>2]*(+g[(c[q>>2]|0)+((c[A>>2]|0)-(c[r>>2]|0)+1<<2)>>2]+ +g[(c[q>>2]|0)+((c[A>>2]|0)-(c[r>>2]|0)-1<<2)>>2])+(1.0-+g[M>>2])*+g[D>>2]*(+g[(c[q>>2]|0)+((c[A>>2]|0)-(c[r>>2]|0)+2<<2)>>2]+ +g[(c[q>>2]|0)+((c[A>>2]|0)-(c[r>>2]|0)-2<<2)>>2])+ +g[M>>2]*+g[E>>2]*+g[J>>2]+ +g[M>>2]*+g[F>>2]*(+g[I>>2]+ +g[K>>2])+ +g[M>>2]*+g[G>>2]*(+g[H>>2]+ +g[L>>2]);g[L>>2]=+g[K>>2];g[K>>2]=+g[J>>2];g[J>>2]=+g[I>>2];g[I>>2]=+g[H>>2];c[A>>2]=(c[A>>2]|0)+1}if(!(+g[v>>2]==0.0)){Vc((c[p>>2]|0)+(c[A>>2]<<2)|0,(c[q>>2]|0)+(c[A>>2]<<2)|0,c[s>>2]|0,(c[t>>2]|0)-(c[A>>2]|0)|0,+g[E>>2],+g[F>>2],+g[G>>2]);i=o;return}if((c[q>>2]|0)==(c[p>>2]|0)){i=o;return}ff((c[p>>2]|0)+(c[z>>2]<<2)|0,(c[q>>2]|0)+(c[z>>2]<<2)|0,((c[t>>2]|0)-(c[z>>2]|0)<<2)+0|0)|0;i=o;return}function Ya(a,e,f,g){a=a|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0;h=i;i=i+32|0;j=h+20|0;k=h+16|0;l=h+12|0;m=h+8|0;n=h+4|0;o=h;c[j>>2]=a;c[k>>2]=e;c[l>>2]=f;c[m>>2]=g;c[n>>2]=0;while(1){if((c[n>>2]|0)>=(c[(c[j>>2]|0)+8>>2]|0))break;c[o>>2]=(b[(c[(c[j>>2]|0)+32>>2]|0)+((c[n>>2]|0)+1<<1)>>1]|0)-(b[(c[(c[j>>2]|0)+32>>2]|0)+(c[n>>2]<<1)>>1]|0)<<c[l>>2];g=_(c[(c[j>>2]|0)+8>>2]|0,(c[l>>2]<<1)+(c[m>>2]|0)-1|0)|0;f=_((d[(c[(c[j>>2]|0)+92+12>>2]|0)+(g+(c[n>>2]|0))>>0]|0)+64|0,c[m>>2]|0)|0;g=(_(f,c[o>>2]|0)|0)>>2;c[(c[k>>2]|0)+(c[n>>2]<<2)>>2]=g;c[n>>2]=(c[n>>2]|0)+1}i=h;return}function Za(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b+4|0;e=b;c[d>>2]=a;c[e>>2]=ub(48e3,960,0)|0;a=Wc(c[e>>2]|0,c[d>>2]|0)|0;i=b;return a|0}function _a(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e+4|0;k=e;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;d=c[g>>2]|0;b=ub(48e3,960,0)|0;c[k>>2]=Xc(d,b,c[j>>2]|0)|0;if(c[k>>2]|0){c[f>>2]=c[k>>2];l=c[f>>2]|0;i=e;return l|0}k=Wa(c[h>>2]|0)|0;c[(c[g>>2]|0)+16>>2]=k;if(!(c[(c[g>>2]|0)+16>>2]|0)){c[f>>2]=-1;l=c[f>>2]|0;i=e;return l|0}else{c[f>>2]=0;l=c[f>>2]|0;i=e;return l|0}return 0}function $a(a,d,e,f,h,j,k){a=a|0;d=d|0;e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0.0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0.0,Ca=0.0,Da=0;l=i;i=i+288|0;m=l+164|0;n=l+148|0;o=l+4|0;p=l+8|0;q=l+144|0;r=l+272|0;s=l+160|0;t=l+24|0;u=l+28|0;v=l+32|0;w=l+36|0;x=l+40|0;y=l+44|0;z=l+48|0;A=l+96|0;B=l+104|0;C=l+112|0;D=l+116|0;E=l+120|0;F=l+124|0;G=l+128|0;H=l+132|0;I=l+136|0;J=l+140|0;K=l+244|0;L=l+252|0;M=l+260|0;N=l+268|0;O=l+276|0;P=l+280|0;Q=l+168|0;R=l+172|0;S=l+176|0;T=l+180|0;U=l+184|0;V=l+188|0;W=l+192|0;X=l+196|0;Y=l+200|0;Z=l+204|0;$=l+208|0;aa=l+212|0;ba=l+216|0;ca=l+220|0;da=l+224|0;ea=l+228|0;fa=l+232|0;ga=l+236|0;ha=l+16|0;ia=l;ja=l+12|0;la=l+240|0;ma=l+248|0;na=l+152|0;oa=l+256|0;pa=l+20|0;qa=l+156|0;ra=l+264|0;c[n>>2]=a;c[o>>2]=d;c[p>>2]=e;c[q>>2]=f;c[r>>2]=h;c[s>>2]=j;c[t>>2]=k;c[K>>2]=c[(c[n>>2]|0)+8>>2];c[U>>2]=0;c[V>>2]=0;c[ba>>2]=0;c[da>>2]=c[(c[n>>2]|0)+12>>2];c[ea>>2]=c[c[n>>2]>>2];c[fa>>2]=c[(c[ea>>2]|0)+8>>2];c[ga>>2]=c[(c[ea>>2]|0)+4>>2];c[ha>>2]=c[(c[ea>>2]|0)+32>>2];c[N>>2]=c[(c[n>>2]|0)+20>>2];c[O>>2]=c[(c[n>>2]|0)+24>>2];c[r>>2]=_(c[r>>2]|0,c[(c[n>>2]|0)+16>>2]|0)|0;c[C>>2]=(c[n>>2]|0)+84+((_(2048+(c[ga>>2]|0)|0,c[K>>2]|0)|0)<<2);c[D>>2]=(c[C>>2]|0)+((c[K>>2]|0)*24<<2);c[E>>2]=(c[D>>2]|0)+(c[fa>>2]<<1<<2);c[F>>2]=(c[E>>2]|0)+(c[fa>>2]<<1<<2);c[G>>2]=(c[F>>2]|0)+(c[fa>>2]<<1<<2);c[L>>2]=0;while(1){if((c[L>>2]|0)>(c[(c[ea>>2]|0)+36>>2]|0))break;if((c[(c[ea>>2]|0)+44>>2]<<c[L>>2]|0)==(c[r>>2]|0))break;c[L>>2]=(c[L>>2]|0)+1}if((c[L>>2]|0)>(c[(c[ea>>2]|0)+36>>2]|0)){c[m>>2]=-1;sa=c[m>>2]|0;i=l;return sa|0}c[M>>2]=1<<c[L>>2];if((c[p>>2]|0)<0|(c[p>>2]|0)>1275|(c[q>>2]|0)==0){c[m>>2]=-1;sa=c[m>>2]|0;i=l;return sa|0}c[w>>2]=_(c[M>>2]|0,c[(c[ea>>2]|0)+44>>2]|0)|0;c[u>>2]=0;do{C=(c[n>>2]|0)+84+((_(c[u>>2]|0,2048+(c[ga>>2]|0)|0)|0)<<2)|0;c[A+(c[u>>2]<<2)>>2]=C;c[B+(c[u>>2]<<2)>>2]=(c[A+(c[u>>2]<<2)>>2]|0)+8192+(0-(c[w>>2]|0)<<2);C=(c[u>>2]|0)+1|0;c[u>>2]=C}while((C|0)<(c[K>>2]|0));c[P>>2]=c[O>>2];if((c[P>>2]|0)>(c[(c[ea>>2]|0)+12>>2]|0))c[P>>2]=c[(c[ea>>2]|0)+12>>2];if((c[o>>2]|0)==0|(c[p>>2]|0)<=1){Yc(c[n>>2]|0,c[w>>2]|0,c[L>>2]|0);Zc(B,c[q>>2]|0,c[w>>2]|0,c[K>>2]|0,c[(c[n>>2]|0)+16>>2]|0,(c[ea>>2]|0)+16|0,(c[n>>2]|0)+76|0,c[t>>2]|0);c[m>>2]=(c[r>>2]|0)/(c[(c[n>>2]|0)+16>>2]|0)|0;sa=c[m>>2]|0;i=l;return sa|0}if(!(c[s>>2]|0)){eb(z,c[o>>2]|0,c[p>>2]|0);c[s>>2]=z}a:do if((c[da>>2]|0)==1){c[v>>2]=0;while(1){if((c[v>>2]|0)>=(c[fa>>2]|0))break a;if(+g[(c[D>>2]|0)+(c[v>>2]<<2)>>2]>+g[(c[D>>2]|0)+((c[fa>>2]|0)+(c[v>>2]|0)<<2)>>2])ta=+g[(c[D>>2]|0)+(c[v>>2]<<2)>>2];else ta=+g[(c[D>>2]|0)+((c[fa>>2]|0)+(c[v>>2]|0)<<2)>>2];g[(c[D>>2]|0)+(c[v>>2]<<2)>>2]=ta;c[v>>2]=(c[v>>2]|0)+1}}while(0);c[W>>2]=c[p>>2]<<3;c[Y>>2]=_c(c[s>>2]|0)|0;do if((c[Y>>2]|0)<(c[W>>2]|0))if((c[Y>>2]|0)==1){c[ca>>2]=ib(c[s>>2]|0,15)|0;break}else{c[ca>>2]=0;break}else c[ca>>2]=1;while(0);if(c[ca>>2]|0){c[Y>>2]=c[p>>2]<<3;z=c[Y>>2]|0;o=z-(_c(c[s>>2]|0)|0)|0;z=(c[s>>2]|0)+20|0;c[z>>2]=(c[z>>2]|0)+o}g[T>>2]=0.0;c[S>>2]=0;c[$>>2]=0;if((c[N>>2]|0)==0?((c[Y>>2]|0)+16|0)<=(c[W>>2]|0):0){if(ib(c[s>>2]|0,1)|0){c[ja>>2]=kb(c[s>>2]|0,6)|0;o=16<<c[ja>>2];c[S>>2]=o+(lb(c[s>>2]|0,4+(c[ja>>2]|0)|0)|0)-1;c[ia>>2]=lb(c[s>>2]|0,3)|0;ja=(_c(c[s>>2]|0)|0)+2|0;if((ja|0)<=(c[W>>2]|0))c[$>>2]=jb(c[s>>2]|0,2416,2)|0;g[T>>2]=+((c[ia>>2]|0)+1|0)*.09375}c[Y>>2]=_c(c[s>>2]|0)|0}if((c[L>>2]|0)>0?((c[Y>>2]|0)+3|0)<=(c[W>>2]|0):0){c[I>>2]=ib(c[s>>2]|0,3)|0;c[Y>>2]=_c(c[s>>2]|0)|0}else c[I>>2]=0;if(c[I>>2]|0)c[H>>2]=c[M>>2];else c[H>>2]=0;if(((c[Y>>2]|0)+3|0)<=(c[W>>2]|0))va=ib(c[s>>2]|0,3)|0;else va=0;c[J>>2]=va;Cb(c[ea>>2]|0,c[N>>2]|0,c[O>>2]|0,c[D>>2]|0,c[J>>2]|0,c[s>>2]|0,c[da>>2]|0,c[L>>2]|0);J=c[fa>>2]|0;c[la>>2]=ua()|0;va=i;i=i+((1*(J<<2)|0)+15&-16)|0;$c(c[N>>2]|0,c[O>>2]|0,c[I>>2]|0,va,c[L>>2]|0,c[s>>2]|0);c[Y>>2]=_c(c[s>>2]|0)|0;c[x>>2]=2;if(((c[Y>>2]|0)+4|0)<=(c[W>>2]|0))c[x>>2]=jb(c[s>>2]|0,2424,5)|0;J=i;i=i+((1*(c[fa>>2]<<2)|0)+15&-16)|0;Ya(c[ea>>2]|0,J,c[L>>2]|0,c[da>>2]|0);ia=i;i=i+((1*(c[fa>>2]<<2)|0)+15&-16)|0;c[Z>>2]=6;c[W>>2]=c[W>>2]<<3;c[Y>>2]=db(c[s>>2]|0)|0;c[v>>2]=c[N>>2];while(1){if((c[v>>2]|0)>=(c[O>>2]|0))break;ja=_(c[da>>2]|0,(b[(c[ha>>2]|0)+((c[v>>2]|0)+1<<1)>>1]|0)-(b[(c[ha>>2]|0)+(c[v>>2]<<1)>>1]|0)|0)|0;c[ma>>2]=ja<<c[L>>2];ja=c[ma>>2]|0;if((c[ma>>2]<<3|0)<((48>(c[ma>>2]|0)?48:c[ma>>2]|0)|0))wa=ja<<3;else wa=48>(ja|0)?48:c[ma>>2]|0;c[na>>2]=wa;c[oa>>2]=c[Z>>2];c[pa>>2]=0;while(1){if(((c[Y>>2]|0)+(c[oa>>2]<<3)|0)>=(c[W>>2]|0))break;if((c[pa>>2]|0)>=(c[J+(c[v>>2]<<2)>>2]|0))break;c[qa>>2]=ib(c[s>>2]|0,c[oa>>2]|0)|0;c[Y>>2]=db(c[s>>2]|0)|0;if(!(c[qa>>2]|0))break;c[pa>>2]=(c[pa>>2]|0)+(c[na>>2]|0);c[W>>2]=(c[W>>2]|0)-(c[na>>2]|0);c[oa>>2]=1}c[ia+(c[v>>2]<<2)>>2]=c[pa>>2];if((c[pa>>2]|0)>0)c[Z>>2]=2>((c[Z>>2]|0)-1|0)?2:(c[Z>>2]|0)-1|0;c[v>>2]=(c[v>>2]|0)+1}Z=i;i=i+((1*(c[fa>>2]<<2)|0)+15&-16)|0;if(((c[Y>>2]|0)+48|0)<=(c[W>>2]|0))xa=jb(c[s>>2]|0,2432,7)|0;else xa=5;c[R>>2]=xa;xa=c[p>>2]<<3<<3;c[y>>2]=xa-(db(c[s>>2]|0)|0)-1;if((c[I>>2]|0)!=0&(c[L>>2]|0)>=2)ya=(c[y>>2]|0)>=((c[L>>2]|0)+2<<3|0);else ya=0;c[aa>>2]=ya?8:0;c[y>>2]=(c[y>>2]|0)-(c[aa>>2]|0);ya=i;i=i+((1*(c[fa>>2]<<2)|0)+15&-16)|0;xa=i;i=i+((1*(c[fa>>2]<<2)|0)+15&-16)|0;c[Q>>2]=Fb(c[ea>>2]|0,c[N>>2]|0,c[O>>2]|0,ia,J,c[R>>2]|0,U,V,c[y>>2]|0,X,ya,Z,xa,c[da>>2]|0,c[L>>2]|0,c[s>>2]|0,0,0,0)|0;Db(c[ea>>2]|0,c[N>>2]|0,c[O>>2]|0,c[D>>2]|0,Z,c[s>>2]|0,c[da>>2]|0);c[u>>2]=0;do{ff(c[A+(c[u>>2]<<2)>>2]|0,(c[A+(c[u>>2]<<2)>>2]|0)+(c[w>>2]<<2)|0,(2048-(c[w>>2]|0)+((c[ga>>2]|0)/2|0)<<2)+0|0)|0;y=(c[u>>2]|0)+1|0;c[u>>2]=y}while((y|0)<(c[K>>2]|0));A=_(c[da>>2]|0,c[fa>>2]|0)|0;y=i;i=i+((1*A|0)+15&-16)|0;A=(_(c[da>>2]|0,c[w>>2]|0)|0)<<2;R=i;i=i+((1*A|0)+15&-16)|0;Va(0,c[ea>>2]|0,c[N>>2]|0,c[O>>2]|0,R,(c[da>>2]|0)==2?R+(c[w>>2]<<2)|0:0,y,0,ya,c[H>>2]|0,c[x>>2]|0,c[V>>2]|0,c[U>>2]|0,va,(c[p>>2]<<6)-(c[aa>>2]|0)|0,c[X>>2]|0,c[s>>2]|0,c[L>>2]|0,c[Q>>2]|0,(c[n>>2]|0)+36|0);if((c[aa>>2]|0)>0)c[ba>>2]=lb(c[s>>2]|0,1)|0;aa=c[ea>>2]|0;Q=c[N>>2]|0;X=c[O>>2]|0;va=c[D>>2]|0;U=c[p>>2]<<3;V=U-(_c(c[s>>2]|0)|0)|0;Eb(aa,Q,X,va,Z,xa,V,c[s>>2]|0,c[da>>2]|0);if(c[ba>>2]|0)Ta(c[ea>>2]|0,R,y,c[L>>2]|0,c[da>>2]|0,c[w>>2]|0,c[N>>2]|0,c[O>>2]|0,c[D>>2]|0,c[E>>2]|0,c[F>>2]|0,ya,c[(c[n>>2]|0)+36>>2]|0);b:do if(c[ca>>2]|0){c[v>>2]=0;while(1){if((c[v>>2]|0)>=(_(c[da>>2]|0,c[fa>>2]|0)|0))break b;g[(c[D>>2]|0)+(c[v>>2]<<2)>>2]=-28.0;c[v>>2]=(c[v>>2]|0)+1}}while(0);ad(c[ea>>2]|0,R,B,c[D>>2]|0,c[N>>2]|0,c[P>>2]|0,c[da>>2]|0,c[K>>2]|0,c[I>>2]|0,c[L>>2]|0,c[(c[n>>2]|0)+16>>2]|0,c[ca>>2]|0);c[u>>2]=0;do{if((c[(c[n>>2]|0)+52>>2]|0)>15)za=c[(c[n>>2]|0)+52>>2]|0;else za=15;c[(c[n>>2]|0)+52>>2]=za;if((c[(c[n>>2]|0)+56>>2]|0)>15)Aa=c[(c[n>>2]|0)+56>>2]|0;else Aa=15;c[(c[n>>2]|0)+56>>2]=Aa;Xa(c[B+(c[u>>2]<<2)>>2]|0,c[B+(c[u>>2]<<2)>>2]|0,c[(c[n>>2]|0)+56>>2]|0,c[(c[n>>2]|0)+52>>2]|0,c[(c[ea>>2]|0)+44>>2]|0,+g[(c[n>>2]|0)+64>>2],+g[(c[n>>2]|0)+60>>2],c[(c[n>>2]|0)+72>>2]|0,c[(c[n>>2]|0)+68>>2]|0,c[(c[ea>>2]|0)+60>>2]|0,c[ga>>2]|0);if(c[L>>2]|0)Xa((c[B+(c[u>>2]<<2)>>2]|0)+(c[(c[ea>>2]|0)+44>>2]<<2)|0,(c[B+(c[u>>2]<<2)>>2]|0)+(c[(c[ea>>2]|0)+44>>2]<<2)|0,c[(c[n>>2]|0)+52>>2]|0,c[S>>2]|0,(c[w>>2]|0)-(c[(c[ea>>2]|0)+44>>2]|0)|0,+g[(c[n>>2]|0)+60>>2],+g[T>>2],c[(c[n>>2]|0)+68>>2]|0,c[$>>2]|0,c[(c[ea>>2]|0)+60>>2]|0,c[ga>>2]|0);ca=(c[u>>2]|0)+1|0;c[u>>2]=ca}while((ca|0)<(c[K>>2]|0));c[(c[n>>2]|0)+56>>2]=c[(c[n>>2]|0)+52>>2];g[(c[n>>2]|0)+64>>2]=+g[(c[n>>2]|0)+60>>2];c[(c[n>>2]|0)+72>>2]=c[(c[n>>2]|0)+68>>2];c[(c[n>>2]|0)+52>>2]=c[S>>2];g[(c[n>>2]|0)+60>>2]=+g[T>>2];c[(c[n>>2]|0)+68>>2]=c[$>>2];if(c[L>>2]|0){c[(c[n>>2]|0)+56>>2]=c[(c[n>>2]|0)+52>>2];g[(c[n>>2]|0)+64>>2]=+g[(c[n>>2]|0)+60>>2];c[(c[n>>2]|0)+72>>2]=c[(c[n>>2]|0)+68>>2]}if((c[da>>2]|0)==1)df((c[D>>2]|0)+(c[fa>>2]<<2)|0,c[D>>2]|0,(c[fa>>2]<<2)+0|0)|0;c:do if(c[I>>2]|0){c[v>>2]=0;while(1){if((c[v>>2]|0)>=(c[fa>>2]<<1|0))break c;da=c[v>>2]|0;if(+g[(c[E>>2]|0)+(c[v>>2]<<2)>>2]<+g[(c[D>>2]|0)+(c[v>>2]<<2)>>2])Ba=+g[(c[E>>2]|0)+(da<<2)>>2];else Ba=+g[(c[D>>2]|0)+(da<<2)>>2];g[(c[E>>2]|0)+(c[v>>2]<<2)>>2]=Ba;c[v>>2]=(c[v>>2]|0)+1}}else{df(c[F>>2]|0,c[E>>2]|0,(c[fa>>2]<<1<<2)+0|0)|0;df(c[E>>2]|0,c[D>>2]|0,(c[fa>>2]<<1<<2)+0|0)|0;c[v>>2]=0;while(1){if((c[v>>2]|0)>=(c[fa>>2]<<1|0))break c;da=c[v>>2]|0;if(+g[(c[G>>2]|0)+(c[v>>2]<<2)>>2]+ +(c[M>>2]|0)*1.0000000474974513e-03<+g[(c[D>>2]|0)+(c[v>>2]<<2)>>2])Ca=+g[(c[G>>2]|0)+(da<<2)>>2]+ +(c[M>>2]|0)*1.0000000474974513e-03;else Ca=+g[(c[D>>2]|0)+(da<<2)>>2];g[(c[G>>2]|0)+(c[v>>2]<<2)>>2]=Ca;c[v>>2]=(c[v>>2]|0)+1}}while(0);c[u>>2]=0;do{c[v>>2]=0;while(1){if((c[v>>2]|0)>=(c[N>>2]|0))break;G=_(c[u>>2]|0,c[fa>>2]|0)|0;g[(c[D>>2]|0)+(G+(c[v>>2]|0)<<2)>>2]=0.0;G=_(c[u>>2]|0,c[fa>>2]|0)|0;g[(c[F>>2]|0)+(G+(c[v>>2]|0)<<2)>>2]=-28.0;G=_(c[u>>2]|0,c[fa>>2]|0)|0;g[(c[E>>2]|0)+(G+(c[v>>2]|0)<<2)>>2]=-28.0;c[v>>2]=(c[v>>2]|0)+1}c[v>>2]=c[O>>2];while(1){Da=c[u>>2]|0;if((c[v>>2]|0)>=(c[fa>>2]|0))break;G=_(Da,c[fa>>2]|0)|0;g[(c[D>>2]|0)+(G+(c[v>>2]|0)<<2)>>2]=0.0;G=_(c[u>>2]|0,c[fa>>2]|0)|0;g[(c[F>>2]|0)+(G+(c[v>>2]|0)<<2)>>2]=-28.0;G=_(c[u>>2]|0,c[fa>>2]|0)|0;g[(c[E>>2]|0)+(G+(c[v>>2]|0)<<2)>>2]=-28.0;c[v>>2]=(c[v>>2]|0)+1}G=Da+1|0;c[u>>2]=G}while((G|0)<2);c[(c[n>>2]|0)+36>>2]=c[(c[s>>2]|0)+28>>2];Zc(B,c[q>>2]|0,c[w>>2]|0,c[K>>2]|0,c[(c[n>>2]|0)+16>>2]|0,(c[ea>>2]|0)+16|0,(c[n>>2]|0)+76|0,c[t>>2]|0);c[(c[n>>2]|0)+48>>2]=0;t=_c(c[s>>2]|0)|0;if((t|0)>(c[p>>2]<<3|0)){c[m>>2]=-3;c[ra>>2]=1}else{if(bd(c[s>>2]|0)|0)c[(c[n>>2]|0)+40>>2]=1;c[m>>2]=(c[r>>2]|0)/(c[(c[n>>2]|0)+16>>2]|0)|0;c[ra>>2]=1}ka(c[la>>2]|0);sa=c[m>>2]|0;i=l;return sa|0}function ab(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;e=i;i=i+96|0;f=e+32|0;h=e+24|0;j=e+44|0;k=e+64|0;l=e+12|0;m=e+40|0;n=e+48|0;o=e+56|0;p=e+80|0;q=e+84|0;r=e+8|0;s=e+4|0;t=e;u=e+36|0;v=e+16|0;w=e+20|0;x=e+52|0;y=e+28|0;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;a:do switch(c[j>>2]|0){case 10010:{d=(c[k>>2]|0)+(4-1)&~(4-1);b=c[d>>2]|0;c[k>>2]=d+4;c[l>>2]=b;if((c[l>>2]|0)>=0?(c[l>>2]|0)<(c[(c[c[h>>2]>>2]|0)+8>>2]|0):0){c[(c[h>>2]|0)+20>>2]=c[l>>2];z=24}else z=25;break}case 10012:{b=(c[k>>2]|0)+(4-1)&~(4-1);d=c[b>>2]|0;c[k>>2]=b+4;c[m>>2]=d;if((c[m>>2]|0)>=1?(c[m>>2]|0)<=(c[(c[c[h>>2]>>2]|0)+8>>2]|0):0){c[(c[h>>2]|0)+24>>2]=c[m>>2];z=24}else z=25;break}case 4028:{c[r>>2]=(c[h>>2]|0)+84+((_(2048+(c[(c[h>>2]|0)+4>>2]|0)|0,c[(c[h>>2]|0)+8>>2]|0)|0)<<2);c[s>>2]=(c[r>>2]|0)+((c[(c[h>>2]|0)+8>>2]|0)*24<<2);c[t>>2]=(c[s>>2]|0)+(c[(c[c[h>>2]>>2]|0)+8>>2]<<1<<2);c[u>>2]=(c[t>>2]|0)+(c[(c[c[h>>2]>>2]|0)+8>>2]<<1<<2);bf((c[h>>2]|0)+36|0,0,(Wc(c[c[h>>2]>>2]|0,c[(c[h>>2]|0)+8>>2]|0)|0)-((c[h>>2]|0)+36-(c[h>>2]|0))|0)|0;c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[(c[c[h>>2]>>2]|0)+8>>2]<<1|0)){z=24;break a}g[(c[u>>2]|0)+(c[q>>2]<<2)>>2]=-28.0;g[(c[t>>2]|0)+(c[q>>2]<<2)>>2]=-28.0;c[q>>2]=(c[q>>2]|0)+1}break}case 4033:{d=(c[k>>2]|0)+(4-1)&~(4-1);b=c[d>>2]|0;c[k>>2]=d+4;c[v>>2]=b;if(!(c[v>>2]|0))z=25;else{c[c[v>>2]>>2]=c[(c[h>>2]|0)+52>>2];z=24}break}case 10015:{b=(c[k>>2]|0)+(4-1)&~(4-1);d=c[b>>2]|0;c[k>>2]=b+4;c[w>>2]=d;if(!(c[w>>2]|0))z=25;else{c[c[w>>2]>>2]=c[c[h>>2]>>2];z=24}break}case 10016:{d=(c[k>>2]|0)+(4-1)&~(4-1);b=c[d>>2]|0;c[k>>2]=d+4;c[x>>2]=b;c[(c[h>>2]|0)+28>>2]=c[x>>2];z=24;break}case 4031:{b=(c[k>>2]|0)+(4-1)&~(4-1);d=c[b>>2]|0;c[k>>2]=b+4;c[y>>2]=d;if(!(c[y>>2]|0))z=25;else{c[c[y>>2]>>2]=c[(c[h>>2]|0)+36>>2];z=24}break}case 10008:{d=(c[k>>2]|0)+(4-1)&~(4-1);b=c[d>>2]|0;c[k>>2]=d+4;c[n>>2]=b;if((c[n>>2]|0)<1|(c[n>>2]|0)>2)z=25;else{c[(c[h>>2]|0)+12>>2]=c[n>>2];z=24}break}case 10007:{b=(c[k>>2]|0)+(4-1)&~(4-1);d=c[b>>2]|0;c[k>>2]=b+4;c[o>>2]=d;if(!(c[o>>2]|0))z=25;else{c[c[o>>2]>>2]=c[(c[h>>2]|0)+40>>2];c[(c[h>>2]|0)+40>>2]=0;z=24}break}case 4027:{d=(c[k>>2]|0)+(4-1)&~(4-1);b=c[d>>2]|0;c[k>>2]=d+4;c[p>>2]=b;if(!(c[p>>2]|0))z=25;else{c[c[p>>2]>>2]=(c[(c[h>>2]|0)+4>>2]|0)/(c[(c[h>>2]|0)+16>>2]|0)|0;z=24}break}default:{c[f>>2]=-5;A=c[f>>2]|0;i=e;return A|0}}while(0);if((z|0)==24){c[f>>2]=0;A=c[f>>2]|0;i=e;return A|0}else if((z|0)==25){c[f>>2]=-1;A=c[f>>2]|0;i=e;return A|0}return 0}function bb(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0;f=i;i=i+16|0;g=f+12|0;h=f+8|0;j=f+4|0;k=f;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[k>>2]=e;e=c[k>>2]|0;k=cd(c[h>>2]|0,c[g>>2]|0)|0;ob(e,k,(c[(c[2448+(((c[h>>2]|0)<(c[j>>2]|0)?c[h>>2]|0:c[j>>2]|0)<<2)>>2]|0)+(((c[h>>2]|0)>(c[j>>2]|0)?c[h>>2]|0:c[j>>2]|0)<<2)>>2]|0)+(c[(c[2448+(((c[h>>2]|0)<((c[j>>2]|0)+1|0)?c[h>>2]|0:(c[j>>2]|0)+1|0)<<2)>>2]|0)+(((c[h>>2]|0)>((c[j>>2]|0)+1|0)?c[h>>2]|0:(c[j>>2]|0)+1|0)<<2)>>2]|0)|0);i=f;return}function cb(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0.0;f=i;i=i+16|0;g=f+12|0;h=f+8|0;j=f+4|0;k=f;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[k>>2]=e;e=c[h>>2]|0;d=c[j>>2]|0;b=kb(c[k>>2]|0,(c[(c[2448+(((c[h>>2]|0)<(c[j>>2]|0)?c[h>>2]|0:c[j>>2]|0)<<2)>>2]|0)+(((c[h>>2]|0)>(c[j>>2]|0)?c[h>>2]|0:c[j>>2]|0)<<2)>>2]|0)+(c[(c[2448+(((c[h>>2]|0)<((c[j>>2]|0)+1|0)?c[h>>2]|0:(c[j>>2]|0)+1|0)<<2)>>2]|0)+(((c[h>>2]|0)>((c[j>>2]|0)+1|0)?c[h>>2]|0:(c[j>>2]|0)+1|0)<<2)>>2]|0)|0)|0;l=+dd(e,d,b,c[g>>2]|0);i=f;return +l}function db(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;b=i;i=i+32|0;d=b+16|0;e=b+12|0;f=b+8|0;g=b+4|0;h=b;c[d>>2]=a;c[e>>2]=c[(c[d>>2]|0)+20>>2]<<3;c[g>>2]=32-(aa(c[(c[d>>2]|0)+28>>2]|0)|0);c[f>>2]=(c[(c[d>>2]|0)+28>>2]|0)>>>((c[g>>2]|0)-16|0);c[h>>2]=((c[f>>2]|0)>>>12)-8;c[h>>2]=(c[h>>2]|0)+((c[f>>2]|0)>>>0>(c[2512+(c[h>>2]<<2)>>2]|0)>>>0&1);c[g>>2]=(c[g>>2]<<3)+(c[h>>2]|0);i=b;return (c[e>>2]|0)-(c[g>>2]|0)|0}function eb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;e=i;i=i+16|0;f=e+8|0;g=e+4|0;h=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;c[c[f>>2]>>2]=c[g>>2];c[(c[f>>2]|0)+4>>2]=c[h>>2];c[(c[f>>2]|0)+8>>2]=0;c[(c[f>>2]|0)+12>>2]=0;c[(c[f>>2]|0)+16>>2]=0;c[(c[f>>2]|0)+20>>2]=9;c[(c[f>>2]|0)+24>>2]=0;c[(c[f>>2]|0)+28>>2]=128;h=ed(c[f>>2]|0)|0;c[(c[f>>2]|0)+40>>2]=h;c[(c[f>>2]|0)+32>>2]=(c[(c[f>>2]|0)+28>>2]|0)-1-(c[(c[f>>2]|0)+40>>2]>>1);c[(c[f>>2]|0)+44>>2]=0;fd(c[f>>2]|0);i=e;return}function fb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;i=i+16|0;e=d+8|0;f=d+4|0;g=d;c[e>>2]=a;c[f>>2]=b;b=gd(c[(c[e>>2]|0)+28>>2]|0,c[f>>2]|0)|0;c[(c[e>>2]|0)+36>>2]=b;c[g>>2]=((c[(c[e>>2]|0)+32>>2]|0)>>>0)/((c[(c[e>>2]|0)+36>>2]|0)>>>0)|0;i=d;return (c[f>>2]|0)-((c[g>>2]|0)+1+((c[f>>2]|0)-((c[g>>2]|0)+1)&0-((c[f>>2]|0)>>>0<((c[g>>2]|0)+1|0)>>>0&1)))|0}function gb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;i=i+16|0;e=d+8|0;f=d+4|0;g=d;c[e>>2]=a;c[f>>2]=b;c[(c[e>>2]|0)+36>>2]=(c[(c[e>>2]|0)+28>>2]|0)>>>(c[f>>2]|0);c[g>>2]=((c[(c[e>>2]|0)+32>>2]|0)>>>0)/((c[(c[e>>2]|0)+36>>2]|0)>>>0)|0;i=d;return (1<<c[f>>2])-((c[g>>2]|0)+1+((1<<c[f>>2])-((c[g>>2]|0)+1)&0-(1<<c[f>>2]>>>0<((c[g>>2]|0)+1|0)>>>0&1)))|0}function hb(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;f=i;i=i+32|0;g=f+16|0;h=f+12|0;j=f+8|0;k=f+4|0;l=f;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[k>>2]=e;c[l>>2]=_(c[(c[g>>2]|0)+36>>2]|0,(c[k>>2]|0)-(c[j>>2]|0)|0)|0;k=(c[g>>2]|0)+32|0;c[k>>2]=(c[k>>2]|0)-(c[l>>2]|0);k=c[g>>2]|0;if((c[h>>2]|0)>>>0>0){m=_(c[k+36>>2]|0,(c[j>>2]|0)-(c[h>>2]|0)|0)|0;n=c[g>>2]|0;o=n+28|0;c[o>>2]=m;p=c[g>>2]|0;fd(p);i=f;return}else{m=(c[k+28>>2]|0)-(c[l>>2]|0)|0;n=c[g>>2]|0;o=n+28|0;c[o>>2]=m;p=c[g>>2]|0;fd(p);i=f;return}}function ib(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;d=i;i=i+32|0;e=d+20|0;f=d+16|0;g=d+12|0;h=d+8|0;j=d+4|0;k=d;c[e>>2]=a;c[f>>2]=b;c[g>>2]=c[(c[e>>2]|0)+28>>2];c[h>>2]=c[(c[e>>2]|0)+32>>2];c[j>>2]=(c[g>>2]|0)>>>(c[f>>2]|0);c[k>>2]=(c[h>>2]|0)>>>0<(c[j>>2]|0)>>>0&1;if(!(c[k>>2]|0))c[(c[e>>2]|0)+32>>2]=(c[h>>2]|0)-(c[j>>2]|0);if(c[k>>2]|0){l=c[j>>2]|0;m=c[e>>2]|0;n=m+28|0;c[n>>2]=l;o=c[e>>2]|0;fd(o);p=c[k>>2]|0;i=d;return p|0}else{l=(c[g>>2]|0)-(c[j>>2]|0)|0;m=c[e>>2]|0;n=m+28|0;c[n>>2]=l;o=c[e>>2]|0;fd(o);p=c[k>>2]|0;i=d;return p|0}return 0}function jb(a,b,e){a=a|0;b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;f=i;i=i+32|0;g=f+4|0;h=f+16|0;j=f+8|0;k=f+20|0;l=f+28|0;m=f;n=f+12|0;o=f+24|0;c[g>>2]=a;c[h>>2]=b;c[j>>2]=e;c[m>>2]=c[(c[g>>2]|0)+28>>2];c[l>>2]=c[(c[g>>2]|0)+32>>2];c[k>>2]=(c[m>>2]|0)>>>(c[j>>2]|0);c[o>>2]=-1;do{c[n>>2]=c[m>>2];j=c[k>>2]|0;e=(c[o>>2]|0)+1|0;c[o>>2]=e;c[m>>2]=_(j,d[(c[h>>2]|0)+e>>0]|0)|0}while((c[l>>2]|0)>>>0<(c[m>>2]|0)>>>0);c[(c[g>>2]|0)+32>>2]=(c[l>>2]|0)-(c[m>>2]|0);c[(c[g>>2]|0)+28>>2]=(c[n>>2]|0)-(c[m>>2]|0);fd(c[g>>2]|0);i=f;return c[o>>2]|0}function kb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;d=i;i=i+32|0;e=d+8|0;f=d+16|0;g=d+20|0;h=d+24|0;j=d+4|0;k=d;l=d+12|0;c[f>>2]=a;c[g>>2]=b;c[g>>2]=(c[g>>2]|0)+-1;c[k>>2]=32-(aa(c[g>>2]|0)|0);if((c[k>>2]|0)<=8){c[g>>2]=(c[g>>2]|0)+1;c[j>>2]=fb(c[f>>2]|0,c[g>>2]|0)|0;hb(c[f>>2]|0,c[j>>2]|0,(c[j>>2]|0)+1|0,c[g>>2]|0);c[e>>2]=c[j>>2];m=c[e>>2]|0;i=d;return m|0}c[k>>2]=(c[k>>2]|0)-8;c[h>>2]=((c[g>>2]|0)>>>(c[k>>2]|0))+1;c[j>>2]=fb(c[f>>2]|0,c[h>>2]|0)|0;hb(c[f>>2]|0,c[j>>2]|0,(c[j>>2]|0)+1|0,c[h>>2]|0);h=c[j>>2]<<c[k>>2];c[l>>2]=h|(lb(c[f>>2]|0,c[k>>2]|0)|0);if((c[l>>2]|0)>>>0<=(c[g>>2]|0)>>>0){c[e>>2]=c[l>>2];m=c[e>>2]|0;i=d;return m|0}else{c[(c[f>>2]|0)+44>>2]=1;c[e>>2]=c[g>>2];m=c[e>>2]|0;i=d;return m|0}return 0}function lb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;i=i+32|0;e=d+16|0;f=d+12|0;g=d+8|0;h=d+4|0;j=d;c[e>>2]=a;c[f>>2]=b;c[g>>2]=c[(c[e>>2]|0)+12>>2];c[h>>2]=c[(c[e>>2]|0)+16>>2];if((c[h>>2]|0)>>>0<(c[f>>2]|0)>>>0)do{b=hd(c[e>>2]|0)|0;c[g>>2]=c[g>>2]|b<<c[h>>2];c[h>>2]=(c[h>>2]|0)+8}while((c[h>>2]|0)<=24);c[j>>2]=c[g>>2]&(1<<c[f>>2])-1;c[g>>2]=(c[g>>2]|0)>>>(c[f>>2]|0);c[h>>2]=(c[h>>2]|0)-(c[f>>2]|0);c[(c[e>>2]|0)+12>>2]=c[g>>2];c[(c[e>>2]|0)+16>>2]=c[h>>2];h=(c[e>>2]|0)+20|0;c[h>>2]=(c[h>>2]|0)+(c[f>>2]|0);i=d;return c[j>>2]|0}function mb(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+32|0;g=f+16|0;h=f+12|0;j=f+8|0;k=f+4|0;l=f;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[k>>2]=e;c[l>>2]=id(c[(c[g>>2]|0)+28>>2]|0,c[k>>2]|0)|0;if((c[h>>2]|0)>>>0>0){e=(c[(c[g>>2]|0)+28>>2]|0)-(_(c[l>>2]|0,(c[k>>2]|0)-(c[h>>2]|0)|0)|0)|0;d=(c[g>>2]|0)+32|0;c[d>>2]=(c[d>>2]|0)+e;e=_(c[l>>2]|0,(c[j>>2]|0)-(c[h>>2]|0)|0)|0;c[(c[g>>2]|0)+28>>2]=e;m=c[g>>2]|0;jd(m);i=f;return}else{e=_(c[l>>2]|0,(c[k>>2]|0)-(c[j>>2]|0)|0)|0;j=(c[g>>2]|0)+28|0;c[j>>2]=(c[j>>2]|0)-e;m=c[g>>2]|0;jd(m);i=f;return}}function nb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;i=i+32|0;f=e+20|0;g=e+16|0;h=e+12|0;j=e+8|0;k=e+4|0;l=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;c[j>>2]=c[(c[f>>2]|0)+28>>2];c[l>>2]=c[(c[f>>2]|0)+32>>2];c[k>>2]=(c[j>>2]|0)>>>(c[h>>2]|0);c[j>>2]=(c[j>>2]|0)-(c[k>>2]|0);if(c[g>>2]|0)c[(c[f>>2]|0)+32>>2]=(c[l>>2]|0)+(c[j>>2]|0);c[(c[f>>2]|0)+28>>2]=(c[g>>2]|0)!=0?c[k>>2]|0:c[j>>2]|0;jd(c[f>>2]|0);i=e;return}function ob(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;i=i+32|0;f=e+20|0;g=e+16|0;h=e+12|0;j=e+8|0;k=e+4|0;l=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;c[h>>2]=(c[h>>2]|0)+-1;c[l>>2]=32-(aa(c[h>>2]|0)|0);if((c[l>>2]|0)>8){c[l>>2]=(c[l>>2]|0)-8;c[j>>2]=((c[h>>2]|0)>>>(c[l>>2]|0))+1;c[k>>2]=(c[g>>2]|0)>>>(c[l>>2]|0);mb(c[f>>2]|0,c[k>>2]|0,(c[k>>2]|0)+1|0,c[j>>2]|0);pb(c[f>>2]|0,c[g>>2]&(1<<c[l>>2])-1,c[l>>2]|0);i=e;return}else{mb(c[f>>2]|0,c[g>>2]|0,(c[g>>2]|0)+1|0,(c[h>>2]|0)+1|0);i=e;return}}function pb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e+4|0;k=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;c[j>>2]=c[(c[f>>2]|0)+12>>2];c[k>>2]=c[(c[f>>2]|0)+16>>2];if(((c[k>>2]|0)+(c[h>>2]|0)|0)>>>0>32)do{d=kd(c[f>>2]|0,c[j>>2]&255)|0;b=(c[f>>2]|0)+44|0;c[b>>2]=c[b>>2]|d;c[j>>2]=(c[j>>2]|0)>>>8;c[k>>2]=(c[k>>2]|0)-8}while((c[k>>2]|0)>=8);c[j>>2]=c[j>>2]|c[g>>2]<<c[k>>2];c[k>>2]=(c[k>>2]|0)+(c[h>>2]|0);c[(c[f>>2]|0)+12>>2]=c[j>>2];c[(c[f>>2]|0)+16>>2]=c[k>>2];k=(c[f>>2]|0)+20|0;c[k>>2]=(c[k>>2]|0)+(c[h>>2]|0);i=e;return}function qb(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;e=i;i=i+80|0;f=e+60|0;g=e+48|0;h=e+4|0;j=e+8|0;k=e+64|0;l=e;m=e+16|0;n=e+56|0;o=e+52|0;c[f>>2]=a;c[g>>2]=d;if((c[(c[f>>2]|0)+8>>2]|0)>0)p=c[(c[f>>2]|0)+8>>2]|0;else p=0;c[o>>2]=p;c[m>>2]=1;c[l>>2]=0;do{c[k>>2]=b[(c[f>>2]|0)+12+(c[l>>2]<<1<<1)>>1];c[j>>2]=b[(c[f>>2]|0)+12+((c[l>>2]<<1)+1<<1)>>1];p=_(c[m+(c[l>>2]<<2)>>2]|0,c[k>>2]|0)|0;c[m+((c[l>>2]|0)+1<<2)>>2]=p;c[l>>2]=(c[l>>2]|0)+1}while((c[j>>2]|0)!=1);c[j>>2]=b[(c[f>>2]|0)+12+((c[l>>2]<<1)-1<<1)>>1];c[n>>2]=(c[l>>2]|0)-1;while(1){if((c[n>>2]|0)<0)break;if(c[n>>2]|0)c[h>>2]=b[(c[f>>2]|0)+12+((c[n>>2]<<1)-1<<1)>>1];else c[h>>2]=1;l=b[(c[f>>2]|0)+12+(c[n>>2]<<1<<1)>>1]|0;if((l|0)==2)md(c[g>>2]|0,c[j>>2]|0,c[m+(c[n>>2]<<2)>>2]|0);else if((l|0)==4)nd(c[g>>2]|0,c[m+(c[n>>2]<<2)>>2]<<c[o>>2],c[f>>2]|0,c[j>>2]|0,c[m+(c[n>>2]<<2)>>2]|0,c[h>>2]|0);else if((l|0)==3)od(c[g>>2]|0,c[m+(c[n>>2]<<2)>>2]<<c[o>>2],c[f>>2]|0,c[j>>2]|0,c[m+(c[n>>2]<<2)>>2]|0,c[h>>2]|0);else if((l|0)==5)pd(c[g>>2]|0,c[m+(c[n>>2]<<2)>>2]<<c[o>>2],c[f>>2]|0,c[j>>2]|0,c[m+(c[n>>2]<<2)>>2]|0,c[h>>2]|0);c[j>>2]=c[h>>2];c[n>>2]=(c[n>>2]|0)+-1}i=e;return}function rb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;e=i;i=i+32|0;f=e+8|0;g=e+16|0;h=e+20|0;j=e+24|0;k=e+4|0;l=e;m=e+12|0;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;c[j>>2]=0;c[l>>2]=gb(c[f>>2]|0,15)|0;c[k>>2]=0;do if((c[l>>2]|0)>>>0>=(c[g>>2]|0)>>>0){c[j>>2]=(c[j>>2]|0)+1;c[k>>2]=c[g>>2];c[g>>2]=(qd(c[g>>2]|0,c[h>>2]|0)|0)+1;while(1){if((c[g>>2]|0)>>>0>1)n=(c[l>>2]|0)>>>0>=((c[k>>2]|0)+(c[g>>2]<<1)|0)>>>0;else n=0;o=c[g>>2]|0;if(!n)break;c[g>>2]=o<<1;c[k>>2]=(c[k>>2]|0)+(c[g>>2]|0);c[g>>2]=(_((c[g>>2]|0)-2|0,c[h>>2]|0)|0)>>>15;c[g>>2]=(c[g>>2]|0)+1;c[j>>2]=(c[j>>2]|0)+1}if(o>>>0<=1){c[m>>2]=((c[l>>2]|0)-(c[k>>2]|0)|0)>>>1;c[j>>2]=(c[j>>2]|0)+(c[m>>2]|0);c[k>>2]=(c[k>>2]|0)+(c[m>>2]<<1)}if((c[l>>2]|0)>>>0<((c[k>>2]|0)+(c[g>>2]|0)|0)>>>0){c[j>>2]=0-(c[j>>2]|0);break}else{c[k>>2]=(c[k>>2]|0)+(c[g>>2]|0);break}}while(0);l=c[f>>2]|0;f=c[k>>2]|0;if(((c[k>>2]|0)+(c[g>>2]|0)|0)>>>0>=32768){p=32768;hb(l,f,p,32768);q=c[j>>2]|0;i=e;return q|0}p=(c[k>>2]|0)+(c[g>>2]|0)|0;hb(l,f,p,32768);q=c[j>>2]|0;i=e;return q|0}function sb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;b=i;i=i+32|0;d=b+16|0;e=b+12|0;f=b+8|0;g=b+4|0;h=b;c[d>>2]=a;c[f>>2]=0;c[g>>2]=32-(aa(c[d>>2]|0)|0)-1>>1;c[e>>2]=1<<c[g>>2];do{c[h>>2]=(c[f>>2]<<1)+(c[e>>2]|0)<<c[g>>2];if((c[h>>2]|0)>>>0<=(c[d>>2]|0)>>>0){c[f>>2]=(c[f>>2]|0)+(c[e>>2]|0);c[d>>2]=(c[d>>2]|0)-(c[h>>2]|0)}c[e>>2]=(c[e>>2]|0)>>>1;c[g>>2]=(c[g>>2]|0)+-1}while((c[g>>2]|0)>=0);i=b;return c[f>>2]|0}function tb(a,d,e,f,h,j,k){a=a|0;d=d|0;e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0.0;l=i;i=i+144|0;m=l+132|0;n=l+108|0;o=l+8|0;p=l+56|0;q=l+64|0;r=l+16|0;s=l+20|0;t=l+24|0;u=l+28|0;v=l+32|0;w=l+36|0;x=l+40|0;y=l+44|0;z=l+104|0;A=l+112|0;B=l+120|0;C=l+128|0;D=l+136|0;E=l+68|0;F=l+72|0;G=l+76|0;H=l+80|0;I=l+84|0;J=l+88|0;K=l+92|0;L=l+12|0;M=l+4|0;N=l;O=l+96|0;P=l+48|0;Q=l+100|0;R=l+52|0;S=l+116|0;T=l+60|0;U=l+124|0;c[m>>2]=a;c[n>>2]=d;c[o>>2]=e;c[p>>2]=f;c[q>>2]=h;c[r>>2]=j;c[s>>2]=k;c[u>>2]=c[c[m>>2]>>2];c[x>>2]=c[(c[m>>2]|0)+24>>2];c[t>>2]=0;while(1){V=c[u>>2]>>1;if((c[t>>2]|0)>=(c[r>>2]|0))break;c[u>>2]=V;c[x>>2]=(c[x>>2]|0)+(c[u>>2]<<2);c[t>>2]=(c[t>>2]|0)+1}c[v>>2]=V;c[w>>2]=c[u>>2]>>2;c[y>>2]=c[n>>2];c[z>>2]=(c[n>>2]|0)+((_(c[s>>2]|0,(c[v>>2]|0)-1|0)|0)<<2);c[A>>2]=(c[o>>2]|0)+(c[q>>2]>>1<<2);c[B>>2]=c[x>>2];c[C>>2]=c[(c[(c[m>>2]|0)+8+(c[r>>2]<<2)>>2]|0)+44>>2];c[t>>2]=0;while(1){if((c[t>>2]|0)>=(c[w>>2]|0))break;n=c[C>>2]|0;c[C>>2]=n+2;c[D>>2]=b[n>>1];g[E>>2]=+g[c[z>>2]>>2]*+g[(c[B>>2]|0)+(c[t>>2]<<2)>>2]+ +g[c[y>>2]>>2]*+g[(c[B>>2]|0)+((c[w>>2]|0)+(c[t>>2]|0)<<2)>>2];g[F>>2]=+g[c[y>>2]>>2]*+g[(c[B>>2]|0)+(c[t>>2]<<2)>>2]-+g[c[z>>2]>>2]*+g[(c[B>>2]|0)+((c[w>>2]|0)+(c[t>>2]|0)<<2)>>2];g[(c[A>>2]|0)+((c[D>>2]<<1)+1<<2)>>2]=+g[E>>2];g[(c[A>>2]|0)+(c[D>>2]<<1<<2)>>2]=+g[F>>2];c[y>>2]=(c[y>>2]|0)+(c[s>>2]<<1<<2);c[z>>2]=(c[z>>2]|0)+(0-(c[s>>2]<<1)<<2);c[t>>2]=(c[t>>2]|0)+1}qb(c[(c[m>>2]|0)+8+(c[r>>2]<<2)>>2]|0,(c[o>>2]|0)+(c[q>>2]>>1<<2)|0);c[G>>2]=(c[o>>2]|0)+(c[q>>2]>>1<<2);c[H>>2]=(c[o>>2]|0)+(c[q>>2]>>1<<2)+(c[v>>2]<<2)+-8;c[I>>2]=c[x>>2];c[t>>2]=0;while(1){if((c[t>>2]|0)>=((c[w>>2]|0)+1>>1|0))break;g[J>>2]=+g[(c[G>>2]|0)+4>>2];g[K>>2]=+g[c[G>>2]>>2];g[N>>2]=+g[(c[I>>2]|0)+(c[t>>2]<<2)>>2];g[O>>2]=+g[(c[I>>2]|0)+((c[w>>2]|0)+(c[t>>2]|0)<<2)>>2];g[L>>2]=+g[J>>2]*+g[N>>2]+ +g[K>>2]*+g[O>>2];g[M>>2]=+g[J>>2]*+g[O>>2]-+g[K>>2]*+g[N>>2];g[J>>2]=+g[(c[H>>2]|0)+4>>2];g[K>>2]=+g[c[H>>2]>>2];g[c[G>>2]>>2]=+g[L>>2];g[(c[H>>2]|0)+4>>2]=+g[M>>2];g[N>>2]=+g[(c[I>>2]|0)+((c[w>>2]|0)-(c[t>>2]|0)-1<<2)>>2];g[O>>2]=+g[(c[I>>2]|0)+((c[v>>2]|0)-(c[t>>2]|0)-1<<2)>>2];g[L>>2]=+g[J>>2]*+g[N>>2]+ +g[K>>2]*+g[O>>2];g[M>>2]=+g[J>>2]*+g[O>>2]-+g[K>>2]*+g[N>>2];g[c[H>>2]>>2]=+g[L>>2];g[(c[G>>2]|0)+4>>2]=+g[M>>2];c[G>>2]=(c[G>>2]|0)+8;c[H>>2]=(c[H>>2]|0)+-8;c[t>>2]=(c[t>>2]|0)+1}c[P>>2]=(c[o>>2]|0)+(c[q>>2]<<2)+-4;c[Q>>2]=c[o>>2];c[R>>2]=c[p>>2];c[S>>2]=(c[p>>2]|0)+(c[q>>2]<<2)+-4;c[t>>2]=0;while(1){if((c[t>>2]|0)>=((c[q>>2]|0)/2|0|0))break;g[T>>2]=+g[c[P>>2]>>2];g[U>>2]=+g[c[Q>>2]>>2];W=+g[c[S>>2]>>2]*+g[U>>2]-+g[c[R>>2]>>2]*+g[T>>2];p=c[Q>>2]|0;c[Q>>2]=p+4;g[p>>2]=W;W=+g[c[R>>2]>>2]*+g[U>>2]+ +g[c[S>>2]>>2]*+g[T>>2];p=c[P>>2]|0;c[P>>2]=p+-4;g[p>>2]=W;c[R>>2]=(c[R>>2]|0)+4;c[S>>2]=(c[S>>2]|0)+-4;c[t>>2]=(c[t>>2]|0)+1}i=l;return}function ub(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;i=i+32|0;f=e+20|0;g=e+16|0;h=e+12|0;j=e+8|0;k=e+4|0;l=e;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[k>>2]=0;a:while(1){if((c[k>>2]|0)>=1){m=12;break}c[l>>2]=0;while(1){if((c[l>>2]|0)>=4)break;if((c[g>>2]|0)==(c[c[2544+(c[k>>2]<<2)>>2]>>2]|0)?(c[h>>2]<<c[l>>2]|0)==(_(c[(c[2544+(c[k>>2]<<2)>>2]|0)+44>>2]|0,c[(c[2544+(c[k>>2]<<2)>>2]|0)+40>>2]|0)|0):0){m=7;break a}c[l>>2]=(c[l>>2]|0)+1}c[k>>2]=(c[k>>2]|0)+1}if((m|0)==7){if(c[j>>2]|0)c[c[j>>2]>>2]=0;c[f>>2]=c[2544+(c[k>>2]<<2)>>2];n=c[f>>2]|0;i=e;return n|0}else if((m|0)==12){if(c[j>>2]|0)c[c[j>>2]>>2]=-1;c[f>>2]=0;n=c[f>>2]|0;i=e;return n|0}return 0}function vb(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;h=i;i=i+112|0;j=h+4|0;k=h+48|0;l=h+84|0;m=h;n=h+80|0;o=h+88|0;p=h+92|0;q=h+72|0;r=h+56|0;s=h+8|0;t=h+28|0;u=h+76|0;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[n>>2]=f;g[q>>2]=1.0;c[s>>2]=0;c[s+4>>2]=0;c[s+8>>2]=0;c[s+12>>2]=0;c[s+16>>2]=0;g[u>>2]=.800000011920929;c[o>>2]=1;while(1){if((c[o>>2]|0)>=(c[l>>2]>>1|0))break;g[(c[k>>2]|0)+(c[o>>2]<<2)>>2]=((+g[(c[c[j>>2]>>2]|0)+((c[o>>2]<<1)-1<<2)>>2]+ +g[(c[c[j>>2]>>2]|0)+((c[o>>2]<<1)+1<<2)>>2])*.5+ +g[(c[c[j>>2]>>2]|0)+(c[o>>2]<<1<<2)>>2])*.5;c[o>>2]=(c[o>>2]|0)+1}g[c[k>>2]>>2]=(+g[(c[c[j>>2]>>2]|0)+4>>2]*.5+ +g[c[c[j>>2]>>2]>>2])*.5;if((c[m>>2]|0)==2){c[o>>2]=1;while(1){if((c[o>>2]|0)>=(c[l>>2]>>1|0))break;m=(c[k>>2]|0)+(c[o>>2]<<2)|0;g[m>>2]=+g[m>>2]+((+g[(c[(c[j>>2]|0)+4>>2]|0)+((c[o>>2]<<1)-1<<2)>>2]+ +g[(c[(c[j>>2]|0)+4>>2]|0)+((c[o>>2]<<1)+1<<2)>>2])*.5+ +g[(c[(c[j>>2]|0)+4>>2]|0)+(c[o>>2]<<1<<2)>>2])*.5;c[o>>2]=(c[o>>2]|0)+1}m=c[k>>2]|0;g[m>>2]=+g[m>>2]+(+g[(c[(c[j>>2]|0)+4>>2]|0)+4>>2]*.5+ +g[c[(c[j>>2]|0)+4>>2]>>2])*.5}Bb(c[k>>2]|0,p,0,0,4,c[l>>2]>>1,c[n>>2]|0)|0;g[p>>2]=+g[p>>2]*1.000100016593933;c[o>>2]=1;while(1){if((c[o>>2]|0)>4)break;n=p+(c[o>>2]<<2)|0;g[n>>2]=+g[n>>2]-+g[p+(c[o>>2]<<2)>>2]*(+(c[o>>2]|0)*.00800000037997961)*(+(c[o>>2]|0)*.00800000037997961);c[o>>2]=(c[o>>2]|0)+1}yb(r,p,4);c[o>>2]=0;while(1){if((c[o>>2]|0)>=4)break;g[q>>2]=+g[q>>2]*.8999999761581421;g[r+(c[o>>2]<<2)>>2]=+g[r+(c[o>>2]<<2)>>2]*+g[q>>2];c[o>>2]=(c[o>>2]|0)+1}g[t>>2]=+g[r>>2]+.800000011920929;g[t+4>>2]=+g[r+4>>2]+ +g[u>>2]*+g[r>>2];g[t+8>>2]=+g[r+8>>2]+ +g[u>>2]*+g[r+4>>2];g[t+12>>2]=+g[r+12>>2]+ +g[u>>2]*+g[r+8>>2];g[t+16>>2]=+g[u>>2]*+g[r+12>>2];rd(c[k>>2]|0,t,c[k>>2]|0,c[l>>2]>>1,s);i=h;return}function wb(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;h=i;i=i+48|0;j=h+4|0;k=h+32|0;l=h+8|0;m=h+36|0;n=h+44|0;o=h;p=h+16|0;q=h+40|0;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[n>>2]=f;c[o>>2]=0;while(1){if((c[o>>2]|0)>=((c[n>>2]|0)-3|0))break;c[p>>2]=0;c[p+4>>2]=0;c[p+8>>2]=0;c[p+12>>2]=0;sd(c[j>>2]|0,(c[k>>2]|0)+(c[o>>2]<<2)|0,p,c[m>>2]|0);g[(c[l>>2]|0)+(c[o>>2]<<2)>>2]=+g[p>>2];g[(c[l>>2]|0)+((c[o>>2]|0)+1<<2)>>2]=+g[p+4>>2];g[(c[l>>2]|0)+((c[o>>2]|0)+2<<2)>>2]=+g[p+8>>2];g[(c[l>>2]|0)+((c[o>>2]|0)+3<<2)>>2]=+g[p+12>>2];c[o>>2]=(c[o>>2]|0)+4}while(1){if((c[o>>2]|0)>=(c[n>>2]|0))break;g[q>>2]=+td(c[j>>2]|0,(c[k>>2]|0)+(c[o>>2]<<2)|0,c[m>>2]|0);g[(c[l>>2]|0)+(c[o>>2]<<2)>>2]=+g[q>>2];c[o>>2]=(c[o>>2]|0)+1}i=h;return}function xb(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0;j=i;i=i+80|0;k=j+16|0;l=j+32|0;m=j+52|0;n=j+60|0;o=j+40|0;p=j+56|0;q=j+64|0;r=j+68|0;s=j+8|0;t=j+36|0;u=j+20|0;v=j;w=j+24|0;x=j+44|0;y=j+28|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=d;c[n>>2]=e;c[o>>2]=f;c[j+48>>2]=h;c[s>>2]=0;c[s+4>>2]=0;c[r>>2]=(c[m>>2]|0)+(c[n>>2]|0);h=c[m>>2]>>2;c[u>>2]=ua()|0;f=i;i=i+((1*(h<<2)|0)+15&-16)|0;h=i;i=i+((1*(c[r>>2]>>2<<2)|0)+15&-16)|0;e=i;i=i+((1*(c[n>>2]>>1<<2)|0)+15&-16)|0;c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[m>>2]>>2|0))break;g[f+(c[q>>2]<<2)>>2]=+g[(c[k>>2]|0)+(c[q>>2]<<1<<2)>>2];c[q>>2]=(c[q>>2]|0)+1}c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[r>>2]>>2|0))break;g[h+(c[q>>2]<<2)>>2]=+g[(c[l>>2]|0)+(c[q>>2]<<1<<2)>>2];c[q>>2]=(c[q>>2]|0)+1}wb(f,h,e,c[m>>2]>>2,c[n>>2]>>2);ud(e,h,c[m>>2]>>2,c[n>>2]>>2,s);c[p>>2]=0;while(1){if((c[p>>2]|0)>=(c[n>>2]>>1|0))break;g[e+(c[p>>2]<<2)>>2]=0.0;if(!((N((c[p>>2]|0)-(c[s>>2]<<1)|0)|0)>2?(N((c[p>>2]|0)-(c[s+4>>2]<<1)|0)|0)>2:0)){g[v>>2]=+td(c[k>>2]|0,(c[l>>2]|0)+(c[p>>2]<<2)|0,c[m>>2]>>1);g[e+(c[p>>2]<<2)>>2]=-1.0>+g[v>>2]?-1.0:+g[v>>2]}c[p>>2]=(c[p>>2]|0)+1}ud(e,c[l>>2]|0,c[m>>2]>>1,c[n>>2]>>1,s);if((c[s>>2]|0)>0?(c[s>>2]|0)<((c[n>>2]>>1)-1|0):0){g[w>>2]=+g[e+((c[s>>2]|0)-1<<2)>>2];g[x>>2]=+g[e+(c[s>>2]<<2)>>2];g[y>>2]=+g[e+((c[s>>2]|0)+1<<2)>>2];if(+g[y>>2]-+g[w>>2]>(+g[x>>2]-+g[w>>2])*.699999988079071){c[t>>2]=1;z=c[s>>2]|0;A=z<<1;B=c[t>>2]|0;C=A-B|0;D=c[o>>2]|0;c[D>>2]=C;E=c[u>>2]|0;ka(E|0);i=j;return}if(+g[w>>2]-+g[y>>2]>(+g[x>>2]-+g[y>>2])*.699999988079071){c[t>>2]=-1;z=c[s>>2]|0;A=z<<1;B=c[t>>2]|0;C=A-B|0;D=c[o>>2]|0;c[D>>2]=C;E=c[u>>2]|0;ka(E|0);i=j;return}else{c[t>>2]=0;z=c[s>>2]|0;A=z<<1;B=c[t>>2]|0;C=A-B|0;D=c[o>>2]|0;c[D>>2]=C;E=c[u>>2]|0;ka(E|0);i=j;return}}c[t>>2]=0;z=c[s>>2]|0;A=z<<1;B=c[t>>2]|0;C=A-B|0;D=c[o>>2]|0;c[D>>2]=C;E=c[u>>2]|0;ka(E|0);i=j;return}function yb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;e=i;i=i+48|0;f=e+36|0;h=e+16|0;j=e;k=e+28|0;l=e+32|0;m=e+40|0;n=e+12|0;o=e+24|0;p=e+20|0;q=e+8|0;r=e+4|0;c[f>>2]=a;c[h>>2]=b;c[j>>2]=d;g[n>>2]=+g[c[h>>2]>>2];c[o>>2]=c[f>>2];c[k>>2]=0;while(1){if((c[k>>2]|0)>=(c[j>>2]|0))break;g[(c[o>>2]|0)+(c[k>>2]<<2)>>2]=0.0;c[k>>2]=(c[k>>2]|0)+1}if(!(+g[c[h>>2]>>2]!=0.0)){i=e;return}c[k>>2]=0;while(1){if((c[k>>2]|0)>=(c[j>>2]|0)){s=15;break}g[p>>2]=0.0;c[l>>2]=0;while(1){if((c[l>>2]|0)>=(c[k>>2]|0))break;g[p>>2]=+g[p>>2]+ +g[(c[o>>2]|0)+(c[l>>2]<<2)>>2]*+g[(c[h>>2]|0)+((c[k>>2]|0)-(c[l>>2]|0)<<2)>>2];c[l>>2]=(c[l>>2]|0)+1}g[p>>2]=+g[p>>2]+ +g[(c[h>>2]|0)+((c[k>>2]|0)+1<<2)>>2];g[m>>2]=-(+g[p>>2]/+g[n>>2]);g[(c[o>>2]|0)+(c[k>>2]<<2)>>2]=+g[m>>2];c[l>>2]=0;while(1){if((c[l>>2]|0)>=((c[k>>2]|0)+1>>1|0))break;g[q>>2]=+g[(c[o>>2]|0)+(c[l>>2]<<2)>>2];g[r>>2]=+g[(c[o>>2]|0)+((c[k>>2]|0)-1-(c[l>>2]|0)<<2)>>2];g[(c[o>>2]|0)+(c[l>>2]<<2)>>2]=+g[q>>2]+ +g[m>>2]*+g[r>>2];g[(c[o>>2]|0)+((c[k>>2]|0)-1-(c[l>>2]|0)<<2)>>2]=+g[r>>2]+ +g[m>>2]*+g[q>>2];c[l>>2]=(c[l>>2]|0)+1}g[n>>2]=+g[n>>2]-+g[m>>2]*+g[m>>2]*+g[n>>2];if(+g[n>>2]<+g[c[h>>2]>>2]*1.0000000474974513e-03){s=15;break}c[k>>2]=(c[k>>2]|0)+1}if((s|0)==15){i=e;return}}function zb(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;j=i;i=i+64|0;k=j+48|0;l=j+28|0;m=j;n=j+40|0;o=j+44|0;p=j+52|0;q=j+24|0;r=j+36|0;s=j+32|0;t=j+8|0;u=j+4|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=d;c[n>>2]=e;c[o>>2]=f;c[p>>2]=h;h=c[o>>2]|0;c[s>>2]=ua()|0;f=i;i=i+((1*(h<<2)|0)+15&-16)|0;h=i;i=i+((1*((c[n>>2]|0)+(c[o>>2]|0)<<2)|0)+15&-16)|0;c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[o>>2]|0))break;g[f+(c[q>>2]<<2)>>2]=+g[(c[l>>2]|0)+((c[o>>2]|0)-(c[q>>2]|0)-1<<2)>>2];c[q>>2]=(c[q>>2]|0)+1}c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[o>>2]|0))break;g[h+(c[q>>2]<<2)>>2]=+g[(c[p>>2]|0)+((c[o>>2]|0)-(c[q>>2]|0)-1<<2)>>2];c[q>>2]=(c[q>>2]|0)+1}c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[n>>2]|0))break;g[h+((c[q>>2]|0)+(c[o>>2]|0)<<2)>>2]=+g[(c[k>>2]|0)+(c[q>>2]<<2)>>2];c[q>>2]=(c[q>>2]|0)+1}c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[o>>2]|0))break;g[(c[p>>2]|0)+(c[q>>2]<<2)>>2]=+g[(c[k>>2]|0)+((c[n>>2]|0)-(c[q>>2]|0)-1<<2)>>2];c[q>>2]=(c[q>>2]|0)+1}c[q>>2]=0;while(1){if((c[q>>2]|0)>=((c[n>>2]|0)-3|0))break;c[t>>2]=0;c[t+4>>2]=0;c[t+8>>2]=0;c[t+12>>2]=0;vd(f,h+(c[q>>2]<<2)|0,t,c[o>>2]|0);g[(c[m>>2]|0)+(c[q>>2]<<2)>>2]=+g[(c[k>>2]|0)+(c[q>>2]<<2)>>2]+ +g[t>>2];g[(c[m>>2]|0)+((c[q>>2]|0)+1<<2)>>2]=+g[(c[k>>2]|0)+((c[q>>2]|0)+1<<2)>>2]+ +g[t+4>>2];g[(c[m>>2]|0)+((c[q>>2]|0)+2<<2)>>2]=+g[(c[k>>2]|0)+((c[q>>2]|0)+2<<2)>>2]+ +g[t+8>>2];g[(c[m>>2]|0)+((c[q>>2]|0)+3<<2)>>2]=+g[(c[k>>2]|0)+((c[q>>2]|0)+3<<2)>>2]+ +g[t+12>>2];c[q>>2]=(c[q>>2]|0)+4}while(1){if((c[q>>2]|0)>=(c[n>>2]|0))break;g[u>>2]=0.0;c[r>>2]=0;while(1){if((c[r>>2]|0)>=(c[o>>2]|0))break;g[u>>2]=+g[u>>2]+ +g[f+(c[r>>2]<<2)>>2]*+g[h+((c[q>>2]|0)+(c[r>>2]|0)<<2)>>2];c[r>>2]=(c[r>>2]|0)+1}g[(c[m>>2]|0)+(c[q>>2]<<2)>>2]=+g[(c[k>>2]|0)+(c[q>>2]<<2)>>2]+ +g[u>>2];c[q>>2]=(c[q>>2]|0)+1}ka(c[s>>2]|0);i=j;return}function Ab(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;j=i;i=i+64|0;k=j+48|0;l=j+28|0;m=j;n=j+40|0;o=j+44|0;p=j+52|0;q=j+24|0;r=j+36|0;s=j+32|0;t=j+8|0;u=j+4|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=d;c[n>>2]=e;c[o>>2]=f;c[p>>2]=h;h=c[o>>2]|0;c[s>>2]=ua()|0;f=i;i=i+((1*(h<<2)|0)+15&-16)|0;h=i;i=i+((1*((c[n>>2]|0)+(c[o>>2]|0)<<2)|0)+15&-16)|0;c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[o>>2]|0))break;g[f+(c[q>>2]<<2)>>2]=+g[(c[l>>2]|0)+((c[o>>2]|0)-(c[q>>2]|0)-1<<2)>>2];c[q>>2]=(c[q>>2]|0)+1}c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[o>>2]|0))break;g[h+(c[q>>2]<<2)>>2]=-+g[(c[p>>2]|0)+((c[o>>2]|0)-(c[q>>2]|0)-1<<2)>>2];c[q>>2]=(c[q>>2]|0)+1}while(1){if((c[q>>2]|0)>=((c[n>>2]|0)+(c[o>>2]|0)|0))break;g[h+(c[q>>2]<<2)>>2]=0.0;c[q>>2]=(c[q>>2]|0)+1}c[q>>2]=0;while(1){if((c[q>>2]|0)>=((c[n>>2]|0)-3|0))break;g[t>>2]=+g[(c[k>>2]|0)+(c[q>>2]<<2)>>2];g[t+4>>2]=+g[(c[k>>2]|0)+((c[q>>2]|0)+1<<2)>>2];g[t+8>>2]=+g[(c[k>>2]|0)+((c[q>>2]|0)+2<<2)>>2];g[t+12>>2]=+g[(c[k>>2]|0)+((c[q>>2]|0)+3<<2)>>2];vd(f,h+(c[q>>2]<<2)|0,t,c[o>>2]|0);g[h+((c[q>>2]|0)+(c[o>>2]|0)<<2)>>2]=-+g[t>>2];g[(c[m>>2]|0)+(c[q>>2]<<2)>>2]=+g[t>>2];g[t+4>>2]=+g[t+4>>2]+ +g[h+((c[q>>2]|0)+(c[o>>2]|0)<<2)>>2]*+g[c[l>>2]>>2];g[h+((c[q>>2]|0)+(c[o>>2]|0)+1<<2)>>2]=-+g[t+4>>2];g[(c[m>>2]|0)+((c[q>>2]|0)+1<<2)>>2]=+g[t+4>>2];g[t+8>>2]=+g[t+8>>2]+ +g[h+((c[q>>2]|0)+(c[o>>2]|0)+1<<2)>>2]*+g[c[l>>2]>>2];g[t+8>>2]=+g[t+8>>2]+ +g[h+((c[q>>2]|0)+(c[o>>2]|0)<<2)>>2]*+g[(c[l>>2]|0)+4>>2];g[h+((c[q>>2]|0)+(c[o>>2]|0)+2<<2)>>2]=-+g[t+8>>2];g[(c[m>>2]|0)+((c[q>>2]|0)+2<<2)>>2]=+g[t+8>>2];g[t+12>>2]=+g[t+12>>2]+ +g[h+((c[q>>2]|0)+(c[o>>2]|0)+2<<2)>>2]*+g[c[l>>2]>>2];g[t+12>>2]=+g[t+12>>2]+ +g[h+((c[q>>2]|0)+(c[o>>2]|0)+1<<2)>>2]*+g[(c[l>>2]|0)+4>>2];g[t+12>>2]=+g[t+12>>2]+ +g[h+((c[q>>2]|0)+(c[o>>2]|0)<<2)>>2]*+g[(c[l>>2]|0)+8>>2];g[h+((c[q>>2]|0)+(c[o>>2]|0)+3<<2)>>2]=-+g[t+12>>2];g[(c[m>>2]|0)+((c[q>>2]|0)+3<<2)>>2]=+g[t+12>>2];c[q>>2]=(c[q>>2]|0)+4}while(1){if((c[q>>2]|0)>=(c[n>>2]|0))break;g[u>>2]=+g[(c[k>>2]|0)+(c[q>>2]<<2)>>2];c[r>>2]=0;while(1){if((c[r>>2]|0)>=(c[o>>2]|0))break;g[u>>2]=+g[u>>2]-+g[f+(c[r>>2]<<2)>>2]*+g[h+((c[q>>2]|0)+(c[r>>2]|0)<<2)>>2];c[r>>2]=(c[r>>2]|0)+1}g[h+((c[q>>2]|0)+(c[o>>2]|0)<<2)>>2]=+g[u>>2];g[(c[m>>2]|0)+(c[q>>2]<<2)>>2]=+g[u>>2];c[q>>2]=(c[q>>2]|0)+1}c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[o>>2]|0))break;g[(c[p>>2]|0)+(c[q>>2]<<2)>>2]=+g[(c[m>>2]|0)+((c[n>>2]|0)-(c[q>>2]|0)-1<<2)>>2];c[q>>2]=(c[q>>2]|0)+1}ka(c[s>>2]|0);i=j;return}function Bb(a,b,d,e,f,h,j){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0;k=i;i=i+64|0;l=k+52|0;m=k+44|0;n=k+24|0;o=k+20|0;p=k+12|0;q=k+40|0;r=k+56|0;s=k+28|0;t=k+8|0;u=k+4|0;v=k+32|0;w=k;x=k+16|0;y=k+36|0;c[l>>2]=a;c[m>>2]=b;c[n>>2]=d;c[o>>2]=e;c[p>>2]=f;c[q>>2]=h;c[k+48>>2]=j;c[u>>2]=(c[q>>2]|0)-(c[p>>2]|0);j=c[q>>2]|0;c[x>>2]=ua()|0;h=i;i=i+((1*(j<<2)|0)+15&-16)|0;if(!(c[o>>2]|0))c[w>>2]=c[l>>2];else{c[s>>2]=0;while(1){if((c[s>>2]|0)>=(c[q>>2]|0))break;g[h+(c[s>>2]<<2)>>2]=+g[(c[l>>2]|0)+(c[s>>2]<<2)>>2];c[s>>2]=(c[s>>2]|0)+1}c[s>>2]=0;while(1){if((c[s>>2]|0)>=(c[o>>2]|0))break;g[h+(c[s>>2]<<2)>>2]=+g[(c[l>>2]|0)+(c[s>>2]<<2)>>2]*+g[(c[n>>2]|0)+(c[s>>2]<<2)>>2];g[h+((c[q>>2]|0)-(c[s>>2]|0)-1<<2)>>2]=+g[(c[l>>2]|0)+((c[q>>2]|0)-(c[s>>2]|0)-1<<2)>>2]*+g[(c[n>>2]|0)+(c[s>>2]<<2)>>2];c[s>>2]=(c[s>>2]|0)+1}c[w>>2]=h}c[v>>2]=0;wb(c[w>>2]|0,c[w>>2]|0,c[m>>2]|0,c[u>>2]|0,(c[p>>2]|0)+1|0);c[t>>2]=0;while(1){if((c[t>>2]|0)>(c[p>>2]|0))break;c[s>>2]=(c[t>>2]|0)+(c[u>>2]|0);g[r>>2]=0.0;while(1){z=+g[r>>2];if((c[s>>2]|0)>=(c[q>>2]|0))break;g[r>>2]=z+ +g[(c[w>>2]|0)+(c[s>>2]<<2)>>2]*+g[(c[w>>2]|0)+((c[s>>2]|0)-(c[t>>2]|0)<<2)>>2];c[s>>2]=(c[s>>2]|0)+1}h=(c[m>>2]|0)+(c[t>>2]<<2)|0;g[h>>2]=+g[h>>2]+z;c[t>>2]=(c[t>>2]|0)+1}t=c[v>>2]|0;c[y>>2]=1;ka(c[x>>2]|0);i=k;return t|0}function Cb(a,b,e,f,h,j,k,l){a=a|0;b=b|0;e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;l=l|0;var m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0.0;m=i;i=i+96|0;n=m+36|0;o=m+24|0;p=m+20|0;q=m+72|0;r=m+32|0;s=m+16|0;t=m+52|0;u=m+60|0;v=m+68|0;w=m+76|0;x=m+80|0;y=m+40|0;z=m+8|0;A=m;B=m+4|0;C=m+48|0;D=m+56|0;E=m+28|0;F=m+64|0;G=m+12|0;c[n>>2]=a;c[o>>2]=b;c[p>>2]=e;c[q>>2]=f;c[r>>2]=h;c[s>>2]=j;c[t>>2]=k;c[u>>2]=l;c[v>>2]=2552+((c[u>>2]|0)*84|0)+((c[r>>2]|0)*42|0);c[y>>2]=0;c[y+4>>2]=0;if(c[r>>2]|0){g[z>>2]=0.0;g[A>>2]=.149993896484375}else{g[A>>2]=+g[2904+(c[u>>2]<<2)>>2];g[z>>2]=+g[2888+(c[u>>2]<<2)>>2]}c[B>>2]=c[(c[s>>2]|0)+4>>2]<<3;c[w>>2]=c[o>>2];while(1){if((c[w>>2]|0)>=(c[p>>2]|0))break;c[x>>2]=0;do{c[C>>2]=wd(c[s>>2]|0)|0;do if(((c[B>>2]|0)-(c[C>>2]|0)|0)<15){if(((c[B>>2]|0)-(c[C>>2]|0)|0)>=2){c[D>>2]=jb(c[s>>2]|0,2920,2)|0;c[D>>2]=c[D>>2]>>1^0-(c[D>>2]&1);break}if(((c[B>>2]|0)-(c[C>>2]|0)|0)>=1){c[D>>2]=0-(ib(c[s>>2]|0,1)|0);break}else{c[D>>2]=-1;break}}else{c[G>>2]=((c[w>>2]|0)<20?c[w>>2]|0:20)<<1;c[D>>2]=rb(c[s>>2]|0,(d[(c[v>>2]|0)+(c[G>>2]|0)>>0]|0)<<7,(d[(c[v>>2]|0)+((c[G>>2]|0)+1)>>0]|0)<<6)|0}while(0);g[E>>2]=+(c[D>>2]|0);o=(c[w>>2]|0)+(_(c[x>>2]|0,c[(c[n>>2]|0)+8>>2]|0)|0)|0;if(-9.0>+g[(c[q>>2]|0)+(o<<2)>>2])H=-9.0;else{o=(c[w>>2]|0)+(_(c[x>>2]|0,c[(c[n>>2]|0)+8>>2]|0)|0)|0;H=+g[(c[q>>2]|0)+(o<<2)>>2]}o=(c[w>>2]|0)+(_(c[x>>2]|0,c[(c[n>>2]|0)+8>>2]|0)|0)|0;g[(c[q>>2]|0)+(o<<2)>>2]=H;o=(c[w>>2]|0)+(_(c[x>>2]|0,c[(c[n>>2]|0)+8>>2]|0)|0)|0;g[F>>2]=+g[z>>2]*+g[(c[q>>2]|0)+(o<<2)>>2]+ +g[y+(c[x>>2]<<2)>>2]+ +g[E>>2];o=(c[w>>2]|0)+(_(c[x>>2]|0,c[(c[n>>2]|0)+8>>2]|0)|0)|0;g[(c[q>>2]|0)+(o<<2)>>2]=+g[F>>2];g[y+(c[x>>2]<<2)>>2]=+g[y+(c[x>>2]<<2)>>2]+ +g[E>>2]-+g[A>>2]*+g[E>>2];o=(c[x>>2]|0)+1|0;c[x>>2]=o}while((o|0)<(c[t>>2]|0));c[w>>2]=(c[w>>2]|0)+1}i=m;return}function Db(a,b,d,e,f,h,j){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;k=i;i=i+48|0;l=k+36|0;m=k+16|0;n=k;o=k+28|0;p=k+32|0;q=k+40|0;r=k+12|0;s=k+24|0;t=k+20|0;u=k+8|0;v=k+4|0;c[l>>2]=a;c[m>>2]=b;c[n>>2]=d;c[o>>2]=e;c[p>>2]=f;c[q>>2]=h;c[r>>2]=j;c[s>>2]=c[m>>2];while(1){if((c[s>>2]|0)>=(c[n>>2]|0))break;if((c[(c[p>>2]|0)+(c[s>>2]<<2)>>2]|0)>0){c[t>>2]=0;do{c[u>>2]=lb(c[q>>2]|0,c[(c[p>>2]|0)+(c[s>>2]<<2)>>2]|0)|0;g[v>>2]=(+(c[u>>2]|0)+.5)*+(1<<14-(c[(c[p>>2]|0)+(c[s>>2]<<2)>>2]|0)|0)*.00006103515625-.5;m=(c[s>>2]|0)+(_(c[t>>2]|0,c[(c[l>>2]|0)+8>>2]|0)|0)|0;j=(c[o>>2]|0)+(m<<2)|0;g[j>>2]=+g[j>>2]+ +g[v>>2];j=(c[t>>2]|0)+1|0;c[t>>2]=j}while((j|0)<(c[r>>2]|0))}c[s>>2]=(c[s>>2]|0)+1}i=k;return}function Eb(a,b,d,e,f,h,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;l=l|0;var m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;m=i;i=i+64|0;n=m+24|0;o=m+20|0;p=m+44|0;q=m+36|0;r=m+32|0;s=m+40|0;t=m+48|0;u=m+52|0;v=m+8|0;w=m+4|0;x=m+28|0;y=m+12|0;z=m;A=m+16|0;c[n>>2]=a;c[o>>2]=b;c[p>>2]=d;c[q>>2]=e;c[r>>2]=f;c[s>>2]=h;c[t>>2]=j;c[u>>2]=k;c[v>>2]=l;c[x>>2]=0;while(1){if((c[x>>2]|0)>=2)break;c[w>>2]=c[o>>2];while(1){if((c[w>>2]|0)>=(c[p>>2]|0))break;if((c[t>>2]|0)<(c[v>>2]|0))break;if((c[(c[r>>2]|0)+(c[w>>2]<<2)>>2]|0)<8?(c[(c[s>>2]|0)+(c[w>>2]<<2)>>2]|0)==(c[x>>2]|0):0){c[y>>2]=0;do{c[z>>2]=lb(c[u>>2]|0,1)|0;g[A>>2]=(+(c[z>>2]|0)-.5)*+(1<<14-(c[(c[r>>2]|0)+(c[w>>2]<<2)>>2]|0)-1|0)*.00006103515625;l=(c[w>>2]|0)+(_(c[y>>2]|0,c[(c[n>>2]|0)+8>>2]|0)|0)|0;k=(c[q>>2]|0)+(l<<2)|0;g[k>>2]=+g[k>>2]+ +g[A>>2];c[t>>2]=(c[t>>2]|0)+-1;k=(c[y>>2]|0)+1|0;c[y>>2]=k}while((k|0)<(c[v>>2]|0))}c[w>>2]=(c[w>>2]|0)+1}c[x>>2]=(c[x>>2]|0)+1}i=m;return}function Fb(a,e,f,g,h,j,k,l,m,n,o,p,q,r,s,t,u,v,w){a=a|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0;q=q|0;r=r|0;s=s|0;t=t|0;u=u|0;v=v|0;w=w|0;var x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0;x=i;i=i+160|0;y=x+72|0;z=x+56|0;A=x+4|0;B=x+52|0;C=x+140|0;D=x+68|0;E=x+20|0;F=x+24|0;G=x+28|0;H=x+32|0;I=x+36|0;J=x+40|0;K=x+44|0;L=x+48|0;M=x+112|0;N=x+120|0;O=x+128|0;P=x+136|0;Q=x+144|0;R=x+148|0;S=x+76|0;T=x+80|0;U=x+84|0;V=x+88|0;W=x+92|0;X=x+96|0;Y=x+100|0;Z=x+104|0;$=x+12|0;aa=x;ba=x+8|0;ca=x+108|0;da=x+116|0;ea=x+60|0;fa=x+124|0;ga=x+16|0;ha=x+64|0;ia=x+132|0;c[y>>2]=a;c[z>>2]=e;c[A>>2]=f;c[B>>2]=g;c[C>>2]=h;c[D>>2]=j;c[E>>2]=k;c[F>>2]=l;c[G>>2]=m;c[H>>2]=n;c[I>>2]=o;c[J>>2]=p;c[K>>2]=q;c[L>>2]=r;c[M>>2]=s;c[N>>2]=t;c[O>>2]=u;c[P>>2]=v;c[Q>>2]=w;c[G>>2]=(c[G>>2]|0)>0?c[G>>2]|0:0;c[T>>2]=c[(c[y>>2]|0)+8>>2];c[W>>2]=c[z>>2];c[X>>2]=(c[G>>2]|0)>=8?8:0;c[G>>2]=(c[G>>2]|0)-(c[X>>2]|0);c[Z>>2]=0;c[Y>>2]=0;do if((c[L>>2]|0)==2){c[Y>>2]=d[2928+((c[A>>2]|0)-(c[z>>2]|0))>>0];if((c[Y>>2]|0)>(c[G>>2]|0)){c[Y>>2]=0;break}else{c[G>>2]=(c[G>>2]|0)-(c[Y>>2]|0);c[Z>>2]=(c[G>>2]|0)>=8?8:0;c[G>>2]=(c[G>>2]|0)-(c[Z>>2]|0);break}}while(0);w=c[T>>2]|0;c[$>>2]=ua()|0;v=i;i=i+((1*(w<<2)|0)+15&-16)|0;w=i;i=i+((1*(c[T>>2]<<2)|0)+15&-16)|0;u=i;i=i+((1*(c[T>>2]<<2)|0)+15&-16)|0;t=i;i=i+((1*(c[T>>2]<<2)|0)+15&-16)|0;c[U>>2]=c[z>>2];while(1){if((c[U>>2]|0)>=(c[A>>2]|0))break;if((c[L>>2]<<3|0)>(((b[(c[(c[y>>2]|0)+32>>2]|0)+((c[U>>2]|0)+1<<1)>>1]|0)-(b[(c[(c[y>>2]|0)+32>>2]|0)+(c[U>>2]<<1)>>1]|0)|0)*3<<c[M>>2]<<3>>4|0))ja=c[L>>2]<<3;else ja=((b[(c[(c[y>>2]|0)+32>>2]|0)+((c[U>>2]|0)+1<<1)>>1]|0)-(b[(c[(c[y>>2]|0)+32>>2]|0)+(c[U>>2]<<1)>>1]|0)|0)*3<<c[M>>2]<<3>>4;c[u+(c[U>>2]<<2)>>2]=ja;s=_(c[L>>2]|0,(b[(c[(c[y>>2]|0)+32>>2]|0)+((c[U>>2]|0)+1<<1)>>1]|0)-(b[(c[(c[y>>2]|0)+32>>2]|0)+(c[U>>2]<<1)>>1]|0)|0)|0;r=_(s,(c[D>>2]|0)-5-(c[M>>2]|0)|0)|0;s=_(r,(c[A>>2]|0)-(c[U>>2]|0)-1|0)|0;r=(_(s,1<<(c[M>>2]|0)+3)|0)>>6;c[t+(c[U>>2]<<2)>>2]=r;if(((b[(c[(c[y>>2]|0)+32>>2]|0)+((c[U>>2]|0)+1<<1)>>1]|0)-(b[(c[(c[y>>2]|0)+32>>2]|0)+(c[U>>2]<<1)>>1]|0)<<c[M>>2]|0)==1){r=t+(c[U>>2]<<2)|0;c[r>>2]=(c[r>>2]|0)-(c[L>>2]<<3)}c[U>>2]=(c[U>>2]|0)+1}c[R>>2]=1;c[S>>2]=(c[(c[y>>2]|0)+48>>2]|0)-1;do{c[aa>>2]=0;c[ba>>2]=0;c[ca>>2]=(c[R>>2]|0)+(c[S>>2]|0)>>1;c[U>>2]=c[A>>2];while(1){D=c[U>>2]|0;c[U>>2]=D+-1;if((D|0)<=(c[z>>2]|0))break;c[ea>>2]=(b[(c[(c[y>>2]|0)+32>>2]|0)+((c[U>>2]|0)+1<<1)>>1]|0)-(b[(c[(c[y>>2]|0)+32>>2]|0)+(c[U>>2]<<1)>>1]|0);D=_(c[L>>2]|0,c[ea>>2]|0)|0;ja=_(c[ca>>2]|0,c[T>>2]|0)|0;r=_(D,d[(c[(c[y>>2]|0)+52>>2]|0)+(ja+(c[U>>2]|0))>>0]|0)|0;c[da>>2]=r<<c[M>>2]>>2;if((c[da>>2]|0)>0){if(0>((c[da>>2]|0)+(c[t+(c[U>>2]<<2)>>2]|0)|0))la=0;else la=(c[da>>2]|0)+(c[t+(c[U>>2]<<2)>>2]|0)|0;c[da>>2]=la}c[da>>2]=(c[da>>2]|0)+(c[(c[B>>2]|0)+(c[U>>2]<<2)>>2]|0);if(!((c[aa>>2]|0)!=0?1:(c[da>>2]|0)>=(c[u+(c[U>>2]<<2)>>2]|0))){if((c[da>>2]|0)<(c[L>>2]<<3|0))continue;c[ba>>2]=(c[ba>>2]|0)+(c[L>>2]<<3);continue}c[aa>>2]=1;if((c[da>>2]|0)<(c[(c[C>>2]|0)+(c[U>>2]<<2)>>2]|0))ma=c[da>>2]|0;else ma=c[(c[C>>2]|0)+(c[U>>2]<<2)>>2]|0;c[ba>>2]=(c[ba>>2]|0)+ma}r=c[ca>>2]|0;if((c[ba>>2]|0)>(c[G>>2]|0))c[S>>2]=r-1;else c[R>>2]=r+1}while((c[R>>2]|0)<=(c[S>>2]|0));ba=c[R>>2]|0;c[R>>2]=ba+-1;c[S>>2]=ba;c[U>>2]=c[z>>2];while(1){if((c[U>>2]|0)>=(c[A>>2]|0))break;c[ha>>2]=(b[(c[(c[y>>2]|0)+32>>2]|0)+((c[U>>2]|0)+1<<1)>>1]|0)-(b[(c[(c[y>>2]|0)+32>>2]|0)+(c[U>>2]<<1)>>1]|0);ba=_(c[L>>2]|0,c[ha>>2]|0)|0;ca=_(c[R>>2]|0,c[T>>2]|0)|0;ma=_(ba,d[(c[(c[y>>2]|0)+52>>2]|0)+(ca+(c[U>>2]|0))>>0]|0)|0;c[fa>>2]=ma<<c[M>>2]>>2;if((c[S>>2]|0)>=(c[(c[y>>2]|0)+48>>2]|0))na=c[(c[C>>2]|0)+(c[U>>2]<<2)>>2]|0;else{ma=_(c[L>>2]|0,c[ha>>2]|0)|0;ca=_(c[S>>2]|0,c[T>>2]|0)|0;ba=_(ma,d[(c[(c[y>>2]|0)+52>>2]|0)+(ca+(c[U>>2]|0))>>0]|0)|0;na=ba<<c[M>>2]>>2}c[ga>>2]=na;if((c[fa>>2]|0)>0){if(0>((c[fa>>2]|0)+(c[t+(c[U>>2]<<2)>>2]|0)|0))oa=0;else oa=(c[fa>>2]|0)+(c[t+(c[U>>2]<<2)>>2]|0)|0;c[fa>>2]=oa}if((c[ga>>2]|0)>0){if(0>((c[ga>>2]|0)+(c[t+(c[U>>2]<<2)>>2]|0)|0))pa=0;else pa=(c[ga>>2]|0)+(c[t+(c[U>>2]<<2)>>2]|0)|0;c[ga>>2]=pa}if((c[R>>2]|0)>0)c[fa>>2]=(c[fa>>2]|0)+(c[(c[B>>2]|0)+(c[U>>2]<<2)>>2]|0);c[ga>>2]=(c[ga>>2]|0)+(c[(c[B>>2]|0)+(c[U>>2]<<2)>>2]|0);if((c[(c[B>>2]|0)+(c[U>>2]<<2)>>2]|0)>0)c[W>>2]=c[U>>2];if(0>((c[ga>>2]|0)-(c[fa>>2]|0)|0))qa=0;else qa=(c[ga>>2]|0)-(c[fa>>2]|0)|0;c[ga>>2]=qa;c[v+(c[U>>2]<<2)>>2]=c[fa>>2];c[w+(c[U>>2]<<2)>>2]=c[ga>>2];c[U>>2]=(c[U>>2]|0)+1}c[V>>2]=xd(c[y>>2]|0,c[z>>2]|0,c[A>>2]|0,c[W>>2]|0,v,w,u,c[C>>2]|0,c[G>>2]|0,c[H>>2]|0,c[X>>2]|0,c[E>>2]|0,c[Y>>2]|0,c[F>>2]|0,c[Z>>2]|0,c[I>>2]|0,c[J>>2]|0,c[K>>2]|0,c[L>>2]|0,c[M>>2]|0,c[N>>2]|0,c[O>>2]|0,c[P>>2]|0,c[Q>>2]|0)|0;Q=c[V>>2]|0;c[ia>>2]=1;ka(c[$>>2]|0);i=x;return Q|0}function Gb(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0;j=i;i=i+96|0;k=j+84|0;l=j;m=j+4|0;n=j+40|0;o=j+76|0;p=j+16|0;q=j+20|0;r=j+24|0;s=j+64|0;t=j+72|0;u=j+80|0;v=j+88|0;w=j+44|0;x=j+48|0;y=j+52|0;z=j+8|0;A=j+56|0;B=j+28|0;C=j+60|0;D=j+12|0;E=j+32|0;F=j+68|0;G=j+36|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=d;c[n>>2]=e;c[o>>2]=f;c[p>>2]=h;h=c[l>>2]|0;c[y>>2]=ua()|0;f=i;i=i+((1*(h<<2)|0)+15&-16)|0;h=i;i=i+((1*(c[l>>2]<<2)|0)+15&-16)|0;e=i;i=i+((1*(c[l>>2]<<2)|0)+15&-16)|0;yd(c[k>>2]|0,c[l>>2]|0,1,c[o>>2]|0,c[m>>2]|0,c[n>>2]|0);g[u>>2]=0.0;c[r>>2]=0;do{n=e+(c[r>>2]<<2)|0;if(+g[(c[k>>2]|0)+(c[r>>2]<<2)>>2]>0.0)g[n>>2]=1.0;else{g[n>>2]=-1.0;g[(c[k>>2]|0)+(c[r>>2]<<2)>>2]=-+g[(c[k>>2]|0)+(c[r>>2]<<2)>>2]}c[h+(c[r>>2]<<2)>>2]=0;g[f+(c[r>>2]<<2)>>2]=0.0;n=(c[r>>2]|0)+1|0;c[r>>2]=n}while((n|0)<(c[l>>2]|0));g[w>>2]=0.0;g[v>>2]=0.0;c[t>>2]=c[m>>2];if((c[m>>2]|0)>(c[l>>2]>>1|0)){c[r>>2]=0;do{g[u>>2]=+g[u>>2]+ +g[(c[k>>2]|0)+(c[r>>2]<<2)>>2];n=(c[r>>2]|0)+1|0;c[r>>2]=n}while((n|0)<(c[l>>2]|0));if(!(+g[u>>2]>1.0000000036274937e-15&+g[u>>2]<64.0)){g[c[k>>2]>>2]=1.0;c[r>>2]=1;do{g[(c[k>>2]|0)+(c[r>>2]<<2)>>2]=0.0;n=(c[r>>2]|0)+1|0;c[r>>2]=n}while((n|0)<(c[l>>2]|0));g[u>>2]=1.0}g[z>>2]=+((c[m>>2]|0)-1|0)*(1.0/+g[u>>2]);c[r>>2]=0;do{u=~~+M(+(+g[z>>2]*+g[(c[k>>2]|0)+(c[r>>2]<<2)>>2]));c[h+(c[r>>2]<<2)>>2]=u;g[f+(c[r>>2]<<2)>>2]=+(c[h+(c[r>>2]<<2)>>2]|0);g[w>>2]=+g[w>>2]+ +g[f+(c[r>>2]<<2)>>2]*+g[f+(c[r>>2]<<2)>>2];g[v>>2]=+g[v>>2]+ +g[(c[k>>2]|0)+(c[r>>2]<<2)>>2]*+g[f+(c[r>>2]<<2)>>2];u=f+(c[r>>2]<<2)|0;g[u>>2]=+g[u>>2]*2.0;c[t>>2]=(c[t>>2]|0)-(c[h+(c[r>>2]<<2)>>2]|0);u=(c[r>>2]|0)+1|0;c[r>>2]=u}while((u|0)<(c[l>>2]|0))}if((c[t>>2]|0)>((c[l>>2]|0)+3|0)){g[A>>2]=+(c[t>>2]|0);g[w>>2]=+g[w>>2]+ +g[A>>2]*+g[A>>2];g[w>>2]=+g[w>>2]+ +g[A>>2]*+g[f>>2];c[h>>2]=(c[h>>2]|0)+(c[t>>2]|0);c[t>>2]=0}g[s>>2]=1.0;c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[t>>2]|0))break;g[C>>2]=-999999986991104.0;g[D>>2]=0.0;c[B>>2]=0;g[w>>2]=+g[w>>2]+1.0;c[r>>2]=0;do{g[E>>2]=+g[v>>2]+ +g[(c[k>>2]|0)+(c[r>>2]<<2)>>2];g[F>>2]=+g[w>>2]+ +g[f+(c[r>>2]<<2)>>2];g[E>>2]=+g[E>>2]*+g[E>>2];if(+g[D>>2]*+g[E>>2]>+g[F>>2]*+g[C>>2]){g[D>>2]=+g[F>>2];g[C>>2]=+g[E>>2];c[B>>2]=c[r>>2]}A=(c[r>>2]|0)+1|0;c[r>>2]=A}while((A|0)<(c[l>>2]|0));g[v>>2]=+g[v>>2]+ +g[(c[k>>2]|0)+(c[B>>2]<<2)>>2];g[w>>2]=+g[w>>2]+ +g[f+(c[B>>2]<<2)>>2];A=f+(c[B>>2]<<2)|0;g[A>>2]=+g[A>>2]+ +g[s>>2]*2.0;A=h+(c[B>>2]<<2)|0;c[A>>2]=(c[A>>2]|0)+1;c[q>>2]=(c[q>>2]|0)+1}c[r>>2]=0;do{g[(c[k>>2]|0)+(c[r>>2]<<2)>>2]=+g[e+(c[r>>2]<<2)>>2]*+g[(c[k>>2]|0)+(c[r>>2]<<2)>>2];if(+g[e+(c[r>>2]<<2)>>2]<0.0)c[h+(c[r>>2]<<2)>>2]=0-(c[h+(c[r>>2]<<2)>>2]|0);q=(c[r>>2]|0)+1|0;c[r>>2]=q}while((q|0)<(c[l>>2]|0));bb(h,c[l>>2]|0,c[m>>2]|0,c[p>>2]|0);c[x>>2]=zd(h,c[l>>2]|0,c[o>>2]|0)|0;o=c[x>>2]|0;c[G>>2]=1;ka(c[y>>2]|0);i=j;return o|0}function Hb(a,b,d,e,f,h,j){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;j=+j;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;k=i;i=i+48|0;l=k+36|0;m=k+16|0;n=k;o=k+28|0;p=k+32|0;q=k+40|0;r=k+12|0;s=k+24|0;t=k+20|0;u=k+8|0;c[l>>2]=a;c[m>>2]=b;c[n>>2]=d;c[o>>2]=e;c[p>>2]=f;c[q>>2]=h;g[r>>2]=j;h=c[m>>2]|0;c[u>>2]=ua()|0;f=i;i=i+((1*(h<<2)|0)+15&-16)|0;g[s>>2]=+cb(f,c[m>>2]|0,c[n>>2]|0,c[q>>2]|0);Ad(f,c[l>>2]|0,c[m>>2]|0,+g[s>>2],+g[r>>2]);yd(c[l>>2]|0,c[m>>2]|0,-1,c[p>>2]|0,c[n>>2]|0,c[o>>2]|0);c[t>>2]=zd(f,c[m>>2]|0,c[p>>2]|0)|0;p=c[t>>2]|0;c[k+4>>2]=1;ka(c[u>>2]|0);i=k;return p|0}function Ib(a,b,d){a=a|0;b=b|0;d=+d;var e=0,f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;i=i+32|0;f=e+4|0;h=e+16|0;j=e+8|0;k=e+20|0;l=e+28|0;m=e;n=e+12|0;o=e+24|0;c[f>>2]=a;c[h>>2]=b;g[j>>2]=d;g[l>>2]=+Bd(c[f>>2]|0,c[f>>2]|0,c[h>>2]|0)+1.0000000036274937e-15;g[n>>2]=+g[l>>2];d=1.0/+O(+(+g[n>>2]));g[m>>2]=d*+g[j>>2];c[o>>2]=c[f>>2];c[k>>2]=0;while(1){if((c[k>>2]|0)>=(c[h>>2]|0))break;g[c[o>>2]>>2]=+g[m>>2]*+g[c[o>>2]>>2];c[o>>2]=(c[o>>2]|0)+4;c[k>>2]=(c[k>>2]|0)+1}i=e;return}function Jb(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0.0;f=i;i=i+48|0;h=f+4|0;j=f+16|0;k=f+36|0;l=f;m=f+32|0;n=f+40|0;o=f+44|0;p=f+24|0;q=f+20|0;r=f+8|0;s=f+12|0;t=f+28|0;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;g[r>>2]=1.0000000036274937e-15;g[q>>2]=1.0000000036274937e-15;a:do if(c[k>>2]|0){c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[l>>2]|0))break a;g[s>>2]=+g[(c[h>>2]|0)+(c[m>>2]<<2)>>2]+ +g[(c[j>>2]|0)+(c[m>>2]<<2)>>2];g[t>>2]=+g[(c[h>>2]|0)+(c[m>>2]<<2)>>2]-+g[(c[j>>2]|0)+(c[m>>2]<<2)>>2];g[q>>2]=+g[q>>2]+ +g[s>>2]*+g[s>>2];g[r>>2]=+g[r>>2]+ +g[t>>2]*+g[t>>2];c[m>>2]=(c[m>>2]|0)+1}}else{u=+Bd(c[h>>2]|0,c[h>>2]|0,c[l>>2]|0);g[q>>2]=+g[q>>2]+u;u=+Bd(c[j>>2]|0,c[j>>2]|0,c[l>>2]|0);g[r>>2]=+g[r>>2]+u}while(0);g[o>>2]=+O(+(+g[q>>2]));g[p>>2]=+O(+(+g[r>>2]));c[n>>2]=~~+M(+(+W(+(+g[p>>2]),+(+g[o>>2]))*10430.3818359375+.5));i=f;return c[n>>2]|0}function Kb(a){a=a|0;var d=0,e=0,f=0,g=0,h=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[e>>2]=a;c[g>>2]=32767/((c[(c[e>>2]|0)+2340>>2]|0)+1|0)|0;c[h>>2]=0;c[f>>2]=0;while(1){if((c[f>>2]|0)>=(c[(c[e>>2]|0)+2340>>2]|0))break;c[h>>2]=(c[h>>2]|0)+(c[g>>2]|0);b[(c[e>>2]|0)+2772+1280+(c[f>>2]<<1)>>1]=c[h>>2];c[f>>2]=(c[f>>2]|0)+1}c[(c[e>>2]|0)+2772+1376>>2]=0;c[(c[e>>2]|0)+2772+1380>>2]=3176576;i=d;return}function Lb(a,d,e,f){a=a|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;g=i;i=i+80|0;h=g;j=g+16|0;k=g+4|0;l=g+8|0;m=g+32|0;n=g+36|0;o=g+12|0;p=g+24|0;q=g+40|0;r=g+28|0;s=g+20|0;c[h>>2]=a;c[j>>2]=d;c[k>>2]=e;c[l>>2]=f;c[r>>2]=(c[h>>2]|0)+2772;if((c[(c[h>>2]|0)+2316>>2]|0)!=(c[(c[r>>2]|0)+1384>>2]|0)){Kb(c[h>>2]|0);c[(c[r>>2]|0)+1384>>2]=c[(c[h>>2]|0)+2316>>2]}a:do if((c[(c[h>>2]|0)+4160>>2]|0)==0?(c[(c[h>>2]|0)+4164>>2]|0)==0:0){c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[(c[h>>2]|0)+2340>>2]|0))break;f=(c[r>>2]|0)+1280+(c[m>>2]<<1)|0;b[f>>1]=(b[f>>1]|0)+((((b[(c[h>>2]|0)+2344+(c[m>>2]<<1)>>1]|0)-(b[(c[r>>2]|0)+1280+(c[m>>2]<<1)>>1]|0)>>16)*16348|0)+(((b[(c[h>>2]|0)+2344+(c[m>>2]<<1)>>1]|0)-(b[(c[r>>2]|0)+1280+(c[m>>2]<<1)>>1]|0)&65535)*16348>>16));c[m>>2]=(c[m>>2]|0)+1}c[p>>2]=0;c[n>>2]=0;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[(c[h>>2]|0)+2324>>2]|0))break;if((c[(c[j>>2]|0)+16+(c[m>>2]<<2)>>2]|0)>(c[p>>2]|0)){c[p>>2]=c[(c[j>>2]|0)+16+(c[m>>2]<<2)>>2];c[n>>2]=c[m>>2]}c[m>>2]=(c[m>>2]|0)+1}ff((c[r>>2]|0)+(c[(c[h>>2]|0)+2332>>2]<<2)|0,c[r>>2]|0,(_((c[(c[h>>2]|0)+2324>>2]|0)-1|0,c[(c[h>>2]|0)+2332>>2]|0)|0)<<2|0)|0;f=_(c[n>>2]|0,c[(c[h>>2]|0)+2332>>2]|0)|0;df(c[r>>2]|0,(c[h>>2]|0)+4+(f<<2)|0,c[(c[h>>2]|0)+2332>>2]<<2|0)|0;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[(c[h>>2]|0)+2324>>2]|0))break a;f=(c[r>>2]|0)+1376|0;c[f>>2]=(c[f>>2]|0)+((((c[(c[j>>2]|0)+16+(c[m>>2]<<2)>>2]|0)-(c[(c[r>>2]|0)+1376>>2]|0)>>16)*4634|0)+(((c[(c[j>>2]|0)+16+(c[m>>2]<<2)>>2]|0)-(c[(c[r>>2]|0)+1376>>2]|0)&65535)*4634>>16));c[m>>2]=(c[m>>2]|0)+1}}while(0);if(!(c[(c[h>>2]|0)+4160>>2]|0)){bf((c[r>>2]|0)+1312|0,0,c[(c[h>>2]|0)+2340>>2]<<2|0)|0;i=g;return}j=(c[l>>2]|0)+16|0;c[s>>2]=ua()|0;n=i;i=i+((1*(j<<2)|0)+15&-16)|0;Cd(n+64|0,c[r>>2]|0,c[(c[r>>2]|0)+1376>>2]|0,c[l>>2]|0,(c[r>>2]|0)+1380|0);jc(q,(c[r>>2]|0)+1280|0,c[(c[h>>2]|0)+2340>>2]|0);j=n;p=(c[r>>2]|0)+1312|0;f=j+64|0;do{c[j>>2]=c[p>>2];j=j+4|0;p=p+4|0}while((j|0)<(f|0));c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[l>>2]|0))break;c[o>>2]=c[(c[h>>2]|0)+2340>>2]>>1;e=_(c[n+(16+(c[m>>2]|0)-1<<2)>>2]>>16,b[q>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-1<<2)>>2]&65535,b[q>>1]|0)|0)>>16));e=_(c[n+(16+(c[m>>2]|0)-2<<2)>>2]>>16,b[q+2>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-2<<2)>>2]&65535,b[q+2>>1]|0)|0)>>16));e=_(c[n+(16+(c[m>>2]|0)-3<<2)>>2]>>16,b[q+4>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-3<<2)>>2]&65535,b[q+4>>1]|0)|0)>>16));e=_(c[n+(16+(c[m>>2]|0)-4<<2)>>2]>>16,b[q+6>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-4<<2)>>2]&65535,b[q+6>>1]|0)|0)>>16));e=_(c[n+(16+(c[m>>2]|0)-5<<2)>>2]>>16,b[q+8>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-5<<2)>>2]&65535,b[q+8>>1]|0)|0)>>16));e=_(c[n+(16+(c[m>>2]|0)-6<<2)>>2]>>16,b[q+10>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-6<<2)>>2]&65535,b[q+10>>1]|0)|0)>>16));e=_(c[n+(16+(c[m>>2]|0)-7<<2)>>2]>>16,b[q+12>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-7<<2)>>2]&65535,b[q+12>>1]|0)|0)>>16));e=_(c[n+(16+(c[m>>2]|0)-8<<2)>>2]>>16,b[q+14>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-8<<2)>>2]&65535,b[q+14>>1]|0)|0)>>16));e=_(c[n+(16+(c[m>>2]|0)-9<<2)>>2]>>16,b[q+16>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-9<<2)>>2]&65535,b[q+16>>1]|0)|0)>>16));e=_(c[n+(16+(c[m>>2]|0)-10<<2)>>2]>>16,b[q+18>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-10<<2)>>2]&65535,b[q+18>>1]|0)|0)>>16));if((c[(c[h>>2]|0)+2340>>2]|0)==16){e=_(c[n+(16+(c[m>>2]|0)-11<<2)>>2]>>16,b[q+20>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-11<<2)>>2]&65535,b[q+20>>1]|0)|0)>>16));e=_(c[n+(16+(c[m>>2]|0)-12<<2)>>2]>>16,b[q+22>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-12<<2)>>2]&65535,b[q+22>>1]|0)|0)>>16));e=_(c[n+(16+(c[m>>2]|0)-13<<2)>>2]>>16,b[q+24>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-13<<2)>>2]&65535,b[q+24>>1]|0)|0)>>16));e=_(c[n+(16+(c[m>>2]|0)-14<<2)>>2]>>16,b[q+26>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-14<<2)>>2]&65535,b[q+26>>1]|0)|0)>>16));e=_(c[n+(16+(c[m>>2]|0)-15<<2)>>2]>>16,b[q+28>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-15<<2)>>2]&65535,b[q+28>>1]|0)|0)>>16));e=_(c[n+(16+(c[m>>2]|0)-16<<2)>>2]>>16,b[q+30>>1]|0)|0;c[o>>2]=(c[o>>2]|0)+(e+((_(c[n+(16+(c[m>>2]|0)-16<<2)>>2]&65535,b[q+30>>1]|0)|0)>>16))}c[n+(16+(c[m>>2]|0)<<2)>>2]=(c[n+(16+(c[m>>2]|0)<<2)>>2]|0)+(c[o>>2]<<4);if(((b[(c[k>>2]|0)+(c[m>>2]<<1)>>1]|0)+((c[o>>2]>>5)+1>>1)|0)<=32767)if(((b[(c[k>>2]|0)+(c[m>>2]<<1)>>1]|0)+((c[o>>2]>>5)+1>>1)|0)<-32768)t=-32768;else t=(b[(c[k>>2]|0)+(c[m>>2]<<1)>>1]|0)+((c[o>>2]>>5)+1>>1)|0;else t=32767;b[(c[k>>2]|0)+(c[m>>2]<<1)>>1]=t;c[m>>2]=(c[m>>2]|0)+1}j=(c[r>>2]|0)+1312|0;p=n+(c[l>>2]<<2)|0;f=j+64|0;do{c[j>>2]=c[p>>2];j=j+4|0;p=p+4|0}while((j|0)<(f|0));ka(c[s>>2]|0);i=g;return}function Mb(d,e,f,g,h,j){d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;k=i;i=i+48|0;l=k+12|0;m=k+16|0;n=k+28|0;o=k+4|0;p=k+32|0;q=k+36|0;r=k+40|0;s=k+24|0;t=k+20|0;u=k+44|0;v=k;w=k+8|0;c[l>>2]=d;c[m>>2]=e;c[n>>2]=f;c[o>>2]=g;c[p>>2]=h;c[q>>2]=j;a[u+1>>0]=0;c[v>>2]=c[m>>2];c[r>>2]=(((c[p>>2]|0)+(c[o>>2]<<1)&65535)<<16>>16)*7;c[w>>2]=1496+(c[r>>2]|0);c[n>>2]=(c[n>>2]|0)+8>>4;c[r>>2]=0;while(1){if((c[r>>2]|0)>=(c[n>>2]|0))break;c[t>>2]=c[(c[q>>2]|0)+(c[r>>2]<<2)>>2];a:do if((c[t>>2]|0)>0){a[u>>0]=a[(c[w>>2]|0)+((c[t>>2]&31|0)<6?c[t>>2]&31:6)>>0]|0;c[s>>2]=0;while(1){if((c[s>>2]|0)>=16)break a;if((b[(c[v>>2]|0)+(c[s>>2]<<1)>>1]|0)>0){o=((jb(c[l>>2]|0,u,8)|0)<<1)-1|0;p=(c[v>>2]|0)+(c[s>>2]<<1)|0;b[p>>1]=_(b[p>>1]|0,o)|0}c[s>>2]=(c[s>>2]|0)+1}}while(0);c[v>>2]=(c[v>>2]|0)+32;c[r>>2]=(c[r>>2]|0)+1}i=k;return}function Nb(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;bf(c[d>>2]|0,0,4260)|0;c[(c[d>>2]|0)+2376>>2]=1;c[c[d>>2]>>2]=65536;Kb(c[d>>2]|0);Zb(c[d>>2]|0);i=b;return 0}function Ob(d,e,f,g){d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;h=i;i=i+144|0;j=h+48|0;k=h+40|0;l=h;m=h+84|0;n=h+4|0;o=h+16|0;p=h+20|0;q=h+24|0;r=h+28|0;s=h+72|0;t=h+80|0;u=h+88|0;v=h+92|0;w=h+96|0;x=h+104|0;y=h+56|0;z=h+60|0;A=h+8|0;B=h+64|0;C=h+12|0;D=h+32|0;E=h+68|0;F=h+36|0;G=h+76|0;H=h+44|0;I=h+52|0;c[j>>2]=d;c[k>>2]=e;c[l>>2]=f;c[m>>2]=g;c[p>>2]=0;g=c[(c[j>>2]|0)+2336>>2]|0;c[I>>2]=ua()|0;f=i;i=i+((1*(g<<1)|0)+15&-16)|0;g=i;i=i+((1*((c[(c[j>>2]|0)+2336>>2]|0)+(c[(c[j>>2]|0)+2328>>2]|0)<<2)|0)+15&-16)|0;e=i;i=i+((1*(c[(c[j>>2]|0)+2332>>2]<<2)|0)+15&-16)|0;d=i;i=i+((1*((c[(c[j>>2]|0)+2332>>2]|0)+16<<2)|0)+15&-16)|0;c[E>>2]=b[456+(a[(c[j>>2]|0)+2736+29>>0]>>1<<2)+(a[(c[j>>2]|0)+2736+30>>0]<<1)>>1];if((a[(c[j>>2]|0)+2736+31>>0]|0)<4)c[s>>2]=1;else c[s>>2]=0;c[D>>2]=a[(c[j>>2]|0)+2736+34>>0];c[n>>2]=0;while(1){if((c[n>>2]|0)>=(c[(c[j>>2]|0)+2328>>2]|0))break;c[D>>2]=907633515+(_(c[D>>2]|0,196314165)|0);c[(c[j>>2]|0)+4+(c[n>>2]<<2)>>2]=b[(c[m>>2]|0)+(c[n>>2]<<1)>>1]<<14;J=(c[j>>2]|0)+4+(c[n>>2]<<2)|0;K=c[J>>2]|0;if((c[(c[j>>2]|0)+4+(c[n>>2]<<2)>>2]|0)<=0){if((K|0)<0){L=(c[j>>2]|0)+4+(c[n>>2]<<2)|0;c[L>>2]=(c[L>>2]|0)+1280}}else c[J>>2]=K-1280;K=(c[j>>2]|0)+4+(c[n>>2]<<2)|0;c[K>>2]=(c[K>>2]|0)+(c[E>>2]<<4);if((c[D>>2]|0)<0)c[(c[j>>2]|0)+4+(c[n>>2]<<2)>>2]=0-(c[(c[j>>2]|0)+4+(c[n>>2]<<2)>>2]|0);c[D>>2]=(c[D>>2]|0)+(b[(c[m>>2]|0)+(c[n>>2]<<1)>>1]|0);c[n>>2]=(c[n>>2]|0)+1}m=d;D=(c[j>>2]|0)+1284|0;E=m+64|0;do{c[m>>2]=c[D>>2];m=m+4|0;D=D+4|0}while((m|0)<(E|0));c[G>>2]=(c[j>>2]|0)+4;c[w>>2]=c[l>>2];c[r>>2]=c[(c[j>>2]|0)+2336>>2];c[o>>2]=0;while(1){if((c[o>>2]|0)>=(c[(c[j>>2]|0)+2324>>2]|0))break;c[H>>2]=e;c[u>>2]=(c[k>>2]|0)+32+(c[o>>2]>>1<<5);df(x|0,c[u>>2]|0,c[(c[j>>2]|0)+2340>>2]<<1|0)|0;c[v>>2]=(c[k>>2]|0)+96+((c[o>>2]|0)*5<<1);c[t>>2]=a[(c[j>>2]|0)+2736+29>>0];c[A>>2]=c[(c[k>>2]|0)+16+(c[o>>2]<<2)>>2]>>6;c[B>>2]=Dd(c[(c[k>>2]|0)+16+(c[o>>2]<<2)>>2]|0,47)|0;a:do if((c[(c[k>>2]|0)+16+(c[o>>2]<<2)>>2]|0)!=(c[c[j>>2]>>2]|0)){c[C>>2]=Ed(c[c[j>>2]>>2]|0,c[(c[k>>2]|0)+16+(c[o>>2]<<2)>>2]|0,16)|0;c[n>>2]=0;while(1){if((c[n>>2]|0)>=16)break a;K=_(c[C>>2]>>16,(c[d+(c[n>>2]<<2)>>2]&65535)<<16>>16)|0;J=K+((_(c[C>>2]&65535,(c[d+(c[n>>2]<<2)>>2]&65535)<<16>>16)|0)>>16)|0;K=J+(_(c[C>>2]|0,(c[d+(c[n>>2]<<2)>>2]>>15)+1>>1)|0)|0;c[d+(c[n>>2]<<2)>>2]=K;c[n>>2]=(c[n>>2]|0)+1}}else c[C>>2]=65536;while(0);c[c[j>>2]>>2]=c[(c[k>>2]|0)+16+(c[o>>2]<<2)>>2];if(((c[(c[j>>2]|0)+4160>>2]|0)!=0?(c[(c[j>>2]|0)+4164>>2]|0)==2:0)?((c[o>>2]|0)<2?(a[(c[j>>2]|0)+2736+29>>0]|0)!=2:0):0){K=c[v>>2]|0;b[K>>1]=0;b[K+2>>1]=0;b[K+4>>1]=0;b[K+6>>1]=0;b[K+8>>1]=0;b[(c[v>>2]|0)+4>>1]=4096;c[t>>2]=2;c[(c[k>>2]|0)+(c[o>>2]<<2)>>2]=c[(c[j>>2]|0)+2308>>2]}b:do if((c[t>>2]|0)==2){c[p>>2]=c[(c[k>>2]|0)+(c[o>>2]<<2)>>2];if((c[o>>2]|0)!=0?!((c[o>>2]|0)==2&(c[s>>2]|0)!=0):0){if((c[C>>2]|0)==65536)break;c[n>>2]=0;while(1){if((c[n>>2]|0)>=((c[p>>2]|0)+2|0))break b;K=_(c[C>>2]>>16,(c[g+((c[r>>2]|0)-(c[n>>2]|0)-1<<2)>>2]&65535)<<16>>16)|0;J=K+((_(c[C>>2]&65535,(c[g+((c[r>>2]|0)-(c[n>>2]|0)-1<<2)>>2]&65535)<<16>>16)|0)>>16)|0;K=J+(_(c[C>>2]|0,(c[g+((c[r>>2]|0)-(c[n>>2]|0)-1<<2)>>2]>>15)+1>>1)|0)|0;c[g+((c[r>>2]|0)-(c[n>>2]|0)-1<<2)>>2]=K;c[n>>2]=(c[n>>2]|0)+1}}c[q>>2]=(c[(c[j>>2]|0)+2336>>2]|0)-(c[p>>2]|0)-(c[(c[j>>2]|0)+2340>>2]|0)-2;if((c[o>>2]|0)==2)df((c[j>>2]|0)+1348+(c[(c[j>>2]|0)+2336>>2]<<1)|0,c[l>>2]|0,c[(c[j>>2]|0)+2332>>2]<<1<<1|0)|0;K=(c[q>>2]|0)+(_(c[o>>2]|0,c[(c[j>>2]|0)+2332>>2]|0)|0)|0;hc(f+(c[q>>2]<<1)|0,(c[j>>2]|0)+1348+(K<<1)|0,c[u>>2]|0,(c[(c[j>>2]|0)+2336>>2]|0)-(c[q>>2]|0)|0,c[(c[j>>2]|0)+2340>>2]|0);if(!(c[o>>2]|0)){K=_(c[B>>2]>>16,(c[(c[k>>2]|0)+136>>2]&65535)<<16>>16)|0;c[B>>2]=K+((_(c[B>>2]&65535,(c[(c[k>>2]|0)+136>>2]&65535)<<16>>16)|0)>>16)<<2}c[n>>2]=0;while(1){if((c[n>>2]|0)>=((c[p>>2]|0)+2|0))break b;K=_(c[B>>2]>>16,b[f+((c[(c[j>>2]|0)+2336>>2]|0)-(c[n>>2]|0)-1<<1)>>1]|0)|0;J=K+((_(c[B>>2]&65535,b[f+((c[(c[j>>2]|0)+2336>>2]|0)-(c[n>>2]|0)-1<<1)>>1]|0)|0)>>16)|0;c[g+((c[r>>2]|0)-(c[n>>2]|0)-1<<2)>>2]=J;c[n>>2]=(c[n>>2]|0)+1}}while(0);c:do if((c[t>>2]|0)==2){c[F>>2]=g+((c[r>>2]|0)-(c[p>>2]|0)+2<<2);c[n>>2]=0;while(1){if((c[n>>2]|0)>=(c[(c[j>>2]|0)+2332>>2]|0))break c;c[y>>2]=2;J=_(c[c[F>>2]>>2]>>16,b[c[v>>2]>>1]|0)|0;c[y>>2]=(c[y>>2]|0)+(J+((_(c[c[F>>2]>>2]&65535,b[c[v>>2]>>1]|0)|0)>>16));J=_(c[(c[F>>2]|0)+-4>>2]>>16,b[(c[v>>2]|0)+2>>1]|0)|0;c[y>>2]=(c[y>>2]|0)+(J+((_(c[(c[F>>2]|0)+-4>>2]&65535,b[(c[v>>2]|0)+2>>1]|0)|0)>>16));J=_(c[(c[F>>2]|0)+-8>>2]>>16,b[(c[v>>2]|0)+4>>1]|0)|0;c[y>>2]=(c[y>>2]|0)+(J+((_(c[(c[F>>2]|0)+-8>>2]&65535,b[(c[v>>2]|0)+4>>1]|0)|0)>>16));J=_(c[(c[F>>2]|0)+-12>>2]>>16,b[(c[v>>2]|0)+6>>1]|0)|0;c[y>>2]=(c[y>>2]|0)+(J+((_(c[(c[F>>2]|0)+-12>>2]&65535,b[(c[v>>2]|0)+6>>1]|0)|0)>>16));J=_(c[(c[F>>2]|0)+-16>>2]>>16,b[(c[v>>2]|0)+8>>1]|0)|0;c[y>>2]=(c[y>>2]|0)+(J+((_(c[(c[F>>2]|0)+-16>>2]&65535,b[(c[v>>2]|0)+8>>1]|0)|0)>>16));c[F>>2]=(c[F>>2]|0)+4;c[(c[H>>2]|0)+(c[n>>2]<<2)>>2]=(c[(c[G>>2]|0)+(c[n>>2]<<2)>>2]|0)+(c[y>>2]<<1);c[g+(c[r>>2]<<2)>>2]=c[(c[H>>2]|0)+(c[n>>2]<<2)>>2]<<1;c[r>>2]=(c[r>>2]|0)+1;c[n>>2]=(c[n>>2]|0)+1}}else c[H>>2]=c[G>>2];while(0);c[n>>2]=0;while(1){if((c[n>>2]|0)>=(c[(c[j>>2]|0)+2332>>2]|0))break;c[z>>2]=c[(c[j>>2]|0)+2340>>2]>>1;J=_(c[d+(16+(c[n>>2]|0)-1<<2)>>2]>>16,b[x>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-1<<2)>>2]&65535,b[x>>1]|0)|0)>>16));J=_(c[d+(16+(c[n>>2]|0)-2<<2)>>2]>>16,b[x+2>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-2<<2)>>2]&65535,b[x+2>>1]|0)|0)>>16));J=_(c[d+(16+(c[n>>2]|0)-3<<2)>>2]>>16,b[x+4>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-3<<2)>>2]&65535,b[x+4>>1]|0)|0)>>16));J=_(c[d+(16+(c[n>>2]|0)-4<<2)>>2]>>16,b[x+6>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-4<<2)>>2]&65535,b[x+6>>1]|0)|0)>>16));J=_(c[d+(16+(c[n>>2]|0)-5<<2)>>2]>>16,b[x+8>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-5<<2)>>2]&65535,b[x+8>>1]|0)|0)>>16));J=_(c[d+(16+(c[n>>2]|0)-6<<2)>>2]>>16,b[x+10>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-6<<2)>>2]&65535,b[x+10>>1]|0)|0)>>16));J=_(c[d+(16+(c[n>>2]|0)-7<<2)>>2]>>16,b[x+12>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-7<<2)>>2]&65535,b[x+12>>1]|0)|0)>>16));J=_(c[d+(16+(c[n>>2]|0)-8<<2)>>2]>>16,b[x+14>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-8<<2)>>2]&65535,b[x+14>>1]|0)|0)>>16));J=_(c[d+(16+(c[n>>2]|0)-9<<2)>>2]>>16,b[x+16>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-9<<2)>>2]&65535,b[x+16>>1]|0)|0)>>16));J=_(c[d+(16+(c[n>>2]|0)-10<<2)>>2]>>16,b[x+18>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-10<<2)>>2]&65535,b[x+18>>1]|0)|0)>>16));if((c[(c[j>>2]|0)+2340>>2]|0)==16){J=_(c[d+(16+(c[n>>2]|0)-11<<2)>>2]>>16,b[x+20>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-11<<2)>>2]&65535,b[x+20>>1]|0)|0)>>16));J=_(c[d+(16+(c[n>>2]|0)-12<<2)>>2]>>16,b[x+22>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-12<<2)>>2]&65535,b[x+22>>1]|0)|0)>>16));J=_(c[d+(16+(c[n>>2]|0)-13<<2)>>2]>>16,b[x+24>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-13<<2)>>2]&65535,b[x+24>>1]|0)|0)>>16));J=_(c[d+(16+(c[n>>2]|0)-14<<2)>>2]>>16,b[x+26>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-14<<2)>>2]&65535,b[x+26>>1]|0)|0)>>16));J=_(c[d+(16+(c[n>>2]|0)-15<<2)>>2]>>16,b[x+28>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-15<<2)>>2]&65535,b[x+28>>1]|0)|0)>>16));J=_(c[d+(16+(c[n>>2]|0)-16<<2)>>2]>>16,b[x+30>>1]|0)|0;c[z>>2]=(c[z>>2]|0)+(J+((_(c[d+(16+(c[n>>2]|0)-16<<2)>>2]&65535,b[x+30>>1]|0)|0)>>16))}c[d+(16+(c[n>>2]|0)<<2)>>2]=(c[(c[H>>2]|0)+(c[n>>2]<<2)>>2]|0)+(c[z>>2]<<4);J=_(c[d+(16+(c[n>>2]|0)<<2)>>2]>>16,(c[A>>2]&65535)<<16>>16)|0;K=J+((_(c[d+(16+(c[n>>2]|0)<<2)>>2]&65535,(c[A>>2]&65535)<<16>>16)|0)>>16)|0;if(((K+(_(c[d+(16+(c[n>>2]|0)<<2)>>2]|0,(c[A>>2]>>15)+1>>1)|0)>>7)+1>>1|0)<=32767){K=_(c[d+(16+(c[n>>2]|0)<<2)>>2]>>16,(c[A>>2]&65535)<<16>>16)|0;J=K+((_(c[d+(16+(c[n>>2]|0)<<2)>>2]&65535,(c[A>>2]&65535)<<16>>16)|0)>>16)|0;if(((J+(_(c[d+(16+(c[n>>2]|0)<<2)>>2]|0,(c[A>>2]>>15)+1>>1)|0)>>7)+1>>1|0)<-32768)M=-32768;else{J=_(c[d+(16+(c[n>>2]|0)<<2)>>2]>>16,(c[A>>2]&65535)<<16>>16)|0;K=J+((_(c[d+(16+(c[n>>2]|0)<<2)>>2]&65535,(c[A>>2]&65535)<<16>>16)|0)>>16)|0;M=(K+(_(c[d+(16+(c[n>>2]|0)<<2)>>2]|0,(c[A>>2]>>15)+1>>1)|0)>>7)+1>>1}}else M=32767;b[(c[w>>2]|0)+(c[n>>2]<<1)>>1]=M;c[n>>2]=(c[n>>2]|0)+1}m=d;D=d+(c[(c[j>>2]|0)+2332>>2]<<2)|0;E=m+64|0;do{c[m>>2]=c[D>>2];m=m+4|0;D=D+4|0}while((m|0)<(E|0));c[G>>2]=(c[G>>2]|0)+(c[(c[j>>2]|0)+2332>>2]<<2);c[w>>2]=(c[w>>2]|0)+(c[(c[j>>2]|0)+2332>>2]<<1);c[o>>2]=(c[o>>2]|0)+1}m=(c[j>>2]|0)+1284|0;D=d;E=m+64|0;do{c[m>>2]=c[D>>2];m=m+4|0;D=D+4|0}while((m|0)<(E|0));ka(c[I>>2]|0);i=h;return}function Pb(b,d,e,f,g,h){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;j=i;i=i+192|0;k=j+172|0;l=j+152|0;m=j;n=j+164|0;o=j+168|0;p=j+176|0;q=j+148|0;r=j+160|0;s=j+156|0;t=j+8|0;u=j+4|0;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[n>>2]=f;c[o>>2]=g;c[p>>2]=h;c[s>>2]=0;c[q>>2]=c[(c[k>>2]|0)+2328>>2];c[t+136>>2]=0;do if(!(c[o>>2]|0))v=4;else{if((c[o>>2]|0)==2?(c[(c[k>>2]|0)+2420+(c[(c[k>>2]|0)+2388>>2]<<2)>>2]|0)==1:0){v=4;break}_b(c[k>>2]|0,t,c[m>>2]|0,1)}while(0);if((v|0)==4){v=(c[q>>2]|0)+16-1&-16;c[u>>2]=ua()|0;h=i;i=i+((1*(v<<1)|0)+15&-16)|0;Rb(c[k>>2]|0,c[l>>2]|0,c[(c[k>>2]|0)+2388>>2]|0,c[o>>2]|0,c[p>>2]|0);Sb(c[l>>2]|0,h,a[(c[k>>2]|0)+2736+29>>0]|0,a[(c[k>>2]|0)+2736+30>>0]|0,c[(c[k>>2]|0)+2328>>2]|0);Qb(c[k>>2]|0,t,c[p>>2]|0);Ob(c[k>>2]|0,t,c[m>>2]|0,h);_b(c[k>>2]|0,t,c[m>>2]|0,0);c[(c[k>>2]|0)+4160>>2]=0;c[(c[k>>2]|0)+4164>>2]=a[(c[k>>2]|0)+2736+29>>0];c[(c[k>>2]|0)+2376>>2]=0;ka(c[u>>2]|0)}c[r>>2]=(c[(c[k>>2]|0)+2336>>2]|0)-(c[(c[k>>2]|0)+2328>>2]|0);ff((c[k>>2]|0)+1348|0,(c[k>>2]|0)+1348+(c[(c[k>>2]|0)+2328>>2]<<1)|0,c[r>>2]<<1|0)|0;df((c[k>>2]|0)+1348+(c[r>>2]<<1)|0,c[m>>2]|0,c[(c[k>>2]|0)+2328>>2]<<1|0)|0;$b(c[k>>2]|0,c[m>>2]|0,c[q>>2]|0);Lb(c[k>>2]|0,t,c[m>>2]|0,c[q>>2]|0);c[(c[k>>2]|0)+2308>>2]=c[t+((c[(c[k>>2]|0)+2324>>2]|0)-1<<2)>>2];c[c[n>>2]>>2]=c[q>>2];i=j;return c[s>>2]|0}function Qb(d,e,f){d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;g=i;i=i+96|0;h=g+4|0;j=g+16|0;k=g+12|0;l=g+8|0;m=g+24|0;n=g;o=g+32|0;p=g+64|0;q=g+20|0;c[h>>2]=d;c[j>>2]=e;c[k>>2]=f;Xb((c[j>>2]|0)+16|0,(c[h>>2]|0)+2736|0,(c[h>>2]|0)+2312|0,(c[k>>2]|0)==2&1,c[(c[h>>2]|0)+2324>>2]|0);Yb(o,(c[h>>2]|0)+2736+8|0,c[(c[h>>2]|0)+2732>>2]|0);jc((c[j>>2]|0)+32+32|0,o,c[(c[h>>2]|0)+2340>>2]|0);if((c[(c[h>>2]|0)+2376>>2]|0)==1)a[(c[h>>2]|0)+2736+31>>0]=4;if((a[(c[h>>2]|0)+2736+31>>0]|0)<4){c[l>>2]=0;while(1){if((c[l>>2]|0)>=(c[(c[h>>2]|0)+2340>>2]|0))break;k=(b[(c[h>>2]|0)+2344+(c[l>>2]<<1)>>1]|0)+((_(a[(c[h>>2]|0)+2736+31>>0]|0,(b[o+(c[l>>2]<<1)>>1]|0)-(b[(c[h>>2]|0)+2344+(c[l>>2]<<1)>>1]|0)|0)|0)>>2)&65535;b[p+(c[l>>2]<<1)>>1]=k;c[l>>2]=(c[l>>2]|0)+1}jc((c[j>>2]|0)+32|0,p,c[(c[h>>2]|0)+2340>>2]|0)}else df((c[j>>2]|0)+32|0,(c[j>>2]|0)+32+32|0,c[(c[h>>2]|0)+2340>>2]<<1|0)|0;df((c[h>>2]|0)+2344|0,o|0,c[(c[h>>2]|0)+2340>>2]<<1|0)|0;if(c[(c[h>>2]|0)+4160>>2]|0){ec((c[j>>2]|0)+32|0,c[(c[h>>2]|0)+2340>>2]|0,63570);ec((c[j>>2]|0)+32+32|0,c[(c[h>>2]|0)+2340>>2]|0,63570)}if((a[(c[h>>2]|0)+2736+29>>0]|0)!=2){bf(c[j>>2]|0,0,c[(c[h>>2]|0)+2324>>2]<<2|0)|0;bf((c[j>>2]|0)+96|0,0,(c[(c[h>>2]|0)+2324>>2]|0)*5<<1|0)|0;a[(c[h>>2]|0)+2736+32>>0]=0;c[(c[j>>2]|0)+136>>2]=0;i=g;return}fc(b[(c[h>>2]|0)+2736+26>>1]|0,a[(c[h>>2]|0)+2736+28>>0]|0,c[j>>2]|0,c[(c[h>>2]|0)+2316>>2]|0,c[(c[h>>2]|0)+2324>>2]|0);c[q>>2]=c[240+(a[(c[h>>2]|0)+2736+32>>0]<<2)>>2];c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[(c[h>>2]|0)+2324>>2]|0))break;c[n>>2]=a[(c[h>>2]|0)+2736+4+(c[m>>2]|0)>>0];c[l>>2]=0;while(1){if((c[l>>2]|0)>=5)break;b[(c[j>>2]|0)+96+(((c[m>>2]|0)*5|0)+(c[l>>2]|0)<<1)>>1]=a[(c[q>>2]|0)+(((c[n>>2]|0)*5|0)+(c[l>>2]|0))>>0]<<7;c[l>>2]=(c[l>>2]|0)+1}c[m>>2]=(c[m>>2]|0)+1}c[n>>2]=a[(c[h>>2]|0)+2736+33>>0];c[(c[j>>2]|0)+136>>2]=b[464+(c[n>>2]<<1)>>1];i=g;return}function Rb(d,e,f,g,h){d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0;j=i;i=i+96|0;k=j+36|0;l=j+4|0;m=j+28|0;n=j+16|0;o=j+32|0;p=j;q=j+12|0;r=j+24|0;s=j+20|0;t=j+8|0;u=j+40|0;v=j+72|0;c[k>>2]=d;c[l>>2]=e;c[m>>2]=f;c[n>>2]=g;c[o>>2]=h;if((c[n>>2]|0)==0?(c[(c[k>>2]|0)+2404+(c[m>>2]<<2)>>2]|0)==0:0)c[r>>2]=jb(c[l>>2]|0,440,8)|0;else c[r>>2]=(jb(c[l>>2]|0,432,8)|0)+2;a[(c[k>>2]|0)+2736+29>>0]=c[r>>2]>>1;a[(c[k>>2]|0)+2736+30>>0]=c[r>>2]&1;m=c[l>>2]|0;if((c[o>>2]|0)==2){n=(jb(m,168,8)|0)&255;a[(c[k>>2]|0)+2736>>0]=n}else{n=(jb(m,144+(a[(c[k>>2]|0)+2736+29>>0]<<3)|0,8)|0)<<3&255;a[(c[k>>2]|0)+2736>>0]=n;n=((jb(c[l>>2]|0,504,8)|0)&255)<<24>>24;m=(c[k>>2]|0)+2736|0;a[m>>0]=(a[m>>0]|0)+n}c[p>>2]=1;while(1){w=c[l>>2]|0;if((c[p>>2]|0)>=(c[(c[k>>2]|0)+2324>>2]|0))break;n=(jb(w,168,8)|0)&255;a[(c[k>>2]|0)+2736+(c[p>>2]|0)>>0]=n;c[p>>2]=(c[p>>2]|0)+1}n=_(a[(c[k>>2]|0)+2736+29>>0]>>1,b[c[(c[k>>2]|0)+2732>>2]>>1]|0)|0;m=(jb(w,(c[(c[(c[k>>2]|0)+2732>>2]|0)+12>>2]|0)+n|0,8)|0)&255;a[(c[k>>2]|0)+2736+8>>0]=m;bc(u,v,c[(c[k>>2]|0)+2732>>2]|0,a[(c[k>>2]|0)+2736+8>>0]|0);c[p>>2]=0;while(1){if((c[p>>2]|0)>=(b[(c[(c[k>>2]|0)+2732>>2]|0)+2>>1]|0))break;c[r>>2]=jb(c[l>>2]|0,(c[(c[(c[k>>2]|0)+2732>>2]|0)+24>>2]|0)+(b[u+(c[p>>2]<<1)>>1]|0)|0,8)|0;if(c[r>>2]|0){if((c[r>>2]|0)==8){v=jb(c[l>>2]|0,512,8)|0;c[r>>2]=(c[r>>2]|0)+v}}else{v=jb(c[l>>2]|0,512,8)|0;c[r>>2]=(c[r>>2]|0)-v}a[(c[k>>2]|0)+2736+8+((c[p>>2]|0)+1)>>0]=(c[r>>2]|0)-4;c[p>>2]=(c[p>>2]|0)+1}if((c[(c[k>>2]|0)+2324>>2]|0)==4){p=(jb(c[l>>2]|0,448,8)|0)&255;a[(c[k>>2]|0)+2736+31>>0]=p}else a[(c[k>>2]|0)+2736+31>>0]=4;if((a[(c[k>>2]|0)+2736+29>>0]|0)!=2){x=c[k>>2]|0;y=x+2736|0;z=y+29|0;A=a[z>>0]|0;B=A<<24>>24;C=c[k>>2]|0;D=C+2396|0;c[D>>2]=B;E=c[l>>2]|0;F=jb(E,480,8)|0;G=F&255;H=c[k>>2]|0;I=H+2736|0;J=I+34|0;a[J>>0]=G;i=j;return}c[s>>2]=1;if(((c[o>>2]|0)==2?(c[(c[k>>2]|0)+2396>>2]|0)==2:0)?(c[t>>2]=((jb(c[l>>2]|0,552,8)|0)&65535)<<16>>16,(c[t>>2]|0)>0):0){c[t>>2]=(c[t>>2]|0)-9;b[(c[k>>2]|0)+2736+26>>1]=(b[(c[k>>2]|0)+2400>>1]|0)+(c[t>>2]|0);c[s>>2]=0}if(c[s>>2]|0){s=((jb(c[l>>2]|0,520,8)|0)&65535)<<16>>16;t=(_(s,c[(c[k>>2]|0)+2316>>2]>>1)|0)&65535;b[(c[k>>2]|0)+2736+26>>1]=t;t=((jb(c[l>>2]|0,c[(c[k>>2]|0)+2380>>2]|0,8)|0)&65535)<<16>>16;s=(c[k>>2]|0)+2736+26|0;b[s>>1]=(b[s>>1]|0)+t}b[(c[k>>2]|0)+2400>>1]=b[(c[k>>2]|0)+2736+26>>1]|0;t=(jb(c[l>>2]|0,c[(c[k>>2]|0)+2384>>2]|0,8)|0)&255;a[(c[k>>2]|0)+2736+28>>0]=t;t=(jb(c[l>>2]|0,216,8)|0)&255;a[(c[k>>2]|0)+2736+32>>0]=t;c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[(c[k>>2]|0)+2324>>2]|0))break;t=(jb(c[l>>2]|0,c[224+(a[(c[k>>2]|0)+2736+32>>0]<<2)>>2]|0,8)|0)&255;a[(c[k>>2]|0)+2736+4+(c[q>>2]|0)>>0]=t;c[q>>2]=(c[q>>2]|0)+1}if(!(c[o>>2]|0)){o=(jb(c[l>>2]|0,424,8)|0)&255;a[(c[k>>2]|0)+2736+33>>0]=o;x=c[k>>2]|0;y=x+2736|0;z=y+29|0;A=a[z>>0]|0;B=A<<24>>24;C=c[k>>2]|0;D=C+2396|0;c[D>>2]=B;E=c[l>>2]|0;F=jb(E,480,8)|0;G=F&255;H=c[k>>2]|0;I=H+2736|0;J=I+34|0;a[J>>0]=G;i=j;return}else{a[(c[k>>2]|0)+2736+33>>0]=0;x=c[k>>2]|0;y=x+2736|0;z=y+29|0;A=a[z>>0]|0;B=A<<24>>24;C=c[k>>2]|0;D=C+2396|0;c[D>>2]=B;E=c[l>>2]|0;F=jb(E,480,8)|0;G=F&255;H=c[k>>2]|0;I=H+2736|0;J=I+34|0;a[J>>0]=G;i=j;return}}function Sb(a,d,e,f,g){a=a|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;h=i;i=i+224|0;j=h+84|0;k=h+180|0;l=h+200|0;m=h+208|0;n=h+188|0;o=h+196|0;p=h+204|0;q=h+212|0;r=h+216|0;s=h+80|0;t=h+184|0;u=h+88|0;v=h;w=h+96|0;x=h+192|0;y=h+176|0;c[j>>2]=a;c[k>>2]=d;c[l>>2]=e;c[m>>2]=f;c[n>>2]=g;c[u>>2]=jb(c[j>>2]|0,840+((c[l>>2]>>1)*9|0)|0,8)|0;c[r>>2]=c[n>>2]>>4;if((c[r>>2]<<4|0)<(c[n>>2]|0))c[r>>2]=(c[r>>2]|0)+1;c[y>>2]=656+((c[u>>2]|0)*18|0);c[o>>2]=0;while(1){if((c[o>>2]|0)>=(c[r>>2]|0))break;c[w+(c[o>>2]<<2)>>2]=0;u=jb(c[j>>2]|0,c[y>>2]|0,8)|0;c[v+(c[o>>2]<<2)>>2]=u;while(1){z=c[o>>2]|0;if((c[v+(c[o>>2]<<2)>>2]|0)!=17)break;u=w+(z<<2)|0;c[u>>2]=(c[u>>2]|0)+1;u=jb(c[j>>2]|0,818+((c[w+(c[o>>2]<<2)>>2]|0)==10&1)|0,8)|0;c[v+(c[o>>2]<<2)>>2]=u}c[o>>2]=z+1}c[o>>2]=0;while(1){if((c[o>>2]|0)>=(c[r>>2]|0))break;z=(c[k>>2]|0)+((c[o>>2]&65535)<<16>>16<<4<<1)|0;if((c[v+(c[o>>2]<<2)>>2]|0)>0)ac(z,c[j>>2]|0,c[v+(c[o>>2]<<2)>>2]|0);else{y=z;z=y+32|0;do{b[y>>1]=0;y=y+2|0}while((y|0)<(z|0))}c[o>>2]=(c[o>>2]|0)+1}c[o>>2]=0;while(1){if((c[o>>2]|0)>=(c[r>>2]|0))break;if((c[w+(c[o>>2]<<2)>>2]|0)>0){c[t>>2]=c[w+(c[o>>2]<<2)>>2];c[x>>2]=(c[k>>2]|0)+((c[o>>2]&65535)<<16>>16<<4<<1);c[q>>2]=0;while(1){if((c[q>>2]|0)>=16)break;c[s>>2]=b[(c[x>>2]|0)+(c[q>>2]<<1)>>1];c[p>>2]=0;while(1){A=c[s>>2]|0;if((c[p>>2]|0)>=(c[t>>2]|0))break;c[s>>2]=A<<1;y=jb(c[j>>2]|0,416,8)|0;c[s>>2]=(c[s>>2]|0)+y;c[p>>2]=(c[p>>2]|0)+1}b[(c[x>>2]|0)+(c[q>>2]<<1)>>1]=A;c[q>>2]=(c[q>>2]|0)+1}y=v+(c[o>>2]<<2)|0;c[y>>2]=c[y>>2]|c[t>>2]<<5}c[o>>2]=(c[o>>2]|0)+1}Mb(c[j>>2]|0,c[k>>2]|0,c[n>>2]|0,c[l>>2]|0,c[m>>2]|0,v);i=h;return}function Tb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+32|0;g=f+16|0;h=f+12|0;j=f+8|0;k=f+4|0;l=f;c[g>>2]=b;c[h>>2]=d;c[j>>2]=e;c[l>>2]=0;c[(c[g>>2]|0)+2332>>2]=((c[h>>2]&65535)<<16>>16)*5;c[k>>2]=_((c[(c[g>>2]|0)+2324>>2]&65535)<<16>>16,(c[(c[g>>2]|0)+2332>>2]&65535)<<16>>16)|0;if(!((c[(c[g>>2]|0)+2316>>2]|0)==(c[h>>2]|0)?(c[(c[g>>2]|0)+2320>>2]|0)==(c[j>>2]|0):0)){e=mc((c[g>>2]|0)+2432|0,((c[h>>2]&65535)<<16>>16)*1e3|0,c[j>>2]|0,0)|0;c[l>>2]=(c[l>>2]|0)+e;c[(c[g>>2]|0)+2320>>2]=c[j>>2]}if((c[(c[g>>2]|0)+2316>>2]|0)==(c[h>>2]|0)?(c[k>>2]|0)==(c[(c[g>>2]|0)+2328>>2]|0):0){m=c[l>>2]|0;i=f;return m|0}j=(c[(c[g>>2]|0)+2324>>2]|0)==4;e=(c[g>>2]|0)+2384|0;do if((c[h>>2]|0)==8)if(j){c[e>>2]=616;break}else{c[e>>2]=648;break}else if(j){c[e>>2]=576;break}else{c[e>>2]=632;break}while(0);if((c[(c[g>>2]|0)+2316>>2]|0)!=(c[h>>2]|0)){c[(c[g>>2]|0)+2336>>2]=((c[h>>2]&65535)<<16>>16)*20;e=(c[g>>2]|0)+2340|0;if((c[h>>2]|0)==8|(c[h>>2]|0)==12){c[e>>2]=10;c[(c[g>>2]|0)+2732>>2]=256}else{c[e>>2]=16;c[(c[g>>2]|0)+2732>>2]=296}do if((c[h>>2]|0)!=16){if((c[h>>2]|0)==12){c[(c[g>>2]|0)+2380>>2]=496;break}if((c[h>>2]|0)==8)c[(c[g>>2]|0)+2380>>2]=480}else c[(c[g>>2]|0)+2380>>2]=504;while(0);c[(c[g>>2]|0)+2376>>2]=1;c[(c[g>>2]|0)+2308>>2]=100;a[(c[g>>2]|0)+2312>>0]=10;c[(c[g>>2]|0)+4164>>2]=0;bf((c[g>>2]|0)+1348|0,0,960)|0;e=(c[g>>2]|0)+1284|0;j=e+64|0;do{c[e>>2]=0;e=e+4|0}while((e|0)<(j|0))}c[(c[g>>2]|0)+2316>>2]=c[h>>2];c[(c[g>>2]|0)+2328>>2]=c[k>>2];m=c[l>>2]|0;i=f;return m|0}function Ub(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b+4|0;e=b;c[d>>2]=a;c[e>>2]=0;c[c[d>>2]>>2]=8544;i=b;return c[e>>2]|0}function Vb(a){a=a|0;var d=0,e=0,f=0,g=0,h=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[e>>2]=a;c[g>>2]=0;c[h>>2]=c[e>>2];c[f>>2]=0;while(1){if((c[f>>2]|0)>=2)break;c[g>>2]=Nb((c[h>>2]|0)+((c[f>>2]|0)*4260|0)|0)|0;c[f>>2]=(c[f>>2]|0)+1}f=(c[e>>2]|0)+8520|0;b[f>>1]=0;b[f+2>>1]=0;b[f+4>>1]=0;b[f+6>>1]=0;b[f+8>>1]=0;b[f+10>>1]=0;c[(c[e>>2]|0)+8540>>2]=0;i=d;return c[g>>2]|0}function Wb(d,e,f,g,h,j,k){d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0;l=i;i=i+784|0;m=l+64|0;n=l+48|0;o=l+44|0;p=l+108|0;q=l+100|0;r=l+16|0;s=l+20|0;t=l+24|0;u=l+28|0;v=l+32|0;w=l+36|0;x=l+96|0;y=l+104|0;z=l+112|0;A=l+120|0;B=l+128|0;C=l+68|0;D=l+72|0;E=l+76|0;F=l+80|0;G=l+84|0;H=l+12|0;I=l+8|0;J=l+136|0;K=l+4|0;L=l;M=l+40|0;N=l+92|0;O=l+52|0;P=l+88|0;c[n>>2]=d;c[o>>2]=e;c[p>>2]=f;c[q>>2]=g;c[r>>2]=h;c[s>>2]=j;c[t>>2]=k;c[w>>2]=0;c[x>>2]=0;c[B>>2]=0;c[B+4>>2]=0;c[D>>2]=c[n>>2];c[E>>2]=c[D>>2];a:do if(c[q>>2]|0){c[v>>2]=0;while(1){if((c[v>>2]|0)>=(c[(c[o>>2]|0)+4>>2]|0))break a;c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2388>>2]=0;c[v>>2]=(c[v>>2]|0)+1}}while(0);if((c[(c[o>>2]|0)+4>>2]|0)>(c[(c[D>>2]|0)+8536>>2]|0)){q=Nb((c[E>>2]|0)+4260|0)|0;c[x>>2]=(c[x>>2]|0)+q}if((c[(c[o>>2]|0)+4>>2]|0)==1?(c[(c[D>>2]|0)+8536>>2]|0)==2:0)Q=(c[(c[o>>2]|0)+12>>2]|0)==((c[(c[E>>2]|0)+2316>>2]|0)*1e3|0);else Q=0;c[G>>2]=Q&1;b:do if(!(c[(c[E>>2]|0)+2388>>2]|0)){c[v>>2]=0;c:while(1){if((c[v>>2]|0)>=(c[(c[o>>2]|0)+4>>2]|0))break b;do if(!(c[(c[o>>2]|0)+16>>2]|0)){c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2392>>2]=1;c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2324>>2]=2}else{if((c[(c[o>>2]|0)+16>>2]|0)==10){c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2392>>2]=1;c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2324>>2]=2;break}if((c[(c[o>>2]|0)+16>>2]|0)==20){c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2392>>2]=1;c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2324>>2]=4;break}if((c[(c[o>>2]|0)+16>>2]|0)==40){c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2392>>2]=2;c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2324>>2]=4;break}if((c[(c[o>>2]|0)+16>>2]|0)!=60){R=23;break c}c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2392>>2]=3;c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2324>>2]=4}while(0);c[I>>2]=(c[(c[o>>2]|0)+12>>2]>>10)+1;if((c[I>>2]|0)!=8&(c[I>>2]|0)!=12&(c[I>>2]|0)!=16){R=25;break}Q=Tb((c[E>>2]|0)+((c[v>>2]|0)*4260|0)|0,c[I>>2]|0,c[(c[o>>2]|0)+8>>2]|0)|0;c[x>>2]=(c[x>>2]|0)+Q;c[v>>2]=(c[v>>2]|0)+1}if((R|0)==23){c[m>>2]=-203;S=c[m>>2]|0;i=l;return S|0}else if((R|0)==25){c[m>>2]=-200;S=c[m>>2]|0;i=l;return S|0}}while(0);do if((c[c[o>>2]>>2]|0)==2?(c[(c[o>>2]|0)+4>>2]|0)==2:0){if((c[(c[D>>2]|0)+8532>>2]|0)!=1?(c[(c[D>>2]|0)+8536>>2]|0)!=1:0)break;I=(c[D>>2]|0)+8520|0;b[I>>1]=0;b[I+2>>1]=0;I=(c[D>>2]|0)+8520+8|0;b[I>>1]=0;b[I+2>>1]=0;df((c[E>>2]|0)+4260+2432|0,(c[E>>2]|0)+2432|0,300)|0}while(0);c[(c[D>>2]|0)+8532>>2]=c[c[o>>2]>>2];c[(c[D>>2]|0)+8536>>2]=c[(c[o>>2]|0)+4>>2];if((c[(c[o>>2]|0)+8>>2]|0)<=48e3?(c[(c[o>>2]|0)+8>>2]|0)>=8e3:0){d:do if((c[p>>2]|0)!=1?(c[(c[E>>2]|0)+2388>>2]|0)==0:0){c[v>>2]=0;while(1){if((c[v>>2]|0)>=(c[(c[o>>2]|0)+4>>2]|0))break;c[u>>2]=0;while(1){I=(c[u>>2]|0)<(c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2392>>2]|0);T=ib(c[r>>2]|0,1)|0;if(!I)break;c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2404+(c[u>>2]<<2)>>2]=T;c[u>>2]=(c[u>>2]|0)+1}c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2416>>2]=T;c[v>>2]=(c[v>>2]|0)+1}c[v>>2]=0;while(1){if((c[v>>2]|0)>=(c[(c[o>>2]|0)+4>>2]|0))break;I=(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2420|0;c[I>>2]=0;c[I+4>>2]=0;c[I+8>>2]=0;e:do if(c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2416>>2]|0){if((c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2392>>2]|0)==1){c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2420>>2]=1;break}c[z>>2]=(jb(c[r>>2]|0,c[408+((c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2392>>2]|0)-2<<2)>>2]|0,8)|0)+1;c[u>>2]=0;while(1){if((c[u>>2]|0)>=(c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2392>>2]|0))break e;c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2420+(c[u>>2]<<2)>>2]=c[z>>2]>>c[u>>2]&1;c[u>>2]=(c[u>>2]|0)+1}}while(0);c[v>>2]=(c[v>>2]|0)+1}if(!(c[p>>2]|0)){c[u>>2]=0;while(1){if((c[u>>2]|0)>=(c[(c[E>>2]|0)+2392>>2]|0))break d;c[v>>2]=0;while(1){U=c[u>>2]|0;if((c[v>>2]|0)>=(c[(c[o>>2]|0)+4>>2]|0))break;if(c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2420+(U<<2)>>2]|0){do if((c[v>>2]|0)==0?(c[(c[o>>2]|0)+4>>2]|0)==2:0){vc(c[r>>2]|0,B);if(c[(c[E>>2]|0)+4260+2420+(c[u>>2]<<2)>>2]|0)break;wc(c[r>>2]|0,w)}while(0);do if((c[u>>2]|0)>0){if(!(c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2420+((c[u>>2]|0)-1<<2)>>2]|0)){R=64;break}c[K>>2]=2}else R=64;while(0);if((R|0)==64){R=0;c[K>>2]=0}Rb((c[E>>2]|0)+((c[v>>2]|0)*4260|0)|0,c[r>>2]|0,c[u>>2]|0,1,c[K>>2]|0);Sb(c[r>>2]|0,J,a[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2736+29>>0]|0,a[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2736+30>>0]|0,c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2328>>2]|0)}c[v>>2]=(c[v>>2]|0)+1}c[u>>2]=U+1}}}while(0);f:do if((c[(c[o>>2]|0)+4>>2]|0)==2){do if(c[p>>2]|0){if((c[p>>2]|0)==2?(c[(c[E>>2]|0)+2420+(c[(c[E>>2]|0)+2388>>2]<<2)>>2]|0)==1:0)break;c[v>>2]=0;while(1){if((c[v>>2]|0)>=2)break f;c[B+(c[v>>2]<<2)>>2]=b[(c[D>>2]|0)+8520+(c[v>>2]<<1)>>1];c[v>>2]=(c[v>>2]|0)+1}}while(0);vc(c[r>>2]|0,B);if(!((c[p>>2]|0)==0?(c[(c[E>>2]|0)+4260+2404+(c[(c[E>>2]|0)+2388>>2]<<2)>>2]|0)==0:0))R=74;do if((R|0)==74){if((c[p>>2]|0)==2?(c[(c[E>>2]|0)+4260+2420+(c[(c[E>>2]|0)+2388>>2]<<2)>>2]|0)==0:0)break;c[w>>2]=0;break f}while(0);wc(c[r>>2]|0,w)}while(0);if(((c[w>>2]|0)==0?(c[(c[o>>2]|0)+4>>2]|0)==2:0)?(c[(c[D>>2]|0)+8540>>2]|0)==1:0){bf((c[D>>2]|0)+4260+1348|0,0,960)|0;R=(c[D>>2]|0)+4260+1284|0;U=R+64|0;do{c[R>>2]=0;R=R+4|0}while((R|0)<(U|0));c[(c[D>>2]|0)+4260+2308>>2]=100;a[(c[D>>2]|0)+4260+2312>>0]=10;c[(c[D>>2]|0)+4260+4164>>2]=0;c[(c[D>>2]|0)+4260+2376>>2]=1}R=_(c[(c[o>>2]|0)+12>>2]|0,c[(c[o>>2]|0)+4>>2]|0)|0;c[H>>2]=(R|0)<(_(c[(c[o>>2]|0)+8>>2]|0,c[c[o>>2]>>2]|0)|0)&1;if(c[H>>2]|0)V=1;else V=_(c[(c[o>>2]|0)+4>>2]|0,(c[(c[E>>2]|0)+2328>>2]|0)+2|0)|0;c[L>>2]=ua()|0;R=i;i=i+((1*(V<<1)|0)+15&-16)|0;if(c[H>>2]|0){c[A>>2]=c[s>>2];c[A+4>>2]=(c[s>>2]|0)+(c[(c[E>>2]|0)+2328>>2]<<1)+4}else{c[A>>2]=R;c[A+4>>2]=R+(c[(c[E>>2]|0)+2328>>2]<<1)+4}if(!(c[p>>2]|0))c[F>>2]=((c[w>>2]|0)!=0^1)&1;else{if(c[(c[D>>2]|0)+8540>>2]|0)if((c[p>>2]|0)==2?(c[(c[o>>2]|0)+4>>2]|0)==2:0)W=(c[(c[E>>2]|0)+4260+2420+(c[(c[E>>2]|0)+4260+2388>>2]<<2)>>2]|0)==1;else W=0;else W=1;c[F>>2]=W&1}c[v>>2]=0;while(1){if((c[v>>2]|0)>=(c[(c[o>>2]|0)+4>>2]|0))break;if((c[v>>2]|0)==0|(c[F>>2]|0)!=0){c[M>>2]=(c[(c[E>>2]|0)+2388>>2]|0)-(c[v>>2]|0);g:do if((c[M>>2]|0)<=0)c[N>>2]=0;else{if((c[p>>2]|0)==2){c[N>>2]=(c[(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2420+((c[M>>2]|0)-1<<2)>>2]|0)!=0?2:0;break}do if((c[v>>2]|0)>0){if(!(c[(c[D>>2]|0)+8540>>2]|0))break;c[N>>2]=1;break g}while(0);c[N>>2]=2}while(0);W=Pb((c[E>>2]|0)+((c[v>>2]|0)*4260|0)|0,c[r>>2]|0,(c[A+(c[v>>2]<<2)>>2]|0)+4|0,y,c[p>>2]|0,c[N>>2]|0)|0;c[x>>2]=(c[x>>2]|0)+W}else bf((c[A+(c[v>>2]<<2)>>2]|0)+4|0,0,c[y>>2]<<1|0)|0;W=(c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2388|0;c[W>>2]=(c[W>>2]|0)+1;c[v>>2]=(c[v>>2]|0)+1}if((c[c[o>>2]>>2]|0)==2?(c[(c[o>>2]|0)+4>>2]|0)==2:0)cc((c[D>>2]|0)+8520|0,c[A>>2]|0,c[A+4>>2]|0,B,c[(c[E>>2]|0)+2316>>2]|0,c[y>>2]|0);else{B=c[A>>2]|0;N=(c[D>>2]|0)+8520+4|0;b[B>>1]=b[N>>1]|0;b[B+2>>1]=b[N+2>>1]|0;N=(c[D>>2]|0)+8520+4|0;B=(c[A>>2]|0)+(c[y>>2]<<1)|0;b[N>>1]=b[B>>1]|0;b[N+2>>1]=b[B+2>>1]|0}B=_(c[y>>2]|0,c[(c[o>>2]|0)+8>>2]|0)|0;c[c[t>>2]>>2]=(B|0)/(((c[(c[E>>2]|0)+2316>>2]&65535)<<16>>16)*1e3|0)|0;if((c[c[o>>2]>>2]|0)==2)X=c[c[t>>2]>>2]|0;else X=1;B=i;i=i+((1*(X<<1)|0)+15&-16)|0;if((c[c[o>>2]>>2]|0)==2)c[C>>2]=B;else c[C>>2]=c[s>>2];if(c[H>>2]|0)Y=_(c[(c[o>>2]|0)+4>>2]|0,(c[(c[E>>2]|0)+2328>>2]|0)+2|0)|0;else Y=1;B=i;i=i+((1*(Y<<1)|0)+15&-16)|0;if(c[H>>2]|0){H=(_(c[(c[o>>2]|0)+4>>2]|0,(c[(c[E>>2]|0)+2328>>2]|0)+2|0)|0)<<1;df(B|0,c[s>>2]|0,H+0|0)|0;c[A>>2]=B;c[A+4>>2]=B+(c[(c[E>>2]|0)+2328>>2]<<1)+4}c[v>>2]=0;while(1){B=c[o>>2]|0;if((c[c[o>>2]>>2]|0)<(c[(c[o>>2]|0)+4>>2]|0))Z=c[B>>2]|0;else Z=c[B+4>>2]|0;if((c[v>>2]|0)>=(Z|0))break;B=nc((c[E>>2]|0)+((c[v>>2]|0)*4260|0)+2432|0,c[C>>2]|0,(c[A+(c[v>>2]<<2)>>2]|0)+2|0,c[y>>2]|0)|0;c[x>>2]=(c[x>>2]|0)+B;h:do if((c[c[o>>2]>>2]|0)==2){c[u>>2]=0;while(1){if((c[u>>2]|0)>=(c[c[t>>2]>>2]|0))break h;b[(c[s>>2]|0)+((c[v>>2]|0)+(c[u>>2]<<1)<<1)>>1]=b[(c[C>>2]|0)+(c[u>>2]<<1)>>1]|0;c[u>>2]=(c[u>>2]|0)+1}}while(0);c[v>>2]=(c[v>>2]|0)+1}i:do if((c[c[o>>2]>>2]|0)==2){if((c[(c[o>>2]|0)+4>>2]|0)!=1)break;if(c[G>>2]|0){v=nc((c[E>>2]|0)+4260+2432|0,c[C>>2]|0,(c[A>>2]|0)+2|0,c[y>>2]|0)|0;c[x>>2]=(c[x>>2]|0)+v;c[u>>2]=0;while(1){if((c[u>>2]|0)>=(c[c[t>>2]>>2]|0))break i;b[(c[s>>2]|0)+(1+(c[u>>2]<<1)<<1)>>1]=b[(c[C>>2]|0)+(c[u>>2]<<1)>>1]|0;c[u>>2]=(c[u>>2]|0)+1}}else{c[u>>2]=0;while(1){if((c[u>>2]|0)>=(c[c[t>>2]>>2]|0))break i;b[(c[s>>2]|0)+(1+(c[u>>2]<<1)<<1)>>1]=b[(c[s>>2]|0)+(0+(c[u>>2]<<1)<<1)>>1]|0;c[u>>2]=(c[u>>2]|0)+1}}}while(0);if((c[(c[E>>2]|0)+4164>>2]|0)==2){c[O>>2]=c[738];c[O+4>>2]=c[739];c[O+8>>2]=c[740];s=_(c[(c[E>>2]|0)+2308>>2]|0,c[O+((c[(c[E>>2]|0)+2316>>2]|0)-8>>2<<2)>>2]|0)|0;c[(c[o>>2]|0)+20>>2]=s}else c[(c[o>>2]|0)+20>>2]=0;j:do if((c[p>>2]|0)==1){c[u>>2]=0;while(1){if((c[u>>2]|0)>=(c[(c[D>>2]|0)+8536>>2]|0))break j;a[(c[D>>2]|0)+((c[u>>2]|0)*4260|0)+2312>>0]=10;c[u>>2]=(c[u>>2]|0)+1}}else c[(c[D>>2]|0)+8540>>2]=c[w>>2];while(0);c[m>>2]=c[x>>2];c[P>>2]=1;ka(c[L>>2]|0);S=c[m>>2]|0;i=l;return S|0}c[x>>2]=-200;c[m>>2]=c[x>>2];S=c[m>>2]|0;i=l;return S|0}function Xb(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;h=i;i=i+32|0;j=h+4|0;k=h+16|0;l=h+8|0;m=h+20|0;n=h+28|0;o=h;p=h+12|0;q=h+24|0;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;c[m>>2]=f;c[n>>2]=g;c[o>>2]=0;while(1){if((c[o>>2]|0)>=(c[n>>2]|0))break;g=a[(c[k>>2]|0)+(c[o>>2]|0)>>0]|0;do if(!((c[o>>2]|0)==0&(c[m>>2]|0)==0)){c[p>>2]=g+-4;c[q>>2]=8+(a[c[l>>2]>>0]|0);f=c[p>>2]|0;if((c[p>>2]|0)>(c[q>>2]|0)){e=c[l>>2]|0;a[e>>0]=(a[e>>0]|0)+((f<<1)-(c[q>>2]|0));break}else{e=c[l>>2]|0;a[e>>0]=(a[e>>0]|0)+f;break}}else{f=(Gd(g,(a[c[l>>2]>>0]|0)-16|0)|0)&255;a[c[l>>2]>>0]=f}while(0);if((a[c[l>>2]>>0]|0)<=63)if((a[c[l>>2]>>0]|0)<0)r=0;else r=a[c[l>>2]>>0]|0;else r=63;a[c[l>>2]>>0]=r;g=gc(Fd(((a[c[l>>2]>>0]<<16>>16)*29|0)+((a[c[l>>2]>>0]<<16>>16)*7281>>16)+2090|0,3967)|0)|0;c[(c[j>>2]|0)+(c[o>>2]<<2)>>2]=g;c[o>>2]=(c[o>>2]|0)+1}i=h;return}function Yb(e,f,g){e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;h=i;i=i+144|0;j=h+24|0;k=h+16|0;l=h+12|0;m=h+8|0;n=h+128|0;o=h+32|0;p=h+64|0;q=h+96|0;r=h+20|0;s=h;t=h+4|0;c[j>>2]=e;c[k>>2]=f;c[l>>2]=g;g=_(a[c[k>>2]>>0]|0,b[(c[l>>2]|0)+2>>1]|0)|0;c[t>>2]=(c[(c[l>>2]|0)+8>>2]|0)+g;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(b[(c[l>>2]|0)+2>>1]|0))break;b[(c[j>>2]|0)+(c[m>>2]<<1)>>1]=d[(c[t>>2]|0)+(c[m>>2]|0)>>0]<<7;c[m>>2]=(c[m>>2]|0)+1}bc(o,n,c[l>>2]|0,a[c[k>>2]>>0]|0);Hd(p,(c[k>>2]|0)+1|0,n,b[(c[l>>2]|0)+4>>1]|0,b[(c[l>>2]|0)+2>>1]|0);lc(q,c[j>>2]|0,b[(c[l>>2]|0)+2>>1]|0);c[m>>2]=0;while(1){if((c[m>>2]|0)>=(b[(c[l>>2]|0)+2>>1]|0))break;c[r>>2]=Id(b[q+(c[m>>2]<<1)>>1]<<16)|0;c[s>>2]=(b[(c[j>>2]|0)+(c[m>>2]<<1)>>1]|0)+((b[p+(c[m>>2]<<1)>>1]<<14|0)/(c[r>>2]|0)|0);if((c[s>>2]|0)>32767)u=32767;else u=(c[s>>2]|0)<0?0:c[s>>2]|0;b[(c[j>>2]|0)+(c[m>>2]<<1)>>1]=u;c[m>>2]=(c[m>>2]|0)+1}kc(c[j>>2]|0,c[(c[l>>2]|0)+32>>2]|0,b[(c[l>>2]|0)+2>>1]|0);i=h;return}function Zb(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;c[(c[d>>2]|0)+4168>>2]=c[(c[d>>2]|0)+2328>>2]<<7;c[(c[d>>2]|0)+4168+72>>2]=65536;c[(c[d>>2]|0)+4168+72+4>>2]=65536;c[(c[d>>2]|0)+4168+88>>2]=20;c[(c[d>>2]|0)+4168+84>>2]=2;i=b;return}function _b(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0;f=i;i=i+16|0;g=f+12|0;h=f+8|0;j=f+4|0;k=f;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[k>>2]=e;if((c[(c[g>>2]|0)+2316>>2]|0)!=(c[(c[g>>2]|0)+4168+80>>2]|0)){Zb(c[g>>2]|0);c[(c[g>>2]|0)+4168+80>>2]=c[(c[g>>2]|0)+2316>>2]}e=c[g>>2]|0;d=c[h>>2]|0;if(c[k>>2]|0){Jd(e,d,c[j>>2]|0);j=(c[g>>2]|0)+4160|0;c[j>>2]=(c[j>>2]|0)+1;i=f;return}else{Kd(e,d);i=f;return}}function $b(a,d,e){a=a|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;f=i;i=i+48|0;g=f+36|0;h=f+16|0;j=f;k=f+28|0;l=f+32|0;m=f+40|0;n=f+12|0;o=f+24|0;p=f+20|0;q=f+8|0;r=f+4|0;c[g>>2]=a;c[h>>2]=d;c[j>>2]=e;c[n>>2]=(c[g>>2]|0)+4168;if(c[(c[g>>2]|0)+4160>>2]|0){uc((c[n>>2]|0)+60|0,(c[n>>2]|0)+64|0,c[h>>2]|0,c[j>>2]|0);c[(c[n>>2]|0)+48>>2]=1;i=f;return}a:do if(c[(c[g>>2]|0)+4168+48>>2]|0){uc(m,l,c[h>>2]|0,c[j>>2]|0);if((c[l>>2]|0)<=(c[(c[n>>2]|0)+64>>2]|0)){if((c[l>>2]|0)<(c[(c[n>>2]|0)+64>>2]|0))c[m>>2]=c[m>>2]>>(c[(c[n>>2]|0)+64>>2]|0)-(c[l>>2]|0)}else c[(c[n>>2]|0)+60>>2]=c[(c[n>>2]|0)+60>>2]>>(c[l>>2]|0)-(c[(c[n>>2]|0)+64>>2]|0);if((c[m>>2]|0)>(c[(c[n>>2]|0)+60>>2]|0)){c[p>>2]=Ld(c[(c[n>>2]|0)+60>>2]|0)|0;c[p>>2]=(c[p>>2]|0)-1;c[(c[n>>2]|0)+60>>2]=c[(c[n>>2]|0)+60>>2]<<c[p>>2];e=c[m>>2]|0;c[m>>2]=e>>(Md(24-(c[p>>2]|0)|0,0)|0);c[o>>2]=(c[(c[n>>2]|0)+60>>2]|0)/(((c[m>>2]|0)>1?c[m>>2]|0:1)|0)|0;c[q>>2]=(Nd(c[o>>2]|0)|0)<<4;c[r>>2]=(65536-(c[q>>2]|0)|0)/(c[j>>2]|0)|0;c[r>>2]=c[r>>2]<<2;c[k>>2]=0;while(1){if((c[k>>2]|0)>=(c[j>>2]|0))break a;e=_(c[q>>2]>>16,b[(c[h>>2]|0)+(c[k>>2]<<1)>>1]|0)|0;d=e+((_(c[q>>2]&65535,b[(c[h>>2]|0)+(c[k>>2]<<1)>>1]|0)|0)>>16)&65535;b[(c[h>>2]|0)+(c[k>>2]<<1)>>1]=d;c[q>>2]=(c[q>>2]|0)+(c[r>>2]|0);if((c[q>>2]|0)>65536)break a;c[k>>2]=(c[k>>2]|0)+1}}}while(0);c[(c[n>>2]|0)+48>>2]=0;i=f;return}function ac(a,d,e){a=a|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+48|0;g=f+8|0;h=f+4|0;j=f;k=f+40|0;l=f+32|0;m=f+16|0;c[g>>2]=a;c[h>>2]=d;c[j>>2]=e;Od(k,k+2|0,c[h>>2]|0,c[j>>2]|0,1320);Od(l,l+2|0,c[h>>2]|0,b[k>>1]|0,1168);Od(m,m+2|0,c[h>>2]|0,b[l>>1]|0,1016);Od(c[g>>2]|0,(c[g>>2]|0)+2|0,c[h>>2]|0,b[m>>1]|0,864);Od((c[g>>2]|0)+4|0,(c[g>>2]|0)+6|0,c[h>>2]|0,b[m+2>>1]|0,864);Od(m+4|0,m+6|0,c[h>>2]|0,b[l+2>>1]|0,1016);Od((c[g>>2]|0)+8|0,(c[g>>2]|0)+10|0,c[h>>2]|0,b[m+4>>1]|0,864);Od((c[g>>2]|0)+12|0,(c[g>>2]|0)+14|0,c[h>>2]|0,b[m+6>>1]|0,864);Od(l+4|0,l+6|0,c[h>>2]|0,b[k+2>>1]|0,1168);Od(m+8|0,m+10|0,c[h>>2]|0,b[l+4>>1]|0,1016);Od((c[g>>2]|0)+16|0,(c[g>>2]|0)+18|0,c[h>>2]|0,b[m+8>>1]|0,864);Od((c[g>>2]|0)+20|0,(c[g>>2]|0)+22|0,c[h>>2]|0,b[m+10>>1]|0,864);Od(m+12|0,m+14|0,c[h>>2]|0,b[l+6>>1]|0,1016);Od((c[g>>2]|0)+24|0,(c[g>>2]|0)+26|0,c[h>>2]|0,b[m+12>>1]|0,864);Od((c[g>>2]|0)+28|0,(c[g>>2]|0)+30|0,c[h>>2]|0,b[m+14>>1]|0,864);i=f;return}function bc(e,f,g,h){e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;j=i;i=i+32|0;k=j+4|0;l=j+12|0;m=j+8|0;n=j+20|0;o=j;p=j+24|0;q=j+16|0;c[k>>2]=e;c[l>>2]=f;c[m>>2]=g;c[n>>2]=h;h=(_(c[n>>2]|0,b[(c[m>>2]|0)+2>>1]|0)|0)/2|0;c[q>>2]=(c[(c[m>>2]|0)+20>>2]|0)+h;c[o>>2]=0;while(1){if((c[o>>2]|0)>=(b[(c[m>>2]|0)+2>>1]|0))break;h=c[q>>2]|0;c[q>>2]=h+1;a[p>>0]=a[h>>0]|0;b[(c[k>>2]|0)+(c[o>>2]<<1)>>1]=((d[p>>0]>>1&7)<<16>>16)*9;h=(c[o>>2]|0)+(_(d[p>>0]&1,(b[(c[m>>2]|0)+2>>1]|0)-1|0)|0)|0;a[(c[l>>2]|0)+(c[o>>2]|0)>>0]=a[(c[(c[m>>2]|0)+16>>2]|0)+h>>0]|0;b[(c[k>>2]|0)+((c[o>>2]|0)+1<<1)>>1]=((d[p>>0]>>5&7)<<16>>16)*9;h=(c[o>>2]|0)+(_(d[p>>0]>>4&1,(b[(c[m>>2]|0)+2>>1]|0)-1|0)|0)+1|0;a[(c[l>>2]|0)+((c[o>>2]|0)+1)>>0]=a[(c[(c[m>>2]|0)+16>>2]|0)+h>>0]|0;c[o>>2]=(c[o>>2]|0)+2}i=j;return}function cc(a,d,e,f,g,h){a=a|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;j=i;i=i+64|0;k=j+24|0;l=j+20|0;m=j+44|0;n=j+36|0;o=j+32|0;p=j+40|0;q=j+48|0;r=j+52|0;s=j+8|0;t=j+4|0;u=j+28|0;v=j+12|0;w=j;x=j+16|0;c[k>>2]=a;c[l>>2]=d;c[m>>2]=e;c[n>>2]=f;c[o>>2]=g;c[p>>2]=h;h=c[l>>2]|0;g=(c[k>>2]|0)+4|0;b[h>>1]=b[g>>1]|0;b[h+2>>1]=b[g+2>>1]|0;g=c[m>>2]|0;h=(c[k>>2]|0)+8|0;b[g>>1]=b[h>>1]|0;b[g+2>>1]=b[h+2>>1]|0;h=(c[k>>2]|0)+4|0;g=(c[l>>2]|0)+(c[p>>2]<<1)|0;b[h>>1]=b[g>>1]|0;b[h+2>>1]=b[g+2>>1]|0;g=(c[k>>2]|0)+8|0;h=(c[m>>2]|0)+(c[p>>2]<<1)|0;b[g>>1]=b[h>>1]|0;b[g+2>>1]=b[h+2>>1]|0;c[w>>2]=b[c[k>>2]>>1];c[x>>2]=b[(c[k>>2]|0)+2>>1];c[r>>2]=65536/(c[o>>2]<<3|0)|0;c[s>>2]=((_(((c[c[n>>2]>>2]|0)-(b[c[k>>2]>>1]|0)&65535)<<16>>16,(c[r>>2]&65535)<<16>>16)|0)>>15)+1>>1;c[t>>2]=((_(((c[(c[n>>2]|0)+4>>2]|0)-(b[(c[k>>2]|0)+2>>1]|0)&65535)<<16>>16,(c[r>>2]&65535)<<16>>16)|0)>>15)+1>>1;c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[o>>2]<<3|0))break;c[w>>2]=(c[w>>2]|0)+(c[s>>2]|0);c[x>>2]=(c[x>>2]|0)+(c[t>>2]|0);c[u>>2]=(b[(c[l>>2]|0)+(c[q>>2]<<1)>>1]|0)+(b[(c[l>>2]|0)+((c[q>>2]|0)+2<<1)>>1]|0)+(b[(c[l>>2]|0)+((c[q>>2]|0)+1<<1)>>1]<<1)<<9;r=_(c[u>>2]>>16,(c[w>>2]&65535)<<16>>16)|0;c[u>>2]=(b[(c[m>>2]|0)+((c[q>>2]|0)+1<<1)>>1]<<8)+(r+((_(c[u>>2]&65535,(c[w>>2]&65535)<<16>>16)|0)>>16));r=_(b[(c[l>>2]|0)+((c[q>>2]|0)+1<<1)>>1]<<11>>16,(c[x>>2]&65535)<<16>>16)|0;c[u>>2]=(c[u>>2]|0)+(r+((_(b[(c[l>>2]|0)+((c[q>>2]|0)+1<<1)>>1]<<11&65535,(c[x>>2]&65535)<<16>>16)|0)>>16));if(((c[u>>2]>>7)+1>>1|0)<=32767)if(((c[u>>2]>>7)+1>>1|0)<-32768)y=-32768;else y=(c[u>>2]>>7)+1>>1;else y=32767;b[(c[m>>2]|0)+((c[q>>2]|0)+1<<1)>>1]=y;c[q>>2]=(c[q>>2]|0)+1}c[w>>2]=c[c[n>>2]>>2];c[x>>2]=c[(c[n>>2]|0)+4>>2];c[q>>2]=c[o>>2]<<3;while(1){if((c[q>>2]|0)>=(c[p>>2]|0))break;c[u>>2]=(b[(c[l>>2]|0)+(c[q>>2]<<1)>>1]|0)+(b[(c[l>>2]|0)+((c[q>>2]|0)+2<<1)>>1]|0)+(b[(c[l>>2]|0)+((c[q>>2]|0)+1<<1)>>1]<<1)<<9;o=_(c[u>>2]>>16,(c[w>>2]&65535)<<16>>16)|0;c[u>>2]=(b[(c[m>>2]|0)+((c[q>>2]|0)+1<<1)>>1]<<8)+(o+((_(c[u>>2]&65535,(c[w>>2]&65535)<<16>>16)|0)>>16));o=_(b[(c[l>>2]|0)+((c[q>>2]|0)+1<<1)>>1]<<11>>16,(c[x>>2]&65535)<<16>>16)|0;c[u>>2]=(c[u>>2]|0)+(o+((_(b[(c[l>>2]|0)+((c[q>>2]|0)+1<<1)>>1]<<11&65535,(c[x>>2]&65535)<<16>>16)|0)>>16));if(((c[u>>2]>>7)+1>>1|0)<=32767)if(((c[u>>2]>>7)+1>>1|0)<-32768)z=-32768;else z=(c[u>>2]>>7)+1>>1;else z=32767;b[(c[m>>2]|0)+((c[q>>2]|0)+1<<1)>>1]=z;c[q>>2]=(c[q>>2]|0)+1}b[c[k>>2]>>1]=c[c[n>>2]>>2];b[(c[k>>2]|0)+2>>1]=c[(c[n>>2]|0)+4>>2];c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[p>>2]|0))break;c[u>>2]=(b[(c[l>>2]|0)+((c[q>>2]|0)+1<<1)>>1]|0)+(b[(c[m>>2]|0)+((c[q>>2]|0)+1<<1)>>1]|0);c[v>>2]=(b[(c[l>>2]|0)+((c[q>>2]|0)+1<<1)>>1]|0)-(b[(c[m>>2]|0)+((c[q>>2]|0)+1<<1)>>1]|0);if((c[u>>2]|0)>32767)A=32767;else A=(c[u>>2]|0)<-32768?-32768:c[u>>2]|0;b[(c[l>>2]|0)+((c[q>>2]|0)+1<<1)>>1]=A;if((c[v>>2]|0)>32767)B=32767;else B=(c[v>>2]|0)<-32768?-32768:c[v>>2]|0;b[(c[m>>2]|0)+((c[q>>2]|0)+1<<1)>>1]=B;c[q>>2]=(c[q>>2]|0)+1}i=j;return}function dc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e+4|0;k=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;c[k>>2]=(c[h>>2]|0)-65536;c[j>>2]=0;while(1){l=c[h>>2]>>16;if((c[j>>2]|0)>=((c[g>>2]|0)-1|0))break;d=_(l,(c[(c[f>>2]|0)+(c[j>>2]<<2)>>2]&65535)<<16>>16)|0;b=d+((_(c[h>>2]&65535,(c[(c[f>>2]|0)+(c[j>>2]<<2)>>2]&65535)<<16>>16)|0)>>16)|0;d=b+(_(c[h>>2]|0,(c[(c[f>>2]|0)+(c[j>>2]<<2)>>2]>>15)+1>>1)|0)|0;c[(c[f>>2]|0)+(c[j>>2]<<2)>>2]=d;d=((_(c[h>>2]|0,c[k>>2]|0)|0)>>15)+1>>1;c[h>>2]=(c[h>>2]|0)+d;c[j>>2]=(c[j>>2]|0)+1}j=_(l,(c[(c[f>>2]|0)+((c[g>>2]|0)-1<<2)>>2]&65535)<<16>>16)|0;l=j+((_(c[h>>2]&65535,(c[(c[f>>2]|0)+((c[g>>2]|0)-1<<2)>>2]&65535)<<16>>16)|0)>>16)|0;j=l+(_(c[h>>2]|0,(c[(c[f>>2]|0)+((c[g>>2]|0)-1<<2)>>2]>>15)+1>>1)|0)|0;c[(c[f>>2]|0)+((c[g>>2]|0)-1<<2)>>2]=j;i=e;return}function ec(a,d,e){a=a|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+32|0;g=f+16|0;h=f+12|0;j=f+8|0;k=f+4|0;l=f;c[g>>2]=a;c[h>>2]=d;c[j>>2]=e;c[l>>2]=(c[j>>2]|0)-65536;c[k>>2]=0;while(1){m=c[j>>2]|0;if((c[k>>2]|0)>=((c[h>>2]|0)-1|0))break;e=((_(m,b[(c[g>>2]|0)+(c[k>>2]<<1)>>1]|0)|0)>>15)+1>>1&65535;b[(c[g>>2]|0)+(c[k>>2]<<1)>>1]=e;e=((_(c[j>>2]|0,c[l>>2]|0)|0)>>15)+1>>1;c[j>>2]=(c[j>>2]|0)+e;c[k>>2]=(c[k>>2]|0)+1}k=((_(m,b[(c[g>>2]|0)+((c[h>>2]|0)-1<<1)>>1]|0)|0)>>15)+1>>1&65535;b[(c[g>>2]|0)+((c[h>>2]|0)-1<<1)>>1]=k;i=f;return}function fc(d,e,f,g,h){d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;j=i;i=i+48|0;k=j+36|0;l=j+38|0;m=j+8|0;n=j+20|0;o=j+28|0;p=j+32|0;q=j+12|0;r=j+24|0;s=j+4|0;t=j;u=j+16|0;b[k>>1]=d;a[l>>0]=e;c[m>>2]=f;c[n>>2]=g;c[o>>2]=h;h=(c[o>>2]|0)==4;do if((c[n>>2]|0)==8)if(h){c[u>>2]=1840;c[t>>2]=11;break}else{c[u>>2]=1808;c[t>>2]=3;break}else if(h){c[u>>2]=1888;c[t>>2]=34;break}else{c[u>>2]=1816;c[t>>2]=12;break}while(0);c[r>>2]=(c[n>>2]&65535)<<16>>16<<1;c[s>>2]=((c[n>>2]&65535)<<16>>16)*18;c[p>>2]=(c[r>>2]|0)+(b[k>>1]|0);c[q>>2]=0;while(1){if((c[q>>2]|0)>=(c[o>>2]|0))break;k=_(c[q>>2]|0,c[t>>2]|0)|0;c[(c[m>>2]|0)+(c[q>>2]<<2)>>2]=(c[p>>2]|0)+(a[(c[u>>2]|0)+(k+(a[l>>0]|0))>>0]|0);k=c[(c[m>>2]|0)+(c[q>>2]<<2)>>2]|0;do if((c[r>>2]|0)>(c[s>>2]|0)){if((k|0)>(c[r>>2]|0)){v=c[r>>2]|0;break}if((c[(c[m>>2]|0)+(c[q>>2]<<2)>>2]|0)<(c[s>>2]|0)){v=c[s>>2]|0;break}else{v=c[(c[m>>2]|0)+(c[q>>2]<<2)>>2]|0;break}}else{if((k|0)>(c[s>>2]|0)){v=c[s>>2]|0;break}if((c[(c[m>>2]|0)+(c[q>>2]<<2)>>2]|0)<(c[r>>2]|0)){v=c[r>>2]|0;break}else{v=c[(c[m>>2]|0)+(c[q>>2]<<2)>>2]|0;break}}while(0);c[(c[m>>2]|0)+(c[q>>2]<<2)>>2]=v;c[q>>2]=(c[q>>2]|0)+1}i=j;return}function gc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0;b=i;i=i+16|0;d=b+12|0;e=b+8|0;f=b+4|0;g=b;c[e>>2]=a;if((c[e>>2]|0)<0){c[d>>2]=0;h=c[d>>2]|0;i=b;return h|0}if((c[e>>2]|0)>=3967){c[d>>2]=2147483647;h=c[d>>2]|0;i=b;return h|0}c[f>>2]=1<<(c[e>>2]>>7);c[g>>2]=c[e>>2]&127;a=c[f>>2]|0;j=c[f>>2]|0;if((c[e>>2]|0)<2048){e=_((_((c[g>>2]&65535)<<16>>16,(128-(c[g>>2]|0)&65535)<<16>>16)|0)>>16,-174)|0;c[f>>2]=a+((_(j,(c[g>>2]|0)+(e+((_((_((c[g>>2]&65535)<<16>>16,(128-(c[g>>2]|0)&65535)<<16>>16)|0)&65535,-174)|0)>>16))|0)|0)>>7)}else{e=_((_((c[g>>2]&65535)<<16>>16,(128-(c[g>>2]|0)&65535)<<16>>16)|0)>>16,-174)|0;c[f>>2]=a+(_(j>>7,(c[g>>2]|0)+(e+((_((_((c[g>>2]&65535)<<16>>16,(128-(c[g>>2]|0)&65535)<<16>>16)|0)&65535,-174)|0)>>16))|0)|0)}c[d>>2]=c[f>>2];h=c[d>>2]|0;i=b;return h|0}function hc(a,d,e,f,g){a=a|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;h=i;i=i+48|0;j=h;k=h+16|0;l=h+28|0;m=h+4|0;n=h+32|0;o=h+36|0;p=h+12|0;q=h+24|0;r=h+20|0;s=h+8|0;c[j>>2]=a;c[k>>2]=d;c[l>>2]=e;c[m>>2]=f;c[n>>2]=g;c[p>>2]=c[n>>2];while(1){if((c[p>>2]|0)>=(c[m>>2]|0))break;c[s>>2]=(c[k>>2]|0)+((c[p>>2]|0)-1<<1);c[q>>2]=_(b[c[s>>2]>>1]|0,b[c[l>>2]>>1]|0)|0;c[q>>2]=(c[q>>2]|0)+(_(b[(c[s>>2]|0)+-2>>1]|0,b[(c[l>>2]|0)+2>>1]|0)|0);c[q>>2]=(c[q>>2]|0)+(_(b[(c[s>>2]|0)+-4>>1]|0,b[(c[l>>2]|0)+4>>1]|0)|0);c[q>>2]=(c[q>>2]|0)+(_(b[(c[s>>2]|0)+-6>>1]|0,b[(c[l>>2]|0)+6>>1]|0)|0);c[q>>2]=(c[q>>2]|0)+(_(b[(c[s>>2]|0)+-8>>1]|0,b[(c[l>>2]|0)+8>>1]|0)|0);c[q>>2]=(c[q>>2]|0)+(_(b[(c[s>>2]|0)+-10>>1]|0,b[(c[l>>2]|0)+10>>1]|0)|0);c[o>>2]=6;while(1){if((c[o>>2]|0)>=(c[n>>2]|0))break;c[q>>2]=(c[q>>2]|0)+(_(b[(c[s>>2]|0)+(0-(c[o>>2]|0)<<1)>>1]|0,b[(c[l>>2]|0)+(c[o>>2]<<1)>>1]|0)|0);c[q>>2]=(c[q>>2]|0)+(_(b[(c[s>>2]|0)+(0-(c[o>>2]|0)-1<<1)>>1]|0,b[(c[l>>2]|0)+((c[o>>2]|0)+1<<1)>>1]|0)|0);c[o>>2]=(c[o>>2]|0)+2}c[q>>2]=(b[(c[s>>2]|0)+2>>1]<<12)-(c[q>>2]|0);c[r>>2]=(c[q>>2]>>11)+1>>1;if((c[r>>2]|0)>32767)t=32767;else t=(c[r>>2]|0)<-32768?-32768:c[r>>2]|0;b[(c[j>>2]|0)+(c[p>>2]<<1)>>1]=t;c[p>>2]=(c[p>>2]|0)+1}bf(c[j>>2]|0,0,c[n>>2]<<1|0)|0;i=h;return}function ic(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;i=i+160|0;f=e+136|0;g=e+144|0;h=e+148|0;j=e+152|0;k=e+8|0;l=e;m=e+140|0;c[g>>2]=a;c[h>>2]=d;c[m>>2]=0;c[l>>2]=k+((c[h>>2]&1)<<6);c[j>>2]=0;while(1){if((c[j>>2]|0)>=(c[h>>2]|0))break;c[m>>2]=(c[m>>2]|0)+(b[(c[g>>2]|0)+(c[j>>2]<<1)>>1]|0);c[(c[l>>2]|0)+(c[j>>2]<<2)>>2]=b[(c[g>>2]|0)+(c[j>>2]<<1)>>1]<<12;c[j>>2]=(c[j>>2]|0)+1}if((c[m>>2]|0)>=4096){c[f>>2]=0;n=c[f>>2]|0;i=e;return n|0}else{c[f>>2]=Pd(k,c[h>>2]|0)|0;n=c[f>>2]|0;i=e;return n|0}return 0}function jc(a,e,f){a=a|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0;g=i;i=i+272|0;h=g+264|0;j=g+48|0;k=g+24|0;l=g+36|0;m=g+224|0;n=g+16|0;o=g+20|0;p=g+120|0;q=g+188|0;r=g+228|0;s=g+268|0;t=g+40|0;u=g+44|0;v=g+8|0;w=g;x=g+4|0;y=g+56|0;z=g+28|0;A=g+184|0;B=g+12|0;C=g+32|0;c[h>>2]=a;c[j>>2]=e;c[k>>2]=f;c[B>>2]=0;c[l>>2]=(c[k>>2]|0)==16?2968:2984;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[k>>2]|0))break;c[u>>2]=b[(c[j>>2]|0)+(c[m>>2]<<1)>>1]>>8;c[v>>2]=(b[(c[j>>2]|0)+(c[m>>2]<<1)>>1]|0)-(c[u>>2]<<8);c[w>>2]=b[1544+(c[u>>2]<<1)>>1];c[x>>2]=(b[1544+((c[u>>2]|0)+1<<1)>>1]|0)-(c[w>>2]|0);f=((c[w>>2]<<8)+(_(c[x>>2]|0,c[v>>2]|0)|0)>>3)+1>>1;c[p+(d[(c[l>>2]|0)+(c[m>>2]|0)>>0]<<2)>>2]=f;c[m>>2]=(c[m>>2]|0)+1}c[o>>2]=c[k>>2]>>1;Qd(q,p,c[o>>2]|0);Qd(r,p+4|0,c[o>>2]|0);c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[o>>2]|0))break;c[s>>2]=(c[q+((c[m>>2]|0)+1<<2)>>2]|0)+(c[q+(c[m>>2]<<2)>>2]|0);c[t>>2]=(c[r+((c[m>>2]|0)+1<<2)>>2]|0)-(c[r+(c[m>>2]<<2)>>2]|0);c[y+(c[m>>2]<<2)>>2]=0-(c[t>>2]|0)-(c[s>>2]|0);c[y+((c[k>>2]|0)-(c[m>>2]|0)-1<<2)>>2]=(c[t>>2]|0)-(c[s>>2]|0);c[m>>2]=(c[m>>2]|0)+1}c[n>>2]=0;while(1){if((c[n>>2]|0)>=10)break;c[z>>2]=0;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[k>>2]|0))break;s=c[y+(c[m>>2]<<2)>>2]|0;c[A>>2]=(c[y+(c[m>>2]<<2)>>2]|0)>0?s:0-s|0;if((c[A>>2]|0)>(c[z>>2]|0)){c[z>>2]=c[A>>2];c[B>>2]=c[m>>2]}c[m>>2]=(c[m>>2]|0)+1}c[z>>2]=(c[z>>2]>>4)+1>>1;if((c[z>>2]|0)<=32767)break;c[z>>2]=(c[z>>2]|0)<163838?c[z>>2]|0:163838;c[C>>2]=65470-(((c[z>>2]|0)-32767<<14|0)/((_(c[z>>2]|0,(c[B>>2]|0)+1|0)|0)>>2|0)|0);dc(y,c[k>>2]|0,c[C>>2]|0);c[n>>2]=(c[n>>2]|0)+1}C=(c[n>>2]|0)==10;c[m>>2]=0;a:do if(C)while(1){if((c[m>>2]|0)>=(c[k>>2]|0))break a;if(((c[y+(c[m>>2]<<2)>>2]>>4)+1>>1|0)<=32767)if(((c[y+(c[m>>2]<<2)>>2]>>4)+1>>1|0)<-32768)D=-32768;else D=(c[y+(c[m>>2]<<2)>>2]>>4)+1>>1;else D=32767;b[(c[h>>2]|0)+(c[m>>2]<<1)>>1]=D;c[y+(c[m>>2]<<2)>>2]=b[(c[h>>2]|0)+(c[m>>2]<<1)>>1]<<5;c[m>>2]=(c[m>>2]|0)+1}else while(1){if((c[m>>2]|0)>=(c[k>>2]|0))break a;b[(c[h>>2]|0)+(c[m>>2]<<1)>>1]=(c[y+(c[m>>2]<<2)>>2]>>4)+1>>1;c[m>>2]=(c[m>>2]|0)+1}while(0);c[n>>2]=0;while(1){if((c[n>>2]|0)>=16){E=31;break}if((ic(c[h>>2]|0,c[k>>2]|0)|0)>=107374){E=31;break}dc(y,c[k>>2]|0,65536-(2<<c[n>>2])|0);c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[k>>2]|0))break;b[(c[h>>2]|0)+(c[m>>2]<<1)>>1]=(c[y+(c[m>>2]<<2)>>2]>>4)+1>>1;c[m>>2]=(c[m>>2]|0)+1}c[n>>2]=(c[n>>2]|0)+1}if((E|0)==31){i=g;return}}
+function Td(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)>(c[f>>2]|0)?c[e>>2]|0:c[f>>2]|0)|0}function Ud(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)<(c[f>>2]|0)?c[e>>2]|0:c[f>>2]|0)|0}function Vd(a,d,e,f,g,h,j){a=a|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;k=i;i=i+48|0;l=k;m=k+8|0;n=k+36|0;o=k+16|0;p=k+32|0;q=k+40|0;r=k+44|0;s=k+24|0;t=k+20|0;u=k+12|0;v=k+4|0;w=k+28|0;c[l>>2]=a;c[m>>2]=d;c[n>>2]=e;c[o>>2]=f;c[p>>2]=g;c[q>>2]=h;c[r>>2]=j;j=c[o>>2]|0;if((j|0)==18){c[s>>2]=0;while(1){if((c[s>>2]|0)>=(c[q>>2]|0))break;c[u>>2]=(c[m>>2]|0)+(c[s>>2]>>16<<2);o=_((c[s>>2]&65535)>>16,(c[p>>2]&65535)<<16>>16)|0;c[v>>2]=o+((_(c[s>>2]&65535,(c[p>>2]&65535)<<16>>16)|0)>>16);c[w>>2]=(c[n>>2]|0)+((c[v>>2]|0)*9<<1);o=_(c[c[u>>2]>>2]>>16,b[c[w>>2]>>1]|0)|0;c[t>>2]=o+((_(c[c[u>>2]>>2]&65535,b[c[w>>2]>>1]|0)|0)>>16);o=_(c[(c[u>>2]|0)+4>>2]>>16,b[(c[w>>2]|0)+2>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+4>>2]&65535,b[(c[w>>2]|0)+2>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+8>>2]>>16,b[(c[w>>2]|0)+4>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+8>>2]&65535,b[(c[w>>2]|0)+4>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+12>>2]>>16,b[(c[w>>2]|0)+6>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+12>>2]&65535,b[(c[w>>2]|0)+6>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+16>>2]>>16,b[(c[w>>2]|0)+8>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+16>>2]&65535,b[(c[w>>2]|0)+8>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+20>>2]>>16,b[(c[w>>2]|0)+10>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+20>>2]&65535,b[(c[w>>2]|0)+10>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+24>>2]>>16,b[(c[w>>2]|0)+12>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+24>>2]&65535,b[(c[w>>2]|0)+12>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+28>>2]>>16,b[(c[w>>2]|0)+14>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+28>>2]&65535,b[(c[w>>2]|0)+14>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+32>>2]>>16,b[(c[w>>2]|0)+16>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+32>>2]&65535,b[(c[w>>2]|0)+16>>1]|0)|0)>>16));c[w>>2]=(c[n>>2]|0)+(((c[p>>2]|0)-1-(c[v>>2]|0)|0)*9<<1);o=_(c[(c[u>>2]|0)+68>>2]>>16,b[c[w>>2]>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+68>>2]&65535,b[c[w>>2]>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+64>>2]>>16,b[(c[w>>2]|0)+2>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+64>>2]&65535,b[(c[w>>2]|0)+2>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+60>>2]>>16,b[(c[w>>2]|0)+4>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+60>>2]&65535,b[(c[w>>2]|0)+4>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+56>>2]>>16,b[(c[w>>2]|0)+6>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+56>>2]&65535,b[(c[w>>2]|0)+6>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+52>>2]>>16,b[(c[w>>2]|0)+8>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+52>>2]&65535,b[(c[w>>2]|0)+8>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+48>>2]>>16,b[(c[w>>2]|0)+10>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+48>>2]&65535,b[(c[w>>2]|0)+10>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+44>>2]>>16,b[(c[w>>2]|0)+12>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+44>>2]&65535,b[(c[w>>2]|0)+12>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+40>>2]>>16,b[(c[w>>2]|0)+14>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+40>>2]&65535,b[(c[w>>2]|0)+14>>1]|0)|0)>>16));o=_(c[(c[u>>2]|0)+36>>2]>>16,b[(c[w>>2]|0)+16>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(o+((_(c[(c[u>>2]|0)+36>>2]&65535,b[(c[w>>2]|0)+16>>1]|0)|0)>>16));if(((c[t>>2]>>5)+1>>1|0)<=32767)if(((c[t>>2]>>5)+1>>1|0)<-32768)x=-32768;else x=(c[t>>2]>>5)+1>>1;else x=32767;o=c[l>>2]|0;c[l>>2]=o+2;b[o>>1]=x;c[s>>2]=(c[s>>2]|0)+(c[r>>2]|0)}y=c[l>>2]|0;i=k;return y|0}else if((j|0)==24){c[s>>2]=0;while(1){if((c[s>>2]|0)>=(c[q>>2]|0))break;c[u>>2]=(c[m>>2]|0)+(c[s>>2]>>16<<2);x=_((c[c[u>>2]>>2]|0)+(c[(c[u>>2]|0)+92>>2]|0)>>16,b[c[n>>2]>>1]|0)|0;c[t>>2]=x+((_((c[c[u>>2]>>2]|0)+(c[(c[u>>2]|0)+92>>2]|0)&65535,b[c[n>>2]>>1]|0)|0)>>16);x=_((c[(c[u>>2]|0)+4>>2]|0)+(c[(c[u>>2]|0)+88>>2]|0)>>16,b[(c[n>>2]|0)+2>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(x+((_((c[(c[u>>2]|0)+4>>2]|0)+(c[(c[u>>2]|0)+88>>2]|0)&65535,b[(c[n>>2]|0)+2>>1]|0)|0)>>16));x=_((c[(c[u>>2]|0)+8>>2]|0)+(c[(c[u>>2]|0)+84>>2]|0)>>16,b[(c[n>>2]|0)+4>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(x+((_((c[(c[u>>2]|0)+8>>2]|0)+(c[(c[u>>2]|0)+84>>2]|0)&65535,b[(c[n>>2]|0)+4>>1]|0)|0)>>16));x=_((c[(c[u>>2]|0)+12>>2]|0)+(c[(c[u>>2]|0)+80>>2]|0)>>16,b[(c[n>>2]|0)+6>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(x+((_((c[(c[u>>2]|0)+12>>2]|0)+(c[(c[u>>2]|0)+80>>2]|0)&65535,b[(c[n>>2]|0)+6>>1]|0)|0)>>16));x=_((c[(c[u>>2]|0)+16>>2]|0)+(c[(c[u>>2]|0)+76>>2]|0)>>16,b[(c[n>>2]|0)+8>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(x+((_((c[(c[u>>2]|0)+16>>2]|0)+(c[(c[u>>2]|0)+76>>2]|0)&65535,b[(c[n>>2]|0)+8>>1]|0)|0)>>16));x=_((c[(c[u>>2]|0)+20>>2]|0)+(c[(c[u>>2]|0)+72>>2]|0)>>16,b[(c[n>>2]|0)+10>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(x+((_((c[(c[u>>2]|0)+20>>2]|0)+(c[(c[u>>2]|0)+72>>2]|0)&65535,b[(c[n>>2]|0)+10>>1]|0)|0)>>16));x=_((c[(c[u>>2]|0)+24>>2]|0)+(c[(c[u>>2]|0)+68>>2]|0)>>16,b[(c[n>>2]|0)+12>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(x+((_((c[(c[u>>2]|0)+24>>2]|0)+(c[(c[u>>2]|0)+68>>2]|0)&65535,b[(c[n>>2]|0)+12>>1]|0)|0)>>16));x=_((c[(c[u>>2]|0)+28>>2]|0)+(c[(c[u>>2]|0)+64>>2]|0)>>16,b[(c[n>>2]|0)+14>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(x+((_((c[(c[u>>2]|0)+28>>2]|0)+(c[(c[u>>2]|0)+64>>2]|0)&65535,b[(c[n>>2]|0)+14>>1]|0)|0)>>16));x=_((c[(c[u>>2]|0)+32>>2]|0)+(c[(c[u>>2]|0)+60>>2]|0)>>16,b[(c[n>>2]|0)+16>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(x+((_((c[(c[u>>2]|0)+32>>2]|0)+(c[(c[u>>2]|0)+60>>2]|0)&65535,b[(c[n>>2]|0)+16>>1]|0)|0)>>16));x=_((c[(c[u>>2]|0)+36>>2]|0)+(c[(c[u>>2]|0)+56>>2]|0)>>16,b[(c[n>>2]|0)+18>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(x+((_((c[(c[u>>2]|0)+36>>2]|0)+(c[(c[u>>2]|0)+56>>2]|0)&65535,b[(c[n>>2]|0)+18>>1]|0)|0)>>16));x=_((c[(c[u>>2]|0)+40>>2]|0)+(c[(c[u>>2]|0)+52>>2]|0)>>16,b[(c[n>>2]|0)+20>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(x+((_((c[(c[u>>2]|0)+40>>2]|0)+(c[(c[u>>2]|0)+52>>2]|0)&65535,b[(c[n>>2]|0)+20>>1]|0)|0)>>16));x=_((c[(c[u>>2]|0)+44>>2]|0)+(c[(c[u>>2]|0)+48>>2]|0)>>16,b[(c[n>>2]|0)+22>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(x+((_((c[(c[u>>2]|0)+44>>2]|0)+(c[(c[u>>2]|0)+48>>2]|0)&65535,b[(c[n>>2]|0)+22>>1]|0)|0)>>16));if(((c[t>>2]>>5)+1>>1|0)<=32767)if(((c[t>>2]>>5)+1>>1|0)<-32768)z=-32768;else z=(c[t>>2]>>5)+1>>1;else z=32767;x=c[l>>2]|0;c[l>>2]=x+2;b[x>>1]=z;c[s>>2]=(c[s>>2]|0)+(c[r>>2]|0)}y=c[l>>2]|0;i=k;return y|0}else if((j|0)==36){c[s>>2]=0;while(1){if((c[s>>2]|0)>=(c[q>>2]|0))break;c[u>>2]=(c[m>>2]|0)+(c[s>>2]>>16<<2);j=_((c[c[u>>2]>>2]|0)+(c[(c[u>>2]|0)+140>>2]|0)>>16,b[c[n>>2]>>1]|0)|0;c[t>>2]=j+((_((c[c[u>>2]>>2]|0)+(c[(c[u>>2]|0)+140>>2]|0)&65535,b[c[n>>2]>>1]|0)|0)>>16);j=_((c[(c[u>>2]|0)+4>>2]|0)+(c[(c[u>>2]|0)+136>>2]|0)>>16,b[(c[n>>2]|0)+2>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+4>>2]|0)+(c[(c[u>>2]|0)+136>>2]|0)&65535,b[(c[n>>2]|0)+2>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+8>>2]|0)+(c[(c[u>>2]|0)+132>>2]|0)>>16,b[(c[n>>2]|0)+4>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+8>>2]|0)+(c[(c[u>>2]|0)+132>>2]|0)&65535,b[(c[n>>2]|0)+4>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+12>>2]|0)+(c[(c[u>>2]|0)+128>>2]|0)>>16,b[(c[n>>2]|0)+6>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+12>>2]|0)+(c[(c[u>>2]|0)+128>>2]|0)&65535,b[(c[n>>2]|0)+6>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+16>>2]|0)+(c[(c[u>>2]|0)+124>>2]|0)>>16,b[(c[n>>2]|0)+8>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+16>>2]|0)+(c[(c[u>>2]|0)+124>>2]|0)&65535,b[(c[n>>2]|0)+8>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+20>>2]|0)+(c[(c[u>>2]|0)+120>>2]|0)>>16,b[(c[n>>2]|0)+10>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+20>>2]|0)+(c[(c[u>>2]|0)+120>>2]|0)&65535,b[(c[n>>2]|0)+10>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+24>>2]|0)+(c[(c[u>>2]|0)+116>>2]|0)>>16,b[(c[n>>2]|0)+12>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+24>>2]|0)+(c[(c[u>>2]|0)+116>>2]|0)&65535,b[(c[n>>2]|0)+12>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+28>>2]|0)+(c[(c[u>>2]|0)+112>>2]|0)>>16,b[(c[n>>2]|0)+14>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+28>>2]|0)+(c[(c[u>>2]|0)+112>>2]|0)&65535,b[(c[n>>2]|0)+14>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+32>>2]|0)+(c[(c[u>>2]|0)+108>>2]|0)>>16,b[(c[n>>2]|0)+16>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+32>>2]|0)+(c[(c[u>>2]|0)+108>>2]|0)&65535,b[(c[n>>2]|0)+16>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+36>>2]|0)+(c[(c[u>>2]|0)+104>>2]|0)>>16,b[(c[n>>2]|0)+18>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+36>>2]|0)+(c[(c[u>>2]|0)+104>>2]|0)&65535,b[(c[n>>2]|0)+18>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+40>>2]|0)+(c[(c[u>>2]|0)+100>>2]|0)>>16,b[(c[n>>2]|0)+20>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+40>>2]|0)+(c[(c[u>>2]|0)+100>>2]|0)&65535,b[(c[n>>2]|0)+20>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+44>>2]|0)+(c[(c[u>>2]|0)+96>>2]|0)>>16,b[(c[n>>2]|0)+22>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+44>>2]|0)+(c[(c[u>>2]|0)+96>>2]|0)&65535,b[(c[n>>2]|0)+22>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+48>>2]|0)+(c[(c[u>>2]|0)+92>>2]|0)>>16,b[(c[n>>2]|0)+24>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+48>>2]|0)+(c[(c[u>>2]|0)+92>>2]|0)&65535,b[(c[n>>2]|0)+24>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+52>>2]|0)+(c[(c[u>>2]|0)+88>>2]|0)>>16,b[(c[n>>2]|0)+26>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+52>>2]|0)+(c[(c[u>>2]|0)+88>>2]|0)&65535,b[(c[n>>2]|0)+26>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+56>>2]|0)+(c[(c[u>>2]|0)+84>>2]|0)>>16,b[(c[n>>2]|0)+28>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+56>>2]|0)+(c[(c[u>>2]|0)+84>>2]|0)&65535,b[(c[n>>2]|0)+28>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+60>>2]|0)+(c[(c[u>>2]|0)+80>>2]|0)>>16,b[(c[n>>2]|0)+30>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+60>>2]|0)+(c[(c[u>>2]|0)+80>>2]|0)&65535,b[(c[n>>2]|0)+30>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+64>>2]|0)+(c[(c[u>>2]|0)+76>>2]|0)>>16,b[(c[n>>2]|0)+32>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+64>>2]|0)+(c[(c[u>>2]|0)+76>>2]|0)&65535,b[(c[n>>2]|0)+32>>1]|0)|0)>>16));j=_((c[(c[u>>2]|0)+68>>2]|0)+(c[(c[u>>2]|0)+72>>2]|0)>>16,b[(c[n>>2]|0)+34>>1]|0)|0;c[t>>2]=(c[t>>2]|0)+(j+((_((c[(c[u>>2]|0)+68>>2]|0)+(c[(c[u>>2]|0)+72>>2]|0)&65535,b[(c[n>>2]|0)+34>>1]|0)|0)>>16));if(((c[t>>2]>>5)+1>>1|0)<=32767)if(((c[t>>2]>>5)+1>>1|0)<-32768)A=-32768;else A=(c[t>>2]>>5)+1>>1;else A=32767;j=c[l>>2]|0;c[l>>2]=j+2;b[j>>1]=A;c[s>>2]=(c[s>>2]|0)+(c[r>>2]|0)}y=c[l>>2]|0;i=k;return y|0}else{y=c[l>>2]|0;i=k;return y|0}return 0}function Wd(a,d,e,f){a=a|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;g=i;i=i+32|0;h=g+4|0;j=g+16|0;k=g+8|0;l=g+20|0;m=g+28|0;n=g;o=g+12|0;p=g+24|0;c[h>>2]=a;c[j>>2]=d;c[k>>2]=e;c[l>>2]=f;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[k>>2]|0))break;c[p>>2]=(((c[m>>2]&65535)>>16)*12|0)+((c[m>>2]&65535)*12>>16);c[o>>2]=(c[j>>2]|0)+(c[m>>2]>>16<<1);c[n>>2]=_(b[c[o>>2]>>1]|0,b[2280+(c[p>>2]<<3)>>1]|0)|0;c[n>>2]=(c[n>>2]|0)+(_(b[(c[o>>2]|0)+2>>1]|0,b[2280+(c[p>>2]<<3)+2>>1]|0)|0);c[n>>2]=(c[n>>2]|0)+(_(b[(c[o>>2]|0)+4>>1]|0,b[2280+(c[p>>2]<<3)+4>>1]|0)|0);c[n>>2]=(c[n>>2]|0)+(_(b[(c[o>>2]|0)+6>>1]|0,b[2280+(c[p>>2]<<3)+6>>1]|0)|0);c[n>>2]=(c[n>>2]|0)+(_(b[(c[o>>2]|0)+8>>1]|0,b[2280+(11-(c[p>>2]|0)<<3)+6>>1]|0)|0);c[n>>2]=(c[n>>2]|0)+(_(b[(c[o>>2]|0)+10>>1]|0,b[2280+(11-(c[p>>2]|0)<<3)+4>>1]|0)|0);c[n>>2]=(c[n>>2]|0)+(_(b[(c[o>>2]|0)+12>>1]|0,b[2280+(11-(c[p>>2]|0)<<3)+2>>1]|0)|0);c[n>>2]=(c[n>>2]|0)+(_(b[(c[o>>2]|0)+14>>1]|0,b[2280+(11-(c[p>>2]|0)<<3)>>1]|0)|0);if(((c[n>>2]>>14)+1>>1|0)<=32767)if(((c[n>>2]>>14)+1>>1|0)<-32768)q=-32768;else q=(c[n>>2]>>14)+1>>1;else q=32767;f=c[h>>2]|0;c[h>>2]=f+2;b[f>>1]=q;c[m>>2]=(c[m>>2]|0)+(c[l>>2]|0)}i=g;return c[h>>2]|0}function Xd(a,e,f){a=a|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0;g=i;i=i+16|0;h=g+12|0;j=g+8|0;k=g+4|0;l=g;c[j>>2]=a;c[k>>2]=e;c[l>>2]=f;if((c[k>>2]|0)<1){b[c[l>>2]>>1]=-1;c[h>>2]=-1;m=c[h>>2]|0;i=g;return m|0}if((d[c[j>>2]>>0]|0|0)<252){b[c[l>>2]>>1]=d[c[j>>2]>>0]|0;c[h>>2]=1;m=c[h>>2]|0;i=g;return m|0}if((c[k>>2]|0)<2){b[c[l>>2]>>1]=-1;c[h>>2]=-1;m=c[h>>2]|0;i=g;return m|0}else{b[c[l>>2]>>1]=((d[(c[j>>2]|0)+1>>0]|0)<<2)+(d[c[j>>2]>>0]|0);c[h>>2]=2;m=c[h>>2]|0;i=g;return m|0}return 0}function Yd(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;i=b;return (c[d>>2]|0)+4-1&-4|0}function Zd(d,e,f,h,j,k){d=d|0;e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0;l=i;i=i+320|0;m=l;n=l+72|0;o=l+48|0;p=l+40|0;q=l+24|0;r=l+8|0;s=l+16|0;t=l+56|0;u=l+80|0;v=l+64|0;w=l+32|0;x=l+100|0;y=l+96|0;z=l+88|0;A=l+84|0;B=l+256|0;C=l+252|0;D=l+220|0;E=l+200|0;F=l+192|0;G=l+172|0;H=l+168|0;I=l+160|0;J=l+112|0;K=l+272|0;L=l+284|0;M=l+292|0;N=l+300|0;O=l+304|0;P=l+180|0;Q=l+184|0;R=l+280|0;S=l+288|0;T=l+296|0;U=l+248|0;V=l+216|0;W=l+204|0;Y=l+208|0;Z=l+212|0;$=l+188|0;aa=l+228|0;ba=l+232|0;ca=l+276|0;da=l+164|0;ea=l+236|0;fa=l+240|0;ga=l+244|0;ha=l+92|0;ia=l+104|0;ja=l+260|0;la=l+308|0;ma=l+196|0;na=l+268|0;oa=l+224|0;pa=l+312|0;qa=l+108|0;ra=l+176|0;sa=l+264|0;c[y>>2]=d;c[z>>2]=e;c[A>>2]=f;c[B>>2]=h;c[C>>2]=j;c[D>>2]=k;c[H>>2]=0;c[I>>2]=0;c[O>>2]=0;c[S>>2]=0;c[U>>2]=0;c[V>>2]=0;c[W>>2]=0;c[da>>2]=0;c[E>>2]=(c[y>>2]|0)+(c[(c[y>>2]|0)+4>>2]|0);c[F>>2]=(c[y>>2]|0)+(c[c[y>>2]>>2]|0);c[ba>>2]=(c[(c[y>>2]|0)+12>>2]|0)/50|0;c[aa>>2]=c[ba>>2]>>1;c[$>>2]=c[aa>>2]>>1;c[Z>>2]=c[$>>2]>>1;if((c[C>>2]|0)<(c[Z>>2]|0)){c[x>>2]=-2;ta=c[x>>2]|0;i=l;return ta|0}if((c[C>>2]|0)<(((c[(c[y>>2]|0)+12>>2]|0)/25|0)*3|0))va=c[C>>2]|0;else va=((c[(c[y>>2]|0)+12>>2]|0)/25|0)*3|0;c[C>>2]=va;if((c[A>>2]|0)<=1){c[z>>2]=0;if((c[C>>2]|0)<(c[(c[y>>2]|0)+60>>2]|0))wa=c[C>>2]|0;else wa=c[(c[y>>2]|0)+60>>2]|0;c[C>>2]=wa}do if(!(c[z>>2]|0)){c[Q>>2]=c[C>>2];c[R>>2]=c[(c[y>>2]|0)+56>>2];if(!(c[R>>2]|0)){c[G>>2]=0;while(1){if((c[G>>2]|0)>=(_(c[Q>>2]|0,c[(c[y>>2]|0)+8>>2]|0)|0))break;g[(c[B>>2]|0)+(c[G>>2]<<2)>>2]=0.0;c[G>>2]=(c[G>>2]|0)+1}c[x>>2]=c[Q>>2];ta=c[x>>2]|0;i=l;return ta|0}if((c[Q>>2]|0)>(c[ba>>2]|0)){while(1){c[fa>>2]=Zd(c[y>>2]|0,0,0,c[B>>2]|0,(c[Q>>2]|0)<(c[ba>>2]|0)?c[Q>>2]|0:c[ba>>2]|0,0)|0;xa=c[fa>>2]|0;if((c[fa>>2]|0)<0){ya=20;break}wa=_(xa,c[(c[y>>2]|0)+8>>2]|0)|0;c[B>>2]=(c[B>>2]|0)+(wa<<2);c[Q>>2]=(c[Q>>2]|0)-(c[fa>>2]|0);if((c[Q>>2]|0)<=0){ya=22;break}}if((ya|0)==20){c[x>>2]=xa;ta=c[x>>2]|0;i=l;return ta|0}else if((ya|0)==22){c[x>>2]=c[C>>2];ta=c[x>>2]|0;i=l;return ta|0}}if((c[Q>>2]|0)<(c[ba>>2]|0)){if((c[Q>>2]|0)>(c[aa>>2]|0)){c[Q>>2]=c[aa>>2];break}if(((c[R>>2]|0)!=1e3?(c[Q>>2]|0)>(c[$>>2]|0):0)?(c[Q>>2]|0)<(c[aa>>2]|0):0)c[Q>>2]=c[$>>2]}}else{c[Q>>2]=c[(c[y>>2]|0)+60>>2];c[R>>2]=c[(c[y>>2]|0)+52>>2];eb(J,c[z>>2]|0,c[A>>2]|0)}while(0);c[ea>>2]=0;c[M>>2]=1;c[N>>2]=1;do if((c[z>>2]|0)!=0?(c[(c[y>>2]|0)+56>>2]|0)>0:0){if(!(((c[R>>2]|0)==1002?(c[(c[y>>2]|0)+56>>2]|0)!=1002:0)?(c[(c[y>>2]|0)+64>>2]|0)==0:0)){if((c[R>>2]|0)==1002)break;if((c[(c[y>>2]|0)+56>>2]|0)!=1002)break}c[S>>2]=1;ya=_(c[$>>2]|0,c[(c[y>>2]|0)+8>>2]|0)|0;if((c[R>>2]|0)==1002){c[N>>2]=ya;break}else{c[M>>2]=ya;break}}while(0);ya=c[N>>2]|0;c[ga>>2]=ua()|0;N=i;i=i+((1*(ya<<2)|0)+15&-16)|0;if((c[S>>2]|0)!=0&(c[R>>2]|0)==1002){c[O>>2]=N;Zd(c[y>>2]|0,0,0,c[O>>2]|0,(c[$>>2]|0)<(c[Q>>2]|0)?c[$>>2]|0:c[Q>>2]|0,0)|0}a:do if((c[Q>>2]|0)>(c[C>>2]|0)){c[x>>2]=-1;c[ha>>2]=1}else{c[C>>2]=c[Q>>2];if((c[R>>2]|0)==1002|(c[ea>>2]|0)!=0)za=1;else za=_((c[aa>>2]|0)>(c[C>>2]|0)?c[aa>>2]|0:c[C>>2]|0,c[(c[y>>2]|0)+8>>2]|0)|0;c[L>>2]=za;N=i;i=i+((1*(c[L>>2]<<1)|0)+15&-16)|0;b:do if((c[R>>2]|0)!=1002){c[la>>2]=N;if((c[(c[y>>2]|0)+56>>2]|0)==1002)Vb(c[E>>2]|0)|0;if(10>(((c[Q>>2]|0)*1e3|0)/(c[(c[y>>2]|0)+12>>2]|0)|0|0))Aa=10;else Aa=((c[Q>>2]|0)*1e3|0)/(c[(c[y>>2]|0)+12>>2]|0)|0;c[(c[y>>2]|0)+16+16>>2]=Aa;do if(c[z>>2]|0){c[(c[y>>2]|0)+16+4>>2]=c[(c[y>>2]|0)+44>>2];ya=c[y>>2]|0;if((c[R>>2]|0)!=1e3){c[ya+16+12>>2]=16e3;break}xa=c[y>>2]|0;if((c[ya+48>>2]|0)==1101){c[xa+16+12>>2]=8e3;break}if((c[xa+48>>2]|0)==1102){c[(c[y>>2]|0)+16+12>>2]=12e3;break}else{c[(c[y>>2]|0)+16+12>>2]=16e3;break}}while(0);c[ia>>2]=(c[z>>2]|0)==0?1:c[D>>2]<<1;c[ja>>2]=0;c:while(1){c[ma>>2]=(c[ja>>2]|0)==0&1;c[H>>2]=Wb(c[E>>2]|0,(c[y>>2]|0)+16|0,c[ia>>2]|0,c[ma>>2]|0,J,c[la>>2]|0,K)|0;d:do if(c[H>>2]|0){if(!(c[ia>>2]|0))break c;c[K>>2]=c[C>>2];c[G>>2]=0;while(1){if((c[G>>2]|0)>=(_(c[C>>2]|0,c[(c[y>>2]|0)+8>>2]|0)|0))break d;b[(c[la>>2]|0)+(c[G>>2]<<1)>>1]=0;c[G>>2]=(c[G>>2]|0)+1}}while(0);xa=_(c[K>>2]|0,c[(c[y>>2]|0)+8>>2]|0)|0;c[la>>2]=(c[la>>2]|0)+(xa<<1);c[ja>>2]=(c[ja>>2]|0)+(c[K>>2]|0);if((c[ja>>2]|0)>=(c[C>>2]|0))break b}c[x>>2]=-3;c[ha>>2]=1;break a}while(0);c[T>>2]=0;if((c[D>>2]|0)==0&(c[R>>2]|0)!=1002&(c[z>>2]|0)!=0?(xa=(ge(J)|0)+17|0,(xa+(((c[(c[y>>2]|0)+52>>2]|0)==1001&1)*20|0)|0)<=(c[A>>2]<<3|0)):0){if((c[R>>2]|0)==1001)c[U>>2]=ib(J,12)|0;else c[U>>2]=1;if(c[U>>2]|0){c[W>>2]=ib(J,1)|0;if((c[R>>2]|0)==1001)Ba=(kb(J,256)|0)+2|0;else{xa=c[A>>2]|0;Ba=xa-((ge(J)|0)+7>>3)|0}c[V>>2]=Ba;c[A>>2]=(c[A>>2]|0)-(c[V>>2]|0);xa=c[A>>2]<<3;if((xa|0)<(ge(J)|0)){c[A>>2]=0;c[V>>2]=0;c[U>>2]=0}xa=J+4|0;c[xa>>2]=(c[xa>>2]|0)-(c[V>>2]|0)}}if((c[R>>2]|0)!=1002)c[T>>2]=17;c[na>>2]=21;switch(c[(c[y>>2]|0)+48>>2]|0){case 1101:{c[na>>2]=13;break}case 1103:case 1102:{c[na>>2]=17;break}case 1104:{c[na>>2]=19;break}case 1105:{c[na>>2]=21;break}default:{}}xa=c[F>>2]|0;c[w>>2]=c[na>>2];ab(xa,10012,w)|0;xa=c[F>>2]|0;c[v>>2]=c[(c[y>>2]|0)+44>>2];ab(xa,10008,v)|0;if(c[U>>2]|0){c[S>>2]=0;c[M>>2]=1}xa=i;i=i+((1*(c[M>>2]<<2)|0)+15&-16)|0;if((c[S>>2]|0)!=0&(c[R>>2]|0)!=1002){c[O>>2]=xa;Zd(c[y>>2]|0,0,0,c[O>>2]|0,(c[$>>2]|0)<(c[Q>>2]|0)?c[$>>2]|0:c[Q>>2]|0,0)|0}if(c[U>>2]|0)Ca=_(c[$>>2]|0,c[(c[y>>2]|0)+8>>2]|0)|0;else Ca=1;c[P>>2]=Ca;xa=i;i=i+((1*(c[P>>2]<<2)|0)+15&-16)|0;if((c[U>>2]|0)!=0&(c[W>>2]|0)!=0){ya=c[F>>2]|0;c[u>>2]=0;ab(ya,10010,u)|0;$a(c[F>>2]|0,(c[z>>2]|0)+(c[A>>2]|0)|0,c[V>>2]|0,xa,c[$>>2]|0,0,0)|0;ya=c[F>>2]|0;c[t>>2]=da+(((da-da|0)/4|0)<<2);ab(ya,4031,t)|0}ya=c[F>>2]|0;c[s>>2]=c[T>>2];ab(ya,10010,s)|0;do if((c[R>>2]|0)==1e3){a[pa>>0]=a[5184]|0;a[pa+1>>0]=a[5185]|0;e:do if(!(c[ea>>2]|0)){c[G>>2]=0;while(1){if((c[G>>2]|0)>=(_(c[C>>2]|0,c[(c[y>>2]|0)+8>>2]|0)|0))break e;g[(c[B>>2]|0)+(c[G>>2]<<2)>>2]=0.0;c[G>>2]=(c[G>>2]|0)+1}}while(0);if((c[(c[y>>2]|0)+56>>2]|0)==1001){if((c[U>>2]|0)!=0&(c[W>>2]|0)!=0?(c[(c[y>>2]|0)+64>>2]|0)!=0:0)break;ya=c[F>>2]|0;c[q>>2]=0;ab(ya,10010,q)|0;$a(c[F>>2]|0,pa,2,c[B>>2]|0,c[Z>>2]|0,0,c[ea>>2]|0)|0}}else{c[oa>>2]=(c[ba>>2]|0)<(c[C>>2]|0)?c[ba>>2]|0:c[C>>2]|0;do if((c[R>>2]|0)!=(c[(c[y>>2]|0)+56>>2]|0)){if((c[(c[y>>2]|0)+56>>2]|0)<=0)break;if(c[(c[y>>2]|0)+64>>2]|0)break;ab(c[F>>2]|0,4028,r)|0}while(0);c[I>>2]=$a(c[F>>2]|0,(c[D>>2]|0)!=0?0:c[z>>2]|0,c[A>>2]|0,c[B>>2]|0,c[oa>>2]|0,J,c[ea>>2]|0)|0}while(0);f:do if(!((c[R>>2]|0)==1002|(c[ea>>2]|0)!=0)){c[G>>2]=0;while(1){if((c[G>>2]|0)>=(_(c[C>>2]|0,c[(c[y>>2]|0)+8>>2]|0)|0))break f;g[(c[B>>2]|0)+(c[G>>2]<<2)>>2]=+g[(c[B>>2]|0)+(c[G>>2]<<2)>>2]+ +(b[N+(c[G>>2]<<1)>>1]|0)*.000030517578125;c[G>>2]=(c[G>>2]|0)+1}}while(0);N=c[F>>2]|0;c[p>>2]=qa+(((qa-qa|0)/4|0)<<2);ab(N,10015,p)|0;c[ca>>2]=c[(c[qa>>2]|0)+60>>2];if(!((c[U>>2]|0)==0|(c[W>>2]|0)!=0)){ab(c[F>>2]|0,4028,o)|0;N=c[F>>2]|0;c[n>>2]=0;ab(N,10010,n)|0;$a(c[F>>2]|0,(c[z>>2]|0)+(c[A>>2]|0)|0,c[V>>2]|0,xa,c[$>>2]|0,0,0)|0;N=c[F>>2]|0;c[m>>2]=da+(((da-da|0)/4|0)<<2);ab(N,4031,m)|0;N=(c[B>>2]|0)+((_(c[(c[y>>2]|0)+8>>2]|0,(c[C>>2]|0)-(c[Z>>2]|0)|0)|0)<<2)|0;ya=xa+((_(c[(c[y>>2]|0)+8>>2]|0,c[Z>>2]|0)|0)<<2)|0;fa=(c[B>>2]|0)+((_(c[(c[y>>2]|0)+8>>2]|0,(c[C>>2]|0)-(c[Z>>2]|0)|0)|0)<<2)|0;he(N,ya,fa,c[Z>>2]|0,c[(c[y>>2]|0)+8>>2]|0,c[ca>>2]|0,c[(c[y>>2]|0)+12>>2]|0)}if((c[U>>2]|0)!=0&(c[W>>2]|0)!=0){c[Y>>2]=0;while(1){if((c[Y>>2]|0)>=(c[(c[y>>2]|0)+8>>2]|0))break;c[G>>2]=0;while(1){if((c[G>>2]|0)>=(c[Z>>2]|0))break;fa=_(c[(c[y>>2]|0)+8>>2]|0,c[G>>2]|0)|0;ya=_(c[(c[y>>2]|0)+8>>2]|0,c[G>>2]|0)|0;g[(c[B>>2]|0)+(ya+(c[Y>>2]|0)<<2)>>2]=+g[xa+(fa+(c[Y>>2]|0)<<2)>>2];c[G>>2]=(c[G>>2]|0)+1}c[Y>>2]=(c[Y>>2]|0)+1}fa=xa+((_(c[(c[y>>2]|0)+8>>2]|0,c[Z>>2]|0)|0)<<2)|0;ya=(c[B>>2]|0)+((_(c[(c[y>>2]|0)+8>>2]|0,c[Z>>2]|0)|0)<<2)|0;N=(c[B>>2]|0)+((_(c[(c[y>>2]|0)+8>>2]|0,c[Z>>2]|0)|0)<<2)|0;he(fa,ya,N,c[Z>>2]|0,c[(c[y>>2]|0)+8>>2]|0,c[ca>>2]|0,c[(c[y>>2]|0)+12>>2]|0)}do if(c[S>>2]|0){if((c[Q>>2]|0)<(c[$>>2]|0)){he(c[O>>2]|0,c[B>>2]|0,c[B>>2]|0,c[Z>>2]|0,c[(c[y>>2]|0)+8>>2]|0,c[ca>>2]|0,c[(c[y>>2]|0)+12>>2]|0);break}c[G>>2]=0;while(1){if((c[G>>2]|0)>=(_(c[(c[y>>2]|0)+8>>2]|0,c[Z>>2]|0)|0))break;g[(c[B>>2]|0)+(c[G>>2]<<2)>>2]=+g[(c[O>>2]|0)+(c[G>>2]<<2)>>2];c[G>>2]=(c[G>>2]|0)+1}N=(c[O>>2]|0)+((_(c[(c[y>>2]|0)+8>>2]|0,c[Z>>2]|0)|0)<<2)|0;ya=(c[B>>2]|0)+((_(c[(c[y>>2]|0)+8>>2]|0,c[Z>>2]|0)|0)<<2)|0;fa=(c[B>>2]|0)+((_(c[(c[y>>2]|0)+8>>2]|0,c[Z>>2]|0)|0)<<2)|0;he(N,ya,fa,c[Z>>2]|0,c[(c[y>>2]|0)+8>>2]|0,c[ca>>2]|0,c[(c[y>>2]|0)+12>>2]|0)}while(0);g:do if(c[(c[y>>2]|0)+40>>2]|0){g[ra>>2]=+X(+(+(c[(c[y>>2]|0)+40>>2]|0)*6.488140788860619e-04*.6931471805599453));c[G>>2]=0;while(1){if((c[G>>2]|0)>=(_(c[C>>2]|0,c[(c[y>>2]|0)+8>>2]|0)|0))break g;g[sa>>2]=+g[(c[B>>2]|0)+(c[G>>2]<<2)>>2]*+g[ra>>2];g[(c[B>>2]|0)+(c[G>>2]<<2)>>2]=+g[sa>>2];c[G>>2]=(c[G>>2]|0)+1}}while(0);if((c[A>>2]|0)<=1)c[(c[y>>2]|0)+80>>2]=0;else c[(c[y>>2]|0)+80>>2]=c[J+28>>2]^c[da>>2];c[(c[y>>2]|0)+56>>2]=c[R>>2];if(c[U>>2]|0)Da=(c[W>>2]|0)!=0^1;else Da=0;c[(c[y>>2]|0)+64>>2]=Da&1;if((c[I>>2]|0)>=0)_d()|0;c[x>>2]=(c[I>>2]|0)<0?c[I>>2]|0:c[Q>>2]|0;c[ha>>2]=1}while(0);ka(c[ga>>2]|0);ta=c[x>>2]|0;i=l;return ta|0}function _d(){return 0}function $d(a){a=a|0;var b=0,e=0,f=0;b=i;i=i+16|0;e=b+4|0;f=b;c[e>>2]=a;do if(!((d[c[e>>2]>>0]|0)&128))if(((d[c[e>>2]>>0]|0)&96|0)==96){c[f>>2]=1001;break}else{c[f>>2]=1e3;break}else c[f>>2]=1002;while(0);i=b;return c[f>>2]|0}function ae(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;i=b;return (c[d>>2]|0)+4-1&-4|0}function be(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;a=Ze(c[d>>2]|0)|0;i=b;return a|0}function ce(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;_e(c[d>>2]|0);i=b;return}function de(a,b,e,f,g,h,j,k){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0;l=i;i=i+112|0;m=l;n=l+72|0;o=l+56|0;p=l+12|0;q=l+4|0;r=l+16|0;s=l+20|0;t=l+24|0;u=l+28|0;v=l+32|0;w=l+36|0;x=l+40|0;y=l+44|0;z=l+48|0;A=l+52|0;B=l+8|0;C=l+60|0;D=l+64|0;E=l+68|0;F=l+76|0;G=l+80|0;H=l+84|0;I=l+88|0;J=l+92|0;K=l+96|0;L=l+100|0;M=l+104|0;c[o>>2]=a;c[p>>2]=b;c[q>>2]=e;c[r>>2]=f;c[s>>2]=g;c[t>>2]=h;c[u>>2]=j;c[v>>2]=k;c[C>>2]=0;k=c[o>>2]|0;c[m>>2]=w+(((w-w|0)/4|0)<<2);Qc(k,4029,m)|0;if((c[t>>2]|0)<(((c[w>>2]|0)/25|0)*3|0))N=c[t>>2]|0;else N=((c[w>>2]|0)/25|0)*3|0;c[t>>2]=N;N=c[t>>2]<<1;c[D>>2]=ua()|0;m=i;i=i+((1*(N<<2)|0)+15&-16)|0;N=c[o>>2]|0;c[B>>2]=N+(ae(268)|0);c[x>>2]=Ac(2)|0;c[y>>2]=Ac(1)|0;if(!(c[q>>2]|0))c[C>>2]=1;if((c[q>>2]|0)<0){c[n>>2]=-1;c[E>>2]=1;O=c[D>>2]|0;ka(O|0);P=c[n>>2]|0;i=l;return P|0}if((c[C>>2]|0)==0?(c[q>>2]|0)<((c[(c[o>>2]|0)+4>>2]<<1)-1|0):0){c[n>>2]=-4;c[E>>2]=1;O=c[D>>2]|0;ka(O|0);P=c[n>>2]|0;i=l;return P|0}if(!(c[C>>2]|0)){c[F>>2]=fe(c[p>>2]|0,c[q>>2]|0,c[(c[o>>2]|0)+4>>2]|0,c[w>>2]|0)|0;w=c[F>>2]|0;if((c[F>>2]|0)<0){c[n>>2]=w;c[E>>2]=1;O=c[D>>2]|0;ka(O|0);P=c[n>>2]|0;i=l;return P|0}if((w|0)>(c[t>>2]|0)){c[n>>2]=-2;c[E>>2]=1;O=c[D>>2]|0;ka(O|0);P=c[n>>2]|0;i=l;return P|0}}c[z>>2]=0;while(1){if((c[z>>2]|0)>=(c[(c[o>>2]|0)+4>>2]|0)){Q=36;break}c[G>>2]=c[B>>2];if((c[z>>2]|0)<(c[(c[o>>2]|0)+8>>2]|0))R=ae(c[x>>2]|0)|0;else R=ae(c[y>>2]|0)|0;c[B>>2]=(c[B>>2]|0)+R;if((c[C>>2]|0)==0&(c[q>>2]|0)<=0){Q=22;break}c[H>>2]=0;c[I>>2]=Cc(c[G>>2]|0,c[p>>2]|0,c[q>>2]|0,m,c[t>>2]|0,c[u>>2]|0,(c[z>>2]|0)!=((c[(c[o>>2]|0)+4>>2]|0)-1|0)&1,H,c[v>>2]|0)|0;c[p>>2]=(c[p>>2]|0)+(c[H>>2]|0);c[q>>2]=(c[q>>2]|0)-(c[H>>2]|0);S=c[I>>2]|0;if((c[I>>2]|0)<=0){Q=24;break}c[t>>2]=S;a:do if((c[z>>2]|0)<(c[(c[o>>2]|0)+8>>2]|0)){c[K>>2]=-1;while(1){w=Jc(c[o>>2]|0,c[z>>2]|0,c[K>>2]|0)|0;c[J>>2]=w;if((w|0)==-1)break;Ha[c[s>>2]&1](c[r>>2]|0,c[c[o>>2]>>2]|0,c[J>>2]|0,m,2,c[t>>2]|0);c[K>>2]=c[J>>2]}c[K>>2]=-1;while(1){w=Kc(c[o>>2]|0,c[z>>2]|0,c[K>>2]|0)|0;c[J>>2]=w;if((w|0)==-1)break a;Ha[c[s>>2]&1](c[r>>2]|0,c[c[o>>2]>>2]|0,c[J>>2]|0,m+4|0,2,c[t>>2]|0);c[K>>2]=c[J>>2]}}else{c[M>>2]=-1;while(1){w=Lc(c[o>>2]|0,c[z>>2]|0,c[M>>2]|0)|0;c[L>>2]=w;if((w|0)==-1)break a;Ha[c[s>>2]&1](c[r>>2]|0,c[c[o>>2]>>2]|0,c[L>>2]|0,m,1,c[t>>2]|0);c[M>>2]=c[L>>2]}}while(0);c[z>>2]=(c[z>>2]|0)+1}if((Q|0)==22){c[n>>2]=-3;c[E>>2]=1;O=c[D>>2]|0;ka(O|0);P=c[n>>2]|0;i=l;return P|0}else if((Q|0)==24){c[n>>2]=S;c[E>>2]=1;O=c[D>>2]|0;ka(O|0);P=c[n>>2]|0;i=l;return P|0}else if((Q|0)==36){c[A>>2]=0;while(1){if((c[A>>2]|0)>=(c[c[o>>2]>>2]|0))break;if((d[(c[o>>2]|0)+12+(c[A>>2]|0)>>0]|0|0)==255)Ha[c[s>>2]&1](c[r>>2]|0,c[c[o>>2]>>2]|0,c[A>>2]|0,0,0,c[t>>2]|0);c[A>>2]=(c[A>>2]|0)+1}c[n>>2]=c[t>>2];c[E>>2]=1;O=c[D>>2]|0;ka(O|0);P=c[n>>2]|0;i=l;return P|0}return 0}function ee(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;j=i;i=i+32|0;k=j+4|0;l=j+16|0;m=j+8|0;n=j+20|0;o=j+28|0;p=j;q=j+12|0;r=j+24|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=d;c[n>>2]=e;c[o>>2]=f;c[p>>2]=h;c[q>>2]=c[k>>2];k=(c[n>>2]|0)!=0;c[r>>2]=0;if(k){while(1){if((c[r>>2]|0)>=(c[p>>2]|0))break;k=_(c[r>>2]|0,c[o>>2]|0)|0;h=_(c[r>>2]|0,c[l>>2]|0)|0;g[(c[q>>2]|0)+(h+(c[m>>2]|0)<<2)>>2]=+g[(c[n>>2]|0)+(k<<2)>>2];c[r>>2]=(c[r>>2]|0)+1}i=j;return}else{while(1){if((c[r>>2]|0)>=(c[p>>2]|0))break;n=_(c[r>>2]|0,c[l>>2]|0)|0;g[(c[q>>2]|0)+(n+(c[m>>2]|0)<<2)>>2]=0.0;c[r>>2]=(c[r>>2]|0)+1}i=j;return}}function fe(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;f=i;i=i+144|0;g=f+12|0;h=f+16|0;j=f+4|0;k=f+8|0;l=f+32|0;m=f;n=f+36|0;o=f+136|0;p=f+40|0;q=f+28|0;r=f+20|0;s=f+24|0;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;c[q>>2]=0;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[k>>2]|0)){t=11;break}if((c[j>>2]|0)<=0){t=4;break}c[n>>2]=zc(c[h>>2]|0,c[j>>2]|0,(c[m>>2]|0)!=((c[k>>2]|0)-1|0)&1,o,0,p,0,r)|0;if((c[n>>2]|0)<0){t=6;break}c[s>>2]=Hc(c[h>>2]|0,c[r>>2]|0,c[l>>2]|0)|0;if((c[m>>2]|0)!=0?(c[q>>2]|0)!=(c[s>>2]|0):0){t=9;break}c[q>>2]=c[s>>2];c[h>>2]=(c[h>>2]|0)+(c[r>>2]|0);c[j>>2]=(c[j>>2]|0)-(c[r>>2]|0);c[m>>2]=(c[m>>2]|0)+1}if((t|0)==4){c[g>>2]=-4;u=c[g>>2]|0;i=f;return u|0}else if((t|0)==6){c[g>>2]=c[n>>2];u=c[g>>2]|0;i=f;return u|0}else if((t|0)==9){c[g>>2]=-4;u=c[g>>2]|0;i=f;return u|0}else if((t|0)==11){c[g>>2]=c[q>>2];u=c[g>>2]|0;i=f;return u|0}return 0}function ge(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;a=(c[(c[d>>2]|0)+20>>2]|0)-(32-(aa(c[(c[d>>2]|0)+28>>2]|0)|0))|0;i=b;return a|0}function he(a,b,d,e,f,h,j){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;k=i;i=i+48|0;l=k+36|0;m=k+16|0;n=k;o=k+28|0;p=k+32|0;q=k+40|0;r=k+12|0;s=k+24|0;t=k+20|0;u=k+8|0;v=k+4|0;c[l>>2]=a;c[m>>2]=b;c[n>>2]=d;c[o>>2]=e;c[p>>2]=f;c[q>>2]=h;c[r>>2]=j;c[u>>2]=48e3/(c[r>>2]|0)|0;c[t>>2]=0;while(1){if((c[t>>2]|0)>=(c[p>>2]|0))break;c[s>>2]=0;while(1){if((c[s>>2]|0)>=(c[o>>2]|0))break;r=_(c[s>>2]|0,c[u>>2]|0)|0;j=_(c[s>>2]|0,c[u>>2]|0)|0;g[v>>2]=+g[(c[q>>2]|0)+(r<<2)>>2]*+g[(c[q>>2]|0)+(j<<2)>>2];j=_(c[s>>2]|0,c[p>>2]|0)|0;r=_(c[s>>2]|0,c[p>>2]|0)|0;h=_(c[s>>2]|0,c[p>>2]|0)|0;g[(c[n>>2]|0)+(h+(c[t>>2]|0)<<2)>>2]=+g[v>>2]*+g[(c[m>>2]|0)+(j+(c[t>>2]|0)<<2)>>2]+(1.0-+g[v>>2])*+g[(c[l>>2]|0)+(r+(c[t>>2]|0)<<2)>>2];c[s>>2]=(c[s>>2]|0)+1}c[t>>2]=(c[t>>2]|0)+1}i=k;return}function ie(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b;c[d>>2]=a;if(!(c[d>>2]|0)){e=32;i=b;return e|0}e=32-(32-(aa(c[d>>2]|0)|0))|0;i=b;return e|0}function je(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;d=i;i=i+48|0;e=d+28|0;f=d+16|0;g=d+4|0;h=d+8|0;j=d+32|0;k=d;l=d+12|0;m=d+24|0;n=d+20|0;c[f>>2]=a;c[g>>2]=b;b=c[f>>2]|0;c[h>>2]=(ie((c[f>>2]|0)>0?b:0-b|0)|0)-1;c[l>>2]=c[f>>2]<<c[h>>2];c[k>>2]=536870911/(c[l>>2]>>16|0)|0;c[n>>2]=c[k>>2]<<16;f=_(c[l>>2]>>16,(c[k>>2]&65535)<<16>>16)|0;c[m>>2]=536870912-(f+((_(c[l>>2]&65535,(c[k>>2]&65535)<<16>>16)|0)>>16))<<3;l=_(c[m>>2]>>16,(c[k>>2]&65535)<<16>>16)|0;f=(c[n>>2]|0)+(l+((_(c[m>>2]&65535,(c[k>>2]&65535)<<16>>16)|0)>>16))|0;c[n>>2]=f+(_(c[m>>2]|0,(c[k>>2]>>15)+1>>1)|0);c[j>>2]=61-(c[h>>2]|0)-(c[g>>2]|0);g=c[j>>2]|0;if((c[j>>2]|0)>0)if((g|0)<32){c[e>>2]=c[n>>2]>>c[j>>2];o=c[e>>2]|0;i=d;return o|0}else{c[e>>2]=0;o=c[e>>2]|0;i=d;return o|0}h=c[n>>2]|0;k=0-(c[j>>2]|0)|0;do if((-2147483648>>0-g|0)>(2147483647>>0-(c[j>>2]|0)|0)){if((h|0)>(-2147483648>>k|0)){p=-2147483648>>0-(c[j>>2]|0);break}if((c[n>>2]|0)<(2147483647>>0-(c[j>>2]|0)|0)){p=2147483647>>0-(c[j>>2]|0);break}else{p=c[n>>2]|0;break}}else{if((h|0)>(2147483647>>k|0)){p=2147483647>>0-(c[j>>2]|0);break}if((c[n>>2]|0)<(-2147483648>>0-(c[j>>2]|0)|0)){p=-2147483648>>0-(c[j>>2]|0);break}else{p=c[n>>2]|0;break}}while(0);c[e>>2]=p<<0-(c[j>>2]|0);o=c[e>>2]|0;i=d;return o|0}function ke(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0;e=i;i=i+16|0;f=e+12|0;g=e+8|0;h=e+4|0;j=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;c[j>>2]=Ld(c[f>>2]|0)|0;c[c[g>>2]>>2]=c[j>>2];g=(le(c[f>>2]|0,24-(c[j>>2]|0)|0)|0)&127;c[c[h>>2]>>2]=g;i=e;return}function le(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;i=i+32|0;e=d+20|0;f=d+16|0;g=d+12|0;h=d+8|0;j=d+4|0;k=d;c[f>>2]=a;c[g>>2]=b;c[h>>2]=c[f>>2];c[j>>2]=c[g>>2];c[k>>2]=0-(c[g>>2]|0);if(!(c[g>>2]|0)){c[e>>2]=c[f>>2];l=c[e>>2]|0;i=d;return l|0}f=c[h>>2]|0;if((c[g>>2]|0)<0){c[e>>2]=f<<c[k>>2]|(c[h>>2]|0)>>>(32-(c[k>>2]|0)|0);l=c[e>>2]|0;i=d;return l|0}else{c[e>>2]=f<<32-(c[j>>2]|0)|(c[h>>2]|0)>>>(c[j>>2]|0);l=c[e>>2]|0;i=d;return l|0}return 0}function me(a,d,e,f,g,h,j,k){a=a|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;l=i;i=i+48|0;m=l+4|0;n=l+16|0;o=l+36|0;p=l;q=l+32|0;r=l+40|0;s=l+44|0;t=l+24|0;u=l+20|0;v=l+8|0;w=l+12|0;x=l+28|0;c[m>>2]=a;c[n>>2]=d;c[o>>2]=e;c[p>>2]=f;c[q>>2]=g;c[r>>2]=h;c[s>>2]=j;c[t>>2]=k;k=c[s>>2]<<1;c[x>>2]=ua()|0;j=i;i=i+((1*(k<<1)|0)+15&-16)|0;c[w>>2]=j;c[v>>2]=0;while(1){if((c[v>>2]|0)>=2)break;c[u>>2]=0;while(1){if((c[u>>2]|0)>=(c[s>>2]|0))break;k=(c[u>>2]|0)+(_((c[v>>2]|0)+(c[t>>2]|0)-2|0,c[s>>2]|0)|0)|0;h=_(c[(c[q>>2]|0)+(k<<2)>>2]>>16,(c[(c[r>>2]|0)+(c[v>>2]<<2)>>2]&65535)<<16>>16)|0;k=(c[u>>2]|0)+(_((c[v>>2]|0)+(c[t>>2]|0)-2|0,c[s>>2]|0)|0)|0;g=h+((_(c[(c[q>>2]|0)+(k<<2)>>2]&65535,(c[(c[r>>2]|0)+(c[v>>2]<<2)>>2]&65535)<<16>>16)|0)>>16)|0;k=(c[u>>2]|0)+(_((c[v>>2]|0)+(c[t>>2]|0)-2|0,c[s>>2]|0)|0)|0;if((g+(_(c[(c[q>>2]|0)+(k<<2)>>2]|0,(c[(c[r>>2]|0)+(c[v>>2]<<2)>>2]>>15)+1>>1)|0)>>8|0)<=32767){k=(c[u>>2]|0)+(_((c[v>>2]|0)+(c[t>>2]|0)-2|0,c[s>>2]|0)|0)|0;g=_(c[(c[q>>2]|0)+(k<<2)>>2]>>16,(c[(c[r>>2]|0)+(c[v>>2]<<2)>>2]&65535)<<16>>16)|0;k=(c[u>>2]|0)+(_((c[v>>2]|0)+(c[t>>2]|0)-2|0,c[s>>2]|0)|0)|0;h=g+((_(c[(c[q>>2]|0)+(k<<2)>>2]&65535,(c[(c[r>>2]|0)+(c[v>>2]<<2)>>2]&65535)<<16>>16)|0)>>16)|0;k=(c[u>>2]|0)+(_((c[v>>2]|0)+(c[t>>2]|0)-2|0,c[s>>2]|0)|0)|0;if((h+(_(c[(c[q>>2]|0)+(k<<2)>>2]|0,(c[(c[r>>2]|0)+(c[v>>2]<<2)>>2]>>15)+1>>1)|0)>>8|0)<-32768)y=-32768;else{k=(c[u>>2]|0)+(_((c[v>>2]|0)+(c[t>>2]|0)-2|0,c[s>>2]|0)|0)|0;h=_(c[(c[q>>2]|0)+(k<<2)>>2]>>16,(c[(c[r>>2]|0)+(c[v>>2]<<2)>>2]&65535)<<16>>16)|0;k=(c[u>>2]|0)+(_((c[v>>2]|0)+(c[t>>2]|0)-2|0,c[s>>2]|0)|0)|0;g=h+((_(c[(c[q>>2]|0)+(k<<2)>>2]&65535,(c[(c[r>>2]|0)+(c[v>>2]<<2)>>2]&65535)<<16>>16)|0)>>16)|0;k=(c[u>>2]|0)+(_((c[v>>2]|0)+(c[t>>2]|0)-2|0,c[s>>2]|0)|0)|0;y=g+(_(c[(c[q>>2]|0)+(k<<2)>>2]|0,(c[(c[r>>2]|0)+(c[v>>2]<<2)>>2]>>15)+1>>1)|0)>>8}}else y=32767;b[(c[w>>2]|0)+(c[u>>2]<<1)>>1]=y;c[u>>2]=(c[u>>2]|0)+1}c[w>>2]=(c[w>>2]|0)+(c[s>>2]<<1);c[v>>2]=(c[v>>2]|0)+1}uc(c[m>>2]|0,c[n>>2]|0,j,c[s>>2]|0);uc(c[o>>2]|0,c[p>>2]|0,j+(c[s>>2]<<1)|0,c[s>>2]|0);ka(c[x>>2]|0);i=l;return}function ne(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)>(c[f>>2]|0)?c[e>>2]|0:c[f>>2]|0)|0}function oe(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)<(c[f>>2]|0)?c[e>>2]|0:c[f>>2]|0)|0}function pe(a,c){a=a|0;c=c|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+2|0;f=d;b[e>>1]=a;b[f>>1]=c;i=d;return ((b[e>>1]|0)>(b[f>>1]|0)?b[e>>1]|0:b[f>>1]|0)&65535|0}function qe(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)<(c[f>>2]|0)?c[e>>2]|0:c[f>>2]|0)|0}function re(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;d=i;i=i+48|0;e=d+28|0;f=d+16|0;g=d+4|0;h=d+8|0;j=d+32|0;k=d;l=d+12|0;m=d+24|0;n=d+20|0;c[f>>2]=a;c[g>>2]=b;b=c[f>>2]|0;c[h>>2]=(Ld((c[f>>2]|0)>0?b:0-b|0)|0)-1;c[l>>2]=c[f>>2]<<c[h>>2];c[k>>2]=536870911/(c[l>>2]>>16|0)|0;c[n>>2]=c[k>>2]<<16;f=_(c[l>>2]>>16,(c[k>>2]&65535)<<16>>16)|0;c[m>>2]=536870912-(f+((_(c[l>>2]&65535,(c[k>>2]&65535)<<16>>16)|0)>>16))<<3;l=_(c[m>>2]>>16,(c[k>>2]&65535)<<16>>16)|0;f=(c[n>>2]|0)+(l+((_(c[m>>2]&65535,(c[k>>2]&65535)<<16>>16)|0)>>16))|0;c[n>>2]=f+(_(c[m>>2]|0,(c[k>>2]>>15)+1>>1)|0);c[j>>2]=61-(c[h>>2]|0)-(c[g>>2]|0);g=c[j>>2]|0;if((c[j>>2]|0)>0)if((g|0)<32){c[e>>2]=c[n>>2]>>c[j>>2];o=c[e>>2]|0;i=d;return o|0}else{c[e>>2]=0;o=c[e>>2]|0;i=d;return o|0}h=c[n>>2]|0;k=0-(c[j>>2]|0)|0;do if((-2147483648>>0-g|0)>(2147483647>>0-(c[j>>2]|0)|0)){if((h|0)>(-2147483648>>k|0)){p=-2147483648>>0-(c[j>>2]|0);break}if((c[n>>2]|0)<(2147483647>>0-(c[j>>2]|0)|0)){p=2147483647>>0-(c[j>>2]|0);break}else{p=c[n>>2]|0;break}}else{if((h|0)>(2147483647>>k|0)){p=2147483647>>0-(c[j>>2]|0);break}if((c[n>>2]|0)<(-2147483648>>0-(c[j>>2]|0)|0)){p=-2147483648>>0-(c[j>>2]|0);break}else{p=c[n>>2]|0;break}}while(0);c[e>>2]=p<<0-(c[j>>2]|0);o=c[e>>2]|0;i=d;return o|0}function se(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0;e=i;i=i+16|0;f=e+12|0;g=e+8|0;h=e+4|0;j=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;c[j>>2]=te(c[f>>2]|0)|0;c[c[g>>2]>>2]=c[j>>2];g=(ue(c[f>>2]|0,24-(c[j>>2]|0)|0)|0)&127;c[c[h>>2]>>2]=g;i=e;return}function te(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b;c[d>>2]=a;if(!(c[d>>2]|0)){e=32;i=b;return e|0}e=32-(32-(aa(c[d>>2]|0)|0))|0;i=b;return e|0}function ue(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;i=i+32|0;e=d+20|0;f=d+16|0;g=d+12|0;h=d+8|0;j=d+4|0;k=d;c[f>>2]=a;c[g>>2]=b;c[h>>2]=c[f>>2];c[j>>2]=c[g>>2];c[k>>2]=0-(c[g>>2]|0);if(!(c[g>>2]|0)){c[e>>2]=c[f>>2];l=c[e>>2]|0;i=d;return l|0}f=c[h>>2]|0;if((c[g>>2]|0)<0){c[e>>2]=f<<c[k>>2]|(c[h>>2]|0)>>>(32-(c[k>>2]|0)|0);l=c[e>>2]|0;i=d;return l|0}else{c[e>>2]=f<<32-(c[j>>2]|0)|(c[h>>2]|0)>>>(c[j>>2]|0);l=c[e>>2]|0;i=d;return l|0}return 0}function ve(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b;c[d>>2]=a;if(!(c[d>>2]|0)){e=32;i=b;return e|0}e=32-(32-(aa(c[d>>2]|0)|0))|0;i=b;return e|0}function we(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)>>>0)/((c[f>>2]|0)>>>0)|0|0}function xe(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=+e;f=+f;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;h=i;i=i+48|0;j=h+4|0;k=h+16|0;l=h+36|0;m=h;n=h+32|0;o=h+40|0;p=h+44|0;q=h+24|0;r=h+20|0;s=h+8|0;t=h+12|0;u=h+28|0;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;g[m>>2]=e;g[n>>2]=f;c[q>>2]=c[j>>2];g[p>>2]=-+g[n>>2];c[o>>2]=0;while(1){if((c[o>>2]|0)>=((c[k>>2]|0)-(c[l>>2]|0)|0))break;g[r>>2]=+g[c[q>>2]>>2];g[s>>2]=+g[(c[q>>2]|0)+(c[l>>2]<<2)>>2];g[(c[q>>2]|0)+(c[l>>2]<<2)>>2]=+g[m>>2]*+g[s>>2]+ +g[n>>2]*+g[r>>2];f=+g[m>>2]*+g[r>>2]+ +g[p>>2]*+g[s>>2];d=c[q>>2]|0;c[q>>2]=d+4;g[d>>2]=f;c[o>>2]=(c[o>>2]|0)+1}c[q>>2]=(c[j>>2]|0)+((c[k>>2]|0)-(c[l>>2]<<1)-1<<2);c[o>>2]=(c[k>>2]|0)-(c[l>>2]<<1)-1;while(1){if((c[o>>2]|0)<0)break;g[t>>2]=+g[c[q>>2]>>2];g[u>>2]=+g[(c[q>>2]|0)+(c[l>>2]<<2)>>2];g[(c[q>>2]|0)+(c[l>>2]<<2)>>2]=+g[m>>2]*+g[u>>2]+ +g[n>>2]*+g[t>>2];f=+g[m>>2]*+g[t>>2]+ +g[p>>2]*+g[u>>2];k=c[q>>2]|0;c[q>>2]=k+-4;g[k>>2]=f;c[o>>2]=(c[o>>2]|0)+-1}i=h;return}function ye(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;i=d;return ((c[e>>2]|0)>>>0)/((c[f>>2]|0)>>>0)|0|0}function ze(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0;e=i;i=i+16|0;f=e+8|0;g=e+4|0;h=e;c[g>>2]=b;c[h>>2]=d;if(((c[(c[g>>2]|0)+24>>2]|0)+(c[(c[g>>2]|0)+8>>2]|0)|0)>>>0>=(c[(c[g>>2]|0)+4>>2]|0)>>>0){c[f>>2]=-1;j=c[f>>2]|0;i=e;return j|0}else{d=c[h>>2]&255;h=(c[g>>2]|0)+24|0;b=c[h>>2]|0;c[h>>2]=b+1;a[(c[c[g>>2]>>2]|0)+b>>0]=d;c[f>>2]=0;j=c[f>>2]|0;i=e;return j|0}return 0}function Ae(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;i=i+4112|0;f=e+4108|0;g=e+4104|0;h=e+4100|0;j=e+4096|0;k=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;vb(c[f>>2]|0,k,2048,c[g>>2]|0,c[h>>2]|0);xb(k+1440|0,k,1328,620,j,c[h>>2]|0);c[j>>2]=720-(c[j>>2]|0);i=e;return c[j>>2]|0}function Be(){return 0}function Ce(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;h=i;i=i+48|0;j=h+4|0;k=h+16|0;l=h+36|0;m=h;n=h+32|0;o=h+40|0;p=h+44|0;q=h+24|0;r=h+20|0;s=h+8|0;t=h+12|0;u=h+28|0;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[n>>2]=f;c[o>>2]=((c[c[j>>2]>>2]|0)!=0^1)&1;c[r>>2]=c[k>>2];c[s>>2]=c[c[j>>2]>>2];c[t>>2]=c[(c[j>>2]|0)+24>>2];c[q>>2]=(c[l>>2]|0)!=0&1;c[p>>2]=0;do{c[u>>2]=0;if((c[(c[j>>2]|0)+28>>2]|0)>=8){if(c[s>>2]|0){c[u>>2]=+g[c[r>>2]>>2]<0.0&1;pb(c[t>>2]|0,c[u>>2]|0,1)}else c[u>>2]=lb(c[t>>2]|0,1)|0;f=(c[j>>2]|0)+28|0;c[f>>2]=(c[f>>2]|0)-8;c[m>>2]=(c[m>>2]|0)-8}if(c[o>>2]|0)g[c[r>>2]>>2]=(c[u>>2]|0)!=0?-1.0:1.0;c[r>>2]=c[l>>2];f=(c[p>>2]|0)+1|0;c[p>>2]=f}while((f|0)<(1+(c[q>>2]|0)|0));if(!(c[n>>2]|0)){i=h;return 1}g[c[n>>2]>>2]=+g[c[k>>2]>>2];i=h;return 1}function De(a,d,e,f,h,j,k,l,m,n,o){a=a|0;d=d|0;e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;var p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0;p=i;i=i+160|0;q=p+72|0;r=p+56|0;s=p+4|0;t=p+52|0;u=p+140|0;v=p+68|0;w=p+20|0;x=p+24|0;y=p+28|0;z=p+32|0;A=p+36|0;B=p+40|0;C=p+44|0;D=p+48|0;E=p+112|0;F=p+120|0;G=p+128|0;H=p+136|0;I=p+144|0;J=p+148|0;K=p+76|0;L=p+80|0;M=p+84|0;N=p+88|0;O=p+92|0;P=p+96|0;Q=p+100|0;R=p+104|0;S=p+12|0;T=p;U=p+8|0;V=p+108|0;W=p+116|0;X=p+60|0;Y=p+124|0;Z=p+16|0;$=p+64|0;aa=p+132|0;c[q>>2]=a;c[r>>2]=d;c[s>>2]=e;c[t>>2]=f;c[u>>2]=h;c[v>>2]=j;c[w>>2]=k;c[x>>2]=l;c[y>>2]=m;c[z>>2]=n;c[A>>2]=o;c[C>>2]=0;c[K>>2]=0;c[L>>2]=c[c[q>>2]>>2];c[M>>2]=c[(c[q>>2]|0)+4>>2];c[N>>2]=c[(c[q>>2]|0)+8>>2];c[O>>2]=c[(c[q>>2]|0)+12>>2];c[P>>2]=c[(c[q>>2]|0)+24>>2];c[Q>>2]=c[(c[q>>2]|0)+32>>2];c[H>>2]=(b[(c[(c[M>>2]|0)+56>>2]|0)+(c[N>>2]<<1)>>1]|0)+(c[y>>2]<<3);c[I>>2]=(c[H>>2]>>1)-(((c[z>>2]|0)!=0?(c[u>>2]|0)==2:0)?16:4);c[B>>2]=Ge(c[u>>2]|0,c[c[v>>2]>>2]|0,c[I>>2]|0,c[H>>2]|0,c[z>>2]|0)|0;if((c[z>>2]|0)!=0?(c[N>>2]|0)>=(c[O>>2]|0):0)c[B>>2]=1;if(c[L>>2]|0)c[C>>2]=Jb(c[s>>2]|0,c[t>>2]|0,c[z>>2]|0,c[u>>2]|0)|0;c[J>>2]=db(c[P>>2]|0)|0;do if((c[B>>2]|0)!=1){if(c[L>>2]|0)c[C>>2]=(_(c[C>>2]|0,c[B>>2]|0)|0)+8192>>14;do if((c[z>>2]|0)!=0&(c[u>>2]|0)>2){c[R>>2]=3;c[S>>2]=c[C>>2];c[T>>2]=(c[B>>2]|0)/2|0;O=_(c[R>>2]|0,(c[T>>2]|0)+1|0)|0;c[U>>2]=O+(c[T>>2]|0);O=c[P>>2]|0;if(c[L>>2]|0){if((c[S>>2]|0)<=(c[T>>2]|0))ba=_(c[R>>2]|0,c[S>>2]|0)|0;else ba=(c[S>>2]|0)-1-(c[T>>2]|0)+(_((c[T>>2]|0)+1|0,c[R>>2]|0)|0)|0;if((c[S>>2]|0)<=(c[T>>2]|0))ca=_(c[R>>2]|0,(c[S>>2]|0)+1|0)|0;else ca=(c[S>>2]|0)-(c[T>>2]|0)+(_((c[T>>2]|0)+1|0,c[R>>2]|0)|0)|0;mb(O,ba,ca,c[U>>2]|0);break}c[V>>2]=fb(O,c[U>>2]|0)|0;if((c[V>>2]|0)<(_((c[T>>2]|0)+1|0,c[R>>2]|0)|0))c[S>>2]=(c[V>>2]|0)/(c[R>>2]|0)|0;else c[S>>2]=(c[T>>2]|0)+1+((c[V>>2]|0)-(_((c[T>>2]|0)+1|0,c[R>>2]|0)|0));if((c[S>>2]|0)<=(c[T>>2]|0))da=_(c[R>>2]|0,c[S>>2]|0)|0;else da=(c[S>>2]|0)-1-(c[T>>2]|0)+(_((c[T>>2]|0)+1|0,c[R>>2]|0)|0)|0;if((c[S>>2]|0)<=(c[T>>2]|0))ea=_(c[R>>2]|0,(c[S>>2]|0)+1|0)|0;else ea=(c[S>>2]|0)-(c[T>>2]|0)+(_((c[T>>2]|0)+1|0,c[R>>2]|0)|0)|0;hb(c[P>>2]|0,da,ea,c[U>>2]|0);c[C>>2]=c[S>>2]}else{if((c[x>>2]|0)>1|(c[z>>2]|0)!=0){O=c[P>>2]|0;if(c[L>>2]|0){ob(O,c[C>>2]|0,(c[B>>2]|0)+1|0);break}else{c[C>>2]=kb(O,(c[B>>2]|0)+1|0)|0;break}}c[W>>2]=1;c[X>>2]=_((c[B>>2]>>1)+1|0,(c[B>>2]>>1)+1|0)|0;if(!(c[L>>2]|0)){c[Z>>2]=0;c[$>>2]=fb(c[P>>2]|0,c[X>>2]|0)|0;if((c[$>>2]|0)<((_(c[B>>2]>>1,(c[B>>2]>>1)+1|0)|0)>>1|0)){c[C>>2]=((sb((c[$>>2]<<3)+1|0)|0)-1|0)>>>1;c[W>>2]=(c[C>>2]|0)+1;c[Z>>2]=(_(c[C>>2]|0,(c[C>>2]|0)+1|0)|0)>>1}else{O=(c[B>>2]|0)+1<<1;c[C>>2]=(O-(sb(((c[X>>2]|0)-(c[$>>2]|0)-1<<3)+1|0)|0)|0)>>>1;c[W>>2]=(c[B>>2]|0)+1-(c[C>>2]|0);c[Z>>2]=(c[X>>2]|0)-((_((c[B>>2]|0)+1-(c[C>>2]|0)|0,(c[B>>2]|0)+2-(c[C>>2]|0)|0)|0)>>1)}hb(c[P>>2]|0,c[Z>>2]|0,(c[Z>>2]|0)+(c[W>>2]|0)|0,c[X>>2]|0);break}if((c[C>>2]|0)<=(c[B>>2]>>1|0))fa=(c[C>>2]|0)+1|0;else fa=(c[B>>2]|0)+1-(c[C>>2]|0)|0;c[W>>2]=fa;if((c[C>>2]|0)<=(c[B>>2]>>1|0))ga=(_(c[C>>2]|0,(c[C>>2]|0)+1|0)|0)>>1;else ga=(c[X>>2]|0)-((_((c[B>>2]|0)+1-(c[C>>2]|0)|0,(c[B>>2]|0)+2-(c[C>>2]|0)|0)|0)>>1)|0;c[Y>>2]=ga;mb(c[P>>2]|0,c[Y>>2]|0,(c[Y>>2]|0)+(c[W>>2]|0)|0,c[X>>2]|0)}while(0);c[C>>2]=Rc(c[C>>2]<<14,c[B>>2]|0)|0;if((c[L>>2]|0)!=0&(c[z>>2]|0)!=0)if(!(c[C>>2]|0)){He(c[M>>2]|0,c[s>>2]|0,c[t>>2]|0,c[Q>>2]|0,c[N>>2]|0,c[u>>2]|0);break}else{Ie(c[s>>2]|0,c[t>>2]|0,c[u>>2]|0);break}}else if(c[z>>2]|0){if(c[L>>2]|0){c[K>>2]=(c[C>>2]|0)>8192&1;a:do if(c[K>>2]|0){c[aa>>2]=0;while(1){if((c[aa>>2]|0)>=(c[u>>2]|0))break a;g[(c[t>>2]|0)+(c[aa>>2]<<2)>>2]=-+g[(c[t>>2]|0)+(c[aa>>2]<<2)>>2];c[aa>>2]=(c[aa>>2]|0)+1}}while(0);He(c[M>>2]|0,c[s>>2]|0,c[t>>2]|0,c[Q>>2]|0,c[N>>2]|0,c[u>>2]|0)}do if((c[c[v>>2]>>2]|0)>16?(c[(c[q>>2]|0)+28>>2]|0)>16:0){O=c[P>>2]|0;if(c[L>>2]|0){nb(O,c[K>>2]|0,2);break}else{c[K>>2]=ib(O,2)|0;break}}else ha=60;while(0);if((ha|0)==60)c[K>>2]=0;c[C>>2]=0}while(0);ha=db(c[P>>2]|0)|0;c[G>>2]=ha-(c[J>>2]|0);J=c[v>>2]|0;c[J>>2]=(c[J>>2]|0)-(c[G>>2]|0);if(!(c[C>>2]|0)){c[E>>2]=32767;c[F>>2]=0;J=c[A>>2]|0;c[J>>2]=c[J>>2]&(1<<c[w>>2])-1;c[D>>2]=-16384;ia=c[K>>2]|0;ja=c[r>>2]|0;c[ja>>2]=ia;ka=c[E>>2]|0;la=c[r>>2]|0;ma=la+4|0;c[ma>>2]=ka;na=c[F>>2]|0;oa=c[r>>2]|0;pa=oa+8|0;c[pa>>2]=na;qa=c[D>>2]|0;ra=c[r>>2]|0;sa=ra+12|0;c[sa>>2]=qa;ta=c[C>>2]|0;ua=c[r>>2]|0;va=ua+16|0;c[va>>2]=ta;wa=c[G>>2]|0;xa=c[r>>2]|0;ya=xa+20|0;c[ya>>2]=wa;i=p;return}if((c[C>>2]|0)==16384){c[E>>2]=0;c[F>>2]=32767;J=c[A>>2]|0;c[J>>2]=c[J>>2]&(1<<c[w>>2])-1<<c[w>>2];c[D>>2]=16384;ia=c[K>>2]|0;ja=c[r>>2]|0;c[ja>>2]=ia;ka=c[E>>2]|0;la=c[r>>2]|0;ma=la+4|0;c[ma>>2]=ka;na=c[F>>2]|0;oa=c[r>>2]|0;pa=oa+8|0;c[pa>>2]=na;qa=c[D>>2]|0;ra=c[r>>2]|0;sa=ra+12|0;c[sa>>2]=qa;ta=c[C>>2]|0;ua=c[r>>2]|0;va=ua+16|0;c[va>>2]=ta;wa=c[G>>2]|0;xa=c[r>>2]|0;ya=xa+20|0;c[ya>>2]=wa;i=p;return}else{c[E>>2]=(Je(c[C>>2]&65535)|0)<<16>>16;c[F>>2]=(Je(16384-(c[C>>2]|0)&65535)|0)<<16>>16;w=((c[u>>2]|0)-1<<7&65535)<<16>>16;c[D>>2]=16384+(_(w,((Ke(c[F>>2]|0,c[E>>2]|0)|0)&65535)<<16>>16)|0)>>15;ia=c[K>>2]|0;ja=c[r>>2]|0;c[ja>>2]=ia;ka=c[E>>2]|0;la=c[r>>2]|0;ma=la+4|0;c[ma>>2]=ka;na=c[F>>2]|0;oa=c[r>>2]|0;pa=oa+8|0;c[pa>>2]=na;qa=c[D>>2]|0;ra=c[r>>2]|0;sa=ra+12|0;c[sa>>2]=qa;ta=c[C>>2]|0;ua=c[r>>2]|0;va=ua+16|0;c[va>>2]=ta;wa=c[G>>2]|0;xa=c[r>>2]|0;ya=xa+20|0;c[ya>>2]=wa;i=p;return}}function Ee(a,b,d,e){a=a|0;b=b|0;d=+d;e=e|0;var f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;f=i;i=i+64|0;h=f+52|0;j=f+44|0;k=f+24|0;l=f+20|0;m=f+12|0;n=f+40|0;o=f+48|0;p=f+56|0;q=f+28|0;r=f+8|0;s=f+4|0;t=f+32|0;u=f;v=f+16|0;w=f+36|0;c[h>>2]=a;c[j>>2]=b;g[k>>2]=d;c[l>>2]=e;g[n>>2]=0.0;g[o>>2]=0.0;Fe(c[j>>2]|0,c[h>>2]|0,c[j>>2]|0,c[l>>2]|0,n,o);g[n>>2]=+g[k>>2]*+g[n>>2];g[r>>2]=+g[k>>2];g[p>>2]=+g[r>>2]*+g[r>>2]+ +g[o>>2]-+g[n>>2]*2.0;g[q>>2]=+g[r>>2]*+g[r>>2]+ +g[o>>2]+ +g[n>>2]*2.0;if(+g[q>>2]<6.000000284984708e-04|+g[p>>2]<6.000000284984708e-04){df(c[j>>2]|0,c[h>>2]|0,(c[l>>2]<<2)+0|0)|0;i=f;return}g[s>>2]=+g[p>>2];g[t>>2]=1.0/+O(+(+g[s>>2]));g[s>>2]=+g[q>>2];g[u>>2]=1.0/+O(+(+g[s>>2]));c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[l>>2]|0))break;g[w>>2]=+g[k>>2]*+g[(c[h>>2]|0)+(c[m>>2]<<2)>>2];g[v>>2]=+g[(c[j>>2]|0)+(c[m>>2]<<2)>>2];g[(c[h>>2]|0)+(c[m>>2]<<2)>>2]=+g[t>>2]*(+g[w>>2]-+g[v>>2]);g[(c[j>>2]|0)+(c[m>>2]<<2)>>2]=+g[u>>2]*(+g[w>>2]+ +g[v>>2]);c[m>>2]=(c[m>>2]|0)+1}i=f;return}function Fe(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0.0;j=i;i=i+48|0;k=j+28|0;l=j+16|0;m=j+4|0;n=j+8|0;o=j+32|0;p=j;q=j+12|0;r=j+24|0;s=j+20|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=d;c[n>>2]=e;c[o>>2]=f;c[p>>2]=h;g[r>>2]=0.0;g[s>>2]=0.0;c[q>>2]=0;while(1){t=+g[r>>2];if((c[q>>2]|0)>=(c[n>>2]|0))break;g[r>>2]=t+ +g[(c[k>>2]|0)+(c[q>>2]<<2)>>2]*+g[(c[l>>2]|0)+(c[q>>2]<<2)>>2];g[s>>2]=+g[s>>2]+ +g[(c[k>>2]|0)+(c[q>>2]<<2)>>2]*+g[(c[m>>2]|0)+(c[q>>2]<<2)>>2];c[q>>2]=(c[q>>2]|0)+1}g[c[o>>2]>>2]=t;g[c[p>>2]>>2]=+g[s>>2];i=j;return}function Ge(a,d,e,f,g){a=a|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;h=i;i=i+32|0;j=h+4|0;k=h+16|0;l=h+8|0;m=h+20|0;n=h+28|0;o=h;p=h+12|0;q=h+24|0;c[j>>2]=a;c[k>>2]=d;c[l>>2]=e;c[m>>2]=f;c[n>>2]=g;c[q>>2]=(c[j>>2]<<1)-1;if((c[n>>2]|0)!=0&(c[j>>2]|0)==2)c[q>>2]=(c[q>>2]|0)+-1;j=(c[k>>2]|0)+(_(c[q>>2]|0,c[l>>2]|0)|0)|0;c[p>>2]=Sc(j,c[q>>2]|0)|0;if(((c[k>>2]|0)-(c[m>>2]|0)-32|0)<(c[p>>2]|0))r=(c[k>>2]|0)-(c[m>>2]|0)-32|0;else r=c[p>>2]|0;c[p>>2]=r;c[p>>2]=64<(c[p>>2]|0)?64:c[p>>2]|0;if((c[p>>2]|0)<4){c[o>>2]=1;s=c[o>>2]|0;i=h;return s|0}else{c[o>>2]=b[25080+((c[p>>2]&7)<<1)>>1]>>14-(c[p>>2]>>3);c[o>>2]=(c[o>>2]|0)+1>>1<<1;s=c[o>>2]|0;i=h;return s|0}return 0}function He(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;j=i;i=i+64|0;k=j+52|0;l=j+44|0;m=j+24|0;n=j+20|0;o=j+12|0;p=j+40|0;q=j+48|0;r=j+56|0;s=j+28|0;t=j+8|0;u=j+4|0;v=j+32|0;w=j;x=j+16|0;y=j+36|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=d;c[n>>2]=e;c[o>>2]=f;c[p>>2]=h;c[q>>2]=c[o>>2];g[u>>2]=+g[(c[n>>2]|0)+(c[q>>2]<<2)>>2];g[v>>2]=+g[(c[n>>2]|0)+((c[q>>2]|0)+(c[(c[k>>2]|0)+8>>2]|0)<<2)>>2];g[w>>2]=+O(+(+g[u>>2]*+g[u>>2]+1.0000000036274937e-15+ +g[v>>2]*+g[v>>2]))+1.0000000036274937e-15;g[s>>2]=+g[u>>2]/+g[w>>2];g[t>>2]=+g[v>>2]/+g[w>>2];c[r>>2]=0;while(1){if((c[r>>2]|0)>=(c[p>>2]|0))break;g[y>>2]=+g[(c[l>>2]|0)+(c[r>>2]<<2)>>2];g[x>>2]=+g[(c[m>>2]|0)+(c[r>>2]<<2)>>2];g[(c[l>>2]|0)+(c[r>>2]<<2)>>2]=+g[s>>2]*+g[y>>2]+ +g[t>>2]*+g[x>>2];c[r>>2]=(c[r>>2]|0)+1}i=j;return}function Ie(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,h=0,j=0,k=0,l=0,m=0;e=i;i=i+32|0;f=e+20|0;h=e+16|0;j=e+12|0;k=e+8|0;l=e+4|0;m=e;c[f>>2]=a;c[h>>2]=b;c[j>>2]=d;c[k>>2]=0;while(1){if((c[k>>2]|0)>=(c[j>>2]|0))break;g[m>>2]=+g[(c[f>>2]|0)+(c[k>>2]<<2)>>2]*.7071067690849304;g[l>>2]=+g[(c[h>>2]|0)+(c[k>>2]<<2)>>2]*.7071067690849304;g[(c[f>>2]|0)+(c[k>>2]<<2)>>2]=+g[m>>2]+ +g[l>>2];g[(c[h>>2]|0)+(c[k>>2]<<2)>>2]=+g[l>>2]-+g[m>>2];c[k>>2]=(c[k>>2]|0)+1}i=e;return}function Je(a){a=a|0;var d=0,e=0,f=0,g=0;d=i;i=i+16|0;e=d+6|0;f=d;g=d+4|0;b[e>>1]=a;c[f>>2]=4096+(_(b[e>>1]|0,b[e>>1]|0)|0)>>13;b[g>>1]=c[f>>2];b[g>>1]=32767-(b[g>>1]|0)+(16384+(_(b[g>>1]|0,((16384+(_(b[g>>1]|0,(8277+(16384+(_(-626,b[g>>1]|0)|0)>>15)&65535)<<16>>16)|0)>>15)+-7651&65535)<<16>>16)|0)>>15);i=d;return 1+(b[g>>1]|0)&65535|0}function Ke(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[e>>2]=a;c[f>>2]=b;c[g>>2]=32-(aa(c[f>>2]|0)|0);c[h>>2]=32-(aa(c[e>>2]|0)|0);c[f>>2]=c[f>>2]<<15-(c[g>>2]|0);c[e>>2]=c[e>>2]<<15-(c[h>>2]|0);b=((c[h>>2]|0)-(c[g>>2]|0)<<11)+(16384+(_((c[e>>2]&65535)<<16>>16,((16384+(_((c[e>>2]&65535)<<16>>16,-2597)|0)>>15)+7932&65535)<<16>>16)|0)>>15)|0;e=b-(16384+(_((c[f>>2]&65535)<<16>>16,((16384+(_((c[f>>2]&65535)<<16>>16,-2597)|0)>>15)+7932&65535)<<16>>16)|0)>>15)|0;i=d;return e|0}function Le(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;f=i;i=i+48|0;h=f+28|0;j=f+16|0;k=f+4|0;l=f+8|0;m=f+32|0;n=f;o=f+12|0;p=f+24|0;q=f+20|0;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;c[o>>2]=_(c[j>>2]|0,c[k>>2]|0)|0;e=c[o>>2]|0;c[p>>2]=ua()|0;d=i;i=i+((1*(e<<2)|0)+15&-16)|0;if(c[l>>2]|0){c[q>>2]=25128+(c[k>>2]<<2)+-8;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[k>>2]|0))break;c[n>>2]=0;while(1){if((c[n>>2]|0)>=(c[j>>2]|0))break;l=_(c[n>>2]|0,c[k>>2]|0)|0;e=_(c[(c[q>>2]|0)+(c[m>>2]<<2)>>2]|0,c[j>>2]|0)|0;g[d+(e+(c[n>>2]|0)<<2)>>2]=+g[(c[h>>2]|0)+(l+(c[m>>2]|0)<<2)>>2];c[n>>2]=(c[n>>2]|0)+1}c[m>>2]=(c[m>>2]|0)+1}r=c[h>>2]|0;s=c[o>>2]|0;t=s<<2;u=c[h>>2]|0;v=u;w=d;x=v-w|0;y=(x|0)/4|0;z=0;A=t+z|0;df(r|0,d|0,A|0)|0;B=c[p>>2]|0;ka(B|0);i=f;return}else{c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[k>>2]|0))break;c[n>>2]=0;while(1){if((c[n>>2]|0)>=(c[j>>2]|0))break;q=_(c[n>>2]|0,c[k>>2]|0)|0;l=_(c[m>>2]|0,c[j>>2]|0)|0;g[d+(l+(c[n>>2]|0)<<2)>>2]=+g[(c[h>>2]|0)+(q+(c[m>>2]|0)<<2)>>2];c[n>>2]=(c[n>>2]|0)+1}c[m>>2]=(c[m>>2]|0)+1}r=c[h>>2]|0;s=c[o>>2]|0;t=s<<2;u=c[h>>2]|0;v=u;w=d;x=v-w|0;y=(x|0)/4|0;z=0;A=t+z|0;df(r|0,d|0,A|0)|0;B=c[p>>2]|0;ka(B|0);i=f;return}}function Me(a,e,f,h,j,k,l,m,n){a=a|0;e=e|0;f=f|0;h=h|0;j=j|0;k=k|0;l=l|0;m=+m;n=n|0;var o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0;o=i;i=i+176|0;p=o+160|0;q=o+128|0;r=o+4|0;s=o+56|0;t=o+68|0;u=o+152|0;v=o+20|0;w=o+24|0;x=o+28|0;y=o+32|0;z=o+36|0;A=o+40|0;B=o+44|0;C=o+48|0;D=o+132|0;E=o+140|0;F=o+148|0;G=o+156|0;H=o+164|0;I=o+72|0;J=o+76|0;K=o+80|0;L=o+84|0;M=o+88|0;N=o+92|0;O=o+96|0;P=o+100|0;Q=o+12|0;R=o;S=o+8|0;T=o+104|0;U=o+52|0;V=o+136|0;W=o+60|0;X=o+144|0;Y=o+16|0;Z=o+64|0;c[p>>2]=a;c[q>>2]=e;c[r>>2]=f;c[s>>2]=h;c[t>>2]=j;c[u>>2]=k;c[v>>2]=l;g[w>>2]=m;c[x>>2]=n;c[B>>2]=0;c[C>>2]=0;c[D>>2]=c[t>>2];g[E>>2]=0.0;g[F>>2]=0.0;c[G>>2]=0;c[H>>2]=((c[c[p>>2]>>2]|0)!=0^1)&1;c[I>>2]=0;c[J>>2]=c[c[p>>2]>>2];c[K>>2]=c[(c[p>>2]|0)+4>>2];c[L>>2]=c[(c[p>>2]|0)+8>>2];c[M>>2]=c[(c[p>>2]|0)+16>>2];c[N>>2]=c[(c[p>>2]|0)+24>>2];n=_((c[v>>2]|0)+1|0,c[(c[K>>2]|0)+8>>2]|0)|0;c[y>>2]=(c[(c[K>>2]|0)+92+8>>2]|0)+(b[(c[(c[K>>2]|0)+92+4>>2]|0)+(n+(c[L>>2]|0)<<1)>>1]|0);if((c[v>>2]|0)!=-1?((c[r>>2]|0)>2?(c[s>>2]|0)>((d[(c[y>>2]|0)+(d[c[y>>2]>>0]|0)>>0]|0)+12|0):0):0){c[U>>2]=0;c[r>>2]=c[r>>2]>>1;c[I>>2]=(c[q>>2]|0)+(c[r>>2]<<2);c[v>>2]=(c[v>>2]|0)-1;if((c[t>>2]|0)==1)c[x>>2]=c[x>>2]&1|c[x>>2]<<1;c[t>>2]=(c[t>>2]|0)+1>>1;De(c[p>>2]|0,T,c[q>>2]|0,c[I>>2]|0,c[r>>2]|0,s,c[t>>2]|0,c[D>>2]|0,c[v>>2]|0,0,x);c[B>>2]=c[T+4>>2];c[C>>2]=c[T+8>>2];c[Q>>2]=c[T+12>>2];c[R>>2]=c[T+16>>2];c[S>>2]=c[T+20>>2];g[E>>2]=+(c[B>>2]|0)*.000030517578125;g[F>>2]=+(c[C>>2]|0)*.000030517578125;do if((c[D>>2]|0)>1?(c[R>>2]&16383|0)!=0:0){C=c[Q>>2]|0;if((c[R>>2]|0)>8192){c[Q>>2]=(c[Q>>2]|0)-(C>>4-(c[v>>2]|0));break}if(0<(C+(c[r>>2]<<3>>5-(c[v>>2]|0))|0))$=0;else $=(c[Q>>2]|0)+(c[r>>2]<<3>>5-(c[v>>2]|0))|0;c[Q>>2]=$}while(0);$=c[s>>2]|0;if((c[s>>2]|0)<(((c[s>>2]|0)-(c[Q>>2]|0)|0)/2|0|0))aa=$;else aa=($-(c[Q>>2]|0)|0)/2|0;if(0<=(aa|0)){aa=c[s>>2]|0;if((c[s>>2]|0)<(((c[s>>2]|0)-(c[Q>>2]|0)|0)/2|0|0))ba=aa;else ba=(aa-(c[Q>>2]|0)|0)/2|0}else ba=0;c[O>>2]=ba;c[P>>2]=(c[s>>2]|0)-(c[O>>2]|0);ba=(c[p>>2]|0)+28|0;c[ba>>2]=(c[ba>>2]|0)-(c[S>>2]|0);if(c[u>>2]|0)c[U>>2]=(c[u>>2]|0)+(c[r>>2]<<2);c[V>>2]=c[(c[p>>2]|0)+28>>2];S=c[p>>2]|0;if((c[O>>2]|0)>=(c[P>>2]|0)){c[G>>2]=Me(S,c[q>>2]|0,c[r>>2]|0,c[O>>2]|0,c[t>>2]|0,c[u>>2]|0,c[v>>2]|0,+g[w>>2]*+g[E>>2],c[x>>2]|0)|0;c[V>>2]=(c[O>>2]|0)-((c[V>>2]|0)-(c[(c[p>>2]|0)+28>>2]|0));if((c[V>>2]|0)>24&(c[R>>2]|0)!=0)c[P>>2]=(c[P>>2]|0)+((c[V>>2]|0)-24);ba=Me(c[p>>2]|0,c[I>>2]|0,c[r>>2]|0,c[P>>2]|0,c[t>>2]|0,c[U>>2]|0,c[v>>2]|0,+g[w>>2]*+g[F>>2],c[x>>2]>>c[t>>2])|0;c[G>>2]=c[G>>2]|ba<<(c[D>>2]>>1);ca=c[G>>2]|0;i=o;return ca|0}else{ba=Me(S,c[I>>2]|0,c[r>>2]|0,c[P>>2]|0,c[t>>2]|0,c[U>>2]|0,c[v>>2]|0,+g[w>>2]*+g[F>>2],c[x>>2]>>c[t>>2])|0;c[G>>2]=ba<<(c[D>>2]>>1);c[V>>2]=(c[P>>2]|0)-((c[V>>2]|0)-(c[(c[p>>2]|0)+28>>2]|0));if((c[V>>2]|0)>24&(c[R>>2]|0)!=16384)c[O>>2]=(c[O>>2]|0)+((c[V>>2]|0)-24);V=Me(c[p>>2]|0,c[q>>2]|0,c[r>>2]|0,c[O>>2]|0,c[t>>2]|0,c[u>>2]|0,c[v>>2]|0,+g[w>>2]*+g[E>>2],c[x>>2]|0)|0;c[G>>2]=c[G>>2]|V;ca=c[G>>2]|0;i=o;return ca|0}}c[z>>2]=Oe(c[K>>2]|0,c[L>>2]|0,c[v>>2]|0,c[s>>2]|0)|0;c[A>>2]=Pe(c[K>>2]|0,c[L>>2]|0,c[v>>2]|0,c[z>>2]|0)|0;s=(c[p>>2]|0)+28|0;c[s>>2]=(c[s>>2]|0)-(c[A>>2]|0);while(1){if(!((c[(c[p>>2]|0)+28>>2]|0)<0?(c[z>>2]|0)>0:0))break;s=(c[p>>2]|0)+28|0;c[s>>2]=(c[s>>2]|0)+(c[A>>2]|0);c[z>>2]=(c[z>>2]|0)+-1;c[A>>2]=Pe(c[K>>2]|0,c[L>>2]|0,c[v>>2]|0,c[z>>2]|0)|0;s=(c[p>>2]|0)+28|0;c[s>>2]=(c[s>>2]|0)-(c[A>>2]|0)}if(c[z>>2]|0){c[W>>2]=Qe(c[z>>2]|0)|0;z=c[q>>2]|0;A=c[r>>2]|0;v=c[W>>2]|0;W=c[M>>2]|0;M=c[t>>2]|0;L=c[N>>2]|0;if(c[J>>2]|0){c[G>>2]=Gb(z,A,v,W,M,L)|0;ca=c[G>>2]|0;i=o;return ca|0}else{c[G>>2]=Hb(z,A,v,W,M,L,+g[w>>2])|0;ca=c[G>>2]|0;i=o;return ca|0}}if(!(c[H>>2]|0)){ca=c[G>>2]|0;i=o;return ca|0}c[Y>>2]=(1<<c[t>>2])-1;c[x>>2]=c[x>>2]&c[Y>>2];if(!(c[x>>2]|0)){bf(c[q>>2]|0,0,c[r>>2]<<2|0)|0;ca=c[G>>2]|0;i=o;return ca|0}t=(c[u>>2]|0)==0;c[X>>2]=0;if(t){while(1){if((c[X>>2]|0)>=(c[r>>2]|0))break;t=Ra(c[(c[p>>2]|0)+36>>2]|0)|0;c[(c[p>>2]|0)+36>>2]=t;g[(c[q>>2]|0)+(c[X>>2]<<2)>>2]=+(c[(c[p>>2]|0)+36>>2]>>20|0);c[X>>2]=(c[X>>2]|0)+1}c[G>>2]=c[Y>>2]}else{while(1){if((c[X>>2]|0)>=(c[r>>2]|0))break;Y=Ra(c[(c[p>>2]|0)+36>>2]|0)|0;c[(c[p>>2]|0)+36>>2]=Y;g[Z>>2]=.00390625;m=+g[Z>>2];g[Z>>2]=(c[(c[p>>2]|0)+36>>2]&32768|0)!=0?m:-m;g[(c[q>>2]|0)+(c[X>>2]<<2)>>2]=+g[(c[u>>2]|0)+(c[X>>2]<<2)>>2]+ +g[Z>>2];c[X>>2]=(c[X>>2]|0)+1}c[G>>2]=c[x>>2]}Ib(c[q>>2]|0,c[r>>2]|0,+g[w>>2]);ca=c[G>>2]|0;i=o;return ca|0}function Ne(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0;f=i;i=i+48|0;h=f+28|0;j=f+16|0;k=f+4|0;l=f+8|0;m=f+32|0;n=f;o=f+12|0;p=f+24|0;q=f+20|0;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;c[o>>2]=_(c[j>>2]|0,c[k>>2]|0)|0;e=c[o>>2]|0;c[p>>2]=ua()|0;d=i;i=i+((1*(e<<2)|0)+15&-16)|0;if(c[l>>2]|0){c[q>>2]=25128+(c[k>>2]<<2)+-8;c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[k>>2]|0))break;c[n>>2]=0;while(1){r=c[m>>2]|0;if((c[n>>2]|0)>=(c[j>>2]|0))break;l=_(c[(c[q>>2]|0)+(r<<2)>>2]|0,c[j>>2]|0)|0;e=_(c[n>>2]|0,c[k>>2]|0)|0;g[d+(e+(c[m>>2]|0)<<2)>>2]=+g[(c[h>>2]|0)+(l+(c[n>>2]|0)<<2)>>2];c[n>>2]=(c[n>>2]|0)+1}c[m>>2]=r+1}s=c[h>>2]|0;t=c[o>>2]|0;u=t<<2;v=c[h>>2]|0;w=v;x=d;y=w-x|0;z=(y|0)/4|0;A=0;B=u+A|0;df(s|0,d|0,B|0)|0;C=c[p>>2]|0;ka(C|0);i=f;return}else{c[m>>2]=0;while(1){if((c[m>>2]|0)>=(c[k>>2]|0))break;c[n>>2]=0;while(1){D=c[m>>2]|0;if((c[n>>2]|0)>=(c[j>>2]|0))break;r=_(D,c[j>>2]|0)|0;q=_(c[n>>2]|0,c[k>>2]|0)|0;g[d+(q+(c[m>>2]|0)<<2)>>2]=+g[(c[h>>2]|0)+(r+(c[n>>2]|0)<<2)>>2];c[n>>2]=(c[n>>2]|0)+1}c[m>>2]=D+1}s=c[h>>2]|0;t=c[o>>2]|0;u=t<<2;v=c[h>>2]|0;w=v;x=d;y=w-x|0;z=(y|0)/4|0;A=0;B=u+A|0;df(s|0,d|0,B|0)|0;C=c[p>>2]|0;ka(C|0);i=f;return}}function Oe(a,e,f,g){a=a|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;h=i;i=i+48|0;j=h;k=h+16|0;l=h+28|0;m=h+4|0;n=h+32|0;o=h+36|0;p=h+12|0;q=h+24|0;r=h+20|0;s=h+8|0;c[k>>2]=a;c[l>>2]=e;c[m>>2]=f;c[n>>2]=g;c[m>>2]=(c[m>>2]|0)+1;g=_(c[m>>2]|0,c[(c[k>>2]|0)+8>>2]|0)|0;c[r>>2]=(c[(c[k>>2]|0)+92+8>>2]|0)+(b[(c[(c[k>>2]|0)+92+4>>2]|0)+(g+(c[l>>2]|0)<<1)>>1]|0);c[p>>2]=0;c[q>>2]=d[c[r>>2]>>0];c[n>>2]=(c[n>>2]|0)+-1;c[o>>2]=0;while(1){if((c[o>>2]|0)>=6)break;c[s>>2]=(c[p>>2]|0)+(c[q>>2]|0)+1>>1;l=c[s>>2]|0;if((d[(c[r>>2]|0)+(c[s>>2]|0)>>0]|0)>=(c[n>>2]|0))c[q>>2]=l;else c[p>>2]=l;c[o>>2]=(c[o>>2]|0)+1}if(!(c[p>>2]|0))t=-1;else t=d[(c[r>>2]|0)+(c[p>>2]|0)>>0]|0;if(((c[n>>2]|0)-t|0)<=((d[(c[r>>2]|0)+(c[q>>2]|0)>>0]|0)-(c[n>>2]|0)|0)){c[j>>2]=c[p>>2];u=c[j>>2]|0;i=h;return u|0}else{c[j>>2]=c[q>>2];u=c[j>>2]|0;i=h;return u|0}return 0}function Pe(a,e,f,g){a=a|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0;h=i;i=i+32|0;j=h+16|0;k=h+12|0;l=h+8|0;m=h+4|0;n=h;c[j>>2]=a;c[k>>2]=e;c[l>>2]=f;c[m>>2]=g;c[l>>2]=(c[l>>2]|0)+1;g=_(c[l>>2]|0,c[(c[j>>2]|0)+8>>2]|0)|0;c[n>>2]=(c[(c[j>>2]|0)+92+8>>2]|0)+(b[(c[(c[j>>2]|0)+92+4>>2]|0)+(g+(c[k>>2]|0)<<1)>>1]|0);if(!(c[m>>2]|0)){o=0;i=h;return o|0}o=(d[(c[n>>2]|0)+(c[m>>2]|0)>>0]|0)+1|0;i=h;return o|0}function Qe(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b;c[d>>2]=a;a=c[d>>2]|0;if((c[d>>2]|0)<8){e=a;i=b;return e|0}e=8+(a&7)<<(c[d>>2]>>3)-1;i=b;return e|0}function Re(){return}function Se(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,h=0,j=0.0;d=i;i=i+48|0;e=d+32|0;f=d;Ve(f,a,b);b=c[6312]|0;if((b|0)==1){c[6312]=2;h=1;i=d;return h|0}else if(!b){b=Xe(f,25264,25272,25280,25288,25296)|0;c[6314]=b;if(!b){h=0;i=d;return h|0}c[6312]=1;j=+g[6322];if(j!=0.0){c[e>>2]=~~j;Qc(b,4034,e)|0}c[6312]=1;h=1;i=d;return h|0}else{pa(c[6318]|0,48e3);h=1;i=d;return h|0}return 0}function Te(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;d=i;i=i+16|0;e=d;f=Ze((c[6318]|0)*23040|0)|0;g=Pc(c[6314]|0,a,b,f,5760,0)|0;if((g|0)<0){c[e>>2]=g;va(25304,e|0)|0;h=0;_e(f);i=d;return h|0}e=c[6320]|0;if((g|0)>(e|0)){b=g-e|0;a=c[6318]|0;j=Ze(_(b<<2,a)|0)|0;k=Ze(a<<2)|0;if((a|0)>0){l=0;do{m=_(l,b)|0;c[k+(l<<2)>>2]=j+(m<<2);n=e;do{c[j+(m+(n-e)<<2)>>2]=c[f+((_(a,n)|0)+l<<2)>>2];n=n+1|0}while((n|0)!=(g|0));l=l+1|0}while((l|0)<(a|0))}wa(k|0,a|0,b|0);_e(k);_e(j);o=c[6320]|0;p=e}else{o=e;p=g}c[6320]=o-p;h=1;_e(f);i=d;return h|0}function Ue(){return}function Ve(a,b,d){a=a|0;b=b|0;d=d|0;c[a>>2]=b;c[a+4>>2]=d;d=a+8|0;c[d>>2]=0;c[d+4>>2]=0;c[d+8>>2]=0;c[d+12>>2]=0;c[d+16>>2]=0;c[d+20>>2]=0;return}function We(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;g=i;i=i+16|0;h=g;a[h+8>>0]=0;if((e|0)<19){i=g;return 0}j=b;k=j;l=j+4|0;j=d[l>>0]|d[l+1>>0]<<8|d[l+2>>0]<<16|d[l+3>>0]<<24;l=h;c[l>>2]=d[k>>0]|d[k+1>>0]<<8|d[k+2>>0]<<16|d[k+3>>0]<<24;c[l+4>>2]=j;if(Ye(h,25336,8)|0){i=g;return 0}h=e+-1|0;if((e|0)<9){i=g;return 0}j=d[b+8>>0]|0;c[f>>2]=j;if((e|0)<10|(j&240|0)!=0){i=g;return 0}l=a[b+9>>0]|0;k=f+4|0;c[k>>2]=l&255;if(!(l<<24>>24)){i=g;return 0}m=e+-2|0;if((m|0)<=9){i=g;return 0}c[f+8>>2]=(d[b+11>>0]|0)<<8|(d[b+10>>0]|0);n=f+12|0;if((e+-4|0)<12){i=g;return 0}o=d[b+12>>0]|0;c[n>>2]=o;p=(d[b+13>>0]|0)<<8|o;c[n>>2]=p;o=(d[b+14>>0]|0)<<16|p;c[n>>2]=o;c[n>>2]=(d[b+15>>0]|0)<<24|o;if((m|0)<16){i=g;return 0}c[f+16>>2]=((d[b+17>>0]|0)<<8|(d[b+16>>0]|0))<<16>>16;if((e|0)<19){i=g;return 0}m=a[b+18>>0]|0;c[f+20>>2]=m&255;if(!(m<<24>>24)){if((l&255)>2){i=g;return 0}c[f+24>>2]=1;c[f+28>>2]=(l&255)>1&1;a[f+32>>0]=0;a[f+33>>0]=1;q=j;r=19;s=q>>>0>1;t=(r|0)==(e|0);u=t|s;v=u&1;i=g;return v|0}if((h|0)<=18){i=g;return 0}j=a[b+19>>0]|0;if(!(j<<24>>24)){i=g;return 0}l=j&255;m=f+24|0;c[m>>2]=l;if((h|0)<=19){i=g;return 0}o=a[b+20>>0]|0;n=o&255;if((o&255)>(j&255)|(n+l|0)>255){i=g;return 0}l=f+28|0;c[l>>2]=n;n=21;j=0;while(1){if((n|0)>(h|0)){w=23;break}o=a[b+n>>0]|0;a[f+32+j>>0]=o;p=n+1|0;j=j+1|0;if(!(o<<24>>24==-1?1:(o&255|0)<=((c[l>>2]|0)+(c[m>>2]|0)|0))){w=23;break}if((j|0)>=(c[k>>2]|0)){x=p;w=21;break}else n=p}if((w|0)==21){q=c[f>>2]|0;r=x;s=q>>>0>1;t=(r|0)==(e|0);u=t|s;v=u&1;i=g;return v|0}else if((w|0)==23){i=g;return 0}return 0}function Xe(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;var j=0,k=0,l=0,m=0,n=0;j=i;i=i+304|0;k=j;l=j+296|0;m=j+8|0;if(!(We(c[a>>2]|0,c[a+4>>2]|0,m)|0)){n=0;i=j;return n|0}c[b>>2]=c[m+20>>2];b=c[m+4>>2]|0;c[d>>2]=b;c[e>>2]=c[m+8>>2];e=m+24|0;d=Oc(48e3,b,c[e>>2]|0,c[m+28>>2]|0,m+32|0,l)|0;if((d|0)==0|(c[l>>2]|0)!=0){n=0;i=j;return n|0}c[h>>2]=c[e>>2];e=m+16|0;m=c[e>>2]|0;do if(m){c[k>>2]=m;h=Qc(d,4034,k)|0;c[l>>2]=h;if(!h)break;else if((h|0)==-5){g[f>>2]=+P(10.0,+(+(c[e>>2]|0)/5120.0));break}else{n=0;i=j;return n|0}}while(0);n=d;i=j;return n|0}function Ye(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;if(!d){e=0;return e|0}else{f=d;g=b;h=c}while(1){c=a[g>>0]|0;b=a[h>>0]|0;if(c<<24>>24!=b<<24>>24){i=c;j=b;break}f=f+-1|0;if(!f){e=0;k=5;break}else{g=g+1|0;h=h+1|0}}if((k|0)==5)return e|0;e=(i&255)-(j&255)|0;return e|0}function Ze(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,pa=0,qa=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,Aa=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0;do if(a>>>0<245){b=a>>>0<11?16:a+11&-8;d=b>>>3;e=c[6338]|0;f=e>>>d;if(f&3){g=(f&1^1)+d|0;h=g<<1;i=25392+(h<<2)|0;j=25392+(h+2<<2)|0;h=c[j>>2]|0;k=h+8|0;l=c[k>>2]|0;do if((i|0)!=(l|0)){if(l>>>0<(c[6342]|0)>>>0)za();m=l+12|0;if((c[m>>2]|0)==(h|0)){c[m>>2]=i;c[j>>2]=l;break}else za()}else c[6338]=e&~(1<<g);while(0);l=g<<3;c[h+4>>2]=l|3;j=h+(l|4)|0;c[j>>2]=c[j>>2]|1;n=k;return n|0}j=c[6340]|0;if(b>>>0>j>>>0){if(f){l=2<<d;i=f<<d&(l|0-l);l=(i&0-i)+-1|0;i=l>>>12&16;m=l>>>i;l=m>>>5&8;o=m>>>l;m=o>>>2&4;p=o>>>m;o=p>>>1&2;q=p>>>o;p=q>>>1&1;r=(l|i|m|o|p)+(q>>>p)|0;p=r<<1;q=25392+(p<<2)|0;o=25392+(p+2<<2)|0;p=c[o>>2]|0;m=p+8|0;i=c[m>>2]|0;do if((q|0)!=(i|0)){if(i>>>0<(c[6342]|0)>>>0)za();l=i+12|0;if((c[l>>2]|0)==(p|0)){c[l>>2]=q;c[o>>2]=i;s=c[6340]|0;break}else za()}else{c[6338]=e&~(1<<r);s=j}while(0);j=r<<3;e=j-b|0;c[p+4>>2]=b|3;i=p+b|0;c[p+(b|4)>>2]=e|1;c[p+j>>2]=e;if(s){j=c[6343]|0;o=s>>>3;q=o<<1;d=25392+(q<<2)|0;f=c[6338]|0;k=1<<o;if(f&k){o=25392+(q+2<<2)|0;h=c[o>>2]|0;if(h>>>0<(c[6342]|0)>>>0)za();else{t=o;u=h}}else{c[6338]=f|k;t=25392+(q+2<<2)|0;u=d}c[t>>2]=j;c[u+12>>2]=j;c[j+8>>2]=u;c[j+12>>2]=d}c[6340]=e;c[6343]=i;n=m;return n|0}i=c[6339]|0;if(i){e=(i&0-i)+-1|0;i=e>>>12&16;d=e>>>i;e=d>>>5&8;j=d>>>e;d=j>>>2&4;q=j>>>d;j=q>>>1&2;k=q>>>j;q=k>>>1&1;f=c[25656+((e|i|d|j|q)+(k>>>q)<<2)>>2]|0;q=(c[f+4>>2]&-8)-b|0;k=f;j=f;while(1){f=c[k+16>>2]|0;if(!f){d=c[k+20>>2]|0;if(!d){v=q;w=j;break}else x=d}else x=f;f=(c[x+4>>2]&-8)-b|0;d=f>>>0<q>>>0;q=d?f:q;k=x;j=d?x:j}j=c[6342]|0;if(w>>>0<j>>>0)za();k=w+b|0;if(w>>>0>=k>>>0)za();q=c[w+24>>2]|0;m=c[w+12>>2]|0;do if((m|0)==(w|0)){p=w+20|0;r=c[p>>2]|0;if(!r){d=w+16|0;f=c[d>>2]|0;if(!f){y=0;break}else{z=f;A=d}}else{z=r;A=p}while(1){p=z+20|0;r=c[p>>2]|0;if(r){z=r;A=p;continue}p=z+16|0;r=c[p>>2]|0;if(!r){B=z;C=A;break}else{z=r;A=p}}if(C>>>0<j>>>0)za();else{c[C>>2]=0;y=B;break}}else{p=c[w+8>>2]|0;if(p>>>0<j>>>0)za();r=p+12|0;if((c[r>>2]|0)!=(w|0))za();d=m+8|0;if((c[d>>2]|0)==(w|0)){c[r>>2]=m;c[d>>2]=p;y=m;break}else za()}while(0);do if(q){m=c[w+28>>2]|0;j=25656+(m<<2)|0;if((w|0)==(c[j>>2]|0)){c[j>>2]=y;if(!y){c[6339]=c[6339]&~(1<<m);break}}else{if(q>>>0<(c[6342]|0)>>>0)za();m=q+16|0;if((c[m>>2]|0)==(w|0))c[m>>2]=y;else c[q+20>>2]=y;if(!y)break}m=c[6342]|0;if(y>>>0<m>>>0)za();c[y+24>>2]=q;j=c[w+16>>2]|0;do if(j)if(j>>>0<m>>>0)za();else{c[y+16>>2]=j;c[j+24>>2]=y;break}while(0);j=c[w+20>>2]|0;if(j)if(j>>>0<(c[6342]|0)>>>0)za();else{c[y+20>>2]=j;c[j+24>>2]=y;break}}while(0);if(v>>>0<16){q=v+b|0;c[w+4>>2]=q|3;j=w+(q+4)|0;c[j>>2]=c[j>>2]|1}else{c[w+4>>2]=b|3;c[w+(b|4)>>2]=v|1;c[w+(v+b)>>2]=v;j=c[6340]|0;if(j){q=c[6343]|0;m=j>>>3;j=m<<1;p=25392+(j<<2)|0;d=c[6338]|0;r=1<<m;if(d&r){m=25392+(j+2<<2)|0;f=c[m>>2]|0;if(f>>>0<(c[6342]|0)>>>0)za();else{D=m;E=f}}else{c[6338]=d|r;D=25392+(j+2<<2)|0;E=p}c[D>>2]=q;c[E+12>>2]=q;c[q+8>>2]=E;c[q+12>>2]=p}c[6340]=v;c[6343]=k}n=w+8|0;return n|0}else F=b}else F=b}else if(a>>>0<=4294967231){p=a+11|0;q=p&-8;j=c[6339]|0;if(j){r=0-q|0;d=p>>>8;if(d)if(q>>>0>16777215)G=31;else{p=(d+1048320|0)>>>16&8;f=d<<p;d=(f+520192|0)>>>16&4;m=f<<d;f=(m+245760|0)>>>16&2;i=14-(d|p|f)+(m<<f>>>15)|0;G=q>>>(i+7|0)&1|i<<1}else G=0;i=c[25656+(G<<2)>>2]|0;a:do if(!i){H=r;I=0;J=0;K=86}else{f=r;m=0;p=q<<((G|0)==31?0:25-(G>>>1)|0);d=i;e=0;while(1){h=c[d+4>>2]&-8;o=h-q|0;if(o>>>0<f>>>0)if((h|0)==(q|0)){L=o;M=d;N=d;K=90;break a}else{O=o;P=d}else{O=f;P=e}o=c[d+20>>2]|0;d=c[d+16+(p>>>31<<2)>>2]|0;h=(o|0)==0|(o|0)==(d|0)?m:o;if(!d){H=O;I=h;J=P;K=86;break}else{f=O;m=h;p=p<<1;e=P}}}while(0);if((K|0)==86){if((I|0)==0&(J|0)==0){i=2<<G;r=j&(i|0-i);if(!r){F=q;break}i=(r&0-r)+-1|0;r=i>>>12&16;b=i>>>r;i=b>>>5&8;k=b>>>i;b=k>>>2&4;e=k>>>b;k=e>>>1&2;p=e>>>k;e=p>>>1&1;Q=c[25656+((i|r|b|k|e)+(p>>>e)<<2)>>2]|0;R=0}else{Q=I;R=J}if(!Q){S=H;T=R}else{L=H;M=Q;N=R;K=90}}if((K|0)==90)while(1){K=0;e=(c[M+4>>2]&-8)-q|0;p=e>>>0<L>>>0;k=p?e:L;e=p?M:N;p=c[M+16>>2]|0;if(p){L=k;M=p;N=e;K=90;continue}M=c[M+20>>2]|0;if(!M){S=k;T=e;break}else{L=k;N=e;K=90}}if((T|0)!=0?S>>>0<((c[6340]|0)-q|0)>>>0:0){j=c[6342]|0;if(T>>>0<j>>>0)za();e=T+q|0;if(T>>>0>=e>>>0)za();k=c[T+24>>2]|0;p=c[T+12>>2]|0;do if((p|0)==(T|0)){b=T+20|0;r=c[b>>2]|0;if(!r){i=T+16|0;m=c[i>>2]|0;if(!m){U=0;break}else{V=m;W=i}}else{V=r;W=b}while(1){b=V+20|0;r=c[b>>2]|0;if(r){V=r;W=b;continue}b=V+16|0;r=c[b>>2]|0;if(!r){X=V;Y=W;break}else{V=r;W=b}}if(Y>>>0<j>>>0)za();else{c[Y>>2]=0;U=X;break}}else{b=c[T+8>>2]|0;if(b>>>0<j>>>0)za();r=b+12|0;if((c[r>>2]|0)!=(T|0))za();i=p+8|0;if((c[i>>2]|0)==(T|0)){c[r>>2]=p;c[i>>2]=b;U=p;break}else za()}while(0);do if(k){p=c[T+28>>2]|0;j=25656+(p<<2)|0;if((T|0)==(c[j>>2]|0)){c[j>>2]=U;if(!U){c[6339]=c[6339]&~(1<<p);break}}else{if(k>>>0<(c[6342]|0)>>>0)za();p=k+16|0;if((c[p>>2]|0)==(T|0))c[p>>2]=U;else c[k+20>>2]=U;if(!U)break}p=c[6342]|0;if(U>>>0<p>>>0)za();c[U+24>>2]=k;j=c[T+16>>2]|0;do if(j)if(j>>>0<p>>>0)za();else{c[U+16>>2]=j;c[j+24>>2]=U;break}while(0);j=c[T+20>>2]|0;if(j)if(j>>>0<(c[6342]|0)>>>0)za();else{c[U+20>>2]=j;c[j+24>>2]=U;break}}while(0);b:do if(S>>>0>=16){c[T+4>>2]=q|3;c[T+(q|4)>>2]=S|1;c[T+(S+q)>>2]=S;k=S>>>3;if(S>>>0<256){j=k<<1;p=25392+(j<<2)|0;b=c[6338]|0;i=1<<k;if(b&i){k=25392+(j+2<<2)|0;r=c[k>>2]|0;if(r>>>0<(c[6342]|0)>>>0)za();else{Z=k;_=r}}else{c[6338]=b|i;Z=25392+(j+2<<2)|0;_=p}c[Z>>2]=e;c[_+12>>2]=e;c[T+(q+8)>>2]=_;c[T+(q+12)>>2]=p;break}p=S>>>8;if(p)if(S>>>0>16777215)$=31;else{j=(p+1048320|0)>>>16&8;i=p<<j;p=(i+520192|0)>>>16&4;b=i<<p;i=(b+245760|0)>>>16&2;r=14-(p|j|i)+(b<<i>>>15)|0;$=S>>>(r+7|0)&1|r<<1}else $=0;r=25656+($<<2)|0;c[T+(q+28)>>2]=$;c[T+(q+20)>>2]=0;c[T+(q+16)>>2]=0;i=c[6339]|0;b=1<<$;if(!(i&b)){c[6339]=i|b;c[r>>2]=e;c[T+(q+24)>>2]=r;c[T+(q+12)>>2]=e;c[T+(q+8)>>2]=e;break}b=c[r>>2]|0;c:do if((c[b+4>>2]&-8|0)!=(S|0)){r=S<<(($|0)==31?0:25-($>>>1)|0);i=b;while(1){j=i+16+(r>>>31<<2)|0;p=c[j>>2]|0;if(!p){aa=j;ba=i;break}if((c[p+4>>2]&-8|0)==(S|0)){ca=p;break c}else{r=r<<1;i=p}}if(aa>>>0<(c[6342]|0)>>>0)za();else{c[aa>>2]=e;c[T+(q+24)>>2]=ba;c[T+(q+12)>>2]=e;c[T+(q+8)>>2]=e;break b}}else ca=b;while(0);b=ca+8|0;i=c[b>>2]|0;r=c[6342]|0;if(i>>>0>=r>>>0&ca>>>0>=r>>>0){c[i+12>>2]=e;c[b>>2]=e;c[T+(q+8)>>2]=i;c[T+(q+12)>>2]=ca;c[T+(q+24)>>2]=0;break}else za()}else{i=S+q|0;c[T+4>>2]=i|3;b=T+(i+4)|0;c[b>>2]=c[b>>2]|1}while(0);n=T+8|0;return n|0}else F=q}else F=q}else F=-1;while(0);T=c[6340]|0;if(T>>>0>=F>>>0){S=T-F|0;ca=c[6343]|0;if(S>>>0>15){c[6343]=ca+F;c[6340]=S;c[ca+(F+4)>>2]=S|1;c[ca+T>>2]=S;c[ca+4>>2]=F|3}else{c[6340]=0;c[6343]=0;c[ca+4>>2]=T|3;S=ca+(T+4)|0;c[S>>2]=c[S>>2]|1}n=ca+8|0;return n|0}ca=c[6341]|0;if(ca>>>0>F>>>0){S=ca-F|0;c[6341]=S;ca=c[6344]|0;c[6344]=ca+F;c[ca+(F+4)>>2]=S|1;c[ca+4>>2]=F|3;n=ca+8|0;return n|0}do if(!(c[6456]|0)){ca=ra(30)|0;if(!(ca+-1&ca)){c[6458]=ca;c[6457]=ca;c[6459]=-1;c[6460]=-1;c[6461]=0;c[6449]=0;c[6456]=(Ba(0)|0)&-16^1431655768;break}else za()}while(0);ca=F+48|0;S=c[6458]|0;T=F+47|0;ba=S+T|0;aa=0-S|0;S=ba&aa;if(S>>>0<=F>>>0){n=0;return n|0}$=c[6448]|0;if(($|0)!=0?(_=c[6446]|0,Z=_+S|0,Z>>>0<=_>>>0|Z>>>0>$>>>0):0){n=0;return n|0}d:do if(!(c[6449]&4)){$=c[6344]|0;e:do if($){Z=25800;while(1){_=c[Z>>2]|0;if(_>>>0<=$>>>0?(U=Z+4|0,(_+(c[U>>2]|0)|0)>>>0>$>>>0):0){da=Z;ea=U;break}Z=c[Z+8>>2]|0;if(!Z){K=174;break e}}Z=ba-(c[6341]|0)&aa;if(Z>>>0<2147483647){U=oa(Z|0)|0;_=(U|0)==((c[da>>2]|0)+(c[ea>>2]|0)|0);X=_?Z:0;if(_)if((U|0)==(-1|0))fa=X;else{ga=U;ha=X;K=194;break d}else{ia=U;ja=Z;ka=X;K=184}}else fa=0}else K=174;while(0);do if((K|0)==174){$=oa(0)|0;if(($|0)!=(-1|0)){q=$;X=c[6457]|0;Z=X+-1|0;if(!(Z&q))la=S;else la=S-q+(Z+q&0-X)|0;X=c[6446]|0;q=X+la|0;if(la>>>0>F>>>0&la>>>0<2147483647){Z=c[6448]|0;if((Z|0)!=0?q>>>0<=X>>>0|q>>>0>Z>>>0:0){fa=0;break}Z=oa(la|0)|0;q=(Z|0)==($|0);X=q?la:0;if(q){ga=$;ha=X;K=194;break d}else{ia=Z;ja=la;ka=X;K=184}}else fa=0}else fa=0}while(0);f:do if((K|0)==184){X=0-ja|0;do if(ca>>>0>ja>>>0&(ja>>>0<2147483647&(ia|0)!=(-1|0))?(Z=c[6458]|0,$=T-ja+Z&0-Z,$>>>0<2147483647):0)if((oa($|0)|0)==(-1|0)){oa(X|0)|0;fa=ka;break f}else{ma=$+ja|0;break}else ma=ja;while(0);if((ia|0)==(-1|0))fa=ka;else{ga=ia;ha=ma;K=194;break d}}while(0);c[6449]=c[6449]|4;na=fa;K=191}else{na=0;K=191}while(0);if((((K|0)==191?S>>>0<2147483647:0)?(fa=oa(S|0)|0,S=oa(0)|0,fa>>>0<S>>>0&((fa|0)!=(-1|0)&(S|0)!=(-1|0))):0)?(ma=S-fa|0,S=ma>>>0>(F+40|0)>>>0,S):0){ga=fa;ha=S?ma:na;K=194}if((K|0)==194){na=(c[6446]|0)+ha|0;c[6446]=na;if(na>>>0>(c[6447]|0)>>>0)c[6447]=na;na=c[6344]|0;g:do if(na){ma=25800;do{S=c[ma>>2]|0;fa=ma+4|0;ia=c[fa>>2]|0;if((ga|0)==(S+ia|0)){pa=S;qa=fa;sa=ia;ta=ma;K=204;break}ma=c[ma+8>>2]|0}while((ma|0)!=0);if(((K|0)==204?(c[ta+12>>2]&8|0)==0:0)?na>>>0<ga>>>0&na>>>0>=pa>>>0:0){c[qa>>2]=sa+ha;ma=(c[6341]|0)+ha|0;ia=na+8|0;fa=(ia&7|0)==0?0:0-ia&7;ia=ma-fa|0;c[6344]=na+fa;c[6341]=ia;c[na+(fa+4)>>2]=ia|1;c[na+(ma+4)>>2]=40;c[6345]=c[6460];break}ma=c[6342]|0;if(ga>>>0<ma>>>0){c[6342]=ga;ua=ga}else ua=ma;ma=ga+ha|0;ia=25800;while(1){if((c[ia>>2]|0)==(ma|0)){va=ia;wa=ia;K=212;break}ia=c[ia+8>>2]|0;if(!ia){xa=25800;break}}if((K|0)==212)if(!(c[wa+12>>2]&8)){c[va>>2]=ga;ia=wa+4|0;c[ia>>2]=(c[ia>>2]|0)+ha;ia=ga+8|0;ma=(ia&7|0)==0?0:0-ia&7;ia=ga+(ha+8)|0;fa=(ia&7|0)==0?0:0-ia&7;ia=ga+(fa+ha)|0;S=ma+F|0;ka=ga+S|0;ja=ia-(ga+ma)-F|0;c[ga+(ma+4)>>2]=F|3;h:do if((ia|0)!=(na|0)){if((ia|0)==(c[6343]|0)){T=(c[6340]|0)+ja|0;c[6340]=T;c[6343]=ka;c[ga+(S+4)>>2]=T|1;c[ga+(T+S)>>2]=T;break}T=ha+4|0;ca=c[ga+(T+fa)>>2]|0;if((ca&3|0)==1){la=ca&-8;ea=ca>>>3;i:do if(ca>>>0>=256){da=c[ga+((fa|24)+ha)>>2]|0;aa=c[ga+(ha+12+fa)>>2]|0;do if((aa|0)==(ia|0)){ba=fa|16;X=ga+(T+ba)|0;$=c[X>>2]|0;if(!$){Z=ga+(ba+ha)|0;ba=c[Z>>2]|0;if(!ba){Aa=0;break}else{Ca=ba;Da=Z}}else{Ca=$;Da=X}while(1){X=Ca+20|0;$=c[X>>2]|0;if($){Ca=$;Da=X;continue}X=Ca+16|0;$=c[X>>2]|0;if(!$){Ea=Ca;Fa=Da;break}else{Ca=$;Da=X}}if(Fa>>>0<ua>>>0)za();else{c[Fa>>2]=0;Aa=Ea;break}}else{X=c[ga+((fa|8)+ha)>>2]|0;if(X>>>0<ua>>>0)za();$=X+12|0;if((c[$>>2]|0)!=(ia|0))za();Z=aa+8|0;if((c[Z>>2]|0)==(ia|0)){c[$>>2]=aa;c[Z>>2]=X;Aa=aa;break}else za()}while(0);if(!da)break;aa=c[ga+(ha+28+fa)>>2]|0;X=25656+(aa<<2)|0;do if((ia|0)!=(c[X>>2]|0)){if(da>>>0<(c[6342]|0)>>>0)za();Z=da+16|0;if((c[Z>>2]|0)==(ia|0))c[Z>>2]=Aa;else c[da+20>>2]=Aa;if(!Aa)break i}else{c[X>>2]=Aa;if(Aa)break;c[6339]=c[6339]&~(1<<aa);break i}while(0);aa=c[6342]|0;if(Aa>>>0<aa>>>0)za();c[Aa+24>>2]=da;X=fa|16;Z=c[ga+(X+ha)>>2]|0;do if(Z)if(Z>>>0<aa>>>0)za();else{c[Aa+16>>2]=Z;c[Z+24>>2]=Aa;break}while(0);Z=c[ga+(T+X)>>2]|0;if(!Z)break;if(Z>>>0<(c[6342]|0)>>>0)za();else{c[Aa+20>>2]=Z;c[Z+24>>2]=Aa;break}}else{Z=c[ga+((fa|8)+ha)>>2]|0;aa=c[ga+(ha+12+fa)>>2]|0;da=25392+(ea<<1<<2)|0;do if((Z|0)!=(da|0)){if(Z>>>0<ua>>>0)za();if((c[Z+12>>2]|0)==(ia|0))break;za()}while(0);if((aa|0)==(Z|0)){c[6338]=c[6338]&~(1<<ea);break}do if((aa|0)==(da|0))Ga=aa+8|0;else{if(aa>>>0<ua>>>0)za();X=aa+8|0;if((c[X>>2]|0)==(ia|0)){Ga=X;break}za()}while(0);c[Z+12>>2]=aa;c[Ga>>2]=Z}while(0);Ha=ga+((la|fa)+ha)|0;Ia=la+ja|0}else{Ha=ia;Ia=ja}ea=Ha+4|0;c[ea>>2]=c[ea>>2]&-2;c[ga+(S+4)>>2]=Ia|1;c[ga+(Ia+S)>>2]=Ia;ea=Ia>>>3;if(Ia>>>0<256){T=ea<<1;ca=25392+(T<<2)|0;da=c[6338]|0;X=1<<ea;do if(!(da&X)){c[6338]=da|X;Ja=25392+(T+2<<2)|0;Ka=ca}else{ea=25392+(T+2<<2)|0;$=c[ea>>2]|0;if($>>>0>=(c[6342]|0)>>>0){Ja=ea;Ka=$;break}za()}while(0);c[Ja>>2]=ka;c[Ka+12>>2]=ka;c[ga+(S+8)>>2]=Ka;c[ga+(S+12)>>2]=ca;break}T=Ia>>>8;do if(!T)La=0;else{if(Ia>>>0>16777215){La=31;break}X=(T+1048320|0)>>>16&8;da=T<<X;la=(da+520192|0)>>>16&4;$=da<<la;da=($+245760|0)>>>16&2;ea=14-(la|X|da)+($<<da>>>15)|0;La=Ia>>>(ea+7|0)&1|ea<<1}while(0);T=25656+(La<<2)|0;c[ga+(S+28)>>2]=La;c[ga+(S+20)>>2]=0;c[ga+(S+16)>>2]=0;ca=c[6339]|0;ea=1<<La;if(!(ca&ea)){c[6339]=ca|ea;c[T>>2]=ka;c[ga+(S+24)>>2]=T;c[ga+(S+12)>>2]=ka;c[ga+(S+8)>>2]=ka;break}ea=c[T>>2]|0;j:do if((c[ea+4>>2]&-8|0)!=(Ia|0)){T=Ia<<((La|0)==31?0:25-(La>>>1)|0);ca=ea;while(1){da=ca+16+(T>>>31<<2)|0;$=c[da>>2]|0;if(!$){Ma=da;Na=ca;break}if((c[$+4>>2]&-8|0)==(Ia|0)){Oa=$;break j}else{T=T<<1;ca=$}}if(Ma>>>0<(c[6342]|0)>>>0)za();else{c[Ma>>2]=ka;c[ga+(S+24)>>2]=Na;c[ga+(S+12)>>2]=ka;c[ga+(S+8)>>2]=ka;break h}}else Oa=ea;while(0);ea=Oa+8|0;ca=c[ea>>2]|0;T=c[6342]|0;if(ca>>>0>=T>>>0&Oa>>>0>=T>>>0){c[ca+12>>2]=ka;c[ea>>2]=ka;c[ga+(S+8)>>2]=ca;c[ga+(S+12)>>2]=Oa;c[ga+(S+24)>>2]=0;break}else za()}else{ca=(c[6341]|0)+ja|0;c[6341]=ca;c[6344]=ka;c[ga+(S+4)>>2]=ca|1}while(0);n=ga+(ma|8)|0;return n|0}else xa=25800;while(1){S=c[xa>>2]|0;if(S>>>0<=na>>>0?(ka=c[xa+4>>2]|0,ja=S+ka|0,ja>>>0>na>>>0):0){Pa=S;Qa=ka;Ra=ja;break}xa=c[xa+8>>2]|0}ma=Pa+(Qa+-39)|0;ja=Pa+(Qa+-47+((ma&7|0)==0?0:0-ma&7))|0;ma=na+16|0;ka=ja>>>0<ma>>>0?na:ja;ja=ka+8|0;S=ga+8|0;ia=(S&7|0)==0?0:0-S&7;S=ha+-40-ia|0;c[6344]=ga+ia;c[6341]=S;c[ga+(ia+4)>>2]=S|1;c[ga+(ha+-36)>>2]=40;c[6345]=c[6460];S=ka+4|0;c[S>>2]=27;c[ja>>2]=c[6450];c[ja+4>>2]=c[6451];c[ja+8>>2]=c[6452];c[ja+12>>2]=c[6453];c[6450]=ga;c[6451]=ha;c[6453]=0;c[6452]=ja;ja=ka+28|0;c[ja>>2]=7;if((ka+32|0)>>>0<Ra>>>0){ia=ja;do{ja=ia;ia=ia+4|0;c[ia>>2]=7}while((ja+8|0)>>>0<Ra>>>0)}if((ka|0)!=(na|0)){ia=ka-na|0;c[S>>2]=c[S>>2]&-2;c[na+4>>2]=ia|1;c[ka>>2]=ia;ja=ia>>>3;if(ia>>>0<256){fa=ja<<1;ca=25392+(fa<<2)|0;ea=c[6338]|0;T=1<<ja;if(ea&T){ja=25392+(fa+2<<2)|0;Z=c[ja>>2]|0;if(Z>>>0<(c[6342]|0)>>>0)za();else{Sa=ja;Ta=Z}}else{c[6338]=ea|T;Sa=25392+(fa+2<<2)|0;Ta=ca}c[Sa>>2]=na;c[Ta+12>>2]=na;c[na+8>>2]=Ta;c[na+12>>2]=ca;break}ca=ia>>>8;if(ca)if(ia>>>0>16777215)Ua=31;else{fa=(ca+1048320|0)>>>16&8;T=ca<<fa;ca=(T+520192|0)>>>16&4;ea=T<<ca;T=(ea+245760|0)>>>16&2;Z=14-(ca|fa|T)+(ea<<T>>>15)|0;Ua=ia>>>(Z+7|0)&1|Z<<1}else Ua=0;Z=25656+(Ua<<2)|0;c[na+28>>2]=Ua;c[na+20>>2]=0;c[ma>>2]=0;T=c[6339]|0;ea=1<<Ua;if(!(T&ea)){c[6339]=T|ea;c[Z>>2]=na;c[na+24>>2]=Z;c[na+12>>2]=na;c[na+8>>2]=na;break}ea=c[Z>>2]|0;k:do if((c[ea+4>>2]&-8|0)!=(ia|0)){Z=ia<<((Ua|0)==31?0:25-(Ua>>>1)|0);T=ea;while(1){fa=T+16+(Z>>>31<<2)|0;ca=c[fa>>2]|0;if(!ca){Va=fa;Wa=T;break}if((c[ca+4>>2]&-8|0)==(ia|0)){Xa=ca;break k}else{Z=Z<<1;T=ca}}if(Va>>>0<(c[6342]|0)>>>0)za();else{c[Va>>2]=na;c[na+24>>2]=Wa;c[na+12>>2]=na;c[na+8>>2]=na;break g}}else Xa=ea;while(0);ea=Xa+8|0;ia=c[ea>>2]|0;ma=c[6342]|0;if(ia>>>0>=ma>>>0&Xa>>>0>=ma>>>0){c[ia+12>>2]=na;c[ea>>2]=na;c[na+8>>2]=ia;c[na+12>>2]=Xa;c[na+24>>2]=0;break}else za()}}else{ia=c[6342]|0;if((ia|0)==0|ga>>>0<ia>>>0)c[6342]=ga;c[6450]=ga;c[6451]=ha;c[6453]=0;c[6347]=c[6456];c[6346]=-1;ia=0;do{ea=ia<<1;ma=25392+(ea<<2)|0;c[25392+(ea+3<<2)>>2]=ma;c[25392+(ea+2<<2)>>2]=ma;ia=ia+1|0}while((ia|0)!=32);ia=ga+8|0;ma=(ia&7|0)==0?0:0-ia&7;ia=ha+-40-ma|0;c[6344]=ga+ma;c[6341]=ia;c[ga+(ma+4)>>2]=ia|1;c[ga+(ha+-36)>>2]=40;c[6345]=c[6460]}while(0);ha=c[6341]|0;if(ha>>>0>F>>>0){ga=ha-F|0;c[6341]=ga;ha=c[6344]|0;c[6344]=ha+F;c[ha+(F+4)>>2]=ga|1;c[ha+4>>2]=F|3;n=ha+8|0;return n|0}}c[(ya()|0)>>2]=12;n=0;return n|0}function _e(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;if(!a)return;b=a+-8|0;d=c[6342]|0;if(b>>>0<d>>>0)za();e=c[a+-4>>2]|0;f=e&3;if((f|0)==1)za();g=e&-8;h=a+(g+-8)|0;do if(!(e&1)){i=c[b>>2]|0;if(!f)return;j=-8-i|0;k=a+j|0;l=i+g|0;if(k>>>0<d>>>0)za();if((k|0)==(c[6343]|0)){m=a+(g+-4)|0;n=c[m>>2]|0;if((n&3|0)!=3){o=k;p=l;break}c[6340]=l;c[m>>2]=n&-2;c[a+(j+4)>>2]=l|1;c[h>>2]=l;return}n=i>>>3;if(i>>>0<256){i=c[a+(j+8)>>2]|0;m=c[a+(j+12)>>2]|0;q=25392+(n<<1<<2)|0;if((i|0)!=(q|0)){if(i>>>0<d>>>0)za();if((c[i+12>>2]|0)!=(k|0))za()}if((m|0)==(i|0)){c[6338]=c[6338]&~(1<<n);o=k;p=l;break}if((m|0)!=(q|0)){if(m>>>0<d>>>0)za();q=m+8|0;if((c[q>>2]|0)==(k|0))r=q;else za()}else r=m+8|0;c[i+12>>2]=m;c[r>>2]=i;o=k;p=l;break}i=c[a+(j+24)>>2]|0;m=c[a+(j+12)>>2]|0;do if((m|0)==(k|0)){q=a+(j+20)|0;n=c[q>>2]|0;if(!n){s=a+(j+16)|0;t=c[s>>2]|0;if(!t){u=0;break}else{v=t;w=s}}else{v=n;w=q}while(1){q=v+20|0;n=c[q>>2]|0;if(n){v=n;w=q;continue}q=v+16|0;n=c[q>>2]|0;if(!n){x=v;y=w;break}else{v=n;w=q}}if(y>>>0<d>>>0)za();else{c[y>>2]=0;u=x;break}}else{q=c[a+(j+8)>>2]|0;if(q>>>0<d>>>0)za();n=q+12|0;if((c[n>>2]|0)!=(k|0))za();s=m+8|0;if((c[s>>2]|0)==(k|0)){c[n>>2]=m;c[s>>2]=q;u=m;break}else za()}while(0);if(i){m=c[a+(j+28)>>2]|0;q=25656+(m<<2)|0;if((k|0)==(c[q>>2]|0)){c[q>>2]=u;if(!u){c[6339]=c[6339]&~(1<<m);o=k;p=l;break}}else{if(i>>>0<(c[6342]|0)>>>0)za();m=i+16|0;if((c[m>>2]|0)==(k|0))c[m>>2]=u;else c[i+20>>2]=u;if(!u){o=k;p=l;break}}m=c[6342]|0;if(u>>>0<m>>>0)za();c[u+24>>2]=i;q=c[a+(j+16)>>2]|0;do if(q)if(q>>>0<m>>>0)za();else{c[u+16>>2]=q;c[q+24>>2]=u;break}while(0);q=c[a+(j+20)>>2]|0;if(q)if(q>>>0<(c[6342]|0)>>>0)za();else{c[u+20>>2]=q;c[q+24>>2]=u;o=k;p=l;break}else{o=k;p=l}}else{o=k;p=l}}else{o=b;p=g}while(0);if(o>>>0>=h>>>0)za();b=a+(g+-4)|0;u=c[b>>2]|0;if(!(u&1))za();if(!(u&2)){if((h|0)==(c[6344]|0)){d=(c[6341]|0)+p|0;c[6341]=d;c[6344]=o;c[o+4>>2]=d|1;if((o|0)!=(c[6343]|0))return;c[6343]=0;c[6340]=0;return}if((h|0)==(c[6343]|0)){d=(c[6340]|0)+p|0;c[6340]=d;c[6343]=o;c[o+4>>2]=d|1;c[o+d>>2]=d;return}d=(u&-8)+p|0;x=u>>>3;do if(u>>>0>=256){y=c[a+(g+16)>>2]|0;w=c[a+(g|4)>>2]|0;do if((w|0)==(h|0)){v=a+(g+12)|0;r=c[v>>2]|0;if(!r){f=a+(g+8)|0;e=c[f>>2]|0;if(!e){z=0;break}else{A=e;B=f}}else{A=r;B=v}while(1){v=A+20|0;r=c[v>>2]|0;if(r){A=r;B=v;continue}v=A+16|0;r=c[v>>2]|0;if(!r){C=A;D=B;break}else{A=r;B=v}}if(D>>>0<(c[6342]|0)>>>0)za();else{c[D>>2]=0;z=C;break}}else{v=c[a+g>>2]|0;if(v>>>0<(c[6342]|0)>>>0)za();r=v+12|0;if((c[r>>2]|0)!=(h|0))za();f=w+8|0;if((c[f>>2]|0)==(h|0)){c[r>>2]=w;c[f>>2]=v;z=w;break}else za()}while(0);if(y){w=c[a+(g+20)>>2]|0;l=25656+(w<<2)|0;if((h|0)==(c[l>>2]|0)){c[l>>2]=z;if(!z){c[6339]=c[6339]&~(1<<w);break}}else{if(y>>>0<(c[6342]|0)>>>0)za();w=y+16|0;if((c[w>>2]|0)==(h|0))c[w>>2]=z;else c[y+20>>2]=z;if(!z)break}w=c[6342]|0;if(z>>>0<w>>>0)za();c[z+24>>2]=y;l=c[a+(g+8)>>2]|0;do if(l)if(l>>>0<w>>>0)za();else{c[z+16>>2]=l;c[l+24>>2]=z;break}while(0);l=c[a+(g+12)>>2]|0;if(l)if(l>>>0<(c[6342]|0)>>>0)za();else{c[z+20>>2]=l;c[l+24>>2]=z;break}}}else{l=c[a+g>>2]|0;w=c[a+(g|4)>>2]|0;y=25392+(x<<1<<2)|0;if((l|0)!=(y|0)){if(l>>>0<(c[6342]|0)>>>0)za();if((c[l+12>>2]|0)!=(h|0))za()}if((w|0)==(l|0)){c[6338]=c[6338]&~(1<<x);break}if((w|0)!=(y|0)){if(w>>>0<(c[6342]|0)>>>0)za();y=w+8|0;if((c[y>>2]|0)==(h|0))E=y;else za()}else E=w+8|0;c[l+12>>2]=w;c[E>>2]=l}while(0);c[o+4>>2]=d|1;c[o+d>>2]=d;if((o|0)==(c[6343]|0)){c[6340]=d;return}else F=d}else{c[b>>2]=u&-2;c[o+4>>2]=p|1;c[o+p>>2]=p;F=p}p=F>>>3;if(F>>>0<256){u=p<<1;b=25392+(u<<2)|0;d=c[6338]|0;E=1<<p;if(d&E){p=25392+(u+2<<2)|0;h=c[p>>2]|0;if(h>>>0<(c[6342]|0)>>>0)za();else{G=p;H=h}}else{c[6338]=d|E;G=25392+(u+2<<2)|0;H=b}c[G>>2]=o;c[H+12>>2]=o;c[o+8>>2]=H;c[o+12>>2]=b;return}b=F>>>8;if(b)if(F>>>0>16777215)I=31;else{H=(b+1048320|0)>>>16&8;G=b<<H;b=(G+520192|0)>>>16&4;u=G<<b;G=(u+245760|0)>>>16&2;E=14-(b|H|G)+(u<<G>>>15)|0;I=F>>>(E+7|0)&1|E<<1}else I=0;E=25656+(I<<2)|0;c[o+28>>2]=I;c[o+20>>2]=0;c[o+16>>2]=0;G=c[6339]|0;u=1<<I;a:do if(G&u){H=c[E>>2]|0;b:do if((c[H+4>>2]&-8|0)!=(F|0)){b=F<<((I|0)==31?0:25-(I>>>1)|0);d=H;while(1){h=d+16+(b>>>31<<2)|0;p=c[h>>2]|0;if(!p){J=h;K=d;break}if((c[p+4>>2]&-8|0)==(F|0)){L=p;break b}else{b=b<<1;d=p}}if(J>>>0<(c[6342]|0)>>>0)za();else{c[J>>2]=o;c[o+24>>2]=K;c[o+12>>2]=o;c[o+8>>2]=o;break a}}else L=H;while(0);H=L+8|0;d=c[H>>2]|0;b=c[6342]|0;if(d>>>0>=b>>>0&L>>>0>=b>>>0){c[d+12>>2]=o;c[H>>2]=o;c[o+8>>2]=d;c[o+12>>2]=L;c[o+24>>2]=0;break}else za()}else{c[6339]=G|u;c[E>>2]=o;c[o+24>>2]=E;c[o+12>>2]=o;c[o+8>>2]=o}while(0);o=(c[6346]|0)+-1|0;c[6346]=o;if(!o)M=25808;else return;while(1){o=c[M>>2]|0;if(!o)break;else M=o+8|0}c[6346]=-1;return}function $e(){}function af(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){C=b>>c;return a>>>c|(b&(1<<c)-1)<<32-c}C=(b|0)<0?-1:0;return b>>c-32|0}function bf(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=b+e|0;if((e|0)>=20){d=d&255;g=b&3;h=d|d<<8|d<<16|d<<24;i=f&~3;if(g){g=b+4-g|0;while((b|0)<(g|0)){a[b>>0]=d;b=b+1|0}}while((b|0)<(i|0)){c[b>>2]=h;b=b+4|0}}while((b|0)<(f|0)){a[b>>0]=d;b=b+1|0}return b-e|0}function cf(b){b=b|0;var c=0;c=b;while(a[c>>0]|0)c=c+1|0;return c-b|0}function df(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if((e|0)>=4096)return sa(b|0,d|0,e|0)|0;f=b|0;if((b&3)==(d&3)){while(b&3){if(!e)return f|0;a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function ef(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=a+c>>>0;return (C=b+d+(e>>>0<a>>>0|0)>>>0,e|0)|0}function ff(b,c,d){b=b|0;c=c|0;d=d|0;var e=0;if((c|0)<(b|0)&(b|0)<(c+d|0)){e=b;c=c+d|0;b=b+d|0;while((d|0)>0){b=b-1|0;c=c-1|0;d=d-1|0;a[b>>0]=a[c>>0]|0}b=e}else df(b,c,d)|0;return b|0}function gf(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=b-d>>>0;e=b-d-(c>>>0>a>>>0|0)>>>0;return (C=e,a-c>>>0|0)|0}function hf(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){C=b<<c|(a&(1<<c)-1<<32-c)>>>32-c;return a<<c}C=a<<c-32;return 0}function jf(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){C=b>>>c;return a>>>c|(b&(1<<c)-1)<<32-c}C=0;return b>>>c-32|0}function kf(b){b=b|0;var c=0;c=a[m+(b&255)>>0]|0;if((c|0)<8)return c|0;c=a[m+(b>>8&255)>>0]|0;if((c|0)<8)return c+8|0;c=a[m+(b>>16&255)>>0]|0;if((c|0)<8)return c+16|0;return (a[m+(b>>>24)>>0]|0)+24|0}function lf(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;c=a&65535;d=b&65535;e=_(d,c)|0;f=a>>>16;a=(e>>>16)+(_(d,f)|0)|0;d=b>>>16;b=_(d,c)|0;return (C=(a>>>16)+(_(d,f)|0)+(((a&65535)+b|0)>>>16)|0,a+b<<16|e&65535|0)|0}function mf(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;e=b>>31|((b|0)<0?-1:0)<<1;f=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;g=d>>31|((d|0)<0?-1:0)<<1;h=((d|0)<0?-1:0)>>31|((d|0)<0?-1:0)<<1;i=gf(e^a,f^b,e,f)|0;b=C;a=g^e;e=h^f;return gf((rf(i,b,gf(g^c,h^d,g,h)|0,C,0)|0)^a,C^e,a,e)|0}function nf(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+8|0;g=f|0;h=b>>31|((b|0)<0?-1:0)<<1;j=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;k=e>>31|((e|0)<0?-1:0)<<1;l=((e|0)<0?-1:0)>>31|((e|0)<0?-1:0)<<1;m=gf(h^a,j^b,h,j)|0;b=C;rf(m,b,gf(k^d,l^e,k,l)|0,C,g)|0;l=gf(c[g>>2]^h,c[g+4>>2]^j,h,j)|0;j=C;i=f;return (C=j,l)|0}function of(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=a;a=c;c=lf(e,a)|0;f=C;return (C=(_(b,a)|0)+(_(d,e)|0)+f|f&0,c|0|0)|0}function pf(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return rf(a,b,c,d,0)|0}function qf(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=i;i=i+8|0;g=f|0;rf(a,b,d,e,g)|0;i=f;return (C=c[g+4>>2]|0,c[g>>2]|0)|0}function rf(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,D=0,E=0,F=0,G=0,H=0;g=a;h=b;i=h;j=d;k=e;l=k;if(!i){m=(f|0)!=0;if(!l){if(m){c[f>>2]=(g>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(g>>>0)/(j>>>0)>>>0;return (C=n,o)|0}else{if(!m){n=0;o=0;return (C=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=b&0;n=0;o=0;return (C=n,o)|0}}m=(l|0)==0;do if(j){if(!m){p=(aa(l|0)|0)-(aa(i|0)|0)|0;if(p>>>0<=31){q=p+1|0;r=31-p|0;s=p-31>>31;t=q;u=g>>>(q>>>0)&s|i<<r;v=i>>>(q>>>0)&s;w=0;x=g<<r;break}if(!f){n=0;o=0;return (C=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return (C=n,o)|0}r=j-1|0;if(r&j){s=(aa(j|0)|0)+33-(aa(i|0)|0)|0;q=64-s|0;p=32-s|0;y=p>>31;z=s-32|0;A=z>>31;t=s;u=p-1>>31&i>>>(z>>>0)|(i<<p|g>>>(s>>>0))&A;v=A&i>>>(s>>>0);w=g<<q&y;x=(i<<q|g>>>(z>>>0))&y|g<<p&s-33>>31;break}if(f){c[f>>2]=r&g;c[f+4>>2]=0}if((j|0)==1){n=h|b&0;o=a|0|0;return (C=n,o)|0}else{r=kf(j|0)|0;n=i>>>(r>>>0)|0;o=i<<32-r|g>>>(r>>>0)|0;return (C=n,o)|0}}else{if(m){if(f){c[f>>2]=(i>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(i>>>0)/(j>>>0)>>>0;return (C=n,o)|0}if(!g){if(f){c[f>>2]=0;c[f+4>>2]=(i>>>0)%(l>>>0)}n=0;o=(i>>>0)/(l>>>0)>>>0;return (C=n,o)|0}r=l-1|0;if(!(r&l)){if(f){c[f>>2]=a|0;c[f+4>>2]=r&i|b&0}n=0;o=i>>>((kf(l|0)|0)>>>0);return (C=n,o)|0}r=(aa(l|0)|0)-(aa(i|0)|0)|0;if(r>>>0<=30){s=r+1|0;p=31-r|0;t=s;u=i<<p|g>>>(s>>>0);v=i>>>(s>>>0);w=0;x=g<<p;break}if(!f){n=0;o=0;return (C=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return (C=n,o)|0}while(0);if(!t){B=x;D=w;E=v;F=u;G=0;H=0}else{b=d|0|0;d=k|e&0;e=ef(b|0,d|0,-1,-1)|0;k=C;h=x;x=w;w=v;v=u;u=t;t=0;do{a=h;h=x>>>31|h<<1;x=t|x<<1;g=v<<1|a>>>31|0;a=v>>>31|w<<1|0;gf(e,k,g,a)|0;i=C;l=i>>31|((i|0)<0?-1:0)<<1;t=l&1;v=gf(g,a,l&b,(((i|0)<0?-1:0)>>31|((i|0)<0?-1:0)<<1)&d)|0;w=C;u=u-1|0}while((u|0)!=0);B=h;D=x;E=w;F=v;G=0;H=t}t=D;D=0;if(f){c[f>>2]=F;c[f+4>>2]=E}n=(t|0)>>>31|(B|D)<<1|(D<<1|t>>>31)&0|G;o=(t<<1|0>>>31)&-2|H;return (C=n,o)|0}function sf(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;Ha[a&1](b|0,c|0,d|0,e|0,f|0,g|0)}function tf(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;ba(0)}
+
+// EMSCRIPTEN_END_FUNCS
+var Ha=[tf,ee];return{_strlen:cf,_free:_e,_ogv_audio_decoder_destroy:Ue,_ogv_audio_decoder_init:Re,_i64Add:ef,_memmove:ff,_bitshift64Ashr:af,_memset:bf,_ogv_audio_decoder_process_header:Se,_malloc:Ze,_memcpy:df,_ogv_audio_decoder_process_audio:Te,runPostSets:$e,stackAlloc:Ia,stackSave:Ja,stackRestore:Ka,establishStackSpace:La,setThrew:Ma,setTempRet0:Pa,getTempRet0:Qa,dynCall_viiiiii:sf}})
+
+
+// EMSCRIPTEN_END_ASM
+(Module.asmGlobalArg,Module.asmLibraryArg,buffer);var _strlen=Module["_strlen"]=asm["_strlen"];var _free=Module["_free"]=asm["_free"];var runPostSets=Module["runPostSets"]=asm["runPostSets"];var _ogv_audio_decoder_destroy=Module["_ogv_audio_decoder_destroy"]=asm["_ogv_audio_decoder_destroy"];var _ogv_audio_decoder_init=Module["_ogv_audio_decoder_init"]=asm["_ogv_audio_decoder_init"];var _i64Add=Module["_i64Add"]=asm["_i64Add"];var _memmove=Module["_memmove"]=asm["_memmove"];var _bitshift64Ashr=Module["_bitshift64Ashr"]=asm["_bitshift64Ashr"];var _memset=Module["_memset"]=asm["_memset"];var _ogv_audio_decoder_process_header=Module["_ogv_audio_decoder_process_header"]=asm["_ogv_audio_decoder_process_header"];var _malloc=Module["_malloc"]=asm["_malloc"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _ogv_audio_decoder_process_audio=Module["_ogv_audio_decoder_process_audio"]=asm["_ogv_audio_decoder_process_audio"];var dynCall_viiiiii=Module["dynCall_viiiiii"]=asm["dynCall_viiiiii"];Runtime.stackAlloc=asm["stackAlloc"];Runtime.stackSave=asm["stackSave"];Runtime.stackRestore=asm["stackRestore"];Runtime.establishStackSpace=asm["establishStackSpace"];Runtime.setTempRet0=asm["setTempRet0"];Runtime.getTempRet0=asm["getTempRet0"];var i64Math=(function(){var goog={math:{}};goog.math.Long=(function(low,high){this.low_=low|0;this.high_=high|0});goog.math.Long.IntCache_={};goog.math.Long.fromInt=(function(value){if(-128<=value&&value<128){var cachedObj=goog.math.Long.IntCache_[value];if(cachedObj){return cachedObj}}var obj=new goog.math.Long(value|0,value<0?-1:0);if(-128<=value&&value<128){goog.math.Long.IntCache_[value]=obj}return obj});goog.math.Long.fromNumber=(function(value){if(isNaN(value)||!isFinite(value)){return goog.math.Long.ZERO}else if(value<=-goog.math.Long.TWO_PWR_63_DBL_){return goog.math.Long.MIN_VALUE}else if(value+1>=goog.math.Long.TWO_PWR_63_DBL_){return goog.math.Long.MAX_VALUE}else if(value<0){return goog.math.Long.fromNumber(-value).negate()}else{return new goog.math.Long(value%goog.math.Long.TWO_PWR_32_DBL_|0,value/goog.math.Long.TWO_PWR_32_DBL_|0)}});goog.math.Long.fromBits=(function(lowBits,highBits){return new goog.math.Long(lowBits,highBits)});goog.math.Long.fromString=(function(str,opt_radix){if(str.length==0){throw Error("number format error: empty string")}var radix=opt_radix||10;if(radix<2||36<radix){throw Error("radix out of range: "+radix)}if(str.charAt(0)=="-"){return goog.math.Long.fromString(str.substring(1),radix).negate()}else if(str.indexOf("-")>=0){throw Error('number format error: interior "-" character: '+str)}var radixToPower=goog.math.Long.fromNumber(Math.pow(radix,8));var result=goog.math.Long.ZERO;for(var i=0;i<str.length;i+=8){var size=Math.min(8,str.length-i);var value=parseInt(str.substring(i,i+size),radix);if(size<8){var power=goog.math.Long.fromNumber(Math.pow(radix,size));result=result.multiply(power).add(goog.math.Long.fromNumber(value))}else{result=result.multiply(radixToPower);result=result.add(goog.math.Long.fromNumber(value))}}return result});goog.math.Long.TWO_PWR_16_DBL_=1<<16;goog.math.Long.TWO_PWR_24_DBL_=1<<24;goog.math.Long.TWO_PWR_32_DBL_=goog.math.Long.TWO_PWR_16_DBL_*goog.math.Long.TWO_PWR_16_DBL_;goog.math.Long.TWO_PWR_31_DBL_=goog.math.Long.TWO_PWR_32_DBL_/2;goog.math.Long.TWO_PWR_48_DBL_=goog.math.Long.TWO_PWR_32_DBL_*goog.math.Long.TWO_PWR_16_DBL_;goog.math.Long.TWO_PWR_64_DBL_=goog.math.Long.TWO_PWR_32_DBL_*goog.math.Long.TWO_PWR_32_DBL_;goog.math.Long.TWO_PWR_63_DBL_=goog.math.Long.TWO_PWR_64_DBL_/2;goog.math.Long.ZERO=goog.math.Long.fromInt(0);goog.math.Long.ONE=goog.math.Long.fromInt(1);goog.math.Long.NEG_ONE=goog.math.Long.fromInt(-1);goog.math.Long.MAX_VALUE=goog.math.Long.fromBits(4294967295|0,2147483647|0);goog.math.Long.MIN_VALUE=goog.math.Long.fromBits(0,2147483648|0);goog.math.Long.TWO_PWR_24_=goog.math.Long.fromInt(1<<24);goog.math.Long.prototype.toInt=(function(){return this.low_});goog.math.Long.prototype.toNumber=(function(){return this.high_*goog.math.Long.TWO_PWR_32_DBL_+this.getLowBitsUnsigned()});goog.math.Long.prototype.toString=(function(opt_radix){var radix=opt_radix||10;if(radix<2||36<radix){throw Error("radix out of range: "+radix)}if(this.isZero()){return"0"}if(this.isNegative()){if(this.equals(goog.math.Long.MIN_VALUE)){var radixLong=goog.math.Long.fromNumber(radix);var div=this.div(radixLong);var rem=div.multiply(radixLong).subtract(this);return div.toString(radix)+rem.toInt().toString(radix)}else{return"-"+this.negate().toString(radix)}}var radixToPower=goog.math.Long.fromNumber(Math.pow(radix,6));var rem=this;var result="";while(true){var remDiv=rem.div(radixToPower);var intval=rem.subtract(remDiv.multiply(radixToPower)).toInt();var digits=intval.toString(radix);rem=remDiv;if(rem.isZero()){return digits+result}else{while(digits.length<6){digits="0"+digits}result=""+digits+result}}});goog.math.Long.prototype.getHighBits=(function(){return this.high_});goog.math.Long.prototype.getLowBits=(function(){return this.low_});goog.math.Long.prototype.getLowBitsUnsigned=(function(){return this.low_>=0?this.low_:goog.math.Long.TWO_PWR_32_DBL_+this.low_});goog.math.Long.prototype.getNumBitsAbs=(function(){if(this.isNegative()){if(this.equals(goog.math.Long.MIN_VALUE)){return 64}else{return this.negate().getNumBitsAbs()}}else{var val=this.high_!=0?this.high_:this.low_;for(var bit=31;bit>0;bit--){if((val&1<<bit)!=0){break}}return this.high_!=0?bit+33:bit+1}});goog.math.Long.prototype.isZero=(function(){return this.high_==0&&this.low_==0});goog.math.Long.prototype.isNegative=(function(){return this.high_<0});goog.math.Long.prototype.isOdd=(function(){return(this.low_&1)==1});goog.math.Long.prototype.equals=(function(other){return this.high_==other.high_&&this.low_==other.low_});goog.math.Long.prototype.notEquals=(function(other){return this.high_!=other.high_||this.low_!=other.low_});goog.math.Long.prototype.lessThan=(function(other){return this.compare(other)<0});goog.math.Long.prototype.lessThanOrEqual=(function(other){return this.compare(other)<=0});goog.math.Long.prototype.greaterThan=(function(other){return this.compare(other)>0});goog.math.Long.prototype.greaterThanOrEqual=(function(other){return this.compare(other)>=0});goog.math.Long.prototype.compare=(function(other){if(this.equals(other)){return 0}var thisNeg=this.isNegative();var otherNeg=other.isNegative();if(thisNeg&&!otherNeg){return-1}if(!thisNeg&&otherNeg){return 1}if(this.subtract(other).isNegative()){return-1}else{return 1}});goog.math.Long.prototype.negate=(function(){if(this.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.MIN_VALUE}else{return this.not().add(goog.math.Long.ONE)}});goog.math.Long.prototype.add=(function(other){var a48=this.high_>>>16;var a32=this.high_&65535;var a16=this.low_>>>16;var a00=this.low_&65535;var b48=other.high_>>>16;var b32=other.high_&65535;var b16=other.low_>>>16;var b00=other.low_&65535;var c48=0,c32=0,c16=0,c00=0;c00+=a00+b00;c16+=c00>>>16;c00&=65535;c16+=a16+b16;c32+=c16>>>16;c16&=65535;c32+=a32+b32;c48+=c32>>>16;c32&=65535;c48+=a48+b48;c48&=65535;return goog.math.Long.fromBits(c16<<16|c00,c48<<16|c32)});goog.math.Long.prototype.subtract=(function(other){return this.add(other.negate())});goog.math.Long.prototype.multiply=(function(other){if(this.isZero()){return goog.math.Long.ZERO}else if(other.isZero()){return goog.math.Long.ZERO}if(this.equals(goog.math.Long.MIN_VALUE)){return other.isOdd()?goog.math.Long.MIN_VALUE:goog.math.Long.ZERO}else if(other.equals(goog.math.Long.MIN_VALUE)){return this.isOdd()?goog.math.Long.MIN_VALUE:goog.math.Long.ZERO}if(this.isNegative()){if(other.isNegative()){return this.negate().multiply(other.negate())}else{return this.negate().multiply(other).negate()}}else if(other.isNegative()){return this.multiply(other.negate()).negate()}if(this.lessThan(goog.math.Long.TWO_PWR_24_)&&other.lessThan(goog.math.Long.TWO_PWR_24_)){return goog.math.Long.fromNumber(this.toNumber()*other.toNumber())}var a48=this.high_>>>16;var a32=this.high_&65535;var a16=this.low_>>>16;var a00=this.low_&65535;var b48=other.high_>>>16;var b32=other.high_&65535;var b16=other.low_>>>16;var b00=other.low_&65535;var c48=0,c32=0,c16=0,c00=0;c00+=a00*b00;c16+=c00>>>16;c00&=65535;c16+=a16*b00;c32+=c16>>>16;c16&=65535;c16+=a00*b16;c32+=c16>>>16;c16&=65535;c32+=a32*b00;c48+=c32>>>16;c32&=65535;c32+=a16*b16;c48+=c32>>>16;c32&=65535;c32+=a00*b32;c48+=c32>>>16;c32&=65535;c48+=a48*b00+a32*b16+a16*b32+a00*b48;c48&=65535;return goog.math.Long.fromBits(c16<<16|c00,c48<<16|c32)});goog.math.Long.prototype.div=(function(other){if(other.isZero()){throw Error("division by zero")}else if(this.isZero()){return goog.math.Long.ZERO}if(this.equals(goog.math.Long.MIN_VALUE)){if(other.equals(goog.math.Long.ONE)||other.equals(goog.math.Long.NEG_ONE)){return goog.math.Long.MIN_VALUE}else if(other.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.ONE}else{var halfThis=this.shiftRight(1);var approx=halfThis.div(other).shiftLeft(1);if(approx.equals(goog.math.Long.ZERO)){return other.isNegative()?goog.math.Long.ONE:goog.math.Long.NEG_ONE}else{var rem=this.subtract(other.multiply(approx));var result=approx.add(rem.div(other));return result}}}else if(other.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.ZERO}if(this.isNegative()){if(other.isNegative()){return this.negate().div(other.negate())}else{return this.negate().div(other).negate()}}else if(other.isNegative()){return this.div(other.negate()).negate()}var res=goog.math.Long.ZERO;var rem=this;while(rem.greaterThanOrEqual(other)){var approx=Math.max(1,Math.floor(rem.toNumber()/other.toNumber()));var log2=Math.ceil(Math.log(approx)/Math.LN2);var delta=log2<=48?1:Math.pow(2,log2-48);var approxRes=goog.math.Long.fromNumber(approx);var approxRem=approxRes.multiply(other);while(approxRem.isNegative()||approxRem.greaterThan(rem)){approx-=delta;approxRes=goog.math.Long.fromNumber(approx);approxRem=approxRes.multiply(other)}if(approxRes.isZero()){approxRes=goog.math.Long.ONE}res=res.add(approxRes);rem=rem.subtract(approxRem)}return res});goog.math.Long.prototype.modulo=(function(other){return this.subtract(this.div(other).multiply(other))});goog.math.Long.prototype.not=(function(){return goog.math.Long.fromBits(~this.low_,~this.high_)});goog.math.Long.prototype.and=(function(other){return goog.math.Long.fromBits(this.low_&other.low_,this.high_&other.high_)});goog.math.Long.prototype.or=(function(other){return goog.math.Long.fromBits(this.low_|other.low_,this.high_|other.high_)});goog.math.Long.prototype.xor=(function(other){return goog.math.Long.fromBits(this.low_^other.low_,this.high_^other.high_)});goog.math.Long.prototype.shiftLeft=(function(numBits){numBits&=63;if(numBits==0){return this}else{var low=this.low_;if(numBits<32){var high=this.high_;return goog.math.Long.fromBits(low<<numBits,high<<numBits|low>>>32-numBits)}else{return goog.math.Long.fromBits(0,low<<numBits-32)}}});goog.math.Long.prototype.shiftRight=(function(numBits){numBits&=63;if(numBits==0){return this}else{var high=this.high_;if(numBits<32){var low=this.low_;return goog.math.Long.fromBits(low>>>numBits|high<<32-numBits,high>>numBits)}else{return goog.math.Long.fromBits(high>>numBits-32,high>=0?0:-1)}}});goog.math.Long.prototype.shiftRightUnsigned=(function(numBits){numBits&=63;if(numBits==0){return this}else{var high=this.high_;if(numBits<32){var low=this.low_;return goog.math.Long.fromBits(low>>>numBits|high<<32-numBits,high>>>numBits)}else if(numBits==32){return goog.math.Long.fromBits(high,0)}else{return goog.math.Long.fromBits(high>>>numBits-32,0)}}});var navigator={appName:"Modern Browser"};var dbits;var canary=0xdeadbeefcafe;var j_lm=(canary&16777215)==15715070;function BigInteger(a,b,c){if(a!=null)if("number"==typeof a)this.fromNumber(a,b,c);else if(b==null&&"string"!=typeof a)this.fromString(a,256);else this.fromString(a,b)}function nbi(){return new BigInteger(null)}function am1(i,x,w,j,c,n){while(--n>=0){var v=x*this[i++]+w[j]+c;c=Math.floor(v/67108864);w[j++]=v&67108863}return c}function am2(i,x,w,j,c,n){var xl=x&32767,xh=x>>15;while(--n>=0){var l=this[i]&32767;var h=this[i++]>>15;var m=xh*l+h*xl;l=xl*l+((m&32767)<<15)+w[j]+(c&1073741823);c=(l>>>30)+(m>>>15)+xh*h+(c>>>30);w[j++]=l&1073741823}return c}function am3(i,x,w,j,c,n){var xl=x&16383,xh=x>>14;while(--n>=0){var l=this[i]&16383;var h=this[i++]>>14;var m=xh*l+h*xl;l=xl*l+((m&16383)<<14)+w[j]+c;c=(l>>28)+(m>>14)+xh*h;w[j++]=l&268435455}return c}if(j_lm&&navigator.appName=="Microsoft Internet Explorer"){BigInteger.prototype.am=am2;dbits=30}else if(j_lm&&navigator.appName!="Netscape"){BigInteger.prototype.am=am1;dbits=26}else{BigInteger.prototype.am=am3;dbits=28}BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=(1<<dbits)-1;BigInteger.prototype.DV=1<<dbits;var BI_FP=52;BigInteger.prototype.FV=Math.pow(2,BI_FP);BigInteger.prototype.F1=BI_FP-dbits;BigInteger.prototype.F2=2*dbits-BI_FP;var BI_RM="0123456789abcdefghijklmnopqrstuvwxyz";var BI_RC=new Array;var rr,vv;rr="0".charCodeAt(0);for(vv=0;vv<=9;++vv)BI_RC[rr++]=vv;rr="a".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;rr="A".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;function int2char(n){return BI_RM.charAt(n)}function intAt(s,i){var c=BI_RC[s.charCodeAt(i)];return c==null?-1:c}function bnpCopyTo(r){for(var i=this.t-1;i>=0;--i)r[i]=this[i];r.t=this.t;r.s=this.s}function bnpFromInt(x){this.t=1;this.s=x<0?-1:0;if(x>0)this[0]=x;else if(x<-1)this[0]=x+DV;else this.t=0}function nbv(i){var r=nbi();r.fromInt(i);return r}function bnpFromString(s,b){var k;if(b==16)k=4;else if(b==8)k=3;else if(b==256)k=8;else if(b==2)k=1;else if(b==32)k=5;else if(b==4)k=2;else{this.fromRadix(s,b);return}this.t=0;this.s=0;var i=s.length,mi=false,sh=0;while(--i>=0){var x=k==8?s[i]&255:intAt(s,i);if(x<0){if(s.charAt(i)=="-")mi=true;continue}mi=false;if(sh==0)this[this.t++]=x;else if(sh+k>this.DB){this[this.t-1]|=(x&(1<<this.DB-sh)-1)<<sh;this[this.t++]=x>>this.DB-sh}else this[this.t-1]|=x<<sh;sh+=k;if(sh>=this.DB)sh-=this.DB}if(k==8&&(s[0]&128)!=0){this.s=-1;if(sh>0)this[this.t-1]|=(1<<this.DB-sh)-1<<sh}this.clamp();if(mi)BigInteger.ZERO.subTo(this,this)}function bnpClamp(){var c=this.s&this.DM;while(this.t>0&&this[this.t-1]==c)--this.t}function bnToString(b){if(this.s<0)return"-"+this.negate().toString(b);var k;if(b==16)k=4;else if(b==8)k=3;else if(b==2)k=1;else if(b==32)k=5;else if(b==4)k=2;else return this.toRadix(b);var km=(1<<k)-1,d,m=false,r="",i=this.t;var p=this.DB-i*this.DB%k;if(i-->0){if(p<this.DB&&(d=this[i]>>p)>0){m=true;r=int2char(d)}while(i>=0){if(p<k){d=(this[i]&(1<<p)-1)<<k-p;d|=this[--i]>>(p+=this.DB-k)}else{d=this[i]>>(p-=k)&km;if(p<=0){p+=this.DB;--i}}if(d>0)m=true;if(m)r+=int2char(d)}}return m?r:"0"}function bnNegate(){var r=nbi();BigInteger.ZERO.subTo(this,r);return r}function bnAbs(){return this.s<0?this.negate():this}function bnCompareTo(a){var r=this.s-a.s;if(r!=0)return r;var i=this.t;r=i-a.t;if(r!=0)return this.s<0?-r:r;while(--i>=0)if((r=this[i]-a[i])!=0)return r;return 0}function nbits(x){var r=1,t;if((t=x>>>16)!=0){x=t;r+=16}if((t=x>>8)!=0){x=t;r+=8}if((t=x>>4)!=0){x=t;r+=4}if((t=x>>2)!=0){x=t;r+=2}if((t=x>>1)!=0){x=t;r+=1}return r}function bnBitLength(){if(this.t<=0)return 0;return this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(n,r){var i;for(i=this.t-1;i>=0;--i)r[i+n]=this[i];for(i=n-1;i>=0;--i)r[i]=0;r.t=this.t+n;r.s=this.s}function bnpDRShiftTo(n,r){for(var i=n;i<this.t;++i)r[i-n]=this[i];r.t=Math.max(this.t-n,0);r.s=this.s}function bnpLShiftTo(n,r){var bs=n%this.DB;var cbs=this.DB-bs;var bm=(1<<cbs)-1;var ds=Math.floor(n/this.DB),c=this.s<<bs&this.DM,i;for(i=this.t-1;i>=0;--i){r[i+ds+1]=this[i]>>cbs|c;c=(this[i]&bm)<<bs}for(i=ds-1;i>=0;--i)r[i]=0;r[ds]=c;r.t=this.t+ds+1;r.s=this.s;r.clamp()}function bnpRShiftTo(n,r){r.s=this.s;var ds=Math.floor(n/this.DB);if(ds>=this.t){r.t=0;return}var bs=n%this.DB;var cbs=this.DB-bs;var bm=(1<<bs)-1;r[0]=this[ds]>>bs;for(var i=ds+1;i<this.t;++i){r[i-ds-1]|=(this[i]&bm)<<cbs;r[i-ds]=this[i]>>bs}if(bs>0)r[this.t-ds-1]|=(this.s&bm)<<cbs;r.t=this.t-ds;r.clamp()}function bnpSubTo(a,r){var i=0,c=0,m=Math.min(a.t,this.t);while(i<m){c+=this[i]-a[i];r[i++]=c&this.DM;c>>=this.DB}if(a.t<this.t){c-=a.s;while(i<this.t){c+=this[i];r[i++]=c&this.DM;c>>=this.DB}c+=this.s}else{c+=this.s;while(i<a.t){c-=a[i];r[i++]=c&this.DM;c>>=this.DB}c-=a.s}r.s=c<0?-1:0;if(c<-1)r[i++]=this.DV+c;else if(c>0)r[i++]=c;r.t=i;r.clamp()}function bnpMultiplyTo(a,r){var x=this.abs(),y=a.abs();var i=x.t;r.t=i+y.t;while(--i>=0)r[i]=0;for(i=0;i<y.t;++i)r[i+x.t]=x.am(0,y[i],r,i,0,x.t);r.s=0;r.clamp();if(this.s!=a.s)BigInteger.ZERO.subTo(r,r)}function bnpSquareTo(r){var x=this.abs();var i=r.t=2*x.t;while(--i>=0)r[i]=0;for(i=0;i<x.t-1;++i){var c=x.am(i,x[i],r,2*i,0,1);if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1))>=x.DV){r[i+x.t]-=x.DV;r[i+x.t+1]=1}}if(r.t>0)r[r.t-1]+=x.am(i,x[i],r,2*i,0,1);r.s=0;r.clamp()}function bnpDivRemTo(m,q,r){var pm=m.abs();if(pm.t<=0)return;var pt=this.abs();if(pt.t<pm.t){if(q!=null)q.fromInt(0);if(r!=null)this.copyTo(r);return}if(r==null)r=nbi();var y=nbi(),ts=this.s,ms=m.s;var nsh=this.DB-nbits(pm[pm.t-1]);if(nsh>0){pm.lShiftTo(nsh,y);pt.lShiftTo(nsh,r)}else{pm.copyTo(y);pt.copyTo(r)}var ys=y.t;var y0=y[ys-1];if(y0==0)return;var yt=y0*(1<<this.F1)+(ys>1?y[ys-2]>>this.F2:0);var d1=this.FV/yt,d2=(1<<this.F1)/yt,e=1<<this.F2;var i=r.t,j=i-ys,t=q==null?nbi():q;y.dlShiftTo(j,t);if(r.compareTo(t)>=0){r[r.t++]=1;r.subTo(t,r)}BigInteger.ONE.dlShiftTo(ys,t);t.subTo(y,y);while(y.t<ys)y[y.t++]=0;while(--j>=0){var qd=r[--i]==y0?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);if((r[i]+=y.am(0,qd,r,j,0,ys))<qd){y.dlShiftTo(j,t);r.subTo(t,r);while(r[i]<--qd)r.subTo(t,r)}}if(q!=null){r.drShiftTo(ys,q);if(ts!=ms)BigInteger.ZERO.subTo(q,q)}r.t=ys;r.clamp();if(nsh>0)r.rShiftTo(nsh,r);if(ts<0)BigInteger.ZERO.subTo(r,r)}function bnMod(a){var r=nbi();this.abs().divRemTo(a,null,r);if(this.s<0&&r.compareTo(BigInteger.ZERO)>0)a.subTo(r,r);return r}function Classic(m){this.m=m}function cConvert(x){if(x.s<0||x.compareTo(this.m)>=0)return x.mod(this.m);else return x}function cRevert(x){return x}function cReduce(x){x.divRemTo(this.m,null,x)}function cMulTo(x,y,r){x.multiplyTo(y,r);this.reduce(r)}function cSqrTo(x,r){x.squareTo(r);this.reduce(r)}Classic.prototype.convert=cConvert;Classic.prototype.revert=cRevert;Classic.prototype.reduce=cReduce;Classic.prototype.mulTo=cMulTo;Classic.prototype.sqrTo=cSqrTo;function bnpInvDigit(){if(this.t<1)return 0;var x=this[0];if((x&1)==0)return 0;var y=x&3;y=y*(2-(x&15)*y)&15;y=y*(2-(x&255)*y)&255;y=y*(2-((x&65535)*y&65535))&65535;y=y*(2-x*y%this.DV)%this.DV;return y>0?this.DV-y:-y}function Montgomery(m){this.m=m;this.mp=m.invDigit();this.mpl=this.mp&32767;this.mph=this.mp>>15;this.um=(1<<m.DB-15)-1;this.mt2=2*m.t}function montConvert(x){var r=nbi();x.abs().dlShiftTo(this.m.t,r);r.divRemTo(this.m,null,r);if(x.s<0&&r.compareTo(BigInteger.ZERO)>0)this.m.subTo(r,r);return r}function montRevert(x){var r=nbi();x.copyTo(r);this.reduce(r);return r}function montReduce(x){while(x.t<=this.mt2)x[x.t++]=0;for(var i=0;i<this.m.t;++i){var j=x[i]&32767;var u0=j*this.mpl+((j*this.mph+(x[i]>>15)*this.mpl&this.um)<<15)&x.DM;j=i+this.m.t;x[j]+=this.m.am(0,u0,x,i,0,this.m.t);while(x[j]>=x.DV){x[j]-=x.DV;x[++j]++}}x.clamp();x.drShiftTo(this.m.t,x);if(x.compareTo(this.m)>=0)x.subTo(this.m,x)}function montSqrTo(x,r){x.squareTo(r);this.reduce(r)}function montMulTo(x,y,r){x.multiplyTo(y,r);this.reduce(r)}Montgomery.prototype.convert=montConvert;Montgomery.prototype.revert=montRevert;Montgomery.prototype.reduce=montReduce;Montgomery.prototype.mulTo=montMulTo;Montgomery.prototype.sqrTo=montSqrTo;function bnpIsEven(){return(this.t>0?this[0]&1:this.s)==0}function bnpExp(e,z){if(e>4294967295||e<1)return BigInteger.ONE;var r=nbi(),r2=nbi(),g=z.convert(this),i=nbits(e)-1;g.copyTo(r);while(--i>=0){z.sqrTo(r,r2);if((e&1<<i)>0)z.mulTo(r2,g,r);else{var t=r;r=r2;r2=t}}return z.revert(r)}function bnModPowInt(e,m){var z;if(e<256||m.isEven())z=new Classic(m);else z=new Montgomery(m);return this.exp(e,z)}BigInteger.prototype.copyTo=bnpCopyTo;BigInteger.prototype.fromInt=bnpFromInt;BigInteger.prototype.fromString=bnpFromString;BigInteger.prototype.clamp=bnpClamp;BigInteger.prototype.dlShiftTo=bnpDLShiftTo;BigInteger.prototype.drShiftTo=bnpDRShiftTo;BigInteger.prototype.lShiftTo=bnpLShiftTo;BigInteger.prototype.rShiftTo=bnpRShiftTo;BigInteger.prototype.subTo=bnpSubTo;BigInteger.prototype.multiplyTo=bnpMultiplyTo;BigInteger.prototype.squareTo=bnpSquareTo;BigInteger.prototype.divRemTo=bnpDivRemTo;BigInteger.prototype.invDigit=bnpInvDigit;BigInteger.prototype.isEven=bnpIsEven;BigInteger.prototype.exp=bnpExp;BigInteger.prototype.toString=bnToString;BigInteger.prototype.negate=bnNegate;BigInteger.prototype.abs=bnAbs;BigInteger.prototype.compareTo=bnCompareTo;BigInteger.prototype.bitLength=bnBitLength;BigInteger.prototype.mod=bnMod;BigInteger.prototype.modPowInt=bnModPowInt;BigInteger.ZERO=nbv(0);BigInteger.ONE=nbv(1);function bnpFromRadix(s,b){this.fromInt(0);if(b==null)b=10;var cs=this.chunkSize(b);var d=Math.pow(b,cs),mi=false,j=0,w=0;for(var i=0;i<s.length;++i){var x=intAt(s,i);if(x<0){if(s.charAt(i)=="-"&&this.signum()==0)mi=true;continue}w=b*w+x;if(++j>=cs){this.dMultiply(d);this.dAddOffset(w,0);j=0;w=0}}if(j>0){this.dMultiply(Math.pow(b,j));this.dAddOffset(w,0)}if(mi)BigInteger.ZERO.subTo(this,this)}function bnpChunkSize(r){return Math.floor(Math.LN2*this.DB/Math.log(r))}function bnSigNum(){if(this.s<0)return-1;else if(this.t<=0||this.t==1&&this[0]<=0)return 0;else return 1}function bnpDMultiply(n){this[this.t]=this.am(0,n-1,this,0,0,this.t);++this.t;this.clamp()}function bnpDAddOffset(n,w){if(n==0)return;while(this.t<=w)this[this.t++]=0;this[w]+=n;while(this[w]>=this.DV){this[w]-=this.DV;if(++w>=this.t)this[this.t++]=0;++this[w]}}function bnpToRadix(b){if(b==null)b=10;if(this.signum()==0||b<2||b>36)return"0";var cs=this.chunkSize(b);var a=Math.pow(b,cs);var d=nbv(a),y=nbi(),z=nbi(),r="";this.divRemTo(d,y,z);while(y.signum()>0){r=(a+z.intValue()).toString(b).substr(1)+r;y.divRemTo(d,y,z)}return z.intValue().toString(b)+r}function bnIntValue(){if(this.s<0){if(this.t==1)return this[0]-this.DV;else if(this.t==0)return-1}else if(this.t==1)return this[0];else if(this.t==0)return 0;return(this[1]&(1<<32-this.DB)-1)<<this.DB|this[0]}function bnpAddTo(a,r){var i=0,c=0,m=Math.min(a.t,this.t);while(i<m){c+=this[i]+a[i];r[i++]=c&this.DM;c>>=this.DB}if(a.t<this.t){c+=a.s;while(i<this.t){c+=this[i];r[i++]=c&this.DM;c>>=this.DB}c+=this.s}else{c+=this.s;while(i<a.t){c+=a[i];r[i++]=c&this.DM;c>>=this.DB}c+=a.s}r.s=c<0?-1:0;if(c>0)r[i++]=c;else if(c<-1)r[i++]=this.DV+c;r.t=i;r.clamp()}BigInteger.prototype.fromRadix=bnpFromRadix;BigInteger.prototype.chunkSize=bnpChunkSize;BigInteger.prototype.signum=bnSigNum;BigInteger.prototype.dMultiply=bnpDMultiply;BigInteger.prototype.dAddOffset=bnpDAddOffset;BigInteger.prototype.toRadix=bnpToRadix;BigInteger.prototype.intValue=bnIntValue;BigInteger.prototype.addTo=bnpAddTo;var Wrapper={abs:(function(l,h){var x=new goog.math.Long(l,h);var ret;if(x.isNegative()){ret=x.negate()}else{ret=x}HEAP32[tempDoublePtr>>2]=ret.low_;HEAP32[tempDoublePtr+4>>2]=ret.high_}),ensureTemps:(function(){if(Wrapper.ensuredTemps)return;Wrapper.ensuredTemps=true;Wrapper.two32=new BigInteger;Wrapper.two32.fromString("4294967296",10);Wrapper.two64=new BigInteger;Wrapper.two64.fromString("18446744073709551616",10);Wrapper.temp1=new BigInteger;Wrapper.temp2=new BigInteger}),lh2bignum:(function(l,h){var a=new BigInteger;a.fromString(h.toString(),10);var b=new BigInteger;a.multiplyTo(Wrapper.two32,b);var c=new BigInteger;c.fromString(l.toString(),10);var d=new BigInteger;c.addTo(b,d);return d}),stringify:(function(l,h,unsigned){var ret=(new goog.math.Long(l,h)).toString();if(unsigned&&ret[0]=="-"){Wrapper.ensureTemps();var bignum=new BigInteger;bignum.fromString(ret,10);ret=new BigInteger;Wrapper.two64.addTo(bignum,ret);ret=ret.toString(10)}return ret}),fromString:(function(str,base,min,max,unsigned){Wrapper.ensureTemps();var bignum=new BigInteger;bignum.fromString(str,base);var bigmin=new BigInteger;bigmin.fromString(min,10);var bigmax=new BigInteger;bigmax.fromString(max,10);if(unsigned&&bignum.compareTo(BigInteger.ZERO)<0){var temp=new BigInteger;bignum.addTo(Wrapper.two64,temp);bignum=temp}var error=false;if(bignum.compareTo(bigmin)<0){bignum=bigmin;error=true}else if(bignum.compareTo(bigmax)>0){bignum=bigmax;error=true}var ret=goog.math.Long.fromString(bignum.toString());HEAP32[tempDoublePtr>>2]=ret.low_;HEAP32[tempDoublePtr+4>>2]=ret.high_;if(error)throw"range error"})};return Wrapper})();function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}ExitStatus.prototype=new Error;ExitStatus.prototype.constructor=ExitStatus;var initialStackTop;var preloadStartTime=null;var calledMain=false;dependenciesFulfilled=function runCaller(){if(!Module["calledRun"])run();if(!Module["calledRun"])dependenciesFulfilled=runCaller};Module["callMain"]=Module.callMain=function callMain(args){assert(runDependencies==0,"cannot call main when async dependencies remain! (listen on __ATMAIN__)");assert(__ATPRERUN__.length==0,"cannot call main when preRun functions remain to be called");args=args||[];ensureInitRuntime();var argc=args.length+1;function pad(){for(var i=0;i<4-1;i++){argv.push(0)}}var argv=[allocate(intArrayFromString(Module["thisProgram"]),"i8",ALLOC_NORMAL)];pad();for(var i=0;i<argc-1;i=i+1){argv.push(allocate(intArrayFromString(args[i]),"i8",ALLOC_NORMAL));pad()}argv.push(0);argv=allocate(argv,"i32",ALLOC_NORMAL);initialStackTop=STACKTOP;try{var ret=Module["_main"](argc,argv,0);exit(ret,true)}catch(e){if(e instanceof ExitStatus){return}else if(e=="SimulateInfiniteLoop"){Module["noExitRuntime"]=true;return}else{if(e&&typeof e==="object"&&e.stack)Module.printErr("exception thrown: "+[e,e.stack]);throw e}}finally{calledMain=true}};function run(args){args=args||Module["arguments"];if(preloadStartTime===null)preloadStartTime=Date.now();if(runDependencies>0){return}preRun();if(runDependencies>0)return;if(Module["calledRun"])return;function doRun(){if(Module["calledRun"])return;Module["calledRun"]=true;if(ABORT)return;ensureInitRuntime();preMain();if(ENVIRONMENT_IS_WEB&&preloadStartTime!==null){Module.printErr("pre-main prep time: "+(Date.now()-preloadStartTime)+" ms")}if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(Module["_main"]&&shouldRunNow)Module["callMain"](args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout((function(){setTimeout((function(){Module["setStatus"]("")}),1);doRun()}),1)}else{doRun()}}Module["run"]=Module.run=run;function exit(status,implicit){if(implicit&&Module["noExitRuntime"]){return}if(Module["noExitRuntime"]){}else{ABORT=true;EXITSTATUS=status;STACKTOP=initialStackTop;exitRuntime();if(Module["onExit"])Module["onExit"](status)}if(ENVIRONMENT_IS_NODE){process["stdout"]["once"]("drain",(function(){process["exit"](status)}));console.log(" ");setTimeout((function(){process["exit"](status)}),500)}else if(ENVIRONMENT_IS_SHELL&&typeof quit==="function"){quit(status)}throw new ExitStatus(status)}Module["exit"]=Module.exit=exit;var abortDecorators=[];function abort(what){if(what!==undefined){Module.print(what);Module.printErr(what);what=JSON.stringify(what)}else{what=""}ABORT=true;EXITSTATUS=1;var extra="\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.";var output="abort("+what+") at "+stackTrace()+extra;if(abortDecorators){abortDecorators.forEach((function(decorator){output=decorator(output,what)}))}throw output}Module["abort"]=Module.abort=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=false;if(Module["noInitialRun"]){shouldRunNow=false}Module["noExitRuntime"]=true;run();var inputBuffer,inputBufferSize;function reallocInputBuffer(size){if(inputBuffer&&inputBufferSize>=size){return inputBuffer}if(inputBuffer){Module._free(inputBuffer)}inputBufferSize=size;inputBuffer=Module._malloc(inputBufferSize);return inputBuffer}Module.loadedMetadata=!!options.audioFormat;Module.audioFormat=options.audioFormat||null;Module.audioBuffer=null;Object.defineProperty(Module,"processing",{get:function getProcessing(){return false}});Module.init=(function(callback){Module._ogv_audio_decoder_init();callback()});Module.processHeader=(function(data,callback){var len=data.byteLength;var buffer=reallocInputBuffer(len);Module.HEAPU8.set(new Uint8Array(data),buffer);var ret=Module._ogv_audio_decoder_process_header(buffer,len);callback(ret)});Module.processAudio=(function(data,callback){var len=data.byteLength;var buffer=reallocInputBuffer(len);Module.HEAPU8.set(new Uint8Array(data),buffer);var ret=Module._ogv_audio_decoder_process_audio(buffer,len);callback(ret)})
+
+
+
+
+
+ return Module;
+};
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-decoder-audio-vorbis.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-decoder-audio-vorbis.js
new file mode 100644
index 00000000..7815d228
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-decoder-audio-vorbis.js
@@ -0,0 +1,23 @@
+var OGVDecoderAudioVorbis = function(Module) {
+ Module = Module || {};
+
+var options=Module;Module={print:(function(str){console.log(str)})};var Module;if(!Module)Module=(typeof OGVDecoderAudioVorbis!=="undefined"?OGVDecoderAudioVorbis:null)||{};var moduleOverrides={};for(var key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var ENVIRONMENT_IS_WEB=typeof window==="object";var ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof require==="function"&&!ENVIRONMENT_IS_WEB;var ENVIRONMENT_IS_WORKER=typeof importScripts==="function";var ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){if(!Module["print"])Module["print"]=function print(x){process["stdout"].write(x+"\n")};if(!Module["printErr"])Module["printErr"]=function printErr(x){process["stderr"].write(x+"\n")};var nodeFS=require("fs");var nodePath=require("path");Module["read"]=function read(filename,binary){filename=nodePath["normalize"](filename);var ret=nodeFS["readFileSync"](filename);if(!ret&&filename!=nodePath["resolve"](filename)){filename=path.join(__dirname,"..","src",filename);ret=nodeFS["readFileSync"](filename)}if(ret&&!binary)ret=ret.toString();return ret};Module["readBinary"]=function readBinary(filename){return Module["read"](filename,true)};Module["load"]=function load(f){globalEval(read(f))};if(!Module["thisProgram"]){if(process["argv"].length>1){Module["thisProgram"]=process["argv"][1].replace(/\\/g,"/")}else{Module["thisProgram"]="unknown-program"}}Module["arguments"]=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",(function(ex){if(!(ex instanceof ExitStatus)){throw ex}}));Module["inspect"]=(function(){return"[Emscripten Module object]"})}else if(ENVIRONMENT_IS_SHELL){if(!Module["print"])Module["print"]=print;if(typeof printErr!="undefined")Module["printErr"]=printErr;if(typeof read!="undefined"){Module["read"]=read}else{Module["read"]=function read(){throw"no read() available (jsc?)"}}Module["readBinary"]=function readBinary(f){if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}var data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){Module["arguments"]=scriptArgs}else if(typeof arguments!="undefined"){Module["arguments"]=arguments}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){Module["read"]=function read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(typeof arguments!="undefined"){Module["arguments"]=arguments}if(typeof console!=="undefined"){if(!Module["print"])Module["print"]=function print(x){console.log(x)};if(!Module["printErr"])Module["printErr"]=function printErr(x){console.log(x)}}else{var TRY_USE_DUMP=false;if(!Module["print"])Module["print"]=TRY_USE_DUMP&&typeof dump!=="undefined"?(function(x){dump(x)}):(function(x){})}if(ENVIRONMENT_IS_WORKER){Module["load"]=importScripts}if(typeof Module["setWindowTitle"]==="undefined"){Module["setWindowTitle"]=(function(title){document.title=title})}}else{throw"Unknown runtime environment. Where are we?"}function globalEval(x){eval.call(null,x)}if(!Module["load"]&&Module["read"]){Module["load"]=function load(f){globalEval(Module["read"](f))}}if(!Module["print"]){Module["print"]=(function(){})}if(!Module["printErr"]){Module["printErr"]=Module["print"]}if(!Module["arguments"]){Module["arguments"]=[]}if(!Module["thisProgram"]){Module["thisProgram"]="./this.program"}Module.print=Module["print"];Module.printErr=Module["printErr"];Module["preRun"]=[];Module["postRun"]=[];for(var key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}var Runtime={setTempRet0:(function(value){tempRet0=value}),getTempRet0:(function(){return tempRet0}),stackSave:(function(){return STACKTOP}),stackRestore:(function(stackTop){STACKTOP=stackTop}),getNativeTypeSize:(function(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return Runtime.QUANTUM_SIZE}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0);return bits/8}else{return 0}}}}),getNativeFieldSize:(function(type){return Math.max(Runtime.getNativeTypeSize(type),Runtime.QUANTUM_SIZE)}),STACK_ALIGN:16,prepVararg:(function(ptr,type){if(type==="double"||type==="i64"){if(ptr&7){assert((ptr&7)===4);ptr+=4}}else{assert((ptr&3)===0)}return ptr}),getAlignSize:(function(type,size,vararg){if(!vararg&&(type=="i64"||type=="double"))return 8;if(!type)return Math.min(size,8);return Math.min(size||(type?Runtime.getNativeFieldSize(type):0),Runtime.QUANTUM_SIZE)}),dynCall:(function(sig,ptr,args){if(args&&args.length){if(!args.splice)args=Array.prototype.slice.call(args);args.splice(0,0,ptr);return Module["dynCall_"+sig].apply(null,args)}else{return Module["dynCall_"+sig].call(null,ptr)}}),functionPointers:[],addFunction:(function(func){for(var i=0;i<Runtime.functionPointers.length;i++){if(!Runtime.functionPointers[i]){Runtime.functionPointers[i]=func;return 2*(1+i)}}throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS."}),removeFunction:(function(index){Runtime.functionPointers[(index-2)/2]=null}),warnOnce:(function(text){if(!Runtime.warnOnce.shown)Runtime.warnOnce.shown={};if(!Runtime.warnOnce.shown[text]){Runtime.warnOnce.shown[text]=1;Module.printErr(text)}}),funcWrappers:{},getFuncWrapper:(function(func,sig){assert(sig);if(!Runtime.funcWrappers[sig]){Runtime.funcWrappers[sig]={}}var sigCache=Runtime.funcWrappers[sig];if(!sigCache[func]){sigCache[func]=function dynCall_wrapper(){return Runtime.dynCall(sig,func,arguments)}}return sigCache[func]}),getCompilerSetting:(function(name){throw"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work"}),stackAlloc:(function(size){var ret=STACKTOP;STACKTOP=STACKTOP+size|0;STACKTOP=STACKTOP+15&-16;return ret}),staticAlloc:(function(size){var ret=STATICTOP;STATICTOP=STATICTOP+size|0;STATICTOP=STATICTOP+15&-16;return ret}),dynamicAlloc:(function(size){var ret=DYNAMICTOP;DYNAMICTOP=DYNAMICTOP+size|0;DYNAMICTOP=DYNAMICTOP+15&-16;if(DYNAMICTOP>=TOTAL_MEMORY){var success=enlargeMemory();if(!success){DYNAMICTOP=ret;return 0}}return ret}),alignMemory:(function(size,quantum){var ret=size=Math.ceil(size/(quantum?quantum:16))*(quantum?quantum:16);return ret}),makeBigInt:(function(low,high,unsigned){var ret=unsigned?+(low>>>0)+ +(high>>>0)*+4294967296:+(low>>>0)+ +(high|0)*+4294967296;return ret}),GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module["Runtime"]=Runtime;var __THREW__=0;var ABORT=false;var EXITSTATUS=0;var undef=0;var tempValue,tempInt,tempBigInt,tempInt2,tempBigInt2,tempPair,tempBigIntI,tempBigIntR,tempBigIntS,tempBigIntP,tempBigIntD,tempDouble,tempFloat;var tempI64,tempI64b;var tempRet0,tempRet1,tempRet2,tempRet3,tempRet4,tempRet5,tempRet6,tempRet7,tempRet8,tempRet9;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var globalScope=this;function getCFunc(ident){var func=Module["_"+ident];if(!func){try{func=eval("_"+ident)}catch(e){}}assert(func,"Cannot call unknown function "+ident+" (perhaps LLVM optimizations or closure removed it?)");return func}var cwrap,ccall;((function(){var JSfuncs={"stackSave":(function(){Runtime.stackSave()}),"stackRestore":(function(){Runtime.stackRestore()}),"arrayToC":(function(arr){var ret=Runtime.stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}),"stringToC":(function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=Runtime.stackAlloc((str.length<<2)+1);writeStringToMemory(str,ret)}return ret})};var toC={"string":JSfuncs["stringToC"],"array":JSfuncs["arrayToC"]};ccall=function ccallFunc(ident,returnType,argTypes,args,opts){var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=Runtime.stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func.apply(null,cArgs);if(returnType==="string")ret=Pointer_stringify(ret);if(stack!==0){if(opts&&opts.async){EmterpreterAsync.asyncFinalizers.push((function(){Runtime.stackRestore(stack)}));return}Runtime.stackRestore(stack)}return ret};var sourceRegex=/^function\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/;function parseJSFunc(jsfunc){var parsed=jsfunc.toString().match(sourceRegex).slice(1);return{arguments:parsed[0],body:parsed[1],returnValue:parsed[2]}}var JSsource={};for(var fun in JSfuncs){if(JSfuncs.hasOwnProperty(fun)){JSsource[fun]=parseJSFunc(JSfuncs[fun])}}cwrap=function cwrap(ident,returnType,argTypes){argTypes=argTypes||[];var cfunc=getCFunc(ident);var numericArgs=argTypes.every((function(type){return type==="number"}));var numericRet=returnType!=="string";if(numericRet&&numericArgs){return cfunc}var argNames=argTypes.map((function(x,i){return"$"+i}));var funcstr="(function("+argNames.join(",")+") {";var nargs=argTypes.length;if(!numericArgs){funcstr+="var stack = "+JSsource["stackSave"].body+";";for(var i=0;i<nargs;i++){var arg=argNames[i],type=argTypes[i];if(type==="number")continue;var convertCode=JSsource[type+"ToC"];funcstr+="var "+convertCode.arguments+" = "+arg+";";funcstr+=convertCode.body+";";funcstr+=arg+"="+convertCode.returnValue+";"}}var cfuncname=parseJSFunc((function(){return cfunc})).returnValue;funcstr+="var ret = "+cfuncname+"("+argNames.join(",")+");";if(!numericRet){var strgfy=parseJSFunc((function(){return Pointer_stringify})).returnValue;funcstr+="ret = "+strgfy+"(ret);"}if(!numericArgs){funcstr+=JSsource["stackRestore"].body.replace("()","(stack)")+";"}funcstr+="return ret})";return eval(funcstr)}}))();Module["cwrap"]=cwrap;Module["ccall"]=ccall;function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble- +(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}Module["setValue"]=setValue;function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for setValue: "+type)}return null}Module["getValue"]=getValue;var ALLOC_NORMAL=0;var ALLOC_STACK=1;var ALLOC_STATIC=2;var ALLOC_DYNAMIC=3;var ALLOC_NONE=4;Module["ALLOC_NORMAL"]=ALLOC_NORMAL;Module["ALLOC_STACK"]=ALLOC_STACK;Module["ALLOC_STATIC"]=ALLOC_STATIC;Module["ALLOC_DYNAMIC"]=ALLOC_DYNAMIC;Module["ALLOC_NONE"]=ALLOC_NONE;function allocate(slab,types,allocator,ptr){var zeroinit,size;if(typeof slab==="number"){zeroinit=true;size=slab}else{zeroinit=false;size=slab.length}var singleType=typeof types==="string"?types:null;var ret;if(allocator==ALLOC_NONE){ret=ptr}else{ret=[_malloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][allocator===undefined?ALLOC_STATIC:allocator](Math.max(size,singleType?1:types.length))}if(zeroinit){var ptr=ret,stop;assert((ret&3)==0);stop=ret+(size&~3);for(;ptr<stop;ptr+=4){HEAP32[ptr>>2]=0}stop=ret+size;while(ptr<stop){HEAP8[ptr++>>0]=0}return ret}if(singleType==="i8"){if(slab.subarray||slab.slice){HEAPU8.set(slab,ret)}else{HEAPU8.set(new Uint8Array(slab),ret)}return ret}var i=0,type,typeSize,previousType;while(i<size){var curr=slab[i];if(typeof curr==="function"){curr=Runtime.getFunctionIndex(curr)}type=singleType||types[i];if(type===0){i++;continue}if(type=="i64")type="i32";setValue(ret+i,curr,type);if(previousType!==type){typeSize=Runtime.getNativeTypeSize(type);previousType=type}i+=typeSize}return ret}Module["allocate"]=allocate;function getMemory(size){if(!staticSealed)return Runtime.staticAlloc(size);if(typeof _sbrk!=="undefined"&&!_sbrk.called||!runtimeInitialized)return Runtime.dynamicAlloc(size);return _malloc(size)}Module["getMemory"]=getMemory;function Pointer_stringify(ptr,length){if(length===0||!ptr)return"";var hasUtf=0;var t;var i=0;while(1){t=HEAPU8[ptr+i>>0];hasUtf|=t;if(t==0&&!length)break;i++;if(length&&i==length)break}if(!length)length=i;var ret="";if(hasUtf<128){var MAX_CHUNK=1024;var curr;while(length>0){curr=String.fromCharCode.apply(String,HEAPU8.subarray(ptr,ptr+Math.min(length,MAX_CHUNK)));ret=ret?ret+curr:curr;ptr+=MAX_CHUNK;length-=MAX_CHUNK}return ret}return Module["UTF8ToString"](ptr)}Module["Pointer_stringify"]=Pointer_stringify;function AsciiToString(ptr){var str="";while(1){var ch=HEAP8[ptr++>>0];if(!ch)return str;str+=String.fromCharCode(ch)}}Module["AsciiToString"]=AsciiToString;function stringToAscii(str,outPtr){return writeAsciiToMemory(str,outPtr,false)}Module["stringToAscii"]=stringToAscii;function UTF8ArrayToString(u8Array,idx){var u0,u1,u2,u3,u4,u5;var str="";while(1){u0=u8Array[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}u1=u8Array[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}u2=u8Array[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u3=u8Array[idx++]&63;if((u0&248)==240){u0=(u0&7)<<18|u1<<12|u2<<6|u3}else{u4=u8Array[idx++]&63;if((u0&252)==248){u0=(u0&3)<<24|u1<<18|u2<<12|u3<<6|u4}else{u5=u8Array[idx++]&63;u0=(u0&1)<<30|u1<<24|u2<<18|u3<<12|u4<<6|u5}}}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}Module["UTF8ArrayToString"]=UTF8ArrayToString;function UTF8ToString(ptr){return UTF8ArrayToString(HEAPU8,ptr)}Module["UTF8ToString"]=UTF8ToString;function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=2097151){if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=67108863){if(outIdx+4>=endIdx)break;outU8Array[outIdx++]=248|u>>24;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+5>=endIdx)break;outU8Array[outIdx++]=252|u>>30;outU8Array[outIdx++]=128|u>>24&63;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}Module["stringToUTF8Array"]=stringToUTF8Array;function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}Module["stringToUTF8"]=stringToUTF8;function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){++len}else if(u<=2047){len+=2}else if(u<=65535){len+=3}else if(u<=2097151){len+=4}else if(u<=67108863){len+=5}else{len+=6}}return len}Module["lengthBytesUTF8"]=lengthBytesUTF8;function UTF16ToString(ptr){var i=0;var str="";while(1){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)return str;++i;str+=String.fromCharCode(codeUnit)}}Module["UTF16ToString"]=UTF16ToString;function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite<str.length*2?maxBytesToWrite/2:str.length;for(var i=0;i<numCharsToWrite;++i){var codeUnit=str.charCodeAt(i);HEAP16[outPtr>>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}Module["stringToUTF16"]=stringToUTF16;function lengthBytesUTF16(str){return str.length*2}Module["lengthBytesUTF16"]=lengthBytesUTF16;function UTF32ToString(ptr){var i=0;var str="";while(1){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)return str;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}}Module["UTF32ToString"]=UTF32ToString;function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);if(codeUnit>=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}Module["stringToUTF32"]=stringToUTF32;function lengthBytesUTF32(str){var len=0;for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);if(codeUnit>=55296&&codeUnit<=57343)++i;len+=4}return len}Module["lengthBytesUTF32"]=lengthBytesUTF32;function demangle(func){var hasLibcxxabi=!!Module["___cxa_demangle"];if(hasLibcxxabi){try{var buf=_malloc(func.length);writeStringToMemory(func.substr(1),buf);var status=_malloc(4);var ret=Module["___cxa_demangle"](buf,0,0,status);if(getValue(status,"i32")===0&&ret){return Pointer_stringify(ret)}}catch(e){}finally{if(buf)_free(buf);if(status)_free(status);if(ret)_free(ret)}}var i=3;var basicTypes={"v":"void","b":"bool","c":"char","s":"short","i":"int","l":"long","f":"float","d":"double","w":"wchar_t","a":"signed char","h":"unsigned char","t":"unsigned short","j":"unsigned int","m":"unsigned long","x":"long long","y":"unsigned long long","z":"..."};var subs=[];var first=true;function dump(x){if(x)Module.print(x);Module.print(func);var pre="";for(var a=0;a<i;a++)pre+=" ";Module.print(pre+"^")}function parseNested(){i++;if(func[i]==="K")i++;var parts=[];while(func[i]!=="E"){if(func[i]==="S"){i++;var next=func.indexOf("_",i);var num=func.substring(i,next)||0;parts.push(subs[num]||"?");i=next+1;continue}if(func[i]==="C"){parts.push(parts[parts.length-1]);i+=2;continue}var size=parseInt(func.substr(i));var pre=size.toString().length;if(!size||!pre){i--;break}var curr=func.substr(i+pre,size);parts.push(curr);subs.push(curr);i+=pre+size}i++;return parts}function parse(rawList,limit,allowVoid){limit=limit||Infinity;var ret="",list=[];function flushList(){return"("+list.join(", ")+")"}var name;if(func[i]==="N"){name=parseNested().join("::");limit--;if(limit===0)return rawList?[name]:name}else{if(func[i]==="K"||first&&func[i]==="L")i++;var size=parseInt(func.substr(i));if(size){var pre=size.toString().length;name=func.substr(i+pre,size);i+=pre+size}}first=false;if(func[i]==="I"){i++;var iList=parse(true);var iRet=parse(true,1,true);ret+=iRet[0]+" "+name+"<"+iList.join(", ")+">"}else{ret=name}paramLoop:while(i<func.length&&limit-->0){var c=func[i++];if(c in basicTypes){list.push(basicTypes[c])}else{switch(c){case"P":list.push(parse(true,1,true)[0]+"*");break;case"R":list.push(parse(true,1,true)[0]+"&");break;case"L":{i++;var end=func.indexOf("E",i);var size=end-i;list.push(func.substr(i,size));i+=size+2;break};case"A":{var size=parseInt(func.substr(i));i+=size.toString().length;if(func[i]!=="_")throw"?";i++;list.push(parse(true,1,true)[0]+" ["+size+"]");break};case"E":break paramLoop;default:ret+="?"+c;break paramLoop}}}if(!allowVoid&&list.length===1&&list[0]==="void")list=[];if(rawList){if(ret){list.push(ret+"?")}return list}else{return ret+flushList()}}var parsed=func;try{if(func=="Object._main"||func=="_main"){return"main()"}if(typeof func==="number")func=Pointer_stringify(func);if(func[0]!=="_")return func;if(func[1]!=="_")return func;if(func[2]!=="Z")return func;switch(func[3]){case"n":return"operator new()";case"d":return"operator delete()"}parsed=parse()}catch(e){parsed+="?"}if(parsed.indexOf("?")>=0&&!hasLibcxxabi){Runtime.warnOnce("warning: a problem occurred in builtin C++ name demangling; build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling")}return parsed}function demangleAll(text){return text.replace(/__Z[\w\d_]+/g,(function(x){var y=demangle(x);return x===y?x:x+" ["+y+"]"}))}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){return demangleAll(jsStackTrace())}Module["stackTrace"]=stackTrace;var PAGE_SIZE=4096;function alignMemoryPage(x){if(x%4096>0){x+=4096-x%4096}return x}var HEAP;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var STATIC_BASE=0,STATICTOP=0,staticSealed=false;var STACK_BASE=0,STACKTOP=0,STACK_MAX=0;var DYNAMIC_BASE=0,DYNAMICTOP=0;function enlargeMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.")}var TOTAL_STACK=Module["TOTAL_STACK"]||5242880;var TOTAL_MEMORY=Module["TOTAL_MEMORY"]||16777216;var totalMemory=64*1024;while(totalMemory<TOTAL_MEMORY||totalMemory<2*TOTAL_STACK){if(totalMemory<16*1024*1024){totalMemory*=2}else{totalMemory+=16*1024*1024}}if(totalMemory!==TOTAL_MEMORY){Module.printErr("increasing TOTAL_MEMORY to "+totalMemory+" to be compliant with the asm.js spec (and given that TOTAL_STACK="+TOTAL_STACK+")");TOTAL_MEMORY=totalMemory}assert(typeof Int32Array!=="undefined"&&typeof Float64Array!=="undefined"&&!!(new Int32Array(1))["subarray"]&&!!(new Int32Array(1))["set"],"JS engine does not provide full typed array support");var buffer;buffer=new ArrayBuffer(TOTAL_MEMORY);HEAP8=new Int8Array(buffer);HEAP16=new Int16Array(buffer);HEAP32=new Int32Array(buffer);HEAPU8=new Uint8Array(buffer);HEAPU16=new Uint16Array(buffer);HEAPU32=new Uint32Array(buffer);HEAPF32=new Float32Array(buffer);HEAPF64=new Float64Array(buffer);HEAP32[0]=255;assert(HEAPU8[0]===255&&HEAPU8[3]===0,"Typed arrays 2 must be run on a little-endian system");Module["HEAP"]=HEAP;Module["buffer"]=buffer;Module["HEAP8"]=HEAP8;Module["HEAP16"]=HEAP16;Module["HEAP32"]=HEAP32;Module["HEAPU8"]=HEAPU8;Module["HEAPU16"]=HEAPU16;Module["HEAPU32"]=HEAPU32;Module["HEAPF32"]=HEAPF32;Module["HEAPF64"]=HEAPF64;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Runtime.dynCall("v",func)}else{Runtime.dynCall("vi",func,[callback.arg])}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){if(runtimeInitialized)return;runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__);runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}Module["addOnPreRun"]=Module.addOnPreRun=addOnPreRun;function addOnInit(cb){__ATINIT__.unshift(cb)}Module["addOnInit"]=Module.addOnInit=addOnInit;function addOnPreMain(cb){__ATMAIN__.unshift(cb)}Module["addOnPreMain"]=Module.addOnPreMain=addOnPreMain;function addOnExit(cb){__ATEXIT__.unshift(cb)}Module["addOnExit"]=Module.addOnExit=addOnExit;function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}Module["addOnPostRun"]=Module.addOnPostRun=addOnPostRun;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}Module["intArrayFromString"]=intArrayFromString;function intArrayToString(array){var ret=[];for(var i=0;i<array.length;i++){var chr=array[i];if(chr>255){chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}Module["intArrayToString"]=intArrayToString;function writeStringToMemory(string,buffer,dontAddNull){var array=intArrayFromString(string,dontAddNull);var i=0;while(i<array.length){var chr=array[i];HEAP8[buffer+i>>0]=chr;i=i+1}}Module["writeStringToMemory"]=writeStringToMemory;function writeArrayToMemory(array,buffer){for(var i=0;i<array.length;i++){HEAP8[buffer++>>0]=array[i]}}Module["writeArrayToMemory"]=writeArrayToMemory;function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i<str.length;++i){HEAP8[buffer++>>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}Module["writeAsciiToMemory"]=writeAsciiToMemory;function unSign(value,bits,ignore){if(value>=0){return value}return bits<=32?2*Math.abs(1<<bits-1)+value:Math.pow(2,bits)+value}function reSign(value,bits,ignore){if(value<=0){return value}var half=bits<=32?Math.abs(1<<bits-1):Math.pow(2,bits-1);if(value>=half&&(bits<=32||value>half)){value=-2*half+value}return value}if(!Math["imul"]||Math["imul"](4294967295,5)!==-5)Math["imul"]=function imul(a,b){var ah=a>>>16;var al=a&65535;var bh=b>>>16;var bl=b&65535;return al*bl+(ah*bl+al*bh<<16)|0};Math.imul=Math["imul"];if(!Math["clz32"])Math["clz32"]=(function(x){x=x>>>0;for(var i=0;i<32;i++){if(x&1<<31-i)return i}return 32});Math.clz32=Math["clz32"];var Math_abs=Math.abs;var Math_cos=Math.cos;var Math_sin=Math.sin;var Math_tan=Math.tan;var Math_acos=Math.acos;var Math_asin=Math.asin;var Math_atan=Math.atan;var Math_atan2=Math.atan2;var Math_exp=Math.exp;var Math_log=Math.log;var Math_sqrt=Math.sqrt;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_pow=Math.pow;var Math_imul=Math.imul;var Math_fround=Math.fround;var Math_min=Math.min;var Math_clz32=Math.clz32;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}Module["addRunDependency"]=addRunDependency;function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["removeRunDependency"]=removeRunDependency;Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var ASM_CONSTS=[];STATIC_BASE=8;STATICTOP=STATIC_BASE+58272;__ATINIT__.push();allocate([0,0,0,0,1,0,0,0,3,0,0,0,7,0,0,0,15,0,0,0,31,0,0,0,63,0,0,0,127,0,0,0,255,0,0,0,255,1,0,0,255,3,0,0,255,7,0,0,255,15,0,0,255,31,0,0,255,63,0,0,255,127,0,0,255,255,0,0,255,255,1,0,255,255,3,0,255,255,7,0,255,255,15,0,255,255,31,0,255,255,63,0,255,255,127,0,255,255,255,0,255,255,255,1,255,255,255,3,255,255,255,7,255,255,255,15,255,255,255,31,255,255,255,63,255,255,255,127,255,255,255,255,0,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,5,0,0,0,3,0,0,0,4,0,0,0,6,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,8,0,0,0,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,7,0,0,0,8,0,0,0,5,0,0,0,6,0,0,0,2,0,0,0,1,0,0,0,3,0,0,0,2,0,0,0,7,0,0,0,8,0,0,0,5,0,0,0,6,0,0,0,4,0,0,0,2,0,0,0,5,0,0,0,1,0,0,0,9,0,0,0,7,0,0,0,1,0,0,0,10,0,0,0,0,0,0,0,176,0,0,0,144,0,0,0,208,0,0,0,240,0,0,0,16,1,0,0,0,0,0,0,48,1,0,0,0,0,0,0,4,0,0,0,2,0,0,0,3,0,0,0,5,0,0,0,144,3,0,0,16,4,0,0,16,5,0,0,16,7,0,0,16,11,0,0,16,19,0,0,16,35,0,0,16,67,0,0,0,0,76,194,0,0,80,194,0,0,84,194,0,0,88,194,0,0,92,194,0,0,96,194,0,0,100,194,0,0,104,194,0,0,108,194,0,0,112,194,0,0,116,194,0,0,120,194,0,0,124,194,0,0,128,194,0,0,130,194,0,0,132,194,0,0,134,194,0,0,136,194,0,0,138,194,0,0,140,194,0,0,142,194,0,0,144,194,0,0,146,194,0,0,148,194,0,0,150,194,0,0,152,194,0,0,154,194,0,0,156,194,0,0,160,194,0,0,162,194,0,0,164,194,0,0,166,194,0,0,168,194,0,0,170,194,0,0,172,194,0,0,174,194,0,0,176,194,0,0,176,194,0,0,178,194,0,0,178,194,0,0,180,194,0,0,182,194,0,0,182,194,0,0,184,194,0,0,186,194,0,0,188,194,0,0,190,194,0,0,192,194,0,0,192,194,0,0,194,194,0,0,196,194,0,0,196,194,0,0,198,194,0,0,198,194,0,0,200,194,0,0,200,194,0,0,202,194,0,0,204,194,0,0,206,194,0,0,208,194,0,0,212,194,0,0,214,194,0,0,214,194,0,0,214,194,0,0,214,194,0,0,210,194,0,0,206,194,0,0,204,194,0,0,202,194,0,0,198,194,0,0,196,194,0,0,192,194,0,0,190,194,0,0,190,194,0,0,192,194,0,0,194,194,0,0,192,194,0,0,190,194,0,0,186,194,0,0,180,194,0,0,160,194,0,0,140,194,0,0,72,194,0,0,32,194,0,0,240,193,0,0,240,193,0,0,240,193,0,0,240,193,0,0,0,0,0,0,0,0,0,0,0,0,0,0,224,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,248,63,0,0,0,0,0,0,4,64,0,0,0,0,0,0,18,64,0,0,0,0,0,0,33,64,0,0,0,0,0,128,48,64,0,0,0,4,107,244,52,66,0,0,0,0,0,0,0,0,0,0,0,0,0,0,224,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,248,63,0,0,0,0,0,0,0,64,0,0,0,0,0,0,4,64,0,0,0,0,0,0,18,64,0,0,0,0,0,0,33,64,0,0,0,4,107,244,52,66,118,111,114,98,105,115,0,0,24,0,120,58,76,70,11,60,242,204,192,60,116,252,59,61,86,73,154,61,241,93,228,61,248,163,29,62,180,231,78,62,54,157,130,62,78,220,159,62,193,174,190,62,65,132,222,62,173,194,254,62,186,101,15,63,248,0,31,63,29,233,45,63,249,219,59,63,45,162,72,63,160,17,84,63,38,15,94,63,46,143,102,63,112,149,109,63,174,51,115,63,159,135,119,63,66,184,122,63,196,242,124,63,75,103,126,63,196,69,127,63,241,186,127,63,217,237,127,63,162,253,127,63,248,255,127,63,168,9,120,57,17,119,11,59,135,139,193,59,74,113,61,60,148,82,156,60,94,8,233,60,42,83,34,61,74,118,87,61,138,227,137,61,7,140,171,61,34,154,208,61,108,239,248,61,164,52,18,62,100,112,41,62,65,21,66,62,67,11,92,62,47,56,119,62,197,191,137,62,92,97,152,62,135,112,167,62,4,220,182,62,188,145,198,62,231,126,214,62,48,144,230,62,227,177,246,62,13,104,3,63,121,107,11,63,98,89,19,63,42,40,27,63,137,206,34,63,166,67,42,63,49,127,49,63,126,121,56,63,153,43,63,63,92,143,69,63,127,159,75,63,165,87,81,63,104,180,86,63,89,179,91,63,8,83,96,63,252,146,100,63,177,115,104,63,138,246,107,63,198,29,111,63,109,236,113,63,62,102,116,63,154,143,118,63,104,109,120,63,3,5,122,63,26,92,123,63,153,120,124,63,143,96,125,63,17,26,126,63,39,171,126,63,176,25,127,63,74,107,127,63,68,165,127,63,132,204,127,63,123,229,127,63,17,244,127,63,158,251,127,63,219,254,127,63,218,255,127,63,0,0,128,63,5,12,120,56,50,131,11,58,118,186,193,58,226,203,61,59,38,207,156,59,139,32,234,59,245,102,35,60,63,100,89,60,184,127,139,60,59,23,174,60,239,114,212,60,96,140,254,60,45,46,22,61,114,237,46,61,155,127,73,61,220,223,101,61,123,4,130,61,159,250,145,61,71,207,162,61,38,127,180,61,173,6,199,61,16,98,218,61,63,141,238,61,244,193,1,62,185,160,12,62,128,224,23,62,182,126,35,62,166,120,47,62,116,203,59,62,34,116,72,62,141,111,85,62,107,186,98,62,83,81,112,62,180,48,126,62,110,42,134,62,252,92,141,62,9,174,148,62,138,27,156,62,100,163,163,62,112,67,171,62,119,249,178,62,54,195,186,62,93,158,194,62,147,136,202,62,118,127,210,62,154,128,218,62,142,137,226,62,217,151,234,62,2,169,242,62,139,186,250,62,251,100,1,63,99,106,5,63,65,108,9,63,89,105,13,63,116,96,17,63,94,80,21,63,231,55,25,63,231,21,29,63,58,233,32,63,197,176,36,63,116,107,40,63,62,24,44,63,35,182,47,63,43,68,51,63,109,193,54,63,10,45,58,63,48,134,61,63,26,204,64,63,17,254,67,63,107,27,71,63,142,35,74,63,238,21,77,63,15,242,79,63,132,183,82,63,239,101,85,63,3,253,87,63,129,124,90,63,60,228,92,63,21,52,95,63,254,107,97,63,246,139,99,63,14,148,101,63,98,132,103,63,33,93,105,63,133,30,107,63,213,200,108,63,103,92,110,63,155,217,111,63,224,64,113,63,172,146,114,63,131,207,115,63,241,247,116,63,139,12,118,63,239,13,119,63,193,252,119,63,172,217,120,63,99,165,121,63,155,96,122,63,15,12,123,63,124,168,123,63,163,54,124,63,71,183,124,63,41,43,125,63,13,147,125,63,183,239,125,63,229,65,126,63,89,138,126,63,205,201,126,63,251,0,127,63,150,48,127,63,78,89,127,63,205,123,127,63,182,152,127,63,167,176,127,63,53,196,127,63,239,211,127,63,91,224,127,63,245,233,127,63,51,241,127,63,127,246,127,63,59,250,127,63,190,252,127,63,84,254,127,63,64,255,127,63,186,255,127,63,238,255,127,63,254,255,127,63,0,0,128,63,169,12,120,55,54,134,11,57,38,198,193,57,94,226,61,58,234,237,156,58,85,101,234,58,56,170,35,59,207,219,89,59,169,226,139,59,42,178,174,59,13,91,213,59,204,219,255,59,91,25,23,60,250,46,48,60,194,45,75,60,156,20,104,60,46,113,131,60,225,202,147,60,185,22,165,60,1,84,183,60,245,129,202,60,198,159,222,60,155,172,243,60,199,211,4,61,213,71,16,61,250,49,28,61,174,145,40,61,101,102,53,61,141,175,66,61,140,108,80,61,193,156,94,61,133,63,109,61,41,84,124,61,252,236,133,61,26,232,141,61,13,27,150,61,110,133,158,61,212,38,167,61,210,254,175,61,245,12,185,61,200,80,194,61,209,201,203,61,146,119,213,61,139,89,223,61,51,111,233,61,2,184,243,61,105,51,254,61,106,112,4,62,214,223,9,62,171,103,15,62,153,7,21,62,77,191,26,62,116,142,32,62,181,116,38,62,184,113,44,62,34,133,50,62,149,174,56,62,178,237,62,62,21,66,69,62,92,171,75,62,30,41,82,62,243,186,88,62,112,96,95,62,40,25,102,62,170,228,108,62,132,194,115,62,68,178,122,62,185,217,128,62,203,98,132,62,26,244,135,62,105,141,139,62,120,46,143,62,6,215,146,62,211,134,150,62,156,61,154,62,29,251,157,62,19,191,161,62,57,137,165,62,71,89,169,62,249,46,173,62,5,10,177,62,36,234,180,62,13,207,184,62,117,184,188,62,18,166,192,62,153,151,196,62,190,140,200,62,52,133,204,62,175,128,208,62,225,126,212,62,125,127,216,62,52,130,220,62,184,134,224,62,185,140,228,62,233,147,232,62,248,155,236,62,150,164,240,62,117,173,244,62,67,182,248,62,178,190,252,62,57,99,0,63,153,102,2,63,82,105,4,63,60,107,6,63,48,108,8,63,6,108,10,63,151,106,12,63,188,103,14,63,78,99,16,63,39,93,18,63,33,85,20,63,21,75,22,63,222,62,24,63,87,48,26,63,92,31,28,63,199,11,30,63,117,245,31,63,66,220,33,63,12,192,35,63,176,160,37,63,12,126,39,63,254,87,41,63,104,46,43,63,39,1,45,63,29,208,46,63,43,155,48,63,51,98,50,63,23,37,52,63,188,227,53,63,4,158,55,63,214,83,57,63,23,5,59,63,173,177,60,63,128,89,62,63,120,252,63,63,126,154,65,63,124,51,67,63,93,199,68,63,12,86,70,63,119,223,71,63,138,99,73,63,54,226,74,63,104,91,76,63,17,207,77,63,35,61,79,63,145,165,80,63,76,8,82,63,75,101,83,63,130,188,84,63,231,13,86,63,114,89,87,63,26,159,88,63,218,222,89,63,172,24,91,63,138,76,92,63,113,122,93,63,93,162,94,63,78,196,95,63,67,224,96,63,58,246,97,63,54,6,99,63,56,16,100,63,67,20,101,63,92,18,102,63,133,10,103,63,198,252,103,63,37,233,104,63,168,207,105,63,89,176,106,63,64,139,107,63,102,96,108,63,216,47,109,63,159,249,109,63,201,189,110,63,97,124,111,63,118,53,112,63,23,233,112,63,81,151,113,63,53,64,114,63,212,227,114,63,61,130,115,63,131,27,116,63,184,175,116,63,238,62,117,63,56,201,117,63,171,78,118,63,90,207,118,63,90,75,119,63,192,194,119,63,162,53,120,63,21,164,120,63,48,14,121,63,8,116,121,63,182,213,121,63,79,51,122,63,235,140,122,63,162,226,122,63,139,52,123,63,191,130,123,63,85,205,123,63,102,20,124,63,9,88,124,63,88,152,124,63,106,213,124,63,88,15,125,63,58,70,125,63,41,122,125,63,62,171,125,63,143,217,125,63,54,5,126,63,75,46,126,63,228,84,126,63,27,121,126,63,7,155,126,63,190,186,126,63,88,216,126,63,236,243,126,63,144,13,127,63,91,37,127,63,99,59,127,63,188,79,127,63,125,98,127,63,185,115,127,63,135,131,127,63,249,145,127,63,36,159,127,63,26,171,127,63,238,181,127,63,179,191,127,63,122,200,127,63,85,208,127,63,84,215,127,63,136,221,127,63,0,227,127,63,204,231,127,63,249,235,127,63,150,239,127,63,177,242,127,63,85,245,127,63,144,247,127,63,109,249,127,63,246,250,127,63,54,252,127,63,55,253,127,63,1,254,127,63,156,254,127,63,18,255,127,63,103,255,127,63,163,255,127,63,204,255,127,63,229,255,127,63,244,255,127,63,252,255,127,63,255,255,127,63,0,0,128,63,0,0,128,63,60,12,120,54,253,134,11,56,19,201,193,56,248,231,61,57,148,245,156,57,115,118,234,57,238,186,35,58,113,249,89,58,32,251,139,58,96,216,174,58,34,148,213,58,3,23,0,59,209,82,23,59,65,125,48,59,21,150,75,59,8,157,104,59,233,200,131,59,20,58,148,59,218,161,165,59,16,0,184,59,136,84,203,59,16,159,223,59,118,223,244,59,194,138,5,60,128,32,17,60,217,48,29,60,172,187,41,60,219,192,54,60,67,64,68,60,194,57,82,60,52,173,96,60,115,154,111,60,88,1,127,60,222,112,135,60,186,157,143,60,42,7,152,60,25,173,160,60,112,143,169,60,23,174,178,60,246,8,188,60,243,159,197,60,245,114,207,60,225,129,217,60,156,204,227,60,10,83,238,60,14,21,249,60,70,9,2,61,177,165,7,61,187,95,13,61,81,55,19,61,102,44,25,61,230,62,31,61,195,110,37,61,233,187,43,61,71,38,50,61,202,173,56,61,97,82,63,61,247,19,70,61,121,242,76,61,210,237,83,61,240,5,91,61,187,58,98,61,32,140,105,61,8,250,112,61,93,132,120,61,132,21,128,61,249,246,131,61,130,230,135,61,19,228,139,61,159,239,143,61,26,9,148,61,119,48,152,61,169,101,156,61,163,168,160,61,88,249,164,61,186,87,169,61,186,195,173,61,76,61,178,61,95,196,182,61,230,88,187,61,209,250,191,61,18,170,196,61,152,102,201,61,85,48,206,61,56,7,211,61,48,235,215,61,47,220,220,61,34,218,225,61,248,228,230,61,161,252,235,61,11,33,241,61,35,82,246,61,217,143,251,61,13,109,0,62,105,24,3,62,247,201,5,62,174,129,8,62,133,63,11,62,113,3,14,62,104,205,16,62,96,157,19,62,79,115,22,62,42,79,25,62,232,48,28,62,124,24,31,62,221,5,34,62,255,248,36,62,215,241,39,62,90,240,42,62,125,244,45,62,51,254,48,62,114,13,52,62,45,34,55,62,88,60,58,62,232,91,61,62,208,128,64,62,3,171,67,62,118,218,70,62,26,15,74,62,229,72,77,62,199,135,80,62,181,203,83,62,162,20,87,62,127,98,90,62,63,181,93,62,213,12,97,62,50,105,100,62,73,202,103,62,12,48,107,62,108,154,110,62,92,9,114,62,203,124,117,62,173,244,120,62,241,112,124,62,138,241,127,62,52,187,129,62,190,127,131,62,91,70,133,62,4,15,135,62,176,217,136,62,89,166,138,62,245,116,140,62,126,69,142,62,234,23,144,62,50,236,145,62,78,194,147,62,54,154,149,62,224,115,151,62,70,79,153,62,93,44,155,62,31,11,157,62,130,235,158,62,127,205,160,62,11,177,162,62,31,150,164,62,177,124,166,62,186,100,168,62,47,78,170,62,9,57,172,62,62,37,174,62,198,18,176,62,150,1,178,62,167,241,179,62,238,226,181,62,100,213,183,62,254,200,185,62,179,189,187,62,122,179,189,62,74,170,191,62,25,162,193,62,221,154,195,62,142,148,197,62,34,143,199,62,142,138,201,62,203,134,203,62,205,131,205,62,140,129,207,62,253,127,209,62,24,127,211,62,210,126,213,62,33,127,215,62,252,127,217,62,88,129,219,62,45,131,221,62,112,133,223,62,23,136,225,62,25,139,227,62,108,142,229,62,5,146,231,62,219,149,233,62,228,153,235,62,21,158,237,62,102,162,239,62,203,166,241,62,59,171,243,62,173,175,245,62,21,180,247,62,107,184,249,62,164,188,251,62,181,192,253,62,150,196,255,62,30,228,0,63,207,229,1,63,88,231,2,63,182,232,3,63,226,233,4,63,215,234,5,63,146,235,6,63,12,236,7,63,66,236,8,63,45,236,9,63,202,235,10,63,19,235,11,63,4,234,12,63,151,232,13,63,200,230,14,63,145,228,15,63,239,225,16,63,220,222,17,63,84,219,18,63,81,215,19,63,208,210,20,63,202,205,21,63,61,200,22,63,34,194,23,63,117,187,24,63,50,180,25,63,85,172,26,63,215,163,27,63,182,154,28,63,236,144,29,63,117,134,30,63,77,123,31,63,110,111,32,63,214,98,33,63,126,85,34,63,100,71,35,63,130,56,36,63,212,40,37,63,87,24,38,63,5,7,39,63,219,244,39,63,213,225,40,63,239,205,41,63,36,185,42,63,113,163,43,63,209,140,44,63,64,117,45,63,188,92,46,63,63,67,47,63,199,40,48,63,78,13,49,63,211,240,49,63,80,211,50,63,195,180,51,63,39,149,52,63,122,116,53,63,184,82,54,63,220,47,55,63,229,11,56,63,206,230,56,63,149,192,57,63,54,153,58,63,174,112,59,63,249,70,60,63,21,28,61,63,255,239,61,63,179,194,62,63,48,148,63,63,113,100,64,63,116,51,65,63,55,1,66,63,182,205,66,63,239,152,67,63,224,98,68,63,134,43,69,63,222,242,69,63,230,184,70,63,156,125,71,63,253,64,72,63,7,3,73,63,184,195,73,63,14,131,74,63,6,65,75,63,159,253,75,63,215,184,76,63,172,114,77,63,28,43,78,63,38,226,78,63,199,151,79,63,253,75,80,63,201,254,80,63,39,176,81,63,22,96,82,63,150,14,83,63,164,187,83,63,63,103,84,63,103,17,85,63,26,186,85,63,86,97,86,63,28,7,87,63,105,171,87,63,62,78,88,63,152,239,88,63,120,143,89,63,221,45,90,63,198,202,90,63,50,102,91,63,33,0,92,63,147,152,92,63,134,47,93,63,251,196,93,63,242,88,94,63,105,235,94,63,98,124,95,63,219,11,96,63,213,153,96,63,80,38,97,63,76,177,97,63,201,58,98,63,199,194,98,63,70,73,99,63,71,206,99,63,202,81,100,63,208,211,100,63,88,84,101,63,100,211,101,63,244,80,102,63,9,205,102,63,163,71,103,63,195,192,103,63,107,56,104,63,154,174,104,63,82,35,105,63,147,150,105,63,96,8,106,63,184,120,106,63,157,231,106,63,16,85,107,63,19,193,107,63,166,43,108,63,203,148,108,63,132,252,108,63,209,98,109,63,180,199,109,63,48,43,110,63,68,141,110,63,244,237,110,63,64,77,111,63,42,171,111,63,181,7,112,63,225,98,112,63,177,188,112,63,38,21,113,63,67,108,113,63,10,194,113,63,123,22,114,63,155,105,114,63,106,187,114,63,234,11,115,63,31,91,115,63,9,169,115,63,172,245,115,63,9,65,116,63,35,139,116,63,252,211,116,63,151,27,117,63,245,97,117,63,26,167,117,63,8,235,117,63,193,45,118,63,72,111,118,63,159,175,118,63,202,238,118,63,201,44,119,63,161,105,119,63,84,165,119,63,228,223,119,63,85,25,120,63,168,81,120,63,226,136,120,63,3,191,120,63,16,244,120,63,11,40,121,63,247,90,121,63,215,140,121,63,173,189,121,63,125,237,121,63,73,28,122,63,20,74,122,63,226,118,122,63,181,162,122,63,144,205,122,63,118,247,122,63,107,32,123,63,112,72,123,63,138,111,123,63,186,149,123,63,5,187,123,63,109,223,123,63,245,2,124,63,160,37,124,63,113,71,124,63,108,104,124,63,147,136,124,63,233,167,124,63,114,198,124,63,48,228,124,63,38,1,125,63,89,29,125,63,201,56,125,63,124,83,125,63,115,109,125,63,178,134,125,63,60,159,125,63,19,183,125,63,60,206,125,63,184,228,125,63,139,250,125,63,184,15,126,63,66,36,126,63,44,56,126,63,120,75,126,63,43,94,126,63,70,112,126,63,204,129,126,63,194,146,126,63,41,163,126,63,4,179,126,63,86,194,126,63,35,209,126,63,109,223,126,63,55,237,126,63,131,250,126,63,85,7,127,63,175,19,127,63,148,31,127,63,7,43,127,63,10,54,127,63,160,64,127,63,205,74,127,63,146,84,127,63,242,93,127,63,239,102,127,63,141,111,127,63,206,119,127,63,181,127,127,63,67,135,127,63,124,142,127,63,98,149,127,63,247,155,127,63,61,162,127,63,56,168,127,63,233,173,127,63,83,179,127,63,120,184,127,63,90,189,127,63,252,193,127,63,95,198,127,63,134,202,127,63,116,206,127,63,41,210,127,63,168,213,127,63,244,216,127,63,13,220,127,63,247,222,127,63,179,225,127,63,67,228,127,63,168,230,127,63,229,232,127,63,252,234,127,63,237,236,127,63,188,238,127,63,105,240,127,63,246,241,127,63,101,243,127,63,183,244,127,63,238,245,127,63,11,247,127,63,16,248,127,63,254,248,127,63,214,249,127,63,155,250,127,63,76,251,127,63,236,251,127,63,124,252,127,63,252,252,127,63,110,253,127,63,211,253,127,63,44,254,127,63,121,254,127,63,189,254,127,63,247,254,127,63,42,255,127,63,84,255,127,63,120,255,127,63,150,255,127,63,175,255,127,63,195,255,127,63,211,255,127,63,224,255,127,63,234,255,127,63,241,255,127,63,246,255,127,63,250,255,127,63,253,255,127,63,254,255,127,63,255,255,127,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,171,15,120,53,24,135,11,55,225,201,193,55,107,233,61,56,128,247,156,56,187,122,234,56,24,191,35,57,213,0,90,57,56,1,140,57,229,225,174,57,88,162,213,57,60,33,0,58,24,97,23,58,175,144,48,58,243,175,75,58,212,190,104,58,159,222,131,58,143,85,148,58,48,196,165,58,119,42,184,58,90,136,203,58,204,221,223,58,191,42,245,58,148,183,5,59,124,85,17,59,16,111,29,59,73,4,42,59,31,21,55,59,138,161,68,59,129,169,82,59,252,44,97,59,241,43,112,59,88,166,127,59,19,206,135,59,169,6,144,59,233,124,152,59,204,48,161,59,79,34,170,59,106,81,179,59,26,190,188,59,86,104,198,59,26,80,208,59,95,117,218,59,31,216,228,59,83,120,239,59,244,85,250,59,126,184,2,60,177,100,8,60,145,47,14,60,25,25,20,60,70,33,26,60,19,72,32,60,126,141,38,60,129,241,44,60,25,116,51,60,65,21,58,60,246,212,64,60,50,179,71,60,243,175,78,60,50,203,85,60,235,4,93,60,26,93,100,60,186,211,107,60,198,104,115,60,58,28,123,60,7,119,129,60,33,111,133,60,102,118,137,60,212,140,141,60,105,178,145,60,33,231,149,60,251,42,154,60,243,125,158,60,6,224,162,60,50,81,167,60,115,209,171,60,199,96,176,60,43,255,180,60,154,172,185,60,19,105,190,60,146,52,195,60,20,15,200,60,149,248,204,60,19,241,209,60,137,248,214,60,245,14,220,60,83,52,225,60,160,104,230,60,215,171,235,60,246,253,240,60,249,94,246,60,220,206,251,60,205,166,0,61,153,109,3,61,207,59,6,61,109,17,9,61,114,238,11,61,220,210,14,61,167,190,17,61,211,177,20,61,94,172,23,61,68,174,26,61,133,183,29,61,30,200,32,61,12,224,35,61,78,255,38,61,225,37,42,61,196,83,45,61,243,136,48,61,109,197,51,61,47,9,55,61,55,84,58,61,130,166,61,61,15,0,65,61,218,96,68,61,226,200,71,61,35,56,75,61,156,174,78,61,73,44,82,61,40,177,85,61,55,61,89,61,115,208,92,61,217,106,96,61,103,12,100,61,25,181,103,61,238,100,107,61,227,27,111,61,244,217,114,61,30,159,118,61,96,107,122,61,182,62,126,61,143,12,129,61,73,253,130,61,138,241,132,61,79,233,134,61,150,228,136,61,94,227,138,61,167,229,140,61,109,235,142,61,175,244,144,61,109,1,147,61,164,17,149,61,83,37,151,61,120,60,153,61,17,87,155,61,30,117,157,61,155,150,159,61,136,187,161,61,226,227,163,61,169,15,166,61,218,62,168,61,116,113,170,61,116,167,172,61,218,224,174,61,162,29,177,61,205,93,179,61,87,161,181,61,62,232,183,61,130,50,186,61,32,128,188,61,22,209,190,61,98,37,193,61,2,125,195,61,245,215,197,61,57,54,200,61,203,151,202,61,169,252,204,61,211,100,207,61,68,208,209,61,252,62,212,61,249,176,214,61,56,38,217,61,184,158,219,61,117,26,222,61,111,153,224,61,163,27,227,61,14,161,229,61,175,41,232,61,132,181,234,61,138,68,237,61,191,214,239,61,33,108,242,61,174,4,245,61,99,160,247,61,62,63,250,61,61,225,252,61,93,134,255,61,78,23,1,62,252,108,2,62,56,196,3,62,255,28,5,62,81,119,6,62,45,211,7,62,145,48,9,62,125,143,10,62,238,239,11,62,228,81,13,62,94,181,14,62,89,26,16,62,214,128,17,62,210,232,18,62,77,82,20,62,69,189,21,62,184,41,23,62,166,151,24,62,13,7,26,62,236,119,27,62,65,234,28,62,11,94,30,62,73,211,31,62,250,73,33,62,28,194,34,62,173,59,36,62,172,182,37,62,24,51,39,62,240,176,40,62,50,48,42,62,220,176,43,62,238,50,45,62,101,182,46,62,64,59,48,62,126,193,49,62,30,73,51,62,29,210,52,62,123,92,54,62,54,232,55,62,76,117,57,62,187,3,59,62,131,147,60,62,162,36,62,62,22,183,63,62,222,74,65,62,248,223,66,62,98,118,68,62,28,14,70,62,35,167,71,62,117,65,73,62,18,221,74,62,247,121,76,62,35,24,78,62,149,183,79,62,74,88,81,62,66,250,82,62,121,157,84,62,240,65,86,62,163,231,87,62,146,142,89,62,186,54,91,62,26,224,92,62,177,138,94,62,124,54,96,62,122,227,97,62,169,145,99,62,7,65,101,62,147,241,102,62,75,163,104,62,44,86,106,62,54,10,108,62,102,191,109,62,187,117,111,62,51,45,113,62,204,229,114,62,132,159,116,62,90,90,118,62,75,22,120,62,85,211,121,62,120,145,123,62,176,80,125,62,253,16,127,62,46,105,128,62,101,74,129,62,36,44,130,62,105,14,131,62,52,241,131,62,130,212,132,62,84,184,133,62,169,156,134,62,127,129,135,62,213,102,136,62,171,76,137,62,255,50,138,62,209,25,139,62,32,1,140,62,233,232,140,62,46,209,141,62,236,185,142,62,34,163,143,62,208,140,144,62,244,118,145,62,142,97,146,62,156,76,147,62,29,56,148,62,17,36,149,62,118,16,150,62,76,253,150,62,144,234,151,62,67,216,152,62,99,198,153,62,239,180,154,62,230,163,155,62,71,147,156,62,17,131,157,62,67,115,158,62,219,99,159,62,218,84,160,62,60,70,161,62,3,56,162,62,43,42,163,62,181,28,164,62,160,15,165,62,233,2,166,62,145,246,166,62,149,234,167,62,245,222,168,62,176,211,169,62,197,200,170,62,50,190,171,62,246,179,172,62,17,170,173,62,129,160,174,62,69,151,175,62,91,142,176,62,196,133,177,62,125,125,178,62,133,117,179,62,220,109,180,62,128,102,181,62,112,95,182,62,171,88,183,62,47,82,184,62,252,75,185,62,17,70,186,62,108,64,187,62,11,59,188,62,239,53,189,62,22,49,190,62,126,44,191,62,38,40,192,62,13,36,193,62,51,32,194,62,150,28,195,62,52,25,196,62,12,22,197,62,30,19,198,62,104,16,199,62,233,13,200,62,159,11,201,62,138,9,202,62,169,7,203,62,249,5,204,62,123,4,205,62,44,3,206,62,11,2,207,62,24,1,208,62,81,0,209,62,181,255,209,62,66,255,210,62,248,254,211,62,213,254,212,62,216,254,213,62,255,254,214,62,75,255,215,62,184,255,216,62,71,0,218,62,245,0,219,62,195,1,220,62,173,2,221,62,180,3,222,62,214,4,223,62,17,6,224,62,101,7,225,62,208,8,226,62,81,10,227,62,231,11,228,62,144,13,229,62,76,15,230,62,25,17,231,62,245,18,232,62,224,20,233,62,217,22,234,62,221,24,235,62,236,26,236,62,5,29,237,62,39,31,238,62,79,33,239,62,125,35,240,62,176,37,241,62,230,39,242,62,31,42,243,62,88,44,244,62,145,46,245,62,200,48,246,62,253,50,247,62,45,53,248,62,88,55,249,62,124,57,250,62,153,59,251,62,172,61,252,62,181,63,253,62,179,65,254,62,163,67,255,62,195,34,0,63,173,163,0,63,142,36,1,63,102,165,1,63,53,38,2,63,250,166,2,63,180,39,3,63,99,168,3,63,5,41,4,63,155,169,4,63,36,42,5,63,159,170,5,63,12,43,6,63,105,171,6,63,183,43,7,63,244,171,7,63,32,44,8,63,59,172,8,63,68,44,9,63,58,172,9,63,28,44,10,63,235,171,10,63,164,43,11,63,73,171,11,63,216,42,12,63,80,170,12,63,177,41,13,63,251,168,13,63,44,40,14,63,69,167,14,63,68,38,15,63,41,165,15,63,243,35,16,63,162,162,16,63,53,33,17,63,172,159,17,63,5,30,18,63,65,156,18,63,95,26,19,63,94,152,19,63,61,22,20,63,252,147,20,63,155,17,21,63,24,143,21,63,116,12,22,63,173,137,22,63,195,6,23,63,182,131,23,63,133,0,24,63,46,125,24,63,179,249,24,63,18,118,25,63,74,242,25,63,91,110,26,63,69,234,26,63,6,102,27,63,159,225,27,63,14,93,28,63,84,216,28,63,111,83,29,63,95,206,29,63,36,73,30,63,188,195,30,63,40,62,31,63,102,184,31,63,119,50,32,63,90,172,32,63,14,38,33,63,146,159,33,63,230,24,34,63,10,146,34,63,253,10,35,63,190,131,35,63,77,252,35,63,169,116,36,63,211,236,36,63,200,100,37,63,138,220,37,63,22,84,38,63,110,203,38,63,143,66,39,63,122,185,39,63,47,48,40,63,172,166,40,63,241,28,41,63,254,146,41,63,210,8,42,63,108,126,42,63,205,243,42,63,243,104,43,63,223,221,43,63,143,82,44,63,3,199,44,63,59,59,45,63,54,175,45,63,244,34,46,63,116,150,46,63,182,9,47,63,185,124,47,63,125,239,47,63,1,98,48,63,69,212,48,63,72,70,49,63,10,184,49,63,139,41,50,63,202,154,50,63,198,11,51,63,127,124,51,63,246,236,51,63,40,93,52,63,22,205,52,63,191,60,53,63,36,172,53,63,66,27,54,63,27,138,54,63,174,248,54,63,249,102,55,63,254,212,55,63,187,66,56,63,47,176,56,63,91,29,57,63,63,138,57,63,217,246,57,63,41,99,58,63,48,207,58,63,236,58,59,63,93,166,59,63,130,17,60,63,93,124,60,63,235,230,60,63,44,81,61,63,33,187,61,63,201,36,62,63,35,142,62,63,48,247,62,63,238,95,63,63,94,200,63,63,126,48,64,63,80,152,64,63,209,255,64,63,3,103,65,63,228,205,65,63,117,52,66,63,181,154,66,63,163,0,67,63,64,102,67,63,139,203,67,63,131,48,68,63,41,149,68,63,124,249,68,63,123,93,69,63,39,193,69,63,127,36,70,63,132,135,70,63,51,234,70,63,142,76,71,63,148,174,71,63,68,16,72,63,159,113,72,63,164,210,72,63,83,51,73,63,172,147,73,63,174,243,73,63,89,83,74,63,173,178,74,63,169,17,75,63,77,112,75,63,154,206,75,63,143,44,76,63,43,138,76,63,110,231,76,63,89,68,77,63,234,160,77,63,34,253,77,63,0,89,78,63,133,180,78,63,176,15,79,63,128,106,79,63,246,196,79,63,18,31,80,63,210,120,80,63,56,210,80,63,66,43,81,63,242,131,81,63,69,220,81,63,61,52,82,63,217,139,82,63,24,227,82,63,252,57,83,63,131,144,83,63,174,230,83,63,123,60,84,63,236,145,84,63,0,231,84,63,183,59,85,63,16,144,85,63,12,228,85,63,170,55,86,63,235,138,86,63,206,221,86,63,83,48,87,63,121,130,87,63,66,212,87,63,172,37,88,63,184,118,88,63,101,199,88,63,180,23,89,63,164,103,89,63,53,183,89,63,104,6,90,63,59,85,90,63,175,163,90,63,197,241,90,63,123,63,91,63,210,140,91,63,201,217,91,63,97,38,92,63,154,114,92,63,115,190,92,63,237,9,93,63,7,85,93,63,194,159,93,63,29,234,93,63,24,52,94,63,179,125,94,63,239,198,94,63,203,15,95,63,72,88,95,63,100,160,95,63,33,232,95,63,126,47,96,63,123,118,96,63,24,189,96,63,85,3,97,63,51,73,97,63,177,142,97,63,207,211,97,63,141,24,98,63,236,92,98,63,235,160,98,63,138,228,98,63,202,39,99,63,170,106,99,63,42,173,99,63,75,239,99,63,13,49,100,63,111,114,100,63,114,179,100,63,21,244,100,63,90,52,101,63,63,116,101,63,197,179,101,63,236,242,101,63,180,49,102,63,29,112,102,63,39,174,102,63,211,235,102,63,32,41,103,63,15,102,103,63,159,162,103,63,209,222,103,63,164,26,104,63,26,86,104,63,49,145,104,63,235,203,104,63,71,6,105,63,69,64,105,63,230,121,105,63,42,179,105,63,16,236,105,63,153,36,106,63,197,92,106,63,148,148,106,63,7,204,106,63,29,3,107,63,214,57,107,63,52,112,107,63,53,166,107,63,218,219,107,63,36,17,108,63,18,70,108,63,164,122,108,63,220,174,108,63,184,226,108,63,57,22,109,63,96,73,109,63,44,124,109,63,157,174,109,63,181,224,109,63,115,18,110,63,214,67,110,63,225,116,110,63,146,165,110,63,233,213,110,63,232,5,111,63,142,53,111,63,219,100,111,63,209,147,111,63,110,194,111,63,179,240,111,63,160,30,112,63,54,76,112,63,117,121,112,63,93,166,112,63,239,210,112,63,41,255,112,63,14,43,113,63,156,86,113,63,213,129,113,63,184,172,113,63,70,215,113,63,127,1,114,63,99,43,114,63,243,84,114,63,46,126,114,63,21,167,114,63,169,207,114,63,233,247,114,63,214,31,115,63,113,71,115,63,184,110,115,63,173,149,115,63,80,188,115,63,162,226,115,63,161,8,116,63,80,46,116,63,174,83,116,63,187,120,116,63,119,157,116,63,228,193,116,63,1,230,116,63,206,9,117,63,76,45,117,63,123,80,117,63,92,115,117,63,238,149,117,63,51,184,117,63,42,218,117,63,211,251,117,63,48,29,118,63,64,62,118,63,3,95,118,63,122,127,118,63,166,159,118,63,134,191,118,63,27,223,118,63,101,254,118,63,101,29,119,63,27,60,119,63,135,90,119,63,169,120,119,63,131,150,119,63,19,180,119,63,91,209,119,63,91,238,119,63,20,11,120,63,132,39,120,63,174,67,120,63,145,95,120,63,46,123,120,63,132,150,120,63,149,177,120,63,96,204,120,63,231,230,120,63,41,1,121,63,38,27,121,63,223,52,121,63,85,78,121,63,136,103,121,63,120,128,121,63,37,153,121,63,144,177,121,63,185,201,121,63,161,225,121,63,72,249,121,63,174,16,122,63,212,39,122,63,185,62,122,63,96,85,122,63,198,107,122,63,238,129,122,63,216,151,122,63,131,173,122,63,241,194,122,63,33,216,122,63,20,237,122,63,202,1,123,63,68,22,123,63,130,42,123,63,133,62,123,63,77,82,123,63,217,101,123,63,43,121,123,63,68,140,123,63,34,159,123,63,200,177,123,63,52,196,123,63,104,214,123,63,99,232,123,63,39,250,123,63,180,11,124,63,9,29,124,63,40,46,124,63,17,63,124,63,196,79,124,63,65,96,124,63,137,112,124,63,156,128,124,63,124,144,124,63,39,160,124,63,158,175,124,63,226,190,124,63,244,205,124,63,211,220,124,63,128,235,124,63,251,249,124,63,69,8,125,63,94,22,125,63,71,36,125,63,255,49,125,63,136,63,125,63,225,76,125,63,11,90,125,63,7,103,125,63,212,115,125,63,115,128,125,63,229,140,125,63,42,153,125,63,66,165,125,63,46,177,125,63,238,188,125,63,130,200,125,63,235,211,125,63,41,223,125,63,61,234,125,63,38,245,125,63,230,255,125,63,124,10,126,63,234,20,126,63,47,31,126,63,75,41,126,63,64,51,126,63,13,61,126,63,180,70,126,63,51,80,126,63,140,89,126,63,191,98,126,63,205,107,126,63,181,116,126,63,120,125,126,63,23,134,126,63,146,142,126,63,233,150,126,63,28,159,126,63,44,167,126,63,26,175,126,63,229,182,126,63,142,190,126,63,22,198,126,63,124,205,126,63,194,212,126,63,231,219,126,63,235,226,126,63,208,233,126,63,149,240,126,63,59,247,126,63,195,253,126,63,44,4,127,63,118,10,127,63,163,16,127,63,179,22,127,63,165,28,127,63,123,34,127,63,52,40,127,63,210,45,127,63,83,51,127,63,186,56,127,63,5,62,127,63,53,67,127,63,75,72,127,63,72,77,127,63,42,82,127,63,243,86,127,63,163,91,127,63,58,96,127,63,185,100,127,63,32,105,127,63,111,109,127,63,166,113,127,63,199,117,127,63,208,121,127,63,196,125,127,63,161,129,127,63,104,133,127,63,25,137,127,63,182,140,127,63,61,144,127,63,176,147,127,63,14,151,127,63,89,154,127,63,143,157,127,63,179,160,127,63,195,163,127,63,192,166,127,63,171,169,127,63,132,172,127,63,74,175,127,63,255,177,127,63,163,180,127,63,53,183,127,63,183,185,127,63,40,188,127,63,137,190,127,63,217,192,127,63,26,195,127,63,76,197,127,63,111,199,127,63,130,201,127,63,135,203,127,63,126,205,127,63,102,207,127,63,65,209,127,63,14,211,127,63,205,212,127,63,128,214,127,63,38,216,127,63,191,217,127,63,76,219,127,63,204,220,127,63,65,222,127,63,170,223,127,63,8,225,127,63,91,226,127,63,163,227,127,63,224,228,127,63,19,230,127,63,59,231,127,63,90,232,127,63,110,233,127,63,122,234,127,63,124,235,127,63,116,236,127,63,100,237,127,63,75,238,127,63,42,239,127,63,1,240,127,63,207,240,127,63,149,241,127,63,84,242,127,63,12,243,127,63,188,243,127,63,101,244,127,63,7,245,127,63,162,245,127,63,55,246,127,63,198,246,127,63,78,247,127,63,209,247,127,63,77,248,127,63,196,248,127,63,54,249,127,63,162,249,127,63,9,250,127,63,108,250,127,63,201,250,127,63,34,251,127,63,118,251,127,63,198,251,127,63,18,252,127,63,89,252,127,63,157,252,127,63,221,252,127,63,26,253,127,63,83,253,127,63,136,253,127,63,187,253,127,63,234,253,127,63,22,254,127,63,64,254,127,63,103,254,127,63,139,254,127,63,173,254,127,63,204,254,127,63,234,254,127,63,5,255,127,63,30,255,127,63,53,255,127,63,74,255,127,63,94,255,127,63,112,255,127,63,128,255,127,63,143,255,127,63,157,255,127,63,169,255,127,63,180,255,127,63,191,255,127,63,200,255,127,63,208,255,127,63,215,255,127,63,221,255,127,63,227,255,127,63,232,255,127,63,236,255,127,63,239,255,127,63,243,255,127,63,245,255,127,63,248,255,127,63,249,255,127,63,251,255,127,63,252,255,127,63,253,255,127,63,254,255,127,63,255,255,127,63,255,255,127,63,255,255,127,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,204,8,120,52,171,134,11,54,79,202,193,54,190,233,61,55,238,247,156,55,192,123,234,55,43,192,35,56,161,2,90,56,189,2,140,56,76,228,174,56,227,165,213,56,199,35,0,57,168,100,23,57,134,149,48,57,104,182,75,57,64,199,104,57,7,228,131,57,105,92,148,57,191,204,165,57,6,53,184,57,65,149,203,57,105,237,223,57,120,61,245,57,184,194,5,58,166,98,17,58,134,126,29,58,81,22,42,58,9,42,55,58,172,185,68,58,54,197,82,58,165,76,97,58,250,79,112,58,47,207,127,58,34,229,135,58,154,32,144,58,255,153,152,58,80,81,161,58,139,70,170,58,174,121,179,58,186,234,188,58,171,153,198,58,129,134,208,58,58,177,218,58,212,25,229,58,79,192,239,58,167,164,250,58,109,227,2,59,117,147,8,59,105,98,14,59,73,80,20,59,19,93,26,59,199,136,32,59,100,211,38,59,232,60,45,59,83,197,51,59,164,108,58,59,218,50,65,59,243,23,72,59,239,27,79,59,204,62,86,59,138,128,93,59,38,225,100,59,161,96,108,59,249,254,115,59,45,188,123,59,29,204,129,59,145,201,133,59,113,214,137,59,188,242,141,59,113,30,146,59,145,89,150,59,26,164,154,59,12,254,158,59,102,103,163,59,40,224,167,59,80,104,172,59,222,255,176,59,209,166,181,59,40,93,186,59,228,34,191,59,2,248,195,59,131,220,200,59,101,208,205,59,168,211,210,59,74,230,215,59,76,8,221,59,172,57,226,59,105,122,231,59,131,202,236,59,249,41,242,59,202,152,247,59,245,22,253,59,60,82,1,60,170,32,4,60,196,246,6,60,137,212,9,60,249,185,12,60,19,167,15,60,216,155,18,60,69,152,21,60,92,156,24,60,26,168,27,60,129,187,30,60,143,214,33,60,69,249,36,60,160,35,40,60,162,85,43,60,73,143,46,60,149,208,49,60,133,25,53,60,26,106,56,60,81,194,59,60,44,34,63,60,168,137,66,60,199,248,69,60,134,111,73,60,230,237,76,60,231,115,80,60,134,1,84,60,197,150,87,60,162,51,91,60,28,216,94,60,52,132,98,60,232,55,102,60,56,243,105,60,35,182,109,60,170,128,113,60,202,82,117,60,131,44,121,60,214,13,125,60,96,123,128,60,161,115,130,60,174,111,132,60,134,111,134,60,40,115,136,60,149,122,138,60,205,133,140,60,206,148,142,60,152,167,144,60,44,190,146,60,136,216,148,60,173,246,150,60,154,24,153,60,78,62,155,60,202,103,157,60,13,149,159,60,23,198,161,60,231,250,163,60,125,51,166,60,217,111,168,60,249,175,170,60,223,243,172,60,137,59,175,60,247,134,177,60,40,214,179,60,29,41,182,60,213,127,184,60,80,218,186,60,140,56,189,60,138,154,191,60,74,0,194,60,202,105,196,60,11,215,198,60,12,72,201,60,205,188,203,60,77,53,206,60,140,177,208,60,137,49,211,60,69,181,213,60,189,60,216,60,243,199,218,60,230,86,221,60,149,233,223,60,0,128,226,60,39,26,229,60,8,184,231,60,164,89,234,60,250,254,236,60,9,168,239,60,210,84,242,60,83,5,245,60,141,185,247,60,126,113,250,60,39,45,253,60,134,236,255,60,206,87,1,61,52,187,2,61,117,32,4,61,144,135,5,61,133,240,6,61,84,91,8,61,253,199,9,61,128,54,11,61,219,166,12,61,16,25,14,61,29,141,15,61,3,3,17,61,193,122,18,61,87,244,19,61,197,111,21,61,10,237,22,61,39,108,24,61,26,237,25,61,228,111,27,61,132,244,28,61,251,122,30,61,71,3,32,61,105,141,33,61,96,25,35,61,45,167,36,61,206,54,38,61,67,200,39,61,141,91,41,61,171,240,42,61,156,135,44,61,96,32,46,61,248,186,47,61,99,87,49,61,160,245,50,61,175,149,52,61,144,55,54,61,67,219,55,61,199,128,57,61,28,40,59,61,65,209,60,61,56,124,62,61,254,40,64,61,148,215,65,61,250,135,67,61,47,58,69,61,51,238,70,61,5,164,72,61,166,91,74,61,20,21,76,61,80,208,77,61,90,141,79,61,49,76,81,61,212,12,83,61,68,207,84,61,128,147,86,61,135,89,88,61,90,33,90,61,248,234,91,61,97,182,93,61,148,131,95,61,145,82,97,61,88,35,99,61,232,245,100,61,65,202,102,61,100,160,104,61,78,120,106,61,1,82,108,61,123,45,110,61,188,10,112,61,197,233,113,61,148,202,115,61,41,173,117,61,133,145,119,61,166,119,121,61,140,95,123,61,55,73,125,61,166,52,127,61,237,144,128,61,105,136,129,61,198,128,130,61,5,122,131,61,37,116,132,61,39,111,133,61,9,107,134,61,204,103,135,61,112,101,136,61,244,99,137,61,88,99,138,61,157,99,139,61,193,100,140,61,196,102,141,61,167,105,142,61,106,109,143,61,11,114,144,61,139,119,145,61,234,125,146,61,40,133,147,61,67,141,148,61,61,150,149,61,20,160,150,61,201,170,151,61,92,182,152,61,203,194,153,61,24,208,154,61,66,222,155,61,72,237,156,61,42,253,157,61,233,13,159,61,132,31,160,61,250,49,161,61,76,69,162,61,122,89,163,61,130,110,164,61,101,132,165,61,35,155,166,61,188,178,167,61,47,203,168,61,124,228,169,61,162,254,170,61,163,25,172,61,124,53,173,61,47,82,174,61,187,111,175,61,31,142,176,61,92,173,177,61,113,205,178,61,94,238,179,61,35,16,181,61,192,50,182,61,52,86,183,61,127,122,184,61,160,159,185,61,153,197,186,61],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE);allocate([104,236,187,61,13,20,189,61,136,60,190,61,217,101,191,61,255,143,192,61,250,186,193,61,202,230,194,61,111,19,196,61,233,64,197,61,55,111,198,61,89,158,199,61,78,206,200,61,23,255,201,61,179,48,203,61,35,99,204,61,101,150,205,61,121,202,206,61,96,255,207,61,25,53,209,61,164,107,210,61,0,163,211,61,45,219,212,61,44,20,214,61,251,77,215,61,154,136,216,61,10,196,217,61,74,0,219,61,89,61,220,61,56,123,221,61,230,185,222,61,99,249,223,61,174,57,225,61,200,122,226,61,176,188,227,61,102,255,228,61,233,66,230,61,58,135,231,61,88,204,232,61,66,18,234,61,249,88,235,61,124,160,236,61,203,232,237,61,230,49,239,61,204,123,240,61,125,198,241,61,249,17,243,61,63,94,244,61,79,171,245,61,42,249,246,61,206,71,248,61,60,151,249,61,114,231,250,61,114,56,252,61,58,138,253,61,202,220,254,61,17,24,0,62,33,194,0,62,149,108,1,62,108,23,2,62,166,194,2,62,68,110,3,62,69,26,4,62,168,198,4,62,111,115,5,62,152,32,6,62,35,206,6,62,17,124,7,62,98,42,8,62,20,217,8,62,40,136,9,62,157,55,10,62,117,231,10,62,173,151,11,62,71,72,12,62,66,249,12,62,158,170,13,62,91,92,14,62,120,14,15,62,246,192,15,62,213,115,16,62,19,39,17,62,177,218,17,62,175,142,18,62,13,67,19,62,202,247,19,62,231,172,20,62,99,98,21,62,62,24,22,62,120,206,22,62,16,133,23,62,7,60,24,62,92,243,24,62,16,171,25,62,33,99,26,62,145,27,27,62,94,212,27,62,137,141,28,62,17,71,29,62,246,0,30,62,56,187,30,62,215,117,31,62,211,48,32,62,43,236,32,62,224,167,33,62,241,99,34,62,93,32,35,62,38,221,35,62,74,154,36,62,202,87,37,62,165,21,38,62,219,211,38,62,108,146,39,62,88,81,40,62,159,16,41,62,64,208,41,62,59,144,42,62,144,80,43,62,63,17,44,62,72,210,44,62,170,147,45,62,102,85,46,62,122,23,47,62,232,217,47,62,175,156,48,62,206,95,49,62,69,35,50,62,21,231,50,62,61,171,51,62,189,111,52,62,148,52,53,62,195,249,53,62,73,191,54,62,38,133,55,62,91,75,56,62,230,17,57,62,199,216,57,62,255,159,58,62,141,103,59,62,113,47,60,62,171,247,60,62,59,192,61,62,31,137,62,62,89,82,63,62,232,27,64,62,204,229,64,62,5,176,65,62,146,122,66,62,115,69,67,62,168,16,68,62,49,220,68,62,14,168,69,62,62,116,70,62,194,64,71,62,152,13,72,62,193,218,72,62,61,168,73,62,12,118,74,62,44,68,75,62,159,18,76,62,100,225,76,62,122,176,77,62,225,127,78,62,154,79,79,62,164,31,80,62,255,239,80,62,170,192,81,62,166,145,82,62,242,98,83,62,141,52,84,62,121,6,85,62,180,216,85,62,63,171,86,62,25,126,87,62,65,81,88,62,185,36,89,62,126,248,89,62,147,204,90,62,245,160,91,62,165,117,92,62,163,74,93,62,238,31,94,62,135,245,94,62,109,203,95,62,159,161,96,62,30,120,97,62,233,78,98,62,1,38,99,62,100,253,99,62,19,213,100,62,14,173,101,62,84,133,102,62,229,93,103,62,193,54,104,62,231,15,105,62,88,233,105,62,19,195,106,62,24,157,107,62,103,119,108,62,255,81,109,62,224,44,110,62,11,8,111,62,126,227,111,62,58,191,112,62,62,155,113,62,139,119,114,62,31,84,115,62,251,48,116,62,31,14,117,62,138,235,117,62,59,201,118,62,52,167,119,62,115,133,120,62,248,99,121,62,196,66,122,62,213,33,123,62,44,1,124,62,200,224,124,62,170,192,125,62,208,160,126,62,59,129,127,62,245,48,128,62,111,161,128,62,11,18,129,62,201,130,129,62,168,243,129,62,169,100,130,62,204,213,130,62,15,71,131,62,117,184,131,62,251,41,132,62,162,155,132,62,107,13,133,62,84,127,133,62,93,241,133,62,136,99,134,62,210,213,134,62,61,72,135,62,200,186,135,62,116,45,136,62,63,160,136,62,42,19,137,62,52,134,137,62,94,249,137,62,168,108,138,62,17,224,138,62,153,83,139,62,64,199,139,62,6,59,140,62,235,174,140,62,239,34,141,62,17,151,141,62,82,11,142,62,177,127,142,62,46,244,142,62,201,104,143,62,130,221,143,62,89,82,144,62,78,199,144,62,96,60,145,62,143,177,145,62,220,38,146,62,70,156,146,62,205,17,147,62,113,135,147,62,50,253,147,62,16,115,148,62,9,233,148,62,32,95,149,62,82,213,149,62,161,75,150,62,12,194,150,62,146,56,151,62,53,175,151,62,243,37,152,62,204,156,152,62,193,19,153,62,209,138,153,62,252,1,154,62,66,121,154,62,163,240,154,62,31,104,155,62,181,223,155,62,101,87,156,62,48,207,156,62,21,71,157,62,20,191,157,62,45,55,158,62,96,175,158,62,172,39,159,62,18,160,159,62,145,24,160,62,41,145,160,62,218,9,161,62,165,130,161,62,136,251,161,62,132,116,162,62,152,237,162,62,197,102,163,62,10,224,163,62,103,89,164,62,220,210,164,62,105,76,165,62,14,198,165,62,202,63,166,62,158,185,166,62,137,51,167,62,139,173,167,62,164,39,168,62,213,161,168,62,27,28,169,62,121,150,169,62,237,16,170,62,119,139,170,62,24,6,171,62,206,128,171,62,155,251,171,62,125,118,172,62,117,241,172,62,130,108,173,62,165,231,173,62,221,98,174,62,42,222,174,62,140,89,175,62,2,213,175,62,142,80,176,62,46,204,176,62,226,71,177,62,170,195,177,62,135,63,178,62,119,187,178,62,124,55,179,62,148,179,179,62,191,47,180,62,254,171,180,62,80,40,181,62,181,164,181,62,45,33,182,62,184,157,182,62,85,26,183,62,5,151,183,62,199,19,184,62,156,144,184,62,130,13,185,62,123,138,185,62,133,7,186,62,161,132,186,62,206,1,187,62,13,127,187,62,93,252,187,62,190,121,188,62,48,247,188,62,178,116,189,62,70,242,189,62,233,111,190,62,157,237,190,62,98,107,191,62,54,233,191,62,26,103,192,62,14,229,192,62,17,99,193,62,36,225,193,62,70,95,194,62,119,221,194,62,184,91,195,62,7,218,195,62,100,88,196,62,209,214,196,62,75,85,197,62,212,211,197,62,107,82,198,62,16,209,198,62,195,79,199,62,132,206,199,62,82,77,200,62,45,204,200,62,21,75,201,62,11,202,201,62,13,73,202,62,29,200,202,62,56,71,203,62,97,198,203,62,149,69,204,62,214,196,204,62,34,68,205,62,123,195,205,62,223,66,206,62,79,194,206,62,202,65,207,62,81,193,207,62,226,64,208,62,127,192,208,62,38,64,209,62,216,191,209,62,148,63,210,62,91,191,210,62,44,63,211,62,7,191,211,62,235,62,212,62,218,190,212,62,210,62,213,62,211,190,213,62,222,62,214,62,242,190,214,62,15,63,215,62,53,191,215,62,99,63,216,62,154,191,216,62,217,63,217,62,32,192,217,62,112,64,218,62,199,192,218,62,38,65,219,62,140,193,219,62,250,65,220,62,112,194,220,62,236,66,221,62,112,195,221,62,250,67,222,62,139,196,222,62,34,69,223,62,192,197,223,62,100,70,224,62,14,199,224,62,189,71,225,62,115,200,225,62,46,73,226,62,239,201,226,62,181,74,227,62,127,203,227,62,79,76,228,62,36,205,228,62,253,77,229,62,219,206,229,62,190,79,230,62,164,208,230,62,142,81,231,62,125,210,231,62,111,83,232,62,100,212,232,62,93,85,233,62,89,214,233,62,89,87,234,62,91,216,234,62,96,89,235,62,104,218,235,62,114,91,236,62,126,220,236,62,141,93,237,62,158,222,237,62,176,95,238,62,196,224,238,62,218,97,239,62,241,226,239,62,10,100,240,62,35,229,240,62,62,102,241,62,89,231,241,62,116,104,242,62,145,233,242,62,173,106,243,62,202,235,243,62,230,108,244,62,3,238,244,62,31,111,245,62,59,240,245,62,86,113,246,62,112,242,246,62,137,115,247,62,161,244,247,62,184,117,248,62,206,246,248,62,226,119,249,62,244,248,249,62,4,122,250,62,18,251,250,62,30,124,251,62,40,253,251,62,47,126,252,62,52,255,252,62,54,128,253,62,52,1,254,62,48,130,254,62,40,3,255,62,29,132,255,62,135,2,0,63,254,66,0,63,115,131,0,63,230,195,0,63,86,4,1,63,197,68,1,63,49,133,1,63,155,197,1,63,3,6,2,63,103,70,2,63,202,134,2,63,42,199,2,63,135,7,3,63,225,71,3,63,56,136,3,63,141,200,3,63,222,8,4,63,44,73,4,63,119,137,4,63,191,201,4,63,3,10,5,63,68,74,5,63,130,138,5,63,188,202,5,63,242,10,6,63,36,75,6,63,83,139,6,63,126,203,6,63,165,11,7,63,199,75,7,63,230,139,7,63,1,204,7,63,23,12,8,63,41,76,8,63,54,140,8,63,63,204,8,63,67,12,9,63,67,76,9,63,62,140,9,63,52,204,9,63,37,12,10,63,18,76,10,63,249,139,10,63,219,203,10,63,184,11,11,63,144,75,11,63,98,139,11,63,47,203,11,63,246,10,12,63,184,74,12,63,116,138,12,63,43,202,12,63,219,9,13,63,134,73,13,63,43,137,13,63,202,200,13,63,98,8,14,63,245,71,14,63,129,135,14,63,7,199,14,63,135,6,15,63,0,70,15,63,114,133,15,63,222,196,15,63,67,4,16,63,161,67,16,63,249,130,16,63,73,194,16,63,147,1,17,63,213,64,17,63,17,128,17,63,69,191,17,63,114,254,17,63,151,61,18,63,181,124,18,63,203,187,18,63,218,250,18,63,225,57,19,63,225,120,19,63,216,183,19,63,200,246,19,63,176,53,20,63,143,116,20,63,103,179,20,63,54,242,20,63,253,48,21,63,188,111,21,63,114,174,21,63,32,237,21,63,197,43,22,63,98,106,22,63,246,168,22,63,129,231,22,63,3,38,23,63,125,100,23,63,237,162,23,63,84,225,23,63,178,31,24,63,7,94,24,63,83,156,24,63,149,218,24,63,206,24,25,63,253,86,25,63,35,149,25,63,63,211,25,63,82,17,26,63,90,79,26,63,89,141,26,63,78,203,26,63,57,9,27,63,25,71,27,63,240,132,27,63,188,194,27,63,126,0,28,63,54,62,28,63,227,123,28,63,134,185,28,63,30,247,28,63,172,52,29,63,47,114,29,63,167,175,29,63,20,237,29,63,118,42,30,63,206,103,30,63,26,165,30,63,91,226,30,63,145,31,31,63,188,92,31,63,219,153,31,63,239,214,31,63,247,19,32,63,244,80,32,63,230,141,32,63,203,202,32,63,165,7,33,63,115,68,33,63,53,129,33,63,235,189,33,63,150,250,33,63,52,55,34,63,198,115,34,63,75,176,34,63,197,236,34,63,50,41,35,63,146,101,35,63,230,161,35,63,46,222,35,63,105,26,36,63,151,86,36,63,185,146,36,63,205,206,36,63,213,10,37,63,208,70,37,63,190,130,37,63,158,190,37,63,114,250,37,63,56,54,38,63,241,113,38,63,157,173,38,63,59,233,38,63,204,36,39,63,79,96,39,63,197,155,39,63,45,215,39,63,135,18,40,63,211,77,40,63,18,137,40,63,66,196,40,63,101,255,40,63,121,58,41,63,128,117,41,63,120,176,41,63,98,235,41,63,62,38,42,63,11,97,42,63,202,155,42,63,122,214,42,63,28,17,43,63,175,75,43,63,52,134,43,63,170,192,43,63,16,251,43,63,105,53,44,63,178,111,44,63,236,169,44,63,23,228,44,63,51,30,45,63,64,88,45,63,61,146,45,63,43,204,45,63,10,6,46,63,218,63,46,63,154,121,46,63,74,179,46,63,235,236,46,63,124,38,47,63,254,95,47,63,112,153,47,63,210,210,47,63,36,12,48,63,102,69,48,63,152,126,48,63,186,183,48,63,204,240,48,63,205,41,49,63,191,98,49,63,160,155,49,63,113,212,49,63,49,13,50,63,225,69,50,63,128,126,50,63,15,183,50,63,141,239,50,63,251,39,51,63,87,96,51,63,163,152,51,63,222,208,51,63,8,9,52,63,34,65,52,63,42,121,52,63,33,177,52,63,7,233,52,63,219,32,53,63,159,88,53,63,81,144,53,63,242,199,53,63,129,255,53,63,255,54,54,63,108,110,54,63,198,165,54,63,16,221,54,63,71,20,55,63,109,75,55,63,129,130,55,63,131,185,55,63,116,240,55,63,82,39,56,63,30,94,56,63,217,148,56,63,129,203,56,63,23,2,57,63,155,56,57,63,13,111,57,63,108,165,57,63,185,219,57,63,244,17,58,63,28,72,58,63,50,126,58,63,53,180,58,63,38,234,58,63,4,32,59,63,207,85,59,63,135,139,59,63,45,193,59,63,192,246,59,63,64,44,60,63,173,97,60,63,7,151,60,63,78,204,60,63,130,1,61,63,163,54,61,63,177,107,61,63,171,160,61,63,146,213,61,63,102,10,62,63,39,63,62,63,212,115,62,63,110,168,62,63,244,220,62,63,103,17,63,63,198,69,63,63,17,122,63,63,73,174,63,63,109,226,63,63,126,22,64,63,122,74,64,63,99,126,64,63,56,178,64,63,248,229,64,63,165,25,65,63,62,77,65,63,195,128,65,63,52,180,65,63,144,231,65,63,216,26,66,63,13,78,66,63,44,129,66,63,56,180,66,63,47,231,66,63,18,26,67,63,224,76,67,63,154,127,67,63,64,178,67,63,208,228,67,63,77,23,68,63,180,73,68,63,7,124,68,63,69,174,68,63,111,224,68,63,131,18,69,63,131,68,69,63,110,118,69,63,68,168,69,63,5,218,69,63,177,11,70,63,72,61,70,63,202,110,70,63,55,160,70,63,143,209,70,63,210,2,71,63,255,51,71,63,23,101,71,63,26,150,71,63,8,199,71,63,224,247,71,63,163,40,72,63,81,89,72,63,233,137,72,63,107,186,72,63,216,234,72,63,48,27,73,63,114,75,73,63,158,123,73,63,181,171,73,63,181,219,73,63,161,11,74,63,118,59,74,63,54,107,74,63,224,154,74,63,116,202,74,63,242,249,74,63,90,41,75,63,173,88,75,63,233,135,75,63,15,183,75,63,32,230,75,63,26,21,76,63,254,67,76,63,204,114,76,63,132,161,76,63,38,208,76,63,177,254,76,63,38,45,77,63,133,91,77,63,206,137,77,63,0,184,77,63,28,230,77,63,34,20,78,63,17,66,78,63,234,111,78,63,172,157,78,63,88,203,78,63,238,248,78,63,108,38,79,63,213,83,79,63,38,129,79,63,97,174,79,63,134,219,79,63,147,8,80,63,138,53,80,63,107,98,80,63,52,143,80,63,231,187,80,63,131,232,80,63,8,21,81,63,119,65,81,63,206,109,81,63,15,154,81,63,57,198,81,63,76,242,81,63,71,30,82,63,44,74,82,63,250,117,82,63,177,161,82,63,81,205,82,63,218,248,82,63,76,36,83,63,166,79,83,63,234,122,83,63,22,166,83,63,44,209,83,63,42,252,83,63,17,39,84,63,224,81,84,63,153,124,84,63,58,167,84,63,196,209,84,63,54,252,84,63,146,38,85,63,214,80,85,63,2,123,85,63,24,165,85,63,22,207,85,63,252,248,85,63,204,34,86,63,131,76,86,63,36,118,86,63,172,159,86,63,30,201,86,63,120,242,86,63,186,27,87,63,229,68,87,63,248,109,87,63,244,150,87,63,216,191,87,63,165,232,87,63,90,17,88,63,248,57,88,63,126,98,88,63,236,138,88,63,67,179,88,63,130,219,88,63,169,3,89,63,185,43,89,63,177,83,89,63,145,123,89,63,90,163,89,63,11,203,89,63,164,242,89,63,37,26,90,63,143,65,90,63,225,104,90,63,27,144,90,63,62,183,90,63,72,222,90,63,59,5,91,63,22,44,91,63,217,82,91,63,133,121,91,63,24,160,91,63,148,198,91,63,248,236,91,63,68,19,92,63,120,57,92,63,149,95,92,63,153,133,92,63,134,171,92,63,91,209,92,63,24,247,92,63,189,28,93,63,74,66,93,63,191,103,93,63,28,141,93,63,98,178,93,63,143,215,93,63,165,252,93,63,162,33,94,63,136,70,94,63,86,107,94,63,11,144,94,63,169,180,94,63,47,217,94,63,157,253,94,63,243,33,95,63,49,70,95,63,88,106,95,63,102,142,95,63,92,178,95,63,59,214,95,63,1,250,95,63,175,29,96,63,70,65,96,63,196,100,96,63,43,136,96,63,122,171,96,63,176,206,96,63,207,241,96,63,214,20,97,63,197,55,97,63,155,90,97,63,90,125,97,63,1,160,97,63,144,194,97,63,8,229,97,63,103,7,98,63,174,41,98,63,221,75,98,63,245,109,98,63,244,143,98,63,220,177,98,63,171,211,98,63,99,245,98,63,3,23,99,63,139,56,99,63,251,89,99,63,83,123,99,63,147,156,99,63,188,189,99,63,204,222,99,63,197,255,99,63,166,32,100,63,110,65,100,63,32,98,100,63,185,130,100,63,58,163,100,63,164,195,100,63,245,227,100,63,47,4,101,63,82,36,101,63,92,68,101,63,78,100,101,63,41,132,101,63,236,163,101,63,151,195,101,63,43,227,101,63,167,2,102,63,11,34,102,63,87,65,102,63,139,96,102,63,168,127,102,63,174,158,102,63,155,189,102,63,113,220,102,63,47,251,102,63,214,25,103,63,101,56,103,63,220,86,103,63,59,117,103,63,132,147,103,63,180,177,103,63,205,207,103,63,206,237,103,63,184,11,104,63,138,41,104,63,69,71,104,63,233,100,104,63,116,130,104,63,233,159,104,63,69,189,104,63,139,218,104,63,185,247,104,63,207,20,105,63,207,49,105,63,182,78,105,63,135,107,105,63,64,136,105,63,225,164,105,63,108,193,105,63,223,221,105,63,59,250,105,63,127,22,106,63,172,50,106,63,195,78,106,63,193,106,106,63,169,134,106,63,121,162,106,63,51,190,106,63,213,217,106,63,96,245,106,63,212,16,107,63,48,44,107,63,118,71,107,63,165,98,107,63,188,125,107,63,189,152,107,63,167,179,107,63,121,206,107,63,53,233,107,63,218,3,108,63,104,30,108,63,223,56,108,63,63,83,108,63,136,109,108,63,187,135,108,63,214,161,108,63,219,187,108,63,201,213,108,63,161,239,108,63,97,9,109,63,11,35,109,63,159,60,109,63,27,86,109,63,129,111,109,63,209,136,109,63,9,162,109,63,44,187,109,63,56,212,109,63,45,237,109,63,12,6,110,63,212,30,110,63,134,55,110,63,33,80,110,63,166,104,110,63,21,129,110,63,110,153,110,63,176,177,110,63,220,201,110,63,241,225,110,63,241,249,110,63,218,17,111,63,173,41,111,63,106,65,111,63,16,89,111,63,161,112,111,63,28,136,111,63,128,159,111,63,207,182,111,63,7,206,111,63,42,229,111,63,54,252,111,63,45,19,112,63,14,42,112,63,217,64,112,63,142,87,112,63,46,110,112,63,184,132,112,63,43,155,112,63,138,177,112,63,210,199,112,63,5,222,112,63,35,244,112,63,42,10,113,63,29,32,113,63,249,53,113,63,193,75,113,63,114,97,113,63,15,119,113,63,150,140,113,63,7,162,113,63,99,183,113,63,170,204,113,63,220,225,113,63,249,246,113,63,0,12,114,63,242,32,114,63,207,53,114,63,151,74,114,63,73,95,114,63,231,115,114,63,112,136,114,63,227,156,114,63,66,177,114,63,140,197,114,63,193,217,114,63,225,237,114,63,236,1,115,63,227,21,115,63,197,41,115,63,146,61,115,63,74,81,115,63,238,100,115,63,125,120,115,63,248,139,115,63,94,159,115,63,175,178,115,63,236,197,115,63,21,217,115,63,41,236,115,63,41,255,115,63,21,18,116,63,236,36,116,63,175,55,116,63,94,74,116,63,248,92,116,63,127,111,116,63,241,129,116,63,80,148,116,63,154,166,116,63,208,184,116,63,242,202,116,63,1,221,116,63,251,238,116,63,226,0,117,63,181,18,117,63,116,36,117,63,31,54,117,63,183,71,117,63,59,89,117,63,171,106,117,63,8,124,117,63,81,141,117,63,135,158,117,63,169,175,117,63,184,192,117,63,179,209,117,63,155,226,117,63,112,243,117,63,50,4,118,63,224,20,118,63,123,37,118,63,3,54,118,63,120,70,118,63,217,86,118,63,40,103,118,63,100,119,118,63,140,135,118,63,162,151,118,63,165,167,118,63,149,183,118,63,114,199,118,63,61,215,118,63,245,230,118,63,154,246,118,63,44,6,119,63,172,21,119,63,26,37,119,63,117,52,119,63,189,67,119,63,243,82,119,63,22,98,119,63,40,113,119,63,39,128,119,63,19,143,119,63,238,157,119,63,182,172,119,63,108,187,119,63,16,202,119,63,162,216,119,63,34,231,119,63,144,245,119,63,236,3,120,63,55,18,120,63,111,32,120,63,150,46,120,63,170,60,120,63,174,74,120,63,159,88,120,63,127,102,120,63,77,116,120,63,10,130,120,63,181,143,120,63,79,157,120,63,215,170,120,63,78,184,120,63,180,197,120,63,8,211,120,63,76,224,120,63,126,237,120,63,158,250,120,63,174,7,121,63,173,20,121,63,155,33,121,63,119,46,121,63,67,59,121,63,254,71,121,63,168,84,121,63,66,97,121,63,202,109,121,63,66,122,121,63,169,134,121,63,0,147,121,63,70,159,121,63,124,171,121,63,161,183,121,63,181,195,121,63,186,207,121,63,173,219,121,63,145,231,121,63,100,243,121,63,40,255,121,63,219,10,122,63,126,22,122,63,16,34,122,63,147,45,122,63,6,57,122,63,105,68,122,63,188,79,122,63,255,90,122,63,51,102,122,63,86,113,122,63,106,124,122,63,111,135,122,63,99,146,122,63,72,157,122,63,30,168,122,63,228,178,122,63,155,189,122,63,66,200,122,63,218,210,122,63,99,221,122,63,221,231,122,63,71,242,122,63,162,252,122,63,238,6,123,63,43,17,123,63,89,27,123,63,120,37,123,63,137,47,123,63,138,57,123,63,124,67,123,63,96,77,123,63,53,87,123,63,252,96,123,63,179,106,123,63,92,116,123,63,247,125,123,63,131,135,123,63,1,145,123,63,112,154,123,63,209,163,123,63,36,173,123,63,104,182,123,63,158,191,123,63,198,200,123,63,224,209,123,63,236,218,123,63,234,227,123,63,218,236,123,63,188,245,123,63,144,254,123,63,86,7,124,63,14,16,124,63,185,24,124,63,86,33,124,63,230,41,124,63,104,50,124,63,220,58,124,63,67,67,124,63,156,75,124,63,232,83,124,63,39,92,124,63,88,100,124,63,124,108,124,63,147,116,124,63,157,124,124,63,153,132,124,63,137,140,124,63,107,148,124,63,65,156,124,63,9,164,124,63,197,171,124,63,116,179,124,63,22,187,124,63,172,194,124,63,52,202,124,63,176,209,124,63,32,217,124,63,131,224,124,63,217,231,124,63,35,239,124,63,97,246,124,63,146,253,124,63,183,4,125,63,208,11,125,63,221,18,125,63,221,25,125,63,209,32,125,63,185,39,125,63,150,46,125,63,102,53,125,63,42,60,125,63,227,66,125,63,143,73,125,63,48,80,125,63,197,86,125,63,78,93,125,63,204,99,125,63,62,106,125,63,165,112,125,63,0,119,125,63,80,125,125,63,148,131,125,63,205,137,125,63,251,143,125,63,29,150,125,63,52,156,125,63,64,162,125,63,65,168,125,63,55,174,125,63,34,180,125,63,2,186,125,63,215,191,125,63,161,197,125,63,96,203,125,63,21,209,125,63,190,214,125,63,93,220,125,63,242,225,125,63,124,231,125,63,251,236,125,63,112,242,125,63,218,247,125,63,58,253,125,63,143,2,126,63,219,7,126,63,28,13,126,63,82,18,126,63,127,23,126,63,161,28,126,63,186,33,126,63,200,38,126,63,204,43,126,63,199,48,126,63,183,53,126,63,158,58,126,63,123,63,126,63,78,68,126,63,23,73,126,63,215,77,126,63,141,82,126,63,58,87,126,63,221,91,126,63,118,96,126,63,6,101,126,63,141,105,126,63,10,110,126,63,126,114,126,63,233,118,126,63,75,123,126,63,164,127,126,63,243,131,126,63,57,136,126,63,119,140,126,63,171,144,126,63,214,148,126,63,249,152,126,63,18,157,126,63,35,161,126,63,44,165,126,63,43,169,126,63,34,173,126,63,16,177,126,63,246,180,126,63,211,184,126,63,167,188,126,63,115,192,126,63,55,196,126,63,243,199,126,63,166,203,126,63,81,207,126,63,243,210,126,63,142,214,126,63,32,218,126,63,171,221,126,63,45,225,126,63,167,228,126,63,26,232,126,63,132,235,126,63,231,238,126,63,66,242,126,63,149,245,126,63,224,248,126,63,36,252,126,63,96,255,126,63,148,2,127,63,193,5,127,63,230,8,127,63,4,12,127,63,27,15,127,63,42,18,127,63,50,21,127,63,50,24,127,63,43,27,127,63,29,30,127,63,8,33,127,63,236,35,127,63,201,38,127,63,158,41,127,63,109,44,127,63,53,47,127,63,246,49,127,63,175,52,127,63,99,55,127,63,15,58,127,63,181,60,127,63,83,63,127,63,236,65,127,63,125,68,127,63,8,71,127,63,141,73,127,63,11,76,127,63,131,78,127,63,244,80,127,63,95,83,127,63,195,85,127,63,33,88,127,63,121,90,127,63,203,92,127,63,23,95,127,63,92,97,127,63,155,99,127,63,213,101,127,63,8,104,127,63,54,106,127,63,93,108,127,63,127,110,127,63,155,112,127,63,177,114,127,63,193,116,127,63,203,118,127,63,208,120,127,63,207,122,127,63,201,124,127,63,189,126,127,63,171,128,127,63,148,130,127,63,120,132,127,63,86,134,127,63,47,136,127,63,2,138,127,63,209,139,127,63,153,141,127,63,93,143,127,63,28,145,127,63,213,146,127,63,137,148,127,63,57,150,127,63,227,151,127,63,136,153,127,63,40,155,127,63,196,156,127,63,90,158,127,63,236,159,127,63,121,161,127,63,1,163,127,63,132,164,127,63,3,166,127,63,125,167,127,63,242,168,127,63,99,170,127,63,207,171,127,63,55,173,127,63,154,174,127,63,249,175,127,63,84,177,127,63,170,178,127,63,251,179,127,63,73,181,127,63,146,182,127,63,215,183,127,63,24,185,127,63,85,186,127,63,141,187,127,63,193,188,127,63,242,189,127,63,30,191,127,63,71,192,127,63,107,193,127,63,140,194,127,63,168,195,127,63,193,196,127,63,214,197,127,63,231,198,127,63,245,199,127,63,255,200,127,63,5,202,127,63,7,203,127,63,6,204,127,63,1,205,127,63,249,205,127,63,237,206,127,63,222,207,127,63,203,208,127,63,181,209,127,63,156,210,127,63,127,211,127,63,95,212,127,63,59,213,127,63,20,214,127,63,234,214,127,63,189,215,127,63,141,216,127,63,90,217,127,63,35,218,127,63,233,218,127,63,173,219,127,63,109,220,127,63,43,221,127,63,229,221,127,63,156,222,127,63,81,223,127,63,3,224,127,63,178,224,127,63,94,225,127,63,7,226,127,63,174,226,127,63,82,227,127,63,243,227,127,63,146,228,127,63,46,229,127,63,199,229,127,63,94,230,127,63,242,230,127,63,132,231,127,63,19,232,127,63,160,232,127,63,42,233,127,63,178,233,127,63,56,234,127,63,187,234,127,63,60,235,127,63,187,235,127,63,55,236,127,63,177,236,127,63,41,237,127,63,159,237,127,63,18,238,127,63,132,238,127,63,243,238,127,63,96,239,127,63,204,239,127,63,53,240,127,63,156,240,127,63,1,241,127,63,101,241,127,63,198,241,127,63,37,242,127,63,131,242,127,63,222,242,127,63,56,243,127,63,144,243,127,63,231,243,127,63,59,244,127,63,142,244,127,63,223,244,127,63,46,245,127,63,124,245,127,63,200,245,127,63,19,246,127,63,91,246,127,63,163,246,127,63,233,246,127,63,45,247,127,63,111,247,127,63,177,247,127,63,240,247,127,63,47,248,127,63,108,248,127,63,167,248,127,63,225,248,127,63,26,249,127,63,82,249,127,63,136,249,127,63,188,249,127,63,240,249,127,63,34,250,127,63,83,250,127,63,131,250,127,63,178,250,127,63,224,250,127,63,12,251,127,63,55,251,127,63,97,251,127,63,138,251,127,63,178,251,127,63,217,251,127,63,255,251,127,63,36,252,127,63,72,252,127,63,107,252,127,63,141,252,127,63,173,252,127,63,205,252,127,63,237,252,127,63,11,253,127,63,40,253,127,63,69,253,127,63,96,253,127,63,123,253,127,63,149,253,127,63,174,253,127,63,199,253,127,63,222,253,127,63,245,253,127,63,12,254,127,63,33,254,127,63,54,254,127,63,74,254,127,63,93,254,127,63,112,254,127,63,130,254,127,63,148,254,127,63,165,254,127,63,181,254,127,63,197,254,127,63,212,254,127,63,227,254,127,63,241,254,127,63,254,254,127,63,11,255,127,63,24,255,127,63,36,255,127,63,47,255,127,63,59,255,127,63,69,255,127,63,79,255,127,63,89,255,127,63,99,255,127,63,108,255,127,63,116,255,127,63,124,255,127,63,132,255,127,63,140,255,127,63,147,255,127,63,154,255,127,63,160,255,127,63,166,255,127,63,172,255,127,63,178,255,127,63,183,255,127,63,188,255,127,63,193,255,127,63,197,255,127,63,202,255,127,63,206,255,127,63,209,255,127,63,213,255,127,63,216,255,127,63,220,255,127,63,223,255,127,63,225,255,127,63,228,255,127,63,230,255,127,63,233,255,127,63,235,255,127,63,237,255,127,63,239,255,127,63,240,255,127,63,242,255,127,63,243,255,127,63,245,255,127,63,246,255,127,63,247,255,127,63,248,255,127,63,249,255,127,63,250,255,127,63,251,255,127,63,251,255,127,63,252,255,127,63,252,255,127,63,253,255,127,63,253,255,127,63,254,255,127,63,254,255,127,63,254,255,127,63,255,255,127,63,255,255,127,63,255,255,127,63,255,255,127,63,255,255,127,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,198,63,120,51,98,136,11,53,151,200,193,53,80,233,61,54,183,247,156,54,46,124,234,54,153,192,35,55,244,2,90,55,56,3,140,55,227,228,174,55,177,166,213,55,108,36,0,56,146,101,23,56,201,150,48,56,18,184,75,56,81,201,104,56,94,229,131,56,29,94,148,56,229,206,165,56,167,55,184,56,128,152,203,56,85,241,223,56,36,66,245,56,126,197,5,57,238,101,17,57,99,130,29,57,207,26,42,57,63,47,55,57,179,191,68,57,30,204,82,57,141,84,97,57,243,88,112,57,94,217,127,57,227,234,135,57,18,39,144,57,64,161,152,57,105,89,161,57,146,79,170,57,181,131,179,57,215,245,188,57,245,165,198,57,14,148,208,57,34,192,218,57,46,42,229,57,57,210,239,57,60,184,250,57,27,238,2,58,22,159,8,58,13,111,14,58,0,94,20,58,239,107,26,58,218,152,32,58,192,228,38,58,161,79,45,58,124,217,51,58,83,130,58,58,37,74,65,58,240,48,72,58,182,54,79,58,116,91,86,58,45,159,93,58,222,1,101,58,136,131,108,58,42,36,116,58,196,227,123,58,44,225,129,58,241,223,133,58,49,238,137,58,238,11,142,58,37,57,146,58,215,117,150,58,5,194,154,58,174,29,159,58,209,136,163,58,110,3,168,58,134,141,172,58,24,39,177,58,36,208,181,58,169,136,186,58,169,80,191,58,33,40,196,58,19,15,201,58,126,5,206,58,98,11,211,58,191,32,216,58,148,69,221,58,225,121,226,58,166,189,231,58,227,16,237,58,152,115,242,58,196,229,247,58,103,103,253,58,65,124,1,59,137,76,4,59,141,36,7,59,76,4,10,59,198,235,12,59,251,218,15,59,235,209,18,59,149,208,21,59,251,214,24,59,26,229,27,59,244,250,30,59,136,24,34,59,215,61,37,59,223,106,40,59,161,159,43,59,29,220,46,59,83,32,50,59,66,108,53,59,234,191,56,59,76,27,60,59,103,126,63,59,59,233,66,59,199,91,70,59,12,214,73,59,10,88,77,59,193,225,80,59,48,115,84,59,86,12,88,59,53,173,91,59,204,85,95,59,26,6,99,59,32,190,102,59,222,125,106,59,82,69,110,59,127,20,114,59,97,235,117,59,251,201,121,59,76,176,125,59,41,207,128,59,8,202,130,59,194,200,132,59,87,203,134,59,198,209,136,59,17,220,138,59,55,234,140,59,55,252,142,59,18,18,145,59,199,43,147,59,87,73,149,59,194,106,151,59,6,144,153,59,37,185,155,59,30,230,157,59,241,22,160,59,158,75,162,59,37,132,164,59,134,192,166,59,192,0,169,59,212,68,171,59,193,140,173,59,137,216,175,59,41,40,178,59,163,123,180,59,245,210,182,59,33,46,185,59,38,141,187,59,4,240,189,59,186,86,192,59,73,193,194,59,177,47,197,59,242,161,199,59,10,24,202,59,251,145,204,59,196,15,207,59,102,145,209,59,223,22,212,59,49,160,214,59,90,45,217,59,91,190,219,59,51,83,222,59,227,235,224,59,107,136,227,59,201,40,230,59,255,204,232,59,12,117,235,59,240,32,238,59,171,208,240,59,61,132,243,59,165,59,246,59,228,246,248,59,250,181,251,59,229,120,254,59,212,159,0,60,32,5,2,60,87,108,3,60,121,213,4,60,134,64,6,60,126,173,7,60,96,28,9,60,45,141,10,60,229,255,11,60,136,116,13,60,21,235,14,60,141,99,16,60,239,221,17,60,59,90,19,60,114,216,20,60,147,88,22,60,158,218,23,60,147,94,25,60,115,228,26,60,60,108,28,60,240,245,29,60,141,129,31,60,20,15,33,60,133,158,34,60,224,47,36,60,36,195,37,60,82,88,39,60,105,239,40,60,106,136,42,60,84,35,44,60,40,192,45,60,229,94,47,60,139,255,48,60,26,162,50,60,146,70,52,60,243,236,53,60,61,149,55,60,112,63,57,60,140,235,58,60,145,153,60,60,126,73,62,60,84,251,63,60,18,175,65,60,185,100,67,60,72,28,69,60,192,213,70,60,31,145,72,60,103,78,74,60,151,13,76,60,175,206,77,60,176,145,79,60,152,86,81,60,103,29,83,60,31,230,84,60,190,176,86,60,69,125,88,60,179,75,90,60,9,28,92,60,71,238,93,60,107,194,95,60,119,152,97,60,106,112,99,60,68,74,101,60,5,38,103,60,173,3,105,60,60,227,106,60,178,196,108,60,14,168,110,60,81,141,112,60,123,116,114,60,139,93,116,60,130,72,118,60,95,53,120,60,34,36,122,60,203,20,124,60,90,7,126,60,208,251,127,60,22,249,128,60,54,245,129,60,74,242,130,60,80,240,131,60,73,239,132,60,53,239,133,60,19,240,134,60,229,241,135,60,169,244,136,60,95,248,137,60,8,253,138,60,164,2,140,60,50,9,141,60,178,16,142,60,37,25,143,60,139,34,144,60,226,44,145,60,44,56,146,60,104,68,147,60,150,81,148,60,182,95,149,60,201,110,150,60,205,126,151,60,196,143,152,60,172,161,153,60,135,180,154,60,83,200,155,60,17,221,156,60,193,242,157,60,98,9,159,60,245,32,160,60,122,57,161,60,241,82,162,60,89,109,163,60,178,136,164,60,253,164,165,60,57,194,166,60,103,224,167,60,134,255,168,60,151,31,170,60,152,64,171,60,139,98,172,60,111,133,173,60,68,169,174,60,10,206,175,60,193,243,176,60,105,26,178,60,2,66,179,60,139,106,180,60,6,148,181,60,113,190,182,60,205,233,183,60,26,22,185,60,87,67,186,60,133,113,187,60,163,160,188,60,177,208,189,60,177,1,191,60,160,51,192,60,128,102,193,60,80,154,194,60,16,207,195,60,193,4,197,60,97,59,198,60,242,114,199,60,114,171,200,60,227,228,201,60,67,31,203,60,147,90,204,60,211,150,205,60,3,212,206,60,34,18,208,60,49,81,209,60,48,145,210,60,30,210,211,60,252,19,213,60,201,86,214,60,133,154,215,60,49,223,216,60,204,36,218,60,86,107,219,60,208,178,220,60,56,251,221,60,144,68,223,60,214,142,224,60,12,218,225,60,48,38,227,60,67,115,228,60,69,193,229,60,54,16,231,60,21,96,232,60,227,176,233,60,160,2,235,60,75,85,236,60,228,168,237,60,108,253,238,60,226,82,240,60,70,169,241,60,153,0,243,60,218,88,244,60,8,178,245,60,37,12,247,60,48,103,248,60,41,195,249,60,15,32,251,60,228,125,252,60,166,220,253,60,85,60,255,60,121,78,0,61,63,255,0,61,123,176,1,61,46,98,2,61,88,20,3,61,248,198,3,61,15,122,4,61,156,45,5,61,161,225,5,61,27,150,6,61,12,75,7,61,116,0,8,61,82,182,8,61,167,108,9,61,113,35,10,61,179,218,10,61,106,146,11,61,152,74,12,61,60,3,13,61,87,188,13,61,231,117,14,61,238,47,15,61,107,234,15,61,94,165,16,61,199,96,17,61,166,28,18,61,251,216,18,61,198,149,19,61,7,83,20,61,190,16,21,61,234,206,21,61,141,141,22,61,165,76,23,61,52,12,24,61,56,204,24,61,177,140,25,61,161,77,26,61,6,15,27,61,224,208,27,61,48,147,28,61,246,85,29,61,49,25,30,61,226,220,30,61,8,161,31,61,164,101,32,61,181,42,33,61,59,240,33,61,55,182,34,61,168,124,35,61,142,67,36,61,233,10,37,61,186,210,37,61,255,154,38,61,186,99,39,61,234,44,40,61,143,246,40,61,168,192,41,61,55,139,42,61,59,86,43,61,180,33,44,61,161,237,44,61,4,186,45,61,219,134,46,61,38,84,47,61,231,33,48,61,28,240,48,61,198,190,49,61,229,141,50,61,120,93,51,61,127,45,52,61,251,253,52,61,236,206,53,61,81,160,54,61,42,114,55,61,120,68,56,61,58,23,57,61,112,234,57,61,27,190,58,61,58,146,59,61,204,102,60,61,211,59,61,61,79,17,62,61,62,231,62,61,161,189,63,61,120,148,64,61,195,107,65,61,130,67,66,61,181,27,67,61,92,244,67,61,118,205,68,61,4,167,69,61,6,129,70,61,124,91,71,61,101,54,72,61,194,17,73,61,146,237,73,61,214,201,74,61,141,166,75,61,184,131,76,61,86,97,77,61,104,63,78,61,236,29,79,61,229,252,79,61,80,220,80,61,46,188,81,61,128,156,82,61,69,125,83,61,125,94,84,61,40,64,85,61,69,34,86,61,214,4,87,61,218,231,87,61,81,203,88,61,58,175,89,61,150,147,90,61,101,120,91,61,167,93,92,61,91,67,93,61,130,41,94,61,28,16,95,61,40,247,95,61,167,222,96,61,152,198,97,61,251,174,98,61,209,151,99,61,25,129,100,61,212,106,101,61,0,85,102,61,159,63,103,61,176,42,104,61,51,22,105,61,41,2,106,61,144,238,106,61,105,219,107,61,180,200,108,61,113,182,109,61,160,164,110,61,65,147,111,61,84,130,112,61,216,113,113,61,206,97,114,61,54,82,115,61,15,67,116,61,89,52,117,61,22,38,118,61,67,24,119,61,226,10,120,61,243,253,120,61,117,241,121,61,104,229,122,61,204,217,123,61,162,206,124,61,232,195,125,61,160,185,126,61,201,175,127,61,49,83,128,61,183,206,128,61,117,74,129,61,107,198,129,61,154,66,130,61,1,191,130,61,160,59,131,61,120,184,131,61,136,53,132,61,209,178,132,61,81,48,133,61,10,174,133,61,251,43,134,61,37,170,134,61,134,40,135,61,32,167,135,61,242,37,136,61,252,164,136,61,62,36,137,61,184,163,137,61,106,35,138,61,84,163,138,61,118,35,139,61,209,163,139,61,99,36,140,61,45,165,140,61,46,38,141,61,104,167,141,61,218,40,142,61,131,170,142,61,100,44,143,61,125,174,143,61,206,48,144,61,86,179,144,61,23,54,145,61,14,185,145,61,62,60,146,61,165,191,146,61,67,67,147,61,26,199,147,61,39,75,148,61,109,207,148,61,234,83,149,61,158,216,149,61,138,93,150,61,173,226,150,61,7,104,151,61,153,237,151,61,98,115,152,61,99,249,152,61,155,127,153,61,10,6,154,61,176,140,154,61,142,19,155,61,163,154,155,61,239,33,156,61,114,169,156,61,44,49,157,61,29,185,157,61,69,65,158,61,165,201,158,61,59,82,159,61,8,219,159,61,13,100,160,61,72,237,160,61,186,118,161,61,99,0,162,61,67,138,162,61,90,20,163,61,167,158,163,61,43,41,164,61,230,179,164,61,216,62,165,61,0,202,165,61,95,85,166,61,245,224,166,61,193,108,167,61,196,248,167,61,254,132,168,61,110,17,169,61,20,158,169,61,241,42,170,61,4,184,170,61,78,69,171,61,206,210,171,61,133,96,172,61,113,238,172,61,149,124,173,61,238,10,174,61,126,153,174,61,67,40,175,61,63,183,175,61,114,70,176,61,218,213,176,61,120,101,177,61,77,245,177,61,88,133,178,61,152,21,179,61,15,166,179,61,187,54,180,61,158,199,180,61,182,88,181,61,4,234,181,61,137,123,182,61,67,13,183,61,50,159,183,61,88,49,184,61,179,195,184,61,68,86,185,61,11,233,185,61,7,124,186,61,57,15,187,61,160,162,187,61,61,54,188,61,16,202,188,61,24,94,189,61,85,242,189,61,200,134,190,61,112,27,191,61,78,176,191,61,97,69,192,61,170,218,192,61,39,112,193,61,218,5,194,61,194,155,194,61,224,49,195,61,50,200,195,61,186,94,196,61,119,245,196,61,104,140,197,61,143,35,198,61,235,186,198,61,124,82,199,61,66,234,199,61,61,130,200,61,108,26,201,61,209,178,201,61,106,75,202,61,57,228,202,61,59,125,203,61,115,22,204,61,224,175,204,61,129,73,205,61,86,227,205,61,97,125,206,61,159,23,207,61,19,178,207,61,187,76,208,61,151,231,208,61,168,130,209,61,237,29,210,61,103,185,210,61,21,85,211,61,248,240,211,61,14,141,212,61,89,41,213,61,216,197,213,61,140,98,214,61,115,255,214,61,143,156,215,61,223,57,216,61,99,215,216,61,27,117,217,61,7,19,218,61,38,177,218,61,122,79,219,61,2,238,219,61,189,140,220,61,173,43,221,61,208,202,221,61,39,106,222,61,178,9,223,61,112,169,223,61,98,73,224,61,136,233,224,61,226,137,225,61,111,42,226,61,47,203,226,61,35,108,227,61,74,13,228,61,165,174,228,61,52,80,229,61,245,241,229,61,234,147,230,61,19,54,231,61,110,216,231,61,253,122,232,61,191,29,233,61,180,192,233,61,221,99,234,61,56,7,235,61,199,170,235,61,136,78,236,61,125,242,236,61,164,150,237,61,255,58,238,61,140,223,238,61,76,132,239,61,63,41,240,61,101,206,240,61,189,115,241,61,73,25,242,61,7,191,242,61,247,100,243,61,26,11,244,61,112,177,244,61,248,87,245,61,179,254,245,61,160,165,246,61,192,76,247,61,18,244,247,61,151,155,248,61,77,67,249,61,55,235,249,61,82,147,250,61,159,59,251,61,31,228,251,61,209,140,252,61,181,53,253,61,203,222,253,61,19,136,254,61,141,49,255,61,57,219,255,61,140,66,0,62,148,151,0,62,181,236,0,62,238,65,1,62,65,151,1,62,173,236,1,62,49,66,2,62,206,151,2,62,132,237,2,62,83,67,3,62,59,153,3,62,59,239,3,62,84,69,4,62,134,155,4,62,209,241,4,62,52,72,5,62,176,158,5,62,68,245,5,62,242,75,6,62,183,162,6,62,150,249,6,62,141,80,7,62,156,167,7,62,196,254,7,62,5,86,8,62,94,173,8,62,207,4,9,62,89,92,9,62,252,179,9,62,183,11,10,62,138,99,10,62,118,187,10,62,122,19,11,62,150,107,11,62,203,195,11,62,24,28,12,62,125,116,12,62,250,204,12,62,144,37,13,62,62,126,13,62,4,215,13,62,227,47,14,62,217,136,14,62,232,225,14,62,15,59,15,62,78,148,15,62,165,237,15,62,20,71,16,62,155,160,16,62,58,250,16,62,241,83,17,62,193,173,17,62,168,7,18,62,167,97,18,62,190,187,18,62,237,21,19,62,51,112,19,62,146,202,19,62,9,37,20,62,151,127,20,62,61,218,20,62,251,52,21,62,209,143,21,62,190,234,21,62,195,69,22,62,224,160,22,62,21,252,22,62,97,87,23,62,197,178,23,62,64,14,24,62,211,105,24,62,126,197,24,62,64,33,25,62,26,125,25,62,11,217,25,62,20,53,26,62,52,145,26,62,108,237,26,62,187,73,27,62,34,166,27,62,160,2,28,62,53,95,28,62,226,187,28,62],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE+10240);allocate([166,24,29,62,129,117,29,62,116,210,29,62,126,47,30,62,159,140,30,62,215,233,30,62,39,71,31,62,141,164,31,62,11,2,32,62,160,95,32,62,76,189,32,62,16,27,33,62,234,120,33,62,219,214,33,62,228,52,34,62,3,147,34,62,58,241,34,62,135,79,35,62,235,173,35,62,103,12,36,62,249,106,36,62,162,201,36,62,98,40,37,62,56,135,37,62,38,230,37,62,42,69,38,62,69,164,38,62,119,3,39,62,192,98,39,62,31,194,39,62,149,33,40,62,33,129,40,62,197,224,40,62,126,64,41,62,79,160,41,62,54,0,42,62,51,96,42,62,72,192,42,62,114,32,43,62,179,128,43,62,11,225,43,62,121,65,44,62,253,161,44,62,152,2,45,62,73,99,45,62,16,196,45,62,238,36,46,62,226,133,46,62,237,230,46,62,13,72,47,62,68,169,47,62,145,10,48,62,245,107,48,62,110,205,48,62,254,46,49,62,163,144,49,62,95,242,49,62,49,84,50,62,25,182,50,62,23,24,51,62,43,122,51,62,85,220,51,62,148,62,52,62,234,160,52,62,86,3,53,62,216,101,53,62,111,200,53,62,28,43,54,62,223,141,54,62,184,240,54,62,167,83,55,62,171,182,55,62,197,25,56,62,245,124,56,62,59,224,56,62,150,67,57,62,7,167,57,62,141,10,58,62,41,110,58,62,219,209,58,62,162,53,59,62,126,153,59,62,112,253,59,62,120,97,60,62,149,197,60,62,199,41,61,62,15,142,61,62,108,242,61,62,222,86,62,62,102,187,62,62,3,32,63,62,181,132,63,62,125,233,63,62,90,78,64,62,75,179,64,62,83,24,65,62,111,125,65,62,160,226,65,62,231,71,66,62,66,173,66,62,179,18,67,62,57,120,67,62,211,221,67,62,131,67,68,62,71,169,68,62,33,15,69,62,15,117,69,62,18,219,69,62,42,65,70,62,87,167,70,62,153,13,71,62,240,115,71,62,91,218,71,62,219,64,72,62,111,167,72,62,25,14,73,62,215,116,73,62,169,219,73,62,144,66,74,62,140,169,74,62,157,16,75,62,193,119,75,62,251,222,75,62,73,70,76,62,171,173,76,62,34,21,77,62,173,124,77,62,76,228,77,62,0,76,78,62,200,179,78,62,164,27,79,62,149,131,79,62,154,235,79,62,179,83,80,62,225,187,80,62,34,36,81,62,120,140,81,62,225,244,81,62,95,93,82,62,241,197,82,62,151,46,83,62,81,151,83,62,31,0,84,62,1,105,84,62,247,209,84,62,0,59,85,62,30,164,85,62,79,13,86,62,149,118,86,62,238,223,86,62,91,73,87,62,219,178,87,62,112,28,88,62,24,134,88,62,211,239,88,62,163,89,89,62,134,195,89,62,124,45,90,62,134,151,90,62,164,1,91,62,213,107,91,62,26,214,91,62,114,64,92,62,221,170,92,62,92,21,93,62,239,127,93,62,148,234,93,62,77,85,94,62,26,192,94,62,249,42,95,62,236,149,95,62,242,0,96,62,11,108,96,62,55,215,96,62,119,66,97,62,202,173,97,62,47,25,98,62,168,132,98,62,52,240,98,62,210,91,99,62,132,199,99,62,73,51,100,62,32,159,100,62,11,11,101,62,8,119,101,62,24,227,101,62,59,79,102,62,113,187,102,62,186,39,103,62,21,148,103,62,131,0,104,62,3,109,104,62,151,217,104,62,60,70,105,62,245,178,105,62,192,31,106,62,157,140,106,62,141,249,106,62,144,102,107,62,165,211,107,62,204,64,108,62,6,174,108,62,82,27,109,62,176,136,109,62,33,246,109,62,164,99,110,62,57,209,110,62,225,62,111,62,154,172,111,62,102,26,112,62,68,136,112,62,52,246,112,62,55,100,113,62,75,210,113,62,113,64,114,62,169,174,114,62,243,28,115,62,80,139,115,62,190,249,115,62,61,104,116,62,207,214,116,62,115,69,117,62,40,180,117,62,239,34,118,62,200,145,118,62,179,0,119,62,175,111,119,62,189,222,119,62,221,77,120,62,14,189,120,62,80,44,121,62,165,155,121,62,10,11,122,62,130,122,122,62,10,234,122,62,164,89,123,62,80,201,123,62,13,57,124,62,219,168,124,62,186,24,125,62,171,136,125,62,173,248,125,62,192,104,126,62,228,216,126,62,26,73,127,62,96,185,127,62,220,20,128,62,16,77,128,62,77,133,128,62,147,189,128,62,225,245,128,62,55,46,129,62,150,102,129,62,253,158,129,62,109,215,129,62,229,15,130,62,102,72,130,62,238,128,130,62,128,185,130,62,25,242,130,62,187,42,131,62,102,99,131,62,24,156,131,62,211,212,131,62,150,13,132,62,98,70,132,62,53,127,132,62,17,184,132,62,245,240,132,62,226,41,133,62,214,98,133,62,211,155,133,62,216,212,133,62,229,13,134,62,250,70,134,62,23,128,134,62,61,185,134,62,106,242,134,62,160,43,135,62,221,100,135,62,35,158,135,62,112,215,135,62,198,16,136,62,35,74,136,62,137,131,136,62,247,188,136,62,108,246,136,62,233,47,137,62,111,105,137,62,252,162,137,62,145,220,137,62,46,22,138,62,211,79,138,62,127,137,138,62,52,195,138,62,240,252,138,62,180,54,139,62,128,112,139,62,84,170,139,62,47,228,139,62,18,30,140,62,253,87,140,62,239,145,140,62,233,203,140,62,235,5,141,62,245,63,141,62,6,122,141,62,31,180,141,62,63,238,141,62,103,40,142,62,150,98,142,62,205,156,142,62,12,215,142,62,82,17,143,62,159,75,143,62,245,133,143,62,81,192,143,62,181,250,143,62,33,53,144,62,147,111,144,62,14,170,144,62,143,228,144,62,25,31,145,62,169,89,145,62,65,148,145,62,224,206,145,62,134,9,146,62,52,68,146,62,233,126,146,62,165,185,146,62,105,244,146,62,52,47,147,62,6,106,147,62,223,164,147,62,191,223,147,62,167,26,148,62,150,85,148,62,139,144,148,62,136,203,148,62,140,6,149,62,152,65,149,62,170,124,149,62,195,183,149,62,227,242,149,62,11,46,150,62,57,105,150,62,111,164,150,62,171,223,150,62,238,26,151,62,56,86,151,62,138,145,151,62,226,204,151,62,65,8,152,62,167,67,152,62,19,127,152,62,135,186,152,62,1,246,152,62,130,49,153,62,10,109,153,62,153,168,153,62,47,228,153,62,203,31,154,62,110,91,154,62,24,151,154,62,200,210,154,62,127,14,155,62,61,74,155,62,2,134,155,62,205,193,155,62,158,253,155,62,119,57,156,62,85,117,156,62,59,177,156,62,39,237,156,62,25,41,157,62,18,101,157,62,18,161,157,62,24,221,157,62,36,25,158,62,55,85,158,62,80,145,158,62,112,205,158,62,150,9,159,62,195,69,159,62,246,129,159,62,47,190,159,62,111,250,159,62,180,54,160,62,1,115,160,62,83,175,160,62,172,235,160,62,11,40,161,62,112,100,161,62,219,160,161,62,77,221,161,62,196,25,162,62,66,86,162,62,198,146,162,62,81,207,162,62,225,11,163,62,119,72,163,62,20,133,163,62,182,193,163,62,95,254,163,62,13,59,164,62,194,119,164,62,125,180,164,62,61,241,164,62,4,46,165,62,208,106,165,62,162,167,165,62,123,228,165,62,89,33,166,62,61,94,166,62,39,155,166,62,23,216,166,62,12,21,167,62,7,82,167,62,8,143,167,62,15,204,167,62,28,9,168,62,46,70,168,62,70,131,168,62,100,192,168,62,136,253,168,62,177,58,169,62,223,119,169,62,20,181,169,62,78,242,169,62,141,47,170,62,211,108,170,62,29,170,170,62,109,231,170,62,195,36,171,62,31,98,171,62,127,159,171,62,230,220,171,62,81,26,172,62,194,87,172,62,57,149,172,62,181,210,172,62,54,16,173,62,189,77,173,62,73,139,173,62,218,200,173,62,113,6,174,62,13,68,174,62,174,129,174,62,85,191,174,62,0,253,174,62,177,58,175,62,103,120,175,62,35,182,175,62,227,243,175,62,169,49,176,62,116,111,176,62,68,173,176,62,25,235,176,62,243,40,177,62,210,102,177,62,182,164,177,62,160,226,177,62,142,32,178,62,129,94,178,62,121,156,178,62,119,218,178,62,121,24,179,62,128,86,179,62,140,148,179,62,157,210,179,62,178,16,180,62,205,78,180,62,236,140,180,62,16,203,180,62,57,9,181,62,103,71,181,62,154,133,181,62,209,195,181,62,13,2,182,62,78,64,182,62,147,126,182,62,221,188,182,62,44,251,182,62,127,57,183,62,215,119,183,62,52,182,183,62,149,244,183,62,251,50,184,62,101,113,184,62,212,175,184,62,71,238,184,62,191,44,185,62,59,107,185,62,188,169,185,62,65,232,185,62,202,38,186,62,88,101,186,62,235,163,186,62,129,226,186,62,28,33,187,62,188,95,187,62,95,158,187,62,7,221,187,62,180,27,188,62,100,90,188,62,25,153,188,62,210,215,188,62,143,22,189,62,80,85,189,62,22,148,189,62,223,210,189,62,173,17,190,62,127,80,190,62,85,143,190,62,47,206,190,62,13,13,191,62,239,75,191,62,213,138,191,62,191,201,191,62,173,8,192,62,159,71,192,62,149,134,192,62,143,197,192,62,141,4,193,62,143,67,193,62,148,130,193,62,158,193,193,62,171,0,194,62,188,63,194,62,209,126,194,62,234,189,194,62,6,253,194,62,38,60,195,62,74,123,195,62,113,186,195,62,157,249,195,62,204,56,196,62,254,119,196,62,52,183,196,62,110,246,196,62,171,53,197,62,236,116,197,62,49,180,197,62,121,243,197,62,196,50,198,62,19,114,198,62,102,177,198,62,188,240,198,62,21,48,199,62,114,111,199,62,210,174,199,62,54,238,199,62,157,45,200,62,7,109,200,62,117,172,200,62,230,235,200,62,90,43,201,62,209,106,201,62,76,170,201,62,202,233,201,62,75,41,202,62,208,104,202,62,88,168,202,62,226,231,202,62,112,39,203,62,1,103,203,62,149,166,203,62,45,230,203,62,199,37,204,62,100,101,204,62,4,165,204,62,168,228,204,62,78,36,205,62,248,99,205,62,164,163,205,62,83,227,205,62,5,35,206,62,186,98,206,62,114,162,206,62,45,226,206,62,234,33,207,62,171,97,207,62,110,161,207,62,52,225,207,62,253,32,208,62,200,96,208,62,150,160,208,62,103,224,208,62,59,32,209,62,17,96,209,62,234,159,209,62,198,223,209,62,164,31,210,62,133,95,210,62,104,159,210,62,78,223,210,62,55,31,211,62,33,95,211,62,15,159,211,62,255,222,211,62,241,30,212,62,230,94,212,62,221,158,212,62,215,222,212,62,211,30,213,62,209,94,213,62,210,158,213,62,213,222,213,62,219,30,214,62,226,94,214,62,236,158,214,62,248,222,214,62,7,31,215,62,24,95,215,62,42,159,215,62,63,223,215,62,87,31,216,62,112,95,216,62,139,159,216,62,169,223,216,62,200,31,217,62,234,95,217,62,14,160,217,62,51,224,217,62,91,32,218,62,133,96,218,62,176,160,218,62,222,224,218,62,13,33,219,62,63,97,219,62,114,161,219,62,167,225,219,62,222,33,220,62,23,98,220,62,82,162,220,62,142,226,220,62,204,34,221,62,12,99,221,62,78,163,221,62,146,227,221,62,215,35,222,62,29,100,222,62,102,164,222,62,176,228,222,62,252,36,223,62,73,101,223,62,152,165,223,62,232,229,223,62,58,38,224,62,142,102,224,62,227,166,224,62,57,231,224,62,145,39,225,62,234,103,225,62,69,168,225,62,161,232,225,62,255,40,226,62,94,105,226,62,190,169,226,62,32,234,226,62,131,42,227,62,231,106,227,62,76,171,227,62,179,235,227,62,27,44,228,62,132,108,228,62,238,172,228,62,90,237,228,62,199,45,229,62,52,110,229,62,163,174,229,62,19,239,229,62,133,47,230,62,247,111,230,62,106,176,230,62,222,240,230,62,83,49,231,62,202,113,231,62,65,178,231,62,185,242,231,62,50,51,232,62,172,115,232,62,38,180,232,62,162,244,232,62,31,53,233,62,156,117,233,62,26,182,233,62,153,246,233,62,25,55,234,62,153,119,234,62,26,184,234,62,156,248,234,62,31,57,235,62,162,121,235,62,38,186,235,62,170,250,235,62,47,59,236,62,181,123,236,62,59,188,236,62,194,252,236,62,73,61,237,62,209,125,237,62,89,190,237,62,226,254,237,62,107,63,238,62,245,127,238,62,127,192,238,62,10,1,239,62,149,65,239,62,32,130,239,62,171,194,239,62,55,3,240,62,196,67,240,62,80,132,240,62,221,196,240,62,106,5,241,62,247,69,241,62,132,134,241,62,18,199,241,62,160,7,242,62,45,72,242,62,187,136,242,62,74,201,242,62,216,9,243,62,102,74,243,62,244,138,243,62,131,203,243,62,17,12,244,62,159,76,244,62,46,141,244,62,188,205,244,62,74,14,245,62,216,78,245,62,102,143,245,62,244,207,245,62,129,16,246,62,15,81,246,62,156,145,246,62,41,210,246,62,182,18,247,62,67,83,247,62,207,147,247,62,91,212,247,62,231,20,248,62,115,85,248,62,254,149,248,62,136,214,248,62,19,23,249,62,157,87,249,62,38,152,249,62,175,216,249,62,56,25,250,62,192,89,250,62,72,154,250,62,207,218,250,62,86,27,251,62,220,91,251,62,97,156,251,62,230,220,251,62,106,29,252,62,238,93,252,62,113,158,252,62,243,222,252,62,117,31,253,62,245,95,253,62,118,160,253,62,245,224,253,62,116,33,254,62,241,97,254,62,110,162,254,62,235,226,254,62,102,35,255,62,224,99,255,62,90,164,255,62,211,228,255,62,165,18,0,63,225,50,0,63,27,83,0,63,86,115,0,63,144,147,0,63,201,179,0,63,2,212,0,63,58,244,0,63,114,20,1,63,169,52,1,63,224,84,1,63,22,117,1,63,76,149,1,63,129,181,1,63,181,213,1,63,233,245,1,63,28,22,2,63,78,54,2,63,128,86,2,63,178,118,2,63,226,150,2,63,18,183,2,63,65,215,2,63,112,247,2,63,157,23,3,63,203,55,3,63,247,87,3,63,35,120,3,63,78,152,3,63,120,184,3,63,161,216,3,63,202,248,3,63,242,24,4,63,25,57,4,63,63,89,4,63,101,121,4,63,137,153,4,63,173,185,4,63,208,217,4,63,243,249,4,63,20,26,5,63,52,58,5,63,84,90,5,63,115,122,5,63,145,154,5,63,173,186,5,63,202,218,5,63,229,250,5,63,255,26,6,63,24,59,6,63,48,91,6,63,72,123,6,63,94,155,6,63,116,187,6,63,136,219,6,63,155,251,6,63,174,27,7,63,191,59,7,63,208,91,7,63,223,123,7,63,237,155,7,63,250,187,7,63,7,220,7,63,18,252,7,63,28,28,8,63,37,60,8,63,44,92,8,63,51,124,8,63,57,156,8,63,61,188,8,63,64,220,8,63,67,252,8,63,68,28,9,63,68,60,9,63,66,92,9,63,64,124,9,63,60,156,9,63,55,188,9,63,49,220,9,63,41,252,9,63,33,28,10,63,23,60,10,63,12,92,10,63,255,123,10,63,242,155,10,63,227,187,10,63,211,219,10,63,193,251,10,63,174,27,11,63,154,59,11,63,133,91,11,63,110,123,11,63,86,155,11,63,60,187,11,63,33,219,11,63,5,251,11,63,231,26,12,63,200,58,12,63,168,90,12,63,134,122,12,63,98,154,12,63,62,186,12,63,23,218,12,63,240,249,12,63,199,25,13,63,156,57,13,63,112,89,13,63,66,121,13,63,19,153,13,63,227,184,13,63,176,216,13,63,125,248,13,63,72,24,14,63,17,56,14,63,216,87,14,63,159,119,14,63,99,151,14,63,38,183,14,63,232,214,14,63,167,246,14,63,101,22,15,63,34,54,15,63,221,85,15,63,150,117,15,63,78,149,15,63,4,181,15,63,184,212,15,63,106,244,15,63,27,20,16,63,202,51,16,63,120,83,16,63,36,115,16,63,206,146,16,63,118,178,16,63,28,210,16,63,193,241,16,63,100,17,17,63,6,49,17,63,165,80,17,63,67,112,17,63,223,143,17,63,121,175,17,63,17,207,17,63,167,238,17,63,60,14,18,63,206,45,18,63,95,77,18,63,238,108,18,63,123,140,18,63,7,172,18,63,144,203,18,63,23,235,18,63,157,10,19,63,32,42,19,63,162,73,19,63,34,105,19,63,159,136,19,63,27,168,19,63,149,199,19,63,13,231,19,63,131,6,20,63,247,37,20,63,104,69,20,63,216,100,20,63,70,132,20,63,178,163,20,63,27,195,20,63,131,226,20,63,233,1,21,63,76,33,21,63,174,64,21,63,13,96,21,63,106,127,21,63,197,158,21,63,31,190,21,63,117,221,21,63,202,252,21,63,29,28,22,63,109,59,22,63,188,90,22,63,8,122,22,63,82,153,22,63,153,184,22,63,223,215,22,63,34,247,22,63,100,22,23,63,162,53,23,63,223,84,23,63,26,116,23,63,82,147,23,63,136,178,23,63,187,209,23,63,237,240,23,63,28,16,24,63,73,47,24,63,115,78,24,63,155,109,24,63,193,140,24,63,228,171,24,63,6,203,24,63,36,234,24,63,65,9,25,63,91,40,25,63,115,71,25,63,136,102,25,63,155,133,25,63,171,164,25,63,185,195,25,63,197,226,25,63,206,1,26,63,213,32,26,63,217,63,26,63,219,94,26,63,218,125,26,63,215,156,26,63,210,187,26,63,202,218,26,63,191,249,26,63,178,24,27,63,162,55,27,63,144,86,27,63,123,117,27,63,100,148,27,63,74,179,27,63,46,210,27,63,15,241,27,63,237,15,28,63,201,46,28,63,162,77,28,63,121,108,28,63,77,139,28,63,31,170,28,63,237,200,28,63,185,231,28,63,131,6,29,63,74,37,29,63,14,68,29,63,207,98,29,63,142,129,29,63,74,160,29,63,3,191,29,63,186,221,29,63,110,252,29,63,31,27,30,63,205,57,30,63,121,88,30,63,34,119,30,63,200,149,30,63,107,180,30,63,12,211,30,63,170,241,30,63,69,16,31,63,221,46,31,63,114,77,31,63,5,108,31,63,148,138,31,63,33,169,31,63,171,199,31,63,50,230,31,63,182,4,32,63,56,35,32,63,182,65,32,63,50,96,32,63,170,126,32,63,32,157,32,63,147,187,32,63,3,218,32,63,112,248,32,63,218,22,33,63,65,53,33,63,165,83,33,63,6,114,33,63,100,144,33,63,191,174,33,63,23,205,33,63,108,235,33,63,190,9,34,63,13,40,34,63,89,70,34,63,162,100,34,63,232,130,34,63,43,161,34,63,107,191,34,63,167,221,34,63,225,251,34,63,24,26,35,63,75,56,35,63,123,86,35,63,168,116,35,63,211,146,35,63,249,176,35,63,29,207,35,63,62,237,35,63,91,11,36,63,118,41,36,63,141,71,36,63,161,101,36,63,177,131,36,63,191,161,36,63,201,191,36,63,208,221,36,63,212,251,36,63,213,25,37,63,210,55,37,63,204,85,37,63,195,115,37,63,183,145,37,63,167,175,37,63,148,205,37,63,126,235,37,63,101,9,38,63,72,39,38,63,40,69,38,63,4,99,38,63,221,128,38,63,179,158,38,63,134,188,38,63,85,218,38,63,33,248,38,63,233,21,39,63,174,51,39,63,112,81,39,63,46,111,39,63,233,140,39,63,160,170,39,63,84,200,39,63,4,230,39,63,178,3,40,63,91,33,40,63,1,63,40,63,164,92,40,63,67,122,40,63,223,151,40,63,120,181,40,63,12,211,40,63,158,240,40,63,43,14,41,63,182,43,41,63,60,73,41,63,192,102,41,63,63,132,41,63,187,161,41,63,52,191,41,63,169,220,41,63,26,250,41,63,136,23,42,63,242,52,42,63,89,82,42,63,188,111,42,63,28,141,42,63,119,170,42,63,208,199,42,63,36,229,42,63,117,2,43,63,194,31,43,63,12,61,43,63,82,90,43,63,148,119,43,63,211,148,43,63,14,178,43,63,69,207,43,63,120,236,43,63,168,9,44,63,212,38,44,63,252,67,44,63,33,97,44,63,66,126,44,63,95,155,44,63,120,184,44,63,142,213,44,63,159,242,44,63,173,15,45,63,184,44,45,63,190,73,45,63,193,102,45,63,191,131,45,63,186,160,45,63,177,189,45,63,165,218,45,63,148,247,45,63,128,20,46,63,103,49,46,63,75,78,46,63,43,107,46,63,7,136,46,63,224,164,46,63,180,193,46,63,132,222,46,63,81,251,46,63,26,24,47,63,222,52,47,63,159,81,47,63,92,110,47,63,21,139,47,63,202,167,47,63,123,196,47,63,40,225,47,63,209,253,47,63,118,26,48,63,23,55,48,63,180,83,48,63,77,112,48,63,226,140,48,63,115,169,48,63,0,198,48,63,137,226,48,63,14,255,48,63,142,27,49,63,11,56,49,63,132,84,49,63,248,112,49,63,105,141,49,63,214,169,49,63,62,198,49,63,162,226,49,63,2,255,49,63,95,27,50,63,182,55,50,63,10,84,50,63,90,112,50,63,166,140,50,63,237,168,50,63,48,197,50,63,111,225,50,63,170,253,50,63,225,25,51,63,19,54,51,63,66,82,51,63,108,110,51,63,146,138,51,63,180,166,51,63,209,194,51,63,234,222,51,63,0,251,51,63,16,23,52,63,29,51,52,63,37,79,52,63,41,107,52,63,41,135,52,63,37,163,52,63,28,191,52,63,15,219,52,63,253,246,52,63,232,18,53,63,206,46,53,63,176,74,53,63,141,102,53,63,102,130,53,63,59,158,53,63,11,186,53,63,215,213,53,63,159,241,53,63,98,13,54,63,33,41,54,63,220,68,54,63,146,96,54,63,68,124,54,63,241,151,54,63,154,179,54,63,63,207,54,63,223,234,54,63,123,6,55,63,18,34,55,63,165,61,55,63,52,89,55,63,190,116,55,63,67,144,55,63,196,171,55,63,65,199,55,63,185,226,55,63,45,254,55,63,156,25,56,63,7,53,56,63,109,80,56,63,207,107,56,63,44,135,56,63,133,162,56,63,217,189,56,63,40,217,56,63,115,244,56,63,186,15,57,63,252,42,57,63,57,70,57,63,114,97,57,63,166,124,57,63,214,151,57,63,1,179,57,63,40,206,57,63,74,233,57,63,103,4,58,63,128,31,58,63,148,58,58,63,163,85,58,63,174,112,58,63,180,139,58,63,182,166,58,63,179,193,58,63,171,220,58,63,159,247,58,63,142,18,59,63,120,45,59,63,94,72,59,63,63,99,59,63,27,126,59,63,243,152,59,63,197,179,59,63,148,206,59,63,93,233,59,63,34,4,60,63,226,30,60,63,157,57,60,63,84,84,60,63,5,111,60,63,178,137,60,63,91,164,60,63,254,190,60,63,157,217,60,63,55,244,60,63,204,14,61,63,93,41,61,63,232,67,61,63,111,94,61,63,241,120,61,63,110,147,61,63,231,173,61,63,91,200,61,63,201,226,61,63,51,253,61,63,152,23,62,63,249,49,62,63,84,76,62,63,171,102,62,63,252,128,62,63,73,155,62,63,145,181,62,63,212,207,62,63,19,234,62,63,76,4,63,63,128,30,63,63,176,56,63,63,219,82,63,63,0,109,63,63,33,135,63,63,61,161,63,63,84,187,63,63,102,213,63,63,115,239,63,63,123,9,64,63,127,35,64,63,125,61,64,63,118,87,64,63,106,113,64,63,90,139,64,63,68,165,64,63,42,191,64,63,10,217,64,63,229,242,64,63,188,12,65,63,141,38,65,63,90,64,65,63,33,90,65,63,228,115,65,63,161,141,65,63,89,167,65,63,13,193,65,63,187,218,65,63,100,244,65,63,8,14,66,63,167,39,66,63,65,65,66,63,214,90,66,63,102,116,66,63,241,141,66,63,119,167,66,63,248,192,66,63,115,218,66,63,234,243,66,63,91,13,67,63,199,38,67,63,47,64,67,63,145,89,67,63,238,114,67,63,69,140,67,63,152,165,67,63,230,190,67,63,46,216,67,63,113,241,67,63,175,10,68,63,232,35,68,63,28,61,68,63,75,86,68,63,116,111,68,63,153,136,68,63,184,161,68,63,210,186,68,63,230,211,68,63,246,236,68,63,0,6,69,63,5,31,69,63,5,56,69,63,0,81,69,63,245,105,69,63,230,130,69,63,209,155,69,63,182,180,69,63,151,205,69,63,114,230,69,63,72,255,69,63,25,24,70,63,229,48,70,63,171,73,70,63,108,98,70,63,40,123,70,63,222,147,70,63,143,172,70,63,59,197,70,63,226,221,70,63,131,246,70,63,31,15,71,63,182,39,71,63,71,64,71,63,211,88,71,63,90,113,71,63,220,137,71,63,88,162,71,63,207,186,71,63,64,211,71,63,172,235,71,63,19,4,72,63,116,28,72,63,209,52,72,63,39,77,72,63,121,101,72,63,197,125,72,63,11,150,72,63,77,174,72,63,137,198,72,63,191,222,72,63,240,246,72,63,28,15,73,63,66,39,73,63,99,63,73,63,127,87,73,63,149,111,73,63,166,135,73,63,177,159,73,63,183,183,73,63,183,207,73,63,178,231,73,63,168,255,73,63,152,23,74,63,131,47,74,63,104,71,74,63,72,95,74,63,34,119,74,63,247,142,74,63,199,166,74,63,145,190,74,63,85,214,74,63,20,238,74,63,206,5,75,63,130,29,75,63,49,53,75,63,218,76,75,63,126,100,75,63,28,124,75,63,181,147,75,63,72,171,75,63,213,194,75,63,93,218,75,63,224,241,75,63,93,9,76,63,213,32,76,63,71,56,76,63,179,79,76,63,26,103,76,63,124,126,76,63,216,149,76,63,46,173,76,63,127,196,76,63,202,219,76,63,16,243,76,63,80,10,77,63,139,33,77,63,192,56,77,63,240,79,77,63,26,103,77,63,62,126,77,63,93,149,77,63,118,172,77,63,137,195,77,63,151,218,77,63,160,241,77,63,163,8,78,63,160,31,78,63,151,54,78,63,137,77,78,63,118,100,78,63,93,123,78,63,62,146,78,63,25,169,78,63,239,191,78,63,192,214,78,63,138,237,78,63,79,4,79,63,15,27,79,63,201,49,79,63,125,72,79,63,43,95,79,63,212,117,79,63,119,140,79,63,21,163,79,63,172,185,79,63,63,208,79,63,203,230,79,63,82,253,79,63,211,19,80,63,79,42,80,63,197,64,80,63,53,87,80,63,159,109,80,63,4,132,80,63,99,154,80,63,189,176,80,63,16,199,80,63,94,221,80,63,167,243,80,63,233,9,81,63,38,32,81,63,93,54,81,63,143,76,81,63,187,98,81,63,225,120,81,63,1,143,81,63,28,165,81,63,48,187,81,63,64,209,81,63,73,231,81,63,77,253,81,63,75,19,82,63,67,41,82,63,53,63,82,63,34,85,82,63,9,107,82,63,234,128,82,63,198,150,82,63,155,172,82,63,107,194,82,63,53,216,82,63,250,237,82,63,185,3,83,63,113,25,83,63,37,47,83,63,210,68,83,63,121,90,83,63,27,112,83,63,183,133,83,63,77,155,83,63,222,176,83,63,104,198,83,63,237,219,83,63,108,241,83,63,230,6,84,63,89,28,84,63,199,49,84,63,46,71,84,63,145,92,84,63,237,113,84,63,67,135,84,63,148,156,84,63,223,177,84,63,35,199,84,63,99,220,84,63,156,241,84,63,207,6,85,63,253,27,85,63,37,49,85,63,71,70,85,63,99,91,85,63,121,112,85,63,138,133,85,63,149,154,85,63,153,175,85,63,152,196,85,63,146,217,85,63,133,238,85,63,114,3,86,63,90,24,86,63,60,45,86,63,24,66,86,63,238,86,86,63,190,107,86,63,136,128,86,63,76,149,86,63,11,170,86,63,196,190,86,63,118,211,86,63,35,232,86,63,203,252,86,63,108,17,87,63,7,38,87,63,156,58,87,63,44,79,87,63,182,99,87,63,58,120,87,63,183,140,87,63,47,161,87,63,162,181,87,63,14,202,87,63,116,222,87,63,213,242,87,63,47,7,88,63,132,27,88,63,211,47,88,63,28,68,88,63,95,88,88,63,156,108,88,63,211,128,88,63,4,149,88,63,47,169,88,63,85,189,88,63,116,209,88,63,142,229,88,63,162,249,88,63,175,13,89,63,183,33,89,63,185,53,89,63,181,73,89,63,171,93,89,63,155,113,89,63,134,133,89,63,106,153,89,63,72,173,89,63,33,193,89,63,243,212,89,63,192,232,89,63,135,252,89,63,71,16,90,63,2,36,90,63,183,55,90,63,102,75,90,63,15,95,90,63,178,114,90,63,79,134,90,63,230,153,90,63,119,173,90,63,3,193,90,63,136,212,90,63,7,232,90,63,129,251,90,63,244,14,91,63,98,34,91,63,201,53,91,63,43,73,91,63,135,92,91,63,220,111,91,63,44,131,91,63,118,150,91,63,186,169,91,63,248,188,91,63,47,208,91,63,97,227,91,63,141,246,91,63,179,9,92,63,212,28,92,63,238,47,92,63,2,67,92,63,16,86,92,63,24,105,92,63,26,124,92,63,23,143,92,63,13,162,92,63,253,180,92,63,232,199,92,63,204,218,92,63,171,237,92,63,131,0,93,63,86,19,93,63,34,38,93,63,233,56,93,63,169,75,93,63,100,94,93,63,24,113,93,63,199,131,93,63,112,150,93,63,18,169,93,63,175,187,93,63,70,206,93,63,215,224,93,63,97,243,93,63,230,5,94,63,101,24,94,63,222,42,94,63,81,61,94,63,190,79,94,63,36,98,94,63,133,116,94,63,224,134,94,63,53,153,94,63,132,171,94,63,205,189,94,63,16,208,94,63,77,226,94,63,132,244,94,63,181,6,95,63,224,24,95,63,5,43,95,63,36,61,95,63,61,79,95,63,80,97,95,63,93,115,95,63,101,133,95,63,102,151,95,63,97,169,95,63,86,187,95,63,69,205,95,63,46,223,95,63,18,241,95,63,239,2,96,63,198,20,96,63,151,38,96,63,98,56,96,63,40,74,96,63,231,91,96,63,160,109,96,63,84,127,96,63,1,145,96,63,168,162,96,63,73,180,96,63,229,197,96,63,122,215,96,63,10,233,96,63,147,250,96,63,22,12,97,63,148,29,97,63,11,47,97,63,125,64,97,63,232,81,97,63,77,99,97,63,173,116,97,63,6,134,97,63,90,151,97,63,167,168,97,63,239,185,97,63,48,203,97,63,108,220,97,63,162,237,97,63,209,254,97,63,251,15,98,63,30,33,98,63,60,50,98,63,84,67,98,63,101,84,98,63,113,101,98,63,119,118,98,63,119,135,98,63,112,152,98,63,100,169,98,63,82,186,98,63,58,203,98,63,28,220,98,63,247,236,98,63,205,253,98,63,157,14,99,63,103,31,99,63,43,48,99,63,233,64,99,63,161,81,99,63,83,98,99,63,255,114,99,63,165,131,99,63,69,148,99,63,224,164,99,63,116,181,99,63,2,198,99,63,138,214,99,63,13,231,99,63,137,247,99,63,255,7,100,63,112,24,100,63,218,40,100,63,62,57,100,63,157,73,100,63,246,89,100,63,72,106,100,63,149,122,100,63,219,138,100,63,28,155,100,63,87,171,100,63,140,187,100,63,186,203,100,63,227,219,100,63,6,236,100,63,35,252,100,63,58,12,101,63,75,28,101,63,86,44,101,63,91,60,101,63,91,76,101,63,84,92,101,63,71,108,101,63,53,124,101,63,28,140,101,63,254,155,101,63,217,171,101,63,175,187,101,63,126,203,101,63,72,219,101,63,12,235,101,63,202,250,101,63,130,10,102,63,52,26,102,63,224,41,102,63,134,57,102,63,38,73,102,63,193,88,102,63,85,104,102,63,227,119,102,63,108,135,102,63,238,150,102,63,107,166,102,63,226,181,102,63,83,197,102,63,190,212,102,63,35,228,102,63,130,243,102,63,219,2,103,63,46,18,103,63,124,33,103,63,195,48,103,63,5,64,103,63,64,79,103,63,118,94,103,63,166,109,103,63,208,124,103,63,244,139,103,63,18,155,103,63,42,170,103,63,61,185,103,63,73,200,103,63,80,215,103,63,80,230,103,63,75,245,103,63,64,4,104,63,47,19,104,63,24,34,104,63,251,48,104,63,217,63,104,63,176,78,104,63,130,93,104,63,78,108,104,63,20,123,104,63,212,137,104,63,142,152,104,63,66,167,104,63,240,181,104,63,153,196,104,63,60,211,104,63,217,225,104,63,112,240,104,63,1,255,104,63,140,13,105,63,17,28,105,63,145,42,105,63,11,57,105,63,127,71,105,63,237,85,105,63,85,100,105,63,183,114,105,63,20,129,105,63,106,143,105,63,187,157,105,63,6,172,105,63,75,186,105,63,139,200,105,63,196,214,105,63,248,228,105,63,38,243,105,63,78,1,106,63,112,15,106,63,141,29,106,63,163,43,106,63,180,57,106,63,191,71,106,63,196,85,106,63,196,99,106,63,189,113,106,63,177,127,106,63,159,141,106,63,135,155,106,63,106,169,106,63,70,183,106,63,29,197,106,63,238,210,106,63,186,224,106,63,127,238,106,63,63,252,106,63,249,9,107,63,173,23,107,63,91,37,107,63,4,51,107,63,167,64,107,63,68,78,107,63,219,91,107,63,109,105,107,63,249,118,107,63,127,132,107,63,255,145,107,63,122,159,107,63,238,172,107,63,94,186,107,63,199,199,107,63,42,213,107,63,136,226,107,63,224,239,107,63,51,253,107,63,128,10,108,63,198,23,108,63,8,37,108,63,67,50,108,63,121,63,108,63,169,76,108,63,211,89,108,63,248,102,108,63,23,116,108,63,48,129,108,63,68,142,108,63,82,155,108,63,90,168,108,63,92,181,108,63,89,194,108,63,80,207,108,63,65,220,108,63,45,233,108,63,19,246,108,63,243,2,109,63,206,15,109,63,163,28,109,63,114,41,109,63,60,54,109,63,0,67,109,63,190,79,109,63,119,92,109,63,42,105,109,63,215,117,109,63,127,130,109,63,33,143,109,63,189,155,109,63,84,168,109,63,229,180,109,63,113,193,109,63,247,205,109,63,119,218,109,63,242,230,109,63,103,243,109,63,214,255,109,63,64,12,110,63,164,24,110,63,3,37,110,63,91,49,110,63,175,61,110,63,253,73,110,63,69,86,110,63,135,98,110,63,196,110,110,63,252,122,110,63,45,135,110,63,90,147,110,63,128,159,110,63,161,171,110,63,189,183,110,63,211,195,110,63,227,207,110,63,238,219,110,63,243,231,110,63,243,243,110,63,237,255,110,63,226,11,111,63,209,23,111,63,186,35,111,63,158,47,111,63,125,59,111,63,85,71,111,63,41,83,111,63,247,94,111,63,191,106,111,63,130,118,111,63,63,130,111,63,247,141,111,63,169,153,111,63,86,165,111,63,253,176,111,63,159,188,111,63,59,200,111,63,210,211,111,63,99,223,111,63,239,234,111,63,117,246,111,63,246,1,112,63,114,13,112,63,231,24,112,63,88,36,112,63,195,47,112,63,40,59,112,63,137,70,112,63,227,81,112,63,56,93,112,63,136,104,112,63,210,115,112,63,23,127,112,63,87,138,112,63,145,149,112,63,197,160,112,63,244,171,112,63,30,183,112,63,66,194,112,63,97,205,112,63,123,216,112,63,143,227,112,63,157,238,112,63,167,249,112,63,171,4,113,63,169,15,113,63,162,26,113,63,150,37,113,63,132,48,113,63,109,59,113,63,81,70,113,63,47,81,113,63,8,92,113,63,219,102,113,63,170,113,113,63,114,124,113,63,54,135,113,63,244,145,113,63,173,156,113,63,96,167,113,63,14,178,113,63,183,188,113,63,91,199,113,63,249,209,113,63,146,220,113,63,37,231,113,63,179,241,113,63,60,252,113,63,192,6,114,63,62,17,114,63,183,27,114,63,43,38,114,63,154,48,114,63,3,59,114,63,103,69,114,63,197,79,114,63,31,90,114,63,115,100,114,63,194,110,114,63,11,121,114,63,79,131,114,63,143,141,114,63,200,151,114,63,253,161,114,63,44,172,114,63,87,182,114,63,123,192,114,63,155,202,114,63,182,212,114,63,203,222,114,63,219,232,114,63,230,242,114,63,235,252,114,63,236,6,115,63,231,16,115,63,221,26,115,63,206,36,115,63,186,46,115,63,160,56,115,63,130,66,115,63,94,76,115,63,53,86,115,63,7,96,115,63,212,105,115,63,155,115,115,63,94,125,115,63,27,135,115,63,211,144,115,63,134,154,115,63,52,164,115,63,221,173,115,63,128,183,115,63,31,193,115,63,184,202,115,63,77,212,115,63,220,221,115,63,102,231,115,63,235,240,115,63,107,250,115,63,230,3,116,63,92,13,116,63,204,22,116,63,56,32,116,63,159,41,116,63,0,51,116,63,93,60,116,63,180,69,116,63,6,79,116,63,84,88,116,63,156,97,116,63,223,106,116,63,29,116,116,63,87,125,116,63,139,134,116,63,186,143,116,63,228,152,116,63,9,162,116,63,41,171,116,63,68,180,116,63,91,189,116,63,108,198,116,63,120,207,116,63,127,216,116,63,129,225,116,63,127,234,116,63,119,243,116,63,106,252,116,63,89,5,117,63,66,14,117,63,38,23,117,63,6,32,117,63,225,40,117,63,182,49,117,63,135,58,117,63,83,67,117,63,26,76,117,63,220,84,117,63,153,93,117,63,81,102,117,63,4,111,117,63,179,119,117,63,92,128,117,63,1,137,117,63,160,145,117,63,59,154,117,63,209,162,117,63,98,171,117,63,239,179,117,63,118,188,117,63,249,196,117,63,118,205,117,63,239,213,117,63,99,222,117,63,210,230,117,63,61,239,117,63,162,247,117,63,3,0,118,63,95,8,118,63,182,16,118,63,8,25,118,63,86,33,118,63,159,41,118,63,227,49,118,63,34,58,118,63,92,66,118,63,146,74,118,63,195,82,118,63,239,90,118,63,22,99,118,63,57,107,118,63,86,115,118,63,112,123,118,63,132,131,118,63,148,139,118,63,158,147,118,63,165,155,118,63,166,163,118,63,163,171,118,63,155,179,118,63,142,187,118,63,125,195,118,63,103,203,118,63,76,211,118,63,45,219,118,63,9,227,118,63,224,234,118,63,178,242,118,63,128,250,118,63,74,2,119,63,14,10,119,63,206,17,119,63,137,25,119,63,64,33,119,63,242,40,119,63,160,48,119,63,72,56,119,63,237,63,119,63,140,71,119,63,39,79,119,63,190,86,119,63,79,94,119,63,220,101,119,63,101,109,119,63,233,116,119,63,105,124,119,63,228,131,119,63,90,139,119,63,204,146,119,63,57,154,119,63,162,161,119,63,6,169,119,63,101,176,119,63,192,183,119,63,23,191,119,63,105,198,119,63,182,205,119,63,255,212,119,63,68,220,119,63,132,227,119,63,191,234,119,63,246,241,119,63,41,249,119,63,87,0,120,63,129,7,120,63,166,14,120,63,198,21,120,63,227,28,120,63,250,35,120,63,14,43,120,63,28,50,120,63,39,57,120,63,45,64,120,63,46,71,120,63,44,78,120,63,36,85,120,63,25,92,120,63,9,99,120,63,244,105,120,63,219,112,120,63,190,119,120,63,156,126,120,63,118,133,120,63,76,140,120,63,29,147,120,63,234,153,120,63,179,160,120,63,119,167,120,63,55,174,120,63,242,180,120,63,169,187,120,63,92,194,120,63,11,201,120,63,181,207,120,63,91,214,120,63,252,220,120,63,154,227,120,63,51,234,120,63,199,240,120,63,88,247,120,63,228,253,120,63,108,4,121,63,240,10,121,63,111,17,121,63,234,23,121,63,97,30,121,63,211,36,121,63,66,43,121,63,172,49,121,63,18,56,121,63,116,62,121,63,209,68,121,63,42,75,121,63,127,81,121,63,208,87,121,63,29,94,121,63,101,100,121,63,170,106,121,63,234,112,121,63,38,119,121,63,93,125,121,63,145,131,121,63,193,137,121,63,236,143,121,63,19,150,121,63,54,156,121,63,85,162,121,63,112,168,121,63,134,174,121,63,153,180,121,63,167,186,121,63,178,192,121,63,184,198,121,63,186,204,121,63,184,210,121,63,178,216,121,63,168,222,121,63,154,228,121,63,135,234,121,63,113,240,121,63,87,246,121,63,56,252,121,63,22,2,122,63,239,7,122,63,197,13,122,63,150,19,122,63,100,25,122,63,45,31,122,63,243,36,122,63,180,42,122,63,113,48,122,63,43,54,122,63,224,59,122,63,146,65,122,63,63,71,122,63,233,76,122,63,142,82,122,63,48,88,122,63,206,93,122,63,103,99,122,63,253,104,122,63,143,110,122,63,29,116,122,63,167,121,122,63,45,127,122,63,175,132,122,63,45,138,122,63,168,143,122,63,30,149,122,63,145,154,122,63,255,159,122,63,106,165,122,63,209,170,122,63,52,176,122,63,147,181,122,63,239,186,122,63,70,192,122,63,154,197,122,63,234,202,122,63,54,208,122,63,126,213,122,63,194,218,122,63,3,224,122,63,64,229,122,63,121,234,122,63,174,239,122,63,223,244,122,63,13,250,122,63,55,255,122,63,93,4,123,63,127,9,123,63,157,14,123,63,184,19,123,63,207,24,123,63,227,29,123,63,242,34,123,63,254,39,123,63,6,45,123,63,10,50,123,63,11,55,123,63,8,60,123,63,1,65,123,63,247,69,123,63,233,74,123,63,215,79,123,63,193,84,123,63,168,89,123,63,139,94,123,63,107,99,123,63,71,104,123,63,31,109,123,63,243,113,123,63,196,118,123,63,146,123,123,63,91,128,123,63,33,133,123,63,228,137,123,63,163,142,123,63,94,147,123,63,22,152,123,63,202,156,123,63,122,161,123,63,39,166,123,63,208,170,123,63,118,175,123,63,24,180,123,63,183,184,123,63,82,189,123,63,233,193,123,63,125,198,123,63,14,203,123,63,155,207,123,63,36,212,123,63,170,216,123,63,45,221,123,63,172,225,123,63,39,230,123,63,159,234,123,63,19,239,123,63,132,243,123,63,242,247,123,63,92,252,123,63,195,0,124,63,38,5,124,63,133,9,124,63,226,13,124,63,58,18,124,63,144,22,124,63,226,26,124,63,48,31,124,63,123,35,124,63,195,39,124,63,7,44,124,63,72,48,124,63,134,52,124,63,192,56,124,63,247,60,124,63,42,65,124,63,90,69,124,63,135,73,124,63,176,77,124,63,214,81,124,63,249,85,124,63,24,90,124,63,52,94,124,63,77,98,124,63,98,102,124,63,116,106,124,63,131,110,124,63,142,114,124,63,150,118,124,63,155,122,124,63,157,126,124,63,155,130,124,63,150,134,124,63,142,138,124,63,130,142,124,63,116,146,124,63,98,150,124,63,77,154,124,63,52,158,124,63,24,162,124,63,249,165,124,63,215,169,124,63,178,173,124,63,137,177,124,63,94,181,124,63,47,185,124,63,253,188,124,63,199,192,124,63,143,196,124,63,83,200,124,63,20,204,124,63,211,207,124,63,141,211,124,63,69,215,124,63,250,218,124,63,171,222,124,63,90,226,124,63,5,230,124,63,173,233,124,63,82,237,124,63,244,240,124,63,147,244,124,63,46,248,124,63,199,251,124,63,93,255,124,63,239,2,125,63,127,6,125,63,11,10,125,63,148,13,125,63,27,17,125,63,158,20,125,63,30,24,125,63,155,27,125,63,21,31,125,63,140,34,125,63,0,38,125,63,114,41,125,63,224,44,125,63,75,48,125,63,179,51,125,63,24,55,125,63,122,58,125,63,217,61,125,63,54,65,125,63,143,68,125,63,229,71,125,63,56,75,125,63,137,78,125,63,214,81,125,63,33,85,125,63,104,88,125,63,173,91,125,63,239,94,125,63,46,98,125,63,106,101,125,63,163,104,125,63,217,107,125,63,12,111,125,63,61,114,125,63,106,117,125,63,149,120,125,63,189,123,125,63,226,126,125,63,4,130,125,63,36,133,125,63,64,136,125,63,90,139,125,63,112,142,125,63,133,145,125,63,150,148,125,63,164,151,125,63,176,154,125,63,185,157,125,63,191,160,125,63,194,163,125,63,194,166,125,63,192,169,125,63,187,172,125,63,179,175,125,63,168,178,125,63,155,181,125,63,139,184,125,63,120,187,125,63,99,190,125,63,74,193,125,63,48,196,125,63,18,199,125,63,241,201,125,63,206,204,125,63,169,207,125,63,128,210,125,63,85,213,125,63,39,216,125,63,247,218,125,63,196,221,125,63,142,224,125,63,85,227,125,63,26,230,125,63,220,232,125,63,156,235,125,63,89,238,125,63,19,241,125,63,203,243,125,63,128,246,125,63,51,249,125,63,227,251,125,63,144,254,125,63,59,1,126,63,227,3,126,63,137,6,126,63,44,9,126,63,204,11,126,63,106,14,126,63,6,17,126,63,158,19,126,63,53,22,126,63,200,24,126,63,90,27,126,63,232,29,126,63,116,32,126,63,254,34,126,63,133,37,126,63,10,40,126,63,140,42,126,63,12,45,126,63,137,47,126,63,4,50,126,63,124,52,126,63,242,54,126,63,101,57,126,63,214,59,126,63,68,62,126,63,176,64,126,63,26,67,126,63,129,69,126,63,230,71,126,63,72,74,126,63,168,76,126,63,5,79,126,63,96,81,126,63,185,83,126,63,15,86,126,63,99,88,126,63,181,90,126,63,4,93,126,63,81,95,126,63,155,97,126,63],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE+20480);allocate([227,99,126,63,41,102,126,63,108,104,126,63,173,106,126,63,236,108,126,63,40,111,126,63,98,113,126,63,154,115,126,63,208,117,126,63,3,120,126,63,51,122,126,63,98,124,126,63,142,126,126,63,184,128,126,63,224,130,126,63,5,133,126,63,40,135,126,63,73,137,126,63,104,139,126,63,132,141,126,63,159,143,126,63,183,145,126,63,204,147,126,63,224,149,126,63,241,151,126,63,0,154,126,63,13,156,126,63,24,158,126,63,32,160,126,63,38,162,126,63,42,164,126,63,44,166,126,63,44,168,126,63,41,170,126,63,37,172,126,63,30,174,126,63,21,176,126,63,10,178,126,63,253,179,126,63,238,181,126,63,220,183,126,63,201,185,126,63,179,187,126,63,155,189,126,63,129,191,126,63,101,193,126,63,71,195,126,63,39,197,126,63,5,199,126,63,224,200,126,63,186,202,126,63,145,204,126,63,103,206,126,63,58,208,126,63,12,210,126,63,219,211,126,63,168,213,126,63,115,215,126,63,61,217,126,63,4,219,126,63,201,220,126,63,140,222,126,63,77,224,126,63,12,226,126,63,202,227,126,63,133,229,126,63,62,231,126,63,245,232,126,63,170,234,126,63,94,236,126,63,15,238,126,63,190,239,126,63,108,241,126,63,23,243,126,63,193,244,126,63,104,246,126,63,14,248,126,63,178,249,126,63,84,251,126,63,243,252,126,63,145,254,126,63,46,0,127,63,200,1,127,63,96,3,127,63,247,4,127,63,139,6,127,63,30,8,127,63,175,9,127,63,62,11,127,63,203,12,127,63,86,14,127,63,223,15,127,63,103,17,127,63,237,18,127,63,112,20,127,63,242,21,127,63,115,23,127,63,241,24,127,63,110,26,127,63,233,27,127,63,98,29,127,63,217,30,127,63,78,32,127,63,194,33,127,63,52,35,127,63,164,36,127,63,18,38,127,63,127,39,127,63,234,40,127,63,83,42,127,63,186,43,127,63,32,45,127,63,131,46,127,63,230,47,127,63,70,49,127,63,165,50,127,63,2,52,127,63,93,53,127,63,182,54,127,63,14,56,127,63,100,57,127,63,185,58,127,63,12,60,127,63,93,61,127,63,172,62,127,63,250,63,127,63,70,65,127,63,145,66,127,63,217,67,127,63,33,69,127,63,102,70,127,63,170,71,127,63,236,72,127,63,45,74,127,63,108,75,127,63,169,76,127,63,229,77,127,63,31,79,127,63,88,80,127,63,143,81,127,63,196,82,127,63,248,83,127,63,42,85,127,63,91,86,127,63,138,87,127,63,184,88,127,63,228,89,127,63,14,91,127,63,55,92,127,63,94,93,127,63,132,94,127,63,169,95,127,63,203,96,127,63,237,97,127,63,12,99,127,63,42,100,127,63,71,101,127,63,98,102,127,63,124,103,127,63,148,104,127,63,171,105,127,63,192,106,127,63,212,107,127,63,230,108,127,63,247,109,127,63,6,111,127,63,20,112,127,63,33,113,127,63,44,114,127,63,53,115,127,63,61,116,127,63,68,117,127,63,73,118,127,63,77,119,127,63,79,120,127,63,80,121,127,63,80,122,127,63,78,123,127,63,75,124,127,63,70,125,127,63,64,126,127,63,57,127,127,63,48,128,127,63,38,129,127,63,27,130,127,63,14,131,127,63,0,132,127,63,240,132,127,63,223,133,127,63,205,134,127,63,185,135,127,63,164,136,127,63,142,137,127,63,118,138,127,63,93,139,127,63,67,140,127,63,40,141,127,63,11,142,127,63,237,142,127,63,205,143,127,63,173,144,127,63,139,145,127,63,103,146,127,63,67,147,127,63,29,148,127,63,246,148,127,63,205,149,127,63,164,150,127,63,121,151,127,63,77,152,127,63,31,153,127,63,241,153,127,63,193,154,127,63,144,155,127,63,93,156,127,63,42,157,127,63,245,157,127,63,191,158,127,63,136,159,127,63,79,160,127,63,22,161,127,63,219,161,127,63,159,162,127,63,98,163,127,63,36,164,127,63,228,164,127,63,163,165,127,63,98,166,127,63,31,167,127,63,219,167,127,63,149,168,127,63,79,169,127,63,7,170,127,63,190,170,127,63,117,171,127,63,42,172,127,63,221,172,127,63,144,173,127,63,66,174,127,63,242,174,127,63,162,175,127,63,80,176,127,63,253,176,127,63,169,177,127,63,85,178,127,63,254,178,127,63,167,179,127,63,79,180,127,63,246,180,127,63,156,181,127,63,64,182,127,63,228,182,127,63,134,183,127,63,40,184,127,63,200,184,127,63,103,185,127,63,6,186,127,63,163,186,127,63,63,187,127,63,219,187,127,63,117,188,127,63,14,189,127,63,166,189,127,63,61,190,127,63,212,190,127,63,105,191,127,63,253,191,127,63,144,192,127,63,34,193,127,63,180,193,127,63,68,194,127,63,211,194,127,63,98,195,127,63,239,195,127,63,123,196,127,63,7,197,127,63,145,197,127,63,27,198,127,63,163,198,127,63,43,199,127,63,178,199,127,63,56,200,127,63,189,200,127,63,65,201,127,63,196,201,127,63,70,202,127,63,199,202,127,63,71,203,127,63,199,203,127,63,69,204,127,63,195,204,127,63,64,205,127,63,187,205,127,63,54,206,127,63,177,206,127,63,42,207,127,63,162,207,127,63,26,208,127,63,144,208,127,63,6,209,127,63,123,209,127,63,239,209,127,63,98,210,127,63,213,210,127,63,70,211,127,63,183,211,127,63,39,212,127,63,150,212,127,63,4,213,127,63,114,213,127,63,222,213,127,63,74,214,127,63,181,214,127,63,32,215,127,63,137,215,127,63,242,215,127,63,89,216,127,63,192,216,127,63,39,217,127,63,140,217,127,63,241,217,127,63,85,218,127,63,184,218,127,63,27,219,127,63,124,219,127,63,221,219,127,63,61,220,127,63,157,220,127,63,251,220,127,63,89,221,127,63,183,221,127,63,19,222,127,63,111,222,127,63,202,222,127,63,36,223,127,63,126,223,127,63,215,223,127,63,47,224,127,63,134,224,127,63,221,224,127,63,51,225,127,63,137,225,127,63,221,225,127,63,49,226,127,63,133,226,127,63,215,226,127,63,41,227,127,63,122,227,127,63,203,227,127,63,27,228,127,63,106,228,127,63,185,228,127,63,7,229,127,63,84,229,127,63,161,229,127,63,237,229,127,63,56,230,127,63,131,230,127,63,205,230,127,63,23,231,127,63,96,231,127,63,168,231,127,63,239,231,127,63,54,232,127,63,125,232,127,63,195,232,127,63,8,233,127,63,76,233,127,63,144,233,127,63,212,233,127,63,23,234,127,63,89,234,127,63,154,234,127,63,219,234,127,63,28,235,127,63,92,235,127,63,155,235,127,63,218,235,127,63,24,236,127,63,86,236,127,63,147,236,127,63,207,236,127,63,11,237,127,63,71,237,127,63,130,237,127,63,188,237,127,63,246,237,127,63,47,238,127,63,104,238,127,63,160,238,127,63,216,238,127,63,15,239,127,63,69,239,127,63,123,239,127,63,177,239,127,63,230,239,127,63,27,240,127,63,79,240,127,63,130,240,127,63,182,240,127,63,232,240,127,63,26,241,127,63,76,241,127,63,125,241,127,63,174,241,127,63,222,241,127,63,14,242,127,63,61,242,127,63,108,242,127,63,154,242,127,63,200,242,127,63,245,242,127,63,34,243,127,63,79,243,127,63,123,243,127,63,166,243,127,63,209,243,127,63,252,243,127,63,38,244,127,63,80,244,127,63,121,244,127,63,162,244,127,63,203,244,127,63,243,244,127,63,27,245,127,63,66,245,127,63,105,245,127,63,143,245,127,63,181,245,127,63,219,245,127,63,0,246,127,63,37,246,127,63,73,246,127,63,109,246,127,63,145,246,127,63,180,246,127,63,215,246,127,63,250,246,127,63,28,247,127,63,62,247,127,63,95,247,127,63,128,247,127,63,160,247,127,63,193,247,127,63,225,247,127,63,0,248,127,63,31,248,127,63,62,248,127,63,93,248,127,63,123,248,127,63,152,248,127,63,182,248,127,63,211,248,127,63,240,248,127,63,12,249,127,63,40,249,127,63,68,249,127,63,95,249,127,63,122,249,127,63,149,249,127,63,175,249,127,63,202,249,127,63,227,249,127,63,253,249,127,63,22,250,127,63,47,250,127,63,71,250,127,63,96,250,127,63,120,250,127,63,143,250,127,63,166,250,127,63,190,250,127,63,212,250,127,63,235,250,127,63,1,251,127,63,23,251,127,63,44,251,127,63,66,251,127,63,87,251,127,63,108,251,127,63,128,251,127,63,148,251,127,63,168,251,127,63,188,251,127,63,208,251,127,63,227,251,127,63,246,251,127,63,8,252,127,63,27,252,127,63,45,252,127,63,63,252,127,63,81,252,127,63,98,252,127,63,115,252,127,63,132,252,127,63,149,252,127,63,165,252,127,63,182,252,127,63,198,252,127,63,213,252,127,63,229,252,127,63,244,252,127,63,3,253,127,63,18,253,127,63,33,253,127,63,47,253,127,63,62,253,127,63,76,253,127,63,89,253,127,63,103,253,127,63,116,253,127,63,130,253,127,63,143,253,127,63,155,253,127,63,168,253,127,63,181,253,127,63,193,253,127,63,205,253,127,63,217,253,127,63,228,253,127,63,240,253,127,63,251,253,127,63,6,254,127,63,17,254,127,63,28,254,127,63,38,254,127,63,49,254,127,63,59,254,127,63,69,254,127,63,79,254,127,63,89,254,127,63,98,254,127,63,108,254,127,63,117,254,127,63,126,254,127,63,135,254,127,63,144,254,127,63,152,254,127,63,161,254,127,63,169,254,127,63,177,254,127,63,185,254,127,63,193,254,127,63,201,254,127,63,208,254,127,63,216,254,127,63,223,254,127,63,230,254,127,63,237,254,127,63,244,254,127,63,251,254,127,63,2,255,127,63,8,255,127,63,14,255,127,63,21,255,127,63,27,255,127,63,33,255,127,63,39,255,127,63,45,255,127,63,50,255,127,63,56,255,127,63,61,255,127,63,67,255,127,63,72,255,127,63,77,255,127,63,82,255,127,63,87,255,127,63,92,255,127,63,96,255,127,63,101,255,127,63,105,255,127,63,110,255,127,63,114,255,127,63,118,255,127,63,122,255,127,63,126,255,127,63,130,255,127,63,134,255,127,63,138,255,127,63,142,255,127,63,145,255,127,63,149,255,127,63,152,255,127,63,155,255,127,63,159,255,127,63,162,255,127,63,165,255,127,63,168,255,127,63,171,255,127,63,174,255,127,63,176,255,127,63,179,255,127,63,182,255,127,63,184,255,127,63,187,255,127,63,189,255,127,63,192,255,127,63,194,255,127,63,196,255,127,63,198,255,127,63,201,255,127,63,203,255,127,63,205,255,127,63,207,255,127,63,209,255,127,63,210,255,127,63,212,255,127,63,214,255,127,63,216,255,127,63,217,255,127,63,219,255,127,63,220,255,127,63,222,255,127,63,223,255,127,63,225,255,127,63,226,255,127,63,227,255,127,63,229,255,127,63,230,255,127,63,231,255,127,63,232,255,127,63,233,255,127,63,234,255,127,63,235,255,127,63,236,255,127,63,237,255,127,63,238,255,127,63,239,255,127,63,240,255,127,63,241,255,127,63,241,255,127,63,242,255,127,63,243,255,127,63,244,255,127,63,244,255,127,63,245,255,127,63,246,255,127,63,246,255,127,63,247,255,127,63,247,255,127,63,248,255,127,63,248,255,127,63,249,255,127,63,249,255,127,63,250,255,127,63,250,255,127,63,250,255,127,63,251,255,127,63,251,255,127,63,251,255,127,63,252,255,127,63,252,255,127,63,252,255,127,63,253,255,127,63,253,255,127,63,253,255,127,63,253,255,127,63,254,255,127,63,254,255,127,63,254,255,127,63,254,255,127,63,254,255,127,63,254,255,127,63,255,255,127,63,255,255,127,63,255,255,127,63,255,255,127,63,255,255,127,63,255,255,127,63,255,255,127,63,255,255,127,63,255,255,127,63,255,255,127,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,128,63,0,0,112,194,0,0,112,194,0,0,112,194,0,0,112,194,0,0,112,194,0,0,112,194,0,0,112,194,0,0,112,194,0,0,112,194,0,0,112,194,0,0,112,194,0,0,112,194,0,0,120,194,0,0,120,194,0,0,130,194,0,0,146,194,0,0,138,194,0,0,136,194,0,0,136,194,0,0,134,194,0,0,140,194,0,0,140,194,0,0,144,194,0,0,148,194,0,0,150,194,0,0,158,194,0,0,158,194,0,0,160,194,0,0,166,194,0,0,176,194,0,0,186,194,0,0,200,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,64,194,0,0,64,194,0,0,64,194,0,0,64,194,0,0,64,194,0,0,64,194,0,0,64,194,0,0,64,194,0,0,64,194,0,0,64,194,0,0,64,194,0,0,64,194,0,0,64,194,0,0,84,194,0,0,116,194,0,0,132,194,0,0,132,194,0,0,136,194,0,0,134,194,0,0,140,194,0,0,152,194,0,0,152,194,0,0,144,194,0,0,146,194,0,0,150,194,0,0,152,194,0,0,156,194,0,0,158,194,0,0,166,194,0,0,176,194,0,0,186,194,0,0,200,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,20,194,0,0,20,194,0,0,20,194,0,0,20,194,0,0,20,194,0,0,20,194,0,0,20,194,0,0,20,194,0,0,24,194,0,0,32,194,0,0,40,194,0,0,56,194,0,0,64,194,0,0,84,194,0,0,92,194,0,0,120,194,0,0,130,194,0,0,104,194,0,0,96,194,0,0,96,194,0,0,116,194,0,0,112,194,0,0,130,194,0,0,134,194,0,0,138,194,0,0,142,194,0,0,154,194,0,0,154,194,0,0,156,194,0,0,160,194,0,0,164,194,0,0,168,194,0,0,176,194,0,0,186,194,0,0,196,194,0,0,212,194,0,0,224,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,200,193,0,0,200,193,0,0,200,193,0,0,200,193,0,0,200,193,0,0,200,193,0,0,200,193,0,0,200,193,0,0,200,193,0,0,208,193,0,0,216,193,0,0,232,193,0,0,0,194,0,0,24,194,0,0,64,194,0,0,80,194,0,0,80,194,0,0,72,194,0,0,64,194,0,0,64,194,0,0,76,194,0,0,80,194,0,0,88,194,0,0,112,194,0,0,134,194,0,0,134,194,0,0,132,194,0,0,136,194,0,0,138,194,0,0,146,194,0,0,146,194,0,0,152,194,0,0,160,194,0,0,162,194,0,0,162,194,0,0,170,194,0,0,170,194,0,0,172,194,0,0,176,194,0,0,186,194,0,0,200,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,128,193,0,0,128,193,0,0,128,193,0,0,128,193,0,0,128,193,0,0,128,193,0,0,128,193,0,0,128,193,0,0,136,193,0,0,152,193,0,0,160,193,0,0,176,193,0,0,208,193,0,0,224,193,0,0,248,193,0,0,32,194,0,0,60,194,0,0,28,194,0,0,28,194,0,0,32,194,0,0,40,194,0,0,44,194,0,0,60,194,0,0,76,194,0,0,100,194,0,0,80,194,0,0,92,194,0,0,92,194,0,0,112,194,0,0,104,194,0,0,120,194,0,0,124,194,0,0,140,194,0,0,134,194,0,0,138,194,0,0,144,194,0,0,146,194,0,0,154,194,0,0,160,194,0,0,164,194,0,0,166,194,0,0,174,194,0,0,180,194,0,0,188,194,0,0,196,194,0,0,208,194,0,0,230,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,0,193,0,0,0,193,0,0,0,193,0,0,0,193,0,0,0,193,0,0,0,193,0,0,0,193,0,0,0,193,0,0,0,193,0,0,0,193,0,0,32,193,0,0,48,193,0,0,112,193,0,0,152,193,0,0,200,193,0,0,240,193,0,0,8,194,0,0,248,193,0,0,240,193,0,0,248,193,0,0,232,193,0,0,0,194,0,0,12,194,0,0,40,194,0,0,64,194,0,0,40,194,0,0,48,194,0,0,56,194,0,0,72,194,0,0,72,194,0,0,76,194,0,0,80,194,0,0,108,194,0,0,88,194,0,0,92,194,0,0,92,194,0,0,104,194,0,0,120,194,0,0,124,194,0,0,132,194,0,0,144,194,0,0,146,194,0,0,152,194,0,0,150,194,0,0,156,194,0,0,160,194,0,0,160,194,0,0,162,194,0,0,168,194,0,0,176,194,0,0,180,194,0,0,188,194,0,0,196,194,0,0,202,194,0,0,212,194,0,0,220,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,134,194,0,0,134,194,0,0,134,194,0,0,152,194,0,0,144,194,0,0,142,194,0,0,148,194,0,0,152,194,0,0,152,194,0,0,150,194,0,0,156,194,0,0,158,194,0,0,158,194,0,0,162,194,0,0,166,194,0,0,172,194,0,0,178,194,0,0,186,194,0,0,194,194,0,0,200,194,0,0,210,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,60,194,0,0,60,194,0,0,60,194,0,0,60,194,0,0,60,194,0,0,60,194,0,0,60,194,0,0,60,194,0,0,60,194,0,0,60,194,0,0,60,194,0,0,64,194,0,0,76,194,0,0,92,194,0,0,108,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,134,194,0,0,132,194,0,0,136,194,0,0,138,194,0,0,140,194,0,0,148,194,0,0,158,194,0,0,154,194,0,0,154,194,0,0,156,194,0,0,160,194,0,0,162,194,0,0,164,194,0,0,168,194,0,0,172,194,0,0,176,194,0,0,182,194,0,0,190,194,0,0,200,194,0,0,216,194,0,0,232,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,16,194,0,0,16,194,0,0,16,194,0,0,16,194,0,0,16,194,0,0,16,194,0,0,16,194,0,0,16,194,0,0,16,194,0,0,20,194,0,0,20,194,0,0,36,194,0,0,48,194,0,0,64,194,0,0,76,194,0,0,104,194,0,0,120,194,0,0,112,194,0,0,100,194,0,0,108,194,0,0,108,194,0,0,112,194,0,0,124,194,0,0,130,194,0,0,144,194,0,0,142,194,0,0,140,194,0,0,144,194,0,0,148,194,0,0,154,194,0,0,152,194,0,0,156,194,0,0,162,194,0,0,162,194,0,0,160,194,0,0,166,194,0,0,172,194,0,0,182,194,0,0,192,194,0,0,200,194,0,0,210,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,224,193,0,0,224,193,0,0,224,193,0,0,224,193,0,0,224,193,0,0,224,193,0,0,224,193,0,0,224,193,0,0,224,193,0,0,240,193,0,0,0,194,0,0,0,194,0,0,4,194,0,0,12,194,0,0,36,194,0,0,68,194,0,0,72,194,0,0,68,194,0,0,60,194,0,0,64,194,0,0,64,194,0,0,80,194,0,0,76,194,0,0,100,194,0,0,130,194,0,0,116,194,0,0,108,194,0,0,116,194,0,0,128,194,0,0,138,194,0,0,140,194,0,0,148,194,0,0,154,194,0,0,154,194,0,0,156,194,0,0,162,194,0,0,168,194,0,0,170,194,0,0,174,194,0,0,180,194,0,0,184,194,0,0,192,194,0,0,200,194,0,0,214,194,0,0,224,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,152,193,0,0,152,193,0,0,152,193,0,0,152,193,0,0,152,193,0,0,152,193,0,0,152,193,0,0,152,193,0,0,160,193,0,0,168,193,0,0,184,193,0,0,216,193,0,0,240,193,0,0,12,194,0,0,16,194,0,0,36,194,0,0,56,194,0,0,48,194,0,0,40,194,0,0,32,194,0,0,36,194,0,0,36,194,0,0,44,194,0,0,64,194,0,0,92,194,0,0,84,194,0,0,80,194,0,0,84,194,0,0,96,194,0,0,108,194,0,0,104,194,0,0,112,194,0,0,134,194,0,0,132,194,0,0,138,194,0,0,142,194,0,0,144,194,0,0,150,194,0,0,158,194,0,0,162,194,0,0,168,194,0,0,174,194,0,0,180,194,0,0,186,194,0,0,194,194,0,0,202,194,0,0,214,194,0,0,228,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,16,193,0,0,16,193,0,0,16,193,0,0,16,193,0,0,16,193,0,0,16,193,0,0,16,193,0,0,16,193,0,0,48,193,0,0,64,193,0,0,64,193,0,0,112,193,0,0,128,193,0,0,160,193,0,0,184,193,0,0,240,193,0,0,20,194,0,0,8,194,0,0,4,194,0,0,8,194,0,0,248,193,0,0,0,194,0,0,0,194,0,0,24,194,0,0,60,194,0,0,48,194,0,0,36,194,0,0,32,194,0,0,60,194,0,0,68,194,0,0,56,194,0,0,56,194,0,0,104,194,0,0,72,194,0,0,72,194,0,0,88,194,0,0,104,194,0,0,120,194,0,0,128,194,0,0,134,194,0,0,134,194,0,0,140,194,0,0,144,194,0,0,152,194,0,0,158,194,0,0,166,194,0,0,174,194,0,0,182,194,0,0,192,194,0,0,200,194,0,0,208,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,120,194,0,0,120,194,0,0,120,194,0,0,120,194,0,0,120,194,0,0,120,194,0,0,120,194,0,0,120,194,0,0,120,194,0,0,120,194,0,0,124,194,0,0,128,194,0,0,132,194,0,0,134,194,0,0,132,194,0,0,136,194,0,0,150,194,0,0,144,194,0,0,152,194,0,0,150,194,0,0,152,194,0,0,156,194,0,0,158,194,0,0,164,194,0,0,168,194,0,0,170,194,0,0,180,194,0,0,188,194,0,0,202,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,108,194,0,0,108,194,0,0,108,194,0,0,108,194,0,0,108,194,0,0,108,194,0,0,108,194,0,0,108,194,0,0,108,194,0,0,108,194,0,0,108,194,0,0,112,194,0,0,112,194,0,0,116,194,0,0,124,194,0,0,132,194,0,0,142,194,0,0,136,194,0,0,140,194,0,0,140,194,0,0,142,194,0,0,144,194,0,0,144,194,0,0,150,194,0,0,162,194,0,0,156,194,0,0,158,194,0,0,164,194,0,0,166,194,0,0,172,194,0,0,180,194,0,0,194,194,0,0,206,194,0,0,226,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,84,194,0,0,84,194,0,0,84,194,0,0,84,194,0,0,84,194,0,0,84,194,0,0,84,194,0,0,84,194,0,0,84,194,0,0,88,194,0,0,92,194,0,0,100,194,0,0,96,194,0,0,100,194,0,0,92,194,0,0,116,194,0,0,130,194,0,0,112,194,0,0,112,194,0,0,120,194,0,0,124,194,0,0,124,194,0,0,132,194,0,0,136,194,0,0,148,194,0,0,146,194,0,0,150,194,0,0,150,194,0,0,156,194,0,0,160,194,0,0,160,194,0,0,164,194,0,0,170,194,0,0,180,194,0,0,192,194,0,0,202,194,0,0,216,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,56,194,0,0,56,194,0,0,56,194,0,0,56,194,0,0,56,194,0,0,56,194,0,0,56,194,0,0,56,194,0,0,56,194,0,0,56,194,0,0,60,194,0,0,60,194,0,0,60,194,0,0,60,194,0,0,64,194,0,0,76,194,0,0,100,194,0,0,76,194,0,0,68,194,0,0,72,194,0,0,76,194,0,0,84,194,0,0,88,194,0,0,108,194,0,0,132,194,0,0,112,194,0,0,120,194,0,0,134,194,0,0,134,194,0,0,140,194,0,0,144,194,0,0,150,194,0,0,152,194,0,0,156,194,0,0,162,194,0,0,170,194,0,0,176,194,0,0,188,194,0,0,194,194,0,0,208,194,0,0,224,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,16,194,0,0,16,194,0,0,16,194,0,0,16,194,0,0,16,194,0,0,16,194,0,0,16,194,0,0,16,194,0,0,28,194,0,0,36,194,0,0,40,194,0,0,40,194,0,0,28,194,0,0,24,194,0,0,36,194,0,0,44,194,0,0,80,194,0,0,48,194,0,0,32,194,0,0,28,194,0,0,20,194,0,0,20,194,0,0,32,194,0,0,60,194,0,0,88,194,0,0,72,194,0,0,64,194,0,0,72,194,0,0,92,194,0,0,116,194,0,0,108,194,0,0,120,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,138,194,0,0,138,194,0,0,146,194,0,0,148,194,0,0,148,194,0,0,150,194,0,0,154,194,0,0,158,194,0,0,164,194,0,0,174,194,0,0,182,194,0,0,190,194,0,0,200,194,0,0,216,194,0,0,230,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,224,193,0,0,208,193,0,0,192,193,0,0,176,193,0,0,160,193,0,0,160,193,0,0,184,193,0,0,232,193,0,0,240,193,0,0,248,193,0,0,224,193,0,0,216,193,0,0,224,193,0,0,224,193,0,0,224,193,0,0,12,194,0,0,32,194,0,0,4,194,0,0,0,194,0,0,232,193,0,0,240,193,0,0,240,193,0,0,240,193,0,0,20,194,0,0,52,194,0,0,36,194,0,0,20,194,0,0,24,194,0,0,52,194,0,0,60,194,0,0,60,194,0,0,64,194,0,0,84,194,0,0,68,194,0,0,64,194,0,0,72,194,0,0,68,194,0,0,68,194,0,0,76,194,0,0,80,194,0,0,104,194,0,0,96,194,0,0,100,194,0,0,96,194,0,0,112,194,0,0,116,194,0,0,120,194,0,0,140,194,0,0,144,194,0,0,148,194,0,0,156,194,0,0,166,194,0,0,176,194,0,0,186,194,0,0,200,194,0,0,212,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,210,194,0,0,200,194,0,0,190,194,0,0,182,194,0,0,174,194,0,0,166,194,0,0,160,194,0,0,156,194,0,0,152,194,0,0,156,194,0,0,156,194,0,0,162,194,0,0,166,194,0,0,170,194,0,0,172,194,0,0,170,194,0,0,172,194,0,0,174,194,0,0,180,194,0,0,194,194,0,0,214,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,210,194,0,0,200,194,0,0,190,194,0,0,180,194,0,0,170,194,0,0,162,194,0,0,154,194,0,0,146,194,0,0,140,194,0,0,134,194,0,0,134,194,0,0,136,194,0,0,150,194,0,0,146,194,0,0,140,194,0,0,138,194,0,0,140,194,0,0,144,194,0,0,150,194,0,0,158,194,0,0,168,194,0,0,166,194,0,0,168,194,0,0,172,194,0,0,176,194,0,0,178,194,0,0,178,194,0,0,186,194,0,0,196,194,0,0,210,194,0,0,224,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,210,194,0,0,200,194,0,0,190,194,0,0,180,194,0,0,170,194,0,0,160,194,0,0,152,194,0,0,142,194,0,0,136,194,0,0,136,194,0,0,130,194,0,0,124,194,0,0,124,194,0,0,120,194,0,0,120,194,0,0,128,194,0,0,130,194,0,0,128,194,0,0,116,194,0,0,120,194,0,0,124,194,0,0,128,194,0,0,132,194,0,0,136,194,0,0,146,194,0,0,146,194,0,0,148,194,0,0,150,194,0,0,152,194,0,0,162,194,0,0,166,194,0,0,170,194,0,0,176,194,0,0,178,194,0,0,184,194,0,0,190,194,0,0,200,194,0,0,216,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,160,194,0,0,150,194,0,0,142,194,0,0,136,194,0,0,130,194,0,0,124,194,0,0,120,194,0,0,116,194,0,0,116,194,0,0,116,194,0,0,116,194,0,0,108,194,0,0,96,194,0,0,100,194,0,0,84,194,0,0,72,194,0,0,104,194,0,0,80,194,0,0,72,194,0,0,72,194,0,0,80,194,0,0,84,194,0,0,88,194,0,0,104,194,0,0,134,194,0,0,124,194,0,0,134,194,0,0,136,194,0,0,144,194,0,0,150,194,0,0,156,194,0,0,160,194,0,0,162,194,0,0,162,194,0,0,164,194,0,0,170,194,0,0,178,194,0,0,180,194,0,0,186,194,0,0,194,194,0,0,202,194,0,0,214,194,0,0,228,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,130,194,0,0,116,194,0,0,108,194,0,0,100,194,0,0,96,194,0,0,92,194,0,0,92,194,0,0,96,194,0,0,96,194,0,0,100,194,0,0,92,194,0,0,84,194,0,0,80,194,0,0,60,194,0,0,48,194,0,0,48,194,0,0,72,194,0,0,48,194,0,0,36,194,0,0,28,194,0,0,28,194,0,0,40,194,0,0,32,194,0,0,56,194,0,0,76,194,0,0,68,194,0,0,72,194,0,0,84,194,0,0,88,194,0,0,124,194,0,0,112,194,0,0,116,194,0,0,120,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,140,194,0,0,146,194,0,0,148,194,0,0,150,194,0,0,152,194,0,0,150,194,0,0,158,194,0,0,170,194,0,0,178,194,0,0,182,194,0,0,192,194,0,0,204,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,80,194,0,0,72,194,0,0,68,194,0,0,68,194,0,0,64,194,0,0,64,194,0,0,64,194,0,0,68,194,0,0,72,194,0,0,72,194,0,0,68,194,0,0,56,194,0,0,44,194,0,0,28,194,0,0,12,194,0,0,4,194,0,0,24,194,0,0,16,194,0,0,0,194,0,0,232,193,0,0,0,194,0,0,0,194,0,0,0,194,0,0,12,194,0,0,48,194,0,0,28,194,0,0,24,194,0,0,24,194,0,0,56,194,0,0,72,194,0,0,52,194,0,0,56,194,0,0,84,194,0,0,72,194,0,0,72,194,0,0,72,194,0,0,88,194,0,0,88,194,0,0,84,194,0,0,84,194,0,0,96,194,0,0,100,194,0,0,108,194,0,0,132,194,0,0,140,194,0,0,144,194,0,0,148,194,0,0,158,194,0,0,166,194,0,0,170,194,0,0,180,194,0,0,194,194,0,0,228,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,210,194,0,0,200,194,0,0,190,194,0,0,180,194,0,0,172,194,0,0,160,194,0,0,150,194,0,0,150,194,0,0,158,194,0,0,160,194,0,0,158,194,0,0,160,194,0,0,162,194,0,0,164,194,0,0,176,194,0,0,190,194,0,0,206,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,216,194,0,0,206,194,0,0,196,194,0,0,186,194,0,0,176,194,0,0,166,194,0,0,158,194,0,0,156,194,0,0,150,194,0,0,142,194,0,0,134,194,0,0,136,194,0,0,146,194,0,0,146,194,0,0,144,194,0,0,146,194,0,0,150,194,0,0,154,194,0,0,160,194,0,0,164,194,0,0,176,194,0,0,186,194,0,0,200,194,0,0,214,194,0,0,228,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,210,194,0,0,202,194,0,0,192,194,0,0,180,194,0,0,172,194,0,0,162,194,0,0,154,194,0,0,146,194,0,0,138,194,0,0,132,194,0,0,116,194,0,0,120,194,0,0,132,194,0,0,128,194,0,0,120,194,0,0,130,194,0,0,132,194,0,0,140,194,0,0,144,194,0,0,152,194,0,0,162,194,0,0,160,194,0,0,168,194,0,0,180,194,0,0,190,194,0,0,204,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,214,194,0,0,206,194,0,0,194,194,0,0,184,194,0,0,176,194,0,0,166,194,0,0,158,194,0,0,148,194,0,0,140,194,0,0,132,194,0,0,108,194,0,0,84,194,0,0,104,194,0,0,120,194,0,0,92,194,0,0,88,194,0,0,88,194,0,0,88,194,0,0,104,194,0,0,116,194,0,0,120,194,0,0,144,194,0,0,140,194,0,0,144,194,0,0,150,194,0,0,156,194,0,0,160,194,0,0,162,194,0,0,160,194,0,0,166,194,0,0,166,194,0,0,176,194,0,0,186,194,0,0,200,194,0,0,214,194,0,0,230,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,210,194,0,0,200,194,0,0,190,194,0,0,180,194,0,0,170,194,0,0,160,194,0,0,150,194,0,0,140,194,0,0,132,194,0,0,120,194,0,0,96,194,0,0,64,194,0,0,48,194,0,0,64,194,0,0,56,194,0,0,56,194,0,0,44,194,0,0,56,194,0,0,64,194,0,0,64,194,0,0,76,194,0,0,104,194,0,0,104,194,0,0,108,194,0,0,112,194,0,0,120,194,0,0,120,194,0,0,116,194,0,0,116,194,0,0,130,194,0,0,128,194,0,0,130,194,0,0,136,194,0,0,140,194,0,0,148,194,0,0,150,194,0,0,156,194,0,0,162,194,0,0,172,194,0,0,190,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,210,194,0,0,200,194,0,0,190,194,0,0,180,194,0,0,170,194,0,0,160,194,0,0,150,194,0,0,140,194,0,0,130,194,0,0,116,194,0,0,92,194,0,0,68,194,0,0,28,194,0,0,4,194,0,0,32,194,0,0,12,194,0,0,0,194,0,0,24,194,0,0,32,194,0,0,4,194,0,0,12,194,0,0,20,194,0,0,56,194,0,0,36,194,0,0,52,194,0,0,48,194,0,0,56,194,0,0,40,194,0,0,52,194,0,0,56,194,0,0,80,194,0,0,72,194,0,0,72,194,0,0,72,194,0,0,88,194,0,0,88,194,0,0,92,194,0,0,100,194,0,0,120,194,0,0,128,194,0,0,132,194,0,0,136,194,0,0,140,194,0,0,152,194,0,0,162,194,0,0,180,194,0,0,200,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,210,194,0,0,196,194,0,0,180,194,0,0,170,194,0,0,164,194,0,0,166,194,0,0,160,194,0,0,156,194,0,0,168,194,0,0,158,194,0,0,160,194,0,0,166,194,0,0,174,194,0,0,178,194,0,0,182,194,0,0,186,194,0,0,198,194,0,0,212,194,0,0,234,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,210,194,0,0,196,194,0,0,180,194,0,0,170,194,0,0,160,194,0,0,150,194,0,0,140,194,0,0,136,194,0,0,148,194,0,0,144,194,0,0,148,194,0,0,154,194,0,0,160,194,0,0,164,194,0,0,170,194,0,0,174,194,0,0,184,194,0,0,178,194,0,0,182,194,0,0,190,194,0,0,200,194,0,0,212,194,0,0,224,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,210,194,0,0,196,194,0,0,180,194,0,0,166,194,0,0,150,194,0,0,142,194,0,0,124,194,0,0,128,194,0,0,134,194,0,0,120,194,0,0,128,194,0,0,134,194,0,0,140,194,0,0,146,194,0,0,154,194,0,0,162,194,0,0,168,194,0,0,166,194,0,0,170,194,0,0,178,194,0,0,180,194,0,0,186,194,0,0,196,194,0,0,208,194,0,0,218,194,0,0,228,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE+30720);allocate([0,192,121,196,0,192,121,196,0,0,206,194,0,0,192,194,0,0,176,194,0,0,162,194,0,0,150,194,0,0,136,194,0,0,104,194,0,0,88,194,0,0,96,194,0,0,88,194,0,0,96,194,0,0,96,194,0,0,104,194,0,0,112,194,0,0,124,194,0,0,132,194,0,0,148,194,0,0,138,194,0,0,144,194,0,0,144,194,0,0,150,194,0,0,148,194,0,0,154,194,0,0,162,194,0,0,162,194,0,0,164,194,0,0,168,194,0,0,174,194,0,0,186,194,0,0,192,194,0,0,198,194,0,0,208,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,216,194,0,0,204,194,0,0,192,194,0,0,182,194,0,0,170,194,0,0,160,194,0,0,148,194,0,0,136,194,0,0,112,194,0,0,76,194,0,0,56,194,0,0,64,194,0,0,56,194,0,0,44,194,0,0,52,194,0,0,60,194,0,0,60,194,0,0,68,194,0,0,64,194,0,0,96,194,0,0,84,194,0,0,92,194,0,0,104,194,0,0,100,194,0,0,124,194,0,0,104,194,0,0,112,194,0,0,132,194,0,0,128,194,0,0,134,194,0,0,140,194,0,0,140,194,0,0,148,194,0,0,154,194,0,0,168,194,0,0,172,194,0,0,178,194,0,0,182,194,0,0,186,194,0,0,188,194,0,0,202,194,0,0,218,194,0,0,236,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,216,194,0,0,206,194,0,0,196,194,0,0,186,194,0,0,176,194,0,0,166,194,0,0,156,194,0,0,146,194,0,0,136,194,0,0,112,194,0,0,84,194,0,0,48,194,0,0,12,194,0,0,24,194,0,0,24,194,0,0,8,194,0,0,8,194,0,0,16,194,0,0,32,194,0,0,36,194,0,0,48,194,0,0,76,194,0,0,52,194,0,0,56,194,0,0,60,194,0,0,56,194,0,0,88,194,0,0,72,194,0,0,68,194,0,0,72,194,0,0,72,194,0,0,72,194,0,0,76,194,0,0,88,194,0,0,100,194,0,0,104,194,0,0,112,194,0,0,132,194,0,0,132,194,0,0,132,194,0,0,128,194,0,0,130,194,0,0,136,194,0,0,154,194,0,0,164,194,0,0,174,194,0,0,190,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,214,194,0,0,204,194,0,0,194,194,0,0,184,194,0,0,174,194,0,0,166,194,0,0,156,194,0,0,150,194,0,0,164,194,0,0,158,194,0,0,166,194,0,0,170,194,0,0,178,194,0,0,184,194,0,0,190,194,0,0,196,194,0,0,202,194,0,0,210,194,0,0,218,194,0,0,226,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,212,194,0,0,200,194,0,0,190,194,0,0,180,194,0,0,172,194,0,0,162,194,0,0,156,194,0,0,148,194,0,0,138,194,0,0,148,194,0,0,148,194,0,0,152,194,0,0,158,194,0,0,166,194,0,0,168,194,0,0,172,194,0,0,178,194,0,0,184,194,0,0,194,194,0,0,186,194,0,0,200,194,0,0,206,194,0,0,214,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,212,194,0,0,200,194,0,0,190,194,0,0,180,194,0,0,174,194,0,0,166,194,0,0,160,194,0,0,150,194,0,0,138,194,0,0,112,194,0,0,132,194,0,0,132,194,0,0,136,194,0,0,140,194,0,0,148,194,0,0,156,194,0,0,158,194,0,0,162,194,0,0,162,194,0,0,166,194,0,0,168,194,0,0,174,194,0,0,186,194,0,0,192,194,0,0,198,194,0,0,206,194,0,0,214,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,216,194,0,0,206,194,0,0,196,194,0,0,186,194,0,0,178,194,0,0,170,194,0,0,164,194,0,0,156,194,0,0,142,194,0,0,120,194,0,0,92,194,0,0,104,194,0,0,104,194,0,0,88,194,0,0,88,194,0,0,92,194,0,0,108,194,0,0,116,194,0,0,120,194,0,0,140,194,0,0,132,194,0,0,132,194,0,0,134,194,0,0,140,194,0,0,144,194,0,0,150,194,0,0,156,194,0,0,168,194,0,0,168,194,0,0,168,194,0,0,176,194,0,0,182,194,0,0,180,194,0,0,190,194,0,0,196,194,0,0,204,194,0,0,206,194,0,0,212,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,216,194,0,0,206,194,0,0,196,194,0,0,188,194,0,0,180,194,0,0,174,194,0,0,164,194,0,0,158,194,0,0,146,194,0,0,134,194,0,0,104,194,0,0,60,194,0,0,72,194,0,0,52,194,0,0,36,194,0,0,52,194,0,0,64,194,0,0,48,194,0,0,48,194,0,0,68,194,0,0,88,194,0,0,76,194,0,0,64,194,0,0,60,194,0,0,68,194,0,0,72,194,0,0,76,194,0,0,100,194,0,0,104,194,0,0,112,194,0,0,124,194,0,0,138,194,0,0,140,194,0,0,138,194,0,0,142,194,0,0,148,194,0,0,156,194,0,0,164,194,0,0,180,194,0,0,190,194,0,0,202,194,0,0,210,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,210,194,0,0,202,194,0,0,194,194,0,0,186,194,0,0,180,194,0,0,170,194,0,0,160,194,0,0,154,194,0,0,144,194,0,0,130,194,0,0,96,194,0,0,64,194,0,0,20,194,0,0,32,194,0,0,16,194,0,0,8,194,0,0,32,194,0,0,72,194,0,0,60,194,0,0,24,194,0,0,36,194,0,0,60,194,0,0,24,194,0,0,12,194,0,0,28,194,0,0,24,194,0,0,44,194,0,0,32,194,0,0,52,194,0,0,72,194,0,0,52,194,0,0,48,194,0,0,60,194,0,0,72,194,0,0,92,194,0,0,64,194,0,0,64,194,0,0,80,194,0,0,132,194,0,0,140,194,0,0,152,194,0,0,164,194,0,0,180,194,0,0,194,194,0,0,210,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,216,194,0,0,206,194,0,0,196,194,0,0,186,194,0,0,172,194,0,0,158,194,0,0,152,194,0,0,166,194,0,0,162,194,0,0,170,194,0,0,174,194,0,0,178,194,0,0,186,194,0,0,196,194,0,0,204,194,0,0,214,194,0,0,224,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,216,194,0,0,206,194,0,0,196,194,0,0,186,194,0,0,172,194,0,0,158,194,0,0,142,194,0,0,154,194,0,0,148,194,0,0,154,194,0,0,158,194,0,0,162,194,0,0,168,194,0,0,170,194,0,0,180,194,0,0,184,194,0,0,186,194,0,0,184,194,0,0,196,194,0,0,202,194,0,0,216,194,0,0,224,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,216,194,0,0,206,194,0,0,196,194,0,0,186,194,0,0,174,194,0,0,156,194,0,0,136,194,0,0,130,194,0,0,132,194,0,0,120,194,0,0,130,194,0,0,134,194,0,0,140,194,0,0,146,194,0,0,150,194,0,0,156,194,0,0,164,194,0,0,164,194,0,0,166,194,0,0,168,194,0,0,182,194,0,0,186,194,0,0,196,194,0,0,204,194,0,0,212,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,210,194,0,0,200,194,0,0,190,194,0,0,180,194,0,0,164,194,0,0,148,194,0,0,120,194,0,0,100,194,0,0,104,194,0,0,96,194,0,0,76,194,0,0,80,194,0,0,80,194,0,0,88,194,0,0,88,194,0,0,104,194,0,0,132,194,0,0,108,194,0,0,112,194,0,0,124,194,0,0,132,194,0,0,138,194,0,0,146,194,0,0,158,194,0,0,166,194,0,0,168,194,0,0,160,194,0,0,162,194,0,0,162,194,0,0,164,194,0,0,176,194,0,0,184,194,0,0,196,194,0,0,210,194,0,0,226,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,214,194,0,0,204,194,0,0,194,194,0,0,184,194,0,0,168,194,0,0,158,194,0,0,138,194,0,0,100,194,0,0,60,194,0,0,80,194,0,0,60,194,0,0,48,194,0,0,52,194,0,0,72,194,0,0,80,194,0,0,40,194,0,0,40,194,0,0,84,194,0,0,44,194,0,0,44,194,0,0,64,194,0,0,76,194,0,0,96,194,0,0,92,194,0,0,80,194,0,0,100,194,0,0,108,194,0,0,116,194,0,0,120,194,0,0,134,194,0,0,142,194,0,0,156,194,0,0,166,194,0,0,172,194,0,0,188,194,0,0,196,194,0,0,206,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,210,194,0,0,200,194,0,0,190,194,0,0,180,194,0,0,168,194,0,0,156,194,0,0,140,194,0,0,116,194,0,0,76,194,0,0,36,194,0,0,32,194,0,0,24,194,0,0,32,194,0,0,56,194,0,0,80,194,0,0,76,194,0,0,36,194,0,0,32,194,0,0,56,194,0,0,32,194,0,0,24,194,0,0,24,194,0,0,36,194,0,0,56,194,0,0,36,194,0,0,56,194,0,0,60,194,0,0,44,194,0,0,44,194,0,0,52,194,0,0,36,194,0,0,52,194,0,0,96,194,0,0,134,194,0,0,136,194,0,0,166,194,0,0,174,194,0,0,180,194,0,0,190,194,0,0,204,194,0,0,214,194,0,0,226,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,218,194,0,0,210,194,0,0,202,194,0,0,192,194,0,0,182,194,0,0,168,194,0,0,154,194,0,0,164,194,0,0,164,194,0,0,170,194,0,0,178,194,0,0,188,194,0,0,200,194,0,0,212,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,212,194,0,0,206,194,0,0,196,194,0,0,184,194,0,0,170,194,0,0,160,194,0,0,142,194,0,0,150,194,0,0,144,194,0,0,152,194,0,0,160,194,0,0,168,194,0,0,172,194,0,0,178,194,0,0,186,194,0,0,200,194,0,0,214,194,0,0,226,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,214,194,0,0,208,194,0,0,202,194,0,0,194,194,0,0,184,194,0,0,176,194,0,0,168,194,0,0,160,194,0,0,128,194,0,0,132,194,0,0,124,194,0,0,128,194,0,0,132,194,0,0,138,194,0,0,146,194,0,0,154,194,0,0,166,194,0,0,166,194,0,0,172,194,0,0,182,194,0,0,196,194,0,0,208,194,0,0,222,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,214,194,0,0,208,194,0,0,202,194,0,0,194,194,0,0,184,194,0,0,180,194,0,0,168,194,0,0,148,194,0,0,100,194,0,0,104,194,0,0,80,194,0,0,92,194,0,0,88,194,0,0,72,194,0,0,80,194,0,0,72,194,0,0,80,194,0,0,124,194,0,0,120,194,0,0,138,194,0,0,152,194,0,0,154,194,0,0,156,194,0,0,156,194,0,0,158,194,0,0,164,194,0,0,176,194,0,0,188,194,0,0,200,194,0,0,212,194,0,0,222,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,212,194,0,0,204,194,0,0,196,194,0,0,190,194,0,0,180,194,0,0,170,194,0,0,166,194,0,0,156,194,0,0,140,194,0,0,72,194,0,0,72,194,0,0,36,194,0,0,48,194,0,0,68,194,0,0,60,194,0,0,72,194,0,0,72,194,0,0,48,194,0,0,92,194,0,0,56,194,0,0,60,194,0,0,64,194,0,0,64,194,0,0,88,194,0,0,68,194,0,0,68,194,0,0,104,194,0,0,120,194,0,0,142,194,0,0,162,194,0,0,174,194,0,0,184,194,0,0,194,194,0,0,204,194,0,0,216,194,0,0,228,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,212,194,0,0,204,194,0,0,196,194,0,0,190,194,0,0,180,194,0,0,170,194,0,0,166,194,0,0,156,194,0,0,140,194,0,0,52,194,0,0,44,194,0,0,36,194,0,0,60,194,0,0,72,194,0,0,76,194,0,0,72,194,0,0,68,194,0,0,52,194,0,0,60,194,0,0,36,194,0,0,48,194,0,0,36,194,0,0,28,194,0,0,44,194,0,0,24,194,0,0,20,194,0,0,32,194,0,0,36,194,0,0,48,194,0,0,72,194,0,0,104,194,0,0,130,194,0,0,146,194,0,0,158,194,0,0,170,194,0,0,184,194,0,0,194,194,0,0,202,194,0,0,210,194,0,0,218,194,0,0,226,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,214,194,0,0,200,194,0,0,190,194,0,0,174,194,0,0,162,194,0,0,170,194,0,0,166,194,0,0,176,194,0,0,186,194,0,0,200,194,0,0,214,194,0,0,228,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,214,194,0,0,202,194,0,0,190,194,0,0,176,194,0,0,166,194,0,0,152,194,0,0,146,194,0,0,144,194,0,0,158,194,0,0,168,194,0,0,180,194,0,0,190,194,0,0,200,194,0,0,210,194,0,0,220,194,0,0,230,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,208,194,0,0,196,194,0,0,184,194,0,0,174,194,0,0,162,194,0,0,140,194,0,0,130,194,0,0,120,194,0,0,134,194,0,0,142,194,0,0,148,194,0,0,160,194,0,0,170,194,0,0,182,194,0,0,190,194,0,0,198,194,0,0,206,194,0,0,216,194,0,0,222,194,0,0,228,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,206,194,0,0,194,194,0,0,180,194,0,0,170,194,0,0,152,194,0,0,112,194,0,0,96,194,0,0,88,194,0,0,112,194,0,0,120,194,0,0,116,194,0,0,96,194,0,0,124,194,0,0,130,194,0,0,146,194,0,0,148,194,0,0,154,194,0,0,150,194,0,0,156,194,0,0,162,194,0,0,172,194,0,0,174,194,0,0,176,194,0,0,182,194,0,0,188,194,0,0,196,194,0,0,206,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,210,194,0,0,200,194,0,0,194,194,0,0,184,194,0,0,172,194,0,0,162,194,0,0,158,194,0,0,140,194,0,0,100,194,0,0,76,194,0,0,60,194,0,0,76,194,0,0,104,194,0,0,112,194,0,0,96,194,0,0,84,194,0,0,72,194,0,0,104,194,0,0,80,194,0,0,72,194,0,0,72,194,0,0,84,194,0,0,92,194,0,0,128,194,0,0,138,194,0,0,142,194,0,0,170,194,0,0,164,194,0,0,156,194,0,0,162,194,0,0,170,194,0,0,190,194,0,0,204,194,0,0,224,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,210,194,0,0,200,194,0,0,194,194,0,0,184,194,0,0,170,194,0,0,166,194,0,0,158,194,0,0,144,194,0,0,68,194,0,0,32,194,0,0,44,194,0,0,44,194,0,0,88,194,0,0,96,194,0,0,76,194,0,0,72,194,0,0,32,194,0,0,44,194,0,0,24,194,0,0,16,194,0,0,12,194,0,0,20,194,0,0,24,194,0,0,20,194,0,0,48,194,0,0,88,194,0,0,112,194,0,0,100,194,0,0,112,194,0,0,140,194,0,0,150,194,0,0,168,194,0,0,184,194,0,0,206,194,0,0,224,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,204,194,0,0,190,194,0,0,178,194,0,0,164,194,0,0,166,194,0,0,168,194,0,0,180,194,0,0,184,194,0,0,198,194,0,0,214,194,0,0,226,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,214,194,0,0,202,194,0,0,190,194,0,0,178,194,0,0,166,194,0,0,144,194,0,0,148,194,0,0,156,194,0,0,170,194,0,0,176,194,0,0,176,194,0,0,180,194,0,0,184,194,0,0,196,194,0,0,210,194,0,0,222,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,218,194,0,0,206,194,0,0,194,194,0,0,186,194,0,0,174,194,0,0,162,194,0,0,140,194,0,0,140,194,0,0,134,194,0,0,150,194,0,0,146,194,0,0,152,194,0,0,158,194,0,0,162,194,0,0,166,194,0,0,176,194,0,0,178,194,0,0,194,194,0,0,206,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,214,194,0,0,200,194,0,0,188,194,0,0,176,194,0,0,166,194,0,0,150,194,0,0,124,194,0,0,108,194,0,0,108,194,0,0,124,194,0,0,132,194,0,0,112,194,0,0,120,194,0,0,134,194,0,0,134,194,0,0,154,194,0,0,152,194,0,0,162,194,0,0,176,194,0,0,172,194,0,0,184,194,0,0,192,194,0,0,204,194,0,0,218,194,0,0,232,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,210,194,0,0,196,194,0,0,184,194,0,0,172,194,0,0,162,194,0,0,146,194,0,0,96,194,0,0,80,194,0,0,60,194,0,0,92,194,0,0,112,194,0,0,104,194,0,0,80,194,0,0,76,194,0,0,52,194,0,0,68,194,0,0,72,194,0,0,84,194,0,0,88,194,0,0,116,194,0,0,142,194,0,0,140,194,0,0,138,194,0,0,156,194,0,0,158,194,0,0,174,194,0,0,180,194,0,0,192,194,0,0,208,194,0,0,224,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,206,194,0,0,192,194,0,0,180,194,0,0,172,194,0,0,156,194,0,0,140,194,0,0,76,194,0,0,40,194,0,0,60,194,0,0,64,194,0,0,92,194,0,0,88,194,0,0,88,194,0,0,84,194,0,0,40,194,0,0,12,194,0,0,224,193,0,0,4,194,0,0,24,194,0,0,20,194,0,0,48,194,0,0,60,194,0,0,68,194,0,0,88,194,0,0,124,194,0,0,136,194,0,0,156,194,0,0,164,194,0,0,178,194,0,0,188,194,0,0,198,194,0,0,208,194,0,0,218,194,0,0,228,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,200,194,0,0,180,194,0,0,158,194,0,0,170,194,0,0,162,194,0,0,164,194,0,0,164,194,0,0,178,194,0,0,188,194,0,0,198,194,0,0,206,194,0,0,218,194,0,0,230,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,210,194,0,0,194,194,0,0,170,194,0,0,144,194,0,0,148,194,0,0,140,194,0,0,140,194,0,0,140,194,0,0,152,194,0,0,170,194,0,0,182,194,0,0,186,194,0,0,194,194,0,0,206,194,0,0,218,194,0,0,230,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,224,194,0,0,186,194,0,0,162,194,0,0,136,194,0,0,120,194,0,0,112,194,0,0,112,194,0,0,100,194,0,0,124,194,0,0,140,194,0,0,154,194,0,0,164,194,0,0,180,194,0,0,186,194,0,0,196,194,0,0,208,194,0,0,218,194,0,0,226,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,226,194,0,0,200,194,0,0,186,194,0,0,168,194,0,0,124,194,0,0,104,194,0,0,64,194,0,0,84,194,0,0,88,194,0,0,80,194,0,0,80,194,0,0,100,194,0,0,128,194,0,0,132,194,0,0,152,194,0,0,166,194,0,0,162,194,0,0,170,194,0,0,170,194,0,0,180,194,0,0,190,194,0,0,196,194,0,0,202,194,0,0,206,194,0,0,212,194,0,0,216,194,0,0,222,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,210,194,0,0,190,194,0,0,172,194,0,0,148,194,0,0,84,194,0,0,72,194,0,0,24,194,0,0,44,194,0,0,68,194,0,0,44,194,0,0,40,194,0,0,28,194,0,0,28,194,0,0,56,194,0,0,80,194,0,0,100,194,0,0,96,194,0,0,144,194,0,0,138,194,0,0,148,194,0,0,162,194,0,0,174,194,0,0,184,194,0,0,188,194,0,0,194,194,0,0,198,194,0,0,204,194,0,0,210,194,0,0,216,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,216,194,0,0,198,194,0,0,180,194,0,0,152,194,0,0,132,194,0,0,52,194,0,0,44,194,0,0,36,194,0,0,48,194,0,0,60,194,0,0,44,194,0,0,60,194,0,0,32,194,0,0,240,193,0,0,248,193,0,0,248,193,0,0,28,194,0,0,4,194,0,0,32,194,0,0,36,194,0,0,44,194,0,0,84,194,0,0,108,194,0,0,140,194,0,0,146,194,0,0,154,194,0,0,158,194,0,0,164,194,0,0,168,194,0,0,174,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,182,194,0,0,152,194,0,0,150,194,0,0,170,194,0,0,186,194,0,0,196,194,0,0,208,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,182,194,0,0,140,194,0,0,140,194,0,0,150,194,0,0,172,194,0,0,178,194,0,0,188,194,0,0,196,194,0,0,202,194,0,0,212,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,190,194,0,0,160,194,0,0,112,194,0,0,130,194,0,0,128,194,0,0,148,194,0,0,166,194,0,0,176,194,0,0,182,194,0,0,190,194,0,0,198,194,0,0,206,194,0,0,214,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,190,194,0,0,160,194,0,0,104,194,0,0,92,194,0,0,68,194,0,0,132,194,0,0,136,194,0,0,142,194,0,0,156,194,0,0,156,194,0,0,160,194,0,0,176,194,0,0,170,194,0,0,178,194,0,0,194,194,0,0,200,194,0,0,210,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,190,194,0,0,160,194,0,0,84,194,0,0,80,194,0,0,36,194,0,0,108,194,0,0,108,194,0,0,68,194,0,0,104,194,0,0,96,194,0,0,124,194,0,0,172,194,0,0,158,194,0,0,180,194,0,0,186,194,0,0,196,194,0,0,206,194,0,0,214,194,0,0,224,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,194,194,0,0,182,194,0,0,146,194,0,0,52,194,0,0,32,194,0,0,4,194,0,0,84,194,0,0,116,194,0,0,68,194,0,0,88,194,0,0,72,194,0,0,72,194,0,0,112,194,0,0,80,194,0,0,134,194,0,0,148,194,0,0,162,194,0,0,184,194,0,0,192,194,0,0,200,194,0,0,210,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,226,194,0,0,212,194,0,0,198,194,0,0,184,194,0,0,154,194,0,0,160,194,0,0,176,194,0,0,194,194,0,0,212,194,0,0,230,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE+40960);allocate([0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,232,194,0,0,218,194,0,0,204,194,0,0,190,194,0,0,178,194,0,0,148,194,0,0,144,194,0,0,176,194,0,0,174,194,0,0,190,194,0,0,204,194,0,0,218,194,0,0,232,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,232,194,0,0,218,194,0,0,204,194,0,0,190,194,0,0,178,194,0,0,150,194,0,0,132,194,0,0,148,194,0,0,154,194,0,0,156,194,0,0,172,194,0,0,174,194,0,0,180,194,0,0,192,194,0,0,210,194,0,0,230,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,230,194,0,0,216,194,0,0,202,194,0,0,188,194,0,0,176,194,0,0,132,194,0,0,96,194,0,0,116,194,0,0,140,194,0,0,130,194,0,0,156,194,0,0,144,194,0,0,166,194,0,0,168,194,0,0,186,194,0,0,196,194,0,0,210,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,210,194,0,0,190,194,0,0,178,194,0,0,164,194,0,0,100,194,0,0,80,194,0,0,80,194,0,0,108,194,0,0,96,194,0,0,108,194,0,0,104,194,0,0,138,194,0,0,134,194,0,0,176,194,0,0,164,194,0,0,164,194,0,0,178,194,0,0,188,194,0,0,200,194,0,0,216,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,202,194,0,0,192,194,0,0,180,194,0,0,166,194,0,0,154,194,0,0,88,194,0,0,44,194,0,0,24,194,0,0,72,194,0,0,64,194,0,0,80,194,0,0,64,194,0,0,40,194,0,0,40,194,0,0,76,194,0,0,80,194,0,0,84,194,0,0,108,194,0,0,130,194,0,0,142,194,0,0,156,194,0,0,170,194,0,0,190,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,240,194,0,0,210,194,0,0,172,194,0,0,136,194,0,0,156,194,0,0,158,194,0,0,180,194,0,0,200,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,240,194,0,0,210,194,0,0,172,194,0,0,132,194,0,0,146,194,0,0,154,194,0,0,176,194,0,0,192,194,0,0,210,194,0,0,230,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,240,194,0,0,210,194,0,0,184,194,0,0,160,194,0,0,116,194,0,0,128,194,0,0,136,194,0,0,160,194,0,0,174,194,0,0,184,194,0,0,200,194,0,0,220,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,240,194,0,0,208,194,0,0,182,194,0,0,158,194,0,0,80,194,0,0,112,194,0,0,88,194,0,0,128,194,0,0,138,194,0,0,154,194,0,0,160,194,0,0,164,194,0,0,168,194,0,0,170,194,0,0,174,194,0,0,176,194,0,0,180,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,236,194,0,0,200,194,0,0,174,194,0,0,154,194,0,0,68,194,0,0,72,194,0,0,48,194,0,0,104,194,0,0,116,194,0,0,116,194,0,0,134,194,0,0,130,194,0,0,120,194,0,0,120,194,0,0,120,194,0,0,130,194,0,0,136,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,230,194,0,0,196,194,0,0,168,194,0,0,120,194,0,0,68,194,0,0,48,194,0,0,24,194,0,0,56,194,0,0,68,194,0,0,68,194,0,0,56,194,0,0,28,194,0,0,20,194,0,0,28,194,0,0,32,194,0,0,40,194,0,0,44,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,176,194,0,0,148,194,0,0,154,194,0,0,164,194,0,0,164,194,0,0,170,194,0,0,180,194,0,0,188,194,0,0,198,194,0,0,208,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,176,194,0,0,132,194,0,0,140,194,0,0,162,194,0,0,160,194,0,0,162,194,0,0,168,194,0,0,176,194,0,0,182,194,0,0,186,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,176,194,0,0,116,194,0,0,124,194,0,0,140,194,0,0,142,194,0,0,148,194,0,0,154,194,0,0,160,194,0,0,166,194,0,0,170,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,172,194,0,0,120,194,0,0,124,194,0,0,120,194,0,0,120,194,0,0,104,194,0,0,80,194,0,0,72,194,0,0,72,194,0,0,80,194,0,0,88,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,236,194,0,0,216,194,0,0,168,194,0,0,84,194,0,0,72,194,0,0,72,194,0,0,72,194,0,0,92,194,0,0,60,194,0,0,52,194,0,0,32,194,0,0,32,194,0,0,32,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,236,194,0,0,200,194,0,0,146,194,0,0,44,194,0,0,20,194,0,0,40,194,0,0,44,194,0,0,84,194,0,0,24,194,0,0,20,194,0,0,12,194,0,0,12,194,0,0,24,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,200,194,0,0,182,194,0,0,168,194,0,0,148,194,0,0,160,194,0,0,160,194,0,0,160,194,0,0,160,194,0,0,160,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,200,194,0,0,182,194,0,0,168,194,0,0,148,194,0,0,136,194,0,0,136,194,0,0,136,194,0,0,136,194,0,0,136,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,200,194,0,0,172,194,0,0,156,194,0,0,140,194,0,0,112,194,0,0,52,194,0,0,240,193,0,0,168,193,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,200,194,0,0,174,194,0,0,156,194,0,0,134,194,0,0,64,194,0,0,24,194,0,0,232,193,0,0,168,193,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,200,194,0,0,172,194,0,0,138,194,0,0,96,194,0,0,52,194,0,0,12,194,0,0,4,194,0,0,232,193,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,0,220,194,0,0,200,194,0,0,166,194,0,0,142,194,0,0,64,194,0,0,216,193,0,0,24,194,0,0,20,194,0,0,8,194,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,0,192,121,196,62,180,228,51,9,145,243,51,139,178,1,52,60,32,10,52,35,26,19,52,96,169,28,52,167,215,38,52,75,175,49,52,80,59,61,52,112,135,73,52,35,160,86,52,184,146,100,52,85,109,115,52,136,159,129,52,252,11,138,52,147,4,147,52,105,146,156,52,50,191,166,52,63,149,177,52,147,31,189,52,228,105,201,52,173,128,214,52,54,113,228,52,166,73,243,52,136,140,1,53,192,247,9,53,6,239,18,53,118,123,28,53,192,166,38,53,55,123,49,53,218,3,61,53,94,76,73,53,59,97,86,53,185,79,100,53,252,37,115,53,138,121,129,53,134,227,137,53,124,217,146,53,133,100,156,53,82,142,166,53,51,97,177,53,37,232,188,53,220,46,201,53,206,65,214,53,65,46,228,53,87,2,243,53,143,102,1,54,79,207,9,54,245,195,18,54,152,77,28,54,232,117,38,54,50,71,49,54,116,204,60,54,94,17,73,54,101,34,86,54,206,12,100,54,184,222,114,54,151,83,129,54,28,187,137,54,114,174,146,54,175,54,156,54,129,93,166,54,53,45,177,54,199,176,188,54,228,243,200,54,1,3,214,54,96,235,227,54,30,187,242,54,162,64,1,55,235,166,9,55,241,152,18,55,201,31,28,55,30,69,38,55,61,19,49,55,30,149,60,55,111,214,72,55,162,227,85,55,247,201,99,55,137,151,114,55,175,45,129,55,190,146,137,55,116,131,146,55,230,8,156,55,190,44,166,55,71,249,176,55,121,121,188,55,254,184,200,55,71,196,213,55,146,168,227,55,248,115,242,55,192,26,1,56,147,126,9,56,249,109,18,56,6,242,27,56,98,20,38,56,86,223,48,56,216,93,60,56,146,155,72,56,242,164,85,56,51,135,99,56,110,80,114,56,211,7,129,56,107,106,137,56,130,88,146,56,42,219,155,56,9,252,165,56,104,197,176,56,59,66,188,56,41,126,200,56,160,133,213,56,217,101,227,56,232,44,242,56,233,244,0,57,70,86,9,57,14,67,18,57,81,196,27,57,181,227,37,57,127,171,48,57,162,38,60,57,197,96,72,57,83,102,85,57,131,68,99,57,104,9,114,57,1,226,128,57,36,66,137,57,157,45,146,57,123,173,155,57,99,203,165,57,153,145,176,57,13,11,188,57,102,67,200,57,11,71,213,57,50,35,227,57,237,229,241,57,29,207,0,58,5,46,9,58,48,24,18,58,169,150,27,58,21,179,37,58,183,119,48,58,124,239,59,58,10,38,72,58,199,39,85,58,230,1,99,58,120,194,113,58,59,188,128,58,233,25,137,58,198,2,146,58,219,127,155,58,203,154,165,58,216,93,176,58,239,211,187,58,179,8,200,58,136,8,213,58,159,224,226,58,7,159,241,58,92,169,0,59,208,5,9,59,94,237,17,59,15,105,27,59,132,130,37,59,253,67,48,59,103,184,59,59,97,235,71,59,77,233,84,59,93,191,98,59,156,123,113,59,127,150,128,59,186,241,136,59,249,215,145,59,71,82,155,59,65,106,165,59,39,42,176,59,226,156,187,59,18,206,199,59,23,202,212,59,32,158,226,59,53,88,241,59,166,131,0,60,167,221,8,60,152,194,17,60,130,59,27,60,1,82,37,60,84,16,48,60,97,129,59,60,200,176,71,60,229,170,84,60,232,124,98,60,212,52,113,60,207,112,128,60,150,201,136,60,58,173,145,60,192,36,155,60,197,57,165,60,133,246,175,60,229,101,187,60,130,147,199,60,185,139,212,60,180,91,226,60,121,17,241,60,251,93,0,61,137,181,8,61,223,151,17,61,2,14,27,61,141,33,37,61,185,220,47,61,109,74,59,61,64,118,71,61,145,108,84,61,133,58,98,61,34,238,112,61,42,75,128,61,127,161,136,61,136,130,145,61,72,247,154,61,88,9,165,61,242,194,175,61,248,46,187,61,3,89,199,61,109,77,212,61,92,25,226,61,209,202,240,61,91,56,0,62,119,141,8,62,51,109,17,62,144,224,26,62,39,241,36,62,46,169,47,62,135,19,59,62,202,59,71,62,77,46,84,62,55,248,97,62,132,167,112,62,143,37,128,62,115,121,136,62,226,87,145,62,220,201,154,62,249,216,164,62,109,143,175,62,27,248,186,62,149,30,199,62,51,15,212,62,23,215,225,62,61,132,240,62,198,18,0,63,114,101,8,63,147,66,17,63,43,179,26,63,206,192,36,63,177,117,47,63,178,220,58,63,101,1,71,63,29,240,83,63,251,181,97,63,251,96,112,63,0,0,128,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,73,110,118,97,108,105,100,32,118,111,114,98,105,115,32,104,101,97,100,101,114,63,0,0,86,111,114,98,105,115,32,100,101,99,111,100,101,114,32,102,97,105,108,101,100,32,109,121,115,116,101,114,105,111,117,115,108,121,63,32,37,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE+51200);var tempDoublePtr=Runtime.alignMemory(allocate(12,"i8",ALLOC_STATIC),8);assert(tempDoublePtr%8==0);function copyTempFloat(ptr){HEAP8[tempDoublePtr]=HEAP8[ptr];HEAP8[tempDoublePtr+1]=HEAP8[ptr+1];HEAP8[tempDoublePtr+2]=HEAP8[ptr+2];HEAP8[tempDoublePtr+3]=HEAP8[ptr+3]}function copyTempDouble(ptr){HEAP8[tempDoublePtr]=HEAP8[ptr];HEAP8[tempDoublePtr+1]=HEAP8[ptr+1];HEAP8[tempDoublePtr+2]=HEAP8[ptr+2];HEAP8[tempDoublePtr+3]=HEAP8[ptr+3];HEAP8[tempDoublePtr+4]=HEAP8[ptr+4];HEAP8[tempDoublePtr+5]=HEAP8[ptr+5];HEAP8[tempDoublePtr+6]=HEAP8[ptr+6];HEAP8[tempDoublePtr+7]=HEAP8[ptr+7]}var _cosf=Math_cos;Module["_i64Subtract"]=_i64Subtract;var _fabsf=Math_abs;var ___errno_state=0;function ___setErrNo(value){HEAP32[___errno_state>>2]=value;return value}var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};function _sysconf(name){switch(name){case 30:return PAGE_SIZE;case 85:return totalMemory/PAGE_SIZE;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:return 200809;case 79:return 0;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return-1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}___setErrNo(ERRNO_CODES.EINVAL);return-1}Module["_memset"]=_memset;var _BDtoILow=true;Module["_bitshift64Shl"]=_bitshift64Shl;function _abort(){Module["abort"]()}var FS=undefined;var SOCKFS=undefined;function _send(fd,buf,len,flags){var sock=SOCKFS.getSocket(fd);if(!sock){___setErrNo(ERRNO_CODES.EBADF);return-1}return _write(fd,buf,len)}function _pwrite(fildes,buf,nbyte,offset){var stream=FS.getStream(fildes);if(!stream){___setErrNo(ERRNO_CODES.EBADF);return-1}try{var slab=HEAP8;return FS.write(stream,slab,buf,nbyte,offset)}catch(e){FS.handleFSError(e);return-1}}function _write(fildes,buf,nbyte){var stream=FS.getStream(fildes);if(!stream){___setErrNo(ERRNO_CODES.EBADF);return-1}try{var slab=HEAP8;return FS.write(stream,slab,buf,nbyte)}catch(e){FS.handleFSError(e);return-1}}function _fileno(stream){stream=FS.getStreamFromPtr(stream);if(!stream)return-1;return stream.fd}function _fwrite(ptr,size,nitems,stream){var bytesToWrite=nitems*size;if(bytesToWrite==0)return 0;var fd=_fileno(stream);var bytesWritten=_write(fd,ptr,bytesToWrite);if(bytesWritten==-1){var streamObj=FS.getStreamFromPtr(stream);if(streamObj)streamObj.error=true;return 0}else{return bytesWritten/size|0}}Module["_strlen"]=_strlen;function __reallyNegative(x){return x<0||x===0&&1/x===-Infinity}function __formatString(format,varargs){assert((varargs&3)===0);var textIndex=format;var argIndex=0;function getNextArg(type){var ret;argIndex=Runtime.prepVararg(argIndex,type);if(type==="double"){ret=(HEAP32[tempDoublePtr>>2]=HEAP32[varargs+argIndex>>2],HEAP32[tempDoublePtr+4>>2]=HEAP32[varargs+(argIndex+4)>>2],+HEAPF64[tempDoublePtr>>3]);argIndex+=8}else if(type=="i64"){ret=[HEAP32[varargs+argIndex>>2],HEAP32[varargs+(argIndex+4)>>2]];argIndex+=8}else{assert((argIndex&3)===0);type="i32";ret=HEAP32[varargs+argIndex>>2];argIndex+=4}return ret}var ret=[];var curr,next,currArg;while(1){var startTextIndex=textIndex;curr=HEAP8[textIndex>>0];if(curr===0)break;next=HEAP8[textIndex+1>>0];if(curr==37){var flagAlwaysSigned=false;var flagLeftAlign=false;var flagAlternative=false;var flagZeroPad=false;var flagPadSign=false;flagsLoop:while(1){switch(next){case 43:flagAlwaysSigned=true;break;case 45:flagLeftAlign=true;break;case 35:flagAlternative=true;break;case 48:if(flagZeroPad){break flagsLoop}else{flagZeroPad=true;break};case 32:flagPadSign=true;break;default:break flagsLoop}textIndex++;next=HEAP8[textIndex+1>>0]}var width=0;if(next==42){width=getNextArg("i32");textIndex++;next=HEAP8[textIndex+1>>0]}else{while(next>=48&&next<=57){width=width*10+(next-48);textIndex++;next=HEAP8[textIndex+1>>0]}}var precisionSet=false,precision=-1;if(next==46){precision=0;precisionSet=true;textIndex++;next=HEAP8[textIndex+1>>0];if(next==42){precision=getNextArg("i32");textIndex++}else{while(1){var precisionChr=HEAP8[textIndex+1>>0];if(precisionChr<48||precisionChr>57)break;precision=precision*10+(precisionChr-48);textIndex++}}next=HEAP8[textIndex+1>>0]}if(precision<0){precision=6;precisionSet=false}var argSize;switch(String.fromCharCode(next)){case"h":var nextNext=HEAP8[textIndex+2>>0];if(nextNext==104){textIndex++;argSize=1}else{argSize=2}break;case"l":var nextNext=HEAP8[textIndex+2>>0];if(nextNext==108){textIndex++;argSize=8}else{argSize=4}break;case"L":case"q":case"j":argSize=8;break;case"z":case"t":case"I":argSize=4;break;default:argSize=null}if(argSize)textIndex++;next=HEAP8[textIndex+1>>0];switch(String.fromCharCode(next)){case"d":case"i":case"u":case"o":case"x":case"X":case"p":{var signed=next==100||next==105;argSize=argSize||4;var currArg=getNextArg("i"+argSize*8);var origArg=currArg;var argText;if(argSize==8){currArg=Runtime.makeBigInt(currArg[0],currArg[1],next==117)}if(argSize<=4){var limit=Math.pow(256,argSize)-1;currArg=(signed?reSign:unSign)(currArg&limit,argSize*8)}var currAbsArg=Math.abs(currArg);var prefix="";if(next==100||next==105){if(argSize==8&&i64Math)argText=i64Math.stringify(origArg[0],origArg[1],null);else argText=reSign(currArg,8*argSize,1).toString(10)}else if(next==117){if(argSize==8&&i64Math)argText=i64Math.stringify(origArg[0],origArg[1],true);else argText=unSign(currArg,8*argSize,1).toString(10);currArg=Math.abs(currArg)}else if(next==111){argText=(flagAlternative?"0":"")+currAbsArg.toString(8)}else if(next==120||next==88){prefix=flagAlternative&&currArg!=0?"0x":"";if(argSize==8&&i64Math){if(origArg[1]){argText=(origArg[1]>>>0).toString(16);var lower=(origArg[0]>>>0).toString(16);while(lower.length<8)lower="0"+lower;argText+=lower}else{argText=(origArg[0]>>>0).toString(16)}}else if(currArg<0){currArg=-currArg;argText=(currAbsArg-1).toString(16);var buffer=[];for(var i=0;i<argText.length;i++){buffer.push((15-parseInt(argText[i],16)).toString(16))}argText=buffer.join("");while(argText.length<argSize*2)argText="f"+argText}else{argText=currAbsArg.toString(16)}if(next==88){prefix=prefix.toUpperCase();argText=argText.toUpperCase()}}else if(next==112){if(currAbsArg===0){argText="(nil)"}else{prefix="0x";argText=currAbsArg.toString(16)}}if(precisionSet){while(argText.length<precision){argText="0"+argText}}if(currArg>=0){if(flagAlwaysSigned){prefix="+"+prefix}else if(flagPadSign){prefix=" "+prefix}}if(argText.charAt(0)=="-"){prefix="-"+prefix;argText=argText.substr(1)}while(prefix.length+argText.length<width){if(flagLeftAlign){argText+=" "}else{if(flagZeroPad){argText="0"+argText}else{prefix=" "+prefix}}}argText=prefix+argText;argText.split("").forEach((function(chr){ret.push(chr.charCodeAt(0))}));break};case"f":case"F":case"e":case"E":case"g":case"G":{var currArg=getNextArg("double");var argText;if(isNaN(currArg)){argText="nan";flagZeroPad=false}else if(!isFinite(currArg)){argText=(currArg<0?"-":"")+"inf";flagZeroPad=false}else{var isGeneral=false;var effectivePrecision=Math.min(precision,20);if(next==103||next==71){isGeneral=true;precision=precision||1;var exponent=parseInt(currArg.toExponential(effectivePrecision).split("e")[1],10);if(precision>exponent&&exponent>=-4){next=(next==103?"f":"F").charCodeAt(0);precision-=exponent+1}else{next=(next==103?"e":"E").charCodeAt(0);precision--}effectivePrecision=Math.min(precision,20)}if(next==101||next==69){argText=currArg.toExponential(effectivePrecision);if(/[eE][-+]\d$/.test(argText)){argText=argText.slice(0,-1)+"0"+argText.slice(-1)}}else if(next==102||next==70){argText=currArg.toFixed(effectivePrecision);if(currArg===0&&__reallyNegative(currArg)){argText="-"+argText}}var parts=argText.split("e");if(isGeneral&&!flagAlternative){while(parts[0].length>1&&parts[0].indexOf(".")!=-1&&(parts[0].slice(-1)=="0"||parts[0].slice(-1)==".")){parts[0]=parts[0].slice(0,-1)}}else{if(flagAlternative&&argText.indexOf(".")==-1)parts[0]+=".";while(precision>effectivePrecision++)parts[0]+="0"}argText=parts[0]+(parts.length>1?"e"+parts[1]:"");if(next==69)argText=argText.toUpperCase();if(currArg>=0){if(flagAlwaysSigned){argText="+"+argText}else if(flagPadSign){argText=" "+argText}}}while(argText.length<width){if(flagLeftAlign){argText+=" "}else{if(flagZeroPad&&(argText[0]=="-"||argText[0]=="+")){argText=argText[0]+"0"+argText.slice(1)}else{argText=(flagZeroPad?"0":" ")+argText}}}if(next<97)argText=argText.toUpperCase();argText.split("").forEach((function(chr){ret.push(chr.charCodeAt(0))}));break};case"s":{var arg=getNextArg("i8*");var argLength=arg?_strlen(arg):"(null)".length;if(precisionSet)argLength=Math.min(argLength,precision);if(!flagLeftAlign){while(argLength<width--){ret.push(32)}}if(arg){for(var i=0;i<argLength;i++){ret.push(HEAPU8[arg++>>0])}}else{ret=ret.concat(intArrayFromString("(null)".substr(0,argLength),true))}if(flagLeftAlign){while(argLength<width--){ret.push(32)}}break};case"c":{if(flagLeftAlign)ret.push(getNextArg("i8"));while(--width>0){ret.push(32)}if(!flagLeftAlign)ret.push(getNextArg("i8"));break};case"n":{var ptr=getNextArg("i32*");HEAP32[ptr>>2]=ret.length;break};case"%":{ret.push(curr);break};default:{for(var i=startTextIndex;i<textIndex+2;i++){ret.push(HEAP8[i>>0])}}}textIndex+=2}else{ret.push(curr);textIndex+=1}}return ret}function _fprintf(stream,format,varargs){var result=__formatString(format,varargs);var stack=Runtime.stackSave();var ret=_fwrite(allocate(result,"i8",ALLOC_STACK),1,result.length,stream);Runtime.stackRestore(stack);return ret}function _printf(format,varargs){var result=__formatString(format,varargs);var string=intArrayToString(result);if(string[string.length-1]==="\n")string=string.substr(0,string.length-1);Module.print(string);return result.length}Module["_i64Add"]=_i64Add;function _fputs(s,stream){var fd=_fileno(stream);return _write(fd,s,_strlen(s))}function _fputc(c,stream){var chr=unSign(c&255);HEAP8[_fputc.ret>>0]=chr;var fd=_fileno(stream);var ret=_write(fd,_fputc.ret,1);if(ret==-1){var streamObj=FS.getStreamFromPtr(stream);if(streamObj)streamObj.error=true;return-1}else{return chr}}var _stdout=allocate(1,"i32*",ALLOC_STATIC);function _puts(s){var result=Pointer_stringify(s);var string=result.substr(0);if(string[string.length-1]==="\n")string=string.substr(0,string.length-1);Module.print(string);return result.length}var _floor=Math_floor;function _ogvjs_callback_init_audio(channels,rate){Module.audioFormat={channels:channels,rate:rate};Module.loadedMetadata=true}var _llvm_sqrt_f64=Math_sqrt;function __exit(status){Module["exit"](status)}function _exit(status){__exit(status)}var _sin=Math_sin;var _atan=Math_atan;var _BDtoIHigh=true;var _ceil=Math_ceil;var _sinf=Math_sin;function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest);return dest}Module["_memcpy"]=_memcpy;var _log=Math_log;var _cos=Math_cos;var _llvm_pow_f64=Math_pow;function _ogvjs_callback_audio(buffers,channels,sampleCount){var HEAPU32=Module.HEAPU32;var HEAPF32=Module.HEAPF32;var outputBuffers=[];if(buffers!==0){var inPtr,inArray,outArray,i;for(var channel=0;channel<channels;channel++){inPtr=HEAPU32[buffers/4+channel];inArray=HEAPF32.subarray(inPtr/4,inPtr/4+sampleCount);outArray=new Float32Array(inArray);outputBuffers.push(outArray)}}Module.audioBuffer=outputBuffers}function ___errno_location(){return ___errno_state}var _BItoD=true;function _sbrk(bytes){var self=_sbrk;if(!self.called){DYNAMICTOP=alignMemoryPage(DYNAMICTOP);self.called=true;assert(Runtime.dynamicAlloc);self.alloc=Runtime.dynamicAlloc;Runtime.dynamicAlloc=(function(){abort("cannot dynamically allocate, sbrk now has control")})}var ret=DYNAMICTOP;if(bytes!=0){var success=self.alloc(bytes);if(!success)return-1>>>0}return ret}var _exp=Math_exp;function _time(ptr){var ret=Date.now()/1e3|0;if(ptr){HEAP32[ptr>>2]=ret}return ret}___errno_state=Runtime.staticAlloc(4);HEAP32[___errno_state>>2]=0;_fputc.ret=allocate([0],"i8",ALLOC_STATIC);STACK_BASE=STACKTOP=Runtime.alignMemory(STATICTOP);staticSealed=true;STACK_MAX=STACK_BASE+TOTAL_STACK;DYNAMIC_BASE=DYNAMICTOP=Runtime.alignMemory(STACK_MAX);assert(DYNAMIC_BASE<TOTAL_MEMORY,"TOTAL_MEMORY not big enough for stack");var cttz_i8=allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0],"i8",ALLOC_DYNAMIC);function invoke_iiiii(index,a1,a2,a3,a4){try{return Module["dynCall_iiiii"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}function invoke_vi(index,a1){try{Module["dynCall_vi"](index,a1)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}function invoke_vii(index,a1,a2){try{Module["dynCall_vii"](index,a1,a2)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}function invoke_ii(index,a1){try{return Module["dynCall_ii"](index,a1)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}function invoke_viii(index,a1,a2,a3){try{Module["dynCall_viii"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}function invoke_iiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){try{return Module["dynCall_iiiiiiiii"](index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}function invoke_iii(index,a1,a2){try{return Module["dynCall_iii"](index,a1,a2)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}function invoke_iiiiii(index,a1,a2,a3,a4,a5){try{return Module["dynCall_iiiiii"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}Module.asmGlobalArg={"Math":Math,"Int8Array":Int8Array,"Int16Array":Int16Array,"Int32Array":Int32Array,"Uint8Array":Uint8Array,"Uint16Array":Uint16Array,"Uint32Array":Uint32Array,"Float32Array":Float32Array,"Float64Array":Float64Array,"NaN":NaN,"Infinity":Infinity};Module.asmLibraryArg={"abort":abort,"assert":assert,"invoke_iiiii":invoke_iiiii,"invoke_vi":invoke_vi,"invoke_vii":invoke_vii,"invoke_ii":invoke_ii,"invoke_viii":invoke_viii,"invoke_iiiiiiiii":invoke_iiiiiiiii,"invoke_iii":invoke_iii,"invoke_iiiiii":invoke_iiiiii,"_sin":_sin,"_exp":_exp,"_cosf":_cosf,"_send":_send,"___setErrNo":___setErrNo,"_floor":_floor,"_pwrite":_pwrite,"_llvm_sqrt_f64":_llvm_sqrt_f64,"_llvm_pow_f64":_llvm_pow_f64,"__reallyNegative":__reallyNegative,"_fabsf":_fabsf,"_sbrk":_sbrk,"_atan":_atan,"_sinf":_sinf,"_fileno":_fileno,"_sysconf":_sysconf,"_ogvjs_callback_init_audio":_ogvjs_callback_init_audio,"_cos":_cos,"_puts":_puts,"_printf":_printf,"_ogvjs_callback_audio":_ogvjs_callback_audio,"_log":_log,"_write":_write,"_emscripten_memcpy_big":_emscripten_memcpy_big,"___errno_location":___errno_location,"_fputc":_fputc,"__exit":__exit,"_abort":_abort,"_fwrite":_fwrite,"_time":_time,"_fprintf":_fprintf,"_ceil":_ceil,"__formatString":__formatString,"_fputs":_fputs,"_exit":_exit,"STACKTOP":STACKTOP,"STACK_MAX":STACK_MAX,"tempDoublePtr":tempDoublePtr,"ABORT":ABORT,"cttz_i8":cttz_i8};// EMSCRIPTEN_START_ASM
+var asm=(function(global,env,buffer) {
+"use asm";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.tempDoublePtr|0;var l=env.ABORT|0;var m=env.cttz_i8|0;var n=0;var o=0;var p=0;var q=0;var r=global.NaN,s=global.Infinity;var t=0,u=0,v=0,w=0,x=0.0,y=0,z=0,A=0,B=0.0;var C=0;var D=0;var E=0;var F=0;var G=0;var H=0;var I=0;var J=0;var K=0;var L=0;var M=global.Math.floor;var N=global.Math.abs;var O=global.Math.sqrt;var P=global.Math.pow;var Q=global.Math.cos;var R=global.Math.sin;var S=global.Math.tan;var T=global.Math.acos;var U=global.Math.asin;var V=global.Math.atan;var W=global.Math.atan2;var X=global.Math.exp;var Y=global.Math.log;var Z=global.Math.ceil;var _=global.Math.imul;var $=global.Math.min;var aa=global.Math.clz32;var ba=env.abort;var ca=env.assert;var da=env.invoke_iiiii;var ea=env.invoke_vi;var fa=env.invoke_vii;var ga=env.invoke_ii;var ha=env.invoke_viii;var ia=env.invoke_iiiiiiiii;var ja=env.invoke_iii;var ka=env.invoke_iiiiii;var la=env._sin;var ma=env._exp;var na=env._cosf;var oa=env._send;var pa=env.___setErrNo;var qa=env._floor;var ra=env._pwrite;var sa=env._llvm_sqrt_f64;var ta=env._llvm_pow_f64;var ua=env.__reallyNegative;var va=env._fabsf;var wa=env._sbrk;var xa=env._atan;var ya=env._sinf;var za=env._fileno;var Aa=env._sysconf;var Ba=env._ogvjs_callback_init_audio;var Ca=env._cos;var Da=env._puts;var Ea=env._printf;var Fa=env._ogvjs_callback_audio;var Ga=env._log;var Ha=env._write;var Ia=env._emscripten_memcpy_big;var Ja=env.___errno_location;var Ka=env._fputc;var La=env.__exit;var Ma=env._abort;var Na=env._fwrite;var Oa=env._time;var Pa=env._fprintf;var Qa=env._ceil;var Ra=env.__formatString;var Sa=env._fputs;var Ta=env._exit;var Ua=0.0;
+// EMSCRIPTEN_START_FUNCS
+function bb(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+15&-16;return b|0}function cb(){return i|0}function db(a){a=a|0;i=a}function eb(a,b){a=a|0;b=b|0;i=a;j=b}function fb(a,b){a=a|0;b=b|0;if(!n){n=a;o=b}}function gb(b){b=b|0;a[k>>0]=a[b>>0];a[k+1>>0]=a[b+1>>0];a[k+2>>0]=a[b+2>>0];a[k+3>>0]=a[b+3>>0]}function hb(b){b=b|0;a[k>>0]=a[b>>0];a[k+1>>0]=a[b+1>>0];a[k+2>>0]=a[b+2>>0];a[k+3>>0]=a[b+3>>0];a[k+4>>0]=a[b+4>>0];a[k+5>>0]=a[b+5>>0];a[k+6>>0]=a[b+6>>0];a[k+7>>0]=a[b+7>>0]}function ib(a){a=a|0;C=a}function jb(){return C|0}function kb(b){b=b|0;var d=0;c[b>>2]=0;c[b+4>>2]=0;c[b+8>>2]=0;c[b+12>>2]=0;d=xd(256)|0;c[b+8>>2]=d;c[b+12>>2]=d;a[d>>0]=0;c[b+16>>2]=256;return}function lb(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0;do if(f>>>0<=32){g=b+16|0;h=c[g>>2]|0;i=b+12|0;j=c[i>>2]|0;if((c[b>>2]|0)<(h+-4|0))k=j;else{if(!j)return;if((h|0)>2147483391)break;j=b+8|0;l=Ad(c[j>>2]|0,h+256|0)|0;if(!l)break;c[j>>2]=l;c[g>>2]=(c[g>>2]|0)+256;g=l+(c[b>>2]|0)|0;c[i>>2]=g;k=g}g=c[8+(f<<2)>>2]&e;l=b+4|0;j=c[l>>2]|0;h=j+f|0;a[k>>0]=d[k>>0]|0|g<<j;do if((((h|0)>7?(a[(c[i>>2]|0)+1>>0]=g>>>(8-(c[l>>2]|0)|0),(h|0)>15):0)?(a[(c[i>>2]|0)+2>>0]=g>>>(16-(c[l>>2]|0)|0),(h|0)>23):0)?(a[(c[i>>2]|0)+3>>0]=g>>>(24-(c[l>>2]|0)|0),(h|0)>31):0){j=c[l>>2]|0;if(!j){a[(c[i>>2]|0)+4>>0]=0;break}else{a[(c[i>>2]|0)+4>>0]=g>>>(32-j|0);break}}while(0);g=(h|0)/8|0;c[b>>2]=(c[b>>2]|0)+g;c[i>>2]=(c[i>>2]|0)+g;c[l>>2]=h&7;return}while(0);k=c[b+8>>2]|0;if(k)yd(k);c[b>>2]=0;c[b+4>>2]=0;c[b+8>>2]=0;c[b+12>>2]=0;c[b+16>>2]=0;return}function mb(a){a=a|0;var b=0;b=c[a+8>>2]|0;if(b)yd(b);c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0;c[a+16>>2]=0;return}function nb(a,b,d){a=a|0;b=b|0;d=d|0;c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0;c[a+12>>2]=b;c[a+8>>2]=b;c[a+16>>2]=d;return}function ob(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;if(b>>>0>32){e=-1;return e|0}f=c[8+(b<<2)>>2]|0;g=c[a+4>>2]|0;h=g+b|0;b=c[a>>2]|0;i=c[a+16>>2]|0;if((b|0)>=(i+-4|0)){if((b|0)>(i-(h+7>>3)|0)){e=-1;return e|0}if(!h){e=0;return e|0}}i=c[a+12>>2]|0;a=(d[i>>0]|0)>>>g;if((h|0)>8){b=(d[i+1>>0]|0)<<8-g|a;if((h|0)>16){j=(d[i+2>>0]|0)<<16-g|b;if((h|0)>24){k=(d[i+3>>0]|0)<<24-g|j;if((h|0)<33|(g|0)==0)l=k;else l=(d[i+4>>0]|0)<<32-g|k}else l=j}else l=b}else l=a;e=l&f;return e|0}function pb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=a+4|0;e=(c[d>>2]|0)+b|0;b=c[a>>2]|0;f=c[a+16>>2]|0;if((b|0)>(f-(e+7>>3)|0)){c[a+12>>2]=0;c[a>>2]=f;g=1;c[d>>2]=g;return}else{f=(e|0)/8|0;h=a+12|0;c[h>>2]=(c[h>>2]|0)+f;c[a>>2]=b+f;g=e&7;c[d>>2]=g;return}}function qb(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;do if(b>>>0>32){e=a;f=a+4|0;g=c[a+16>>2]|0}else{h=c[8+(b<<2)>>2]|0;i=a+4|0;j=c[i>>2]|0;k=j+b|0;l=c[a>>2]|0;m=c[a+16>>2]|0;if((l|0)>=(m+-4|0)){if((l|0)>(m-(k+7>>3)|0)){e=a;f=i;g=m;break}if(!k){n=0;return n|0}}m=a+12|0;o=c[m>>2]|0;p=(d[o>>0]|0)>>>j;if((k|0)>8){q=(d[o+1>>0]|0)<<8-j|p;if((k|0)>16){r=(d[o+2>>0]|0)<<16-j|q;if((k|0)>24){s=(d[o+3>>0]|0)<<24-j|r;if((k|0)<33|(j|0)==0)t=s;else t=(d[o+4>>0]|0)<<32-j|s}else t=r}else t=q}else t=p;p=(k|0)/8|0;c[m>>2]=o+p;c[a>>2]=l+p;c[i>>2]=k&7;n=t&h;return n|0}while(0);c[a+12>>2]=0;c[e>>2]=g;c[f>>2]=1;n=-1;return n|0}function rb(a){a=a|0;return (((c[a+4>>2]|0)+7|0)/8|0)+(c[a>>2]|0)|0}function sb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,h=0,i=0.0,j=0,k=0.0,l=0,m=0.0,n=0.0,o=0,p=0.0,q=0,r=0,s=0,t=0;d=(b|0)/4|0;e=xd(d<<2)|0;f=xd(d+b<<2)|0;h=b>>1;i=+(b|0);j=~~+td(+Y(+i)*1.4426950408889634);c[a+4>>2]=j;c[a>>2]=b;c[a+8>>2]=f;c[a+12>>2]=e;if((b|0)<=3){k=4.0/i;l=a+16|0;g[l>>2]=k;return}m=3.141592653589793/+(b|0);n=3.141592653589793/+(b<<1|0);o=0;do{p=m*+(o<<2|0);q=o<<1;g[f+(q<<2)>>2]=+Q(+p);r=q|1;g[f+(r<<2)>>2]=-+R(+p);p=n*+(r|0);r=q+h|0;g[f+(r<<2)>>2]=+Q(+p);g[f+(r+1<<2)>>2]=+R(+p);o=o+1|0}while((o|0)<(d|0));d=(b|0)/8|0;o=(b|0)>7;if(!o){k=4.0/i;l=a+16|0;g[l>>2]=k;return}n=3.141592653589793/+(b|0);h=0;do{m=n*+(h<<2|2|0);r=(h<<1)+b|0;g[f+(r<<2)>>2]=+Q(+m)*.5;g[f+(r+1<<2)>>2]=+R(+m)*-.5;h=h+1|0}while((h|0)<(d|0));h=(1<<j+-1)+-1|0;f=1<<j+-2;if(o)s=0;else{k=4.0/i;l=a+16|0;g[l>>2]=k;return}do{o=f;j=0;b=0;while(1){r=((o&s|0)==0?0:1<<b)|j;b=b+1|0;o=f>>b;if(!o){t=r;break}else j=r}j=s<<1;c[e+(j<<2)>>2]=(h&~t)+-1;c[e+((j|1)<<2)>>2]=t;s=s+1|0}while((s|0)<(d|0));k=4.0/i;l=a+16|0;g[l>>2]=k;return}function tb(a){a=a|0;var b=0;if(!a)return;b=c[a+8>>2]|0;if(b)yd(b);b=c[a+12>>2]|0;if(b)yd(b);c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0;c[a+16>>2]=0;return}function ub(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0.0,t=0,u=0;e=c[a>>2]|0;f=e>>1;h=e>>2;e=d+(f+h<<2)|0;i=a+8|0;j=c[i>>2]|0;k=j+(h<<2)|0;l=k;m=b+(f+-7<<2)|0;n=e;while(1){o=n;n=n+-16|0;p=m+8|0;q=l+12|0;r=l+8|0;g[n>>2]=-(+g[p>>2]*+g[q>>2])-+g[r>>2]*+g[m>>2];g[o+-12>>2]=+g[q>>2]*+g[m>>2]-+g[r>>2]*+g[p>>2];p=m+24|0;r=l+4|0;q=m+16|0;g[o+-8>>2]=-(+g[p>>2]*+g[r>>2])-+g[l>>2]*+g[q>>2];g[o+-4>>2]=+g[r>>2]*+g[q>>2]-+g[l>>2]*+g[p>>2];m=m+-32|0;if(m>>>0<b>>>0)break;else l=l+16|0}l=d+(f<<2)|0;m=k;k=b+(f+-8<<2)|0;n=e;while(1){p=k+16|0;q=m+-4|0;r=k+24|0;o=m+-8|0;g[n>>2]=+g[o>>2]*+g[r>>2]+ +g[q>>2]*+g[p>>2];g[n+4>>2]=+g[o>>2]*+g[p>>2]-+g[q>>2]*+g[r>>2];r=m+-12|0;m=m+-16|0;q=k+8|0;g[n+8>>2]=+g[m>>2]*+g[q>>2]+ +g[r>>2]*+g[k>>2];g[n+12>>2]=+g[m>>2]*+g[k>>2]-+g[r>>2]*+g[q>>2];k=k+-32|0;if(k>>>0<b>>>0)break;else n=n+16|0}Ec(c[a+4>>2]|0,j,l,f);Fc(c[a>>2]|0,c[i>>2]|0,c[a+12>>2]|0,d);a=(c[i>>2]|0)+(f<<2)|0;f=d;i=e;j=e;while(1){n=a+4|0;b=f+4|0;g[i+-4>>2]=+g[n>>2]*+g[f>>2]-+g[a>>2]*+g[b>>2];g[j>>2]=-(+g[a>>2]*+g[f>>2]+ +g[n>>2]*+g[b>>2]);b=f+8|0;n=a+12|0;k=f+12|0;m=a+8|0;g[i+-8>>2]=+g[n>>2]*+g[b>>2]-+g[m>>2]*+g[k>>2];g[j+4>>2]=-(+g[m>>2]*+g[b>>2]+ +g[n>>2]*+g[k>>2]);k=f+16|0;n=a+20|0;b=f+20|0;m=a+16|0;g[i+-12>>2]=+g[n>>2]*+g[k>>2]-+g[m>>2]*+g[b>>2];i=i+-16|0;g[j+8>>2]=-(+g[m>>2]*+g[k>>2]+ +g[n>>2]*+g[b>>2]);b=f+24|0;n=a+28|0;k=f+28|0;m=a+24|0;g[i>>2]=+g[n>>2]*+g[b>>2]-+g[m>>2]*+g[k>>2];g[j+12>>2]=-(+g[m>>2]*+g[b>>2]+ +g[n>>2]*+g[k>>2]);f=f+32|0;if(f>>>0>=i>>>0)break;else{a=a+32|0;j=j+16|0}}j=d+(h<<2)|0;h=e;d=j;a=j;do{j=d;d=d+-16|0;s=+g[h+-4>>2];g[j+-4>>2]=s;g[a>>2]=-s;s=+g[h+-8>>2];g[j+-8>>2]=s;g[a+4>>2]=-s;s=+g[h+-12>>2];h=h+-16|0;g[j+-12>>2]=s;g[a+8>>2]=-s;s=+g[h>>2];g[d>>2]=s;g[a+12>>2]=-s;a=a+16|0}while(a>>>0<h>>>0);t=e;u=e;while(1){e=u;u=u+-16|0;c[u>>2]=c[t+12>>2];c[e+-12>>2]=c[t+8>>2];c[e+-8>>2]=c[t+4>>2];c[e+-4>>2]=c[t>>2];if(u>>>0<=l>>>0)break;else t=t+16|0}return}function vb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0,B=0.0,C=0,D=0,E=0,F=0,G=0,H=0,I=0;e=i;f=c[a>>2]|0;h=f>>1;j=f>>2;k=f>>3;l=i;i=i+((1*(f<<2)|0)+15&-16)|0;m=l+(h<<2)|0;n=h+j|0;o=b+(n<<2)|0;p=a+8|0;q=c[p>>2]|0;r=q+(h<<2)|0;if((k|0)>0){s=(k+-1|0)>>>1;t=s<<1;u=h+-2-t|0;v=n+-4-(s<<2)|0;s=r;w=0;x=o;y=b+(n+1<<2)|0;while(1){n=x;x=x+-16|0;z=s;s=s+-8|0;A=+g[y>>2]+ +g[n+-8>>2];B=+g[y+8>>2]+ +g[x>>2];n=z+-4|0;g[l+(w+h<<2)>>2]=+g[s>>2]*A+B*+g[n>>2];g[l+((w|1)+h<<2)>>2]=+g[s>>2]*B-+g[n>>2]*A;w=w+2|0;if((w|0)>=(k|0))break;else y=y+16|0}C=u;D=q+(u<<2)|0;E=t+2|0;F=b+(v<<2)|0}else{C=h;D=r;E=0;F=o}o=b+4|0;r=h-k|0;if((E|0)<(r|0)){v=(h+-1-E-k|0)>>>1;k=v<<1;t=E+k|0;u=(v<<2)+5|0;v=-2-k|0;k=D;y=E;w=F;F=o;while(1){s=k;k=k+-8|0;A=+g[w+-8>>2]-+g[F>>2];w=w+-16|0;B=+g[w>>2]-+g[F+8>>2];x=s+-4|0;g[l+(y+h<<2)>>2]=+g[k>>2]*A+B*+g[x>>2];g[l+((y|1)+h<<2)>>2]=+g[k>>2]*B-+g[x>>2]*A;y=y+2|0;if((y|0)>=(r|0))break;else F=F+16|0}G=q+(C+v<<2)|0;H=t+2|0;I=b+(u<<2)|0}else{G=D;H=E;I=o}if((H|0)<(h|0)){o=G;G=H;H=b+(f<<2)|0;f=I;while(1){I=o;o=o+-8|0;A=-+g[H+-8>>2]-+g[f>>2];H=H+-16|0;B=-+g[H>>2]-+g[f+8>>2];b=I+-4|0;g[l+(G+h<<2)>>2]=+g[o>>2]*A+B*+g[b>>2];g[l+((G|1)+h<<2)>>2]=+g[o>>2]*B-+g[b>>2]*A;G=G+2|0;if((G|0)>=(h|0))break;else f=f+16|0}}Ec(c[a+4>>2]|0,q,m,h);Fc(c[a>>2]|0,c[p>>2]|0,c[a+12>>2]|0,l);if((j|0)<=0){i=e;return}m=a+16|0;a=(c[p>>2]|0)+(h<<2)|0;p=0;q=l;l=d+(h<<2)|0;while(1){l=l+-4|0;h=q+4|0;f=a+4|0;g[d+(p<<2)>>2]=(+g[f>>2]*+g[h>>2]+ +g[a>>2]*+g[q>>2])*+g[m>>2];g[l>>2]=(+g[f>>2]*+g[q>>2]-+g[a>>2]*+g[h>>2])*+g[m>>2];p=p+1|0;if((p|0)==(j|0))break;else{a=a+8|0;q=q+8|0}}i=e;return}function wb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;d=c[a>>2]|0;if((d|0)==1)return;e=c[a+4>>2]|0;f=c[a+8>>2]|0;a=c[f+4>>2]|0;if((a|0)<=0)return;g=a+1|0;h=d+-1|0;i=d;j=0;k=d;l=1;while(1){m=c[f+(g-j<<2)>>2]|0;n=(d|0)/(k|0)|0;k=(k|0)/(m|0)|0;o=_(n,k)|0;i=i-(_(n,m+-1|0)|0)|0;p=1-l|0;do if((m|0)==4){q=i+n|0;r=e+(h+i<<2)|0;s=e+(h+q<<2)|0;t=e+(h+n+q<<2)|0;if(!p){Gc(n,k,b,e,r,s,t);u=0;break}else{Gc(n,k,e,b,r,s,t);u=p;break}}else if((m|0)==2){t=e+(h+i<<2)|0;if(!p){Hc(n,k,b,e,t);u=0;break}else{Hc(n,k,e,b,t);u=p;break}}else{t=e+(h+i<<2)|0;if(!(((n|0)==1?l:p)|0)){Ic(n,m,k,o,b,b,b,e,e,t);u=1;break}else{Ic(n,m,k,o,e,e,e,b,b,t);u=0;break}}while(0);j=j+1|0;if((j|0)==(a|0)){v=u;break}else l=u}if((d|0)>0&(v|0)!=1)w=0;else return;do{c[b+(w<<2)>>2]=c[e+(w<<2)>>2];w=w+1|0}while((w|0)!=(d|0));return}function xb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0;c[a>>2]=b;d=zd(b*3|0,4)|0;c[a+4>>2]=d;e=zd(32,4)|0;c[a+8>>2]=e;if((b|0)==1)return;a=e+8|0;f=-1;h=0;i=b;j=0;a:while(1){k=f+1|0;if((k|0)<4)l=c[360+(k<<2)>>2]|0;else l=j+2|0;m=(l|0)!=2;n=h;o=i;while(1){p=n+1|0;q=o;o=(o|0)/(l|0)|0;if((q|0)!=(_(o,l)|0)){f=k;h=n;i=q;j=l;continue a}c[e+(n+2<<2)>>2]=l;q=(n|0)==0;if(!(m|q)){if((n|0)>=1){r=1;do{s=p-r|0;c[e+(s+2<<2)>>2]=c[e+(s+1<<2)>>2];r=r+1|0}while((r|0)!=(p|0))}c[a>>2]=2}if((o|0)==1){t=q;u=p;v=n;break a}else n=p}}c[e>>2]=b;c[e+4>>2]=u;w=6.2831854820251465/+(b|0);if(!((v|0)>0&(t^1)))return;t=b+1|0;u=0;a=0;l=1;while(1){j=c[e+(a+2<<2)>>2]|0;i=l;l=_(j,l)|0;h=(b|0)/(l|0)|0;if((j|0)>1){f=(h|0)>2;n=j+-1|0;j=u;o=0;m=0;while(1){m=m+i|0;x=+(m|0)*w;if(f){y=0.0;k=j;r=2;while(1){y=y+1.0;z=x*y;g[d+(k+b<<2)>>2]=+Q(+z);g[d+(t+k<<2)>>2]=+R(+z);r=r+2|0;if((r|0)>=(h|0))break;else k=k+2|0}}o=o+1|0;if((o|0)==(n|0))break;else j=j+h|0}A=(_(h,n)|0)+u|0}else A=u;a=a+1|0;if((a|0)==(v|0))break;else u=A}return}function yb(a){a=a|0;var b=0;if(!a)return;b=c[a+4>>2]|0;if(b)yd(b);b=c[a+8>>2]|0;if(b)yd(b);c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;return}function zb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=b;e=d+112|0;do{c[d>>2]=0;d=d+4|0}while((d|0)<(e|0));c[b+64>>2]=a;c[b+76>>2]=0;c[b+68>>2]=0;if(!(c[a>>2]|0))return 0;a=zd(1,72)|0;c[b+104>>2]=a;g[a+4>>2]=-9999.0;d=b+4|0;b=a+12|0;e=a+40|0;a=0;while(1)if((a|0)!=7){f=zd(1,20)|0;c[b+(a<<2)>>2]=f;kb(f);f=a+1|0;if((f|0)==15)break;else{a=f;continue}}else{c[e>>2]=d;kb(d);a=8;continue}return 0}function Ab(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0;d=b+7&-8;b=a+72|0;e=c[b>>2]|0;f=a+76|0;g=a+68|0;h=c[g>>2]|0;if((e+d|0)<=(c[f>>2]|0)){i=h;j=e;k=i+j|0;l=j+d|0;c[b>>2]=l;return k|0}if(h){m=xd(8)|0;n=a+80|0;c[n>>2]=(c[n>>2]|0)+e;e=a+84|0;c[m+4>>2]=c[e>>2];c[m>>2]=h;c[e>>2]=m}c[f>>2]=d;f=xd(d)|0;c[g>>2]=f;c[b>>2]=0;i=f;j=0;k=i+j|0;l=j+d|0;c[b>>2]=l;return k|0}function Bb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;b=a+84|0;d=c[b>>2]|0;if(d){e=d;do{d=e;e=c[e+4>>2]|0;yd(c[d>>2]|0);yd(d)}while((e|0)!=0)}e=a+80|0;d=c[e>>2]|0;if(!d){f=a+72|0;c[f>>2]=0;c[b>>2]=0;return}g=a+68|0;h=a+76|0;c[g>>2]=Ad(c[g>>2]|0,(c[h>>2]|0)+d|0)|0;c[h>>2]=(c[h>>2]|0)+(c[e>>2]|0);c[e>>2]=0;f=a+72|0;c[f>>2]=0;c[b>>2]=0;return}function Cb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0;b=c[a+104>>2]|0;d=a+84|0;e=c[d>>2]|0;if(e){f=e;do{e=f;f=c[f+4>>2]|0;yd(c[e>>2]|0);yd(e)}while((f|0)!=0)}f=a+80|0;e=c[f>>2]|0;g=a+68|0;h=c[g>>2]|0;if(!e)i=h;else{j=a+76|0;k=Ad(h,(c[j>>2]|0)+e|0)|0;c[g>>2]=k;c[j>>2]=(c[j>>2]|0)+(c[f>>2]|0);c[f>>2]=0;i=k}c[a+72>>2]=0;c[d>>2]=0;if(i)yd(i);if(!b){l=a;m=l+112|0;do{c[l>>2]=0;l=l+4|0}while((l|0)<(m|0));return 0}else n=0;while(1){i=b+12+(n<<2)|0;mb(c[i>>2]|0);if((n|0)==7){n=8;continue}yd(c[i>>2]|0);n=n+1|0;if((n|0)==15)break}yd(b);l=a;m=l+112|0;do{c[l>>2]=0;l=l+4|0}while((l|0)<(m|0));return 0}function Db(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;if(!a)return;b=c[a+4>>2]|0;d=(b|0)!=0;if(d)e=c[b+28>>2]|0;else e=0;f=c[a+104>>2]|0;g=(f|0)!=0;if(g){h=c[f>>2]|0;if(h){Ib(h);yd(c[f>>2]|0)}h=f+12|0;i=c[h>>2]|0;if(i){tb(c[i>>2]|0);yd(c[c[h>>2]>>2]|0);yd(c[h>>2]|0)}h=f+16|0;i=c[h>>2]|0;if(i){tb(c[i>>2]|0);yd(c[c[h>>2]>>2]|0);yd(c[h>>2]|0)}h=f+48|0;i=c[h>>2]|0;if(i){if((e|0)!=0?(j=e+16|0,(c[j>>2]|0)>0):0){k=e+800|0;Wa[c[(c[328+(c[k>>2]<<2)>>2]|0)+16>>2]&7](c[i>>2]|0);if((c[j>>2]|0)>1){l=1;do{Wa[c[(c[328+(c[k+(l<<2)>>2]<<2)>>2]|0)+16>>2]&7](c[(c[h>>2]|0)+(l<<2)>>2]|0);l=l+1|0}while((l|0)<(c[j>>2]|0))}m=c[h>>2]|0}else m=i;yd(m)}m=f+52|0;i=c[m>>2]|0;if(i){if((e|0)!=0?(h=e+20|0,(c[h>>2]|0)>0):0){j=e+1312|0;Wa[c[(c[336+(c[j>>2]<<2)>>2]|0)+16>>2]&7](c[i>>2]|0);if((c[h>>2]|0)>1){l=1;do{Wa[c[(c[336+(c[j+(l<<2)>>2]<<2)>>2]|0)+16>>2]&7](c[(c[m>>2]|0)+(l<<2)>>2]|0);l=l+1|0}while((l|0)<(c[h>>2]|0))}n=c[m>>2]|0}else n=i;yd(n)}n=f+56|0;i=c[n>>2]|0;if(i){if((e|0)!=0?(m=e+28|0,(c[m>>2]|0)>0):0){Qb(i);if((c[m>>2]|0)>1){e=1;do{Qb((c[n>>2]|0)+(e*52|0)|0);e=e+1|0}while((e|0)<(c[m>>2]|0))}o=c[n>>2]|0}else o=i;yd(o)}o=c[f+60>>2]|0;if(o)Nb(o);Cc(f+80|0);yb(f+20|0);yb(f+32|0)}o=a+8|0;i=c[o>>2]|0;if(i){if(d?(d=b+4|0,b=c[d>>2]|0,(b|0)>0):0){n=i;m=b;b=0;while(1){e=c[n+(b<<2)>>2]|0;if(!e)p=m;else{yd(e);p=c[d>>2]|0}e=b+1|0;if((e|0)>=(p|0))break;n=c[o>>2]|0;m=p;b=e}q=c[o>>2]|0}else q=i;yd(q);q=c[a+12>>2]|0;if(q)yd(q)}if(g){g=c[f+64>>2]|0;if(g)yd(g);g=c[f+68>>2]|0;if(g)yd(g);g=c[f+72>>2]|0;if(g)yd(g);yd(f)}f=a;a=f+112|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(a|0));return}function Eb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;if(Jc(a,b,0)|0){Db(a);d=1;return d|0}b=c[a+4>>2]|0;e=c[a+104>>2]|0;if((b|0)==0|(e|0)==0){d=0;return d|0}f=c[b+28>>2]|0;if(!f){d=0;return d|0}b=c[f+3656>>2]|0;g=c[f+4>>2]>>b+1;c[a+48>>2]=g;c[a+20>>2]=g>>b;c[a+24>>2]=-1;b=a+56|0;c[b>>2]=-1;c[b+4>>2]=-1;c[b+8>>2]=-1;c[b+12>>2]=-1;c[a+32>>2]=0;a=e+128|0;c[a>>2]=-1;c[a+4>>2]=-1;d=0;return d|0}function Fb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0;d=c[a+4>>2]|0;e=c[d+28>>2]|0;f=c[a+104>>2]|0;h=c[e+3656>>2]|0;if(!b){i=-131;return i|0}j=a+20|0;k=c[j>>2]|0;l=a+24|0;m=c[l>>2]|0;if(!((k|0)<=(m|0)|(m|0)==-1)){i=-131;return i|0}n=a+40|0;o=c[n>>2]|0;p=a+36|0;c[p>>2]=o;q=c[b+28>>2]|0;c[n>>2]=q;c[a+44>>2]=-1;r=a+64|0;s=r;t=c[s>>2]|0;u=c[s+4>>2]|0;if(!((t|0)==-1&(u|0)==-1)){s=Id(t|0,u|0,1,0)|0;u=C;t=b+56|0;v=c[t>>2]|0;w=c[t+4>>2]|0;if((s|0)==(v|0)&(u|0)==(w|0)){x=s;y=u}else{z=v;A=w;B=6}}else{w=b+56|0;z=c[w>>2]|0;A=c[w+4>>2]|0;B=6}if((B|0)==6){B=a+56|0;c[B>>2]=-1;c[B+4>>2]=-1;B=f+128|0;c[B>>2]=-1;c[B+4>>2]=-1;x=z;y=A}A=r;c[A>>2]=x;c[A+4>>2]=y;do if(c[b>>2]|0){y=h+1|0;A=c[e+(q<<2)>>2]>>y;x=c[e>>2]>>y;r=c[e+4>>2]>>y;y=c[b+88>>2]|0;z=a+72|0;B=z;w=Id(c[B>>2]|0,c[B+4>>2]|0,y|0,((y|0)<0)<<31>>31|0)|0;y=z;c[y>>2]=w;c[y+4>>2]=C;y=c[b+92>>2]|0;w=a+80|0;z=w;B=Id(c[z>>2]|0,c[z+4>>2]|0,y|0,((y|0)<0)<<31>>31|0)|0;y=w;c[y>>2]=B;c[y+4>>2]=C;y=c[b+96>>2]|0;B=a+88|0;w=B;z=Id(c[w>>2]|0,c[w+4>>2]|0,y|0,((y|0)<0)<<31>>31|0)|0;y=B;c[y>>2]=z;c[y+4>>2]=C;y=c[b+100>>2]|0;z=a+96|0;B=z;w=Id(c[B>>2]|0,c[B+4>>2]|0,y|0,((y|0)<0)<<31>>31|0)|0;y=z;c[y>>2]=w;c[y+4>>2]=C;y=a+48|0;w=c[y>>2]|0;z=(w|0)==0;B=z?r:0;v=z?0:r;z=d+4|0;if((c[z>>2]|0)>0){u=f+4|0;s=a+8|0;t=(r|0)/2|0;D=(x|0)/2|0;E=t-D|0;F=(x|0)>0;G=D+t|0;D=x+-1|0;H=(A|0)>0;I=f+8|0;J=(r|0)>0;K=r+-1|0;L=t+B+((x|0)/-2|0)|0;t=o;M=q;N=0;while(1){O=(M|0)!=0;a:do if(!t){P=Jb((c[u>>2]|0)-h|0)|0;Q=c[(c[s>>2]|0)+(N<<2)>>2]|0;R=c[(c[b>>2]|0)+(N<<2)>>2]|0;if(!O){if(F)S=0;else{T=R;U=Q;break}while(1){V=Q+(S+B<<2)|0;g[V>>2]=+g[P+(S<<2)>>2]*+g[R+(S<<2)>>2]+ +g[P+(D-S<<2)>>2]*+g[V>>2];S=S+1|0;if((S|0)==(x|0)){T=R;U=Q;break a}}}if(F){V=0;do{W=Q+(V+B<<2)|0;g[W>>2]=+g[P+(V<<2)>>2]*+g[R+(V+E<<2)>>2]+ +g[P+(D-V<<2)>>2]*+g[W>>2];V=V+1|0}while((V|0)!=(x|0));X=x}else X=0;if((X|0)<(G|0)){V=X;do{c[Q+(V+B<<2)>>2]=c[R+(V+E<<2)>>2];V=V+1|0}while((V|0)!=(G|0));T=R;U=Q}else{T=R;U=Q}}else if(O){V=Jb((c[I>>2]|0)-h|0)|0;P=c[(c[s>>2]|0)+(N<<2)>>2]|0;W=c[(c[b>>2]|0)+(N<<2)>>2]|0;if(J)Y=0;else{T=W;U=P;break}do{Z=P+(Y+B<<2)|0;g[Z>>2]=+g[V+(Y<<2)>>2]*+g[W+(Y<<2)>>2]+ +g[V+(K-Y<<2)>>2]*+g[Z>>2];Y=Y+1|0}while((Y|0)!=(r|0));T=W;U=P}else{P=Jb((c[u>>2]|0)-h|0)|0;W=c[(c[s>>2]|0)+(N<<2)>>2]|0;V=c[(c[b>>2]|0)+(N<<2)>>2]|0;if(F)_=0;else{T=V;U=W;break}do{Q=W+(L+_<<2)|0;g[Q>>2]=+g[P+(_<<2)>>2]*+g[V+(_<<2)>>2]+ +g[P+(D-_<<2)>>2]*+g[Q>>2];_=_+1|0}while((_|0)!=(x|0));T=V;U=W}while(0);if(H){O=0;do{c[U+(O+v<<2)>>2]=c[T+(O+A<<2)>>2];O=O+1|0}while((O|0)!=(A|0))}O=N+1|0;if((O|0)>=(c[z>>2]|0))break;t=c[p>>2]|0;M=c[n>>2]|0;N=O}$=c[y>>2]|0;aa=c[l>>2]|0}else{$=w;aa=m}c[y>>2]=($|0)==0?r:0;if((aa|0)==-1){c[l>>2]=v;c[j>>2]=v;ba=v;ca=v;break}else{c[l>>2]=B;N=(((c[e+(c[n>>2]<<2)>>2]|0)/4|0)+((c[e+(c[p>>2]<<2)>>2]|0)/4|0)>>h)+B|0;c[j>>2]=N;ba=N;ca=B;break}}else{ba=k;ca=m}while(0);m=f+128|0;f=m;k=c[f>>2]|0;aa=c[f+4>>2]|0;if((k|0)==-1&(aa|0)==-1){da=0;ea=0}else{f=((c[e+(c[n>>2]<<2)>>2]|0)/4|0)+((c[e+(c[p>>2]<<2)>>2]|0)/4|0)|0;$=Id(f|0,((f|0)<0)<<31>>31|0,k|0,aa|0)|0;da=$;ea=C}$=m;c[$>>2]=da;c[$+4>>2]=ea;$=a+56|0;m=$;aa=c[m>>2]|0;k=c[m+4>>2]|0;do if((aa|0)==-1&(k|0)==-1){m=b+48|0;f=c[m>>2]|0;T=c[m+4>>2]|0;if(!((f|0)==-1&(T|0)==-1)?(m=$,c[m>>2]=f,c[m+4>>2]=T,(ea|0)>(T|0)|(ea|0)==(T|0)&da>>>0>f>>>0):0){m=Ed(da|0,ea|0,f|0,T|0)|0;T=(m|0)<0?0:m;if(!(c[b+44>>2]|0)){m=ca+(T>>h)|0;c[l>>2]=(m|0)>(ba|0)?ba:m;break}else{m=ba-ca<<h;c[j>>2]=ba-(((T|0)>(m|0)?m:T)>>h);break}}}else{T=((c[e+(c[n>>2]<<2)>>2]|0)/4|0)+((c[e+(c[p>>2]<<2)>>2]|0)/4|0)|0;m=Id(T|0,((T|0)<0)<<31>>31|0,aa|0,k|0)|0;T=C;f=$;c[f>>2]=m;c[f+4>>2]=T;f=b+48|0;U=c[f>>2]|0;_=c[f+4>>2]|0;if(!((U|0)==-1&(_|0)==-1|(m|0)==(U|0)&(T|0)==(_|0))){if(((T|0)>(_|0)|(T|0)==(_|0)&m>>>0>U>>>0?(f=Ed(m|0,T|0,U|0,_|0)|0,(f|0)!=0):0)?(c[b+44>>2]|0)!=0:0){T=ba-ca<<h;m=(f|0)>(T|0)?T:f;c[j>>2]=ba-(((m|0)<0?0:m)>>h)}m=$;c[m>>2]=U;c[m+4>>2]=_}}while(0);if(!(c[b+44>>2]|0)){i=0;return i|0}c[a+32>>2]=1;i=0;return i|0}function Gb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;d=c[a+24>>2]|0;if((d|0)<=-1){e=0;return e|0}f=c[a+20>>2]|0;if((f|0)<=(d|0)){e=0;return e|0}if(b){g=c[(c[a+4>>2]|0)+4>>2]|0;if((g|0)>0){h=a+8|0;i=a+12|0;j=0;do{c[(c[i>>2]|0)+(j<<2)>>2]=(c[(c[h>>2]|0)+(j<<2)>>2]|0)+(d<<2);j=j+1|0}while((j|0)<(g|0));k=i}else k=a+12|0;c[b>>2]=c[k>>2]}e=f-d|0;return e|0}function Hb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=a+24|0;e=c[d>>2]|0;if((b|0)!=0?(e+b|0)>(c[a+20>>2]|0):0){f=-131;return f|0}c[d>>2]=e+b;f=0;return f|0}function Ib(a){a=a|0;tb(a+16|0);yd(c[a+48>>2]|0);yd(c[a+64>>2]|0);yd(c[a+80>>2]|0);yd(c[a+96>>2]|0);yd(c[a+112>>2]|0);yd(c[a+128>>2]|0);yd(c[a+144>>2]|0);yd(c[a+36>>2]|0);yd(c[a+152>>2]|0);yd(c[a+160>>2]|0);Fd(a|0,0,180)|0;return}function Jb(a){a=a|0;return c[376+(a<<2)>>2]|0}function Kb(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;var i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;i=(f|0)!=0;j=i?e:0;e=i?h:0;h=c[376+(c[b+(j<<2)>>2]<<2)>>2]|0;i=c[376+(c[b+(e<<2)>>2]<<2)>>2]|0;b=c[d+(f<<2)>>2]|0;f=c[d+(j<<2)>>2]|0;j=c[d+(e<<2)>>2]|0;e=(b|0)/4|0;d=(f|0)/4|0;k=e-d|0;l=(f|0)/2|0;f=((b|0)/2|0)+e+((j|0)/-4|0)|0;m=(j|0)/2|0;n=f+m|0;if((k|0)>0){Fd(a|0,0,e-d<<2|0)|0;o=k}else o=0;if((o|0)<(k+l|0)){k=e+l-o-d|0;d=o;o=0;while(1){l=a+(d<<2)|0;g[l>>2]=+g[l>>2]*+g[h+(o<<2)>>2];o=o+1|0;if((o|0)==(k|0))break;else d=d+1|0}}if((j|0)>1){j=f+1|0;d=(n|0)>(j|0);k=f;o=m;do{o=o+-1|0;m=a+(k<<2)|0;g[m>>2]=+g[m>>2]*+g[i+(o<<2)>>2];k=k+1|0}while((k|0)<(n|0));p=d?n:j}else p=f;if((b|0)<=(p|0))return;Fd(a+(p<<2)|0,0,b-p<<2|0)|0;return}function Lb(a,b,d,e,f,h,i,j){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;i=+i;j=+j;var k=0.0,l=0,m=0.0,n=0,o=0.0,p=0.0,q=0.0,r=0,s=0,t=0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0;k=3.141592653589793/+(e|0);if((h|0)>0){e=0;do{l=f+(e<<2)|0;g[l>>2]=+Q(+(+g[l>>2]))*2.0;e=e+1|0}while((e|0)!=(h|0))}if((d|0)<=0)return;m=i;i=j;if((h|0)<=1){e=(h|0)==1;l=0;while(1){n=c[b+(l<<2)>>2]|0;j=+Q(+(+(n|0)*k))*2.0;if(e){o=(j-+g[f>>2])*.5;p=4.0-j*j;q=o*o}else{p=2.0-j;q=(j+2.0)*.25}j=+X(+((m/+O(+(q+p*.25))-i)*.1151292473077774));r=a+(l<<2)|0;g[r>>2]=+g[r>>2]*j;r=l+1|0;if((c[b+(r<<2)>>2]|0)==(n|0)){s=r;while(1){t=a+(s<<2)|0;g[t>>2]=+g[t>>2]*j;t=s+1|0;if((c[b+(t<<2)>>2]|0)==(n|0))s=t;else{u=t;break}}}else u=r;if((u|0)<(d|0))l=u;else break}return}u=((h+-2&-2)+3|0)==(h|0);l=f+(h+-1<<2)|0;e=0;while(1){s=c[b+(e<<2)>>2]|0;p=+Q(+(+(s|0)*k))*2.0;n=1;q=.5;j=.5;while(1){o=(p-+g[f+(n+-1<<2)>>2])*j;v=(p-+g[f+(n<<2)>>2])*q;n=n+2|0;if((n|0)>=(h|0)){w=o;x=v;break}else{q=v;j=o}}if(u){j=(p-+g[l>>2])*w;y=x*x*(4.0-p*p);z=j*j}else{y=x*x*(2.0-p);z=w*w*(p+2.0)}j=+X(+((m/+O(+(z+y))-i)*.1151292473077774));n=a+(e<<2)|0;g[n>>2]=+g[n>>2]*j;n=e+1|0;if((c[b+(n<<2)>>2]|0)==(s|0)){r=n;while(1){t=a+(r<<2)|0;g[t>>2]=+g[t>>2]*j;t=r+1|0;if((c[b+(t<<2)>>2]|0)==(s|0))r=t;else{A=t;break}}}else A=n;if((A|0)<(d|0))e=A;else break}return}function Mb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0;d=(a|0)!=0;if(d?(e=c[a+64>>2]|0,(e|0)!=0):0){f=c[e+104>>2]|0;g=c[e+4>>2]|0;if(!g){h=f;i=1;j=0;k=0;l=0}else{h=f;i=1;j=1;k=c[g+28>>2]|0;l=g}}else{h=0;i=0;j=0;k=0;l=0}g=d?a+4|0:0;if(!(d&((k|0)!=0&(j&(i&(h|0)!=0))))){m=-136;return m|0}Bb(a);nb(g,c[b>>2]|0,c[b+4>>2]|0);if(qb(g,1)|0){m=-135;return m|0}i=qb(g,c[h+44>>2]|0)|0;if((i|0)==-1){m=-136;return m|0}c[a+40>>2]=i;h=k+32+(i<<2)|0;i=c[h>>2]|0;if(!i){m=-136;return m|0}j=c[i>>2]|0;i=a+28|0;c[i>>2]=j;do if(j){c[a+24>>2]=qb(g,1)|0;d=qb(g,1)|0;c[a+32>>2]=d;if((d|0)==-1){m=-136;return m|0}else{n=c[i>>2]|0;break}}else{c[a+24>>2]=0;c[a+32>>2]=0;n=0}while(0);i=b+16|0;g=c[i+4>>2]|0;j=a+48|0;c[j>>2]=c[i>>2];c[j+4>>2]=g;g=b+24|0;j=c[g+4>>2]|0;i=a+56|0;c[i>>2]=c[g>>2];c[i+4>>2]=j;c[a+44>>2]=c[b+12>>2];b=a+36|0;c[b>>2]=c[k+(n<<2)>>2];n=l+4|0;c[a>>2]=Ab(a,c[n>>2]<<2)|0;if((c[n>>2]|0)>0){l=0;do{j=Ab(a,c[b>>2]<<2)|0;c[(c[a>>2]|0)+(l<<2)>>2]=j;l=l+1|0}while((l|0)<(c[n>>2]|0))}n=c[(c[h>>2]|0)+12>>2]|0;m=$a[c[(c[352+(c[k+288+(n<<2)>>2]<<2)>>2]|0)+16>>2]&15](a,c[k+544+(n<<2)>>2]|0)|0;return m|0}function Nb(a){a=a|0;if(!a)return;yd(a);return}function Ob(a){a=a|0;if(a)yd(a);return}function Pb(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var h=0,i=0,j=0.0,k=0.0,l=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0,B=0.0,C=0.0,D=0,E=0,F=0.0,G=0;h=a;i=h+48|0;do{c[h>>2]=0;h=h+4|0}while((h|0)<(i|0));h=c[d>>2]|0;c[a+36>>2]=h;d=~~(+td(+Y(+(+(h|0)*8.0))*1.4426950408889634)+-1.0);i=a+32|0;c[i>>2]=d;j=+(f|0);k=+(e|0);l=+(1<<d+1|0);d=~~(l*(+Y(+(j*.25*.5/k))*1.4426950216293335+-5.965784072875977)-+(h|0));c[a+28>>2]=d;c[a+40>>2]=1-d+~~(l*(+Y(+((+(e|0)+.25)*j*.5/k))*1.4426950216293335+-5.965784072875977)+.5);d=e<<2;h=xd(d)|0;c[a+16>>2]=h;m=xd(d)|0;c[a+20>>2]=m;n=xd(d)|0;c[a+24>>2]=n;o=a+4|0;c[o>>2]=b;c[a>>2]=e;c[a+44>>2]=f;p=a+48|0;g[p>>2]=1.0;do if((f|0)>=26e3){if((f|0)<38e3){g[p>>2]=.9399999976158142;break}if((f|0)>46e3)g[p>>2]=1.274999976158142}else g[p>>2]=0.0;while(0);j=k*2.0;l=+(f|0);p=(e|0)>0;q=0;r=0;a:while(1){s=p^1;t=q;while(1){u=t;t=t+1|0;v=~~+td(j*+X(+(+(t|0)*.08664337545633316+2.7488713472395148))/l);if(!((v|0)<=(r|0)|s)){w=t;x=v;y=u;break}if((t|0)>=87){z=r;break a}}A=+g[408+(y<<2)>>2];B=(+g[408+(w<<2)>>2]-A)/+(x-r|0);t=r-x|0;s=r-e|0;u=r-(t>>>0>s>>>0?t:s)|0;C=A;s=r;while(1){g[h+(s<<2)>>2]=C+100.0;s=s+1|0;if((s|0)==(u|0))break;else C=C+B}if((w|0)<87){p=(u|0)<(e|0);q=w;r=u}else{z=u;break}}if((z|0)<(e|0)){r=z;do{c[h+(r<<2)>>2]=c[h+(r+-1<<2)>>2];r=r+1|0}while((r|0)!=(e|0))}r=(e|0)>0;if(r){h=(f|0)/(e<<1|0)|0;f=c[b+120>>2]|0;z=b+124|0;w=b+116|0;q=b+112|0;p=1;x=0;y=-99;while(1){s=_(h,x)|0;B=+(s|0);C=+V(+(+(_(s,s)|0)*1.8499999754340024e-08))*2.240000009536743+ +V(+(B*7.399999885819852e-04))*13.100000381469727+B*9.999999747378752e-05;b:do if((f+y|0)<(x|0)){B=C-+g[q>>2];s=y;while(1){t=_(s,h)|0;A=+(t|0);if(!(+V(+(A*7.399999885819852e-04))*13.100000381469727+A*9.999999747378752e-05+ +V(+(+(_(t,t)|0)*1.8499999754340024e-08))*2.240000009536743<B)){D=s;break b}t=s+1|0;if((f+t|0)<(x|0))s=t;else{D=t;break}}}else D=y;while(0);c:do if((p|0)>(e|0))E=p;else{u=(c[z>>2]|0)+x|0;s=p;while(1){if((s|0)>=(u|0)?(t=_(s,h)|0,B=+(t|0),A=+V(+(B*7.399999885819852e-04))*13.100000381469727+B*9.999999747378752e-05+ +V(+(+(_(t,t)|0)*1.8499999754340024e-08))*2.240000009536743,!(A<+g[w>>2]+C)):0){E=s;break c}t=s+1|0;if((s|0)<(e|0))s=t;else{E=t;break}}}while(0);c[n+(x<<2)>>2]=(D<<16)+-65537+E;x=x+1|0;if((x|0)==(e|0))break;else{p=E;y=D}}if(r){C=l*.5;A=+(1<<(c[i>>2]|0)+1|0);i=0;do{c[m+(i<<2)>>2]=~~(A*(+Y(+(C*(+(i|0)+.25)/k))*1.4426950216293335+-5.965784072875977)+.5);i=i+1|0}while((i|0)!=(e|0));F=C}else G=19}else G=19;if((G|0)==19)F=l*.5;c[a+8>>2]=Kc(b+36|0,F/k,e,+g[b+24>>2],+g[b+28>>2])|0;b=xd(12)|0;c[a+12>>2]=b;c[b>>2]=xd(d)|0;c[b+4>>2]=xd(d)|0;c[b+8>>2]=xd(d)|0;if(!r)return;r=c[o>>2]|0;o=c[b>>2]|0;d=c[b+4>>2]|0;a=c[b+8>>2]|0;b=0;do{k=+Y(+((+(b|0)+.5)*l/j))*2.885390043258667+-11.931568145751953;F=k<0.0?0.0:k;k=F>=16.0?16.0:F;G=~~k;F=k-+(G|0);k=1.0-F;i=G+1|0;g[o+(b<<2)>>2]=+g[r+132+(i<<2)>>2]*F+ +g[r+132+(G<<2)>>2]*k;g[d+(b<<2)>>2]=+g[r+200+(i<<2)>>2]*F+ +g[r+200+(G<<2)>>2]*k;g[a+(b<<2)>>2]=+g[r+268+(i<<2)>>2]*F+ +g[r+268+(G<<2)>>2]*k;b=b+1|0}while((b|0)!=(e|0));return}function Qb(a){a=a|0;var b=0,d=0,e=0,f=0;if(!a)return;b=c[a+16>>2]|0;if(b)yd(b);b=c[a+20>>2]|0;if(b)yd(b);b=c[a+24>>2]|0;if(b)yd(b);b=a+8|0;d=c[b>>2]|0;if(d){e=d;d=0;while(1){yd(c[c[e+(d<<2)>>2]>>2]|0);yd(c[(c[(c[b>>2]|0)+(d<<2)>>2]|0)+4>>2]|0);yd(c[(c[(c[b>>2]|0)+(d<<2)>>2]|0)+8>>2]|0);yd(c[(c[(c[b>>2]|0)+(d<<2)>>2]|0)+12>>2]|0);yd(c[(c[(c[b>>2]|0)+(d<<2)>>2]|0)+16>>2]|0);yd(c[(c[(c[b>>2]|0)+(d<<2)>>2]|0)+20>>2]|0);yd(c[(c[(c[b>>2]|0)+(d<<2)>>2]|0)+24>>2]|0);yd(c[(c[(c[b>>2]|0)+(d<<2)>>2]|0)+28>>2]|0);yd(c[(c[b>>2]|0)+(d<<2)>>2]|0);f=d+1|0;if((f|0)==17)break;e=c[b>>2]|0;d=f}yd(c[b>>2]|0)}b=a+12|0;d=c[b>>2]|0;if(d){yd(c[d>>2]|0);yd(c[(c[b>>2]|0)+4>>2]|0);yd(c[(c[b>>2]|0)+8>>2]|0);yd(c[b>>2]|0)}b=a;a=b+52|0;do{c[b>>2]=0;b=b+4|0}while((b|0)<(a|0));return}function Rb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,h=0,j=0,k=0,l=0,m=0;e=i;f=c[a>>2]|0;h=i;i=i+((1*(f<<2)|0)+15&-16)|0;j=a+24|0;Lc(f,c[j>>2]|0,b,d,140.0,-1);k=(f|0)>0;if(k){l=0;do{g[h+(l<<2)>>2]=+g[b+(l<<2)>>2]-+g[d+(l<<2)>>2];l=l+1|0}while((l|0)!=(f|0))}l=a+4|0;Lc(f,c[j>>2]|0,h,d,0.0,c[(c[l>>2]|0)+128>>2]|0);if(k)m=0;else{i=e;return}do{j=h+(m<<2)|0;g[j>>2]=+g[b+(m<<2)>>2]-+g[j>>2];m=m+1|0}while((m|0)!=(f|0));if(!k){i=e;return}k=c[l>>2]|0;l=0;do{m=d+(l<<2)|0;b=~~(+g[m>>2]+.5);j=(b|0)>39?39:b;g[m>>2]=+g[k+336+(((j|0)<0?0:j)<<2)>>2]+ +g[h+(l<<2)>>2];l=l+1|0}while((l|0)!=(f|0));i=e;return}function Sb(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=+e;f=+f;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0.0,q=0,r=0.0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0,F=0,G=0,H=0,I=0,J=0,K=0.0,L=0.0,M=0,N=0,O=0,P=0;h=i;j=c[a>>2]|0;k=a+40|0;l=c[k>>2]|0;m=i;i=i+((1*(l<<2)|0)+15&-16)|0;n=a+4|0;o=c[n>>2]|0;p=+g[o+4>>2]+f;if((l|0)>0){q=0;do{g[m+(q<<2)>>2]=-9999.0;q=q+1|0}while((q|0)<(l|0))}f=+g[o+8>>2];r=p<f?f:p;q=(j|0)>0;if(q){s=c[a+16>>2]|0;t=0;do{g[d+(t<<2)>>2]=+g[s+(t<<2)>>2]+r;t=t+1|0}while((t|0)!=(j|0));t=c[a+8>>2]|0;r=+g[o+496>>2]-e;if(q){q=c[a+20>>2]|0;o=a+32|0;s=a+36|0;u=a+28|0;v=0;while(1){w=c[q+(v<<2)>>2]|0;x=v;e=+g[b+(v<<2)>>2];a:while(1){y=x;while(1){z=y+1|0;if((z|0)>=(j|0)){A=0;B=z;C=y;D=e;break a}if((c[q+(z<<2)>>2]|0)!=(w|0)){A=1;B=z;C=y;D=e;break a}p=+g[b+(z<<2)>>2];if(p>e){x=z;e=p;continue a}else y=z}}if(D+6.0>+g[d+(C<<2)>>2]?(x=w>>c[o>>2],y=(x|0)>16?16:x,x=c[s>>2]|0,z=~~((r+D+-30.0)*.10000000149011612),E=(z|0)<0?0:z,z=c[(c[t+(((y|0)<0?0:y)<<2)>>2]|0)+(((E|0)>7?7:E)<<2)>>2]|0,E=~~+g[z+4>>2],e=+g[z>>2],y=~~e,(y|0)<(E|0)):0){F=y;y=~~((e+-16.0)*+(x|0)-+(x>>1|0)+ +((c[q+(C<<2)>>2]|0)-(c[u>>2]|0)|0));do{if((y|0)>0?(e=+g[z+(F+2<<2)>>2]+D,G=m+(y<<2)|0,+g[G>>2]<e):0)g[G>>2]=e;y=y+x|0;F=F+1|0}while((F|0)<(E|0)&(y|0)<(l|0))}if(A)v=B;else{H=s;break}}}else I=7}else I=7;if((I|0)==7)H=a+36|0;I=c[H>>2]|0;Mc(m,I,l);l=c[a>>2]|0;b:do if((l|0)>1){H=c[a+20>>2]|0;s=c[H>>2]|0;B=c[a+28>>2]|0;v=(c[n>>2]|0)+32|0;A=1;u=s;C=0;q=s-(I>>1)-B|0;while(1){D=+g[m+(q<<2)>>2];s=((c[H+(A<<2)>>2]|0)+u>>1)-B|0;r=+g[v>>2];e=D>r?r:D;c:do if((q|0)<(s|0)){t=q;D=e;while(1){o=D==-9999.0;b=t;while(1){j=b+1|0;r=+g[m+(j<<2)>>2];if(r>-9999.0){if(o|r<D){J=j;K=r;break}}else if(o){J=j;K=r;break}if((j|0)<(s|0))b=j;else{L=D;M=j;break c}}if((J|0)<(s|0)){t=J;D=K}else{L=K;M=J;break}}}else{L=e;M=q}while(0);s=M+B|0;d:do if((C|0)>=(l|0)|(u|0)>(s|0))N=C;else{t=C;while(1){b=d+(t<<2)|0;if(+g[b>>2]<L)g[b>>2]=L;b=t+1|0;if((b|0)>=(l|0)){N=b;break d}if((c[H+(b<<2)>>2]|0)>(s|0)){N=b;break}else t=b}}while(0);s=N+1|0;if((s|0)>=(l|0)){O=N;break b}A=s;u=c[H+(N<<2)>>2]|0;C=N;q=M}}else O=0;while(0);L=+g[m+((c[k>>2]|0)+-1<<2)>>2];if((O|0)<(l|0))P=O;else{i=h;return}do{O=d+(P<<2)|0;if(+g[O>>2]<L)g[O>>2]=L;P=P+1|0}while((P|0)!=(l|0));i=h;return}function Tb(a,b,d,e,f,h,i){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;i=i|0;var j=0,k=0,l=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0;j=c[a>>2]|0;k=c[a+4>>2]|0;l=+g[k+12+(e<<2)>>2];if((j|0)<=0)return;m=c[(c[a+12>>2]|0)+(e<<2)>>2]|0;n=k+108|0;k=(e|0)==1;o=+g[a+48>>2];p=o*.005;q=o*.0003;a=0;do{o=+g[m+(a<<2)>>2]+ +g[b+(a<<2)>>2];r=+g[n>>2];s=o>r?r:o;o=+g[d+(a<<2)>>2]+l;g[f+(a<<2)>>2]=s<o?o:s;if(k){o=s-+g[i+(a<<2)>>2];s=o+17.200000762939453;if(o>-17.200000762939453){o=1.0-p*s;if(o<0.0)t=9.999999747378752e-05;else t=o}else t=1.0-q*s;e=h+(a<<2)|0;g[e>>2]=+g[e>>2]*t}a=a+1|0}while((a|0)!=(j|0));return}function Ub(a,b,d,e,f,j,k,l,m){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0,o=0,p=0,q=0,r=0,s=0.0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,O=0,P=0,Q=0,R=0,S=0.0,T=0,U=0.0,V=0,W=0,X=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0.0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0;n=i;o=c[d>>2]|0;p=d+4|0;d=c[p>>2]|0;if(!(c[d+500>>2]|0))q=16;else q=c[d+508>>2]|0;r=c[b+132+((c[d>>2]|0)*60|0)+(a<<2)>>2]|0;s=+h[760+(c[b+252+(a<<2)>>2]<<3)>>3];d=m<<2;t=i;i=i+((1*d|0)+15&-16)|0;u=i;i=i+((1*d|0)+15&-16)|0;v=i;i=i+((1*d|0)+15&-16)|0;w=i;i=i+((1*d|0)+15&-16)|0;x=i;i=i+((1*d|0)+15&-16)|0;y=e+1156|0;z=+h[((o|0)>1e3?832:760)+(c[b+312+(a<<2)>>2]<<3)>>3];a=_(d,q)|0;b=i;i=i+((1*a|0)+15&-16)|0;c[t>>2]=b;A=i;i=i+((1*a|0)+15&-16)|0;c[u>>2]=A;B=i;i=i+((1*a|0)+15&-16)|0;c[v>>2]=B;C=i;i=i+((1*a|0)+15&-16)|0;c[w>>2]=C;if((m|0)>1?(c[t+4>>2]=b+(q<<2),c[u+4>>2]=A+(q<<2),c[v+4>>2]=B+(q<<2),c[w+4>>2]=C+(q<<2),(m|0)!=2):0){C=2;do{B=c[u>>2]|0;A=c[v>>2]|0;b=c[w>>2]|0;D=_(C,q)|0;c[t+(C<<2)>>2]=(c[t>>2]|0)+(D<<2);c[u+(C<<2)>>2]=B+(D<<2);c[v+(C<<2)>>2]=A+(D<<2);c[w+(C<<2)>>2]=b+(D<<2);C=C+1|0}while((C|0)!=(m|0))}C=c[y>>2]|0;if((o|0)>0){D=c[w>>2]|0;b=(m|0)>0;A=~q;B=0;E=~o;while(1){F=~((E|0)>(A|0)?E:A);G=o-B|0;H=(q|0)>(G|0)?G:q;Jd(x|0,k|0,d|0)|0;Fd(D|0,0,a|0)|0;if(b){G=(H|0)>0;I=r-B|0;J=0;do{K=c[j+(J<<2)>>2]|0;L=K+(B<<2)|0;if(!(c[x+(J<<2)>>2]|0)){if(G){M=c[v+(J<<2)>>2]|0;O=c[t+(J<<2)>>2]|0;P=c[u+(J<<2)>>2]|0;Q=c[w+(J<<2)>>2]|0;R=0;do{g[M+(R<<2)>>2]=1.000000013351432e-10;g[O+(R<<2)>>2]=0.0;g[P+(R<<2)>>2]=0.0;c[Q+(R<<2)>>2]=0;c[K+(R+B<<2)>>2]=0;R=R+1|0}while((R|0)!=(F|0))}}else{R=c[v+(J<<2)>>2]|0;if(G){Q=0;do{c[R+(Q<<2)>>2]=c[56400+(c[K+(Q+B<<2)>>2]<<2)>>2];Q=Q+1|0}while((Q|0)!=(F|0));Q=c[f+(J<<2)>>2]|0;K=c[w+(J<<2)>>2]|0;if(G){P=0;do{S=+N(+(+g[Q+(P+B<<2)>>2]));c[K+(P<<2)>>2]=!(S/+g[R+(P<<2)>>2]<((P|0)>=(I|0)?z:s))&1;P=P+1|0}while((P|0)!=(H|0));if(G){P=c[t+(J<<2)>>2]|0;K=u+(J<<2)|0;O=c[K>>2]|0;M=0;do{T=Q+(M+B<<2)|0;S=+g[T>>2];U=S*S;V=P+(M<<2)|0;g[V>>2]=U;g[O+(M<<2)>>2]=U;if(+g[T>>2]<0.0)g[V>>2]=-+g[V>>2];V=R+(M<<2)|0;U=+g[V>>2];g[V>>2]=U*U;M=M+1|0}while((M|0)!=(F|0));W=K;X=P}else Y=21}else Y=21}else Y=21;if((Y|0)==21){Y=0;W=u+(J<<2)|0;X=c[t+(J<<2)>>2]|0}+Nc(c[p>>2]|0,r,X,c[W>>2]|0,R,0,B,H,L)}J=J+1|0}while((J|0)!=(m|0))}J=c[y>>2]|0;if((J|0)>0){G=(H|0)>0;I=l-B|0;P=r-B|0;K=J;M=0;while(1){O=c[e+1160+(M<<2)>>2]|0;Q=c[e+2184+(M<<2)>>2]|0;V=c[j+(O<<2)>>2]|0;T=V+(B<<2)|0;Z=c[j+(Q<<2)>>2]|0;$=c[t+(O<<2)>>2]|0;aa=c[t+(Q<<2)>>2]|0;ba=c[u+(O<<2)>>2]|0;ca=c[u+(Q<<2)>>2]|0;da=c[v+(O<<2)>>2]|0;ea=c[v+(Q<<2)>>2]|0;fa=c[w+(O<<2)>>2]|0;ga=c[w+(Q<<2)>>2]|0;ha=x+(O<<2)|0;O=x+(Q<<2)|0;if((c[ha>>2]|0)==0?(c[O>>2]|0)==0:0)ia=K;else{c[O>>2]=1;c[ha>>2]=1;if(G){ha=0;do{do if((ha|0)<(I|0)){O=fa+(ha<<2)|0;Q=ga+(ha<<2)|0;if((c[O>>2]|0)==0?(c[Q>>2]|0)==0:0){do if((ha|0)>=(P|0)){ja=$+(ha<<2)|0;U=+g[ja>>2];ka=aa+(ha<<2)|0;S=+g[ka>>2];la=+N(+S)+ +N(+U);g[ba+(ha<<2)>>2]=la;if(S+U<0.0){g[ja>>2]=-la;ma=ka;break}else{g[ja>>2]=la;ma=ka;break}}else{ka=aa+(ha<<2)|0;ja=$+(ha<<2)|0;la=+g[ja>>2]+ +g[ka>>2];g[ja>>2]=la;g[ba+(ha<<2)>>2]=+N(+la);ma=ka}while(0);g[ca+(ha<<2)>>2]=0.0;g[ma>>2]=0.0;c[Q>>2]=1;c[Z+(ha+B<<2)>>2]=0;break}ka=$+(ha<<2)|0;la=+N(+(+g[ka>>2]));g[ka>>2]=+N(+(+g[aa+(ha<<2)>>2]))+la;ka=ba+(ha<<2)|0;g[ka>>2]=+g[ca+(ha<<2)>>2]+ +g[ka>>2];c[Q>>2]=1;c[O>>2]=1;ka=ha+B|0;ja=V+(ka<<2)|0;na=c[ja>>2]|0;oa=Z+(ka<<2)|0;ka=c[oa>>2]|0;if((((na|0)>-1?na:0-na|0)|0)>(((ka|0)>-1?ka:0-ka|0)|0)){pa=(na|0)>0?na-ka|0:ka-na|0;c[oa>>2]=pa;qa=c[ja>>2]|0;ra=pa}else{c[oa>>2]=(ka|0)>0?na-ka|0:ka-na|0;c[ja>>2]=ka;qa=ka;ra=c[oa>>2]|0}if((ra|0)>=(((qa|0)>-1?qa:0-qa|0)<<1|0)){c[oa>>2]=0-ra;c[ja>>2]=0-(c[ja>>2]|0)}}while(0);ja=da+(ha<<2)|0;oa=ea+(ha<<2)|0;la=+g[oa>>2]+ +g[ja>>2];g[oa>>2]=la;g[ja>>2]=la;ha=ha+1|0}while((ha|0)!=(F|0))}+Nc(c[p>>2]|0,r,$,ba,da,fa,B,H,T);ia=c[y>>2]|0}M=M+1|0;if((M|0)>=(ia|0)){sa=ia;break}else K=ia}}else sa=J;B=B+q|0;if((o|0)<=(B|0)){ta=sa;break}else E=E+q|0}}else ta=C;if((ta|0)>0){ua=ta;va=0}else{i=n;return}while(1){ta=k+(c[e+1160+(va<<2)>>2]<<2)|0;C=e+2184+(va<<2)|0;if((c[ta>>2]|0)==0?(c[k+(c[C>>2]<<2)>>2]|0)==0:0)wa=ua;else{c[ta>>2]=1;c[k+(c[C>>2]<<2)>>2]=1;wa=c[y>>2]|0}va=va+1|0;if((va|0)>=(wa|0))break;else ua=wa}i=n;return}function Vb(a){a=a|0;c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0;return}function Wb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;if(!a)return;b=c[a>>2]|0;if(b){d=a+8|0;e=c[d>>2]|0;if((e|0)>0){f=e;e=b;g=0;while(1){h=c[e+(g<<2)>>2]|0;if(!h)i=f;else{yd(h);i=c[d>>2]|0}h=g+1|0;if((h|0)>=(i|0))break;f=i;e=c[a>>2]|0;g=h}j=c[a>>2]|0}else j=b;yd(j)}j=c[a+4>>2]|0;if(j)yd(j);j=c[a+12>>2]|0;if(j)yd(j);c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0;return}function Xb(a){a=a|0;c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0;c[a+16>>2]=0;c[a+20>>2]=0;c[a+24>>2]=0;c[a+28>>2]=zd(1,3664)|0;return}function Yb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;b=c[a+28>>2]|0;if(!b){c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0;c[a+16>>2]=0;c[a+20>>2]=0;c[a+24>>2]=0;c[a+28>>2]=0;return}d=b+8|0;e=c[d>>2]|0;if((e|0)>0){f=e;e=0;while(1){g=c[b+32+(e<<2)>>2]|0;if(!g)h=f;else{yd(g);h=c[d>>2]|0}e=e+1|0;if((e|0)>=(h|0))break;else f=h}}h=b+12|0;f=c[h>>2]|0;if((f|0)>0){e=f;f=0;while(1){d=c[b+544+(f<<2)>>2]|0;if(!d)i=e;else{Wa[c[(c[352+(c[b+288+(f<<2)>>2]<<2)>>2]|0)+8>>2]&7](d);i=c[h>>2]|0}f=f+1|0;if((f|0)>=(i|0))break;else e=i}}i=b+16|0;e=c[i>>2]|0;if((e|0)>0){f=e;e=0;while(1){h=c[b+1056+(e<<2)>>2]|0;if(!h)j=f;else{Wa[c[(c[328+(c[b+800+(e<<2)>>2]<<2)>>2]|0)+12>>2]&7](h);j=c[i>>2]|0}e=e+1|0;if((e|0)>=(j|0))break;else f=j}}j=b+20|0;f=c[j>>2]|0;if((f|0)>0){e=f;f=0;while(1){i=c[b+1568+(f<<2)>>2]|0;if(!i)k=e;else{Wa[c[(c[336+(c[b+1312+(f<<2)>>2]<<2)>>2]|0)+12>>2]&7](i);k=c[j>>2]|0}f=f+1|0;if((f|0)>=(k|0))break;else e=k}}k=b+24|0;e=b+2848|0;if((c[k>>2]|0)>0){f=0;do{j=c[b+1824+(f<<2)>>2]|0;if(j)yc(j);j=c[e>>2]|0;if(j)zc(j+(f*56|0)|0);f=f+1|0}while((f|0)<(c[k>>2]|0))}k=c[e>>2]|0;if(k)yd(k);k=b+28|0;if((c[k>>2]|0)>0){e=0;do{Ob(c[b+2852+(e<<2)>>2]|0);e=e+1|0}while((e|0)<(c[k>>2]|0))}yd(b);c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0;c[a+16>>2]=0;c[a+20>>2]=0;c[a+24>>2]=0;c[a+28>>2]=0;return}function Zb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;f=i;i=i+32|0;g=f;h=f+20|0;if(!e){j=-133;i=f;return j|0}nb(g,c[e>>2]|0,c[e+4>>2]|0);k=qb(g,8)|0;a[h>>0]=0;a[h+1>>0]=0;a[h+2>>0]=0;a[h+3>>0]=0;a[h+4>>0]=0;a[h>>0]=qb(g,8)|0;a[h+1>>0]=qb(g,8)|0;a[h+2>>0]=qb(g,8)|0;a[h+3>>0]=qb(g,8)|0;a[h+4>>0]=qb(g,8)|0;a[h+5>>0]=qb(g,8)|0;if(wd(h,904,6)|0){j=-132;i=f;return j|0}if((k|0)==5){if(!(c[b+8>>2]|0)){j=-133;i=f;return j|0}if(!(c[d+12>>2]|0)){j=-133;i=f;return j|0}h=c[b+28>>2]|0;if(!h){j=-129;i=f;return j|0}l=qb(g,8)|0;m=h+24|0;c[m>>2]=l+1;a:do if((l|0)>=0){n=0;do{o=nc(g)|0;c[h+1824+(n<<2)>>2]=o;n=n+1|0;if(!o)break a}while((n|0)<(c[m>>2]|0));n=qb(g,6)|0;if((n|0)>=0){o=0;while(1){if(qb(g,16)|0)break a;if((o|0)<(n|0))o=o+1|0;else break}o=qb(g,6)|0;n=h+16|0;c[n>>2]=o+1;if((o|0)>=0){o=0;do{p=qb(g,16)|0;c[h+800+(o<<2)>>2]=p;if(p>>>0>1)break a;q=$a[c[(c[328+(p<<2)>>2]|0)+4>>2]&15](b,g)|0;c[h+1056+(o<<2)>>2]=q;o=o+1|0;if(!q)break a}while((o|0)<(c[n>>2]|0));n=qb(g,6)|0;o=h+20|0;c[o>>2]=n+1;if((n|0)>=0){n=0;do{q=qb(g,16)|0;c[h+1312+(n<<2)>>2]=q;if(q>>>0>2)break a;p=$a[c[(c[336+(q<<2)>>2]|0)+4>>2]&15](b,g)|0;c[h+1568+(n<<2)>>2]=p;n=n+1|0;if(!p)break a}while((n|0)<(c[o>>2]|0));o=qb(g,6)|0;n=h+12|0;c[n>>2]=o+1;if((o|0)>=0){o=(c[88]|0)+4|0;p=0;do{q=qb(g,16)|0;c[h+288+(p<<2)>>2]=q;if(q)break a;q=$a[c[o>>2]&15](b,g)|0;c[h+544+(p<<2)>>2]=q;p=p+1|0;if(!q)break a}while((p|0)<(c[n>>2]|0));p=qb(g,6)|0;o=h+8|0;c[o>>2]=p+1;if((p|0)>=0){p=0;do{q=h+32+(p<<2)|0;c[q>>2]=zd(1,16)|0;r=qb(g,1)|0;c[c[q>>2]>>2]=r;r=qb(g,16)|0;c[(c[q>>2]|0)+4>>2]=r;r=qb(g,16)|0;c[(c[q>>2]|0)+8>>2]=r;r=qb(g,8)|0;s=c[q>>2]|0;c[s+12>>2]=r;if((c[s+4>>2]|0)>0)break a;if((c[s+8>>2]|0)>0)break a;p=p+1|0;if((r|0)<0?1:(r|0)>=(c[n>>2]|0))break a}while((p|0)<(c[o>>2]|0));if((qb(g,1)|0)==1){j=0;i=f;return j|0}}}}}}}while(0);Yb(b);j=-133;i=f;return j|0}else if((k|0)==1){if(!(c[e+8>>2]|0)){j=-133;i=f;return j|0}e=b+8|0;if(c[e>>2]|0){j=-133;i=f;return j|0}h=c[b+28>>2]|0;if(!h){j=-129;i=f;return j|0}m=qb(g,32)|0;c[b>>2]=m;if(m){j=-134;i=f;return j|0}m=b+4|0;c[m>>2]=qb(g,8)|0;c[e>>2]=qb(g,32)|0;c[b+12>>2]=qb(g,32)|0;c[b+16>>2]=qb(g,32)|0;c[b+20>>2]=qb(g,32)|0;c[h>>2]=1<<(qb(g,4)|0);l=1<<(qb(g,4)|0);c[h+4>>2]=l;if((((c[e>>2]|0)>=1?(c[m>>2]|0)>=1:0)?(m=c[h>>2]|0,!((l|0)>8192|((m|0)<64|(l|0)<(m|0)))):0)?(qb(g,1)|0)==1:0){j=0;i=f;return j|0}Yb(b);j=-133;i=f;return j|0}else if((k|0)==3){if(!(c[b+8>>2]|0)){j=-133;i=f;return j|0}b=qb(g,32)|0;b:do if((b|0)>=0?(k=g+16|0,(b|0)<=((c[k>>2]|0)+-8|0)):0){m=zd(b+1|0,1)|0;c[d+12>>2]=m;if(b){l=m;m=b;while(1){m=m+-1|0;a[l>>0]=qb(g,8)|0;if(!m)break;else l=l+1|0}}l=qb(g,32)|0;if((l|0)>=0?(m=c[k>>2]|0,(l|0)<=(m-(rb(g)|0)>>2|0)):0){m=d+8|0;c[m>>2]=l;h=l+1|0;c[d>>2]=zd(h,4)|0;e=d+4|0;c[e>>2]=zd(h,4)|0;if((l|0)>0){l=0;do{h=qb(g,32)|0;if((h|0)<0){t=d;break b}o=c[k>>2]|0;if((h|0)>(o-(rb(g)|0)|0)){t=d;break b}c[(c[e>>2]|0)+(l<<2)>>2]=h;o=zd(h+1|0,1)|0;c[(c[d>>2]|0)+(l<<2)>>2]=o;if(h){o=c[(c[d>>2]|0)+(l<<2)>>2]|0;p=h;while(1){p=p+-1|0;a[o>>0]=qb(g,8)|0;if(!p)break;else o=o+1|0}}l=l+1|0}while((l|0)<(c[m>>2]|0))}if((qb(g,1)|0)==1){j=0;i=f;return j|0}else t=d}else u=28}else u=28;while(0);do if((u|0)==28)if(!d){j=-133;i=f;return j|0}else{t=d;break}while(0);u=c[t>>2]|0;if(u){g=d+8|0;b=c[g>>2]|0;if((b|0)>0){m=u;l=b;b=0;while(1){e=c[m+(b<<2)>>2]|0;if(!e)v=l;else{yd(e);v=c[g>>2]|0}e=b+1|0;if((e|0)>=(v|0))break;m=c[t>>2]|0;l=v;b=e}w=c[d>>2]|0}else w=u;yd(w)}w=c[d+4>>2]|0;if(w)yd(w);w=c[d+12>>2]|0;if(w)yd(w);c[d>>2]=0;c[d+4>>2]=0;c[d+8>>2]=0;c[d+12>>2]=0;j=-133;i=f;return j|0}else{j=-133;i=f;return j|0}return 0}function _b(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0.0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0.0,$a=0.0,ab=0,bb=0,cb=0.0,db=0,eb=0,fb=0,gb=0,hb=0,ib=0;f=i;i=i+4912|0;h=f+264|0;j=f+3856|0;k=f+4388|0;l=f;m=f+4128|0;n=f+4648|0;o=f+4908|0;p=f+4120|0;q=f+4116|0;r=f+3848|0;s=f+3852|0;t=f+4124|0;u=c[b+1296>>2]|0;v=c[b+1288>>2]|0;w=c[b+1284>>2]|0;x=(w|0)>0;if(x){y=0;do{c[j+(y<<2)>>2]=-200;y=y+1|0}while((y|0)!=(w|0));if(x){y=0;do{c[k+(y<<2)>>2]=-200;y=y+1|0}while((y|0)!=(w|0));if(x){Fd(l|0,0,w<<2|0)|0;y=0;do{c[m+(y<<2)>>2]=1;y=y+1|0}while((y|0)!=(w|0));if(x){Fd(n|0,-1,w<<2|0)|0;if((w|0)<=1){z=0;i=f;return z|0}x=v+-1|0;y=u+1112|0;A=w+-1|0;B=c[b>>2]|0;C=0;D=0;while(1){E=C;C=C+1|0;F=B;B=c[b+(C<<2)>>2]|0;G=h+(E*56|0)|0;H=G;I=H+56|0;do{c[H>>2]=0;H=H+4|0}while((H|0)<(I|0));c[G>>2]=F;c[h+(E*56|0)+4>>2]=B;J=(B|0)<(v|0)?B:x;if((J|0)<(F|0)){K=0;L=0;M=0;N=0;O=0;P=0;Q=0;R=0;S=0;T=0;U=0;V=0}else{W=F;X=0;Y=0;Z=0;$=0;aa=0;ba=0;ca=0;da=0;ea=0;fa=0;ga=0;ha=0;while(1){ia=+g[e+(W<<2)>>2];ja=~~(ia*7.314285755157471+1023.5);ka=(ja|0)>1023?1023:(ja|0)<0?0:ja;do if(ka)if(!(+g[y>>2]+ +g[d+(W<<2)>>2]>=ia)){la=X;ma=Y+1|0;na=Z;oa=(_(W,W)|0)+$|0;pa=aa;qa=W+ba|0;ra=ca;sa=(_(ka,W)|0)+da|0;ta=ea;ua=(_(ka,ka)|0)+fa|0;va=ga;wa=ka+ha|0;break}else{la=X+1|0;ma=Y;na=(_(W,W)|0)+Z|0;oa=$;pa=W+aa|0;qa=ba;ra=(_(ka,W)|0)+ca|0;sa=da;ta=(_(ka,ka)|0)+ea|0;ua=fa;va=ka+ga|0;wa=ha;break}else{la=X;ma=Y;na=Z;oa=$;pa=aa;qa=ba;ra=ca;sa=da;ta=ea;ua=fa;va=ga;wa=ha}while(0);if((W|0)<(J|0)){W=W+1|0;X=la;Y=ma;Z=na;$=oa;aa=pa;ba=qa;ca=ra;da=sa;ea=ta;fa=ua;ga=va;ha=wa}else{K=la;L=ma;M=na;N=oa;O=pa;P=qa;Q=ra;R=sa;S=ta;T=ua;U=va;V=wa;break}}}c[h+(E*56|0)+8>>2]=O;c[h+(E*56|0)+12>>2]=U;c[h+(E*56|0)+16>>2]=M;c[h+(E*56|0)+20>>2]=S;c[h+(E*56|0)+24>>2]=Q;c[h+(E*56|0)+28>>2]=K;c[h+(E*56|0)+32>>2]=P;c[h+(E*56|0)+36>>2]=V;c[h+(E*56|0)+40>>2]=N;c[h+(E*56|0)+44>>2]=T;c[h+(E*56|0)+48>>2]=R;c[h+(E*56|0)+52>>2]=L;ha=K+D|0;if((C|0)==(A|0)){xa=ha;break}else D=ha}}else ya=9}else ya=9}else ya=9}else ya=9;if((ya|0)==9){if(w){z=0;i=f;return z|0}D=h+4|0;H=h;I=H+56|0;do{c[H>>2]=0;H=H+4|0}while((H|0)<(I|0));c[D>>2]=v;if((v|0)<1){za=0;Aa=0;Ba=0;Ca=0;Da=0;Ea=0;Fa=0;Ga=0;Ha=0;Ia=0;Ja=0;Ka=0}else{D=u+1112|0;H=0;I=0;A=0;C=0;K=0;L=0;R=0;T=0;N=0;V=0;P=0;Q=0;S=0;while(1){ia=+g[e+(H<<2)>>2];M=~~(ia*7.314285755157471+1023.5);U=(M|0)>1023?1023:(M|0)<0?0:M;do if(U)if(!(+g[D>>2]+ +g[d+(H<<2)>>2]>=ia)){La=I;Ma=A+1|0;Na=C;Oa=(_(H,H)|0)+K|0;Pa=L;Qa=H+R|0;Ra=T;Sa=(_(U,H)|0)+N|0;Ua=V;Va=(_(U,U)|0)+P|0;Wa=Q;Xa=U+S|0;break}else{La=I+1|0;Ma=A;Na=(_(H,H)|0)+C|0;Oa=K;Pa=H+L|0;Qa=R;Ra=(_(U,H)|0)+T|0;Sa=N;Ua=(_(U,U)|0)+V|0;Va=P;Wa=U+Q|0;Xa=S;break}else{La=I;Ma=A;Na=C;Oa=K;Pa=L;Qa=R;Ra=T;Sa=N;Ua=V;Va=P;Wa=Q;Xa=S}while(0);H=H+1|0;if((H|0)==(v|0)){za=La;Aa=Ma;Ba=Na;Ca=Oa;Da=Pa;Ea=Qa;Fa=Ra;Ga=Sa;Ha=Ua;Ia=Va;Ja=Wa;Ka=Xa;break}else{I=La;A=Ma;C=Na;K=Oa;L=Pa;R=Qa;T=Ra;N=Sa;V=Ua;P=Va;Q=Wa;S=Xa}}}c[h+8>>2]=Da;c[h+12>>2]=Ja;c[h+16>>2]=Ba;c[h+20>>2]=Ha;c[h+24>>2]=Fa;c[h+28>>2]=za;c[h+32>>2]=Ea;c[h+36>>2]=Ka;c[h+40>>2]=Ca;c[h+44>>2]=Ia;c[h+48>>2]=Ga;c[h+52>>2]=Aa;xa=za}if(!xa){z=0;i=f;return z|0}c[o>>2]=-200;c[p>>2]=-200;Oc(h,w+-1|0,o,p,u)|0;xa=c[o>>2]|0;c[j>>2]=xa;c[k>>2]=xa;o=c[p>>2]|0;p=k+4|0;c[p>>2]=o;za=j+4|0;c[za>>2]=o;o=(w|0)>2;do if(o){Aa=u+1112|0;Ga=u+1096|0;Ia=u+1100|0;Ca=u+1104|0;Ka=2;a:while(1){Ea=c[b+520+(Ka<<2)>>2]|0;Fa=c[l+(Ea<<2)>>2]|0;Ha=c[m+(Ea<<2)>>2]|0;Ba=n+(Fa<<2)|0;b:do if((c[Ba>>2]|0)!=(Ha|0)){Ja=c[b+520+(Fa<<2)>>2]|0;Da=c[b+520+(Ha<<2)>>2]|0;c[Ba>>2]=Ha;Xa=c[u+836+(Fa<<2)>>2]|0;S=c[u+836+(Ha<<2)>>2]|0;Wa=c[j+(Fa<<2)>>2]|0;Q=k+(Fa<<2)|0;Va=c[Q>>2]|0;if((Wa|0)>=0)if((Va|0)<0)Ya=Wa;else Ya=Va+Wa>>1;else Ya=Va;Va=j+(Ha<<2)|0;Wa=c[Va>>2]|0;P=c[k+(Ha<<2)>>2]|0;if((Wa|0)>=0)if((P|0)<0)Za=Wa;else Za=P+Wa>>1;else Za=P;if((Ya|0)==-1|(Za|0)==-1){ya=38;break a}P=Za-Ya|0;Wa=S-Xa|0;Ua=(P|0)/(Wa|0)|0;V=P>>31|1;ia=+g[e+(Xa<<2)>>2];Sa=~~(ia*7.314285755157471+1023.5);N=(Sa|0)>1023?1023:(Sa|0)<0?0:Sa;Sa=_(Ua,Wa)|0;Ra=((P|0)>-1?P:0-P|0)-((Sa|0)>-1?Sa:0-Sa|0)|0;Sa=Ya-N|0;P=_(Sa,Sa)|0;_a=+g[Aa>>2];if(_a+ +g[d+(Xa<<2)>>2]>=ia){ia=+(Ya|0);$a=+(N|0);if(!(+g[Ga>>2]+ia<$a)?!(ia-+g[Ia>>2]>$a):0)ya=42}else ya=42;c:do if((ya|0)==42){ya=0;N=Xa+1|0;if((N|0)<(S|0)){Sa=N;N=0;T=P;Qa=1;R=Ya;while(1){Pa=N+Ra|0;L=(Pa|0)<(Wa|0);N=Pa-(L?0:Wa)|0;R=R+Ua+(L?0:V)|0;$a=+g[e+(Sa<<2)>>2];L=~~($a*7.314285755157471+1023.5);Pa=(L|0)>1023?1023:(L|0)<0?0:L;L=R-Pa|0;Oa=(_(L,L)|0)+T|0;L=Qa+1|0;if((Pa|0)!=0?+g[d+(Sa<<2)>>2]+_a>=$a:0){$a=+(R|0);ia=+(Pa|0);if(+g[Ga>>2]+$a<ia)break c;if($a-+g[Ia>>2]>ia)break c}Sa=Sa+1|0;if((Sa|0)>=(S|0)){ab=Oa;bb=L;break}else{T=Oa;Qa=L}}}else{ab=P;bb=1}ia=+g[Ga>>2];$a=+(bb|0);cb=+g[Ca>>2];if((!(ia*ia/$a>cb)?(ia=+g[Ia>>2],!(ia*ia/$a>cb)):0)?+((ab|0)/(bb|0)|0|0)>cb:0)break;c[j+(Ka<<2)>>2]=-200;c[k+(Ka<<2)>>2]=-200;break b}while(0);c[q>>2]=-200;c[r>>2]=-200;c[s>>2]=-200;c[t>>2]=-200;P=Oc(h+(Ja*56|0)|0,Ea-Ja|0,q,r,u)|0;S=Oc(h+(Ea*56|0)|0,Da-Ea|0,s,t,u)|0;V=(P|0)!=0;if(V){c[q>>2]=Ya;c[r>>2]=c[s>>2]}if((S|0)!=0?(c[s>>2]=c[r>>2],c[t>>2]=Za,V):0){c[j+(Ka<<2)>>2]=-200;c[k+(Ka<<2)>>2]=-200;break}V=c[q>>2]|0;c[Q>>2]=V;if(!Fa)c[j>>2]=V;V=c[r>>2]|0;c[j+(Ka<<2)>>2]=V;S=c[s>>2]|0;c[k+(Ka<<2)>>2]=S;P=c[t>>2]|0;c[Va>>2]=P;if((Ha|0)==1)c[p>>2]=P;if((S&V|0)>-1){d:do if((Ea|0)>0){V=Ea;do{S=V;V=V+-1|0;P=m+(V<<2)|0;if((c[P>>2]|0)!=(Ha|0))break d;c[P>>2]=Ka}while((S|0)>1)}while(0);Va=Ea+1|0;if((Va|0)<(w|0)){Q=Va;do{Va=l+(Q<<2)|0;if((c[Va>>2]|0)!=(Fa|0))break b;c[Va>>2]=Ka;Q=Q+1|0}while((Q|0)<(w|0))}}}while(0);Ka=Ka+1|0;if((Ka|0)>=(w|0)){ya=68;break}}if((ya|0)==38)Ta(1);else if((ya|0)==68){db=c[j>>2]|0;eb=c[k>>2]|0;break}}else{db=xa;eb=xa}while(0);xa=Ab(a,w<<2)|0;if((db|0)>=0)if((eb|0)<0)fb=db;else fb=eb+db>>1;else fb=eb;c[xa>>2]=fb;fb=c[za>>2]|0;za=c[p>>2]|0;if((fb|0)>=0)if((za|0)<0)gb=fb;else gb=za+fb>>1;else gb=za;c[xa+4>>2]=gb;if(o)hb=2;else{z=xa;i=f;return z|0}do{o=hb+-2|0;gb=c[b+1032+(o<<2)>>2]|0;za=c[b+780+(o<<2)>>2]|0;o=c[u+836+(gb<<2)>>2]|0;fb=c[xa+(gb<<2)>>2]&32767;gb=(c[xa+(za<<2)>>2]&32767)-fb|0;p=(_((gb|0)>-1?gb:0-gb|0,(c[u+836+(hb<<2)>>2]|0)-o|0)|0)/((c[u+836+(za<<2)>>2]|0)-o|0)|0;o=((gb|0)<0?0-p|0:p)+fb|0;fb=c[j+(hb<<2)>>2]|0;p=c[k+(hb<<2)>>2]|0;if((fb|0)>=0)if((p|0)<0)ib=fb;else ib=p+fb>>1;else ib=p;c[xa+(hb<<2)>>2]=(ib|0)<0|(o|0)==(ib|0)?o|32768:ib;hb=hb+1|0}while((hb|0)!=(w|0));z=xa;i=f;return z|0}function $b(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0;g=c[b+1284>>2]|0;if(!((d|0)!=0&(e|0)!=0)){h=0;return h|0}b=Ab(a,g<<2)|0;if((g|0)<=0){h=b;return h|0}a=65536-f|0;i=0;do{j=d+(i<<2)|0;k=_(c[j>>2]&32767,a)|0;l=e+(i<<2)|0;m=k+32768+(_(c[l>>2]&32767,f)|0)>>16;k=b+(i<<2)|0;c[k>>2]=m;if((c[j>>2]&32768|0)!=0?(c[l>>2]&32768|0)!=0:0)c[k>>2]=m|32768;i=i+1|0}while((i|0)!=(g|0));h=b;return h|0}function ac(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0;g=i;i=i+336|0;h=g+64|0;j=g+32|0;k=g;l=c[d+1296>>2]|0;m=d+1284|0;n=c[m>>2]|0;o=c[(c[(c[b+64>>2]|0)+4>>2]|0)+28>>2]|0;p=c[o+2848>>2]|0;if(!e){lb(a,0,1);Fd(f|0,0,((c[b+36>>2]|0)/2|0)<<2|0)|0;q=0;i=g;return q|0}if((n|0)>0){r=l+832|0;s=0;do{t=e+(s<<2)|0;u=c[t>>2]|0;v=u&32767;w=c[r>>2]|0;if((w|0)==3)x=(v>>>0)/12|0;else if((w|0)==4)x=v>>>4;else if((w|0)==1)x=v>>>2;else if((w|0)==2)x=v>>>3;else x=v;c[t>>2]=u&32768|x;s=s+1|0}while((s|0)!=(n|0))}c[h>>2]=c[e>>2];s=h+4|0;c[s>>2]=c[e+4>>2];x=d+1292|0;if((n|0)>2){r=2;do{u=r+-2|0;t=c[d+1032+(u<<2)>>2]|0;v=c[d+780+(u<<2)>>2]|0;u=c[l+836+(t<<2)>>2]|0;w=e+(t<<2)|0;t=e+(v<<2)|0;y=c[w>>2]&32767;z=(c[t>>2]&32767)-y|0;A=(_((z|0)>-1?z:0-z|0,(c[l+836+(r<<2)>>2]|0)-u|0)|0)/((c[l+836+(v<<2)>>2]|0)-u|0)|0;u=((z|0)<0?0-A|0:A)+y|0;A=e+(r<<2)|0;z=c[A>>2]|0;if((z&32768|0)!=0|(z|0)==(u|0)){c[A>>2]=u|32768;c[h+(r<<2)>>2]=0}else{A=(c[x>>2]|0)-u|0;v=(A|0)<(u|0)?A:u;A=z-u|0;do if((A|0)<0)if((A|0)<(0-v|0)){B=v+~A|0;break}else{B=~(A<<1);break}else if((v|0)>(A|0)){B=A<<1;break}else{B=v+A|0;break}while(0);c[h+(r<<2)>>2]=B;c[w>>2]=y;c[t>>2]=c[t>>2]&32767}r=r+1|0}while((r|0)!=(n|0))}lb(a,1,1);n=d+1308|0;c[n>>2]=(c[n>>2]|0)+1;n=(c[x>>2]|0)+-1|0;r=(n|0)==0;if(!r){B=n;A=0;while(1){v=A+1|0;B=B>>>1;if(!B){C=v;break}else A=v}A=d+1304|0;c[A>>2]=(c[A>>2]|0)+(C<<1);C=c[h>>2]|0;if(r){D=C;E=A;F=0}else{r=n;n=0;while(1){B=n+1|0;r=r>>>1;if(!r){D=C;E=A;F=B;break}else n=B}}}else{D=c[h>>2]|0;E=d+1304|0;F=0}lb(a,D,F);F=c[s>>2]|0;s=(c[x>>2]|0)+-1|0;if(!s)G=0;else{x=s;s=0;while(1){D=s+1|0;x=x>>>1;if(!x){G=D;break}else s=D}}lb(a,F,G);if((c[l>>2]|0)>0){G=d+1300|0;F=0;s=2;while(1){x=c[l+4+(F<<2)>>2]|0;D=c[l+128+(x<<2)>>2]|0;n=c[l+192+(x<<2)>>2]|0;A=1<<n;c[j>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;c[j+16>>2]=0;c[j+20>>2]=0;c[j+24>>2]=0;c[j+28>>2]=0;if(n){C=(n|0)==31;if(!C){r=0;do{B=c[l+320+(x<<5)+(r<<2)>>2]|0;if((B|0)<0)H=1;else H=c[(c[o+1824+(B<<2)>>2]|0)+4>>2]|0;c[k+(r<<2)>>2]=H;r=r+1|0}while((r|0)<(A|0))}a:do if((D|0)>0){if(C){r=0;t=0;y=0;while(1){w=c[j+(y<<2)>>2]<<r|t;y=y+1|0;if((y|0)==(D|0)){I=w;break a}else{r=r+31|0;t=w}}}else{J=0;K=0;L=0}while(1){t=c[h+(L+s<<2)>>2]|0;r=0;while(1){if((t|0)<(c[k+(r<<2)>>2]|0)){M=r;N=37;break}r=r+1|0;if((r|0)>=(A|0)){N=39;break}}if((N|0)==37){N=0;c[j+(L<<2)>>2]=M;O=M}else if((N|0)==39){N=0;O=c[j+(L<<2)>>2]|0}r=O<<J|K;L=L+1|0;if((L|0)==(D|0)){I=r;break}else{J=J+n|0;K=r}}}else I=0;while(0);n=oc(p+((c[l+256+(x<<2)>>2]|0)*56|0)|0,I,a)|0;c[G>>2]=(c[G>>2]|0)+n}if((D|0)>0){n=0;do{A=c[l+320+(x<<5)+(c[j+(n<<2)>>2]<<2)>>2]|0;if((A|0)>-1?(C=c[h+(n+s<<2)>>2]|0,(C|0)<(c[p+(A*56|0)+4>>2]|0)):0){r=oc(p+(A*56|0)|0,C,a)|0;c[E>>2]=(c[E>>2]|0)+r}n=n+1|0}while((n|0)!=(D|0))}F=F+1|0;if((F|0)>=(c[l>>2]|0))break;else s=D+s|0}}s=l+832|0;F=_(c[s>>2]|0,c[e>>2]|0)|0;E=(c[o+(c[b+28>>2]<<2)>>2]|0)/2|0;if((c[m>>2]|0)>1){o=0;a=1;p=0;h=F;while(1){j=c[d+260+(a<<2)>>2]|0;G=c[e+(j<<2)>>2]|0;if((G&32767|0)==(G|0)){I=_(c[s>>2]|0,G)|0;G=c[l+836+(j<<2)>>2]|0;j=I-h|0;K=G-p|0;J=(j|0)/(K|0)|0;L=j>>31|1;O=_(J,K)|0;N=((j|0)>-1?j:0-j|0)-((O|0)>-1?O:0-O|0)|0;O=(E|0)>(G|0)?G:E;if((O|0)>(p|0))c[f+(p<<2)>>2]=h;j=p+1|0;if((j|0)<(O|0)){M=j;j=0;k=h;while(1){H=j+N|0;n=(H|0)<(K|0);k=k+J+(n?0:L)|0;c[f+(M<<2)>>2]=k;M=M+1|0;if((M|0)==(O|0)){P=G;Q=G;R=I;break}else j=H-(n?0:K)|0}}else{P=G;Q=G;R=I}}else{P=o;Q=p;R=h}a=a+1|0;if((a|0)>=(c[m>>2]|0)){S=P;T=R;break}else{o=P;p=Q;h=R}}}else{S=0;T=F}F=b+36|0;if((S|0)<((c[F>>2]|0)/2|0|0))U=S;else{q=1;i=g;return q|0}do{c[f+(U<<2)>>2]=T;U=U+1|0}while((U|0)<((c[F>>2]|0)/2|0|0));q=1;i=g;return q|0}function bc(a){a=a|0;if(a)yd(a);return}function cc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;if(!a)return;b=a+4|0;d=c[b>>2]|0;e=a+20|0;if((d|0)>0){f=d;d=0;while(1){g=c[(c[e>>2]|0)+(d<<2)>>2]|0;if(!g)h=f;else{yd(g);h=c[b>>2]|0}d=d+1|0;if((d|0)>=(h|0))break;else f=h}}yd(c[e>>2]|0);e=a+24|0;h=a+28|0;if((c[e>>2]|0)>0){f=0;do{yd(c[(c[h>>2]|0)+(f<<2)>>2]|0);f=f+1|0}while((f|0)<(c[e>>2]|0))}yd(c[h>>2]|0);yd(a);return}function dc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;lb(b,c[a>>2]|0,24);lb(b,c[a+4>>2]|0,24);lb(b,(c[a+8>>2]|0)+-1|0,24);d=a+12|0;lb(b,(c[d>>2]|0)+-1|0,6);lb(b,c[a+20>>2]|0,8);if((c[d>>2]|0)<=0)return;e=a+24|0;f=0;g=0;while(1){h=e+(g<<2)|0;i=c[h>>2]|0;if(i){j=i;k=0;while(1){j=j>>>1;if(!j){l=k;break}else k=k+1|0}if((l|0)>2){lb(b,i,3);lb(b,1,1);lb(b,c[h>>2]>>3,5)}else m=9}else m=9;if((m|0)==9){m=0;lb(b,i,4)}k=c[h>>2]|0;if(!k)n=0;else{j=k;k=0;while(1){o=(j&1)+k|0;j=j>>>1;if(!j){n=o;break}else k=o}}k=n+f|0;g=g+1|0;if((g|0)>=(c[d>>2]|0)){p=k;break}else f=k}if((p|0)<=0)return;f=a+280|0;a=0;do{lb(b,c[f+(a<<2)>>2]|0,8);a=a+1|0}while((a|0)!=(p|0));return}function ec(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;d=zd(1,2840)|0;e=c[a+28>>2]|0;c[d>>2]=qb(b,24)|0;c[d+4>>2]=qb(b,24)|0;c[d+8>>2]=(qb(b,24)|0)+1;a=qb(b,6)|0;f=d+12|0;c[f>>2]=a+1;g=qb(b,8)|0;h=d+20|0;c[h>>2]=g;a:do if((g|0)>=0){if((a|0)>-1){i=d+24|0;j=0;k=0;while(1){l=qb(b,3)|0;m=qb(b,1)|0;if((m|0)<0){n=26;break a}if(!m)o=l;else{m=qb(b,5)|0;if((m|0)<0){n=26;break a}o=m<<3|l}c[i+(k<<2)>>2]=o;if(!o)p=0;else{l=o;m=0;while(1){q=(l&1)+m|0;l=l>>>1;if(!l){p=q;break}else m=q}}m=p+j|0;k=k+1|0;if((k|0)>=(c[f>>2]|0)){r=m;break}else j=m}j=(r|0)>0;if(j){k=d+280|0;i=0;while(1){m=qb(b,8)|0;if((m|0)<0)break a;c[k+(i<<2)>>2]=m;i=i+1|0;if((i|0)>=(r|0)){s=j;t=r;break}}}else{s=0;t=r}}else{s=0;t=0}j=c[h>>2]|0;i=c[e+24>>2]|0;if((j|0)<(i|0)){if(s){k=d+280|0;m=0;do{l=c[k+(m<<2)>>2]|0;if((l|0)>=(i|0))break a;m=m+1|0;if(!(c[(c[e+1824+(l<<2)>>2]|0)+12>>2]|0))break a}while((m|0)<(t|0))}m=c[e+1824+(j<<2)>>2]|0;i=c[m+4>>2]|0;k=c[m>>2]|0;if((k|0)>=1){m=c[f>>2]|0;l=k;k=1;while(1){q=_(m,k)|0;if((q|0)>(i|0))break a;if((l|0)>1){l=l+-1|0;k=q}else{u=q;break}}c[d+16>>2]=u;v=d;return v|0}}}else n=26;while(0);if((n|0)==26?(d|0)==0:0){v=0;return v|0}yd(d);v=0;return v|0}function fc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;d=zd(1,44)|0;e=c[(c[a+4>>2]|0)+28>>2]|0;c[d>>2]=b;a=c[b+12>>2]|0;c[d+4>>2]=a;f=e+2848|0;e=c[f>>2]|0;c[d+12>>2]=e;g=e+((c[b+20>>2]|0)*56|0)|0;c[d+16>>2]=g;e=c[g>>2]|0;g=zd(a,4)|0;c[d+20>>2]=g;if((a|0)>0){h=b+24|0;i=b+280|0;b=0;j=0;k=0;while(1){l=c[h+(j<<2)>>2]|0;if(l){m=l;n=0;while(1){o=n+1|0;m=m>>>1;if(!m){p=o;q=n;break}else n=o}if(p){n=(p|0)>(k|0)?p:k;c[g+(j<<2)>>2]=zd(p,4)|0;if((q|0)>-1){m=g+(j<<2)|0;o=b;r=0;while(1){if(!(l&1<<r))s=o;else{c[(c[m>>2]|0)+(r<<2)>>2]=(c[f>>2]|0)+((c[i+(o<<2)>>2]|0)*56|0);s=o+1|0}r=r+1|0;if((r|0)>=(p|0)){t=s;u=n;break}else o=s}}else{t=b;u=n}}else{t=b;u=k}}else{t=b;u=k}j=j+1|0;if((j|0)>=(a|0)){v=u;break}else{b=t;k=u}}}else v=0;u=d+24|0;c[u>>2]=1;k=(e|0)>0;if(k){t=1;b=0;while(1){j=_(t,a)|0;b=b+1|0;if((b|0)==(e|0)){w=j;break}else t=j}c[u>>2]=w;x=w}else x=1;c[d+8>>2]=v;v=xd(x<<2)|0;w=d+28|0;c[w>>2]=v;if((x|0)<=0)return d|0;u=e<<2;if(!k){k=0;do{c[v+(k<<2)>>2]=xd(u)|0;k=k+1|0}while((k|0)<(x|0));return d|0}k=c[w>>2]|0;w=0;do{c[v+(w<<2)>>2]=xd(u)|0;t=c[k+(w<<2)>>2]|0;b=x;j=0;s=w;do{b=(b|0)/(a|0)|0;p=(s|0)/(b|0)|0;s=s-(_(p,b)|0)|0;c[t+(j<<2)>>2]=p;j=j+1|0}while((j|0)!=(e|0));w=w+1|0}while((w|0)<(x|0));return d|0}function gc(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;if((f|0)>0){g=0;h=0}else return 0;while(1){if(!(c[e+(g<<2)>>2]|0))i=h;else{c[d+(h<<2)>>2]=c[d+(g<<2)>>2];i=h+1|0}g=g+1|0;if((g|0)==(f|0)){j=i;break}else h=i}if(!j)return 0;Pc(a,b,d,j,3);return 0}function hc(a,b,d,e,f,g,h,i){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;var j=0,k=0,l=0,m=0;if((g|0)>0){j=0;k=0}else return 0;while(1){if(!(c[f+(j<<2)>>2]|0))l=k;else{c[e+(k<<2)>>2]=c[e+(j<<2)>>2];l=k+1|0}j=j+1|0;if((j|0)==(g|0)){m=l;break}else k=l}if(!m)return 0;Qc(a,d,e,m,h);return 0}function ic(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;if((f|0)>0){g=0;h=0}else{i=0;return i|0}while(1){if(!(c[e+(g<<2)>>2]|0))j=h;else{c[d+(h<<2)>>2]=c[d+(g<<2)>>2];j=h+1|0}g=g+1|0;if((g|0)==(f|0)){k=j;break}else h=j}if(!k){i=0;return i|0}j=c[b>>2]|0;h=c[j+8>>2]|0;f=c[j+12>>2]|0;g=((c[j+4>>2]|0)-(c[j>>2]|0)|0)/(h|0)|0;e=Ab(a,k<<2)|0;l=100.0/+(h|0);m=(k|0)>0;if(m){n=g<<2;o=0;do{p=Ab(a,n)|0;c[e+(o<<2)>>2]=p;Fd(p|0,0,n|0)|0;o=o+1|0}while((o|0)!=(k|0))}if((g|0)>0){o=(h|0)>0;n=f+-1|0;a=(f|0)>1;f=0;do{p=_(f,h)|0;q=(c[j>>2]|0)+p|0;if(m){p=0;do{if(o){r=c[d+(p<<2)>>2]|0;s=0;t=0;u=0;while(1){v=c[r+(q+t<<2)>>2]|0;w=(v|0)>-1?v:0-v|0;v=(w|0)>(u|0)?w:u;x=w+s|0;t=t+1|0;if((t|0)==(h|0)){y=x;z=v;break}else{s=x;u=v}}}else{y=0;z=0}u=~~(+(y|0)*l);a:do if(a){s=0;while(1){if((z|0)<=(c[j+2328+(s<<2)>>2]|0)?(t=c[j+2584+(s<<2)>>2]|0,(t|0)<0|(u|0)<(t|0)):0){A=s;break a}t=s+1|0;if((t|0)<(n|0))s=t;else{A=t;break}}}else A=0;while(0);c[(c[e+(p<<2)>>2]|0)+(f<<2)>>2]=A;p=p+1|0}while((p|0)!=(k|0))}f=f+1|0}while((f|0)!=(g|0))}g=b+40|0;c[g>>2]=(c[g>>2]|0)+1;i=e;return i|0}function jc(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;if((f|0)>0){g=0;h=0}else return 0;while(1){if(!(c[e+(g<<2)>>2]|0))i=h;else{c[d+(h<<2)>>2]=c[d+(g<<2)>>2];i=h+1|0}g=g+1|0;if((g|0)==(f|0)){j=i;break}else h=i}if(!j)return 0;Pc(a,b,d,j,4);return 0}function kc(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0;if((f|0)>0){g=0;h=0}else{i=0;return i|0}while(1){j=((c[e+(g<<2)>>2]|0)!=0&1)+h|0;g=g+1|0;if((g|0)==(f|0)){k=j;break}else h=j}if(!k){i=0;return i|0}k=c[b>>2]|0;h=c[k+8>>2]|0;g=c[k+12>>2]|0;e=((c[k+4>>2]|0)-(c[k>>2]|0)|0)/(h|0)|0;j=Ab(a,4)|0;l=e<<2;m=Ab(a,l)|0;c[j>>2]=m;Fd(m|0,0,l|0)|0;if((e|0)>0){l=(h|0)>0;m=g+-1|0;a=(g|0)>1;g=c[j>>2]|0;n=(f|0)>1;o=0;p=(c[k>>2]|0)/(f|0)|0;while(1){if(l){q=c[d>>2]|0;r=0;s=0;t=p;u=0;while(1){v=c[q+(t<<2)>>2]|0;w=(v|0)>-1?v:0-v|0;v=(w|0)>(u|0)?w:u;if(n){w=r;x=1;while(1){y=c[(c[d+(x<<2)>>2]|0)+(t<<2)>>2]|0;z=(y|0)>-1?y:0-y|0;y=(z|0)>(w|0)?z:w;x=x+1|0;if((x|0)==(f|0)){A=y;break}else w=y}}else A=r;w=t+1|0;s=s+f|0;if((s|0)>=(h|0)){B=A;C=w;D=v;break}else{r=A;t=w;u=v}}}else{B=0;C=p;D=0}a:do if(a){u=0;while(1){if((D|0)<=(c[k+2328+(u<<2)>>2]|0)?(B|0)<=(c[k+2584+(u<<2)>>2]|0):0){E=u;break a}t=u+1|0;if((t|0)<(m|0))u=t;else{E=t;break}}}else E=0;while(0);c[g+(o<<2)>>2]=E;o=o+1|0;if((o|0)==(e|0))break;else p=C}}C=b+40|0;c[C>>2]=(c[C>>2]|0)+1;i=j;return i|0}function lc(a,b,d,e,f,g,h,j){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;j=i;i=i+16|0;k=j;l=c[b+36>>2]|0;m=(l|0)/2|0;n=Ab(b,_(g<<2,m)|0)|0;c[k>>2]=n;if((g|0)<=0){i=j;return 0}b=(l|0)>1;l=0;o=0;while(1){p=c[e+(l<<2)>>2]|0;q=((c[f+(l<<2)>>2]|0)!=0&1)+o|0;if(b){r=0;s=l;while(1){c[n+(s<<2)>>2]=c[p+(r<<2)>>2];r=r+1|0;if((r|0)>=(m|0))break;else s=s+g|0}}l=l+1|0;if((l|0)==(g|0)){t=q;break}else o=q}if(!t){i=j;return 0}Qc(a,d,k,1,h);i=j;return 0}function mc(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0;g=c[b>>2]|0;h=c[g+8>>2]|0;i=b+16|0;j=c[c[i>>2]>>2]|0;k=(_(c[a+36>>2]|0,f)|0)>>1;l=c[g+4>>2]|0;m=((l|0)<(k|0)?l:k)-(c[g>>2]|0)|0;if((m|0)<=0)return 0;k=(m|0)/(h|0)|0;m=Ab(a,((j+-1+k|0)/(j|0)|0)<<2)|0;a:do if((f|0)>0){l=0;while(1){if(c[e+(l<<2)>>2]|0){n=l;break a}o=l+1|0;if((o|0)<(f|0))l=o;else{n=o;break}}}else n=0;while(0);if((n|0)==(f|0))return 0;n=b+8|0;e=c[n>>2]|0;if((e|0)<=0)return 0;l=(k|0)>0;o=a+4|0;a=g+16|0;p=b+28|0;q=(j|0)>0;r=b+20|0;b=e;e=0;b:while(1){if(l){s=(e|0)==0;t=1<<e;u=0;v=0;while(1){if(s){w=pc(c[i>>2]|0,o)|0;if((w|0)==-1){x=23;break b}if((w|0)>=(c[a>>2]|0)){x=23;break b}y=c[(c[p>>2]|0)+(w<<2)>>2]|0;c[m+(v<<2)>>2]=y;if(!y){x=23;break b}}if(q&(u|0)<(k|0)){y=m+(v<<2)|0;w=u;z=0;while(1){A=c[(c[y>>2]|0)+(z<<2)>>2]|0;if(((c[g+24+(A<<2)>>2]&t|0)!=0?(B=c[(c[(c[r>>2]|0)+(A<<2)>>2]|0)+(e<<2)>>2]|0,(B|0)!=0):0)?(A=_(w,h)|0,(tc(B,d,(c[g>>2]|0)+A|0,f,o,h)|0)==-1):0){x=23;break b}z=z+1|0;A=w+1|0;if(!((z|0)<(j|0)&(A|0)<(k|0))){C=A;break}else w=A}}else C=u;if((C|0)<(k|0)){u=C;v=v+1|0}else break}D=c[n>>2]|0}else D=b;e=e+1|0;if((e|0)>=(D|0)){x=23;break}else b=D}if((x|0)==23)return 0;return 0}function nc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;b=zd(1,40)|0;c[b+36>>2]=1;a:do if(((qb(a,24)|0)==5653314?(c[b>>2]=qb(a,16)|0,d=qb(a,24)|0,e=b+4|0,c[e>>2]=d,(d|0)!=-1):0)?(d=uc(c[b>>2]|0)|0,((uc(c[e>>2]|0)|0)+d|0)<=24):0){d=qb(a,1)|0;b:do if(!d){f=qb(a,1)|0;g=(f|0)!=0;f=(_(g?1:5,c[e>>2]|0)|0)+7>>3;h=c[a+16>>2]|0;if((f|0)>(h-(rb(a)|0)|0))break a;h=c[e>>2]|0;f=b+8|0;c[f>>2]=xd(h<<2)|0;i=(h|0)>0;if(!g){if(i)j=0;else break;while(1){g=qb(a,5)|0;if((g|0)==-1)break a;c[(c[f>>2]|0)+(j<<2)>>2]=g+1;j=j+1|0;if((j|0)>=(c[e>>2]|0))break b}}if(i){g=0;do{if(!(qb(a,1)|0))c[(c[f>>2]|0)+(g<<2)>>2]=0;else{h=qb(a,5)|0;if((h|0)==-1)break a;c[(c[f>>2]|0)+(g<<2)>>2]=h+1}g=g+1|0}while((g|0)<(c[e>>2]|0))}}else if((d|0)==1){g=(qb(a,5)|0)+1|0;if(!g)break a;f=c[e>>2]|0;i=b+8|0;c[i>>2]=xd(f<<2)|0;if((f|0)>0){h=f;f=0;k=g;while(1){g=qb(a,uc(h-f|0)|0)|0;if((k|0)>32|(g|0)==-1)break a;l=c[e>>2]|0;if((g|0)>(l-f|0))break a;if((g|0)>0){if((g+-1>>k+-1|0)>1)break a;m=c[i>>2]|0;n=f;o=0;while(1){c[m+(n<<2)>>2]=k;o=o+1|0;if((o|0)==(g|0))break;else n=n+1|0}p=c[e>>2]|0;q=g+f|0}else{p=l;q=f}if((p|0)>(q|0)){h=p;f=q;k=k+1|0}else break}}}else break a;while(0);d=qb(a,4)|0;k=b+12|0;c[k>>2]=d;if(!d){r=b;return r|0}else if(!((d|0)==2|(d|0)==1))break;c[b+16>>2]=qb(a,32)|0;c[b+20>>2]=qb(a,32)|0;d=b+24|0;c[d>>2]=(qb(a,4)|0)+1;f=qb(a,1)|0;c[b+28>>2]=f;if((f|0)!=-1){f=c[k>>2]|0;if((f|0)==1)if(!(c[b>>2]|0))s=0;else s=wc(b)|0;else if((f|0)==2)s=_(c[b>>2]|0,c[e>>2]|0)|0;else s=0;f=(_(c[d>>2]|0,s)|0)+7>>3;k=c[a+16>>2]|0;if((f|0)<=(k-(rb(a)|0)|0)){k=xd(s<<2)|0;f=b+32|0;c[f>>2]=k;if((s|0)>0){h=0;do{i=qb(a,c[d>>2]|0)|0;n=c[f>>2]|0;c[n+(h<<2)>>2]=i;h=h+1|0}while((h|0)!=(s|0));t=n}else t=k;if(!s){r=b;return r|0}if((c[t+(s+-1<<2)>>2]|0)!=-1){r=b;return r|0}}}}while(0);yc(b);r=0;return r|0}function oc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;if((b|0)<0){e=0;return e|0}f=a+12|0;g=c[f>>2]|0;if((c[g+4>>2]|0)<=(b|0)){e=0;return e|0}lb(d,c[(c[a+20>>2]|0)+(b<<2)>>2]|0,c[(c[g+8>>2]|0)+(b<<2)>>2]|0);e=c[(c[(c[f>>2]|0)+8>>2]|0)+(b<<2)>>2]|0;return e|0}function pc(a,b){a=a|0;b=b|0;var d=0,e=0;if((c[a+8>>2]|0)<=0){d=-1;return d|0}e=Rc(a,b)|0;if((e|0)<=-1){d=-1;return d|0}d=c[(c[a+24>>2]|0)+(e<<2)>>2]|0;return d|0}function qc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;f=i;if((c[a+8>>2]|0)<=0){h=0;i=f;return h|0}j=c[a>>2]|0;k=(e|0)/(j|0)|0;e=i;i=i+((1*(k<<2)|0)+15&-16)|0;l=(k|0)>0;a:do if(l){m=a+16|0;n=0;while(1){o=Rc(a,d)|0;if((o|0)==-1){h=-1;break}p=c[a>>2]|0;c[e+(n<<2)>>2]=(c[m>>2]|0)+((_(p,o)|0)<<2);n=n+1|0;if((n|0)>=(k|0)){q=p;break a}}i=f;return h|0}else q=j;while(0);if((q|0)<1|l^1){h=0;i=f;return h|0}else{r=0;s=0}while(1){l=0;do{j=b+(l+s<<2)|0;g[j>>2]=+g[j>>2]+ +g[(c[e+(l<<2)>>2]|0)+(r<<2)>>2];l=l+1|0}while((l|0)!=(k|0));r=r+1|0;if((r|0)>=(q|0)){h=0;break}else s=s+k|0}i=f;return h|0}function rc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0;if((c[a+8>>2]|0)<=0){f=0;return f|0}if((c[a>>2]|0)>8){if((e|0)<=0){f=0;return f|0}h=a+16|0;i=0;while(1){j=Rc(a,d)|0;if((j|0)==-1){f=-1;k=29;break}l=c[h>>2]|0;m=c[a>>2]|0;n=_(m,j)|0;if((m|0)>0){j=(m|0)>1?m:1;o=i;p=0;while(1){q=b+(o<<2)|0;g[q>>2]=+g[q>>2]+ +g[l+(p+n<<2)>>2];p=p+1|0;if((p|0)>=(m|0))break;else o=o+1|0}r=i+j|0}else r=i;if((r|0)<(e|0))i=r;else{f=0;k=29;break}}if((k|0)==29)return f|0}r=a+16|0;if((e|0)>0)s=0;else{f=0;return f|0}a:while(1){b:while(1){i=Rc(a,d)|0;if((i|0)==-1){f=-1;k=29;break a}h=c[r>>2]|0;switch(c[a>>2]|0){case 6:{t=i;u=h;k=15;break b;break}case 5:{v=i;w=h;k=17;break b;break}case 4:{x=i;y=h;k=19;break b;break}case 1:{z=i;A=h;B=s;C=0;break b;break}case 7:{D=i;E=h;k=13;break b;break}case 2:{F=i;G=h;k=23;break b;break}case 8:{H=h;I=i;k=12;break b;break}case 3:{J=i;K=h;k=21;break b;break}default:{}}}if((k|0)==12){k=0;j=I<<3;h=b+(s<<2)|0;g[h>>2]=+g[h>>2]+ +g[H+(j<<2)>>2];L=j;M=H;N=s+1|0;O=1;k=14}else if((k|0)==13){k=0;L=D*7|0;M=E;N=s;O=0;k=14}else if((k|0)==15){k=0;P=t*6|0;Q=u;R=s;S=0;k=16}else if((k|0)==17){k=0;T=v*5|0;U=w;V=s;W=0;k=18}else if((k|0)==19){k=0;X=x<<2;Y=y;Z=s;$=0;k=20}else if((k|0)==21){k=0;aa=J*3|0;ba=K;ca=s;da=0;k=22}else if((k|0)==23){k=0;ea=F<<1;fa=G;ga=s;ha=0;k=24}if((k|0)==14){k=0;j=b+(N<<2)|0;g[j>>2]=+g[j>>2]+ +g[M+(O+L<<2)>>2];P=L;Q=M;R=N+1|0;S=O+1|0;k=16}if((k|0)==16){k=0;j=b+(R<<2)|0;g[j>>2]=+g[j>>2]+ +g[Q+(S+P<<2)>>2];T=P;U=Q;V=R+1|0;W=S+1|0;k=18}if((k|0)==18){k=0;j=b+(V<<2)|0;g[j>>2]=+g[j>>2]+ +g[U+(W+T<<2)>>2];X=T;Y=U;Z=V+1|0;$=W+1|0;k=20}if((k|0)==20){k=0;j=b+(Z<<2)|0;g[j>>2]=+g[j>>2]+ +g[Y+($+X<<2)>>2];aa=X;ba=Y;ca=Z+1|0;da=$+1|0;k=22}if((k|0)==22){k=0;j=b+(ca<<2)|0;g[j>>2]=+g[j>>2]+ +g[ba+(da+aa<<2)>>2];ea=aa;fa=ba;ga=ca+1|0;ha=da+1|0;k=24}if((k|0)==24){k=0;j=b+(ga<<2)|0;g[j>>2]=+g[j>>2]+ +g[fa+(ha+ea<<2)>>2];z=ea;A=fa;B=ga+1|0;C=ha+1|0}s=B+1|0;j=b+(B<<2)|0;g[j>>2]=+g[j>>2]+ +g[A+(C+z<<2)>>2];if((s|0)>=(e|0)){f=0;k=29;break}}if((k|0)==29)return f|0;return 0}function sc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;f=(e|0)>0;if((c[a+8>>2]|0)<=0){if(!f){g=0;return g|0}Fd(b|0,0,e<<2|0)|0;g=0;return g|0}if(!f){g=0;return g|0}f=a+16|0;h=0;while(1){i=Rc(a,d)|0;if((i|0)==-1){g=-1;j=11;break}k=c[f>>2]|0;l=c[a>>2]|0;m=_(l,i)|0;a:do if((h|0)<(e|0)){i=h;n=0;while(1){if((n|0)>=(l|0)){o=i;break a}p=i+1|0;c[b+(i<<2)>>2]=c[k+(n+m<<2)>>2];if((p|0)<(e|0)){i=p;n=n+1|0}else{o=p;break}}}else o=h;while(0);if((o|0)<(e|0))h=o;else{g=0;j=11;break}}if((j|0)==11)return g|0;return 0}function tc(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;var i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;if((c[a+8>>2]|0)<=0){i=0;return i|0}j=(d|0)/(e|0)|0;k=(h+d|0)/(e|0)|0;if((j|0)>=(k|0)){i=0;return i|0}d=a+16|0;h=0;l=j;while(1){j=Rc(a,f)|0;if((j|0)==-1){i=-1;m=8;break}n=c[d>>2]|0;o=c[a>>2]|0;p=_(o,j)|0;if((o|0)>0){j=h;q=l;r=0;while(1){s=j+1|0;t=(c[b+(j<<2)>>2]|0)+(q<<2)|0;g[t>>2]=+g[t>>2]+ +g[n+(r+p<<2)>>2];t=(s|0)==(e|0);u=(t&1)+q|0;v=t?0:s;r=r+1|0;if((r|0)>=(o|0)){w=v;x=u;break}else{j=v;q=u}}}else{w=h;x=l}if((x|0)<(k|0)){h=w;l=x}else{i=0;m=8;break}}if((m|0)==8)return i|0;return 0}function uc(a){a=a|0;var b=0,c=0,d=0;if(!a)b=0;else{c=a;a=0;while(1){d=a+1|0;c=c>>>1;if(!c){b=d;break}else a=d}}return b|0}function vc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0;e=i;i=i+144|0;f=e;g=(d|0)!=0;h=xd((g?d:b)<<2)|0;Fd(f|0,0,132)|0;j=(b|0)>0;a:do if(j){k=f+4|0;l=(d|0)==0&1;m=0;n=0;b:while(1){o=c[a+(n<<2)>>2]|0;c:do if((o|0)>0){p=c[f+(o<<2)>>2]|0;if(!((o|0)>31|(p>>>o|0)==0))break b;c[h+(m<<2)>>2]=p;q=f+(o<<2)|0;d:do if(!(p&1)){r=p;s=q;t=o;while(1){c[s>>2]=r+1;u=t+-1|0;if((t|0)<=1)break d;r=c[f+(u<<2)>>2]|0;v=f+(u<<2)|0;if(r&1){w=v;x=u;y=8;break}else{s=v;t=u}}}else{w=q;x=o;y=8}while(0);do if((y|0)==8){y=0;if((x|0)==1){c[k>>2]=(c[k>>2]|0)+1;break}else{c[w>>2]=c[f+(x+-1<<2)>>2]<<1;break}}while(0);q=o+1|0;if((q|0)<33){t=p;s=o;r=q;while(1){q=f+(r<<2)|0;u=t;t=c[q>>2]|0;if((t>>>1|0)!=(u|0)){z=1;break c}c[q>>2]=c[f+(s<<2)>>2]<<1;q=r+1|0;if((q|0)>=33){z=1;break}else{u=r;r=q;s=u}}}else z=1}else z=l;while(0);n=n+1|0;if((n|0)>=(b|0))break a;else m=m+z|0}yd(h);A=0;i=e;return A|0}while(0);e:do if((d|0)!=1){z=1;while(1){if(c[f+(z<<2)>>2]&-1>>>(32-z|0))break;z=z+1|0;if((z|0)>=33)break e}yd(h);A=0;i=e;return A|0}while(0);if(!j){A=h;i=e;return A|0}if(g){B=0;C=0}else{g=0;j=0;while(1){f=c[a+(j<<2)>>2]|0;if((f|0)>0){d=c[h+(g<<2)>>2]|0;z=0;x=0;while(1){w=d>>>z&1|x<<1;z=z+1|0;if((z|0)>=(f|0)){D=w;break}else x=w}}else D=0;c[h+(g<<2)>>2]=D;j=j+1|0;if((j|0)==(b|0)){A=h;break}else g=g+1|0}i=e;return A|0}while(1){g=c[a+(C<<2)>>2]|0;if((g|0)>0){j=c[h+(B<<2)>>2]|0;D=0;x=0;while(1){f=j>>>D&1|x<<1;D=D+1|0;if((D|0)>=(g|0)){E=f;break}else x=f}}else E=0;if(!g)F=B;else{c[h+(B<<2)>>2]=E;F=B+1|0}C=C+1|0;if((C|0)==(b|0)){A=h;break}else B=F}i=e;return A|0}function wc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;b=c[a+4>>2]|0;d=c[a>>2]|0;if((d|0)<=0)while(1){}a=~~+M(+(+P(+(+(b|0)),+(1.0/+(d|0)))));while(1){e=a+1|0;f=1;g=1;h=0;while(1){i=_(f,a)|0;j=_(g,e)|0;h=h+1|0;if((h|0)>=(d|0)){k=i;l=j;break}else{f=i;g=j}}if((k|0)<=(b|0)&(l|0)>(b|0)){m=a;break}a=a+((k|0)>(b|0)?-1:1)|0}return m|0}function xc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,h=0,i=0.0,j=0.0,k=0.0,l=0,m=0,n=0,o=0,p=0.0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0.0,C=0.0,D=0,E=0,F=0,G=0,H=0;e=c[a+12>>2]|0;if((e+-1|0)>>>0>=2){f=0;return f|0}h=c[a+16>>2]|0;i=+(h&2097151|0);j=+qd((h|0)<0?-i:i,(h>>>21&1023)+-788|0);h=c[a+20>>2]|0;i=+(h&2097151|0);k=+qd((h|0)<0?-i:i,(h>>>21&1023)+-788|0);h=c[a>>2]|0;l=zd(_(h,b)|0,4)|0;if((e|0)==2){b=c[a+4>>2]|0;if((b|0)<=0){f=l;return f|0}m=(d|0)!=0;n=a+8|0;o=a+32|0;i=k;p=j;q=a+28|0;r=(h|0)>0;s=0;t=0;while(1){if(m?(c[(c[n>>2]|0)+(t<<2)>>2]|0)==0:0)u=s;else{if(r){v=c[o>>2]|0;w=(c[q>>2]|0)==0;x=d+(s<<2)|0;y=_(h,t)|0;z=_(h,s)|0;A=0;B=0.0;while(1){C=B+p+ +N(+(+(c[v+(y+A<<2)>>2]|0)))*i;if(m)g[l+((_(c[x>>2]|0,h)|0)+A<<2)>>2]=C;else g[l+(z+A<<2)>>2]=C;A=A+1|0;if((A|0)>=(h|0))break;else B=w?B:C}}u=s+1|0}t=t+1|0;if((t|0)>=(b|0)){f=l;break}else s=u}return f|0}else if((e|0)==1){e=c[a+4>>2]|0;if((h|0)<=0)while(1){}u=~~+M(+(+P(+(+(e|0)),+(1.0/+(h|0)))));while(1){s=u+1|0;b=1;t=1;m=0;while(1){q=_(b,u)|0;o=_(t,s)|0;m=m+1|0;if((m|0)==(h|0)){D=q;E=o;break}else{b=q;t=o}}if((E|0)>(e|0)&(D|0)<=(e|0)){F=u;break}u=((D|0)>(e|0)?-1:1)+u|0}if((e|0)<=0){f=l;return f|0}u=(d|0)==0;D=a+8|0;E=a+32|0;i=k;k=j;t=a+28|0;a=0;b=0;while(1){if(u){m=c[E>>2]|0;s=_(h,a)|0;if(!(c[t>>2]|0)){o=1;q=0;do{g[l+(s+q<<2)>>2]=k+ +N(+(+(c[m+((((b|0)/(o|0)|0|0)%(F|0)|0)<<2)>>2]|0)))*i;o=_(o,F)|0;q=q+1|0}while((q|0)<(h|0));G=21}else{q=1;o=0;j=0.0;do{j=j+k+ +N(+(+(c[m+((((b|0)/(q|0)|0|0)%(F|0)|0)<<2)>>2]|0)))*i;g[l+(s+o<<2)>>2]=j;q=_(q,F)|0;o=o+1|0}while((o|0)<(h|0));G=21}}else if(!(c[(c[D>>2]|0)+(b<<2)>>2]|0))H=a;else{o=c[E>>2]|0;q=(c[t>>2]|0)==0;s=_(c[d+(a<<2)>>2]|0,h)|0;m=1;r=0;j=0.0;while(1){p=j+k+ +N(+(+(c[o+((((b|0)/(m|0)|0|0)%(F|0)|0)<<2)>>2]|0)))*i;g[l+(s+r<<2)>>2]=p;m=_(m,F)|0;r=r+1|0;if((r|0)>=(h|0)){G=21;break}else j=q?j:p}}if((G|0)==21){G=0;H=a+1|0}b=b+1|0;if((b|0)>=(e|0)){f=l;break}else a=H}return f|0}else{f=l;return f|0}return 0}function yc(a){a=a|0;var b=0;if(!(c[a+36>>2]|0))return;b=c[a+32>>2]|0;if(b)yd(b);b=c[a+8>>2]|0;if(b)yd(b);yd(a);return}function zc(a){a=a|0;var b=0;b=c[a+16>>2]|0;if(b)yd(b);b=c[a+20>>2]|0;if(b)yd(b);b=c[a+24>>2]|0;if(b)yd(b);b=c[a+28>>2]|0;if(b)yd(b);b=c[a+32>>2]|0;if(b)yd(b);b=a;a=b+56|0;do{c[b>>2]=0;b=b+4|0}while((b|0)<(a|0));return}function Ac(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0.0;d=a;e=d+56|0;do{c[d>>2]=0;d=d+4|0}while((d|0)<(e|0));c[a+12>>2]=b;d=b+4|0;e=c[d>>2]|0;c[a+4>>2]=e;c[a+8>>2]=e;c[a>>2]=c[b>>2];c[a+20>>2]=vc(c[b+8>>2]|0,e,0)|0;e=c[d>>2]|0;d=c[b>>2]|0;if((d|0)<=0)while(1){}f=~~+M(+(+P(+(+(e|0)),+(1.0/+(d|0)))));while(1){g=f+1|0;h=1;i=1;j=0;while(1){k=_(h,f)|0;l=_(i,g)|0;j=j+1|0;if((j|0)==(d|0)){m=k;n=l;break}else{h=k;i=l}}if((n|0)>(e|0)&(m|0)<=(e|0)){o=f;break}f=((m|0)>(e|0)?-1:1)+f|0}c[a+44>>2]=o;o=c[b+16>>2]|0;p=+(o&2097151|0);c[a+48>>2]=~~+ud(+qd((o|0)<0?-p:p,(o>>>21&1023)+-788|0));o=c[b+20>>2]|0;p=+(o&2097151|0);c[a+52>>2]=~~+ud(+qd((o|0)<0?-p:p,(o>>>21&1023)+-788|0));return 0}function Bc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;e=i;f=b;g=f+56|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(g|0));h=d+4|0;j=c[h>>2]|0;if((j|0)>0){k=c[d+8>>2]|0;l=0;m=0;while(1){n=((c[k+(l<<2)>>2]|0)>0&1)+m|0;l=l+1|0;if((l|0)>=(j|0)){o=n;break}else m=n}}else o=0;c[b+4>>2]=j;m=b+8|0;c[m>>2]=o;c[b>>2]=c[d>>2];if((o|0)<=0){p=0;i=e;return p|0}l=d+8|0;k=vc(c[l>>2]|0,j,o)|0;j=o<<2;n=i;i=i+((1*j|0)+15&-16)|0;if(!k){q=c[b+16>>2]|0;if(q)yd(q);q=c[b+20>>2]|0;if(q)yd(q);q=c[b+24>>2]|0;if(q)yd(q);q=c[b+28>>2]|0;if(q)yd(q);q=c[b+32>>2]|0;if(q)yd(q);f=b;g=f+56|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(g|0));p=-1;i=e;return p|0}else r=0;do{f=k+(r<<2)|0;g=c[f>>2]|0;q=g>>>16|g<<16;g=q>>>8&16711935|q<<8&-16711936;q=g>>>4&252645135|g<<4&-252645136;g=q>>>2&858993459|q<<2&-858993460;c[f>>2]=g>>>1&1431655765|g<<1&-1431655766;c[n+(r<<2)>>2]=f;r=r+1|0}while((r|0)!=(o|0));rd(n,o,4,11);r=i;i=i+((1*j|0)+15&-16)|0;f=xd(j)|0;g=b+20|0;c[g>>2]=f;q=k;s=0;do{c[r+((c[n+(s<<2)>>2]|0)-q>>2<<2)>>2]=s;s=s+1|0}while((s|0)!=(o|0));t=0;do{c[f+(c[r+(t<<2)>>2]<<2)>>2]=c[k+(t<<2)>>2];t=t+1|0}while((t|0)!=(o|0));yd(k);c[b+16>>2]=xc(d,o,r)|0;o=xd(j)|0;c[b+24>>2]=o;j=c[h>>2]|0;d=(j|0)>0;if(d){k=c[l>>2]|0;t=0;f=0;while(1){if((c[k+(t<<2)>>2]|0)>0){c[o+(c[r+(f<<2)>>2]<<2)>>2]=t;u=f+1|0}else u=f;t=t+1|0;if((t|0)>=(j|0)){v=u;break}else f=u}u=b+28|0;c[u>>2]=xd(v)|0;if(d){d=j;j=0;v=0;while(1){f=c[(c[l>>2]|0)+(j<<2)>>2]|0;if((f|0)>0){a[(c[u>>2]|0)+(c[r+(v<<2)>>2]|0)>>0]=f;w=c[h>>2]|0;x=v+1|0}else{w=d;x=v}j=j+1|0;if((j|0)>=(w|0)){y=u;z=x;break}else{d=w;v=x}}}else{y=u;z=0}}else{u=b+28|0;c[u>>2]=xd(0)|0;y=u;z=0}u=c[m>>2]|0;if(!u)A=-4;else{m=u;u=0;while(1){m=m>>>1;if(!m){B=u;break}else u=u+1|0}A=B+-3|0}B=b+36|0;u=(A|0)<5?5:A;A=(u|0)>8?8:u;c[B>>2]=A;u=1<<A;m=zd(u,4)|0;c[b+32>>2]=m;x=b+40|0;c[x>>2]=0;a:do if((z|0)>0){b=c[y>>2]|0;v=0;w=A;d=0;while(1){j=b+d|0;h=a[j>>0]|0;r=h<<24>>24;if((v|0)<(r|0)){c[x>>2]=r;C=a[j>>0]|0}else C=h;h=C<<24>>24;if((w|0)>=(h|0)?(r=c[(c[g>>2]|0)+(d<<2)>>2]|0,l=r>>>16|r<<16,r=l>>>8&16711935|l<<8&-16711936,l=r>>>4&252645135|r<<4&-252645136,r=l>>>2&858993459|l<<2&-858993460,l=r>>>1&1431655765|r<<1&-1431655766,(w-h|0)!=31):0){r=d+1|0;f=h;h=0;do{c[m+((l|h<<f)<<2)>>2]=r;h=h+1|0;t=c[B>>2]|0;f=a[j>>0]|0}while((h|0)<(1<<t-f|0));D=t}else D=w;f=d+1|0;if((f|0)==(z|0)){E=D;break a}v=c[x>>2]|0;w=D;d=f}}else E=A;while(0);D=-2<<31-E;if((A|0)==31){p=0;i=e;return p|0}else{F=E;G=0;H=0;I=0}while(1){E=H<<32-F;A=E>>>16|E<<16;x=A>>>8&16711935|A<<8&-16711936;A=x>>>4&252645135|x<<4&-252645136;x=A>>>2&858993459|A<<2&-858993460;A=m+((x>>>1&1431655765|x<<1&-1431655766)<<2)|0;if(!(c[A>>2]|0)){x=I;while(1){C=x+1|0;if((C|0)>=(z|0)){J=x;break}if((c[(c[g>>2]|0)+(C<<2)>>2]|0)>>>0>E>>>0){J=x;break}else x=C}b:do if((z|0)>(G|0)){x=c[g>>2]|0;C=G;while(1){if(E>>>0<(c[x+(C<<2)>>2]&D)>>>0){K=C;break b}y=C+1|0;if((z|0)>(y|0))C=y;else{K=y;break}}}else K=G;while(0);E=z-K|0;c[A>>2]=(J>>>0>32767?-1073774592:J<<15|-2147483648)|(E>>>0>32767?32767:E);L=K;M=J}else{L=G;M=I}E=H+1|0;if((E|0)>=(u|0)){p=0;break}F=c[B>>2]|0;G=L;H=E;I=M}i=e;return p|0}function Cc(a){a=a|0;var b=0;b=a;a=b+48|0;do{c[b>>2]=0;b=b+4|0}while((b|0)<(a|0));return}function Dc(a){a=a|0;return (c[(c[(c[a+64>>2]|0)+104>>2]|0)+80>>2]|0)!=0|0}function Ec(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,h=0,i=0,j=0.0,k=0,l=0.0,m=0.0,n=0,o=0.0,p=0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0.0,I=0.0,J=0.0,K=0,L=0.0,M=0.0,N=0,O=0,P=0,Q=0,R=0.0,S=0.0,T=0,U=0,V=0,W=0.0,X=0.0,Y=0.0,Z=0.0,$=0.0,aa=0.0,ba=0.0,ca=0.0,da=0.0;e=a+-6|0;if((a|0)>6){a=b;f=c+(d+-8<<2)|0;h=c+((d>>1)+-8<<2)|0;while(1){i=f+24|0;j=+g[i>>2];k=h+24|0;l=+g[k>>2];m=j-l;n=f+28|0;o=+g[n>>2];p=h+28|0;q=o-+g[p>>2];g[i>>2]=l+j;g[n>>2]=+g[p>>2]+o;n=a+4|0;g[k>>2]=+g[a>>2]*m+ +g[n>>2]*q;g[p>>2]=+g[a>>2]*q-+g[n>>2]*m;n=f+16|0;m=+g[n>>2];p=h+16|0;q=+g[p>>2];o=m-q;k=f+20|0;j=+g[k>>2];i=h+20|0;l=j-+g[i>>2];g[n>>2]=q+m;g[k>>2]=+g[i>>2]+j;k=a+20|0;n=a+16|0;g[p>>2]=+g[n>>2]*o+ +g[k>>2]*l;g[i>>2]=+g[n>>2]*l-+g[k>>2]*o;k=f+8|0;o=+g[k>>2];n=h+8|0;l=+g[n>>2];j=o-l;i=f+12|0;m=+g[i>>2];p=h+12|0;q=m-+g[p>>2];g[k>>2]=l+o;g[i>>2]=+g[p>>2]+m;i=a+36|0;k=a+32|0;g[n>>2]=+g[k>>2]*j+ +g[i>>2]*q;g[p>>2]=+g[k>>2]*q-+g[i>>2]*j;j=+g[f>>2];q=+g[h>>2];m=j-q;i=f+4|0;o=+g[i>>2];k=h+4|0;l=o-+g[k>>2];g[f>>2]=q+j;g[i>>2]=+g[k>>2]+o;i=a+52|0;p=a+48|0;g[h>>2]=+g[p>>2]*m+ +g[i>>2]*l;g[k>>2]=+g[p>>2]*l-+g[i>>2]*m;h=h+-32|0;if(h>>>0<c>>>0)break;else{a=a+64|0;f=f+-32|0}}}if((e|0)>1){f=1;do{a=1<<f;if((f|0)!=31){h=d>>f;i=4<<f;p=h+-8|0;k=(h>>1)+-8|0;n=i+1|0;r=i<<1;s=r|1;t=i*3|0;u=t+1|0;v=i<<2;w=0;do{x=_(w,h)|0;y=c+(x<<2)|0;z=b;A=c+(p+x<<2)|0;B=c+(k+x<<2)|0;while(1){x=A+24|0;m=+g[x>>2];C=B+24|0;l=+g[C>>2];o=m-l;D=A+28|0;j=+g[D>>2];E=B+28|0;q=j-+g[E>>2];g[x>>2]=l+m;g[D>>2]=+g[E>>2]+j;D=z+4|0;g[C>>2]=+g[z>>2]*o+ +g[D>>2]*q;g[E>>2]=+g[z>>2]*q-+g[D>>2]*o;D=z+(i<<2)|0;E=A+16|0;o=+g[E>>2];C=B+16|0;q=+g[C>>2];j=o-q;x=A+20|0;m=+g[x>>2];F=B+20|0;l=m-+g[F>>2];g[E>>2]=q+o;g[x>>2]=+g[F>>2]+m;x=z+(n<<2)|0;g[C>>2]=+g[D>>2]*j+ +g[x>>2]*l;g[F>>2]=+g[D>>2]*l-+g[x>>2]*j;x=z+(r<<2)|0;D=A+8|0;j=+g[D>>2];F=B+8|0;l=+g[F>>2];m=j-l;C=A+12|0;o=+g[C>>2];E=B+12|0;q=o-+g[E>>2];g[D>>2]=l+j;g[C>>2]=+g[E>>2]+o;C=z+(s<<2)|0;g[F>>2]=+g[x>>2]*m+ +g[C>>2]*q;g[E>>2]=+g[x>>2]*q-+g[C>>2]*m;C=z+(t<<2)|0;m=+g[A>>2];q=+g[B>>2];o=m-q;x=A+4|0;j=+g[x>>2];E=B+4|0;l=j-+g[E>>2];g[A>>2]=q+m;g[x>>2]=+g[E>>2]+j;x=z+(u<<2)|0;g[B>>2]=+g[C>>2]*o+ +g[x>>2]*l;g[E>>2]=+g[C>>2]*l-+g[x>>2]*o;B=B+-32|0;if(B>>>0<y>>>0)break;else{z=z+(v<<2)|0;A=A+-32|0}}w=w+1|0}while((w|0)<(a|0))}f=f+1|0}while((f|0)!=(e|0))}if((d|0)>0)G=0;else return;do{e=c+(G<<2)|0;f=c+((G|30)<<2)|0;o=+g[f>>2];b=c+((G|14)<<2)|0;l=+g[b>>2];a=c+((G|31)<<2)|0;j=+g[a>>2];w=c+((G|15)<<2)|0;m=+g[w>>2];g[f>>2]=l+o;g[a>>2]=m+j;g[b>>2]=o-l;g[w>>2]=j-m;v=c+((G|28)<<2)|0;m=+g[v>>2];u=c+((G|12)<<2)|0;j=+g[u>>2];l=m-j;t=c+((G|29)<<2)|0;o=+g[t>>2];s=c+((G|13)<<2)|0;q=+g[s>>2];H=o-q;g[v>>2]=j+m;g[t>>2]=q+o;g[u>>2]=l*.9238795042037964-H*.3826834261417389;g[s>>2]=H*.9238795042037964+l*.3826834261417389;r=c+((G|26)<<2)|0;l=+g[r>>2];n=c+((G|10)<<2)|0;H=+g[n>>2];o=l-H;i=c+((G|27)<<2)|0;q=+g[i>>2];k=c+((G|11)<<2)|0;m=+g[k>>2];j=q-m;g[r>>2]=H+l;g[i>>2]=m+q;g[n>>2]=(o-j)*.7071067690849304;g[k>>2]=(j+o)*.7071067690849304;p=c+((G|24)<<2)|0;o=+g[p>>2];h=c+((G|8)<<2)|0;j=+g[h>>2];q=o-j;A=c+((G|25)<<2)|0;m=+g[A>>2];z=c+((G|9)<<2)|0;l=+g[z>>2];H=m-l;g[p>>2]=j+o;g[A>>2]=l+m;m=q*.3826834261417389-H*.9238795042037964;l=H*.3826834261417389+q*.9238795042037964;y=c+((G|22)<<2)|0;q=+g[y>>2];B=c+((G|6)<<2)|0;H=+g[B>>2];o=q-H;x=c+((G|7)<<2)|0;j=+g[x>>2];C=c+((G|23)<<2)|0;I=+g[C>>2];J=j-I;g[y>>2]=H+q;g[C>>2]=I+j;g[B>>2]=J;g[x>>2]=o;E=c+((G|4)<<2)|0;j=+g[E>>2];F=c+((G|20)<<2)|0;I=+g[F>>2];q=j-I;D=c+((G|5)<<2)|0;H=+g[D>>2];K=c+((G|21)<<2)|0;L=+g[K>>2];M=H-L;g[F>>2]=I+j;g[K>>2]=L+H;H=M*.9238795042037964+q*.3826834261417389;L=M*.3826834261417389-q*.9238795042037964;N=c+((G|2)<<2)|0;q=+g[N>>2];O=c+((G|18)<<2)|0;M=+g[O>>2];j=q-M;P=c+((G|3)<<2)|0;I=+g[P>>2];Q=c+((G|19)<<2)|0;R=+g[Q>>2];S=I-R;g[O>>2]=M+q;g[Q>>2]=R+I;I=(S+j)*.7071067690849304;R=(S-j)*.7071067690849304;j=+g[e>>2];T=c+((G|16)<<2)|0;S=+g[T>>2];q=j-S;U=c+((G|1)<<2)|0;M=+g[U>>2];V=c+((G|17)<<2)|0;W=+g[V>>2];X=M-W;Y=S+j;g[T>>2]=Y;j=W+M;g[V>>2]=j;M=X*.3826834261417389+q*.9238795042037964;W=X*.9238795042037964-q*.3826834261417389;q=W-l;X=M-m;S=M+m;m=W+l;l=X+q;W=q-X;X=+g[k>>2];q=R-X;M=+g[n>>2];Z=M-I;$=M+I;I=X+R;R=+g[u>>2];X=R-H;M=+g[s>>2];aa=M-L;ba=R+H;H=M+L;L=X-aa;M=aa+X;X=+g[b>>2];aa=X-J;R=+g[w>>2];ca=R-o;da=J+X;X=o+R;R=aa+q;o=aa-q;q=(L+l)*.7071067690849304;aa=(L-l)*.7071067690849304;g[B>>2]=q+R;g[E>>2]=R-q;q=(M-W)*.7071067690849304;R=ca-Z;g[e>>2]=q+o;g[N>>2]=o-q;q=(M+W)*.7071067690849304;W=ca+Z;g[P>>2]=R+aa;g[U>>2]=R-aa;g[x>>2]=W+q;g[D>>2]=W-q;q=da+$;W=da-$;$=S+ba;da=ba-S;g[b>>2]=q+$;g[u>>2]=q-$;$=H-m;q=X-I;g[h>>2]=W+$;g[n>>2]=W-$;$=H+m;m=X+I;g[k>>2]=q+da;g[z>>2]=q-da;g[w>>2]=m+$;g[s>>2]=m-$;$=+g[A>>2];m=j-$;da=+g[p>>2];q=Y-da;I=da+Y;Y=$+j;j=q+m;$=m-q;q=+g[Q>>2];m=+g[i>>2];da=q-m;X=+g[r>>2];H=+g[O>>2];W=X-H;S=H+X;X=m+q;q=+g[v>>2];m=+g[F>>2];H=q-m;ba=+g[t>>2];aa=+g[K>>2];R=ba-aa;Z=m+q;q=aa+ba;ba=H-R;aa=R+H;H=+g[f>>2];R=+g[y>>2];m=H-R;ca=+g[a>>2];M=+g[C>>2];o=ca-M;l=R+H;H=M+ca;ca=m+da;M=m-da;da=(ba+j)*.7071067690849304;m=(ba-j)*.7071067690849304;g[y>>2]=da+ca;g[F>>2]=ca-da;da=(aa-$)*.7071067690849304;ca=o-W;g[T>>2]=da+M;g[O>>2]=M-da;da=(aa+$)*.7071067690849304;$=o+W;g[Q>>2]=ca+m;g[V>>2]=ca-m;g[C>>2]=$+da;g[K>>2]=$-da;da=l+S;$=l-S;S=Z+I;l=Z-I;g[f>>2]=da+S;g[v>>2]=da-S;S=q-Y;da=H-X;g[p>>2]=$+S;g[r>>2]=$-S;S=q+Y;Y=H+X;g[i>>2]=da+l;g[A>>2]=da-l;g[a>>2]=Y+S;g[t>>2]=Y-S;G=G+32|0}while((G|0)<(d|0));return}function Fc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0,i=0,j=0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0;f=a>>1;h=b+(a<<2)|0;a=d;d=e;b=e+(f<<2)|0;while(1){i=(c[a>>2]|0)+f|0;j=(c[a+4>>2]|0)+f|0;k=+g[e+(i+1<<2)>>2];l=+g[e+(j+1<<2)>>2];m=k-l;n=+g[e+(i<<2)>>2];o=+g[e+(j<<2)>>2];p=o+n;q=+g[h>>2];r=+g[h+4>>2];s=r*m+p*q;t=r*p-q*m;j=b;b=b+-16|0;m=(l+k)*.5;k=(n-o)*.5;g[d>>2]=s+m;g[j+-8>>2]=m-s;g[d+4>>2]=t+k;g[j+-4>>2]=t-k;i=(c[a+8>>2]|0)+f|0;u=(c[a+12>>2]|0)+f|0;k=+g[e+(i+1<<2)>>2];t=+g[e+(u+1<<2)>>2];s=k-t;m=+g[e+(i<<2)>>2];o=+g[e+(u<<2)>>2];n=o+m;l=+g[h+8>>2];q=+g[h+12>>2];p=q*s+n*l;r=q*n-l*s;s=(t+k)*.5;k=(m-o)*.5;g[d+8>>2]=p+s;g[b>>2]=s-p;g[d+12>>2]=r+k;g[j+-12>>2]=r-k;d=d+16|0;if(d>>>0>=b>>>0)break;else{h=h+16|0;a=a+16|0}}return}function Gc(a,b,c,d,e,f,h){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;h=h|0;var i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0.0,v=0,w=0,x=0.0,y=0,z=0,A=0.0,B=0.0,C=0.0,D=0.0,E=0,F=0.0,G=0.0,H=0.0,I=0.0;i=_(b,a)|0;j=i<<1;k=(b|0)>0;if(k){l=(a<<2)+-1|0;m=a<<1;n=0;o=i;p=i*3|0;q=0;r=j;while(1){s=c+(o<<2)|0;t=c+(p<<2)|0;u=+g[t>>2]+ +g[s>>2];v=c+(q<<2)|0;w=c+(r<<2)|0;x=+g[w>>2]+ +g[v>>2];y=q<<2;g[d+(y<<2)>>2]=x+u;g[d+(l+y<<2)>>2]=x-u;z=y+m|0;g[d+(z+-1<<2)>>2]=+g[v>>2]-+g[w>>2];g[d+(z<<2)>>2]=+g[t>>2]-+g[s>>2];n=n+1|0;if((n|0)==(b|0))break;else{o=o+a|0;p=p+a|0;q=q+a|0;r=r+a|0}}}if((a|0)<2)return;if((a|0)!=2){if(k){r=a<<1;q=0;p=0;while(1){o=p<<2;n=2;m=p;l=o;s=o+r|0;do{o=m;m=m+2|0;t=l;l=l+2|0;z=s;s=s+-2|0;w=m+i|0;v=n+-2|0;u=+g[e+(v<<2)>>2];x=+g[c+(w+-1<<2)>>2];y=n+-1|0;A=+g[e+(y<<2)>>2];B=+g[c+(w<<2)>>2];C=B*A+x*u;D=B*u-A*x;E=w+i|0;x=+g[f+(v<<2)>>2];A=+g[c+(E+-1<<2)>>2];u=+g[f+(y<<2)>>2];B=+g[c+(E<<2)>>2];F=B*u+A*x;G=B*x-u*A;w=E+i|0;A=+g[h+(v<<2)>>2];u=+g[c+(w+-1<<2)>>2];x=+g[h+(y<<2)>>2];B=+g[c+(w<<2)>>2];H=B*x+u*A;I=B*A-x*u;u=H+C;x=H-C;C=I+D;H=D-I;I=+g[c+(m<<2)>>2];D=I+G;A=I-G;G=+g[c+(o+1<<2)>>2];I=G+F;B=G-F;g[d+((t|1)<<2)>>2]=u+I;g[d+(l<<2)>>2]=C+D;g[d+(z+-3<<2)>>2]=B-H;g[d+(s<<2)>>2]=x-A;z=l+r|0;g[d+(z+-1<<2)>>2]=H+B;g[d+(z<<2)>>2]=x+A;z=s+r|0;g[d+(z+-1<<2)>>2]=I-u;g[d+(z<<2)>>2]=C-D;n=n+2|0}while((n|0)<(a|0));q=q+1|0;if((q|0)==(b|0))break;else p=p+a|0}}if(a&1)return}p=a+-1+i|0;q=a<<2;r=a<<1;if(!k)return;k=0;h=p;f=p+j|0;j=a;p=a;while(1){D=+g[c+(h<<2)>>2];C=+g[c+(f<<2)>>2];u=(C+D)*-.7071067690849304;I=(D-C)*.7071067690849304;e=c+(p+-1<<2)|0;g[d+(j+-1<<2)>>2]=I+ +g[e>>2];n=j+r|0;g[d+(n+-1<<2)>>2]=+g[e>>2]-I;e=c+(h+i<<2)|0;g[d+(j<<2)>>2]=u-+g[e>>2];g[d+(n<<2)>>2]=+g[e>>2]+u;k=k+1|0;if((k|0)==(b|0))break;else{h=h+a|0;f=f+a|0;j=j+q|0;p=p+a|0}}return}function Hc(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0;h=_(b,a)|0;i=a<<1;j=(b|0)>0;if(j){k=i+-1|0;l=0;m=0;n=h;while(1){o=d+(m<<2)|0;p=d+(n<<2)|0;q=m<<1;g[e+(q<<2)>>2]=+g[p>>2]+ +g[o>>2];g[e+(k+q<<2)>>2]=+g[o>>2]-+g[p>>2];l=l+1|0;if((l|0)==(b|0))break;else{m=m+a|0;n=n+a|0}}}if((a|0)<2)return;if((a|0)!=2){if(j){n=0;m=0;l=h;while(1){k=m<<1;p=2;o=l;q=k+i|0;r=m;s=k;do{k=o;o=o+2|0;t=q;q=q+-2|0;u=r;r=r+2|0;v=s;s=s+2|0;w=+g[f+(p+-2<<2)>>2];x=+g[d+(k+1<<2)>>2];y=+g[f+(p+-1<<2)>>2];z=+g[d+(o<<2)>>2];A=z*y+x*w;B=z*w-y*x;k=d+(r<<2)|0;g[e+(s<<2)>>2]=B+ +g[k>>2];g[e+(q<<2)>>2]=B-+g[k>>2];k=d+(u+1<<2)|0;g[e+((v|1)<<2)>>2]=+g[k>>2]+A;g[e+(t+-3<<2)>>2]=+g[k>>2]-A;p=p+2|0}while((p|0)<(a|0));n=n+1|0;if((n|0)==(b|0))break;else{m=m+a|0;l=l+a|0}}}if(((a|0)%2|0|0)==1)return}l=a+-1|0;if(!j)return;j=0;m=a;n=h+l|0;h=l;while(1){g[e+(m<<2)>>2]=-+g[d+(n<<2)>>2];c[e+(m+-1<<2)>>2]=c[d+(h<<2)>>2];j=j+1|0;if((j|0)==(b|0))break;else{m=m+i|0;n=n+a|0;h=h+a|0}}return}function Ic(a,b,d,e,f,h,i,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;var m=0.0,n=0.0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0.0,N=0.0,O=0.0,P=0.0;m=6.2831854820251465/+(b|0);n=+Q(+m);o=+R(+m);p=b+1>>1;q=a+-1>>1;r=_(d,a)|0;s=_(b,a)|0;t=(a|0)==1;a:do if(!t){if((e|0)>0){u=0;do{c[k+(u<<2)>>2]=c[i+(u<<2)>>2];u=u+1|0}while((u|0)!=(e|0))}u=(b|0)>1;if(u){v=(d|0)>0;w=1;x=0;do{x=x+r|0;if(v){y=0;z=x;while(1){c[j+(z<<2)>>2]=c[h+(z<<2)>>2];y=y+1|0;if((y|0)==(d|0))break;else z=z+a|0}}w=w+1|0}while((w|0)!=(b|0))}w=0-a|0;if((q|0)>(d|0)){if(u){x=(d|0)>0;v=(a|0)>2;z=w;y=1;A=0;do{A=A+r|0;z=z+a|0;if(x){B=z+-1|0;C=0;D=A-a|0;do{D=D+a|0;if(v){E=2;F=B;G=D;do{H=F;F=F+2|0;I=l+(H+1<<2)|0;H=G+1|0;G=G+2|0;J=h+(H<<2)|0;K=l+(F<<2)|0;L=h+(G<<2)|0;g[j+(H<<2)>>2]=+g[L>>2]*+g[K>>2]+ +g[J>>2]*+g[I>>2];g[j+(G<<2)>>2]=+g[L>>2]*+g[I>>2]-+g[J>>2]*+g[K>>2];E=E+2|0}while((E|0)<(a|0))}C=C+1|0}while((C|0)!=(d|0))}y=y+1|0}while((y|0)!=(b|0))}}else if(u){y=(a|0)>2;v=(d|0)>0;A=w;z=1;x=0;do{A=A+a|0;x=x+r|0;if(y){C=2;D=A+-1|0;B=x;do{E=D;D=D+2|0;B=B+2|0;if(v){G=l+(E+1<<2)|0;E=l+(D<<2)|0;F=0;K=B;while(1){J=K+-1|0;I=h+(J<<2)|0;L=h+(K<<2)|0;g[j+(J<<2)>>2]=+g[L>>2]*+g[E>>2]+ +g[I>>2]*+g[G>>2];g[j+(K<<2)>>2]=+g[L>>2]*+g[G>>2]-+g[I>>2]*+g[E>>2];F=F+1|0;if((F|0)==(d|0))break;else K=K+a|0}}C=C+2|0}while((C|0)<(a|0))}z=z+1|0}while((z|0)!=(b|0))}z=_(r,b)|0;v=(p|0)>1;if((q|0)>=(d|0)){if(!v)break;x=(d|0)>0;A=(a|0)>2;y=1;w=0;u=z;while(1){w=w+r|0;u=u-r|0;if(x){C=0;B=w;D=u;while(1){if(A){K=2;F=B;E=D;do{G=F;F=F+2|0;I=G+1|0;G=j+(I<<2)|0;L=E+1|0;E=E+2|0;J=j+(L<<2)|0;g[h+(I<<2)>>2]=+g[J>>2]+ +g[G>>2];I=j+(F<<2)|0;H=j+(E<<2)|0;g[h+(L<<2)>>2]=+g[I>>2]-+g[H>>2];g[h+(F<<2)>>2]=+g[H>>2]+ +g[I>>2];g[h+(E<<2)>>2]=+g[J>>2]-+g[G>>2];K=K+2|0}while((K|0)<(a|0))}C=C+1|0;if((C|0)==(d|0))break;else{B=B+a|0;D=D+a|0}}}y=y+1|0;if((y|0)==(p|0))break a}}if(v){y=(a|0)>2;A=(d|0)>0;u=1;w=0;x=z;do{w=w+r|0;x=x-r|0;if(y){D=2;B=w;C=x;do{B=B+2|0;C=C+2|0;if(A){K=0;E=B-a|0;F=C-a|0;do{E=E+a|0;F=F+a|0;G=E+-1|0;J=j+(G<<2)|0;I=F+-1|0;H=j+(I<<2)|0;g[h+(G<<2)>>2]=+g[H>>2]+ +g[J>>2];G=j+(E<<2)|0;L=j+(F<<2)|0;g[h+(I<<2)>>2]=+g[G>>2]-+g[L>>2];g[h+(E<<2)>>2]=+g[L>>2]+ +g[G>>2];g[h+(F<<2)>>2]=+g[H>>2]-+g[J>>2];K=K+1|0}while((K|0)!=(d|0))}D=D+2|0}while((D|0)<(a|0))}u=u+1|0}while((u|0)!=(p|0))}}while(0);l=(e|0)>0;if(l){u=0;do{c[i+(u<<2)>>2]=c[k+(u<<2)>>2];u=u+1|0}while((u|0)!=(e|0))}u=_(e,b)|0;A=(p|0)>1;if(A){x=(d|0)>0;w=1;y=0;z=u;do{y=y+r|0;z=z-r|0;if(x){v=0;D=y-a|0;C=z-a|0;do{D=D+a|0;C=C+a|0;B=j+(D<<2)|0;K=j+(C<<2)|0;g[h+(D<<2)>>2]=+g[K>>2]+ +g[B>>2];g[h+(C<<2)>>2]=+g[K>>2]-+g[B>>2];v=v+1|0}while((v|0)!=(d|0))}w=w+1|0}while((w|0)!=(p|0));w=_(b+-1|0,e)|0;if(A){h=(p|0)>2;m=0.0;M=1.0;z=1;y=0;x=u;do{y=y+e|0;x=x-e|0;N=M;M=M*n-m*o;m=N*o+m*n;if(l){u=0;v=y;C=x;D=w;B=e;while(1){g[k+(v<<2)>>2]=+g[i+(B<<2)>>2]*M+ +g[i+(u<<2)>>2];g[k+(C<<2)>>2]=+g[i+(D<<2)>>2]*m;u=u+1|0;if((u|0)==(e|0))break;else{v=v+1|0;C=C+1|0;D=D+1|0;B=B+1|0}}}if(h){N=m;O=M;B=2;D=e;C=w;do{D=D+e|0;C=C-e|0;P=O;O=O*M-N*m;N=P*m+N*M;if(l){v=0;u=y;K=x;F=D;E=C;while(1){J=k+(u<<2)|0;g[J>>2]=+g[J>>2]+ +g[i+(F<<2)>>2]*O;J=k+(K<<2)|0;g[J>>2]=+g[J>>2]+ +g[i+(E<<2)>>2]*N;v=v+1|0;if((v|0)==(e|0))break;else{u=u+1|0;K=K+1|0;F=F+1|0;E=E+1|0}}}B=B+1|0}while((B|0)!=(p|0))}z=z+1|0}while((z|0)!=(p|0));if(A){z=1;x=0;do{x=x+e|0;if(l){y=0;w=x;while(1){h=k+(y<<2)|0;g[h>>2]=+g[h>>2]+ +g[i+(w<<2)>>2];y=y+1|0;if((y|0)==(e|0))break;else w=w+1|0}}z=z+1|0}while((z|0)!=(p|0))}}}if((a|0)<(d|0)){if((a|0)>0){z=(d|0)>0;e=0;do{if(z){i=0;k=e;x=e;while(1){c[f+(x<<2)>>2]=c[j+(k<<2)>>2];i=i+1|0;if((i|0)==(d|0))break;else{k=k+a|0;x=x+s|0}}}e=e+1|0}while((e|0)!=(a|0))}}else if((d|0)>0){e=(a|0)>0;z=0;x=0;k=0;while(1){if(e){i=0;l=x;w=k;while(1){c[f+(w<<2)>>2]=c[j+(l<<2)>>2];i=i+1|0;if((i|0)==(a|0))break;else{l=l+1|0;w=w+1|0}}}z=z+1|0;if((z|0)==(d|0))break;else{x=x+a|0;k=k+s|0}}}k=a<<1;x=_(r,b)|0;if(A){b=(d|0)>0;z=1;e=0;w=0;l=x;do{e=e+k|0;w=w+r|0;l=l-r|0;if(b){i=0;y=e;h=w;B=l;while(1){c[f+(y+-1<<2)>>2]=c[j+(h<<2)>>2];c[f+(y<<2)>>2]=c[j+(B<<2)>>2];i=i+1|0;if((i|0)==(d|0))break;else{y=y+s|0;h=h+a|0;B=B+a|0}}}z=z+1|0}while((z|0)!=(p|0))}if(t)return;t=0-a|0;if((q|0)>=(d|0)){if(!A)return;q=(d|0)<1|(a|0)<3;z=1;l=t;w=0;e=0;b=x;do{l=l+k|0;w=w+k|0;e=e+r|0;b=b-r|0;if(!q){B=0;h=l;y=w;i=e;C=b;while(1){D=2;do{E=D+i|0;F=j+(E+-1<<2)|0;K=D+C|0;u=j+(K+-1<<2)|0;v=D+y|0;g[f+(v+-1<<2)>>2]=+g[u>>2]+ +g[F>>2];J=a-D+h|0;g[f+(J+-1<<2)>>2]=+g[F>>2]-+g[u>>2];u=j+(E<<2)|0;E=j+(K<<2)|0;g[f+(v<<2)>>2]=+g[E>>2]+ +g[u>>2];g[f+(J<<2)>>2]=+g[E>>2]-+g[u>>2];D=D+2|0}while((D|0)<(a|0));B=B+1|0;if((B|0)==(d|0))break;else{h=h+s|0;y=y+s|0;i=i+a|0;C=C+a|0}}}z=z+1|0}while((z|0)!=(p|0));return}if(!A)return;A=(a|0)>2;z=(d|0)>0;b=1;e=t;t=0;w=0;l=x;do{e=e+k|0;t=t+k|0;w=w+r|0;l=l-r|0;if(A?(x=e+a|0,z):0){q=2;do{C=0;i=x-q|0;y=q+t|0;h=q+w|0;B=q+l|0;while(1){D=j+(h+-1<<2)|0;u=j+(B+-1<<2)|0;g[f+(y+-1<<2)>>2]=+g[u>>2]+ +g[D>>2];g[f+(i+-1<<2)>>2]=+g[D>>2]-+g[u>>2];u=j+(h<<2)|0;D=j+(B<<2)|0;g[f+(y<<2)>>2]=+g[D>>2]+ +g[u>>2];g[f+(i<<2)>>2]=+g[D>>2]-+g[u>>2];C=C+1|0;if((C|0)==(d|0))break;else{i=i+s|0;y=y+s|0;h=h+a|0;B=B+a|0}}q=q+2|0}while((q|0)<(a|0))}b=b+1|0}while((b|0)!=(p|0));return}function Jc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;e=c[b+28>>2]|0;if(!e){f=1;return f|0}g=c[e+3656>>2]|0;h=a;i=h+112|0;do{c[h>>2]=0;h=h+4|0}while((h|0)<(i|0));h=zd(1,136)|0;c[a+104>>2]=h;c[a+4>>2]=b;i=c[e+8>>2]|0;j=i+-1|0;if((i|0)==0|(j|0)==0)k=0;else{i=j;j=0;while(1){l=j+1|0;i=i>>>1;if(!i){k=l;break}else j=l}}c[h+44>>2]=k;k=zd(1,4)|0;c[h+12>>2]=k;j=zd(1,4)|0;i=h+16|0;c[i>>2]=j;l=zd(1,20)|0;c[k>>2]=l;c[j>>2]=zd(1,20)|0;sb(l,c[e>>2]>>g);l=e+4|0;sb(c[c[i>>2]>>2]|0,c[l>>2]>>g);g=c[e>>2]|0;i=g+-1|0;if((g|0)==0|(i|0)==0)m=0;else{j=i;i=0;while(1){k=i+1|0;j=j>>>1;if(!j){m=k;break}else i=k}}c[h+4>>2]=m+-6;m=c[l>>2]|0;i=m+-1|0;if((m|0)==0|(i|0)==0)n=0;else{m=i;i=0;while(1){j=i+1|0;m=m>>>1;if(!m){n=j;break}else i=j}}c[h+8>>2]=n+-6;a:do if(!d){n=e+2848|0;if((c[n>>2]|0)==0?(i=e+24|0,c[n>>2]=zd(c[i>>2]|0,56)|0,m=c[i>>2]|0,(m|0)>0):0){j=m;m=0;while(1){k=e+1824+(m<<2)|0;o=c[k>>2]|0;if(!o){p=j;break}if(Bc((c[n>>2]|0)+(m*56|0)|0,o)|0){q=23;break}yc(c[k>>2]|0);c[k>>2]=0;m=m+1|0;j=c[i>>2]|0;if((m|0)>=(j|0))break a}if((q|0)==23)p=c[i>>2]|0;if((p|0)>0){j=p;m=0;while(1){n=e+1824+(m<<2)|0;k=c[n>>2]|0;if(!k)r=j;else{yc(k);c[n>>2]=0;r=c[i>>2]|0}m=m+1|0;if((m|0)>=(r|0))break;else j=r}}Db(a);f=-1;return f|0}}else{xb(h+20|0,g);xb(h+32|0,c[l>>2]|0);j=e+2848|0;if(((c[j>>2]|0)==0?(m=e+24|0,i=zd(c[m>>2]|0,56)|0,c[j>>2]=i,(c[m>>2]|0)>0):0)?(Ac(i,c[e+1824>>2]|0)|0,(c[m>>2]|0)>1):0){i=1;do{Ac((c[j>>2]|0)+(i*56|0)|0,c[e+1824+(i<<2)>>2]|0)|0;i=i+1|0}while((i|0)<(c[m>>2]|0))}m=e+28|0;i=zd(c[m>>2]|0,52)|0;j=h+56|0;c[j>>2]=i;b:do if((c[m>>2]|0)>0){n=e+2868|0;k=b+8|0;o=i;s=0;while(1){t=c[e+2852+(s<<2)>>2]|0;Pb(o+(s*52|0)|0,t,n,(c[e+(c[t>>2]<<2)>>2]|0)/2|0,c[k>>2]|0);t=s+1|0;if((t|0)>=(c[m>>2]|0))break b;o=c[j>>2]|0;s=t}}while(0);c[a>>2]=1}while(0);g=c[l>>2]|0;c[a+16>>2]=g;r=c[b+4>>2]|0;b=r<<2;p=xd(b)|0;q=a+8|0;c[q>>2]=p;c[a+12>>2]=xd(b)|0;if((r|0)>0?(c[p>>2]=zd(g,4)|0,(r|0)>1):0){p=1;do{b=c[q>>2]|0;c[b+(p<<2)>>2]=zd(g,4)|0;p=p+1|0}while((p|0)<(r|0))}c[a+36>>2]=0;c[a+40>>2]=0;r=(c[l>>2]|0)/2|0;c[a+48>>2]=r;c[a+20>>2]=r;r=e+16|0;l=h+48|0;c[l>>2]=zd(c[r>>2]|0,4)|0;p=e+20|0;g=h+52|0;c[g>>2]=zd(c[p>>2]|0,4)|0;if((c[r>>2]|0)>0){h=0;do{q=$a[c[(c[328+(c[e+800+(h<<2)>>2]<<2)>>2]|0)+8>>2]&15](a,c[e+1056+(h<<2)>>2]|0)|0;c[(c[l>>2]|0)+(h<<2)>>2]=q;h=h+1|0}while((h|0)<(c[r>>2]|0))}if((c[p>>2]|0)>0)u=0;else{f=0;return f|0}do{r=$a[c[(c[336+(c[e+1312+(u<<2)>>2]<<2)>>2]|0)+8>>2]&15](a,c[e+1568+(u<<2)>>2]|0)|0;c[(c[g>>2]|0)+(u<<2)>>2]=r;u=u+1|0}while((u|0)<(c[p>>2]|0));f=0;return f|0}function Kc(a,b,d,e,f){a=a|0;b=+b;d=d|0;e=+e;f=+f;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0.0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,N=0,O=0.0,P=0;h=i;i=i+32480|0;j=h+32256|0;k=h+1792|0;l=h;m=i;i=i+((1*(d<<2)|0)+15&-16)|0;n=xd(68)|0;Fd(k|0,0,30464)|0;o=e>0.0;p=e<0.0;q=0;do{r=q<<2;s=0;do{t=s+r|0;if((t|0)<88)u=+g[408+(t<<2)>>2];else u=-30.0;v=t+1|0;if((v|0)<88){w=+g[408+(v<<2)>>2];if(u>w)x=w;else x=u}else if(u>-30.0)x=-30.0;else x=u;v=t+2|0;if((v|0)<88){w=+g[408+(v<<2)>>2];if(x>w)y=w;else y=x}else if(x>-30.0)y=-30.0;else y=x;v=t+3|0;if((v|0)<88){w=+g[408+(v<<2)>>2];if(y>w)z=w;else z=y}else if(y>-30.0)z=-30.0;else z=y;g[j+(s<<2)>>2]=z;s=s+1|0}while((s|0)!=56);s=33552+(q*1344|0)|0;Jd(k+(q*1792|0)+448|0,s|0,224)|0;Jd(k+(q*1792|0)+672|0,33552+(q*1344|0)+224|0,224)|0;Jd(k+(q*1792|0)+896|0,33552+(q*1344|0)+448|0,224)|0;Jd(k+(q*1792|0)+1120|0,33552+(q*1344|0)+672|0,224)|0;Jd(k+(q*1792|0)+1344|0,33552+(q*1344|0)+896|0,224)|0;Jd(k+(q*1792|0)+1568|0,33552+(q*1344|0)+1120|0,224)|0;Jd(k+(q*1792|0)|0,s|0,224)|0;Jd(k+(q*1792|0)+224|0,s|0,224)|0;if(o){s=0;do{if(p){r=0;do{v=16-r|0;w=+(((v|0)>-1?v:0-v|0)|0)*f+e;A=w<0.0?0.0:w;v=k+(q*1792|0)+(s*224|0)+(r<<2)|0;g[v>>2]=+g[v>>2]+(A>0.0?0.0:A);r=r+1|0}while((r|0)!=56)}else{r=0;do{v=16-r|0;A=+(((v|0)>-1?v:0-v|0)|0)*f+e;v=k+(q*1792|0)+(s*224|0)+(r<<2)|0;g[v>>2]=+g[v>>2]+(A<0.0?0.0:A);r=r+1|0}while((r|0)!=56)}s=s+1|0}while((s|0)!=8)}else{s=0;do{if(p){r=0;do{v=16-r|0;A=+(((v|0)>-1?v:0-v|0)|0)*f+e;v=k+(q*1792|0)+(s*224|0)+(r<<2)|0;g[v>>2]=+g[v>>2]+(A>0.0?0.0:A);r=r+1|0}while((r|0)!=56)}else{r=0;do{v=16-r|0;t=k+(q*1792|0)+(s*224|0)+(r<<2)|0;g[t>>2]=+g[t>>2]+(+(((v|0)>-1?v:0-v|0)|0)*f+e);r=r+1|0}while((r|0)!=56)}s=s+1|0}while((s|0)!=8)}A=+g[a+(q<<2)>>2];s=0;do{w=((s|0)<2?50.0:70.0-+(s|0)*10.0)+A;r=0;do{v=k+(q*1792|0)+(s*224|0)+(r<<2)|0;g[v>>2]=+g[v>>2]+w;r=r+1|0}while((r|0)!=56);Jd(l+(s*224|0)|0,j|0,224)|0;w=70.0-+(s|0)*10.0;r=0;do{v=l+(s*224|0)+(r<<2)|0;g[v>>2]=w+ +g[v>>2];r=r+1|0}while((r|0)!=56);B=0;do{w=+g[k+(q*1792|0)+(s*224|0)+(B<<2)>>2];r=l+(s*224|0)+(B<<2)|0;if(w>+g[r>>2])g[r>>2]=w;B=B+1|0}while((B|0)!=56);s=s+1|0}while((s|0)!=8);C=1;do{s=C+-1|0;r=0;do{A=+g[l+(s*224|0)+(r<<2)>>2];v=l+(C*224|0)+(r<<2)|0;if(A<+g[v>>2])g[v>>2]=A;r=r+1|0}while((r|0)!=56);D=0;do{A=+g[l+(C*224|0)+(D<<2)>>2];r=k+(q*1792|0)+(C*224|0)+(D<<2)|0;if(A<+g[r>>2])g[r>>2]=A;D=D+1|0}while((D|0)!=56);C=C+1|0}while((C|0)!=8);q=q+1|0}while((q|0)!=17);e=b;q=(d|0)>0;C=~d;D=0;do{l=xd(32)|0;c[n+(D<<2)>>2]=l;f=+(D|0);z=f*.5;B=~~+M(+(+X(+(f*.34657350182533264+4.135165354540845))/e));j=~~+Z(+(+Y(+(+(B|0)*b+1.0))*2.885390043258667+-11.931568145751953));a=~~+M(+(+Y(+(+(B+1|0)*b))*2.885390043258667+-11.931568145751953));B=(j|0)>(D|0)?D:j;j=(B|0)<0?0:B;B=(a|0)>16?16:a;a=(j|0)>(B|0);D=D+1|0;p=(D|0)<17;f=z+3.9657840728759766;o=0;do{r=xd(232)|0;c[l+(o<<2)>>2]=r;if(q){s=0;do{g[m+(s<<2)>>2]=999.0;s=s+1|0}while((s|0)!=(d|0))}if(!a){s=j;while(1){y=+(s|0)*.5;v=0;t=0;while(1){x=+(v|0)*.125+y;E=~~(+X(+((x+3.9032840728759766)*.6931470036506653))/e);F=~~(+X(+((x+4.028284072875977)*.6931470036506653))/e+1.0);G=(E|0)<0?0:E;H=(G|0)>(d|0)?d:G;G=(H|0)<(t|0)?H:t;H=(F|0)<0?0:F;if((G|0)<(d|0)?(G|0)<(((H|0)>(d|0)?d:H)|0):0){x=+g[k+(s*1792|0)+(o*224|0)+(v<<2)>>2];H=~((t|0)<(d|0)?t:d);I=(E|0)>0?~E:-1;E=(I|0)<(H|0)?H:I;I=(F|0)>0?~F:-1;F=((I|0)<(C|0)?C:I)-E|0;I=~(E+d);H=~E-(F>>>0>I>>>0?F:I)|0;I=G;do{F=m+(I<<2)|0;if(+g[F>>2]>x)g[F>>2]=x;I=I+1|0}while((I|0)!=(H|0));J=H}else J=G;v=v+1|0;if((v|0)==56){K=J;break}else t=J}if((K|0)<(d|0)){y=+g[k+(s*1792|0)+(o*224|0)+220>>2];t=K;do{v=m+(t<<2)|0;if(+g[v>>2]>y)g[v>>2]=y;t=t+1|0}while((t|0)!=(d|0))}if((s|0)<(B|0))s=s+1|0;else break}}if(p){s=0;t=0;while(1){y=+(s|0)*.125+z;v=~~(+X(+((y+3.9032840728759766)*.6931470036506653))/e);H=~~(+X(+((y+4.028284072875977)*.6931470036506653))/e+1.0);I=(v|0)<0?0:v;F=(I|0)>(d|0)?d:I;I=(F|0)<(t|0)?F:t;F=(H|0)<0?0:H;if((I|0)<(d|0)?(I|0)<(((F|0)>(d|0)?d:F)|0):0){y=+g[k+(D*1792|0)+(o*224|0)+(s<<2)>>2];F=~((t|0)<(d|0)?t:d);E=(v|0)>0?~v:-1;v=(E|0)<(F|0)?F:E;E=(H|0)>0?~H:-1;H=((E|0)<(C|0)?C:E)-v|0;E=~(v+d);F=~v-(H>>>0>E>>>0?H:E)|0;E=I;do{H=m+(E<<2)|0;if(+g[H>>2]>y)g[H>>2]=y;E=E+1|0}while((E|0)!=(F|0));L=F}else L=I;s=s+1|0;if((s|0)==56){N=L;break}else t=L}if((N|0)<(d|0)){y=+g[k+(D*1792|0)+(o*224|0)+220>>2];t=N;do{s=m+(t<<2)|0;if(+g[s>>2]>y)g[s>>2]=y;t=t+1|0}while((t|0)!=(d|0))}}t=l+(o<<2)|0;s=l+(o<<2)|0;F=l+(o<<2)|0;E=0;do{H=~~(+X(+((f+ +(E|0)*.125)*.6931470036506653))/e);do if((H|0)>=0)if((H|0)<(d|0)){c[(c[s>>2]|0)+(E+2<<2)>>2]=c[m+(H<<2)>>2];break}else{g[(c[F>>2]|0)+(E+2<<2)>>2]=-999.0;break}else g[(c[t>>2]|0)+(E+2<<2)>>2]=-999.0;while(0);E=E+1|0}while((E|0)!=56);do if(!(+g[r+8>>2]>-200.0))if(!(+g[r+12>>2]>-200.0))if(!(+g[r+16>>2]>-200.0))if(!(+g[r+20>>2]>-200.0))if(!(+g[r+24>>2]>-200.0))if(!(+g[r+28>>2]>-200.0))if(!(+g[r+32>>2]>-200.0))if(!(+g[r+36>>2]>-200.0))if(!(+g[r+40>>2]>-200.0))if(!(+g[r+44>>2]>-200.0))if(!(+g[r+48>>2]>-200.0))if(!(+g[r+52>>2]>-200.0))if(!(+g[r+56>>2]>-200.0))if(+g[r+60>>2]>-200.0)O=13.0;else{if(+g[r+64>>2]>-200.0){O=14.0;break}if(+g[r+68>>2]>-200.0){O=15.0;break}O=16.0}else O=12.0;else O=11.0;else O=10.0;else O=9.0;else O=8.0;else O=7.0;else O=6.0;else O=5.0;else O=4.0;else O=3.0;else O=2.0;else O=1.0;else O=0.0;while(0);g[r>>2]=O;E=55;while(1){if(+g[r+(E+2<<2)>>2]>-200.0){P=E;break}t=E+-1|0;if((t|0)>17)E=t;else{P=t;break}}g[r+4>>2]=+(P|0);o=o+1|0}while((o|0)!=8)}while((D|0)!=17);i=h;return n|0}function Lc(a,b,d,e,f,h){a=a|0;b=b|0;d=d|0;e=e|0;f=+f;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0,A=0.0,B=0.0,C=0.0,D=0,E=0.0,F=0,G=0,H=0,I=0.0,J=0.0,K=0.0,L=0,M=0.0,N=0.0,O=0.0,P=0.0,Q=0,R=0.0,S=0.0,T=0.0,U=0.0,V=0,W=0.0,X=0,Y=0.0;j=i;k=a<<2;l=i;i=i+((1*k|0)+15&-16)|0;m=i;i=i+((1*k|0)+15&-16)|0;n=i;i=i+((1*k|0)+15&-16)|0;o=i;i=i+((1*k|0)+15&-16)|0;p=i;i=i+((1*k|0)+15&-16)|0;q=+g[d>>2]+f;r=q<1.0?1.0:q;q=r*r*.5;s=q*r;g[l>>2]=q;g[m>>2]=q;g[n>>2]=0.0;g[o>>2]=s;g[p>>2]=0.0;if((a|0)>1){k=1;r=q;t=q;q=0.0;u=0.0;v=s;s=1.0;while(1){w=+g[d+(k<<2)>>2]+f;x=w<1.0?1.0:w;w=x*x;r=w+r;y=w*s;t=y+t;q=y*s+q;v=w*x+v;u=y*x+u;g[l+(k<<2)>>2]=r;g[m+(k<<2)>>2]=t;g[n+(k<<2)>>2]=q;g[o+(k<<2)>>2]=v;g[p+(k<<2)>>2]=u;k=k+1|0;if((k|0)==(a|0))break;else s=s+1.0}}k=c[b>>2]|0;d=k>>16;if((d|0)>-1){z=k;A=0.0;B=0.0;C=1.0;D=0;E=0.0}else{F=k;k=d;d=0;s=0.0;while(1){G=F&65535;H=0-k|0;u=+g[l+(H<<2)>>2]+ +g[l+(G<<2)>>2];v=+g[m+(G<<2)>>2]-+g[m+(H<<2)>>2];q=+g[n+(H<<2)>>2]+ +g[n+(G<<2)>>2];t=+g[o+(H<<2)>>2]+ +g[o+(G<<2)>>2];r=+g[p+(G<<2)>>2]-+g[p+(H<<2)>>2];x=t*q-r*v;y=r*u-t*v;t=q*u-v*v;v=(y*s+x)/t;g[e+(d<<2)>>2]=(v<0.0?0.0:v)-f;H=d+1|0;v=s+1.0;G=c[b+(H<<2)>>2]|0;k=G>>16;if((k|0)>-1){z=G;A=x;B=y;C=t;D=H;E=v;break}else{F=G;d=H;s=v}}}d=z&65535;if((d|0)<(a|0)){F=z;z=d;d=D;s=E;while(1){k=F>>16;v=+g[l+(z<<2)>>2]-+g[l+(k<<2)>>2];t=+g[m+(z<<2)>>2]-+g[m+(k<<2)>>2];y=+g[n+(z<<2)>>2]-+g[n+(k<<2)>>2];x=+g[o+(z<<2)>>2]-+g[o+(k<<2)>>2];u=+g[p+(z<<2)>>2]-+g[p+(k<<2)>>2];q=x*y-u*t;r=u*v-x*t;x=y*v-t*t;t=(r*s+q)/x;g[e+(d<<2)>>2]=(t<0.0?0.0:t)-f;k=d+1|0;t=s+1.0;F=c[b+(k<<2)>>2]|0;z=F&65535;if((z|0)>=(a|0)){I=q;J=r;K=x;L=k;M=t;break}else{d=k;s=t}}}else{I=A;J=B;K=C;L=D;M=E}if((L|0)<(a|0)){D=L;E=M;while(1){M=(E*J+I)/K;g[e+(D<<2)>>2]=(M<0.0?0.0:M)-f;D=D+1|0;if((D|0)==(a|0))break;else E=E+1.0}}if((h|0)<1){i=j;return}D=(h|0)/2|0;L=D-h|0;if((L|0)>-1){N=I;O=J;P=K;Q=0;R=0.0}else{d=h-D|0;z=D;F=L;L=0;K=0.0;while(1){b=0-F|0;J=+g[l+(b<<2)>>2]+ +g[l+(z<<2)>>2];I=+g[m+(z<<2)>>2]-+g[m+(b<<2)>>2];E=+g[n+(b<<2)>>2]+ +g[n+(z<<2)>>2];M=+g[o+(b<<2)>>2]+ +g[o+(z<<2)>>2];C=+g[p+(z<<2)>>2]-+g[p+(b<<2)>>2];B=M*E-C*I;A=C*J-M*I;M=E*J-I*I;I=(A*K+B)/M-f;b=e+(L<<2)|0;if(I<+g[b>>2])g[b>>2]=I;L=L+1|0;I=K+1.0;b=D+L|0;if((L|0)==(d|0)){N=B;O=A;P=M;Q=d;R=I;break}else{z=b;F=b-h|0;K=I}}}F=Q+D|0;if((F|0)<(a|0)){z=a-D|0;d=F;F=Q;K=R;while(1){L=d-h|0;I=+g[l+(d<<2)>>2]-+g[l+(L<<2)>>2];M=+g[m+(d<<2)>>2]-+g[m+(L<<2)>>2];A=+g[n+(d<<2)>>2]-+g[n+(L<<2)>>2];B=+g[o+(d<<2)>>2]-+g[o+(L<<2)>>2];J=+g[p+(d<<2)>>2]-+g[p+(L<<2)>>2];E=B*A-J*M;C=J*I-B*M;B=A*I-M*M;M=(C*K+E)/B-f;L=e+(F<<2)|0;if(M<+g[L>>2])g[L>>2]=M;L=F+1|0;M=K+1.0;if((L|0)==(z|0)){S=E;T=C;U=B;V=z;W=M;break}else{d=L+D|0;F=L;K=M}}}else{S=N;T=O;U=P;V=Q;W=R}if((V|0)<(a|0)){X=V;Y=W}else{i=j;return}while(1){W=(Y*T+S)/U-f;V=e+(X<<2)|0;if(W<+g[V>>2])g[V>>2]=W;X=X+1|0;if((X|0)==(a|0))break;else Y=Y+1.0}i=j;return}function Mc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,h=0,j=0,k=0,l=0,m=0.0,n=0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;e=i;f=d<<2;h=i;i=i+((1*f|0)+15&-16)|0;j=i;i=i+((1*f|0)+15&-16)|0;if((d|0)>0){k=0;l=0}else{i=e;return}while(1){do if((l|0)>=2){m=+g[a+(k<<2)>>2];f=l;while(1){n=f+-1|0;o=+g[j+(n<<2)>>2];if(m<o){p=f;q=8;break}if(!((f|0)>1?(k|0)<((c[h+(n<<2)>>2]|0)+b|0):0)){r=f;q=12;break}s=f+-2|0;if(!(o<=+g[j+(s<<2)>>2])){r=f;q=12;break}if((k|0)<((c[h+(s<<2)>>2]|0)+b|0))f=n;else{r=f;q=12;break}}if((q|0)==8){q=0;c[h+(p<<2)>>2]=k;g[j+(p<<2)>>2]=m;t=p;break}else if((q|0)==12){q=0;c[h+(r<<2)>>2]=k;g[j+(r<<2)>>2]=m;t=r;break}}else{c[h+(l<<2)>>2]=k;c[j+(l<<2)>>2]=c[a+(k<<2)>>2];t=l}while(0);f=t+1|0;k=k+1|0;if((k|0)==(d|0)){u=t;v=f;break}else l=f}if((u|0)<=-1){i=e;return}l=b+1|0;b=0;t=0;while(1){if((b|0)<(u|0)?(k=b+1|0,+g[j+(k<<2)>>2]>+g[j+(b<<2)>>2]):0)w=c[h+(k<<2)>>2]|0;else w=l+(c[h+(b<<2)>>2]|0)|0;if((t|0)<(((w|0)>(d|0)?d:w)|0)){k=c[j+(b<<2)>>2]|0;r=(w|0)<(d|0)?w:d;q=t;do{c[a+(q<<2)>>2]=k;q=q+1|0}while((q|0)!=(r|0));x=r}else x=t;b=b+1|0;if((b|0)==(v|0))break;else t=x}i=e;return}function Nc(a,b,d,e,f,j,l,m,n){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;j=j|0;l=l|0;m=m|0;n=n|0;var o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0.0,w=0,x=0.0,y=0.0,z=0,A=0.0,B=0.0,C=0,D=0.0,E=0,F=0.0,G=0,H=0.0;o=i;p=i;i=i+((1*(m<<2)|0)+15&-16)|0;if(!(c[a+500>>2]|0))q=m;else q=(c[a+504>>2]|0)-l|0;if((((q|0)>(m|0)?m:q)|0)>0){r=(j|0)==0;s=(q|0)<(m|0)?q:m;q=0;do{if(!(!r?(c[j+(q<<2)>>2]|0)!=0:0))t=9;do if((t|0)==9){t=0;u=+g[d+(q<<2)>>2]<0.0;v=+td(+O(+(+g[e+(q<<2)>>2]/+g[f+(q<<2)>>2])));if(u){c[n+(q<<2)>>2]=~~-v;break}else{c[n+(q<<2)>>2]=~~v;break}}while(0);q=q+1|0}while((q|0)!=(s|0));w=s}else w=0;if((w|0)>=(m|0)){x=0.0;i=o;return +x}s=(j|0)!=0;q=b-l|0;v=0.0;l=0;b=w;while(1){if(s?(c[j+(b<<2)>>2]|0)!=0:0){y=v;z=l}else t=15;do if((t|0)==15){t=0;w=e+(b<<2)|0;r=f+(b<<2)|0;A=+g[w>>2]/+g[r>>2];if(!(A<.25)|s&(b|0)<(q|0)){u=+g[d+(b<<2)>>2]<0.0;B=+td(+O(+A));C=~~(u?-B:B);c[n+(b<<2)>>2]=C;B=+(_(C,C)|0);g[w>>2]=B*+g[r>>2];y=v;z=l;break}else{c[p+(l<<2)>>2]=w;y=A+v;z=l+1|0;break}}while(0);b=b+1|0;if((b|0)==(m|0)){D=y;E=z;break}else{v=y;l=z}}if(!E){x=D;i=o;return +x}rd(p,E,4,12);if((E|0)<=0){x=D;i=o;return +x}z=e;y=+h[a+512>>3];v=D;a=0;while(1){e=c[p+(a<<2)>>2]|0;l=e-z>>2;if(!(v>=y)){F=v;G=0;H=0.0}else{F=v+-1.0;G=~~(c[k>>2]=c[d+(l<<2)>>2]&-2147483648|1065353216,+g[k>>2]);H=+g[f+(l<<2)>>2]}c[n+(l<<2)>>2]=G;g[e>>2]=H;a=a+1|0;if((a|0)==(E|0)){x=F;break}else v=F}i=o;return +x}function Oc(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var h=0,i=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0,p=0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0.0,L=0.0,M=0,N=0,O=0,P=0,Q=0,R=0;h=c[a>>2]|0;i=c[a+((b+-1|0)*56|0)+4>>2]|0;if((b|0)>0){j=+g[f+1108>>2];k=0.0;f=0;l=0.0;m=0.0;n=0.0;o=0.0;while(1){p=c[a+(f*56|0)+52>>2]|0;q=c[a+(f*56|0)+28>>2]|0;r=+(q+p|0)*j/+(q+1|0)+1.0;s=+(c[a+(f*56|0)+32>>2]|0)+m+ +(c[a+(f*56|0)+8>>2]|0)*r;t=+(c[a+(f*56|0)+36>>2]|0)+o+ +(c[a+(f*56|0)+12>>2]|0)*r;u=+(c[a+(f*56|0)+40>>2]|0)+l+ +(c[a+(f*56|0)+16>>2]|0)*r;v=+(c[a+(f*56|0)+48>>2]|0)+n+ +(c[a+(f*56|0)+24>>2]|0)*r;w=+(p|0)+k+r*+(q|0);f=f+1|0;if((f|0)==(b|0)){x=w;y=u;z=s;A=v;B=t;break}else{k=w;l=u;m=s;n=v;o=t}}}else{x=0.0;y=0.0;z=0.0;A=0.0;B=0.0}b=c[d>>2]|0;if((b|0)>-1){C=x+1.0;D=y+ +(_(h,h)|0);E=z+ +(h|0);F=+(_(b,h)|0)+A;G=+(b|0)+B}else{C=x;D=y;E=z;F=A;G=B}b=c[e>>2]|0;if((b|0)>-1){H=C+1.0;I=D+ +(_(i,i)|0);J=E+ +(i|0);K=+(_(b,i)|0)+F;L=+(b|0)+G}else{H=C;I=D;J=E;K=F;L=G}G=I*H-J*J;if(!(G>0.0)){c[d>>2]=0;c[e>>2]=0;M=1;return M|0}F=(L*I-J*K)/G;I=(K*H-J*L)/G;c[d>>2]=~~+td(I*+(h|0)+F);h=~~+td(I*+(i|0)+F);c[e>>2]=h;i=c[d>>2]|0;if((i|0)>1023){c[d>>2]=1023;N=c[e>>2]|0;O=1023}else{N=h;O=i}if((N|0)>1023){c[e>>2]=1023;P=c[d>>2]|0;Q=1023}else{P=O;Q=N}if((P|0)<0){c[d>>2]=0;R=c[e>>2]|0}else R=Q;if((R|0)>=0){M=0;return M|0}c[e>>2]=0;M=0;return M|0}function Pc(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0;g=i;h=c[b>>2]|0;j=c[h+8>>2]|0;k=b+16|0;l=c[c[k>>2]>>2]|0;m=c[a+36>>2]>>1;n=c[h+4>>2]|0;o=((n|0)<(m|0)?n:m)-(c[h>>2]|0)|0;if((o|0)<=0){i=g;return}m=(o|0)/(j|0)|0;o=i;i=i+((1*(e<<2)|0)+15&-16)|0;n=(e|0)>0;if(n){p=((l+-1+m|0)/(l|0)|0)<<2;q=0;do{c[o+(q<<2)>>2]=Ab(a,p)|0;q=q+1|0}while((q|0)!=(e|0))}q=b+8|0;if((c[q>>2]|0)<=0){i=g;return}p=(m|0)>0;r=a+4|0;a=h+16|0;s=b+28|0;t=(l|0)>0;u=b+20|0;b=n^1;v=0;a:while(1){if(p){w=1<<v;x=(v|0)!=0|b;y=0;z=0;while(1){if(!x){A=0;do{B=pc(c[k>>2]|0,r)|0;if((B|0)==-1){C=25;break a}if((B|0)>=(c[a>>2]|0)){C=25;break a}D=c[(c[s>>2]|0)+(B<<2)>>2]|0;c[(c[o+(A<<2)>>2]|0)+(z<<2)>>2]=D;A=A+1|0;if(!D){C=25;break a}}while((A|0)<(e|0))}b:do if(t&(y|0)<(m|0)){if(n){E=y;F=0}else{A=y;D=0;while(1){D=D+1|0;B=A+1|0;if(!((D|0)<(l|0)&(B|0)<(m|0))){G=B;break b}else A=B}}while(1){A=_(E,j)|0;D=0;do{B=(c[h>>2]|0)+A|0;H=c[(c[(c[o+(D<<2)>>2]|0)+(z<<2)>>2]|0)+(F<<2)>>2]|0;if(((c[h+24+(H<<2)>>2]&w|0)!=0?(I=c[(c[(c[u>>2]|0)+(H<<2)>>2]|0)+(v<<2)>>2]|0,(I|0)!=0):0)?(Va[f&7](I,(c[d+(D<<2)>>2]|0)+(B<<2)|0,r,j)|0)==-1:0){C=25;break a}D=D+1|0}while((D|0)<(e|0));F=F+1|0;D=E+1|0;if(!((F|0)<(l|0)&(D|0)<(m|0))){G=D;break}else E=D}}else G=y;while(0);if((G|0)<(m|0)){y=G;z=z+1|0}else break}}v=v+1|0;if((v|0)>=(c[q>>2]|0)){C=25;break}}if((C|0)==25){i=g;return}}function Qc(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0;g=i;i=i+1088|0;h=g+1056|0;j=g+1024|0;k=g+512|0;l=g;m=c[b>>2]|0;n=c[m+8>>2]|0;o=c[m+12>>2]|0;p=b+16|0;q=c[c[p>>2]>>2]|0;r=((c[m+4>>2]|0)-(c[m>>2]|0)|0)/(n|0)|0;Fd(k|0,0,512)|0;Fd(l|0,0,512)|0;s=b+8|0;t=c[s>>2]|0;if((t|0)<=0){i=g;return}u=(r|0)>0;v=(e|0)>0;w=(q|0)>1;x=b+36|0;y=(q|0)>0;z=b+20|0;A=b+32|0;b=0-q|0;B=t;t=0;while(1){if(u){C=(t|0)==0;D=1<<t;E=C&v;F=0;while(1){a:do if(E){if(w)G=0;else{H=0;while(1){I=c[(c[f+(H<<2)>>2]|0)+(F<<2)>>2]|0;J=c[p>>2]|0;if((I|0)<(c[J+4>>2]|0)){K=oc(J,I,a)|0;c[x>>2]=(c[x>>2]|0)+K}H=H+1|0;if((H|0)==(e|0))break a}}do{H=c[f+(G<<2)>>2]|0;K=1;I=c[H+(F<<2)>>2]|0;while(1){J=_(I,o)|0;L=K+F|0;if((L|0)<(r|0))M=(c[H+(L<<2)>>2]|0)+J|0;else M=J;K=K+1|0;if((K|0)==(q|0)){N=M;break}else I=M}I=c[p>>2]|0;if((N|0)<(c[I+4>>2]|0)){K=oc(I,N,a)|0;c[x>>2]=(c[x>>2]|0)+K}G=G+1|0}while((G|0)!=(e|0))}while(0);if(y&(F|0)<(r|0)){K=F-r|0;I=K>>>0<b>>>0?b:K;K=0-I|0;H=F;J=0;while(1){L=_(H,n)|0;O=(c[m>>2]|0)+L|0;if(v){L=0;do{P=f+(L<<2)|0;Q=c[P>>2]|0;R=c[Q+(H<<2)>>2]|0;if(C){S=l+(R<<2)|0;c[S>>2]=(c[S>>2]|0)+n}if((c[m+24+(R<<2)>>2]&D|0)!=0?(S=c[(c[(c[z>>2]|0)+(R<<2)>>2]|0)+(t<<2)>>2]|0,(S|0)!=0):0){R=c[d+(L<<2)>>2]|0;T=c[S>>2]|0;U=(n|0)/(T|0)|0;if((U|0)>0){V=S+48|0;W=S+52|0;X=S+44|0;Y=S+12|0;Z=S+4|0;$=T;aa=0;ba=0;while(1){ca=(_(ba,T)|0)+O|0;da=R+(ca<<2)|0;ea=c[V>>2]|0;fa=c[W>>2]|0;ga=c[X>>2]|0;ha=ga>>1;c[h>>2]=0;c[h+4>>2]=0;c[h+8>>2]=0;c[h+12>>2]=0;c[h+16>>2]=0;c[h+20>>2]=0;c[h+24>>2]=0;c[h+28>>2]=0;ia=($|0)>0;do if((fa|0)==1){if(!ia){ja=0;break}ka=ga+-1|0;la=0;ma=0;na=$;while(1){na=na+-1|0;oa=c[R+(ca+na<<2)>>2]|0;pa=oa-ea|0;if((pa|0)<(ha|0))qa=(ha-pa<<1)+-1|0;else qa=pa-ha<<1;pa=_(ma,ga)|0;ra=((qa|0)<0?0:(qa|0)>=(ga|0)?ka:qa)+pa|0;c[h+(na<<2)>>2]=oa;la=la+1|0;if((la|0)==($|0)){ja=ra;break}else ma=ra}}else{if(!ia){ja=0;break}ma=(fa>>1)-ea|0;la=ga+-1|0;na=0;ka=0;ra=$;while(1){ra=ra+-1|0;oa=(ma+(c[R+(ca+ra<<2)>>2]|0)|0)/(fa|0)|0;if((oa|0)<(ha|0))sa=(ha-oa<<1)+-1|0;else sa=oa-ha<<1;pa=_(ka,ga)|0;ta=((sa|0)<0?0:(sa|0)>=(ga|0)?la:sa)+pa|0;c[h+(ra<<2)>>2]=(_(oa,fa)|0)+ea;na=na+1|0;if((na|0)==($|0)){ja=ta;break}else ka=ta}}while(0);ha=c[(c[Y>>2]|0)+8>>2]|0;do if((c[ha+(ja<<2)>>2]|0)<1){c[j>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;c[j+16>>2]=0;c[j+20>>2]=0;c[j+24>>2]=0;c[j+28>>2]=0;ka=(_(ga+-1|0,fa)|0)+ea|0;na=c[Z>>2]|0;if((na|0)>0){ua=-1;va=0;wa=ja}else{xa=ja;break}while(1){do if((c[ha+(va<<2)>>2]|0)>0){if(ia){ra=0;la=0;while(1){ma=(c[j+(ra<<2)>>2]|0)-(c[R+(ca+ra<<2)>>2]|0)|0;ta=(_(ma,ma)|0)+la|0;ra=ra+1|0;if((ra|0)==($|0)){ya=ta;break}else la=ta}}else ya=0;if(!((ua|0)==-1|(ya|0)<(ua|0))){za=ua;Aa=wa;break};c[h>>2]=c[j>>2];c[h+4>>2]=c[j+4>>2];c[h+8>>2]=c[j+8>>2];c[h+12>>2]=c[j+12>>2];c[h+16>>2]=c[j+16>>2];c[h+20>>2]=c[j+20>>2];c[h+24>>2]=c[j+24>>2];c[h+28>>2]=c[j+28>>2];za=ya;Aa=va}else{za=ua;Aa=wa}while(0);la=c[j>>2]|0;if((la|0)<(ka|0)){Ba=j;Ca=la}else{la=j;ra=0;while(1){ra=ra+1|0;c[la>>2]=0;ta=j+(ra<<2)|0;ma=c[ta>>2]|0;if((ma|0)<(ka|0)){Ba=ta;Ca=ma;break}else la=ta}}if((Ca|0)>-1){la=Ca+fa|0;c[Ba>>2]=la;Da=la}else Da=Ca;c[Ba>>2]=0-Da;va=va+1|0;if((va|0)==(na|0)){xa=Aa;break}else{ua=za;wa=Aa}}}else xa=ja;while(0);if(ia&(xa|0)>-1){fa=da;ca=0;while(1){c[fa>>2]=(c[fa>>2]|0)-(c[h+(ca<<2)>>2]|0);ca=ca+1|0;if((ca|0)==($|0))break;else fa=fa+4|0}}fa=(oc(S,xa,a)|0)+aa|0;ca=ba+1|0;if((ca|0)==(U|0)){Ea=fa;break}$=c[S>>2]|0;aa=fa;ba=ca}Fa=c[P>>2]|0;Ga=Ea}else{Fa=Q;Ga=0}c[A>>2]=(c[A>>2]|0)+Ga;ba=k+(c[Fa+(H<<2)>>2]<<2)|0;c[ba>>2]=(c[ba>>2]|0)+Ga}L=L+1|0}while((L|0)!=(e|0))}J=J+1|0;if((J|0)==(K|0))break;else H=H+1|0}Ha=F-I|0}else Ha=F;if((Ha|0)<(r|0))F=Ha;else break}Ia=c[s>>2]|0}else Ia=B;t=t+1|0;if((t|0)>=(Ia|0))break;else B=Ia}i=g;return}function Rc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;e=c[b+40>>2]|0;f=ob(d,c[b+36>>2]|0)|0;do if((f|0)>-1){g=c[(c[b+32>>2]|0)+(f<<2)>>2]|0;if((g|0)<0){h=(c[b+8>>2]|0)-(g&32767)|0;i=g>>>15&32767;break}j=g+-1|0;pb(d,a[(c[b+28>>2]|0)+j>>0]|0);k=j;return k|0}else{h=c[b+8>>2]|0;i=0}while(0);f=ob(d,e)|0;j=(f|0)<0;if(j&(e|0)>1){g=e;while(1){l=g+-1|0;m=ob(d,l)|0;n=(m|0)<0;if(n&(l|0)>1)g=l;else{o=n;p=m;q=l;break}}}else{o=j;p=f;q=e}if(o){k=-1;return k|0}o=p>>>16|p<<16;p=o>>>8&16711935|o<<8&-16711936;o=p>>>4&252645135|p<<4&-252645136;p=o>>>2&858993459|o<<2&-858993460;o=p>>>1&1431655765|p<<1&-1431655766;p=h-i|0;if((p|0)>1){e=c[b+20>>2]|0;f=p;p=h;h=i;while(1){j=f>>1;g=(c[e+(j+h<<2)>>2]|0)>>>0>o>>>0;l=(g?0:j)+h|0;p=p-(g?j:0)|0;f=p-l|0;if((f|0)<=1){r=l;break}else h=l}}else r=i;i=a[(c[b+28>>2]|0)+r>>0]|0;if((i|0)>(q|0)){pb(d,q);k=-1;return k|0}else{pb(d,i);k=r;return k|0}return 0}function Sc(a,b){a=a|0;b=b|0;var d=0;d=c[c[a>>2]>>2]|0;a=c[c[b>>2]>>2]|0;return (d>>>0>a>>>0&1)-(d>>>0<a>>>0&1)|0}function Tc(a,b){a=a|0;b=b|0;var d=0.0,e=0.0;d=+g[c[a>>2]>>2];e=+g[c[b>>2]>>2];return (d<e&1)-(d>e&1)|0}function Uc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;d=a+836|0;e=c[a+840>>2]|0;lb(b,c[a>>2]|0,5);if((c[a>>2]|0)>0){f=a+4|0;g=0;h=-1;while(1){i=f+(g<<2)|0;lb(b,c[i>>2]|0,4);j=c[i>>2]|0;i=(h|0)<(j|0)?j:h;g=g+1|0;if((g|0)>=(c[a>>2]|0)){k=i;break}else h=i}if((k|0)>-1){h=a+128|0;g=a+192|0;f=a+256|0;i=a+320|0;j=0;while(1){lb(b,(c[h+(j<<2)>>2]|0)+-1|0,3);l=g+(j<<2)|0;lb(b,c[l>>2]|0,2);if(!((c[l>>2]|0)!=0?(lb(b,c[f+(j<<2)>>2]|0,8),(c[l>>2]|0)==31):0)){m=0;n=8}if((n|0)==8)while(1){n=0;lb(b,(c[i+(j<<5)+(m<<2)>>2]|0)+1|0,8);m=m+1|0;if((m|0)>=(1<<c[l>>2]|0))break;else n=8}if((j|0)==(k|0))break;else j=j+1|0}}}lb(b,(c[a+832>>2]|0)+-1|0,2);j=e+-1|0;if((e|0)==0|(j|0)==0){lb(b,0,4);o=0}else{e=j;k=0;while(1){n=k+1|0;e=e>>>1;if(!e){p=n;break}else k=n}lb(b,p,4);p=j;j=0;while(1){k=j+1|0;p=p>>>1;if(!p){o=k;break}else j=k}}j=c[a>>2]|0;if((j|0)<=0)return;p=a+4|0;k=a+128|0;e=j;j=0;n=0;m=0;while(1){j=(c[k+(c[p+(n<<2)>>2]<<2)>>2]|0)+j|0;if((m|0)<(j|0)){i=m;do{lb(b,c[d+(i+2<<2)>>2]|0,o);i=i+1|0}while((i|0)!=(j|0));q=c[a>>2]|0;r=j}else{q=e;r=m}n=n+1|0;if((n|0)>=(q|0))break;else{e=q;m=r}}return}function Vc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;d=i;i=i+272|0;e=d;f=c[a+28>>2]|0;a=zd(1,1120)|0;g=qb(b,5)|0;c[a>>2]=g;a:do if((g|0)>0){h=a+4|0;j=0;k=-1;while(1){l=qb(b,4)|0;c[h+(j<<2)>>2]=l;if((l|0)<0)break a;m=(k|0)<(l|0)?l:k;j=j+1|0;if((j|0)>=(c[a>>2]|0)){n=m;break}else k=m}if((n|0)>-1){k=a+128|0;j=a+192|0;h=a+256|0;m=f+24|0;l=a+320|0;o=0;while(1){c[k+(o<<2)>>2]=(qb(b,3)|0)+1;p=qb(b,2)|0;q=j+(o<<2)|0;c[q>>2]=p;if((p|0)<0)break a;if(!p)r=c[h+(o<<2)>>2]|0;else{p=qb(b,8)|0;c[h+(o<<2)>>2]=p;r=p}if((r|0)<0)break a;if((r|0)>=(c[m>>2]|0))break a;if((c[q>>2]|0)!=31){p=0;do{s=qb(b,8)|0;c[l+(o<<5)+(p<<2)>>2]=s+-1;if((s|0)<0)break a;p=p+1|0;if((s|0)>(c[m>>2]|0))break a}while((p|0)<(1<<c[q>>2]|0))}if((o|0)<(n|0))o=o+1|0;else{t=18;break}}}else t=18}else t=18;while(0);b:do if((t|0)==18?(c[a+832>>2]=(qb(b,2)|0)+1,n=qb(b,4)|0,(n|0)>=0):0){r=c[a>>2]|0;if((r|0)>0){f=a+4|0;g=a+128|0;o=a+836|0;m=1<<n;l=r;r=0;h=0;j=0;while(1){k=(c[g+(c[f+(h<<2)>>2]<<2)>>2]|0)+r|0;if((k|0)>63)break b;if((j|0)<(k|0)){q=j;while(1){p=qb(b,n)|0;c[o+(q+2<<2)>>2]=p;if(!((p|0)>-1&(p|0)<(m|0)))break b;p=q+1|0;if((p|0)<(k|0))q=p;else{u=p;break}}v=c[a>>2]|0;w=u}else{v=l;w=j}h=h+1|0;if((h|0)>=(v|0)){x=o;y=m;z=k;break}else{l=v;r=k;j=w}}}else{x=a+836|0;y=1<<n;z=0}c[x>>2]=0;c[a+840>>2]=y;j=z+2|0;if((z|0)>-2){r=0;do{c[e+(r<<2)>>2]=x+(r<<2);r=r+1|0}while((r|0)<(j|0))}rd(e,j,4,13);c:do if((j|0)>1){r=c[c[e>>2]>>2]|0;n=1;while(1){l=r;r=c[c[e+(n<<2)>>2]>>2]|0;n=n+1|0;if((l|0)==(r|0))break;if((n|0)>=(j|0))break c}if(!a)A=0;else break b;i=d;return A|0}while(0);A=a;i=d;return A|0}while(0);yd(a);A=0;i=d;return A|0}function Wc(a,b){a=a|0;b=b|0;return (c[c[a>>2]>>2]|0)-(c[c[b>>2]>>2]|0)|0}function Xc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;a=i;i=i+272|0;d=a;e=zd(1,1312)|0;c[e+1296>>2]=b;f=b+836|0;g=e+1288|0;c[g>>2]=c[b+840>>2];h=c[b>>2]|0;if((h|0)>0){j=b+4|0;k=b+128|0;l=0;m=0;while(1){n=(c[k+(c[j+(l<<2)>>2]<<2)>>2]|0)+m|0;l=l+1|0;if((l|0)>=(h|0)){o=n;break}else m=n}m=o+2|0;c[e+1284>>2]=m;if((o|0)>-2){p=m;q=o;r=7}else{rd(d,m,4,13);s=o}}else{c[e+1284>>2]=2;p=2;q=0;r=7}if((r|0)==7){r=0;do{c[d+(r<<2)>>2]=f+(r<<2);r=r+1|0}while((r|0)<(p|0));rd(d,p,4,13);r=f;o=e+260|0;m=0;do{c[o+(m<<2)>>2]=(c[d+(m<<2)>>2]|0)-r>>2;m=m+1|0}while((m|0)<(p|0));m=e+260|0;r=e+520|0;d=0;do{c[r+(c[m+(d<<2)>>2]<<2)>>2]=d;d=d+1|0}while((d|0)<(p|0));d=e+260|0;m=0;do{c[e+(m<<2)>>2]=c[f+(c[d+(m<<2)>>2]<<2)>>2];m=m+1|0}while((m|0)<(p|0));s=q}q=c[b+832>>2]|0;if((q|0)==2)c[e+1292>>2]=128;else if((q|0)==1)c[e+1292>>2]=256;else if((q|0)==3)c[e+1292>>2]=86;else if((q|0)==4)c[e+1292>>2]=64;if((s|0)<=0){i=a;return e|0}q=e+1032|0;b=e+780|0;p=0;do{m=p+2|0;d=c[f+(m<<2)>>2]|0;r=1;o=c[g>>2]|0;h=0;l=0;j=0;while(1){k=c[f+(h<<2)>>2]|0;n=(k|0)>(j|0)&(k|0)<(d|0);t=n?h:l;u=(k|0)<(o|0)&(k|0)>(d|0);v=u?h:r;h=h+1|0;if((h|0)>=(m|0)){w=v;x=t;break}else{r=v;o=u?k:o;l=t;j=n?k:j}}c[q+(p<<2)>>2]=x;c[b+(p<<2)>>2]=w;p=p+1|0}while((p|0)!=(s|0));i=a;return e|0}function Yc(a){a=a|0;if(a)yd(a);return}function Zc(a){a=a|0;if(a)yd(a);return}function _c(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;d=c[b+1296>>2]|0;e=c[(c[(c[(c[a+64>>2]|0)+4>>2]|0)+28>>2]|0)+2848>>2]|0;f=a+4|0;if((qb(f,1)|0)!=1){g=0;return g|0}h=b+1284|0;i=Ab(a,c[h>>2]<<2)|0;a=b+1292|0;j=(c[a>>2]|0)+-1|0;if(!j)k=0;else{l=j;j=0;while(1){m=j+1|0;l=l>>>1;if(!l){k=m;break}else j=m}}c[i>>2]=qb(f,k)|0;k=(c[a>>2]|0)+-1|0;if(!k)n=0;else{j=k;k=0;while(1){l=k+1|0;j=j>>>1;if(!j){n=l;break}else k=l}}c[i+4>>2]=qb(f,n)|0;a:do if((c[d>>2]|0)>0){n=0;k=2;b:while(1){j=c[d+4+(n<<2)>>2]|0;l=c[d+128+(j<<2)>>2]|0;m=c[d+192+(j<<2)>>2]|0;o=1<<m;if(m){p=pc(e+((c[d+256+(j<<2)>>2]|0)*56|0)|0,f)|0;if((p|0)==-1){g=0;q=29;break}else r=p}else r=0;if((l|0)>0){p=o+-1|0;o=r;s=0;do{t=c[d+320+(j<<5)+((o&p)<<2)>>2]|0;o=o>>m;if((t|0)>-1){u=pc(e+(t*56|0)|0,f)|0;c[i+(s+k<<2)>>2]=u;if((u|0)==-1){g=0;q=29;break b}}else c[i+(s+k<<2)>>2]=0;s=s+1|0}while((s|0)<(l|0))}n=n+1|0;if((n|0)>=(c[d>>2]|0))break a;else k=l+k|0}if((q|0)==29)return g|0}while(0);if((c[h>>2]|0)<=2){g=i;return g|0}q=b+1032|0;f=b+780|0;b=2;do{e=b+-2|0;r=q+(e<<2)|0;k=c[r>>2]|0;n=c[d+836+(k<<2)>>2]|0;s=f+(e<<2)|0;e=c[s>>2]|0;m=c[i+(k<<2)>>2]&32767;k=(c[i+(e<<2)>>2]&32767)-m|0;o=(_((k|0)>-1?k:0-k|0,(c[d+836+(b<<2)>>2]|0)-n|0)|0)/((c[d+836+(e<<2)>>2]|0)-n|0)|0;n=((k|0)<0?0-o|0:o)+m|0;m=(c[a>>2]|0)-n|0;o=i+(b<<2)|0;k=c[o>>2]|0;if(!k)c[o>>2]=n|32768;else{do if((k|0)<(((m|0)<(n|0)?m:n)<<1|0))if(!(k&1)){v=k>>1;break}else{v=0-(k+1>>1)|0;break}else if((m|0)>(n|0)){v=k-n|0;break}else{v=~(k-m);break}while(0);c[o>>2]=v+n&32767;m=i+(c[r>>2]<<2)|0;c[m>>2]=c[m>>2]&32767;m=i+(c[s>>2]<<2)|0;c[m>>2]=c[m>>2]&32767}b=b+1|0}while((b|0)<(c[h>>2]|0));g=i;return g|0}function $c(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0.0;f=c[b+1296>>2]|0;h=(c[(c[(c[(c[a+64>>2]|0)+4>>2]|0)+28>>2]|0)+(c[a+28>>2]<<2)>>2]|0)/2|0;if(!d){Fd(e|0,0,h<<2|0)|0;i=0;return i|0}a=c[f+832>>2]|0;j=_(a,c[d>>2]|0)|0;k=(j|0)<0?0:(j|0)>255?255:j;j=c[b+1284>>2]|0;if((j|0)>1){l=b+260|0;b=0;m=1;n=0;o=k;while(1){p=c[l+(m<<2)>>2]|0;q=c[d+(p<<2)>>2]|0;if((q&32767|0)==(q|0)){r=c[f+836+(p<<2)>>2]|0;p=_(a,q)|0;q=(p|0)<0?0:(p|0)>255?255:p;p=q-o|0;s=r-n|0;t=(p|0)/(s|0)|0;u=p>>31|1;v=_(t,s)|0;w=((p|0)>-1?p:0-p|0)-((v|0)>-1?v:0-v|0)|0;v=(h|0)>(r|0)?r:h;if((v|0)>(n|0)){p=e+(n<<2)|0;g[p>>2]=+g[p>>2]*+g[56400+(o<<2)>>2]}p=n+1|0;if((p|0)<(v|0)){x=p;p=0;y=o;while(1){z=p+w|0;A=(z|0)<(s|0);y=y+t+(A?0:u)|0;B=e+(x<<2)|0;g[B>>2]=+g[B>>2]*+g[56400+(y<<2)>>2];x=x+1|0;if((x|0)==(v|0)){C=r;D=r;E=q;break}else p=z-(A?0:s)|0}}else{C=r;D=r;E=q}}else{C=b;D=n;E=o}m=m+1|0;if((m|0)>=(j|0)){F=C;G=E;break}else{b=C;n=D;o=E}}}else{F=0;G=k}if((F|0)>=(h|0)){i=1;return i|0}H=+g[56400+(G<<2)>>2];G=F;do{F=e+(G<<2)|0;g[F>>2]=+g[F>>2]*H;G=G+1|0}while((G|0)!=(h|0));i=1;return i|0}function ad(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;d=c[a+28>>2]|0;a=xd(96)|0;e=qb(b,8)|0;c[a>>2]=e;f=qb(b,16)|0;c[a+4>>2]=f;g=qb(b,16)|0;c[a+8>>2]=g;c[a+12>>2]=qb(b,6)|0;c[a+16>>2]=qb(b,8)|0;h=qb(b,4)|0;i=a+20|0;c[i>>2]=h+1;a:do if((e|0)<1){if(!a){j=0;return j|0}}else if((f|0)>=1?!((h|0)<0|(g|0)<1):0){if((h|0)<=-1){j=a;return j|0}k=a+24|0;l=d+24|0;m=0;while(1){n=qb(b,8)|0;c[k+(m<<2)>>2]=n;if((n|0)<0)break a;if((n|0)>=(c[l>>2]|0))break a;o=c[d+1824+(n<<2)>>2]|0;if(!(c[o+12>>2]|0))break a;m=m+1|0;if((c[o>>2]|0)<1)break a;if((m|0)>=(c[i>>2]|0)){j=a;break}}return j|0}while(0);yd(a);j=0;return j|0}function bd(a,b){a=a|0;b=b|0;a=zd(1,32)|0;c[a+4>>2]=c[b>>2];c[a>>2]=c[b+8>>2];c[a+20>>2]=b;c[a+8>>2]=zd(2,4)|0;return a|0}function cd(a){a=a|0;if(a)yd(a);return}function dd(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;if(!a)return;b=a+8|0;d=c[b>>2]|0;if(d){e=c[d>>2]|0;if(!e)f=d;else{yd(e);f=c[b>>2]|0}e=c[f+4>>2]|0;if(!e)g=f;else{yd(e);g=c[b>>2]|0}yd(g)}yd(a);return}function ed(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,h=0,i=0,j=0.0,k=0.0,l=0,m=0,n=0;d=c[b+20>>2]|0;e=a+4|0;f=d+12|0;h=qb(e,c[f>>2]|0)|0;if((h|0)<=0){i=0;return i|0}j=+(c[d+16>>2]|0)*(+(h|0)/+((1<<c[f>>2])+-1|0));f=d+20|0;h=qb(e,uc(c[f>>2]|0)|0)|0;if((h|0)==-1){i=0;return i|0}if((h|0)>=(c[f>>2]|0)){i=0;return i|0}f=(c[(c[(c[(c[a+64>>2]|0)+4>>2]|0)+28>>2]|0)+2848>>2]|0)+((c[d+24+(h<<2)>>2]|0)*56|0)|0;h=b+4|0;b=Ab(a,((c[f>>2]|0)+(c[h>>2]|0)<<2)+4|0)|0;if((sc(f,b,e,c[h>>2]|0)|0)==-1){i=0;return i|0}e=c[h>>2]|0;if((e|0)>0){h=0;k=0.0;while(1){a:do if((h|0)<(e|0)){a=c[f>>2]|0;d=h;l=0;while(1){if((l|0)>=(a|0)){m=d;break a}n=b+(d<<2)|0;g[n>>2]=+g[n>>2]+k;n=d+1|0;if((n|0)<(e|0)){d=n;l=l+1|0}else{m=n;break}}}else m=h;while(0);if((m|0)<(e|0)){h=m;k=+g[b+(m+-1<<2)>>2]}else break}}g[b+(e<<2)>>2]=j;i=b;return i|0}function fd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0,i=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0,q=0,r=0,s=0;f=c[b+20>>2]|0;h=c[a+28>>2]|0;i=b+8|0;j=(c[i>>2]|0)+(h<<2)|0;if(!(c[j>>2]|0)){k=c[(c[(c[(c[a+64>>2]|0)+4>>2]|0)+28>>2]|0)+(h<<2)>>2]|0;a=(k|0)/2|0;l=c[b>>2]|0;m=+(c[f+4>>2]|0);c[j>>2]=xd((a<<2)+4|0)|0;if((k|0)>1){n=m*.5/+(a|0);o=+(l|0)/(+V(+(m*m*4.624999938585006e-09))*2.240000009536743+m*4.999999873689376e-05+ +V(+(m*3.699999942909926e-04))*13.100000381469727);k=c[(c[i>>2]|0)+(h<<2)>>2]|0;j=l;l=0;while(1){m=+(l|0)*n;p=~~+M(+((+V(+(m*m*1.8499999754340024e-08))*2.240000009536743+ +V(+(m*7.399999885819852e-04))*13.100000381469727+m*9.999999747378752e-05)*o));c[k+(l<<2)>>2]=(p|0)<(j|0)?p:j+-1|0;p=l+1|0;if((p|0)>=(a|0))break;j=c[b>>2]|0;l=p}q=k;r=(a|0)>1?a:1}else{q=c[(c[i>>2]|0)+(h<<2)>>2]|0;r=0}c[q+(r<<2)>>2]=-1;c[b+12+(h<<2)>>2]=a}if(!d){Fd(e|0,0,c[b+12+(h<<2)>>2]<<2|0)|0;s=0;return s|0}else{a=c[b+4>>2]|0;Lb(e,c[(c[i>>2]|0)+(h<<2)>>2]|0,c[b+12+(h<<2)>>2]|0,c[b>>2]|0,d,a,+g[d+(a<<2)>>2],+(c[f+16>>2]|0));s=1;return s|0}return 0}
+function gd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;if((c[b>>2]|0)>1){lb(d,1,1);lb(d,(c[b>>2]|0)+-1|0,4)}else lb(d,0,1);e=b+1156|0;if((c[e>>2]|0)>0){lb(d,1,1);lb(d,(c[e>>2]|0)+-1|0,8);if((c[e>>2]|0)>0){f=b+1160|0;g=a+4|0;h=b+2184|0;i=0;do{j=c[f+(i<<2)>>2]|0;k=c[g>>2]|0;l=k+-1|0;if((k|0)==0|(l|0)==0)m=0;else{k=l;l=0;while(1){n=l+1|0;k=k>>>1;if(!k){m=n;break}else l=n}}lb(d,j,m);l=c[h+(i<<2)>>2]|0;k=c[g>>2]|0;n=k+-1|0;if((k|0)==0|(n|0)==0)o=0;else{k=n;n=0;while(1){p=n+1|0;k=k>>>1;if(!k){o=p;break}else n=p}}lb(d,l,o);i=i+1|0}while((i|0)<(c[e>>2]|0))}}else lb(d,0,1);lb(d,0,2);e=c[b>>2]|0;if((e|0)>1){i=a+4|0;if((c[i>>2]|0)>0){a=b+4|0;o=0;do{lb(d,c[a+(o<<2)>>2]|0,4);o=o+1|0}while((o|0)<(c[i>>2]|0));q=c[b>>2]|0;r=17}}else{q=e;r=17}if((r|0)==17?(q|0)<=0:0)return;q=b+1028|0;r=b+1092|0;e=0;do{lb(d,0,8);lb(d,c[q+(e<<2)>>2]|0,8);lb(d,c[r+(e<<2)>>2]|0,8);e=e+1|0}while((e|0)<(c[b>>2]|0));return}function hd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;d=zd(1,3208)|0;e=c[a+28>>2]|0;Fd(d|0,0,3208)|0;f=qb(b,1)|0;a:do if((f|0)<0){if(!d){g=0;return g|0}}else{if(f){h=qb(b,4)|0;c[d>>2]=h+1;if((h|0)<0)break}else c[d>>2]=1;h=qb(b,1)|0;if((h|0)>=0){if(h){h=qb(b,8)|0;i=d+1156|0;c[i>>2]=h+1;if((h|0)<0)break;h=a+4|0;j=d+1160|0;k=d+2184|0;l=c[h>>2]|0;m=0;do{n=l+-1|0;if((l|0)==0|(n|0)==0)o=0;else{p=n;n=0;while(1){q=n+1|0;p=p>>>1;if(!p){o=q;break}else n=q}}n=qb(b,o)|0;c[j+(m<<2)>>2]=n;p=c[h>>2]|0;q=p+-1|0;if((p|0)==0|(q|0)==0)r=0;else{p=q;q=0;while(1){s=q+1|0;p=p>>>1;if(!p){r=s;break}else q=s}}q=qb(b,r)|0;c[k+(m<<2)>>2]=q;if((n|0)==(q|0)|(q|n|0)<0)break a;l=c[h>>2]|0;m=m+1|0;if(!((n|0)<(l|0)&(q|0)<(l|0)))break a}while((m|0)<(c[i>>2]|0))}if(!(qb(b,2)|0)){i=c[d>>2]|0;if((i|0)>1){m=a+4|0;if((c[m>>2]|0)>0){l=d+4|0;h=0;while(1){k=qb(b,4)|0;c[l+(h<<2)>>2]=k;j=c[d>>2]|0;h=h+1|0;if((k|0)<0|(k|0)>=(j|0))break a;if((h|0)>=(c[m>>2]|0)){t=j;u=20;break}}}}else{t=i;u=20}if((u|0)==20?(t|0)<=0:0){g=d;return g|0}m=d+1028|0;h=e+16|0;l=d+1092|0;j=e+20|0;k=0;while(1){qb(b,8)|0;q=qb(b,8)|0;c[m+(k<<2)>>2]=q;if((q|0)<0?1:(q|0)>=(c[h>>2]|0))break a;q=qb(b,8)|0;c[l+(k<<2)>>2]=q;k=k+1|0;if((q|0)<0?1:(q|0)>=(c[j>>2]|0))break a;if((k|0)>=(c[d>>2]|0)){g=d;break}}return g|0}}}while(0);yd(d);g=0;return g|0}function id(a){a=a|0;if(a)yd(a);return}function jd(a){a=a|0;var b=0,d=0,e=0,f=0,h=0,j=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0,B=0,C=0,D=0.0,E=0,F=0,G=0.0,H=0,I=0,J=0,K=0.0,L=0.0,M=0,N=0.0,O=0,P=0.0,Q=0.0,R=0.0,S=0.0,T=0.0,U=0,V=0,W=0.0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0;b=i;d=c[a+64>>2]|0;e=c[d+4>>2]|0;f=c[e+28>>2]|0;h=c[d+104>>2]|0;d=c[a+104>>2]|0;j=c[a+36>>2]|0;l=e+4|0;e=c[l>>2]<<2;m=i;i=i+((1*e|0)+15&-16)|0;n=Ab(a,e)|0;e=Ab(a,c[l>>2]<<2)|0;o=Ab(a,c[l>>2]<<2)|0;p=d+4|0;q=+g[p>>2];r=c[l>>2]|0;s=i;i=i+((1*(r<<2)|0)+15&-16)|0;t=a+28|0;u=c[t>>2]|0;v=c[f+544+(u<<2)>>2]|0;w=(c[h+56>>2]|0)+((((u|0)!=0?2:0)+(c[d+8>>2]|0)|0)*52|0)|0;x=a+40|0;c[x>>2]=u;if((r|0)>0){r=(j|0)/2|0;y=r<<2;z=+(((g[k>>2]=4.0/+(j|0),c[k>>2]|0)&2147483647)>>>0)*7.177114298428933e-07+-764.6162109375+.345;A=h+4|0;B=a+24|0;C=a+32|0;D=z+-764.6162109375;E=j+-1|0;F=(E|0)>1;G=z+-382.30810546875;z=q;H=0;while(1){I=c[(c[a>>2]|0)+(H<<2)>>2]|0;c[e+(H<<2)>>2]=Ab(a,y)|0;J=n+(H<<2)|0;c[J>>2]=Ab(a,y)|0;Kb(I,A,f,c[B>>2]|0,c[t>>2]|0,c[C>>2]|0);vb(c[c[h+12+(c[t>>2]<<2)>>2]>>2]|0,I,c[J>>2]|0);wb(h+20+((c[t>>2]|0)*12|0)|0,I);K=D+ +((c[I>>2]&2147483647)>>>0)*7.177114298428933e-07+.345;g[I>>2]=K;J=s+(H<<2)|0;g[J>>2]=K;if(F){L=K;M=1;while(1){N=+g[I+(M<<2)>>2];O=M+1|0;P=+g[I+(O<<2)>>2];Q=G+ +(((g[k>>2]=P*P+N*N,c[k>>2]|0)&2147483647)>>>0)*3.5885571492144663e-07+.345;g[I+(O>>1<<2)>>2]=Q;if(Q>L){g[J>>2]=Q;R=Q}else R=L;M=M+2|0;if((M|0)>=(E|0)){S=R;break}else L=R}}else S=K;if(S>0.0){g[J>>2]=0.0;T=0.0}else T=S;L=T>z?T:z;H=H+1|0;if((H|0)>=(c[l>>2]|0)){U=y;V=r;W=L;break}else z=L}}else{r=(j|0)/2|0;U=r<<2;V=r;W=q}r=Ab(a,U)|0;y=Ab(a,U)|0;U=c[l>>2]|0;a:do if((U|0)>0){H=h+48|0;if((j|0)>1)X=0;else{E=0;while(1){F=c[v+4+(E<<2)>>2]|0;C=c[n+(E<<2)>>2]|0;B=c[(c[a>>2]|0)+(E<<2)>>2]|0;A=B+(V<<2)|0;c[x>>2]=u;M=Ab(a,60)|0;I=o+(E<<2)|0;c[I>>2]=M;Y=M;Z=Y+60|0;do{c[Y>>2]=0;Y=Y+4|0}while((Y|0)<(Z|0));Rb(w,A,r);Sb(w,B,y,W,+g[s+(E<<2)>>2]);Tb(w,r,y,1,B,C,A);M=v+1028+(F<<2)|0;O=c[M>>2]|0;if((c[f+800+(O<<2)>>2]|0)!=1){_=-1;break}$=_b(a,c[(c[H>>2]|0)+(O<<2)>>2]|0,A,B)|0;c[(c[I>>2]|0)+28>>2]=$;if((Dc(a)|0)!=0?(c[(c[I>>2]|0)+28>>2]|0)!=0:0){Tb(w,r,y,2,B,C,A);$=_b(a,c[(c[H>>2]|0)+(c[M>>2]<<2)>>2]|0,A,B)|0;c[(c[I>>2]|0)+56>>2]=$;Tb(w,r,y,0,B,C,A);$=_b(a,c[(c[H>>2]|0)+(c[M>>2]<<2)>>2]|0,A,B)|0;c[c[I>>2]>>2]=$;$=c[I>>2]|0;O=$b(a,c[(c[H>>2]|0)+(c[M>>2]<<2)>>2]|0,c[$>>2]|0,c[$+28>>2]|0,9362)|0;c[(c[I>>2]|0)+4>>2]=O;O=c[I>>2]|0;$=$b(a,c[(c[H>>2]|0)+(c[M>>2]<<2)>>2]|0,c[O>>2]|0,c[O+28>>2]|0,18724)|0;c[(c[I>>2]|0)+8>>2]=$;$=c[I>>2]|0;O=$b(a,c[(c[H>>2]|0)+(c[M>>2]<<2)>>2]|0,c[$>>2]|0,c[$+28>>2]|0,28086)|0;c[(c[I>>2]|0)+12>>2]=O;O=c[I>>2]|0;$=$b(a,c[(c[H>>2]|0)+(c[M>>2]<<2)>>2]|0,c[O>>2]|0,c[O+28>>2]|0,37449)|0;c[(c[I>>2]|0)+16>>2]=$;$=c[I>>2]|0;O=$b(a,c[(c[H>>2]|0)+(c[M>>2]<<2)>>2]|0,c[$>>2]|0,c[$+28>>2]|0,46811)|0;c[(c[I>>2]|0)+20>>2]=O;O=c[I>>2]|0;$=$b(a,c[(c[H>>2]|0)+(c[M>>2]<<2)>>2]|0,c[O>>2]|0,c[O+28>>2]|0,56173)|0;c[(c[I>>2]|0)+24>>2]=$;$=c[I>>2]|0;O=$b(a,c[(c[H>>2]|0)+(c[M>>2]<<2)>>2]|0,c[$+28>>2]|0,c[$+56>>2]|0,9362)|0;c[(c[I>>2]|0)+32>>2]=O;O=c[I>>2]|0;$=$b(a,c[(c[H>>2]|0)+(c[M>>2]<<2)>>2]|0,c[O+28>>2]|0,c[O+56>>2]|0,18724)|0;c[(c[I>>2]|0)+36>>2]=$;$=c[I>>2]|0;O=$b(a,c[(c[H>>2]|0)+(c[M>>2]<<2)>>2]|0,c[$+28>>2]|0,c[$+56>>2]|0,28086)|0;c[(c[I>>2]|0)+40>>2]=O;O=c[I>>2]|0;$=$b(a,c[(c[H>>2]|0)+(c[M>>2]<<2)>>2]|0,c[O+28>>2]|0,c[O+56>>2]|0,37449)|0;c[(c[I>>2]|0)+44>>2]=$;$=c[I>>2]|0;O=$b(a,c[(c[H>>2]|0)+(c[M>>2]<<2)>>2]|0,c[$+28>>2]|0,c[$+56>>2]|0,46811)|0;c[(c[I>>2]|0)+48>>2]=O;O=c[I>>2]|0;$=$b(a,c[(c[H>>2]|0)+(c[M>>2]<<2)>>2]|0,c[O+28>>2]|0,c[O+56>>2]|0,56173)|0;c[(c[I>>2]|0)+52>>2]=$}E=E+1|0;$=c[l>>2]|0;if((E|0)>=($|0)){aa=H;ba=$;break a}}i=b;return _|0}while(1){E=c[v+4+(X<<2)>>2]|0;J=c[n+(X<<2)>>2]|0;$=c[(c[a>>2]|0)+(X<<2)>>2]|0;O=$+(V<<2)|0;c[x>>2]=u;M=Ab(a,60)|0;ca=o+(X<<2)|0;c[ca>>2]=M;Y=M;Z=Y+60|0;do{c[Y>>2]=0;Y=Y+4|0}while((Y|0)<(Z|0));I=0;do{g[$+(I+V<<2)>>2]=+((c[J+(I<<2)>>2]&2147483647)>>>0)*7.177114298428933e-07+-764.6162109375+.345;I=I+1|0}while((I|0)<(V|0));Rb(w,O,r);Sb(w,$,y,W,+g[s+(X<<2)>>2]);Tb(w,r,y,1,$,J,O);I=v+1028+(E<<2)|0;B=c[I>>2]|0;if((c[f+800+(B<<2)>>2]|0)!=1){_=-1;break}A=_b(a,c[(c[H>>2]|0)+(B<<2)>>2]|0,O,$)|0;c[(c[ca>>2]|0)+28>>2]=A;if((Dc(a)|0)!=0?(c[(c[ca>>2]|0)+28>>2]|0)!=0:0){Tb(w,r,y,2,$,J,O);A=_b(a,c[(c[H>>2]|0)+(c[I>>2]<<2)>>2]|0,O,$)|0;c[(c[ca>>2]|0)+56>>2]=A;Tb(w,r,y,0,$,J,O);A=_b(a,c[(c[H>>2]|0)+(c[I>>2]<<2)>>2]|0,O,$)|0;c[c[ca>>2]>>2]=A;A=c[ca>>2]|0;B=$b(a,c[(c[H>>2]|0)+(c[I>>2]<<2)>>2]|0,c[A>>2]|0,c[A+28>>2]|0,9362)|0;c[(c[ca>>2]|0)+4>>2]=B;B=c[ca>>2]|0;A=$b(a,c[(c[H>>2]|0)+(c[I>>2]<<2)>>2]|0,c[B>>2]|0,c[B+28>>2]|0,18724)|0;c[(c[ca>>2]|0)+8>>2]=A;A=c[ca>>2]|0;B=$b(a,c[(c[H>>2]|0)+(c[I>>2]<<2)>>2]|0,c[A>>2]|0,c[A+28>>2]|0,28086)|0;c[(c[ca>>2]|0)+12>>2]=B;B=c[ca>>2]|0;A=$b(a,c[(c[H>>2]|0)+(c[I>>2]<<2)>>2]|0,c[B>>2]|0,c[B+28>>2]|0,37449)|0;c[(c[ca>>2]|0)+16>>2]=A;A=c[ca>>2]|0;B=$b(a,c[(c[H>>2]|0)+(c[I>>2]<<2)>>2]|0,c[A>>2]|0,c[A+28>>2]|0,46811)|0;c[(c[ca>>2]|0)+20>>2]=B;B=c[ca>>2]|0;A=$b(a,c[(c[H>>2]|0)+(c[I>>2]<<2)>>2]|0,c[B>>2]|0,c[B+28>>2]|0,56173)|0;c[(c[ca>>2]|0)+24>>2]=A;A=c[ca>>2]|0;B=$b(a,c[(c[H>>2]|0)+(c[I>>2]<<2)>>2]|0,c[A+28>>2]|0,c[A+56>>2]|0,9362)|0;c[(c[ca>>2]|0)+32>>2]=B;B=c[ca>>2]|0;A=$b(a,c[(c[H>>2]|0)+(c[I>>2]<<2)>>2]|0,c[B+28>>2]|0,c[B+56>>2]|0,18724)|0;c[(c[ca>>2]|0)+36>>2]=A;A=c[ca>>2]|0;B=$b(a,c[(c[H>>2]|0)+(c[I>>2]<<2)>>2]|0,c[A+28>>2]|0,c[A+56>>2]|0,28086)|0;c[(c[ca>>2]|0)+40>>2]=B;B=c[ca>>2]|0;A=$b(a,c[(c[H>>2]|0)+(c[I>>2]<<2)>>2]|0,c[B+28>>2]|0,c[B+56>>2]|0,37449)|0;c[(c[ca>>2]|0)+44>>2]=A;A=c[ca>>2]|0;B=$b(a,c[(c[H>>2]|0)+(c[I>>2]<<2)>>2]|0,c[A+28>>2]|0,c[A+56>>2]|0,46811)|0;c[(c[ca>>2]|0)+48>>2]=B;B=c[ca>>2]|0;A=$b(a,c[(c[H>>2]|0)+(c[I>>2]<<2)>>2]|0,c[B+28>>2]|0,c[B+56>>2]|0,56173)|0;c[(c[ca>>2]|0)+52>>2]=A}X=X+1|0;A=c[l>>2]|0;if((X|0)>=(A|0)){aa=H;ba=A;break a}}i=b;return _|0}else{aa=h+48|0;ba=U}while(0);g[p>>2]=W;p=ba<<2;ba=i;i=i+((1*p|0)+15&-16)|0;U=i;i=i+((1*p|0)+15&-16)|0;p=(Dc(a)|0)!=0;X=h+44|0;y=a+24|0;r=a+32|0;s=f+2868|0;V=h+52|0;h=p?0:7;while(1){p=c[d+12+(h<<2)>>2]|0;lb(p,0,1);lb(p,u,c[X>>2]|0);if(c[t>>2]|0){lb(p,c[y>>2]|0,1);lb(p,c[r>>2]|0,1)}Y=c[l>>2]|0;if((Y|0)>0){Z=0;do{c[m+(Z<<2)>>2]=ac(p,a,c[(c[aa>>2]|0)+(c[v+1028+(c[v+4+(Z<<2)>>2]<<2)>>2]<<2)>>2]|0,c[(c[o+(Z<<2)>>2]|0)+(h<<2)>>2]|0,c[e+(Z<<2)>>2]|0)|0;Z=Z+1|0;x=c[l>>2]|0}while((Z|0)<(x|0));da=x}else da=Y;Ub(h,s,w,v,n,e,m,c[f+3240+((c[t>>2]|0)*60|0)+(h<<2)>>2]|0,da);if((c[v>>2]|0)>0){Z=0;do{x=c[v+1092+(Z<<2)>>2]|0;j=c[l>>2]|0;if((j|0)>0){H=j;j=0;A=0;while(1){if((c[v+4+(A<<2)>>2]|0)==(Z|0)){c[U+(j<<2)>>2]=(c[m+(A<<2)>>2]|0)!=0&1;c[ba+(j<<2)>>2]=c[e+(A<<2)>>2];ea=c[l>>2]|0;fa=j+1|0}else{ea=H;fa=j}A=A+1|0;if((A|0)>=(ea|0)){ga=fa;break}else{H=ea;j=fa}}}else ga=0;j=f+1312+(x<<2)|0;H=ab[c[(c[336+(c[j>>2]<<2)>>2]|0)+20>>2]&7](a,c[(c[V>>2]|0)+(x<<2)>>2]|0,ba,U,ga)|0;A=c[l>>2]|0;if((A|0)>0){ca=0;$=0;while(1){if((c[v+4+($<<2)>>2]|0)==(Z|0)){c[ba+(ca<<2)>>2]=c[e+($<<2)>>2];ha=ca+1|0}else ha=ca;$=$+1|0;if(($|0)>=(A|0)){ia=ha;break}else ca=ha}}else ia=0;_a[c[(c[336+(c[j>>2]<<2)>>2]|0)+24>>2]&3](p,a,c[(c[V>>2]|0)+(x<<2)>>2]|0,ba,U,ia,H,Z)|0;Z=Z+1|0}while((Z|0)<(c[v>>2]|0))}Z=(Dc(a)|0)!=0;if((h|0)<((Z?14:7)|0))h=h+1|0;else{_=0;break}}i=b;return _|0}function kd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0.0,F=0;d=i;e=c[a+64>>2]|0;f=c[e+4>>2]|0;h=c[f+28>>2]|0;j=c[e+104>>2]|0;e=a+28|0;k=c[h+(c[e>>2]<<2)>>2]|0;c[a+36>>2]=k;l=f+4|0;f=c[l>>2]<<2;m=i;i=i+((1*f|0)+15&-16)|0;n=i;i=i+((1*f|0)+15&-16)|0;o=i;i=i+((1*f|0)+15&-16)|0;p=i;i=i+((1*f|0)+15&-16)|0;f=c[l>>2]|0;if((f|0)>0){q=b+4|0;r=b+1028|0;s=j+48|0;t=k<<1&2147483646;u=0;do{v=c[r+(c[q+(u<<2)>>2]<<2)>>2]|0;w=$a[c[(c[328+(c[h+800+(v<<2)>>2]<<2)>>2]|0)+20>>2]&15](a,c[(c[s>>2]|0)+(v<<2)>>2]|0)|0;c[p+(u<<2)>>2]=w;c[o+(u<<2)>>2]=(w|0)!=0&1;Fd(c[(c[a>>2]|0)+(u<<2)>>2]|0,0,t|0)|0;u=u+1|0;w=c[l>>2]|0}while((u|0)<(w|0));x=w}else x=f;f=b+1156|0;u=c[f>>2]|0;if((u|0)>0){t=b+1160|0;s=b+2184|0;q=0;do{r=o+(c[t+(q<<2)>>2]<<2)|0;w=c[s+(q<<2)>>2]|0;if(!((c[r>>2]|0)==0?(c[o+(w<<2)>>2]|0)==0:0)){c[r>>2]=1;c[o+(w<<2)>>2]=1}q=q+1|0}while((q|0)<(u|0))}if((c[b>>2]|0)>0){q=b+1092|0;s=j+52|0;t=b+4|0;w=x;x=0;while(1){if((w|0)>0){r=w;v=0;y=0;while(1){if((c[t+(y<<2)>>2]|0)==(x|0)){c[n+(v<<2)>>2]=(c[o+(y<<2)>>2]|0)!=0&1;c[m+(v<<2)>>2]=c[(c[a>>2]|0)+(y<<2)>>2];z=c[l>>2]|0;A=v+1|0}else{z=r;A=v}y=y+1|0;if((y|0)>=(z|0)){B=A;break}else{r=z;v=A}}}else B=0;v=c[q+(x<<2)>>2]|0;ab[c[(c[336+(c[h+1312+(v<<2)>>2]<<2)>>2]|0)+28>>2]&7](a,c[(c[s>>2]|0)+(v<<2)>>2]|0,m,n,B)|0;v=x+1|0;if((v|0)>=(c[b>>2]|0))break;w=c[l>>2]|0;x=v}C=c[f>>2]|0}else C=u;if((C|0)>0){u=b+1160|0;f=c[a>>2]|0;x=b+2184|0;w=(k|0)/2|0;B=(k|0)>1;k=C;do{C=k;k=k+-1|0;n=c[f+(c[u+(k<<2)>>2]<<2)>>2]|0;m=c[f+(c[x+(k<<2)>>2]<<2)>>2]|0;if(B){s=0;do{q=n+(s<<2)|0;D=+g[q>>2];A=m+(s<<2)|0;E=+g[A>>2];z=E>0.0;do if(D>0.0)if(z){g[q>>2]=D;g[A>>2]=D-E;break}else{g[A>>2]=D;g[q>>2]=E+D;break}else if(z){g[q>>2]=D;g[A>>2]=E+D;break}else{g[A>>2]=D;g[q>>2]=D-E;break}while(0);s=s+1|0}while((s|0)<(w|0))}}while((C|0)>1)}if((c[l>>2]|0)<=0){i=d;return 0}w=b+4|0;B=b+1028|0;b=j+48|0;k=0;do{x=c[B+(c[w+(k<<2)>>2]<<2)>>2]|0;Va[c[(c[328+(c[h+800+(x<<2)>>2]<<2)>>2]|0)+24>>2]&7](a,c[(c[b>>2]|0)+(x<<2)>>2]|0,c[p+(k<<2)>>2]|0,c[(c[a>>2]|0)+(k<<2)>>2]|0)|0;k=k+1|0;x=c[l>>2]|0}while((k|0)<(x|0));F=x;if((F|0)<=0){i=d;return 0}F=0;do{k=c[(c[a>>2]|0)+(F<<2)>>2]|0;ub(c[c[j+12+(c[e>>2]<<2)>>2]>>2]|0,k,k);F=F+1|0}while((F|0)<(c[l>>2]|0));i=d;return 0}function ld(){Xb(57432);Vb(57464);return}function md(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+32|0;e=d;pd(e,a,b);if(!(c[14356]|0))c[e+8>>2]=1;if(Zb(57432,57464,e)|0){Da(57704)|0;f=0;i=d;return f|0}e=(c[14356]|0)+1|0;c[14356]=e;if((e|0)<3){f=1;i=d;return f|0}Eb(57480,57432)|0;zb(57480,57592)|0;Ba(c[14359]|0,c[14360]|0);f=1;i=d;return f|0}function nd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;i=i+48|0;e=d+32|0;f=d;g=d+36|0;pd(f,a,b);b=Mb(57592,f)|0;if(!b){Fb(57480,57592)|0;f=Gb(57480,g)|0;Fa(c[g>>2]|0,c[14359]|0,f|0);Hb(57480,f)|0;h=1;i=d;return h|0}else{c[e>>2]=b;Ea(57728,e|0)|0;h=0;i=d;return h|0}return 0}function od(){if(!(c[14356]|0))return;Yb(57432);Db(57480);Cb(57592)|0;Wb(57464);return}function pd(a,b,d){a=a|0;b=b|0;d=d|0;c[a>>2]=b;c[a+4>>2]=d;d=a+8|0;c[d>>2]=0;c[d+4>>2]=0;c[d+8>>2]=0;c[d+12>>2]=0;c[d+16>>2]=0;c[d+20>>2]=0;return}function qd(a,b){a=+a;b=b|0;return +(+vd(a,b))}function rd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0,da=0;f=i;i=i+688|0;g=f+424|0;h=f+192|0;j=f;k=_(d,b)|0;if(!k){i=f;return}b=k-d|0;c[j+4>>2]=d;c[j>>2]=d;l=d;m=d;n=2;while(1){o=l+d+m|0;c[j+(n<<2)>>2]=o;if(o>>>0<k>>>0){p=m;m=o;n=n+1|0;l=p}else break}l=0-d|0;n=a+b|0;if((b|0)>0){b=(d|0)==0;m=n;k=1;p=0;o=a;q=1;while(1){do if((k&3|0)!=3){r=q+-1|0;if((c[j+(r<<2)>>2]|0)>>>0<(m-o|0)>>>0){c[h>>2]=o;a:do if((q|0)>1){s=q;t=o;u=o;v=1;while(1){w=t+l|0;x=s+-2|0;y=t+(0-((c[j+(x<<2)>>2]|0)+d))|0;if(($a[e&15](u,y)|0)>-1?($a[e&15](u,w)|0)>-1:0){z=v;break}A=v+1|0;B=h+(v<<2)|0;if(($a[e&15](y,w)|0)>-1){c[B>>2]=y;C=y;D=s+-1|0}else{c[B>>2]=w;C=w;D=x}if((D|0)<=1){z=A;break}s=D;t=C;u=c[h>>2]|0;v=A}if((z|0)>=2?(v=h+(z<<2)|0,c[v>>2]=g,!b):0){u=d;t=g;while(1){s=u>>>0>256?256:u;A=c[h>>2]|0;Jd(t|0,A|0,s|0)|0;x=A;A=0;do{w=A;A=A+1|0;B=x;x=c[h+(A<<2)>>2]|0;Jd(B|0,x|0,s|0)|0;c[h+(w<<2)>>2]=B+s}while((A|0)!=(z|0));if((u|0)==(s|0))break a;u=u-s|0;t=c[v>>2]|0}}}while(0)}else sd(o,d,e,k,p,q,0,j);if((q|0)==1){E=k<<1;F=k>>>31|p<<1;G=0;break}else{v=r>>>0>31;t=v?0:k;u=v?q+-33|0:r;E=t<<u;F=t>>>(32-u|0)|(v?k:p)<<u;G=1;break}}else{c[h>>2]=o;b:do if((q|0)>1){u=q;v=o;t=o;A=1;while(1){x=v+l|0;B=u+-2|0;w=v+(0-((c[j+(B<<2)>>2]|0)+d))|0;if(($a[e&15](t,w)|0)>-1?($a[e&15](t,x)|0)>-1:0){H=A;break}y=A+1|0;I=h+(A<<2)|0;if(($a[e&15](w,x)|0)>-1){c[I>>2]=w;J=w;K=u+-1|0}else{c[I>>2]=x;J=x;K=B}if((K|0)<=1){H=y;break}u=K;v=J;t=c[h>>2]|0;A=y}if((H|0)>=2?(A=h+(H<<2)|0,c[A>>2]=g,!b):0){t=d;v=g;while(1){u=t>>>0>256?256:t;y=c[h>>2]|0;Jd(v|0,y|0,u|0)|0;B=y;y=0;do{x=y;y=y+1|0;I=B;B=c[h+(y<<2)>>2]|0;Jd(I|0,B|0,u|0)|0;c[h+(x<<2)>>2]=I+u}while((y|0)!=(H|0));if((t|0)==(u|0))break b;t=t-u|0;v=c[A>>2]|0}}}while(0);E=k>>>2|p<<30;F=p>>>2;G=q+2|0}while(0);r=E|1;A=o+d|0;if(A>>>0<n>>>0){k=r;p=F;o=A;q=G}else{L=F;M=r;N=A;O=G;break}}}else{L=0;M=1;N=a;O=1}sd(N,d,e,M,L,O,0,j);if((L|0)==0&((M|0)==1&(O|0)==1)){i=f;return}else{P=M;Q=L;R=N;S=O}while(1){if((S|0)>=2){O=P>>>30;N=S+-2|0;L=(P<<1&2147483646|O<<31)^3;M=(O|Q<<2)>>>1;sd(R+(0-((c[j+(N<<2)>>2]|0)+d))|0,d,e,L,M,S+-1|0,1,j);a=M<<1|O&1;O=L<<1|1;L=R+l|0;sd(L,d,e,O,a,N,1,j);P=O;Q=a;R=L;S=N;continue}N=P+-1|0;do if(N){if(!(N&1)){L=N;a=0;while(1){O=a+1|0;L=L>>>1;if(L&1){T=O;break}else a=O}if(T)U=T;else V=51}else V=51;if((V|0)==51){V=0;if(!Q){W=64;V=56;break}if(!(Q&1)){X=Q;Y=0}else{Z=0;$=P;aa=Q;ba=0;break}while(1){a=Y+1|0;X=X>>>1;if(X&1){ca=a;da=Y;break}else Y=a}if(!ca){Z=0;$=P;aa=Q;ba=0;break}else U=da+33|0}if(U>>>0>31){W=U;V=56}else{Z=U;$=P;aa=Q;ba=U}}else{W=32;V=56}while(0);if((V|0)==56){V=0;Z=W+-32|0;$=Q;aa=0;ba=W}P=aa<<32-Z|$>>>Z;Q=aa>>>Z;S=ba+S|0;if((Q|0)==0&((P|0)==1&(S|0)==1))break;else R=R+l|0}i=f;return}function sd(a,b,d,e,f,g,h,j){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0;k=i;i=i+720|0;l=k+456|0;m=k+228|0;n=k;c[n>>2]=a;o=0-b|0;a:do if((f|0)!=0|(e|0)!=1?(p=a+(0-(c[j+(g<<2)>>2]|0))|0,($a[d&15](p,a)|0)>=1):0){q=a;r=g;s=h;t=p;p=f;u=1;v=e;while(1){if((s|0)==0&(r|0)>1){w=c[j+(r+-2<<2)>>2]|0;if(($a[d&15](q+o|0,t)|0)>-1){x=q;y=r;z=u;break a}if(($a[d&15](q+(0-(w+b))|0,t)|0)>-1){x=q;y=r;z=u;break a}}w=u+1|0;c[n+(u<<2)>>2]=t;A=v+-1|0;do if(A){if(!(A&1)){B=A;C=0;while(1){D=C+1|0;B=B>>>1;if(B&1){E=D;break}else C=D}if(E)F=E;else G=10}else G=10;if((G|0)==10){G=0;if(!p){H=64;G=15;break}if(!(p&1)){I=p;J=0}else{K=0;L=v;M=p;N=0;break}while(1){C=J+1|0;I=I>>>1;if(I&1){O=C;P=J;break}else J=C}if(!O){K=0;L=v;M=p;N=0;break}else F=P+33|0}if(F>>>0>31){H=F;G=15}else{K=F;L=v;M=p;N=F}}else{H=32;G=15}while(0);if((G|0)==15){G=0;K=H+-32|0;L=p;M=0;N=H}v=M<<32-K|L>>>K;p=M>>>K;A=N+r|0;if(!((p|0)!=0|(v|0)!=1)){x=t;y=A;z=w;break a}C=t+(0-(c[j+(A<<2)>>2]|0))|0;if(($a[d&15](C,c[n>>2]|0)|0)<1){Q=t;R=A;S=0;T=w;G=18;break}else{B=t;r=A;s=0;t=C;u=w;q=B}}}else{Q=a;R=g;S=h;T=1;G=18}while(0);if((G|0)==18)if(!S){x=Q;y=R;z=T}else{i=k;return}b:do if((z|0)>=2?(T=n+(z<<2)|0,c[T>>2]=l,(b|0)!=0):0){R=b;Q=l;while(1){S=R>>>0>256?256:R;G=c[n>>2]|0;Jd(Q|0,G|0,S|0)|0;h=G;G=0;do{g=G;G=G+1|0;a=h;h=c[n+(G<<2)>>2]|0;Jd(a|0,h|0,S|0)|0;c[n+(g<<2)>>2]=a+S}while((G|0)!=(z|0));if((R|0)==(S|0))break b;R=R-S|0;Q=c[T>>2]|0}}while(0);c[m>>2]=x;c:do if((y|0)>1){z=y;n=x;T=x;Q=1;while(1){R=n+o|0;G=z+-2|0;h=n+(0-((c[j+(G<<2)>>2]|0)+b))|0;if(($a[d&15](T,h)|0)>-1?($a[d&15](T,R)|0)>-1:0){U=Q;break}w=Q+1|0;a=m+(Q<<2)|0;if(($a[d&15](h,R)|0)>-1){c[a>>2]=h;V=h;W=z+-1|0}else{c[a>>2]=R;V=R;W=G}if((W|0)<=1){U=w;break}z=W;n=V;T=c[m>>2]|0;Q=w}if((U|0)>=2?(Q=m+(U<<2)|0,c[Q>>2]=l,(b|0)!=0):0){T=b;n=l;while(1){z=T>>>0>256?256:T;w=c[m>>2]|0;Jd(n|0,w|0,z|0)|0;G=w;w=0;do{R=w;w=w+1|0;a=G;G=c[m+(w<<2)>>2]|0;Jd(a|0,G|0,z|0)|0;c[m+(R<<2)>>2]=a+z}while((w|0)!=(U|0));if((T|0)==(z|0)){X=l;break c}T=T-z|0;n=c[Q>>2]|0}}else X=l}else X=l;while(0);i=k;return}function td(a){a=+a;var b=0,d=0,e=0.0,f=0.0;h[k>>3]=a;b=c[k+4>>2]|0;d=b&2146435072;if(d>>>0>1126170624|(d|0)==1126170624&0>0){e=a;return +e}d=(b|0)<0;f=d?a+-4503599627370496.0+4503599627370496.0:a+4503599627370496.0+-4503599627370496.0;if(!(f==0.0)){e=f;return +e}e=d?-0.0:0.0;return +e}function ud(a){a=+a;var b=0,d=0.0,e=0,f=0.0;b=(g[k>>2]=a,c[k>>2]|0);if((b&2130706432)>>>0>1249902592){d=a;return +d}e=(b|0)<0;f=e?a+-8388608.0+8388608.0:a+8388608.0+-8388608.0;if(!(f==0.0)){d=f;return +d}d=e?-0.0:0.0;return +d}function vd(a,b){a=+a;b=b|0;var d=0.0,e=0,f=0,g=0,i=0.0;if((b|0)>1023){d=a*8988465674311579538646525.0e283;e=b+-1023|0;if((e|0)>1023){f=b+-2046|0;g=(f|0)>1023?1023:f;i=d*8988465674311579538646525.0e283}else{g=e;i=d}}else if((b|0)<-1022){d=a*2.2250738585072014e-308;e=b+1022|0;if((e|0)<-1022){f=b+2044|0;g=(f|0)<-1022?-1022:f;i=d*2.2250738585072014e-308}else{g=e;i=d}}else{g=b;i=a}b=Gd(g+1023|0,0,52)|0;g=C;c[k>>2]=b;c[k+4>>2]=g;return +(i*+h[k>>3])}function wd(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;if(!d){e=0;return e|0}else{f=d;g=b;h=c}while(1){c=a[g>>0]|0;b=a[h>>0]|0;if(c<<24>>24!=b<<24>>24){i=c;j=b;break}f=f+-1|0;if(!f){e=0;k=5;break}else{g=g+1|0;h=h+1|0}}if((k|0)==5)return e|0;e=(i&255)-(j&255)|0;return e|0}function xd(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,xa=0,ya=0,za=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ka=0,La=0,Na=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0;do if(a>>>0<245){b=a>>>0<11?16:a+11&-8;d=b>>>3;e=c[14442]|0;f=e>>>d;if(f&3){g=(f&1^1)+d|0;h=g<<1;i=57808+(h<<2)|0;j=57808+(h+2<<2)|0;h=c[j>>2]|0;k=h+8|0;l=c[k>>2]|0;do if((i|0)!=(l|0)){if(l>>>0<(c[14446]|0)>>>0)Ma();m=l+12|0;if((c[m>>2]|0)==(h|0)){c[m>>2]=i;c[j>>2]=l;break}else Ma()}else c[14442]=e&~(1<<g);while(0);l=g<<3;c[h+4>>2]=l|3;j=h+(l|4)|0;c[j>>2]=c[j>>2]|1;n=k;return n|0}j=c[14444]|0;if(b>>>0>j>>>0){if(f){l=2<<d;i=f<<d&(l|0-l);l=(i&0-i)+-1|0;i=l>>>12&16;m=l>>>i;l=m>>>5&8;o=m>>>l;m=o>>>2&4;p=o>>>m;o=p>>>1&2;q=p>>>o;p=q>>>1&1;r=(l|i|m|o|p)+(q>>>p)|0;p=r<<1;q=57808+(p<<2)|0;o=57808+(p+2<<2)|0;p=c[o>>2]|0;m=p+8|0;i=c[m>>2]|0;do if((q|0)!=(i|0)){if(i>>>0<(c[14446]|0)>>>0)Ma();l=i+12|0;if((c[l>>2]|0)==(p|0)){c[l>>2]=q;c[o>>2]=i;s=c[14444]|0;break}else Ma()}else{c[14442]=e&~(1<<r);s=j}while(0);j=r<<3;e=j-b|0;c[p+4>>2]=b|3;i=p+b|0;c[p+(b|4)>>2]=e|1;c[p+j>>2]=e;if(s){j=c[14447]|0;o=s>>>3;q=o<<1;d=57808+(q<<2)|0;f=c[14442]|0;k=1<<o;if(f&k){o=57808+(q+2<<2)|0;h=c[o>>2]|0;if(h>>>0<(c[14446]|0)>>>0)Ma();else{t=o;u=h}}else{c[14442]=f|k;t=57808+(q+2<<2)|0;u=d}c[t>>2]=j;c[u+12>>2]=j;c[j+8>>2]=u;c[j+12>>2]=d}c[14444]=e;c[14447]=i;n=m;return n|0}i=c[14443]|0;if(i){e=(i&0-i)+-1|0;i=e>>>12&16;d=e>>>i;e=d>>>5&8;j=d>>>e;d=j>>>2&4;q=j>>>d;j=q>>>1&2;k=q>>>j;q=k>>>1&1;f=c[58072+((e|i|d|j|q)+(k>>>q)<<2)>>2]|0;q=(c[f+4>>2]&-8)-b|0;k=f;j=f;while(1){f=c[k+16>>2]|0;if(!f){d=c[k+20>>2]|0;if(!d){v=q;w=j;break}else x=d}else x=f;f=(c[x+4>>2]&-8)-b|0;d=f>>>0<q>>>0;q=d?f:q;k=x;j=d?x:j}j=c[14446]|0;if(w>>>0<j>>>0)Ma();k=w+b|0;if(w>>>0>=k>>>0)Ma();q=c[w+24>>2]|0;m=c[w+12>>2]|0;do if((m|0)==(w|0)){p=w+20|0;r=c[p>>2]|0;if(!r){d=w+16|0;f=c[d>>2]|0;if(!f){y=0;break}else{z=f;A=d}}else{z=r;A=p}while(1){p=z+20|0;r=c[p>>2]|0;if(r){z=r;A=p;continue}p=z+16|0;r=c[p>>2]|0;if(!r){B=z;C=A;break}else{z=r;A=p}}if(C>>>0<j>>>0)Ma();else{c[C>>2]=0;y=B;break}}else{p=c[w+8>>2]|0;if(p>>>0<j>>>0)Ma();r=p+12|0;if((c[r>>2]|0)!=(w|0))Ma();d=m+8|0;if((c[d>>2]|0)==(w|0)){c[r>>2]=m;c[d>>2]=p;y=m;break}else Ma()}while(0);do if(q){m=c[w+28>>2]|0;j=58072+(m<<2)|0;if((w|0)==(c[j>>2]|0)){c[j>>2]=y;if(!y){c[14443]=c[14443]&~(1<<m);break}}else{if(q>>>0<(c[14446]|0)>>>0)Ma();m=q+16|0;if((c[m>>2]|0)==(w|0))c[m>>2]=y;else c[q+20>>2]=y;if(!y)break}m=c[14446]|0;if(y>>>0<m>>>0)Ma();c[y+24>>2]=q;j=c[w+16>>2]|0;do if(j)if(j>>>0<m>>>0)Ma();else{c[y+16>>2]=j;c[j+24>>2]=y;break}while(0);j=c[w+20>>2]|0;if(j)if(j>>>0<(c[14446]|0)>>>0)Ma();else{c[y+20>>2]=j;c[j+24>>2]=y;break}}while(0);if(v>>>0<16){q=v+b|0;c[w+4>>2]=q|3;j=w+(q+4)|0;c[j>>2]=c[j>>2]|1}else{c[w+4>>2]=b|3;c[w+(b|4)>>2]=v|1;c[w+(v+b)>>2]=v;j=c[14444]|0;if(j){q=c[14447]|0;m=j>>>3;j=m<<1;p=57808+(j<<2)|0;d=c[14442]|0;r=1<<m;if(d&r){m=57808+(j+2<<2)|0;f=c[m>>2]|0;if(f>>>0<(c[14446]|0)>>>0)Ma();else{D=m;E=f}}else{c[14442]=d|r;D=57808+(j+2<<2)|0;E=p}c[D>>2]=q;c[E+12>>2]=q;c[q+8>>2]=E;c[q+12>>2]=p}c[14444]=v;c[14447]=k}n=w+8|0;return n|0}else F=b}else F=b}else if(a>>>0<=4294967231){p=a+11|0;q=p&-8;j=c[14443]|0;if(j){r=0-q|0;d=p>>>8;if(d)if(q>>>0>16777215)G=31;else{p=(d+1048320|0)>>>16&8;f=d<<p;d=(f+520192|0)>>>16&4;m=f<<d;f=(m+245760|0)>>>16&2;i=14-(d|p|f)+(m<<f>>>15)|0;G=q>>>(i+7|0)&1|i<<1}else G=0;i=c[58072+(G<<2)>>2]|0;a:do if(!i){H=r;I=0;J=0;K=86}else{f=r;m=0;p=q<<((G|0)==31?0:25-(G>>>1)|0);d=i;e=0;while(1){h=c[d+4>>2]&-8;o=h-q|0;if(o>>>0<f>>>0)if((h|0)==(q|0)){L=o;M=d;N=d;K=90;break a}else{O=o;P=d}else{O=f;P=e}o=c[d+20>>2]|0;d=c[d+16+(p>>>31<<2)>>2]|0;h=(o|0)==0|(o|0)==(d|0)?m:o;if(!d){H=O;I=h;J=P;K=86;break}else{f=O;m=h;p=p<<1;e=P}}}while(0);if((K|0)==86){if((I|0)==0&(J|0)==0){i=2<<G;r=j&(i|0-i);if(!r){F=q;break}i=(r&0-r)+-1|0;r=i>>>12&16;b=i>>>r;i=b>>>5&8;k=b>>>i;b=k>>>2&4;e=k>>>b;k=e>>>1&2;p=e>>>k;e=p>>>1&1;Q=c[58072+((i|r|b|k|e)+(p>>>e)<<2)>>2]|0;R=0}else{Q=I;R=J}if(!Q){S=H;T=R}else{L=H;M=Q;N=R;K=90}}if((K|0)==90)while(1){K=0;e=(c[M+4>>2]&-8)-q|0;p=e>>>0<L>>>0;k=p?e:L;e=p?M:N;p=c[M+16>>2]|0;if(p){L=k;M=p;N=e;K=90;continue}M=c[M+20>>2]|0;if(!M){S=k;T=e;break}else{L=k;N=e;K=90}}if((T|0)!=0?S>>>0<((c[14444]|0)-q|0)>>>0:0){j=c[14446]|0;if(T>>>0<j>>>0)Ma();e=T+q|0;if(T>>>0>=e>>>0)Ma();k=c[T+24>>2]|0;p=c[T+12>>2]|0;do if((p|0)==(T|0)){b=T+20|0;r=c[b>>2]|0;if(!r){i=T+16|0;m=c[i>>2]|0;if(!m){U=0;break}else{V=m;W=i}}else{V=r;W=b}while(1){b=V+20|0;r=c[b>>2]|0;if(r){V=r;W=b;continue}b=V+16|0;r=c[b>>2]|0;if(!r){X=V;Y=W;break}else{V=r;W=b}}if(Y>>>0<j>>>0)Ma();else{c[Y>>2]=0;U=X;break}}else{b=c[T+8>>2]|0;if(b>>>0<j>>>0)Ma();r=b+12|0;if((c[r>>2]|0)!=(T|0))Ma();i=p+8|0;if((c[i>>2]|0)==(T|0)){c[r>>2]=p;c[i>>2]=b;U=p;break}else Ma()}while(0);do if(k){p=c[T+28>>2]|0;j=58072+(p<<2)|0;if((T|0)==(c[j>>2]|0)){c[j>>2]=U;if(!U){c[14443]=c[14443]&~(1<<p);break}}else{if(k>>>0<(c[14446]|0)>>>0)Ma();p=k+16|0;if((c[p>>2]|0)==(T|0))c[p>>2]=U;else c[k+20>>2]=U;if(!U)break}p=c[14446]|0;if(U>>>0<p>>>0)Ma();c[U+24>>2]=k;j=c[T+16>>2]|0;do if(j)if(j>>>0<p>>>0)Ma();else{c[U+16>>2]=j;c[j+24>>2]=U;break}while(0);j=c[T+20>>2]|0;if(j)if(j>>>0<(c[14446]|0)>>>0)Ma();else{c[U+20>>2]=j;c[j+24>>2]=U;break}}while(0);b:do if(S>>>0>=16){c[T+4>>2]=q|3;c[T+(q|4)>>2]=S|1;c[T+(S+q)>>2]=S;k=S>>>3;if(S>>>0<256){j=k<<1;p=57808+(j<<2)|0;b=c[14442]|0;i=1<<k;if(b&i){k=57808+(j+2<<2)|0;r=c[k>>2]|0;if(r>>>0<(c[14446]|0)>>>0)Ma();else{Z=k;_=r}}else{c[14442]=b|i;Z=57808+(j+2<<2)|0;_=p}c[Z>>2]=e;c[_+12>>2]=e;c[T+(q+8)>>2]=_;c[T+(q+12)>>2]=p;break}p=S>>>8;if(p)if(S>>>0>16777215)$=31;else{j=(p+1048320|0)>>>16&8;i=p<<j;p=(i+520192|0)>>>16&4;b=i<<p;i=(b+245760|0)>>>16&2;r=14-(p|j|i)+(b<<i>>>15)|0;$=S>>>(r+7|0)&1|r<<1}else $=0;r=58072+($<<2)|0;c[T+(q+28)>>2]=$;c[T+(q+20)>>2]=0;c[T+(q+16)>>2]=0;i=c[14443]|0;b=1<<$;if(!(i&b)){c[14443]=i|b;c[r>>2]=e;c[T+(q+24)>>2]=r;c[T+(q+12)>>2]=e;c[T+(q+8)>>2]=e;break}b=c[r>>2]|0;c:do if((c[b+4>>2]&-8|0)!=(S|0)){r=S<<(($|0)==31?0:25-($>>>1)|0);i=b;while(1){j=i+16+(r>>>31<<2)|0;p=c[j>>2]|0;if(!p){aa=j;ba=i;break}if((c[p+4>>2]&-8|0)==(S|0)){ca=p;break c}else{r=r<<1;i=p}}if(aa>>>0<(c[14446]|0)>>>0)Ma();else{c[aa>>2]=e;c[T+(q+24)>>2]=ba;c[T+(q+12)>>2]=e;c[T+(q+8)>>2]=e;break b}}else ca=b;while(0);b=ca+8|0;i=c[b>>2]|0;r=c[14446]|0;if(i>>>0>=r>>>0&ca>>>0>=r>>>0){c[i+12>>2]=e;c[b>>2]=e;c[T+(q+8)>>2]=i;c[T+(q+12)>>2]=ca;c[T+(q+24)>>2]=0;break}else Ma()}else{i=S+q|0;c[T+4>>2]=i|3;b=T+(i+4)|0;c[b>>2]=c[b>>2]|1}while(0);n=T+8|0;return n|0}else F=q}else F=q}else F=-1;while(0);T=c[14444]|0;if(T>>>0>=F>>>0){S=T-F|0;ca=c[14447]|0;if(S>>>0>15){c[14447]=ca+F;c[14444]=S;c[ca+(F+4)>>2]=S|1;c[ca+T>>2]=S;c[ca+4>>2]=F|3}else{c[14444]=0;c[14447]=0;c[ca+4>>2]=T|3;S=ca+(T+4)|0;c[S>>2]=c[S>>2]|1}n=ca+8|0;return n|0}ca=c[14445]|0;if(ca>>>0>F>>>0){S=ca-F|0;c[14445]=S;ca=c[14448]|0;c[14448]=ca+F;c[ca+(F+4)>>2]=S|1;c[ca+4>>2]=F|3;n=ca+8|0;return n|0}do if(!(c[14560]|0)){ca=Aa(30)|0;if(!(ca+-1&ca)){c[14562]=ca;c[14561]=ca;c[14563]=-1;c[14564]=-1;c[14565]=0;c[14553]=0;c[14560]=(Oa(0)|0)&-16^1431655768;break}else Ma()}while(0);ca=F+48|0;S=c[14562]|0;T=F+47|0;ba=S+T|0;aa=0-S|0;S=ba&aa;if(S>>>0<=F>>>0){n=0;return n|0}$=c[14552]|0;if(($|0)!=0?(_=c[14550]|0,Z=_+S|0,Z>>>0<=_>>>0|Z>>>0>$>>>0):0){n=0;return n|0}d:do if(!(c[14553]&4)){$=c[14448]|0;e:do if($){Z=58216;while(1){_=c[Z>>2]|0;if(_>>>0<=$>>>0?(U=Z+4|0,(_+(c[U>>2]|0)|0)>>>0>$>>>0):0){da=Z;ea=U;break}Z=c[Z+8>>2]|0;if(!Z){K=174;break e}}Z=ba-(c[14445]|0)&aa;if(Z>>>0<2147483647){U=wa(Z|0)|0;_=(U|0)==((c[da>>2]|0)+(c[ea>>2]|0)|0);X=_?Z:0;if(_)if((U|0)==(-1|0))fa=X;else{ga=U;ha=X;K=194;break d}else{ia=U;ja=Z;ka=X;K=184}}else fa=0}else K=174;while(0);do if((K|0)==174){$=wa(0)|0;if(($|0)!=(-1|0)){q=$;X=c[14561]|0;Z=X+-1|0;if(!(Z&q))la=S;else la=S-q+(Z+q&0-X)|0;X=c[14550]|0;q=X+la|0;if(la>>>0>F>>>0&la>>>0<2147483647){Z=c[14552]|0;if((Z|0)!=0?q>>>0<=X>>>0|q>>>0>Z>>>0:0){fa=0;break}Z=wa(la|0)|0;q=(Z|0)==($|0);X=q?la:0;if(q){ga=$;ha=X;K=194;break d}else{ia=Z;ja=la;ka=X;K=184}}else fa=0}else fa=0}while(0);f:do if((K|0)==184){X=0-ja|0;do if(ca>>>0>ja>>>0&(ja>>>0<2147483647&(ia|0)!=(-1|0))?(Z=c[14562]|0,$=T-ja+Z&0-Z,$>>>0<2147483647):0)if((wa($|0)|0)==(-1|0)){wa(X|0)|0;fa=ka;break f}else{ma=$+ja|0;break}else ma=ja;while(0);if((ia|0)==(-1|0))fa=ka;else{ga=ia;ha=ma;K=194;break d}}while(0);c[14553]=c[14553]|4;na=fa;K=191}else{na=0;K=191}while(0);if((((K|0)==191?S>>>0<2147483647:0)?(fa=wa(S|0)|0,S=wa(0)|0,fa>>>0<S>>>0&((fa|0)!=(-1|0)&(S|0)!=(-1|0))):0)?(ma=S-fa|0,S=ma>>>0>(F+40|0)>>>0,S):0){ga=fa;ha=S?ma:na;K=194}if((K|0)==194){na=(c[14550]|0)+ha|0;c[14550]=na;if(na>>>0>(c[14551]|0)>>>0)c[14551]=na;na=c[14448]|0;g:do if(na){ma=58216;do{S=c[ma>>2]|0;fa=ma+4|0;ia=c[fa>>2]|0;if((ga|0)==(S+ia|0)){oa=S;pa=fa;qa=ia;ra=ma;K=204;break}ma=c[ma+8>>2]|0}while((ma|0)!=0);if(((K|0)==204?(c[ra+12>>2]&8|0)==0:0)?na>>>0<ga>>>0&na>>>0>=oa>>>0:0){c[pa>>2]=qa+ha;ma=(c[14445]|0)+ha|0;ia=na+8|0;fa=(ia&7|0)==0?0:0-ia&7;ia=ma-fa|0;c[14448]=na+fa;c[14445]=ia;c[na+(fa+4)>>2]=ia|1;c[na+(ma+4)>>2]=40;c[14449]=c[14564];break}ma=c[14446]|0;if(ga>>>0<ma>>>0){c[14446]=ga;sa=ga}else sa=ma;ma=ga+ha|0;ia=58216;while(1){if((c[ia>>2]|0)==(ma|0)){ta=ia;ua=ia;K=212;break}ia=c[ia+8>>2]|0;if(!ia){va=58216;break}}if((K|0)==212)if(!(c[ua+12>>2]&8)){c[ta>>2]=ga;ia=ua+4|0;c[ia>>2]=(c[ia>>2]|0)+ha;ia=ga+8|0;ma=(ia&7|0)==0?0:0-ia&7;ia=ga+(ha+8)|0;fa=(ia&7|0)==0?0:0-ia&7;ia=ga+(fa+ha)|0;S=ma+F|0;ka=ga+S|0;ja=ia-(ga+ma)-F|0;c[ga+(ma+4)>>2]=F|3;h:do if((ia|0)!=(na|0)){if((ia|0)==(c[14447]|0)){T=(c[14444]|0)+ja|0;c[14444]=T;c[14447]=ka;c[ga+(S+4)>>2]=T|1;c[ga+(T+S)>>2]=T;break}T=ha+4|0;ca=c[ga+(T+fa)>>2]|0;if((ca&3|0)==1){la=ca&-8;ea=ca>>>3;i:do if(ca>>>0>=256){da=c[ga+((fa|24)+ha)>>2]|0;aa=c[ga+(ha+12+fa)>>2]|0;do if((aa|0)==(ia|0)){ba=fa|16;X=ga+(T+ba)|0;$=c[X>>2]|0;if(!$){Z=ga+(ba+ha)|0;ba=c[Z>>2]|0;if(!ba){xa=0;break}else{ya=ba;za=Z}}else{ya=$;za=X}while(1){X=ya+20|0;$=c[X>>2]|0;if($){ya=$;za=X;continue}X=ya+16|0;$=c[X>>2]|0;if(!$){Ba=ya;Ca=za;break}else{ya=$;za=X}}if(Ca>>>0<sa>>>0)Ma();else{c[Ca>>2]=0;xa=Ba;break}}else{X=c[ga+((fa|8)+ha)>>2]|0;if(X>>>0<sa>>>0)Ma();$=X+12|0;if((c[$>>2]|0)!=(ia|0))Ma();Z=aa+8|0;if((c[Z>>2]|0)==(ia|0)){c[$>>2]=aa;c[Z>>2]=X;xa=aa;break}else Ma()}while(0);if(!da)break;aa=c[ga+(ha+28+fa)>>2]|0;X=58072+(aa<<2)|0;do if((ia|0)!=(c[X>>2]|0)){if(da>>>0<(c[14446]|0)>>>0)Ma();Z=da+16|0;if((c[Z>>2]|0)==(ia|0))c[Z>>2]=xa;else c[da+20>>2]=xa;if(!xa)break i}else{c[X>>2]=xa;if(xa)break;c[14443]=c[14443]&~(1<<aa);break i}while(0);aa=c[14446]|0;if(xa>>>0<aa>>>0)Ma();c[xa+24>>2]=da;X=fa|16;Z=c[ga+(X+ha)>>2]|0;do if(Z)if(Z>>>0<aa>>>0)Ma();else{c[xa+16>>2]=Z;c[Z+24>>2]=xa;break}while(0);Z=c[ga+(T+X)>>2]|0;if(!Z)break;if(Z>>>0<(c[14446]|0)>>>0)Ma();else{c[xa+20>>2]=Z;c[Z+24>>2]=xa;break}}else{Z=c[ga+((fa|8)+ha)>>2]|0;aa=c[ga+(ha+12+fa)>>2]|0;da=57808+(ea<<1<<2)|0;do if((Z|0)!=(da|0)){if(Z>>>0<sa>>>0)Ma();if((c[Z+12>>2]|0)==(ia|0))break;Ma()}while(0);if((aa|0)==(Z|0)){c[14442]=c[14442]&~(1<<ea);break}do if((aa|0)==(da|0))Da=aa+8|0;else{if(aa>>>0<sa>>>0)Ma();X=aa+8|0;if((c[X>>2]|0)==(ia|0)){Da=X;break}Ma()}while(0);c[Z+12>>2]=aa;c[Da>>2]=Z}while(0);Ea=ga+((la|fa)+ha)|0;Fa=la+ja|0}else{Ea=ia;Fa=ja}ea=Ea+4|0;c[ea>>2]=c[ea>>2]&-2;c[ga+(S+4)>>2]=Fa|1;c[ga+(Fa+S)>>2]=Fa;ea=Fa>>>3;if(Fa>>>0<256){T=ea<<1;ca=57808+(T<<2)|0;da=c[14442]|0;X=1<<ea;do if(!(da&X)){c[14442]=da|X;Ga=57808+(T+2<<2)|0;Ha=ca}else{ea=57808+(T+2<<2)|0;$=c[ea>>2]|0;if($>>>0>=(c[14446]|0)>>>0){Ga=ea;Ha=$;break}Ma()}while(0);c[Ga>>2]=ka;c[Ha+12>>2]=ka;c[ga+(S+8)>>2]=Ha;c[ga+(S+12)>>2]=ca;break}T=Fa>>>8;do if(!T)Ia=0;else{if(Fa>>>0>16777215){Ia=31;break}X=(T+1048320|0)>>>16&8;da=T<<X;la=(da+520192|0)>>>16&4;$=da<<la;da=($+245760|0)>>>16&2;ea=14-(la|X|da)+($<<da>>>15)|0;Ia=Fa>>>(ea+7|0)&1|ea<<1}while(0);T=58072+(Ia<<2)|0;c[ga+(S+28)>>2]=Ia;c[ga+(S+20)>>2]=0;c[ga+(S+16)>>2]=0;ca=c[14443]|0;ea=1<<Ia;if(!(ca&ea)){c[14443]=ca|ea;c[T>>2]=ka;c[ga+(S+24)>>2]=T;c[ga+(S+12)>>2]=ka;c[ga+(S+8)>>2]=ka;break}ea=c[T>>2]|0;j:do if((c[ea+4>>2]&-8|0)!=(Fa|0)){T=Fa<<((Ia|0)==31?0:25-(Ia>>>1)|0);ca=ea;while(1){da=ca+16+(T>>>31<<2)|0;$=c[da>>2]|0;if(!$){Ka=da;La=ca;break}if((c[$+4>>2]&-8|0)==(Fa|0)){Na=$;break j}else{T=T<<1;ca=$}}if(Ka>>>0<(c[14446]|0)>>>0)Ma();else{c[Ka>>2]=ka;c[ga+(S+24)>>2]=La;c[ga+(S+12)>>2]=ka;c[ga+(S+8)>>2]=ka;break h}}else Na=ea;while(0);ea=Na+8|0;ca=c[ea>>2]|0;T=c[14446]|0;if(ca>>>0>=T>>>0&Na>>>0>=T>>>0){c[ca+12>>2]=ka;c[ea>>2]=ka;c[ga+(S+8)>>2]=ca;c[ga+(S+12)>>2]=Na;c[ga+(S+24)>>2]=0;break}else Ma()}else{ca=(c[14445]|0)+ja|0;c[14445]=ca;c[14448]=ka;c[ga+(S+4)>>2]=ca|1}while(0);n=ga+(ma|8)|0;return n|0}else va=58216;while(1){S=c[va>>2]|0;if(S>>>0<=na>>>0?(ka=c[va+4>>2]|0,ja=S+ka|0,ja>>>0>na>>>0):0){Pa=S;Qa=ka;Ra=ja;break}va=c[va+8>>2]|0}ma=Pa+(Qa+-39)|0;ja=Pa+(Qa+-47+((ma&7|0)==0?0:0-ma&7))|0;ma=na+16|0;ka=ja>>>0<ma>>>0?na:ja;ja=ka+8|0;S=ga+8|0;ia=(S&7|0)==0?0:0-S&7;S=ha+-40-ia|0;c[14448]=ga+ia;c[14445]=S;c[ga+(ia+4)>>2]=S|1;c[ga+(ha+-36)>>2]=40;c[14449]=c[14564];S=ka+4|0;c[S>>2]=27;c[ja>>2]=c[14554];c[ja+4>>2]=c[14555];c[ja+8>>2]=c[14556];c[ja+12>>2]=c[14557];c[14554]=ga;c[14555]=ha;c[14557]=0;c[14556]=ja;ja=ka+28|0;c[ja>>2]=7;if((ka+32|0)>>>0<Ra>>>0){ia=ja;do{ja=ia;ia=ia+4|0;c[ia>>2]=7}while((ja+8|0)>>>0<Ra>>>0)}if((ka|0)!=(na|0)){ia=ka-na|0;c[S>>2]=c[S>>2]&-2;c[na+4>>2]=ia|1;c[ka>>2]=ia;ja=ia>>>3;if(ia>>>0<256){fa=ja<<1;ca=57808+(fa<<2)|0;ea=c[14442]|0;T=1<<ja;if(ea&T){ja=57808+(fa+2<<2)|0;Z=c[ja>>2]|0;if(Z>>>0<(c[14446]|0)>>>0)Ma();else{Sa=ja;Ta=Z}}else{c[14442]=ea|T;Sa=57808+(fa+2<<2)|0;Ta=ca}c[Sa>>2]=na;c[Ta+12>>2]=na;c[na+8>>2]=Ta;c[na+12>>2]=ca;break}ca=ia>>>8;if(ca)if(ia>>>0>16777215)Ua=31;else{fa=(ca+1048320|0)>>>16&8;T=ca<<fa;ca=(T+520192|0)>>>16&4;ea=T<<ca;T=(ea+245760|0)>>>16&2;Z=14-(ca|fa|T)+(ea<<T>>>15)|0;Ua=ia>>>(Z+7|0)&1|Z<<1}else Ua=0;Z=58072+(Ua<<2)|0;c[na+28>>2]=Ua;c[na+20>>2]=0;c[ma>>2]=0;T=c[14443]|0;ea=1<<Ua;if(!(T&ea)){c[14443]=T|ea;c[Z>>2]=na;c[na+24>>2]=Z;c[na+12>>2]=na;c[na+8>>2]=na;break}ea=c[Z>>2]|0;k:do if((c[ea+4>>2]&-8|0)!=(ia|0)){Z=ia<<((Ua|0)==31?0:25-(Ua>>>1)|0);T=ea;while(1){fa=T+16+(Z>>>31<<2)|0;ca=c[fa>>2]|0;if(!ca){Va=fa;Wa=T;break}if((c[ca+4>>2]&-8|0)==(ia|0)){Xa=ca;break k}else{Z=Z<<1;T=ca}}if(Va>>>0<(c[14446]|0)>>>0)Ma();else{c[Va>>2]=na;c[na+24>>2]=Wa;c[na+12>>2]=na;c[na+8>>2]=na;break g}}else Xa=ea;while(0);ea=Xa+8|0;ia=c[ea>>2]|0;ma=c[14446]|0;if(ia>>>0>=ma>>>0&Xa>>>0>=ma>>>0){c[ia+12>>2]=na;c[ea>>2]=na;c[na+8>>2]=ia;c[na+12>>2]=Xa;c[na+24>>2]=0;break}else Ma()}}else{ia=c[14446]|0;if((ia|0)==0|ga>>>0<ia>>>0)c[14446]=ga;c[14554]=ga;c[14555]=ha;c[14557]=0;c[14451]=c[14560];c[14450]=-1;ia=0;do{ea=ia<<1;ma=57808+(ea<<2)|0;c[57808+(ea+3<<2)>>2]=ma;c[57808+(ea+2<<2)>>2]=ma;ia=ia+1|0}while((ia|0)!=32);ia=ga+8|0;ma=(ia&7|0)==0?0:0-ia&7;ia=ha+-40-ma|0;c[14448]=ga+ma;c[14445]=ia;c[ga+(ma+4)>>2]=ia|1;c[ga+(ha+-36)>>2]=40;c[14449]=c[14564]}while(0);ha=c[14445]|0;if(ha>>>0>F>>>0){ga=ha-F|0;c[14445]=ga;ha=c[14448]|0;c[14448]=ha+F;c[ha+(F+4)>>2]=ga|1;c[ha+4>>2]=F|3;n=ha+8|0;return n|0}}c[(Ja()|0)>>2]=12;n=0;return n|0}function yd(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;if(!a)return;b=a+-8|0;d=c[14446]|0;if(b>>>0<d>>>0)Ma();e=c[a+-4>>2]|0;f=e&3;if((f|0)==1)Ma();g=e&-8;h=a+(g+-8)|0;do if(!(e&1)){i=c[b>>2]|0;if(!f)return;j=-8-i|0;k=a+j|0;l=i+g|0;if(k>>>0<d>>>0)Ma();if((k|0)==(c[14447]|0)){m=a+(g+-4)|0;n=c[m>>2]|0;if((n&3|0)!=3){o=k;p=l;break}c[14444]=l;c[m>>2]=n&-2;c[a+(j+4)>>2]=l|1;c[h>>2]=l;return}n=i>>>3;if(i>>>0<256){i=c[a+(j+8)>>2]|0;m=c[a+(j+12)>>2]|0;q=57808+(n<<1<<2)|0;if((i|0)!=(q|0)){if(i>>>0<d>>>0)Ma();if((c[i+12>>2]|0)!=(k|0))Ma()}if((m|0)==(i|0)){c[14442]=c[14442]&~(1<<n);o=k;p=l;break}if((m|0)!=(q|0)){if(m>>>0<d>>>0)Ma();q=m+8|0;if((c[q>>2]|0)==(k|0))r=q;else Ma()}else r=m+8|0;c[i+12>>2]=m;c[r>>2]=i;o=k;p=l;break}i=c[a+(j+24)>>2]|0;m=c[a+(j+12)>>2]|0;do if((m|0)==(k|0)){q=a+(j+20)|0;n=c[q>>2]|0;if(!n){s=a+(j+16)|0;t=c[s>>2]|0;if(!t){u=0;break}else{v=t;w=s}}else{v=n;w=q}while(1){q=v+20|0;n=c[q>>2]|0;if(n){v=n;w=q;continue}q=v+16|0;n=c[q>>2]|0;if(!n){x=v;y=w;break}else{v=n;w=q}}if(y>>>0<d>>>0)Ma();else{c[y>>2]=0;u=x;break}}else{q=c[a+(j+8)>>2]|0;if(q>>>0<d>>>0)Ma();n=q+12|0;if((c[n>>2]|0)!=(k|0))Ma();s=m+8|0;if((c[s>>2]|0)==(k|0)){c[n>>2]=m;c[s>>2]=q;u=m;break}else Ma()}while(0);if(i){m=c[a+(j+28)>>2]|0;q=58072+(m<<2)|0;if((k|0)==(c[q>>2]|0)){c[q>>2]=u;if(!u){c[14443]=c[14443]&~(1<<m);o=k;p=l;break}}else{if(i>>>0<(c[14446]|0)>>>0)Ma();m=i+16|0;if((c[m>>2]|0)==(k|0))c[m>>2]=u;else c[i+20>>2]=u;if(!u){o=k;p=l;break}}m=c[14446]|0;if(u>>>0<m>>>0)Ma();c[u+24>>2]=i;q=c[a+(j+16)>>2]|0;do if(q)if(q>>>0<m>>>0)Ma();else{c[u+16>>2]=q;c[q+24>>2]=u;break}while(0);q=c[a+(j+20)>>2]|0;if(q)if(q>>>0<(c[14446]|0)>>>0)Ma();else{c[u+20>>2]=q;c[q+24>>2]=u;o=k;p=l;break}else{o=k;p=l}}else{o=k;p=l}}else{o=b;p=g}while(0);if(o>>>0>=h>>>0)Ma();b=a+(g+-4)|0;u=c[b>>2]|0;if(!(u&1))Ma();if(!(u&2)){if((h|0)==(c[14448]|0)){d=(c[14445]|0)+p|0;c[14445]=d;c[14448]=o;c[o+4>>2]=d|1;if((o|0)!=(c[14447]|0))return;c[14447]=0;c[14444]=0;return}if((h|0)==(c[14447]|0)){d=(c[14444]|0)+p|0;c[14444]=d;c[14447]=o;c[o+4>>2]=d|1;c[o+d>>2]=d;return}d=(u&-8)+p|0;x=u>>>3;do if(u>>>0>=256){y=c[a+(g+16)>>2]|0;w=c[a+(g|4)>>2]|0;do if((w|0)==(h|0)){v=a+(g+12)|0;r=c[v>>2]|0;if(!r){f=a+(g+8)|0;e=c[f>>2]|0;if(!e){z=0;break}else{A=e;B=f}}else{A=r;B=v}while(1){v=A+20|0;r=c[v>>2]|0;if(r){A=r;B=v;continue}v=A+16|0;r=c[v>>2]|0;if(!r){C=A;D=B;break}else{A=r;B=v}}if(D>>>0<(c[14446]|0)>>>0)Ma();else{c[D>>2]=0;z=C;break}}else{v=c[a+g>>2]|0;if(v>>>0<(c[14446]|0)>>>0)Ma();r=v+12|0;if((c[r>>2]|0)!=(h|0))Ma();f=w+8|0;if((c[f>>2]|0)==(h|0)){c[r>>2]=w;c[f>>2]=v;z=w;break}else Ma()}while(0);if(y){w=c[a+(g+20)>>2]|0;l=58072+(w<<2)|0;if((h|0)==(c[l>>2]|0)){c[l>>2]=z;if(!z){c[14443]=c[14443]&~(1<<w);break}}else{if(y>>>0<(c[14446]|0)>>>0)Ma();w=y+16|0;if((c[w>>2]|0)==(h|0))c[w>>2]=z;else c[y+20>>2]=z;if(!z)break}w=c[14446]|0;if(z>>>0<w>>>0)Ma();c[z+24>>2]=y;l=c[a+(g+8)>>2]|0;do if(l)if(l>>>0<w>>>0)Ma();else{c[z+16>>2]=l;c[l+24>>2]=z;break}while(0);l=c[a+(g+12)>>2]|0;if(l)if(l>>>0<(c[14446]|0)>>>0)Ma();else{c[z+20>>2]=l;c[l+24>>2]=z;break}}}else{l=c[a+g>>2]|0;w=c[a+(g|4)>>2]|0;y=57808+(x<<1<<2)|0;if((l|0)!=(y|0)){if(l>>>0<(c[14446]|0)>>>0)Ma();if((c[l+12>>2]|0)!=(h|0))Ma()}if((w|0)==(l|0)){c[14442]=c[14442]&~(1<<x);break}if((w|0)!=(y|0)){if(w>>>0<(c[14446]|0)>>>0)Ma();y=w+8|0;if((c[y>>2]|0)==(h|0))E=y;else Ma()}else E=w+8|0;c[l+12>>2]=w;c[E>>2]=l}while(0);c[o+4>>2]=d|1;c[o+d>>2]=d;if((o|0)==(c[14447]|0)){c[14444]=d;return}else F=d}else{c[b>>2]=u&-2;c[o+4>>2]=p|1;c[o+p>>2]=p;F=p}p=F>>>3;if(F>>>0<256){u=p<<1;b=57808+(u<<2)|0;d=c[14442]|0;E=1<<p;if(d&E){p=57808+(u+2<<2)|0;h=c[p>>2]|0;if(h>>>0<(c[14446]|0)>>>0)Ma();else{G=p;H=h}}else{c[14442]=d|E;G=57808+(u+2<<2)|0;H=b}c[G>>2]=o;c[H+12>>2]=o;c[o+8>>2]=H;c[o+12>>2]=b;return}b=F>>>8;if(b)if(F>>>0>16777215)I=31;else{H=(b+1048320|0)>>>16&8;G=b<<H;b=(G+520192|0)>>>16&4;u=G<<b;G=(u+245760|0)>>>16&2;E=14-(b|H|G)+(u<<G>>>15)|0;I=F>>>(E+7|0)&1|E<<1}else I=0;E=58072+(I<<2)|0;c[o+28>>2]=I;c[o+20>>2]=0;c[o+16>>2]=0;G=c[14443]|0;u=1<<I;a:do if(G&u){H=c[E>>2]|0;b:do if((c[H+4>>2]&-8|0)!=(F|0)){b=F<<((I|0)==31?0:25-(I>>>1)|0);d=H;while(1){h=d+16+(b>>>31<<2)|0;p=c[h>>2]|0;if(!p){J=h;K=d;break}if((c[p+4>>2]&-8|0)==(F|0)){L=p;break b}else{b=b<<1;d=p}}if(J>>>0<(c[14446]|0)>>>0)Ma();else{c[J>>2]=o;c[o+24>>2]=K;c[o+12>>2]=o;c[o+8>>2]=o;break a}}else L=H;while(0);H=L+8|0;d=c[H>>2]|0;b=c[14446]|0;if(d>>>0>=b>>>0&L>>>0>=b>>>0){c[d+12>>2]=o;c[H>>2]=o;c[o+8>>2]=d;c[o+12>>2]=L;c[o+24>>2]=0;break}else Ma()}else{c[14443]=G|u;c[E>>2]=o;c[o+24>>2]=E;c[o+12>>2]=o;c[o+8>>2]=o}while(0);o=(c[14450]|0)+-1|0;c[14450]=o;if(!o)M=58224;else return;while(1){o=c[M>>2]|0;if(!o)break;else M=o+8|0}c[14450]=-1;return}function zd(a,b){a=a|0;b=b|0;var d=0,e=0;if(a){d=_(b,a)|0;if((b|a)>>>0>65535)e=((d>>>0)/(a>>>0)|0|0)==(b|0)?d:-1;else e=d}else e=0;d=xd(e)|0;if(!d)return d|0;if(!(c[d+-4>>2]&3))return d|0;Fd(d|0,0,e|0)|0;return d|0}function Ad(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;if(!a){d=xd(b)|0;return d|0}if(b>>>0>4294967231){c[(Ja()|0)>>2]=12;d=0;return d|0}e=Bd(a+-8|0,b>>>0<11?16:b+11&-8)|0;if(e){d=e+8|0;return d|0}e=xd(b)|0;if(!e){d=0;return d|0}f=c[a+-4>>2]|0;g=(f&-8)-((f&3|0)==0?8:4)|0;Jd(e|0,a|0,(g>>>0<b>>>0?g:b)|0)|0;yd(a);d=e;return d|0}function Bd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;d=a+4|0;e=c[d>>2]|0;f=e&-8;g=a+f|0;h=c[14446]|0;i=e&3;if(!((i|0)!=1&a>>>0>=h>>>0&a>>>0<g>>>0))Ma();j=a+(f|4)|0;k=c[j>>2]|0;if(!(k&1))Ma();if(!i){if(b>>>0<256){l=0;return l|0}if(f>>>0>=(b+4|0)>>>0?(f-b|0)>>>0<=c[14562]<<1>>>0:0){l=a;return l|0}l=0;return l|0}if(f>>>0>=b>>>0){i=f-b|0;if(i>>>0<=15){l=a;return l|0}c[d>>2]=e&1|b|2;c[a+(b+4)>>2]=i|3;c[j>>2]=c[j>>2]|1;Cd(a+b|0,i);l=a;return l|0}if((g|0)==(c[14448]|0)){i=(c[14445]|0)+f|0;if(i>>>0<=b>>>0){l=0;return l|0}j=i-b|0;c[d>>2]=e&1|b|2;c[a+(b+4)>>2]=j|1;c[14448]=a+b;c[14445]=j;l=a;return l|0}if((g|0)==(c[14447]|0)){j=(c[14444]|0)+f|0;if(j>>>0<b>>>0){l=0;return l|0}i=j-b|0;if(i>>>0>15){c[d>>2]=e&1|b|2;c[a+(b+4)>>2]=i|1;c[a+j>>2]=i;m=a+(j+4)|0;c[m>>2]=c[m>>2]&-2;n=a+b|0;o=i}else{c[d>>2]=e&1|j|2;i=a+(j+4)|0;c[i>>2]=c[i>>2]|1;n=0;o=0}c[14444]=o;c[14447]=n;l=a;return l|0}if(k&2){l=0;return l|0}n=(k&-8)+f|0;if(n>>>0<b>>>0){l=0;return l|0}o=n-b|0;i=k>>>3;do if(k>>>0>=256){j=c[a+(f+24)>>2]|0;m=c[a+(f+12)>>2]|0;do if((m|0)==(g|0)){p=a+(f+20)|0;q=c[p>>2]|0;if(!q){r=a+(f+16)|0;s=c[r>>2]|0;if(!s){t=0;break}else{u=s;v=r}}else{u=q;v=p}while(1){p=u+20|0;q=c[p>>2]|0;if(q){u=q;v=p;continue}p=u+16|0;q=c[p>>2]|0;if(!q){w=u;x=v;break}else{u=q;v=p}}if(x>>>0<h>>>0)Ma();else{c[x>>2]=0;t=w;break}}else{p=c[a+(f+8)>>2]|0;if(p>>>0<h>>>0)Ma();q=p+12|0;if((c[q>>2]|0)!=(g|0))Ma();r=m+8|0;if((c[r>>2]|0)==(g|0)){c[q>>2]=m;c[r>>2]=p;t=m;break}else Ma()}while(0);if(j){m=c[a+(f+28)>>2]|0;p=58072+(m<<2)|0;if((g|0)==(c[p>>2]|0)){c[p>>2]=t;if(!t){c[14443]=c[14443]&~(1<<m);break}}else{if(j>>>0<(c[14446]|0)>>>0)Ma();m=j+16|0;if((c[m>>2]|0)==(g|0))c[m>>2]=t;else c[j+20>>2]=t;if(!t)break}m=c[14446]|0;if(t>>>0<m>>>0)Ma();c[t+24>>2]=j;p=c[a+(f+16)>>2]|0;do if(p)if(p>>>0<m>>>0)Ma();else{c[t+16>>2]=p;c[p+24>>2]=t;break}while(0);p=c[a+(f+20)>>2]|0;if(p)if(p>>>0<(c[14446]|0)>>>0)Ma();else{c[t+20>>2]=p;c[p+24>>2]=t;break}}}else{p=c[a+(f+8)>>2]|0;m=c[a+(f+12)>>2]|0;j=57808+(i<<1<<2)|0;if((p|0)!=(j|0)){if(p>>>0<h>>>0)Ma();if((c[p+12>>2]|0)!=(g|0))Ma()}if((m|0)==(p|0)){c[14442]=c[14442]&~(1<<i);break}if((m|0)!=(j|0)){if(m>>>0<h>>>0)Ma();j=m+8|0;if((c[j>>2]|0)==(g|0))y=j;else Ma()}else y=m+8|0;c[p+12>>2]=m;c[y>>2]=p}while(0);if(o>>>0<16){c[d>>2]=n|e&1|2;y=a+(n|4)|0;c[y>>2]=c[y>>2]|1;l=a;return l|0}else{c[d>>2]=e&1|b|2;c[a+(b+4)>>2]=o|3;e=a+(n|4)|0;c[e>>2]=c[e>>2]|1;Cd(a+b|0,o);l=a;return l|0}return 0}function Cd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0;d=a+b|0;e=c[a+4>>2]|0;do if(!(e&1)){f=c[a>>2]|0;if(!(e&3))return;g=a+(0-f)|0;h=f+b|0;i=c[14446]|0;if(g>>>0<i>>>0)Ma();if((g|0)==(c[14447]|0)){j=a+(b+4)|0;k=c[j>>2]|0;if((k&3|0)!=3){l=g;m=h;break}c[14444]=h;c[j>>2]=k&-2;c[a+(4-f)>>2]=h|1;c[d>>2]=h;return}k=f>>>3;if(f>>>0<256){j=c[a+(8-f)>>2]|0;n=c[a+(12-f)>>2]|0;o=57808+(k<<1<<2)|0;if((j|0)!=(o|0)){if(j>>>0<i>>>0)Ma();if((c[j+12>>2]|0)!=(g|0))Ma()}if((n|0)==(j|0)){c[14442]=c[14442]&~(1<<k);l=g;m=h;break}if((n|0)!=(o|0)){if(n>>>0<i>>>0)Ma();o=n+8|0;if((c[o>>2]|0)==(g|0))p=o;else Ma()}else p=n+8|0;c[j+12>>2]=n;c[p>>2]=j;l=g;m=h;break}j=c[a+(24-f)>>2]|0;n=c[a+(12-f)>>2]|0;do if((n|0)==(g|0)){o=16-f|0;k=a+(o+4)|0;q=c[k>>2]|0;if(!q){r=a+o|0;o=c[r>>2]|0;if(!o){s=0;break}else{t=o;u=r}}else{t=q;u=k}while(1){k=t+20|0;q=c[k>>2]|0;if(q){t=q;u=k;continue}k=t+16|0;q=c[k>>2]|0;if(!q){v=t;w=u;break}else{t=q;u=k}}if(w>>>0<i>>>0)Ma();else{c[w>>2]=0;s=v;break}}else{k=c[a+(8-f)>>2]|0;if(k>>>0<i>>>0)Ma();q=k+12|0;if((c[q>>2]|0)!=(g|0))Ma();r=n+8|0;if((c[r>>2]|0)==(g|0)){c[q>>2]=n;c[r>>2]=k;s=n;break}else Ma()}while(0);if(j){n=c[a+(28-f)>>2]|0;i=58072+(n<<2)|0;if((g|0)==(c[i>>2]|0)){c[i>>2]=s;if(!s){c[14443]=c[14443]&~(1<<n);l=g;m=h;break}}else{if(j>>>0<(c[14446]|0)>>>0)Ma();n=j+16|0;if((c[n>>2]|0)==(g|0))c[n>>2]=s;else c[j+20>>2]=s;if(!s){l=g;m=h;break}}n=c[14446]|0;if(s>>>0<n>>>0)Ma();c[s+24>>2]=j;i=16-f|0;k=c[a+i>>2]|0;do if(k)if(k>>>0<n>>>0)Ma();else{c[s+16>>2]=k;c[k+24>>2]=s;break}while(0);k=c[a+(i+4)>>2]|0;if(k)if(k>>>0<(c[14446]|0)>>>0)Ma();else{c[s+20>>2]=k;c[k+24>>2]=s;l=g;m=h;break}else{l=g;m=h}}else{l=g;m=h}}else{l=a;m=b}while(0);s=c[14446]|0;if(d>>>0<s>>>0)Ma();v=a+(b+4)|0;w=c[v>>2]|0;if(!(w&2)){if((d|0)==(c[14448]|0)){u=(c[14445]|0)+m|0;c[14445]=u;c[14448]=l;c[l+4>>2]=u|1;if((l|0)!=(c[14447]|0))return;c[14447]=0;c[14444]=0;return}if((d|0)==(c[14447]|0)){u=(c[14444]|0)+m|0;c[14444]=u;c[14447]=l;c[l+4>>2]=u|1;c[l+u>>2]=u;return}u=(w&-8)+m|0;t=w>>>3;do if(w>>>0>=256){p=c[a+(b+24)>>2]|0;e=c[a+(b+12)>>2]|0;do if((e|0)==(d|0)){k=a+(b+20)|0;n=c[k>>2]|0;if(!n){f=a+(b+16)|0;j=c[f>>2]|0;if(!j){x=0;break}else{y=j;z=f}}else{y=n;z=k}while(1){k=y+20|0;n=c[k>>2]|0;if(n){y=n;z=k;continue}k=y+16|0;n=c[k>>2]|0;if(!n){A=y;B=z;break}else{y=n;z=k}}if(B>>>0<s>>>0)Ma();else{c[B>>2]=0;x=A;break}}else{k=c[a+(b+8)>>2]|0;if(k>>>0<s>>>0)Ma();n=k+12|0;if((c[n>>2]|0)!=(d|0))Ma();f=e+8|0;if((c[f>>2]|0)==(d|0)){c[n>>2]=e;c[f>>2]=k;x=e;break}else Ma()}while(0);if(p){e=c[a+(b+28)>>2]|0;h=58072+(e<<2)|0;if((d|0)==(c[h>>2]|0)){c[h>>2]=x;if(!x){c[14443]=c[14443]&~(1<<e);break}}else{if(p>>>0<(c[14446]|0)>>>0)Ma();e=p+16|0;if((c[e>>2]|0)==(d|0))c[e>>2]=x;else c[p+20>>2]=x;if(!x)break}e=c[14446]|0;if(x>>>0<e>>>0)Ma();c[x+24>>2]=p;h=c[a+(b+16)>>2]|0;do if(h)if(h>>>0<e>>>0)Ma();else{c[x+16>>2]=h;c[h+24>>2]=x;break}while(0);h=c[a+(b+20)>>2]|0;if(h)if(h>>>0<(c[14446]|0)>>>0)Ma();else{c[x+20>>2]=h;c[h+24>>2]=x;break}}}else{h=c[a+(b+8)>>2]|0;e=c[a+(b+12)>>2]|0;p=57808+(t<<1<<2)|0;if((h|0)!=(p|0)){if(h>>>0<s>>>0)Ma();if((c[h+12>>2]|0)!=(d|0))Ma()}if((e|0)==(h|0)){c[14442]=c[14442]&~(1<<t);break}if((e|0)!=(p|0)){if(e>>>0<s>>>0)Ma();p=e+8|0;if((c[p>>2]|0)==(d|0))C=p;else Ma()}else C=e+8|0;c[h+12>>2]=e;c[C>>2]=h}while(0);c[l+4>>2]=u|1;c[l+u>>2]=u;if((l|0)==(c[14447]|0)){c[14444]=u;return}else D=u}else{c[v>>2]=w&-2;c[l+4>>2]=m|1;c[l+m>>2]=m;D=m}m=D>>>3;if(D>>>0<256){w=m<<1;v=57808+(w<<2)|0;u=c[14442]|0;C=1<<m;if(u&C){m=57808+(w+2<<2)|0;d=c[m>>2]|0;if(d>>>0<(c[14446]|0)>>>0)Ma();else{E=m;F=d}}else{c[14442]=u|C;E=57808+(w+2<<2)|0;F=v}c[E>>2]=l;c[F+12>>2]=l;c[l+8>>2]=F;c[l+12>>2]=v;return}v=D>>>8;if(v)if(D>>>0>16777215)G=31;else{F=(v+1048320|0)>>>16&8;E=v<<F;v=(E+520192|0)>>>16&4;w=E<<v;E=(w+245760|0)>>>16&2;C=14-(v|F|E)+(w<<E>>>15)|0;G=D>>>(C+7|0)&1|C<<1}else G=0;C=58072+(G<<2)|0;c[l+28>>2]=G;c[l+20>>2]=0;c[l+16>>2]=0;E=c[14443]|0;w=1<<G;if(!(E&w)){c[14443]=E|w;c[C>>2]=l;c[l+24>>2]=C;c[l+12>>2]=l;c[l+8>>2]=l;return}w=c[C>>2]|0;a:do if((c[w+4>>2]&-8|0)==(D|0))H=w;else{C=D<<((G|0)==31?0:25-(G>>>1)|0);E=w;while(1){F=E+16+(C>>>31<<2)|0;v=c[F>>2]|0;if(!v){I=F;J=E;break}if((c[v+4>>2]&-8|0)==(D|0)){H=v;break a}else{C=C<<1;E=v}}if(I>>>0<(c[14446]|0)>>>0)Ma();c[I>>2]=l;c[l+24>>2]=J;c[l+12>>2]=l;c[l+8>>2]=l;return}while(0);J=H+8|0;I=c[J>>2]|0;D=c[14446]|0;if(!(I>>>0>=D>>>0&H>>>0>=D>>>0))Ma();c[I+12>>2]=l;c[J>>2]=l;c[l+8>>2]=I;c[l+12>>2]=H;c[l+24>>2]=0;return}function Dd(){}function Ed(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=b-d>>>0;e=b-d-(c>>>0>a>>>0|0)>>>0;return (C=e,a-c>>>0|0)|0}function Fd(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=b+e|0;if((e|0)>=20){d=d&255;g=b&3;h=d|d<<8|d<<16|d<<24;i=f&~3;if(g){g=b+4-g|0;while((b|0)<(g|0)){a[b>>0]=d;b=b+1|0}}while((b|0)<(i|0)){c[b>>2]=h;b=b+4|0}}while((b|0)<(f|0)){a[b>>0]=d;b=b+1|0}return b-e|0}function Gd(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){C=b<<c|(a&(1<<c)-1<<32-c)>>>32-c;return a<<c}C=a<<c-32;return 0}function Hd(b){b=b|0;var c=0;c=b;while(a[c>>0]|0)c=c+1|0;return c-b|0}function Id(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=a+c>>>0;return (C=b+d+(e>>>0<a>>>0|0)>>>0,e|0)|0}function Jd(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if((e|0)>=4096)return Ia(b|0,d|0,e|0)|0;f=b|0;if((b&3)==(d&3)){while(b&3){if(!e)return f|0;a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function Kd(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){C=b>>>c;return a>>>c|(b&(1<<c)-1)<<32-c}C=0;return b>>>c-32|0}function Ld(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){C=b>>c;return a>>>c|(b&(1<<c)-1)<<32-c}C=(b|0)<0?-1:0;return b>>c-32|0}function Md(b){b=b|0;var c=0;c=a[m+(b&255)>>0]|0;if((c|0)<8)return c|0;c=a[m+(b>>8&255)>>0]|0;if((c|0)<8)return c+8|0;c=a[m+(b>>16&255)>>0]|0;if((c|0)<8)return c+16|0;return (a[m+(b>>>24)>>0]|0)+24|0}function Nd(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;c=a&65535;d=b&65535;e=_(d,c)|0;f=a>>>16;a=(e>>>16)+(_(d,f)|0)|0;d=b>>>16;b=_(d,c)|0;return (C=(a>>>16)+(_(d,f)|0)+(((a&65535)+b|0)>>>16)|0,a+b<<16|e&65535|0)|0}function Od(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;e=b>>31|((b|0)<0?-1:0)<<1;f=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;g=d>>31|((d|0)<0?-1:0)<<1;h=((d|0)<0?-1:0)>>31|((d|0)<0?-1:0)<<1;i=Ed(e^a,f^b,e,f)|0;b=C;a=g^e;e=h^f;return Ed((Td(i,b,Ed(g^c,h^d,g,h)|0,C,0)|0)^a,C^e,a,e)|0}function Pd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+8|0;g=f|0;h=b>>31|((b|0)<0?-1:0)<<1;j=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;k=e>>31|((e|0)<0?-1:0)<<1;l=((e|0)<0?-1:0)>>31|((e|0)<0?-1:0)<<1;m=Ed(h^a,j^b,h,j)|0;b=C;Td(m,b,Ed(k^d,l^e,k,l)|0,C,g)|0;l=Ed(c[g>>2]^h,c[g+4>>2]^j,h,j)|0;j=C;i=f;return (C=j,l)|0}function Qd(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=a;a=c;c=Nd(e,a)|0;f=C;return (C=(_(b,a)|0)+(_(d,e)|0)+f|f&0,c|0|0)|0}function Rd(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return Td(a,b,c,d,0)|0}function Sd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=i;i=i+8|0;g=f|0;Td(a,b,d,e,g)|0;i=f;return (C=c[g+4>>2]|0,c[g>>2]|0)|0}function Td(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,D=0,E=0,F=0,G=0,H=0;g=a;h=b;i=h;j=d;k=e;l=k;if(!i){m=(f|0)!=0;if(!l){if(m){c[f>>2]=(g>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(g>>>0)/(j>>>0)>>>0;return (C=n,o)|0}else{if(!m){n=0;o=0;return (C=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=b&0;n=0;o=0;return (C=n,o)|0}}m=(l|0)==0;do if(j){if(!m){p=(aa(l|0)|0)-(aa(i|0)|0)|0;if(p>>>0<=31){q=p+1|0;r=31-p|0;s=p-31>>31;t=q;u=g>>>(q>>>0)&s|i<<r;v=i>>>(q>>>0)&s;w=0;x=g<<r;break}if(!f){n=0;o=0;return (C=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return (C=n,o)|0}r=j-1|0;if(r&j){s=(aa(j|0)|0)+33-(aa(i|0)|0)|0;q=64-s|0;p=32-s|0;y=p>>31;z=s-32|0;A=z>>31;t=s;u=p-1>>31&i>>>(z>>>0)|(i<<p|g>>>(s>>>0))&A;v=A&i>>>(s>>>0);w=g<<q&y;x=(i<<q|g>>>(z>>>0))&y|g<<p&s-33>>31;break}if(f){c[f>>2]=r&g;c[f+4>>2]=0}if((j|0)==1){n=h|b&0;o=a|0|0;return (C=n,o)|0}else{r=Md(j|0)|0;n=i>>>(r>>>0)|0;o=i<<32-r|g>>>(r>>>0)|0;return (C=n,o)|0}}else{if(m){if(f){c[f>>2]=(i>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(i>>>0)/(j>>>0)>>>0;return (C=n,o)|0}if(!g){if(f){c[f>>2]=0;c[f+4>>2]=(i>>>0)%(l>>>0)}n=0;o=(i>>>0)/(l>>>0)>>>0;return (C=n,o)|0}r=l-1|0;if(!(r&l)){if(f){c[f>>2]=a|0;c[f+4>>2]=r&i|b&0}n=0;o=i>>>((Md(l|0)|0)>>>0);return (C=n,o)|0}r=(aa(l|0)|0)-(aa(i|0)|0)|0;if(r>>>0<=30){s=r+1|0;p=31-r|0;t=s;u=i<<p|g>>>(s>>>0);v=i>>>(s>>>0);w=0;x=g<<p;break}if(!f){n=0;o=0;return (C=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return (C=n,o)|0}while(0);if(!t){B=x;D=w;E=v;F=u;G=0;H=0}else{b=d|0|0;d=k|e&0;e=Id(b|0,d|0,-1,-1)|0;k=C;h=x;x=w;w=v;v=u;u=t;t=0;do{a=h;h=x>>>31|h<<1;x=t|x<<1;g=v<<1|a>>>31|0;a=v>>>31|w<<1|0;Ed(e,k,g,a)|0;i=C;l=i>>31|((i|0)<0?-1:0)<<1;t=l&1;v=Ed(g,a,l&b,(((i|0)<0?-1:0)>>31|((i|0)<0?-1:0)<<1)&d)|0;w=C;u=u-1|0}while((u|0)!=0);B=h;D=x;E=w;F=v;G=0;H=t}t=D;D=0;if(f){c[f>>2]=F;c[f+4>>2]=E}n=(t|0)>>>31|(B|D)<<1|(D<<1|t>>>31)&0|G;o=(t<<1|0>>>31)&-2|H;return (C=n,o)|0}function Ud(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return Va[a&7](b|0,c|0,d|0,e|0)|0}function Vd(a,b){a=a|0;b=b|0;Wa[a&7](b|0)}function Wd(a,b,c){a=a|0;b=b|0;c=c|0;Xa[a&3](b|0,c|0)}function Xd(a,b){a=a|0;b=b|0;return Ya[a&1](b|0)|0}function Yd(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;Za[a&1](b|0,c|0,d|0)}function Zd(a,b,c,d,e,f,g,h,i){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;return _a[a&3](b|0,c|0,d|0,e|0,f|0,g|0,h|0,i|0)|0}function _d(a,b,c){a=a|0;b=b|0;c=c|0;return $a[a&15](b|0,c|0)|0}function $d(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return ab[a&7](b|0,c|0,d|0,e|0,f|0)|0}function ae(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;ba(0);return 0}function be(a){a=a|0;ba(1)}function ce(a,b){a=a|0;b=b|0;ba(2)}function de(a){a=a|0;ba(3);return 0}function ee(a,b,c){a=a|0;b=b|0;c=c|0;ba(4)}function fe(a,b,c,d,e,f,g,h){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;ba(5);return 0}function ge(a,b){a=a|0;b=b|0;ba(6);return 0}function he(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;ba(7);return 0}
+
+// EMSCRIPTEN_END_FUNCS
+var Va=[ae,$c,fd,qc,rc,ae,ae,ae];var Wa=[be,Yc,Zc,cd,dd,bc,cc,id];var Xa=[ce,Uc,dc,ce];var Ya=[de,jd];var Za=[ee,gd];var _a=[fe,hc,lc,fe];var $a=[ge,Vc,Xc,_c,ad,bd,ed,ec,fc,hd,kd,Sc,Tc,Wc,ge,ge];var ab=[he,gc,ic,jc,kc,mc,he,he];return{_i64Subtract:Ed,_free:yd,_ogv_audio_decoder_destroy:od,_ogv_audio_decoder_init:ld,_i64Add:Id,_strlen:Hd,_ogv_audio_decoder_process_header:md,_memset:Fd,_malloc:xd,_memcpy:Jd,_ogv_audio_decoder_process_audio:nd,_bitshift64Shl:Gd,runPostSets:Dd,stackAlloc:bb,stackSave:cb,stackRestore:db,establishStackSpace:eb,setThrew:fb,setTempRet0:ib,getTempRet0:jb,dynCall_iiiii:Ud,dynCall_vi:Vd,dynCall_vii:Wd,dynCall_ii:Xd,dynCall_viii:Yd,dynCall_iiiiiiiii:Zd,dynCall_iii:_d,dynCall_iiiiii:$d}})
+
+
+// EMSCRIPTEN_END_ASM
+(Module.asmGlobalArg,Module.asmLibraryArg,buffer);var _i64Subtract=Module["_i64Subtract"]=asm["_i64Subtract"];var _free=Module["_free"]=asm["_free"];var runPostSets=Module["runPostSets"]=asm["runPostSets"];var _ogv_audio_decoder_destroy=Module["_ogv_audio_decoder_destroy"]=asm["_ogv_audio_decoder_destroy"];var _ogv_audio_decoder_init=Module["_ogv_audio_decoder_init"]=asm["_ogv_audio_decoder_init"];var _i64Add=Module["_i64Add"]=asm["_i64Add"];var _strlen=Module["_strlen"]=asm["_strlen"];var _ogv_audio_decoder_process_header=Module["_ogv_audio_decoder_process_header"]=asm["_ogv_audio_decoder_process_header"];var _memset=Module["_memset"]=asm["_memset"];var _malloc=Module["_malloc"]=asm["_malloc"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _ogv_audio_decoder_process_audio=Module["_ogv_audio_decoder_process_audio"]=asm["_ogv_audio_decoder_process_audio"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var dynCall_iiiii=Module["dynCall_iiiii"]=asm["dynCall_iiiii"];var dynCall_vi=Module["dynCall_vi"]=asm["dynCall_vi"];var dynCall_vii=Module["dynCall_vii"]=asm["dynCall_vii"];var dynCall_ii=Module["dynCall_ii"]=asm["dynCall_ii"];var dynCall_viii=Module["dynCall_viii"]=asm["dynCall_viii"];var dynCall_iiiiiiiii=Module["dynCall_iiiiiiiii"]=asm["dynCall_iiiiiiiii"];var dynCall_iii=Module["dynCall_iii"]=asm["dynCall_iii"];var dynCall_iiiiii=Module["dynCall_iiiiii"]=asm["dynCall_iiiiii"];Runtime.stackAlloc=asm["stackAlloc"];Runtime.stackSave=asm["stackSave"];Runtime.stackRestore=asm["stackRestore"];Runtime.establishStackSpace=asm["establishStackSpace"];Runtime.setTempRet0=asm["setTempRet0"];Runtime.getTempRet0=asm["getTempRet0"];var i64Math=(function(){var goog={math:{}};goog.math.Long=(function(low,high){this.low_=low|0;this.high_=high|0});goog.math.Long.IntCache_={};goog.math.Long.fromInt=(function(value){if(-128<=value&&value<128){var cachedObj=goog.math.Long.IntCache_[value];if(cachedObj){return cachedObj}}var obj=new goog.math.Long(value|0,value<0?-1:0);if(-128<=value&&value<128){goog.math.Long.IntCache_[value]=obj}return obj});goog.math.Long.fromNumber=(function(value){if(isNaN(value)||!isFinite(value)){return goog.math.Long.ZERO}else if(value<=-goog.math.Long.TWO_PWR_63_DBL_){return goog.math.Long.MIN_VALUE}else if(value+1>=goog.math.Long.TWO_PWR_63_DBL_){return goog.math.Long.MAX_VALUE}else if(value<0){return goog.math.Long.fromNumber(-value).negate()}else{return new goog.math.Long(value%goog.math.Long.TWO_PWR_32_DBL_|0,value/goog.math.Long.TWO_PWR_32_DBL_|0)}});goog.math.Long.fromBits=(function(lowBits,highBits){return new goog.math.Long(lowBits,highBits)});goog.math.Long.fromString=(function(str,opt_radix){if(str.length==0){throw Error("number format error: empty string")}var radix=opt_radix||10;if(radix<2||36<radix){throw Error("radix out of range: "+radix)}if(str.charAt(0)=="-"){return goog.math.Long.fromString(str.substring(1),radix).negate()}else if(str.indexOf("-")>=0){throw Error('number format error: interior "-" character: '+str)}var radixToPower=goog.math.Long.fromNumber(Math.pow(radix,8));var result=goog.math.Long.ZERO;for(var i=0;i<str.length;i+=8){var size=Math.min(8,str.length-i);var value=parseInt(str.substring(i,i+size),radix);if(size<8){var power=goog.math.Long.fromNumber(Math.pow(radix,size));result=result.multiply(power).add(goog.math.Long.fromNumber(value))}else{result=result.multiply(radixToPower);result=result.add(goog.math.Long.fromNumber(value))}}return result});goog.math.Long.TWO_PWR_16_DBL_=1<<16;goog.math.Long.TWO_PWR_24_DBL_=1<<24;goog.math.Long.TWO_PWR_32_DBL_=goog.math.Long.TWO_PWR_16_DBL_*goog.math.Long.TWO_PWR_16_DBL_;goog.math.Long.TWO_PWR_31_DBL_=goog.math.Long.TWO_PWR_32_DBL_/2;goog.math.Long.TWO_PWR_48_DBL_=goog.math.Long.TWO_PWR_32_DBL_*goog.math.Long.TWO_PWR_16_DBL_;goog.math.Long.TWO_PWR_64_DBL_=goog.math.Long.TWO_PWR_32_DBL_*goog.math.Long.TWO_PWR_32_DBL_;goog.math.Long.TWO_PWR_63_DBL_=goog.math.Long.TWO_PWR_64_DBL_/2;goog.math.Long.ZERO=goog.math.Long.fromInt(0);goog.math.Long.ONE=goog.math.Long.fromInt(1);goog.math.Long.NEG_ONE=goog.math.Long.fromInt(-1);goog.math.Long.MAX_VALUE=goog.math.Long.fromBits(4294967295|0,2147483647|0);goog.math.Long.MIN_VALUE=goog.math.Long.fromBits(0,2147483648|0);goog.math.Long.TWO_PWR_24_=goog.math.Long.fromInt(1<<24);goog.math.Long.prototype.toInt=(function(){return this.low_});goog.math.Long.prototype.toNumber=(function(){return this.high_*goog.math.Long.TWO_PWR_32_DBL_+this.getLowBitsUnsigned()});goog.math.Long.prototype.toString=(function(opt_radix){var radix=opt_radix||10;if(radix<2||36<radix){throw Error("radix out of range: "+radix)}if(this.isZero()){return"0"}if(this.isNegative()){if(this.equals(goog.math.Long.MIN_VALUE)){var radixLong=goog.math.Long.fromNumber(radix);var div=this.div(radixLong);var rem=div.multiply(radixLong).subtract(this);return div.toString(radix)+rem.toInt().toString(radix)}else{return"-"+this.negate().toString(radix)}}var radixToPower=goog.math.Long.fromNumber(Math.pow(radix,6));var rem=this;var result="";while(true){var remDiv=rem.div(radixToPower);var intval=rem.subtract(remDiv.multiply(radixToPower)).toInt();var digits=intval.toString(radix);rem=remDiv;if(rem.isZero()){return digits+result}else{while(digits.length<6){digits="0"+digits}result=""+digits+result}}});goog.math.Long.prototype.getHighBits=(function(){return this.high_});goog.math.Long.prototype.getLowBits=(function(){return this.low_});goog.math.Long.prototype.getLowBitsUnsigned=(function(){return this.low_>=0?this.low_:goog.math.Long.TWO_PWR_32_DBL_+this.low_});goog.math.Long.prototype.getNumBitsAbs=(function(){if(this.isNegative()){if(this.equals(goog.math.Long.MIN_VALUE)){return 64}else{return this.negate().getNumBitsAbs()}}else{var val=this.high_!=0?this.high_:this.low_;for(var bit=31;bit>0;bit--){if((val&1<<bit)!=0){break}}return this.high_!=0?bit+33:bit+1}});goog.math.Long.prototype.isZero=(function(){return this.high_==0&&this.low_==0});goog.math.Long.prototype.isNegative=(function(){return this.high_<0});goog.math.Long.prototype.isOdd=(function(){return(this.low_&1)==1});goog.math.Long.prototype.equals=(function(other){return this.high_==other.high_&&this.low_==other.low_});goog.math.Long.prototype.notEquals=(function(other){return this.high_!=other.high_||this.low_!=other.low_});goog.math.Long.prototype.lessThan=(function(other){return this.compare(other)<0});goog.math.Long.prototype.lessThanOrEqual=(function(other){return this.compare(other)<=0});goog.math.Long.prototype.greaterThan=(function(other){return this.compare(other)>0});goog.math.Long.prototype.greaterThanOrEqual=(function(other){return this.compare(other)>=0});goog.math.Long.prototype.compare=(function(other){if(this.equals(other)){return 0}var thisNeg=this.isNegative();var otherNeg=other.isNegative();if(thisNeg&&!otherNeg){return-1}if(!thisNeg&&otherNeg){return 1}if(this.subtract(other).isNegative()){return-1}else{return 1}});goog.math.Long.prototype.negate=(function(){if(this.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.MIN_VALUE}else{return this.not().add(goog.math.Long.ONE)}});goog.math.Long.prototype.add=(function(other){var a48=this.high_>>>16;var a32=this.high_&65535;var a16=this.low_>>>16;var a00=this.low_&65535;var b48=other.high_>>>16;var b32=other.high_&65535;var b16=other.low_>>>16;var b00=other.low_&65535;var c48=0,c32=0,c16=0,c00=0;c00+=a00+b00;c16+=c00>>>16;c00&=65535;c16+=a16+b16;c32+=c16>>>16;c16&=65535;c32+=a32+b32;c48+=c32>>>16;c32&=65535;c48+=a48+b48;c48&=65535;return goog.math.Long.fromBits(c16<<16|c00,c48<<16|c32)});goog.math.Long.prototype.subtract=(function(other){return this.add(other.negate())});goog.math.Long.prototype.multiply=(function(other){if(this.isZero()){return goog.math.Long.ZERO}else if(other.isZero()){return goog.math.Long.ZERO}if(this.equals(goog.math.Long.MIN_VALUE)){return other.isOdd()?goog.math.Long.MIN_VALUE:goog.math.Long.ZERO}else if(other.equals(goog.math.Long.MIN_VALUE)){return this.isOdd()?goog.math.Long.MIN_VALUE:goog.math.Long.ZERO}if(this.isNegative()){if(other.isNegative()){return this.negate().multiply(other.negate())}else{return this.negate().multiply(other).negate()}}else if(other.isNegative()){return this.multiply(other.negate()).negate()}if(this.lessThan(goog.math.Long.TWO_PWR_24_)&&other.lessThan(goog.math.Long.TWO_PWR_24_)){return goog.math.Long.fromNumber(this.toNumber()*other.toNumber())}var a48=this.high_>>>16;var a32=this.high_&65535;var a16=this.low_>>>16;var a00=this.low_&65535;var b48=other.high_>>>16;var b32=other.high_&65535;var b16=other.low_>>>16;var b00=other.low_&65535;var c48=0,c32=0,c16=0,c00=0;c00+=a00*b00;c16+=c00>>>16;c00&=65535;c16+=a16*b00;c32+=c16>>>16;c16&=65535;c16+=a00*b16;c32+=c16>>>16;c16&=65535;c32+=a32*b00;c48+=c32>>>16;c32&=65535;c32+=a16*b16;c48+=c32>>>16;c32&=65535;c32+=a00*b32;c48+=c32>>>16;c32&=65535;c48+=a48*b00+a32*b16+a16*b32+a00*b48;c48&=65535;return goog.math.Long.fromBits(c16<<16|c00,c48<<16|c32)});goog.math.Long.prototype.div=(function(other){if(other.isZero()){throw Error("division by zero")}else if(this.isZero()){return goog.math.Long.ZERO}if(this.equals(goog.math.Long.MIN_VALUE)){if(other.equals(goog.math.Long.ONE)||other.equals(goog.math.Long.NEG_ONE)){return goog.math.Long.MIN_VALUE}else if(other.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.ONE}else{var halfThis=this.shiftRight(1);var approx=halfThis.div(other).shiftLeft(1);if(approx.equals(goog.math.Long.ZERO)){return other.isNegative()?goog.math.Long.ONE:goog.math.Long.NEG_ONE}else{var rem=this.subtract(other.multiply(approx));var result=approx.add(rem.div(other));return result}}}else if(other.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.ZERO}if(this.isNegative()){if(other.isNegative()){return this.negate().div(other.negate())}else{return this.negate().div(other).negate()}}else if(other.isNegative()){return this.div(other.negate()).negate()}var res=goog.math.Long.ZERO;var rem=this;while(rem.greaterThanOrEqual(other)){var approx=Math.max(1,Math.floor(rem.toNumber()/other.toNumber()));var log2=Math.ceil(Math.log(approx)/Math.LN2);var delta=log2<=48?1:Math.pow(2,log2-48);var approxRes=goog.math.Long.fromNumber(approx);var approxRem=approxRes.multiply(other);while(approxRem.isNegative()||approxRem.greaterThan(rem)){approx-=delta;approxRes=goog.math.Long.fromNumber(approx);approxRem=approxRes.multiply(other)}if(approxRes.isZero()){approxRes=goog.math.Long.ONE}res=res.add(approxRes);rem=rem.subtract(approxRem)}return res});goog.math.Long.prototype.modulo=(function(other){return this.subtract(this.div(other).multiply(other))});goog.math.Long.prototype.not=(function(){return goog.math.Long.fromBits(~this.low_,~this.high_)});goog.math.Long.prototype.and=(function(other){return goog.math.Long.fromBits(this.low_&other.low_,this.high_&other.high_)});goog.math.Long.prototype.or=(function(other){return goog.math.Long.fromBits(this.low_|other.low_,this.high_|other.high_)});goog.math.Long.prototype.xor=(function(other){return goog.math.Long.fromBits(this.low_^other.low_,this.high_^other.high_)});goog.math.Long.prototype.shiftLeft=(function(numBits){numBits&=63;if(numBits==0){return this}else{var low=this.low_;if(numBits<32){var high=this.high_;return goog.math.Long.fromBits(low<<numBits,high<<numBits|low>>>32-numBits)}else{return goog.math.Long.fromBits(0,low<<numBits-32)}}});goog.math.Long.prototype.shiftRight=(function(numBits){numBits&=63;if(numBits==0){return this}else{var high=this.high_;if(numBits<32){var low=this.low_;return goog.math.Long.fromBits(low>>>numBits|high<<32-numBits,high>>numBits)}else{return goog.math.Long.fromBits(high>>numBits-32,high>=0?0:-1)}}});goog.math.Long.prototype.shiftRightUnsigned=(function(numBits){numBits&=63;if(numBits==0){return this}else{var high=this.high_;if(numBits<32){var low=this.low_;return goog.math.Long.fromBits(low>>>numBits|high<<32-numBits,high>>>numBits)}else if(numBits==32){return goog.math.Long.fromBits(high,0)}else{return goog.math.Long.fromBits(high>>>numBits-32,0)}}});var navigator={appName:"Modern Browser"};var dbits;var canary=0xdeadbeefcafe;var j_lm=(canary&16777215)==15715070;function BigInteger(a,b,c){if(a!=null)if("number"==typeof a)this.fromNumber(a,b,c);else if(b==null&&"string"!=typeof a)this.fromString(a,256);else this.fromString(a,b)}function nbi(){return new BigInteger(null)}function am1(i,x,w,j,c,n){while(--n>=0){var v=x*this[i++]+w[j]+c;c=Math.floor(v/67108864);w[j++]=v&67108863}return c}function am2(i,x,w,j,c,n){var xl=x&32767,xh=x>>15;while(--n>=0){var l=this[i]&32767;var h=this[i++]>>15;var m=xh*l+h*xl;l=xl*l+((m&32767)<<15)+w[j]+(c&1073741823);c=(l>>>30)+(m>>>15)+xh*h+(c>>>30);w[j++]=l&1073741823}return c}function am3(i,x,w,j,c,n){var xl=x&16383,xh=x>>14;while(--n>=0){var l=this[i]&16383;var h=this[i++]>>14;var m=xh*l+h*xl;l=xl*l+((m&16383)<<14)+w[j]+c;c=(l>>28)+(m>>14)+xh*h;w[j++]=l&268435455}return c}if(j_lm&&navigator.appName=="Microsoft Internet Explorer"){BigInteger.prototype.am=am2;dbits=30}else if(j_lm&&navigator.appName!="Netscape"){BigInteger.prototype.am=am1;dbits=26}else{BigInteger.prototype.am=am3;dbits=28}BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=(1<<dbits)-1;BigInteger.prototype.DV=1<<dbits;var BI_FP=52;BigInteger.prototype.FV=Math.pow(2,BI_FP);BigInteger.prototype.F1=BI_FP-dbits;BigInteger.prototype.F2=2*dbits-BI_FP;var BI_RM="0123456789abcdefghijklmnopqrstuvwxyz";var BI_RC=new Array;var rr,vv;rr="0".charCodeAt(0);for(vv=0;vv<=9;++vv)BI_RC[rr++]=vv;rr="a".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;rr="A".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;function int2char(n){return BI_RM.charAt(n)}function intAt(s,i){var c=BI_RC[s.charCodeAt(i)];return c==null?-1:c}function bnpCopyTo(r){for(var i=this.t-1;i>=0;--i)r[i]=this[i];r.t=this.t;r.s=this.s}function bnpFromInt(x){this.t=1;this.s=x<0?-1:0;if(x>0)this[0]=x;else if(x<-1)this[0]=x+DV;else this.t=0}function nbv(i){var r=nbi();r.fromInt(i);return r}function bnpFromString(s,b){var k;if(b==16)k=4;else if(b==8)k=3;else if(b==256)k=8;else if(b==2)k=1;else if(b==32)k=5;else if(b==4)k=2;else{this.fromRadix(s,b);return}this.t=0;this.s=0;var i=s.length,mi=false,sh=0;while(--i>=0){var x=k==8?s[i]&255:intAt(s,i);if(x<0){if(s.charAt(i)=="-")mi=true;continue}mi=false;if(sh==0)this[this.t++]=x;else if(sh+k>this.DB){this[this.t-1]|=(x&(1<<this.DB-sh)-1)<<sh;this[this.t++]=x>>this.DB-sh}else this[this.t-1]|=x<<sh;sh+=k;if(sh>=this.DB)sh-=this.DB}if(k==8&&(s[0]&128)!=0){this.s=-1;if(sh>0)this[this.t-1]|=(1<<this.DB-sh)-1<<sh}this.clamp();if(mi)BigInteger.ZERO.subTo(this,this)}function bnpClamp(){var c=this.s&this.DM;while(this.t>0&&this[this.t-1]==c)--this.t}function bnToString(b){if(this.s<0)return"-"+this.negate().toString(b);var k;if(b==16)k=4;else if(b==8)k=3;else if(b==2)k=1;else if(b==32)k=5;else if(b==4)k=2;else return this.toRadix(b);var km=(1<<k)-1,d,m=false,r="",i=this.t;var p=this.DB-i*this.DB%k;if(i-->0){if(p<this.DB&&(d=this[i]>>p)>0){m=true;r=int2char(d)}while(i>=0){if(p<k){d=(this[i]&(1<<p)-1)<<k-p;d|=this[--i]>>(p+=this.DB-k)}else{d=this[i]>>(p-=k)&km;if(p<=0){p+=this.DB;--i}}if(d>0)m=true;if(m)r+=int2char(d)}}return m?r:"0"}function bnNegate(){var r=nbi();BigInteger.ZERO.subTo(this,r);return r}function bnAbs(){return this.s<0?this.negate():this}function bnCompareTo(a){var r=this.s-a.s;if(r!=0)return r;var i=this.t;r=i-a.t;if(r!=0)return this.s<0?-r:r;while(--i>=0)if((r=this[i]-a[i])!=0)return r;return 0}function nbits(x){var r=1,t;if((t=x>>>16)!=0){x=t;r+=16}if((t=x>>8)!=0){x=t;r+=8}if((t=x>>4)!=0){x=t;r+=4}if((t=x>>2)!=0){x=t;r+=2}if((t=x>>1)!=0){x=t;r+=1}return r}function bnBitLength(){if(this.t<=0)return 0;return this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(n,r){var i;for(i=this.t-1;i>=0;--i)r[i+n]=this[i];for(i=n-1;i>=0;--i)r[i]=0;r.t=this.t+n;r.s=this.s}function bnpDRShiftTo(n,r){for(var i=n;i<this.t;++i)r[i-n]=this[i];r.t=Math.max(this.t-n,0);r.s=this.s}function bnpLShiftTo(n,r){var bs=n%this.DB;var cbs=this.DB-bs;var bm=(1<<cbs)-1;var ds=Math.floor(n/this.DB),c=this.s<<bs&this.DM,i;for(i=this.t-1;i>=0;--i){r[i+ds+1]=this[i]>>cbs|c;c=(this[i]&bm)<<bs}for(i=ds-1;i>=0;--i)r[i]=0;r[ds]=c;r.t=this.t+ds+1;r.s=this.s;r.clamp()}function bnpRShiftTo(n,r){r.s=this.s;var ds=Math.floor(n/this.DB);if(ds>=this.t){r.t=0;return}var bs=n%this.DB;var cbs=this.DB-bs;var bm=(1<<bs)-1;r[0]=this[ds]>>bs;for(var i=ds+1;i<this.t;++i){r[i-ds-1]|=(this[i]&bm)<<cbs;r[i-ds]=this[i]>>bs}if(bs>0)r[this.t-ds-1]|=(this.s&bm)<<cbs;r.t=this.t-ds;r.clamp()}function bnpSubTo(a,r){var i=0,c=0,m=Math.min(a.t,this.t);while(i<m){c+=this[i]-a[i];r[i++]=c&this.DM;c>>=this.DB}if(a.t<this.t){c-=a.s;while(i<this.t){c+=this[i];r[i++]=c&this.DM;c>>=this.DB}c+=this.s}else{c+=this.s;while(i<a.t){c-=a[i];r[i++]=c&this.DM;c>>=this.DB}c-=a.s}r.s=c<0?-1:0;if(c<-1)r[i++]=this.DV+c;else if(c>0)r[i++]=c;r.t=i;r.clamp()}function bnpMultiplyTo(a,r){var x=this.abs(),y=a.abs();var i=x.t;r.t=i+y.t;while(--i>=0)r[i]=0;for(i=0;i<y.t;++i)r[i+x.t]=x.am(0,y[i],r,i,0,x.t);r.s=0;r.clamp();if(this.s!=a.s)BigInteger.ZERO.subTo(r,r)}function bnpSquareTo(r){var x=this.abs();var i=r.t=2*x.t;while(--i>=0)r[i]=0;for(i=0;i<x.t-1;++i){var c=x.am(i,x[i],r,2*i,0,1);if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1))>=x.DV){r[i+x.t]-=x.DV;r[i+x.t+1]=1}}if(r.t>0)r[r.t-1]+=x.am(i,x[i],r,2*i,0,1);r.s=0;r.clamp()}function bnpDivRemTo(m,q,r){var pm=m.abs();if(pm.t<=0)return;var pt=this.abs();if(pt.t<pm.t){if(q!=null)q.fromInt(0);if(r!=null)this.copyTo(r);return}if(r==null)r=nbi();var y=nbi(),ts=this.s,ms=m.s;var nsh=this.DB-nbits(pm[pm.t-1]);if(nsh>0){pm.lShiftTo(nsh,y);pt.lShiftTo(nsh,r)}else{pm.copyTo(y);pt.copyTo(r)}var ys=y.t;var y0=y[ys-1];if(y0==0)return;var yt=y0*(1<<this.F1)+(ys>1?y[ys-2]>>this.F2:0);var d1=this.FV/yt,d2=(1<<this.F1)/yt,e=1<<this.F2;var i=r.t,j=i-ys,t=q==null?nbi():q;y.dlShiftTo(j,t);if(r.compareTo(t)>=0){r[r.t++]=1;r.subTo(t,r)}BigInteger.ONE.dlShiftTo(ys,t);t.subTo(y,y);while(y.t<ys)y[y.t++]=0;while(--j>=0){var qd=r[--i]==y0?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);if((r[i]+=y.am(0,qd,r,j,0,ys))<qd){y.dlShiftTo(j,t);r.subTo(t,r);while(r[i]<--qd)r.subTo(t,r)}}if(q!=null){r.drShiftTo(ys,q);if(ts!=ms)BigInteger.ZERO.subTo(q,q)}r.t=ys;r.clamp();if(nsh>0)r.rShiftTo(nsh,r);if(ts<0)BigInteger.ZERO.subTo(r,r)}function bnMod(a){var r=nbi();this.abs().divRemTo(a,null,r);if(this.s<0&&r.compareTo(BigInteger.ZERO)>0)a.subTo(r,r);return r}function Classic(m){this.m=m}function cConvert(x){if(x.s<0||x.compareTo(this.m)>=0)return x.mod(this.m);else return x}function cRevert(x){return x}function cReduce(x){x.divRemTo(this.m,null,x)}function cMulTo(x,y,r){x.multiplyTo(y,r);this.reduce(r)}function cSqrTo(x,r){x.squareTo(r);this.reduce(r)}Classic.prototype.convert=cConvert;Classic.prototype.revert=cRevert;Classic.prototype.reduce=cReduce;Classic.prototype.mulTo=cMulTo;Classic.prototype.sqrTo=cSqrTo;function bnpInvDigit(){if(this.t<1)return 0;var x=this[0];if((x&1)==0)return 0;var y=x&3;y=y*(2-(x&15)*y)&15;y=y*(2-(x&255)*y)&255;y=y*(2-((x&65535)*y&65535))&65535;y=y*(2-x*y%this.DV)%this.DV;return y>0?this.DV-y:-y}function Montgomery(m){this.m=m;this.mp=m.invDigit();this.mpl=this.mp&32767;this.mph=this.mp>>15;this.um=(1<<m.DB-15)-1;this.mt2=2*m.t}function montConvert(x){var r=nbi();x.abs().dlShiftTo(this.m.t,r);r.divRemTo(this.m,null,r);if(x.s<0&&r.compareTo(BigInteger.ZERO)>0)this.m.subTo(r,r);return r}function montRevert(x){var r=nbi();x.copyTo(r);this.reduce(r);return r}function montReduce(x){while(x.t<=this.mt2)x[x.t++]=0;for(var i=0;i<this.m.t;++i){var j=x[i]&32767;var u0=j*this.mpl+((j*this.mph+(x[i]>>15)*this.mpl&this.um)<<15)&x.DM;j=i+this.m.t;x[j]+=this.m.am(0,u0,x,i,0,this.m.t);while(x[j]>=x.DV){x[j]-=x.DV;x[++j]++}}x.clamp();x.drShiftTo(this.m.t,x);if(x.compareTo(this.m)>=0)x.subTo(this.m,x)}function montSqrTo(x,r){x.squareTo(r);this.reduce(r)}function montMulTo(x,y,r){x.multiplyTo(y,r);this.reduce(r)}Montgomery.prototype.convert=montConvert;Montgomery.prototype.revert=montRevert;Montgomery.prototype.reduce=montReduce;Montgomery.prototype.mulTo=montMulTo;Montgomery.prototype.sqrTo=montSqrTo;function bnpIsEven(){return(this.t>0?this[0]&1:this.s)==0}function bnpExp(e,z){if(e>4294967295||e<1)return BigInteger.ONE;var r=nbi(),r2=nbi(),g=z.convert(this),i=nbits(e)-1;g.copyTo(r);while(--i>=0){z.sqrTo(r,r2);if((e&1<<i)>0)z.mulTo(r2,g,r);else{var t=r;r=r2;r2=t}}return z.revert(r)}function bnModPowInt(e,m){var z;if(e<256||m.isEven())z=new Classic(m);else z=new Montgomery(m);return this.exp(e,z)}BigInteger.prototype.copyTo=bnpCopyTo;BigInteger.prototype.fromInt=bnpFromInt;BigInteger.prototype.fromString=bnpFromString;BigInteger.prototype.clamp=bnpClamp;BigInteger.prototype.dlShiftTo=bnpDLShiftTo;BigInteger.prototype.drShiftTo=bnpDRShiftTo;BigInteger.prototype.lShiftTo=bnpLShiftTo;BigInteger.prototype.rShiftTo=bnpRShiftTo;BigInteger.prototype.subTo=bnpSubTo;BigInteger.prototype.multiplyTo=bnpMultiplyTo;BigInteger.prototype.squareTo=bnpSquareTo;BigInteger.prototype.divRemTo=bnpDivRemTo;BigInteger.prototype.invDigit=bnpInvDigit;BigInteger.prototype.isEven=bnpIsEven;BigInteger.prototype.exp=bnpExp;BigInteger.prototype.toString=bnToString;BigInteger.prototype.negate=bnNegate;BigInteger.prototype.abs=bnAbs;BigInteger.prototype.compareTo=bnCompareTo;BigInteger.prototype.bitLength=bnBitLength;BigInteger.prototype.mod=bnMod;BigInteger.prototype.modPowInt=bnModPowInt;BigInteger.ZERO=nbv(0);BigInteger.ONE=nbv(1);function bnpFromRadix(s,b){this.fromInt(0);if(b==null)b=10;var cs=this.chunkSize(b);var d=Math.pow(b,cs),mi=false,j=0,w=0;for(var i=0;i<s.length;++i){var x=intAt(s,i);if(x<0){if(s.charAt(i)=="-"&&this.signum()==0)mi=true;continue}w=b*w+x;if(++j>=cs){this.dMultiply(d);this.dAddOffset(w,0);j=0;w=0}}if(j>0){this.dMultiply(Math.pow(b,j));this.dAddOffset(w,0)}if(mi)BigInteger.ZERO.subTo(this,this)}function bnpChunkSize(r){return Math.floor(Math.LN2*this.DB/Math.log(r))}function bnSigNum(){if(this.s<0)return-1;else if(this.t<=0||this.t==1&&this[0]<=0)return 0;else return 1}function bnpDMultiply(n){this[this.t]=this.am(0,n-1,this,0,0,this.t);++this.t;this.clamp()}function bnpDAddOffset(n,w){if(n==0)return;while(this.t<=w)this[this.t++]=0;this[w]+=n;while(this[w]>=this.DV){this[w]-=this.DV;if(++w>=this.t)this[this.t++]=0;++this[w]}}function bnpToRadix(b){if(b==null)b=10;if(this.signum()==0||b<2||b>36)return"0";var cs=this.chunkSize(b);var a=Math.pow(b,cs);var d=nbv(a),y=nbi(),z=nbi(),r="";this.divRemTo(d,y,z);while(y.signum()>0){r=(a+z.intValue()).toString(b).substr(1)+r;y.divRemTo(d,y,z)}return z.intValue().toString(b)+r}function bnIntValue(){if(this.s<0){if(this.t==1)return this[0]-this.DV;else if(this.t==0)return-1}else if(this.t==1)return this[0];else if(this.t==0)return 0;return(this[1]&(1<<32-this.DB)-1)<<this.DB|this[0]}function bnpAddTo(a,r){var i=0,c=0,m=Math.min(a.t,this.t);while(i<m){c+=this[i]+a[i];r[i++]=c&this.DM;c>>=this.DB}if(a.t<this.t){c+=a.s;while(i<this.t){c+=this[i];r[i++]=c&this.DM;c>>=this.DB}c+=this.s}else{c+=this.s;while(i<a.t){c+=a[i];r[i++]=c&this.DM;c>>=this.DB}c+=a.s}r.s=c<0?-1:0;if(c>0)r[i++]=c;else if(c<-1)r[i++]=this.DV+c;r.t=i;r.clamp()}BigInteger.prototype.fromRadix=bnpFromRadix;BigInteger.prototype.chunkSize=bnpChunkSize;BigInteger.prototype.signum=bnSigNum;BigInteger.prototype.dMultiply=bnpDMultiply;BigInteger.prototype.dAddOffset=bnpDAddOffset;BigInteger.prototype.toRadix=bnpToRadix;BigInteger.prototype.intValue=bnIntValue;BigInteger.prototype.addTo=bnpAddTo;var Wrapper={abs:(function(l,h){var x=new goog.math.Long(l,h);var ret;if(x.isNegative()){ret=x.negate()}else{ret=x}HEAP32[tempDoublePtr>>2]=ret.low_;HEAP32[tempDoublePtr+4>>2]=ret.high_}),ensureTemps:(function(){if(Wrapper.ensuredTemps)return;Wrapper.ensuredTemps=true;Wrapper.two32=new BigInteger;Wrapper.two32.fromString("4294967296",10);Wrapper.two64=new BigInteger;Wrapper.two64.fromString("18446744073709551616",10);Wrapper.temp1=new BigInteger;Wrapper.temp2=new BigInteger}),lh2bignum:(function(l,h){var a=new BigInteger;a.fromString(h.toString(),10);var b=new BigInteger;a.multiplyTo(Wrapper.two32,b);var c=new BigInteger;c.fromString(l.toString(),10);var d=new BigInteger;c.addTo(b,d);return d}),stringify:(function(l,h,unsigned){var ret=(new goog.math.Long(l,h)).toString();if(unsigned&&ret[0]=="-"){Wrapper.ensureTemps();var bignum=new BigInteger;bignum.fromString(ret,10);ret=new BigInteger;Wrapper.two64.addTo(bignum,ret);ret=ret.toString(10)}return ret}),fromString:(function(str,base,min,max,unsigned){Wrapper.ensureTemps();var bignum=new BigInteger;bignum.fromString(str,base);var bigmin=new BigInteger;bigmin.fromString(min,10);var bigmax=new BigInteger;bigmax.fromString(max,10);if(unsigned&&bignum.compareTo(BigInteger.ZERO)<0){var temp=new BigInteger;bignum.addTo(Wrapper.two64,temp);bignum=temp}var error=false;if(bignum.compareTo(bigmin)<0){bignum=bigmin;error=true}else if(bignum.compareTo(bigmax)>0){bignum=bigmax;error=true}var ret=goog.math.Long.fromString(bignum.toString());HEAP32[tempDoublePtr>>2]=ret.low_;HEAP32[tempDoublePtr+4>>2]=ret.high_;if(error)throw"range error"})};return Wrapper})();function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}ExitStatus.prototype=new Error;ExitStatus.prototype.constructor=ExitStatus;var initialStackTop;var preloadStartTime=null;var calledMain=false;dependenciesFulfilled=function runCaller(){if(!Module["calledRun"])run();if(!Module["calledRun"])dependenciesFulfilled=runCaller};Module["callMain"]=Module.callMain=function callMain(args){assert(runDependencies==0,"cannot call main when async dependencies remain! (listen on __ATMAIN__)");assert(__ATPRERUN__.length==0,"cannot call main when preRun functions remain to be called");args=args||[];ensureInitRuntime();var argc=args.length+1;function pad(){for(var i=0;i<4-1;i++){argv.push(0)}}var argv=[allocate(intArrayFromString(Module["thisProgram"]),"i8",ALLOC_NORMAL)];pad();for(var i=0;i<argc-1;i=i+1){argv.push(allocate(intArrayFromString(args[i]),"i8",ALLOC_NORMAL));pad()}argv.push(0);argv=allocate(argv,"i32",ALLOC_NORMAL);initialStackTop=STACKTOP;try{var ret=Module["_main"](argc,argv,0);exit(ret,true)}catch(e){if(e instanceof ExitStatus){return}else if(e=="SimulateInfiniteLoop"){Module["noExitRuntime"]=true;return}else{if(e&&typeof e==="object"&&e.stack)Module.printErr("exception thrown: "+[e,e.stack]);throw e}}finally{calledMain=true}};function run(args){args=args||Module["arguments"];if(preloadStartTime===null)preloadStartTime=Date.now();if(runDependencies>0){return}preRun();if(runDependencies>0)return;if(Module["calledRun"])return;function doRun(){if(Module["calledRun"])return;Module["calledRun"]=true;if(ABORT)return;ensureInitRuntime();preMain();if(ENVIRONMENT_IS_WEB&&preloadStartTime!==null){Module.printErr("pre-main prep time: "+(Date.now()-preloadStartTime)+" ms")}if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(Module["_main"]&&shouldRunNow)Module["callMain"](args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout((function(){setTimeout((function(){Module["setStatus"]("")}),1);doRun()}),1)}else{doRun()}}Module["run"]=Module.run=run;function exit(status,implicit){if(implicit&&Module["noExitRuntime"]){return}if(Module["noExitRuntime"]){}else{ABORT=true;EXITSTATUS=status;STACKTOP=initialStackTop;exitRuntime();if(Module["onExit"])Module["onExit"](status)}if(ENVIRONMENT_IS_NODE){process["stdout"]["once"]("drain",(function(){process["exit"](status)}));console.log(" ");setTimeout((function(){process["exit"](status)}),500)}else if(ENVIRONMENT_IS_SHELL&&typeof quit==="function"){quit(status)}throw new ExitStatus(status)}Module["exit"]=Module.exit=exit;var abortDecorators=[];function abort(what){if(what!==undefined){Module.print(what);Module.printErr(what);what=JSON.stringify(what)}else{what=""}ABORT=true;EXITSTATUS=1;var extra="\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.";var output="abort("+what+") at "+stackTrace()+extra;if(abortDecorators){abortDecorators.forEach((function(decorator){output=decorator(output,what)}))}throw output}Module["abort"]=Module.abort=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=false;if(Module["noInitialRun"]){shouldRunNow=false}Module["noExitRuntime"]=true;run();var inputBuffer,inputBufferSize;function reallocInputBuffer(size){if(inputBuffer&&inputBufferSize>=size){return inputBuffer}if(inputBuffer){Module._free(inputBuffer)}inputBufferSize=size;inputBuffer=Module._malloc(inputBufferSize);return inputBuffer}Module.loadedMetadata=!!options.audioFormat;Module.audioFormat=options.audioFormat||null;Module.audioBuffer=null;Object.defineProperty(Module,"processing",{get:function getProcessing(){return false}});Module.init=(function(callback){Module._ogv_audio_decoder_init();callback()});Module.processHeader=(function(data,callback){var len=data.byteLength;var buffer=reallocInputBuffer(len);Module.HEAPU8.set(new Uint8Array(data),buffer);var ret=Module._ogv_audio_decoder_process_header(buffer,len);callback(ret)});Module.processAudio=(function(data,callback){var len=data.byteLength;var buffer=reallocInputBuffer(len);Module.HEAPU8.set(new Uint8Array(data),buffer);var ret=Module._ogv_audio_decoder_process_audio(buffer,len);callback(ret)})
+
+
+
+
+
+ return Module;
+};
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-decoder-video-theora.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-decoder-video-theora.js
new file mode 100644
index 00000000..3421de39
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-decoder-video-theora.js
@@ -0,0 +1,22 @@
+var OGVDecoderVideoTheora = function(Module) {
+ Module = Module || {};
+
+var options=Module;Module={print:(function(str){console.log(str)})};var Module;if(!Module)Module=(typeof OGVDecoderVideoTheora!=="undefined"?OGVDecoderVideoTheora:null)||{};var moduleOverrides={};for(var key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var ENVIRONMENT_IS_WEB=typeof window==="object";var ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof require==="function"&&!ENVIRONMENT_IS_WEB;var ENVIRONMENT_IS_WORKER=typeof importScripts==="function";var ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){if(!Module["print"])Module["print"]=function print(x){process["stdout"].write(x+"\n")};if(!Module["printErr"])Module["printErr"]=function printErr(x){process["stderr"].write(x+"\n")};var nodeFS=require("fs");var nodePath=require("path");Module["read"]=function read(filename,binary){filename=nodePath["normalize"](filename);var ret=nodeFS["readFileSync"](filename);if(!ret&&filename!=nodePath["resolve"](filename)){filename=path.join(__dirname,"..","src",filename);ret=nodeFS["readFileSync"](filename)}if(ret&&!binary)ret=ret.toString();return ret};Module["readBinary"]=function readBinary(filename){return Module["read"](filename,true)};Module["load"]=function load(f){globalEval(read(f))};if(!Module["thisProgram"]){if(process["argv"].length>1){Module["thisProgram"]=process["argv"][1].replace(/\\/g,"/")}else{Module["thisProgram"]="unknown-program"}}Module["arguments"]=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",(function(ex){if(!(ex instanceof ExitStatus)){throw ex}}));Module["inspect"]=(function(){return"[Emscripten Module object]"})}else if(ENVIRONMENT_IS_SHELL){if(!Module["print"])Module["print"]=print;if(typeof printErr!="undefined")Module["printErr"]=printErr;if(typeof read!="undefined"){Module["read"]=read}else{Module["read"]=function read(){throw"no read() available (jsc?)"}}Module["readBinary"]=function readBinary(f){if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}var data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){Module["arguments"]=scriptArgs}else if(typeof arguments!="undefined"){Module["arguments"]=arguments}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){Module["read"]=function read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(typeof arguments!="undefined"){Module["arguments"]=arguments}if(typeof console!=="undefined"){if(!Module["print"])Module["print"]=function print(x){console.log(x)};if(!Module["printErr"])Module["printErr"]=function printErr(x){console.log(x)}}else{var TRY_USE_DUMP=false;if(!Module["print"])Module["print"]=TRY_USE_DUMP&&typeof dump!=="undefined"?(function(x){dump(x)}):(function(x){})}if(ENVIRONMENT_IS_WORKER){Module["load"]=importScripts}if(typeof Module["setWindowTitle"]==="undefined"){Module["setWindowTitle"]=(function(title){document.title=title})}}else{throw"Unknown runtime environment. Where are we?"}function globalEval(x){eval.call(null,x)}if(!Module["load"]&&Module["read"]){Module["load"]=function load(f){globalEval(Module["read"](f))}}if(!Module["print"]){Module["print"]=(function(){})}if(!Module["printErr"]){Module["printErr"]=Module["print"]}if(!Module["arguments"]){Module["arguments"]=[]}if(!Module["thisProgram"]){Module["thisProgram"]="./this.program"}Module.print=Module["print"];Module.printErr=Module["printErr"];Module["preRun"]=[];Module["postRun"]=[];for(var key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}var Runtime={setTempRet0:(function(value){tempRet0=value}),getTempRet0:(function(){return tempRet0}),stackSave:(function(){return STACKTOP}),stackRestore:(function(stackTop){STACKTOP=stackTop}),getNativeTypeSize:(function(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return Runtime.QUANTUM_SIZE}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0);return bits/8}else{return 0}}}}),getNativeFieldSize:(function(type){return Math.max(Runtime.getNativeTypeSize(type),Runtime.QUANTUM_SIZE)}),STACK_ALIGN:16,prepVararg:(function(ptr,type){if(type==="double"||type==="i64"){if(ptr&7){assert((ptr&7)===4);ptr+=4}}else{assert((ptr&3)===0)}return ptr}),getAlignSize:(function(type,size,vararg){if(!vararg&&(type=="i64"||type=="double"))return 8;if(!type)return Math.min(size,8);return Math.min(size||(type?Runtime.getNativeFieldSize(type):0),Runtime.QUANTUM_SIZE)}),dynCall:(function(sig,ptr,args){if(args&&args.length){if(!args.splice)args=Array.prototype.slice.call(args);args.splice(0,0,ptr);return Module["dynCall_"+sig].apply(null,args)}else{return Module["dynCall_"+sig].call(null,ptr)}}),functionPointers:[],addFunction:(function(func){for(var i=0;i<Runtime.functionPointers.length;i++){if(!Runtime.functionPointers[i]){Runtime.functionPointers[i]=func;return 2*(1+i)}}throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS."}),removeFunction:(function(index){Runtime.functionPointers[(index-2)/2]=null}),warnOnce:(function(text){if(!Runtime.warnOnce.shown)Runtime.warnOnce.shown={};if(!Runtime.warnOnce.shown[text]){Runtime.warnOnce.shown[text]=1;Module.printErr(text)}}),funcWrappers:{},getFuncWrapper:(function(func,sig){assert(sig);if(!Runtime.funcWrappers[sig]){Runtime.funcWrappers[sig]={}}var sigCache=Runtime.funcWrappers[sig];if(!sigCache[func]){sigCache[func]=function dynCall_wrapper(){return Runtime.dynCall(sig,func,arguments)}}return sigCache[func]}),getCompilerSetting:(function(name){throw"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work"}),stackAlloc:(function(size){var ret=STACKTOP;STACKTOP=STACKTOP+size|0;STACKTOP=STACKTOP+15&-16;return ret}),staticAlloc:(function(size){var ret=STATICTOP;STATICTOP=STATICTOP+size|0;STATICTOP=STATICTOP+15&-16;return ret}),dynamicAlloc:(function(size){var ret=DYNAMICTOP;DYNAMICTOP=DYNAMICTOP+size|0;DYNAMICTOP=DYNAMICTOP+15&-16;if(DYNAMICTOP>=TOTAL_MEMORY){var success=enlargeMemory();if(!success){DYNAMICTOP=ret;return 0}}return ret}),alignMemory:(function(size,quantum){var ret=size=Math.ceil(size/(quantum?quantum:16))*(quantum?quantum:16);return ret}),makeBigInt:(function(low,high,unsigned){var ret=unsigned?+(low>>>0)+ +(high>>>0)*+4294967296:+(low>>>0)+ +(high|0)*+4294967296;return ret}),GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module["Runtime"]=Runtime;var __THREW__=0;var ABORT=false;var EXITSTATUS=0;var undef=0;var tempValue,tempInt,tempBigInt,tempInt2,tempBigInt2,tempPair,tempBigIntI,tempBigIntR,tempBigIntS,tempBigIntP,tempBigIntD,tempDouble,tempFloat;var tempI64,tempI64b;var tempRet0,tempRet1,tempRet2,tempRet3,tempRet4,tempRet5,tempRet6,tempRet7,tempRet8,tempRet9;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var globalScope=this;function getCFunc(ident){var func=Module["_"+ident];if(!func){try{func=eval("_"+ident)}catch(e){}}assert(func,"Cannot call unknown function "+ident+" (perhaps LLVM optimizations or closure removed it?)");return func}var cwrap,ccall;((function(){var JSfuncs={"stackSave":(function(){Runtime.stackSave()}),"stackRestore":(function(){Runtime.stackRestore()}),"arrayToC":(function(arr){var ret=Runtime.stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}),"stringToC":(function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=Runtime.stackAlloc((str.length<<2)+1);writeStringToMemory(str,ret)}return ret})};var toC={"string":JSfuncs["stringToC"],"array":JSfuncs["arrayToC"]};ccall=function ccallFunc(ident,returnType,argTypes,args,opts){var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=Runtime.stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func.apply(null,cArgs);if(returnType==="string")ret=Pointer_stringify(ret);if(stack!==0){if(opts&&opts.async){EmterpreterAsync.asyncFinalizers.push((function(){Runtime.stackRestore(stack)}));return}Runtime.stackRestore(stack)}return ret};var sourceRegex=/^function\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/;function parseJSFunc(jsfunc){var parsed=jsfunc.toString().match(sourceRegex).slice(1);return{arguments:parsed[0],body:parsed[1],returnValue:parsed[2]}}var JSsource={};for(var fun in JSfuncs){if(JSfuncs.hasOwnProperty(fun)){JSsource[fun]=parseJSFunc(JSfuncs[fun])}}cwrap=function cwrap(ident,returnType,argTypes){argTypes=argTypes||[];var cfunc=getCFunc(ident);var numericArgs=argTypes.every((function(type){return type==="number"}));var numericRet=returnType!=="string";if(numericRet&&numericArgs){return cfunc}var argNames=argTypes.map((function(x,i){return"$"+i}));var funcstr="(function("+argNames.join(",")+") {";var nargs=argTypes.length;if(!numericArgs){funcstr+="var stack = "+JSsource["stackSave"].body+";";for(var i=0;i<nargs;i++){var arg=argNames[i],type=argTypes[i];if(type==="number")continue;var convertCode=JSsource[type+"ToC"];funcstr+="var "+convertCode.arguments+" = "+arg+";";funcstr+=convertCode.body+";";funcstr+=arg+"="+convertCode.returnValue+";"}}var cfuncname=parseJSFunc((function(){return cfunc})).returnValue;funcstr+="var ret = "+cfuncname+"("+argNames.join(",")+");";if(!numericRet){var strgfy=parseJSFunc((function(){return Pointer_stringify})).returnValue;funcstr+="ret = "+strgfy+"(ret);"}if(!numericArgs){funcstr+=JSsource["stackRestore"].body.replace("()","(stack)")+";"}funcstr+="return ret})";return eval(funcstr)}}))();Module["cwrap"]=cwrap;Module["ccall"]=ccall;function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble- +(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}Module["setValue"]=setValue;function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for setValue: "+type)}return null}Module["getValue"]=getValue;var ALLOC_NORMAL=0;var ALLOC_STACK=1;var ALLOC_STATIC=2;var ALLOC_DYNAMIC=3;var ALLOC_NONE=4;Module["ALLOC_NORMAL"]=ALLOC_NORMAL;Module["ALLOC_STACK"]=ALLOC_STACK;Module["ALLOC_STATIC"]=ALLOC_STATIC;Module["ALLOC_DYNAMIC"]=ALLOC_DYNAMIC;Module["ALLOC_NONE"]=ALLOC_NONE;function allocate(slab,types,allocator,ptr){var zeroinit,size;if(typeof slab==="number"){zeroinit=true;size=slab}else{zeroinit=false;size=slab.length}var singleType=typeof types==="string"?types:null;var ret;if(allocator==ALLOC_NONE){ret=ptr}else{ret=[_malloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][allocator===undefined?ALLOC_STATIC:allocator](Math.max(size,singleType?1:types.length))}if(zeroinit){var ptr=ret,stop;assert((ret&3)==0);stop=ret+(size&~3);for(;ptr<stop;ptr+=4){HEAP32[ptr>>2]=0}stop=ret+size;while(ptr<stop){HEAP8[ptr++>>0]=0}return ret}if(singleType==="i8"){if(slab.subarray||slab.slice){HEAPU8.set(slab,ret)}else{HEAPU8.set(new Uint8Array(slab),ret)}return ret}var i=0,type,typeSize,previousType;while(i<size){var curr=slab[i];if(typeof curr==="function"){curr=Runtime.getFunctionIndex(curr)}type=singleType||types[i];if(type===0){i++;continue}if(type=="i64")type="i32";setValue(ret+i,curr,type);if(previousType!==type){typeSize=Runtime.getNativeTypeSize(type);previousType=type}i+=typeSize}return ret}Module["allocate"]=allocate;function getMemory(size){if(!staticSealed)return Runtime.staticAlloc(size);if(typeof _sbrk!=="undefined"&&!_sbrk.called||!runtimeInitialized)return Runtime.dynamicAlloc(size);return _malloc(size)}Module["getMemory"]=getMemory;function Pointer_stringify(ptr,length){if(length===0||!ptr)return"";var hasUtf=0;var t;var i=0;while(1){t=HEAPU8[ptr+i>>0];hasUtf|=t;if(t==0&&!length)break;i++;if(length&&i==length)break}if(!length)length=i;var ret="";if(hasUtf<128){var MAX_CHUNK=1024;var curr;while(length>0){curr=String.fromCharCode.apply(String,HEAPU8.subarray(ptr,ptr+Math.min(length,MAX_CHUNK)));ret=ret?ret+curr:curr;ptr+=MAX_CHUNK;length-=MAX_CHUNK}return ret}return Module["UTF8ToString"](ptr)}Module["Pointer_stringify"]=Pointer_stringify;function AsciiToString(ptr){var str="";while(1){var ch=HEAP8[ptr++>>0];if(!ch)return str;str+=String.fromCharCode(ch)}}Module["AsciiToString"]=AsciiToString;function stringToAscii(str,outPtr){return writeAsciiToMemory(str,outPtr,false)}Module["stringToAscii"]=stringToAscii;function UTF8ArrayToString(u8Array,idx){var u0,u1,u2,u3,u4,u5;var str="";while(1){u0=u8Array[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}u1=u8Array[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}u2=u8Array[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u3=u8Array[idx++]&63;if((u0&248)==240){u0=(u0&7)<<18|u1<<12|u2<<6|u3}else{u4=u8Array[idx++]&63;if((u0&252)==248){u0=(u0&3)<<24|u1<<18|u2<<12|u3<<6|u4}else{u5=u8Array[idx++]&63;u0=(u0&1)<<30|u1<<24|u2<<18|u3<<12|u4<<6|u5}}}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}Module["UTF8ArrayToString"]=UTF8ArrayToString;function UTF8ToString(ptr){return UTF8ArrayToString(HEAPU8,ptr)}Module["UTF8ToString"]=UTF8ToString;function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=2097151){if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=67108863){if(outIdx+4>=endIdx)break;outU8Array[outIdx++]=248|u>>24;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+5>=endIdx)break;outU8Array[outIdx++]=252|u>>30;outU8Array[outIdx++]=128|u>>24&63;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}Module["stringToUTF8Array"]=stringToUTF8Array;function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}Module["stringToUTF8"]=stringToUTF8;function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){++len}else if(u<=2047){len+=2}else if(u<=65535){len+=3}else if(u<=2097151){len+=4}else if(u<=67108863){len+=5}else{len+=6}}return len}Module["lengthBytesUTF8"]=lengthBytesUTF8;function UTF16ToString(ptr){var i=0;var str="";while(1){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)return str;++i;str+=String.fromCharCode(codeUnit)}}Module["UTF16ToString"]=UTF16ToString;function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite<str.length*2?maxBytesToWrite/2:str.length;for(var i=0;i<numCharsToWrite;++i){var codeUnit=str.charCodeAt(i);HEAP16[outPtr>>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}Module["stringToUTF16"]=stringToUTF16;function lengthBytesUTF16(str){return str.length*2}Module["lengthBytesUTF16"]=lengthBytesUTF16;function UTF32ToString(ptr){var i=0;var str="";while(1){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)return str;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}}Module["UTF32ToString"]=UTF32ToString;function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);if(codeUnit>=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}Module["stringToUTF32"]=stringToUTF32;function lengthBytesUTF32(str){var len=0;for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);if(codeUnit>=55296&&codeUnit<=57343)++i;len+=4}return len}Module["lengthBytesUTF32"]=lengthBytesUTF32;function demangle(func){var hasLibcxxabi=!!Module["___cxa_demangle"];if(hasLibcxxabi){try{var buf=_malloc(func.length);writeStringToMemory(func.substr(1),buf);var status=_malloc(4);var ret=Module["___cxa_demangle"](buf,0,0,status);if(getValue(status,"i32")===0&&ret){return Pointer_stringify(ret)}}catch(e){}finally{if(buf)_free(buf);if(status)_free(status);if(ret)_free(ret)}}var i=3;var basicTypes={"v":"void","b":"bool","c":"char","s":"short","i":"int","l":"long","f":"float","d":"double","w":"wchar_t","a":"signed char","h":"unsigned char","t":"unsigned short","j":"unsigned int","m":"unsigned long","x":"long long","y":"unsigned long long","z":"..."};var subs=[];var first=true;function dump(x){if(x)Module.print(x);Module.print(func);var pre="";for(var a=0;a<i;a++)pre+=" ";Module.print(pre+"^")}function parseNested(){i++;if(func[i]==="K")i++;var parts=[];while(func[i]!=="E"){if(func[i]==="S"){i++;var next=func.indexOf("_",i);var num=func.substring(i,next)||0;parts.push(subs[num]||"?");i=next+1;continue}if(func[i]==="C"){parts.push(parts[parts.length-1]);i+=2;continue}var size=parseInt(func.substr(i));var pre=size.toString().length;if(!size||!pre){i--;break}var curr=func.substr(i+pre,size);parts.push(curr);subs.push(curr);i+=pre+size}i++;return parts}function parse(rawList,limit,allowVoid){limit=limit||Infinity;var ret="",list=[];function flushList(){return"("+list.join(", ")+")"}var name;if(func[i]==="N"){name=parseNested().join("::");limit--;if(limit===0)return rawList?[name]:name}else{if(func[i]==="K"||first&&func[i]==="L")i++;var size=parseInt(func.substr(i));if(size){var pre=size.toString().length;name=func.substr(i+pre,size);i+=pre+size}}first=false;if(func[i]==="I"){i++;var iList=parse(true);var iRet=parse(true,1,true);ret+=iRet[0]+" "+name+"<"+iList.join(", ")+">"}else{ret=name}paramLoop:while(i<func.length&&limit-->0){var c=func[i++];if(c in basicTypes){list.push(basicTypes[c])}else{switch(c){case"P":list.push(parse(true,1,true)[0]+"*");break;case"R":list.push(parse(true,1,true)[0]+"&");break;case"L":{i++;var end=func.indexOf("E",i);var size=end-i;list.push(func.substr(i,size));i+=size+2;break};case"A":{var size=parseInt(func.substr(i));i+=size.toString().length;if(func[i]!=="_")throw"?";i++;list.push(parse(true,1,true)[0]+" ["+size+"]");break};case"E":break paramLoop;default:ret+="?"+c;break paramLoop}}}if(!allowVoid&&list.length===1&&list[0]==="void")list=[];if(rawList){if(ret){list.push(ret+"?")}return list}else{return ret+flushList()}}var parsed=func;try{if(func=="Object._main"||func=="_main"){return"main()"}if(typeof func==="number")func=Pointer_stringify(func);if(func[0]!=="_")return func;if(func[1]!=="_")return func;if(func[2]!=="Z")return func;switch(func[3]){case"n":return"operator new()";case"d":return"operator delete()"}parsed=parse()}catch(e){parsed+="?"}if(parsed.indexOf("?")>=0&&!hasLibcxxabi){Runtime.warnOnce("warning: a problem occurred in builtin C++ name demangling; build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling")}return parsed}function demangleAll(text){return text.replace(/__Z[\w\d_]+/g,(function(x){var y=demangle(x);return x===y?x:x+" ["+y+"]"}))}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){return demangleAll(jsStackTrace())}Module["stackTrace"]=stackTrace;var PAGE_SIZE=4096;function alignMemoryPage(x){if(x%4096>0){x+=4096-x%4096}return x}var HEAP;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var STATIC_BASE=0,STATICTOP=0,staticSealed=false;var STACK_BASE=0,STACKTOP=0,STACK_MAX=0;var DYNAMIC_BASE=0,DYNAMICTOP=0;function enlargeMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.")}var TOTAL_STACK=Module["TOTAL_STACK"]||5242880;var TOTAL_MEMORY=Module["TOTAL_MEMORY"]||33554432;var totalMemory=64*1024;while(totalMemory<TOTAL_MEMORY||totalMemory<2*TOTAL_STACK){if(totalMemory<16*1024*1024){totalMemory*=2}else{totalMemory+=16*1024*1024}}if(totalMemory!==TOTAL_MEMORY){Module.printErr("increasing TOTAL_MEMORY to "+totalMemory+" to be compliant with the asm.js spec (and given that TOTAL_STACK="+TOTAL_STACK+")");TOTAL_MEMORY=totalMemory}assert(typeof Int32Array!=="undefined"&&typeof Float64Array!=="undefined"&&!!(new Int32Array(1))["subarray"]&&!!(new Int32Array(1))["set"],"JS engine does not provide full typed array support");var buffer;buffer=new ArrayBuffer(TOTAL_MEMORY);HEAP8=new Int8Array(buffer);HEAP16=new Int16Array(buffer);HEAP32=new Int32Array(buffer);HEAPU8=new Uint8Array(buffer);HEAPU16=new Uint16Array(buffer);HEAPU32=new Uint32Array(buffer);HEAPF32=new Float32Array(buffer);HEAPF64=new Float64Array(buffer);HEAP32[0]=255;assert(HEAPU8[0]===255&&HEAPU8[3]===0,"Typed arrays 2 must be run on a little-endian system");Module["HEAP"]=HEAP;Module["buffer"]=buffer;Module["HEAP8"]=HEAP8;Module["HEAP16"]=HEAP16;Module["HEAP32"]=HEAP32;Module["HEAPU8"]=HEAPU8;Module["HEAPU16"]=HEAPU16;Module["HEAPU32"]=HEAPU32;Module["HEAPF32"]=HEAPF32;Module["HEAPF64"]=HEAPF64;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Runtime.dynCall("v",func)}else{Runtime.dynCall("vi",func,[callback.arg])}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){if(runtimeInitialized)return;runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__);runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}Module["addOnPreRun"]=Module.addOnPreRun=addOnPreRun;function addOnInit(cb){__ATINIT__.unshift(cb)}Module["addOnInit"]=Module.addOnInit=addOnInit;function addOnPreMain(cb){__ATMAIN__.unshift(cb)}Module["addOnPreMain"]=Module.addOnPreMain=addOnPreMain;function addOnExit(cb){__ATEXIT__.unshift(cb)}Module["addOnExit"]=Module.addOnExit=addOnExit;function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}Module["addOnPostRun"]=Module.addOnPostRun=addOnPostRun;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}Module["intArrayFromString"]=intArrayFromString;function intArrayToString(array){var ret=[];for(var i=0;i<array.length;i++){var chr=array[i];if(chr>255){chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}Module["intArrayToString"]=intArrayToString;function writeStringToMemory(string,buffer,dontAddNull){var array=intArrayFromString(string,dontAddNull);var i=0;while(i<array.length){var chr=array[i];HEAP8[buffer+i>>0]=chr;i=i+1}}Module["writeStringToMemory"]=writeStringToMemory;function writeArrayToMemory(array,buffer){for(var i=0;i<array.length;i++){HEAP8[buffer++>>0]=array[i]}}Module["writeArrayToMemory"]=writeArrayToMemory;function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i<str.length;++i){HEAP8[buffer++>>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}Module["writeAsciiToMemory"]=writeAsciiToMemory;function unSign(value,bits,ignore){if(value>=0){return value}return bits<=32?2*Math.abs(1<<bits-1)+value:Math.pow(2,bits)+value}function reSign(value,bits,ignore){if(value<=0){return value}var half=bits<=32?Math.abs(1<<bits-1):Math.pow(2,bits-1);if(value>=half&&(bits<=32||value>half)){value=-2*half+value}return value}if(!Math["imul"]||Math["imul"](4294967295,5)!==-5)Math["imul"]=function imul(a,b){var ah=a>>>16;var al=a&65535;var bh=b>>>16;var bl=b&65535;return al*bl+(ah*bl+al*bh<<16)|0};Math.imul=Math["imul"];if(!Math["clz32"])Math["clz32"]=(function(x){x=x>>>0;for(var i=0;i<32;i++){if(x&1<<31-i)return i}return 32});Math.clz32=Math["clz32"];var Math_abs=Math.abs;var Math_cos=Math.cos;var Math_sin=Math.sin;var Math_tan=Math.tan;var Math_acos=Math.acos;var Math_asin=Math.asin;var Math_atan=Math.atan;var Math_atan2=Math.atan2;var Math_exp=Math.exp;var Math_log=Math.log;var Math_sqrt=Math.sqrt;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_pow=Math.pow;var Math_imul=Math.imul;var Math_fround=Math.fround;var Math_min=Math.min;var Math_clz32=Math.clz32;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}Module["addRunDependency"]=addRunDependency;function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["removeRunDependency"]=removeRunDependency;Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var ASM_CONSTS=[];STATIC_BASE=8;STATICTOP=STATIC_BASE+2448;__ATINIT__.push();allocate([0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,3,1,2,0,0,0,0,0,1,2,3,4,8,0,0,0,0,0,0,0,1,2,3,4,5,8,9,0,0,0,0,0,1,2,3,4,6,8,10,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,6,8,8,12,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,116,104,101,111,114,97,0,0,4,0,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,254,252,254,252,253,252,253,252,252,251,251,251,224,251,17,0,2,0,220,253,216,253,180,253,36,253,0,0,0,0,5,0,255,253,255,253,255,253,255,253,255,253,255,253,255,253,255,253,254,253,254,253,254,253,254,253,254,253,254,253,254,253,254,253,253,252,253,252,253,252,253,252,252,252,252,252,252,252,252,252,251,251,251,251,250,251,250,251,33,0,36,0,39,0,44,0,1,0,249,254,248,254,1,0,247,254,246,254,2,0,245,253,244,253,243,253,242,253,4,0,241,251,240,251,239,251,238,251,237,251,236,251,235,251,234,251,233,251,232,251,231,251,230,251,229,251,228,251,227,251,226,251,0,0,0,0,0,0,3,4,2,0,1,5,6,7,3,4,0,2,1,5,6,7,3,2,4,0,1,5,6,7,3,2,0,4,1,5,6,7,0,3,4,2,1,5,6,7,0,5,3,4,2,1,6,7,0,1,2,3,4,5,6,7,3,0,0,253,255,252,254,252,253,252,252,252,251,252,250,252,249,252,0,0,0,0,0,0,4,0,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,255,253,255,253,255,253,255,253,254,252,254,252,253,251,17,0,3,0,252,254,252,254,252,254,252,254,251,253,251,253,250,252,249,252,0,0,0,0,6,0,224,249,224,249,223,249,225,249,222,249,226,249,221,249,227,249,220,249,228,249,219,249,229,249,218,249,230,249,217,249,231,249,216,249,232,249,215,249,233,249,214,249,234,249,213,249,235,249,212,249,236,249,211,249,237,249,210,249,238,249,209,249,239,249,208,249,240,249,207,249,241,249,206,249,242,249,205,249,243,249,204,249,244,249,203,249,245,249,202,249,246,249,201,249,247,249,200,249,248,249,199,249,249,249,198,249,250,249,197,249,251,249,196,249,252,249,195,249,253,249,194,249,254,249,193,249,255,249,0,0,0,0,0,0,5,0,224,252,224,252,224,252,224,252,223,252,223,252,223,252,223,252,225,252,225,252,225,252,225,252,222,251,222,251,226,251,226,251,221,251,221,251,227,251,227,251,33,0,36,0,39,0,42,0,45,0,50,0,55,0,60,0,65,0,74,0,83,0,92,0,1,0,220,254,228,254,1,0,219,254,229,254,1,0,218,254,230,254,1,0,217,254,231,254,2,0,216,253,232,253,215,253,233,253,2,0,214,253,234,253,213,253,235,253,2,0,212,253,236,253,211,253,237,253,2,0,210,253,238,253,209,253,239,253,3,0,208,252,240,252,207,252,241,252,206,252,242,252,205,252,243,252,3,0,204,252,244,252,203,252,245,252,202,252,246,252,201,252,247,252,3,0,200,252,248,252,199,252,249,252,198,252,250,252,197,252,251,252,3,0,196,252,252,252,195,252,253,252,194,252,254,252,193,252,255,252,0,0,0,0,0,0,12,4,3,3,4,4,5,5,8,8,8,8,3,3,6,0,0,0,0,0,0,16,0,0,0,0,160,1,0,0,144,1,0,0,160,2,0,0,144,2,0,0,160,4,0,0,144,4,0,0,160,8,0,0,160,40,0,0,144,8,0,0,144,40,10,0,32,0,10,0,224,255,0,0,240,255,0,1,0,0,0,2,0,0,0,3,0,0,1,0,32,0,1,0,224,255,2,0,32,0,2,0,224,255,3,0,32,0,3,0,224,255,4,0,32,0,4,0,224,255,5,0,32,0,5,0,224,255,1,0,64,0,1,0,96,0,1,0,192,255,1,0,160,255,6,0,32,0,7,0,32,0,8,0,32,0,9,0,32,0,6,0,224,255,7,0,224,255,8,0,224,255,9,0,224,255,2,0,64,0,3,0,64,0,2,0,96,0,3,0,96,0,2,0,192,255,3,0,192,255,2,0,160,255,3,0,160,255,0,0,240,255,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,6,0,0,0,7,0,0,0,0,0,32,0,0,0,224,255,0,0,64,0,0,0,192,255,0,0,96,0,0,0,160,255,0,0,128,0,0,0,128,255,0,0,160,0,0,0,96,255,0,0,192,0,0,0,64,255,0,0,224,0,0,0,0,1,0,0,32,255,0,0,0,255,0,0,32,1,0,0,64,1,0,0,96,1,0,0,128,1,0,0,224,254,0,0,192,254,0,0,160,254,0,0,128,254,0,8,0,0,0,9,0,0,0,10,0,0,0,11,0,0,0,12,0,0,0,13,0,0,0,14,0,0,0,15,0,0,0,4,0,0,0,5,0,0,0,6,0,0,0,7,0,0,1,6,15,28,64,0,0,0,0,0,0,2,3,0,0,3,0,0,0,0,0,1,1,1,1,2,3,1,1,1,2,1,1,1,1,1,3,1,2,3,15,16,17,88,80,1,0,48,14,56,57,58,59,60,62,64,66,68,72,2,4,6,8,18,20,22,24,26,32,12,28,40,16,0,0,0,32,0,0,0,8,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,3,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,241,241,242,242,243,243,244,244,245,245,246,246,247,247,248,248,249,249,250,250,251,251,252,252,253,253,254,254,255,255,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,0,249,249,249,249,250,250,250,250,251,251,251,251,252,252,252,252,253,253,253,253,254,254,254,254,255,255,255,255,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,24,32,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,69,114,114,111,114,32,112,97,114,115,105,110,103,32,116,104,101,111,114,97,32,104,101,97,100,101,114,115,58,32,37,100,46,10,0,0,0,0,0,0,84,104,101,111,114,97,32,100,101,99,111,100,101,114,32,102,97,105,108,101,100,32,109,121,115,116,101,114,105,111,117,115,108,121,63,32,37,100,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE);var tempDoublePtr=Runtime.alignMemory(allocate(12,"i8",ALLOC_STATIC),8);assert(tempDoublePtr%8==0);function copyTempFloat(ptr){HEAP8[tempDoublePtr]=HEAP8[ptr];HEAP8[tempDoublePtr+1]=HEAP8[ptr+1];HEAP8[tempDoublePtr+2]=HEAP8[ptr+2];HEAP8[tempDoublePtr+3]=HEAP8[ptr+3]}function copyTempDouble(ptr){HEAP8[tempDoublePtr]=HEAP8[ptr];HEAP8[tempDoublePtr+1]=HEAP8[ptr+1];HEAP8[tempDoublePtr+2]=HEAP8[ptr+2];HEAP8[tempDoublePtr+3]=HEAP8[ptr+3];HEAP8[tempDoublePtr+4]=HEAP8[ptr+4];HEAP8[tempDoublePtr+5]=HEAP8[ptr+5];HEAP8[tempDoublePtr+6]=HEAP8[ptr+6];HEAP8[tempDoublePtr+7]=HEAP8[ptr+7]}Module["_i64Subtract"]=_i64Subtract;Module["_i64Add"]=_i64Add;Module["_memset"]=_memset;Module["_bitshift64Shl"]=_bitshift64Shl;function _abort(){Module["abort"]()}function _ogvjs_callback_frame(bufferY,strideY,bufferCb,strideCb,bufferCr,strideCr,width,height,hdec,vdec){var HEAPU8=Module.HEAPU8,widthColor=width>>hdec,heightColor=height>>vdec,countBytesY=strideY*height,countBytesCb=strideCb*heightColor,countBytesCr=strideCr*heightColor,bytesY=HEAPU8.subarray(bufferY,bufferY+countBytesY),bytesCb=HEAPU8.subarray(bufferCb,bufferCb+countBytesCb),bytesCr=HEAPU8.subarray(bufferCr,bufferCr+countBytesCr);Module.frameBuffer={bytesY:bytesY,bytesCb:bytesCb,bytesCr:bytesCr,strideY:strideY,strideCb:strideCb,strideCr:strideCr,width:width,height:height,hdec:hdec,vdec:vdec}}var FS=undefined;var ___errno_state=0;function ___setErrNo(value){HEAP32[___errno_state>>2]=value;return value}var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};var SOCKFS=undefined;function _send(fd,buf,len,flags){var sock=SOCKFS.getSocket(fd);if(!sock){___setErrNo(ERRNO_CODES.EBADF);return-1}return _write(fd,buf,len)}function _pwrite(fildes,buf,nbyte,offset){var stream=FS.getStream(fildes);if(!stream){___setErrNo(ERRNO_CODES.EBADF);return-1}try{var slab=HEAP8;return FS.write(stream,slab,buf,nbyte,offset)}catch(e){FS.handleFSError(e);return-1}}function _write(fildes,buf,nbyte){var stream=FS.getStream(fildes);if(!stream){___setErrNo(ERRNO_CODES.EBADF);return-1}try{var slab=HEAP8;return FS.write(stream,slab,buf,nbyte)}catch(e){FS.handleFSError(e);return-1}}function _fileno(stream){stream=FS.getStreamFromPtr(stream);if(!stream)return-1;return stream.fd}function _fwrite(ptr,size,nitems,stream){var bytesToWrite=nitems*size;if(bytesToWrite==0)return 0;var fd=_fileno(stream);var bytesWritten=_write(fd,ptr,bytesToWrite);if(bytesWritten==-1){var streamObj=FS.getStreamFromPtr(stream);if(streamObj)streamObj.error=true;return 0}else{return bytesWritten/size|0}}Module["_strlen"]=_strlen;function __reallyNegative(x){return x<0||x===0&&1/x===-Infinity}function __formatString(format,varargs){assert((varargs&3)===0);var textIndex=format;var argIndex=0;function getNextArg(type){var ret;argIndex=Runtime.prepVararg(argIndex,type);if(type==="double"){ret=(HEAP32[tempDoublePtr>>2]=HEAP32[varargs+argIndex>>2],HEAP32[tempDoublePtr+4>>2]=HEAP32[varargs+(argIndex+4)>>2],+HEAPF64[tempDoublePtr>>3]);argIndex+=8}else if(type=="i64"){ret=[HEAP32[varargs+argIndex>>2],HEAP32[varargs+(argIndex+4)>>2]];argIndex+=8}else{assert((argIndex&3)===0);type="i32";ret=HEAP32[varargs+argIndex>>2];argIndex+=4}return ret}var ret=[];var curr,next,currArg;while(1){var startTextIndex=textIndex;curr=HEAP8[textIndex>>0];if(curr===0)break;next=HEAP8[textIndex+1>>0];if(curr==37){var flagAlwaysSigned=false;var flagLeftAlign=false;var flagAlternative=false;var flagZeroPad=false;var flagPadSign=false;flagsLoop:while(1){switch(next){case 43:flagAlwaysSigned=true;break;case 45:flagLeftAlign=true;break;case 35:flagAlternative=true;break;case 48:if(flagZeroPad){break flagsLoop}else{flagZeroPad=true;break};case 32:flagPadSign=true;break;default:break flagsLoop}textIndex++;next=HEAP8[textIndex+1>>0]}var width=0;if(next==42){width=getNextArg("i32");textIndex++;next=HEAP8[textIndex+1>>0]}else{while(next>=48&&next<=57){width=width*10+(next-48);textIndex++;next=HEAP8[textIndex+1>>0]}}var precisionSet=false,precision=-1;if(next==46){precision=0;precisionSet=true;textIndex++;next=HEAP8[textIndex+1>>0];if(next==42){precision=getNextArg("i32");textIndex++}else{while(1){var precisionChr=HEAP8[textIndex+1>>0];if(precisionChr<48||precisionChr>57)break;precision=precision*10+(precisionChr-48);textIndex++}}next=HEAP8[textIndex+1>>0]}if(precision<0){precision=6;precisionSet=false}var argSize;switch(String.fromCharCode(next)){case"h":var nextNext=HEAP8[textIndex+2>>0];if(nextNext==104){textIndex++;argSize=1}else{argSize=2}break;case"l":var nextNext=HEAP8[textIndex+2>>0];if(nextNext==108){textIndex++;argSize=8}else{argSize=4}break;case"L":case"q":case"j":argSize=8;break;case"z":case"t":case"I":argSize=4;break;default:argSize=null}if(argSize)textIndex++;next=HEAP8[textIndex+1>>0];switch(String.fromCharCode(next)){case"d":case"i":case"u":case"o":case"x":case"X":case"p":{var signed=next==100||next==105;argSize=argSize||4;var currArg=getNextArg("i"+argSize*8);var origArg=currArg;var argText;if(argSize==8){currArg=Runtime.makeBigInt(currArg[0],currArg[1],next==117)}if(argSize<=4){var limit=Math.pow(256,argSize)-1;currArg=(signed?reSign:unSign)(currArg&limit,argSize*8)}var currAbsArg=Math.abs(currArg);var prefix="";if(next==100||next==105){if(argSize==8&&i64Math)argText=i64Math.stringify(origArg[0],origArg[1],null);else argText=reSign(currArg,8*argSize,1).toString(10)}else if(next==117){if(argSize==8&&i64Math)argText=i64Math.stringify(origArg[0],origArg[1],true);else argText=unSign(currArg,8*argSize,1).toString(10);currArg=Math.abs(currArg)}else if(next==111){argText=(flagAlternative?"0":"")+currAbsArg.toString(8)}else if(next==120||next==88){prefix=flagAlternative&&currArg!=0?"0x":"";if(argSize==8&&i64Math){if(origArg[1]){argText=(origArg[1]>>>0).toString(16);var lower=(origArg[0]>>>0).toString(16);while(lower.length<8)lower="0"+lower;argText+=lower}else{argText=(origArg[0]>>>0).toString(16)}}else if(currArg<0){currArg=-currArg;argText=(currAbsArg-1).toString(16);var buffer=[];for(var i=0;i<argText.length;i++){buffer.push((15-parseInt(argText[i],16)).toString(16))}argText=buffer.join("");while(argText.length<argSize*2)argText="f"+argText}else{argText=currAbsArg.toString(16)}if(next==88){prefix=prefix.toUpperCase();argText=argText.toUpperCase()}}else if(next==112){if(currAbsArg===0){argText="(nil)"}else{prefix="0x";argText=currAbsArg.toString(16)}}if(precisionSet){while(argText.length<precision){argText="0"+argText}}if(currArg>=0){if(flagAlwaysSigned){prefix="+"+prefix}else if(flagPadSign){prefix=" "+prefix}}if(argText.charAt(0)=="-"){prefix="-"+prefix;argText=argText.substr(1)}while(prefix.length+argText.length<width){if(flagLeftAlign){argText+=" "}else{if(flagZeroPad){argText="0"+argText}else{prefix=" "+prefix}}}argText=prefix+argText;argText.split("").forEach((function(chr){ret.push(chr.charCodeAt(0))}));break};case"f":case"F":case"e":case"E":case"g":case"G":{var currArg=getNextArg("double");var argText;if(isNaN(currArg)){argText="nan";flagZeroPad=false}else if(!isFinite(currArg)){argText=(currArg<0?"-":"")+"inf";flagZeroPad=false}else{var isGeneral=false;var effectivePrecision=Math.min(precision,20);if(next==103||next==71){isGeneral=true;precision=precision||1;var exponent=parseInt(currArg.toExponential(effectivePrecision).split("e")[1],10);if(precision>exponent&&exponent>=-4){next=(next==103?"f":"F").charCodeAt(0);precision-=exponent+1}else{next=(next==103?"e":"E").charCodeAt(0);precision--}effectivePrecision=Math.min(precision,20)}if(next==101||next==69){argText=currArg.toExponential(effectivePrecision);if(/[eE][-+]\d$/.test(argText)){argText=argText.slice(0,-1)+"0"+argText.slice(-1)}}else if(next==102||next==70){argText=currArg.toFixed(effectivePrecision);if(currArg===0&&__reallyNegative(currArg)){argText="-"+argText}}var parts=argText.split("e");if(isGeneral&&!flagAlternative){while(parts[0].length>1&&parts[0].indexOf(".")!=-1&&(parts[0].slice(-1)=="0"||parts[0].slice(-1)==".")){parts[0]=parts[0].slice(0,-1)}}else{if(flagAlternative&&argText.indexOf(".")==-1)parts[0]+=".";while(precision>effectivePrecision++)parts[0]+="0"}argText=parts[0]+(parts.length>1?"e"+parts[1]:"");if(next==69)argText=argText.toUpperCase();if(currArg>=0){if(flagAlwaysSigned){argText="+"+argText}else if(flagPadSign){argText=" "+argText}}}while(argText.length<width){if(flagLeftAlign){argText+=" "}else{if(flagZeroPad&&(argText[0]=="-"||argText[0]=="+")){argText=argText[0]+"0"+argText.slice(1)}else{argText=(flagZeroPad?"0":" ")+argText}}}if(next<97)argText=argText.toUpperCase();argText.split("").forEach((function(chr){ret.push(chr.charCodeAt(0))}));break};case"s":{var arg=getNextArg("i8*");var argLength=arg?_strlen(arg):"(null)".length;if(precisionSet)argLength=Math.min(argLength,precision);if(!flagLeftAlign){while(argLength<width--){ret.push(32)}}if(arg){for(var i=0;i<argLength;i++){ret.push(HEAPU8[arg++>>0])}}else{ret=ret.concat(intArrayFromString("(null)".substr(0,argLength),true))}if(flagLeftAlign){while(argLength<width--){ret.push(32)}}break};case"c":{if(flagLeftAlign)ret.push(getNextArg("i8"));while(--width>0){ret.push(32)}if(!flagLeftAlign)ret.push(getNextArg("i8"));break};case"n":{var ptr=getNextArg("i32*");HEAP32[ptr>>2]=ret.length;break};case"%":{ret.push(curr);break};default:{for(var i=startTextIndex;i<textIndex+2;i++){ret.push(HEAP8[i>>0])}}}textIndex+=2}else{ret.push(curr);textIndex+=1}}return ret}function _fprintf(stream,format,varargs){var result=__formatString(format,varargs);var stack=Runtime.stackSave();var ret=_fwrite(allocate(result,"i8",ALLOC_STACK),1,result.length,stream);Runtime.stackRestore(stack);return ret}function _printf(format,varargs){var result=__formatString(format,varargs);var string=intArrayToString(result);if(string[string.length-1]==="\n")string=string.substr(0,string.length-1);Module.print(string);return result.length}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest);return dest}Module["_memcpy"]=_memcpy;function _sysconf(name){switch(name){case 30:return PAGE_SIZE;case 85:return totalMemory/PAGE_SIZE;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:return 200809;case 79:return 0;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return-1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}___setErrNo(ERRNO_CODES.EINVAL);return-1}function _sbrk(bytes){var self=_sbrk;if(!self.called){DYNAMICTOP=alignMemoryPage(DYNAMICTOP);self.called=true;assert(Runtime.dynamicAlloc);self.alloc=Runtime.dynamicAlloc;Runtime.dynamicAlloc=(function(){abort("cannot dynamically allocate, sbrk now has control")})}var ret=DYNAMICTOP;if(bytes!=0){var success=self.alloc(bytes);if(!success)return-1>>>0}return ret}function ___errno_location(){return ___errno_state}function _ogvjs_callback_init_video(frameWidth,frameHeight,hdec,vdec,fps,picWidth,picHeight,picX,picY,displayWidth,displayHeight){Module.videoFormat={frameWidth:frameWidth,frameHeight:frameHeight,hdec:hdec,vdec:vdec,fps:fps,picWidth:picWidth,picHeight:picHeight,picX:picX,picY:picY,displayWidth:displayWidth,displayHeight:displayHeight};Module.loadedMetadata=true}function _time(ptr){var ret=Date.now()/1e3|0;if(ptr){HEAP32[ptr>>2]=ret}return ret}___errno_state=Runtime.staticAlloc(4);HEAP32[___errno_state>>2]=0;STACK_BASE=STACKTOP=Runtime.alignMemory(STATICTOP);staticSealed=true;STACK_MAX=STACK_BASE+TOTAL_STACK;DYNAMIC_BASE=DYNAMICTOP=Runtime.alignMemory(STACK_MAX);assert(DYNAMIC_BASE<TOTAL_MEMORY,"TOTAL_MEMORY not big enough for stack");var cttz_i8=allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0],"i8",ALLOC_DYNAMIC);function invoke_vii(index,a1,a2){try{Module["dynCall_vii"](index,a1,a2)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}function invoke_viiii(index,a1,a2,a3,a4){try{Module["dynCall_viiii"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}Module.asmGlobalArg={"Math":Math,"Int8Array":Int8Array,"Int16Array":Int16Array,"Int32Array":Int32Array,"Uint8Array":Uint8Array,"Uint16Array":Uint16Array,"Uint32Array":Uint32Array,"Float32Array":Float32Array,"Float64Array":Float64Array,"NaN":NaN,"Infinity":Infinity};Module.asmLibraryArg={"abort":abort,"assert":assert,"invoke_vii":invoke_vii,"invoke_viiii":invoke_viiii,"_ogvjs_callback_init_video":_ogvjs_callback_init_video,"__formatString":__formatString,"_ogvjs_callback_frame":_ogvjs_callback_frame,"_send":_send,"_pwrite":_pwrite,"_abort":_abort,"___setErrNo":___setErrNo,"_fwrite":_fwrite,"_sbrk":_sbrk,"_printf":_printf,"_fprintf":_fprintf,"__reallyNegative":__reallyNegative,"_emscripten_memcpy_big":_emscripten_memcpy_big,"_fileno":_fileno,"_write":_write,"_time":_time,"_sysconf":_sysconf,"___errno_location":___errno_location,"STACKTOP":STACKTOP,"STACK_MAX":STACK_MAX,"tempDoublePtr":tempDoublePtr,"ABORT":ABORT,"cttz_i8":cttz_i8};// EMSCRIPTEN_START_ASM
+var asm=(function(global,env,buffer) {
+"use asm";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.tempDoublePtr|0;var l=env.ABORT|0;var m=env.cttz_i8|0;var n=0;var o=0;var p=0;var q=0;var r=global.NaN,s=global.Infinity;var t=0,u=0,v=0,w=0,x=0.0,y=0,z=0,A=0,B=0.0;var C=0;var D=0;var E=0;var F=0;var G=0;var H=0;var I=0;var J=0;var K=0;var L=0;var M=global.Math.floor;var N=global.Math.abs;var O=global.Math.sqrt;var P=global.Math.pow;var Q=global.Math.cos;var R=global.Math.sin;var S=global.Math.tan;var T=global.Math.acos;var U=global.Math.asin;var V=global.Math.atan;var W=global.Math.atan2;var X=global.Math.exp;var Y=global.Math.log;var Z=global.Math.ceil;var _=global.Math.imul;var $=global.Math.min;var aa=global.Math.clz32;var ba=env.abort;var ca=env.assert;var da=env.invoke_vii;var ea=env.invoke_viiii;var fa=env._ogvjs_callback_init_video;var ga=env.__formatString;var ha=env._ogvjs_callback_frame;var ia=env._send;var ja=env._pwrite;var ka=env._abort;var la=env.___setErrNo;var ma=env._fwrite;var na=env._sbrk;var oa=env._printf;var pa=env._fprintf;var qa=env.__reallyNegative;var ra=env._emscripten_memcpy_big;var sa=env._fileno;var ta=env._write;var ua=env._time;var va=env._sysconf;var wa=env.___errno_location;var xa=0.0;
+// EMSCRIPTEN_START_FUNCS
+function Aa(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+15&-16;return b|0}function Ba(){return i|0}function Ca(a){a=a|0;i=a}function Da(a,b){a=a|0;b=b|0;i=a;j=b}function Ea(a,b){a=a|0;b=b|0;if(!n){n=a;o=b}}function Fa(b){b=b|0;a[k>>0]=a[b>>0];a[k+1>>0]=a[b+1>>0];a[k+2>>0]=a[b+2>>0];a[k+3>>0]=a[b+3>>0]}function Ga(b){b=b|0;a[k>>0]=a[b>>0];a[k+1>>0]=a[b+1>>0];a[k+2>>0]=a[b+2>>0];a[k+3>>0]=a[b+3>>0];a[k+4>>0]=a[b+4>>0];a[k+5>>0]=a[b+5>>0];a[k+6>>0]=a[b+6>>0];a[k+7>>0]=a[b+7>>0]}function Ha(a){a=a|0;C=a}function Ia(){return C|0}function Ja(a,b,d){a=a|0;b=b|0;d=d|0;c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0;c[a+16>>2]=0;c[a+4>>2]=b;c[a>>2]=b+d;return}function Ka(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0;e=a+8|0;f=a+12|0;g=c[f>>2]|0;if(!b){h=0;return h|0}i=c[e>>2]|0;if((g|0)<(b|0)){j=c[a>>2]|0;k=a+4|0;l=c[k>>2]|0;m=32-g|0;n=l>>>0<j>>>0;if(m>>>0>7&n){o=l-j|0;p=(24-g|0)>>>3;q=~p;r=o>>>0>q>>>0?o:q;q=l+(0-r)|0;s=~p;p=0-(o>>>0>s>>>0?o:s)|0;s=l;o=m;t=i;while(1){o=o+-8|0;u=s;s=s+1|0;v=(d[u>>0]|0)<<o|t;if((s|0)==(q|0)){w=v;break}else t=v}x=(l+p|0)>>>0<j>>>0;y=q;z=m+(r<<3)|0;A=w}else{x=n;y=l;z=m;A=i}c[k>>2]=y;k=32-z|0;do if((k|0)<(b|0))if(x){B=k;C=(d[y>>0]|0)>>>(k&7)|A;break}else{c[a+16>>2]=1;B=1073741824;C=A;break}else{B=k;C=A}while(0);c[f>>2]=B;D=B;E=C}else{D=g;E=i}c[e>>2]=E<<1<<b+-1;c[f>>2]=D-b;h=E>>>(32-b|0);return h|0}function La(a){a=a|0;var b=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0;b=a+8|0;e=c[b>>2]|0;f=a+12|0;g=c[f>>2]|0;if((g|0)>=1){h=g;i=e;j=i>>>31;k=h+-1|0;l=i<<1;c[b>>2]=l;c[f>>2]=k;return j|0}m=c[a>>2]|0;n=a+4|0;o=c[n>>2]|0;p=32-g|0;q=o>>>0<m>>>0;if(p>>>0>7&q){r=o-m|0;s=(24-g|0)>>>3;g=~s;t=r>>>0>g>>>0?r:g;g=o+(0-t)|0;u=~s;s=0-(r>>>0>u>>>0?r:u)|0;u=o;r=p;v=e;while(1){r=r+-8|0;w=u;u=u+1|0;x=(d[w>>0]|0)<<r|v;if((u|0)==(g|0)){y=x;break}else v=x}z=(o+s|0)>>>0<m>>>0;A=g;B=p+(t<<3)|0;C=y}else{z=q;A=o;B=p;C=e}c[n>>2]=A;n=32-B|0;do if((n|0)<1)if(z){D=n;E=(d[A>>0]|0)>>>(n&7)|C;break}else{c[a+16>>2]=1;D=1073741824;E=C;break}else{D=n;E=C}while(0);c[f>>2]=D;h=D;i=E;j=i>>>31;k=h+-1|0;l=i<<1;c[b>>2]=l;c[f>>2]=k;return j|0}function Ma(a){a=a|0;var b=0;if(c[a+16>>2]|0){b=-1;return b|0}b=(c[a>>2]|0)-(c[a+4>>2]|0)+(c[a+12>>2]>>3)|0;return b|0}function Na(b,e,f,g){b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;h=i;i=i+32|0;j=h+20|0;k=h;if(!g){l=-20;i=h;return l|0}if(!b){l=-1;i=h;return l|0}Ja(k,c[g>>2]|0,c[g+4>>2]|0);m=Ka(k,8)|0;if((((m&128|0)==0?(c[b+4>>2]|0)!=0:0)?(c[e+12>>2]|0)!=0:0)?(c[f>>2]|0)!=0:0)n=0;else o=7;a:do if((o|0)==7){a[j>>0]=Ka(k,8)|0;a[j+1>>0]=Ka(k,8)|0;a[j+2>>0]=Ka(k,8)|0;a[j+3>>0]=Ka(k,8)|0;a[j+4>>0]=Ka(k,8)|0;a[j+5>>0]=Ka(k,8)|0;if(!(Nb(j,216,6)|0))if((m|0)==128){if(!(c[g+8>>2]|0)){n=-20;break}p=b+4|0;if(c[p>>2]|0){n=-20;break}a[b>>0]=Ka(k,8)|0;q=b+1|0;a[q>>0]=Ka(k,8)|0;a[b+2>>0]=Ka(k,8)|0;r=a[b>>0]|0;do if((r&255)<=3){if(r<<24>>24==3?(d[q>>0]|0)>2:0){s=-22;break}c[p>>2]=(Ka(k,16)|0)<<4;t=b+8|0;c[t>>2]=(Ka(k,16)|0)<<4;u=b+12|0;c[u>>2]=Ka(k,24)|0;v=b+16|0;c[v>>2]=Ka(k,24)|0;w=b+20|0;c[w>>2]=Ka(k,8)|0;x=b+24|0;c[x>>2]=Ka(k,8)|0;y=b+28|0;c[y>>2]=Ka(k,32)|0;z=Ka(k,32)|0;c[b+32>>2]=z;A=c[p>>2]|0;if(((((((A|0)!=0?(B=c[t>>2]|0,(B|0)!=0):0)?((c[w>>2]|0)+(c[u>>2]|0)|0)>>>0<=A>>>0:0)?(A=c[v>>2]|0,v=c[x>>2]|0,(v+A|0)>>>0<=B>>>0):0)?!((z|0)==0|(c[y>>2]|0)==0):0)?(c[x>>2]=B-A-v,c[b+36>>2]=Ka(k,24)|0,c[b+40>>2]=Ka(k,24)|0,c[b+44>>2]=Ka(k,8)|0,c[b+52>>2]=Ka(k,24)|0,c[b+56>>2]=Ka(k,6)|0,c[b+60>>2]=Ka(k,5)|0,v=Ka(k,2)|0,c[b+48>>2]=v,(v|0)!=1):0)?(Ka(k,3)|0)==0:0){v=(Ma(k)|0)>>31&-20;if((v|0)<0)s=v;else{n=3;break a}}else s=-20}else s=-22;while(0);eb(b);n=s;break}else if((m|0)==129){if(!e){n=-1;break}if(!(c[b+4>>2]|0)){n=-20;break}p=e+12|0;if(c[p>>2]|0){n=-20;break}q=Ka(k,8)|0;r=Ka(k,8)|0;v=Ka(k,8)|0;A=r<<8|q|v<<16|(Ka(k,8)|0)<<24;b:do if((A|0)>=0?(A|0)<=(Ma(k)|0):0){v=Ob(A+1|0)|0;c[p>>2]=v;if(!v)C=-1;else{if(!A)D=v;else{q=A;r=v;while(1){q=q+-1|0;a[r>>0]=Ka(k,8)|0;if(!q)break;else r=r+1|0}D=c[p>>2]|0}a[D+A>>0]=0;r=Ka(k,8)|0;q=Ka(k,8)|0;v=Ka(k,8)|0;B=q<<8|r|v<<16|(Ka(k,8)|0)<<24;v=e+8|0;c[v>>2]=B;if(B>>>0<=536870911?(B<<2|0)<=(Ma(k)|0):0){B=c[v>>2]|0;r=B<<2;q=Ob(r)|0;x=e+4|0;c[x>>2]=q;y=Ob(r)|0;c[e>>2]=y;if((q|0)==0|(y|0)==0){c[v>>2]=0;C=-1;break}c:do if((B|0)>0){y=0;while(1){q=Ka(k,8)|0;r=Ka(k,8)|0;z=Ka(k,8)|0;u=r<<8|q|z<<16|(Ka(k,8)|0)<<24;if((u|0)<0){E=y;o=40;break}if((u|0)>(Ma(k)|0)){E=y;o=40;break}c[(c[x>>2]|0)+(y<<2)>>2]=u;z=Ob(u+1|0)|0;c[(c[e>>2]|0)+(y<<2)>>2]=z;z=c[(c[e>>2]|0)+(y<<2)>>2]|0;if(!z){F=y;o=42;break}if(!u)G=z;else{q=u;r=z;while(1){q=q+-1|0;a[r>>0]=Ka(k,8)|0;if(!q)break;else r=r+1|0}G=c[(c[e>>2]|0)+(y<<2)>>2]|0}a[G+u>>0]=0;y=y+1|0;if((y|0)>=(c[v>>2]|0))break c}if((o|0)==40){c[v>>2]=E;C=-20;break b}else if((o|0)==42){c[v>>2]=F;C=-1;break b}}while(0);x=(Ma(k)|0)>>31&-20;if((x|0)<0){C=x;break}else{n=2;break a}}c[v>>2]=0;C=-20}}else C=-20;while(0);gb(e);n=C;break}else if((m|0)==130){if((e|0)==0|(f|0)==0){n=-1;break}if(!(c[b+4>>2]|0)){n=-20;break}if(!(c[e+12>>2]|0)){n=-20;break}if(c[f>>2]|0){n=-20;break}A=Qb(1,712)|0;if(!A){n=-1;break}p=A+320|0;x=Ta(k,p)|0;if((x|0)>=0){B=_a(k,A)|0;if((B|0)<0)H=B;else{c[f>>2]=A;n=1;break}}else H=x;Ua(p);ab(A);Pb(A);n=H;break}else{n=-20;break}else n=-21}while(0);l=n;i=h;return l|0}function Oa(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0;e=c[b+2936+(d<<2)>>2]|0;f=c[b+2948+(d<<2)>>2]|0;g=c[a+72+(d<<5)>>2]|0;h=c[a+168>>2]|0;if((f|0)<=(e|0)){i=0;j=b+2840+(d<<2)|0;c[j>>2]=i;k=f-e|0;l=_(k,g)|0;m=l-i|0;n=b+2852+(d<<2)|0;c[n>>2]=m;return}o=(g|0)>0;p=1-g|0;q=~g;r=(c[a+72+(d<<5)+8>>2]|0)+(_(g,e)|0)|0;a=e;s=0;while(1){if(!a)if(o){t=r;u=0;v=s;while(1){w=h+(t<<2)|0;x=c[w>>2]|0;if(!(x&1))y=v;else{z=b+2960+(d<<4)+((x>>>6&3)<<2)|0;A=(c[z>>2]<<16)+x|0;c[w>>2]=A;c[z>>2]=A>>16;y=v+1|0}u=u+1|0;if((u|0)==(g|0)){B=y;break}else{t=t+1|0;v=y}}C=g+r|0;D=B}else{C=r;D=s}else if(o){v=r;t=0;u=-1;A=s;z=(c[h+(r-g<<2)>>2]|0)>>>6&3;w=-1;while(1){t=t+1|0;if((t|0)<(g|0))E=(c[h+(p+v<<2)>>2]|0)>>>6&3;else E=-1;x=h+(v<<2)|0;F=c[x>>2]|0;if(!(F&1)){G=-1;H=A}else{I=F>>>6&3;do switch(((w|0)==(I|0)&1)<<1|(u|0)==(I|0)|((z|0)==(I|0)&1)<<2|((E|0)==(I|0)&1)<<3|0){case 13:case 11:case 9:{J=(((c[h+(p+v<<2)>>2]>>16)*53|0)+((c[h+(v+-1<<2)>>2]>>16)*75|0)|0)/128|0;break}case 5:{J=((c[h+(v-g<<2)>>2]>>16)+(c[h+(v+-1<<2)>>2]>>16)|0)/2|0;break}case 12:case 6:case 4:{J=c[h+(v-g<<2)>>2]>>16;break}case 10:{J=((c[h+(p+v<<2)>>2]>>16)+(c[h+(v+q<<2)>>2]>>16)|0)/2|0;break}case 14:{J=((((c[h+(p+v<<2)>>2]>>16)+(c[h+(v+q<<2)>>2]>>16)|0)*3|0)+((c[h+(v-g<<2)>>2]>>16)*10|0)|0)/16|0;break}case 15:case 7:{K=v+-1|0;L=c[h+(K<<2)>>2]>>16;M=c[h+(K-g<<2)>>2]>>16;K=c[h+(v-g<<2)>>2]>>16;N=(((K+L|0)*29|0)+(_(M,-26)|0)|0)/32|0;O=N-K|0;if((((O|0)>-1?O:0-O|0)|0)<=128){O=N-L|0;if((((O|0)>-1?O:0-O|0)|0)>128)J=L;else{L=N-M|0;J=(((L|0)>-1?L:0-L|0)|0)>128?M:N}}else J=K;break}case 8:{J=c[h+(p+v<<2)>>2]>>16;break}case 3:case 1:{J=c[h+(v+-1<<2)>>2]>>16;break}case 2:{J=c[h+(v+q<<2)>>2]>>16;break}default:J=c[b+2960+(d<<4)+(I<<2)>>2]|0}while(0);K=F+(J<<16)|0;c[x>>2]=K;c[b+2960+(d<<4)+(I<<2)>>2]=K>>16;G=I;H=A+1|0}if((t|0)==(g|0)){P=H;break}else{K=z;v=v+1|0;u=G;A=H;z=E;w=K}}C=g+r|0;D=P}else{C=r;D=s}a=a+1|0;if((a|0)==(f|0)){i=D;break}else{r=C;s=D}}j=b+2840+(d<<2)|0;c[j>>2]=i;k=f-e|0;l=_(k,g)|0;m=l-i|0;n=b+2852+(d<<2)|0;c[n>>2]=m;return}function Pa(b,d){b=b|0;d=d|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;if((b|0)==0|(d|0)==0){f=0;return f|0}g=ib(57136,16)|0;do if((g|0)!=0?(mb(g,b,3)|0)>=0:0){h=g+51656|0;if(($a(h,d)|0)<0){nb(g);break}i=Ob((c[g+180>>2]|0)*129|0)|0;c[g+53512>>2]=i;if(!i){ab(h);nb(g);break}else j=0;do{c[g+880+(j*24|0)>>2]=g+2416+(j*768|0);c[g+880+(j*24|0)+4>>2]=g+2416+(j*768|0)+128;c[g+880+(j*24|0)+8>>2]=g+2416+(j*768|0)+256;c[g+880+(j*24|0)+12>>2]=g+2416+(j*768|0)+384;c[g+880+(j*24|0)+16>>2]=g+2416+(j*768|0)+512;c[g+880+(j*24|0)+20>>2]=g+2416+(j*768|0)+640;j=j+1|0}while((j|0)!=64);lb(g+880|0,g+53528|0,d+320|0);h=0;do{i=c[g+880+(h*24|0)>>2]|0;k=c[g+880+(h*24|0)+8>>2]|0;l=c[g+880+(h*24|0)+16>>2]|0;m=c[g+880+(h*24|0)+4>>2]|0;n=c[g+880+(h*24|0)+12>>2]|0;o=c[g+880+(h*24|0)+20>>2]|0;c[g+53784+(h<<2)>>2]=0-((e[k+34>>1]|0)+(e[k+24>>1]|0)+(e[k+36>>1]|0)+(e[k+48>>1]|0)+(e[l+24>>1]|0)+(e[l+34>>1]|0)+(e[l+36>>1]|0)+(e[l+48>>1]|0)+(e[n+24>>1]|0)+(e[n+34>>1]|0)+(e[n+36>>1]|0)+(e[n+48>>1]|0)+(e[o+24>>1]|0)+(e[o+34>>1]|0)+(e[o+36>>1]|0)+(e[o+48>>1]|0)+((e[i+34>>1]|0)+(e[i+24>>1]|0)+(e[i+36>>1]|0)+(e[i+48>>1]|0)+(e[m+24>>1]|0)+(e[m+34>>1]|0)+(e[m+36>>1]|0)+(e[m+48>>1]|0)<<1)>>11);h=h+1|0}while((h|0)!=64);h=g+51568|0;m=d+576|0;i=h+64|0;do{a[h>>0]=a[m>>0]|0;h=h+1|0;m=m+1|0}while((h|0)<(i|0));c[g+53524>>2]=0;c[g+54040>>2]=0;c[g+54044>>2]=0;c[g+54048>>2]=0;c[g+54104>>2]=0;c[g+54108>>2]=0;m=g+856|0;c[m>>2]=0;c[m+4>>2]=0;f=g;return f|0}while(0);jb(g);f=0;return f|0}function Qa(a){a=a|0;if(!a)return;Pb(c[a+54048>>2]|0);Pb(c[a+54044>>2]|0);Pb(c[a+54040>>2]|0);Pb(c[a+53512>>2]|0);ab(a+51656|0);nb(a);jb(a);return}function Ra(f,g,h){f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ma=0,Na=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,cb=0,db=0,eb=0,fb=0,gb=0,hb=0,ib=0,jb=0,lb=0,mb=0,nb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Qb=0,Rb=0,Wb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0,sc=0,tc=0,uc=0,vc=0,wc=0,xc=0,yc=0,zc=0,Ac=0,Bc=0,Cc=0,Dc=0,Ec=0,Fc=0,Gc=0,Hc=0,Ic=0,Jc=0,Kc=0,Lc=0,Mc=0,Nc=0,Oc=0,Pc=0,Qc=0,Rc=0,Sc=0,Tc=0,Uc=0,Vc=0,Wc=0,Xc=0,Yc=0,Zc=0,_c=0,$c=0,ad=0,bd=0,cd=0,dd=0,ed=0,fd=0,gd=0,hd=0,id=0,jd=0,kd=0,ld=0,md=0,nd=0,od=0,pd=0,qd=0,rd=0,sd=0,td=0,ud=0,vd=0,wd=0,xd=0,yd=0,zd=0,Ad=0,Bd=0,Cd=0,Dd=0,Ed=0,Fd=0,Gd=0,Hd=0,Id=0,Jd=0,Kd=0,Ld=0,Md=0,Nd=0,Od=0,Pd=0,Qd=0,Rd=0,Sd=0,Td=0,Ud=0;j=i;i=i+1088|0;k=j;l=j+312|0;m=j+304|0;n=j+256|0;if((f|0)==0|(g|0)==0){o=-1;i=j;return o|0}p=c[g+4>>2]|0;do if(!p){q=f+872|0;a[q>>0]=1;c[f+232>>2]=0;r=q;s=0}else{q=f+51636|0;Ja(q,c[g>>2]|0,p);if(La(q)|0){o=-24;i=j;return o|0}t=f+872|0;a[t>>0]=La(q)|0;a[f+875>>0]=Ka(q,6)|0;do if(La(q)|0){a[f+876>>0]=Ka(q,6)|0;if(!(La(q)|0)){a[f+874>>0]=2;break}else{a[f+877>>0]=Ka(q,6)|0;a[f+874>>0]=3;break}}else a[f+874>>0]=1;while(0);if(!(a[t>>0]|0)){if(Ka(q,3)|0){o=-23;i=j;return o|0}if(!(a[t>>0]|0)){u=c[f+216>>2]|0;v=c[f+184>>2]|0;w=c[f+188>>2]|0;x=c[f+168>>2]|0;y=0;z=0;A=0;B=0;while(1){y=(c[f+72+(z<<5)+28>>2]|0)+y|0;if(B>>>0<y>>>0){D=A;E=B;while(1){F=w+E|0;G=D;H=0;while(1){if((d[F>>0]|0)>>>2&15&1<<H){I=c[v+(E<<6)+(H<<4)>>2]|0;if((I|0)>-1){J=x+(I<<2)|0;c[J>>2]=c[J>>2]&-1986|385;c[u+(G<<2)>>2]=I;K=G+1|0}else K=G;I=c[v+(E<<6)+(H<<4)+4>>2]|0;if((I|0)>-1){J=x+(I<<2)|0;c[J>>2]=c[J>>2]&-1986|385;c[u+(K<<2)>>2]=I;L=K+1|0}else L=K;I=c[v+(E<<6)+(H<<4)+8>>2]|0;if((I|0)>-1){J=x+(I<<2)|0;c[J>>2]=c[J>>2]&-1986|385;c[u+(L<<2)>>2]=I;M=L+1|0}else M=L;I=c[v+(E<<6)+(H<<4)+12>>2]|0;if((I|0)>-1){J=x+(I<<2)|0;c[J>>2]=c[J>>2]&-1986|385;c[u+(M<<2)>>2]=I;N=M+1|0}else N=M}else N=G;H=H+1|0;if((H|0)==4){O=N;break}else G=N}E=E+1|0;if((E|0)==(y|0)){P=O;Q=y;break}else D=O}}else{P=A;Q=B}c[f+220+(z<<2)>>2]=P-A;z=z+1|0;if((z|0)==3){R=P;break}else{A=P;B=Q}}c[f+232>>2]=R;r=t;s=R;break}}B=La(q)|0;A=f+188|0;z=c[A>>2]|0;y=f+192|0;u=c[y>>2]|0;if(u){x=B;B=0;v=0;while(1){w=bb(q,224)|0;if((w|0)>15){D=w&31;S=D+6+(Ka(q,w-D>>4)|0)|0}else S=w;w=(x&255)<<1&2;D=0-S|0;E=v+1|0;G=v-(u>>>0>E>>>0?u:E)|0;E=G>>>0<D>>>0?D:G;G=v;v=v-E|0;do{D=z+G|0;a[D>>0]=a[D>>0]&-4|w;G=G+1|0}while((G|0)!=(v|0));G=_(E,x)|0;w=v>>>0<u>>>0;D=B-G|0;if(S>>>0>4128&w)T=La(q)|0;else T=(x|0)==0&1;if(!w){U=G;V=D;W=B;break}else{x=T;B=D}}B=c[y>>2]|0;a:do if(V>>>0<B>>>0){x=c[A>>2]|0;u=0;while(1)if(!(a[x+u>>0]&2)){X=u;break}else u=u+1|0;u=La(q)|0;E=X;while(1){v=bb(q,224)|0;if((v|0)>15){z=v&31;Y=z+6+(Ka(q,v-z>>4)|0)|0}else Y=v;if(E>>>0>=B>>>0)break a;v=u&1;z=Y;D=E;while(1){G=x+D|0;w=a[G>>0]|0;if(!(w&2)){if(!z){Z=D;break}a[G>>0]=w&-2|v;$=z+-1|0}else $=z;D=D+1|0;if(D>>>0>=B>>>0)break a;else z=$}if(Y>>>0<4129){u=(u|0)==0&1;E=Z;continue}else{u=La(q)|0;E=Z;continue}}}while(0);if((W|0)!=(U|0))aa=(La(q)|0)==0&1;else aa=0}else aa=0;B=c[f+184>>2]|0;y=c[A>>2]|0;E=c[f+200>>2]|0;u=c[f+168>>2]|0;x=c[f+216>>2]|0;z=c[f+180>>2]|0;D=aa;v=0;w=0;G=0;H=0;F=0;I=0;while(1){w=(c[f+72+(H<<5)+28>>2]|0)+w|0;if(I>>>0<w>>>0){J=(H|0)==0;ba=D;ca=v;da=G;ea=F;fa=I;while(1){ga=y+fa|0;ha=fa<<2;if(J){ia=ba;ja=ca;ka=da;la=0;ma=ea;while(1){if(!((d[ga>>0]|0)>>>2&15&1<<la)){na=ia;oa=ja;pa=ka;qa=ma}else{ra=0;sa=ia;ta=ja;ua=ka;va=0;wa=ma;while(1){xa=c[B+(fa<<6)+(la<<4)+(ra<<2)>>2]|0;if((xa|0)>-1){Aa=a[ga>>0]|0;do if(!(Aa&1)){if(Aa&2){if((wa|0)<1){Ba=(sa|0)==0&1;Ca=bb(q,272)|0}else{Ba=sa;Ca=wa}Da=Ca+-1|0;if(!Ba){Ea=0;Fa=Da}else{Ga=Ba;Ha=Ba;Ia=Da;Ma=67;break}}else{Ea=sa;Fa=wa}c[x+(z+~ua<<2)>>2]=xa;Na=0;Pa=Ea;Qa=ta;Ra=ua+1|0;Sa=Fa}else{Ga=1;Ha=sa;Ia=wa;Ma=67}while(0);if((Ma|0)==67){Ma=0;c[x+(ta<<2)>>2]=xa;Na=Ga;Pa=Ha;Qa=ta+1|0;Ra=ua;Sa=Ia}Aa=u+(xa<<2)|0;c[Aa>>2]=Na&1|c[Aa>>2]&-194|192;Ta=Pa;Ua=Qa;Wa=Ra;Xa=Na|va;Ya=Sa}else{Ta=sa;Ua=ta;Wa=ua;Xa=va;Ya=wa}ra=ra+1|0;if((ra|0)==4){Za=Ta;_a=Ua;$a=Wa;ab=Xa;cb=Ya;break}else{sa=Ta;ta=Ua;ua=Wa;va=Xa;wa=Ya}}a[E+(la|ha)>>0]=ab;na=Za;oa=_a;pa=$a;qa=cb}la=la+1|0;if((la|0)==4){db=na;eb=oa;fb=pa;gb=qa;break}else{ia=na;ja=oa;ka=pa;ma=qa}}}else{ma=ba;ka=ca;ja=da;ia=0;la=ea;while(1){if(!((d[ga>>0]|0)>>>2&15&1<<ia)){hb=ma;ib=ka;jb=ja;lb=la}else{ha=0;wa=ma;va=ka;ua=ja;ta=la;while(1){sa=c[B+(fa<<6)+(ia<<4)+(ha<<2)>>2]|0;if((sa|0)>-1){ra=a[ga>>0]|0;do if(!(ra&1)){if(ra&2){if((ta|0)<1){mb=(wa|0)==0&1;nb=bb(q,272)|0}else{mb=wa;nb=ta}Aa=nb+-1|0;if(!mb){wb=0;xb=Aa}else{yb=mb;zb=mb;Ab=Aa;Ma=79;break}}else{wb=wa;xb=ta}c[x+(z+~ua<<2)>>2]=sa;Bb=0;Cb=wb;Db=va;Eb=ua+1|0;Fb=xb}else{yb=1;zb=wa;Ab=ta;Ma=79}while(0);if((Ma|0)==79){Ma=0;c[x+(va<<2)>>2]=sa;Bb=yb;Cb=zb;Db=va+1|0;Eb=ua;Fb=Ab}ra=u+(sa<<2)|0;c[ra>>2]=Bb&1|c[ra>>2]&-194|192;Gb=Cb;Hb=Db;Ib=Eb;Jb=Fb}else{Gb=wa;Hb=va;Ib=ua;Jb=ta}ha=ha+1|0;if((ha|0)==4){hb=Gb;ib=Hb;jb=Ib;lb=Jb;break}else{wa=Gb;va=Hb;ua=Ib;ta=Jb}}}ia=ia+1|0;if((ia|0)==4){db=hb;eb=ib;fb=jb;gb=lb;break}else{ma=hb;ka=ib;ja=jb;la=lb}}}fa=fa+1|0;if((fa|0)==(w|0)){Kb=db;Lb=eb;Mb=fb;Nb=gb;Qb=w;break}else{ba=db;ca=eb;da=fb;ea=gb}}}else{Kb=D;Lb=v;Mb=G;Nb=F;Qb=I}c[f+220+(H<<2)>>2]=Lb-v;H=H+1|0;if((H|0)==3){Rb=Lb;break}else{D=Kb;v=Lb;G=Mb;F=Nb;I=Qb}}c[f+232>>2]=Rb;r=t;s=Rb}while(0);do if(!(a[r>>0]|0))Wb=s;else{Rb=f+524|0;Qb=f+528|0;if((c[Rb>>2]|0)>=0?(c[Qb>>2]|0)>=0:0){Wb=s;break}c[Rb>>2]=0;c[Qb>>2]=0;c[f+532>>2]=0;Qb=c[f+248>>2]|0;c[f+556>>2]=Qb;c[f+552>>2]=Qb;c[f+548>>2]=Qb;Yb=f+54056|0;Zb=f+236|0;_b=Yb+48|0;do{c[Yb>>2]=c[Zb>>2];Yb=Yb+4|0;Zb=Zb+4|0}while((Yb|0)<(_b|0));t=c[f+576>>2]|0;Rb=(t|0)>-1?t:0-t|0;t=c[f+8>>2]|0;Nb=t+32|0;Mb=c[f+580>>2]|0;Ub(Qb+(-16-(_(Rb,t+15|0)|0))|0,-128,(_(Rb,Nb)|0)+16+(_(((Mb|0)>-1?Mb:0-Mb|0)<<1,Nb>>((c[f+48>>2]|0)>>>1&1^1))|0)|0)|0;Wb=c[f+232>>2]|0}while(0);s=f+232|0;if((Wb|0)<1){Wb=f+848|0;Nb=c[Wb>>2]|0;Mb=c[Wb+4>>2]|0;Wb=Tb(d[f+873>>0]|0,0,Nb|0,Mb|0)|0;Rb=Vb(Wb|0,C|0,c[f+60>>2]|0)|0;Wb=C;t=f+856|0;Lb=t;Kb=c[Lb>>2]|0;gb=c[Lb+4>>2]|0;Lb=Sb(Kb|0,gb|0,Nb|0,Mb|0)|0;Mb=Tb(Lb|0,C|0,Rb|0,Wb|0)|0;Wb=C;Rb=f+864|0;c[Rb>>2]=Mb;c[Rb+4>>2]=Wb;Rb=Tb(Kb|0,gb|0,1,0)|0;gb=t;c[gb>>2]=Rb;c[gb+4>>2]=C;if(!h){o=1;i=j;return o|0}gb=h;c[gb>>2]=Mb;c[gb+4>>2]=Wb;o=1;i=j;return o|0}Wb=f+528|0;gb=f+524|0;Mb=c[gb>>2]|0;Rb=c[Wb>>2]|0;t=0;while(1)if((t|0)==(Mb|0)|(t|0)==(Rb|0))t=t+1|0;else{$b=t;break}t=f+532|0;c[t>>2]=$b;Rb=f+548|0;Mb=f+556|0;c[Mb>>2]=c[f+236+($b*48|0)+12>>2];if(a[r>>0]|0){Kb=f+51636|0;Lb=Ka(Kb,3)|0;if(!Lb){Nb=k;c[Nb>>2]=0;c[Nb+4>>2]=0;a[k+(Ka(Kb,3)|0)>>0]=0;a[k+(Ka(Kb,3)|0)>>0]=1;a[k+(Ka(Kb,3)|0)>>0]=2;a[k+(Ka(Kb,3)|0)>>0]=3;a[k+(Ka(Kb,3)|0)>>0]=4;a[k+(Ka(Kb,3)|0)>>0]=5;a[k+(Ka(Kb,3)|0)>>0]=6;a[k+(Ka(Kb,3)|0)>>0]=7;ac=k}else ac=400+(Lb+-1<<3)|0;Nb=(Lb|0)==7?456:480;Lb=f+200|0;fb=c[Lb>>2]|0;eb=f+212|0;db=c[eb>>2]|0;if(db){lb=0;do{jb=fb+lb|0;if((a[jb>>0]|0)>0)a[jb>>0]=a[ac+(bb(Kb,Nb)|0)>>0]|0;lb=lb+1|0}while((lb|0)!=(db|0))}db=f+48|0;lb=c[200+(c[db>>2]<<2)>>2]|0;Nb=(La(Kb)|0)!=0;ac=Nb?536:672;Nb=c[db>>2]|0;db=a[192+Nb>>0]|0;fb=db&255;jb=c[f+168>>2]|0;ib=c[f+176>>2]|0;hb=c[f+196>>2]|0;Jb=c[Lb>>2]|0;Lb=c[eb>>2]|0;if(Lb){eb=(db&255)>4;db=l+2|0;Ib=l+4|0;Hb=l+6|0;Gb=0;Fb=0;Eb=0;while(1){Db=a[Jb+Fb>>0]|0;Cb=Db<<24>>24;if(Db<<24>>24==7){Bb=c[hb+(Fb*48|0)>>2]|0;Ab=jb+(Bb<<2)|0;zb=c[Ab>>2]|0;if(!(zb&1)){b[l>>1]=0;bc=Gb}else{c[Ab>>2]=zb&-1985|1856;zb=(bb(Kb,ac)|0)+224|0;Ab=(((bb(Kb,ac)|0)<<8)+57344|zb&255)&65535;b[l>>1]=Ab;b[ib+(Bb<<1)>>1]=Ab;bc=Ab}Ab=c[hb+(Fb*48|0)+4>>2]|0;Bb=jb+(Ab<<2)|0;zb=c[Bb>>2]|0;if(!(zb&1)){b[db>>1]=0;cc=bc}else{c[Bb>>2]=zb&-1985|1856;zb=(bb(Kb,ac)|0)+224|0;Bb=(((bb(Kb,ac)|0)<<8)+57344|zb&255)&65535;b[db>>1]=Bb;b[ib+(Ab<<1)>>1]=Bb;cc=Bb}Bb=c[hb+(Fb*48|0)+8>>2]|0;Ab=jb+(Bb<<2)|0;zb=c[Ab>>2]|0;if(!(zb&1)){b[Ib>>1]=0;dc=cc}else{c[Ab>>2]=zb&-1985|1856;zb=(bb(Kb,ac)|0)+224|0;Ab=(((bb(Kb,ac)|0)<<8)+57344|zb&255)&65535;b[Ib>>1]=Ab;b[ib+(Bb<<1)>>1]=Ab;dc=Ab}Ab=c[hb+(Fb*48|0)+12>>2]|0;Bb=jb+(Ab<<2)|0;zb=c[Bb>>2]|0;if(!(zb&1)){b[Hb>>1]=0;ec=dc}else{c[Bb>>2]=zb&-1985|1856;zb=(bb(Kb,ac)|0)+224|0;Bb=(((bb(Kb,ac)|0)<<8)+57344|zb&255)&65535;b[Hb>>1]=Bb;b[ib+(Ab<<1)>>1]=Bb;ec=Bb}ya[lb&7](k,l);if(eb){Bb=4;do{Ab=d[144+(Nb*12|0)+Bb>>0]|0;zb=Ab&3;yb=c[hb+(Fb*48|0)+(Ab>>>2<<4)+(zb<<2)>>2]|0;Ab=jb+(yb<<2)|0;xb=c[Ab>>2]|0;if(xb&1){c[Ab>>2]=xb&-1985|1856;b[ib+(yb<<1)>>1]=b[k+(zb<<1)>>1]|0}Bb=Bb+1|0}while((Bb|0)<(fb|0));fc=ec;gc=Gb}else{fc=ec;gc=Gb}}else if(Db<<24>>24==-1){fc=Gb;gc=Eb}else{if((Cb|0)==2){Bb=(bb(Kb,ac)|0)+224|0;Qb=(((bb(Kb,ac)|0)<<8)+57344|Bb&255)&65535;hc=Qb;ic=Qb;jc=Gb}else if((Cb|0)==4){hc=Eb;ic=Eb;jc=Gb}else if((Cb|0)==6){Qb=(bb(Kb,ac)|0)+224|0;hc=Gb;ic=(((bb(Kb,ac)|0)<<8)+57344|Qb&255)&65535;jc=Eb}else if((Cb|0)==3){hc=Gb;ic=Gb;jc=Eb}else{hc=Gb;ic=0;jc=Eb}Qb=268505377>>>(Cb<<2)<<6&192|Cb<<8&1792;Bb=0;do{zb=d[144+(Nb*12|0)+Bb>>0]|0;yb=c[hb+(Fb*48|0)+(zb>>>2<<4)+((zb&3)<<2)>>2]|0;zb=jb+(yb<<2)|0;xb=c[zb>>2]|0;if(xb&1){c[zb>>2]=Qb|xb&-1985;b[ib+(yb<<1)>>1]=ic}Bb=Bb+1|0}while((Bb|0)<(fb|0));fc=hc;gc=jc}Fb=Fb+1|0;if((Fb|0)==(Lb|0))break;else{Gb=fc;Eb=gc}}}}else{gc=f+856|0;Eb=c[gc+4>>2]|0;fc=f+848|0;c[fc>>2]=c[gc>>2];c[fc+4>>2]=Eb}Eb=c[s>>2]|0;b:do if((Eb|0)>=1){s=c[f+168>>2]|0;fc=c[f+216>>2]|0;gc=f+874|0;if((a[gc>>0]|0)==1){Gb=0;while(1){Lb=s+(c[fc+(Gb<<2)>>2]<<2)|0;c[Lb>>2]=c[Lb>>2]&-61;Gb=Gb+1|0;if((Gb|0)==(Eb|0))break b}}Gb=f+51636|0;Lb=La(Gb)|0;Fb=0;jc=0;while(1){hc=bb(Gb,224)|0;if((hc|0)>15){fb=hc&31;kc=fb+6+(Ka(Gb,hc-fb>>4)|0)|0}else kc=hc;hc=(kc|0)>4128;fb=Lb<<2&60;ic=Fb;ib=jc;jb=kc;while(1){hb=ic+1|0;Nb=s+(c[fc+(ic<<2)>>2]<<2)|0;c[Nb>>2]=c[Nb>>2]&-61|fb;Nb=ib+Lb|0;if((jb|0)<=1){lc=hb;mc=Nb;break}if((hb|0)<(Eb|0)){ic=hb;ib=Nb;jb=jb+-1|0}else{lc=hb;mc=Nb;break}}jb=(lc|0)<(Eb|0);if(hc&jb)nc=La(Gb)|0;else nc=(Lb|0)==0&1;if(jb){Lb=nc;Fb=lc;jc=mc}else{oc=mc;break}}if((oc|0)>0&(a[gc>>0]|0)==3){jc=0;while(1)if(!(c[s+(c[fc+(jc<<2)>>2]<<2)>>2]&60))jc=jc+1|0;else{pc=jc;break}jc=La(Gb)|0;gc=pc;while(1){Fb=bb(Gb,224)|0;if((Fb|0)>15){Lb=Fb&31;qc=Lb+6+(Ka(Gb,Fb-Lb>>4)|0)|0}else qc=Fb;if((gc|0)<(Eb|0)){rc=gc;sc=qc}else break b;while(1){Fb=s+(c[fc+(rc<<2)>>2]<<2)|0;Lb=c[Fb>>2]|0;jb=Lb>>>2;if(!(jb&15))tc=sc;else{if((sc|0)<1){uc=rc;break}c[Fb>>2]=jb+jc<<2&60|Lb&-61;tc=sc+-1|0}rc=rc+1|0;if((rc|0)>=(Eb|0))break b;else sc=tc}if((qc|0)<4129){jc=(jc|0)==0&1;gc=uc;continue}else{jc=La(Gb)|0;gc=uc;continue}}}}while(0);uc=f+220|0;qc=c[uc>>2]|0;tc=0;do{c[l+(tc<<2)>>2]=qc;tc=tc+1|0}while((tc|0)!=64);tc=f+224|0;qc=c[tc>>2]|0;sc=0;do{c[l+256+(sc<<2)>>2]=qc;sc=sc+1|0}while((sc|0)!=64);sc=f+228|0;qc=c[sc>>2]|0;Eb=0;do{c[l+512+(Eb<<2)>>2]=qc;Eb=Eb+1|0}while((Eb|0)!=64);Eb=f+51636|0;c[m>>2]=Ka(Eb,4)|0;qc=m+4|0;c[qc>>2]=Ka(Eb,4)|0;c[f+52744>>2]=0;rc=f+53512|0;pc=c[rc>>2]|0;oc=f+168|0;mc=c[oc>>2]|0;lc=f+216|0;nc=c[lc>>2]|0;kc=k+252|0;gc=0;Gb=0;jc=0;fc=0;s=0;while(1){hc=c[f+220+(fc<<2)>>2]|0;Lb=jc;jc=hc+jc|0;Ub(k|0,0,256)|0;c[f+52744+(fc<<8)>>2]=gc;c[f+51976+(fc<<8)>>2]=s;jb=jc-Gb|0;Fb=(jb|0)<(gc|0)?jb:gc;jb=gc-Fb|0;if((Fb|0)>0){ib=Gb+~Lb-hc|0;ic=~gc;fb=(ib|0)>(ic|0)?ib:ic;ic=Fb;ib=Gb;while(1){Nb=mc+(c[nc+(ib<<2)>>2]<<2)|0;c[Nb>>2]=c[Nb>>2]&65535;if((ic|0)>1){ic=ic+-1|0;ib=ib+1|0}else break}vc=Gb+1-fb+((fb|0)>-2?fb:-2)|0}else vc=Gb;c:do if((jc|0)>(vc|0)){ib=~Lb-hc|0;ic=f+51656+(c[m+(fc+1>>1<<2)>>2]<<2)|0;Nb=Fb;hb=vc;ac=s;while(1){Kb=hb;ec=ac;while(1){eb=bb(Eb,c[ic>>2]|0)|0;lb=ec+1|0;a[pc+ec>>0]=eb;if((eb|0)<15){Hb=Ka(Eb,d[880+eb>>0]|0)|0;dc=ec+2|0;a[pc+lb>>0]=Hb;if(!eb){a[pc+dc>>0]=Hb>>>8;wc=ec+3|0}else wc=dc;xc=Hb<<((eb|0)<2?-13:0)+((eb|0)<12?21:0);yc=wc}else{xc=0;yc=lb}lb=(c[896+(eb<<2)>>2]|0)+xc|0;eb=(lb|0)==0?2147483647:lb>>>8&4095;if(eb){zc=eb;Ac=Kb;Bc=yc;break}eb=lb&255;Hb=k+(eb<<2)|0;c[Hb>>2]=(c[Hb>>2]|0)+1;Hb=Kb+1|0;dc=mc+(c[nc+(Kb<<2)>>2]<<2)|0;c[dc>>2]=c[dc>>2]&65535|((eb|0)!=0?0:(lb^0-(lb&1048576))>>21<<16);if((jc|0)>(Hb|0)){Kb=Hb;ec=yc}else{Cc=Nb;Dc=0;Ec=Hb;Fc=yc;break c}}ec=jc-Ac|0;Kb=(ec|0)<(zc|0)?ec-zc|0:0;ec=Kb+zc|0;Hb=ec+Nb|0;if((ec|0)>0){lb=Ac+ib|0;eb=~zc;dc=(lb|0)>(eb|0)?lb:eb;eb=ec;ec=Ac;while(1){lb=mc+(c[nc+(ec<<2)>>2]<<2)|0;c[lb>>2]=c[lb>>2]&65535;if((eb|0)>1){eb=eb+-1|0;ec=ec+1|0}else break}Gc=Ac+1-dc+((dc|0)>-2?dc:-2)|0}else Gc=Ac;if((jc|0)>(Gc|0)){Nb=Hb;hb=Gc;ac=Bc}else{Hc=Kb;Ic=Hb;Jc=Gc;Kc=Bc;break}}Cc=Ic;Dc=0-Hc|0;Ec=Jc;Fc=Kc}else{Cc=Fb;Dc=jb;Ec=vc;Fc=s}while(0);jb=(c[kc>>2]|0)+Cc|0;c[kc>>2]=jb;Fb=62;hc=jb;while(1){jb=k+(Fb<<2)|0;hc=(c[jb>>2]|0)+hc|0;c[jb>>2]=hc;if((Fb|0)<=0){Lc=63;break}else Fb=Fb+-1|0}while(1){Fb=l+(fc<<8)+(Lc<<2)|0;c[Fb>>2]=(c[Fb>>2]|0)-(c[k+(Lc<<2)>>2]|0);if((Lc|0)>0)Lc=Lc+-1|0;else break}fc=fc+1|0;if((fc|0)==3){Mc=Dc;Nc=Fc;break}else{gc=Dc;Gb=Ec;s=Fc}}Fc=f+53520|0;c[Fc>>2]=Nc;Nc=Ka(Eb,4)|0;c[m>>2]=Nc;s=Ka(Eb,4)|0;c[qc>>2]=s;Ec=Nc;Nc=s;s=Mc;Mc=1;Gb=1;while(1){Ec=Ec+16|0;c[m>>2]=Ec;Nc=Nc+16|0;c[qc>>2]=Nc;Dc=d[1264+Mc>>0]|0;if((Gb|0)<(Dc|0)){gc=Gb+1|0;fc=c[Fc>>2]|0;Lc=s;Cc=Gb;while(1){vc=c[rc>>2]|0;Kc=64-Cc|0;Jc=(Kc|0)>0;Hc=Lc;Ic=0;Bc=fc;while(1){c[f+52744+(Ic<<8)+(Cc<<2)>>2]=Hc;c[f+51976+(Ic<<8)+(Cc<<2)>>2]=Bc;Gc=c[l+(Ic<<8)+(Cc<<2)>>2]|0;Ub(k|0,0,256)|0;if(Hc>>>0<Gc>>>0){jc=f+51656+(c[m+(Ic+1>>1<<2)>>2]<<2)|0;Ac=Hc;nc=Hc;mc=0;zc=Bc;while(1){yc=mc+Ac|0;xc=bb(Eb,c[jc>>2]|0)|0;wc=zc+1|0;a[vc+zc>>0]=xc;if((xc|0)<15){pc=Ka(Eb,d[880+xc>>0]|0)|0;Fb=zc+2|0;a[vc+wc>>0]=pc;if(!xc){a[vc+Fb>>0]=pc>>>8;Oc=zc+3|0}else Oc=Fb;Pc=pc<<((xc|0)<2?-13:0)+((xc|0)<12?21:0);Qc=Oc}else{Pc=0;Qc=wc}wc=(c[896+(xc<<2)>>2]|0)+Pc|0;xc=(wc|0)==0?2147483647:wc>>>8&4095;if(!xc){pc=k+((wc&255)<<2)|0;c[pc>>2]=(c[pc>>2]|0)+1;Rc=0;Sc=nc+1|0}else{Rc=xc;Sc=nc}nc=Rc+Sc|0;if(nc>>>0>=Gc>>>0){Tc=Rc;Uc=yc;Vc=Sc;Wc=Qc;break}else{Ac=Rc;mc=yc;zc=Qc}}Xc=Tc;Yc=c[kc>>2]|0;Zc=Uc;_c=Vc;$c=Wc}else{Xc=Hc;Yc=0;Zc=0;_c=0;$c=Bc}zc=Gc-_c|0;mc=Zc+Yc+zc|0;c[kc>>2]=mc;Ac=62;nc=mc;while(1){mc=k+(Ac<<2)|0;nc=(c[mc>>2]|0)+nc|0;c[mc>>2]=nc;if((Ac|0)<=0)break;else Ac=Ac+-1|0}Ac=Xc-zc|0;if(Jc){nc=Kc;do{Gc=nc;nc=nc+-1|0;mc=l+(Ic<<8)+(nc+Cc<<2)|0;c[mc>>2]=(c[mc>>2]|0)-(c[k+(nc<<2)>>2]|0)}while((Gc|0)>1)}Ic=Ic+1|0;if((Ic|0)==3){ad=Ac;bd=$c;break}else{Hc=Ac;Bc=$c}}c[Fc>>2]=bd;Bc=Cc+1|0;if((Bc|0)==(Dc|0)){cd=ad;break}else{fc=bd;Lc=ad;Cc=Bc}}dd=cd;ed=(gc|0)>(Dc|0)?gc:Dc}else{dd=s;ed=Gb}Mc=Mc+1|0;if((Mc|0)==5)break;else{s=dd;Gb=ed}}ed=f+848|0;Gb=c[ed>>2]|0;dd=c[ed+4>>2]|0;ed=Tb(d[f+873>>0]|0,0,Gb|0,dd|0)|0;s=Vb(ed|0,C|0,c[f+60>>2]|0)|0;ed=C;Mc=f+856|0;cd=Mc;ad=c[cd>>2]|0;bd=c[cd+4>>2]|0;cd=Sb(ad|0,bd|0,Gb|0,dd|0)|0;dd=Tb(cd|0,C|0,s|0,ed|0)|0;ed=C;s=f+864|0;c[s>>2]=dd;c[s+4>>2]=ed;s=Tb(ad|0,bd|0,1,0)|0;bd=Mc;c[bd>>2]=s;c[bd+4>>2]=C;if(h){bd=h;c[bd>>2]=dd;c[bd+4>>2]=ed}ed=f+54112|0;bd=f+48|0;dd=f+57120|0;c[dd>>2]=4<<((c[bd>>2]|0)>>>1&1^1);Xb(f+54624|0,f+51976|0,768)|0;Xb(f+56160|0,f+52744|0,768)|0;h=c[lc>>2]|0;s=f+180|0;Mc=c[s>>2]|0;c[f+56928>>2]=h;c[f+56940>>2]=h+(Mc<<2);ad=c[uc>>2]|0;cd=ad-(c[f+84>>2]|0)+Mc|0;c[f+56932>>2]=h+(ad<<2);c[f+56944>>2]=h+(cd<<2);Mc=c[tc>>2]|0;Gb=h+(Mc-(c[f+116>>2]|0)+cd<<2)|0;c[f+56936>>2]=h+(Mc+ad<<2);c[f+56948>>2]=Gb;Gb=a[f+874>>0]|0;if(Gb<<24>>24){ad=Gb&255;Gb=0;do{Mc=f+875+Gb|0;c[f+56976+(Gb<<3)>>2]=c[f+880+((d[Mc>>0]|0)*24|0)>>2];c[f+56976+(Gb<<3)+4>>2]=c[f+880+((d[Mc>>0]|0)*24|0)+4>>2];Gb=Gb+1|0}while((Gb|0)!=(ad|0));fd=0;do{Gb=f+875+fd|0;c[f+57e3+(fd<<3)>>2]=c[f+880+((d[Gb>>0]|0)*24|0)+8>>2];c[f+57e3+(fd<<3)+4>>2]=c[f+880+((d[Gb>>0]|0)*24|0)+12>>2];fd=fd+1|0}while((fd|0)!=(ad|0));gd=0;do{fd=f+875+gd|0;c[f+57024+(gd<<3)>>2]=c[f+880+((d[fd>>0]|0)*24|0)+16>>2];c[f+57024+(gd<<3)+4>>2]=c[f+880+((d[fd>>0]|0)*24|0)+20>>2];gd=gd+1|0}while((gd|0)!=(ad|0))}Yb=f+57072|0;_b=Yb+48|0;do{c[Yb>>2]=0;Yb=Yb+4|0}while((Yb|0)<(_b|0));ad=f+875|0;gd=a[(d[ad>>0]|0)+(f+51568)>>0]|0;fd=gd<<24>>24!=0;Gb=f+57124|0;c[Gb>>2]=fd&1;if(fd)rb(f+54368|0,gd&255);gd=f+53524|0;fd=c[gd>>2]|0;Mc=f+54040|0;h=c[Mc>>2]|0;cd=(h|0)==0;d:do if((fd|0)<1)if(cd)Ma=245;else{Pb(h);c[Mc>>2]=0;Fc=f+54044|0;Pb(c[Fc>>2]|0);c[Fc>>2]=0;Fc=f+54048|0;Pb(c[Fc>>2]|0);c[Fc>>2]=0;Ma=245}else{if(!cd){Fc=c[lc>>2]|0;$c=(c[tc>>2]|0)+(c[uc>>2]|0)+(c[sc>>2]|0)|0;l=a[ad>>0]|0;if(($c|0)>0){Xc=0;do{a[h+(c[Fc+(Xc<<2)>>2]|0)>>0]=l;Xc=Xc+1|0}while((Xc|0)!=($c|0));hd=c[gd>>2]|0}else hd=fd}else{if(a[r>>0]|0){Ma=245;break}$c=c[s>>2]|0;Xc=Ob($c)|0;c[Mc>>2]=Xc;if(!Xc){Ma=245;break}Ub(Xc|0,a[ad>>0]|0,$c|0)|0;hd=fd}$c=f+54044|0;Xc=c[$c>>2]|0;l=(Xc|0)==0;if((hd|0)<2){if(l){Ma=245;break}Pb(Xc);c[$c>>2]=0;Xc=f+54048|0;Pb(c[Xc>>2]|0);c[Xc>>2]=0;Ma=245;break}do if(l){Xc=c[f+4>>2]|0;Fc=c[f+8>>2]|0;Dc=_(Fc,Xc)|0;gc=c[bd>>2]|0;kc=Ob((_(Xc>>>(gc&1^1)<<1,Fc>>>(gc>>>1&1^1))|0)+Dc|0)|0;Dc=f+54048|0;c[Dc>>2]=kc;gc=Ob(c[s>>2]<<2)|0;c[$c>>2]=gc;if((kc|0)==0|(gc|0)==0){Pb(kc);c[Dc>>2]=0;Pb(c[$c>>2]|0);c[$c>>2]=0;Ma=245;break d}else{Dc=f+54052|0;c[Dc>>2]=0;id=Dc;jd=Xc;kd=Fc;Ma=238;break}}else{Fc=f+54052|0;if((c[Fc>>2]|0)==(((hd|0)>4?2:1)|0))ld=hd;else{id=Fc;jd=c[f+4>>2]|0;kd=c[f+8>>2]|0;Ma=238}}while(0);if((Ma|0)==238){if((hd|0)<5){c[f+54056>>2]=jd;c[f+54060>>2]=kd;l=0-jd|0;c[f+54064>>2]=l;c[f+54068>>2]=(c[f+54048>>2]|0)+(_(1-kd|0,l)|0);md=hd}else{l=_(jd,kd)|0;Fc=c[bd>>2]|0;Xc=jd>>>(Fc&1^1);Dc=kd>>>(Fc>>>1&1^1);Fc=_(Dc,Xc)|0;kc=f+54056|0;c[kc>>2]=jd;c[f+54060>>2]=kd;c[f+54064>>2]=jd;gc=c[f+54048>>2]|0;c[f+54068>>2]=gc;c[f+54072>>2]=Xc;c[f+54076>>2]=Dc;c[f+54080>>2]=Xc;Yc=gc;c[f+54084>>2]=Yc+l;c[f+54088>>2]=Xc;c[f+54092>>2]=Dc;c[f+54096>>2]=Xc;c[f+54100>>2]=Yc+(Fc+l);kb(kc,kc);md=c[gd>>2]|0}c[id>>2]=(md|0)>4?2:1;ld=md}if((ld|0)<5){kc=f+54072|0;l=f+236+((c[t>>2]|0)*48|0)+16|0;c[kc>>2]=c[l>>2];c[kc+4>>2]=c[l+4>>2];c[kc+8>>2]=c[l+8>>2];c[kc+12>>2]=c[l+12>>2];c[kc+16>>2]=c[l+16>>2];c[kc+20>>2]=c[l+20>>2];c[kc+24>>2]=c[l+24>>2];c[kc+28>>2]=c[l+28>>2]}l=f+57128|0;c[l>>2]=c[gd>>2];nd=l;od=$c}while(0);if((Ma|0)==245){ld=f+57128|0;c[ld>>2]=0;Yb=f+54056|0;Zb=f+236+((c[t>>2]|0)*48|0)|0;_b=Yb+48|0;do{c[Yb>>2]=c[Zb>>2];Yb=Yb+4|0;Zb=Zb+4|0}while((Yb|0)<(_b|0));nd=ld;od=f+54044|0}Yb=ed;_b=Yb+128|0;do{b[Yb>>1]=0;Yb=Yb+2|0}while((Yb|0)<(_b|0));kb(n,f+54056|0);Yb=f+76|0;_b=f+64|0;ld=k+2|0;Zb=f+552|0;md=f+172|0;id=f+54368|0;jd=f+54108|0;kd=f+54104|0;hd=c[dd>>2]|0;s=0;fd=0;while(1){ad=c[Yb>>2]|0;h=(hd+fd|0)<(ad|0);sc=h&1;uc=ad;tc=ad;ad=0;while(1){lc=(ad|0)!=0;if(lc)pd=(c[bd>>2]&2|0)==0;else pd=0;cd=pd&1;l=fd>>cd;kc=f+57048+(ad<<2)|0;c[kc>>2]=l;Fc=f+72+(ad<<5)+4|0;Yc=c[Fc>>2]|0;Xc=(c[dd>>2]>>cd)+l|0;l=f+57060+(ad<<2)|0;c[l>>2]=(Xc|0)<(Yc|0)?Xc:Yc;Oa(f,ed,ad);Yc=c[rc>>2]|0;Xc=c[_b>>2]|0;Dc=c[oc>>2]|0;gc=f+56928+(ad<<2)|0;Zc=c[gc>>2]|0;_c=c[f+56952+(ad<<2)>>2]|0;b[k>>1]=b[c[f+56976+(ad*24|0)>>2]>>1]|0;b[ld>>1]=b[c[f+56976+(ad*24|0)+4>>2]>>1]|0;if((_c|0)>0){Wc=0;do{Vc=c[Zc+(Wc<<2)>>2]|0;Uc=Dc+(Vc<<2)|0;Tc=c[Uc>>2]|0;Qc=(Tc&1792|0)!=256&1;Rc=c[f+56976+(ad*24|0)+((Tc>>>2&15)<<3)+(Qc<<2)>>2]|0;Tc=0;while(1){Sc=f+56160+(ad<<8)+(Tc<<2)|0;Pc=c[Sc>>2]|0;if(Pc){qd=Sc;rd=Pc;sd=Tc;Ma=257;break}Pc=f+54624+(ad<<8)+(Tc<<2)|0;Oc=c[Pc>>2]|0;Eb=Oc+1|0;m=a[Yc+Oc>>0]|0;Nc=c[896+((m&255)<<2)>>2]|0;do if((m&255)<15){qc=Oc+2|0;Ec=(d[Yc+Eb>>0]<<((m&255)<2?-13:0)+((m&255)<12?21:0))+Nc|0;Cc=Ec>>>8&4095;if(m<<24>>24){td=Ec;ud=Cc;vd=qc;break}Lc=(d[Yc+qc>>0]<<8)+Cc|0;td=Ec;ud=(Lc|0)==0?2147483647:Lc;vd=Oc+3|0}else{td=Nc;ud=Nc>>>8&4095;vd=Eb}while(0);c[Sc>>2]=ud;c[Pc>>2]=vd;Eb=(td&255)+Tc|0;Nc=(_(e[Rc+(Eb<<1)>>1]|0,(td^0-(td&1048576))>>21)|0)&65535;b[f+54112+(d[Xc+Eb>>0]<<1)>>1]=Nc;Nc=((ud|0)==0&1)+Eb|0;if((Nc|0)<64)Tc=Nc;else{wd=Tc;break}}if((Ma|0)==257){Ma=0;c[qd>>2]=rd+-1;wd=sd}b[ed>>1]=(c[Uc>>2]|0)>>>16;qb(f,Vc,ad,ed,wd,b[k+(Qc<<1)>>1]|0);Wc=Wc+1|0}while((Wc|0)!=(_c|0));xd=c[gc>>2]|0}else xd=Zc;c[gc>>2]=xd+(_c<<2);Wc=c[f+56964+(ad<<2)>>2]|0;if((Wc|0)>0){Xc=f+56940+(ad<<2)|0;Yc=(c[Xc>>2]|0)+(0-Wc<<2)|0;c[Xc>>2]=Yc;Va(c[Mb>>2]|0,c[Zb>>2]|0,c[f+576+(ad<<2)>>2]|0,Yc,Wc,c[md>>2]|0)}if(!(c[Gb>>2]|0)){yd=0;zd=0}else{sb(f,id,2,ad,(c[kc>>2]|0)-s|0,(c[l>>2]|0)-sc|0);yd=sc;zd=s}ob(f,$b,ad,((c[kc>>2]|0)-zd<<3)-(zd<<1)|0,((c[l>>2]|0)-yd<<3)-(yd<<1)|0);Wc=lc?3:0;do if((c[nd>>2]|0)<(Wc+2|0))if(!(c[Gb>>2]|0)){Ad=yd;Bd=zd}else{Ad=yd+sc|0;Bd=zd+s|0}else{Yc=zd+s|0;Xc=yd+sc|0;Dc=(c[kc>>2]|0)-Yc|0;Tc=c[l>>2]|0;Rc=Tc-Xc|0;Ac=f+72+(ad<<5)|0;Nc=c[Ac>>2]|0;Eb=f+72+(ad<<5)+8|0;Oc=c[Eb>>2]|0;m=_(Nc,Dc)|0;Lc=Oc+m|0;Ec=c[od>>2]|0;Cc=Ec+(Lc<<2)|0;qc=c[Mc>>2]|0;fc=qc+Lc|0;Bc=(Dc|0)>0;Hc=(c[Fc>>2]|0)>(Rc|0);Ic=Hc&1;Ub(Ec+(Lc+(Bc?Nc:0)<<2)|0,0,_(Nc<<2,Rc-Dc+(Bc<<31>>31)+Ic|0)|0)|0;Lc=(Bc&1)<<2|Dc<<3;Dc=f+54056+(ad<<4)+8|0;Bc=c[Dc>>2]|0;Kc=c[f+236+($b*48|0)+(ad<<4)+8>>2]|0;Jc=f+54056+(ad<<4)+12|0;vc=c[Jc>>2]|0;nc=_(Bc,Lc)|0;zc=vc+nc|0;Gc=c[f+236+($b*48|0)+(ad<<4)+12>>2]|0;mc=_(Kc,Lc)|0;jc=Gc+mc|0;Hb=f+54056+(ad<<4)|0;Kb=c[Hb>>2]|0;if((Lc|0)<4){dc=Kc<<2;yc=zc;xc=jc;pc=Lc;while(1){Xb(yc|0,xc|0,Kb|0)|0;pc=pc+1|0;if((pc|0)==4)break;else{yc=yc+Bc|0;xc=xc+Kc|0}}xc=Bc<<2;Cd=dc;Dd=xc;Ed=vc+xc|0;Fd=Gc+dc|0;Gd=4}else{Cd=mc;Dd=nc;Ed=zc;Fd=jc;Gd=Lc}xc=Ic^1;yc=Rc-xc<<3;if((Gd|0)<(yc|0)){pc=0-Kc|0;Qc=Bc<<3;Vc=Kc<<3;Uc=Nc+1|0;wc=-4-(Bc<<2)|0;if((Kb|0)>8){Fb=(Kb+-9|0)>>>3;hc=Fb+2|0;jb=(Rc<<3)+-1-(xc<<3)-Gd|0;Lb=Oc+Fb+m|0;fb=((Tc-xc-Xc<<3)+-1-Gd|0)>>>3;ac=Ec+(Lb+2<<2)+(_(fb,(Fb<<2)+8|0)|0)|0;Fb=Lb+(_(fb,hc)|0)|0;fb=fc;Lb=Ed;hb=Fd;Nb=Cc;ib=Gd;while(1){ic=c[f+53528+(d[fb>>0]<<2)>>2]|0;tb(Lb,Bc,hb+pc|0,Kc,ic,ic*3>>2,Nb,Nb+(Nc<<2)|0);ic=fb;ec=Nb;eb=8;do{lb=ec;ec=ec+4|0;ic=ic+1|0;Ib=c[f+53528+(d[ic>>0]<<2)>>2]|0;cc=Ib*3>>2;tb(Lb+eb|0,Bc,hb+(eb-Kc)|0,Kc,Ib,cc,ec,lb+(Uc<<2)|0);ub(Lb+(wc+eb)|0,Bc,Ib,cc,lb);eb=eb+8|0}while((eb|0)<(Kb|0));ib=ib+8|0;if((ib|0)>=(yc|0))break;else{fb=fb+hc|0;Lb=Lb+Qc|0;hb=hb+Vc|0;Nb=Nb+(hc<<2)|0}}Hd=Fb+2|0;Id=jb&-8;Jd=ac}else{hc=((Rc<<3)+-1-(xc<<3)-Gd|0)>>>3;Nb=Oc+1+m+hc|0;hb=fc;Lb=Ed;fb=Fd;ib=Cc;wc=Gd;while(1){Uc=c[f+53528+(d[hb>>0]<<2)>>2]|0;tb(Lb,Bc,fb+pc|0,Kc,Uc,Uc*3>>2,ib,ib+(Nc<<2)|0);wc=wc+8|0;if((wc|0)>=(yc|0))break;else{hb=hb+1|0;Lb=Lb+Qc|0;fb=fb+Vc|0;ib=ib+4|0}}Hd=Nb;Id=hc<<3;Jd=Ec+(Nb<<2)|0}ib=Id+8|0;Kd=qc+Hd|0;Ld=vc+((_(ib,Bc)|0)+Dd)|0;Md=Gc+((_(ib,Kc)|0)+Cd)|0;Nd=Jd;Od=Gd+8+Id|0}else{Kd=fc;Ld=Ed;Md=Fd;Nd=Cc;Od=Gd}do if(!Hc){ib=c[f+54056+(ad<<4)+4>>2]|0;if((ib|0)>(Od|0)){Vc=ib-Od|0;fb=Ld;Qc=Md;Lb=Od;while(1){Xb(fb|0,Qc|0,Kb|0)|0;Lb=Lb+1|0;if((Lb|0)==(ib|0))break;else{fb=fb+Bc|0;Qc=Qc+Kc|0}}Pd=Ld+(_(Vc,Bc)|0)|0}else Pd=Ld;if((Kb|0)<=8)break;Qc=-4-(Bc<<3)|0;fb=Kd;ib=Nd;Lb=8;while(1){fb=fb+1|0;hb=c[f+53528+(d[fb>>0]<<2)>>2]|0;ub(Pd+(Qc+Lb)|0,Bc,hb,hb*3>>2,ib);Lb=Lb+8|0;if((Lb|0)>=(Kb|0))break;else ib=ib+4|0}}while(0);if((c[nd>>2]|0)<(Wc+3|0)){Ad=Xc;Bd=Yc;break}Kb=Yc+s|0;Bc=Xc+sc|0;Kc=(c[kc>>2]|0)-Kb|0;Hc=c[Ac>>2]|0;Cc=(c[Eb>>2]|0)+(_(Hc,Kc)|0)|0;fc=(c[gd>>2]|0)>=((lc?7:4)|0);Gc=lc?3840:1920;vc=Kc<<3;Kc=c[Dc>>2]|0;qc=(c[l>>2]|0)-Bc<<3;Nb=c[Hb>>2]|0;Ec=c[f+54056+(ad<<4)+4>>2]|0;if((vc|0)>=(qc|0)){Ad=Bc;Bd=Kb;break}hc=(c[Jc>>2]|0)+(_(Kc,vc)|0)|0;ib=(Nb|0)>0;Lb=Kc<<3;Qc=0-Hc|0;fb=((Nb+-1|0)>>>3)+1|0;Vc=(c[oc>>2]|0)+(Cc<<2)|0;hb=hc;hc=(c[od>>2]|0)+(Cc<<2)|0;Cc=vc;while(1){if(ib){vc=(Cc|0)<1;yc=Cc+8|0;wc=(yc|0)>=(Ec|0);Nc=(wc&1)<<3|(vc&1)<<2;pc=Vc;m=hc;Oc=0;while(1){xc=d[((c[pc>>2]|0)>>>2&15)+(f+875)>>0]|0;Rc=c[m>>2]|0;ac=(Oc|0)<1;jb=Oc;Oc=Oc+8|0;Fb=(Oc|0)>=(Nb|0);Uc=Nc|ac&1|(Fb&1)<<1;e:do if(fc&(Rc|0)>(Gc|0)){Tc=hb+jb|0;Ic=f+53528+(xc<<2)|0;Lc=f+53784+(xc<<2)|0;vb(Tc,Kc,Uc,c[Ic>>2]|0,c[Lc>>2]|0,1);do if(!lc){if(!ac?(c[m+-4>>2]|0)>3840:0)break;if(!Fb?(c[m+4>>2]|0)>3840:0)break;if(!vc?(c[m+(Qc<<2)>>2]|0)>3840:0)break;if(wc)break e;if((c[m+(Hc<<2)>>2]|0)<=3840)break e}while(0);vb(Tc,Kc,Uc,c[Ic>>2]|0,c[Lc>>2]|0,1);vb(Tc,Kc,Uc,c[Ic>>2]|0,c[Lc>>2]|0,1)}else{if((Rc|0)>1536){vb(hb+jb|0,Kc,Uc,c[f+53528+(xc<<2)>>2]|0,c[f+53784+(xc<<2)>>2]|0,1);break}if((Rc|0)<=384)break;vb(hb+jb|0,Kc,Uc,c[f+53528+(xc<<2)>>2]|0,c[f+53784+(xc<<2)>>2]|0,0)}while(0);if((Oc|0)>=(Nb|0))break;else{pc=pc+4|0;m=m+4|0}}Qd=yc;Rd=Vc+(fb<<2)|0;Sd=hc+(fb<<2)|0}else{Qd=Cc+8|0;Rd=Vc;Sd=hc}if((Qd|0)<(qc|0)){Vc=Rd;hb=hb+Lb|0;hc=Sd;Cc=Qd}else{Ad=Bc;Bd=Kb;break}}}while(0);lc=(c[kc>>2]|0)-Bd<<cd;Wc=(lc|0)<(uc|0)?lc:uc;lc=(c[l>>2]|0)-Ad<<cd;Fc=(lc|0)<(tc|0)?lc:tc;ad=ad+1|0;if((ad|0)==3){Td=Wc;Ud=Fc;break}else{uc=Wc;tc=Fc}}tc=c[jd>>2]|0;if(tc){uc=c[Yb>>2]|0;za[tc&7](c[kd>>2]|0,n,uc-Ud|0,uc-Td|0)}uc=c[dd>>2]|0;if(h){hd=uc;s=1;fd=uc+fd|0}else break}pb(f,$b,0);pb(f,$b,1);pb(f,$b,2);$b=(a[r>>0]|0)==0;r=c[t>>2]|0;c[Wb>>2]=r;if($b){c[gb>>2]=r;r=c[Mb>>2]|0;c[Zb>>2]=r;c[Rb>>2]=r}else c[Zb>>2]=c[Mb>>2];o=0;i=j;return o|0}function Sa(a,b){a=a|0;b=b|0;var c=0;if((a|0)==0|(b|0)==0){c=-1;return c|0}kb(b,a+54056|0);c=0;return c|0}function Ta(d,e){d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0;f=i;i=i+512|0;g=f+256|0;h=f;j=Ka(d,3)|0;k=0;do{a[e+256+k>>0]=Ka(d,j)|0;k=k+1|0}while((k|0)!=64);k=(Ka(d,4)|0)+1|0;j=0;do{b[e+128+(j<<1)>>1]=Ka(d,k)|0;j=j+1|0}while((j|0)!=64);j=(Ka(d,4)|0)+1|0;k=0;do{b[e+(k<<1)>>1]=Ka(d,j)|0;k=k+1|0}while((k|0)!=64);k=Ka(d,9)|0;j=k+1|0;l=Ob(j<<6)|0;if(!l){m=-1;i=f;return m|0}if((k|0)>-1){n=0;do{o=0;do{a[l+(n<<6)+o>>0]=Ka(d,8)|0;o=o+1|0}while((o|0)!=64);n=n+1|0}while((n|0)<(j|0))}n=hb(k)|0;k=0;a:while(1){o=(k|0)/3|0;p=(k|0)%3|0;q=e+320+(o*36|0)+(p*12|0)|0;if((k|0)>0?(La(d)|0)==0:0){do if((k|0)>2)if(!(La(d)|0)){r=k+-1|0;s=(r|0)%3|0;t=(r|0)/3|0;break}else{s=p;t=o+-1|0;break}else{r=k+-1|0;s=(r|0)%3|0;t=(r|0)/3|0}while(0);r=e+320+(t*36|0)+(s*12|0)|0;c[q>>2]=c[r>>2];c[q+4>>2]=c[r+4>>2];c[q+8>>2]=c[r+8>>2]}else u=21;b:do if((u|0)==21){u=0;c[h>>2]=Ka(d,n)|0;r=0;v=0;while(1){w=(Ka(d,hb(62-r|0)|0)|0)+1|0;c[g+(v<<2)>>2]=w;x=w+r|0;w=Ka(d,n)|0;y=v+1|0;c[h+(y<<2)>>2]=w;if((x|0)<63){r=x;v=y}else{z=x;A=w;B=y;break}}if((z|0)>63){u=24;break a}c[q>>2]=B;v=B<<2;r=Ob(v)|0;c[e+320+(o*36|0)+(p*12|0)+4>>2]=r;if(!r){u=26;break a}Xb(r|0,g|0,v|0)|0;v=Ob((B<<6)+64|0)|0;if(!v){u=28;break a}c[e+320+(o*36|0)+(p*12|0)+8>>2]=v;if((A|0)<(j|0)){C=A;D=B}else{u=30;break a}while(1){r=v+(D<<6)|0;y=l+(C<<6)|0;w=r+64|0;do{a[r>>0]=a[y>>0]|0;r=r+1|0;y=y+1|0}while((r|0)<(w|0));if((D|0)<=0)break b;D=D+-1|0;C=c[h+(D<<2)>>2]|0;if((C|0)>=(j|0)){u=30;break a}}}while(0);k=k+1|0;if((k|0)>=6){u=34;break}}if((u|0)==24){Pb(l);m=-20;i=f;return m|0}else if((u|0)==26){Pb(l);m=-1;i=f;return m|0}else if((u|0)==28){Pb(l);m=-1;i=f;return m|0}else if((u|0)==30){Pb(l);m=-20;i=f;return m|0}else if((u|0)==34){Pb(l);m=0;i=f;return m|0}return 0}function Ua(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0;b=5;d=6;while(1){e=(b|0)/3|0;f=(b|0)%3|0;if((d|0)>1){g=d+-2|0;h=(g|0)/3|0;i=(g|0)%3|0;g=a+320+(e*36|0)+(f*12|0)+4|0;if((c[g>>2]|0)==(c[a+320+(h*36|0)+(i*12|0)+4>>2]|0))c[g>>2]=0;g=a+320+(e*36|0)+(f*12|0)+8|0;if((c[g>>2]|0)==(c[a+320+(h*36|0)+(i*12|0)+8>>2]|0))c[g>>2]=0}if((b|0)>2){g=a+356+(f*12|0)+4|0;if((c[g>>2]|0)==(c[a+320+(f*12|0)+4>>2]|0))c[g>>2]=0;g=a+356+(f*12|0)+8|0;if((c[g>>2]|0)==(c[a+320+(f*12|0)+8>>2]|0))c[g>>2]=0}Pb(c[a+320+(e*36|0)+(f*12|0)+4>>2]|0);Pb(c[a+320+(e*36|0)+(f*12|0)+8>>2]|0);if((b|0)>0){f=b;b=b+-1|0;d=f}else break}return}function Va(b,e,f,g,h,i){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;if((h|0)<=0)return;j=f<<1;k=f*3|0;l=f<<2;m=f*5|0;n=f*6|0;o=f*7|0;p=0;do{q=c[i+(c[g+(p<<2)>>2]<<2)>>2]|0;r=e+q|0;s=r;t=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;s=r+4|0;r=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;s=b+q|0;u=s;a[u>>0]=t;a[u+1>>0]=t>>8;a[u+2>>0]=t>>16;a[u+3>>0]=t>>24;t=s+4|0;a[t>>0]=r;a[t+1>>0]=r>>8;a[t+2>>0]=r>>16;a[t+3>>0]=r>>24;r=q+f|0;t=e+r|0;s=t;u=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;s=t+4|0;t=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;s=b+r|0;r=s;a[r>>0]=u;a[r+1>>0]=u>>8;a[r+2>>0]=u>>16;a[r+3>>0]=u>>24;u=s+4|0;a[u>>0]=t;a[u+1>>0]=t>>8;a[u+2>>0]=t>>16;a[u+3>>0]=t>>24;t=q+j|0;u=e+t|0;s=u;r=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;s=u+4|0;u=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;s=b+t|0;t=s;a[t>>0]=r;a[t+1>>0]=r>>8;a[t+2>>0]=r>>16;a[t+3>>0]=r>>24;r=s+4|0;a[r>>0]=u;a[r+1>>0]=u>>8;a[r+2>>0]=u>>16;a[r+3>>0]=u>>24;u=q+k|0;r=e+u|0;s=r;t=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;s=r+4|0;r=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;s=b+u|0;u=s;a[u>>0]=t;a[u+1>>0]=t>>8;a[u+2>>0]=t>>16;a[u+3>>0]=t>>24;t=s+4|0;a[t>>0]=r;a[t+1>>0]=r>>8;a[t+2>>0]=r>>16;a[t+3>>0]=r>>24;r=q+l|0;t=e+r|0;s=t;u=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;s=t+4|0;t=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;s=b+r|0;r=s;a[r>>0]=u;a[r+1>>0]=u>>8;a[r+2>>0]=u>>16;a[r+3>>0]=u>>24;u=s+4|0;a[u>>0]=t;a[u+1>>0]=t>>8;a[u+2>>0]=t>>16;a[u+3>>0]=t>>24;t=q+m|0;u=e+t|0;s=u;r=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;s=u+4|0;u=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;s=b+t|0;t=s;a[t>>0]=r;a[t+1>>0]=r>>8;a[t+2>>0]=r>>16;a[t+3>>0]=r>>24;r=s+4|0;a[r>>0]=u;a[r+1>>0]=u>>8;a[r+2>>0]=u>>16;a[r+3>>0]=u>>24;u=q+n|0;r=e+u|0;s=r;t=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;s=r+4|0;r=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;s=b+u|0;u=s;a[u>>0]=t;a[u+1>>0]=t>>8;a[u+2>>0]=t>>16;a[u+3>>0]=t>>24;t=s+4|0;a[t>>0]=r;a[t+1>>0]=r>>8;a[t+2>>0]=r>>16;a[t+3>>0]=r>>24;r=q+o|0;q=e+r|0;t=q;s=d[t>>0]|d[t+1>>0]<<8|d[t+2>>0]<<16|d[t+3>>0]<<24;t=q+4|0;q=d[t>>0]|d[t+1>>0]<<8|d[t+2>>0]<<16|d[t+3>>0]<<24;t=b+r|0;r=t;a[r>>0]=s;a[r+1>>0]=s>>8;a[r+2>>0]=s>>16;a[r+3>>0]=s>>24;s=t+4|0;a[s>>0]=q;a[s+1>>0]=q>>8;a[s+2>>0]=q>>16;a[s+3>>0]=q>>24;p=p+1|0}while((p|0)!=(h|0));return}function Wa(c,d,e){c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=c;c=0;while(1){g=c<<3;h=b[e+(g<<1)>>1]|0;i=(h<<16>>16)+128|0;a[f>>0]=h<<16>>16>-129?((i|0)>255?-1:i&255):0;i=b[e+((g|1)<<1)>>1]|0;h=(i<<16>>16)+128|0;a[f+1>>0]=i<<16>>16>-129?((h|0)>255?-1:h&255):0;h=b[e+((g|2)<<1)>>1]|0;i=(h<<16>>16)+128|0;a[f+2>>0]=h<<16>>16>-129?((i|0)>255?-1:i&255):0;i=b[e+((g|3)<<1)>>1]|0;h=(i<<16>>16)+128|0;a[f+3>>0]=i<<16>>16>-129?((h|0)>255?-1:h&255):0;h=b[e+((g|4)<<1)>>1]|0;i=(h<<16>>16)+128|0;a[f+4>>0]=h<<16>>16>-129?((i|0)>255?-1:i&255):0;i=b[e+((g|5)<<1)>>1]|0;h=(i<<16>>16)+128|0;a[f+5>>0]=i<<16>>16>-129?((h|0)>255?-1:h&255):0;h=b[e+((g|6)<<1)>>1]|0;i=(h<<16>>16)+128|0;a[f+6>>0]=h<<16>>16>-129?((i|0)>255?-1:i&255):0;i=b[e+((g|7)<<1)>>1]|0;g=(i<<16>>16)+128|0;a[f+7>>0]=i<<16>>16>-129?((g|0)>255?-1:g&255):0;c=c+1|0;if((c|0)==8)break;else f=f+d|0}return}function Xa(c,e,f,g){c=c|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0;h=e;e=c;c=0;while(1){i=c<<3;j=(d[h>>0]|0)+(b[g+(i<<1)>>1]|0)|0;a[e>>0]=(j>>>31)+255&((j|0)>255?255:j);j=(d[h+1>>0]|0)+(b[g+((i|1)<<1)>>1]|0)|0;a[e+1>>0]=(j>>>31)+255&((j|0)>255?255:j);j=(d[h+2>>0]|0)+(b[g+((i|2)<<1)>>1]|0)|0;a[e+2>>0]=(j>>>31)+255&((j|0)>255?255:j);j=(d[h+3>>0]|0)+(b[g+((i|3)<<1)>>1]|0)|0;a[e+3>>0]=(j>>>31)+255&((j|0)>255?255:j);j=(d[h+4>>0]|0)+(b[g+((i|4)<<1)>>1]|0)|0;a[e+4>>0]=(j>>>31)+255&((j|0)>255?255:j);j=(d[h+5>>0]|0)+(b[g+((i|5)<<1)>>1]|0)|0;a[e+5>>0]=(j>>>31)+255&((j|0)>255?255:j);j=(d[h+6>>0]|0)+(b[g+((i|6)<<1)>>1]|0)|0;a[e+6>>0]=(j>>>31)+255&((j|0)>255?255:j);j=(d[h+7>>0]|0)+(b[g+((i|7)<<1)>>1]|0)|0;a[e+7>>0]=(j>>>31)+255&((j|0)>255?255:j);c=c+1|0;if((c|0)==8)break;else{h=h+f|0;e=e+f|0}}return}function Ya(c,e,f,g,h){c=c|0;e=e|0;f=f|0;g=g|0;h=h|0;var i=0,j=0,k=0,l=0;i=e;e=f;f=c;c=0;while(1){j=c<<3;k=0;do{l=(((d[e+k>>0]|0)+(d[i+k>>0]|0)|0)>>>1)+(b[h+(k+j<<1)>>1]|0)|0;a[f+k>>0]=(l>>>31)+255&((l|0)>255?255:l);k=k+1|0}while((k|0)!=8);c=c+1|0;if((c|0)==8)break;else{i=i+g|0;e=e+g|0;f=f+g|0}}return}function Za(b,c){b=b|0;c=c|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;e=0;f=0;g=0;h=0;a:while(1){i=f;while(1){j=La(b)|0;if((Ma(b)|0)<0){k=-20;l=12;break a}if(j){m=i;break}if((i|0)>31){k=-20;l=12;break a}else i=i+1|0}if((g|0)>31){k=-20;l=12;break}g=g+1|0;i=Ka(b,5)|0;j=d[1272+i>>0]|0;n=1<<j;o=j+m&255;j=h+2|0;p=(n|0)<1?~n:-2;q=n;r=h;s=d[1304+i>>0]|0;while(1){a[c+(r<<1)>>0]=s;a[c+(r<<1)+1>>0]=o;if((q|0)>1){q=q+-1|0;r=r+1|0;s=s+1|0}else break}s=j+n+p|0;r=-2147483648>>>(m+-1|0);if((m|0)<1|(r&e|0)==0){t=e;u=r;v=m}else{q=e;o=r;r=m;while(1){i=o^q;w=o<<1;x=r+-1|0;if((r|0)<2|(w&i|0)==0){t=i;u=w;v=x;break}else{q=i;o=w;r=x}}}if((v|0)<1){k=s;l=12;break}else{e=u|t;f=v;h=s}}if((l|0)==12)return k|0;return 0}function _a(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;d=i;i=i+512|0;e=d;f=0;while(1){g=Za(a,e)|0;if((g|0)<0){h=g;break}j=wb(0,e,g)|0;if(j>>>0>32767){h=-23;break}k=Ob(j<<1)|0;if(!k){h=-1;break}wb(k,e,g)|0;c[b+(f<<2)>>2]=k;f=f+1|0;if((f|0)>=80){l=0;m=7;break}}if((m|0)==7){i=d;return l|0}l=h;i=d;return l|0}function $a(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;d=0;while(1){e=b+(d<<2)|0;f=(xb(c[e>>2]|0,0)|0)<<1;g=Ob(f)|0;c[a+(d<<2)>>2]=g;if(!g){h=d;break}Xb(g|0,c[e>>2]|0,f|0)|0;d=d+1|0;if((d|0)>=80){i=0;j=6;break}}if((j|0)==6)return i|0;if((h|0)>0)k=h;else{i=-1;return i|0}do{h=k;k=k+-1|0;Pb(c[a+(k<<2)>>2]|0)}while((h|0)>1);i=-1;return i|0}function ab(a){a=a|0;var b=0;b=0;do{Pb(c[a+(b<<2)>>2]|0);b=b+1|0}while((b|0)!=80);return}function bb(a,e){a=a|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0;f=a+4|0;g=a+8|0;h=c[a>>2]|0;i=a+12|0;a=c[i>>2]|0;j=0;k=c[f>>2]|0;l=c[g>>2]|0;while(1){m=b[e+(j<<1)>>1]|0;if((m|0)>(a|0)){n=k;o=32-a|0;p=l;while(1){if(n>>>0>=h>>>0){q=n;r=-1073741824;s=p;break}t=o+-8|0;u=n+1|0;v=d[n>>0]<<t|p;if(t>>>0>7){n=u;o=t;p=v}else{q=u;r=t;s=v;break}}w=32-r|0;x=q;y=s}else{w=a;x=k;y=l}p=b[e+(j+1+(y>>>(32-m|0))<<1)>>1]|0;o=p<<16>>16;if(p<<16>>16<1){z=o;A=w;B=x;C=y;break}a=w-m|0;j=o;k=x;l=y<<m}y=0-z|0;z=y>>8;c[f>>2]=B;c[g>>2]=C<<z;c[i>>2]=A-z;return y&255|0}function cb(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;e=i;i=i+128|0;f=e;if((d|0)<4){g=c+2|0;h=(b[c>>1]|0)*46341>>16;j=b[g>>1]|0;k=j*12785>>16;l=j*64277>>16;j=k*46341>>16;m=l*46341>>16;n=m+j|0;o=m-j|0;b[f>>1]=l+h;b[f+16>>1]=n+h;b[f+32>>1]=o+h;b[f+48>>1]=k+h;b[f+64>>1]=h-k;b[f+80>>1]=h-o;b[f+96>>1]=h-n;b[f+112>>1]=h-l;l=c+16|0;h=((b[l>>1]|0)*46341|0)>>>16&65535;b[f+114>>1]=h;b[f+98>>1]=h;b[f+82>>1]=h;b[f+66>>1]=h;b[f+50>>1]=h;b[f+34>>1]=h;b[f+18>>1]=h;b[f+2>>1]=h;h=0;do{n=h<<3;o=(b[f+(n<<1)>>1]|0)*46341>>16;k=b[f+((n|1)<<1)>>1]|0;n=k*12785>>16;j=k*64277>>16;k=n*46341>>16;m=j*46341>>16;p=m+k|0;q=m-k|0;b[a+(h<<1)>>1]=j+o;b[a+(h+8<<1)>>1]=p+o;b[a+(h+16<<1)>>1]=q+o;b[a+(h+24<<1)>>1]=n+o;b[a+(h+32<<1)>>1]=o-n;b[a+(h+40<<1)>>1]=o-q;b[a+(h+48<<1)>>1]=o-p;b[a+(h+56<<1)>>1]=o-j;h=h+1|0}while((h|0)!=8);r=0;do{h=a+(r<<1)|0;b[h>>1]=((b[h>>1]|0)+8|0)>>>4;r=r+1|0}while((r|0)!=64);b[l>>1]=0;b[g>>1]=0;b[c>>1]=0;i=e;return}if((d|0)>=11){yb(f,c);yb(f+2|0,c+16|0);yb(f+4|0,c+32|0);yb(f+6|0,c+48|0);yb(f+8|0,c+64|0);yb(f+10|0,c+80|0);yb(f+12|0,c+96|0);yb(f+14|0,c+112|0);yb(a,f);yb(a+2|0,f+16|0);yb(a+4|0,f+32|0);yb(a+6|0,f+48|0);yb(a+8|0,f+64|0);yb(a+10|0,f+80|0);yb(a+12|0,f+96|0);yb(a+14|0,f+112|0);d=0;do{g=a+(d<<1)|0;b[g>>1]=((b[g>>1]|0)+8|0)>>>4;d=d+1|0}while((d|0)!=64);d=c;g=d+128|0;do{b[d>>1]=0;d=d+2|0}while((d|0)<(g|0));i=e;return}d=(b[c>>1]|0)*46341>>16;g=b[c+4>>1]|0;l=g*25080>>16;r=g*60547>>16;g=b[c+2>>1]|0;h=g*12785>>16;j=b[c+6>>1]|0;o=j*36410>>16;p=j*54491>>16;j=g*64277>>16;g=h-o|0;q=(o+h<<16>>16)*46341>>16;h=p+j|0;o=(j-p<<16>>16)*46341>>16;p=l+d|0;j=d-l|0;l=r+d|0;n=d-r|0;r=o+q|0;d=o-q|0;b[f>>1]=h+l;b[f+16>>1]=r+p;b[f+32>>1]=d+j;b[f+48>>1]=g+n;b[f+64>>1]=n-g;b[f+80>>1]=j-d;b[f+96>>1]=p-r;b[f+112>>1]=l-h;h=c+16|0;l=c+18|0;r=c+20|0;p=(b[h>>1]|0)*46341>>16;d=b[r>>1]|0;j=d*25080>>16;g=d*60547>>16;d=b[l>>1]|0;n=d*12785>>16;q=d*64277>>16;d=n*46341>>16;o=q*46341>>16;k=j+p|0;m=p-j|0;j=g+p|0;s=p-g|0;g=o+d|0;p=o-d|0;b[f+2>>1]=j+q;b[f+18>>1]=g+k;b[f+34>>1]=p+m;b[f+50>>1]=s+n;b[f+66>>1]=s-n;b[f+82>>1]=m-p;b[f+98>>1]=k-g;b[f+114>>1]=j-q;q=c+32|0;j=c+34|0;g=(b[q>>1]|0)*46341>>16;k=b[j>>1]|0;p=k*12785>>16;m=k*64277>>16;k=p*46341>>16;n=m*46341>>16;s=n+k|0;d=n-k|0;b[f+4>>1]=m+g;b[f+20>>1]=s+g;b[f+36>>1]=d+g;b[f+52>>1]=p+g;b[f+68>>1]=g-p;b[f+84>>1]=g-d;b[f+100>>1]=g-s;b[f+116>>1]=g-m;m=c+48|0;g=((b[m>>1]|0)*46341|0)>>>16&65535;b[f+118>>1]=g;b[f+102>>1]=g;b[f+86>>1]=g;b[f+70>>1]=g;b[f+54>>1]=g;b[f+38>>1]=g;b[f+22>>1]=g;b[f+6>>1]=g;g=0;do{s=g<<3;d=(b[f+(s<<1)>>1]|0)*46341>>16;p=b[f+((s|2)<<1)>>1]|0;k=p*25080>>16;n=p*60547>>16;p=b[f+((s|1)<<1)>>1]|0;o=p*12785>>16;t=b[f+((s|3)<<1)>>1]|0;s=t*36410>>16;u=t*54491>>16;t=p*64277>>16;p=o-s|0;v=(s+o<<16>>16)*46341>>16;o=u+t|0;s=(t-u<<16>>16)*46341>>16;u=k+d|0;t=d-k|0;k=n+d|0;w=d-n|0;n=s+v|0;d=s-v|0;b[a+(g<<1)>>1]=o+k;b[a+(g+8<<1)>>1]=n+u;b[a+(g+16<<1)>>1]=d+t;b[a+(g+24<<1)>>1]=p+w;b[a+(g+32<<1)>>1]=w-p;b[a+(g+40<<1)>>1]=t-d;b[a+(g+48<<1)>>1]=u-n;b[a+(g+56<<1)>>1]=k-o;g=g+1|0}while((g|0)!=8);x=0;do{g=a+(x<<1)|0;b[g>>1]=((b[g>>1]|0)+8|0)>>>4;x=x+1|0}while((x|0)!=64);b[m>>1]=0;b[j>>1]=0;b[q>>1]=0;b[r>>1]=0;b[l>>1]=0;b[h>>1]=0;h=c;c=h;b[c>>1]=0;b[c+2>>1]=0>>>16;c=h+4|0;b[c>>1]=0;b[c+2>>1]=0>>>16;i=e;return}function db(b){b=b|0;var d=0,e=0;d=b;e=d+60|0;do{c[d>>2]=0;d=d+4|0}while((d|0)<(e|0));a[b>>0]=3;a[b+1>>0]=2;a[b+2>>0]=1;c[b+60>>2]=6;return}function eb(a){a=a|0;var b=0;b=a;a=b+64|0;do{c[b>>2]=0;b=b+4|0}while((b|0)<(a|0));return}function fb(a){a=a|0;c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0;return}function gb(a){a=a|0;var b=0,d=0;if(!a)return;b=a+8|0;if((c[b>>2]|0)>0){d=0;do{Pb(c[(c[a>>2]|0)+(d<<2)>>2]|0);d=d+1|0}while((d|0)<(c[b>>2]|0))}Pb(c[a>>2]|0);Pb(c[a+4>>2]|0);Pb(c[a+12>>2]|0);c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0;return}function hb(a){a=a|0;var b=0,c=0,d=0;if(!a)b=0;else{c=a;a=0;while(1){c=c>>>1;d=a+1|0;if(!c){b=d;break}else a=d}}return b|0}function ib(b,c){b=b|0;c=c|0;var d=0,e=0,f=0;d=c+-1|0;if(b>>>0>~c>>>0|(d&(c|-256)|0)!=0){e=0;return e|0}f=Ob(c+b|0)|0;if(!f){e=0;return e|0}b=f+-1&d;a[f+b>>0]=b;e=f+(b+1)|0;return e|0}function jb(a){a=a|0;if(!a)return;Pb(a+~(d[a+-1>>0]|0)|0);return}function kb(a,b){a=a|0;b=b|0;var d=0,e=0;c[a>>2]=c[b>>2];d=c[b+4>>2]|0;c[a+4>>2]=d;e=0-(c[b+8>>2]|0)|0;c[a+8>>2]=e;c[a+12>>2]=(c[b+12>>2]|0)+(_(1-d|0,e)|0);c[a+16>>2]=c[b+16>>2];e=c[b+20>>2]|0;c[a+20>>2]=e;d=0-(c[b+24>>2]|0)|0;c[a+24>>2]=d;c[a+28>>2]=(c[b+28>>2]|0)+(_(1-e|0,d)|0);c[a+32>>2]=c[b+32>>2];d=c[b+36>>2]|0;c[a+36>>2]=d;e=0-(c[b+40>>2]|0)|0;c[a+40>>2]=e;c[a+44>>2]=(c[b+44>>2]|0)+(_(1-d|0,e)|0);return}function lb(f,g,h){f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0;j=i;i=i+64|0;k=j;l=(g|0)==0;m=0;while(1){n=1336+(m<<2)|0;o=1344+(m<<2)|0;p=0;while(1){q=h+320+(m*36|0)+(p*12|0)|0;r=c[q>>2]|0;if((r|0)>=0){s=h+320+(m*36|0)+(p*12|0)+8|0;t=c[n>>2]|0;u=c[o>>2]|0;v=h+320+(m*36|0)+(p*12|0)+4|0;w=r;r=0;x=0;while(1){y=k;z=(c[s>>2]|0)+(x<<6)|0;A=y+64|0;do{a[y>>0]=a[z>>0]|0;y=y+1|0;z=z+1|0}while((y|0)<(A|0));if((x|0)==(w|0))B=r+1|0;else B=(c[(c[v>>2]|0)+(x<<2)>>2]|0)+r|0;z=x;x=x+1|0;a:do if(l){y=r;b:while(1){A=(((_(d[k>>0]|0,e[h+(y<<1)>>1]|0)|0)>>>0)/100|0)<<2;C=A>>>0>4096?4096:A;A=f+(y*24|0)+(p<<3)+(m<<2)|0;D=c[A>>2]|0;b[D>>1]=t-(t>>>0<C>>>0?t-C|0:0);C=h+128+(y<<1)|0;E=1;do{F=(((_(d[k+(d[8+E>>0]|0)>>0]|0,e[C>>1]|0)|0)>>>0)/100|0)<<2;G=F>>>0>4096?4096:F;b[D+(E<<1)>>1]=u-(u>>>0<G>>>0?u-G|0:0);E=E+1|0}while((E|0)!=64);H=0;c:while(1){E=(H|0)<(m|0);C=E?3:p;if((C|0)>0){G=0;do{F=c[f+(y*24|0)+(G<<3)+(H<<2)>>2]|0;if(!(Nb(D,F,128)|0)){I=F;J=13;break c}G=G+1|0}while((G|0)<(C|0))}if(E)H=H+1|0;else break}if((J|0)==13){J=0;c[A>>2]=I}D=y+1|0;if((B|0)<=(D|0)){K=D;L=w;break a}C=B-D|0;G=c[s>>2]|0;F=D-r|0;M=c[(c[v>>2]|0)+(z<<2)>>2]|0;N=M<<1;O=0;while(1){P=_(d[G+(z<<6)+O>>0]|0,C)|0;a[k+O>>0]=(((_(d[G+(x<<6)+O>>0]|0,F)|0)+P<<1)+M|0)/(N|0)|0;P=O+1|0;if((P|0)==64){y=D;continue b}else O=P}}}else{y=r;d:while(1){O=_(d[k>>0]|0,e[h+(y<<1)>>1]|0)|0;c[g+(y<<2)>>2]=(O>>>0)/160|0;D=((O>>>0)/100|0)<<2;O=D>>>0>4096?4096:D;D=f+(y*24|0)+(p<<3)+(m<<2)|0;N=c[D>>2]|0;b[N>>1]=t-(t>>>0<O>>>0?t-O|0:0);O=h+128+(y<<1)|0;M=1;do{F=(((_(d[k+(d[8+M>>0]|0)>>0]|0,e[O>>1]|0)|0)>>>0)/100|0)<<2;G=F>>>0>4096?4096:F;b[N+(M<<1)>>1]=u-(u>>>0<G>>>0?u-G|0:0);M=M+1|0}while((M|0)!=64);Q=0;e:while(1){M=(Q|0)<(m|0);O=M?3:p;if((O|0)>0){G=0;do{F=c[f+(y*24|0)+(G<<3)+(Q<<2)>>2]|0;if(!(Nb(N,F,128)|0)){R=F;J=25;break e}G=G+1|0}while((G|0)<(O|0))}if(M)Q=Q+1|0;else break}if((J|0)==25){J=0;c[D>>2]=R}N=y+1|0;if((B|0)<=(N|0)){S=N;break}O=B-N|0;G=c[s>>2]|0;E=N-r|0;F=c[(c[v>>2]|0)+(z<<2)>>2]|0;C=F<<1;A=0;while(1){P=_(d[G+(z<<6)+A>>0]|0,O)|0;a[k+A>>0]=(((_(d[G+(x<<6)+A>>0]|0,E)|0)+P<<1)+F|0)/(C|0)|0;P=A+1|0;if((P|0)==64){y=N;continue d}else A=P}}K=S;L=c[q>>2]|0}while(0);if((z|0)>=(L|0))break;else{w=L;r=K}}}p=p+1|0;if((p|0)==3)break}m=m+1|0;if((m|0)==2)break}i=j;return}function mb(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,fb=0,gb=0,hb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0;if(!e){g=-1;return g|0}h=c[e+4>>2]|0;if(h&15){g=-10;return g|0}i=e+8|0;j=c[i>>2]|0;if((j+-1|0)>>>0>1048574|((h+-1|0)>>>0>1048574|(j&15|0)!=0)){g=-10;return g|0}k=c[e+20>>2]|0;if(((c[e+12>>2]|0)+k|0)>>>0>h>>>0){g=-10;return g|0}h=e+24|0;l=c[h>>2]|0;m=e+16|0;n=c[m>>2]|0;if(k>>>0>255|(n+l|0)>>>0>j>>>0){g=-10;return g|0}if((j-l-n|0)>>>0>255){g=-10;return g|0}if((c[e+44>>2]|0)>>>0>2){g=-10;return g|0}if((c[e+48>>2]|0)>>>0>3){g=-10;return g|0}if(!(c[e+28>>2]|0)){g=-10;return g|0}if(!(c[e+32>>2]|0)){g=-10;return g|0}Ub(b|0,0,51632)|0;n=b;l=e;j=n+64|0;do{c[n>>2]=c[l>>2];n=n+4|0;l=l+4|0}while((n|0)<(j|0));k=b+24|0;c[k>>2]=(c[i>>2]|0)-(c[m>>2]|0)-(c[h>>2]|0);a[b+872>>0]=-1;c[b+68>>2]=0;c[b+64>>2]=8;h=b+4|0;m=(c[h>>2]|0)>>>3;i=b+8|0;o=(c[i>>2]|0)>>>3;p=b+48|0;q=c[p>>2]|0;r=q&1^1;s=q>>>1&1^1;q=(r+m|0)>>>r;r=(s+o|0)>>>s;s=_(o,m)|0;t=_(r,q)|0;u=t<<1;v=u+s|0;w=(m+3|0)>>>2;x=(o+3|0)>>>2;y=q+3>>2;z=r+3>>2;A=_(x,w)|0;B=_(z,y)|0;D=B<<1;E=D+A|0;F=A<<2;do if(!((t|0)<0|(u|0)<(t|0))?(A&1073741823|0)==(A|0)&((E>>>0<A>>>0|(D>>>0<B>>>0?1:((A>>>0)/(w>>>0)|0|0)!=(x|0)))^1):0){G=b+72|0;c[G>>2]=m;H=b+76|0;c[H>>2]=o;I=b+80|0;c[I>>2]=0;J=b+84|0;c[J>>2]=s;c[b+88>>2]=w;c[b+92>>2]=x;c[b+96>>2]=0;c[b+100>>2]=A;K=b+136|0;c[K>>2]=q;L=b+104|0;c[L>>2]=q;c[b+140>>2]=r;c[b+108>>2]=r;M=b+112|0;c[M>>2]=s;N=b+144|0;c[N>>2]=t+s;O=b+148|0;c[O>>2]=t;P=b+116|0;c[P>>2]=t;c[b+152>>2]=y;c[b+120>>2]=y;c[b+156>>2]=z;c[b+124>>2]=z;c[b+128>>2]=A;c[b+160>>2]=B+A;c[b+164>>2]=B;c[b+132>>2]=B;Q=b+180|0;c[Q>>2]=v;R=Qb(v,4)|0;S=b+168|0;c[S>>2]=R;T=Ob(v<<1)|0;c[b+176>>2]=T;c[b+192>>2]=E;U=Ob(E<<6)|0;V=b+184|0;c[V>>2]=U;W=Qb(E,1)|0;X=b+188|0;c[X>>2]=W;c[b+204>>2]=w<<1;c[b+208>>2]=x<<1;c[b+212>>2]=F;Y=Qb(F,48)|0;Z=b+196|0;c[Z>>2]=Y;$=Qb(F,1)|0;aa=b+200|0;c[aa>>2]=$;ba=Ob(v<<2)|0;c[b+216>>2]=ba;if(!((R|0)==0|(T|0)==0|(U|0)==0|(W|0)==0|(Y|0)==0)?!(($|0)==0|(ba|0)==0):0){ba=o;$=W;W=U;U=0;Y=0;T=0;while(1){R=c[b+72+(T<<5)>>2]|0;ca=R<<2;da=0;ea=0;fa=Y;while(1){ga=ba-ea|0;if((ga|0)<=4)if((ga|0)<1)break;else ha=ga;else ha=4;ga=da;ia=0;while(1){ja=R-ia|0;if((ja|0)<=4)if((ja|0)<1){ka=ga;break}else la=ja;else la=4;ja=ga+U|0;n=W+(ja<<6)|0;j=n+64|0;do{c[n>>2]=-1;n=n+4|0}while((n|0)<(j|0));ma=0;na=ia+fa|0;while(1){oa=0;do{c[W+(ja<<6)+(c[1352+(ma<<5)+(oa<<3)>>2]<<4)+(c[1352+(ma<<5)+(oa<<3)+4>>2]<<2)>>2]=oa+na;oa=oa+1|0}while((oa|0)!=(la|0));ma=ma+1|0;if((ma|0)==(ha|0))break;else na=na+R|0}na=$+ja|0;ma=a[na>>0]|0;oa=ma&-61;pa=(((ma&255)>>>2&255|(c[W+(ja<<6)>>2]|0)>>>31^1)&255)<<2&60|oa;a[na>>0]=pa;ma=(((pa&255)>>>2&255|(c[W+(ja<<6)+16>>2]|0)>>>31<<1^2)&255)<<2&60|oa;a[na>>0]=ma;pa=(((ma&255)>>>2&255|(c[W+(ja<<6)+32>>2]|0)>>>31<<2^4)&255)<<2&60|oa;a[na>>0]=pa;a[na>>0]=(((pa&255)>>>2&255|(c[W+(ja<<6)+56>>2]|0)>>>31<<3^8)&255)<<2&60|oa;ga=ga+1|0;ia=ia+4|0}da=ka;ea=ea+4|0;fa=fa+ca|0}ca=T+1|0;if((ca|0)==3)break;ba=c[b+72+(ca<<5)+4>>2]|0;$=c[X>>2]|0;W=c[V>>2]|0;U=c[b+72+(ca<<5)+24>>2]|0;Y=c[b+72+(ca<<5)+8>>2]|0;T=ca}T=c[Z>>2]|0;Y=c[aa>>2]|0;U=c[1480+(c[p>>2]<<2)>>2]|0;V=c[H>>2]|0;if((V|0)>0){W=c[G>>2]|0;X=V;V=0;$=0;while(1){if((W|0)>0){ba=V;ca=0;while(1){fa=ba<<2;ea=ca|1;da=ca|2;R=ca|3;ia=0;do{ga=ia<<1|$;oa=ga|1;pa=d[136+(ia<<1)>>0]|fa;na=T+(pa*48|0)|0;n=na;j=n+48|0;do{c[n>>2]=-1;n=n+4|0}while((n|0)<(j|0));ja=c[G>>2]|0;do if((ca|0)<(ja|0)){if((ga|0)>=(c[H>>2]|0)){qa=36;break}c[na>>2]=(_(ja,ga)|0)+ca;c[T+(pa*48|0)+4>>2]=(_(c[G>>2]|0,ga)|0)+ea;c[T+(pa*48|0)+8>>2]=(_(c[G>>2]|0,oa)|0)+ca;c[T+(pa*48|0)+12>>2]=(_(c[G>>2]|0,oa)|0)+ea;za[U&7](na,G,ca,ga)}else qa=36;while(0);if((qa|0)==36){qa=0;a[Y+pa>>0]=-1}na=d[136+(ia<<1)+1>>0]|fa;ja=T+(na*48|0)|0;n=ja;j=n+48|0;do{c[n>>2]=-1;n=n+4|0}while((n|0)<(j|0));pa=c[G>>2]|0;do if((da|0)<(pa|0)){if((ga|0)>=(c[H>>2]|0)){qa=43;break}c[ja>>2]=(_(pa,ga)|0)+da;c[T+(na*48|0)+4>>2]=(_(c[G>>2]|0,ga)|0)+R;c[T+(na*48|0)+8>>2]=(_(c[G>>2]|0,oa)|0)+da;c[T+(na*48|0)+12>>2]=(_(c[G>>2]|0,oa)|0)+R;za[U&7](ja,G,da,ga)}else qa=43;while(0);if((qa|0)==43){qa=0;a[Y+na>>0]=-1}ia=ia+1|0}while((ia|0)!=2);ca=ca+4|0;ia=ba+1|0;da=c[G>>2]|0;if((ca|0)>=(da|0)){ra=ia;sa=da;break}else ba=ia}ta=c[H>>2]|0;ua=sa;va=ra}else{ta=X;ua=W;va=V}$=$+4|0;if(($|0)>=(ta|0))break;else{W=ua;X=ta;V=va}}}V=b+588|0;c[V>>2]=0;X=c[S>>2]|0;W=b+20|0;$=b+12|0;H=b+16|0;G=X;Y=0;U=X;while(1){X=c[W>>2]|0;T=(c[$>>2]|0)+X|0;aa=c[k>>2]|0;Z=(c[H>>2]|0)+aa|0;do if((Y|0)>0){ba=c[p>>2]|0;if(!(ba&1)){wa=X>>1;xa=T+1>>1}else{wa=X;xa=T}if(ba&2){ya=wa;Aa=xa;Ba=aa;Ca=Z;break}ya=wa;Aa=xa;Ba=aa>>1;Ca=Z+1>>1}else{ya=X;Aa=T;Ba=aa;Ca=Z}while(0);U=U+(c[b+72+(Y<<5)+12>>2]<<2)|0;if(G>>>0<U>>>0){Z=b+72+(Y<<5)|0;aa=(ya|0)<(Aa|0);T=(Ba|0)<(Ca|0);X=G;ba=0;while(1){ca=c[Z>>2]|0;ia=X+(ca<<2)|0;if((ca|0)>0){ca=ba+8|0;da=(ca|0)>(Ba|0);R=(Ca|0)>(ba|0);fa=(ba|0)<(Ba|0)&da;ea=R&(Ca|0)<(ca|0);ga=X+4|0;ja=(ia>>>0>ga>>>0?ia:ga)+~X|0;ga=T&(aa&(R&da))^1;da=X;R=0;do{oa=R;R=R+8|0;do if((Aa|0)<=(oa|0)|(R|0)<=(ya|0)|ga)c[da>>2]=c[da>>2]|2;else{pa=(oa|0)<(ya|0);if(!(ea|(fa|(pa|(Aa|0)<(R|0))))){c[da>>2]=c[da>>2]|63488;break}ma=oa|1;Da=oa|2;Ea=oa|3;Fa=oa|4;Ga=oa|5;Ha=oa|6;Ia=oa|7;Ja=(ma|0)>=(Aa|0)|(ma|0)<(ya|0);ma=(Da|0)>=(Aa|0)|(Da|0)<(ya|0);Da=(Ea|0)>=(Aa|0)|(Ea|0)<(ya|0);Ea=(Fa|0)>=(Aa|0)|(Fa|0)<(ya|0);Fa=(Ga|0)>=(Aa|0)|(Ga|0)<(ya|0);Ga=(Ha|0)>=(Aa|0)|(Ha|0)<(ya|0);Ha=(Ia|0)>=(Aa|0)|(Ia|0)<(ya|0);Ia=0;Ka=0;La=0;Ma=0;while(1){Na=La+ba|0;Oa=La<<3;Pa=(Na|0)>=(Ca|0)|(Na|0)<(Ba|0);if(pa|Pa){Qa=Ia;Ra=Ka;Sa=Ma}else{Na=Vb(1,0,Oa|0)|0;Qa=Na|Ia;Ra=C|Ka;Sa=Ma+1|0}if(Ja|Pa){Ta=Qa;Ua=Ra;Va=Sa}else{Na=Vb(1,0,Oa|1|0)|0;Ta=Qa|Na;Ua=Ra|C;Va=Sa+1|0}if(ma|Pa){Wa=Ta;Xa=Ua;Ya=Va}else{Na=Vb(1,0,Oa|2|0)|0;Wa=Ta|Na;Xa=Ua|C;Ya=Va+1|0}if(Da|Pa){Za=Wa;_a=Xa;$a=Ya}else{Na=Vb(1,0,Oa|3|0)|0;Za=Wa|Na;_a=Xa|C;$a=Ya+1|0}if(Ea|Pa){ab=Za;bb=_a;cb=$a}else{Na=Vb(1,0,Oa|4|0)|0;ab=Za|Na;bb=_a|C;cb=$a+1|0}if(Fa|Pa){db=ab;eb=bb;fb=cb}else{Na=Vb(1,0,Oa|5|0)|0;db=ab|Na;eb=bb|C;fb=cb+1|0}if(Ga|Pa){gb=db;hb=eb;lb=fb}else{Na=Vb(1,0,Oa|6|0)|0;gb=db|Na;hb=eb|C;lb=fb+1|0}if(Ha|Pa){mb=gb;nb=hb;ob=lb}else{Pa=Vb(1,0,Oa|7|0)|0;mb=gb|Pa;nb=hb|C;ob=lb+1|0}La=La+1|0;if((La|0)==8){pb=mb;qb=nb;rb=ob;break}else{Ia=mb;Ka=nb;Ma=ob}}Ma=c[V>>2]|0;a:do if((Ma|0)>0){Ka=0;while(1){Ia=b+592+(Ka<<4)|0;if((c[Ia>>2]|0)==(pb|0)?(c[Ia+4>>2]|0)==(qb|0):0){sb=Ka;break a}Ia=Ka+1|0;if((Ia|0)<(Ma|0))Ka=Ia;else{tb=Ia;qa=65;break}}}else{tb=0;qa=65}while(0);if((qa|0)==65){qa=0;c[V>>2]=Ma+1;Ka=b+592+(tb<<4)|0;c[Ka>>2]=pb;c[Ka+4>>2]=qb;c[b+592+(tb<<4)+8>>2]=rb;sb=tb}c[da>>2]=c[da>>2]&-63489|sb<<11&63488}while(0);da=da+4|0}while(da>>>0<ia>>>0);ub=ca;vb=X+((ja>>>2)+1<<2)|0}else{ub=ba+8|0;vb=X}if(vb>>>0<U>>>0){X=vb;ba=ub}else{wb=vb;break}}}else wb=G;Y=Y+1|0;if((Y|0)==3)break;else G=wb}if((f+-3|0)>>>0<=3){G=c[p>>2]|0;Y=G&1^1;U=G>>>1&1^1;G=c[h>>2]|0;V=G+32|0;H=(c[i>>2]|0)+32|0;$=(V>>Y)+15&-16;W=_(H,V)|0;S=_($,H>>U)|0;ba=(V<<4)+16|0;X=(_($,16>>>U)|0)+(16>>>Y)|0;aa=0-X&15;T=S<<1;Z=W+16+T|0;ia=_(Z,f)|0;if(!(Z>>>0<W>>>0|((T|16)>>>0<S>>>0?1:((W>>>0)/(V>>>0)|0|0)!=(H|0)))?((ia>>>0)/(f>>>0)|0|0)==(Z|0):0){Z=ib(ia,16)|0;ia=Ob(c[Q>>2]<<2)|0;c[b+172>>2]=ia;if((Z|0)==0|(ia|0)==0){Pb(ia);jb(Z);xb=-1;break}H=c[h>>2]|0;T=b+236|0;c[T>>2]=H;da=c[i>>2]|0;c[b+240>>2]=da;R=b+244|0;c[R>>2]=V;V=H>>>Y;c[b+268>>2]=V;c[b+252>>2]=V;V=da>>>U;c[b+272>>2]=V;c[b+256>>2]=V;V=b+276|0;c[V>>2]=$;U=b+260|0;c[U>>2]=$;if((f|0)>1){da=1;do{n=b+236+(da*48|0)|0;l=T;j=n+48|0;do{c[n>>2]=c[l>>2];n=n+4|0;l=l+4|0}while((n|0)<(j|0));da=da+1|0}while((da|0)!=(f|0))}c[b+572>>2]=Z;if((f|0)>0){da=aa+W|0;T=da+X|0;Q=da+S|0;da=Q+X|0;Y=S+16-aa+Q|0;Q=Z;H=0;while(1){fa=b+236+(H*48|0)|0;c[b+236+(H*48|0)+12>>2]=Q+ba;c[b+236+(H*48|0)+28>>2]=Q+T;c[b+236+(H*48|0)+44>>2]=Q+da;kb(fa,fa);H=H+1|0;if((H|0)==(f|0))break;else Q=Q+Y|0}}c[b+576>>2]=-32-G;Y=0-$|0;c[b+584>>2]=Y;c[b+580>>2]=Y;Y=c[b+248>>2]|0;Q=Y;H=(c[J>>2]|0)+(c[I>>2]|0)|0;da=c[b+72>>2]|0;if((H|0)>0){T=c[R>>2]<<3;ba=(da|0)>0;Z=0;aa=Y;while(1){Y=Z+da|0;if(ba){S=Z+1|0;X=Z;W=aa;while(1){c[ia+(X<<2)>>2]=W-Q;X=X+1|0;if((X|0)>=(Y|0))break;else W=W+8|0}yb=(Y|0)>(S|0)?Y:S}else yb=Z;if((yb|0)<(H|0)){Z=yb;aa=aa+T|0}else{zb=yb;break}}}else zb=0;T=(c[P>>2]|0)+(c[M>>2]|0)|0;aa=c[L>>2]|0;if((zb|0)<(T|0)){Z=c[U>>2]<<3;H=(aa|0)>0;ba=zb;da=c[b+264>>2]|0;while(1){R=ba+aa|0;if(H){I=ba+1|0;J=ba;$=da;while(1){c[ia+(J<<2)>>2]=$-Q;J=J+1|0;if((J|0)>=(R|0))break;else $=$+8|0}Ab=(R|0)>(I|0)?R:I}else Ab=ba;if((Ab|0)<(T|0)){ba=Ab;da=da+Z|0}else{Bb=Ab;break}}}else Bb=zb;Z=(c[O>>2]|0)+(c[N>>2]|0)|0;da=c[K>>2]|0;if((Bb|0)<(Z|0)){ba=c[V>>2]<<3;T=(da|0)>0;H=Bb;aa=c[b+280>>2]|0;while(1){U=H+da|0;if(T){L=H+1|0;M=H;P=aa;while(1){c[ia+(M<<2)>>2]=P-Q;M=M+1|0;if((M|0)>=(U|0))break;else P=P+8|0}Cb=(U|0)>(L|0)?U:L}else Cb=H;if((Cb|0)<(Z|0)){H=Cb;aa=aa+ba|0}else break}}ba=b+524|0;c[ba>>2]=-1;c[ba+4>>2]=-1;c[ba+8>>2]=-1;c[ba+12>>2]=-1;c[ba+16>>2]=-1;c[ba+20>>2]=-1;ba=b+548|0;c[ba>>2]=0;c[ba+4>>2]=0;c[ba+8>>2]=0;c[ba+12>>2]=0;c[ba+16>>2]=0;c[ba+20>>2]=0;if((c[e+60>>2]|0)>>>0>31)c[b+60>>2]=31;ba=b+848|0;c[ba>>2]=0;c[ba+4>>2]=0;ba=b+856|0;c[ba>>2]=-1;c[ba+4>>2]=-1;ba=a[e>>0]|0;do if((ba&255)>3)Db=1;else{if(ba<<24>>24!=3){Db=0;break}aa=a[e+1>>0]|0;if((aa&255)>2){Db=1;break}if(aa<<24>>24!=2){Db=0;break}Db=(a[e+2>>0]|0)!=0&1}while(0);a[b+873>>0]=Db;g=0;return g|0}else xb=-23}else xb=-10}else xb=-1}else xb=-23;while(0);Pb(c[b+216>>2]|0);Pb(c[b+200>>2]|0);Pb(c[b+196>>2]|0);Pb(c[b+188>>2]|0);Pb(c[b+184>>2]|0);Pb(c[b+176>>2]|0);Pb(c[b+168>>2]|0);g=xb;return g|0}function nb(a){a=a|0;Pb(c[a+172>>2]|0);jb(c[a+572>>2]|0);Pb(c[a+216>>2]|0);Pb(c[a+200>>2]|0);Pb(c[a+196>>2]|0);Pb(c[a+188>>2]|0);Pb(c[a+184>>2]|0);Pb(c[a+176>>2]|0);Pb(c[a+168>>2]|0);return}function ob(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0;if(!e)h=0;else h=(c[b+48>>2]&1|0)==0;i=16>>>(h&1);h=c[b+236+(d*48|0)+(e<<4)+8>>2]|0;j=c[b+236+(d*48|0)+(e<<4)+12>>2]|0;k=_(h,f)|0;f=_(h,g)|0;g=j+f|0;if((k|0)==(f|0))return;f=0-i|0;l=j+k|0;m=j+(k+-1+(c[b+236+(d*48|0)+(e<<4)>>2]|0))|0;while(1){Ub(l+f|0,a[l>>0]|0,i|0)|0;Ub(m+1|0,a[m>>0]|0,i|0)|0;l=l+h|0;if((l|0)==(g|0))break;else m=m+h|0}return}function pb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;if(!d){e=16;f=0}else{g=c[a+48>>2]|0;e=16>>>(g&1^1);f=(g&2|0)==0}g=c[a+236+(b*48|0)+(d<<4)+8>>2]|0;h=(c[a+236+(b*48|0)+(d<<4)>>2]|0)+(e<<1)|0;i=c[a+236+(b*48|0)+(d<<4)+12>>2]|0;j=0-e|0;k=0-(e+(_(16>>>(f&1),g)|0))|0;f=i+k|0;if((j|0)==(k|0))return;k=0-g|0;l=i+j|0;j=i+((_((c[a+236+(b*48|0)+(d<<4)+4>>2]|0)+-1|0,g)|0)-e)|0;do{e=l;l=l+k|0;Xb(l|0,e|0,h|0)|0;e=j;j=j+g|0;Xb(j|0,e|0,h|0)|0}while((l|0)!=(f|0));return}function qb(d,e,f,g,h,i){d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;var j=0,k=0,l=0,m=0,n=0,o=0;j=_(b[g>>1]|0,i&65535)|0;if((h|0)<2){i=(j+15|0)>>>5&65535;k=0;do{b[g+(k+64<<1)>>1]=i;k=k+1|0}while((k|0)!=64)}else{b[g>>1]=j;cb(g+128|0,g,h)}h=c[(c[d+172>>2]|0)+(e<<2)>>2]|0;j=(c[(c[d+168>>2]|0)+(e<<2)>>2]|0)>>>6&3;k=c[d+576+(f<<2)>>2]|0;i=(c[d+556>>2]|0)+h|0;if((j|0)==2){Wa(i,k,g+128|0);return}l=c[d+548+(j<<2)>>2]|0;j=b[(c[d+176>>2]|0)+(e<<1)>>1]|0;e=(f|0)!=0;if(e)m=(c[d+48>>2]&2|0)==0;else m=0;f=m&1;m=(j<<16>>16>>8)+31|0;n=a[1624+(f<<6)+m>>0]|0;if(e)o=(c[d+48>>2]&1|0)==0;else o=0;d=o&1;o=((j&65535)<<24>>24)+31|0;j=a[1624+(d<<6)+o>>0]|0;e=(a[1496+(d<<6)+o>>0]|0)+(_(a[1496+(f<<6)+m>>0]|0,k)|0)|0;if(!((j|n)<<24>>24)){Xa(i,l+(e+h)|0,k,g+128|0);return}else{Ya(i,l+(e+h)|0,l+((_(n<<24>>24,k)|0)+h+e+(j<<24>>24))|0,k,g+128|0);return}}function rb(b,c){b=b|0;c=c|0;var d=0,e=0,f=0;Ub(b|0,0,256)|0;if((c|0)>0)d=0;else return;do{e=127-d|0;f=e-c|0;if((f|0)>-1)a[b+f>>0]=d-c;a[b+e>>0]=0-d;e=d+127|0;a[b+e>>0]=d;f=e+c|0;if((f|0)<256)a[b+f>>0]=c-d;d=d+1|0}while((d|0)!=(c|0));return}function sb(b,e,f,g,h,i){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0;j=c[b+72+(g<<5)>>2]|0;k=c[b+72+(g<<5)+8>>2]|0;l=(c[b+72+(g<<5)+12>>2]|0)+k|0;m=k+(_(j,h)|0)|0;h=k+(_(j,i)|0)|0;i=c[b+576+(g<<2)>>2]|0;g=c[b+168>>2]|0;n=c[b+172>>2]|0;o=c[b+548+(f<<2)>>2]|0;if((m|0)>=(h|0))return;f=i<<1;b=i<<3;p=(j|0)>0;q=m;do{m=q;q=q+j|0;if(p){r=(m|0)>(k|0);s=m;while(1){if(c[g+(s<<2)>>2]&1){t=c[n+(s<<2)>>2]|0;if((s|0)>(m|0)){u=o+(t+-2)|0;v=0;while(1){w=u+2|0;x=d[w>>0]|0;y=u+1|0;z=d[y>>0]|0;A=a[e+(((d[u>>0]|0)+4-(d[u+3>>0]|0)+((x-z|0)*3|0)>>3)+127)>>0]|0;B=A+z|0;a[y>>0]=(B>>>31)+255&((B|0)>255?255:B);B=x-A|0;a[w>>0]=(B>>>31)+255&((B|0)>255?255:B);v=v+1|0;if((v|0)==8)break;else u=u+i|0}}if(r){u=t-f|0;v=t+i|0;B=t-i|0;w=0;do{A=o+(w+t)|0;x=o+(B+w)|0;y=d[x>>0]|0;z=a[e+(((d[o+(u+w)>>0]|0)+4-(d[o+(v+w)>>0]|0)+(((d[A>>0]|0)-y|0)*3|0)>>3)+127)>>0]|0;C=z+y|0;a[x>>0]=(C>>>31)+255&((C|0)>255?255:C);C=(d[A>>0]|0)-z|0;a[A>>0]=(C>>>31)+255&((C|0)>255?255:C);w=w+1|0}while((w|0)!=8)}w=s+1|0;if((w|0)<(q|0)?(c[g+(w<<2)>>2]&1|0)==0:0){v=o+(t+6)|0;u=0;while(1){B=v+2|0;C=d[B>>0]|0;A=v+1|0;z=d[A>>0]|0;x=a[e+(((d[v>>0]|0)+4-(d[v+3>>0]|0)+((C-z|0)*3|0)>>3)+127)>>0]|0;y=x+z|0;a[A>>0]=(y>>>31)+255&((y|0)>255?255:y);y=C-x|0;a[B>>0]=(y>>>31)+255&((y|0)>255?255:y);u=u+1|0;if((u|0)==8)break;else v=v+i|0}}v=s+j|0;if((v|0)<(l|0)?(c[g+(v<<2)>>2]&1|0)==0:0){v=t+b|0;u=v-f|0;y=v+i|0;B=v-i|0;x=0;do{C=o+(x+v)|0;A=o+(B+x)|0;z=d[A>>0]|0;D=a[e+(((d[o+(u+x)>>0]|0)+4-(d[o+(y+x)>>0]|0)+(((d[C>>0]|0)-z|0)*3|0)>>3)+127)>>0]|0;E=D+z|0;a[A>>0]=(E>>>31)+255&((E|0)>255?255:E);E=(d[C>>0]|0)-D|0;a[C>>0]=(E>>>31)+255&((E|0)>255?255:E);x=x+1|0}while((x|0)!=8);F=w}else F=w}else F=s+1|0;if((F|0)<(q|0))s=F;else break}}}while((q|0)<(h|0));return}function tb(b,e,f,g,h,j,k,l){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;var m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0;m=i;i=i+48|0;n=m;o=n+20|0;p=n+16|0;q=n+4|0;r=n+8|0;s=n+12|0;t=e<<1;u=n+24|0;v=n+28|0;w=n+32|0;x=n+36|0;y=g<<1;z=g*3|0;A=g<<2;B=g*5|0;C=g*6|0;D=g*7|0;E=g<<3;F=g*9|0;G=e*3|0;H=e<<2;I=e*5|0;J=e<<1;K=e*3|0;L=e<<2;M=e*5|0;N=e*6|0;O=e*7|0;P=0;Q=b+(e*6|0)|0;R=b+(e*5|0)|0;S=b;b=f;while(1){f=d[b>>0]|0;c[n>>2]=f;T=a[b+g>>0]|0;U=T&255;c[q>>2]=U;V=d[b+y>>0]|0;c[r>>2]=V;W=d[b+z>>0]|0;c[s>>2]=W;X=d[b+A>>0]|0;c[p>>2]=X;Y=d[b+B>>0]|0;c[o>>2]=Y;Z=d[b+C>>0]|0;c[u>>2]=Z;_=d[b+D>>0]|0;c[v>>2]=_;$=d[b+E>>0]|0;c[w>>2]=$;aa=d[b+F>>0]|0;c[x>>2]=aa;ba=U-f|0;ca=Y-Z|0;da=V-U|0;ea=Z-_|0;Z=W-V|0;fa=_-$|0;_=X-W|0;ga=((_|0)>-1?_:0-_|0)+(((Z|0)>-1?Z:0-Z|0)+(((da|0)>-1?da:0-da|0)+((ba|0)>-1?ba:0-ba|0)))|0;ba=$-aa|0;aa=((ba|0)>-1?ba:0-ba|0)+(((fa|0)>-1?fa:0-fa|0)+(((ea|0)>-1?ea:0-ea|0)+((ca|0)>-1?ca:0-ca|0)))|0;c[k>>2]=(c[k>>2]|0)+((ga|0)<255?ga:255);c[l>>2]=(c[l>>2]|0)+((aa|0)<255?aa:255);if((ga|0)<(j|0)&(aa|0)<(j|0)?(Y-X|0)<(h|0)&(X-Y|0)<(h|0):0){a[S>>0]=(X+4+(f*3|0)+(U<<1)+V+W|0)>>>3;a[S+e>>0]=((c[q>>2]|0)+4+(c[s>>2]|0)+(c[p>>2]|0)+(c[o>>2]|0)+((c[r>>2]|0)+(c[n>>2]|0)<<1)|0)>>>3;a[S+t>>0]=((c[n>>2]|0)+4+(c[q>>2]|0)+(c[r>>2]|0)+(c[s>>2]<<1)+(c[p>>2]|0)+(c[o>>2]|0)+(c[u>>2]|0)|0)>>>3;a[S+G>>0]=((c[q>>2]|0)+4+(c[r>>2]|0)+(c[s>>2]|0)+(c[p>>2]<<1)+(c[o>>2]|0)+(c[u>>2]|0)+(c[v>>2]|0)|0)>>>3;a[S+H>>0]=((c[r>>2]|0)+4+(c[s>>2]|0)+(c[p>>2]|0)+(c[o>>2]<<1)+(c[u>>2]|0)+(c[v>>2]|0)+(c[w>>2]|0)|0)>>>3;a[S+I>>0]=((c[s>>2]|0)+4+(c[p>>2]|0)+(c[o>>2]|0)+(c[u>>2]<<1)+(c[v>>2]|0)+(c[w>>2]|0)+(c[x>>2]|0)|0)>>>3;a[Q>>0]=((c[p>>2]|0)+4+(c[o>>2]|0)+(c[u>>2]|0)+(c[w>>2]|0)+((c[x>>2]|0)+(c[v>>2]|0)<<1)|0)>>>3;a[R+t>>0]=((c[o>>2]|0)+4+(c[u>>2]|0)+(c[v>>2]|0)+(c[w>>2]<<1)+((c[x>>2]|0)*3|0)|0)>>>3}else{a[S>>0]=T;a[S+e>>0]=c[r>>2];a[S+J>>0]=c[s>>2];a[S+K>>0]=c[p>>2];a[S+L>>0]=c[o>>2];a[S+M>>0]=c[u>>2];a[S+N>>0]=c[v>>2];a[S+O>>0]=c[w>>2]}P=P+1|0;if((P|0)==8)break;else{Q=Q+1|0;R=R+1|0;S=S+1|0;b=b+1|0}}i=m;return}function ub(b,e,f,g,h){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0;j=i;i=i+48|0;k=j;l=h+4|0;m=k+20|0;n=k+16|0;o=k+4|0;p=k+8|0;q=k+12|0;r=k+24|0;s=k+28|0;t=k+32|0;u=k+36|0;v=0;w=b;x=b+6|0;y=b+5|0;while(1){b=d[w+-1>>0]|0;c[k>>2]=b;z=d[w>>0]|0;c[o>>2]=z;A=d[w+1>>0]|0;c[p>>2]=A;B=d[w+2>>0]|0;c[q>>2]=B;C=d[w+3>>0]|0;c[n>>2]=C;D=d[w+4>>0]|0;c[m>>2]=D;E=d[w+5>>0]|0;c[r>>2]=E;F=d[w+6>>0]|0;c[s>>2]=F;G=d[w+7>>0]|0;c[t>>2]=G;H=d[w+8>>0]|0;c[u>>2]=H;I=z-b|0;J=D-E|0;K=A-z|0;L=E-F|0;E=B-A|0;M=F-G|0;F=C-B|0;N=((F|0)>-1?F:0-F|0)+(((E|0)>-1?E:0-E|0)+(((K|0)>-1?K:0-K|0)+((I|0)>-1?I:0-I|0)))|0;I=G-H|0;H=((I|0)>-1?I:0-I|0)+(((M|0)>-1?M:0-M|0)+(((L|0)>-1?L:0-L|0)+((J|0)>-1?J:0-J|0)))|0;c[h>>2]=(c[h>>2]|0)+((N|0)<255?N:255);c[l>>2]=(c[l>>2]|0)+((H|0)<255?H:255);if((N|0)<(g|0)&(H|0)<(g|0)?(D-C|0)<(f|0)&(C-D|0)<(f|0):0){a[w>>0]=(C+4+(b*3|0)+(z<<1)+A+B|0)>>>3;a[w+1>>0]=((c[o>>2]|0)+4+(c[q>>2]|0)+(c[n>>2]|0)+(c[m>>2]|0)+((c[p>>2]|0)+(c[k>>2]|0)<<1)|0)>>>3;a[w+2>>0]=((c[k>>2]|0)+4+(c[o>>2]|0)+(c[p>>2]|0)+(c[q>>2]<<1)+(c[n>>2]|0)+(c[m>>2]|0)+(c[r>>2]|0)|0)>>>3;a[w+3>>0]=((c[o>>2]|0)+4+(c[p>>2]|0)+(c[q>>2]|0)+(c[n>>2]<<1)+(c[m>>2]|0)+(c[r>>2]|0)+(c[s>>2]|0)|0)>>>3;a[w+4>>0]=((c[p>>2]|0)+4+(c[q>>2]|0)+(c[n>>2]|0)+(c[m>>2]<<1)+(c[r>>2]|0)+(c[s>>2]|0)+(c[t>>2]|0)|0)>>>3;a[w+5>>0]=((c[q>>2]|0)+4+(c[n>>2]|0)+(c[m>>2]|0)+(c[r>>2]<<1)+(c[s>>2]|0)+(c[t>>2]|0)+(c[u>>2]|0)|0)>>>3;a[x>>0]=((c[n>>2]|0)+4+(c[m>>2]|0)+(c[r>>2]|0)+(c[t>>2]|0)+((c[u>>2]|0)+(c[s>>2]|0)<<1)|0)>>>3;a[y+2>>0]=((c[m>>2]|0)+4+(c[r>>2]|0)+(c[s>>2]|0)+(c[t>>2]<<1)+((c[u>>2]|0)*3|0)|0)>>>3}v=v+1|0;if((v|0)==8)break;else{w=w+e|0;x=x+e|0;y=y+e|0}}i=j;return}function vb(b,e,f,g,h,j){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;k=i;i=i+576|0;l=k+288|0;m=k;n=g*3|0;o=d[1752+j>>0]|0;p=(o|0)<(n|0)?o:n;n=b+(0-(0-(f>>>2&1^1)&e))|0;o=g+32|0;g=d[1760+j>>0]|0;j=f>>>3&1^1;q=0;r=n;s=b;while(1){t=q<<3;u=0;do{v=(d[s+u>>0]|0)-(d[r+u>>0]|0)|0;w=o-(((v|0)>-1?v:0-v|0)<<g)|0;if((w|0)<-64)x=h;else{v=(p|0)<(w|0)?p:w;x=(v|0)>0?v:0}c[l+(u+t<<2)>>2]=x;u=u+1|0}while((u|0)!=8);u=s+(0-((q|0)<7|j)&e)|0;q=q+1|0;if((q|0)==9)break;else{t=s;s=u;r=t}}r=0-(f&1^1)|0;s=f>>>1&1;f=s^1;q=0;x=b;t=b+r|0;while(1){u=q<<3;v=0;w=t;y=x;while(1){z=(d[y>>0]|0)-(d[w>>0]|0)|0;A=o-(((z|0)>-1?z:0-z|0)<<g)|0;if((A|0)<-64)B=h;else{z=(p|0)<(A|0)?p:A;B=(z|0)>0?z:0}c[m+(v+u<<2)>>2]=B;v=v+1|0;if((v|0)==8)break;else{w=w+e|0;y=y+e|0}}y=x+((q|0)<7|f)|0;q=q+1|0;if((q|0)==9)break;else{w=x;x=y;t=w}}t=8-s|0;s=0;x=b;q=b+e|0;f=n;n=b;while(1){b=c[m+(s<<2)>>2]|0;B=(_(d[n+r>>0]|0,b)|0)+64|0;p=s<<3;h=c[l+(p<<2)>>2]|0;g=B+(_(d[f>>0]|0,h)|0)|0;B=s;s=s+1|0;o=s<<3;w=c[l+(o<<2)>>2]|0;y=g+(_(d[q>>0]|0,w)|0)|0;g=c[m+(B+8<<2)>>2]|0;v=y+(_(d[n+1>>0]|0,g)|0)|0;y=v+(_(d[n>>0]|0,128-b-h-w-g|0)|0)>>7;a[x>>0]=(y>>>31)+255&((y|0)>255?255:y);y=1;do{g=c[m+((y<<3)+B<<2)>>2]|0;w=(_(d[n+(y+-1)>>0]|0,g)|0)+64|0;h=c[l+(y+p<<2)>>2]|0;b=w+(_(d[f+y>>0]|0,h)|0)|0;w=c[l+(y+o<<2)>>2]|0;v=b+(_(d[q+y>>0]|0,w)|0)|0;b=y;y=y+1|0;u=c[m+((y<<3)+B<<2)>>2]|0;z=v+(_(d[n+y>>0]|0,u)|0)|0;v=z+(_(d[n+b>>0]|0,128-g-h-w-u|0)|0)>>7;a[x+b>>0]=(v>>>31)+255&((v|0)>255?255:v)}while((y|0)!=7);y=c[m+(B+56<<2)>>2]|0;v=(_(d[n+6>>0]|0,y)|0)+64|0;b=c[l+((p|7)<<2)>>2]|0;u=v+(_(d[f+7>>0]|0,b)|0)|0;v=c[l+((o|7)<<2)>>2]|0;w=u+(_(d[q+7>>0]|0,v)|0)|0;u=c[m+(B+64<<2)>>2]|0;h=w+(_(d[n+t>>0]|0,u)|0)|0;w=h+(_(d[n+7>>0]|0,128-y-b-v-u|0)|0)>>7;a[x+7>>0]=(w>>>31)+255&((w|0)>255?255:w);w=q+(0-((B|0)<6|j)&e)|0;if((s|0)==8)break;else{u=q;v=n;x=x+e|0;q=w;n=u;f=v}}i=k;return}function wb(c,e,f){c=c|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,$=0;g=i;i=i+144|0;h=g;j=g+102|0;k=g+68|0;a[j>>0]=0;l=f+255&255;a[k>>0]=l;f=(c|0)!=0;m=l;l=0;n=0;o=0;p=0;while(1){q=1-p+(m&255)|0;r=l&255;s=l<<24>>24!=0?2:7;a:do if((q|0)>0){t=0;u=1;v=1;w=2;while(1){x=(u|0)==0;y=v+1|0;z=y+r|0;A=0;B=0;C=0;while(1){D=C+p|0;E=e+(D<<1)|0;F=d[e+(D<<1)+1>>0]|0;do if((F|0)>=(z|0))if((F|0)==(z|0)){G=1;H=C+1|0;break}else{G=A;H=(Hb(E,z)|0)+C|0;break}else{G=A;H=C+1|0}while(0);E=B+1|0;if((H|0)<(q|0)){A=G;B=E;C=H}else{I=E;J=G;K=B;break}}B=x?t:v;if((K|0)<(w|0)){L=B;break a}if((_(I,s)|0)<(1<<y|0)){L=B;break}else{t=B;u=J;v=y;w=I}}}else L=1;while(0);s=o&65535;q=h+(n<<1)|0;b[q>>1]=s;r=o+1+(1<<L)|0;if(f){b[q>>1]=s+1<<16>>16;b[c+(o<<16>>16<<1)>>1]=L;M=m;N=l;O=n;P=L;Q=p}else{M=m;N=l;O=n;P=L;Q=p}while(1){s=M&255;b:do if((Q|0)>(s|0))R=Q;else{q=N&255;w=q+P|0;v=h+(O<<1)|0;if(f)S=Q;else{u=Q;while(1){if((w|0)<(d[e+(u<<1)+1>>0]|0|0)){R=u;break b}t=u+1|0;if((u|0)<(s|0))u=t;else{R=t;break b}}}while(1){u=d[e+(S<<1)+1>>0]|0;if((w|0)<(u|0)){R=S;break b}y=w-u|0;x=0-(d[e+(S<<1)>>0]|0|u-q<<8)&65535;if((y|0)!=31){u=1<<y;y=b[v>>1]|0;t=u+1+((u|0)<1?u^65535:65534)&65535;B=y;C=u;while(1){b[c+(B<<16>>16<<1)>>1]=x;if((C|0)>1){B=B+1<<16>>16;C=C+-1|0}else break}b[v>>1]=(y+1<<16>>16)+t<<16>>16}C=S+1|0;if((S|0)<(s|0))S=C;else{R=C;break}}}while(0);if((R|0)<=(s|0)){T=N;U=O;V=P;W=R;X=25;break}v=O+-1|0;if((O|0)<=0){Y=v;Z=R;break}q=a[j+v>>0]|0;w=(N&255)-(q&255)|0;M=a[k+v>>0]|0;N=q;O=v;P=w;Q=R}if((X|0)==25){X=0;w=(T&255)+V|0;v=U+1|0;a[j+v>>0]=w;if(f){q=h+(U<<1)|0;C=b[q>>1]|0;b[q>>1]=C+1<<16>>16;b[c+(C<<16>>16<<1)>>1]=r}a[k+v>>0]=W+255+(Hb(e+(W<<1)|0,w&255)|0);Y=v;Z=W}if((Y|0)<=-1){$=r;break}m=a[k+Y>>0]|0;l=a[j+Y>>0]|0;n=Y;o=r;p=Z}i=g;return $|0}function xb(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;d=b[a+(c<<1)>>1]|0;e=1<<d;f=c+1|0;c=0;g=e+1|0;while(1){h=b[a+(f+c<<1)>>1]|0;i=h<<16>>16;if(h<<16>>16<1){j=1<<d-(0-i>>8);k=g}else{j=1;k=(xb(a,i)|0)+g|0}c=j+c|0;if((c|0)>=(e|0)){l=k;break}else g=k}return l|0}function yb(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;d=b[c>>1]|0;e=b[c+8>>1]|0;f=(e+d<<16>>16)*46341>>16;g=(d-e<<16>>16)*46341>>16;e=b[c+4>>1]|0;d=b[c+12>>1]|0;h=(e*25080>>16)-(d*60547>>16)|0;i=(d*25080>>16)+(e*60547>>16)|0;e=b[c+2>>1]|0;d=b[c+14>>1]|0;j=(e*12785>>16)-(d*64277>>16)|0;k=b[c+10>>1]|0;l=b[c+6>>1]|0;c=(k*54491>>16)-(l*36410>>16)|0;m=(l*54491>>16)+(k*36410>>16)|0;k=(d*12785>>16)+(e*64277>>16)|0;e=c+j|0;d=(j-c<<16>>16)*46341>>16;c=m+k|0;j=(k-m<<16>>16)*46341>>16;m=f+i|0;k=f-i|0;i=g+h|0;f=g-h|0;h=j+d|0;g=j-d|0;b[a>>1]=c+m;b[a+16>>1]=h+i;b[a+32>>1]=g+f;b[a+48>>1]=e+k;b[a+64>>1]=k-e;b[a+80>>1]=f-g;b[a+96>>1]=i-h;b[a+112>>1]=m-c;return}function zb(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0,h=0;d=b[c>>1]|0;e=b[c+2>>1]|0;f=b[c+4>>1]|0;g=b[c+6>>1]|0;c=((e&65535)<<24>>24)+((d&65535)<<24>>24)+((f&65535)<<24>>24)+((g&65535)<<24>>24)|0;h=(e<<16>>16>>8)+(d<<16>>16>>8)+(f<<16>>16>>8)+(g<<16>>16>>8)|0;b[a>>1]=(c+2+(c>>31)|0)>>>2&255|(h+2+(h>>31)|0)>>>2<<8;return}function Ab(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0;d=b[c>>1]|0;e=b[c+4>>1]|0;f=((e&65535)<<24>>24)+((d&65535)<<24>>24)|0;g=(e<<16>>16>>8)+(d<<16>>16>>8)|0;b[a>>1]=(f+1+(f>>31)|0)>>>1&255|(g+1+(g>>31)|0)>>>1<<8;g=b[c+2>>1]|0;f=b[c+6>>1]|0;c=((f&65535)<<24>>24)+((g&65535)<<24>>24)|0;d=(f<<16>>16>>8)+(g<<16>>16>>8)|0;b[a+2>>1]=(c+1+(c>>31)|0)>>>1&255|(d+1+(d>>31)|0)>>>1<<8;return}function Bb(a,c){a=a|0;c=c|0;var d=0,e=0,f=0,g=0;d=b[c>>1]|0;e=b[c+2>>1]|0;f=((e&65535)<<24>>24)+((d&65535)<<24>>24)|0;g=(e<<16>>16>>8)+(d<<16>>16>>8)|0;b[a>>1]=(f+1+(f>>31)|0)>>>1&255|(g+1+(g>>31)|0)>>>1<<8;g=b[c+4>>1]|0;f=b[c+6>>1]|0;c=((f&65535)<<24>>24)+((g&65535)<<24>>24)|0;d=(f<<16>>16>>8)+(g<<16>>16>>8)|0;b[a+4>>1]=(c+1+(c>>31)|0)>>>1&255|(d+1+(d>>31)|0)>>>1<<8;return}function Cb(a,c){a=a|0;c=c|0;b[a>>1]=b[c>>1]|0;b[a+2>>1]=b[c+2>>1]|0;b[a+4>>1]=b[c+4>>1]|0;b[a+6>>1]=b[c+6>>1]|0;return}function Db(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;f=(_(c[b+32>>2]|0,e>>1)|0)+(d>>1)|0;c[a+16>>2]=f+(c[b+40>>2]|0);c[a+32>>2]=f+(c[b+72>>2]|0);return}function Eb(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;f=(_(c[b+32>>2]|0,e>>1)|0)+d|0;d=b+40|0;e=b+72|0;c[a+16>>2]=(c[d>>2]|0)+f;c[a+32>>2]=(c[e>>2]|0)+f;b=f+1|0;c[a+20>>2]=(c[d>>2]|0)+b;c[a+36>>2]=(c[e>>2]|0)+b;return}function Fb(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=b+32|0;g=(_(c[f>>2]|0,e)|0)+(d>>1)|0;d=b+40|0;e=b+72|0;c[a+16>>2]=(c[d>>2]|0)+g;c[a+32>>2]=(c[e>>2]|0)+g;b=(c[f>>2]|0)+g|0;c[a+24>>2]=(c[d>>2]|0)+b;c[a+40>>2]=(c[e>>2]|0)+b;return}function Gb(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;e=b+40|0;d=b+72|0;b=c[a>>2]|0;c[a+16>>2]=(c[e>>2]|0)+b;c[a+32>>2]=(c[d>>2]|0)+b;b=c[a+4>>2]|0;c[a+20>>2]=(c[e>>2]|0)+b;c[a+36>>2]=(c[d>>2]|0)+b;b=c[a+8>>2]|0;c[a+24>>2]=(c[e>>2]|0)+b;c[a+40>>2]=(c[d>>2]|0)+b;b=c[a+12>>2]|0;c[a+28>>2]=(c[e>>2]|0)+b;c[a+44>>2]=(c[d>>2]|0)+b;return}function Hb(a,b){a=a|0;b=b|0;var c=0,e=0,f=0,g=0,h=0,i=0,j=0;c=b+31|0;e=0;f=0;while(1){g=(d[a+(f<<1)+1>>0]|0)-b|0;if((g|0)<32){h=-2147483648>>>g;i=f+1|0}else{h=1;i=(Hb(a+(f<<1)|0,c)|0)+f|0}e=h+e|0;if((e|0)<=-1){j=i;break}else f=i}return j|0}function Ib(){fb(1776);db(1792);return}function Jb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;d=i;i=i+48|0;e=d+32|0;f=d;Mb(f,a,b);g=c[442]|0;if(!g)c[f+8>>2]=256;c[442]=g+1;g=Na(1792,1776,1856,f)|0;if(!g){c[466]=Pa(1792,c[464]|0)|0;f=c[460]|0;h=c[451]|0;j=c[452]|0;k=c[457]|0;l=c[458]|0;if((k|0)!=0&(l|0)!=0)m=((_(k,h)|0)>>>0)/(l>>>0)|0;else m=h;fa(c[449]|0,c[450]|0,f&1^1|0,f>>>1&1^1|0,+(+((c[455]|0)>>>0)/+((c[456]|0)>>>0)),h|0,j|0,c[453]|0,c[454]|0,m|0,j|0);n=Kb(a,b)|0;i=d;return n|0}else{if((g|0)>0){n=1;i=d;return n|0}c[e>>2]=g;oa(1872,e|0)|0;n=0;i=d;return n|0}return 0}function Kb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;i=i+96|0;e=d+32|0;f=d;g=d+40|0;Mb(f,a,b);b=Ra(c[466]|0,f,0)|0;if(b>>>0<2){Sa(c[466]|0,g)|0;f=c[460]|0;ha(c[g+12>>2]|0,c[g+8>>2]|0,c[g+28>>2]|0,c[g+24>>2]|0,c[g+44>>2]|0,c[g+40>>2]|0,c[449]|0,c[450]|0,f&1^1|0,f>>>1&1^1|0);h=1;i=d;return h|0}else{c[e>>2]=b;oa(1912,e|0)|0;h=0;i=d;return h|0}return 0}function Lb(){var a=0;a=c[466]|0;if(a){Qa(a);c[466]=0}gb(1776);eb(1792);return}function Mb(a,b,d){a=a|0;b=b|0;d=d|0;c[a>>2]=b;c[a+4>>2]=d;d=a+8|0;c[d>>2]=0;c[d+4>>2]=0;c[d+8>>2]=0;c[d+12>>2]=0;c[d+16>>2]=0;c[d+20>>2]=0;return}function Nb(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;if(!d){e=0;return e|0}else{f=d;g=b;h=c}while(1){c=a[g>>0]|0;b=a[h>>0]|0;if(c<<24>>24!=b<<24>>24){i=c;j=b;break}f=f+-1|0;if(!f){e=0;k=5;break}else{g=g+1|0;h=h+1|0}}if((k|0)==5)return e|0;e=(i&255)-(j&255)|0;return e|0}function Ob(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,la=0,ma=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0;do if(a>>>0<245){b=a>>>0<11?16:a+11&-8;d=b>>>3;e=c[488]|0;f=e>>>d;if(f&3){g=(f&1^1)+d|0;h=g<<1;i=1992+(h<<2)|0;j=1992+(h+2<<2)|0;h=c[j>>2]|0;k=h+8|0;l=c[k>>2]|0;do if((i|0)!=(l|0)){if(l>>>0<(c[492]|0)>>>0)ka();m=l+12|0;if((c[m>>2]|0)==(h|0)){c[m>>2]=i;c[j>>2]=l;break}else ka()}else c[488]=e&~(1<<g);while(0);l=g<<3;c[h+4>>2]=l|3;j=h+(l|4)|0;c[j>>2]=c[j>>2]|1;n=k;return n|0}j=c[490]|0;if(b>>>0>j>>>0){if(f){l=2<<d;i=f<<d&(l|0-l);l=(i&0-i)+-1|0;i=l>>>12&16;m=l>>>i;l=m>>>5&8;o=m>>>l;m=o>>>2&4;p=o>>>m;o=p>>>1&2;q=p>>>o;p=q>>>1&1;r=(l|i|m|o|p)+(q>>>p)|0;p=r<<1;q=1992+(p<<2)|0;o=1992+(p+2<<2)|0;p=c[o>>2]|0;m=p+8|0;i=c[m>>2]|0;do if((q|0)!=(i|0)){if(i>>>0<(c[492]|0)>>>0)ka();l=i+12|0;if((c[l>>2]|0)==(p|0)){c[l>>2]=q;c[o>>2]=i;s=c[490]|0;break}else ka()}else{c[488]=e&~(1<<r);s=j}while(0);j=r<<3;e=j-b|0;c[p+4>>2]=b|3;i=p+b|0;c[p+(b|4)>>2]=e|1;c[p+j>>2]=e;if(s){j=c[493]|0;o=s>>>3;q=o<<1;d=1992+(q<<2)|0;f=c[488]|0;k=1<<o;if(f&k){o=1992+(q+2<<2)|0;h=c[o>>2]|0;if(h>>>0<(c[492]|0)>>>0)ka();else{t=o;u=h}}else{c[488]=f|k;t=1992+(q+2<<2)|0;u=d}c[t>>2]=j;c[u+12>>2]=j;c[j+8>>2]=u;c[j+12>>2]=d}c[490]=e;c[493]=i;n=m;return n|0}i=c[489]|0;if(i){e=(i&0-i)+-1|0;i=e>>>12&16;d=e>>>i;e=d>>>5&8;j=d>>>e;d=j>>>2&4;q=j>>>d;j=q>>>1&2;k=q>>>j;q=k>>>1&1;f=c[2256+((e|i|d|j|q)+(k>>>q)<<2)>>2]|0;q=(c[f+4>>2]&-8)-b|0;k=f;j=f;while(1){f=c[k+16>>2]|0;if(!f){d=c[k+20>>2]|0;if(!d){v=q;w=j;break}else x=d}else x=f;f=(c[x+4>>2]&-8)-b|0;d=f>>>0<q>>>0;q=d?f:q;k=x;j=d?x:j}j=c[492]|0;if(w>>>0<j>>>0)ka();k=w+b|0;if(w>>>0>=k>>>0)ka();q=c[w+24>>2]|0;m=c[w+12>>2]|0;do if((m|0)==(w|0)){p=w+20|0;r=c[p>>2]|0;if(!r){d=w+16|0;f=c[d>>2]|0;if(!f){y=0;break}else{z=f;A=d}}else{z=r;A=p}while(1){p=z+20|0;r=c[p>>2]|0;if(r){z=r;A=p;continue}p=z+16|0;r=c[p>>2]|0;if(!r){B=z;C=A;break}else{z=r;A=p}}if(C>>>0<j>>>0)ka();else{c[C>>2]=0;y=B;break}}else{p=c[w+8>>2]|0;if(p>>>0<j>>>0)ka();r=p+12|0;if((c[r>>2]|0)!=(w|0))ka();d=m+8|0;if((c[d>>2]|0)==(w|0)){c[r>>2]=m;c[d>>2]=p;y=m;break}else ka()}while(0);do if(q){m=c[w+28>>2]|0;j=2256+(m<<2)|0;if((w|0)==(c[j>>2]|0)){c[j>>2]=y;if(!y){c[489]=c[489]&~(1<<m);break}}else{if(q>>>0<(c[492]|0)>>>0)ka();m=q+16|0;if((c[m>>2]|0)==(w|0))c[m>>2]=y;else c[q+20>>2]=y;if(!y)break}m=c[492]|0;if(y>>>0<m>>>0)ka();c[y+24>>2]=q;j=c[w+16>>2]|0;do if(j)if(j>>>0<m>>>0)ka();else{c[y+16>>2]=j;c[j+24>>2]=y;break}while(0);j=c[w+20>>2]|0;if(j)if(j>>>0<(c[492]|0)>>>0)ka();else{c[y+20>>2]=j;c[j+24>>2]=y;break}}while(0);if(v>>>0<16){q=v+b|0;c[w+4>>2]=q|3;j=w+(q+4)|0;c[j>>2]=c[j>>2]|1}else{c[w+4>>2]=b|3;c[w+(b|4)>>2]=v|1;c[w+(v+b)>>2]=v;j=c[490]|0;if(j){q=c[493]|0;m=j>>>3;j=m<<1;p=1992+(j<<2)|0;d=c[488]|0;r=1<<m;if(d&r){m=1992+(j+2<<2)|0;f=c[m>>2]|0;if(f>>>0<(c[492]|0)>>>0)ka();else{D=m;E=f}}else{c[488]=d|r;D=1992+(j+2<<2)|0;E=p}c[D>>2]=q;c[E+12>>2]=q;c[q+8>>2]=E;c[q+12>>2]=p}c[490]=v;c[493]=k}n=w+8|0;return n|0}else F=b}else F=b}else if(a>>>0<=4294967231){p=a+11|0;q=p&-8;j=c[489]|0;if(j){r=0-q|0;d=p>>>8;if(d)if(q>>>0>16777215)G=31;else{p=(d+1048320|0)>>>16&8;f=d<<p;d=(f+520192|0)>>>16&4;m=f<<d;f=(m+245760|0)>>>16&2;i=14-(d|p|f)+(m<<f>>>15)|0;G=q>>>(i+7|0)&1|i<<1}else G=0;i=c[2256+(G<<2)>>2]|0;a:do if(!i){H=r;I=0;J=0;K=86}else{f=r;m=0;p=q<<((G|0)==31?0:25-(G>>>1)|0);d=i;e=0;while(1){h=c[d+4>>2]&-8;o=h-q|0;if(o>>>0<f>>>0)if((h|0)==(q|0)){L=o;M=d;N=d;K=90;break a}else{O=o;P=d}else{O=f;P=e}o=c[d+20>>2]|0;d=c[d+16+(p>>>31<<2)>>2]|0;h=(o|0)==0|(o|0)==(d|0)?m:o;if(!d){H=O;I=h;J=P;K=86;break}else{f=O;m=h;p=p<<1;e=P}}}while(0);if((K|0)==86){if((I|0)==0&(J|0)==0){i=2<<G;r=j&(i|0-i);if(!r){F=q;break}i=(r&0-r)+-1|0;r=i>>>12&16;b=i>>>r;i=b>>>5&8;k=b>>>i;b=k>>>2&4;e=k>>>b;k=e>>>1&2;p=e>>>k;e=p>>>1&1;Q=c[2256+((i|r|b|k|e)+(p>>>e)<<2)>>2]|0;R=0}else{Q=I;R=J}if(!Q){S=H;T=R}else{L=H;M=Q;N=R;K=90}}if((K|0)==90)while(1){K=0;e=(c[M+4>>2]&-8)-q|0;p=e>>>0<L>>>0;k=p?e:L;e=p?M:N;p=c[M+16>>2]|0;if(p){L=k;M=p;N=e;K=90;continue}M=c[M+20>>2]|0;if(!M){S=k;T=e;break}else{L=k;N=e;K=90}}if((T|0)!=0?S>>>0<((c[490]|0)-q|0)>>>0:0){j=c[492]|0;if(T>>>0<j>>>0)ka();e=T+q|0;if(T>>>0>=e>>>0)ka();k=c[T+24>>2]|0;p=c[T+12>>2]|0;do if((p|0)==(T|0)){b=T+20|0;r=c[b>>2]|0;if(!r){i=T+16|0;m=c[i>>2]|0;if(!m){U=0;break}else{V=m;W=i}}else{V=r;W=b}while(1){b=V+20|0;r=c[b>>2]|0;if(r){V=r;W=b;continue}b=V+16|0;r=c[b>>2]|0;if(!r){X=V;Y=W;break}else{V=r;W=b}}if(Y>>>0<j>>>0)ka();else{c[Y>>2]=0;U=X;break}}else{b=c[T+8>>2]|0;if(b>>>0<j>>>0)ka();r=b+12|0;if((c[r>>2]|0)!=(T|0))ka();i=p+8|0;if((c[i>>2]|0)==(T|0)){c[r>>2]=p;c[i>>2]=b;U=p;break}else ka()}while(0);do if(k){p=c[T+28>>2]|0;j=2256+(p<<2)|0;if((T|0)==(c[j>>2]|0)){c[j>>2]=U;if(!U){c[489]=c[489]&~(1<<p);break}}else{if(k>>>0<(c[492]|0)>>>0)ka();p=k+16|0;if((c[p>>2]|0)==(T|0))c[p>>2]=U;else c[k+20>>2]=U;if(!U)break}p=c[492]|0;if(U>>>0<p>>>0)ka();c[U+24>>2]=k;j=c[T+16>>2]|0;do if(j)if(j>>>0<p>>>0)ka();else{c[U+16>>2]=j;c[j+24>>2]=U;break}while(0);j=c[T+20>>2]|0;if(j)if(j>>>0<(c[492]|0)>>>0)ka();else{c[U+20>>2]=j;c[j+24>>2]=U;break}}while(0);b:do if(S>>>0>=16){c[T+4>>2]=q|3;c[T+(q|4)>>2]=S|1;c[T+(S+q)>>2]=S;k=S>>>3;if(S>>>0<256){j=k<<1;p=1992+(j<<2)|0;b=c[488]|0;i=1<<k;if(b&i){k=1992+(j+2<<2)|0;r=c[k>>2]|0;if(r>>>0<(c[492]|0)>>>0)ka();else{Z=k;_=r}}else{c[488]=b|i;Z=1992+(j+2<<2)|0;_=p}c[Z>>2]=e;c[_+12>>2]=e;c[T+(q+8)>>2]=_;c[T+(q+12)>>2]=p;break}p=S>>>8;if(p)if(S>>>0>16777215)$=31;else{j=(p+1048320|0)>>>16&8;i=p<<j;p=(i+520192|0)>>>16&4;b=i<<p;i=(b+245760|0)>>>16&2;r=14-(p|j|i)+(b<<i>>>15)|0;$=S>>>(r+7|0)&1|r<<1}else $=0;r=2256+($<<2)|0;c[T+(q+28)>>2]=$;c[T+(q+20)>>2]=0;c[T+(q+16)>>2]=0;i=c[489]|0;b=1<<$;if(!(i&b)){c[489]=i|b;c[r>>2]=e;c[T+(q+24)>>2]=r;c[T+(q+12)>>2]=e;c[T+(q+8)>>2]=e;break}b=c[r>>2]|0;c:do if((c[b+4>>2]&-8|0)!=(S|0)){r=S<<(($|0)==31?0:25-($>>>1)|0);i=b;while(1){j=i+16+(r>>>31<<2)|0;p=c[j>>2]|0;if(!p){aa=j;ba=i;break}if((c[p+4>>2]&-8|0)==(S|0)){ca=p;break c}else{r=r<<1;i=p}}if(aa>>>0<(c[492]|0)>>>0)ka();else{c[aa>>2]=e;c[T+(q+24)>>2]=ba;c[T+(q+12)>>2]=e;c[T+(q+8)>>2]=e;break b}}else ca=b;while(0);b=ca+8|0;i=c[b>>2]|0;r=c[492]|0;if(i>>>0>=r>>>0&ca>>>0>=r>>>0){c[i+12>>2]=e;c[b>>2]=e;c[T+(q+8)>>2]=i;c[T+(q+12)>>2]=ca;c[T+(q+24)>>2]=0;break}else ka()}else{i=S+q|0;c[T+4>>2]=i|3;b=T+(i+4)|0;c[b>>2]=c[b>>2]|1}while(0);n=T+8|0;return n|0}else F=q}else F=q}else F=-1;while(0);T=c[490]|0;if(T>>>0>=F>>>0){S=T-F|0;ca=c[493]|0;if(S>>>0>15){c[493]=ca+F;c[490]=S;c[ca+(F+4)>>2]=S|1;c[ca+T>>2]=S;c[ca+4>>2]=F|3}else{c[490]=0;c[493]=0;c[ca+4>>2]=T|3;S=ca+(T+4)|0;c[S>>2]=c[S>>2]|1}n=ca+8|0;return n|0}ca=c[491]|0;if(ca>>>0>F>>>0){S=ca-F|0;c[491]=S;ca=c[494]|0;c[494]=ca+F;c[ca+(F+4)>>2]=S|1;c[ca+4>>2]=F|3;n=ca+8|0;return n|0}do if(!(c[606]|0)){ca=va(30)|0;if(!(ca+-1&ca)){c[608]=ca;c[607]=ca;c[609]=-1;c[610]=-1;c[611]=0;c[599]=0;c[606]=(ua(0)|0)&-16^1431655768;break}else ka()}while(0);ca=F+48|0;S=c[608]|0;T=F+47|0;ba=S+T|0;aa=0-S|0;S=ba&aa;if(S>>>0<=F>>>0){n=0;return n|0}$=c[598]|0;if(($|0)!=0?(_=c[596]|0,Z=_+S|0,Z>>>0<=_>>>0|Z>>>0>$>>>0):0){n=0;return n|0}d:do if(!(c[599]&4)){$=c[494]|0;e:do if($){Z=2400;while(1){_=c[Z>>2]|0;if(_>>>0<=$>>>0?(U=Z+4|0,(_+(c[U>>2]|0)|0)>>>0>$>>>0):0){da=Z;ea=U;break}Z=c[Z+8>>2]|0;if(!Z){K=174;break e}}Z=ba-(c[491]|0)&aa;if(Z>>>0<2147483647){U=na(Z|0)|0;_=(U|0)==((c[da>>2]|0)+(c[ea>>2]|0)|0);X=_?Z:0;if(_)if((U|0)==(-1|0))fa=X;else{ga=U;ha=X;K=194;break d}else{ia=U;ja=Z;la=X;K=184}}else fa=0}else K=174;while(0);do if((K|0)==174){$=na(0)|0;if(($|0)!=(-1|0)){q=$;X=c[607]|0;Z=X+-1|0;if(!(Z&q))ma=S;else ma=S-q+(Z+q&0-X)|0;X=c[596]|0;q=X+ma|0;if(ma>>>0>F>>>0&ma>>>0<2147483647){Z=c[598]|0;if((Z|0)!=0?q>>>0<=X>>>0|q>>>0>Z>>>0:0){fa=0;break}Z=na(ma|0)|0;q=(Z|0)==($|0);X=q?ma:0;if(q){ga=$;ha=X;K=194;break d}else{ia=Z;ja=ma;la=X;K=184}}else fa=0}else fa=0}while(0);f:do if((K|0)==184){X=0-ja|0;do if(ca>>>0>ja>>>0&(ja>>>0<2147483647&(ia|0)!=(-1|0))?(Z=c[608]|0,$=T-ja+Z&0-Z,$>>>0<2147483647):0)if((na($|0)|0)==(-1|0)){na(X|0)|0;fa=la;break f}else{oa=$+ja|0;break}else oa=ja;while(0);if((ia|0)==(-1|0))fa=la;else{ga=ia;ha=oa;K=194;break d}}while(0);c[599]=c[599]|4;pa=fa;K=191}else{pa=0;K=191}while(0);if((((K|0)==191?S>>>0<2147483647:0)?(fa=na(S|0)|0,S=na(0)|0,fa>>>0<S>>>0&((fa|0)!=(-1|0)&(S|0)!=(-1|0))):0)?(oa=S-fa|0,S=oa>>>0>(F+40|0)>>>0,S):0){ga=fa;ha=S?oa:pa;K=194}if((K|0)==194){pa=(c[596]|0)+ha|0;c[596]=pa;if(pa>>>0>(c[597]|0)>>>0)c[597]=pa;pa=c[494]|0;g:do if(pa){oa=2400;do{S=c[oa>>2]|0;fa=oa+4|0;ia=c[fa>>2]|0;if((ga|0)==(S+ia|0)){qa=S;ra=fa;sa=ia;ta=oa;K=204;break}oa=c[oa+8>>2]|0}while((oa|0)!=0);if(((K|0)==204?(c[ta+12>>2]&8|0)==0:0)?pa>>>0<ga>>>0&pa>>>0>=qa>>>0:0){c[ra>>2]=sa+ha;oa=(c[491]|0)+ha|0;ia=pa+8|0;fa=(ia&7|0)==0?0:0-ia&7;ia=oa-fa|0;c[494]=pa+fa;c[491]=ia;c[pa+(fa+4)>>2]=ia|1;c[pa+(oa+4)>>2]=40;c[495]=c[610];break}oa=c[492]|0;if(ga>>>0<oa>>>0){c[492]=ga;xa=ga}else xa=oa;oa=ga+ha|0;ia=2400;while(1){if((c[ia>>2]|0)==(oa|0)){ya=ia;za=ia;K=212;break}ia=c[ia+8>>2]|0;if(!ia){Aa=2400;break}}if((K|0)==212)if(!(c[za+12>>2]&8)){c[ya>>2]=ga;ia=za+4|0;c[ia>>2]=(c[ia>>2]|0)+ha;ia=ga+8|0;oa=(ia&7|0)==0?0:0-ia&7;ia=ga+(ha+8)|0;fa=(ia&7|0)==0?0:0-ia&7;ia=ga+(fa+ha)|0;S=oa+F|0;la=ga+S|0;ja=ia-(ga+oa)-F|0;c[ga+(oa+4)>>2]=F|3;h:do if((ia|0)!=(pa|0)){if((ia|0)==(c[493]|0)){T=(c[490]|0)+ja|0;c[490]=T;c[493]=la;c[ga+(S+4)>>2]=T|1;c[ga+(T+S)>>2]=T;break}T=ha+4|0;ca=c[ga+(T+fa)>>2]|0;if((ca&3|0)==1){ma=ca&-8;ea=ca>>>3;i:do if(ca>>>0>=256){da=c[ga+((fa|24)+ha)>>2]|0;aa=c[ga+(ha+12+fa)>>2]|0;do if((aa|0)==(ia|0)){ba=fa|16;X=ga+(T+ba)|0;$=c[X>>2]|0;if(!$){Z=ga+(ba+ha)|0;ba=c[Z>>2]|0;if(!ba){Ba=0;break}else{Ca=ba;Da=Z}}else{Ca=$;Da=X}while(1){X=Ca+20|0;$=c[X>>2]|0;if($){Ca=$;Da=X;continue}X=Ca+16|0;$=c[X>>2]|0;if(!$){Ea=Ca;Fa=Da;break}else{Ca=$;Da=X}}if(Fa>>>0<xa>>>0)ka();else{c[Fa>>2]=0;Ba=Ea;break}}else{X=c[ga+((fa|8)+ha)>>2]|0;if(X>>>0<xa>>>0)ka();$=X+12|0;if((c[$>>2]|0)!=(ia|0))ka();Z=aa+8|0;if((c[Z>>2]|0)==(ia|0)){c[$>>2]=aa;c[Z>>2]=X;Ba=aa;break}else ka()}while(0);if(!da)break;aa=c[ga+(ha+28+fa)>>2]|0;X=2256+(aa<<2)|0;do if((ia|0)!=(c[X>>2]|0)){if(da>>>0<(c[492]|0)>>>0)ka();Z=da+16|0;if((c[Z>>2]|0)==(ia|0))c[Z>>2]=Ba;else c[da+20>>2]=Ba;if(!Ba)break i}else{c[X>>2]=Ba;if(Ba)break;c[489]=c[489]&~(1<<aa);break i}while(0);aa=c[492]|0;if(Ba>>>0<aa>>>0)ka();c[Ba+24>>2]=da;X=fa|16;Z=c[ga+(X+ha)>>2]|0;do if(Z)if(Z>>>0<aa>>>0)ka();else{c[Ba+16>>2]=Z;c[Z+24>>2]=Ba;break}while(0);Z=c[ga+(T+X)>>2]|0;if(!Z)break;if(Z>>>0<(c[492]|0)>>>0)ka();else{c[Ba+20>>2]=Z;c[Z+24>>2]=Ba;break}}else{Z=c[ga+((fa|8)+ha)>>2]|0;aa=c[ga+(ha+12+fa)>>2]|0;da=1992+(ea<<1<<2)|0;do if((Z|0)!=(da|0)){if(Z>>>0<xa>>>0)ka();if((c[Z+12>>2]|0)==(ia|0))break;ka()}while(0);if((aa|0)==(Z|0)){c[488]=c[488]&~(1<<ea);break}do if((aa|0)==(da|0))Ga=aa+8|0;else{if(aa>>>0<xa>>>0)ka();X=aa+8|0;if((c[X>>2]|0)==(ia|0)){Ga=X;break}ka()}while(0);c[Z+12>>2]=aa;c[Ga>>2]=Z}while(0);Ha=ga+((ma|fa)+ha)|0;Ia=ma+ja|0}else{Ha=ia;Ia=ja}ea=Ha+4|0;c[ea>>2]=c[ea>>2]&-2;c[ga+(S+4)>>2]=Ia|1;c[ga+(Ia+S)>>2]=Ia;ea=Ia>>>3;if(Ia>>>0<256){T=ea<<1;ca=1992+(T<<2)|0;da=c[488]|0;X=1<<ea;do if(!(da&X)){c[488]=da|X;Ja=1992+(T+2<<2)|0;Ka=ca}else{ea=1992+(T+2<<2)|0;$=c[ea>>2]|0;if($>>>0>=(c[492]|0)>>>0){Ja=ea;Ka=$;break}ka()}while(0);c[Ja>>2]=la;c[Ka+12>>2]=la;c[ga+(S+8)>>2]=Ka;c[ga+(S+12)>>2]=ca;break}T=Ia>>>8;do if(!T)La=0;else{if(Ia>>>0>16777215){La=31;break}X=(T+1048320|0)>>>16&8;da=T<<X;ma=(da+520192|0)>>>16&4;$=da<<ma;da=($+245760|0)>>>16&2;ea=14-(ma|X|da)+($<<da>>>15)|0;La=Ia>>>(ea+7|0)&1|ea<<1}while(0);T=2256+(La<<2)|0;c[ga+(S+28)>>2]=La;c[ga+(S+20)>>2]=0;c[ga+(S+16)>>2]=0;ca=c[489]|0;ea=1<<La;if(!(ca&ea)){c[489]=ca|ea;c[T>>2]=la;c[ga+(S+24)>>2]=T;c[ga+(S+12)>>2]=la;c[ga+(S+8)>>2]=la;break}ea=c[T>>2]|0;j:do if((c[ea+4>>2]&-8|0)!=(Ia|0)){T=Ia<<((La|0)==31?0:25-(La>>>1)|0);ca=ea;while(1){da=ca+16+(T>>>31<<2)|0;$=c[da>>2]|0;if(!$){Ma=da;Na=ca;break}if((c[$+4>>2]&-8|0)==(Ia|0)){Oa=$;break j}else{T=T<<1;ca=$}}if(Ma>>>0<(c[492]|0)>>>0)ka();else{c[Ma>>2]=la;c[ga+(S+24)>>2]=Na;c[ga+(S+12)>>2]=la;c[ga+(S+8)>>2]=la;break h}}else Oa=ea;while(0);ea=Oa+8|0;ca=c[ea>>2]|0;T=c[492]|0;if(ca>>>0>=T>>>0&Oa>>>0>=T>>>0){c[ca+12>>2]=la;c[ea>>2]=la;c[ga+(S+8)>>2]=ca;c[ga+(S+12)>>2]=Oa;c[ga+(S+24)>>2]=0;break}else ka()}else{ca=(c[491]|0)+ja|0;c[491]=ca;c[494]=la;c[ga+(S+4)>>2]=ca|1}while(0);n=ga+(oa|8)|0;return n|0}else Aa=2400;while(1){S=c[Aa>>2]|0;if(S>>>0<=pa>>>0?(la=c[Aa+4>>2]|0,ja=S+la|0,ja>>>0>pa>>>0):0){Pa=S;Qa=la;Ra=ja;break}Aa=c[Aa+8>>2]|0}oa=Pa+(Qa+-39)|0;ja=Pa+(Qa+-47+((oa&7|0)==0?0:0-oa&7))|0;oa=pa+16|0;la=ja>>>0<oa>>>0?pa:ja;ja=la+8|0;S=ga+8|0;ia=(S&7|0)==0?0:0-S&7;S=ha+-40-ia|0;c[494]=ga+ia;c[491]=S;c[ga+(ia+4)>>2]=S|1;c[ga+(ha+-36)>>2]=40;c[495]=c[610];S=la+4|0;c[S>>2]=27;c[ja>>2]=c[600];c[ja+4>>2]=c[601];c[ja+8>>2]=c[602];c[ja+12>>2]=c[603];c[600]=ga;c[601]=ha;c[603]=0;c[602]=ja;ja=la+28|0;c[ja>>2]=7;if((la+32|0)>>>0<Ra>>>0){ia=ja;do{ja=ia;ia=ia+4|0;c[ia>>2]=7}while((ja+8|0)>>>0<Ra>>>0)}if((la|0)!=(pa|0)){ia=la-pa|0;c[S>>2]=c[S>>2]&-2;c[pa+4>>2]=ia|1;c[la>>2]=ia;ja=ia>>>3;if(ia>>>0<256){fa=ja<<1;ca=1992+(fa<<2)|0;ea=c[488]|0;T=1<<ja;if(ea&T){ja=1992+(fa+2<<2)|0;Z=c[ja>>2]|0;if(Z>>>0<(c[492]|0)>>>0)ka();else{Sa=ja;Ta=Z}}else{c[488]=ea|T;Sa=1992+(fa+2<<2)|0;Ta=ca}c[Sa>>2]=pa;c[Ta+12>>2]=pa;c[pa+8>>2]=Ta;c[pa+12>>2]=ca;break}ca=ia>>>8;if(ca)if(ia>>>0>16777215)Ua=31;else{fa=(ca+1048320|0)>>>16&8;T=ca<<fa;ca=(T+520192|0)>>>16&4;ea=T<<ca;T=(ea+245760|0)>>>16&2;Z=14-(ca|fa|T)+(ea<<T>>>15)|0;Ua=ia>>>(Z+7|0)&1|Z<<1}else Ua=0;Z=2256+(Ua<<2)|0;c[pa+28>>2]=Ua;c[pa+20>>2]=0;c[oa>>2]=0;T=c[489]|0;ea=1<<Ua;if(!(T&ea)){c[489]=T|ea;c[Z>>2]=pa;c[pa+24>>2]=Z;c[pa+12>>2]=pa;c[pa+8>>2]=pa;break}ea=c[Z>>2]|0;k:do if((c[ea+4>>2]&-8|0)!=(ia|0)){Z=ia<<((Ua|0)==31?0:25-(Ua>>>1)|0);T=ea;while(1){fa=T+16+(Z>>>31<<2)|0;ca=c[fa>>2]|0;if(!ca){Va=fa;Wa=T;break}if((c[ca+4>>2]&-8|0)==(ia|0)){Xa=ca;break k}else{Z=Z<<1;T=ca}}if(Va>>>0<(c[492]|0)>>>0)ka();else{c[Va>>2]=pa;c[pa+24>>2]=Wa;c[pa+12>>2]=pa;c[pa+8>>2]=pa;break g}}else Xa=ea;while(0);ea=Xa+8|0;ia=c[ea>>2]|0;oa=c[492]|0;if(ia>>>0>=oa>>>0&Xa>>>0>=oa>>>0){c[ia+12>>2]=pa;c[ea>>2]=pa;c[pa+8>>2]=ia;c[pa+12>>2]=Xa;c[pa+24>>2]=0;break}else ka()}}else{ia=c[492]|0;if((ia|0)==0|ga>>>0<ia>>>0)c[492]=ga;c[600]=ga;c[601]=ha;c[603]=0;c[497]=c[606];c[496]=-1;ia=0;do{ea=ia<<1;oa=1992+(ea<<2)|0;c[1992+(ea+3<<2)>>2]=oa;c[1992+(ea+2<<2)>>2]=oa;ia=ia+1|0}while((ia|0)!=32);ia=ga+8|0;oa=(ia&7|0)==0?0:0-ia&7;ia=ha+-40-oa|0;c[494]=ga+oa;c[491]=ia;c[ga+(oa+4)>>2]=ia|1;c[ga+(ha+-36)>>2]=40;c[495]=c[610]}while(0);ha=c[491]|0;if(ha>>>0>F>>>0){ga=ha-F|0;c[491]=ga;ha=c[494]|0;c[494]=ha+F;c[ha+(F+4)>>2]=ga|1;c[ha+4>>2]=F|3;n=ha+8|0;return n|0}}c[(wa()|0)>>2]=12;n=0;return n|0}function Pb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;if(!a)return;b=a+-8|0;d=c[492]|0;if(b>>>0<d>>>0)ka();e=c[a+-4>>2]|0;f=e&3;if((f|0)==1)ka();g=e&-8;h=a+(g+-8)|0;do if(!(e&1)){i=c[b>>2]|0;if(!f)return;j=-8-i|0;k=a+j|0;l=i+g|0;if(k>>>0<d>>>0)ka();if((k|0)==(c[493]|0)){m=a+(g+-4)|0;n=c[m>>2]|0;if((n&3|0)!=3){o=k;p=l;break}c[490]=l;c[m>>2]=n&-2;c[a+(j+4)>>2]=l|1;c[h>>2]=l;return}n=i>>>3;if(i>>>0<256){i=c[a+(j+8)>>2]|0;m=c[a+(j+12)>>2]|0;q=1992+(n<<1<<2)|0;if((i|0)!=(q|0)){if(i>>>0<d>>>0)ka();if((c[i+12>>2]|0)!=(k|0))ka()}if((m|0)==(i|0)){c[488]=c[488]&~(1<<n);o=k;p=l;break}if((m|0)!=(q|0)){if(m>>>0<d>>>0)ka();q=m+8|0;if((c[q>>2]|0)==(k|0))r=q;else ka()}else r=m+8|0;c[i+12>>2]=m;c[r>>2]=i;o=k;p=l;break}i=c[a+(j+24)>>2]|0;m=c[a+(j+12)>>2]|0;do if((m|0)==(k|0)){q=a+(j+20)|0;n=c[q>>2]|0;if(!n){s=a+(j+16)|0;t=c[s>>2]|0;if(!t){u=0;break}else{v=t;w=s}}else{v=n;w=q}while(1){q=v+20|0;n=c[q>>2]|0;if(n){v=n;w=q;continue}q=v+16|0;n=c[q>>2]|0;if(!n){x=v;y=w;break}else{v=n;w=q}}if(y>>>0<d>>>0)ka();else{c[y>>2]=0;u=x;break}}else{q=c[a+(j+8)>>2]|0;if(q>>>0<d>>>0)ka();n=q+12|0;if((c[n>>2]|0)!=(k|0))ka();s=m+8|0;if((c[s>>2]|0)==(k|0)){c[n>>2]=m;c[s>>2]=q;u=m;break}else ka()}while(0);if(i){m=c[a+(j+28)>>2]|0;q=2256+(m<<2)|0;if((k|0)==(c[q>>2]|0)){c[q>>2]=u;if(!u){c[489]=c[489]&~(1<<m);o=k;p=l;break}}else{if(i>>>0<(c[492]|0)>>>0)ka();m=i+16|0;if((c[m>>2]|0)==(k|0))c[m>>2]=u;else c[i+20>>2]=u;if(!u){o=k;p=l;break}}m=c[492]|0;if(u>>>0<m>>>0)ka();c[u+24>>2]=i;q=c[a+(j+16)>>2]|0;do if(q)if(q>>>0<m>>>0)ka();else{c[u+16>>2]=q;c[q+24>>2]=u;break}while(0);q=c[a+(j+20)>>2]|0;if(q)if(q>>>0<(c[492]|0)>>>0)ka();else{c[u+20>>2]=q;c[q+24>>2]=u;o=k;p=l;break}else{o=k;p=l}}else{o=k;p=l}}else{o=b;p=g}while(0);if(o>>>0>=h>>>0)ka();b=a+(g+-4)|0;u=c[b>>2]|0;if(!(u&1))ka();if(!(u&2)){if((h|0)==(c[494]|0)){d=(c[491]|0)+p|0;c[491]=d;c[494]=o;c[o+4>>2]=d|1;if((o|0)!=(c[493]|0))return;c[493]=0;c[490]=0;return}if((h|0)==(c[493]|0)){d=(c[490]|0)+p|0;c[490]=d;c[493]=o;c[o+4>>2]=d|1;c[o+d>>2]=d;return}d=(u&-8)+p|0;x=u>>>3;do if(u>>>0>=256){y=c[a+(g+16)>>2]|0;w=c[a+(g|4)>>2]|0;do if((w|0)==(h|0)){v=a+(g+12)|0;r=c[v>>2]|0;if(!r){f=a+(g+8)|0;e=c[f>>2]|0;if(!e){z=0;break}else{A=e;B=f}}else{A=r;B=v}while(1){v=A+20|0;r=c[v>>2]|0;if(r){A=r;B=v;continue}v=A+16|0;r=c[v>>2]|0;if(!r){C=A;D=B;break}else{A=r;B=v}}if(D>>>0<(c[492]|0)>>>0)ka();else{c[D>>2]=0;z=C;break}}else{v=c[a+g>>2]|0;if(v>>>0<(c[492]|0)>>>0)ka();r=v+12|0;if((c[r>>2]|0)!=(h|0))ka();f=w+8|0;if((c[f>>2]|0)==(h|0)){c[r>>2]=w;c[f>>2]=v;z=w;break}else ka()}while(0);if(y){w=c[a+(g+20)>>2]|0;l=2256+(w<<2)|0;if((h|0)==(c[l>>2]|0)){c[l>>2]=z;if(!z){c[489]=c[489]&~(1<<w);break}}else{if(y>>>0<(c[492]|0)>>>0)ka();w=y+16|0;if((c[w>>2]|0)==(h|0))c[w>>2]=z;else c[y+20>>2]=z;if(!z)break}w=c[492]|0;if(z>>>0<w>>>0)ka();c[z+24>>2]=y;l=c[a+(g+8)>>2]|0;do if(l)if(l>>>0<w>>>0)ka();else{c[z+16>>2]=l;c[l+24>>2]=z;break}while(0);l=c[a+(g+12)>>2]|0;if(l)if(l>>>0<(c[492]|0)>>>0)ka();else{c[z+20>>2]=l;c[l+24>>2]=z;break}}}else{l=c[a+g>>2]|0;w=c[a+(g|4)>>2]|0;y=1992+(x<<1<<2)|0;if((l|0)!=(y|0)){if(l>>>0<(c[492]|0)>>>0)ka();if((c[l+12>>2]|0)!=(h|0))ka()}if((w|0)==(l|0)){c[488]=c[488]&~(1<<x);break}if((w|0)!=(y|0)){if(w>>>0<(c[492]|0)>>>0)ka();y=w+8|0;if((c[y>>2]|0)==(h|0))E=y;else ka()}else E=w+8|0;c[l+12>>2]=w;c[E>>2]=l}while(0);c[o+4>>2]=d|1;c[o+d>>2]=d;if((o|0)==(c[493]|0)){c[490]=d;return}else F=d}else{c[b>>2]=u&-2;c[o+4>>2]=p|1;c[o+p>>2]=p;F=p}p=F>>>3;if(F>>>0<256){u=p<<1;b=1992+(u<<2)|0;d=c[488]|0;E=1<<p;if(d&E){p=1992+(u+2<<2)|0;h=c[p>>2]|0;if(h>>>0<(c[492]|0)>>>0)ka();else{G=p;H=h}}else{c[488]=d|E;G=1992+(u+2<<2)|0;H=b}c[G>>2]=o;c[H+12>>2]=o;c[o+8>>2]=H;c[o+12>>2]=b;return}b=F>>>8;if(b)if(F>>>0>16777215)I=31;else{H=(b+1048320|0)>>>16&8;G=b<<H;b=(G+520192|0)>>>16&4;u=G<<b;G=(u+245760|0)>>>16&2;E=14-(b|H|G)+(u<<G>>>15)|0;I=F>>>(E+7|0)&1|E<<1}else I=0;E=2256+(I<<2)|0;c[o+28>>2]=I;c[o+20>>2]=0;c[o+16>>2]=0;G=c[489]|0;u=1<<I;a:do if(G&u){H=c[E>>2]|0;b:do if((c[H+4>>2]&-8|0)!=(F|0)){b=F<<((I|0)==31?0:25-(I>>>1)|0);d=H;while(1){h=d+16+(b>>>31<<2)|0;p=c[h>>2]|0;if(!p){J=h;K=d;break}if((c[p+4>>2]&-8|0)==(F|0)){L=p;break b}else{b=b<<1;d=p}}if(J>>>0<(c[492]|0)>>>0)ka();else{c[J>>2]=o;c[o+24>>2]=K;c[o+12>>2]=o;c[o+8>>2]=o;break a}}else L=H;while(0);H=L+8|0;d=c[H>>2]|0;b=c[492]|0;if(d>>>0>=b>>>0&L>>>0>=b>>>0){c[d+12>>2]=o;c[H>>2]=o;c[o+8>>2]=d;c[o+12>>2]=L;c[o+24>>2]=0;break}else ka()}else{c[489]=G|u;c[E>>2]=o;c[o+24>>2]=E;c[o+12>>2]=o;c[o+8>>2]=o}while(0);o=(c[496]|0)+-1|0;c[496]=o;if(!o)M=2408;else return;while(1){o=c[M>>2]|0;if(!o)break;else M=o+8|0}c[496]=-1;return}function Qb(a,b){a=a|0;b=b|0;var d=0,e=0;if(a){d=_(b,a)|0;if((b|a)>>>0>65535)e=((d>>>0)/(a>>>0)|0|0)==(b|0)?d:-1;else e=d}else e=0;d=Ob(e)|0;if(!d)return d|0;if(!(c[d+-4>>2]&3))return d|0;Ub(d|0,0,e|0)|0;return d|0}function Rb(){}function Sb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=b-d>>>0;e=b-d-(c>>>0>a>>>0|0)>>>0;return (C=e,a-c>>>0|0)|0}function Tb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=a+c>>>0;return (C=b+d+(e>>>0<a>>>0|0)>>>0,e|0)|0}function Ub(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=b+e|0;if((e|0)>=20){d=d&255;g=b&3;h=d|d<<8|d<<16|d<<24;i=f&~3;if(g){g=b+4-g|0;while((b|0)<(g|0)){a[b>>0]=d;b=b+1|0}}while((b|0)<(i|0)){c[b>>2]=h;b=b+4|0}}while((b|0)<(f|0)){a[b>>0]=d;b=b+1|0}return b-e|0}function Vb(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){C=b<<c|(a&(1<<c)-1<<32-c)>>>32-c;return a<<c}C=a<<c-32;return 0}function Wb(b){b=b|0;var c=0;c=b;while(a[c>>0]|0)c=c+1|0;return c-b|0}function Xb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if((e|0)>=4096)return ra(b|0,d|0,e|0)|0;f=b|0;if((b&3)==(d&3)){while(b&3){if(!e)return f|0;a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function Yb(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){C=b>>>c;return a>>>c|(b&(1<<c)-1)<<32-c}C=0;return b>>>c-32|0}function Zb(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){C=b>>c;return a>>>c|(b&(1<<c)-1)<<32-c}C=(b|0)<0?-1:0;return b>>c-32|0}function _b(b){b=b|0;var c=0;c=a[m+(b&255)>>0]|0;if((c|0)<8)return c|0;c=a[m+(b>>8&255)>>0]|0;if((c|0)<8)return c+8|0;c=a[m+(b>>16&255)>>0]|0;if((c|0)<8)return c+16|0;return (a[m+(b>>>24)>>0]|0)+24|0}function $b(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;c=a&65535;d=b&65535;e=_(d,c)|0;f=a>>>16;a=(e>>>16)+(_(d,f)|0)|0;d=b>>>16;b=_(d,c)|0;return (C=(a>>>16)+(_(d,f)|0)+(((a&65535)+b|0)>>>16)|0,a+b<<16|e&65535|0)|0}function ac(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;e=b>>31|((b|0)<0?-1:0)<<1;f=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;g=d>>31|((d|0)<0?-1:0)<<1;h=((d|0)<0?-1:0)>>31|((d|0)<0?-1:0)<<1;i=Sb(e^a,f^b,e,f)|0;b=C;a=g^e;e=h^f;return Sb((fc(i,b,Sb(g^c,h^d,g,h)|0,C,0)|0)^a,C^e,a,e)|0}function bc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+8|0;g=f|0;h=b>>31|((b|0)<0?-1:0)<<1;j=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;k=e>>31|((e|0)<0?-1:0)<<1;l=((e|0)<0?-1:0)>>31|((e|0)<0?-1:0)<<1;m=Sb(h^a,j^b,h,j)|0;b=C;fc(m,b,Sb(k^d,l^e,k,l)|0,C,g)|0;l=Sb(c[g>>2]^h,c[g+4>>2]^j,h,j)|0;j=C;i=f;return (C=j,l)|0}function cc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=a;a=c;c=$b(e,a)|0;f=C;return (C=(_(b,a)|0)+(_(d,e)|0)+f|f&0,c|0|0)|0}function dc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return fc(a,b,c,d,0)|0}function ec(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=i;i=i+8|0;g=f|0;fc(a,b,d,e,g)|0;i=f;return (C=c[g+4>>2]|0,c[g>>2]|0)|0}function fc(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,D=0,E=0,F=0,G=0,H=0;g=a;h=b;i=h;j=d;k=e;l=k;if(!i){m=(f|0)!=0;if(!l){if(m){c[f>>2]=(g>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(g>>>0)/(j>>>0)>>>0;return (C=n,o)|0}else{if(!m){n=0;o=0;return (C=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=b&0;n=0;o=0;return (C=n,o)|0}}m=(l|0)==0;do if(j){if(!m){p=(aa(l|0)|0)-(aa(i|0)|0)|0;if(p>>>0<=31){q=p+1|0;r=31-p|0;s=p-31>>31;t=q;u=g>>>(q>>>0)&s|i<<r;v=i>>>(q>>>0)&s;w=0;x=g<<r;break}if(!f){n=0;o=0;return (C=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return (C=n,o)|0}r=j-1|0;if(r&j){s=(aa(j|0)|0)+33-(aa(i|0)|0)|0;q=64-s|0;p=32-s|0;y=p>>31;z=s-32|0;A=z>>31;t=s;u=p-1>>31&i>>>(z>>>0)|(i<<p|g>>>(s>>>0))&A;v=A&i>>>(s>>>0);w=g<<q&y;x=(i<<q|g>>>(z>>>0))&y|g<<p&s-33>>31;break}if(f){c[f>>2]=r&g;c[f+4>>2]=0}if((j|0)==1){n=h|b&0;o=a|0|0;return (C=n,o)|0}else{r=_b(j|0)|0;n=i>>>(r>>>0)|0;o=i<<32-r|g>>>(r>>>0)|0;return (C=n,o)|0}}else{if(m){if(f){c[f>>2]=(i>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(i>>>0)/(j>>>0)>>>0;return (C=n,o)|0}if(!g){if(f){c[f>>2]=0;c[f+4>>2]=(i>>>0)%(l>>>0)}n=0;o=(i>>>0)/(l>>>0)>>>0;return (C=n,o)|0}r=l-1|0;if(!(r&l)){if(f){c[f>>2]=a|0;c[f+4>>2]=r&i|b&0}n=0;o=i>>>((_b(l|0)|0)>>>0);return (C=n,o)|0}r=(aa(l|0)|0)-(aa(i|0)|0)|0;if(r>>>0<=30){s=r+1|0;p=31-r|0;t=s;u=i<<p|g>>>(s>>>0);v=i>>>(s>>>0);w=0;x=g<<p;break}if(!f){n=0;o=0;return (C=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return (C=n,o)|0}while(0);if(!t){B=x;D=w;E=v;F=u;G=0;H=0}else{b=d|0|0;d=k|e&0;e=Tb(b|0,d|0,-1,-1)|0;k=C;h=x;x=w;w=v;v=u;u=t;t=0;do{a=h;h=x>>>31|h<<1;x=t|x<<1;g=v<<1|a>>>31|0;a=v>>>31|w<<1|0;Sb(e,k,g,a)|0;i=C;l=i>>31|((i|0)<0?-1:0)<<1;t=l&1;v=Sb(g,a,l&b,(((i|0)<0?-1:0)>>31|((i|0)<0?-1:0)<<1)&d)|0;w=C;u=u-1|0}while((u|0)!=0);B=h;D=x;E=w;F=v;G=0;H=t}t=D;D=0;if(f){c[f>>2]=F;c[f+4>>2]=E}n=(t|0)>>>31|(B|D)<<1|(D<<1|t>>>31)&0|G;o=(t<<1|0>>>31)&-2|H;return (C=n,o)|0}function gc(a,b,c){a=a|0;b=b|0;c=c|0;ya[a&7](b|0,c|0)}function hc(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;za[a&7](b|0,c|0,d|0,e|0)}function ic(a,b){a=a|0;b=b|0;ba(0)}function jc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;ba(1)}
+
+// EMSCRIPTEN_END_FUNCS
+var ya=[ic,zb,Ab,Bb,Cb,ic,ic,ic];var za=[jc,Db,Eb,Fb,Gb,jc,jc,jc];return{_ogv_video_decoder_init:Ib,_free:Pb,_ogv_video_decoder_process_header:Jb,_i64Add:Tb,_ogv_video_decoder_destroy:Lb,_i64Subtract:Sb,_memset:Ub,_malloc:Ob,_memcpy:Xb,_strlen:Wb,_ogv_video_decoder_process_frame:Kb,_bitshift64Shl:Vb,runPostSets:Rb,stackAlloc:Aa,stackSave:Ba,stackRestore:Ca,establishStackSpace:Da,setThrew:Ea,setTempRet0:Ha,getTempRet0:Ia,dynCall_vii:gc,dynCall_viiii:hc}})
+
+
+// EMSCRIPTEN_END_ASM
+(Module.asmGlobalArg,Module.asmLibraryArg,buffer);var _ogv_video_decoder_init=Module["_ogv_video_decoder_init"]=asm["_ogv_video_decoder_init"];var _free=Module["_free"]=asm["_free"];var runPostSets=Module["runPostSets"]=asm["runPostSets"];var _ogv_video_decoder_process_header=Module["_ogv_video_decoder_process_header"]=asm["_ogv_video_decoder_process_header"];var _i64Add=Module["_i64Add"]=asm["_i64Add"];var _ogv_video_decoder_destroy=Module["_ogv_video_decoder_destroy"]=asm["_ogv_video_decoder_destroy"];var _i64Subtract=Module["_i64Subtract"]=asm["_i64Subtract"];var _memset=Module["_memset"]=asm["_memset"];var _malloc=Module["_malloc"]=asm["_malloc"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _strlen=Module["_strlen"]=asm["_strlen"];var _ogv_video_decoder_process_frame=Module["_ogv_video_decoder_process_frame"]=asm["_ogv_video_decoder_process_frame"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var dynCall_vii=Module["dynCall_vii"]=asm["dynCall_vii"];var dynCall_viiii=Module["dynCall_viiii"]=asm["dynCall_viiii"];Runtime.stackAlloc=asm["stackAlloc"];Runtime.stackSave=asm["stackSave"];Runtime.stackRestore=asm["stackRestore"];Runtime.establishStackSpace=asm["establishStackSpace"];Runtime.setTempRet0=asm["setTempRet0"];Runtime.getTempRet0=asm["getTempRet0"];var i64Math=(function(){var goog={math:{}};goog.math.Long=(function(low,high){this.low_=low|0;this.high_=high|0});goog.math.Long.IntCache_={};goog.math.Long.fromInt=(function(value){if(-128<=value&&value<128){var cachedObj=goog.math.Long.IntCache_[value];if(cachedObj){return cachedObj}}var obj=new goog.math.Long(value|0,value<0?-1:0);if(-128<=value&&value<128){goog.math.Long.IntCache_[value]=obj}return obj});goog.math.Long.fromNumber=(function(value){if(isNaN(value)||!isFinite(value)){return goog.math.Long.ZERO}else if(value<=-goog.math.Long.TWO_PWR_63_DBL_){return goog.math.Long.MIN_VALUE}else if(value+1>=goog.math.Long.TWO_PWR_63_DBL_){return goog.math.Long.MAX_VALUE}else if(value<0){return goog.math.Long.fromNumber(-value).negate()}else{return new goog.math.Long(value%goog.math.Long.TWO_PWR_32_DBL_|0,value/goog.math.Long.TWO_PWR_32_DBL_|0)}});goog.math.Long.fromBits=(function(lowBits,highBits){return new goog.math.Long(lowBits,highBits)});goog.math.Long.fromString=(function(str,opt_radix){if(str.length==0){throw Error("number format error: empty string")}var radix=opt_radix||10;if(radix<2||36<radix){throw Error("radix out of range: "+radix)}if(str.charAt(0)=="-"){return goog.math.Long.fromString(str.substring(1),radix).negate()}else if(str.indexOf("-")>=0){throw Error('number format error: interior "-" character: '+str)}var radixToPower=goog.math.Long.fromNumber(Math.pow(radix,8));var result=goog.math.Long.ZERO;for(var i=0;i<str.length;i+=8){var size=Math.min(8,str.length-i);var value=parseInt(str.substring(i,i+size),radix);if(size<8){var power=goog.math.Long.fromNumber(Math.pow(radix,size));result=result.multiply(power).add(goog.math.Long.fromNumber(value))}else{result=result.multiply(radixToPower);result=result.add(goog.math.Long.fromNumber(value))}}return result});goog.math.Long.TWO_PWR_16_DBL_=1<<16;goog.math.Long.TWO_PWR_24_DBL_=1<<24;goog.math.Long.TWO_PWR_32_DBL_=goog.math.Long.TWO_PWR_16_DBL_*goog.math.Long.TWO_PWR_16_DBL_;goog.math.Long.TWO_PWR_31_DBL_=goog.math.Long.TWO_PWR_32_DBL_/2;goog.math.Long.TWO_PWR_48_DBL_=goog.math.Long.TWO_PWR_32_DBL_*goog.math.Long.TWO_PWR_16_DBL_;goog.math.Long.TWO_PWR_64_DBL_=goog.math.Long.TWO_PWR_32_DBL_*goog.math.Long.TWO_PWR_32_DBL_;goog.math.Long.TWO_PWR_63_DBL_=goog.math.Long.TWO_PWR_64_DBL_/2;goog.math.Long.ZERO=goog.math.Long.fromInt(0);goog.math.Long.ONE=goog.math.Long.fromInt(1);goog.math.Long.NEG_ONE=goog.math.Long.fromInt(-1);goog.math.Long.MAX_VALUE=goog.math.Long.fromBits(4294967295|0,2147483647|0);goog.math.Long.MIN_VALUE=goog.math.Long.fromBits(0,2147483648|0);goog.math.Long.TWO_PWR_24_=goog.math.Long.fromInt(1<<24);goog.math.Long.prototype.toInt=(function(){return this.low_});goog.math.Long.prototype.toNumber=(function(){return this.high_*goog.math.Long.TWO_PWR_32_DBL_+this.getLowBitsUnsigned()});goog.math.Long.prototype.toString=(function(opt_radix){var radix=opt_radix||10;if(radix<2||36<radix){throw Error("radix out of range: "+radix)}if(this.isZero()){return"0"}if(this.isNegative()){if(this.equals(goog.math.Long.MIN_VALUE)){var radixLong=goog.math.Long.fromNumber(radix);var div=this.div(radixLong);var rem=div.multiply(radixLong).subtract(this);return div.toString(radix)+rem.toInt().toString(radix)}else{return"-"+this.negate().toString(radix)}}var radixToPower=goog.math.Long.fromNumber(Math.pow(radix,6));var rem=this;var result="";while(true){var remDiv=rem.div(radixToPower);var intval=rem.subtract(remDiv.multiply(radixToPower)).toInt();var digits=intval.toString(radix);rem=remDiv;if(rem.isZero()){return digits+result}else{while(digits.length<6){digits="0"+digits}result=""+digits+result}}});goog.math.Long.prototype.getHighBits=(function(){return this.high_});goog.math.Long.prototype.getLowBits=(function(){return this.low_});goog.math.Long.prototype.getLowBitsUnsigned=(function(){return this.low_>=0?this.low_:goog.math.Long.TWO_PWR_32_DBL_+this.low_});goog.math.Long.prototype.getNumBitsAbs=(function(){if(this.isNegative()){if(this.equals(goog.math.Long.MIN_VALUE)){return 64}else{return this.negate().getNumBitsAbs()}}else{var val=this.high_!=0?this.high_:this.low_;for(var bit=31;bit>0;bit--){if((val&1<<bit)!=0){break}}return this.high_!=0?bit+33:bit+1}});goog.math.Long.prototype.isZero=(function(){return this.high_==0&&this.low_==0});goog.math.Long.prototype.isNegative=(function(){return this.high_<0});goog.math.Long.prototype.isOdd=(function(){return(this.low_&1)==1});goog.math.Long.prototype.equals=(function(other){return this.high_==other.high_&&this.low_==other.low_});goog.math.Long.prototype.notEquals=(function(other){return this.high_!=other.high_||this.low_!=other.low_});goog.math.Long.prototype.lessThan=(function(other){return this.compare(other)<0});goog.math.Long.prototype.lessThanOrEqual=(function(other){return this.compare(other)<=0});goog.math.Long.prototype.greaterThan=(function(other){return this.compare(other)>0});goog.math.Long.prototype.greaterThanOrEqual=(function(other){return this.compare(other)>=0});goog.math.Long.prototype.compare=(function(other){if(this.equals(other)){return 0}var thisNeg=this.isNegative();var otherNeg=other.isNegative();if(thisNeg&&!otherNeg){return-1}if(!thisNeg&&otherNeg){return 1}if(this.subtract(other).isNegative()){return-1}else{return 1}});goog.math.Long.prototype.negate=(function(){if(this.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.MIN_VALUE}else{return this.not().add(goog.math.Long.ONE)}});goog.math.Long.prototype.add=(function(other){var a48=this.high_>>>16;var a32=this.high_&65535;var a16=this.low_>>>16;var a00=this.low_&65535;var b48=other.high_>>>16;var b32=other.high_&65535;var b16=other.low_>>>16;var b00=other.low_&65535;var c48=0,c32=0,c16=0,c00=0;c00+=a00+b00;c16+=c00>>>16;c00&=65535;c16+=a16+b16;c32+=c16>>>16;c16&=65535;c32+=a32+b32;c48+=c32>>>16;c32&=65535;c48+=a48+b48;c48&=65535;return goog.math.Long.fromBits(c16<<16|c00,c48<<16|c32)});goog.math.Long.prototype.subtract=(function(other){return this.add(other.negate())});goog.math.Long.prototype.multiply=(function(other){if(this.isZero()){return goog.math.Long.ZERO}else if(other.isZero()){return goog.math.Long.ZERO}if(this.equals(goog.math.Long.MIN_VALUE)){return other.isOdd()?goog.math.Long.MIN_VALUE:goog.math.Long.ZERO}else if(other.equals(goog.math.Long.MIN_VALUE)){return this.isOdd()?goog.math.Long.MIN_VALUE:goog.math.Long.ZERO}if(this.isNegative()){if(other.isNegative()){return this.negate().multiply(other.negate())}else{return this.negate().multiply(other).negate()}}else if(other.isNegative()){return this.multiply(other.negate()).negate()}if(this.lessThan(goog.math.Long.TWO_PWR_24_)&&other.lessThan(goog.math.Long.TWO_PWR_24_)){return goog.math.Long.fromNumber(this.toNumber()*other.toNumber())}var a48=this.high_>>>16;var a32=this.high_&65535;var a16=this.low_>>>16;var a00=this.low_&65535;var b48=other.high_>>>16;var b32=other.high_&65535;var b16=other.low_>>>16;var b00=other.low_&65535;var c48=0,c32=0,c16=0,c00=0;c00+=a00*b00;c16+=c00>>>16;c00&=65535;c16+=a16*b00;c32+=c16>>>16;c16&=65535;c16+=a00*b16;c32+=c16>>>16;c16&=65535;c32+=a32*b00;c48+=c32>>>16;c32&=65535;c32+=a16*b16;c48+=c32>>>16;c32&=65535;c32+=a00*b32;c48+=c32>>>16;c32&=65535;c48+=a48*b00+a32*b16+a16*b32+a00*b48;c48&=65535;return goog.math.Long.fromBits(c16<<16|c00,c48<<16|c32)});goog.math.Long.prototype.div=(function(other){if(other.isZero()){throw Error("division by zero")}else if(this.isZero()){return goog.math.Long.ZERO}if(this.equals(goog.math.Long.MIN_VALUE)){if(other.equals(goog.math.Long.ONE)||other.equals(goog.math.Long.NEG_ONE)){return goog.math.Long.MIN_VALUE}else if(other.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.ONE}else{var halfThis=this.shiftRight(1);var approx=halfThis.div(other).shiftLeft(1);if(approx.equals(goog.math.Long.ZERO)){return other.isNegative()?goog.math.Long.ONE:goog.math.Long.NEG_ONE}else{var rem=this.subtract(other.multiply(approx));var result=approx.add(rem.div(other));return result}}}else if(other.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.ZERO}if(this.isNegative()){if(other.isNegative()){return this.negate().div(other.negate())}else{return this.negate().div(other).negate()}}else if(other.isNegative()){return this.div(other.negate()).negate()}var res=goog.math.Long.ZERO;var rem=this;while(rem.greaterThanOrEqual(other)){var approx=Math.max(1,Math.floor(rem.toNumber()/other.toNumber()));var log2=Math.ceil(Math.log(approx)/Math.LN2);var delta=log2<=48?1:Math.pow(2,log2-48);var approxRes=goog.math.Long.fromNumber(approx);var approxRem=approxRes.multiply(other);while(approxRem.isNegative()||approxRem.greaterThan(rem)){approx-=delta;approxRes=goog.math.Long.fromNumber(approx);approxRem=approxRes.multiply(other)}if(approxRes.isZero()){approxRes=goog.math.Long.ONE}res=res.add(approxRes);rem=rem.subtract(approxRem)}return res});goog.math.Long.prototype.modulo=(function(other){return this.subtract(this.div(other).multiply(other))});goog.math.Long.prototype.not=(function(){return goog.math.Long.fromBits(~this.low_,~this.high_)});goog.math.Long.prototype.and=(function(other){return goog.math.Long.fromBits(this.low_&other.low_,this.high_&other.high_)});goog.math.Long.prototype.or=(function(other){return goog.math.Long.fromBits(this.low_|other.low_,this.high_|other.high_)});goog.math.Long.prototype.xor=(function(other){return goog.math.Long.fromBits(this.low_^other.low_,this.high_^other.high_)});goog.math.Long.prototype.shiftLeft=(function(numBits){numBits&=63;if(numBits==0){return this}else{var low=this.low_;if(numBits<32){var high=this.high_;return goog.math.Long.fromBits(low<<numBits,high<<numBits|low>>>32-numBits)}else{return goog.math.Long.fromBits(0,low<<numBits-32)}}});goog.math.Long.prototype.shiftRight=(function(numBits){numBits&=63;if(numBits==0){return this}else{var high=this.high_;if(numBits<32){var low=this.low_;return goog.math.Long.fromBits(low>>>numBits|high<<32-numBits,high>>numBits)}else{return goog.math.Long.fromBits(high>>numBits-32,high>=0?0:-1)}}});goog.math.Long.prototype.shiftRightUnsigned=(function(numBits){numBits&=63;if(numBits==0){return this}else{var high=this.high_;if(numBits<32){var low=this.low_;return goog.math.Long.fromBits(low>>>numBits|high<<32-numBits,high>>>numBits)}else if(numBits==32){return goog.math.Long.fromBits(high,0)}else{return goog.math.Long.fromBits(high>>>numBits-32,0)}}});var navigator={appName:"Modern Browser"};var dbits;var canary=0xdeadbeefcafe;var j_lm=(canary&16777215)==15715070;function BigInteger(a,b,c){if(a!=null)if("number"==typeof a)this.fromNumber(a,b,c);else if(b==null&&"string"!=typeof a)this.fromString(a,256);else this.fromString(a,b)}function nbi(){return new BigInteger(null)}function am1(i,x,w,j,c,n){while(--n>=0){var v=x*this[i++]+w[j]+c;c=Math.floor(v/67108864);w[j++]=v&67108863}return c}function am2(i,x,w,j,c,n){var xl=x&32767,xh=x>>15;while(--n>=0){var l=this[i]&32767;var h=this[i++]>>15;var m=xh*l+h*xl;l=xl*l+((m&32767)<<15)+w[j]+(c&1073741823);c=(l>>>30)+(m>>>15)+xh*h+(c>>>30);w[j++]=l&1073741823}return c}function am3(i,x,w,j,c,n){var xl=x&16383,xh=x>>14;while(--n>=0){var l=this[i]&16383;var h=this[i++]>>14;var m=xh*l+h*xl;l=xl*l+((m&16383)<<14)+w[j]+c;c=(l>>28)+(m>>14)+xh*h;w[j++]=l&268435455}return c}if(j_lm&&navigator.appName=="Microsoft Internet Explorer"){BigInteger.prototype.am=am2;dbits=30}else if(j_lm&&navigator.appName!="Netscape"){BigInteger.prototype.am=am1;dbits=26}else{BigInteger.prototype.am=am3;dbits=28}BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=(1<<dbits)-1;BigInteger.prototype.DV=1<<dbits;var BI_FP=52;BigInteger.prototype.FV=Math.pow(2,BI_FP);BigInteger.prototype.F1=BI_FP-dbits;BigInteger.prototype.F2=2*dbits-BI_FP;var BI_RM="0123456789abcdefghijklmnopqrstuvwxyz";var BI_RC=new Array;var rr,vv;rr="0".charCodeAt(0);for(vv=0;vv<=9;++vv)BI_RC[rr++]=vv;rr="a".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;rr="A".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;function int2char(n){return BI_RM.charAt(n)}function intAt(s,i){var c=BI_RC[s.charCodeAt(i)];return c==null?-1:c}function bnpCopyTo(r){for(var i=this.t-1;i>=0;--i)r[i]=this[i];r.t=this.t;r.s=this.s}function bnpFromInt(x){this.t=1;this.s=x<0?-1:0;if(x>0)this[0]=x;else if(x<-1)this[0]=x+DV;else this.t=0}function nbv(i){var r=nbi();r.fromInt(i);return r}function bnpFromString(s,b){var k;if(b==16)k=4;else if(b==8)k=3;else if(b==256)k=8;else if(b==2)k=1;else if(b==32)k=5;else if(b==4)k=2;else{this.fromRadix(s,b);return}this.t=0;this.s=0;var i=s.length,mi=false,sh=0;while(--i>=0){var x=k==8?s[i]&255:intAt(s,i);if(x<0){if(s.charAt(i)=="-")mi=true;continue}mi=false;if(sh==0)this[this.t++]=x;else if(sh+k>this.DB){this[this.t-1]|=(x&(1<<this.DB-sh)-1)<<sh;this[this.t++]=x>>this.DB-sh}else this[this.t-1]|=x<<sh;sh+=k;if(sh>=this.DB)sh-=this.DB}if(k==8&&(s[0]&128)!=0){this.s=-1;if(sh>0)this[this.t-1]|=(1<<this.DB-sh)-1<<sh}this.clamp();if(mi)BigInteger.ZERO.subTo(this,this)}function bnpClamp(){var c=this.s&this.DM;while(this.t>0&&this[this.t-1]==c)--this.t}function bnToString(b){if(this.s<0)return"-"+this.negate().toString(b);var k;if(b==16)k=4;else if(b==8)k=3;else if(b==2)k=1;else if(b==32)k=5;else if(b==4)k=2;else return this.toRadix(b);var km=(1<<k)-1,d,m=false,r="",i=this.t;var p=this.DB-i*this.DB%k;if(i-->0){if(p<this.DB&&(d=this[i]>>p)>0){m=true;r=int2char(d)}while(i>=0){if(p<k){d=(this[i]&(1<<p)-1)<<k-p;d|=this[--i]>>(p+=this.DB-k)}else{d=this[i]>>(p-=k)&km;if(p<=0){p+=this.DB;--i}}if(d>0)m=true;if(m)r+=int2char(d)}}return m?r:"0"}function bnNegate(){var r=nbi();BigInteger.ZERO.subTo(this,r);return r}function bnAbs(){return this.s<0?this.negate():this}function bnCompareTo(a){var r=this.s-a.s;if(r!=0)return r;var i=this.t;r=i-a.t;if(r!=0)return this.s<0?-r:r;while(--i>=0)if((r=this[i]-a[i])!=0)return r;return 0}function nbits(x){var r=1,t;if((t=x>>>16)!=0){x=t;r+=16}if((t=x>>8)!=0){x=t;r+=8}if((t=x>>4)!=0){x=t;r+=4}if((t=x>>2)!=0){x=t;r+=2}if((t=x>>1)!=0){x=t;r+=1}return r}function bnBitLength(){if(this.t<=0)return 0;return this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(n,r){var i;for(i=this.t-1;i>=0;--i)r[i+n]=this[i];for(i=n-1;i>=0;--i)r[i]=0;r.t=this.t+n;r.s=this.s}function bnpDRShiftTo(n,r){for(var i=n;i<this.t;++i)r[i-n]=this[i];r.t=Math.max(this.t-n,0);r.s=this.s}function bnpLShiftTo(n,r){var bs=n%this.DB;var cbs=this.DB-bs;var bm=(1<<cbs)-1;var ds=Math.floor(n/this.DB),c=this.s<<bs&this.DM,i;for(i=this.t-1;i>=0;--i){r[i+ds+1]=this[i]>>cbs|c;c=(this[i]&bm)<<bs}for(i=ds-1;i>=0;--i)r[i]=0;r[ds]=c;r.t=this.t+ds+1;r.s=this.s;r.clamp()}function bnpRShiftTo(n,r){r.s=this.s;var ds=Math.floor(n/this.DB);if(ds>=this.t){r.t=0;return}var bs=n%this.DB;var cbs=this.DB-bs;var bm=(1<<bs)-1;r[0]=this[ds]>>bs;for(var i=ds+1;i<this.t;++i){r[i-ds-1]|=(this[i]&bm)<<cbs;r[i-ds]=this[i]>>bs}if(bs>0)r[this.t-ds-1]|=(this.s&bm)<<cbs;r.t=this.t-ds;r.clamp()}function bnpSubTo(a,r){var i=0,c=0,m=Math.min(a.t,this.t);while(i<m){c+=this[i]-a[i];r[i++]=c&this.DM;c>>=this.DB}if(a.t<this.t){c-=a.s;while(i<this.t){c+=this[i];r[i++]=c&this.DM;c>>=this.DB}c+=this.s}else{c+=this.s;while(i<a.t){c-=a[i];r[i++]=c&this.DM;c>>=this.DB}c-=a.s}r.s=c<0?-1:0;if(c<-1)r[i++]=this.DV+c;else if(c>0)r[i++]=c;r.t=i;r.clamp()}function bnpMultiplyTo(a,r){var x=this.abs(),y=a.abs();var i=x.t;r.t=i+y.t;while(--i>=0)r[i]=0;for(i=0;i<y.t;++i)r[i+x.t]=x.am(0,y[i],r,i,0,x.t);r.s=0;r.clamp();if(this.s!=a.s)BigInteger.ZERO.subTo(r,r)}function bnpSquareTo(r){var x=this.abs();var i=r.t=2*x.t;while(--i>=0)r[i]=0;for(i=0;i<x.t-1;++i){var c=x.am(i,x[i],r,2*i,0,1);if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1))>=x.DV){r[i+x.t]-=x.DV;r[i+x.t+1]=1}}if(r.t>0)r[r.t-1]+=x.am(i,x[i],r,2*i,0,1);r.s=0;r.clamp()}function bnpDivRemTo(m,q,r){var pm=m.abs();if(pm.t<=0)return;var pt=this.abs();if(pt.t<pm.t){if(q!=null)q.fromInt(0);if(r!=null)this.copyTo(r);return}if(r==null)r=nbi();var y=nbi(),ts=this.s,ms=m.s;var nsh=this.DB-nbits(pm[pm.t-1]);if(nsh>0){pm.lShiftTo(nsh,y);pt.lShiftTo(nsh,r)}else{pm.copyTo(y);pt.copyTo(r)}var ys=y.t;var y0=y[ys-1];if(y0==0)return;var yt=y0*(1<<this.F1)+(ys>1?y[ys-2]>>this.F2:0);var d1=this.FV/yt,d2=(1<<this.F1)/yt,e=1<<this.F2;var i=r.t,j=i-ys,t=q==null?nbi():q;y.dlShiftTo(j,t);if(r.compareTo(t)>=0){r[r.t++]=1;r.subTo(t,r)}BigInteger.ONE.dlShiftTo(ys,t);t.subTo(y,y);while(y.t<ys)y[y.t++]=0;while(--j>=0){var qd=r[--i]==y0?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);if((r[i]+=y.am(0,qd,r,j,0,ys))<qd){y.dlShiftTo(j,t);r.subTo(t,r);while(r[i]<--qd)r.subTo(t,r)}}if(q!=null){r.drShiftTo(ys,q);if(ts!=ms)BigInteger.ZERO.subTo(q,q)}r.t=ys;r.clamp();if(nsh>0)r.rShiftTo(nsh,r);if(ts<0)BigInteger.ZERO.subTo(r,r)}function bnMod(a){var r=nbi();this.abs().divRemTo(a,null,r);if(this.s<0&&r.compareTo(BigInteger.ZERO)>0)a.subTo(r,r);return r}function Classic(m){this.m=m}function cConvert(x){if(x.s<0||x.compareTo(this.m)>=0)return x.mod(this.m);else return x}function cRevert(x){return x}function cReduce(x){x.divRemTo(this.m,null,x)}function cMulTo(x,y,r){x.multiplyTo(y,r);this.reduce(r)}function cSqrTo(x,r){x.squareTo(r);this.reduce(r)}Classic.prototype.convert=cConvert;Classic.prototype.revert=cRevert;Classic.prototype.reduce=cReduce;Classic.prototype.mulTo=cMulTo;Classic.prototype.sqrTo=cSqrTo;function bnpInvDigit(){if(this.t<1)return 0;var x=this[0];if((x&1)==0)return 0;var y=x&3;y=y*(2-(x&15)*y)&15;y=y*(2-(x&255)*y)&255;y=y*(2-((x&65535)*y&65535))&65535;y=y*(2-x*y%this.DV)%this.DV;return y>0?this.DV-y:-y}function Montgomery(m){this.m=m;this.mp=m.invDigit();this.mpl=this.mp&32767;this.mph=this.mp>>15;this.um=(1<<m.DB-15)-1;this.mt2=2*m.t}function montConvert(x){var r=nbi();x.abs().dlShiftTo(this.m.t,r);r.divRemTo(this.m,null,r);if(x.s<0&&r.compareTo(BigInteger.ZERO)>0)this.m.subTo(r,r);return r}function montRevert(x){var r=nbi();x.copyTo(r);this.reduce(r);return r}function montReduce(x){while(x.t<=this.mt2)x[x.t++]=0;for(var i=0;i<this.m.t;++i){var j=x[i]&32767;var u0=j*this.mpl+((j*this.mph+(x[i]>>15)*this.mpl&this.um)<<15)&x.DM;j=i+this.m.t;x[j]+=this.m.am(0,u0,x,i,0,this.m.t);while(x[j]>=x.DV){x[j]-=x.DV;x[++j]++}}x.clamp();x.drShiftTo(this.m.t,x);if(x.compareTo(this.m)>=0)x.subTo(this.m,x)}function montSqrTo(x,r){x.squareTo(r);this.reduce(r)}function montMulTo(x,y,r){x.multiplyTo(y,r);this.reduce(r)}Montgomery.prototype.convert=montConvert;Montgomery.prototype.revert=montRevert;Montgomery.prototype.reduce=montReduce;Montgomery.prototype.mulTo=montMulTo;Montgomery.prototype.sqrTo=montSqrTo;function bnpIsEven(){return(this.t>0?this[0]&1:this.s)==0}function bnpExp(e,z){if(e>4294967295||e<1)return BigInteger.ONE;var r=nbi(),r2=nbi(),g=z.convert(this),i=nbits(e)-1;g.copyTo(r);while(--i>=0){z.sqrTo(r,r2);if((e&1<<i)>0)z.mulTo(r2,g,r);else{var t=r;r=r2;r2=t}}return z.revert(r)}function bnModPowInt(e,m){var z;if(e<256||m.isEven())z=new Classic(m);else z=new Montgomery(m);return this.exp(e,z)}BigInteger.prototype.copyTo=bnpCopyTo;BigInteger.prototype.fromInt=bnpFromInt;BigInteger.prototype.fromString=bnpFromString;BigInteger.prototype.clamp=bnpClamp;BigInteger.prototype.dlShiftTo=bnpDLShiftTo;BigInteger.prototype.drShiftTo=bnpDRShiftTo;BigInteger.prototype.lShiftTo=bnpLShiftTo;BigInteger.prototype.rShiftTo=bnpRShiftTo;BigInteger.prototype.subTo=bnpSubTo;BigInteger.prototype.multiplyTo=bnpMultiplyTo;BigInteger.prototype.squareTo=bnpSquareTo;BigInteger.prototype.divRemTo=bnpDivRemTo;BigInteger.prototype.invDigit=bnpInvDigit;BigInteger.prototype.isEven=bnpIsEven;BigInteger.prototype.exp=bnpExp;BigInteger.prototype.toString=bnToString;BigInteger.prototype.negate=bnNegate;BigInteger.prototype.abs=bnAbs;BigInteger.prototype.compareTo=bnCompareTo;BigInteger.prototype.bitLength=bnBitLength;BigInteger.prototype.mod=bnMod;BigInteger.prototype.modPowInt=bnModPowInt;BigInteger.ZERO=nbv(0);BigInteger.ONE=nbv(1);function bnpFromRadix(s,b){this.fromInt(0);if(b==null)b=10;var cs=this.chunkSize(b);var d=Math.pow(b,cs),mi=false,j=0,w=0;for(var i=0;i<s.length;++i){var x=intAt(s,i);if(x<0){if(s.charAt(i)=="-"&&this.signum()==0)mi=true;continue}w=b*w+x;if(++j>=cs){this.dMultiply(d);this.dAddOffset(w,0);j=0;w=0}}if(j>0){this.dMultiply(Math.pow(b,j));this.dAddOffset(w,0)}if(mi)BigInteger.ZERO.subTo(this,this)}function bnpChunkSize(r){return Math.floor(Math.LN2*this.DB/Math.log(r))}function bnSigNum(){if(this.s<0)return-1;else if(this.t<=0||this.t==1&&this[0]<=0)return 0;else return 1}function bnpDMultiply(n){this[this.t]=this.am(0,n-1,this,0,0,this.t);++this.t;this.clamp()}function bnpDAddOffset(n,w){if(n==0)return;while(this.t<=w)this[this.t++]=0;this[w]+=n;while(this[w]>=this.DV){this[w]-=this.DV;if(++w>=this.t)this[this.t++]=0;++this[w]}}function bnpToRadix(b){if(b==null)b=10;if(this.signum()==0||b<2||b>36)return"0";var cs=this.chunkSize(b);var a=Math.pow(b,cs);var d=nbv(a),y=nbi(),z=nbi(),r="";this.divRemTo(d,y,z);while(y.signum()>0){r=(a+z.intValue()).toString(b).substr(1)+r;y.divRemTo(d,y,z)}return z.intValue().toString(b)+r}function bnIntValue(){if(this.s<0){if(this.t==1)return this[0]-this.DV;else if(this.t==0)return-1}else if(this.t==1)return this[0];else if(this.t==0)return 0;return(this[1]&(1<<32-this.DB)-1)<<this.DB|this[0]}function bnpAddTo(a,r){var i=0,c=0,m=Math.min(a.t,this.t);while(i<m){c+=this[i]+a[i];r[i++]=c&this.DM;c>>=this.DB}if(a.t<this.t){c+=a.s;while(i<this.t){c+=this[i];r[i++]=c&this.DM;c>>=this.DB}c+=this.s}else{c+=this.s;while(i<a.t){c+=a[i];r[i++]=c&this.DM;c>>=this.DB}c+=a.s}r.s=c<0?-1:0;if(c>0)r[i++]=c;else if(c<-1)r[i++]=this.DV+c;r.t=i;r.clamp()}BigInteger.prototype.fromRadix=bnpFromRadix;BigInteger.prototype.chunkSize=bnpChunkSize;BigInteger.prototype.signum=bnSigNum;BigInteger.prototype.dMultiply=bnpDMultiply;BigInteger.prototype.dAddOffset=bnpDAddOffset;BigInteger.prototype.toRadix=bnpToRadix;BigInteger.prototype.intValue=bnIntValue;BigInteger.prototype.addTo=bnpAddTo;var Wrapper={abs:(function(l,h){var x=new goog.math.Long(l,h);var ret;if(x.isNegative()){ret=x.negate()}else{ret=x}HEAP32[tempDoublePtr>>2]=ret.low_;HEAP32[tempDoublePtr+4>>2]=ret.high_}),ensureTemps:(function(){if(Wrapper.ensuredTemps)return;Wrapper.ensuredTemps=true;Wrapper.two32=new BigInteger;Wrapper.two32.fromString("4294967296",10);Wrapper.two64=new BigInteger;Wrapper.two64.fromString("18446744073709551616",10);Wrapper.temp1=new BigInteger;Wrapper.temp2=new BigInteger}),lh2bignum:(function(l,h){var a=new BigInteger;a.fromString(h.toString(),10);var b=new BigInteger;a.multiplyTo(Wrapper.two32,b);var c=new BigInteger;c.fromString(l.toString(),10);var d=new BigInteger;c.addTo(b,d);return d}),stringify:(function(l,h,unsigned){var ret=(new goog.math.Long(l,h)).toString();if(unsigned&&ret[0]=="-"){Wrapper.ensureTemps();var bignum=new BigInteger;bignum.fromString(ret,10);ret=new BigInteger;Wrapper.two64.addTo(bignum,ret);ret=ret.toString(10)}return ret}),fromString:(function(str,base,min,max,unsigned){Wrapper.ensureTemps();var bignum=new BigInteger;bignum.fromString(str,base);var bigmin=new BigInteger;bigmin.fromString(min,10);var bigmax=new BigInteger;bigmax.fromString(max,10);if(unsigned&&bignum.compareTo(BigInteger.ZERO)<0){var temp=new BigInteger;bignum.addTo(Wrapper.two64,temp);bignum=temp}var error=false;if(bignum.compareTo(bigmin)<0){bignum=bigmin;error=true}else if(bignum.compareTo(bigmax)>0){bignum=bigmax;error=true}var ret=goog.math.Long.fromString(bignum.toString());HEAP32[tempDoublePtr>>2]=ret.low_;HEAP32[tempDoublePtr+4>>2]=ret.high_;if(error)throw"range error"})};return Wrapper})();function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}ExitStatus.prototype=new Error;ExitStatus.prototype.constructor=ExitStatus;var initialStackTop;var preloadStartTime=null;var calledMain=false;dependenciesFulfilled=function runCaller(){if(!Module["calledRun"])run();if(!Module["calledRun"])dependenciesFulfilled=runCaller};Module["callMain"]=Module.callMain=function callMain(args){assert(runDependencies==0,"cannot call main when async dependencies remain! (listen on __ATMAIN__)");assert(__ATPRERUN__.length==0,"cannot call main when preRun functions remain to be called");args=args||[];ensureInitRuntime();var argc=args.length+1;function pad(){for(var i=0;i<4-1;i++){argv.push(0)}}var argv=[allocate(intArrayFromString(Module["thisProgram"]),"i8",ALLOC_NORMAL)];pad();for(var i=0;i<argc-1;i=i+1){argv.push(allocate(intArrayFromString(args[i]),"i8",ALLOC_NORMAL));pad()}argv.push(0);argv=allocate(argv,"i32",ALLOC_NORMAL);initialStackTop=STACKTOP;try{var ret=Module["_main"](argc,argv,0);exit(ret,true)}catch(e){if(e instanceof ExitStatus){return}else if(e=="SimulateInfiniteLoop"){Module["noExitRuntime"]=true;return}else{if(e&&typeof e==="object"&&e.stack)Module.printErr("exception thrown: "+[e,e.stack]);throw e}}finally{calledMain=true}};function run(args){args=args||Module["arguments"];if(preloadStartTime===null)preloadStartTime=Date.now();if(runDependencies>0){return}preRun();if(runDependencies>0)return;if(Module["calledRun"])return;function doRun(){if(Module["calledRun"])return;Module["calledRun"]=true;if(ABORT)return;ensureInitRuntime();preMain();if(ENVIRONMENT_IS_WEB&&preloadStartTime!==null){Module.printErr("pre-main prep time: "+(Date.now()-preloadStartTime)+" ms")}if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(Module["_main"]&&shouldRunNow)Module["callMain"](args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout((function(){setTimeout((function(){Module["setStatus"]("")}),1);doRun()}),1)}else{doRun()}}Module["run"]=Module.run=run;function exit(status,implicit){if(implicit&&Module["noExitRuntime"]){return}if(Module["noExitRuntime"]){}else{ABORT=true;EXITSTATUS=status;STACKTOP=initialStackTop;exitRuntime();if(Module["onExit"])Module["onExit"](status)}if(ENVIRONMENT_IS_NODE){process["stdout"]["once"]("drain",(function(){process["exit"](status)}));console.log(" ");setTimeout((function(){process["exit"](status)}),500)}else if(ENVIRONMENT_IS_SHELL&&typeof quit==="function"){quit(status)}throw new ExitStatus(status)}Module["exit"]=Module.exit=exit;var abortDecorators=[];function abort(what){if(what!==undefined){Module.print(what);Module.printErr(what);what=JSON.stringify(what)}else{what=""}ABORT=true;EXITSTATUS=1;var extra="\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.";var output="abort("+what+") at "+stackTrace()+extra;if(abortDecorators){abortDecorators.forEach((function(decorator){output=decorator(output,what)}))}throw output}Module["abort"]=Module.abort=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=false;if(Module["noInitialRun"]){shouldRunNow=false}Module["noExitRuntime"]=true;run();var inputBuffer,inputBufferSize;function reallocInputBuffer(size){if(inputBuffer&&inputBufferSize>=size){return inputBuffer}if(inputBuffer){Module._free(inputBuffer)}inputBufferSize=size;inputBuffer=Module._malloc(inputBufferSize);return inputBuffer}Module.loadedMetadata=!!options.videoFormat;Module.videoFormat=options.videoFormat||null;Module.frameBuffer=null;Object.defineProperty(Module,"processing",{get:function getProcessing(){return false}});Module.init=(function(callback){Module._ogv_video_decoder_init();callback()});Module.processHeader=(function(data,callback){var len=data.byteLength;var buffer=reallocInputBuffer(len);Module.HEAPU8.set(new Uint8Array(data),buffer);var ret=Module._ogv_video_decoder_process_header(buffer,len);callback(ret)});Module.processFrame=(function(data,callback){var len=data.byteLength;var buffer=reallocInputBuffer(len);Module.HEAPU8.set(new Uint8Array(data),buffer);var ret=Module._ogv_video_decoder_process_frame(buffer,len);callback(ret)})
+
+
+
+
+
+ return Module;
+};
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-demuxer-ogg.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-demuxer-ogg.js
new file mode 100644
index 00000000..13c6c731
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-demuxer-ogg.js
@@ -0,0 +1,23 @@
+var OGVDemuxerOgg = function(Module) {
+ Module = Module || {};
+
+var options=Module;Module={print:(function(str){console.log(str)})};var Module;if(!Module)Module=(typeof OGVDemuxerOgg!=="undefined"?OGVDemuxerOgg:null)||{};var moduleOverrides={};for(var key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var ENVIRONMENT_IS_WEB=typeof window==="object";var ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof require==="function"&&!ENVIRONMENT_IS_WEB;var ENVIRONMENT_IS_WORKER=typeof importScripts==="function";var ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){if(!Module["print"])Module["print"]=function print(x){process["stdout"].write(x+"\n")};if(!Module["printErr"])Module["printErr"]=function printErr(x){process["stderr"].write(x+"\n")};var nodeFS=require("fs");var nodePath=require("path");Module["read"]=function read(filename,binary){filename=nodePath["normalize"](filename);var ret=nodeFS["readFileSync"](filename);if(!ret&&filename!=nodePath["resolve"](filename)){filename=path.join(__dirname,"..","src",filename);ret=nodeFS["readFileSync"](filename)}if(ret&&!binary)ret=ret.toString();return ret};Module["readBinary"]=function readBinary(filename){return Module["read"](filename,true)};Module["load"]=function load(f){globalEval(read(f))};if(!Module["thisProgram"]){if(process["argv"].length>1){Module["thisProgram"]=process["argv"][1].replace(/\\/g,"/")}else{Module["thisProgram"]="unknown-program"}}Module["arguments"]=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",(function(ex){if(!(ex instanceof ExitStatus)){throw ex}}));Module["inspect"]=(function(){return"[Emscripten Module object]"})}else if(ENVIRONMENT_IS_SHELL){if(!Module["print"])Module["print"]=print;if(typeof printErr!="undefined")Module["printErr"]=printErr;if(typeof read!="undefined"){Module["read"]=read}else{Module["read"]=function read(){throw"no read() available (jsc?)"}}Module["readBinary"]=function readBinary(f){if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}var data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){Module["arguments"]=scriptArgs}else if(typeof arguments!="undefined"){Module["arguments"]=arguments}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){Module["read"]=function read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(typeof arguments!="undefined"){Module["arguments"]=arguments}if(typeof console!=="undefined"){if(!Module["print"])Module["print"]=function print(x){console.log(x)};if(!Module["printErr"])Module["printErr"]=function printErr(x){console.log(x)}}else{var TRY_USE_DUMP=false;if(!Module["print"])Module["print"]=TRY_USE_DUMP&&typeof dump!=="undefined"?(function(x){dump(x)}):(function(x){})}if(ENVIRONMENT_IS_WORKER){Module["load"]=importScripts}if(typeof Module["setWindowTitle"]==="undefined"){Module["setWindowTitle"]=(function(title){document.title=title})}}else{throw"Unknown runtime environment. Where are we?"}function globalEval(x){eval.call(null,x)}if(!Module["load"]&&Module["read"]){Module["load"]=function load(f){globalEval(Module["read"](f))}}if(!Module["print"]){Module["print"]=(function(){})}if(!Module["printErr"]){Module["printErr"]=Module["print"]}if(!Module["arguments"]){Module["arguments"]=[]}if(!Module["thisProgram"]){Module["thisProgram"]="./this.program"}Module.print=Module["print"];Module.printErr=Module["printErr"];Module["preRun"]=[];Module["postRun"]=[];for(var key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}var Runtime={setTempRet0:(function(value){tempRet0=value}),getTempRet0:(function(){return tempRet0}),stackSave:(function(){return STACKTOP}),stackRestore:(function(stackTop){STACKTOP=stackTop}),getNativeTypeSize:(function(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return Runtime.QUANTUM_SIZE}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0);return bits/8}else{return 0}}}}),getNativeFieldSize:(function(type){return Math.max(Runtime.getNativeTypeSize(type),Runtime.QUANTUM_SIZE)}),STACK_ALIGN:16,prepVararg:(function(ptr,type){if(type==="double"||type==="i64"){if(ptr&7){assert((ptr&7)===4);ptr+=4}}else{assert((ptr&3)===0)}return ptr}),getAlignSize:(function(type,size,vararg){if(!vararg&&(type=="i64"||type=="double"))return 8;if(!type)return Math.min(size,8);return Math.min(size||(type?Runtime.getNativeFieldSize(type):0),Runtime.QUANTUM_SIZE)}),dynCall:(function(sig,ptr,args){if(args&&args.length){if(!args.splice)args=Array.prototype.slice.call(args);args.splice(0,0,ptr);return Module["dynCall_"+sig].apply(null,args)}else{return Module["dynCall_"+sig].call(null,ptr)}}),functionPointers:[],addFunction:(function(func){for(var i=0;i<Runtime.functionPointers.length;i++){if(!Runtime.functionPointers[i]){Runtime.functionPointers[i]=func;return 2*(1+i)}}throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS."}),removeFunction:(function(index){Runtime.functionPointers[(index-2)/2]=null}),warnOnce:(function(text){if(!Runtime.warnOnce.shown)Runtime.warnOnce.shown={};if(!Runtime.warnOnce.shown[text]){Runtime.warnOnce.shown[text]=1;Module.printErr(text)}}),funcWrappers:{},getFuncWrapper:(function(func,sig){assert(sig);if(!Runtime.funcWrappers[sig]){Runtime.funcWrappers[sig]={}}var sigCache=Runtime.funcWrappers[sig];if(!sigCache[func]){sigCache[func]=function dynCall_wrapper(){return Runtime.dynCall(sig,func,arguments)}}return sigCache[func]}),getCompilerSetting:(function(name){throw"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work"}),stackAlloc:(function(size){var ret=STACKTOP;STACKTOP=STACKTOP+size|0;STACKTOP=STACKTOP+15&-16;return ret}),staticAlloc:(function(size){var ret=STATICTOP;STATICTOP=STATICTOP+size|0;STATICTOP=STATICTOP+15&-16;return ret}),dynamicAlloc:(function(size){var ret=DYNAMICTOP;DYNAMICTOP=DYNAMICTOP+size|0;DYNAMICTOP=DYNAMICTOP+15&-16;if(DYNAMICTOP>=TOTAL_MEMORY){var success=enlargeMemory();if(!success){DYNAMICTOP=ret;return 0}}return ret}),alignMemory:(function(size,quantum){var ret=size=Math.ceil(size/(quantum?quantum:16))*(quantum?quantum:16);return ret}),makeBigInt:(function(low,high,unsigned){var ret=unsigned?+(low>>>0)+ +(high>>>0)*+4294967296:+(low>>>0)+ +(high|0)*+4294967296;return ret}),GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module["Runtime"]=Runtime;var __THREW__=0;var ABORT=false;var EXITSTATUS=0;var undef=0;var tempValue,tempInt,tempBigInt,tempInt2,tempBigInt2,tempPair,tempBigIntI,tempBigIntR,tempBigIntS,tempBigIntP,tempBigIntD,tempDouble,tempFloat;var tempI64,tempI64b;var tempRet0,tempRet1,tempRet2,tempRet3,tempRet4,tempRet5,tempRet6,tempRet7,tempRet8,tempRet9;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var globalScope=this;function getCFunc(ident){var func=Module["_"+ident];if(!func){try{func=eval("_"+ident)}catch(e){}}assert(func,"Cannot call unknown function "+ident+" (perhaps LLVM optimizations or closure removed it?)");return func}var cwrap,ccall;((function(){var JSfuncs={"stackSave":(function(){Runtime.stackSave()}),"stackRestore":(function(){Runtime.stackRestore()}),"arrayToC":(function(arr){var ret=Runtime.stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}),"stringToC":(function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=Runtime.stackAlloc((str.length<<2)+1);writeStringToMemory(str,ret)}return ret})};var toC={"string":JSfuncs["stringToC"],"array":JSfuncs["arrayToC"]};ccall=function ccallFunc(ident,returnType,argTypes,args,opts){var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=Runtime.stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func.apply(null,cArgs);if(returnType==="string")ret=Pointer_stringify(ret);if(stack!==0){if(opts&&opts.async){EmterpreterAsync.asyncFinalizers.push((function(){Runtime.stackRestore(stack)}));return}Runtime.stackRestore(stack)}return ret};var sourceRegex=/^function\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/;function parseJSFunc(jsfunc){var parsed=jsfunc.toString().match(sourceRegex).slice(1);return{arguments:parsed[0],body:parsed[1],returnValue:parsed[2]}}var JSsource={};for(var fun in JSfuncs){if(JSfuncs.hasOwnProperty(fun)){JSsource[fun]=parseJSFunc(JSfuncs[fun])}}cwrap=function cwrap(ident,returnType,argTypes){argTypes=argTypes||[];var cfunc=getCFunc(ident);var numericArgs=argTypes.every((function(type){return type==="number"}));var numericRet=returnType!=="string";if(numericRet&&numericArgs){return cfunc}var argNames=argTypes.map((function(x,i){return"$"+i}));var funcstr="(function("+argNames.join(",")+") {";var nargs=argTypes.length;if(!numericArgs){funcstr+="var stack = "+JSsource["stackSave"].body+";";for(var i=0;i<nargs;i++){var arg=argNames[i],type=argTypes[i];if(type==="number")continue;var convertCode=JSsource[type+"ToC"];funcstr+="var "+convertCode.arguments+" = "+arg+";";funcstr+=convertCode.body+";";funcstr+=arg+"="+convertCode.returnValue+";"}}var cfuncname=parseJSFunc((function(){return cfunc})).returnValue;funcstr+="var ret = "+cfuncname+"("+argNames.join(",")+");";if(!numericRet){var strgfy=parseJSFunc((function(){return Pointer_stringify})).returnValue;funcstr+="ret = "+strgfy+"(ret);"}if(!numericArgs){funcstr+=JSsource["stackRestore"].body.replace("()","(stack)")+";"}funcstr+="return ret})";return eval(funcstr)}}))();Module["cwrap"]=cwrap;Module["ccall"]=ccall;function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble- +(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}Module["setValue"]=setValue;function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for setValue: "+type)}return null}Module["getValue"]=getValue;var ALLOC_NORMAL=0;var ALLOC_STACK=1;var ALLOC_STATIC=2;var ALLOC_DYNAMIC=3;var ALLOC_NONE=4;Module["ALLOC_NORMAL"]=ALLOC_NORMAL;Module["ALLOC_STACK"]=ALLOC_STACK;Module["ALLOC_STATIC"]=ALLOC_STATIC;Module["ALLOC_DYNAMIC"]=ALLOC_DYNAMIC;Module["ALLOC_NONE"]=ALLOC_NONE;function allocate(slab,types,allocator,ptr){var zeroinit,size;if(typeof slab==="number"){zeroinit=true;size=slab}else{zeroinit=false;size=slab.length}var singleType=typeof types==="string"?types:null;var ret;if(allocator==ALLOC_NONE){ret=ptr}else{ret=[_malloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][allocator===undefined?ALLOC_STATIC:allocator](Math.max(size,singleType?1:types.length))}if(zeroinit){var ptr=ret,stop;assert((ret&3)==0);stop=ret+(size&~3);for(;ptr<stop;ptr+=4){HEAP32[ptr>>2]=0}stop=ret+size;while(ptr<stop){HEAP8[ptr++>>0]=0}return ret}if(singleType==="i8"){if(slab.subarray||slab.slice){HEAPU8.set(slab,ret)}else{HEAPU8.set(new Uint8Array(slab),ret)}return ret}var i=0,type,typeSize,previousType;while(i<size){var curr=slab[i];if(typeof curr==="function"){curr=Runtime.getFunctionIndex(curr)}type=singleType||types[i];if(type===0){i++;continue}if(type=="i64")type="i32";setValue(ret+i,curr,type);if(previousType!==type){typeSize=Runtime.getNativeTypeSize(type);previousType=type}i+=typeSize}return ret}Module["allocate"]=allocate;function getMemory(size){if(!staticSealed)return Runtime.staticAlloc(size);if(typeof _sbrk!=="undefined"&&!_sbrk.called||!runtimeInitialized)return Runtime.dynamicAlloc(size);return _malloc(size)}Module["getMemory"]=getMemory;function Pointer_stringify(ptr,length){if(length===0||!ptr)return"";var hasUtf=0;var t;var i=0;while(1){t=HEAPU8[ptr+i>>0];hasUtf|=t;if(t==0&&!length)break;i++;if(length&&i==length)break}if(!length)length=i;var ret="";if(hasUtf<128){var MAX_CHUNK=1024;var curr;while(length>0){curr=String.fromCharCode.apply(String,HEAPU8.subarray(ptr,ptr+Math.min(length,MAX_CHUNK)));ret=ret?ret+curr:curr;ptr+=MAX_CHUNK;length-=MAX_CHUNK}return ret}return Module["UTF8ToString"](ptr)}Module["Pointer_stringify"]=Pointer_stringify;function AsciiToString(ptr){var str="";while(1){var ch=HEAP8[ptr++>>0];if(!ch)return str;str+=String.fromCharCode(ch)}}Module["AsciiToString"]=AsciiToString;function stringToAscii(str,outPtr){return writeAsciiToMemory(str,outPtr,false)}Module["stringToAscii"]=stringToAscii;function UTF8ArrayToString(u8Array,idx){var u0,u1,u2,u3,u4,u5;var str="";while(1){u0=u8Array[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}u1=u8Array[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}u2=u8Array[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u3=u8Array[idx++]&63;if((u0&248)==240){u0=(u0&7)<<18|u1<<12|u2<<6|u3}else{u4=u8Array[idx++]&63;if((u0&252)==248){u0=(u0&3)<<24|u1<<18|u2<<12|u3<<6|u4}else{u5=u8Array[idx++]&63;u0=(u0&1)<<30|u1<<24|u2<<18|u3<<12|u4<<6|u5}}}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}Module["UTF8ArrayToString"]=UTF8ArrayToString;function UTF8ToString(ptr){return UTF8ArrayToString(HEAPU8,ptr)}Module["UTF8ToString"]=UTF8ToString;function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=2097151){if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=67108863){if(outIdx+4>=endIdx)break;outU8Array[outIdx++]=248|u>>24;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+5>=endIdx)break;outU8Array[outIdx++]=252|u>>30;outU8Array[outIdx++]=128|u>>24&63;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}Module["stringToUTF8Array"]=stringToUTF8Array;function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}Module["stringToUTF8"]=stringToUTF8;function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){++len}else if(u<=2047){len+=2}else if(u<=65535){len+=3}else if(u<=2097151){len+=4}else if(u<=67108863){len+=5}else{len+=6}}return len}Module["lengthBytesUTF8"]=lengthBytesUTF8;function UTF16ToString(ptr){var i=0;var str="";while(1){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)return str;++i;str+=String.fromCharCode(codeUnit)}}Module["UTF16ToString"]=UTF16ToString;function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite<str.length*2?maxBytesToWrite/2:str.length;for(var i=0;i<numCharsToWrite;++i){var codeUnit=str.charCodeAt(i);HEAP16[outPtr>>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}Module["stringToUTF16"]=stringToUTF16;function lengthBytesUTF16(str){return str.length*2}Module["lengthBytesUTF16"]=lengthBytesUTF16;function UTF32ToString(ptr){var i=0;var str="";while(1){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)return str;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}}Module["UTF32ToString"]=UTF32ToString;function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);if(codeUnit>=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}Module["stringToUTF32"]=stringToUTF32;function lengthBytesUTF32(str){var len=0;for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);if(codeUnit>=55296&&codeUnit<=57343)++i;len+=4}return len}Module["lengthBytesUTF32"]=lengthBytesUTF32;function demangle(func){var hasLibcxxabi=!!Module["___cxa_demangle"];if(hasLibcxxabi){try{var buf=_malloc(func.length);writeStringToMemory(func.substr(1),buf);var status=_malloc(4);var ret=Module["___cxa_demangle"](buf,0,0,status);if(getValue(status,"i32")===0&&ret){return Pointer_stringify(ret)}}catch(e){}finally{if(buf)_free(buf);if(status)_free(status);if(ret)_free(ret)}}var i=3;var basicTypes={"v":"void","b":"bool","c":"char","s":"short","i":"int","l":"long","f":"float","d":"double","w":"wchar_t","a":"signed char","h":"unsigned char","t":"unsigned short","j":"unsigned int","m":"unsigned long","x":"long long","y":"unsigned long long","z":"..."};var subs=[];var first=true;function dump(x){if(x)Module.print(x);Module.print(func);var pre="";for(var a=0;a<i;a++)pre+=" ";Module.print(pre+"^")}function parseNested(){i++;if(func[i]==="K")i++;var parts=[];while(func[i]!=="E"){if(func[i]==="S"){i++;var next=func.indexOf("_",i);var num=func.substring(i,next)||0;parts.push(subs[num]||"?");i=next+1;continue}if(func[i]==="C"){parts.push(parts[parts.length-1]);i+=2;continue}var size=parseInt(func.substr(i));var pre=size.toString().length;if(!size||!pre){i--;break}var curr=func.substr(i+pre,size);parts.push(curr);subs.push(curr);i+=pre+size}i++;return parts}function parse(rawList,limit,allowVoid){limit=limit||Infinity;var ret="",list=[];function flushList(){return"("+list.join(", ")+")"}var name;if(func[i]==="N"){name=parseNested().join("::");limit--;if(limit===0)return rawList?[name]:name}else{if(func[i]==="K"||first&&func[i]==="L")i++;var size=parseInt(func.substr(i));if(size){var pre=size.toString().length;name=func.substr(i+pre,size);i+=pre+size}}first=false;if(func[i]==="I"){i++;var iList=parse(true);var iRet=parse(true,1,true);ret+=iRet[0]+" "+name+"<"+iList.join(", ")+">"}else{ret=name}paramLoop:while(i<func.length&&limit-->0){var c=func[i++];if(c in basicTypes){list.push(basicTypes[c])}else{switch(c){case"P":list.push(parse(true,1,true)[0]+"*");break;case"R":list.push(parse(true,1,true)[0]+"&");break;case"L":{i++;var end=func.indexOf("E",i);var size=end-i;list.push(func.substr(i,size));i+=size+2;break};case"A":{var size=parseInt(func.substr(i));i+=size.toString().length;if(func[i]!=="_")throw"?";i++;list.push(parse(true,1,true)[0]+" ["+size+"]");break};case"E":break paramLoop;default:ret+="?"+c;break paramLoop}}}if(!allowVoid&&list.length===1&&list[0]==="void")list=[];if(rawList){if(ret){list.push(ret+"?")}return list}else{return ret+flushList()}}var parsed=func;try{if(func=="Object._main"||func=="_main"){return"main()"}if(typeof func==="number")func=Pointer_stringify(func);if(func[0]!=="_")return func;if(func[1]!=="_")return func;if(func[2]!=="Z")return func;switch(func[3]){case"n":return"operator new()";case"d":return"operator delete()"}parsed=parse()}catch(e){parsed+="?"}if(parsed.indexOf("?")>=0&&!hasLibcxxabi){Runtime.warnOnce("warning: a problem occurred in builtin C++ name demangling; build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling")}return parsed}function demangleAll(text){return text.replace(/__Z[\w\d_]+/g,(function(x){var y=demangle(x);return x===y?x:x+" ["+y+"]"}))}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){return demangleAll(jsStackTrace())}Module["stackTrace"]=stackTrace;var PAGE_SIZE=4096;function alignMemoryPage(x){if(x%4096>0){x+=4096-x%4096}return x}var HEAP;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var STATIC_BASE=0,STATICTOP=0,staticSealed=false;var STACK_BASE=0,STACKTOP=0,STACK_MAX=0;var DYNAMIC_BASE=0,DYNAMICTOP=0;function enlargeMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.")}var TOTAL_STACK=Module["TOTAL_STACK"]||5242880;var TOTAL_MEMORY=Module["TOTAL_MEMORY"]||16777216;var totalMemory=64*1024;while(totalMemory<TOTAL_MEMORY||totalMemory<2*TOTAL_STACK){if(totalMemory<16*1024*1024){totalMemory*=2}else{totalMemory+=16*1024*1024}}if(totalMemory!==TOTAL_MEMORY){Module.printErr("increasing TOTAL_MEMORY to "+totalMemory+" to be compliant with the asm.js spec (and given that TOTAL_STACK="+TOTAL_STACK+")");TOTAL_MEMORY=totalMemory}assert(typeof Int32Array!=="undefined"&&typeof Float64Array!=="undefined"&&!!(new Int32Array(1))["subarray"]&&!!(new Int32Array(1))["set"],"JS engine does not provide full typed array support");var buffer;buffer=new ArrayBuffer(TOTAL_MEMORY);HEAP8=new Int8Array(buffer);HEAP16=new Int16Array(buffer);HEAP32=new Int32Array(buffer);HEAPU8=new Uint8Array(buffer);HEAPU16=new Uint16Array(buffer);HEAPU32=new Uint32Array(buffer);HEAPF32=new Float32Array(buffer);HEAPF64=new Float64Array(buffer);HEAP32[0]=255;assert(HEAPU8[0]===255&&HEAPU8[3]===0,"Typed arrays 2 must be run on a little-endian system");Module["HEAP"]=HEAP;Module["buffer"]=buffer;Module["HEAP8"]=HEAP8;Module["HEAP16"]=HEAP16;Module["HEAP32"]=HEAP32;Module["HEAPU8"]=HEAPU8;Module["HEAPU16"]=HEAPU16;Module["HEAPU32"]=HEAPU32;Module["HEAPF32"]=HEAPF32;Module["HEAPF64"]=HEAPF64;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Runtime.dynCall("v",func)}else{Runtime.dynCall("vi",func,[callback.arg])}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){if(runtimeInitialized)return;runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__);runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}Module["addOnPreRun"]=Module.addOnPreRun=addOnPreRun;function addOnInit(cb){__ATINIT__.unshift(cb)}Module["addOnInit"]=Module.addOnInit=addOnInit;function addOnPreMain(cb){__ATMAIN__.unshift(cb)}Module["addOnPreMain"]=Module.addOnPreMain=addOnPreMain;function addOnExit(cb){__ATEXIT__.unshift(cb)}Module["addOnExit"]=Module.addOnExit=addOnExit;function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}Module["addOnPostRun"]=Module.addOnPostRun=addOnPostRun;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}Module["intArrayFromString"]=intArrayFromString;function intArrayToString(array){var ret=[];for(var i=0;i<array.length;i++){var chr=array[i];if(chr>255){chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}Module["intArrayToString"]=intArrayToString;function writeStringToMemory(string,buffer,dontAddNull){var array=intArrayFromString(string,dontAddNull);var i=0;while(i<array.length){var chr=array[i];HEAP8[buffer+i>>0]=chr;i=i+1}}Module["writeStringToMemory"]=writeStringToMemory;function writeArrayToMemory(array,buffer){for(var i=0;i<array.length;i++){HEAP8[buffer++>>0]=array[i]}}Module["writeArrayToMemory"]=writeArrayToMemory;function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i<str.length;++i){HEAP8[buffer++>>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}Module["writeAsciiToMemory"]=writeAsciiToMemory;function unSign(value,bits,ignore){if(value>=0){return value}return bits<=32?2*Math.abs(1<<bits-1)+value:Math.pow(2,bits)+value}function reSign(value,bits,ignore){if(value<=0){return value}var half=bits<=32?Math.abs(1<<bits-1):Math.pow(2,bits-1);if(value>=half&&(bits<=32||value>half)){value=-2*half+value}return value}if(!Math["imul"]||Math["imul"](4294967295,5)!==-5)Math["imul"]=function imul(a,b){var ah=a>>>16;var al=a&65535;var bh=b>>>16;var bl=b&65535;return al*bl+(ah*bl+al*bh<<16)|0};Math.imul=Math["imul"];if(!Math["clz32"])Math["clz32"]=(function(x){x=x>>>0;for(var i=0;i<32;i++){if(x&1<<31-i)return i}return 32});Math.clz32=Math["clz32"];var Math_abs=Math.abs;var Math_cos=Math.cos;var Math_sin=Math.sin;var Math_tan=Math.tan;var Math_acos=Math.acos;var Math_asin=Math.asin;var Math_atan=Math.atan;var Math_atan2=Math.atan2;var Math_exp=Math.exp;var Math_log=Math.log;var Math_sqrt=Math.sqrt;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_pow=Math.pow;var Math_imul=Math.imul;var Math_fround=Math.fround;var Math_min=Math.min;var Math_clz32=Math.clz32;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}Module["addRunDependency"]=addRunDependency;function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["removeRunDependency"]=removeRunDependency;Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var ASM_CONSTS=[];STATIC_BASE=8;STATICTOP=STATIC_BASE+3392;__ATINIT__.push();allocate([0,0,0,0,183,29,193,4,110,59,130,9,217,38,67,13,220,118,4,19,107,107,197,23,178,77,134,26,5,80,71,30,184,237,8,38,15,240,201,34,214,214,138,47,97,203,75,43,100,155,12,53,211,134,205,49,10,160,142,60,189,189,79,56,112,219,17,76,199,198,208,72,30,224,147,69,169,253,82,65,172,173,21,95,27,176,212,91,194,150,151,86,117,139,86,82,200,54,25,106,127,43,216,110,166,13,155,99,17,16,90,103,20,64,29,121,163,93,220,125,122,123,159,112,205,102,94,116,224,182,35,152,87,171,226,156,142,141,161,145,57,144,96,149,60,192,39,139,139,221,230,143,82,251,165,130,229,230,100,134,88,91,43,190,239,70,234,186,54,96,169,183,129,125,104,179,132,45,47,173,51,48,238,169,234,22,173,164,93,11,108,160,144,109,50,212,39,112,243,208,254,86,176,221,73,75,113,217,76,27,54,199,251,6,247,195,34,32,180,206,149,61,117,202,40,128,58,242,159,157,251,246,70,187,184,251,241,166,121,255,244,246,62,225,67,235,255,229,154,205,188,232,45,208,125,236,119,112,134,52,192,109,71,48,25,75,4,61,174,86,197,57,171,6,130,39,28,27,67,35,197,61,0,46,114,32,193,42,207,157,142,18,120,128,79,22,161,166,12,27,22,187,205,31,19,235,138,1,164,246,75,5,125,208,8,8,202,205,201,12,7,171,151,120,176,182,86,124,105,144,21,113,222,141,212,117,219,221,147,107,108,192,82,111,181,230,17,98,2,251,208,102,191,70,159,94,8,91,94,90,209,125,29,87,102,96,220,83,99,48,155,77,212,45,90,73,13,11,25,68,186,22,216,64,151,198,165,172,32,219,100,168,249,253,39,165,78,224,230,161,75,176,161,191,252,173,96,187,37,139,35,182,146,150,226,178,47,43,173,138,152,54,108,142,65,16,47,131,246,13,238,135,243,93,169,153,68,64,104,157,157,102,43,144,42,123,234,148,231,29,180,224,80,0,117,228,137,38,54,233,62,59,247,237,59,107,176,243,140,118,113,247,85,80,50,250,226,77,243,254,95,240,188,198,232,237,125,194,49,203,62,207,134,214,255,203,131,134,184,213,52,155,121,209,237,189,58,220,90,160,251,216,238,224,12,105,89,253,205,109,128,219,142,96,55,198,79,100,50,150,8,122,133,139,201,126,92,173,138,115,235,176,75,119,86,13,4,79,225,16,197,75,56,54,134,70,143,43,71,66,138,123,0,92,61,102,193,88,228,64,130,85,83,93,67,81,158,59,29,37,41,38,220,33,240,0,159,44,71,29,94,40,66,77,25,54,245,80,216,50,44,118,155,63,155,107,90,59,38,214,21,3,145,203,212,7,72,237,151,10,255,240,86,14,250,160,17,16,77,189,208,20,148,155,147,25,35,134,82,29,14,86,47,241,185,75,238,245,96,109,173,248,215,112,108,252,210,32,43,226,101,61,234,230,188,27,169,235,11,6,104,239,182,187,39,215,1,166,230,211,216,128,165,222,111,157,100,218,106,205,35,196,221,208,226,192,4,246,161,205,179,235,96,201,126,141,62,189,201,144,255,185,16,182,188,180,167,171,125,176,162,251,58,174,21,230,251,170,204,192,184,167,123,221,121,163,198,96,54,155,113,125,247,159,168,91,180,146,31,70,117,150,26,22,50,136,173,11,243,140,116,45,176,129,195,48,113,133,153,144,138,93,46,141,75,89,247,171,8,84,64,182,201,80,69,230,142,78,242,251,79,74,43,221,12,71,156,192,205,67,33,125,130,123,150,96,67,127,79,70,0,114,248,91,193,118,253,11,134,104,74,22,71,108,147,48,4,97,36,45,197,101,233,75,155,17,94,86,90,21,135,112,25,24,48,109,216,28,53,61,159,2,130,32,94,6,91,6,29,11,236,27,220,15,81,166,147,55,230,187,82,51,63,157,17,62,136,128,208,58,141,208,151,36,58,205,86,32,227,235,21,45,84,246,212,41,121,38,169,197,206,59,104,193,23,29,43,204,160,0,234,200,165,80,173,214,18,77,108,210,203,107,47,223,124,118,238,219,193,203,161,227,118,214,96,231,175,240,35,234,24,237,226,238,29,189,165,240,170,160,100,244,115,134,39,249,196,155,230,253,9,253,184,137,190,224,121,141,103,198,58,128,208,219,251,132,213,139,188,154,98,150,125,158,187,176,62,147,12,173,255,151,177,16,176,175,6,13,113,171,223,43,50,166,104,54,243,162,109,102,180,188,218,123,117,184,3,93,54,181,180,64,247,177,79,103,103,83,0,0,0,0,184,8,0,0,7,0,0,0,192,8,0,0,1,0,0,0,1,0,0,0,2,0,0,0,200,8,0,0,7,0,0,0,208,8,0,0,3,0,0,0,2,0,0,0,4,0,0,0,216,8,0,0,5,0,0,0,216,8,0,0,5,0,0,0,3,0,0,0,0,0,0,0,224,8,0,0,8,0,0,0,240,8,0,0,6,0,0,0,0,0,0,0,0,0,0,0,248,8,0,0,8,0,0,0,8,9,0,0,7,0,0,0,0,0,0,0,0,0,0,0,16,9,0,0,7,0,0,0,16,9,0,0,8,0,0,0,0,0,0,0,0,0,0,0,24,9,0,0,7,0,0,0,32,9,0,0,9,0,0,0,0,0,0,0,0,0,0,0,48,9,0,0,4,0,0,0,56,9,0,0,10,0,0,0,4,0,0,0,0,0,0,0,64,9,0,0,5,0,0,0,72,9,0,0,11,0,0,0,4,0,0,0,0,0,0,0,80,9,0,0,7,0,0,0,80,9,0,0,12,0,0,0,0,0,0,0,0,0,0,0,88,9,0,0,8,0,0,0,104,9,0,0,13,0,0,0,5,0,0,0,0,0,0,0,112,9,0,0,8,0,0,0,128,9,0,0,14,0,0,0,0,0,0,0,0,0,0,0,136,9,0,0,5,0,0,0,144,9,0,0,15,0,0,0,0,0,0,0,0,0,0,0,152,9,0,0,8,0,0,0,168,9,0,0,16,0,0,0,6,0,0,0,17,0,0,0,176,9,0,0,5,0,0,0,184,9,0,0,18,0,0,0,7,0,0,0,0,0,0,0,192,9,0,0,0,0,0,0,200,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,118,111,114,98,105,115,0,129,116,104,101,111,114,97,0,129,107,97,116,101,0,0,0,0,0,0,0,0,0,0,0,79,112,117,115,84,97,103,115,0,0,0,0,0,0,0,0,79,86,80,56,48,2,32,0,128,2,0,0,204,1,0,0,24,0,0,0,1,0,0,0,176,0,0,0,120,0,0,0,96,1,0,0,240,0,0,0,96,1,0,0,32,1,0,0,192,2,0,0,224,1,0,0,192,2,0,0,64,2,0,0,208,2,0,0,224,1,0,0,208,2,0,0,64,2,0,0,0,5,0,0,208,2,0,0,0,5,0,0,208,2,0,0,128,7,0,0,56,4,0,0,128,7,0,0,56,4,0,0,128,7,0,0,56,4,0,0,128,7,0,0,56,4,0,0,0,8,0,0,56,4,0,0,0,16,0,0,112,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,9,0,0,0,10,0,0,0,9,0,0,0,10,0,0,0,9,0,0,0,10,0,0,0,4,0,0,0,3,0,0,0,7,0,0,0,6,0,0,0,4,0,0,0,3,0,0,0,7,0,0,0,6,0,0,0,2,0,0,0,2,0,0,0,7,0,0,0,6,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,192,93,0,0,233,3,0,0,24,0,0,0,1,0,0,0,25,0,0,0,1,0,0,0,48,117,0,0,233,3,0,0,30,0,0,0,1,0,0,0,50,0,0,0,1,0,0,0,96,234,0,0,233,3,0,0,60,0,0,0,1,0,0,0,152,58,0,0,233,3,0,0,25,0,0,0,2,0,0,0,224,1,0,0,192,3,0,0,128,7,0,0,64,11,0,0,224,1,0,0,192,3,0,0,128,7,0,0,64,11,0,0,224,1,0,0,192,3,0,0,128,7,0,0,64,11,0,0,224,1,0,0,192,3,0,0,224,1,0,0,192,3,0,0,120,0,0,0,240,0,0,0,224,1,0,0,192,3,0,0,120,0,0,0,240,0,0,0,224,1,0,0,192,3,0,0,120,0,0,0,240,0,0,0,224,1,0,0,192,3,0,0,120,0,0,0,240,0,0,0,224,1,0,0,192,3,0,0,0,0,0,0,1,0,0,0,3,0,0,0,7,0,0,0,15,0,0,0,31,0,0,0,63,0,0,0,127,0,0,0,255,0,0,0,255,1,0,0,255,3,0,0,255,7,0,0,255,15,0,0,255,31,0,0,255,63,0,0,255,127,0,0,255,255,0,0,255,255,1,0,255,255,3,0,255,255,7,0,255,255,15,0,255,255,31,0,255,255,63,0,255,255,127,0,255,255,255,0,255,255,255,1,255,255,255,3,255,255,255,7,255,255,255,15,255,255,255,31,255,255,255,63,255,255,255,127,255,255,255,255,0,0,0,0,128,116,104,101,111,114,97,0,84,104,101,111,114,97,0,0,1,118,111,114,98,105,115,0,86,111,114,98,105,115,0,0,83,112,101,101,120,0,0,0,80,67,77,32,32,32,32,32,0,0,0,0,0,0,0,0,80,67,77,0,0,0,0,0,67,77,77,76,0,0,0,0,0,0,0,0,0,0,0,0,67,77,77,76,0,0,0,0,65,110,110,111,100,101,120,0,102,105,115,104,101,97,100,0,83,107,101,108,101,116,111,110,0,0,0,0,0,0,0,0,102,76,97,67,0,0,0,0,70,108,97,99,48,0,0,0,127,70,76,65,67,0,0,0,70,108,97,99,0,0,0,0,65,110,120,68,97,116,97,0,67,69,76,84,32,32,32,32,0,0,0,0,0,0,0,0,67,69,76,84,0,0,0,0,128,107,97,116,101,0,0,0,0,0,0,0,0,0,0,0,75,97,116,101,0,0,0,0,66,66,67,68,0,0,0,0,68,105,114,97,99,0,0,0,79,112,117,115,72,101,97,100,0,0,0,0,0,0,0,0,79,112,117,115,0,0,0,0,79,86,80,56,48,0,0,0,86,80,56,0,0,0,0,0,0,0,0,0,0,0,0,0,85,110,107,110,111,119,110,0,86,80,56,48,0,0,0,0,102,105,115,104,101,97,100,0,0,0,0,0,0,0,0,0,102,105,115,98,111,110,101,0,0,0,0,0,0,0,0,0,105,110,100,101,120,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,69,114,114,111,114,32,37,100,32,102,114,111,109,32,111,103,103,122,95,114,101,97,100,95,105,110,112,117,116,10,0,0,69,120,112,101,99,116,101,100,32,116,111,32,114,101,97,100,32,37,100,32,102,114,111,109,32,111,103,103,122,95,114,101,97,100,95,105,110,112,117,116,32,98,117,116,32,103,97,118,101,32,37,100,10,0,0,0,116,104,101,111,114,97,0,0,118,111,114,98,105,115,0,0,111,112,117,115,0,0,0,0,73,110,118,97,108,105,100,32,111,103,103,32,115,107,101,108,101,116,111,110,32,116,114,97,99,107,32,100,97,116,97,63,32,37,100,10,0,0,0,0,73,110,118,97,108,105,100,32,115,116,97,116,101,32,105,110,32,79,103,103,32,114,101,97,100,80,97,99,107,101,116,67,97,108,108,98,97,99,107,0,69,114,114,111,114,32,112,114,111,99,101,115,115,105,110,103,32,115,107,101,108,101,116,111,110,32,112,97,99,107,101,116,58,32,37,100,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE);var tempDoublePtr=Runtime.alignMemory(allocate(12,"i8",ALLOC_STATIC),8);assert(tempDoublePtr%8==0);function copyTempFloat(ptr){HEAP8[tempDoublePtr]=HEAP8[ptr];HEAP8[tempDoublePtr+1]=HEAP8[ptr+1];HEAP8[tempDoublePtr+2]=HEAP8[ptr+2];HEAP8[tempDoublePtr+3]=HEAP8[ptr+3]}function copyTempDouble(ptr){HEAP8[tempDoublePtr]=HEAP8[ptr];HEAP8[tempDoublePtr+1]=HEAP8[ptr+1];HEAP8[tempDoublePtr+2]=HEAP8[ptr+2];HEAP8[tempDoublePtr+3]=HEAP8[ptr+3];HEAP8[tempDoublePtr+4]=HEAP8[ptr+4];HEAP8[tempDoublePtr+5]=HEAP8[ptr+5];HEAP8[tempDoublePtr+6]=HEAP8[ptr+6];HEAP8[tempDoublePtr+7]=HEAP8[ptr+7]}function _ogvjs_callback_loaded_metadata(videoCodecStr,audioCodecStr){if(videoCodecStr){Module.videoCodec=Module.Pointer_stringify(videoCodecStr)}if(audioCodecStr){Module.audioCodec=Module.Pointer_stringify(audioCodecStr)}var len=Module._ogv_demuxer_media_duration();if(len>=0){Module.duration=len}else{Module.duration=NaN}Module.loadedMetadata=true}Module["_bitshift64Ashr"]=_bitshift64Ashr;function _ogvjs_callback_video_packet(buffer,len,frameTimestamp,keyframeTimestamp){Module.videoPackets.push({data:Module.HEAPU8.buffer.slice?Module.HEAPU8.buffer.slice(buffer,buffer+len):(new Uint8Array(new Uint8Array(Module.HEAPU8.buffer,buffer,len))).buffer,timestamp:frameTimestamp,keyframeTimestamp:keyframeTimestamp})}Module["_i64Subtract"]=_i64Subtract;var ___errno_state=0;function ___setErrNo(value){HEAP32[___errno_state>>2]=value;return value}var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};function _sysconf(name){switch(name){case 30:return PAGE_SIZE;case 85:return totalMemory/PAGE_SIZE;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:return 200809;case 79:return 0;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return-1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}___setErrNo(ERRNO_CODES.EINVAL);return-1}var _SItoD=true;var _SItoF=true;Module["_memset"]=_memset;var FS=undefined;function _close(fildes){var stream=FS.getStream(fildes);if(!stream){___setErrNo(ERRNO_CODES.EBADF);return-1}try{FS.close(stream);return 0}catch(e){FS.handleFSError(e);return-1}}function _fileno(stream){stream=FS.getStreamFromPtr(stream);if(!stream)return-1;return stream.fd}function _fclose(stream){var fd=_fileno(stream);return _close(fd)}Module["_bitshift64Shl"]=_bitshift64Shl;function _abort(){Module["abort"]()}var SOCKFS=undefined;function _send(fd,buf,len,flags){var sock=SOCKFS.getSocket(fd);if(!sock){___setErrNo(ERRNO_CODES.EBADF);return-1}return _write(fd,buf,len)}function _pwrite(fildes,buf,nbyte,offset){var stream=FS.getStream(fildes);if(!stream){___setErrNo(ERRNO_CODES.EBADF);return-1}try{var slab=HEAP8;return FS.write(stream,slab,buf,nbyte,offset)}catch(e){FS.handleFSError(e);return-1}}function _write(fildes,buf,nbyte){var stream=FS.getStream(fildes);if(!stream){___setErrNo(ERRNO_CODES.EBADF);return-1}try{var slab=HEAP8;return FS.write(stream,slab,buf,nbyte)}catch(e){FS.handleFSError(e);return-1}}function _fwrite(ptr,size,nitems,stream){var bytesToWrite=nitems*size;if(bytesToWrite==0)return 0;var fd=_fileno(stream);var bytesWritten=_write(fd,ptr,bytesToWrite);if(bytesWritten==-1){var streamObj=FS.getStreamFromPtr(stream);if(streamObj)streamObj.error=true;return 0}else{return bytesWritten/size|0}}Module["_strlen"]=_strlen;function __reallyNegative(x){return x<0||x===0&&1/x===-Infinity}function __formatString(format,varargs){assert((varargs&3)===0);var textIndex=format;var argIndex=0;function getNextArg(type){var ret;argIndex=Runtime.prepVararg(argIndex,type);if(type==="double"){ret=(HEAP32[tempDoublePtr>>2]=HEAP32[varargs+argIndex>>2],HEAP32[tempDoublePtr+4>>2]=HEAP32[varargs+(argIndex+4)>>2],+HEAPF64[tempDoublePtr>>3]);argIndex+=8}else if(type=="i64"){ret=[HEAP32[varargs+argIndex>>2],HEAP32[varargs+(argIndex+4)>>2]];argIndex+=8}else{assert((argIndex&3)===0);type="i32";ret=HEAP32[varargs+argIndex>>2];argIndex+=4}return ret}var ret=[];var curr,next,currArg;while(1){var startTextIndex=textIndex;curr=HEAP8[textIndex>>0];if(curr===0)break;next=HEAP8[textIndex+1>>0];if(curr==37){var flagAlwaysSigned=false;var flagLeftAlign=false;var flagAlternative=false;var flagZeroPad=false;var flagPadSign=false;flagsLoop:while(1){switch(next){case 43:flagAlwaysSigned=true;break;case 45:flagLeftAlign=true;break;case 35:flagAlternative=true;break;case 48:if(flagZeroPad){break flagsLoop}else{flagZeroPad=true;break};case 32:flagPadSign=true;break;default:break flagsLoop}textIndex++;next=HEAP8[textIndex+1>>0]}var width=0;if(next==42){width=getNextArg("i32");textIndex++;next=HEAP8[textIndex+1>>0]}else{while(next>=48&&next<=57){width=width*10+(next-48);textIndex++;next=HEAP8[textIndex+1>>0]}}var precisionSet=false,precision=-1;if(next==46){precision=0;precisionSet=true;textIndex++;next=HEAP8[textIndex+1>>0];if(next==42){precision=getNextArg("i32");textIndex++}else{while(1){var precisionChr=HEAP8[textIndex+1>>0];if(precisionChr<48||precisionChr>57)break;precision=precision*10+(precisionChr-48);textIndex++}}next=HEAP8[textIndex+1>>0]}if(precision<0){precision=6;precisionSet=false}var argSize;switch(String.fromCharCode(next)){case"h":var nextNext=HEAP8[textIndex+2>>0];if(nextNext==104){textIndex++;argSize=1}else{argSize=2}break;case"l":var nextNext=HEAP8[textIndex+2>>0];if(nextNext==108){textIndex++;argSize=8}else{argSize=4}break;case"L":case"q":case"j":argSize=8;break;case"z":case"t":case"I":argSize=4;break;default:argSize=null}if(argSize)textIndex++;next=HEAP8[textIndex+1>>0];switch(String.fromCharCode(next)){case"d":case"i":case"u":case"o":case"x":case"X":case"p":{var signed=next==100||next==105;argSize=argSize||4;var currArg=getNextArg("i"+argSize*8);var origArg=currArg;var argText;if(argSize==8){currArg=Runtime.makeBigInt(currArg[0],currArg[1],next==117)}if(argSize<=4){var limit=Math.pow(256,argSize)-1;currArg=(signed?reSign:unSign)(currArg&limit,argSize*8)}var currAbsArg=Math.abs(currArg);var prefix="";if(next==100||next==105){if(argSize==8&&i64Math)argText=i64Math.stringify(origArg[0],origArg[1],null);else argText=reSign(currArg,8*argSize,1).toString(10)}else if(next==117){if(argSize==8&&i64Math)argText=i64Math.stringify(origArg[0],origArg[1],true);else argText=unSign(currArg,8*argSize,1).toString(10);currArg=Math.abs(currArg)}else if(next==111){argText=(flagAlternative?"0":"")+currAbsArg.toString(8)}else if(next==120||next==88){prefix=flagAlternative&&currArg!=0?"0x":"";if(argSize==8&&i64Math){if(origArg[1]){argText=(origArg[1]>>>0).toString(16);var lower=(origArg[0]>>>0).toString(16);while(lower.length<8)lower="0"+lower;argText+=lower}else{argText=(origArg[0]>>>0).toString(16)}}else if(currArg<0){currArg=-currArg;argText=(currAbsArg-1).toString(16);var buffer=[];for(var i=0;i<argText.length;i++){buffer.push((15-parseInt(argText[i],16)).toString(16))}argText=buffer.join("");while(argText.length<argSize*2)argText="f"+argText}else{argText=currAbsArg.toString(16)}if(next==88){prefix=prefix.toUpperCase();argText=argText.toUpperCase()}}else if(next==112){if(currAbsArg===0){argText="(nil)"}else{prefix="0x";argText=currAbsArg.toString(16)}}if(precisionSet){while(argText.length<precision){argText="0"+argText}}if(currArg>=0){if(flagAlwaysSigned){prefix="+"+prefix}else if(flagPadSign){prefix=" "+prefix}}if(argText.charAt(0)=="-"){prefix="-"+prefix;argText=argText.substr(1)}while(prefix.length+argText.length<width){if(flagLeftAlign){argText+=" "}else{if(flagZeroPad){argText="0"+argText}else{prefix=" "+prefix}}}argText=prefix+argText;argText.split("").forEach((function(chr){ret.push(chr.charCodeAt(0))}));break};case"f":case"F":case"e":case"E":case"g":case"G":{var currArg=getNextArg("double");var argText;if(isNaN(currArg)){argText="nan";flagZeroPad=false}else if(!isFinite(currArg)){argText=(currArg<0?"-":"")+"inf";flagZeroPad=false}else{var isGeneral=false;var effectivePrecision=Math.min(precision,20);if(next==103||next==71){isGeneral=true;precision=precision||1;var exponent=parseInt(currArg.toExponential(effectivePrecision).split("e")[1],10);if(precision>exponent&&exponent>=-4){next=(next==103?"f":"F").charCodeAt(0);precision-=exponent+1}else{next=(next==103?"e":"E").charCodeAt(0);precision--}effectivePrecision=Math.min(precision,20)}if(next==101||next==69){argText=currArg.toExponential(effectivePrecision);if(/[eE][-+]\d$/.test(argText)){argText=argText.slice(0,-1)+"0"+argText.slice(-1)}}else if(next==102||next==70){argText=currArg.toFixed(effectivePrecision);if(currArg===0&&__reallyNegative(currArg)){argText="-"+argText}}var parts=argText.split("e");if(isGeneral&&!flagAlternative){while(parts[0].length>1&&parts[0].indexOf(".")!=-1&&(parts[0].slice(-1)=="0"||parts[0].slice(-1)==".")){parts[0]=parts[0].slice(0,-1)}}else{if(flagAlternative&&argText.indexOf(".")==-1)parts[0]+=".";while(precision>effectivePrecision++)parts[0]+="0"}argText=parts[0]+(parts.length>1?"e"+parts[1]:"");if(next==69)argText=argText.toUpperCase();if(currArg>=0){if(flagAlwaysSigned){argText="+"+argText}else if(flagPadSign){argText=" "+argText}}}while(argText.length<width){if(flagLeftAlign){argText+=" "}else{if(flagZeroPad&&(argText[0]=="-"||argText[0]=="+")){argText=argText[0]+"0"+argText.slice(1)}else{argText=(flagZeroPad?"0":" ")+argText}}}if(next<97)argText=argText.toUpperCase();argText.split("").forEach((function(chr){ret.push(chr.charCodeAt(0))}));break};case"s":{var arg=getNextArg("i8*");var argLength=arg?_strlen(arg):"(null)".length;if(precisionSet)argLength=Math.min(argLength,precision);if(!flagLeftAlign){while(argLength<width--){ret.push(32)}}if(arg){for(var i=0;i<argLength;i++){ret.push(HEAPU8[arg++>>0])}}else{ret=ret.concat(intArrayFromString("(null)".substr(0,argLength),true))}if(flagLeftAlign){while(argLength<width--){ret.push(32)}}break};case"c":{if(flagLeftAlign)ret.push(getNextArg("i8"));while(--width>0){ret.push(32)}if(!flagLeftAlign)ret.push(getNextArg("i8"));break};case"n":{var ptr=getNextArg("i32*");HEAP32[ptr>>2]=ret.length;break};case"%":{ret.push(curr);break};default:{for(var i=startTextIndex;i<textIndex+2;i++){ret.push(HEAP8[i>>0])}}}textIndex+=2}else{ret.push(curr);textIndex+=1}}return ret}function _fprintf(stream,format,varargs){var result=__formatString(format,varargs);var stack=Runtime.stackSave();var ret=_fwrite(allocate(result,"i8",ALLOC_STACK),1,result.length,stream);Runtime.stackRestore(stack);return ret}function _printf(format,varargs){var result=__formatString(format,varargs);var string=intArrayToString(result);if(string[string.length-1]==="\n")string=string.substr(0,string.length-1);Module.print(string);return result.length}function _ogvjs_callback_frame_ready(){return Module.videoPackets.length>0?1:0}function _fflush(stream){}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest);return dest}Module["_memcpy"]=_memcpy;Module["_strncpy"]=_strncpy;Module["_i64Add"]=_i64Add;function _ogvjs_callback_audio_packet(buffer,len,audioTimestamp){Module.audioPackets.push({data:Module.HEAPU8.buffer.slice?Module.HEAPU8.buffer.slice(buffer,buffer+len):(new Uint8Array(new Uint8Array(Module.HEAPU8.buffer,buffer,len))).buffer,timestamp:audioTimestamp})}Module["_memmove"]=_memmove;function _ogvjs_callback_audio_ready(){return Module.audioPackets.length>0?1:0}function _lseek(fildes,offset,whence){var stream=FS.getStream(fildes);if(!stream){___setErrNo(ERRNO_CODES.EBADF);return-1}try{return FS.llseek(stream,offset,whence)}catch(e){FS.handleFSError(e);return-1}}function _fseek(stream,offset,whence){var fd=_fileno(stream);var ret=_lseek(fd,offset,whence);if(ret==-1){return-1}stream=FS.getStreamFromPtr(stream);stream.eof=false;return 0}function ___errno_location(){return ___errno_state}function _ftell(stream){stream=FS.getStreamFromPtr(stream);if(!stream){___setErrNo(ERRNO_CODES.EBADF);return-1}if(FS.isChrdev(stream.node.mode)){___setErrNo(ERRNO_CODES.ESPIPE);return-1}else{return stream.position}}Module["_strcpy"]=_strcpy;function _sbrk(bytes){var self=_sbrk;if(!self.called){DYNAMICTOP=alignMemoryPage(DYNAMICTOP);self.called=true;assert(Runtime.dynamicAlloc);self.alloc=Runtime.dynamicAlloc;Runtime.dynamicAlloc=(function(){abort("cannot dynamically allocate, sbrk now has control")})}var ret=DYNAMICTOP;if(bytes!=0){var success=self.alloc(bytes);if(!success)return-1>>>0}return ret}function _time(ptr){var ret=Date.now()/1e3|0;if(ptr){HEAP32[ptr>>2]=ret}return ret}___errno_state=Runtime.staticAlloc(4);HEAP32[___errno_state>>2]=0;STACK_BASE=STACKTOP=Runtime.alignMemory(STATICTOP);staticSealed=true;STACK_MAX=STACK_BASE+TOTAL_STACK;DYNAMIC_BASE=DYNAMICTOP=Runtime.alignMemory(STACK_MAX);assert(DYNAMIC_BASE<TOTAL_MEMORY,"TOTAL_MEMORY not big enough for stack");var cttz_i8=allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0],"i8",ALLOC_DYNAMIC);function invoke_iiii(index,a1,a2,a3){try{return Module["dynCall_iiii"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}function invoke_vi(index,a1){try{Module["dynCall_vi"](index,a1)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}function invoke_ii(index,a1){try{return Module["dynCall_ii"](index,a1)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}function invoke_iiiii(index,a1,a2,a3,a4){try{return Module["dynCall_iiiii"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}function invoke_iii(index,a1,a2){try{return Module["dynCall_iii"](index,a1,a2)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}function invoke_iiiiii(index,a1,a2,a3,a4,a5){try{return Module["dynCall_iiiiii"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;asm["setThrew"](1,0)}}Module.asmGlobalArg={"Math":Math,"Int8Array":Int8Array,"Int16Array":Int16Array,"Int32Array":Int32Array,"Uint8Array":Uint8Array,"Uint16Array":Uint16Array,"Uint32Array":Uint32Array,"Float32Array":Float32Array,"Float64Array":Float64Array,"NaN":NaN,"Infinity":Infinity};Module.asmLibraryArg={"abort":abort,"assert":assert,"invoke_iiii":invoke_iiii,"invoke_vi":invoke_vi,"invoke_ii":invoke_ii,"invoke_iiiii":invoke_iiiii,"invoke_iii":invoke_iii,"invoke_iiiiii":invoke_iiiiii,"_send":_send,"_lseek":_lseek,"___setErrNo":___setErrNo,"_ogvjs_callback_audio_packet":_ogvjs_callback_audio_packet,"_ogvjs_callback_loaded_metadata":_ogvjs_callback_loaded_metadata,"_fflush":_fflush,"_pwrite":_pwrite,"__reallyNegative":__reallyNegative,"_sbrk":_sbrk,"_emscripten_memcpy_big":_emscripten_memcpy_big,"_fileno":_fileno,"_ogvjs_callback_frame_ready":_ogvjs_callback_frame_ready,"_sysconf":_sysconf,"_close":_close,"_ogvjs_callback_video_packet":_ogvjs_callback_video_packet,"_fseek":_fseek,"_printf":_printf,"_fclose":_fclose,"_write":_write,"_ftell":_ftell,"___errno_location":___errno_location,"_abort":_abort,"_fwrite":_fwrite,"_time":_time,"_fprintf":_fprintf,"__formatString":__formatString,"_ogvjs_callback_audio_ready":_ogvjs_callback_audio_ready,"STACKTOP":STACKTOP,"STACK_MAX":STACK_MAX,"tempDoublePtr":tempDoublePtr,"ABORT":ABORT,"cttz_i8":cttz_i8};// EMSCRIPTEN_START_ASM
+var asm=(function(global,env,buffer) {
+"use asm";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.tempDoublePtr|0;var l=env.ABORT|0;var m=env.cttz_i8|0;var n=0;var o=0;var p=0;var q=0;var r=global.NaN,s=global.Infinity;var t=0,u=0,v=0,w=0,x=0.0,y=0,z=0,A=0,B=0.0;var C=0;var D=0;var E=0;var F=0;var G=0;var H=0;var I=0;var J=0;var K=0;var L=0;var M=global.Math.floor;var N=global.Math.abs;var O=global.Math.sqrt;var P=global.Math.pow;var Q=global.Math.cos;var R=global.Math.sin;var S=global.Math.tan;var T=global.Math.acos;var U=global.Math.asin;var V=global.Math.atan;var W=global.Math.atan2;var X=global.Math.exp;var Y=global.Math.log;var Z=global.Math.ceil;var _=global.Math.imul;var $=global.Math.min;var aa=global.Math.clz32;var ba=env.abort;var ca=env.assert;var da=env.invoke_iiii;var ea=env.invoke_vi;var fa=env.invoke_ii;var ga=env.invoke_iiiii;var ha=env.invoke_iii;var ia=env.invoke_iiiiii;var ja=env._send;var ka=env._lseek;var la=env.___setErrNo;var ma=env._ogvjs_callback_audio_packet;var na=env._ogvjs_callback_loaded_metadata;var oa=env._fflush;var pa=env._pwrite;var qa=env.__reallyNegative;var ra=env._sbrk;var sa=env._emscripten_memcpy_big;var ta=env._fileno;var ua=env._ogvjs_callback_frame_ready;var va=env._sysconf;var wa=env._close;var xa=env._ogvjs_callback_video_packet;var ya=env._fseek;var za=env._printf;var Aa=env._fclose;var Ba=env._write;var Ca=env._ftell;var Da=env.___errno_location;var Ea=env._abort;var Fa=env._fwrite;var Ga=env._time;var Ha=env._fprintf;var Ia=env.__formatString;var Ja=env._ogvjs_callback_audio_ready;var Ka=0.0;
+// EMSCRIPTEN_START_FUNCS
+function Ra(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+15&-16;return b|0}function Sa(){return i|0}function Ta(a){a=a|0;i=a}function Ua(a,b){a=a|0;b=b|0;i=a;j=b}function Va(a,b){a=a|0;b=b|0;if(!n){n=a;o=b}}function Wa(b){b=b|0;a[k>>0]=a[b>>0];a[k+1>>0]=a[b+1>>0];a[k+2>>0]=a[b+2>>0];a[k+3>>0]=a[b+3>>0]}function Xa(b){b=b|0;a[k>>0]=a[b>>0];a[k+1>>0]=a[b+1>>0];a[k+2>>0]=a[b+2>>0];a[k+3>>0]=a[b+3>>0];a[k+4>>0]=a[b+4>>0];a[k+5>>0]=a[b+5>>0];a[k+6>>0]=a[b+6>>0];a[k+7>>0]=a[b+7>>0]}function Ya(a){a=a|0;C=a}function Za(){return C|0}function _a(a){a=a|0;return (d[(c[a>>2]|0)+5>>0]|0)&1|0}function $a(a){a=a|0;return (d[(c[a>>2]|0)+5>>0]|0)&2|0}function ab(a){a=a|0;var b=0,e=0;b=c[a>>2]|0;a=Ie(d[b+13>>0]|0|0,0,8)|0;e=Ie(a|(d[b+12>>0]|0)|0,C|0,8)|0;a=Ie(e|(d[b+11>>0]|0)|0,C|0,8)|0;e=Ie(a|(d[b+10>>0]|0)|0,C|0,8)|0;a=Ie(e|(d[b+9>>0]|0)|0,C|0,8)|0;e=Ie(a|(d[b+8>>0]|0)|0,C|0,8)|0;a=Ie(e|(d[b+7>>0]|0)|0,C|0,8)|0;return a|(d[b+6>>0]|0)|0}function bb(a){a=a|0;var b=0;b=c[a>>2]|0;return (d[b+15>>0]|0)<<8|(d[b+14>>0]|0)|(d[b+16>>0]|0)<<16|(d[b+17>>0]|0)<<24|0}function cb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0;if(!a){d=-1;return d|0}He(a|0,0,360)|0;c[a+4>>2]=16384;c[a+24>>2]=1024;e=ye(16384)|0;c[a>>2]=e;f=ye(4096)|0;g=a+16|0;c[g>>2]=f;h=ye(8192)|0;i=a+20|0;c[i>>2]=h;do if(!e)j=f;else{if((h|0)==0|(f|0)==0){ze(e);j=c[g>>2]|0;break}c[a+336>>2]=b;d=0;return d|0}while(0);if(j)ze(j);j=c[i>>2]|0;if(j)ze(j);He(a|0,0,360)|0;d=-1;return d|0}function db(a){a=a|0;var b=0;if(!a)return 0;b=c[a>>2]|0;if(b)ze(b);b=c[a+16>>2]|0;if(b)ze(b);b=c[a+20>>2]|0;if(b)ze(b);He(a|0,0,360)|0;return 0}function eb(a){a=a|0;if(!a)return 0;c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0;c[a+16>>2]=0;c[a+20>>2]=0;c[a+24>>2]=0;return 0}function fb(a){a=a|0;var b=0;if(!a)return 0;b=c[a>>2]|0;if(b)ze(b);c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0;c[a+16>>2]=0;c[a+20>>2]=0;c[a+24>>2]=0;return 0}function gb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;d=a+4|0;e=c[d>>2]|0;if((e|0)<=-1){f=0;return f|0}g=a+12|0;h=c[g>>2]|0;i=a+8|0;if(!h)j=e;else{k=(c[i>>2]|0)-h|0;c[i>>2]=k;if((k|0)>0){l=c[a>>2]|0;Ne(l|0,l+h|0,k|0)|0;m=c[d>>2]|0}else m=e;c[g>>2]=0;j=m}m=c[i>>2]|0;do if((j-m|0)<(b|0)){g=b+4096+m|0;e=c[a>>2]|0;if(!e)n=ye(g)|0;else n=Be(e,g)|0;if(n){c[a>>2]=n;c[d>>2]=g;o=n;p=c[i>>2]|0;break}g=c[a>>2]|0;if(g)ze(g);c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0;c[a+16>>2]=0;c[a+20>>2]=0;c[a+24>>2]=0;f=0;return f|0}else{o=c[a>>2]|0;p=m}while(0);f=o+p|0;return f|0}function hb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=c[a+4>>2]|0;if((d|0)<=-1){e=-1;return e|0}f=a+8|0;a=(c[f>>2]|0)+b|0;if((a|0)>(d|0)){e=-1;return e|0}c[f>>2]=a;e=0;return e|0}function ib(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0;f=i;i=i+16|0;g=f;h=c[b>>2]|0;j=b+12|0;k=c[j>>2]|0;l=h+k|0;m=b+8|0;n=(c[m>>2]|0)-k|0;if((c[b+4>>2]|0)<=-1){o=0;i=f;return o|0}p=b+20|0;q=c[p>>2]|0;do if(!q){if((n|0)<27){o=0;i=f;return o|0}if(ve(l,1032,4)|0){r=b+24|0;break}s=h+(k+26)|0;t=a[s>>0]|0;u=(t&255)+27|0;if((n|0)<(u|0)){o=0;i=f;return o|0}if(t<<24>>24){t=k+27|0;v=b+24|0;w=c[v>>2]|0;x=0;do{w=w+(d[h+(t+x)>>0]|0)|0;c[v>>2]=w;x=x+1|0}while((x|0)<(d[s>>0]|0|0))}c[p>>2]=u;y=u;z=11}else{y=q;z=11}while(0);do if((z|0)==11){q=b+24|0;if((y+(c[q>>2]|0)|0)>(n|0)){o=0;i=f;return o|0}s=h+(k+22)|0;x=d[s>>0]|d[s+1>>0]<<8|d[s+2>>0]<<16|d[s+3>>0]<<24;c[g>>2]=x;a[s>>0]=0;a[s+1>>0]=0;a[s+2>>0]=0;a[s+3>>0]=0;w=c[p>>2]|0;v=w+k|0;t=c[q>>2]|0;a[s>>0]=0;A=h+(k+23)|0;a[A>>0]=0;B=h+(k+24)|0;a[B>>0]=0;C=h+(k+25)|0;a[C>>0]=0;if((w|0)>0){D=0;E=0;while(1){F=c[8+(((d[h+(E+k)>>0]|0)^D>>>24)<<2)>>2]^D<<8;E=E+1|0;if((E|0)==(w|0)){G=F;break}else D=F}}else G=0;if((t|0)>0){D=G;w=0;while(1){E=c[8+(((d[h+(v+w)>>0]|0)^D>>>24)<<2)>>2]^D<<8;w=w+1|0;if((w|0)==(t|0)){H=E;break}else D=E}}else H=G;a[s>>0]=H;a[A>>0]=H>>>8;a[B>>0]=H>>>16;a[C>>0]=H>>>24;if(ve(g,s,4)|0){a[s>>0]=x;a[s+1>>0]=x>>8;a[s+2>>0]=x>>16;a[s+3>>0]=x>>24;r=q;break}D=c[b>>2]|0;t=c[j>>2]|0;if(!e){I=c[q>>2]|0;J=c[p>>2]|0}else{c[e>>2]=D+t;w=c[p>>2]|0;c[e+4>>2]=w;c[e+8>>2]=D+(w+t);D=c[q>>2]|0;c[e+12>>2]=D;I=D;J=w}c[b+16>>2]=0;w=I+J|0;c[j>>2]=t+w;c[p>>2]=0;c[q>>2]=0;o=w;i=f;return o|0}while(0);c[p>>2]=0;c[r>>2]=0;r=ue(h+(k+1)|0,79,n+-1|0)|0;n=c[b>>2]|0;if(!r)K=n+(c[m>>2]|0)|0;else K=r;r=K;c[j>>2]=r-n;o=l-r|0;i=f;return o|0}function jb(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0;f=c[e>>2]|0;g=c[e+8>>2]|0;h=c[e+12>>2]|0;e=a[f+4>>0]|0;i=d[f+5>>0]|0;j=i&1;k=i&2;l=i&4;i=Ie(d[f+13>>0]|0|0,0,8)|0;m=Ie(i|(d[f+12>>0]|0)|0,C|0,8)|0;i=Ie(m|(d[f+11>>0]|0)|0,C|0,8)|0;m=Ie(i|(d[f+10>>0]|0)|0,C|0,8)|0;i=Ie(m|(d[f+9>>0]|0)|0,C|0,8)|0;m=Ie(i|(d[f+8>>0]|0)|0,C|0,8)|0;i=Ie(m|(d[f+7>>0]|0)|0,C|0,8)|0;m=C;n=i|(d[f+6>>0]|0);i=(d[f+15>>0]|0)<<8|(d[f+14>>0]|0)|(d[f+16>>0]|0)<<16|(d[f+17>>0]|0)<<24;o=(d[f+19>>0]|0)<<8|(d[f+18>>0]|0)|(d[f+20>>0]|0)<<16|(d[f+21>>0]|0)<<24;p=d[f+26>>0]|0;if(!b){q=-1;return q|0}r=c[b>>2]|0;if(!r){q=-1;return q|0}s=b+36|0;t=c[s>>2]|0;u=b+12|0;v=c[u>>2]|0;if(v){w=b+8|0;x=c[w>>2]|0;y=x-v|0;c[w>>2]=y;if((x|0)!=(v|0))Ne(r|0,r+v|0,y|0)|0;c[u>>2]=0}if(t){u=b+28|0;y=c[u>>2]|0;if((y|0)==(t|0))z=t;else{v=c[b+16>>2]|0;Ne(v|0,v+(t<<2)|0,y-t<<2|0)|0;y=c[b+20>>2]|0;Ne(y|0,y+(t<<3)|0,(c[u>>2]|0)-t<<3|0)|0;z=c[u>>2]|0}c[u>>2]=z-t;z=b+32|0;c[z>>2]=(c[z>>2]|0)-t;c[s>>2]=0}if(e<<24>>24!=0?1:(i|0)!=(c[b+336>>2]|0)){q=-1;return q|0}if(nb(b,p+1|0)|0){q=-1;return q|0}i=b+340|0;e=c[i>>2]|0;if((o|0)!=(e|0)){s=b+32|0;t=c[s>>2]|0;z=b+28|0;u=c[z>>2]|0;if((t|0)<(u|0)){y=c[b+16>>2]|0;v=b+8|0;r=c[v>>2]|0;x=t;while(1){w=r-(c[y+(x<<2)>>2]&255)|0;x=x+1|0;if((x|0)>=(u|0)){A=w;break}else r=w}c[v>>2]=A}c[z>>2]=t;if((e|0)!=-1){e=t+1|0;c[z>>2]=e;c[(c[b+16>>2]|0)+(t<<2)>>2]=1024;c[s>>2]=e}}a:do if(!j){B=g;D=h;E=k;F=0}else{e=c[b+28>>2]|0;if((e|0)>=1?(c[(c[b+16>>2]|0)+(e+-1<<2)>>2]|0)!=1024:0){B=g;D=h;E=k;F=0;break}else{G=g;H=h;I=0}while(1){if((I|0)>=(p|0)){B=G;D=H;E=0;F=I;break a}e=a[f+(I+27)>>0]|0;s=e&255;t=G+s|0;z=H-s|0;s=I+1|0;if(e<<24>>24==-1){G=t;H=z;I=s}else{B=t;D=z;E=0;F=s;break}}}while(0);if(D){I=b+4|0;H=c[I>>2]|0;G=b+8|0;h=c[G>>2]|0;do if((H-D|0)>(h|0)){J=c[b>>2]|0;K=h}else{if((H|0)>(2147483647-D|0)){g=c[b>>2]|0;if(g)ze(g);g=c[b+16>>2]|0;if(g)ze(g);g=c[b+20>>2]|0;if(g)ze(g);He(b|0,0,360)|0;q=-1;return q|0}g=H+D|0;k=(g|0)<2147482623?g+1024|0:g;g=Be(c[b>>2]|0,k)|0;if(g){c[I>>2]=k;c[b>>2]=g;J=g;K=c[G>>2]|0;break}g=c[b>>2]|0;if(g)ze(g);g=c[b+16>>2]|0;if(g)ze(g);g=c[b+20>>2]|0;if(g)ze(g);He(b|0,0,360)|0;q=-1;return q|0}while(0);Ke(J+K|0,B|0,D|0)|0;c[G>>2]=(c[G>>2]|0)+D}if((F|0)<(p|0)){D=b+28|0;G=b+32|0;B=c[b+16>>2]|0;K=c[b+20>>2]|0;J=c[D>>2]|0;I=E;E=-1;H=F;b:while(1){F=J;h=I;g=H;while(1){k=a[f+(g+27)>>0]|0;j=k&255;s=B+(F<<2)|0;c[s>>2]=j;z=K+(F<<3)|0;c[z>>2]=-1;c[z+4>>2]=-1;if(h)c[s>>2]=j|256;j=F;F=F+1|0;c[D>>2]=F;g=g+1|0;if(k<<24>>24!=-1){L=j;M=F;N=g;break}if((g|0)>=(p|0)){O=E;break b}else h=0}c[G>>2]=M;if((N|0)<(p|0)){J=M;I=0;E=L;H=N}else{O=L;break}}if((O|0)!=-1){L=(c[b+20>>2]|0)+(O<<3)|0;c[L>>2]=n;c[L+4>>2]=m}}if((l|0)!=0?(c[b+328>>2]=1,l=c[b+28>>2]|0,(l|0)>0):0){m=(c[b+16>>2]|0)+(l+-1<<2)|0;c[m>>2]=c[m>>2]|512}c[i>>2]=o+1;q=0;return q|0}function kb(a){a=a|0;var b=0,d=0;if((c[a+4>>2]|0)<=-1){b=-1;return b|0}d=a+8|0;c[d>>2]=0;c[d+4>>2]=0;c[d+8>>2]=0;c[d+12>>2]=0;c[d+16>>2]=0;b=0;return b|0}function lb(a){a=a|0;var b=0,d=0;if(!a){b=-1;return b|0}if(!(c[a>>2]|0)){b=-1;return b|0}c[a+8>>2]=0;c[a+12>>2]=0;c[a+28>>2]=0;c[a+32>>2]=0;c[a+36>>2]=0;c[a+324>>2]=0;c[a+328>>2]=0;c[a+332>>2]=0;c[a+340>>2]=-1;d=a+344|0;c[d>>2]=0;c[d+4>>2]=0;c[d+8>>2]=0;c[d+12>>2]=0;b=0;return b|0}function mb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;if(!a){d=0;return d|0}e=c[a>>2]|0;if(!e){d=0;return d|0}f=a+36|0;g=c[f>>2]|0;if((c[a+32>>2]|0)<=(g|0)){d=0;return d|0}h=c[a+16>>2]|0;i=c[h+(g<<2)>>2]|0;if(i&1024){c[f>>2]=g+1;j=a+344|0;k=j;l=Me(c[k>>2]|0,c[k+4>>2]|0,1,0)|0;k=j;c[k>>2]=l;c[k+4>>2]=C;d=-1;return d|0}k=(b|0)==0;l=i&255;j=i&512;m=i&256;if((l|0)==255){i=255;n=j;o=g;while(1){p=o+1|0;q=c[h+(p<<2)>>2]|0;r=q&255;s=(q&512|0)==0?n:512;q=r+i|0;if((r|0)==255){i=q;n=s;o=p}else{t=q;u=s;v=p;break}}}else{t=l;u=j;v=g}if(k){k=a+12|0;g=a+344|0;j=g;w=g;x=k;y=c[k>>2]|0;z=c[j>>2]|0;A=c[j+4>>2]|0}else{c[b+12>>2]=u;c[b+8>>2]=m;m=a+12|0;u=c[m>>2]|0;c[b>>2]=e+u;e=a+344|0;j=e;k=c[j>>2]|0;g=c[j+4>>2]|0;j=b+24|0;c[j>>2]=k;c[j+4>>2]=g;j=(c[a+20>>2]|0)+(v<<3)|0;a=c[j+4>>2]|0;l=b+16|0;c[l>>2]=c[j>>2];c[l+4>>2]=a;c[b+4>>2]=t;w=e;x=m;y=u;z=k;A=g}c[x>>2]=y+t;c[f>>2]=v+1;v=Me(z|0,A|0,1,0)|0;A=w;c[A>>2]=v;c[A+4>>2]=C;d=1;return d|0}function nb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=a+24|0;e=c[d>>2]|0;if((e-b|0)>(c[a+28>>2]|0)){f=0;return f|0}if((e|0)>(2147483647-b|0)){g=c[a>>2]|0;if(g)ze(g);g=c[a+16>>2]|0;if(g)ze(g);g=c[a+20>>2]|0;if(g)ze(g);He(a|0,0,360)|0;f=-1;return f|0}g=e+b|0;b=(g|0)<2147483615?g+32|0:g;g=a+16|0;e=Be(c[g>>2]|0,b<<2)|0;if(!e){h=c[a>>2]|0;if(h)ze(h);h=c[g>>2]|0;if(h)ze(h);h=c[a+20>>2]|0;if(h)ze(h);He(a|0,0,360)|0;f=-1;return f|0}c[g>>2]=e;e=a+20|0;h=Be(c[e>>2]|0,b<<3)|0;if(h){c[e>>2]=h;c[d>>2]=b;f=0;return f|0}b=c[a>>2]|0;if(b)ze(b);b=c[g>>2]|0;if(b)ze(b);b=c[e>>2]|0;if(b)ze(b);He(a|0,0,360)|0;f=-1;return f|0}function ob(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;b=i;i=i+16|0;d=b+8|0;e=b+4|0;f=b;c[e>>2]=a;if(sc(c[e>>2]|0)|0){c[d>>2]=0;g=c[d>>2]|0;i=b;return g|0}c[f>>2]=ye(568)|0;if(!(c[f>>2]|0)){c[d>>2]=0;g=c[d>>2]|0;i=b;return g|0}c[c[f>>2]>>2]=c[e>>2];c[(c[f>>2]|0)+4>>2]=0;c[(c[f>>2]|0)+8>>2]=0;c[(c[f>>2]|0)+64>>2]=0;c[(c[f>>2]|0)+68>>2]=0;c[(c[f>>2]|0)+72>>2]=1024;c[(c[f>>2]|0)+76>>2]=0;e=_b()|0;c[(c[f>>2]|0)+80>>2]=e;do if(c[(c[f>>2]|0)+80>>2]|0){c[(c[f>>2]|0)+84>>2]=0;c[(c[f>>2]|0)+88>>2]=0;c[(c[f>>2]|0)+92>>2]=0;c[(c[f>>2]|0)+96>>2]=0;c[(c[f>>2]|0)+100>>2]=0;c[(c[f>>2]|0)+104>>2]=0;e=gc()|0;c[(c[f>>2]|0)+560>>2]=e;e=c[f>>2]|0;if(!(c[(c[f>>2]|0)+560>>2]|0)){ze(c[e+80>>2]|0);break}Eb(e)|0;c[d>>2]=c[f>>2];g=c[d>>2]|0;i=b;return g|0}while(0);ze(c[f>>2]|0);c[d>>2]=0;g=c[d>>2]|0;i=b;return g|0}function pb(a){a=a|0;var b=0,d=0,e=0,f=0;b=i;i=i+16|0;d=b+4|0;e=b;c[e>>2]=a;if(!(c[e>>2]|0)){c[d>>2]=-2;f=c[d>>2]|0;i=b;return f|0}Fb(c[e>>2]|0)|0;dc(c[(c[e>>2]|0)+80>>2]|0,1)|0;$b(c[(c[e>>2]|0)+80>>2]|0);lc(c[(c[e>>2]|0)+560>>2]|0,2)|0;hc(c[(c[e>>2]|0)+560>>2]|0);if(c[(c[e>>2]|0)+96>>2]|0)ze(c[(c[e>>2]|0)+92>>2]|0);if((c[(c[e>>2]|0)+4>>2]|0)!=0?(Aa(c[(c[e>>2]|0)+4>>2]|0)|0)==-1:0){c[d>>2]=-10;f=c[d>>2]|0;i=b;return f|0}if(c[(c[e>>2]|0)+8>>2]|0){Db(c[e>>2]|0)|0;ze(c[(c[e>>2]|0)+8>>2]|0)}ze(c[e>>2]|0);c[d>>2]=0;f=c[d>>2]|0;i=b;return f|0}function qb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;b=i;i=i+16|0;d=b;e=b+12|0;f=b+8|0;c[e>>2]=a;do if(c[e>>2]|0)if(c[c[e>>2]>>2]&1){a=d;c[a>>2]=-3;c[a+4>>2]=-1;break}else{c[f>>2]=(c[e>>2]|0)+112;a=(c[f>>2]|0)+416|0;g=c[a+4>>2]|0;h=d;c[h>>2]=c[a>>2];c[h+4>>2]=g;break}else{g=d;c[g>>2]=-2;c[g+4>>2]=-1}while(0);f=d;C=c[f+4>>2]|0;i=b;return c[f>>2]|0}function rb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;b=i;i=i+16|0;d=b;e=b+8|0;c[e>>2]=a;do if(c[e>>2]|0)if(c[c[e>>2]>>2]&1){a=d;c[a>>2]=-3;c[a+4>>2]=-1;break}else{a=(c[e>>2]|0)+112+424|0;f=c[a+4>>2]|0;g=d;c[g>>2]=c[a>>2];c[g+4>>2]=f;break}else{f=d;c[f>>2]=-2;c[f+4>>2]=-1}while(0);e=d;C=c[e+4>>2]|0;i=b;return c[e>>2]|0}function sb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;i=i+16|0;e=d+8|0;f=d+4|0;g=d;c[f>>2]=a;c[g>>2]=b;if((c[g>>2]|0)==-1){c[e>>2]=0;h=c[e>>2]|0;i=d;return h|0}else{c[e>>2]=cc(c[(c[f>>2]|0)+80>>2]|0,1,c[g>>2]|0)|0;h=c[e>>2]|0;i=d;return h|0}return 0}function tb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[f>>2]=a;c[g>>2]=b;c[h>>2]=ye(512)|0;if(!(c[h>>2]|0)){c[e>>2]=0;j=c[e>>2]|0;i=d;return j|0}cb(c[h>>2]|0,c[g>>2]|0)|0;g=(yb(c[h>>2]|0)|0)==-1;b=c[h>>2]|0;if(g){ze(b);c[e>>2]=0;j=c[e>>2]|0;i=d;return j|0}else{c[b+360>>2]=15;c[(c[h>>2]|0)+364>>2]=3;c[(c[h>>2]|0)+368>>2]=0;b=(c[h>>2]|0)+376|0;c[b>>2]=1;c[b+4>>2]=0;b=(c[h>>2]|0)+384|0;c[b>>2]=1;c[b+4>>2]=0;b=(c[h>>2]|0)+392|0;c[b>>2]=0;c[b+4>>2]=0;b=(c[h>>2]|0)+400|0;c[b>>2]=0;c[b+4>>2]=0;c[(c[h>>2]|0)+408>>2]=0;c[(c[h>>2]|0)+420>>2]=0;c[(c[h>>2]|0)+424>>2]=1;c[(c[h>>2]|0)+428>>2]=0;b=(c[h>>2]|0)+432|0;c[b>>2]=0;c[b+4>>2]=0;b=(c[h>>2]|0)+440|0;c[b>>2]=-1;c[b+4>>2]=-1;c[(c[h>>2]|0)+448>>2]=0;c[(c[h>>2]|0)+452>>2]=0;c[(c[h>>2]|0)+456>>2]=0;c[(c[h>>2]|0)+460>>2]=0;c[(c[h>>2]|0)+464>>2]=0;c[(c[h>>2]|0)+468>>2]=0;c[(c[h>>2]|0)+472>>2]=0;c[(c[h>>2]|0)+476>>2]=0;c[(c[h>>2]|0)+480>>2]=0;c[(c[h>>2]|0)+504>>2]=0;ec(c[(c[f>>2]|0)+80>>2]|0,c[h>>2]|0)|0;c[e>>2]=c[h>>2];j=c[e>>2]|0;i=d;return j|0}return 0}function ub(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;g=i;i=i+32|0;h=g+8|0;j=g+16|0;k=g+20|0;l=g+24|0;m=g+4|0;n=g;o=g+12|0;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[n>>2]=f;if(!(c[j>>2]|0)){c[h>>2]=-2;p=c[h>>2]|0;i=g;return p|0}f=c[j>>2]|0;if((c[k>>2]|0)==-1){if((c[f+96>>2]|0)!=0?(c[(c[j>>2]|0)+92>>2]|0)!=0:0)ze(c[(c[j>>2]|0)+92>>2]|0);c[(c[j>>2]|0)+88>>2]=c[l>>2];c[(c[j>>2]|0)+92>>2]=c[m>>2];c[(c[j>>2]|0)+96>>2]=c[n>>2]}else{c[o>>2]=sb(f,c[k>>2]|0)|0;if(!(c[o>>2]|0)){c[h>>2]=-20;p=c[h>>2]|0;i=g;return p|0}if((c[(c[o>>2]|0)+456>>2]|0)!=0?(c[(c[o>>2]|0)+452>>2]|0)!=0:0)ze(c[(c[o>>2]|0)+452>>2]|0);c[(c[o>>2]|0)+448>>2]=c[l>>2];c[(c[o>>2]|0)+452>>2]=c[m>>2];c[(c[o>>2]|0)+456>>2]=c[n>>2]}c[h>>2]=0;p=c[h>>2]|0;i=g;return p|0}function vb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[f>>2]=a;c[g>>2]=b;do if(!(c[(c[f>>2]|0)+88>>2]|0)){c[h>>2]=sb(c[f>>2]|0,c[g>>2]|0)|0;if(!(c[h>>2]|0)){c[e>>2]=-20;break}if(c[(c[h>>2]|0)+448>>2]|0){c[e>>2]=1;break}else{c[e>>2]=0;break}}else c[e>>2]=1;while(0);i=d;return c[e>>2]|0}function wb(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0;f=i;i=i+32|0;g=f+8|0;h=f+24|0;j=f+20|0;k=f;l=f+16|0;c[h>>2]=a;c[j>>2]=b;b=k;c[b>>2]=d;c[b+4>>2]=e;do if(!(c[h>>2]|0)){e=g;c[e>>2]=-2;c[e+4>>2]=-1}else{e=k;if((c[e>>2]|0)==-1?(c[e+4>>2]|0)==-1:0){e=g;c[e>>2]=-1;c[e+4>>2]=-1;break}e=c[h>>2]|0;if((c[j>>2]|0)==-1){if(c[e+88>>2]|0){b=k;d=Qa[c[(c[h>>2]|0)+88>>2]&31](c[h>>2]|0,c[j>>2]|0,c[b>>2]|0,c[b+4>>2]|0,c[(c[h>>2]|0)+92>>2]|0)|0;b=g;c[b>>2]=d;c[b+4>>2]=C;break}}else{c[l>>2]=sb(e,c[j>>2]|0)|0;if(!(c[l>>2]|0)){e=g;c[e>>2]=-1;c[e+4>>2]=-1;break}if(c[(c[l>>2]|0)+448>>2]|0){e=k;b=Qa[c[(c[l>>2]|0)+448>>2]&31](c[h>>2]|0,c[j>>2]|0,c[e>>2]|0,c[e+4>>2]|0,c[(c[l>>2]|0)+452>>2]|0)|0;e=g;c[e>>2]=b;c[e+4>>2]=C;break}if(c[(c[h>>2]|0)+88>>2]|0){e=k;b=Qa[c[(c[h>>2]|0)+88>>2]&31](c[h>>2]|0,c[j>>2]|0,c[e>>2]|0,c[e+4>>2]|0,c[(c[h>>2]|0)+92>>2]|0)|0;e=g;c[e>>2]=b;c[e+4>>2]=C;break}}e=g;c[e>>2]=-1;c[e+4>>2]=-1}while(0);h=g;C=c[h+4>>2]|0;i=f;return c[h>>2]|0}function xb(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b+4|0;e=b;c[e>>2]=a;a=c[e>>2]|0;if((a|0)==1)c[d>>2]=-14;else if((a|0)==-1)c[d>>2]=-15;else if(!a)c[d>>2]=0;else c[d>>2]=c[e>>2];i=b;return c[d>>2]|0}function yb(a){a=a|0;var b=0,d=0,e=0,f=0;b=i;i=i+16|0;d=b+4|0;e=b;c[e>>2]=a;c[(c[e>>2]|0)+412>>2]=0;a=_b()|0;c[(c[e>>2]|0)+416>>2]=a;if(!(c[(c[e>>2]|0)+416>>2]|0)){c[d>>2]=-1;f=c[d>>2]|0;i=b;return f|0}else{fc(c[(c[e>>2]|0)+416>>2]|0,1,0)|0;c[d>>2]=0;f=c[d>>2]|0;i=b;return f|0}return 0}function zb(a){a=a|0;var b=0,d=0,e=0,f=0;b=i;i=i+16|0;d=b;c[d>>2]=a;dc(c[(c[d>>2]|0)+416>>2]|0,1)|0;$b(c[(c[d>>2]|0)+416>>2]|0);c[(c[d>>2]|0)+416>>2]=0;if(!(c[(c[d>>2]|0)+412>>2]|0)){e=c[d>>2]|0;f=e+412|0;c[f>>2]=0;i=b;return 0}ze(c[(c[d>>2]|0)+412>>2]|0);e=c[d>>2]|0;f=e+412|0;c[f>>2]=0;i=b;return 0}function Ab(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;g=i;i=i+64|0;h=g+52|0;j=g+44|0;k=g+24|0;l=g+20|0;m=g+12|0;n=g+40|0;o=g+48|0;p=g+56|0;q=g+28|0;r=g+8|0;s=g+4|0;t=g+32|0;u=g;v=g+16|0;w=g+36|0;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;c[m>>2]=f;c[o>>2]=c[l>>2];c[w>>2]=0;if((c[m>>2]|0)<8){c[h>>2]=-1;x=c[h>>2]|0;i=g;return x|0}c[t>>2]=(c[o>>2]|0)+(c[m>>2]|0);c[s>>2]=a[(c[o>>2]|0)+3>>0]<<24&-16777216|a[(c[o>>2]|0)+2>>0]<<16&16711680|a[(c[o>>2]|0)+1>>0]<<8&65280|a[c[o>>2]>>0]&255;c[o>>2]=(c[o>>2]|0)+4;if((c[s>>2]|0)>>>0>((c[t>>2]|0)-(c[o>>2]|0)|0)>>>0){c[h>>2]=-1;x=c[h>>2]|0;i=g;return x|0}c[n>>2]=sb(c[j>>2]|0,c[k>>2]|0)|0;if(!(c[n>>2]|0)){c[h>>2]=-20;x=c[h>>2]|0;i=g;return x|0}if((c[s>>2]|0)>>>0>0){m=yc(c[o>>2]|0,c[s>>2]|0)|0;c[w>>2]=m;if(!m){c[h>>2]=-18;x=c[h>>2]|0;i=g;return x|0}m=(zc(c[j>>2]|0,c[k>>2]|0,c[w>>2]|0)|0)==-18;ze(c[w>>2]|0);if(m){c[h>>2]=-18;x=c[h>>2]|0;i=g;return x|0}}c[o>>2]=(c[o>>2]|0)+(c[s>>2]|0);if(((c[o>>2]|0)+4|0)>>>0>(c[t>>2]|0)>>>0){c[h>>2]=-1;x=c[h>>2]|0;i=g;return x|0}c[q>>2]=a[(c[o>>2]|0)+3>>0]<<24&-16777216|a[(c[o>>2]|0)+2>>0]<<16&16711680|a[(c[o>>2]|0)+1>>0]<<8&65280|a[c[o>>2]>>0]&255;c[o>>2]=(c[o>>2]|0)+4;c[p>>2]=0;while(1){if((c[p>>2]|0)>=(c[q>>2]|0)){y=34;break}if(((c[o>>2]|0)+4|0)>>>0>(c[t>>2]|0)>>>0){y=17;break}c[s>>2]=a[(c[o>>2]|0)+3>>0]<<24&-16777216|a[(c[o>>2]|0)+2>>0]<<16&16711680|a[(c[o>>2]|0)+1>>0]<<8&65280|a[c[o>>2]>>0]&255;c[o>>2]=(c[o>>2]|0)+4;if((c[s>>2]|0)>>>0>((c[t>>2]|0)-(c[o>>2]|0)|0)>>>0){y=19;break}c[r>>2]=0;c[u>>2]=c[o>>2];c[v>>2]=Ac(c[o>>2]|0,61,c[s>>2]|0)|0;if(c[v>>2]|0){a[c[v>>2]>>0]=0;c[v>>2]=(c[v>>2]|0)+1;c[r>>2]=(c[o>>2]|0)+(c[s>>2]|0)-(c[v>>2]|0)}if(c[r>>2]|0){m=yc(c[v>>2]|0,c[r>>2]|0)|0;c[w>>2]=m;if(!m){y=24;break}m=(Bc(c[n>>2]|0,c[u>>2]|0,c[w>>2]|0)|0)==0;ze(c[w>>2]|0);if(m){y=26;break}}else{m=yc(c[u>>2]|0,c[s>>2]|0)|0;c[w>>2]=m;if(!m){y=28;break}m=(Bc(c[n>>2]|0,c[w>>2]|0,0)|0)==0;ze(c[w>>2]|0);if(m){y=30;break}}if(c[v>>2]|0)a[(c[v>>2]|0)+-1>>0]=61;c[o>>2]=(c[o>>2]|0)+(c[s>>2]|0);c[p>>2]=(c[p>>2]|0)+1}if((y|0)==17){c[h>>2]=-1;x=c[h>>2]|0;i=g;return x|0}else if((y|0)==19){c[h>>2]=-1;x=c[h>>2]|0;i=g;return x|0}else if((y|0)==24){c[h>>2]=-18;x=c[h>>2]|0;i=g;return x|0}else if((y|0)==26){c[h>>2]=-18;x=c[h>>2]|0;i=g;return x|0}else if((y|0)==28){c[h>>2]=-18;x=c[h>>2]|0;i=g;return x|0}else if((y|0)==30){c[h>>2]=-18;x=c[h>>2]|0;i=g;return x|0}else if((y|0)==34){c[h>>2]=0;x=c[h>>2]|0;i=g;return x|0}return 0}function Bb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e+4|0;k=e;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;d=c[g>>2]|0;do if(c[(c[g>>2]|0)+4>>2]|0)if((ya(c[d+4>>2]|0,c[h>>2]|0,c[j>>2]|0)|0)==-1)c[f>>2]=-10;else l=10;else{b=c[d+8>>2]|0;c[k>>2]=b;if(!b){c[f>>2]=-3;break}if(!(c[(c[k>>2]|0)+16>>2]|0)){c[f>>2]=-1;break}if((La[c[(c[k>>2]|0)+16>>2]&1](c[(c[k>>2]|0)+20>>2]|0,c[h>>2]|0,c[j>>2]|0)|0)==-1)c[f>>2]=-1;else l=10}while(0);if((l|0)==10)c[f>>2]=0;i=e;return c[f>>2]|0}function Cb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0;b=i;i=i+16|0;d=b+12|0;e=b+8|0;f=b+4|0;g=b;c[e>>2]=a;a=c[e>>2]|0;do if(c[(c[e>>2]|0)+4>>2]|0){h=Ca(c[a+4>>2]|0)|0;c[g>>2]=h;if((h|0)==-1)c[d>>2]=-1;else j=10}else{h=c[a+8>>2]|0;c[f>>2]=h;if(!h){c[d>>2]=-3;break}if(!(c[(c[f>>2]|0)+24>>2]|0)){c[d>>2]=-1;break}h=Na[c[(c[f>>2]|0)+24>>2]&7](c[(c[f>>2]|0)+28>>2]|0)|0;c[g>>2]=h;if((h|0)==-1)c[d>>2]=-1;else j=10}while(0);if((j|0)==10)c[d>>2]=c[g>>2];i=b;return c[d>>2]|0}function Db(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;b=i;i=i+16|0;d=b+8|0;e=b+4|0;f=b;c[e>>2]=a;a=c[e>>2]|0;do if(c[(c[e>>2]|0)+4>>2]|0)if((oa(c[a+4>>2]|0)|0)==-1)c[d>>2]=-10;else g=10;else{h=c[a+8>>2]|0;c[f>>2]=h;if(!h){c[d>>2]=-3;break}if(!(c[(c[f>>2]|0)+32>>2]|0)){c[d>>2]=-3;break}if((Na[c[(c[f>>2]|0)+32>>2]&7](c[(c[f>>2]|0)+36>>2]|0)|0)==-1)c[d>>2]=-1;else g=10}while(0);if((g|0)==10)c[d>>2]=0;i=b;return c[d>>2]|0}function Eb(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b+4|0;e=b;c[d>>2]=a;c[e>>2]=(c[d>>2]|0)+112;eb(c[e>>2]|0)|0;cb((c[e>>2]|0)+32|0,-1)|0;c[(c[e>>2]|0)+392>>2]=-1;c[(c[e>>2]|0)+396>>2]=0;c[(c[e>>2]|0)+400>>2]=0;c[(c[e>>2]|0)+404>>2]=0;c[(c[e>>2]|0)+408>>2]=0;a=(c[e>>2]|0)+416|0;c[a>>2]=0;c[a+4>>2]=0;c[(c[e>>2]|0)+432>>2]=0;c[(c[e>>2]|0)+436>>2]=0;c[(c[e>>2]|0)+440>>2]=0;i=b;return c[d>>2]|0}function Fb(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b+4|0;e=b;c[d>>2]=a;c[e>>2]=(c[d>>2]|0)+112;db((c[e>>2]|0)+32|0)|0;fb(c[e>>2]|0)|0;i=b;return c[d>>2]|0}function Gb(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;f=i;i=i+32|0;g=f+8|0;h=f+16|0;j=f+20|0;k=f+24|0;l=f+4|0;m=f;n=f+12|0;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;if(!(c[h>>2]|0)){c[g>>2]=-2;o=c[g>>2]|0;i=f;return o|0}c[m>>2]=(c[h>>2]|0)+112;if(c[c[h>>2]>>2]&1){c[g>>2]=-3;o=c[g>>2]|0;i=f;return o|0}do if((c[j>>2]|0)==-1){c[(c[m>>2]|0)+396>>2]=c[k>>2];c[(c[m>>2]|0)+400>>2]=c[l>>2]}else{c[n>>2]=sb(c[h>>2]|0,c[j>>2]|0)|0;if(!(c[n>>2]|0))c[n>>2]=tb(c[h>>2]|0,c[j>>2]|0)|0;if(c[n>>2]|0){c[(c[n>>2]|0)+468>>2]=c[k>>2];c[(c[n>>2]|0)+472>>2]=c[l>>2];break}c[g>>2]=-18;o=c[g>>2]|0;i=f;return o|0}while(0);c[g>>2]=0;o=c[g>>2]|0;i=f;return o|0}function Hb(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;g=i;i=i+32|0;h=g+4|0;j=g+16|0;k=g+8|0;l=g+20|0;m=g+28|0;n=g;o=g+12|0;p=g+24|0;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[n>>2]=f;c[p>>2]=c[k>>2];f=ye(72)|0;c[o>>2]=f;if(!f){c[h>>2]=0;q=c[h>>2]|0;i=g;return q|0}f=c[o>>2]|0;e=c[k>>2]|0;k=f+56|0;do{c[f>>2]=c[e>>2];f=f+4|0;e=e+4|0}while((f|0)<(k|0));e=ye(c[(c[p>>2]|0)+4>>2]|0)|0;c[c[o>>2]>>2]=e;f=c[o>>2]|0;if(!e){ze(f);c[h>>2]=0;q=c[h>>2]|0;i=g;return q|0}else{Ke(c[f>>2]|0,c[c[p>>2]>>2]|0,c[(c[p>>2]|0)+4>>2]|0)|0;c[(c[o>>2]|0)+56>>2]=c[m>>2];c[(c[o>>2]|0)+68>>2]=c[l>>2];c[(c[o>>2]|0)+60>>2]=c[n>>2];c[(c[o>>2]|0)+64>>2]=c[j>>2];c[h>>2]=c[o>>2];q=c[h>>2]|0;i=g;return q|0}return 0}function Ib(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;ze(c[c[d>>2]>>2]|0);ze(c[d>>2]|0);i=b;return}function Jb(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b+4|0;e=b;c[d>>2]=a;c[e>>2]=c[d>>2];Ib(c[e>>2]|0);i=b;return 1}function Kb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0;b=i;i=i+16|0;d=b+12|0;e=b+8|0;f=b+4|0;g=b;c[e>>2]=a;c[f>>2]=c[e>>2];e=(c[f>>2]|0)+32|0;do if(((c[e>>2]|0)==-1?(c[e+4>>2]|0)==-1:0)?(a=(c[(c[f>>2]|0)+56>>2]|0)+488|0,(c[a>>2]|0)!=-1?1:(c[a+4>>2]|0)!=-1):0){c[g>>2]=Xb(c[(c[f>>2]|0)+64>>2]|0,c[(c[f>>2]|0)+68>>2]|0)|0;if(!((c[g>>2]|0)<0|(c[g>>2]|0)>=15)){a=(c[(c[f>>2]|0)+56>>2]|0)+488|0;h=Ub(c[g>>2]|0,c[a>>2]|0,c[a+4>>2]|0,c[(c[f>>2]|0)+56>>2]|0,c[f>>2]|0,c[(c[(c[f>>2]|0)+56>>2]|0)+508>>2]|0)|0;a=(c[f>>2]|0)+32|0;c[a>>2]=h;c[a+4>>2]=C;a=(c[f>>2]|0)+32|0;h=c[a+4>>2]|0;j=(c[(c[f>>2]|0)+56>>2]|0)+488|0;c[j>>2]=c[a>>2];c[j+4>>2]=h;c[(c[(c[f>>2]|0)+56>>2]|0)+508>>2]=c[f>>2];break}c[d>>2]=0;k=c[d>>2]|0;i=b;return k|0}while(0);c[d>>2]=1;k=c[d>>2]|0;i=b;return k|0}function Lb(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;b=i;i=i+32|0;d=b+28|0;e=b+24|0;f=b+20|0;g=b+8|0;h=b;j=b+16|0;c[e>>2]=a;c[f>>2]=c[e>>2];e=(c[f>>2]|0)+32|0;if((c[e>>2]|0)==-1?(c[e+4>>2]|0)==-1:0){c[d>>2]=0;k=c[d>>2]|0;i=b;return k|0}e=(c[(c[f>>2]|0)+60>>2]|0)+424|0;a=c[e+4>>2]|0;l=g;c[l>>2]=c[e>>2];c[l+4>>2]=a;a=(c[(c[f>>2]|0)+60>>2]|0)+416|0;l=c[a+4>>2]|0;e=h;c[e>>2]=c[a>>2];c[e+4>>2]=l;l=(c[f>>2]|0)+32|0;e=c[l+4>>2]|0;a=(c[(c[f>>2]|0)+60>>2]|0)+424|0;c[a>>2]=c[l>>2];c[a+4>>2]=e;e=(c[f>>2]|0)+32|0;a=wb(c[(c[f>>2]|0)+64>>2]|0,c[(c[f>>2]|0)+68>>2]|0,c[e>>2]|0,c[e+4>>2]|0)|0;e=(c[(c[f>>2]|0)+60>>2]|0)+416|0;c[e>>2]=a;c[e+4>>2]=C;e=c[f>>2]|0;if(c[(c[(c[f>>2]|0)+56>>2]|0)+468>>2]|0){a=Oa[c[(c[e+56>>2]|0)+468>>2]&15](c[(c[f>>2]|0)+64>>2]|0,c[f>>2]|0,c[(c[f>>2]|0)+68>>2]|0,c[(c[(c[f>>2]|0)+56>>2]|0)+472>>2]|0)|0;c[j>>2]=a;if((a|0)<0?(c[(c[(c[f>>2]|0)+64>>2]|0)+76>>2]=c[j>>2],(c[j>>2]|0)==-1):0){c[d>>2]=-1;k=c[d>>2]|0;i=b;return k|0}}else if(((c[(c[e+60>>2]|0)+396>>2]|0)!=0?(e=Oa[c[(c[(c[f>>2]|0)+60>>2]|0)+396>>2]&15](c[(c[f>>2]|0)+64>>2]|0,c[f>>2]|0,c[(c[f>>2]|0)+68>>2]|0,c[(c[(c[f>>2]|0)+60>>2]|0)+400>>2]|0)|0,c[j>>2]=e,(e|0)<0):0)?(c[(c[(c[f>>2]|0)+64>>2]|0)+76>>2]=c[j>>2],(c[j>>2]|0)==-1):0){c[d>>2]=-1;k=c[d>>2]|0;i=b;return k|0}j=g;g=c[j+4>>2]|0;e=(c[(c[f>>2]|0)+60>>2]|0)+424|0;c[e>>2]=c[j>>2];c[e+4>>2]=g;g=h;h=c[g+4>>2]|0;e=(c[(c[f>>2]|0)+60>>2]|0)+416|0;c[e>>2]=c[g>>2];c[e+4>>2]=h;Ib(c[f>>2]|0);c[d>>2]=1;k=c[d>>2]|0;i=b;return k|0}function Mb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;e=i;i=i+48|0;f=e;g=e+16|0;h=e+28|0;j=e+4|0;k=e+32|0;l=e+36|0;m=e+12|0;n=e+24|0;o=e+20|0;p=e+8|0;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[n>>2]=c[j>>2];c[o>>2]=0;c[p>>2]=0;if(!(c[g>>2]|0)){c[f>>2]=-2;q=c[f>>2]|0;i=e;return q|0}if(c[c[g>>2]>>2]&1){c[f>>2]=-3;q=c[f>>2]|0;i=e;return q|0}j=c[(c[g>>2]|0)+76>>2]|0;c[p>>2]=j;d=c[g>>2]|0;if(j){c[d+76>>2]=0;c[f>>2]=xb(c[p>>2]|0)|0;q=c[f>>2]|0;i=e;return q|0}c[k>>2]=d+112;c[p>>2]=Dc(c[g>>2]|0)|0;if((c[p>>2]|0)==-18){c[f>>2]=c[p>>2];q=c[f>>2]|0;i=e;return q|0}while(1){if(!((c[p>>2]|0)!=-1&(c[p>>2]|0)!=1&(c[n>>2]|0)>0))break;c[m>>2]=(c[n>>2]|0)<4096?c[n>>2]|0:4096;c[l>>2]=gb(c[k>>2]|0,c[m>>2]|0)|0;Ke(c[l>>2]|0,c[h>>2]|0,c[m>>2]|0)|0;hb(c[k>>2]|0,c[m>>2]|0)|0;c[h>>2]=(c[h>>2]|0)+(c[m>>2]|0);c[n>>2]=(c[n>>2]|0)-(c[m>>2]|0);c[o>>2]=(c[o>>2]|0)+(c[m>>2]|0);c[p>>2]=Dc(c[g>>2]|0)|0;if((c[p>>2]|0)==-18){r=11;break}}if((r|0)==11){c[f>>2]=c[p>>2];q=c[f>>2]|0;i=e;return q|0}if((c[p>>2]|0)==-1)Ob(c[g>>2]|0)|0;r=(c[p>>2]|0)==-404;if(c[o>>2]|0){if(r)c[p>>2]=0;c[(c[g>>2]|0)+76>>2]=c[p>>2];c[f>>2]=c[o>>2];q=c[f>>2]|0;i=e;return q|0}if(r){c[f>>2]=-14;q=c[f>>2]|0;i=e;return q|0}else{c[f>>2]=xb(c[p>>2]|0)|0;q=c[f>>2]|0;i=e;return q|0}return 0}function Nb(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;a=(c[d>>2]|0)+488|0;c[a>>2]=-1;c[a+4>>2]=-1;i=b;return 0}function Ob(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b+4|0;e=b;c[e>>2]=a;do if(!(c[e>>2]|0))c[d>>2]=-2;else{if(c[c[e>>2]>>2]&1){c[d>>2]=-3;break}Ec(c[e>>2]|0);if((c[(c[e>>2]|0)+4>>2]|0)!=0?(Fc(c[e>>2]|0,c[(c[e>>2]|0)+64>>2]|0,-1,-1,0)|0)<0:0){c[d>>2]=-10;break}c[d>>2]=0}while(0);i=b;return c[d>>2]|0}function Pb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;e=i;i=i+32|0;f=e+24|0;g=e+20|0;h=e+16|0;j=e+12|0;k=e+8|0;l=e;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;d=l;c[d>>2]=-1;c[d+4>>2]=-1;if(!(c[g>>2]|0)){c[f>>2]=-1;m=c[f>>2]|0;i=e;return m|0}if(c[c[g>>2]>>2]&1){c[f>>2]=-1;m=c[f>>2]|0;i=e;return m|0}if((c[h>>2]|0)==0&(c[j>>2]|0)==0){d=l;c[d>>2]=0;c[d+4>>2]=0}c[k>>2]=(c[g>>2]|0)+112;if(!((c[h>>2]|0)==0&(c[j>>2]|0)==1)){d=(c[k>>2]|0)+416|0;c[d>>2]=-1;c[d+4>>2]=-1}d=l;c[f>>2]=Fc(c[g>>2]|0,c[h>>2]|0,c[d>>2]|0,c[d+4>>2]|0,c[j>>2]|0)|0;m=c[f>>2]|0;i=e;return m|0}function Qb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;e=i;i=i+16|0;f=e+8|0;g=e+4|0;h=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;d=Hc(c[f>>2]|0,c[h>>2]|0,c[(c[g>>2]|0)+8>>2]|0,c[(c[g>>2]|0)+12>>2]|0)|0;i=e;return d|0}function Rb(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;f=i;i=i+32|0;g=f+20|0;h=f+16|0;j=f+12|0;k=f+8|0;l=f+4|0;m=f;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;c[m>>2]=0;c[m>>2]=Xb(c[h>>2]|0,c[k>>2]|0)|0;if((c[m>>2]|0)<0|(c[m>>2]|0)>=15){c[g>>2]=0;n=c[g>>2]|0;i=f;return n|0}if((c[m>>2]|0)==6?($a(c[j>>2]|0)|0)==0:0){c[g>>2]=Ic(c[h>>2]|0,c[k>>2]|0,c[(c[j>>2]|0)+8>>2]|0,c[(c[j>>2]|0)+12>>2]|0,c[l>>2]|0)|0;n=c[g>>2]|0;i=f;return n|0}c[g>>2]=Qa[c[1040+((c[m>>2]|0)*24|0)+12>>2]&31](c[h>>2]|0,c[k>>2]|0,c[(c[j>>2]|0)+8>>2]|0,c[(c[j>>2]|0)+12>>2]|0,c[l>>2]|0)|0;n=c[g>>2]|0;i=f;return n|0}function Sb(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;f=i;i=i+32|0;g=f+20|0;h=f+16|0;j=f+12|0;k=f+8|0;l=f+4|0;m=f;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;c[m>>2]=0;c[m>>2]=Xb(c[h>>2]|0,c[k>>2]|0)|0;if((c[m>>2]|0)<0|(c[m>>2]|0)>=15){c[g>>2]=0;n=c[g>>2]|0;i=f;return n|0}if((c[m>>2]|0)==6?(c[(c[j>>2]|0)+8>>2]|0)==0:0){c[g>>2]=Ic(c[h>>2]|0,c[k>>2]|0,c[c[j>>2]>>2]|0,c[(c[j>>2]|0)+4>>2]|0,c[l>>2]|0)|0;n=c[g>>2]|0;i=f;return n|0}c[g>>2]=Qa[c[1040+((c[m>>2]|0)*24|0)+12>>2]&31](c[h>>2]|0,c[k>>2]|0,c[c[j>>2]>>2]|0,c[(c[j>>2]|0)+4>>2]|0,c[l>>2]|0)|0;n=c[g>>2]|0;i=f;return n|0}function Tb(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;g=i;i=i+48|0;h=g+16|0;j=g+32|0;k=g+8|0;l=g+28|0;m=g+24|0;n=g;c[j>>2]=a;a=k;c[a>>2]=b;c[a+4>>2]=d;c[l>>2]=e;c[m>>2]=f;if(c[1040+((c[j>>2]|0)*24|0)+16>>2]|0){f=k;e=Oa[c[1040+((c[j>>2]|0)*24|0)+16>>2]&15](c[f>>2]|0,c[f+4>>2]|0,c[l>>2]|0,c[m>>2]|0)|0;m=n;c[m>>2]=e;c[m+4>>2]=C;m=n;n=c[m+4>>2]|0;e=h;c[e>>2]=c[m>>2];c[e+4>>2]=n;o=h;p=o;q=c[p>>2]|0;r=o+4|0;s=r;t=c[s>>2]|0;C=t;i=g;return q|0}else{n=k;k=c[n+4>>2]|0;e=h;c[e>>2]=c[n>>2];c[e+4>>2]=k;o=h;p=o;q=c[p>>2]|0;r=o+4|0;s=r;t=c[s>>2]|0;C=t;i=g;return q|0}return 0}function Ub(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;h=i;i=i+32|0;j=h+8|0;k=h+28|0;l=h;m=h+24|0;n=h+20|0;o=h+16|0;c[k>>2]=a;a=l;c[a>>2]=b;c[a+4>>2]=d;c[m>>2]=e;c[n>>2]=f;c[o>>2]=g;if(c[1040+((c[k>>2]|0)*24|0)+20>>2]|0){g=l;l=Qa[c[1040+((c[k>>2]|0)*24|0)+20>>2]&31](c[g>>2]|0,c[g+4>>2]|0,c[m>>2]|0,c[n>>2]|0,c[o>>2]|0)|0;o=j;c[o>>2]=l;c[o+4>>2]=C;p=j;q=p;r=c[q>>2]|0;s=p+4|0;t=s;u=c[t>>2]|0;C=u;i=h;return r|0}else{o=j;c[o>>2]=0;c[o+4>>2]=0;p=j;q=p;r=c[q>>2]|0;s=p+4|0;t=s;u=c[t>>2]|0;C=u;i=h;return r|0}return 0}function Vb(a,b,e,f){a=a|0;b=b|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0;g=i;i=i+32|0;h=g+20|0;j=g+16|0;k=g+12|0;l=g+8|0;m=g+4|0;n=g;c[h>>2]=a;c[j>>2]=b;c[k>>2]=e;c[l>>2]=f;c[m>>2]=-1;c[n>>2]=-1;switch(c[(c[j>>2]|0)+360>>2]|0){case 3:case 2:{c[m>>2]=0;break}case 14:{if((c[(c[l>>2]|0)+4>>2]|0)>7?(ve(c[c[l>>2]>>2]|0,1472,7)|0)==0:0)c[m>>2]=7;break}case 8:{if((c[(c[l>>2]|0)+4>>2]|0)>4?((d[c[c[l>>2]>>2]>>0]|0)&7|0)==4:0){c[n>>2]=((d[(c[c[l>>2]>>2]|0)+1>>0]|0)<<16)+((d[(c[c[l>>2]>>2]|0)+2>>0]|0)<<8)+(d[(c[c[l>>2]>>2]|0)+3>>0]|0);c[m>>2]=4}break}case 11:{if((c[(c[l>>2]|0)+4>>2]|0)>9?(ve(c[c[l>>2]>>2]|0,1440,8)|0)==0:0)c[m>>2]=9;break}case 0:{if((c[(c[l>>2]|0)+4>>2]|0)>7?(ve(c[c[l>>2]>>2]|0,1432,7)|0)==0:0)c[m>>2]=7;break}case 13:{if((c[(c[l>>2]|0)+4>>2]|0)>8?(ve(c[c[l>>2]>>2]|0,1456,8)|0)==0:0)c[m>>2]=8;break}case 1:{if((c[(c[l>>2]|0)+4>>2]|0)>7?(ve(c[c[l>>2]>>2]|0,1424,7)|0)==0:0)c[m>>2]=7;break}default:{}}if((c[n>>2]|0)==-1)c[n>>2]=(c[(c[l>>2]|0)+4>>2]|0)-(c[m>>2]|0);if((c[m>>2]|0)<0){i=g;return 0}Ab(c[h>>2]|0,c[k>>2]|0,(c[c[l>>2]>>2]|0)+(c[m>>2]|0)|0,c[n>>2]|0)|0;i=g;return 0}function Wb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e+4|0;k=e;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[k>>2]=sb(c[g>>2]|0,c[h>>2]|0)|0;if(!(c[k>>2]|0)){c[f>>2]=-20;l=c[f>>2]|0;i=e;return l|0}else{c[(c[k>>2]|0)+360>>2]=c[j>>2];c[f>>2]=0;l=c[f>>2]|0;i=e;return l|0}return 0}function Xb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[f>>2]=a;c[g>>2]=b;do if(c[f>>2]|0){c[h>>2]=sb(c[f>>2]|0,c[g>>2]|0)|0;if(!(c[h>>2]|0)){c[e>>2]=-20;break}else{c[e>>2]=c[(c[h>>2]|0)+360>>2];break}}else c[e>>2]=-2;while(0);i=d;return c[e>>2]|0}function Yb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[f>>2]=a;c[g>>2]=b;do if(c[f>>2]|0){c[h>>2]=sb(c[f>>2]|0,c[g>>2]|0)|0;if(!(c[h>>2]|0)){c[e>>2]=-20;break}else{c[e>>2]=c[(c[h>>2]|0)+364>>2];break}}else c[e>>2]=-2;while(0);i=d;return c[e>>2]|0}function Zb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e+4|0;k=e;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;if(!(c[g>>2]|0)){c[f>>2]=-2;l=c[f>>2]|0;i=e;return l|0}c[k>>2]=sb(c[g>>2]|0,c[h>>2]|0)|0;if(!(c[k>>2]|0)){c[f>>2]=-20;l=c[f>>2]|0;i=e;return l|0}else{c[(c[k>>2]|0)+368>>2]=c[j>>2];c[f>>2]=0;l=c[f>>2]|0;i=e;return l|0}return 0}function _b(){var a=0,b=0,d=0,e=0;a=i;i=i+16|0;b=a+4|0;d=a;c[d>>2]=ye(20)|0;if(!(c[d>>2]|0)){c[b>>2]=0;e=c[b>>2]|0;i=a;return e|0}else{c[c[d>>2]>>2]=0;c[(c[d>>2]|0)+4>>2]=0;c[(c[d>>2]|0)+8>>2]=0;c[(c[d>>2]|0)+12>>2]=0;c[(c[d>>2]|0)+16>>2]=0;c[b>>2]=c[d>>2];e=c[b>>2]|0;i=a;return e|0}return 0}function $b(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;Jc(c[d>>2]|0);ze(c[d>>2]|0);i=b;return}function ac(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b+4|0;e=b;c[e>>2]=a;if(!(c[e>>2]|0))c[d>>2]=0;else c[d>>2]=c[(c[e>>2]|0)+4>>2];i=b;return c[d>>2]|0}function bc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;i=i+16|0;e=d+8|0;f=d+4|0;g=d;c[f>>2]=a;c[g>>2]=b;do if(c[f>>2]|0)if((c[g>>2]|0)>=(c[(c[f>>2]|0)+4>>2]|0)){c[e>>2]=0;break}else{c[e>>2]=c[(c[(c[f>>2]|0)+8>>2]|0)+(c[g>>2]<<2)>>2];break}else c[e>>2]=0;while(0);i=d;return c[e>>2]|0}function cc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;i=i+32|0;f=e+20|0;g=e+16|0;h=e+12|0;j=e+8|0;k=e+4|0;l=e;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[l>>2]=0;while(1){if((c[l>>2]|0)>=(c[(c[g>>2]|0)+4>>2]|0)){m=6;break}c[k>>2]=c[(c[(c[g>>2]|0)+8>>2]|0)+(c[l>>2]<<2)>>2];if(Pa[c[h>>2]&1](c[k>>2]|0,c[j>>2]|0)|0){m=4;break}c[l>>2]=(c[l>>2]|0)+1}if((m|0)==4){c[f>>2]=c[k>>2];n=c[f>>2]|0;i=e;return n|0}else if((m|0)==6){c[f>>2]=0;n=c[f>>2]|0;i=e;return n|0}return 0}function dc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;i=i+16|0;e=d+8|0;f=d+4|0;g=d;c[e>>2]=a;c[f>>2]=b;c[g>>2]=0;while(1){if((c[g>>2]|0)>=(c[(c[e>>2]|0)+4>>2]|0))break;Na[c[f>>2]&7](c[(c[(c[e>>2]|0)+8>>2]|0)+(c[g>>2]<<2)>>2]|0)|0;c[g>>2]=(c[g>>2]|0)+1}i=d;return 0}function ec(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;i=i+16|0;e=d+8|0;f=d+4|0;g=d;c[f>>2]=a;c[g>>2]=b;if(!(Kc(c[f>>2]|0)|0)){c[e>>2]=0;h=c[e>>2]|0;i=d;return h|0}else{c[(c[(c[f>>2]|0)+8>>2]|0)+((c[(c[f>>2]|0)+4>>2]|0)-1<<2)>>2]=c[g>>2];Lc(c[f>>2]|0);c[e>>2]=c[g>>2];h=c[e>>2]|0;i=d;return h|0}return 0}function fc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;e=i;i=i+16|0;f=e+8|0;g=e+4|0;h=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;c[(c[f>>2]|0)+12>>2]=c[g>>2];c[(c[f>>2]|0)+16>>2]=c[h>>2];if(!(c[g>>2]|0)){i=e;return 0}Mc(c[f>>2]|0,0,(c[(c[f>>2]|0)+4>>2]|0)-1|0);i=e;return 0}function gc(){var a=0,b=0,d=0,e=0,f=0,g=0;a=i;i=i+16|0;b=a+12|0;d=a+8|0;e=a+4|0;f=a;c[d>>2]=ye(8)|0;if(!(c[d>>2]|0)){c[b>>2]=0;g=c[b>>2]|0;i=a;return g|0}c[e>>2]=ye(12)|0;if(!(c[e>>2]|0)){ze(c[d>>2]|0);c[b>>2]=0;g=c[b>>2]|0;i=a;return g|0}c[f>>2]=ye(12)|0;if(!(c[f>>2]|0)){ze(c[e>>2]|0);ze(c[d>>2]|0);c[b>>2]=0;g=c[b>>2]|0;i=a;return g|0}else{c[c[e>>2]>>2]=c[f>>2];c[(c[e>>2]|0)+4>>2]=0;c[(c[f>>2]|0)+4>>2]=c[e>>2];c[c[f>>2]>>2]=0;c[c[d>>2]>>2]=c[e>>2];c[(c[d>>2]|0)+4>>2]=c[f>>2];c[b>>2]=c[d>>2];g=c[b>>2]|0;i=a;return g|0}return 0}function hc(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b+4|0;e=b;c[d>>2]=a;c[e>>2]=c[c[c[d>>2]>>2]>>2];while(1){if(!(c[e>>2]|0))break;ze(c[(c[e>>2]|0)+4>>2]|0);c[e>>2]=c[c[e>>2]>>2]}ze(c[(c[d>>2]|0)+4>>2]|0);ze(c[d>>2]|0);i=b;return}function ic(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;i=b;return (c[c[c[d>>2]>>2]>>2]|0)==(c[(c[d>>2]|0)+4>>2]|0)|0}function jc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[f>>2]=a;c[g>>2]=b;if(!(c[f>>2]|0)){c[e>>2]=-1;j=c[e>>2]|0;i=d;return j|0}c[h>>2]=ye(12)|0;if(!(c[h>>2]|0)){c[e>>2]=-1;j=c[e>>2]|0;i=d;return j|0}else{c[(c[h>>2]|0)+8>>2]=c[g>>2];c[c[h>>2]>>2]=c[(c[f>>2]|0)+4>>2];c[(c[h>>2]|0)+4>>2]=c[(c[(c[f>>2]|0)+4>>2]|0)+4>>2];c[c[(c[h>>2]|0)+4>>2]>>2]=c[h>>2];c[(c[c[h>>2]>>2]|0)+4>>2]=c[h>>2];c[e>>2]=0;j=c[e>>2]|0;i=d;return j|0}return 0}function kc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;i=i+16|0;e=d+8|0;f=d+4|0;g=d;c[e>>2]=a;c[f>>2]=b;c[g>>2]=c[(c[(c[e>>2]|0)+4>>2]|0)+4>>2];while(1){if((c[g>>2]|0)==(c[c[e>>2]>>2]|0)){h=5;break}if(!(Na[c[f>>2]&7](c[(c[g>>2]|0)+8>>2]|0)|0)){h=5;break}c[g>>2]=c[(c[g>>2]|0)+4>>2]}if((h|0)==5){i=d;return}}function lc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;i=i+32|0;e=d+20|0;f=d+16|0;g=d+12|0;h=d+8|0;j=d+4|0;k=d;c[e>>2]=a;c[f>>2]=b;c[j>>2]=0;c[g>>2]=c[c[c[e>>2]>>2]>>2];while(1){if((c[g>>2]|0)==(c[(c[e>>2]|0)+4>>2]|0)){l=7;break}c[k>>2]=Na[c[f>>2]&7](c[(c[g>>2]|0)+8>>2]|0)|0;if((c[k>>2]|0)==-1)c[j>>2]=-1;if(!(c[k>>2]|0)){l=7;break}c[h>>2]=c[c[g>>2]>>2];c[c[(c[g>>2]|0)+4>>2]>>2]=c[c[g>>2]>>2];c[(c[c[g>>2]>>2]|0)+4>>2]=c[(c[g>>2]|0)+4>>2];ze(c[g>>2]|0);c[g>>2]=c[h>>2]}if((l|0)==7){i=d;return c[j>>2]|0}return 0}function mc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e+4|0;k=e;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;if(!(c[g>>2]|0)){c[f>>2]=-2;l=c[f>>2]|0;i=e;return l|0}c[k>>2]=sb(c[g>>2]|0,c[h>>2]|0)|0;if(!(c[k>>2]|0)){c[f>>2]=-20;l=c[f>>2]|0;i=e;return l|0}else{c[(c[k>>2]|0)+408>>2]=c[j>>2];c[f>>2]=Nc(c[g>>2]|0,c[h>>2]|0)|0;l=c[f>>2]|0;i=e;return l|0}return 0}function nc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[f>>2]=a;c[g>>2]=b;do if(c[f>>2]|0){c[h>>2]=sb(c[f>>2]|0,c[g>>2]|0)|0;if(!(c[h>>2]|0)){c[e>>2]=-20;break}else{c[e>>2]=c[(c[h>>2]|0)+408>>2];break}}else c[e>>2]=-2;while(0);i=d;return c[e>>2]|0}function oc(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;h=i;i=i+32|0;j=h+28|0;k=h+24|0;l=h+20|0;m=h+8|0;n=h;o=h+16|0;c[k>>2]=a;c[l>>2]=b;b=m;c[b>>2]=d;c[b+4>>2]=e;e=n;c[e>>2]=f;c[e+4>>2]=g;if(!(c[k>>2]|0)){c[j>>2]=-2;p=c[j>>2]|0;i=h;return p|0}c[o>>2]=sb(c[k>>2]|0,c[l>>2]|0)|0;if(!(c[o>>2]|0)){c[j>>2]=-20;p=c[j>>2]|0;i=h;return p|0}else{g=m;m=c[g+4>>2]|0;e=(c[o>>2]|0)+376|0;c[e>>2]=c[g>>2];c[e+4>>2]=m;m=n;n=c[m+4>>2]|0;e=(c[o>>2]|0)+384|0;c[e>>2]=c[m>>2];c[e+4>>2]=n;c[j>>2]=Nc(c[k>>2]|0,c[l>>2]|0)|0;p=c[j>>2]|0;i=h;return p|0}return 0}function pc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;f=i;i=i+32|0;g=f+20|0;h=f+16|0;j=f+12|0;k=f+8|0;l=f+4|0;m=f;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;if(!(c[h>>2]|0)){c[g>>2]=-2;n=c[g>>2]|0;i=f;return n|0}c[m>>2]=sb(c[h>>2]|0,c[j>>2]|0)|0;if(!(c[m>>2]|0)){c[g>>2]=-20;n=c[g>>2]|0;i=f;return n|0}else{j=(c[m>>2]|0)+376|0;h=c[j+4>>2]|0;e=c[k>>2]|0;c[e>>2]=c[j>>2];c[e+4>>2]=h;h=(c[m>>2]|0)+384|0;m=Ve(c[h>>2]|0,c[h+4>>2]|0,1e3,0)|0;h=c[l>>2]|0;c[h>>2]=m;c[h+4>>2]=C;c[g>>2]=0;n=c[g>>2]|0;i=f;return n|0}return 0}function qc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+32|0;g=f+20|0;h=f+16|0;j=f+12|0;k=f;l=f+8|0;c[h>>2]=a;c[j>>2]=b;b=k;c[b>>2]=d;c[b+4>>2]=e;if(!(c[h>>2]|0)){c[g>>2]=-2;m=c[g>>2]|0;i=f;return m|0}c[l>>2]=sb(c[h>>2]|0,c[j>>2]|0)|0;if(!(c[l>>2]|0)){c[g>>2]=-20;m=c[g>>2]|0;i=f;return m|0}else{e=k;k=c[e+4>>2]|0;b=(c[l>>2]|0)+392|0;c[b>>2]=c[e>>2];c[b+4>>2]=k;c[g>>2]=Nc(c[h>>2]|0,c[j>>2]|0)|0;m=c[g>>2]|0;i=f;return m|0}return 0}function rc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;i=i+48|0;f=e+4|0;g=e+16|0;h=e+8|0;j=e+20|0;k=e+32|0;l=e;m=e+12|0;n=e+24|0;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;Oc(k,c[h>>2]|0,c[j>>2]|0);Pc(k,104);j=Qc(k)|0;c[c[g>>2]>>2]=j;j=Qc(k)|0;c[(c[g>>2]|0)+4>>2]=j;j=Qc(k)|0;c[(c[g>>2]|0)+8>>2]=j;j=Qc(k)|0;c[(c[g>>2]|0)+12>>2]=j;j=Qc(k)|0;c[l>>2]=j;c[(c[g>>2]|0)+20>>2]=j;if((c[l>>2]|0)>>>0>=17){c[f>>2]=-1;o=c[f>>2]|0;i=e;return o|0}c[(c[g>>2]|0)+24>>2]=c[1480+(c[l>>2]<<3)>>2];c[(c[g>>2]|0)+28>>2]=c[1480+(c[l>>2]<<3)+4>>2];if(Rc(k)|0){j=Qc(k)|0;c[(c[g>>2]|0)+24>>2]=j;j=Qc(k)|0;c[(c[g>>2]|0)+28>>2]=j}if(Rc(k)|0){j=Qc(k)|0;c[(c[g>>2]|0)+16>>2]=j}do if(Rc(k)|0){c[m>>2]=Qc(k)|0;if((c[m>>2]|0)<2){c[(c[g>>2]|0)+40>>2]=c[m>>2];break}else{c[(c[g>>2]|0)+40>>2]=0;break}}else c[(c[g>>2]|0)+40>>2]=c[1616+(c[l>>2]<<2)>>2];while(0);c[(c[g>>2]|0)+44>>2]=c[1704+(c[l>>2]<<2)>>2];c[(c[g>>2]|0)+32>>2]=c[1880+(c[1792+(c[l>>2]<<2)>>2]<<3)>>2];c[(c[g>>2]|0)+36>>2]=c[1880+(c[1792+(c[l>>2]<<2)>>2]<<3)+4>>2];if((Rc(k)|0)!=0?(c[n>>2]=Qc(k)|0,c[(c[g>>2]|0)+32>>2]=c[1880+(c[n>>2]<<3)>>2],c[(c[g>>2]|0)+36>>2]=c[1880+(c[n>>2]<<3)+4>>2],(c[n>>2]|0)==0):0){n=Qc(k)|0;c[(c[g>>2]|0)+32>>2]=n;n=Qc(k)|0;c[(c[g>>2]|0)+36>>2]=n}c[f>>2]=0;o=c[f>>2]|0;i=e;return o|0}function sc(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b+4|0;e=b;c[e>>2]=a;if(c[e>>2]&1)c[d>>2]=-11;else c[d>>2]=0;i=b;return c[d>>2]|0}function tc(a){a=a|0;var b=0,d=0,e=0,f=0;b=i;i=i+16|0;d=b+4|0;e=b;c[d>>2]=a;c[e>>2]=c[d>>2];zb(c[e>>2]|0)|0;if((c[(c[e>>2]|0)+336>>2]|0)!=-1)db(c[e>>2]|0)|0;if(c[(c[e>>2]|0)+456>>2]|0)ze(c[(c[e>>2]|0)+452>>2]|0);if(!(c[(c[e>>2]|0)+504>>2]|0)){f=c[e>>2]|0;ze(f);i=b;return 0}ze(c[(c[e>>2]|0)+504>>2]|0);f=c[e>>2]|0;ze(f);i=b;return 0}function uc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;i=i+16|0;e=d+8|0;f=d+4|0;g=d;c[e>>2]=a;c[f>>2]=b;c[g>>2]=c[e>>2];i=d;return (c[(c[g>>2]|0)+336>>2]|0)==(c[f>>2]|0)|0}function vc(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;i=i+16|0;e=d+8|0;f=d+4|0;g=d;c[f>>2]=b;if(!(c[f>>2]|0)){c[e>>2]=0;h=c[e>>2]|0;i=d;return h|0}c[g>>2]=c[f>>2];while(1){if(!(a[c[g>>2]>>0]|0)){j=10;break}if((a[c[g>>2]>>0]|0)<32){j=8;break}if((a[c[g>>2]>>0]|0)>125){j=8;break}if((a[c[g>>2]>>0]|0)==61){j=8;break}c[g>>2]=(c[g>>2]|0)+1}if((j|0)==8){c[e>>2]=0;h=c[e>>2]|0;i=d;return h|0}else if((j|0)==10){c[e>>2]=1;h=c[e>>2]|0;i=d;return h|0}return 0}function wc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;e=i;i=i+16|0;f=e+12|0;g=e+8|0;h=e+4|0;c[g>>2]=a;c[h>>2]=b;c[e>>2]=d;do if((c[g>>2]|0)!=(c[h>>2]|0)){if(!((c[g>>2]|0)!=0&(c[h>>2]|0)!=0)){c[f>>2]=0;break}if(we(c[c[g>>2]>>2]|0,c[c[h>>2]>>2]|0)|0){c[f>>2]=0;break}if(xe(c[(c[g>>2]|0)+4>>2]|0,c[(c[h>>2]|0)+4>>2]|0)|0){c[f>>2]=0;break}else{c[f>>2]=1;break}}else c[f>>2]=1;while(0);i=e;return c[f>>2]|0}function xc(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;if(!(c[d>>2]|0)){i=b;return}if(c[c[d>>2]>>2]|0)ze(c[c[d>>2]>>2]|0);if(c[(c[d>>2]|0)+4>>2]|0)ze(c[(c[d>>2]|0)+4>>2]|0);ze(c[d>>2]|0);i=b;return}function yc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0;e=i;i=i+16|0;f=e+12|0;g=e+8|0;h=e+4|0;j=e;c[g>>2]=b;c[h>>2]=d;do if(c[g>>2]|0){if(!(c[h>>2]|0)){c[f>>2]=0;break}c[h>>2]=(c[h>>2]|0)>>>0<4294967294?c[h>>2]|0:-2;c[j>>2]=ye((c[h>>2]|0)+1|0)|0;if(!(c[j>>2]|0)){c[f>>2]=0;break}if(!(Le(c[j>>2]|0,c[g>>2]|0,c[h>>2]|0)|0)){ze(c[j>>2]|0);c[f>>2]=0;break}else{a[(c[j>>2]|0)+(c[h>>2]|0)>>0]=0;c[f>>2]=c[j>>2];break}}else c[f>>2]=0;while(0);i=e;return c[f>>2]|0}function zc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e+4|0;k=e;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;if(!(c[g>>2]|0)){c[f>>2]=-2;l=c[f>>2]|0;i=e;return l|0}c[k>>2]=sb(c[g>>2]|0,c[h>>2]|0)|0;if(!(c[k>>2]|0)){c[f>>2]=-20;l=c[f>>2]|0;i=e;return l|0}if(c[(c[k>>2]|0)+412>>2]|0)ze(c[(c[k>>2]|0)+412>>2]|0);h=Sc(c[j>>2]|0)|0;c[(c[k>>2]|0)+412>>2]=h;if(!h){c[f>>2]=-18;l=c[f>>2]|0;i=e;return l|0}else{c[f>>2]=0;l=c[f>>2]|0;i=e;return l|0}return 0}function Ac(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;f=i;i=i+32|0;g=f+12|0;h=f+8|0;j=f+16|0;k=f+4|0;l=f;c[h>>2]=b;a[j>>0]=d;c[k>>2]=e;c[l>>2]=0;while(1){if(!(a[c[h>>2]>>0]|0)){m=7;break}if((c[l>>2]|0)>=(c[k>>2]|0)){m=7;break}if((a[c[h>>2]>>0]|0)==(a[j>>0]|0)){m=5;break}c[l>>2]=(c[l>>2]|0)+1;c[h>>2]=(c[h>>2]|0)+1}if((m|0)==5){c[g>>2]=c[h>>2];n=c[g>>2]|0;i=f;return n|0}else if((m|0)==7){c[g>>2]=0;n=c[g>>2]|0;i=f;return n|0}return 0}function Bc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;e=i;i=i+32|0;f=e+8|0;g=e+16|0;h=e+20|0;j=e+24|0;k=e+4|0;l=e;m=e+12|0;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[m>>2]=0;a:while(1){d=c[m>>2]|0;if((d|0)>=(ac(c[(c[g>>2]|0)+416>>2]|0)|0)){n=14;break}c[k>>2]=bc(c[(c[g>>2]|0)+416>>2]|0,c[m>>2]|0)|0;do if((c[c[k>>2]>>2]|0)!=0?(we(c[h>>2]|0,c[c[k>>2]>>2]|0)|0)==0:0){d=c[j>>2]|0;if(!(c[(c[k>>2]|0)+4>>2]|0))if(!d){n=7;break a}else break;if((d|0)!=0?(xe(c[j>>2]|0,c[(c[k>>2]|0)+4>>2]|0)|0)==0:0){n=12;break a}if((c[j>>2]|0)==0?(c[(c[k>>2]|0)+4>>2]|0)==0:0){n=12;break a}}while(0);c[m>>2]=(c[m>>2]|0)+1}if((n|0)==7){c[f>>2]=c[k>>2];o=c[f>>2]|0;i=e;return o|0}else if((n|0)==12){c[f>>2]=c[k>>2];o=c[f>>2]|0;i=e;return o|0}else if((n|0)==14){n=Tc(c[h>>2]|0,c[j>>2]|0)|0;c[l>>2]=n;if(!n){c[f>>2]=0;o=c[f>>2]|0;i=e;return o|0}else{c[f>>2]=ec(c[(c[g>>2]|0)+416>>2]|0,c[l>>2]|0)|0;o=c[f>>2]|0;i=e;return o|0}}return 0}function Cc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;b=i;i=i+16|0;d=b+8|0;e=b+4|0;f=b;c[e>>2]=a;if(!(c[e>>2]|0)){c[d>>2]=0;g=c[d>>2]|0;i=b;return g|0}else{c[f>>2]=Je(c[e>>2]|0)|0;c[d>>2]=(c[f>>2]|0)>>>0<4294967294?c[f>>2]|0:-2;g=c[d>>2]|0;i=b;return g|0}return 0}function Dc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;b=i;i=i+160|0;d=b+120|0;e=b+124|0;f=b+112|0;g=b+88|0;h=b+108|0;j=b+116|0;k=b+100|0;l=b+96|0;m=b+16|0;n=b+136|0;o=b+128|0;p=b;q=b+84|0;r=b+104|0;s=b+92|0;t=b+8|0;u=b+80|0;v=b+72|0;c[e>>2]=a;c[f>>2]=(c[e>>2]|0)+112;c[o>>2]=0;c[j>>2]=m;c[k>>2]=m+32;a:while(1){if(c[o>>2]|0){w=75;break}b:do if((c[o>>2]|0)==0?(c[(c[f>>2]|0)+392>>2]|0)!=-1:0)do{c[l>>2]=c[(c[f>>2]|0)+392>>2];c[g>>2]=sb(c[e>>2]|0,c[l>>2]|0)|0;if((c[g>>2]|0)==0?(a=tb(c[e>>2]|0,c[l>>2]|0)|0,c[g>>2]=a,(a|0)==0):0){w=7;break a}c[h>>2]=c[g>>2];c[q>>2]=mb(c[h>>2]|0,c[j>>2]|0)|0;if((c[q>>2]|0)==-1){a=(c[g>>2]|0)+440|0;x=c[a+4>>2]|0;y=(c[(c[g>>2]|0)+364>>2]|0)-1|0;z=((y|0)<0)<<31>>31;if((x|0)<(z|0)|((x|0)==(z|0)?(c[a>>2]|0)>>>0<y>>>0:0)){w=10;break a}c[q>>2]=mb(c[h>>2]|0,c[j>>2]|0)|0;if((c[q>>2]|0)==-1){w=12;break a}c[(c[f>>2]|0)+440>>2]=1;c[(c[f>>2]|0)+436>>2]=c[(c[e>>2]|0)+64>>2];c[(c[f>>2]|0)+444>>2]=1}if((c[q>>2]|0)<=0)break b;y=(c[g>>2]|0)+440|0;a=y;z=Me(c[a>>2]|0,c[a+4>>2]|0,1,0)|0;a=y;c[a>>2]=z;c[a+4>>2]=C;a=(c[j>>2]|0)+16|0;z=c[a+4>>2]|0;y=p;c[y>>2]=c[a>>2];c[y+4>>2]=z;c[r>>2]=Xb(c[e>>2]|0,c[l>>2]|0)|0;do if(!((c[r>>2]|0)<0|(c[r>>2]|0)>=15)){if(((c[r>>2]|0)==6?1:(c[(c[g>>2]|0)+448>>2]|0)==0)?(c[c[e>>2]>>2]&32|0)!=0:0)Sb(c[e>>2]|0,c[j>>2]|0,c[l>>2]|0,0)|0;if(!(c[c[e>>2]>>2]&32)){z=p;y=c[z+4>>2]|0;a=(c[f>>2]|0)+424|0;c[a>>2]=c[z>>2];c[a+4>>2]=y;break}y=p;a=Tb(c[r>>2]|0,c[y>>2]|0,c[y+4>>2]|0,c[g>>2]|0,c[j>>2]|0)|0;y=(c[f>>2]|0)+424|0;c[y>>2]=a;c[y+4>>2]=C;y=p;if(((c[y>>2]|0)!=-1?1:(c[y+4>>2]|0)!=-1)?(y=(c[f>>2]|0)+424|0,a=c[y+4>>2]|0,z=p,x=c[z+4>>2]|0,(a|0)<(x|0)|((a|0)==(x|0)?(c[y>>2]|0)>>>0<(c[z>>2]|0)>>>0:0)):0){z=p;y=c[z+4>>2]|0;x=(c[f>>2]|0)+424|0;c[x>>2]=c[z>>2];c[x+4>>2]=y}}else{y=p;x=c[y+4>>2]|0;z=(c[f>>2]|0)+424|0;c[z>>2]=c[y>>2];c[z+4>>2]=x}while(0);x=(c[f>>2]|0)+424|0;z=c[x+4>>2]|0;y=(c[g>>2]|0)+488|0;c[y>>2]=c[x>>2];c[y+4>>2]=z;if(!((c[(c[e>>2]|0)+88>>2]|0)==0?(c[(c[g>>2]|0)+448>>2]|0)==0:0))w=27;if((w|0)==27?(w=0,z=(c[f>>2]|0)+424|0,(c[z>>2]|0)!=-1?1:(c[z+4>>2]|0)!=-1):0){z=(c[f>>2]|0)+424|0;y=wb(c[e>>2]|0,c[l>>2]|0,c[z>>2]|0,c[z+4>>2]|0)|0;z=(c[f>>2]|0)+416|0;c[z>>2]=y;c[z+4>>2]=C}z=(c[g>>2]|0)+440|0;if((c[z>>2]|0)==1&(c[z+4>>2]|0)==0)Vb(c[e>>2]|0,c[g>>2]|0,c[l>>2]|0,c[j>>2]|0)|0;z=(c[f>>2]|0)+424|0;y=c[z+4>>2]|0;x=c[k>>2]|0;c[x>>2]=c[z>>2];c[x+4>>2]=y;c[(c[k>>2]|0)+8>>2]=c[(c[f>>2]|0)+436>>2];c[(c[k>>2]|0)+12>>2]=c[(c[e>>2]|0)+64>>2];c[(c[k>>2]|0)+16>>2]=c[(c[f>>2]|0)+440>>2];c[(c[k>>2]|0)+20>>2]=c[(c[f>>2]|0)+444>>2];do if(c[c[e>>2]>>2]&32){y=(c[f>>2]|0)+424|0;x=c[e>>2]|0;if((c[y>>2]|0)==-1?(c[y+4>>2]|0)==-1:0){c[s>>2]=Hb(x,m,c[l>>2]|0,c[g>>2]|0,c[f>>2]|0)|0;jc(c[(c[e>>2]|0)+560>>2]|0,c[s>>2]|0)|0;w=45;break}if(!(ic(c[x+560>>2]|0)|0)){x=(c[g>>2]|0)+488|0;y=c[x+4>>2]|0;z=t;c[z>>2]=c[x>>2];c[z+4>>2]=y;c[(c[g>>2]|0)+508>>2]=c[j>>2];kc(c[(c[e>>2]|0)+560>>2]|0,3);c[(c[e>>2]|0)+76>>2]=0;if((lc(c[(c[e>>2]|0)+560>>2]|0,4)|0)==-1){w=36;break a}y=(c[e>>2]|0)+76|0;if((c[(c[e>>2]|0)+76>>2]|0)>0){c[o>>2]=c[y>>2];c[(c[e>>2]|0)+76>>2]=0;break}c[y>>2]=0;y=t;z=c[y+4>>2]|0;x=(c[g>>2]|0)+488|0;c[x>>2]=c[y>>2];c[x+4>>2]=z;if(!(ic(c[(c[e>>2]|0)+560>>2]|0)|0)){c[u>>2]=Hb(c[e>>2]|0,m,c[l>>2]|0,c[g>>2]|0,c[f>>2]|0)|0;jc(c[(c[e>>2]|0)+560>>2]|0,c[u>>2]|0)|0;w=45}else w=41}else w=41}else w=41;while(0);do if((w|0)==41){w=0;if(c[(c[g>>2]|0)+468>>2]|0){c[o>>2]=Oa[c[(c[g>>2]|0)+468>>2]&15](c[e>>2]|0,m,c[l>>2]|0,c[(c[g>>2]|0)+472>>2]|0)|0;w=45;break}if(c[(c[f>>2]|0)+396>>2]|0){c[o>>2]=Oa[c[(c[f>>2]|0)+396>>2]&15](c[e>>2]|0,m,c[l>>2]|0,c[(c[f>>2]|0)+400>>2]|0)|0;w=45}else w=45}while(0);if((w|0)==45){w=0;if((c[(c[f>>2]|0)+436>>2]|0)==(c[(c[e>>2]|0)+64>>2]|0)){z=(c[f>>2]|0)+444|0;c[z>>2]=(c[z>>2]|0)+1}else{c[(c[f>>2]|0)+436>>2]=c[(c[e>>2]|0)+64>>2];c[(c[f>>2]|0)+444>>2]=1}c[(c[f>>2]|0)+440>>2]=1;if(!(c[(c[j>>2]|0)+8>>2]|0))c[(c[g>>2]|0)+420>>2]=1}}while((c[o>>2]|0)==0);while(0);if((c[o>>2]|0)==1|(c[o>>2]|0)==-1|(c[o>>2]|0)==-17){w=51;break}if((Uc(c[e>>2]|0,n)|0)<0){w=53;break}c[l>>2]=bb(n)|0;c[(c[f>>2]|0)+392>>2]=c[l>>2];c[g>>2]=sb(c[e>>2]|0,c[l>>2]|0)|0;z=c[e>>2]|0;x=c[l>>2]|0;if(!(c[g>>2]|0)){y=tb(z,x)|0;c[g>>2]=y;if(!y){w=56;break}Qb(c[e>>2]|0,n,c[l>>2]|0)|0;if(c[c[e>>2]>>2]&32)Rb(c[e>>2]|0,n,c[l>>2]|0,0)|0}else if((Xb(z,x)|0)==9)Qb(c[e>>2]|0,n,c[l>>2]|0)|0;c[h>>2]=c[g>>2];x=ab(n)|0;z=v;c[z>>2]=x;c[z+4>>2]=C;z=v;x=c[z+4>>2]|0;y=(c[g>>2]|0)+496|0;c[y>>2]=c[z>>2];c[y+4>>2]=x;if(c[(c[e>>2]|0)+88>>2]|0){x=v;if((c[x>>2]|0)!=-1?1:(c[x+4>>2]|0)!=-1)w=64;else w=65}else{x=v;if((c[(c[g>>2]|0)+448>>2]|0)!=0&((c[x>>2]|0)!=-1?1:(c[x+4>>2]|0)!=-1))w=64;else w=65}if((w|0)==64){w=0;x=v;y=wb(c[e>>2]|0,c[l>>2]|0,c[x>>2]|0,c[x+4>>2]|0)|0;x=(c[f>>2]|0)+416|0;c[x>>2]=y;c[x+4>>2]=C}else if((w|0)==65?(w=0,x=v,(c[x>>2]|0)==0&(c[x+4>>2]|0)==0):0){x=(c[f>>2]|0)+416|0;c[x>>2]=0;c[x+4>>2]=0}if(!(c[(c[g>>2]|0)+476>>2]|0)){if(c[(c[f>>2]|0)+404>>2]|0)c[o>>2]=Oa[c[(c[f>>2]|0)+404>>2]&15](c[e>>2]|0,n,c[l>>2]|0,c[(c[f>>2]|0)+408>>2]|0)|0}else c[o>>2]=Oa[c[(c[g>>2]|0)+476>>2]&15](c[e>>2]|0,n,c[l>>2]|0,c[(c[g>>2]|0)+480>>2]|0)|0;jb(c[h>>2]|0,n)|0;x=(_a(n)|0)!=0;y=(c[f>>2]|0)+440|0;if(!x){c[y>>2]=1;c[(c[f>>2]|0)+436>>2]=c[(c[e>>2]|0)+64>>2];c[(c[f>>2]|0)+444>>2]=0;continue}if((c[y>>2]|0)==-1)continue;y=(c[f>>2]|0)+440|0;c[y>>2]=(c[y>>2]|0)+1}if((w|0)==7){c[d>>2]=-18;A=c[d>>2]|0;i=b;return A|0}else if((w|0)==10){c[d>>2]=-17;A=c[d>>2]|0;i=b;return A|0}else if((w|0)==12){c[d>>2]=-17;A=c[d>>2]|0;i=b;return A|0}else if((w|0)==36){c[d>>2]=-17;A=c[d>>2]|0;i=b;return A|0}else if((w|0)==51){c[d>>2]=c[o>>2];A=c[d>>2]|0;i=b;return A|0}else if((w|0)==53){c[d>>2]=-404;A=c[d>>2]|0;i=b;return A|0}else if((w|0)==56){c[d>>2]=-18;A=c[d>>2]|0;i=b;return A|0}else if((w|0)==75){c[d>>2]=c[o>>2];A=c[d>>2]|0;i=b;return A|0}return 0}function Ec(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;dc(c[(c[d>>2]|0)+80>>2]|0,5)|0;i=b;return}function Fc(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0;g=i;i=i+32|0;h=g+16|0;j=g+12|0;k=g;l=g+8|0;c[h>>2]=a;c[j>>2]=b;b=k;c[b>>2]=d;c[b+4>>2]=e;c[l>>2]=f;Ec(c[h>>2]|0);f=k;k=Wc(c[h>>2]|0,c[j>>2]|0,c[f>>2]|0,c[f+4>>2]|0,c[l>>2]|0)|0;i=g;return k|0}function Gc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;e=i;i=i+32|0;f=e+20|0;g=e+16|0;h=e+12|0;j=e+8|0;k=e+4|0;l=e;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[k>>2]=(c[g>>2]|0)+112;if((Bb(c[g>>2]|0,c[h>>2]|0,c[j>>2]|0)|0)==-1){c[f>>2]=-1;m=c[f>>2]|0;i=e;return m|0}else{c[l>>2]=Cb(c[g>>2]|0)|0;c[(c[g>>2]|0)+64>>2]=c[l>>2];kb(c[k>>2]|0)|0;dc(c[(c[g>>2]|0)+80>>2]|0,6)|0;c[f>>2]=c[l>>2];m=c[f>>2]|0;i=e;return m|0}return 0}function Hc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;f=i;i=i+32|0;g=f+8|0;h=f+16|0;j=f+20|0;k=f+24|0;l=f+4|0;m=f;n=f+12|0;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=e;c[m>>2]=0;while(1){if((c[m>>2]|0)>=15){o=7;break}c[n>>2]=1040+((c[m>>2]|0)*24|0);if((c[l>>2]|0)>=(c[(c[n>>2]|0)+4>>2]|0)?(ve(c[k>>2]|0,c[c[n>>2]>>2]|0,c[(c[n>>2]|0)+4>>2]|0)|0)==0:0){o=5;break}c[m>>2]=(c[m>>2]|0)+1}if((o|0)==5){Wb(c[h>>2]|0,c[j>>2]|0,c[m>>2]|0)|0;c[g>>2]=1;p=c[g>>2]|0;i=f;return p|0}else if((o|0)==7){Wb(c[h>>2]|0,c[j>>2]|0,15)|0;c[g>>2]=0;p=c[g>>2]|0;i=f;return p|0}return 0}function Ic(a,b,e,f,g){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;h=i;i=i+64|0;j=h+20|0;k=h+40|0;l=h+44|0;m=h+36|0;n=h+32|0;o=h+52|0;p=h+16|0;q=h;r=h+8|0;s=h+28|0;t=h+24|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=e;c[n>>2]=f;c[h+48>>2]=g;c[o>>2]=c[m>>2];m=q;c[m>>2]=0;c[m+4>>2]=0;m=r;c[m>>2]=0;c[m+4>>2]=0;if((c[n>>2]|0)<48){c[j>>2]=0;u=c[j>>2]|0;i=h;return u|0}c[p>>2]=bd((c[o>>2]|0)+12|0)|0;if(vb(c[k>>2]|0,c[p>>2]|0)|0){c[j>>2]=1;u=c[j>>2]|0;i=h;return u|0}else{n=id((c[o>>2]|0)+20|0)|0;m=q;c[m>>2]=n;c[m+4>>2]=C;m=id((c[o>>2]|0)+28|0)|0;n=r;c[n>>2]=m;c[n+4>>2]=C;c[s>>2]=d[(c[o>>2]|0)+48>>0];o=c[k>>2]|0;n=c[p>>2]|0;m=q;q=c[m>>2]|0;g=c[m+4>>2]|0;m=r;r=Ue(1e3,0,c[m>>2]|0,c[m+4>>2]|0)|0;oc(o,n,q,g,r,C)|0;mc(c[k>>2]|0,c[p>>2]|0,c[s>>2]|0)|0;c[t>>2]=Yb(c[k>>2]|0,c[l>>2]|0)|0;Zc(c[k>>2]|0,c[l>>2]|0,(c[t>>2]|0)+1|0)|0;c[j>>2]=1;u=c[j>>2]|0;i=h;return u|0}return 0}function Jc(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;if(c[(c[d>>2]|0)+8>>2]|0){ze(c[(c[d>>2]|0)+8>>2]|0);c[(c[d>>2]|0)+8>>2]=0}c[(c[d>>2]|0)+4>>2]=0;c[c[d>>2]>>2]=0;i=b;return}function Kc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;b=i;i=i+16|0;d=b+12|0;e=b+8|0;f=b+4|0;g=b;c[e>>2]=a;a=(c[e>>2]|0)+4|0;c[a>>2]=(c[a>>2]|0)+1;do if((c[(c[e>>2]|0)+4>>2]|0)>(c[c[e>>2]>>2]|0)){if(!(c[c[e>>2]>>2]|0))c[g>>2]=1;else c[g>>2]=c[c[e>>2]>>2]<<1;c[f>>2]=Be(c[(c[e>>2]|0)+8>>2]|0,c[g>>2]<<2)|0;if(c[f>>2]|0){c[c[e>>2]>>2]=c[g>>2];c[(c[e>>2]|0)+8>>2]=c[f>>2];break}a=(c[e>>2]|0)+4|0;c[a>>2]=(c[a>>2]|0)+-1;c[d>>2]=0;h=c[d>>2]|0;i=b;return h|0}while(0);c[d>>2]=c[e>>2];h=c[d>>2]|0;i=b;return h|0}function Lc(a){a=a|0;var b=0,d=0,e=0,f=0;b=i;i=i+16|0;d=b+4|0;e=b;c[d>>2]=a;if(!(c[(c[d>>2]|0)+12>>2]|0)){i=b;return}c[e>>2]=(c[(c[d>>2]|0)+4>>2]|0)-1;while(1){if((c[e>>2]|0)<=0){f=6;break}if((La[c[(c[d>>2]|0)+12>>2]&1](c[(c[(c[d>>2]|0)+8>>2]|0)+((c[e>>2]|0)-1<<2)>>2]|0,c[(c[(c[d>>2]|0)+8>>2]|0)+(c[e>>2]<<2)>>2]|0,c[(c[d>>2]|0)+16>>2]|0)|0)<=0){f=6;break}Bd(c[(c[d>>2]|0)+8>>2]|0,c[e>>2]|0,(c[e>>2]|0)-1|0);c[e>>2]=(c[e>>2]|0)+-1}if((f|0)==6){i=b;return}}function Mc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;i=i+32|0;f=e+20|0;g=e+16|0;h=e+12|0;j=e+8|0;k=e+4|0;l=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;c[l>>2]=c[(c[f>>2]|0)+8>>2];if((c[g>>2]|0)>=(c[h>>2]|0)){i=e;return}Bd(c[l>>2]|0,c[g>>2]|0,((c[g>>2]|0)+(c[h>>2]|0)|0)/2|0);c[k>>2]=c[g>>2];c[j>>2]=(c[g>>2]|0)+1;while(1){if((c[j>>2]|0)>(c[h>>2]|0))break;if((La[c[(c[f>>2]|0)+12>>2]&1](c[(c[l>>2]|0)+(c[j>>2]<<2)>>2]|0,c[(c[l>>2]|0)+(c[g>>2]<<2)>>2]|0,c[(c[f>>2]|0)+16>>2]|0)|0)<0){d=c[l>>2]|0;b=(c[k>>2]|0)+1|0;c[k>>2]=b;Bd(d,b,c[j>>2]|0)}c[j>>2]=(c[j>>2]|0)+1}Bd(c[l>>2]|0,c[g>>2]|0,c[k>>2]|0);Mc(c[f>>2]|0,c[g>>2]|0,(c[k>>2]|0)-1|0);Mc(c[f>>2]|0,(c[k>>2]|0)+1|0,c[h>>2]|0);i=e;return}function Nc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[f>>2]=a;c[g>>2]=b;if(!(c[f>>2]|0)){c[e>>2]=-2;j=c[e>>2]|0;i=d;return j|0}c[h>>2]=sb(c[f>>2]|0,c[g>>2]|0)|0;if(!(c[h>>2]|0)){c[e>>2]=-20;j=c[e>>2]|0;i=d;return j|0}b=(c[h>>2]|0)+376|0;if((c[b>>2]|0)==0&(c[b+4>>2]|0)==0){b=(c[h>>2]|0)+376|0;c[b>>2]=1;c[b+4>>2]=0;b=(c[h>>2]|0)+384|0;c[b>>2]=0;c[b+4>>2]=0}b=c[f>>2]|0;a=c[g>>2]|0;if(!(c[(c[h>>2]|0)+408>>2]|0)){c[e>>2]=ub(b,a,19,0,1)|0;j=c[e>>2]|0;i=d;return j|0}h=(Xb(b,a)|0)==12;a=c[f>>2]|0;b=c[g>>2]|0;if(h){c[e>>2]=ub(a,b,20,0,1)|0;j=c[e>>2]|0;i=d;return j|0}h=(Xb(a,b)|0)==14;b=c[f>>2]|0;f=c[g>>2]|0;if(h){c[e>>2]=ub(b,f,21,0,1)|0;j=c[e>>2]|0;i=d;return j|0}else{c[e>>2]=ub(b,f,22,0,1)|0;j=c[e>>2]|0;i=d;return j|0}return 0}function Oc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;e=i;i=i+16|0;f=e+8|0;g=e+4|0;h=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;c[c[f>>2]>>2]=c[g>>2];c[(c[f>>2]|0)+4>>2]=c[g>>2];c[(c[f>>2]|0)+8>>2]=(c[(c[f>>2]|0)+4>>2]|0)+(c[h>>2]|0);c[(c[f>>2]|0)+12>>2]=8;i=e;return}function Pc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;i=i+16|0;e=d+4|0;f=d;c[e>>2]=a;c[f>>2]=b;b=(c[e>>2]|0)+12|0;c[b>>2]=(c[b>>2]|0)-(c[f>>2]|0);while(1){if((c[(c[e>>2]|0)+12>>2]|0)>0)break;f=(c[e>>2]|0)+4|0;c[f>>2]=(c[f>>2]|0)+1;f=(c[e>>2]|0)+12|0;c[f>>2]=(c[f>>2]|0)+8}i=d;return}function Qc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;b=i;i=i+16|0;d=b+8|0;e=b+4|0;f=b;c[d>>2]=a;c[e>>2]=0;c[f>>2]=0;while(1){a=(Gd(c[d>>2]|0,1)|0)!=0^1;g=c[e>>2]|0;if(!a)break;c[e>>2]=g+1;c[f>>2]=c[f>>2]<<1;a=Gd(c[d>>2]|0,1)|0;c[f>>2]=c[f>>2]|a}i=b;return (1<<g)-1+(c[f>>2]|0)|0}function Rc(a){a=a|0;var b=0,d=0;b=i;i=i+16|0;d=b;c[d>>2]=a;a=Gd(c[d>>2]|0,1)|0;i=b;return a|0}function Sc(a){a=a|0;var b=0,d=0,e=0,f=0;b=i;i=i+16|0;d=b+8|0;e=b+4|0;f=b;c[e>>2]=a;do if(c[e>>2]|0){c[f>>2]=ye((Cc(c[e>>2]|0)|0)+1|0)|0;if(!(c[f>>2]|0)){c[d>>2]=0;break}else{c[d>>2]=Oe(c[f>>2]|0,c[e>>2]|0)|0;break}}else c[d>>2]=0;while(0);i=b;return c[d>>2]|0}function Tc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[f>>2]=a;c[g>>2]=b;if(!(vc(c[f>>2]|0)|0)){c[e>>2]=0;j=c[e>>2]|0;i=d;return j|0}c[h>>2]=ye(8)|0;if(!(c[h>>2]|0)){c[e>>2]=0;j=c[e>>2]|0;i=d;return j|0}b=Sc(c[f>>2]|0)|0;c[c[h>>2]>>2]=b;if(!(c[c[h>>2]>>2]|0)){ze(c[h>>2]|0);c[e>>2]=0;j=c[e>>2]|0;i=d;return j|0}if(c[g>>2]|0){b=Sc(c[g>>2]|0)|0;c[(c[h>>2]|0)+4>>2]=b;if(!(c[(c[h>>2]|0)+4>>2]|0)){ze(c[c[h>>2]>>2]|0);ze(c[h>>2]|0);c[e>>2]=0;j=c[e>>2]|0;i=d;return j|0}}else c[(c[h>>2]|0)+4>>2]=0;c[e>>2]=c[h>>2];j=c[e>>2]|0;i=d;return j|0}function Uc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;d=i;i=i+32|0;e=d+20|0;f=d+16|0;g=d+12|0;h=d+8|0;j=d+4|0;k=d;c[f>>2]=a;c[g>>2]=b;c[h>>2]=(c[f>>2]|0)+112;c[k>>2]=0;b=(c[f>>2]|0)+64|0;c[b>>2]=(c[b>>2]|0)+(c[(c[h>>2]|0)+432>>2]|0);while(1){c[j>>2]=ib(c[h>>2]|0,c[g>>2]|0)|0;if(!(c[j>>2]|0)){l=3;break}b=c[j>>2]|0;if((c[j>>2]|0)<0){a=(c[f>>2]|0)+64|0;c[a>>2]=(c[a>>2]|0)+(0-b)}else{c[(c[h>>2]|0)+432>>2]=b;c[k>>2]=1}if(!((c[k>>2]|0)!=0^1)){l=8;break}}if((l|0)==3){c[e>>2]=-2;m=c[e>>2]|0;i=d;return m|0}else if((l|0)==8){c[e>>2]=c[(c[f>>2]|0)+64>>2];m=c[e>>2]|0;i=d;return m|0}return 0}function Vc(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b+4|0;e=b;c[d>>2]=a;c[e>>2]=c[d>>2];if((c[(c[e>>2]|0)+336>>2]|0)==-1){i=b;return 0}lb(c[e>>2]|0)|0;i=b;return 0}function Wc(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;g=i;i=i+32|0;h=g+28|0;j=g+20|0;k=g+24|0;l=g;m=g+16|0;n=g+12|0;o=g+8|0;c[j>>2]=a;c[k>>2]=b;b=l;c[b>>2]=d;c[b+4>>2]=e;c[m>>2]=f;c[n>>2]=(c[j>>2]|0)+112;c[o>>2]=Gc(c[j>>2]|0,c[k>>2]|0,c[m>>2]|0)|0;if((c[o>>2]|0)==-1){c[h>>2]=-1;p=c[h>>2]|0;i=g;return p|0}c[(c[j>>2]|0)+64>>2]=c[o>>2];j=l;if((c[j>>2]|0)!=-1?1:(c[j+4>>2]|0)!=-1){j=l;l=c[j+4>>2]|0;m=(c[n>>2]|0)+416|0;c[m>>2]=c[j>>2];c[m+4>>2]=l}c[h>>2]=c[o>>2];p=c[h>>2]|0;i=g;return p|0}function Xc(b,e,f,g,h){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;j=i;i=i+48|0;k=j+12|0;l=j+16|0;m=j+28|0;n=j+4|0;o=j+32|0;p=j+40|0;q=j+24|0;r=j+20|0;s=j+8|0;t=j+44|0;u=j;c[l>>2]=b;c[m>>2]=e;c[n>>2]=f;c[o>>2]=g;c[j+36>>2]=h;c[p>>2]=c[n>>2];a[t>>0]=0;if((c[o>>2]|0)<41){c[k>>2]=0;v=c[k>>2]|0;i=j;return v|0}c[q>>2]=(d[(c[p>>2]|0)+7>>0]<<16)+(d[(c[p>>2]|0)+8>>0]<<8)+(d[(c[p>>2]|0)+9>>0]|0);c[r>>2]=Yc((c[p>>2]|0)+22|0)|0;c[s>>2]=Yc((c[p>>2]|0)+26|0)|0;if(!(c[r>>2]|0))c[r>>2]=1;a[t>>0]=(d[(c[p>>2]|0)+40>>0]&3)<<3;a[t>>0]=a[t>>0]|(d[(c[p>>2]|0)+41>>0]&224)>>5;c[u>>2]=a[t>>0];t=c[l>>2]|0;p=c[m>>2]|0;o=c[r>>2]|0;r=c[s>>2]|0;s=Ue(1e3,0,r|0,((r|0)<0)<<31>>31|0)|0;oc(t,p,o,((o|0)<0)<<31>>31,s,C)|0;mc(c[l>>2]|0,c[m>>2]|0,c[u>>2]|0)|0;if((c[q>>2]|0)<197120)qc(c[l>>2]|0,c[m>>2]|0,-1,-1)|0;Zc(c[l>>2]|0,c[m>>2]|0,3)|0;c[k>>2]=1;v=c[k>>2]|0;i=j;return v|0}function Yc(a){a=a|0;var b=0,e=0;b=i;i=i+16|0;e=b;c[e>>2]=a;i=b;return (d[c[e>>2]>>0]|0)<<24|(d[(c[e>>2]|0)+1>>0]|0)<<16|(d[(c[e>>2]|0)+2>>0]|0)<<8|(d[(c[e>>2]|0)+3>>0]|0)|0}function Zc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e+4|0;k=e;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;if(!(c[g>>2]|0)){c[f>>2]=-2;l=c[f>>2]|0;i=e;return l|0}c[k>>2]=sb(c[g>>2]|0,c[h>>2]|0)|0;if(!(c[k>>2]|0)){c[f>>2]=-20;l=c[f>>2]|0;i=e;return l|0}else{c[(c[k>>2]|0)+364>>2]=c[j>>2];c[f>>2]=0;l=c[f>>2]|0;i=e;return l|0}return 0}function _c(b,e,f,g){b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;h=i;i=i+48|0;j=h+8|0;k=h;l=h+28|0;m=h+24|0;n=h+20|0;o=h+16|0;p=h+36|0;q=h+32|0;r=k;c[r>>2]=b;c[r+4>>2]=e;c[l>>2]=f;c[m>>2]=g;if(!(c[(c[m>>2]|0)+4>>2]|0))s=64;else s=d[c[c[m>>2]>>2]>>0]|0;a[p>>0]=s;c[q>>2]=c[(c[l>>2]|0)+504>>2];a:do if(!((d[p>>0]|0)&128)){s=k;m=c[s+4>>2]|0;if((m|0)>-1|(m|0)==-1&(c[s>>2]|0)>>>0>4294967295){c[c[q>>2]>>2]=1;s=k;m=c[s+4>>2]|0;g=j;c[g>>2]=c[s>>2];c[g+4>>2]=m;break}m=(c[l>>2]|0)+488|0;g=c[q>>2]|0;if((c[m>>2]|0)==-1?(c[m+4>>2]|0)==-1:0){c[g>>2]=1;m=j;c[m>>2]=-1;c[m+4>>2]=-1;break}if(!(c[g>>2]|0)){c[c[q>>2]>>2]=1;g=j;c[g>>2]=-1;c[g+4>>2]=-1;break}g=c[l>>2]|0;if((d[p>>0]|0)&64){m=g+488|0;s=Me(c[m>>2]|0,c[m+4>>2]|0,1,0)|0;m=j;c[m>>2]=s;c[m+4>>2]=C;break}else{c[o>>2]=c[g+408>>2];g=(c[l>>2]|0)+488|0;m=Fe(c[g>>2]|0,c[g+4>>2]|0,c[o>>2]|0)|0;c[n>>2]=m;m=(c[l>>2]|0)+488|0;g=(1<<c[o>>2])-1|0;s=Me(c[m>>2]&g|0,c[m+4>>2]&((g|0)<0)<<31>>31|0,1,0)|0;g=c[n>>2]|0;m=Me(g|0,((g|0)<0)<<31>>31|0,s|0,C|0)|0;c[n>>2]=m;m=c[n>>2]|0;s=Ie(m|0,((m|0)<0)<<31>>31|0,c[o>>2]|0)|0;m=j;c[m>>2]=s;c[m+4>>2]=C;break}}else{do if(!(c[q>>2]|0)){m=ye(4)|0;c[(c[l>>2]|0)+504>>2]=m;if(!(c[(c[l>>2]|0)+504>>2]|0)){m=j;c[m>>2]=-1;c[m+4>>2]=-1;break a}else{c[q>>2]=c[(c[l>>2]|0)+504>>2];break}}while(0);c[c[q>>2]>>2]=0;m=j;c[m>>2]=0;c[m+4>>2]=0}while(0);q=j;C=c[q+4>>2]|0;i=h;return c[q>>2]|0}function $c(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;g=i;i=i+48|0;h=g;j=g+8|0;k=g+28|0;l=g+16|0;m=g+24|0;n=j;c[n>>2]=a;c[n+4>>2]=b;c[k>>2]=d;c[g+32>>2]=e;c[g+20>>2]=f;f=j;e=Fe(c[f>>2]|0,c[f+4>>2]|0,c[(c[k>>2]|0)+408>>2]|0)|0;c[l>>2]=e;e=j;j=c[l>>2]<<c[(c[k>>2]|0)+408>>2];f=Ge(c[e>>2]|0,c[e+4>>2]|0,j|0,((j|0)<0)<<31>>31|0)|0;c[m>>2]=f;f=c[l>>2]|0;if(!(c[m>>2]|0)){l=(f-60<<c[(c[k>>2]|0)+408>>2])+59|0;j=h;c[j>>2]=l;c[j+4>>2]=((l|0)<0)<<31>>31;o=h;p=o;q=c[p>>2]|0;r=o+4|0;s=r;t=c[s>>2]|0;C=t;i=g;return q|0}else{l=Ie(f|0,((f|0)<0)<<31>>31|0,c[(c[k>>2]|0)+408>>2]|0)|0;k=(c[m>>2]|0)-1|0;m=Me(l|0,C|0,k|0,((k|0)<0)<<31>>31|0)|0;k=h;c[k>>2]=m;c[k+4>>2]=C;o=h;p=o;q=c[p>>2]|0;r=o+4|0;s=r;t=c[s>>2]|0;C=t;i=g;return q|0}return 0}function ad(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;g=i;i=i+48|0;h=g+28|0;j=g+12|0;k=g+24|0;l=g+20|0;m=g+32|0;n=g+16|0;o=g;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[g+8>>2]=f;c[n>>2]=c[l>>2];l=o;c[l>>2]=0;c[l+4>>2]=0;if((c[m>>2]|0)<30){c[h>>2]=0;p=c[h>>2]|0;i=g;return p|0}else{m=bd((c[n>>2]|0)+12|0)|0;n=o;c[n>>2]=m;c[n+4>>2]=((m|0)<0)<<31>>31;m=o;oc(c[j>>2]|0,c[k>>2]|0,c[m>>2]|0,c[m+4>>2]|0,1e3,0)|0;Zb(c[j>>2]|0,c[k>>2]|0,2)|0;Zc(c[j>>2]|0,c[k>>2]|0,3)|0;c[h>>2]=1;p=c[h>>2]|0;i=g;return p|0}return 0}function bd(a){a=a|0;var b=0,e=0;b=i;i=i+16|0;e=b;c[e>>2]=a;i=b;return d[c[e>>2]>>0]|0|(d[(c[e>>2]|0)+1>>0]|0)<<8|(d[(c[e>>2]|0)+2>>0]|0)<<16|(d[(c[e>>2]|0)+3>>0]|0)<<24|0}function cd(a,b,e,f){a=a|0;b=b|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,D=0;g=i;i=i+80|0;h=g+8|0;j=g+24|0;k=g+40|0;l=g+16|0;m=g+20|0;n=g+28|0;o=g+36|0;p=g+32|0;q=g+44|0;r=g+48|0;s=g+52|0;t=g+56|0;u=g+60|0;v=g+64|0;w=g;c[w>>2]=a;c[w+4>>2]=b;c[j>>2]=e;c[k>>2]=f;f=c[c[k>>2]>>2]|0;if(!(c[(c[j>>2]|0)+504>>2]|0)){c[o>>2]=1<<((d[f+28>>0]|0)>>4);c[n>>2]=1<<((d[(c[c[k>>2]>>2]|0)+28>>0]|0)&15);e=ye(44)|0;c[(c[j>>2]|0)+504>>2]=e;if(!(c[(c[j>>2]|0)+504>>2]|0)){e=h;c[e>>2]=-1;c[e+4>>2]=-1;x=h;y=x;z=c[y>>2]|0;A=x+4|0;B=A;D=c[B>>2]|0;C=D;i=g;return z|0}else{c[l>>2]=c[(c[j>>2]|0)+504>>2];c[(c[l>>2]|0)+12>>2]=c[o>>2]>>1;c[(c[l>>2]|0)+8>>2]=((c[o>>2]>>2)*3|0)-(c[n>>2]>>2);c[(c[l>>2]|0)+4>>2]=(c[o>>2]>>2)+(c[n>>2]>>2);c[c[l>>2]>>2]=c[(c[l>>2]|0)+12>>2];c[(c[l>>2]|0)+20>>2]=c[n>>2];c[(c[l>>2]|0)+24>>2]=c[o>>2];c[(c[l>>2]|0)+16>>2]=c[n>>2]>>1;c[(c[l>>2]|0)+28>>2]=0;n=h;c[n>>2]=0;c[n+4>>2]=0;x=h;y=x;z=c[y>>2]|0;A=x+4|0;B=A;D=c[B>>2]|0;C=D;i=g;return z|0}}if(!((d[f>>0]|0)&1)){c[l>>2]=c[(c[j>>2]|0)+504>>2];f=h;c[f>>2]=-1;c[f+4>>2]=-1;x=h;y=x;z=c[y>>2]|0;A=x+4|0;B=A;D=c[B>>2]|0;C=D;i=g;return z|0}a:do if((d[c[c[k>>2]>>2]>>0]|0|0)==5){c[p>>2]=(c[c[k>>2]>>2]|0)+((c[(c[k>>2]|0)+4>>2]|0)-1);c[r>>2]=0;c[q>>2]=8;while(1){f=(c[q>>2]|0)+-1|0;c[q>>2]=f;if(!((1<<f&(d[c[p>>2]>>0]|0)|0)!=0^1))break;if(c[q>>2]|0)continue;c[q>>2]=8;c[p>>2]=(c[p>>2]|0)+-1}while(1){c[q>>2]=((c[q>>2]|0)+7|0)%8|0;if((c[q>>2]|0)==7)c[p>>2]=(c[p>>2]|0)+-1;if((d[(c[p>>2]|0)+-5>>0]|0)&~((1<<(c[q>>2]|0)+1)-1))break;if(d[(c[p>>2]|0)+-4>>0]|0)break;if(d[(c[p>>2]|0)+-3>>0]|0)break;if(d[(c[p>>2]|0)+-2>>0]|0)break;if((d[(c[p>>2]|0)+-1>>0]|0)&(1<<(c[q>>2]|0)+1)-1)break;c[r>>2]=(c[r>>2]|0)+1;c[p>>2]=(c[p>>2]|0)+-5}c[m>>2]=0;while(1){if((c[m>>2]|0)>=2)break;f=d[c[p>>2]>>0]|0;n=c[q>>2]|0;if((c[q>>2]|0)>4)c[s>>2]=f>>n-5&63;else{c[s>>2]=f&(1<<n+1)-1;c[s>>2]=c[s>>2]<<5-(c[q>>2]|0);c[s>>2]=c[s>>2]|((d[(c[p>>2]|0)+-1>>0]|0)&~((1<<(c[q>>2]|0)+3)-1))>>(c[q>>2]|0)+3}c[s>>2]=(c[s>>2]|0)+1;if((c[s>>2]|0)==(c[r>>2]|0))break;c[q>>2]=((c[q>>2]|0)+1|0)%8|0;if(!(c[q>>2]|0))c[p>>2]=(c[p>>2]|0)+1;c[p>>2]=(c[p>>2]|0)+5;c[r>>2]=(c[r>>2]|0)-1;c[m>>2]=(c[m>>2]|0)+1}c[v>>2]=44+((c[r>>2]|0)-1<<2);if((c[v>>2]|0)>>>0<44){n=h;c[n>>2]=-1;c[n+4>>2]=-1;x=h;y=x;z=c[y>>2]|0;A=x+4|0;B=A;D=c[B>>2]|0;C=D;i=g;return z|0}c[l>>2]=Be(c[(c[j>>2]|0)+504>>2]|0,c[v>>2]|0)|0;if(!(c[l>>2]|0)){n=h;c[n>>2]=-1;c[n+4>>2]=-1;x=h;y=x;z=c[y>>2]|0;A=x+4|0;B=A;D=c[B>>2]|0;C=D;i=g;return z|0}c[(c[j>>2]|0)+504>>2]=c[l>>2];c[u>>2]=-1;do{n=(c[u>>2]|0)+1|0;c[u>>2]=n}while((1<<n|0)<(c[r>>2]|0));c[(c[l>>2]|0)+36>>2]=c[u>>2];c[t>>2]=(c[l>>2]|0)+40;c[u>>2]=0;while(1){if((c[u>>2]|0)>=(c[r>>2]|0))break a;c[q>>2]=((c[q>>2]|0)+1|0)%8|0;if(!(c[q>>2]|0))c[p>>2]=(c[p>>2]|0)+1;n=(d[c[p>>2]>>0]|0)>>c[q>>2]&1;f=c[t>>2]|0;c[t>>2]=f+4;c[f>>2]=n;c[p>>2]=(c[p>>2]|0)+5;c[u>>2]=(c[u>>2]|0)+1}}while(0);u=h;c[u>>2]=0;c[u+4>>2]=0;x=h;y=x;z=c[y>>2]|0;A=x+4|0;B=A;D=c[B>>2]|0;C=D;i=g;return z|0}function dd(a,b,e,f,g){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;h=i;i=i+64|0;j=h+16|0;k=h;l=h+36|0;m=h+32|0;n=h+40|0;o=h+44|0;p=h+48|0;q=h+28|0;r=h+24|0;s=h+8|0;t=k;c[t>>2]=a;c[t+4>>2]=b;c[l>>2]=e;c[m>>2]=f;c[n>>2]=g;c[o>>2]=c[(c[l>>2]|0)+504>>2];c[p>>2]=(d[c[c[m>>2]>>2]>>0]|0)>>1&(1<<c[(c[o>>2]|0)+36>>2])-1;m=c[o>>2]|0;if(c[(c[o>>2]|0)+40+(c[p>>2]<<2)>>2]|0)u=c[m+24>>2]|0;else u=c[m+20>>2]|0;c[q>>2]=u;c[p>>2]=(d[c[c[n>>2]>>2]>>0]|0)>>1&(1<<c[(c[o>>2]|0)+36>>2])-1;n=c[o>>2]|0;if(c[(c[o>>2]|0)+40+(c[p>>2]<<2)>>2]|0)v=c[n+24>>2]|0;else v=c[n+20>>2]|0;c[r>>2]=v;v=k;k=((c[q>>2]|0)+(c[r>>2]|0)|0)/4|0;r=Ge(c[v>>2]|0,c[v+4>>2]|0,k|0,((k|0)<0)<<31>>31|0)|0;k=s;c[k>>2]=r;c[k+4>>2]=C;if((c[s+4>>2]|0)<0){k=j;c[k>>2]=0;c[k+4>>2]=0;w=j;x=w;y=c[x>>2]|0;z=w+4|0;A=z;B=c[A>>2]|0;C=B;i=h;return y|0}else{k=s;s=c[k+4>>2]|0;r=j;c[r>>2]=c[k>>2];c[r+4>>2]=s;w=j;x=w;y=c[x>>2]|0;z=w+4|0;A=z;B=c[A>>2]|0;C=B;i=h;return y|0}return 0}function ed(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;g=i;i=i+48|0;h=g+32|0;j=g+12|0;k=g+28|0;l=g+24|0;m=g+36|0;n=g+16|0;o=g;p=g+20|0;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[g+8>>2]=f;c[n>>2]=c[l>>2];l=o;c[l>>2]=0;c[l+4>>2]=0;if((c[m>>2]|0)<68){c[h>>2]=0;q=c[h>>2]|0;i=g;return q|0}else{m=bd((c[n>>2]|0)+36|0)|0;l=o;c[l>>2]=m;c[l+4>>2]=((m|0)<0)<<31>>31;m=o;oc(c[j>>2]|0,c[k>>2]|0,c[m>>2]|0,c[m+4>>2]|0,1e3,0)|0;Zb(c[j>>2]|0,c[k>>2]|0,3)|0;m=bd((c[n>>2]|0)+68|0)|0;n=Me(m|0,((m|0)<0)<<31>>31|0,2,0)|0;c[p>>2]=n;Zc(c[j>>2]|0,c[k>>2]|0,c[p>>2]|0)|0;c[h>>2]=1;q=c[h>>2]|0;i=g;return q|0}return 0}function fd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+32|0;g=f+8|0;h=f;j=f+24|0;k=f+20|0;l=f+16|0;m=h;c[m>>2]=a;c[m+4>>2]=b;c[j>>2]=d;c[k>>2]=e;c[l>>2]=c[(c[j>>2]|0)+504>>2];do if(!(c[(c[j>>2]|0)+504>>2]|0)){e=ye(12)|0;c[(c[j>>2]|0)+504>>2]=e;if(!(c[(c[j>>2]|0)+504>>2]|0)){e=g;c[e>>2]=-1;c[e+4>>2]=-1;break}else{c[l>>2]=c[(c[j>>2]|0)+504>>2];c[(c[l>>2]|0)+8>>2]=0;e=_(c[(c[c[k>>2]>>2]|0)+64>>2]|0,c[(c[c[k>>2]>>2]|0)+56>>2]|0)|0;c[(c[l>>2]|0)+4>>2]=e;c[c[l>>2]>>2]=1;e=g;c[e>>2]=0;c[e+4>>2]=0;break}}else{e=c[l>>2]|0;if((c[c[l>>2]>>2]|0)<2)c[e>>2]=(c[e>>2]|0)+1;else c[e+8>>2]=1;e=h;d=c[e+4>>2]|0;if((d|0)>-1|(d|0)==-1&(c[e>>2]|0)>>>0>4294967295){e=h;d=c[e+4>>2]|0;b=g;c[b>>2]=c[e>>2];c[b+4>>2]=d;break}if(!(c[(c[l>>2]|0)+8>>2]|0)){d=g;c[d>>2]=0;c[d+4>>2]=0;break}d=(c[j>>2]|0)+488|0;b=c[d+4>>2]|0;if((b|0)>0|(b|0)==0&(c[d>>2]|0)>>>0>0){d=(c[j>>2]|0)+488|0;b=c[(c[l>>2]|0)+4>>2]|0;e=Me(c[d>>2]|0,c[d+4>>2]|0,b|0,((b|0)<0)<<31>>31|0)|0;b=g;c[b>>2]=e;c[b+4>>2]=C;break}else{b=g;c[b>>2]=-1;c[b+4>>2]=-1;break}}while(0);l=g;C=c[l+4>>2]|0;i=f;return c[l>>2]|0}function gd(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;g=i;i=i+48|0;h=g+28|0;j=g+12|0;k=g+24|0;l=g+20|0;m=g+32|0;n=g+16|0;o=g;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[g+8>>2]=f;c[n>>2]=c[l>>2];if((c[m>>2]|0)<28){c[h>>2]=0;p=c[h>>2]|0;i=g;return p|0}else{m=Yc((c[n>>2]|0)+16|0)|0;n=o;c[n>>2]=m;c[n+4>>2]=((m|0)<0)<<31>>31;m=o;oc(c[j>>2]|0,c[k>>2]|0,c[m>>2]|0,c[m+4>>2]|0,1e3,0)|0;Zc(c[j>>2]|0,c[k>>2]|0,3)|0;c[h>>2]=1;p=c[h>>2]|0;i=g;return p|0}return 0}function hd(a,b,e,f,g){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;h=i;i=i+48|0;j=h+24|0;k=h+28|0;l=h+32|0;m=h+36|0;n=h+40|0;o=h+20|0;p=h;q=h+8|0;r=h+16|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=e;c[n>>2]=f;c[h+44>>2]=g;c[o>>2]=c[m>>2];m=p;c[m>>2]=0;c[m+4>>2]=0;m=q;c[m>>2]=0;c[m+4>>2]=0;if((c[n>>2]|0)<28){c[j>>2]=0;s=c[j>>2]|0;i=h;return s|0}m=id((c[o>>2]|0)+12|0)|0;g=p;c[g>>2]=m;c[g+4>>2]=C;g=id((c[o>>2]|0)+20|0)|0;m=q;c[m>>2]=g;c[m+4>>2]=C;if((c[n>>2]|0)>28)c[r>>2]=d[(c[o>>2]|0)+28>>0];else c[r>>2]=0;o=c[k>>2]|0;n=c[l>>2]|0;m=p;p=c[m>>2]|0;g=c[m+4>>2]|0;m=q;q=Ue(1e3,0,c[m>>2]|0,c[m+4>>2]|0)|0;oc(o,n,p,g,q,C)|0;mc(c[k>>2]|0,c[l>>2]|0,c[r>>2]|0)|0;Zc(c[k>>2]|0,c[l>>2]|0,3)|0;c[j>>2]=1;s=c[j>>2]|0;i=h;return s|0}function id(a){a=a|0;var b=0,e=0,f=0,g=0;b=i;i=i+16|0;e=b+8|0;f=b+4|0;g=b;c[e>>2]=a;c[f>>2]=d[c[e>>2]>>0]|0|(d[(c[e>>2]|0)+1>>0]|0)<<8|(d[(c[e>>2]|0)+2>>0]|0)<<16|(d[(c[e>>2]|0)+3>>0]|0)<<24;c[g>>2]=d[(c[e>>2]|0)+4>>0]|0|(d[(c[e>>2]|0)+5>>0]|0)<<8|(d[(c[e>>2]|0)+6>>0]|0)<<16|(d[(c[e>>2]|0)+7>>0]|0)<<24;C=c[g>>2]|0;i=b;return c[f>>2]|0}function jd(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0;g=i;i=i+32|0;h=g+16|0;j=g+12|0;c[h>>2]=a;c[j>>2]=b;c[g+8>>2]=d;c[g+4>>2]=e;c[g>>2]=f;oc(c[h>>2]|0,c[j>>2]|0,0,0,1,0)|0;i=g;return 1}function kd(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0;g=i;i=i+32|0;h=g+16|0;j=g+12|0;c[h>>2]=a;c[j>>2]=b;c[g+8>>2]=d;c[g+4>>2]=e;c[g>>2]=f;oc(c[h>>2]|0,c[j>>2]|0,0,0,1,0)|0;Zc(c[h>>2]|0,c[j>>2]|0,1)|0;i=g;return 1}function ld(a,b,e,f,g){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0;h=i;i=i+32|0;j=h+24|0;k=h+16|0;l=h+20|0;m=h+8|0;n=h;c[j>>2]=a;c[k>>2]=b;c[l>>2]=e;c[h+28>>2]=f;c[h+12>>2]=g;c[m>>2]=c[l>>2];l=n;c[l>>2]=0;c[l+4>>2]=0;l=(d[(c[m>>2]|0)+14>>0]|0)<<12;g=(d[(c[m>>2]|0)+15>>0]|0)<<4;f=(d[(c[m>>2]|0)+16>>0]|0)>>4&15;m=n;c[m>>2]=l|g|f;c[m+4>>2]=((l|0)<0)<<31>>31|((g|0)<0)<<31>>31|((f|0)<0)<<31>>31;f=n;oc(c[j>>2]|0,c[k>>2]|0,c[f>>2]|0,c[f+4>>2]|0,1e3,0)|0;Zc(c[j>>2]|0,c[k>>2]|0,3)|0;i=h;return 1}function md(b,e,f,g){b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;h=i;i=i+48|0;j=h;k=h+8|0;l=h+20|0;m=h+28|0;n=h+16|0;o=h+32|0;p=h+24|0;q=k;c[q>>2]=b;c[q+4>>2]=e;c[l>>2]=f;c[m>>2]=g;do if(c[(c[l>>2]|0)+504>>2]|0){c[n>>2]=c[(c[l>>2]|0)+504>>2];if((d[c[c[m>>2]>>2]>>0]|0|0)==255)c[(c[n>>2]|0)+8>>2]=1;g=k;if((((c[g>>2]|0)==-1?(c[g+4>>2]|0)==-1:0)?(d[c[c[m>>2]>>2]>>0]|0|0)==255:0)?(c[(c[m>>2]|0)+4>>2]|0)>2:0){a[o>>0]=((d[(c[c[m>>2]>>2]|0)+2>>0]|0)&240)>>4;do switch(d[o>>0]|0|0){case 0:{c[p>>2]=-1;break}case 1:{c[p>>2]=192;break}case 2:{c[p>>2]=576;break}case 3:{c[p>>2]=1152;break}case 4:{c[p>>2]=2304;break}case 5:{c[p>>2]=4608;break}case 6:{c[p>>2]=-1;break}case 7:{c[p>>2]=-1;break}case 8:{c[p>>2]=256;break}case 9:{c[p>>2]=512;break}case 10:{c[p>>2]=1024;break}case 11:{c[p>>2]=2048;break}case 12:{c[p>>2]=4096;break}case 13:{c[p>>2]=8192;break}case 14:{c[p>>2]=16384;break}case 15:{c[p>>2]=32768;break}default:c[p>>2]=-1}while(0);if((c[p>>2]|0)==-1)break;g=c[n>>2]|0;f=c[p>>2]|0;e=Me(c[g>>2]|0,c[g+4>>2]|0,f|0,((f|0)<0)<<31>>31|0)|0;f=k;c[f>>2]=e;c[f+4>>2]=C;break}f=k;if(((c[f>>2]|0)==-1?(c[f+4>>2]|0)==-1:0)?(c[(c[n>>2]|0)+8>>2]|0)==0:0){f=k;c[f>>2]=0;c[f+4>>2]=0}}else{f=ye(16)|0;c[(c[l>>2]|0)+504>>2]=f;if(c[(c[l>>2]|0)+504>>2]|0){c[n>>2]=c[(c[l>>2]|0)+504>>2];f=c[n>>2]|0;c[f>>2]=0;c[f+4>>2]=0;c[(c[n>>2]|0)+8>>2]=0;break}f=j;c[f>>2]=-1;c[f+4>>2]=-1;r=j;s=r;t=c[s>>2]|0;u=r+4|0;v=u;w=c[v>>2]|0;C=w;i=h;return t|0}while(0);l=k;p=c[l+4>>2]|0;o=c[n>>2]|0;c[o>>2]=c[l>>2];c[o+4>>2]=p;p=k;k=c[p+4>>2]|0;o=j;c[o>>2]=c[p>>2];c[o+4>>2]=k;r=j;s=r;t=c[s>>2]|0;u=r+4|0;v=u;w=c[v>>2]|0;C=w;i=h;return t|0}function nd(a,b,e,f,g){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;h=i;i=i+48|0;j=h+32|0;k=h+12|0;l=h+28|0;m=h+24|0;n=h+36|0;o=h+16|0;p=h;q=h+20|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=e;c[n>>2]=f;c[h+8>>2]=g;c[o>>2]=c[m>>2];m=p;c[m>>2]=0;c[m+4>>2]=0;if((c[n>>2]|0)<51){c[j>>2]=0;r=c[j>>2]|0;i=h;return r|0}else{n=(d[(c[o>>2]|0)+27>>0]|0)<<12;m=(d[(c[o>>2]|0)+28>>0]|0)<<4;g=(d[(c[o>>2]|0)+29>>0]|0)>>4&15;f=p;c[f>>2]=n|m|g;c[f+4>>2]=((n|0)<0)<<31>>31|((m|0)<0)<<31>>31|((g|0)<0)<<31>>31;g=p;oc(c[k>>2]|0,c[l>>2]|0,c[g>>2]|0,c[g+4>>2]|0,1e3,0)|0;c[q>>2]=(od((c[o>>2]|0)+7|0)|0)&65535;Zc(c[k>>2]|0,c[l>>2]|0,c[q>>2]|0)|0;c[j>>2]=1;r=c[j>>2]|0;i=h;return r|0}return 0}function od(a){a=a|0;var b=0,e=0;b=i;i=i+16|0;e=b;c[e>>2]=a;i=b;return ((d[c[e>>2]>>0]|0)<<8|(d[(c[e>>2]|0)+1>>0]|0))&65535|0}function pd(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;g=i;i=i+48|0;h=g+32|0;j=g+28|0;k=g+36|0;l=g+16|0;m=g+40|0;n=g+20|0;o=g;p=g+8|0;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[g+24>>2]=f;c[n>>2]=c[l>>2];l=o;c[l>>2]=0;c[l+4>>2]=0;l=p;c[l>>2]=0;c[l+4>>2]=0;if((c[m>>2]|0)<28){c[h>>2]=0;q=c[h>>2]|0;i=g;return q|0}else{m=id((c[n>>2]|0)+8|0)|0;l=o;c[l>>2]=m;c[l+4>>2]=C;l=id((c[n>>2]|0)+16|0)|0;n=p;c[n>>2]=l;c[n+4>>2]=C;n=c[j>>2]|0;j=c[k>>2]|0;k=o;o=c[k>>2]|0;l=c[k+4>>2]|0;k=p;p=Ue(1e3,0,c[k>>2]|0,c[k+4>>2]|0)|0;oc(n,j,o,l,p,C)|0;c[h>>2]=1;q=c[h>>2]|0;i=g;return q|0}return 0}function qd(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;g=i;i=i+48|0;h=g+32|0;j=g+12|0;k=g+28|0;l=g+24|0;m=g+36|0;n=g+16|0;o=g;p=g+20|0;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[g+8>>2]=f;c[n>>2]=c[l>>2];l=o;c[l>>2]=0;c[l+4>>2]=0;if((c[m>>2]|0)<56){c[h>>2]=0;q=c[h>>2]|0;i=g;return q|0}else{m=bd((c[n>>2]|0)+40|0)|0;l=o;c[l>>2]=m;c[l+4>>2]=((m|0)<0)<<31>>31;m=o;oc(c[j>>2]|0,c[k>>2]|0,c[m>>2]|0,c[m+4>>2]|0,1e3,0)|0;m=bd((c[n>>2]|0)+52|0)|0;n=Me(m|0,((m|0)<0)<<31>>31|0,2,0)|0;c[p>>2]=n;Zc(c[j>>2]|0,c[k>>2]|0,c[p>>2]|0)|0;c[h>>2]=1;q=c[h>>2]|0;i=g;return q|0}return 0}function rd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0;f=i;i=i+32|0;g=f+8|0;h=f;j=f+24|0;k=f+16|0;l=h;c[l>>2]=a;c[l+4>>2]=b;c[j>>2]=d;c[f+20>>2]=e;c[k>>2]=c[(c[j>>2]|0)+504>>2];do if(!(c[(c[j>>2]|0)+504>>2]|0)){e=ye(12)|0;c[(c[j>>2]|0)+504>>2]=e;if(!(c[(c[j>>2]|0)+504>>2]|0)){e=g;c[e>>2]=-1;c[e+4>>2]=-1;break}else{c[k>>2]=c[(c[j>>2]|0)+504>>2];c[(c[k>>2]|0)+8>>2]=0;c[(c[k>>2]|0)+4>>2]=256;c[c[k>>2]>>2]=1;e=g;c[e>>2]=0;c[e+4>>2]=0;break}}else{e=c[k>>2]|0;if((c[c[k>>2]>>2]|0)<2)c[e>>2]=(c[e>>2]|0)+1;else c[e+8>>2]=1;e=h;d=c[e+4>>2]|0;if((d|0)>-1|(d|0)==-1&(c[e>>2]|0)>>>0>4294967295){e=h;d=c[e+4>>2]|0;b=g;c[b>>2]=c[e>>2];c[b+4>>2]=d;break}if(!(c[(c[k>>2]|0)+8>>2]|0)){d=g;c[d>>2]=0;c[d+4>>2]=0;break}d=(c[j>>2]|0)+488|0;b=c[d+4>>2]|0;if((b|0)>0|(b|0)==0&(c[d>>2]|0)>>>0>0){d=(c[j>>2]|0)+488|0;b=c[(c[k>>2]|0)+4>>2]|0;e=Me(c[d>>2]|0,c[d+4>>2]|0,b|0,((b|0)<0)<<31>>31|0)|0;b=g;c[b>>2]=e;c[b+4>>2]=C;break}else{b=g;c[b>>2]=-1;c[b+4>>2]=-1;break}}while(0);k=g;C=c[k+4>>2]|0;i=f;return c[k>>2]|0}function sd(b,e,f,g,h){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;j=i;i=i+48|0;k=j;l=j+16|0;m=j+4|0;n=j+8|0;o=j+32|0;p=j+12|0;q=j+24|0;r=j+20|0;s=j+40|0;t=j+28|0;c[l>>2]=b;c[m>>2]=e;c[n>>2]=f;c[o>>2]=g;c[j+36>>2]=h;c[p>>2]=c[n>>2];a[s>>0]=0;if((c[o>>2]|0)<64){c[k>>2]=0;u=c[k>>2]|0;i=j;return u|0}else{c[q>>2]=bd((c[p>>2]|0)+24|0)|0;c[r>>2]=bd((c[p>>2]|0)+28|0)|0;a[s>>0]=a[(c[p>>2]|0)+15>>0]|0;c[t>>2]=d[(c[p>>2]|0)+11>>0];p=c[l>>2]|0;o=c[m>>2]|0;n=c[q>>2]|0;q=c[r>>2]|0;r=Ue(1e3,0,q|0,((q|0)<0)<<31>>31|0)|0;oc(p,o,n,((n|0)<0)<<31>>31,r,C)|0;mc(c[l>>2]|0,c[m>>2]|0,d[s>>0]|0)|0;Zc(c[l>>2]|0,c[m>>2]|0,c[t>>2]|0)|0;c[k>>2]=1;u=c[k>>2]|0;i=j;return u|0}return 0}function td(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;g=i;i=i+32|0;h=g+4|0;j=g+16|0;k=g+8|0;l=g+20|0;m=g+28|0;n=g+12|0;o=g+24|0;c[j>>2]=a;c[k>>2]=b;c[l>>2]=d;c[m>>2]=e;c[g>>2]=f;c[n>>2]=22;c[o>>2]=ye(48)|0;if(!(c[o>>2]|0)){c[h>>2]=-1;p=c[h>>2]|0;i=g;return p|0}if((rc(c[o>>2]|0,c[l>>2]|0,c[m>>2]|0)|0)==-1){ze(c[o>>2]|0);c[h>>2]=-1;p=c[h>>2]|0;i=g;return p|0}else{m=c[j>>2]|0;l=c[k>>2]|0;f=Ue(2,0,c[(c[o>>2]|0)+32>>2]|0,0)|0;e=C;d=Ue(1e3,0,c[(c[o>>2]|0)+36>>2]|0,0)|0;oc(m,l,f,e,d,C)|0;mc(c[j>>2]|0,c[k>>2]|0,c[n>>2]|0)|0;Zc(c[j>>2]|0,c[k>>2]|0,0)|0;ze(c[o>>2]|0);c[h>>2]=1;p=c[h>>2]|0;i=g;return p|0}return 0}function ud(b,e,f,g,h){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;j=i;i=i+32|0;k=j+24|0;l=j+16|0;m=j+20|0;n=j+12|0;o=j+4|0;p=j+28|0;c[l>>2]=b;c[m>>2]=e;c[n>>2]=f;c[o>>2]=g;c[j>>2]=h;c[j+8>>2]=c[n>>2];if((c[o>>2]|0)<19){c[k>>2]=0;q=c[k>>2]|0;i=j;return q|0}a[p>>0]=a[(c[n>>2]|0)+9>>0]|0;if((d[p>>0]|0|0)<1){c[k>>2]=0;q=c[k>>2]|0;i=j;return q|0}else{oc(c[l>>2]|0,c[m>>2]|0,48e3,0,1e3,0)|0;mc(c[l>>2]|0,c[m>>2]|0,0)|0;p=c[l>>2]|0;o=c[m>>2]|0;qc(p,o,(vd((c[n>>2]|0)+10|0)|0)&65535,0)|0;Zc(c[l>>2]|0,c[m>>2]|0,2)|0;c[k>>2]=1;q=c[k>>2]|0;i=j;return q|0}return 0}function vd(a){a=a|0;var b=0,e=0;b=i;i=i+16|0;e=b;c[e>>2]=a;i=b;return (d[c[e>>2]>>0]|0|(d[(c[e>>2]|0)+1>>0]|0)<<8)&65535|0}function wd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;f=i;i=i+48|0;g=f+16|0;h=f+24|0;j=f+36|0;k=f+40|0;l=f+32|0;m=f;n=f+8|0;o=h;c[o>>2]=a;c[o+4>>2]=b;c[j>>2]=d;c[k>>2]=e;c[l>>2]=c[(c[j>>2]|0)+504>>2];if(!(c[(c[j>>2]|0)+504>>2]|0)){e=ye(16)|0;c[(c[j>>2]|0)+504>>2]=e;if(!(c[(c[j>>2]|0)+504>>2]|0)){e=g;c[e>>2]=-1;c[e+4>>2]=-1;p=g;q=p;r=c[q>>2]|0;s=p+4|0;t=s;u=c[t>>2]|0;C=u;i=f;return r|0}else{c[l>>2]=c[(c[j>>2]|0)+504>>2];c[(c[l>>2]|0)+4>>2]=0;c[c[l>>2]>>2]=1;e=(c[l>>2]|0)+8|0;c[e>>2]=0;c[e+4>>2]=0;e=g;c[e>>2]=0;c[e+4>>2]=0;p=g;q=p;r=c[q>>2]|0;s=p+4|0;t=s;u=c[t>>2]|0;C=u;i=f;return r|0}}e=c[l>>2]|0;if((c[c[l>>2]>>2]|0)<2)c[e>>2]=(c[e>>2]|0)+1;else c[e+4>>2]=1;e=h;d=c[e+4>>2]|0;if((d|0)>-1|(d|0)==-1&(c[e>>2]|0)>>>0>4294967295){e=h;h=c[e+4>>2]|0;d=g;c[d>>2]=c[e>>2];c[d+4>>2]=h;p=g;q=p;r=c[q>>2]|0;s=p+4|0;t=s;u=c[t>>2]|0;C=u;i=f;return r|0}if(!(c[(c[l>>2]|0)+4>>2]|0)){h=g;c[h>>2]=0;c[h+4>>2]=0;p=g;q=p;r=c[q>>2]|0;s=p+4|0;t=s;u=c[t>>2]|0;C=u;i=f;return r|0}h=xd(c[k>>2]|0)|0;k=m;c[k>>2]=h;c[k+4>>2]=C;k=(c[j>>2]|0)+488|0;h=c[k+4>>2]|0;if(!((h|0)>0|(h|0)==0&(c[k>>2]|0)>>>0>0)){k=m;h=(c[l>>2]|0)+8|0;l=h;d=Me(c[l>>2]|0,c[l+4>>2]|0,c[k>>2]|0,c[k+4>>2]|0)|0;k=h;c[k>>2]=d;c[k+4>>2]=C;k=g;c[k>>2]=-1;c[k+4>>2]=-1;p=g;q=p;r=c[q>>2]|0;s=p+4|0;t=s;u=c[t>>2]|0;C=u;i=f;return r|0}k=(c[j>>2]|0)+488|0;d=m;m=Me(c[k>>2]|0,c[k+4>>2]|0,c[d>>2]|0,c[d+4>>2]|0)|0;d=n;c[d>>2]=m;c[d+4>>2]=C;d=n;m=c[d+4>>2]|0;k=(c[j>>2]|0)+496|0;h=c[k+4>>2]|0;if((m|0)>(h|0)|((m|0)==(h|0)?(c[d>>2]|0)>>>0>(c[k>>2]|0)>>>0:0)?(k=(c[j>>2]|0)+496|0,d=c[k+4>>2]|0,h=(c[j>>2]|0)+488|0,m=c[h+4>>2]|0,(d|0)>(m|0)|((d|0)==(m|0)?(c[k>>2]|0)>>>0>=(c[h>>2]|0)>>>0:0)):0){h=(c[j>>2]|0)+496|0;v=c[h>>2]|0;w=c[h+4>>2]|0}else{h=n;v=c[h>>2]|0;w=c[h+4>>2]|0}h=g;c[h>>2]=v;c[h+4>>2]=w;p=g;q=p;r=c[q>>2]|0;s=p+4|0;t=s;u=c[t>>2]|0;C=u;i=f;return r|0}function xd(b){b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;i=i+32|0;f=e;g=e+16|0;h=e+21|0;j=e+22|0;k=e+20|0;l=e+8|0;m=e+12|0;c[g>>2]=b;do if((c[(c[g>>2]|0)+4>>2]|0)>=1){a[h>>0]=a[c[c[g>>2]>>2]>>0]|0;a[j>>0]=(d[h>>0]|0)&3;c[l>>2]=c[1968+((d[h>>0]|0)>>3<<2)>>2];if((d[j>>0]|0|0)==3?(c[(c[g>>2]|0)+4>>2]|0)<2:0){b=f;c[b>>2]=0;c[b+4>>2]=0;break}b=d[j>>0]|0;if((b|0)==3)a[k>>0]=(d[(c[c[g>>2]>>2]|0)+1>>0]|0)&63;else if(!b)a[k>>0]=1;else if((b|0)==2|(b|0)==1)a[k>>0]=2;c[m>>2]=_(c[l>>2]|0,d[k>>0]|0)|0;if((c[m>>2]|0)>5760){b=f;c[b>>2]=0;c[b+4>>2]=0;break}else{b=c[m>>2]|0;n=f;c[n>>2]=b;c[n+4>>2]=((b|0)<0)<<31>>31;break}}else{b=f;c[b>>2]=0;c[b+4>>2]=0}while(0);m=f;C=c[m+4>>2]|0;i=e;return c[m>>2]|0}function yd(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;g=i;i=i+32|0;h=g+8|0;j=g+28|0;k=g+24|0;l=g+20|0;m=g+16|0;n=g;o=h;c[o>>2]=a;c[o+4>>2]=b;c[j>>2]=d;c[k>>2]=e;c[l>>2]=f;c[m>>2]=c[(c[j>>2]|0)+504>>2];j=h;f=c[j+4>>2]|0;e=(c[m>>2]|0)+8|0;d=c[e+4>>2]|0;b=h;h=c[b>>2]|0;o=c[b+4>>2]|0;if(!((f|0)>(d|0)|((f|0)==(d|0)?(c[j>>2]|0)>>>0>=(c[e>>2]|0)>>>0:0))){e=n;c[e>>2]=h;c[e+4>>2]=o;e=xd(c[k>>2]|0)|0;k=(c[m>>2]|0)+8|0;j=k;d=Ge(c[j>>2]|0,c[j+4>>2]|0,e|0,C|0)|0;e=k;c[e>>2]=d;c[e+4>>2]=C;p=n;q=p;r=c[q>>2]|0;s=p+4|0;t=s;u=c[t>>2]|0;C=u;i=g;return r|0}e=xd(c[l>>2]|0)|0;l=Ge(h|0,o|0,e|0,C|0)|0;e=n;c[e>>2]=l;c[e+4>>2]=C;e=n;l=c[e+4>>2]|0;o=(c[m>>2]|0)+8|0;h=c[o+4>>2]|0;if((l|0)<(h|0)|((l|0)==(h|0)?(c[e>>2]|0)>>>0<(c[o>>2]|0)>>>0:0)){o=(c[m>>2]|0)+8|0;e=c[o+4>>2]|0;h=n;c[h>>2]=c[o>>2];c[h+4>>2]=e}e=(c[m>>2]|0)+8|0;c[e>>2]=0;c[e+4>>2]=0;p=n;q=p;r=c[q>>2]|0;s=p+4|0;t=s;u=c[t>>2]|0;C=u;i=g;return r|0}function zd(a,b,e,f,g){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;h=i;i=i+48|0;j=h+28|0;k=h+16|0;l=h+4|0;m=h+8|0;n=h+32|0;o=h+12|0;p=h+24|0;q=h+20|0;c[k>>2]=a;c[l>>2]=b;c[m>>2]=e;c[n>>2]=f;c[h>>2]=g;c[o>>2]=c[m>>2];if((c[n>>2]|0)<26){c[j>>2]=0;r=c[j>>2]|0;i=h;return r|0}if((d[c[m>>2]>>0]|0|0)!=79){c[j>>2]=0;r=c[j>>2]|0;i=h;return r|0}if(ve((c[m>>2]|0)+1|0,2512,4)|0){c[j>>2]=0;r=c[j>>2]|0;i=h;return r|0}if((d[(c[m>>2]|0)+5>>0]|0|0)!=1){c[j>>2]=0;r=c[j>>2]|0;i=h;return r|0}if((d[(c[m>>2]|0)+6>>0]|0|0)!=1){c[j>>2]=0;r=c[j>>2]|0;i=h;return r|0}else{c[p>>2]=Yc((c[o>>2]|0)+18|0)|0;c[q>>2]=Yc((c[o>>2]|0)+22|0)|0;o=c[k>>2]|0;m=c[l>>2]|0;n=c[p>>2]|0;p=c[q>>2]|0;q=Ue(1e3,0,p|0,((p|0)<0)<<31>>31|0)|0;oc(o,m,n,((n|0)<0)<<31>>31,q,C)|0;mc(c[k>>2]|0,c[l>>2]|0,32)|0;Zc(c[k>>2]|0,c[l>>2]|0,1)|0;c[j>>2]=1;r=c[j>>2]|0;i=h;return r|0}return 0}function Ad(a,b,e,f){a=a|0;b=b|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,D=0,E=0;g=i;i=i+80|0;h=g+40|0;j=g+24|0;k=g+48|0;l=g+52|0;m=g+56|0;n=g+60|0;o=g+68|0;p=g+64|0;q=g+32|0;r=g;s=g+8|0;t=g+16|0;u=j;c[u>>2]=a;c[u+4>>2]=b;c[k>>2]=e;c[l>>2]=f;c[p>>2]=c[(c[k>>2]|0)+504>>2];if(!(c[(c[k>>2]|0)+504>>2]|0)){f=ye(8)|0;c[(c[k>>2]|0)+504>>2]=f;if(!(c[(c[k>>2]|0)+504>>2]|0)){f=h;c[f>>2]=-1;c[f+4>>2]=-1;v=h;w=v;x=c[w>>2]|0;y=v+4|0;z=y;A=c[z>>2]|0;C=A;i=g;return x|0}else{c[p>>2]=c[(c[k>>2]|0)+504>>2];c[(c[p>>2]|0)+4>>2]=0;c[c[p>>2]>>2]=1;f=h;c[f>>2]=0;c[f+4>>2]=0;v=h;w=v;x=c[w>>2]|0;y=v+4|0;z=y;A=c[z>>2]|0;C=A;i=g;return x|0}}if(!(c[(c[l>>2]|0)+4>>2]|0))B=1;else B=(d[c[c[l>>2]>>2]>>0]|0|0)==79;c[m>>2]=B&1;if((c[m>>2]|0)==0?(c[(c[l>>2]|0)+4>>2]|0)>0:0)D=((d[c[c[l>>2]>>2]>>0]|0)&1|0)==0;else D=0;c[n>>2]=D&1;if((c[m>>2]|0)==0?(c[(c[l>>2]|0)+4>>2]|0)>0:0)E=((d[c[c[l>>2]>>2]>>0]|0)>>4&1|0)!=0;else E=0;c[o>>2]=E&1;E=c[p>>2]|0;if(c[m>>2]|0)c[E>>2]=(c[E>>2]|0)+1;else c[E+4>>2]=1;E=j;l=c[E+4>>2]|0;if((l|0)>-1|(l|0)==-1&(c[E>>2]|0)>>>0>4294967295){E=j;j=c[E+4>>2]|0;l=h;c[l>>2]=c[E>>2];c[l+4>>2]=j;v=h;w=v;x=c[w>>2]|0;y=v+4|0;z=y;A=c[z>>2]|0;C=A;i=g;return x|0}if(!(c[(c[p>>2]|0)+4>>2]|0)){p=h;c[p>>2]=0;c[p+4>>2]=0;v=h;w=v;x=c[w>>2]|0;y=v+4|0;z=y;A=c[z>>2]|0;C=A;i=g;return x|0}p=(c[k>>2]|0)+488|0;j=c[p+4>>2]|0;if(!((j|0)>0|(j|0)==0&(c[p>>2]|0)>>>0>0)){p=h;c[p>>2]=-1;c[p+4>>2]=-1;v=h;w=v;x=c[w>>2]|0;y=v+4|0;z=y;A=c[z>>2]|0;C=A;i=g;return x|0}p=(c[k>>2]|0)+488|0;j=c[p>>2]|0;l=c[p+4>>2]|0;if(c[m>>2]|0){m=h;c[m>>2]=j;c[m+4>>2]=l;v=h;w=v;x=c[w>>2]|0;y=v+4|0;z=y;A=c[z>>2]|0;C=A;i=g;return x|0}m=Fe(j|0,l|0,32)|0;l=q;c[l>>2]=m;c[l+4>>2]=C;l=(c[k>>2]|0)+488|0;m=Fe(c[l>>2]|0,c[l+4>>2]|0,30)|0;l=r;c[l>>2]=m&3;c[l+4>>2]=0;l=(c[k>>2]|0)+488|0;k=Fe(c[l>>2]|0,c[l+4>>2]|0,3)|0;l=s;c[l>>2]=k&134217727;c[l+4>>2]=0;if(c[n>>2]|0){n=s;c[n>>2]=0;c[n+4>>2]=0}else{n=s;l=Me(c[n>>2]|0,c[n+4>>2]|0,1,0)|0;n=s;c[n>>2]=l;c[n+4>>2]=C}do if(!(c[o>>2]|0)){n=r;if((c[n>>2]|0)==3&(c[n+4>>2]|0)==0){n=r;c[n>>2]=0;c[n+4>>2]=0;break}else{n=r;l=Me(c[n>>2]|0,c[n+4>>2]|0,1,0)|0;n=r;c[n>>2]=l;c[n+4>>2]=C;break}}else{n=q;l=Me(c[n>>2]|0,c[n+4>>2]|0,1,0)|0;n=q;c[n>>2]=l;c[n+4>>2]=C;n=r;c[n>>2]=3;c[n+4>>2]=0}while(0);o=c[q>>2]|0;q=r;r=Ie(c[q>>2]|0,c[q+4>>2]|0,30)|0;q=o|C;o=s;s=Ie(c[o>>2]|0,c[o+4>>2]|0,3)|0;o=t;c[o>>2]=r|s;c[o+4>>2]=q|C;q=t;t=c[q+4>>2]|0;o=h;c[o>>2]=c[q>>2];c[o+4>>2]=t;v=h;w=v;x=c[w>>2]|0;y=v+4|0;z=y;A=c[z>>2]|0;C=A;i=g;return x|0}function Bd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0;e=i;i=i+16|0;f=e+12|0;g=e+8|0;h=e+4|0;j=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=d;c[j>>2]=c[(c[f>>2]|0)+(c[g>>2]<<2)>>2];c[(c[f>>2]|0)+(c[g>>2]<<2)>>2]=c[(c[f>>2]|0)+(c[h>>2]<<2)>>2];c[(c[f>>2]|0)+(c[h>>2]<<2)>>2]=c[j>>2];i=e;return}function Cd(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;g=i;i=i+32|0;h=g+8|0;j=g+28|0;k=g+24|0;l=g;m=g+16|0;c[j>>2]=a;c[k>>2]=b;b=l;c[b>>2]=d;c[b+4>>2]=e;c[g+20>>2]=f;c[m>>2]=sb(c[j>>2]|0,c[k>>2]|0)|0;if(!(c[m>>2]|0)){k=h;c[k>>2]=-1;c[k+4>>2]=-1;n=h;o=n;p=c[o>>2]|0;q=n+4|0;r=q;s=c[r>>2]|0;C=s;i=g;return p|0}k=l;j=c[k+4>>2]|0;f=(c[m>>2]|0)+392|0;e=c[f+4>>2]|0;if((j|0)<(e|0)|((j|0)==(e|0)?(c[k>>2]|0)>>>0<=(c[f>>2]|0)>>>0:0)){t=0;u=0}else{f=l;k=(c[m>>2]|0)+392|0;e=Ge(c[f>>2]|0,c[f+4>>2]|0,c[k>>2]|0,c[k+4>>2]|0)|0;t=e;u=C}e=l;c[e>>2]=t;c[e+4>>2]=u;u=(c[m>>2]|0)+384|0;e=l;l=Ue(c[u>>2]|0,c[u+4>>2]|0,c[e>>2]|0,c[e+4>>2]|0)|0;e=(c[m>>2]|0)+376|0;m=Se(l|0,C|0,c[e>>2]|0,c[e+4>>2]|0)|0;e=h;c[e>>2]=m;c[e+4>>2]=C;n=h;o=n;p=c[o>>2]|0;q=n+4|0;r=q;s=c[r>>2]|0;C=s;i=g;return p|0}function Dd(a,d,f,g,h){a=a|0;d=d|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;j=i;i=i+80|0;k=j+32|0;l=j+48|0;m=j+52|0;n=j+8|0;o=j+64|0;p=j+40|0;q=j;r=j+56|0;s=j+68|0;t=j+16|0;u=j+24|0;c[l>>2]=a;c[m>>2]=d;d=n;c[d>>2]=f;c[d+4>>2]=g;c[j+60>>2]=h;c[o>>2]=sb(c[l>>2]|0,c[m>>2]|0)|0;if(!(c[o>>2]|0)){m=k;c[m>>2]=-1;c[m+4>>2]=-1;v=k;w=v;x=c[w>>2]|0;y=v+4|0;z=y;A=c[z>>2]|0;C=A;i=j;return x|0}else{m=n;l=Fe(c[m>>2]|0,c[m+4>>2]|0,c[(c[o>>2]|0)+408>>2]|0)|0;m=p;c[m>>2]=l;c[m+4>>2]=C;m=n;n=c[m>>2]|0;l=c[m+4>>2]|0;m=p;h=Ie(c[m>>2]|0,c[m+4>>2]|0,c[(c[o>>2]|0)+408>>2]|0)|0;m=Ge(n|0,l|0,h|0,C|0)|0;h=q;c[h>>2]=m;c[h+4>>2]=C;h=p;p=q;m=Me(c[h>>2]|0,c[h+4>>2]|0,c[p>>2]|0,c[p+4>>2]|0)|0;p=Fe(m|0,C|0,9)|0;c[r>>2]=p;p=q;q=Fe(c[p>>2]|0,c[p+4>>2]|0,9)|0;b[s>>1]=q;q=Ge(c[r>>2]|0,0,e[s>>1]|0|0,0)|0;s=t;c[s>>2]=q;c[s+4>>2]=C;s=t;t=(c[o>>2]|0)+384|0;q=Ue(c[s>>2]|0,c[s+4>>2]|0,c[t>>2]|0,c[t+4>>2]|0)|0;t=(c[o>>2]|0)+376|0;o=Se(q|0,C|0,c[t>>2]|0,c[t+4>>2]|0)|0;t=u;c[t>>2]=o;c[t+4>>2]=C;t=u;u=c[t+4>>2]|0;o=k;c[o>>2]=c[t>>2];c[o+4>>2]=u;v=k;w=v;x=c[w>>2]|0;y=v+4|0;z=y;A=c[z>>2]|0;C=A;i=j;return x|0}return 0}function Ed(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;g=i;i=i+48|0;h=g+24|0;j=g+32|0;k=g+36|0;l=g+16|0;m=g+40|0;n=g;o=g+8|0;c[j>>2]=a;c[k>>2]=b;b=l;c[b>>2]=d;c[b+4>>2]=e;c[g+44>>2]=f;c[m>>2]=sb(c[j>>2]|0,c[k>>2]|0)|0;if(!(c[m>>2]|0)){k=h;c[k>>2]=-1;c[k+4>>2]=-1;p=h;q=p;r=c[q>>2]|0;s=p+4|0;t=s;u=c[t>>2]|0;C=u;i=g;return r|0}else{k=l;l=Fe(c[k>>2]|0,c[k+4>>2]|0,c[(c[m>>2]|0)+408>>2]|0)|0;k=n;c[k>>2]=l;c[k+4>>2]=C;k=n;n=(c[m>>2]|0)+384|0;l=Ue(c[k>>2]|0,c[k+4>>2]|0,c[n>>2]|0,c[n+4>>2]|0)|0;n=(c[m>>2]|0)+376|0;m=Se(l|0,C|0,c[n>>2]|0,c[n+4>>2]|0)|0;n=o;c[n>>2]=m;c[n+4>>2]=C;n=o;o=c[n+4>>2]|0;m=h;c[m>>2]=c[n>>2];c[m+4>>2]=o;p=h;q=p;r=c[q>>2]|0;s=p+4|0;t=s;u=c[t>>2]|0;C=u;i=g;return r|0}return 0}function Fd(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;g=i;i=i+64|0;h=g+32|0;j=g+40|0;k=g+44|0;l=g;m=g+52|0;n=g+24|0;o=g+8|0;p=g+16|0;c[j>>2]=a;c[k>>2]=b;b=l;c[b>>2]=d;c[b+4>>2]=e;c[g+48>>2]=f;c[m>>2]=sb(c[j>>2]|0,c[k>>2]|0)|0;if(!(c[m>>2]|0)){k=h;c[k>>2]=-1;c[k+4>>2]=-1;q=h;r=q;s=c[r>>2]|0;t=q+4|0;u=t;v=c[u>>2]|0;C=v;i=g;return s|0}k=l;j=Fe(c[k>>2]|0,c[k+4>>2]|0,c[(c[m>>2]|0)+408>>2]|0)|0;k=n;c[k>>2]=j;c[k+4>>2]=C;k=l;j=c[k>>2]|0;f=c[k+4>>2]|0;k=n;e=Ie(c[k>>2]|0,c[k+4>>2]|0,c[(c[m>>2]|0)+408>>2]|0)|0;k=Ge(j|0,f|0,e|0,C|0)|0;e=o;c[e>>2]=k;c[e+4>>2]=C;e=n;n=o;o=Me(c[e>>2]|0,c[e+4>>2]|0,c[n>>2]|0,c[n+4>>2]|0)|0;n=l;c[n>>2]=o;c[n+4>>2]=C;n=l;o=c[n+4>>2]|0;if((o|0)>0|(o|0)==0&(c[n>>2]|0)>>>0>0){n=(c[m>>2]|0)+392|0;o=l;e=Ge(c[o>>2]|0,c[o+4>>2]|0,c[n>>2]|0,c[n+4>>2]|0)|0;n=l;c[n>>2]=e;c[n+4>>2]=C}n=l;l=(c[m>>2]|0)+384|0;e=Ue(c[n>>2]|0,c[n+4>>2]|0,c[l>>2]|0,c[l+4>>2]|0)|0;l=(c[m>>2]|0)+376|0;m=Se(e|0,C|0,c[l>>2]|0,c[l+4>>2]|0)|0;l=p;c[l>>2]=m;c[l+4>>2]=C;l=p;p=c[l+4>>2]|0;m=h;c[m>>2]=c[l>>2];c[m+4>>2]=p;q=h;r=q;s=c[r>>2]|0;t=q+4|0;u=t;v=c[u>>2]|0;C=v;i=g;return s|0}function Gd(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e+4|0;k=e;c[g>>2]=a;c[h>>2]=b;c[k>>2]=0;while(1){if((c[h>>2]|0)<=0){l=9;break}if((c[(c[g>>2]|0)+4>>2]|0)>>>0>=(c[(c[g>>2]|0)+8>>2]|0)>>>0){l=9;break}b=(c[(c[g>>2]|0)+12>>2]|0)-(c[h>>2]|0)|0;c[j>>2]=b;m=d[c[(c[g>>2]|0)+4>>2]>>0]|0;if((b|0)>=0)break;c[k>>2]=c[k>>2]|(m&c[2096+(c[(c[g>>2]|0)+12>>2]<<2)>>2])<<0-(c[j>>2]|0);c[h>>2]=(c[h>>2]|0)-(c[(c[g>>2]|0)+12>>2]|0);b=(c[g>>2]|0)+4|0;c[b>>2]=(c[b>>2]|0)+1;c[(c[g>>2]|0)+12>>2]=8}if((l|0)==9){c[f>>2]=c[k>>2];n=c[f>>2]|0;i=e;return n|0}c[k>>2]=c[k>>2]|m>>c[j>>2]&c[2096+(c[h>>2]<<2)>>2];j=(c[g>>2]|0)+12|0;c[j>>2]=(c[j>>2]|0)-(c[h>>2]|0);if(!(c[(c[g>>2]|0)+12>>2]|0)){h=(c[g>>2]|0)+4|0;c[h>>2]=(c[h>>2]|0)+1;c[(c[g>>2]|0)+12>>2]=8}c[f>>2]=c[k>>2];n=c[f>>2]|0;i=e;return n|0}function Hd(){var a=0,d=0,e=0,f=0,g=0;a=i;i=i+16|0;d=a+4|0;e=a;c[e>>2]=0;c[e>>2]=Ae(1,136)|0;if(!(c[e>>2]|0)){c[d>>2]=0;f=c[d>>2]|0;i=a;return f|0}g=Sd()|0;c[(c[e>>2]|0)+112>>2]=g;g=c[e>>2]|0;if(!(c[(c[e>>2]|0)+112>>2]|0)){ze(g);c[d>>2]=0;f=c[d>>2]|0;i=a;return f|0}else{b[g+116>>1]=0;b[(c[e>>2]|0)+118>>1]=0;c[(c[e>>2]|0)+120>>2]=0;g=(c[e>>2]|0)+128|0;c[g>>2]=0;c[g+4>>2]=0;c[d>>2]=c[e>>2];f=c[d>>2]|0;i=a;return f|0}return 0}function Id(a){a=a|0;var b=0,d=0,e=0,f=0;b=i;i=i+16|0;d=b+4|0;e=b;c[e>>2]=a;if(!(c[e>>2]|0)){c[d>>2]=-2;f=c[d>>2]|0;i=b;return f|0}else{Td(c[(c[e>>2]|0)+112>>2]|0);ze(c[e>>2]|0);c[d>>2]=0;f=c[d>>2]|0;i=b;return f|0}return 0}function Jd(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;i=i+16|0;f=e+12|0;g=e+8|0;h=e+4|0;j=e;c[g>>2]=a;c[h>>2]=d;c[j>>2]=-1;if(!(c[g>>2]|0)){c[f>>2]=-2;k=c[f>>2]|0;i=e;return k|0}if(!(c[h>>2]|0)){c[f>>2]=-13;k=c[f>>2]|0;i=e;return k|0}if(c[(c[h>>2]|0)+12>>2]|0){if((c[(c[g>>2]|0)+120>>2]|0)!=1){c[f>>2]=-1;k=c[f>>2]|0;i=e;return k|0}b[(c[g>>2]|0)+118>>1]=1;c[(c[g>>2]|0)+120>>2]=2;if(c[(c[h>>2]|0)+4>>2]|0){c[f>>2]=-6;k=c[f>>2]|0;i=e;return k|0}else{c[f>>2]=0;k=c[f>>2]|0;i=e;return k|0}}do if(!(ve(c[c[h>>2]>>2]|0,2520,8)|0)){c[j>>2]=Xd(c[g>>2]|0,c[h>>2]|0)|0;if(c[j>>2]|0){if(c[(c[h>>2]|0)+8>>2]|0){if(c[(c[g>>2]|0)+120>>2]|0)c[j>>2]=-14}else c[j>>2]=-12;c[(c[g>>2]|0)+120>>2]=1}}else{if(!(ve(c[c[h>>2]>>2]|0,2536,8)|0)){c[j>>2]=Yd(c[g>>2]|0,c[h>>2]|0)|0;if(!(c[j>>2]|0))break;if((c[(c[g>>2]|0)+120>>2]|0)==1)break;c[j>>2]=-14;break}if(ve(c[c[h>>2]>>2]|0,2552,6)|0){c[j>>2]=-1;break}b[(c[g>>2]|0)+116>>1]=1;c[j>>2]=Zd(c[g>>2]|0,c[h>>2]|0)|0;if((c[j>>2]|0)!=0?(c[(c[g>>2]|0)+120>>2]|0)!=1:0)c[j>>2]=-14}while(0);c[f>>2]=c[j>>2];k=c[f>>2]|0;i=e;return k|0}function Kd(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;i=i+16|0;f=e+12|0;g=e+8|0;h=e+4|0;j=e;c[g>>2]=a;c[h>>2]=d;c[j>>2]=-1;d=_d(c[g>>2]|0,c[h>>2]|0)|0;c[j>>2]=d;if((d|0)<0){c[f>>2]=c[j>>2];k=c[f>>2]|0;i=e;return k|0}else{b[c[h>>2]>>1]=b[c[g>>2]>>1]|0;c[f>>2]=0;k=c[f>>2]|0;i=e;return k|0}return 0}function Ld(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;i=i+16|0;f=e+12|0;g=e+8|0;h=e+4|0;j=e;c[g>>2]=a;c[h>>2]=d;c[j>>2]=-1;d=_d(c[g>>2]|0,c[h>>2]|0)|0;c[j>>2]=d;if((d|0)<0){c[f>>2]=c[j>>2];k=c[f>>2]|0;i=e;return k|0}else{b[c[h>>2]>>1]=b[(c[g>>2]|0)+2>>1]|0;c[f>>2]=0;k=c[f>>2]|0;i=e;return k|0}return 0}function Md(a,b){a=a|0;b=b|0;var d=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;i=i+32|0;f=d+16|0;g=d+12|0;h=d+8|0;j=d+4|0;k=d;c[g>>2]=a;c[h>>2]=b;c[j>>2]=-1;c[k>>2]=0;b=_d(c[g>>2]|0,c[h>>2]|0)|0;c[j>>2]=b;if((b|0)<0){c[f>>2]=c[j>>2];l=c[f>>2]|0;i=d;return l|0}c[k>>2]=(e[c[g>>2]>>1]|0)<<16|(e[(c[g>>2]|0)+2>>1]|0);if((c[k>>2]|0)>>>0<196610){c[f>>2]=-1;l=c[f>>2]|0;i=d;return l|0}else{k=(c[g>>2]|0)+96|0;g=c[k+4>>2]|0;j=c[h>>2]|0;c[j>>2]=c[k>>2];c[j+4>>2]=g;c[f>>2]=0;l=c[f>>2]|0;i=d;return l|0}return 0}function Nd(a,d,f,g,h,j){a=a|0;d=d|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;k=i;i=i+64|0;l=k+44|0;m=k+28|0;n=k+16|0;o=k+20|0;p=k+8|0;q=k+48|0;r=k+24|0;s=k+36|0;t=k+40|0;u=k;v=k+32|0;c[m>>2]=a;c[n>>2]=d;c[o>>2]=f;f=p;c[f>>2]=g;c[f+4>>2]=h;c[q>>2]=j;c[r>>2]=0;c[s>>2]=-1;c[t>>2]=0;j=u;c[j>>2]=-1;c[j+4>>2]=2147483647;j=_d(c[m>>2]|0,c[q>>2]|0)|0;c[s>>2]=j;if((j|0)<0){c[l>>2]=c[s>>2];w=c[l>>2]|0;i=k;return w|0}if(!(b[(c[m>>2]|0)+116>>1]|0)){c[l>>2]=-19;w=c[l>>2]|0;i=k;return w|0}if((c[n>>2]|0)==0|(c[o>>2]|0)==0){c[l>>2]=-1;w=c[l>>2]|0;i=k;return w|0}do if((e[c[m>>2]>>1]|0)==3){s=(c[m>>2]|0)+80|0;j=c[s+4>>2]|0;h=p;f=c[h+4>>2]|0;if(!((j|0)<(f|0)|((j|0)==(f|0)?(c[s>>2]|0)>>>0<(c[h>>2]|0)>>>0:0))?(h=p,s=c[h+4>>2]|0,f=(c[m>>2]|0)+64|0,j=c[f+4>>2]|0,!((s|0)<(j|0)|((s|0)==(j|0)?(c[h>>2]|0)>>>0<(c[f>>2]|0)>>>0:0))):0)break;c[l>>2]=-17;w=c[l>>2]|0;i=k;return w|0}while(0);c[t>>2]=0;while(1){if((c[t>>2]|0)>>>0>=(c[o>>2]|0)>>>0){x=23;break}c[v>>2]=0;f=Wd(c[(c[m>>2]|0)+112>>2]|0,c[(c[n>>2]|0)+(c[t>>2]<<2)>>2]|0)|0;c[r>>2]=f;if(!f){x=14;break}if((e[c[m>>2]>>1]|0)==4){f=(c[r>>2]|0)+32|0;h=c[f+4>>2]|0;j=p;s=c[j+4>>2]|0;if((h|0)<(s|0)|((h|0)==(s|0)?(c[f>>2]|0)>>>0<(c[j>>2]|0)>>>0:0)){x=18;break}j=p;f=c[j+4>>2]|0;s=(c[r>>2]|0)+24|0;h=c[s+4>>2]|0;if((f|0)<(h|0)|((f|0)==(h|0)?(c[j>>2]|0)>>>0<(c[s>>2]|0)>>>0:0)){x=18;break}}s=p;c[v>>2]=$d(c[r>>2]|0,c[s>>2]|0,c[s+4>>2]|0)|0;if((c[v>>2]|0)!=0?(s=c[v>>2]|0,j=c[s+4>>2]|0,h=u,f=c[h+4>>2]|0,!((j|0)>(f|0)|((j|0)==(f|0)?(c[s>>2]|0)>>>0>(c[h>>2]|0)>>>0:0))):0){h=c[v>>2]|0;s=c[h+4>>2]|0;f=u;c[f>>2]=c[h>>2];c[f+4>>2]=s}c[t>>2]=(c[t>>2]|0)+1}if((x|0)==14){c[l>>2]=-8;w=c[l>>2]|0;i=k;return w|0}else if((x|0)==18){c[l>>2]=-17;w=c[l>>2]|0;i=k;return w|0}else if((x|0)==23){x=u;if((c[x>>2]|0)==-1?(c[x+4>>2]|0)==2147483647:0){c[l>>2]=-1;w=c[l>>2]|0;i=k;return w|0}else{x=u;u=c[x+4>>2]|0;t=c[q>>2]|0;c[t>>2]=c[x>>2];c[t+4>>2]=u;c[l>>2]=0;w=c[l>>2]|0;i=k;return w|0}}return 0}function Od(a,b,d){a=a|0;b=b|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;f=i;i=i+32|0;g=f+20|0;h=f+16|0;j=f+12|0;k=f+8|0;l=f+4|0;m=f;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=-1;d=_d(c[h>>2]|0,c[k>>2]|0)|0;c[l>>2]=d;if((d|0)<0){c[g>>2]=c[l>>2];n=c[g>>2]|0;i=f;return n|0}do if((e[c[h>>2]>>1]|0|0)<4){l=(c[h>>2]|0)+64|0;d=c[l+4>>2]|0;b=c[k>>2]|0;c[b>>2]=c[l>>2];c[b+4>>2]=d}else{c[m>>2]=0;d=Wd(c[(c[h>>2]|0)+112>>2]|0,c[j>>2]|0)|0;c[m>>2]=d;if(d){d=(c[m>>2]|0)+24|0;b=c[d+4>>2]|0;l=c[k>>2]|0;c[l>>2]=c[d>>2];c[l+4>>2]=b;break}c[g>>2]=-8;n=c[g>>2]|0;i=f;return n|0}while(0);c[g>>2]=0;n=c[g>>2]|0;i=f;return n|0}function Pd(a,b,d){a=a|0;b=b|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;f=i;i=i+32|0;g=f+20|0;h=f+16|0;j=f+12|0;k=f+8|0;l=f+4|0;m=f;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=-1;d=_d(c[h>>2]|0,c[k>>2]|0)|0;c[l>>2]=d;if((d|0)<0){c[g>>2]=c[l>>2];n=c[g>>2]|0;i=f;return n|0}do if((e[c[h>>2]>>1]|0|0)<4){l=(c[h>>2]|0)+72|0;d=c[l+4>>2]|0;b=c[k>>2]|0;c[b>>2]=c[l>>2];c[b+4>>2]=d}else{c[m>>2]=0;d=Wd(c[(c[h>>2]|0)+112>>2]|0,c[j>>2]|0)|0;c[m>>2]=d;if(d){d=(c[m>>2]|0)+16|0;b=c[d+4>>2]|0;l=c[k>>2]|0;c[l>>2]=c[d>>2];c[l+4>>2]=b;break}c[g>>2]=-8;n=c[g>>2]|0;i=f;return n|0}while(0);c[g>>2]=0;n=c[g>>2]|0;i=f;return n|0}function Qd(a,b,d){a=a|0;b=b|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;f=i;i=i+32|0;g=f+20|0;h=f+16|0;j=f+12|0;k=f+8|0;l=f+4|0;m=f;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=-1;d=_d(c[h>>2]|0,c[k>>2]|0)|0;c[l>>2]=d;if((d|0)<0){c[g>>2]=c[l>>2];n=c[g>>2]|0;i=f;return n|0}do if((e[c[h>>2]>>1]|0|0)<4){l=(c[h>>2]|0)+80|0;d=c[l+4>>2]|0;b=c[k>>2]|0;c[b>>2]=c[l>>2];c[b+4>>2]=d}else{c[m>>2]=0;d=Wd(c[(c[h>>2]|0)+112>>2]|0,c[j>>2]|0)|0;c[m>>2]=d;if(d){d=(c[m>>2]|0)+32|0;b=c[d+4>>2]|0;l=c[k>>2]|0;c[l>>2]=c[d>>2];c[l+4>>2]=b;break}c[g>>2]=-8;n=c[g>>2]|0;i=f;return n|0}while(0);c[g>>2]=0;n=c[g>>2]|0;i=f;return n|0}function Rd(a,b,d){a=a|0;b=b|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0;f=i;i=i+32|0;g=f+20|0;h=f+16|0;j=f+12|0;k=f+8|0;l=f+4|0;m=f;c[h>>2]=a;c[j>>2]=b;c[k>>2]=d;c[l>>2]=-1;d=_d(c[h>>2]|0,c[k>>2]|0)|0;c[l>>2]=d;if((d|0)<0){c[g>>2]=c[l>>2];n=c[g>>2]|0;i=f;return n|0}do if((e[c[h>>2]>>1]|0|0)<4){l=(c[h>>2]|0)+88|0;d=c[l+4>>2]|0;b=c[k>>2]|0;c[b>>2]=c[l>>2];c[b+4>>2]=d}else{c[m>>2]=0;d=Wd(c[(c[h>>2]|0)+112>>2]|0,c[j>>2]|0)|0;c[m>>2]=d;if(d){d=(c[m>>2]|0)+16|0;b=c[d+4>>2]|0;l=c[k>>2]|0;c[l>>2]=c[d>>2];c[l+4>>2]=b;break}c[g>>2]=-8;n=c[g>>2]|0;i=f;return n|0}while(0);c[g>>2]=0;n=c[g>>2]|0;i=f;return n|0}function Sd(){var a=0,b=0,d=0;a=i;i=i+16|0;b=a+4|0;d=a;c[d>>2]=Ae(1,8)|0;if(!(c[d>>2]|0))c[b>>2]=0;else c[b>>2]=c[d>>2];i=a;return c[b>>2]|0}function Td(a){a=a|0;var b=0,d=0,e=0;b=i;i=i+16|0;d=b+4|0;e=b;c[d>>2]=a;c[e>>2]=0;if(!(c[d>>2]|0)){i=b;return}if(c[(c[d>>2]|0)+4>>2]|0){c[e>>2]=0;while(1){if((c[e>>2]|0)>>>0>=(c[c[d>>2]>>2]|0)>>>0)break;if(c[(c[(c[d>>2]|0)+4>>2]|0)+((c[e>>2]|0)*12|0)+4>>2]|0){if(c[(c[(c[(c[d>>2]|0)+4>>2]|0)+((c[e>>2]|0)*12|0)+4>>2]|0)+48>>2]|0)ze(c[(c[(c[(c[d>>2]|0)+4>>2]|0)+((c[e>>2]|0)*12|0)+4>>2]|0)+48>>2]|0);ze(c[(c[(c[d>>2]|0)+4>>2]|0)+((c[e>>2]|0)*12|0)+4>>2]|0)}if(c[(c[(c[d>>2]|0)+4>>2]|0)+((c[e>>2]|0)*12|0)+8>>2]|0){if(c[(c[(c[(c[d>>2]|0)+4>>2]|0)+((c[e>>2]|0)*12|0)+8>>2]|0)+40>>2]|0)ze(c[(c[(c[(c[d>>2]|0)+4>>2]|0)+((c[e>>2]|0)*12|0)+8>>2]|0)+40>>2]|0);ze(c[(c[(c[d>>2]|0)+4>>2]|0)+((c[e>>2]|0)*12|0)+8>>2]|0)}c[e>>2]=(c[e>>2]|0)+1}ze(c[(c[d>>2]|0)+4>>2]|0)}ze(c[d>>2]|0);i=b;return}function Ud(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e+4|0;k=e;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[k>>2]=0;do if(c[g>>2]|0){if(!(c[h>>2]|0)){c[f>>2]=-1;break}c[k>>2]=be(c[g>>2]|0,c[j>>2]|0)|0;if(!(c[k>>2]|0)){c[f>>2]=-4;break}if(c[(c[k>>2]|0)+4>>2]|0){c[f>>2]=-1;break}else{c[(c[k>>2]|0)+4>>2]=c[h>>2];c[f>>2]=1;break}}else c[f>>2]=-1;while(0);i=e;return c[f>>2]|0}function Vd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e+4|0;k=e;c[g>>2]=a;c[h>>2]=b;c[j>>2]=d;c[k>>2]=0;do if(c[g>>2]|0){if(!(c[h>>2]|0)){c[f>>2]=-1;break}c[k>>2]=be(c[g>>2]|0,c[j>>2]|0)|0;if(!(c[k>>2]|0)){c[f>>2]=-4;break}if(c[(c[k>>2]|0)+8>>2]|0){c[f>>2]=-1;break}else{c[(c[k>>2]|0)+8>>2]=c[h>>2];c[f>>2]=1;break}}else c[f>>2]=-1;while(0);i=e;return c[f>>2]|0}function Wd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[f>>2]=a;c[g>>2]=b;c[h>>2]=0;if(!(c[f>>2]|0)){c[e>>2]=0;j=c[e>>2]|0;i=d;return j|0}c[h>>2]=ae(c[f>>2]|0,c[g>>2]|0)|0;if(!(c[h>>2]|0))k=0;else k=c[(c[h>>2]|0)+8>>2]|0;c[e>>2]=k;j=c[e>>2]|0;i=d;return j|0}function Xd(b,d){b=b|0;d=d|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+32|0;g=f+16|0;h=f+12|0;j=f+8|0;k=f+4|0;l=f;c[h>>2]=b;c[j>>2]=d;c[l>>2]=0;if(!(c[h>>2]|0)){c[g>>2]=-2;m=c[g>>2]|0;i=f;return m|0}if((c[j>>2]|0)!=0?(c[c[j>>2]>>2]|0)!=0:0){c[l>>2]=(c[c[j>>2]>>2]|0)+8;c[l>>2]=ce(c[l>>2]|0,c[h>>2]|0)|0;c[l>>2]=ce(c[l>>2]|0,(c[h>>2]|0)+2|0)|0;c[k>>2]=(e[c[h>>2]>>1]|0)<<16|(e[(c[h>>2]|0)+2>>1]|0);if((c[k>>2]|0)>>>0>262144){c[g>>2]=-11;m=c[g>>2]|0;i=f;return m|0}if((c[k>>2]|0)==262144?(c[(c[j>>2]|0)+4>>2]|0)!=80:0){c[g>>2]=-18;m=c[g>>2]|0;i=f;return m|0}if((e[c[h>>2]>>1]|0|0)==3){if((e[(c[h>>2]|0)+2>>1]|0|0)>=2?(c[(c[j>>2]|0)+4>>2]|0)!=112:0){c[g>>2]=-18;m=c[g>>2]|0;i=f;return m|0}if((e[(c[h>>2]|0)+2>>1]|0|0)==0?(c[(c[j>>2]|0)+4>>2]|0)!=64:0){c[g>>2]=-18;m=c[g>>2]|0;i=f;return m|0}}c[l>>2]=de(c[l>>2]|0,(c[h>>2]|0)+8|0)|0;c[l>>2]=de(c[l>>2]|0,(c[h>>2]|0)+16|0)|0;c[l>>2]=de(c[l>>2]|0,(c[h>>2]|0)+24|0)|0;c[l>>2]=de(c[l>>2]|0,(c[h>>2]|0)+32|0)|0;j=(c[h>>2]|0)+40|0;d=c[l>>2]|0;b=j+20|0;do{a[j>>0]=a[d>>0]|0;j=j+1|0;d=d+1|0}while((j|0)<(b|0));if((c[k>>2]|0)>>>0>=196610){c[l>>2]=(c[l>>2]|0)+20;if((e[c[h>>2]>>1]|0|0)==3){c[l>>2]=de(c[l>>2]|0,(c[h>>2]|0)+64|0)|0;c[l>>2]=de(c[l>>2]|0,(c[h>>2]|0)+72|0)|0;c[l>>2]=de(c[l>>2]|0,(c[h>>2]|0)+80|0)|0;c[l>>2]=de(c[l>>2]|0,(c[h>>2]|0)+88|0)|0}c[l>>2]=de(c[l>>2]|0,(c[h>>2]|0)+96|0)|0;de(c[l>>2]|0,(c[h>>2]|0)+104|0)|0}c[g>>2]=1;m=c[g>>2]|0;i=f;return m|0}c[g>>2]=-13;m=c[g>>2]|0;i=f;return m|0}function Yd(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;e=i;i=i+32|0;f=e+20|0;g=e+16|0;h=e+12|0;j=e+8|0;k=e+4|0;l=e;c[g>>2]=b;c[h>>2]=d;c[j>>2]=0;c[k>>2]=-1;c[l>>2]=0;if(!(c[g>>2]|0)){c[f>>2]=-2;m=c[f>>2]|0;i=e;return m|0}if((c[h>>2]|0)!=0?(c[c[h>>2]>>2]|0)!=0:0){if((c[(c[h>>2]|0)+4>>2]|0)<52){c[f>>2]=-7;m=c[f>>2]|0;i=e;return m|0}c[j>>2]=Ae(1,56)|0;if(!(c[j>>2]|0)){c[f>>2]=-4;m=c[f>>2]|0;i=e;return m|0}c[l>>2]=(c[c[h>>2]>>2]|0)+8;c[l>>2]=ee(c[l>>2]|0,c[j>>2]|0)|0;c[l>>2]=fe(c[l>>2]|0,(c[j>>2]|0)+4|0)|0;c[l>>2]=ee(c[l>>2]|0,(c[j>>2]|0)+8|0)|0;c[l>>2]=de(c[l>>2]|0,(c[j>>2]|0)+16|0)|0;c[l>>2]=de(c[l>>2]|0,(c[j>>2]|0)+24|0)|0;c[l>>2]=de(c[l>>2]|0,(c[j>>2]|0)+32|0)|0;c[l>>2]=ee(c[l>>2]|0,(c[j>>2]|0)+40|0)|0;a[(c[j>>2]|0)+44>>0]=a[c[l>>2]>>0]|0;l=Ae((c[(c[h>>2]|0)+4>>2]|0)-52|0,1)|0;c[(c[j>>2]|0)+48>>2]=l;l=c[j>>2]|0;if(!(c[(c[j>>2]|0)+48>>2]|0)){ze(l);c[f>>2]=-4;m=c[f>>2]|0;i=e;return m|0}Ke(c[l+48>>2]|0,(c[c[h>>2]>>2]|0)+52|0,(c[(c[h>>2]|0)+4>>2]|0)-52|0)|0;c[k>>2]=Ud(c[(c[g>>2]|0)+112>>2]|0,c[j>>2]|0,c[(c[j>>2]|0)+4>>2]|0)|0;if((c[k>>2]|0)<0)ze(c[j>>2]|0);c[f>>2]=c[k>>2];m=c[f>>2]|0;i=e;return m|0}c[f>>2]=-13;m=c[f>>2]|0;i=e;return m|0}function Zd(a,b){a=a|0;b=b|0;var d=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;d=i;i=i+80|0;f=d+72|0;g=d+56|0;h=d+60|0;j=d+16|0;k=d+8|0;l=d;m=d+48|0;n=d+76|0;o=d+40|0;p=d+68|0;q=d+64|0;r=d+24|0;s=d+32|0;c[g>>2]=a;c[h>>2]=b;b=j;c[b>>2]=0;c[b+4>>2]=0;b=k;c[b>>2]=0;c[b+4>>2]=0;b=l;c[b>>2]=0;c[b+4>>2]=0;b=m;c[b>>2]=1e3;c[b+4>>2]=0;c[n>>2]=0;b=o;c[b>>2]=-1;c[b+4>>2]=-1;c[p>>2]=0;c[q>>2]=-1;if(!(c[g>>2]|0)){c[f>>2]=-2;t=c[f>>2]|0;i=d;return t|0}if((c[h>>2]|0)!=0?(c[c[h>>2]>>2]|0)!=0:0){c[n>>2]=Ae(1,48)|0;if(!(c[n>>2]|0)){c[f>>2]=-4;t=c[f>>2]|0;i=d;return t|0}c[p>>2]=(c[c[h>>2]>>2]|0)+6;c[p>>2]=fe(c[p>>2]|0,c[n>>2]|0)|0;c[p>>2]=de(c[p>>2]|0,(c[n>>2]|0)+8|0)|0;c[p>>2]=de(c[p>>2]|0,(c[n>>2]|0)+16|0)|0;if(((e[c[g>>2]>>1]|0)<<16|(e[(c[g>>2]|0)+2>>1]|0)|0)==262144){c[p>>2]=de(c[p>>2]|0,(c[n>>2]|0)+24|0)|0;c[p>>2]=de(c[p>>2]|0,(c[n>>2]|0)+32|0)|0}b=(c[n>>2]|0)+16|0;do if((c[b>>2]|0)==0&(c[b+4>>2]|0)==0)c[q>>2]=-9;else{a=(c[n>>2]|0)+8|0;u=Ue(c[a>>2]|0,c[a+4>>2]|0,2,0)|0;a=Me(26,0,u|0,C|0)|0;u=o;c[u>>2]=a;c[u+4>>2]=C;u=o;a=c[u+4>>2]|0;v=c[(c[h>>2]|0)+4>>2]|0;w=((v|0)<0)<<31>>31;if((a|0)>(w|0)|((a|0)==(w|0)?(c[u>>2]|0)>>>0>v>>>0:0)){c[q>>2]=-10;break}v=Ae(c[(c[n>>2]|0)+8>>2]|0,16)|0;c[(c[n>>2]|0)+40>>2]=v;if(!(c[(c[n>>2]|0)+40>>2]|0)){c[q>>2]=-4;break}v=j;c[v>>2]=0;c[v+4>>2]=0;while(1){v=j;u=c[v+4>>2]|0;w=(c[n>>2]|0)+8|0;a=c[w+4>>2]|0;if(!((u|0)<(a|0)|((u|0)==(a|0)?(c[v>>2]|0)>>>0<(c[w>>2]|0)>>>0:0)))break;w=r;c[w>>2]=0;c[w+4>>2]=0;w=s;c[w>>2]=0;c[w+4>>2]=0;c[p>>2]=ge(c[p>>2]|0,r)|0;w=r;v=k;a=Me(c[v>>2]|0,c[v+4>>2]|0,c[w>>2]|0,c[w+4>>2]|0)|0;w=k;c[w>>2]=a;c[w+4>>2]=C;c[p>>2]=ge(c[p>>2]|0,s)|0;w=s;a=l;v=Me(c[a>>2]|0,c[a+4>>2]|0,c[w>>2]|0,c[w+4>>2]|0)|0;w=l;c[w>>2]=v;c[w+4>>2]=C;w=k;v=c[w+4>>2]|0;a=(c[(c[n>>2]|0)+40>>2]|0)+(c[j>>2]<<4)|0;c[a>>2]=c[w>>2];c[a+4>>2]=v;v=l;a=m;w=Ue(c[v>>2]|0,c[v+4>>2]|0,c[a>>2]|0,c[a+4>>2]|0)|0;a=(c[n>>2]|0)+16|0;v=Se(w|0,C|0,c[a>>2]|0,c[a+4>>2]|0)|0;a=(c[(c[n>>2]|0)+40>>2]|0)+(c[j>>2]<<4)+8|0;c[a>>2]=v;c[a+4>>2]=C;a=j;v=Me(c[a>>2]|0,c[a+4>>2]|0,1,0)|0;a=j;c[a>>2]=v;c[a+4>>2]=C}c[q>>2]=Vd(c[(c[g>>2]|0)+112>>2]|0,c[n>>2]|0,c[c[n>>2]>>2]|0)|0}while(0);if((c[q>>2]|0)<0)ze(c[n>>2]|0);c[f>>2]=c[q>>2];t=c[f>>2]|0;i=d;return t|0}c[f>>2]=-13;t=c[f>>2]|0;i=d;return t|0}function _d(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,h=0;e=i;i=i+16|0;f=e+8|0;g=e+4|0;h=e;c[g>>2]=a;c[h>>2]=d;do if(c[g>>2]|0){if(!(b[(c[g>>2]|0)+118>>1]|0)){c[f>>2]=-5;break}if(!(c[h>>2]|0)){c[f>>2]=-16;break}else{c[f>>2]=0;break}}else c[f>>2]=-2;while(0);i=e;return c[f>>2]|0}function $d(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;e=i;i=i+48|0;f=e+36|0;g=e+32|0;h=e+24|0;j=e+16|0;k=e+8|0;l=e;c[g>>2]=a;a=h;c[a>>2]=b;c[a+4>>2]=d;d=j;c[d>>2]=0;c[d+4>>2]=0;d=k;c[d>>2]=0;c[d+4>>2]=0;if(!(c[g>>2]|0)){c[f>>2]=0;m=c[f>>2]|0;i=e;return m|0}d=(c[g>>2]|0)+8|0;a=Ge(c[d>>2]|0,c[d+4>>2]|0,1,0)|0;d=k;c[d>>2]=a;c[d+4>>2]=C;while(1){d=k;a=c[d+4>>2]|0;b=j;n=c[b+4>>2]|0;if(!((a|0)>(n|0)|((a|0)==(n|0)?(c[d>>2]|0)>>>0>(c[b>>2]|0)>>>0:0)))break;b=j;d=k;n=Me(c[b>>2]|0,c[b+4>>2]|0,c[d>>2]|0,c[d+4>>2]|0)|0;d=Me(n|0,C|0,1,0)|0;n=Fe(d|0,C|0,1)|0;d=l;c[d>>2]=n;c[d+4>>2]=C;d=(c[(c[g>>2]|0)+40>>2]|0)+(c[l>>2]<<4)+8|0;n=h;b=l;o=c[b>>2]|0;p=c[b+4>>2]|0;if((c[d>>2]|0)==(c[n>>2]|0)?(c[d+4>>2]|0)==(c[n+4>>2]|0):0){q=6;break}n=(c[(c[g>>2]|0)+40>>2]|0)+(o<<4)+8|0;d=c[n+4>>2]|0;b=h;a=c[b+4>>2]|0;r=l;s=c[r>>2]|0;t=c[r+4>>2]|0;if((d|0)<(a|0)|((d|0)==(a|0)?(c[n>>2]|0)>>>0<(c[b>>2]|0)>>>0:0)){b=j;c[b>>2]=s;c[b+4>>2]=t;continue}else{b=Ge(s|0,t|0,1,0)|0;t=k;c[t>>2]=b;c[t+4>>2]=C;continue}}if((q|0)==6){q=j;c[q>>2]=o;c[q+4>>2]=p}c[f>>2]=(c[(c[g>>2]|0)+40>>2]|0)+(c[j>>2]<<4);m=c[f>>2]|0;i=e;return m|0}function ae(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[f>>2]=a;c[g>>2]=b;c[h>>2]=0;c[h>>2]=0;while(1){if((c[h>>2]|0)>>>0>=(c[c[f>>2]>>2]|0)>>>0){j=6;break}k=c[h>>2]|0;if((c[(c[(c[f>>2]|0)+4>>2]|0)+((c[h>>2]|0)*12|0)>>2]|0)==(c[g>>2]|0)){j=4;break}c[h>>2]=k+1}if((j|0)==4){c[e>>2]=(c[(c[f>>2]|0)+4>>2]|0)+(k*12|0);l=c[e>>2]|0;i=d;return l|0}else if((j|0)==6){c[e>>2]=0;l=c[e>>2]|0;i=d;return l|0}return 0}function be(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0;d=i;i=i+16|0;e=d+12|0;f=d+8|0;g=d+4|0;h=d;c[f>>2]=a;c[g>>2]=b;c[h>>2]=0;b=ae(c[f>>2]|0,c[g>>2]|0)|0;c[h>>2]=b;do if(!b){c[h>>2]=Be(c[(c[f>>2]|0)+4>>2]|0,((c[c[f>>2]>>2]|0)+1|0)*12|0)|0;if(c[h>>2]|0){c[(c[f>>2]|0)+4>>2]=c[h>>2];a=c[f>>2]|0;c[a>>2]=(c[a>>2]|0)+1;c[h>>2]=(c[(c[f>>2]|0)+4>>2]|0)+(((c[c[f>>2]>>2]|0)-1|0)*12|0);c[c[h>>2]>>2]=c[g>>2];c[(c[h>>2]|0)+4>>2]=0;c[(c[h>>2]|0)+8>>2]=0;break}c[e>>2]=0;j=c[e>>2]|0;i=d;return j|0}while(0);c[e>>2]=c[h>>2];j=c[e>>2]|0;i=d;return j|0}function ce(a,e){a=a|0;e=e|0;var f=0,g=0,h=0,j=0,k=0;f=i;i=i+16|0;g=f+8|0;h=f+4|0;j=f;c[h>>2]=a;c[j>>2]=e;if((c[h>>2]|0)==0|(c[j>>2]|0)==0){c[g>>2]=0;k=c[g>>2]|0;i=f;return k|0}else{b[c[j>>2]>>1]=d[c[h>>2]>>0]|0|(d[(c[h>>2]|0)+1>>0]|0)<<8;c[g>>2]=(c[h>>2]|0)+2;k=c[g>>2]|0;i=f;return k|0}return 0}function de(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0;d=i;i=i+32|0;e=d+16|0;f=d+12|0;g=d+8|0;h=d+4|0;j=d;c[f>>2]=a;c[g>>2]=b;c[h>>2]=-1;c[j>>2]=-1;if((c[f>>2]|0)==0|(c[g>>2]|0)==0){c[e>>2]=0;k=c[e>>2]|0;i=d;return k|0}else{c[f>>2]=ee(c[f>>2]|0,h)|0;c[f>>2]=fe(c[f>>2]|0,j)|0;b=c[j>>2]|0;j=Me(c[h>>2]|0,0,0,b|0)|0;b=c[g>>2]|0;c[b>>2]=j;c[b+4>>2]=C;c[e>>2]=c[f>>2];k=c[e>>2]|0;i=d;return k|0}return 0}function ee(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0;e=i;i=i+16|0;f=e+8|0;g=e+4|0;h=e;c[g>>2]=a;c[h>>2]=b;if((c[g>>2]|0)==0|(c[h>>2]|0)==0){c[f>>2]=0;j=c[f>>2]|0;i=e;return j|0}else{c[c[h>>2]>>2]=d[c[g>>2]>>0]|0|(d[(c[g>>2]|0)+1>>0]|0)<<8|(d[(c[g>>2]|0)+2>>0]|0)<<16|(d[(c[g>>2]|0)+3>>0]|0)<<24;c[f>>2]=(c[g>>2]|0)+4;j=c[f>>2]|0;i=e;return j|0}return 0}function fe(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0;e=i;i=i+16|0;f=e+8|0;g=e+4|0;h=e;c[g>>2]=a;c[h>>2]=b;if((c[g>>2]|0)==0|(c[h>>2]|0)==0){c[f>>2]=0;j=c[f>>2]|0;i=e;return j|0}else{c[c[h>>2]>>2]=d[c[g>>2]>>0]|0|(d[(c[g>>2]|0)+1>>0]|0)<<8|(d[(c[g>>2]|0)+2>>0]|0)<<16|(d[(c[g>>2]|0)+3>>0]|0)<<24;c[f>>2]=(c[g>>2]|0)+4;j=c[f>>2]|0;i=e;return j|0}return 0}function ge(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0;e=i;i=i+32|0;f=e+16|0;g=e+12|0;h=e+8|0;j=e;c[f>>2]=a;c[g>>2]=b;c[h>>2]=0;b=j;c[b>>2]=0;c[b+4>>2]=0;b=c[g>>2]|0;c[b>>2]=0;c[b+4>>2]=0;do{b=j;c[b>>2]=d[c[f>>2]>>0];c[b+4>>2]=0;b=Ie(c[j>>2]&127|0,0,c[h>>2]|0)|0;a=c[g>>2]|0;k=a;l=c[k+4>>2]|C;m=a;c[m>>2]=c[k>>2]|b;c[m+4>>2]=l;c[h>>2]=(c[h>>2]|0)+7;c[f>>2]=(c[f>>2]|0)+1}while(0!=0?1:(c[j>>2]&128|0)!=128);i=e;return c[f>>2]|0}function he(){var a=0;c[644]=0;a=ob(32)|0;c[646]=a;Gb(a,-1,8,0)|0;c[648]=Hd()|0;return}function ie(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=i;i=i+16|0;e=d+8|0;f=d;c[662]=1;do if((c[644]|0)==2){if((c[650]|0)!=0?(ua()|0)==0:0)break;if((c[652]|0)!=0?(Ja()|0)==0:0)break;c[662]=0}while(0);do if((b|0)>0){g=Mb(c[646]|0,a,b)|0;if((g|0)<0){c[f>>2]=g;za(2656,f|0)|0;break}if((g|0)<(b|0)){c[e>>2]=g;c[e+4>>2]=b;za(2688,e|0)|0}}while(0);i=d;return c[662]^1|0}function je(){Id(c[648]|0)|0;pb(c[646]|0)|0;return}function ke(){var a=0,b=0,d=0,e=0;a=i;i=i+16|0;b=a;d=b;c[d>>2]=-1;c[d+4>>2]=-1;if(!(c[654]|0)){e=-1;i=a;return e|0}Md(c[648]|0,b)|0;e=c[b>>2]|0;i=a;return e|0}function le(){var a=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0.0,m=0,n=0.0,o=0.0,p=0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0;a=i;i=i+48|0;d=a+42|0;e=a+40|0;f=a+32|0;g=a+24|0;h=a+16|0;j=a;k=a+8|0;if(!(c[654]|0)){l=-1.0;i=a;return +l}b[d>>1]=-1;b[e>>1]=-1;Kd(c[648]|0,d)|0;Ld(c[648]|0,e)|0;e=c[656]|0;if(!e)m=0;else{c[f>>2]=e;m=1}e=c[658]|0;if(!e)if(!m){n=-1.0;o=-1.0}else{p=1;q=7}else{c[f+(m<<2)>>2]=e;p=m+1|0;q=7}if((q|0)==7){r=-1.0;q=0;s=-1.0;while(1){m=g;c[m>>2]=-1;c[m+4>>2]=-1;m=h;c[m>>2]=-1;c[m+4>>2]=-1;m=j;c[m>>2]=-1;c[m+4>>2]=-1;m=k;c[m>>2]=-1;c[m+4>>2]=-1;m=c[f+(q<<2)>>2]|0;Od(c[648]|0,m,g)|0;Pd(c[648]|0,m,h)|0;Qd(c[648]|0,m,j)|0;Rd(c[648]|0,m,k)|0;m=g;e=h;t=(+((c[m>>2]|0)>>>0)+4294967296.0*+(c[m+4>>2]|0))/(+((c[e>>2]|0)>>>0)+4294967296.0*+(c[e+4>>2]|0));u=r==-1.0|t<r?t:r;e=j;m=k;t=(+((c[e>>2]|0)>>>0)+4294967296.0*+(c[e+4>>2]|0))/(+((c[m>>2]|0)>>>0)+4294967296.0*+(c[m+4>>2]|0));v=s==-1.0|t>s?t:s;q=q+1|0;if((q|0)==(p|0)){n=u;o=v;break}else{r=u;s=v}}}l=o-n;i=a;return +l}function me(){return c[654]|0}function ne(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0;b=i;i=i+16|0;d=b;e=b+8|0;f=d;c[f>>2]=-1;c[f+4>>2]=-1;if(!(c[654]|0)){g=-1;i=b;return g|0}f=c[656]|0;if(!f){h=c[658]|0;if(!h){j=e;k=0}else{c[e>>2]=h;j=e;k=1}}else{c[e>>2]=f;j=e;k=1}Nd(c[648]|0,j,k,a,((a|0)<0)<<31>>31,d)|0;g=c[d>>2]|0;i=b;return g|0}function oe(){Ob(c[646]|0)|0;Pb(c[646]|0,0,1)|0;return}function pe(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0;e=i;i=i+16|0;a=e+8|0;f=e;c[662]=0;g=c[644]|0;if(!g){if(!(c[b+8>>2]|0))if(!(c[660]|0)){c[644]=2;na(c[640]|0,c[642]|0);re(b,d);h=0;i=e;return h|0}else{c[644]=1;h=qe(b,d)|0;i=e;return h|0}j=Xb(c[646]|0,d)|0;if(!(c[656]|j)){c[650]=j;c[640]=2744;c[656]=d;xa(c[b>>2]|0,c[b+4>>2]|0,-1.0,-1.0);h=0;i=e;return h|0}k=(c[658]|0)==0;if((j|0)==1&k){c[652]=1;c[642]=2752;c[658]=d;ma(c[b>>2]|0,c[b+4>>2]|0,-1.0);h=0;i=e;return h|0}if((j|0)==13&k){c[652]=13;c[642]=2760;c[658]=d;ma(c[b>>2]|0,c[b+4>>2]|0,-1.0);h=0;i=e;return h|0}if(!((j|0)==6&(c[660]|0)==0)){h=0;i=e;return h|0}c[660]=d;j=Jd(c[648]|0,b)|0;if(!j){c[654]=1;h=0;i=e;return h|0}if((j|0)>0){h=0;i=e;return h|0}c[f>>2]=j;za(2768,f|0)|0;h=-1;i=e;return h|0}else if((g|0)==2){re(b,d);h=0;i=e;return h|0}else if((g|0)==1){h=qe(b,d)|0;i=e;return h|0}else{za(2808,a|0)|0;h=-1;i=e;return h|0}return 0}function qe(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0.0,k=0,l=0,m=0,n=0.0,o=0;d=i;i=i+32|0;e=d+16|0;f=d+8|0;g=d;h=qb(c[646]|0)|0;j=(+(h>>>0)+4294967296.0*+(C|0))/1.0e3;h=rb(c[646]|0)|0;k=C;l=nc(c[646]|0,b)|0;m=f;c[m>>2]=0;c[m+4>>2]=0;m=g;c[m>>2]=0;c[m+4>>2]=0;pc(c[646]|0,b,f,g)|0;m=Fe(h|0,k|0,l|0)|0;l=g;g=f;n=(+(m>>>0)+4294967296.0*+(C|0))*(+((c[l>>2]|0)>>>0)+4294967296.0*+(c[l+4>>2]|0))/(+((c[g>>2]|0)>>>0)+4294967296.0*+(c[g+4>>2]|0));do if((c[660]|0)==(b|0)){g=Jd(c[648]|0,a)|0;if((g|0)<0){c[e>>2]=g;za(2848,e|0)|0;o=-1;i=d;return o|0}else{if(!(c[a+12>>2]|0))break;c[654]=1;c[644]=2;na(c[640]|0,c[642]|0);break}}while(0);if((c[656]|0)==(b|0))xa(c[a>>2]|0,c[a+4>>2]|0,+j,+n);if((c[658]|0)!=(b|0)){o=0;i=d;return o|0}ma(c[a>>2]|0,c[a+4>>2]|0,+j);o=0;i=d;return o|0}function re(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0.0,j=0,k=0,l=0,m=0,n=0;d=i;i=i+16|0;e=d+8|0;f=d;g=qb(c[646]|0)|0;h=(+(g>>>0)+4294967296.0*+(C|0))/1.0e3;g=rb(c[646]|0)|0;j=C;k=nc(c[646]|0,b)|0;l=e;c[l>>2]=0;c[l+4>>2]=0;l=f;c[l>>2]=0;c[l+4>>2]=0;pc(c[646]|0,b,e,f)|0;l=f;f=c[l>>2]|0;m=c[l+4>>2]|0;l=e;e=c[l>>2]|0;n=c[l+4>>2]|0;if((c[656]|0)==(b|0)){l=Fe(g|0,j|0,k|0)|0;xa(c[a>>2]|0,c[a+4>>2]|0,+h,+((+(l>>>0)+4294967296.0*+(C|0))*(+(f>>>0)+4294967296.0*+(m|0))/(+(e>>>0)+4294967296.0*+(n|0))))}if((c[658]|0)!=(b|0)){i=d;return}ma(c[a>>2]|0,c[a+4>>2]|0,+h);i=d;return}function se(a){a=a|0;return (a+-65|0)>>>0<26|0}function te(a){a=a|0;var b=0;b=(se(a)|0)==0;return (b?a:a|32)|0}function ue(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;f=d&255;g=(e|0)!=0;a:do if(g&(b&3|0)!=0){h=d&255;i=e;j=b;while(1){if((a[j>>0]|0)==h<<24>>24){k=i;l=j;m=6;break a}n=j+1|0;o=i+-1|0;p=(o|0)!=0;if(p&(n&3|0)!=0){i=o;j=n}else{q=o;r=p;s=n;m=5;break}}}else{q=e;r=g;s=b;m=5}while(0);if((m|0)==5)if(r){k=q;l=s;m=6}else{t=0;u=s}b:do if((m|0)==6){s=d&255;if((a[l>>0]|0)==s<<24>>24){t=k;u=l}else{q=_(f,16843009)|0;c:do if(k>>>0>3){r=k;b=l;while(1){g=c[b>>2]^q;if((g&-2139062144^-2139062144)&g+-16843009){v=r;w=b;break}g=b+4|0;e=r+-4|0;if(e>>>0>3){r=e;b=g}else{x=e;y=g;m=11;break c}}z=v;A=w}else{x=k;y=l;m=11}while(0);if((m|0)==11)if(!x){t=0;u=y;break}else{z=x;A=y}while(1){if((a[A>>0]|0)==s<<24>>24){t=z;u=A;break b}q=A+1|0;z=z+-1|0;if(!z){t=0;u=q;break}else A=q}}}while(0);return ((t|0)!=0?u:0)|0}function ve(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;if(!d){e=0;return e|0}else{f=d;g=b;h=c}while(1){c=a[g>>0]|0;b=a[h>>0]|0;if(c<<24>>24!=b<<24>>24){i=c;j=b;break}f=f+-1|0;if(!f){e=0;k=5;break}else{g=g+1|0;h=h+1|0}}if((k|0)==5)return e|0;e=(i&255)-(j&255)|0;return e|0}function we(b,c){b=b|0;c=c|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;e=a[b>>0]|0;a:do if(!(e<<24>>24)){f=0;g=c}else{h=e;i=e&255;j=b;k=c;while(1){l=a[k>>0]|0;if(!(l<<24>>24)){f=h;g=k;break a}if(h<<24>>24!=l<<24>>24?(l=te(i)|0,(l|0)!=(te(d[k>>0]|0)|0)):0){m=j;n=k;break}j=j+1|0;l=k+1|0;o=a[j>>0]|0;if(!(o<<24>>24)){f=0;g=l;break a}else{h=o;i=o&255;k=l}}f=a[m>>0]|0;g=n}while(0);n=te(f&255)|0;return n-(te(d[g>>0]|0)|0)|0}function xe(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0;d=a[b>>0]|0;e=a[c>>0]|0;if(d<<24>>24==0?1:d<<24>>24!=e<<24>>24){f=d;g=e}else{e=b;b=c;do{e=e+1|0;b=b+1|0;c=a[e>>0]|0;d=a[b>>0]|0}while(!(c<<24>>24==0?1:c<<24>>24!=d<<24>>24));f=c;g=d}return (f&255)-(g&255)|0}
+function ye(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,sa=0,ta=0,ua=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Fa=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0;do if(a>>>0<245){b=a>>>0<11?16:a+11&-8;d=b>>>3;e=c[722]|0;f=e>>>d;if(f&3){g=(f&1^1)+d|0;h=g<<1;i=2928+(h<<2)|0;j=2928+(h+2<<2)|0;h=c[j>>2]|0;k=h+8|0;l=c[k>>2]|0;do if((i|0)!=(l|0)){if(l>>>0<(c[726]|0)>>>0)Ea();m=l+12|0;if((c[m>>2]|0)==(h|0)){c[m>>2]=i;c[j>>2]=l;break}else Ea()}else c[722]=e&~(1<<g);while(0);l=g<<3;c[h+4>>2]=l|3;j=h+(l|4)|0;c[j>>2]=c[j>>2]|1;n=k;return n|0}j=c[724]|0;if(b>>>0>j>>>0){if(f){l=2<<d;i=f<<d&(l|0-l);l=(i&0-i)+-1|0;i=l>>>12&16;m=l>>>i;l=m>>>5&8;o=m>>>l;m=o>>>2&4;p=o>>>m;o=p>>>1&2;q=p>>>o;p=q>>>1&1;r=(l|i|m|o|p)+(q>>>p)|0;p=r<<1;q=2928+(p<<2)|0;o=2928+(p+2<<2)|0;p=c[o>>2]|0;m=p+8|0;i=c[m>>2]|0;do if((q|0)!=(i|0)){if(i>>>0<(c[726]|0)>>>0)Ea();l=i+12|0;if((c[l>>2]|0)==(p|0)){c[l>>2]=q;c[o>>2]=i;s=c[724]|0;break}else Ea()}else{c[722]=e&~(1<<r);s=j}while(0);j=r<<3;e=j-b|0;c[p+4>>2]=b|3;i=p+b|0;c[p+(b|4)>>2]=e|1;c[p+j>>2]=e;if(s){j=c[727]|0;o=s>>>3;q=o<<1;d=2928+(q<<2)|0;f=c[722]|0;k=1<<o;if(f&k){o=2928+(q+2<<2)|0;h=c[o>>2]|0;if(h>>>0<(c[726]|0)>>>0)Ea();else{t=o;u=h}}else{c[722]=f|k;t=2928+(q+2<<2)|0;u=d}c[t>>2]=j;c[u+12>>2]=j;c[j+8>>2]=u;c[j+12>>2]=d}c[724]=e;c[727]=i;n=m;return n|0}i=c[723]|0;if(i){e=(i&0-i)+-1|0;i=e>>>12&16;d=e>>>i;e=d>>>5&8;j=d>>>e;d=j>>>2&4;q=j>>>d;j=q>>>1&2;k=q>>>j;q=k>>>1&1;f=c[3192+((e|i|d|j|q)+(k>>>q)<<2)>>2]|0;q=(c[f+4>>2]&-8)-b|0;k=f;j=f;while(1){f=c[k+16>>2]|0;if(!f){d=c[k+20>>2]|0;if(!d){v=q;w=j;break}else x=d}else x=f;f=(c[x+4>>2]&-8)-b|0;d=f>>>0<q>>>0;q=d?f:q;k=x;j=d?x:j}j=c[726]|0;if(w>>>0<j>>>0)Ea();k=w+b|0;if(w>>>0>=k>>>0)Ea();q=c[w+24>>2]|0;m=c[w+12>>2]|0;do if((m|0)==(w|0)){p=w+20|0;r=c[p>>2]|0;if(!r){d=w+16|0;f=c[d>>2]|0;if(!f){y=0;break}else{z=f;A=d}}else{z=r;A=p}while(1){p=z+20|0;r=c[p>>2]|0;if(r){z=r;A=p;continue}p=z+16|0;r=c[p>>2]|0;if(!r){B=z;C=A;break}else{z=r;A=p}}if(C>>>0<j>>>0)Ea();else{c[C>>2]=0;y=B;break}}else{p=c[w+8>>2]|0;if(p>>>0<j>>>0)Ea();r=p+12|0;if((c[r>>2]|0)!=(w|0))Ea();d=m+8|0;if((c[d>>2]|0)==(w|0)){c[r>>2]=m;c[d>>2]=p;y=m;break}else Ea()}while(0);do if(q){m=c[w+28>>2]|0;j=3192+(m<<2)|0;if((w|0)==(c[j>>2]|0)){c[j>>2]=y;if(!y){c[723]=c[723]&~(1<<m);break}}else{if(q>>>0<(c[726]|0)>>>0)Ea();m=q+16|0;if((c[m>>2]|0)==(w|0))c[m>>2]=y;else c[q+20>>2]=y;if(!y)break}m=c[726]|0;if(y>>>0<m>>>0)Ea();c[y+24>>2]=q;j=c[w+16>>2]|0;do if(j)if(j>>>0<m>>>0)Ea();else{c[y+16>>2]=j;c[j+24>>2]=y;break}while(0);j=c[w+20>>2]|0;if(j)if(j>>>0<(c[726]|0)>>>0)Ea();else{c[y+20>>2]=j;c[j+24>>2]=y;break}}while(0);if(v>>>0<16){q=v+b|0;c[w+4>>2]=q|3;j=w+(q+4)|0;c[j>>2]=c[j>>2]|1}else{c[w+4>>2]=b|3;c[w+(b|4)>>2]=v|1;c[w+(v+b)>>2]=v;j=c[724]|0;if(j){q=c[727]|0;m=j>>>3;j=m<<1;p=2928+(j<<2)|0;d=c[722]|0;r=1<<m;if(d&r){m=2928+(j+2<<2)|0;f=c[m>>2]|0;if(f>>>0<(c[726]|0)>>>0)Ea();else{D=m;E=f}}else{c[722]=d|r;D=2928+(j+2<<2)|0;E=p}c[D>>2]=q;c[E+12>>2]=q;c[q+8>>2]=E;c[q+12>>2]=p}c[724]=v;c[727]=k}n=w+8|0;return n|0}else F=b}else F=b}else if(a>>>0<=4294967231){p=a+11|0;q=p&-8;j=c[723]|0;if(j){r=0-q|0;d=p>>>8;if(d)if(q>>>0>16777215)G=31;else{p=(d+1048320|0)>>>16&8;f=d<<p;d=(f+520192|0)>>>16&4;m=f<<d;f=(m+245760|0)>>>16&2;i=14-(d|p|f)+(m<<f>>>15)|0;G=q>>>(i+7|0)&1|i<<1}else G=0;i=c[3192+(G<<2)>>2]|0;a:do if(!i){H=r;I=0;J=0;K=86}else{f=r;m=0;p=q<<((G|0)==31?0:25-(G>>>1)|0);d=i;e=0;while(1){h=c[d+4>>2]&-8;o=h-q|0;if(o>>>0<f>>>0)if((h|0)==(q|0)){L=o;M=d;N=d;K=90;break a}else{O=o;P=d}else{O=f;P=e}o=c[d+20>>2]|0;d=c[d+16+(p>>>31<<2)>>2]|0;h=(o|0)==0|(o|0)==(d|0)?m:o;if(!d){H=O;I=h;J=P;K=86;break}else{f=O;m=h;p=p<<1;e=P}}}while(0);if((K|0)==86){if((I|0)==0&(J|0)==0){i=2<<G;r=j&(i|0-i);if(!r){F=q;break}i=(r&0-r)+-1|0;r=i>>>12&16;b=i>>>r;i=b>>>5&8;k=b>>>i;b=k>>>2&4;e=k>>>b;k=e>>>1&2;p=e>>>k;e=p>>>1&1;Q=c[3192+((i|r|b|k|e)+(p>>>e)<<2)>>2]|0;R=0}else{Q=I;R=J}if(!Q){S=H;T=R}else{L=H;M=Q;N=R;K=90}}if((K|0)==90)while(1){K=0;e=(c[M+4>>2]&-8)-q|0;p=e>>>0<L>>>0;k=p?e:L;e=p?M:N;p=c[M+16>>2]|0;if(p){L=k;M=p;N=e;K=90;continue}M=c[M+20>>2]|0;if(!M){S=k;T=e;break}else{L=k;N=e;K=90}}if((T|0)!=0?S>>>0<((c[724]|0)-q|0)>>>0:0){j=c[726]|0;if(T>>>0<j>>>0)Ea();e=T+q|0;if(T>>>0>=e>>>0)Ea();k=c[T+24>>2]|0;p=c[T+12>>2]|0;do if((p|0)==(T|0)){b=T+20|0;r=c[b>>2]|0;if(!r){i=T+16|0;m=c[i>>2]|0;if(!m){U=0;break}else{V=m;W=i}}else{V=r;W=b}while(1){b=V+20|0;r=c[b>>2]|0;if(r){V=r;W=b;continue}b=V+16|0;r=c[b>>2]|0;if(!r){X=V;Y=W;break}else{V=r;W=b}}if(Y>>>0<j>>>0)Ea();else{c[Y>>2]=0;U=X;break}}else{b=c[T+8>>2]|0;if(b>>>0<j>>>0)Ea();r=b+12|0;if((c[r>>2]|0)!=(T|0))Ea();i=p+8|0;if((c[i>>2]|0)==(T|0)){c[r>>2]=p;c[i>>2]=b;U=p;break}else Ea()}while(0);do if(k){p=c[T+28>>2]|0;j=3192+(p<<2)|0;if((T|0)==(c[j>>2]|0)){c[j>>2]=U;if(!U){c[723]=c[723]&~(1<<p);break}}else{if(k>>>0<(c[726]|0)>>>0)Ea();p=k+16|0;if((c[p>>2]|0)==(T|0))c[p>>2]=U;else c[k+20>>2]=U;if(!U)break}p=c[726]|0;if(U>>>0<p>>>0)Ea();c[U+24>>2]=k;j=c[T+16>>2]|0;do if(j)if(j>>>0<p>>>0)Ea();else{c[U+16>>2]=j;c[j+24>>2]=U;break}while(0);j=c[T+20>>2]|0;if(j)if(j>>>0<(c[726]|0)>>>0)Ea();else{c[U+20>>2]=j;c[j+24>>2]=U;break}}while(0);b:do if(S>>>0>=16){c[T+4>>2]=q|3;c[T+(q|4)>>2]=S|1;c[T+(S+q)>>2]=S;k=S>>>3;if(S>>>0<256){j=k<<1;p=2928+(j<<2)|0;b=c[722]|0;i=1<<k;if(b&i){k=2928+(j+2<<2)|0;r=c[k>>2]|0;if(r>>>0<(c[726]|0)>>>0)Ea();else{Z=k;_=r}}else{c[722]=b|i;Z=2928+(j+2<<2)|0;_=p}c[Z>>2]=e;c[_+12>>2]=e;c[T+(q+8)>>2]=_;c[T+(q+12)>>2]=p;break}p=S>>>8;if(p)if(S>>>0>16777215)$=31;else{j=(p+1048320|0)>>>16&8;i=p<<j;p=(i+520192|0)>>>16&4;b=i<<p;i=(b+245760|0)>>>16&2;r=14-(p|j|i)+(b<<i>>>15)|0;$=S>>>(r+7|0)&1|r<<1}else $=0;r=3192+($<<2)|0;c[T+(q+28)>>2]=$;c[T+(q+20)>>2]=0;c[T+(q+16)>>2]=0;i=c[723]|0;b=1<<$;if(!(i&b)){c[723]=i|b;c[r>>2]=e;c[T+(q+24)>>2]=r;c[T+(q+12)>>2]=e;c[T+(q+8)>>2]=e;break}b=c[r>>2]|0;c:do if((c[b+4>>2]&-8|0)!=(S|0)){r=S<<(($|0)==31?0:25-($>>>1)|0);i=b;while(1){j=i+16+(r>>>31<<2)|0;p=c[j>>2]|0;if(!p){aa=j;ba=i;break}if((c[p+4>>2]&-8|0)==(S|0)){ca=p;break c}else{r=r<<1;i=p}}if(aa>>>0<(c[726]|0)>>>0)Ea();else{c[aa>>2]=e;c[T+(q+24)>>2]=ba;c[T+(q+12)>>2]=e;c[T+(q+8)>>2]=e;break b}}else ca=b;while(0);b=ca+8|0;i=c[b>>2]|0;r=c[726]|0;if(i>>>0>=r>>>0&ca>>>0>=r>>>0){c[i+12>>2]=e;c[b>>2]=e;c[T+(q+8)>>2]=i;c[T+(q+12)>>2]=ca;c[T+(q+24)>>2]=0;break}else Ea()}else{i=S+q|0;c[T+4>>2]=i|3;b=T+(i+4)|0;c[b>>2]=c[b>>2]|1}while(0);n=T+8|0;return n|0}else F=q}else F=q}else F=-1;while(0);T=c[724]|0;if(T>>>0>=F>>>0){S=T-F|0;ca=c[727]|0;if(S>>>0>15){c[727]=ca+F;c[724]=S;c[ca+(F+4)>>2]=S|1;c[ca+T>>2]=S;c[ca+4>>2]=F|3}else{c[724]=0;c[727]=0;c[ca+4>>2]=T|3;S=ca+(T+4)|0;c[S>>2]=c[S>>2]|1}n=ca+8|0;return n|0}ca=c[725]|0;if(ca>>>0>F>>>0){S=ca-F|0;c[725]=S;ca=c[728]|0;c[728]=ca+F;c[ca+(F+4)>>2]=S|1;c[ca+4>>2]=F|3;n=ca+8|0;return n|0}do if(!(c[840]|0)){ca=va(30)|0;if(!(ca+-1&ca)){c[842]=ca;c[841]=ca;c[843]=-1;c[844]=-1;c[845]=0;c[833]=0;c[840]=(Ga(0)|0)&-16^1431655768;break}else Ea()}while(0);ca=F+48|0;S=c[842]|0;T=F+47|0;ba=S+T|0;aa=0-S|0;S=ba&aa;if(S>>>0<=F>>>0){n=0;return n|0}$=c[832]|0;if(($|0)!=0?(_=c[830]|0,Z=_+S|0,Z>>>0<=_>>>0|Z>>>0>$>>>0):0){n=0;return n|0}d:do if(!(c[833]&4)){$=c[728]|0;e:do if($){Z=3336;while(1){_=c[Z>>2]|0;if(_>>>0<=$>>>0?(U=Z+4|0,(_+(c[U>>2]|0)|0)>>>0>$>>>0):0){da=Z;ea=U;break}Z=c[Z+8>>2]|0;if(!Z){K=174;break e}}Z=ba-(c[725]|0)&aa;if(Z>>>0<2147483647){U=ra(Z|0)|0;_=(U|0)==((c[da>>2]|0)+(c[ea>>2]|0)|0);X=_?Z:0;if(_)if((U|0)==(-1|0))fa=X;else{ga=U;ha=X;K=194;break d}else{ia=U;ja=Z;ka=X;K=184}}else fa=0}else K=174;while(0);do if((K|0)==174){$=ra(0)|0;if(($|0)!=(-1|0)){q=$;X=c[841]|0;Z=X+-1|0;if(!(Z&q))la=S;else la=S-q+(Z+q&0-X)|0;X=c[830]|0;q=X+la|0;if(la>>>0>F>>>0&la>>>0<2147483647){Z=c[832]|0;if((Z|0)!=0?q>>>0<=X>>>0|q>>>0>Z>>>0:0){fa=0;break}Z=ra(la|0)|0;q=(Z|0)==($|0);X=q?la:0;if(q){ga=$;ha=X;K=194;break d}else{ia=Z;ja=la;ka=X;K=184}}else fa=0}else fa=0}while(0);f:do if((K|0)==184){X=0-ja|0;do if(ca>>>0>ja>>>0&(ja>>>0<2147483647&(ia|0)!=(-1|0))?(Z=c[842]|0,$=T-ja+Z&0-Z,$>>>0<2147483647):0)if((ra($|0)|0)==(-1|0)){ra(X|0)|0;fa=ka;break f}else{ma=$+ja|0;break}else ma=ja;while(0);if((ia|0)==(-1|0))fa=ka;else{ga=ia;ha=ma;K=194;break d}}while(0);c[833]=c[833]|4;na=fa;K=191}else{na=0;K=191}while(0);if((((K|0)==191?S>>>0<2147483647:0)?(fa=ra(S|0)|0,S=ra(0)|0,fa>>>0<S>>>0&((fa|0)!=(-1|0)&(S|0)!=(-1|0))):0)?(ma=S-fa|0,S=ma>>>0>(F+40|0)>>>0,S):0){ga=fa;ha=S?ma:na;K=194}if((K|0)==194){na=(c[830]|0)+ha|0;c[830]=na;if(na>>>0>(c[831]|0)>>>0)c[831]=na;na=c[728]|0;g:do if(na){ma=3336;do{S=c[ma>>2]|0;fa=ma+4|0;ia=c[fa>>2]|0;if((ga|0)==(S+ia|0)){oa=S;pa=fa;qa=ia;sa=ma;K=204;break}ma=c[ma+8>>2]|0}while((ma|0)!=0);if(((K|0)==204?(c[sa+12>>2]&8|0)==0:0)?na>>>0<ga>>>0&na>>>0>=oa>>>0:0){c[pa>>2]=qa+ha;ma=(c[725]|0)+ha|0;ia=na+8|0;fa=(ia&7|0)==0?0:0-ia&7;ia=ma-fa|0;c[728]=na+fa;c[725]=ia;c[na+(fa+4)>>2]=ia|1;c[na+(ma+4)>>2]=40;c[729]=c[844];break}ma=c[726]|0;if(ga>>>0<ma>>>0){c[726]=ga;ta=ga}else ta=ma;ma=ga+ha|0;ia=3336;while(1){if((c[ia>>2]|0)==(ma|0)){ua=ia;wa=ia;K=212;break}ia=c[ia+8>>2]|0;if(!ia){xa=3336;break}}if((K|0)==212)if(!(c[wa+12>>2]&8)){c[ua>>2]=ga;ia=wa+4|0;c[ia>>2]=(c[ia>>2]|0)+ha;ia=ga+8|0;ma=(ia&7|0)==0?0:0-ia&7;ia=ga+(ha+8)|0;fa=(ia&7|0)==0?0:0-ia&7;ia=ga+(fa+ha)|0;S=ma+F|0;ka=ga+S|0;ja=ia-(ga+ma)-F|0;c[ga+(ma+4)>>2]=F|3;h:do if((ia|0)!=(na|0)){if((ia|0)==(c[727]|0)){T=(c[724]|0)+ja|0;c[724]=T;c[727]=ka;c[ga+(S+4)>>2]=T|1;c[ga+(T+S)>>2]=T;break}T=ha+4|0;ca=c[ga+(T+fa)>>2]|0;if((ca&3|0)==1){la=ca&-8;ea=ca>>>3;i:do if(ca>>>0>=256){da=c[ga+((fa|24)+ha)>>2]|0;aa=c[ga+(ha+12+fa)>>2]|0;do if((aa|0)==(ia|0)){ba=fa|16;X=ga+(T+ba)|0;$=c[X>>2]|0;if(!$){Z=ga+(ba+ha)|0;ba=c[Z>>2]|0;if(!ba){ya=0;break}else{za=ba;Aa=Z}}else{za=$;Aa=X}while(1){X=za+20|0;$=c[X>>2]|0;if($){za=$;Aa=X;continue}X=za+16|0;$=c[X>>2]|0;if(!$){Ba=za;Ca=Aa;break}else{za=$;Aa=X}}if(Ca>>>0<ta>>>0)Ea();else{c[Ca>>2]=0;ya=Ba;break}}else{X=c[ga+((fa|8)+ha)>>2]|0;if(X>>>0<ta>>>0)Ea();$=X+12|0;if((c[$>>2]|0)!=(ia|0))Ea();Z=aa+8|0;if((c[Z>>2]|0)==(ia|0)){c[$>>2]=aa;c[Z>>2]=X;ya=aa;break}else Ea()}while(0);if(!da)break;aa=c[ga+(ha+28+fa)>>2]|0;X=3192+(aa<<2)|0;do if((ia|0)!=(c[X>>2]|0)){if(da>>>0<(c[726]|0)>>>0)Ea();Z=da+16|0;if((c[Z>>2]|0)==(ia|0))c[Z>>2]=ya;else c[da+20>>2]=ya;if(!ya)break i}else{c[X>>2]=ya;if(ya)break;c[723]=c[723]&~(1<<aa);break i}while(0);aa=c[726]|0;if(ya>>>0<aa>>>0)Ea();c[ya+24>>2]=da;X=fa|16;Z=c[ga+(X+ha)>>2]|0;do if(Z)if(Z>>>0<aa>>>0)Ea();else{c[ya+16>>2]=Z;c[Z+24>>2]=ya;break}while(0);Z=c[ga+(T+X)>>2]|0;if(!Z)break;if(Z>>>0<(c[726]|0)>>>0)Ea();else{c[ya+20>>2]=Z;c[Z+24>>2]=ya;break}}else{Z=c[ga+((fa|8)+ha)>>2]|0;aa=c[ga+(ha+12+fa)>>2]|0;da=2928+(ea<<1<<2)|0;do if((Z|0)!=(da|0)){if(Z>>>0<ta>>>0)Ea();if((c[Z+12>>2]|0)==(ia|0))break;Ea()}while(0);if((aa|0)==(Z|0)){c[722]=c[722]&~(1<<ea);break}do if((aa|0)==(da|0))Fa=aa+8|0;else{if(aa>>>0<ta>>>0)Ea();X=aa+8|0;if((c[X>>2]|0)==(ia|0)){Fa=X;break}Ea()}while(0);c[Z+12>>2]=aa;c[Fa>>2]=Z}while(0);Ha=ga+((la|fa)+ha)|0;Ia=la+ja|0}else{Ha=ia;Ia=ja}ea=Ha+4|0;c[ea>>2]=c[ea>>2]&-2;c[ga+(S+4)>>2]=Ia|1;c[ga+(Ia+S)>>2]=Ia;ea=Ia>>>3;if(Ia>>>0<256){T=ea<<1;ca=2928+(T<<2)|0;da=c[722]|0;X=1<<ea;do if(!(da&X)){c[722]=da|X;Ja=2928+(T+2<<2)|0;Ka=ca}else{ea=2928+(T+2<<2)|0;$=c[ea>>2]|0;if($>>>0>=(c[726]|0)>>>0){Ja=ea;Ka=$;break}Ea()}while(0);c[Ja>>2]=ka;c[Ka+12>>2]=ka;c[ga+(S+8)>>2]=Ka;c[ga+(S+12)>>2]=ca;break}T=Ia>>>8;do if(!T)La=0;else{if(Ia>>>0>16777215){La=31;break}X=(T+1048320|0)>>>16&8;da=T<<X;la=(da+520192|0)>>>16&4;$=da<<la;da=($+245760|0)>>>16&2;ea=14-(la|X|da)+($<<da>>>15)|0;La=Ia>>>(ea+7|0)&1|ea<<1}while(0);T=3192+(La<<2)|0;c[ga+(S+28)>>2]=La;c[ga+(S+20)>>2]=0;c[ga+(S+16)>>2]=0;ca=c[723]|0;ea=1<<La;if(!(ca&ea)){c[723]=ca|ea;c[T>>2]=ka;c[ga+(S+24)>>2]=T;c[ga+(S+12)>>2]=ka;c[ga+(S+8)>>2]=ka;break}ea=c[T>>2]|0;j:do if((c[ea+4>>2]&-8|0)!=(Ia|0)){T=Ia<<((La|0)==31?0:25-(La>>>1)|0);ca=ea;while(1){da=ca+16+(T>>>31<<2)|0;$=c[da>>2]|0;if(!$){Ma=da;Na=ca;break}if((c[$+4>>2]&-8|0)==(Ia|0)){Oa=$;break j}else{T=T<<1;ca=$}}if(Ma>>>0<(c[726]|0)>>>0)Ea();else{c[Ma>>2]=ka;c[ga+(S+24)>>2]=Na;c[ga+(S+12)>>2]=ka;c[ga+(S+8)>>2]=ka;break h}}else Oa=ea;while(0);ea=Oa+8|0;ca=c[ea>>2]|0;T=c[726]|0;if(ca>>>0>=T>>>0&Oa>>>0>=T>>>0){c[ca+12>>2]=ka;c[ea>>2]=ka;c[ga+(S+8)>>2]=ca;c[ga+(S+12)>>2]=Oa;c[ga+(S+24)>>2]=0;break}else Ea()}else{ca=(c[725]|0)+ja|0;c[725]=ca;c[728]=ka;c[ga+(S+4)>>2]=ca|1}while(0);n=ga+(ma|8)|0;return n|0}else xa=3336;while(1){S=c[xa>>2]|0;if(S>>>0<=na>>>0?(ka=c[xa+4>>2]|0,ja=S+ka|0,ja>>>0>na>>>0):0){Pa=S;Qa=ka;Ra=ja;break}xa=c[xa+8>>2]|0}ma=Pa+(Qa+-39)|0;ja=Pa+(Qa+-47+((ma&7|0)==0?0:0-ma&7))|0;ma=na+16|0;ka=ja>>>0<ma>>>0?na:ja;ja=ka+8|0;S=ga+8|0;ia=(S&7|0)==0?0:0-S&7;S=ha+-40-ia|0;c[728]=ga+ia;c[725]=S;c[ga+(ia+4)>>2]=S|1;c[ga+(ha+-36)>>2]=40;c[729]=c[844];S=ka+4|0;c[S>>2]=27;c[ja>>2]=c[834];c[ja+4>>2]=c[835];c[ja+8>>2]=c[836];c[ja+12>>2]=c[837];c[834]=ga;c[835]=ha;c[837]=0;c[836]=ja;ja=ka+28|0;c[ja>>2]=7;if((ka+32|0)>>>0<Ra>>>0){ia=ja;do{ja=ia;ia=ia+4|0;c[ia>>2]=7}while((ja+8|0)>>>0<Ra>>>0)}if((ka|0)!=(na|0)){ia=ka-na|0;c[S>>2]=c[S>>2]&-2;c[na+4>>2]=ia|1;c[ka>>2]=ia;ja=ia>>>3;if(ia>>>0<256){fa=ja<<1;ca=2928+(fa<<2)|0;ea=c[722]|0;T=1<<ja;if(ea&T){ja=2928+(fa+2<<2)|0;Z=c[ja>>2]|0;if(Z>>>0<(c[726]|0)>>>0)Ea();else{Sa=ja;Ta=Z}}else{c[722]=ea|T;Sa=2928+(fa+2<<2)|0;Ta=ca}c[Sa>>2]=na;c[Ta+12>>2]=na;c[na+8>>2]=Ta;c[na+12>>2]=ca;break}ca=ia>>>8;if(ca)if(ia>>>0>16777215)Ua=31;else{fa=(ca+1048320|0)>>>16&8;T=ca<<fa;ca=(T+520192|0)>>>16&4;ea=T<<ca;T=(ea+245760|0)>>>16&2;Z=14-(ca|fa|T)+(ea<<T>>>15)|0;Ua=ia>>>(Z+7|0)&1|Z<<1}else Ua=0;Z=3192+(Ua<<2)|0;c[na+28>>2]=Ua;c[na+20>>2]=0;c[ma>>2]=0;T=c[723]|0;ea=1<<Ua;if(!(T&ea)){c[723]=T|ea;c[Z>>2]=na;c[na+24>>2]=Z;c[na+12>>2]=na;c[na+8>>2]=na;break}ea=c[Z>>2]|0;k:do if((c[ea+4>>2]&-8|0)!=(ia|0)){Z=ia<<((Ua|0)==31?0:25-(Ua>>>1)|0);T=ea;while(1){fa=T+16+(Z>>>31<<2)|0;ca=c[fa>>2]|0;if(!ca){Va=fa;Wa=T;break}if((c[ca+4>>2]&-8|0)==(ia|0)){Xa=ca;break k}else{Z=Z<<1;T=ca}}if(Va>>>0<(c[726]|0)>>>0)Ea();else{c[Va>>2]=na;c[na+24>>2]=Wa;c[na+12>>2]=na;c[na+8>>2]=na;break g}}else Xa=ea;while(0);ea=Xa+8|0;ia=c[ea>>2]|0;ma=c[726]|0;if(ia>>>0>=ma>>>0&Xa>>>0>=ma>>>0){c[ia+12>>2]=na;c[ea>>2]=na;c[na+8>>2]=ia;c[na+12>>2]=Xa;c[na+24>>2]=0;break}else Ea()}}else{ia=c[726]|0;if((ia|0)==0|ga>>>0<ia>>>0)c[726]=ga;c[834]=ga;c[835]=ha;c[837]=0;c[731]=c[840];c[730]=-1;ia=0;do{ea=ia<<1;ma=2928+(ea<<2)|0;c[2928+(ea+3<<2)>>2]=ma;c[2928+(ea+2<<2)>>2]=ma;ia=ia+1|0}while((ia|0)!=32);ia=ga+8|0;ma=(ia&7|0)==0?0:0-ia&7;ia=ha+-40-ma|0;c[728]=ga+ma;c[725]=ia;c[ga+(ma+4)>>2]=ia|1;c[ga+(ha+-36)>>2]=40;c[729]=c[844]}while(0);ha=c[725]|0;if(ha>>>0>F>>>0){ga=ha-F|0;c[725]=ga;ha=c[728]|0;c[728]=ha+F;c[ha+(F+4)>>2]=ga|1;c[ha+4>>2]=F|3;n=ha+8|0;return n|0}}c[(Da()|0)>>2]=12;n=0;return n|0}function ze(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;if(!a)return;b=a+-8|0;d=c[726]|0;if(b>>>0<d>>>0)Ea();e=c[a+-4>>2]|0;f=e&3;if((f|0)==1)Ea();g=e&-8;h=a+(g+-8)|0;do if(!(e&1)){i=c[b>>2]|0;if(!f)return;j=-8-i|0;k=a+j|0;l=i+g|0;if(k>>>0<d>>>0)Ea();if((k|0)==(c[727]|0)){m=a+(g+-4)|0;n=c[m>>2]|0;if((n&3|0)!=3){o=k;p=l;break}c[724]=l;c[m>>2]=n&-2;c[a+(j+4)>>2]=l|1;c[h>>2]=l;return}n=i>>>3;if(i>>>0<256){i=c[a+(j+8)>>2]|0;m=c[a+(j+12)>>2]|0;q=2928+(n<<1<<2)|0;if((i|0)!=(q|0)){if(i>>>0<d>>>0)Ea();if((c[i+12>>2]|0)!=(k|0))Ea()}if((m|0)==(i|0)){c[722]=c[722]&~(1<<n);o=k;p=l;break}if((m|0)!=(q|0)){if(m>>>0<d>>>0)Ea();q=m+8|0;if((c[q>>2]|0)==(k|0))r=q;else Ea()}else r=m+8|0;c[i+12>>2]=m;c[r>>2]=i;o=k;p=l;break}i=c[a+(j+24)>>2]|0;m=c[a+(j+12)>>2]|0;do if((m|0)==(k|0)){q=a+(j+20)|0;n=c[q>>2]|0;if(!n){s=a+(j+16)|0;t=c[s>>2]|0;if(!t){u=0;break}else{v=t;w=s}}else{v=n;w=q}while(1){q=v+20|0;n=c[q>>2]|0;if(n){v=n;w=q;continue}q=v+16|0;n=c[q>>2]|0;if(!n){x=v;y=w;break}else{v=n;w=q}}if(y>>>0<d>>>0)Ea();else{c[y>>2]=0;u=x;break}}else{q=c[a+(j+8)>>2]|0;if(q>>>0<d>>>0)Ea();n=q+12|0;if((c[n>>2]|0)!=(k|0))Ea();s=m+8|0;if((c[s>>2]|0)==(k|0)){c[n>>2]=m;c[s>>2]=q;u=m;break}else Ea()}while(0);if(i){m=c[a+(j+28)>>2]|0;q=3192+(m<<2)|0;if((k|0)==(c[q>>2]|0)){c[q>>2]=u;if(!u){c[723]=c[723]&~(1<<m);o=k;p=l;break}}else{if(i>>>0<(c[726]|0)>>>0)Ea();m=i+16|0;if((c[m>>2]|0)==(k|0))c[m>>2]=u;else c[i+20>>2]=u;if(!u){o=k;p=l;break}}m=c[726]|0;if(u>>>0<m>>>0)Ea();c[u+24>>2]=i;q=c[a+(j+16)>>2]|0;do if(q)if(q>>>0<m>>>0)Ea();else{c[u+16>>2]=q;c[q+24>>2]=u;break}while(0);q=c[a+(j+20)>>2]|0;if(q)if(q>>>0<(c[726]|0)>>>0)Ea();else{c[u+20>>2]=q;c[q+24>>2]=u;o=k;p=l;break}else{o=k;p=l}}else{o=k;p=l}}else{o=b;p=g}while(0);if(o>>>0>=h>>>0)Ea();b=a+(g+-4)|0;u=c[b>>2]|0;if(!(u&1))Ea();if(!(u&2)){if((h|0)==(c[728]|0)){d=(c[725]|0)+p|0;c[725]=d;c[728]=o;c[o+4>>2]=d|1;if((o|0)!=(c[727]|0))return;c[727]=0;c[724]=0;return}if((h|0)==(c[727]|0)){d=(c[724]|0)+p|0;c[724]=d;c[727]=o;c[o+4>>2]=d|1;c[o+d>>2]=d;return}d=(u&-8)+p|0;x=u>>>3;do if(u>>>0>=256){y=c[a+(g+16)>>2]|0;w=c[a+(g|4)>>2]|0;do if((w|0)==(h|0)){v=a+(g+12)|0;r=c[v>>2]|0;if(!r){f=a+(g+8)|0;e=c[f>>2]|0;if(!e){z=0;break}else{A=e;B=f}}else{A=r;B=v}while(1){v=A+20|0;r=c[v>>2]|0;if(r){A=r;B=v;continue}v=A+16|0;r=c[v>>2]|0;if(!r){C=A;D=B;break}else{A=r;B=v}}if(D>>>0<(c[726]|0)>>>0)Ea();else{c[D>>2]=0;z=C;break}}else{v=c[a+g>>2]|0;if(v>>>0<(c[726]|0)>>>0)Ea();r=v+12|0;if((c[r>>2]|0)!=(h|0))Ea();f=w+8|0;if((c[f>>2]|0)==(h|0)){c[r>>2]=w;c[f>>2]=v;z=w;break}else Ea()}while(0);if(y){w=c[a+(g+20)>>2]|0;l=3192+(w<<2)|0;if((h|0)==(c[l>>2]|0)){c[l>>2]=z;if(!z){c[723]=c[723]&~(1<<w);break}}else{if(y>>>0<(c[726]|0)>>>0)Ea();w=y+16|0;if((c[w>>2]|0)==(h|0))c[w>>2]=z;else c[y+20>>2]=z;if(!z)break}w=c[726]|0;if(z>>>0<w>>>0)Ea();c[z+24>>2]=y;l=c[a+(g+8)>>2]|0;do if(l)if(l>>>0<w>>>0)Ea();else{c[z+16>>2]=l;c[l+24>>2]=z;break}while(0);l=c[a+(g+12)>>2]|0;if(l)if(l>>>0<(c[726]|0)>>>0)Ea();else{c[z+20>>2]=l;c[l+24>>2]=z;break}}}else{l=c[a+g>>2]|0;w=c[a+(g|4)>>2]|0;y=2928+(x<<1<<2)|0;if((l|0)!=(y|0)){if(l>>>0<(c[726]|0)>>>0)Ea();if((c[l+12>>2]|0)!=(h|0))Ea()}if((w|0)==(l|0)){c[722]=c[722]&~(1<<x);break}if((w|0)!=(y|0)){if(w>>>0<(c[726]|0)>>>0)Ea();y=w+8|0;if((c[y>>2]|0)==(h|0))E=y;else Ea()}else E=w+8|0;c[l+12>>2]=w;c[E>>2]=l}while(0);c[o+4>>2]=d|1;c[o+d>>2]=d;if((o|0)==(c[727]|0)){c[724]=d;return}else F=d}else{c[b>>2]=u&-2;c[o+4>>2]=p|1;c[o+p>>2]=p;F=p}p=F>>>3;if(F>>>0<256){u=p<<1;b=2928+(u<<2)|0;d=c[722]|0;E=1<<p;if(d&E){p=2928+(u+2<<2)|0;h=c[p>>2]|0;if(h>>>0<(c[726]|0)>>>0)Ea();else{G=p;H=h}}else{c[722]=d|E;G=2928+(u+2<<2)|0;H=b}c[G>>2]=o;c[H+12>>2]=o;c[o+8>>2]=H;c[o+12>>2]=b;return}b=F>>>8;if(b)if(F>>>0>16777215)I=31;else{H=(b+1048320|0)>>>16&8;G=b<<H;b=(G+520192|0)>>>16&4;u=G<<b;G=(u+245760|0)>>>16&2;E=14-(b|H|G)+(u<<G>>>15)|0;I=F>>>(E+7|0)&1|E<<1}else I=0;E=3192+(I<<2)|0;c[o+28>>2]=I;c[o+20>>2]=0;c[o+16>>2]=0;G=c[723]|0;u=1<<I;a:do if(G&u){H=c[E>>2]|0;b:do if((c[H+4>>2]&-8|0)!=(F|0)){b=F<<((I|0)==31?0:25-(I>>>1)|0);d=H;while(1){h=d+16+(b>>>31<<2)|0;p=c[h>>2]|0;if(!p){J=h;K=d;break}if((c[p+4>>2]&-8|0)==(F|0)){L=p;break b}else{b=b<<1;d=p}}if(J>>>0<(c[726]|0)>>>0)Ea();else{c[J>>2]=o;c[o+24>>2]=K;c[o+12>>2]=o;c[o+8>>2]=o;break a}}else L=H;while(0);H=L+8|0;d=c[H>>2]|0;b=c[726]|0;if(d>>>0>=b>>>0&L>>>0>=b>>>0){c[d+12>>2]=o;c[H>>2]=o;c[o+8>>2]=d;c[o+12>>2]=L;c[o+24>>2]=0;break}else Ea()}else{c[723]=G|u;c[E>>2]=o;c[o+24>>2]=E;c[o+12>>2]=o;c[o+8>>2]=o}while(0);o=(c[730]|0)+-1|0;c[730]=o;if(!o)M=3344;else return;while(1){o=c[M>>2]|0;if(!o)break;else M=o+8|0}c[730]=-1;return}function Ae(a,b){a=a|0;b=b|0;var d=0,e=0;if(a){d=_(b,a)|0;if((b|a)>>>0>65535)e=((d>>>0)/(a>>>0)|0|0)==(b|0)?d:-1;else e=d}else e=0;d=ye(e)|0;if(!d)return d|0;if(!(c[d+-4>>2]&3))return d|0;He(d|0,0,e|0)|0;return d|0}function Be(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;if(!a){d=ye(b)|0;return d|0}if(b>>>0>4294967231){c[(Da()|0)>>2]=12;d=0;return d|0}e=Ce(a+-8|0,b>>>0<11?16:b+11&-8)|0;if(e){d=e+8|0;return d|0}e=ye(b)|0;if(!e){d=0;return d|0}f=c[a+-4>>2]|0;g=(f&-8)-((f&3|0)==0?8:4)|0;Ke(e|0,a|0,(g>>>0<b>>>0?g:b)|0)|0;ze(a);d=e;return d|0}function Ce(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;d=a+4|0;e=c[d>>2]|0;f=e&-8;g=a+f|0;h=c[726]|0;i=e&3;if(!((i|0)!=1&a>>>0>=h>>>0&a>>>0<g>>>0))Ea();j=a+(f|4)|0;k=c[j>>2]|0;if(!(k&1))Ea();if(!i){if(b>>>0<256){l=0;return l|0}if(f>>>0>=(b+4|0)>>>0?(f-b|0)>>>0<=c[842]<<1>>>0:0){l=a;return l|0}l=0;return l|0}if(f>>>0>=b>>>0){i=f-b|0;if(i>>>0<=15){l=a;return l|0}c[d>>2]=e&1|b|2;c[a+(b+4)>>2]=i|3;c[j>>2]=c[j>>2]|1;De(a+b|0,i);l=a;return l|0}if((g|0)==(c[728]|0)){i=(c[725]|0)+f|0;if(i>>>0<=b>>>0){l=0;return l|0}j=i-b|0;c[d>>2]=e&1|b|2;c[a+(b+4)>>2]=j|1;c[728]=a+b;c[725]=j;l=a;return l|0}if((g|0)==(c[727]|0)){j=(c[724]|0)+f|0;if(j>>>0<b>>>0){l=0;return l|0}i=j-b|0;if(i>>>0>15){c[d>>2]=e&1|b|2;c[a+(b+4)>>2]=i|1;c[a+j>>2]=i;m=a+(j+4)|0;c[m>>2]=c[m>>2]&-2;n=a+b|0;o=i}else{c[d>>2]=e&1|j|2;i=a+(j+4)|0;c[i>>2]=c[i>>2]|1;n=0;o=0}c[724]=o;c[727]=n;l=a;return l|0}if(k&2){l=0;return l|0}n=(k&-8)+f|0;if(n>>>0<b>>>0){l=0;return l|0}o=n-b|0;i=k>>>3;do if(k>>>0>=256){j=c[a+(f+24)>>2]|0;m=c[a+(f+12)>>2]|0;do if((m|0)==(g|0)){p=a+(f+20)|0;q=c[p>>2]|0;if(!q){r=a+(f+16)|0;s=c[r>>2]|0;if(!s){t=0;break}else{u=s;v=r}}else{u=q;v=p}while(1){p=u+20|0;q=c[p>>2]|0;if(q){u=q;v=p;continue}p=u+16|0;q=c[p>>2]|0;if(!q){w=u;x=v;break}else{u=q;v=p}}if(x>>>0<h>>>0)Ea();else{c[x>>2]=0;t=w;break}}else{p=c[a+(f+8)>>2]|0;if(p>>>0<h>>>0)Ea();q=p+12|0;if((c[q>>2]|0)!=(g|0))Ea();r=m+8|0;if((c[r>>2]|0)==(g|0)){c[q>>2]=m;c[r>>2]=p;t=m;break}else Ea()}while(0);if(j){m=c[a+(f+28)>>2]|0;p=3192+(m<<2)|0;if((g|0)==(c[p>>2]|0)){c[p>>2]=t;if(!t){c[723]=c[723]&~(1<<m);break}}else{if(j>>>0<(c[726]|0)>>>0)Ea();m=j+16|0;if((c[m>>2]|0)==(g|0))c[m>>2]=t;else c[j+20>>2]=t;if(!t)break}m=c[726]|0;if(t>>>0<m>>>0)Ea();c[t+24>>2]=j;p=c[a+(f+16)>>2]|0;do if(p)if(p>>>0<m>>>0)Ea();else{c[t+16>>2]=p;c[p+24>>2]=t;break}while(0);p=c[a+(f+20)>>2]|0;if(p)if(p>>>0<(c[726]|0)>>>0)Ea();else{c[t+20>>2]=p;c[p+24>>2]=t;break}}}else{p=c[a+(f+8)>>2]|0;m=c[a+(f+12)>>2]|0;j=2928+(i<<1<<2)|0;if((p|0)!=(j|0)){if(p>>>0<h>>>0)Ea();if((c[p+12>>2]|0)!=(g|0))Ea()}if((m|0)==(p|0)){c[722]=c[722]&~(1<<i);break}if((m|0)!=(j|0)){if(m>>>0<h>>>0)Ea();j=m+8|0;if((c[j>>2]|0)==(g|0))y=j;else Ea()}else y=m+8|0;c[p+12>>2]=m;c[y>>2]=p}while(0);if(o>>>0<16){c[d>>2]=n|e&1|2;y=a+(n|4)|0;c[y>>2]=c[y>>2]|1;l=a;return l|0}else{c[d>>2]=e&1|b|2;c[a+(b+4)>>2]=o|3;e=a+(n|4)|0;c[e>>2]=c[e>>2]|1;De(a+b|0,o);l=a;return l|0}return 0}function De(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0;d=a+b|0;e=c[a+4>>2]|0;do if(!(e&1)){f=c[a>>2]|0;if(!(e&3))return;g=a+(0-f)|0;h=f+b|0;i=c[726]|0;if(g>>>0<i>>>0)Ea();if((g|0)==(c[727]|0)){j=a+(b+4)|0;k=c[j>>2]|0;if((k&3|0)!=3){l=g;m=h;break}c[724]=h;c[j>>2]=k&-2;c[a+(4-f)>>2]=h|1;c[d>>2]=h;return}k=f>>>3;if(f>>>0<256){j=c[a+(8-f)>>2]|0;n=c[a+(12-f)>>2]|0;o=2928+(k<<1<<2)|0;if((j|0)!=(o|0)){if(j>>>0<i>>>0)Ea();if((c[j+12>>2]|0)!=(g|0))Ea()}if((n|0)==(j|0)){c[722]=c[722]&~(1<<k);l=g;m=h;break}if((n|0)!=(o|0)){if(n>>>0<i>>>0)Ea();o=n+8|0;if((c[o>>2]|0)==(g|0))p=o;else Ea()}else p=n+8|0;c[j+12>>2]=n;c[p>>2]=j;l=g;m=h;break}j=c[a+(24-f)>>2]|0;n=c[a+(12-f)>>2]|0;do if((n|0)==(g|0)){o=16-f|0;k=a+(o+4)|0;q=c[k>>2]|0;if(!q){r=a+o|0;o=c[r>>2]|0;if(!o){s=0;break}else{t=o;u=r}}else{t=q;u=k}while(1){k=t+20|0;q=c[k>>2]|0;if(q){t=q;u=k;continue}k=t+16|0;q=c[k>>2]|0;if(!q){v=t;w=u;break}else{t=q;u=k}}if(w>>>0<i>>>0)Ea();else{c[w>>2]=0;s=v;break}}else{k=c[a+(8-f)>>2]|0;if(k>>>0<i>>>0)Ea();q=k+12|0;if((c[q>>2]|0)!=(g|0))Ea();r=n+8|0;if((c[r>>2]|0)==(g|0)){c[q>>2]=n;c[r>>2]=k;s=n;break}else Ea()}while(0);if(j){n=c[a+(28-f)>>2]|0;i=3192+(n<<2)|0;if((g|0)==(c[i>>2]|0)){c[i>>2]=s;if(!s){c[723]=c[723]&~(1<<n);l=g;m=h;break}}else{if(j>>>0<(c[726]|0)>>>0)Ea();n=j+16|0;if((c[n>>2]|0)==(g|0))c[n>>2]=s;else c[j+20>>2]=s;if(!s){l=g;m=h;break}}n=c[726]|0;if(s>>>0<n>>>0)Ea();c[s+24>>2]=j;i=16-f|0;k=c[a+i>>2]|0;do if(k)if(k>>>0<n>>>0)Ea();else{c[s+16>>2]=k;c[k+24>>2]=s;break}while(0);k=c[a+(i+4)>>2]|0;if(k)if(k>>>0<(c[726]|0)>>>0)Ea();else{c[s+20>>2]=k;c[k+24>>2]=s;l=g;m=h;break}else{l=g;m=h}}else{l=g;m=h}}else{l=a;m=b}while(0);s=c[726]|0;if(d>>>0<s>>>0)Ea();v=a+(b+4)|0;w=c[v>>2]|0;if(!(w&2)){if((d|0)==(c[728]|0)){u=(c[725]|0)+m|0;c[725]=u;c[728]=l;c[l+4>>2]=u|1;if((l|0)!=(c[727]|0))return;c[727]=0;c[724]=0;return}if((d|0)==(c[727]|0)){u=(c[724]|0)+m|0;c[724]=u;c[727]=l;c[l+4>>2]=u|1;c[l+u>>2]=u;return}u=(w&-8)+m|0;t=w>>>3;do if(w>>>0>=256){p=c[a+(b+24)>>2]|0;e=c[a+(b+12)>>2]|0;do if((e|0)==(d|0)){k=a+(b+20)|0;n=c[k>>2]|0;if(!n){f=a+(b+16)|0;j=c[f>>2]|0;if(!j){x=0;break}else{y=j;z=f}}else{y=n;z=k}while(1){k=y+20|0;n=c[k>>2]|0;if(n){y=n;z=k;continue}k=y+16|0;n=c[k>>2]|0;if(!n){A=y;B=z;break}else{y=n;z=k}}if(B>>>0<s>>>0)Ea();else{c[B>>2]=0;x=A;break}}else{k=c[a+(b+8)>>2]|0;if(k>>>0<s>>>0)Ea();n=k+12|0;if((c[n>>2]|0)!=(d|0))Ea();f=e+8|0;if((c[f>>2]|0)==(d|0)){c[n>>2]=e;c[f>>2]=k;x=e;break}else Ea()}while(0);if(p){e=c[a+(b+28)>>2]|0;h=3192+(e<<2)|0;if((d|0)==(c[h>>2]|0)){c[h>>2]=x;if(!x){c[723]=c[723]&~(1<<e);break}}else{if(p>>>0<(c[726]|0)>>>0)Ea();e=p+16|0;if((c[e>>2]|0)==(d|0))c[e>>2]=x;else c[p+20>>2]=x;if(!x)break}e=c[726]|0;if(x>>>0<e>>>0)Ea();c[x+24>>2]=p;h=c[a+(b+16)>>2]|0;do if(h)if(h>>>0<e>>>0)Ea();else{c[x+16>>2]=h;c[h+24>>2]=x;break}while(0);h=c[a+(b+20)>>2]|0;if(h)if(h>>>0<(c[726]|0)>>>0)Ea();else{c[x+20>>2]=h;c[h+24>>2]=x;break}}}else{h=c[a+(b+8)>>2]|0;e=c[a+(b+12)>>2]|0;p=2928+(t<<1<<2)|0;if((h|0)!=(p|0)){if(h>>>0<s>>>0)Ea();if((c[h+12>>2]|0)!=(d|0))Ea()}if((e|0)==(h|0)){c[722]=c[722]&~(1<<t);break}if((e|0)!=(p|0)){if(e>>>0<s>>>0)Ea();p=e+8|0;if((c[p>>2]|0)==(d|0))C=p;else Ea()}else C=e+8|0;c[h+12>>2]=e;c[C>>2]=h}while(0);c[l+4>>2]=u|1;c[l+u>>2]=u;if((l|0)==(c[727]|0)){c[724]=u;return}else D=u}else{c[v>>2]=w&-2;c[l+4>>2]=m|1;c[l+m>>2]=m;D=m}m=D>>>3;if(D>>>0<256){w=m<<1;v=2928+(w<<2)|0;u=c[722]|0;C=1<<m;if(u&C){m=2928+(w+2<<2)|0;d=c[m>>2]|0;if(d>>>0<(c[726]|0)>>>0)Ea();else{E=m;F=d}}else{c[722]=u|C;E=2928+(w+2<<2)|0;F=v}c[E>>2]=l;c[F+12>>2]=l;c[l+8>>2]=F;c[l+12>>2]=v;return}v=D>>>8;if(v)if(D>>>0>16777215)G=31;else{F=(v+1048320|0)>>>16&8;E=v<<F;v=(E+520192|0)>>>16&4;w=E<<v;E=(w+245760|0)>>>16&2;C=14-(v|F|E)+(w<<E>>>15)|0;G=D>>>(C+7|0)&1|C<<1}else G=0;C=3192+(G<<2)|0;c[l+28>>2]=G;c[l+20>>2]=0;c[l+16>>2]=0;E=c[723]|0;w=1<<G;if(!(E&w)){c[723]=E|w;c[C>>2]=l;c[l+24>>2]=C;c[l+12>>2]=l;c[l+8>>2]=l;return}w=c[C>>2]|0;a:do if((c[w+4>>2]&-8|0)==(D|0))H=w;else{C=D<<((G|0)==31?0:25-(G>>>1)|0);E=w;while(1){F=E+16+(C>>>31<<2)|0;v=c[F>>2]|0;if(!v){I=F;J=E;break}if((c[v+4>>2]&-8|0)==(D|0)){H=v;break a}else{C=C<<1;E=v}}if(I>>>0<(c[726]|0)>>>0)Ea();c[I>>2]=l;c[l+24>>2]=J;c[l+12>>2]=l;c[l+8>>2]=l;return}while(0);J=H+8|0;I=c[J>>2]|0;D=c[726]|0;if(!(I>>>0>=D>>>0&H>>>0>=D>>>0))Ea();c[I+12>>2]=l;c[J>>2]=l;c[l+8>>2]=I;c[l+12>>2]=H;c[l+24>>2]=0;return}function Ee(){}function Fe(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){C=b>>c;return a>>>c|(b&(1<<c)-1)<<32-c}C=(b|0)<0?-1:0;return b>>c-32|0}function Ge(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=b-d>>>0;e=b-d-(c>>>0>a>>>0|0)>>>0;return (C=e,a-c>>>0|0)|0}function He(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=b+e|0;if((e|0)>=20){d=d&255;g=b&3;h=d|d<<8|d<<16|d<<24;i=f&~3;if(g){g=b+4-g|0;while((b|0)<(g|0)){a[b>>0]=d;b=b+1|0}}while((b|0)<(i|0)){c[b>>2]=h;b=b+4|0}}while((b|0)<(f|0)){a[b>>0]=d;b=b+1|0}return b-e|0}function Ie(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){C=b<<c|(a&(1<<c)-1<<32-c)>>>32-c;return a<<c}C=a<<c-32;return 0}function Je(b){b=b|0;var c=0;c=b;while(a[c>>0]|0)c=c+1|0;return c-b|0}function Ke(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if((e|0)>=4096)return sa(b|0,d|0,e|0)|0;f=b|0;if((b&3)==(d&3)){while(b&3){if(!e)return f|0;a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function Le(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0;while((e|0)<(d|0)){a[b+e>>0]=f?0:a[c+e>>0]|0;f=f?1:(a[c+e>>0]|0)==0;e=e+1|0}return b|0}function Me(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=a+c>>>0;return (C=b+d+(e>>>0<a>>>0|0)>>>0,e|0)|0}function Ne(b,c,d){b=b|0;c=c|0;d=d|0;var e=0;if((c|0)<(b|0)&(b|0)<(c+d|0)){e=b;c=c+d|0;b=b+d|0;while((d|0)>0){b=b-1|0;c=c-1|0;d=d-1|0;a[b>>0]=a[c>>0]|0}b=e}else Ke(b,c,d)|0;return b|0}function Oe(b,c){b=b|0;c=c|0;var d=0;do{a[b+d>>0]=a[c+d>>0];d=d+1|0}while(a[c+(d-1)>>0]|0);return b|0}function Pe(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){C=b>>>c;return a>>>c|(b&(1<<c)-1)<<32-c}C=0;return b>>>c-32|0}function Qe(b){b=b|0;var c=0;c=a[m+(b&255)>>0]|0;if((c|0)<8)return c|0;c=a[m+(b>>8&255)>>0]|0;if((c|0)<8)return c+8|0;c=a[m+(b>>16&255)>>0]|0;if((c|0)<8)return c+16|0;return (a[m+(b>>>24)>>0]|0)+24|0}function Re(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;c=a&65535;d=b&65535;e=_(d,c)|0;f=a>>>16;a=(e>>>16)+(_(d,f)|0)|0;d=b>>>16;b=_(d,c)|0;return (C=(a>>>16)+(_(d,f)|0)+(((a&65535)+b|0)>>>16)|0,a+b<<16|e&65535|0)|0}function Se(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;e=b>>31|((b|0)<0?-1:0)<<1;f=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;g=d>>31|((d|0)<0?-1:0)<<1;h=((d|0)<0?-1:0)>>31|((d|0)<0?-1:0)<<1;i=Ge(e^a,f^b,e,f)|0;b=C;a=g^e;e=h^f;return Ge((Xe(i,b,Ge(g^c,h^d,g,h)|0,C,0)|0)^a,C^e,a,e)|0}function Te(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0;f=i;i=i+8|0;g=f|0;h=b>>31|((b|0)<0?-1:0)<<1;j=((b|0)<0?-1:0)>>31|((b|0)<0?-1:0)<<1;k=e>>31|((e|0)<0?-1:0)<<1;l=((e|0)<0?-1:0)>>31|((e|0)<0?-1:0)<<1;m=Ge(h^a,j^b,h,j)|0;b=C;Xe(m,b,Ge(k^d,l^e,k,l)|0,C,g)|0;l=Ge(c[g>>2]^h,c[g+4>>2]^j,h,j)|0;j=C;i=f;return (C=j,l)|0}function Ue(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=a;a=c;c=Re(e,a)|0;f=C;return (C=(_(b,a)|0)+(_(d,e)|0)+f|f&0,c|0|0)|0}function Ve(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return Xe(a,b,c,d,0)|0}function We(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=i;i=i+8|0;g=f|0;Xe(a,b,d,e,g)|0;i=f;return (C=c[g+4>>2]|0,c[g>>2]|0)|0}function Xe(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,D=0,E=0,F=0,G=0,H=0;g=a;h=b;i=h;j=d;k=e;l=k;if(!i){m=(f|0)!=0;if(!l){if(m){c[f>>2]=(g>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(g>>>0)/(j>>>0)>>>0;return (C=n,o)|0}else{if(!m){n=0;o=0;return (C=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=b&0;n=0;o=0;return (C=n,o)|0}}m=(l|0)==0;do if(j){if(!m){p=(aa(l|0)|0)-(aa(i|0)|0)|0;if(p>>>0<=31){q=p+1|0;r=31-p|0;s=p-31>>31;t=q;u=g>>>(q>>>0)&s|i<<r;v=i>>>(q>>>0)&s;w=0;x=g<<r;break}if(!f){n=0;o=0;return (C=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return (C=n,o)|0}r=j-1|0;if(r&j){s=(aa(j|0)|0)+33-(aa(i|0)|0)|0;q=64-s|0;p=32-s|0;y=p>>31;z=s-32|0;A=z>>31;t=s;u=p-1>>31&i>>>(z>>>0)|(i<<p|g>>>(s>>>0))&A;v=A&i>>>(s>>>0);w=g<<q&y;x=(i<<q|g>>>(z>>>0))&y|g<<p&s-33>>31;break}if(f){c[f>>2]=r&g;c[f+4>>2]=0}if((j|0)==1){n=h|b&0;o=a|0|0;return (C=n,o)|0}else{r=Qe(j|0)|0;n=i>>>(r>>>0)|0;o=i<<32-r|g>>>(r>>>0)|0;return (C=n,o)|0}}else{if(m){if(f){c[f>>2]=(i>>>0)%(j>>>0);c[f+4>>2]=0}n=0;o=(i>>>0)/(j>>>0)>>>0;return (C=n,o)|0}if(!g){if(f){c[f>>2]=0;c[f+4>>2]=(i>>>0)%(l>>>0)}n=0;o=(i>>>0)/(l>>>0)>>>0;return (C=n,o)|0}r=l-1|0;if(!(r&l)){if(f){c[f>>2]=a|0;c[f+4>>2]=r&i|b&0}n=0;o=i>>>((Qe(l|0)|0)>>>0);return (C=n,o)|0}r=(aa(l|0)|0)-(aa(i|0)|0)|0;if(r>>>0<=30){s=r+1|0;p=31-r|0;t=s;u=i<<p|g>>>(s>>>0);v=i>>>(s>>>0);w=0;x=g<<p;break}if(!f){n=0;o=0;return (C=n,o)|0}c[f>>2]=a|0;c[f+4>>2]=h|b&0;n=0;o=0;return (C=n,o)|0}while(0);if(!t){B=x;D=w;E=v;F=u;G=0;H=0}else{b=d|0|0;d=k|e&0;e=Me(b|0,d|0,-1,-1)|0;k=C;h=x;x=w;w=v;v=u;u=t;t=0;do{a=h;h=x>>>31|h<<1;x=t|x<<1;g=v<<1|a>>>31|0;a=v>>>31|w<<1|0;Ge(e,k,g,a)|0;i=C;l=i>>31|((i|0)<0?-1:0)<<1;t=l&1;v=Ge(g,a,l&b,(((i|0)<0?-1:0)>>31|((i|0)<0?-1:0)<<1)&d)|0;w=C;u=u-1|0}while((u|0)!=0);B=h;D=x;E=w;F=v;G=0;H=t}t=D;D=0;if(f){c[f>>2]=F;c[f+4>>2]=E}n=(t|0)>>>31|(B|D)<<1|(D<<1|t>>>31)&0|G;o=(t<<1|0>>>31)&-2|H;return (C=n,o)|0}function Ye(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return La[a&1](b|0,c|0,d|0)|0}function Ze(a,b){a=a|0;b=b|0;Ma[a&1](b|0)}function _e(a,b){a=a|0;b=b|0;return Na[a&7](b|0)|0}function $e(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return Oa[a&15](b|0,c|0,d|0,e|0)|0}function af(a,b,c){a=a|0;b=b|0;c=c|0;return Pa[a&1](b|0,c|0)|0}function bf(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return Qa[a&31](b|0,c|0,d|0,e|0,f|0)|0}function cf(a,b,c){a=a|0;b=b|0;c=c|0;ba(0);return 0}function df(a){a=a|0;ba(1)}function ef(a){a=a|0;ba(2);return 0}function ff(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;ba(3);return 0}function gf(a,b){a=a|0;b=b|0;ba(4);return 0}function hf(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;ba(5);return 0}
+
+// EMSCRIPTEN_END_FUNCS
+var La=[cf,wc];var Ma=[df,xc];var Na=[ef,tc,Jb,Kb,Lb,Vc,Nb,ef];var Oa=[ff,_c,cd,fd,md,rd,wd,Ad,pe,ff,ff,ff,ff,ff,ff,ff];var Pa=[gf,uc];var Qa=[hf,Xc,$c,ad,dd,ed,gd,hd,jd,kd,ld,nd,pd,qd,sd,td,ud,yd,zd,Cd,Dd,Ed,Fd,hf,hf,hf,hf,hf,hf,hf,hf,hf];return{_i64Subtract:Ge,_ogv_demuxer_keypoint_offset:ne,_memset:He,_ogv_demuxer_process:ie,_strncpy:Le,_ogv_demuxer_flush:oe,_bitshift64Ashr:Fe,_ogv_demuxer_init:he,_strlen:Je,_ogv_demuxer_destroy:je,_malloc:ye,_i64Add:Me,_ogv_demuxer_seekable:me,_ogv_demuxer_media_duration:le,_ogv_demuxer_media_length:ke,_memmove:Ne,_free:ze,_memcpy:Ke,_strcpy:Oe,_bitshift64Shl:Ie,runPostSets:Ee,stackAlloc:Ra,stackSave:Sa,stackRestore:Ta,establishStackSpace:Ua,setThrew:Va,setTempRet0:Ya,getTempRet0:Za,dynCall_iiii:Ye,dynCall_vi:Ze,dynCall_ii:_e,dynCall_iiiii:$e,dynCall_iii:af,dynCall_iiiiii:bf}})
+
+
+// EMSCRIPTEN_END_ASM
+(Module.asmGlobalArg,Module.asmLibraryArg,buffer);var runPostSets=Module["runPostSets"]=asm["runPostSets"];var _i64Subtract=Module["_i64Subtract"]=asm["_i64Subtract"];var _ogv_demuxer_keypoint_offset=Module["_ogv_demuxer_keypoint_offset"]=asm["_ogv_demuxer_keypoint_offset"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _ogv_demuxer_process=Module["_ogv_demuxer_process"]=asm["_ogv_demuxer_process"];var _strncpy=Module["_strncpy"]=asm["_strncpy"];var _ogv_demuxer_flush=Module["_ogv_demuxer_flush"]=asm["_ogv_demuxer_flush"];var _bitshift64Ashr=Module["_bitshift64Ashr"]=asm["_bitshift64Ashr"];var _ogv_demuxer_init=Module["_ogv_demuxer_init"]=asm["_ogv_demuxer_init"];var _memset=Module["_memset"]=asm["_memset"];var _ogv_demuxer_destroy=Module["_ogv_demuxer_destroy"]=asm["_ogv_demuxer_destroy"];var _malloc=Module["_malloc"]=asm["_malloc"];var _i64Add=Module["_i64Add"]=asm["_i64Add"];var _ogv_demuxer_seekable=Module["_ogv_demuxer_seekable"]=asm["_ogv_demuxer_seekable"];var _ogv_demuxer_media_duration=Module["_ogv_demuxer_media_duration"]=asm["_ogv_demuxer_media_duration"];var _strlen=Module["_strlen"]=asm["_strlen"];var _ogv_demuxer_media_length=Module["_ogv_demuxer_media_length"]=asm["_ogv_demuxer_media_length"];var _memmove=Module["_memmove"]=asm["_memmove"];var _free=Module["_free"]=asm["_free"];var _strcpy=Module["_strcpy"]=asm["_strcpy"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var dynCall_iiii=Module["dynCall_iiii"]=asm["dynCall_iiii"];var dynCall_vi=Module["dynCall_vi"]=asm["dynCall_vi"];var dynCall_ii=Module["dynCall_ii"]=asm["dynCall_ii"];var dynCall_iiiii=Module["dynCall_iiiii"]=asm["dynCall_iiiii"];var dynCall_iii=Module["dynCall_iii"]=asm["dynCall_iii"];var dynCall_iiiiii=Module["dynCall_iiiiii"]=asm["dynCall_iiiiii"];Runtime.stackAlloc=asm["stackAlloc"];Runtime.stackSave=asm["stackSave"];Runtime.stackRestore=asm["stackRestore"];Runtime.establishStackSpace=asm["establishStackSpace"];Runtime.setTempRet0=asm["setTempRet0"];Runtime.getTempRet0=asm["getTempRet0"];var i64Math=(function(){var goog={math:{}};goog.math.Long=(function(low,high){this.low_=low|0;this.high_=high|0});goog.math.Long.IntCache_={};goog.math.Long.fromInt=(function(value){if(-128<=value&&value<128){var cachedObj=goog.math.Long.IntCache_[value];if(cachedObj){return cachedObj}}var obj=new goog.math.Long(value|0,value<0?-1:0);if(-128<=value&&value<128){goog.math.Long.IntCache_[value]=obj}return obj});goog.math.Long.fromNumber=(function(value){if(isNaN(value)||!isFinite(value)){return goog.math.Long.ZERO}else if(value<=-goog.math.Long.TWO_PWR_63_DBL_){return goog.math.Long.MIN_VALUE}else if(value+1>=goog.math.Long.TWO_PWR_63_DBL_){return goog.math.Long.MAX_VALUE}else if(value<0){return goog.math.Long.fromNumber(-value).negate()}else{return new goog.math.Long(value%goog.math.Long.TWO_PWR_32_DBL_|0,value/goog.math.Long.TWO_PWR_32_DBL_|0)}});goog.math.Long.fromBits=(function(lowBits,highBits){return new goog.math.Long(lowBits,highBits)});goog.math.Long.fromString=(function(str,opt_radix){if(str.length==0){throw Error("number format error: empty string")}var radix=opt_radix||10;if(radix<2||36<radix){throw Error("radix out of range: "+radix)}if(str.charAt(0)=="-"){return goog.math.Long.fromString(str.substring(1),radix).negate()}else if(str.indexOf("-")>=0){throw Error('number format error: interior "-" character: '+str)}var radixToPower=goog.math.Long.fromNumber(Math.pow(radix,8));var result=goog.math.Long.ZERO;for(var i=0;i<str.length;i+=8){var size=Math.min(8,str.length-i);var value=parseInt(str.substring(i,i+size),radix);if(size<8){var power=goog.math.Long.fromNumber(Math.pow(radix,size));result=result.multiply(power).add(goog.math.Long.fromNumber(value))}else{result=result.multiply(radixToPower);result=result.add(goog.math.Long.fromNumber(value))}}return result});goog.math.Long.TWO_PWR_16_DBL_=1<<16;goog.math.Long.TWO_PWR_24_DBL_=1<<24;goog.math.Long.TWO_PWR_32_DBL_=goog.math.Long.TWO_PWR_16_DBL_*goog.math.Long.TWO_PWR_16_DBL_;goog.math.Long.TWO_PWR_31_DBL_=goog.math.Long.TWO_PWR_32_DBL_/2;goog.math.Long.TWO_PWR_48_DBL_=goog.math.Long.TWO_PWR_32_DBL_*goog.math.Long.TWO_PWR_16_DBL_;goog.math.Long.TWO_PWR_64_DBL_=goog.math.Long.TWO_PWR_32_DBL_*goog.math.Long.TWO_PWR_32_DBL_;goog.math.Long.TWO_PWR_63_DBL_=goog.math.Long.TWO_PWR_64_DBL_/2;goog.math.Long.ZERO=goog.math.Long.fromInt(0);goog.math.Long.ONE=goog.math.Long.fromInt(1);goog.math.Long.NEG_ONE=goog.math.Long.fromInt(-1);goog.math.Long.MAX_VALUE=goog.math.Long.fromBits(4294967295|0,2147483647|0);goog.math.Long.MIN_VALUE=goog.math.Long.fromBits(0,2147483648|0);goog.math.Long.TWO_PWR_24_=goog.math.Long.fromInt(1<<24);goog.math.Long.prototype.toInt=(function(){return this.low_});goog.math.Long.prototype.toNumber=(function(){return this.high_*goog.math.Long.TWO_PWR_32_DBL_+this.getLowBitsUnsigned()});goog.math.Long.prototype.toString=(function(opt_radix){var radix=opt_radix||10;if(radix<2||36<radix){throw Error("radix out of range: "+radix)}if(this.isZero()){return"0"}if(this.isNegative()){if(this.equals(goog.math.Long.MIN_VALUE)){var radixLong=goog.math.Long.fromNumber(radix);var div=this.div(radixLong);var rem=div.multiply(radixLong).subtract(this);return div.toString(radix)+rem.toInt().toString(radix)}else{return"-"+this.negate().toString(radix)}}var radixToPower=goog.math.Long.fromNumber(Math.pow(radix,6));var rem=this;var result="";while(true){var remDiv=rem.div(radixToPower);var intval=rem.subtract(remDiv.multiply(radixToPower)).toInt();var digits=intval.toString(radix);rem=remDiv;if(rem.isZero()){return digits+result}else{while(digits.length<6){digits="0"+digits}result=""+digits+result}}});goog.math.Long.prototype.getHighBits=(function(){return this.high_});goog.math.Long.prototype.getLowBits=(function(){return this.low_});goog.math.Long.prototype.getLowBitsUnsigned=(function(){return this.low_>=0?this.low_:goog.math.Long.TWO_PWR_32_DBL_+this.low_});goog.math.Long.prototype.getNumBitsAbs=(function(){if(this.isNegative()){if(this.equals(goog.math.Long.MIN_VALUE)){return 64}else{return this.negate().getNumBitsAbs()}}else{var val=this.high_!=0?this.high_:this.low_;for(var bit=31;bit>0;bit--){if((val&1<<bit)!=0){break}}return this.high_!=0?bit+33:bit+1}});goog.math.Long.prototype.isZero=(function(){return this.high_==0&&this.low_==0});goog.math.Long.prototype.isNegative=(function(){return this.high_<0});goog.math.Long.prototype.isOdd=(function(){return(this.low_&1)==1});goog.math.Long.prototype.equals=(function(other){return this.high_==other.high_&&this.low_==other.low_});goog.math.Long.prototype.notEquals=(function(other){return this.high_!=other.high_||this.low_!=other.low_});goog.math.Long.prototype.lessThan=(function(other){return this.compare(other)<0});goog.math.Long.prototype.lessThanOrEqual=(function(other){return this.compare(other)<=0});goog.math.Long.prototype.greaterThan=(function(other){return this.compare(other)>0});goog.math.Long.prototype.greaterThanOrEqual=(function(other){return this.compare(other)>=0});goog.math.Long.prototype.compare=(function(other){if(this.equals(other)){return 0}var thisNeg=this.isNegative();var otherNeg=other.isNegative();if(thisNeg&&!otherNeg){return-1}if(!thisNeg&&otherNeg){return 1}if(this.subtract(other).isNegative()){return-1}else{return 1}});goog.math.Long.prototype.negate=(function(){if(this.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.MIN_VALUE}else{return this.not().add(goog.math.Long.ONE)}});goog.math.Long.prototype.add=(function(other){var a48=this.high_>>>16;var a32=this.high_&65535;var a16=this.low_>>>16;var a00=this.low_&65535;var b48=other.high_>>>16;var b32=other.high_&65535;var b16=other.low_>>>16;var b00=other.low_&65535;var c48=0,c32=0,c16=0,c00=0;c00+=a00+b00;c16+=c00>>>16;c00&=65535;c16+=a16+b16;c32+=c16>>>16;c16&=65535;c32+=a32+b32;c48+=c32>>>16;c32&=65535;c48+=a48+b48;c48&=65535;return goog.math.Long.fromBits(c16<<16|c00,c48<<16|c32)});goog.math.Long.prototype.subtract=(function(other){return this.add(other.negate())});goog.math.Long.prototype.multiply=(function(other){if(this.isZero()){return goog.math.Long.ZERO}else if(other.isZero()){return goog.math.Long.ZERO}if(this.equals(goog.math.Long.MIN_VALUE)){return other.isOdd()?goog.math.Long.MIN_VALUE:goog.math.Long.ZERO}else if(other.equals(goog.math.Long.MIN_VALUE)){return this.isOdd()?goog.math.Long.MIN_VALUE:goog.math.Long.ZERO}if(this.isNegative()){if(other.isNegative()){return this.negate().multiply(other.negate())}else{return this.negate().multiply(other).negate()}}else if(other.isNegative()){return this.multiply(other.negate()).negate()}if(this.lessThan(goog.math.Long.TWO_PWR_24_)&&other.lessThan(goog.math.Long.TWO_PWR_24_)){return goog.math.Long.fromNumber(this.toNumber()*other.toNumber())}var a48=this.high_>>>16;var a32=this.high_&65535;var a16=this.low_>>>16;var a00=this.low_&65535;var b48=other.high_>>>16;var b32=other.high_&65535;var b16=other.low_>>>16;var b00=other.low_&65535;var c48=0,c32=0,c16=0,c00=0;c00+=a00*b00;c16+=c00>>>16;c00&=65535;c16+=a16*b00;c32+=c16>>>16;c16&=65535;c16+=a00*b16;c32+=c16>>>16;c16&=65535;c32+=a32*b00;c48+=c32>>>16;c32&=65535;c32+=a16*b16;c48+=c32>>>16;c32&=65535;c32+=a00*b32;c48+=c32>>>16;c32&=65535;c48+=a48*b00+a32*b16+a16*b32+a00*b48;c48&=65535;return goog.math.Long.fromBits(c16<<16|c00,c48<<16|c32)});goog.math.Long.prototype.div=(function(other){if(other.isZero()){throw Error("division by zero")}else if(this.isZero()){return goog.math.Long.ZERO}if(this.equals(goog.math.Long.MIN_VALUE)){if(other.equals(goog.math.Long.ONE)||other.equals(goog.math.Long.NEG_ONE)){return goog.math.Long.MIN_VALUE}else if(other.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.ONE}else{var halfThis=this.shiftRight(1);var approx=halfThis.div(other).shiftLeft(1);if(approx.equals(goog.math.Long.ZERO)){return other.isNegative()?goog.math.Long.ONE:goog.math.Long.NEG_ONE}else{var rem=this.subtract(other.multiply(approx));var result=approx.add(rem.div(other));return result}}}else if(other.equals(goog.math.Long.MIN_VALUE)){return goog.math.Long.ZERO}if(this.isNegative()){if(other.isNegative()){return this.negate().div(other.negate())}else{return this.negate().div(other).negate()}}else if(other.isNegative()){return this.div(other.negate()).negate()}var res=goog.math.Long.ZERO;var rem=this;while(rem.greaterThanOrEqual(other)){var approx=Math.max(1,Math.floor(rem.toNumber()/other.toNumber()));var log2=Math.ceil(Math.log(approx)/Math.LN2);var delta=log2<=48?1:Math.pow(2,log2-48);var approxRes=goog.math.Long.fromNumber(approx);var approxRem=approxRes.multiply(other);while(approxRem.isNegative()||approxRem.greaterThan(rem)){approx-=delta;approxRes=goog.math.Long.fromNumber(approx);approxRem=approxRes.multiply(other)}if(approxRes.isZero()){approxRes=goog.math.Long.ONE}res=res.add(approxRes);rem=rem.subtract(approxRem)}return res});goog.math.Long.prototype.modulo=(function(other){return this.subtract(this.div(other).multiply(other))});goog.math.Long.prototype.not=(function(){return goog.math.Long.fromBits(~this.low_,~this.high_)});goog.math.Long.prototype.and=(function(other){return goog.math.Long.fromBits(this.low_&other.low_,this.high_&other.high_)});goog.math.Long.prototype.or=(function(other){return goog.math.Long.fromBits(this.low_|other.low_,this.high_|other.high_)});goog.math.Long.prototype.xor=(function(other){return goog.math.Long.fromBits(this.low_^other.low_,this.high_^other.high_)});goog.math.Long.prototype.shiftLeft=(function(numBits){numBits&=63;if(numBits==0){return this}else{var low=this.low_;if(numBits<32){var high=this.high_;return goog.math.Long.fromBits(low<<numBits,high<<numBits|low>>>32-numBits)}else{return goog.math.Long.fromBits(0,low<<numBits-32)}}});goog.math.Long.prototype.shiftRight=(function(numBits){numBits&=63;if(numBits==0){return this}else{var high=this.high_;if(numBits<32){var low=this.low_;return goog.math.Long.fromBits(low>>>numBits|high<<32-numBits,high>>numBits)}else{return goog.math.Long.fromBits(high>>numBits-32,high>=0?0:-1)}}});goog.math.Long.prototype.shiftRightUnsigned=(function(numBits){numBits&=63;if(numBits==0){return this}else{var high=this.high_;if(numBits<32){var low=this.low_;return goog.math.Long.fromBits(low>>>numBits|high<<32-numBits,high>>>numBits)}else if(numBits==32){return goog.math.Long.fromBits(high,0)}else{return goog.math.Long.fromBits(high>>>numBits-32,0)}}});var navigator={appName:"Modern Browser"};var dbits;var canary=0xdeadbeefcafe;var j_lm=(canary&16777215)==15715070;function BigInteger(a,b,c){if(a!=null)if("number"==typeof a)this.fromNumber(a,b,c);else if(b==null&&"string"!=typeof a)this.fromString(a,256);else this.fromString(a,b)}function nbi(){return new BigInteger(null)}function am1(i,x,w,j,c,n){while(--n>=0){var v=x*this[i++]+w[j]+c;c=Math.floor(v/67108864);w[j++]=v&67108863}return c}function am2(i,x,w,j,c,n){var xl=x&32767,xh=x>>15;while(--n>=0){var l=this[i]&32767;var h=this[i++]>>15;var m=xh*l+h*xl;l=xl*l+((m&32767)<<15)+w[j]+(c&1073741823);c=(l>>>30)+(m>>>15)+xh*h+(c>>>30);w[j++]=l&1073741823}return c}function am3(i,x,w,j,c,n){var xl=x&16383,xh=x>>14;while(--n>=0){var l=this[i]&16383;var h=this[i++]>>14;var m=xh*l+h*xl;l=xl*l+((m&16383)<<14)+w[j]+c;c=(l>>28)+(m>>14)+xh*h;w[j++]=l&268435455}return c}if(j_lm&&navigator.appName=="Microsoft Internet Explorer"){BigInteger.prototype.am=am2;dbits=30}else if(j_lm&&navigator.appName!="Netscape"){BigInteger.prototype.am=am1;dbits=26}else{BigInteger.prototype.am=am3;dbits=28}BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=(1<<dbits)-1;BigInteger.prototype.DV=1<<dbits;var BI_FP=52;BigInteger.prototype.FV=Math.pow(2,BI_FP);BigInteger.prototype.F1=BI_FP-dbits;BigInteger.prototype.F2=2*dbits-BI_FP;var BI_RM="0123456789abcdefghijklmnopqrstuvwxyz";var BI_RC=new Array;var rr,vv;rr="0".charCodeAt(0);for(vv=0;vv<=9;++vv)BI_RC[rr++]=vv;rr="a".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;rr="A".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;function int2char(n){return BI_RM.charAt(n)}function intAt(s,i){var c=BI_RC[s.charCodeAt(i)];return c==null?-1:c}function bnpCopyTo(r){for(var i=this.t-1;i>=0;--i)r[i]=this[i];r.t=this.t;r.s=this.s}function bnpFromInt(x){this.t=1;this.s=x<0?-1:0;if(x>0)this[0]=x;else if(x<-1)this[0]=x+DV;else this.t=0}function nbv(i){var r=nbi();r.fromInt(i);return r}function bnpFromString(s,b){var k;if(b==16)k=4;else if(b==8)k=3;else if(b==256)k=8;else if(b==2)k=1;else if(b==32)k=5;else if(b==4)k=2;else{this.fromRadix(s,b);return}this.t=0;this.s=0;var i=s.length,mi=false,sh=0;while(--i>=0){var x=k==8?s[i]&255:intAt(s,i);if(x<0){if(s.charAt(i)=="-")mi=true;continue}mi=false;if(sh==0)this[this.t++]=x;else if(sh+k>this.DB){this[this.t-1]|=(x&(1<<this.DB-sh)-1)<<sh;this[this.t++]=x>>this.DB-sh}else this[this.t-1]|=x<<sh;sh+=k;if(sh>=this.DB)sh-=this.DB}if(k==8&&(s[0]&128)!=0){this.s=-1;if(sh>0)this[this.t-1]|=(1<<this.DB-sh)-1<<sh}this.clamp();if(mi)BigInteger.ZERO.subTo(this,this)}function bnpClamp(){var c=this.s&this.DM;while(this.t>0&&this[this.t-1]==c)--this.t}function bnToString(b){if(this.s<0)return"-"+this.negate().toString(b);var k;if(b==16)k=4;else if(b==8)k=3;else if(b==2)k=1;else if(b==32)k=5;else if(b==4)k=2;else return this.toRadix(b);var km=(1<<k)-1,d,m=false,r="",i=this.t;var p=this.DB-i*this.DB%k;if(i-->0){if(p<this.DB&&(d=this[i]>>p)>0){m=true;r=int2char(d)}while(i>=0){if(p<k){d=(this[i]&(1<<p)-1)<<k-p;d|=this[--i]>>(p+=this.DB-k)}else{d=this[i]>>(p-=k)&km;if(p<=0){p+=this.DB;--i}}if(d>0)m=true;if(m)r+=int2char(d)}}return m?r:"0"}function bnNegate(){var r=nbi();BigInteger.ZERO.subTo(this,r);return r}function bnAbs(){return this.s<0?this.negate():this}function bnCompareTo(a){var r=this.s-a.s;if(r!=0)return r;var i=this.t;r=i-a.t;if(r!=0)return this.s<0?-r:r;while(--i>=0)if((r=this[i]-a[i])!=0)return r;return 0}function nbits(x){var r=1,t;if((t=x>>>16)!=0){x=t;r+=16}if((t=x>>8)!=0){x=t;r+=8}if((t=x>>4)!=0){x=t;r+=4}if((t=x>>2)!=0){x=t;r+=2}if((t=x>>1)!=0){x=t;r+=1}return r}function bnBitLength(){if(this.t<=0)return 0;return this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(n,r){var i;for(i=this.t-1;i>=0;--i)r[i+n]=this[i];for(i=n-1;i>=0;--i)r[i]=0;r.t=this.t+n;r.s=this.s}function bnpDRShiftTo(n,r){for(var i=n;i<this.t;++i)r[i-n]=this[i];r.t=Math.max(this.t-n,0);r.s=this.s}function bnpLShiftTo(n,r){var bs=n%this.DB;var cbs=this.DB-bs;var bm=(1<<cbs)-1;var ds=Math.floor(n/this.DB),c=this.s<<bs&this.DM,i;for(i=this.t-1;i>=0;--i){r[i+ds+1]=this[i]>>cbs|c;c=(this[i]&bm)<<bs}for(i=ds-1;i>=0;--i)r[i]=0;r[ds]=c;r.t=this.t+ds+1;r.s=this.s;r.clamp()}function bnpRShiftTo(n,r){r.s=this.s;var ds=Math.floor(n/this.DB);if(ds>=this.t){r.t=0;return}var bs=n%this.DB;var cbs=this.DB-bs;var bm=(1<<bs)-1;r[0]=this[ds]>>bs;for(var i=ds+1;i<this.t;++i){r[i-ds-1]|=(this[i]&bm)<<cbs;r[i-ds]=this[i]>>bs}if(bs>0)r[this.t-ds-1]|=(this.s&bm)<<cbs;r.t=this.t-ds;r.clamp()}function bnpSubTo(a,r){var i=0,c=0,m=Math.min(a.t,this.t);while(i<m){c+=this[i]-a[i];r[i++]=c&this.DM;c>>=this.DB}if(a.t<this.t){c-=a.s;while(i<this.t){c+=this[i];r[i++]=c&this.DM;c>>=this.DB}c+=this.s}else{c+=this.s;while(i<a.t){c-=a[i];r[i++]=c&this.DM;c>>=this.DB}c-=a.s}r.s=c<0?-1:0;if(c<-1)r[i++]=this.DV+c;else if(c>0)r[i++]=c;r.t=i;r.clamp()}function bnpMultiplyTo(a,r){var x=this.abs(),y=a.abs();var i=x.t;r.t=i+y.t;while(--i>=0)r[i]=0;for(i=0;i<y.t;++i)r[i+x.t]=x.am(0,y[i],r,i,0,x.t);r.s=0;r.clamp();if(this.s!=a.s)BigInteger.ZERO.subTo(r,r)}function bnpSquareTo(r){var x=this.abs();var i=r.t=2*x.t;while(--i>=0)r[i]=0;for(i=0;i<x.t-1;++i){var c=x.am(i,x[i],r,2*i,0,1);if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1))>=x.DV){r[i+x.t]-=x.DV;r[i+x.t+1]=1}}if(r.t>0)r[r.t-1]+=x.am(i,x[i],r,2*i,0,1);r.s=0;r.clamp()}function bnpDivRemTo(m,q,r){var pm=m.abs();if(pm.t<=0)return;var pt=this.abs();if(pt.t<pm.t){if(q!=null)q.fromInt(0);if(r!=null)this.copyTo(r);return}if(r==null)r=nbi();var y=nbi(),ts=this.s,ms=m.s;var nsh=this.DB-nbits(pm[pm.t-1]);if(nsh>0){pm.lShiftTo(nsh,y);pt.lShiftTo(nsh,r)}else{pm.copyTo(y);pt.copyTo(r)}var ys=y.t;var y0=y[ys-1];if(y0==0)return;var yt=y0*(1<<this.F1)+(ys>1?y[ys-2]>>this.F2:0);var d1=this.FV/yt,d2=(1<<this.F1)/yt,e=1<<this.F2;var i=r.t,j=i-ys,t=q==null?nbi():q;y.dlShiftTo(j,t);if(r.compareTo(t)>=0){r[r.t++]=1;r.subTo(t,r)}BigInteger.ONE.dlShiftTo(ys,t);t.subTo(y,y);while(y.t<ys)y[y.t++]=0;while(--j>=0){var qd=r[--i]==y0?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);if((r[i]+=y.am(0,qd,r,j,0,ys))<qd){y.dlShiftTo(j,t);r.subTo(t,r);while(r[i]<--qd)r.subTo(t,r)}}if(q!=null){r.drShiftTo(ys,q);if(ts!=ms)BigInteger.ZERO.subTo(q,q)}r.t=ys;r.clamp();if(nsh>0)r.rShiftTo(nsh,r);if(ts<0)BigInteger.ZERO.subTo(r,r)}function bnMod(a){var r=nbi();this.abs().divRemTo(a,null,r);if(this.s<0&&r.compareTo(BigInteger.ZERO)>0)a.subTo(r,r);return r}function Classic(m){this.m=m}function cConvert(x){if(x.s<0||x.compareTo(this.m)>=0)return x.mod(this.m);else return x}function cRevert(x){return x}function cReduce(x){x.divRemTo(this.m,null,x)}function cMulTo(x,y,r){x.multiplyTo(y,r);this.reduce(r)}function cSqrTo(x,r){x.squareTo(r);this.reduce(r)}Classic.prototype.convert=cConvert;Classic.prototype.revert=cRevert;Classic.prototype.reduce=cReduce;Classic.prototype.mulTo=cMulTo;Classic.prototype.sqrTo=cSqrTo;function bnpInvDigit(){if(this.t<1)return 0;var x=this[0];if((x&1)==0)return 0;var y=x&3;y=y*(2-(x&15)*y)&15;y=y*(2-(x&255)*y)&255;y=y*(2-((x&65535)*y&65535))&65535;y=y*(2-x*y%this.DV)%this.DV;return y>0?this.DV-y:-y}function Montgomery(m){this.m=m;this.mp=m.invDigit();this.mpl=this.mp&32767;this.mph=this.mp>>15;this.um=(1<<m.DB-15)-1;this.mt2=2*m.t}function montConvert(x){var r=nbi();x.abs().dlShiftTo(this.m.t,r);r.divRemTo(this.m,null,r);if(x.s<0&&r.compareTo(BigInteger.ZERO)>0)this.m.subTo(r,r);return r}function montRevert(x){var r=nbi();x.copyTo(r);this.reduce(r);return r}function montReduce(x){while(x.t<=this.mt2)x[x.t++]=0;for(var i=0;i<this.m.t;++i){var j=x[i]&32767;var u0=j*this.mpl+((j*this.mph+(x[i]>>15)*this.mpl&this.um)<<15)&x.DM;j=i+this.m.t;x[j]+=this.m.am(0,u0,x,i,0,this.m.t);while(x[j]>=x.DV){x[j]-=x.DV;x[++j]++}}x.clamp();x.drShiftTo(this.m.t,x);if(x.compareTo(this.m)>=0)x.subTo(this.m,x)}function montSqrTo(x,r){x.squareTo(r);this.reduce(r)}function montMulTo(x,y,r){x.multiplyTo(y,r);this.reduce(r)}Montgomery.prototype.convert=montConvert;Montgomery.prototype.revert=montRevert;Montgomery.prototype.reduce=montReduce;Montgomery.prototype.mulTo=montMulTo;Montgomery.prototype.sqrTo=montSqrTo;function bnpIsEven(){return(this.t>0?this[0]&1:this.s)==0}function bnpExp(e,z){if(e>4294967295||e<1)return BigInteger.ONE;var r=nbi(),r2=nbi(),g=z.convert(this),i=nbits(e)-1;g.copyTo(r);while(--i>=0){z.sqrTo(r,r2);if((e&1<<i)>0)z.mulTo(r2,g,r);else{var t=r;r=r2;r2=t}}return z.revert(r)}function bnModPowInt(e,m){var z;if(e<256||m.isEven())z=new Classic(m);else z=new Montgomery(m);return this.exp(e,z)}BigInteger.prototype.copyTo=bnpCopyTo;BigInteger.prototype.fromInt=bnpFromInt;BigInteger.prototype.fromString=bnpFromString;BigInteger.prototype.clamp=bnpClamp;BigInteger.prototype.dlShiftTo=bnpDLShiftTo;BigInteger.prototype.drShiftTo=bnpDRShiftTo;BigInteger.prototype.lShiftTo=bnpLShiftTo;BigInteger.prototype.rShiftTo=bnpRShiftTo;BigInteger.prototype.subTo=bnpSubTo;BigInteger.prototype.multiplyTo=bnpMultiplyTo;BigInteger.prototype.squareTo=bnpSquareTo;BigInteger.prototype.divRemTo=bnpDivRemTo;BigInteger.prototype.invDigit=bnpInvDigit;BigInteger.prototype.isEven=bnpIsEven;BigInteger.prototype.exp=bnpExp;BigInteger.prototype.toString=bnToString;BigInteger.prototype.negate=bnNegate;BigInteger.prototype.abs=bnAbs;BigInteger.prototype.compareTo=bnCompareTo;BigInteger.prototype.bitLength=bnBitLength;BigInteger.prototype.mod=bnMod;BigInteger.prototype.modPowInt=bnModPowInt;BigInteger.ZERO=nbv(0);BigInteger.ONE=nbv(1);function bnpFromRadix(s,b){this.fromInt(0);if(b==null)b=10;var cs=this.chunkSize(b);var d=Math.pow(b,cs),mi=false,j=0,w=0;for(var i=0;i<s.length;++i){var x=intAt(s,i);if(x<0){if(s.charAt(i)=="-"&&this.signum()==0)mi=true;continue}w=b*w+x;if(++j>=cs){this.dMultiply(d);this.dAddOffset(w,0);j=0;w=0}}if(j>0){this.dMultiply(Math.pow(b,j));this.dAddOffset(w,0)}if(mi)BigInteger.ZERO.subTo(this,this)}function bnpChunkSize(r){return Math.floor(Math.LN2*this.DB/Math.log(r))}function bnSigNum(){if(this.s<0)return-1;else if(this.t<=0||this.t==1&&this[0]<=0)return 0;else return 1}function bnpDMultiply(n){this[this.t]=this.am(0,n-1,this,0,0,this.t);++this.t;this.clamp()}function bnpDAddOffset(n,w){if(n==0)return;while(this.t<=w)this[this.t++]=0;this[w]+=n;while(this[w]>=this.DV){this[w]-=this.DV;if(++w>=this.t)this[this.t++]=0;++this[w]}}function bnpToRadix(b){if(b==null)b=10;if(this.signum()==0||b<2||b>36)return"0";var cs=this.chunkSize(b);var a=Math.pow(b,cs);var d=nbv(a),y=nbi(),z=nbi(),r="";this.divRemTo(d,y,z);while(y.signum()>0){r=(a+z.intValue()).toString(b).substr(1)+r;y.divRemTo(d,y,z)}return z.intValue().toString(b)+r}function bnIntValue(){if(this.s<0){if(this.t==1)return this[0]-this.DV;else if(this.t==0)return-1}else if(this.t==1)return this[0];else if(this.t==0)return 0;return(this[1]&(1<<32-this.DB)-1)<<this.DB|this[0]}function bnpAddTo(a,r){var i=0,c=0,m=Math.min(a.t,this.t);while(i<m){c+=this[i]+a[i];r[i++]=c&this.DM;c>>=this.DB}if(a.t<this.t){c+=a.s;while(i<this.t){c+=this[i];r[i++]=c&this.DM;c>>=this.DB}c+=this.s}else{c+=this.s;while(i<a.t){c+=a[i];r[i++]=c&this.DM;c>>=this.DB}c+=a.s}r.s=c<0?-1:0;if(c>0)r[i++]=c;else if(c<-1)r[i++]=this.DV+c;r.t=i;r.clamp()}BigInteger.prototype.fromRadix=bnpFromRadix;BigInteger.prototype.chunkSize=bnpChunkSize;BigInteger.prototype.signum=bnSigNum;BigInteger.prototype.dMultiply=bnpDMultiply;BigInteger.prototype.dAddOffset=bnpDAddOffset;BigInteger.prototype.toRadix=bnpToRadix;BigInteger.prototype.intValue=bnIntValue;BigInteger.prototype.addTo=bnpAddTo;var Wrapper={abs:(function(l,h){var x=new goog.math.Long(l,h);var ret;if(x.isNegative()){ret=x.negate()}else{ret=x}HEAP32[tempDoublePtr>>2]=ret.low_;HEAP32[tempDoublePtr+4>>2]=ret.high_}),ensureTemps:(function(){if(Wrapper.ensuredTemps)return;Wrapper.ensuredTemps=true;Wrapper.two32=new BigInteger;Wrapper.two32.fromString("4294967296",10);Wrapper.two64=new BigInteger;Wrapper.two64.fromString("18446744073709551616",10);Wrapper.temp1=new BigInteger;Wrapper.temp2=new BigInteger}),lh2bignum:(function(l,h){var a=new BigInteger;a.fromString(h.toString(),10);var b=new BigInteger;a.multiplyTo(Wrapper.two32,b);var c=new BigInteger;c.fromString(l.toString(),10);var d=new BigInteger;c.addTo(b,d);return d}),stringify:(function(l,h,unsigned){var ret=(new goog.math.Long(l,h)).toString();if(unsigned&&ret[0]=="-"){Wrapper.ensureTemps();var bignum=new BigInteger;bignum.fromString(ret,10);ret=new BigInteger;Wrapper.two64.addTo(bignum,ret);ret=ret.toString(10)}return ret}),fromString:(function(str,base,min,max,unsigned){Wrapper.ensureTemps();var bignum=new BigInteger;bignum.fromString(str,base);var bigmin=new BigInteger;bigmin.fromString(min,10);var bigmax=new BigInteger;bigmax.fromString(max,10);if(unsigned&&bignum.compareTo(BigInteger.ZERO)<0){var temp=new BigInteger;bignum.addTo(Wrapper.two64,temp);bignum=temp}var error=false;if(bignum.compareTo(bigmin)<0){bignum=bigmin;error=true}else if(bignum.compareTo(bigmax)>0){bignum=bigmax;error=true}var ret=goog.math.Long.fromString(bignum.toString());HEAP32[tempDoublePtr>>2]=ret.low_;HEAP32[tempDoublePtr+4>>2]=ret.high_;if(error)throw"range error"})};return Wrapper})();function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}ExitStatus.prototype=new Error;ExitStatus.prototype.constructor=ExitStatus;var initialStackTop;var preloadStartTime=null;var calledMain=false;dependenciesFulfilled=function runCaller(){if(!Module["calledRun"])run();if(!Module["calledRun"])dependenciesFulfilled=runCaller};Module["callMain"]=Module.callMain=function callMain(args){assert(runDependencies==0,"cannot call main when async dependencies remain! (listen on __ATMAIN__)");assert(__ATPRERUN__.length==0,"cannot call main when preRun functions remain to be called");args=args||[];ensureInitRuntime();var argc=args.length+1;function pad(){for(var i=0;i<4-1;i++){argv.push(0)}}var argv=[allocate(intArrayFromString(Module["thisProgram"]),"i8",ALLOC_NORMAL)];pad();for(var i=0;i<argc-1;i=i+1){argv.push(allocate(intArrayFromString(args[i]),"i8",ALLOC_NORMAL));pad()}argv.push(0);argv=allocate(argv,"i32",ALLOC_NORMAL);initialStackTop=STACKTOP;try{var ret=Module["_main"](argc,argv,0);exit(ret,true)}catch(e){if(e instanceof ExitStatus){return}else if(e=="SimulateInfiniteLoop"){Module["noExitRuntime"]=true;return}else{if(e&&typeof e==="object"&&e.stack)Module.printErr("exception thrown: "+[e,e.stack]);throw e}}finally{calledMain=true}};function run(args){args=args||Module["arguments"];if(preloadStartTime===null)preloadStartTime=Date.now();if(runDependencies>0){return}preRun();if(runDependencies>0)return;if(Module["calledRun"])return;function doRun(){if(Module["calledRun"])return;Module["calledRun"]=true;if(ABORT)return;ensureInitRuntime();preMain();if(ENVIRONMENT_IS_WEB&&preloadStartTime!==null){Module.printErr("pre-main prep time: "+(Date.now()-preloadStartTime)+" ms")}if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(Module["_main"]&&shouldRunNow)Module["callMain"](args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout((function(){setTimeout((function(){Module["setStatus"]("")}),1);doRun()}),1)}else{doRun()}}Module["run"]=Module.run=run;function exit(status,implicit){if(implicit&&Module["noExitRuntime"]){return}if(Module["noExitRuntime"]){}else{ABORT=true;EXITSTATUS=status;STACKTOP=initialStackTop;exitRuntime();if(Module["onExit"])Module["onExit"](status)}if(ENVIRONMENT_IS_NODE){process["stdout"]["once"]("drain",(function(){process["exit"](status)}));console.log(" ");setTimeout((function(){process["exit"](status)}),500)}else if(ENVIRONMENT_IS_SHELL&&typeof quit==="function"){quit(status)}throw new ExitStatus(status)}Module["exit"]=Module.exit=exit;var abortDecorators=[];function abort(what){if(what!==undefined){Module.print(what);Module.printErr(what);what=JSON.stringify(what)}else{what=""}ABORT=true;EXITSTATUS=1;var extra="\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.";var output="abort("+what+") at "+stackTrace()+extra;if(abortDecorators){abortDecorators.forEach((function(decorator){output=decorator(output,what)}))}throw output}Module["abort"]=Module.abort=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=false;if(Module["noInitialRun"]){shouldRunNow=false}Module["noExitRuntime"]=true;run();var inputBuffer,inputBufferSize;function reallocInputBuffer(size){if(inputBuffer&&inputBufferSize>=size){return inputBuffer}if(inputBuffer){Module._free(inputBuffer)}inputBufferSize=size;inputBuffer=Module._malloc(inputBufferSize);return inputBuffer}Module.loadedmetadata=false;Module.videoCodec=null;Module.audioCodec=null;Module.duration=NaN;Module.audioPackets=[];Object.defineProperty(Module,"hasAudio",{get:(function(){return Module.loadedMetadata&&Module.audioCodec})});Object.defineProperty(Module,"audioReady",{get:(function(){return Module.audioPackets.length>0})});Object.defineProperty(Module,"audioTimestamp",{get:(function(){if(Module.audioPackets.length>0){return Module.audioPackets[0].timestamp}else{return-1}})});Module.videoPackets=[];Object.defineProperty(Module,"hasVideo",{get:(function(){return Module.loadedMetadata&&Module.videoCodec})});Object.defineProperty(Module,"frameReady",{get:(function(){return Module.videoPackets.length>0})});Object.defineProperty(Module,"frameTimestamp",{get:(function(){if(Module.videoPackets.length>0){return Module.videoPackets[0].timestamp}else{return-1}})});Object.defineProperty(Module,"keyframeTimestamp",{get:(function(){if(Module.videoPackets.length>0){return Module.videoPackets[0].keyframeTimestamp}else{return-1}})});Object.defineProperty(Module,"processing",{get:function getProcessing(){return false}});Object.defineProperty(Module,"seekable",{get:(function(){return!!Module._ogv_demuxer_seekable()})});Module.init=(function(callback){Module._ogv_demuxer_init();callback()});Module.process=(function(data,callback){var len=data.byteLength;var buffer=reallocInputBuffer(len);Module.HEAPU8.set(new Uint8Array(data),buffer);var ret=Module._ogv_demuxer_process(buffer,len);callback(ret)});Module.dequeueVideoPacket=(function(callback){if(Module.videoPackets.length){var packet=Module.videoPackets.shift().data;callback(packet)}else{callback(null)}});Module.dequeueAudioPacket=(function(callback){if(Module.audioPackets.length){var packet=Module.audioPackets.shift().data;callback(packet)}else{callback(null)}});Module.getKeypointOffset=(function(timeSeconds,callback){var offset=Module._ogv_demuxer_keypoint_offset(timeSeconds*1e3);callback(offset)});Module.flush=(function(callback){Module.audioPackets.splice(0,Module.audioPackets.length);Module.videoPackets.splice(0,Module.videoPackets.length);Module._ogv_demuxer_flush();callback()})
+
+
+
+
+
+ return Module;
+};
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-support.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-support.js
new file mode 100644
index 00000000..5c2933ed
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-support.js
@@ -0,0 +1,201 @@
+//
+// -- ogv-support.js
+// https://github.com/brion/ogv.js
+// Copyright (c) 2013-2015 Brion Vibber
+//
+
+(function() {
+
+
+/**
+ * A quick CPU/JS engine benchmark to guesstimate whether we're
+ * fast enough to handle 360p video in JavaScript.
+ */
+function BogoSlow() {
+ var self = this;
+
+ var timer;
+ if (window.performance && window.performance.now) {
+ timer = function() {
+ return window.performance.now();
+ };
+ } else {
+ timer = function() {
+ return Date.now();
+ };
+ }
+
+ var savedSpeed = null;
+ function run() {
+ var ops = 0;
+ var fibonacci = function(n) {
+ ops++;
+ if (n < 2) {
+ return n;
+ } else {
+ return fibonacci(n - 2) + fibonacci(n - 1);
+ }
+ };
+
+ var start = timer();
+
+ fibonacci(30);
+
+ var delta = timer() - start;
+ savedSpeed = (ops / delta);
+ }
+
+ /**
+ * Return a scale value of operations/sec from the benchmark.
+ * If the benchmark has already been run, uses a memoized result.
+ *
+ * @property {number}
+ */
+ Object.defineProperty(self, 'speed', {
+ get: function() {
+ if (savedSpeed === null) {
+ run();
+ }
+ return savedSpeed;
+ }
+ });
+
+ /**
+ * Return the defined cutoff speed value for 'slow' devices,
+ * based on results measured from some test devices.
+ *
+ * @property {number}
+ */
+ Object.defineProperty(self, 'slowCutoff', {
+ get: function() {
+ // 2012 Retina MacBook Pro (Safari 7) ~150,000
+ // 2009 Dell T5500 (IE 11) ~100,000
+ // iPad Air (iOS 7) ~65,000
+ // 2010 MBP / OS X 10.9 (Safari 7) ~62,500
+ // 2010 MBP / Win7 VM (IE 11) ~50,000+-
+ // ^ these play 360p ok
+ // ----------- line of moderate doom ----------
+ return 50000;
+ // v these play 160p ok
+ // iPad Mini non-Retina (iOS 8 beta) ~25,000
+ // Dell Inspiron Duo (IE 11) ~25,000
+ // Surface RT (IE 11) ~18,000
+ // iPod Touch 5th-gen (iOS 8 beta) ~16,000
+ }
+ });
+
+ /**
+ * Return the defined cutoff speed value for 'too slow' devices,
+ * based on results measured from some test devices.
+ *
+ * @property {number}
+ */
+ Object.defineProperty(self, 'tooSlowCutoff', {
+ get: function() {
+ // ------------ line of total doom ------------
+ return 12000;
+ // v these are toooooo slow and explode
+ // Chrome on iPhone 5s (iOS 8) ~8,000
+ // iPod 4th-gen (iOS 6.1) ~6,750
+ // iPhone 3Gs (iOS 6.1) ~4,500
+ }
+ });
+
+ /**
+ * 'Slow' devices can play audio and should sorta play our
+ * extra-tiny Wikimedia 160p15 transcodes
+ *
+ * @property {boolean}
+ */
+ Object.defineProperty(self, 'slow', {
+ get: function() {
+ return (self.speed < self.slowCutoff);
+ }
+ });
+
+ /**
+ * 'Too slow' devices aren't reliable at all
+ *
+ * @property {boolean}
+ */
+ Object.defineProperty(self, 'tooSlow', {
+ get: function() {
+ return (self.speed < self.tooSlowCutoff);
+ }
+ });
+}
+
+
+
+OGVCompat = {
+ benchmark: new BogoSlow(),
+
+ hasTypedArrays: function() {
+ // emscripten-compiled code requires typed arrays
+ return !!window.Uint32Array;
+ },
+
+ hasWebAudio: function() {
+ return !!(window.AudioContext || window.webkitAudioContext);
+ },
+
+ hasFlash: function() {
+ if (navigator.userAgent.indexOf('Trident') !== -1) {
+ // We only do the ActiveX test because we only need Flash in
+ // Internet Explorer 10/11. Other browsers use Web Audio directly
+ // (Edge, Safari) or native playback, so there's no need to test
+ // other ways of loading Flash.
+ try {
+ var obj = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
+ return true;
+ } catch(e) {
+ return false;
+ }
+ }
+ return false;
+ },
+
+ hasAudio: function() {
+ return this.hasWebAudio() || this.hasFlash();
+ },
+
+ isBlacklisted: function(userAgent) {
+ // JIT bugs in old Safari versions
+ var blacklist = [
+ /\(i.* OS [67]_.* like Mac OS X\).* Mobile\/.* Safari\//,
+ /\(Macintosh.* Version\/6\..* Safari\/\d/
+ ];
+ var blacklisted = false;
+ blacklist.forEach(function(regex) {
+ if (userAgent.match(regex)) {
+ blacklisted = true;
+ }
+ });
+ return blacklisted;
+ },
+
+ isSlow: function() {
+ return this.benchmark.slow;
+ },
+
+ isTooSlow: function() {
+ return this.benchmark.tooSlow;
+ },
+
+ supported: function(component) {
+ if (component === 'OGVDecoder') {
+ return (this.hasTypedArrays() && !this.isBlacklisted(navigator.userAgent));
+ }
+ if (component === 'OGVPlayer') {
+ return (this.supported('OGVDecoder') && this.hasAudio() && !this.isTooSlow());
+ }
+ return false;
+ }
+};
+
+
+ this.OGVCompat = OGVCompat;
+
+})();
+
+this.OGVVersion = "1.0-20150904182230-dd3c8e8";
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-version.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-version.js
new file mode 100644
index 00000000..e6a7a670
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-version.js
@@ -0,0 +1 @@
+this.OGVVersion = "1.0-20150904182230-dd3c8e8";
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-worker-audio.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-worker-audio.js
new file mode 100644
index 00000000..c7c0ff25
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-worker-audio.js
@@ -0,0 +1,317 @@
+(function() {
+ var global = this;
+
+ var scriptMap = {
+ OGVDemuxerOgg: 'ogv-demuxer-ogg.js',
+ OGVDemuxerWebM: 'ogv-demuxer-webm.js',
+ OGVDecoderAudioOpus: 'ogv-decoder-audio-opus.js',
+ OGVDecoderAudioVorbis: 'ogv-decoder-audio-vorbis.js',
+ OGVDecoderVideoTheora: 'ogv-decoder-video-theora.js',
+ OGVDecoderVideoVP8: 'ogv-decoder-video-vp8.js'
+ };
+
+ var proxyMap = {
+ OGVDecoderAudioOpus: 'OGVDecoderAudioProxy',
+ OGVDecoderAudioVorbis: 'OGVDecoderAudioProxy',
+ OGVDecoderVideoTheora: 'OGVDecoderVideoProxy',
+ OGVDecoderVideoVP8: 'OGVDecoderVideoProxy'
+ };
+ var workerMap = {
+ OGVDecoderAudioProxy: 'ogv-worker-audio.js',
+ OGVDecoderVideoProxy: 'ogv-worker-video.js'
+ };
+
+ function urlForClass(className) {
+ var scriptName = scriptMap[className];
+ if (scriptName) {
+ return urlForScript(scriptName);
+ } else {
+ throw new Error('asked for URL for unknown class ' + className);
+ }
+ };
+
+ function urlForScript(scriptName) {
+ if (scriptName) {
+ var base = OGVLoader.base;
+ if (base) {
+ base += '/';
+ }
+ return base + scriptName + '?version=' + encodeURIComponent(OGVVersion);
+ } else {
+ throw new Error('asked for URL for unknown script ' + scriptName);
+ }
+ };
+
+ var scriptStatus = {},
+ scriptCallbacks = {};
+ function loadWebScript(src, callback) {
+ if (scriptStatus[src] == 'done') {
+ callback();
+ } else if (scriptStatus[src] == 'loading') {
+ scriptCallbacks[src].push(callback);
+ } else {
+ scriptStatus[src] = 'loading';
+ scriptCallbacks[src] = [callback];
+
+ var scriptNode = document.createElement('script');
+ function done(event) {
+ var callbacks = scriptCallbacks[src];
+ delete scriptCallbacks[src];
+ scriptStatus[src] = 'done';
+
+ callbacks.forEach(function(cb) {
+ cb();
+ });
+ }
+ scriptNode.addEventListener('load', done);
+ scriptNode.addEventListener('error', done);
+ scriptNode.src = src;
+ document.querySelector('head').appendChild(scriptNode);
+ }
+ }
+
+ function defaultBase() {
+ if (typeof global.window === 'object') {
+
+ // for browser, try to autodetect
+ var scriptNodes = document.querySelectorAll('script'),
+ regex = /^(?:(.*)\/)ogv(?:-support)?\.js(?:\?|#|$)/,
+ path;
+ for (var i = 0; i < scriptNodes.length; i++) {
+ path = scriptNodes[i].getAttribute('src');
+ if (path) {
+ matches = path.match(regex);
+ if (matches) {
+ return matches[1];
+ }
+ }
+ }
+
+ } else {
+
+ // for workers, assume current directory
+ // if not a worker, too bad.
+ return '';
+
+ }
+ }
+
+ OGVLoader = {
+ base: defaultBase(),
+
+ loadClass: function(className, callback, options) {
+ options = options || {};
+ if (options.worker) {
+ this.workerProxy(className, callback);
+ } else if (typeof global[className] === 'function') {
+ // already loaded!
+ callback(global[className]);
+ } else if (typeof global.window === 'object') {
+ loadWebScript(urlForClass(className), function() {
+ callback(global[className]);
+ });
+ } else if (typeof global.importScripts === 'function') {
+ // worker has convenient sync importScripts
+ global.importScripts(urlForClass(className));
+ callback(global[className]);
+ }
+ },
+
+ workerProxy: function(className, callback) {
+ var proxyClass = proxyMap[className],
+ workerScript = workerMap[proxyClass];
+
+ if (!proxyClass) {
+ throw new Error('Requested worker for class with no proxy: ' + className);
+ }
+ if (!workerScript) {
+ throw new Error('Requested worker for class with no worker: ' + className);
+ }
+
+ this.loadClass(proxyClass, function(classObj) {
+ var construct = function(options) {
+ var worker = new Worker(urlForScript(workerScript));
+ return new classObj(worker, className, options);
+ };
+ callback(construct);
+ });
+ }
+ };
+})();
+/**
+ * Web Worker wrapper for codec fun
+ */
+function OGVWorkerSupport(propList, handlers) {
+
+ var transferables = (function() {
+ var buffer = new ArrayBuffer(1024),
+ bytes = new Uint8Array(buffer);
+ try {
+ postMessage({
+ action: 'transferTest',
+ bytes: bytes
+ }, [buffer]);
+ if (buffer.byteLength) {
+ // No transferable support
+ return false;
+ } else {
+ return true;
+ }
+ } catch (e) {
+ return false;
+ }
+ })();
+
+ var self = this;
+ self.target = null;
+
+ var sentProps = {};
+
+ function copyObject(obj) {
+ var copy = {};
+ for (var prop in obj) {
+ if (obj.hasOwnProperty(prop)) {
+ copy[prop] = obj[prop];
+ }
+ }
+ return copy;
+ }
+
+ function copyAudioBuffer(data) {
+ if (data == null) {
+ return null;
+ } else {
+ // Array of Float32Arrays
+ var copy = [];
+ for (var i = 0; i < data.length; i++) {
+ copy[i] = new Float32Array(data[i]);
+ }
+ return copy;
+ }
+ }
+
+ function copyByteArray(bytes) {
+ var heap = bytes.buffer;
+ if (typeof heap.slice === 'function') {
+ var extract = heap.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
+ return new Uint8Array(extract);
+ } else {
+ // Hella slow in IE 10/11!
+ // But only game in town on IE 10.
+ return new Uint8Array(bytes);
+ }
+ }
+
+ function copyFrameBuffer(buffer) {
+ if (buffer == null) {
+ return null;
+ } else {
+ var copy = copyObject(buffer);
+ copy.bytesY = copyByteArray(buffer.bytesY);
+ copy.bytesCb = copyByteArray(buffer.bytesCb);
+ copy.bytesCr = copyByteArray(buffer.bytesCr);
+ return copy;
+ }
+ }
+
+ handlers.construct = function(args, callback) {
+ var className = args[0],
+ options = args[1];
+
+ OGVLoader.loadClass(className, function(classObj) {
+ self.target = new classObj(options);
+ callback();
+ });
+ };
+
+ addEventListener('message', function workerOnMessage(event) {
+ var data = event.data;
+
+ if (data && data.action == 'transferTest') {
+ // ignore
+ return;
+ }
+
+ if (typeof data !== 'object' || typeof data.action !== 'string' || typeof data.callbackId !== 'string' || typeof data.args !== 'object') {
+ console.log('invalid message data', data);
+ } else if (!(data.action in handlers)) {
+ console.log('invalid message action', data.action);
+ } else {
+ handlers[data.action].call(self, data.args, function(args) {
+ args = args || [];
+
+ // Collect and send any changed properties...
+ var props = {},
+ transfers = [];
+ propList.forEach(function(propName) {
+ var propVal = self.target[propName];
+
+ if (sentProps[propName] !== propVal) {
+ // Save this value for later reference...
+ sentProps[propName] = propVal;
+
+ if (propName == 'duration' && isNaN(propVal) && isNaN(sentProps[propName])) {
+ // NaN is not === itself. Nice!
+ // no need to update it here.
+ } else if (propName == 'audioBuffer') {
+ // Don't send the entire emscripten heap!
+ propVal = copyAudioBuffer(propVal);
+ props[propName] = propVal;
+ if (propVal) {
+ for (i = 0; i < propVal.length; i++) {
+ transfers.push(propVal[i].buffer);
+ }
+ }
+ } else if (propName == 'frameBuffer') {
+ // Don't send the entire emscripten heap!
+ propVal = copyFrameBuffer(propVal);
+ props[propName] = propVal;
+ if (propVal) {
+ transfers.push(propVal.bytesY.buffer);
+ transfers.push(propVal.bytesCb.buffer);
+ transfers.push(propVal.bytesCr.buffer);
+ }
+ } else {
+ props[propName] = propVal;
+ }
+ }
+ });
+
+ var out = {
+ action: 'callback',
+ callbackId: data.callbackId,
+ args: args,
+ props: props
+ };
+ if (transferables) {
+ postMessage(out, transfers);
+ } else {
+ postMessage(out);
+ }
+ });
+ }
+ });
+
+}
+proxy = new OGVWorkerSupport([
+ 'loadedMetadata',
+ 'audioFormat',
+ 'audioBuffer'
+], {
+ init: function(args, callback) {
+ this.target.init(callback);
+ },
+
+ processHeader: function(args, callback) {
+ this.target.processHeader(args[0], function(ok) {
+ callback([ok]);
+ });
+ },
+
+ processAudio: function(args, callback) {
+ this.target.processAudio(args[0], function(ok) {
+ callback([ok]);
+ });
+ }
+});
+this.OGVVersion = "1.0-20150904182230-dd3c8e8";
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-worker-video.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-worker-video.js
new file mode 100644
index 00000000..3afd769b
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-worker-video.js
@@ -0,0 +1,317 @@
+(function() {
+ var global = this;
+
+ var scriptMap = {
+ OGVDemuxerOgg: 'ogv-demuxer-ogg.js',
+ OGVDemuxerWebM: 'ogv-demuxer-webm.js',
+ OGVDecoderAudioOpus: 'ogv-decoder-audio-opus.js',
+ OGVDecoderAudioVorbis: 'ogv-decoder-audio-vorbis.js',
+ OGVDecoderVideoTheora: 'ogv-decoder-video-theora.js',
+ OGVDecoderVideoVP8: 'ogv-decoder-video-vp8.js'
+ };
+
+ var proxyMap = {
+ OGVDecoderAudioOpus: 'OGVDecoderAudioProxy',
+ OGVDecoderAudioVorbis: 'OGVDecoderAudioProxy',
+ OGVDecoderVideoTheora: 'OGVDecoderVideoProxy',
+ OGVDecoderVideoVP8: 'OGVDecoderVideoProxy'
+ };
+ var workerMap = {
+ OGVDecoderAudioProxy: 'ogv-worker-audio.js',
+ OGVDecoderVideoProxy: 'ogv-worker-video.js'
+ };
+
+ function urlForClass(className) {
+ var scriptName = scriptMap[className];
+ if (scriptName) {
+ return urlForScript(scriptName);
+ } else {
+ throw new Error('asked for URL for unknown class ' + className);
+ }
+ };
+
+ function urlForScript(scriptName) {
+ if (scriptName) {
+ var base = OGVLoader.base;
+ if (base) {
+ base += '/';
+ }
+ return base + scriptName + '?version=' + encodeURIComponent(OGVVersion);
+ } else {
+ throw new Error('asked for URL for unknown script ' + scriptName);
+ }
+ };
+
+ var scriptStatus = {},
+ scriptCallbacks = {};
+ function loadWebScript(src, callback) {
+ if (scriptStatus[src] == 'done') {
+ callback();
+ } else if (scriptStatus[src] == 'loading') {
+ scriptCallbacks[src].push(callback);
+ } else {
+ scriptStatus[src] = 'loading';
+ scriptCallbacks[src] = [callback];
+
+ var scriptNode = document.createElement('script');
+ function done(event) {
+ var callbacks = scriptCallbacks[src];
+ delete scriptCallbacks[src];
+ scriptStatus[src] = 'done';
+
+ callbacks.forEach(function(cb) {
+ cb();
+ });
+ }
+ scriptNode.addEventListener('load', done);
+ scriptNode.addEventListener('error', done);
+ scriptNode.src = src;
+ document.querySelector('head').appendChild(scriptNode);
+ }
+ }
+
+ function defaultBase() {
+ if (typeof global.window === 'object') {
+
+ // for browser, try to autodetect
+ var scriptNodes = document.querySelectorAll('script'),
+ regex = /^(?:(.*)\/)ogv(?:-support)?\.js(?:\?|#|$)/,
+ path;
+ for (var i = 0; i < scriptNodes.length; i++) {
+ path = scriptNodes[i].getAttribute('src');
+ if (path) {
+ matches = path.match(regex);
+ if (matches) {
+ return matches[1];
+ }
+ }
+ }
+
+ } else {
+
+ // for workers, assume current directory
+ // if not a worker, too bad.
+ return '';
+
+ }
+ }
+
+ OGVLoader = {
+ base: defaultBase(),
+
+ loadClass: function(className, callback, options) {
+ options = options || {};
+ if (options.worker) {
+ this.workerProxy(className, callback);
+ } else if (typeof global[className] === 'function') {
+ // already loaded!
+ callback(global[className]);
+ } else if (typeof global.window === 'object') {
+ loadWebScript(urlForClass(className), function() {
+ callback(global[className]);
+ });
+ } else if (typeof global.importScripts === 'function') {
+ // worker has convenient sync importScripts
+ global.importScripts(urlForClass(className));
+ callback(global[className]);
+ }
+ },
+
+ workerProxy: function(className, callback) {
+ var proxyClass = proxyMap[className],
+ workerScript = workerMap[proxyClass];
+
+ if (!proxyClass) {
+ throw new Error('Requested worker for class with no proxy: ' + className);
+ }
+ if (!workerScript) {
+ throw new Error('Requested worker for class with no worker: ' + className);
+ }
+
+ this.loadClass(proxyClass, function(classObj) {
+ var construct = function(options) {
+ var worker = new Worker(urlForScript(workerScript));
+ return new classObj(worker, className, options);
+ };
+ callback(construct);
+ });
+ }
+ };
+})();
+/**
+ * Web Worker wrapper for codec fun
+ */
+function OGVWorkerSupport(propList, handlers) {
+
+ var transferables = (function() {
+ var buffer = new ArrayBuffer(1024),
+ bytes = new Uint8Array(buffer);
+ try {
+ postMessage({
+ action: 'transferTest',
+ bytes: bytes
+ }, [buffer]);
+ if (buffer.byteLength) {
+ // No transferable support
+ return false;
+ } else {
+ return true;
+ }
+ } catch (e) {
+ return false;
+ }
+ })();
+
+ var self = this;
+ self.target = null;
+
+ var sentProps = {};
+
+ function copyObject(obj) {
+ var copy = {};
+ for (var prop in obj) {
+ if (obj.hasOwnProperty(prop)) {
+ copy[prop] = obj[prop];
+ }
+ }
+ return copy;
+ }
+
+ function copyAudioBuffer(data) {
+ if (data == null) {
+ return null;
+ } else {
+ // Array of Float32Arrays
+ var copy = [];
+ for (var i = 0; i < data.length; i++) {
+ copy[i] = new Float32Array(data[i]);
+ }
+ return copy;
+ }
+ }
+
+ function copyByteArray(bytes) {
+ var heap = bytes.buffer;
+ if (typeof heap.slice === 'function') {
+ var extract = heap.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
+ return new Uint8Array(extract);
+ } else {
+ // Hella slow in IE 10/11!
+ // But only game in town on IE 10.
+ return new Uint8Array(bytes);
+ }
+ }
+
+ function copyFrameBuffer(buffer) {
+ if (buffer == null) {
+ return null;
+ } else {
+ var copy = copyObject(buffer);
+ copy.bytesY = copyByteArray(buffer.bytesY);
+ copy.bytesCb = copyByteArray(buffer.bytesCb);
+ copy.bytesCr = copyByteArray(buffer.bytesCr);
+ return copy;
+ }
+ }
+
+ handlers.construct = function(args, callback) {
+ var className = args[0],
+ options = args[1];
+
+ OGVLoader.loadClass(className, function(classObj) {
+ self.target = new classObj(options);
+ callback();
+ });
+ };
+
+ addEventListener('message', function workerOnMessage(event) {
+ var data = event.data;
+
+ if (data && data.action == 'transferTest') {
+ // ignore
+ return;
+ }
+
+ if (typeof data !== 'object' || typeof data.action !== 'string' || typeof data.callbackId !== 'string' || typeof data.args !== 'object') {
+ console.log('invalid message data', data);
+ } else if (!(data.action in handlers)) {
+ console.log('invalid message action', data.action);
+ } else {
+ handlers[data.action].call(self, data.args, function(args) {
+ args = args || [];
+
+ // Collect and send any changed properties...
+ var props = {},
+ transfers = [];
+ propList.forEach(function(propName) {
+ var propVal = self.target[propName];
+
+ if (sentProps[propName] !== propVal) {
+ // Save this value for later reference...
+ sentProps[propName] = propVal;
+
+ if (propName == 'duration' && isNaN(propVal) && isNaN(sentProps[propName])) {
+ // NaN is not === itself. Nice!
+ // no need to update it here.
+ } else if (propName == 'audioBuffer') {
+ // Don't send the entire emscripten heap!
+ propVal = copyAudioBuffer(propVal);
+ props[propName] = propVal;
+ if (propVal) {
+ for (i = 0; i < propVal.length; i++) {
+ transfers.push(propVal[i].buffer);
+ }
+ }
+ } else if (propName == 'frameBuffer') {
+ // Don't send the entire emscripten heap!
+ propVal = copyFrameBuffer(propVal);
+ props[propName] = propVal;
+ if (propVal) {
+ transfers.push(propVal.bytesY.buffer);
+ transfers.push(propVal.bytesCb.buffer);
+ transfers.push(propVal.bytesCr.buffer);
+ }
+ } else {
+ props[propName] = propVal;
+ }
+ }
+ });
+
+ var out = {
+ action: 'callback',
+ callbackId: data.callbackId,
+ args: args,
+ props: props
+ };
+ if (transferables) {
+ postMessage(out, transfers);
+ } else {
+ postMessage(out);
+ }
+ });
+ }
+ });
+
+}
+proxy = new OGVWorkerSupport([
+ 'loadedMetadata',
+ 'videoFormat',
+ 'frameBuffer'
+], {
+ init: function(args, callback) {
+ this.target.init(callback);
+ },
+
+ processHeader: function(args, callback) {
+ this.target.processHeader(args[0], function(ok) {
+ callback([ok]);
+ });
+ },
+
+ processFrame: function(args, callback) {
+ this.target.processFrame(args[0], function(ok) {
+ callback([ok]);
+ });
+ }
+});
+this.OGVVersion = "1.0-20150904182230-dd3c8e8";
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv.js
new file mode 100644
index 00000000..a29b4b3b
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv.js
@@ -0,0 +1,3966 @@
+//
+// -- ogv.js
+// https://github.com/brion/ogv.js
+// Copyright (c) 2013-2015 Brion Vibber
+//
+
+(function() {
+
+// -- OGVLoader.js
+
+(function() {
+ var global = this;
+
+ var scriptMap = {
+ OGVDemuxerOgg: 'ogv-demuxer-ogg.js',
+ OGVDemuxerWebM: 'ogv-demuxer-webm.js',
+ OGVDecoderAudioOpus: 'ogv-decoder-audio-opus.js',
+ OGVDecoderAudioVorbis: 'ogv-decoder-audio-vorbis.js',
+ OGVDecoderVideoTheora: 'ogv-decoder-video-theora.js',
+ OGVDecoderVideoVP8: 'ogv-decoder-video-vp8.js'
+ };
+
+ var proxyMap = {
+ OGVDecoderAudioOpus: 'OGVDecoderAudioProxy',
+ OGVDecoderAudioVorbis: 'OGVDecoderAudioProxy',
+ OGVDecoderVideoTheora: 'OGVDecoderVideoProxy',
+ OGVDecoderVideoVP8: 'OGVDecoderVideoProxy'
+ };
+ var workerMap = {
+ OGVDecoderAudioProxy: 'ogv-worker-audio.js',
+ OGVDecoderVideoProxy: 'ogv-worker-video.js'
+ };
+
+ function urlForClass(className) {
+ var scriptName = scriptMap[className];
+ if (scriptName) {
+ return urlForScript(scriptName);
+ } else {
+ throw new Error('asked for URL for unknown class ' + className);
+ }
+ };
+
+ function urlForScript(scriptName) {
+ if (scriptName) {
+ var base = OGVLoader.base;
+ if (base) {
+ base += '/';
+ }
+ return base + scriptName + '?version=' + encodeURIComponent(OGVVersion);
+ } else {
+ throw new Error('asked for URL for unknown script ' + scriptName);
+ }
+ };
+
+ var scriptStatus = {},
+ scriptCallbacks = {};
+ function loadWebScript(src, callback) {
+ if (scriptStatus[src] == 'done') {
+ callback();
+ } else if (scriptStatus[src] == 'loading') {
+ scriptCallbacks[src].push(callback);
+ } else {
+ scriptStatus[src] = 'loading';
+ scriptCallbacks[src] = [callback];
+
+ var scriptNode = document.createElement('script');
+ function done(event) {
+ var callbacks = scriptCallbacks[src];
+ delete scriptCallbacks[src];
+ scriptStatus[src] = 'done';
+
+ callbacks.forEach(function(cb) {
+ cb();
+ });
+ }
+ scriptNode.addEventListener('load', done);
+ scriptNode.addEventListener('error', done);
+ scriptNode.src = src;
+ document.querySelector('head').appendChild(scriptNode);
+ }
+ }
+
+ function defaultBase() {
+ if (typeof global.window === 'object') {
+
+ // for browser, try to autodetect
+ var scriptNodes = document.querySelectorAll('script'),
+ regex = /^(?:(.*)\/)ogv(?:-support)?\.js(?:\?|#|$)/,
+ path;
+ for (var i = 0; i < scriptNodes.length; i++) {
+ path = scriptNodes[i].getAttribute('src');
+ if (path) {
+ matches = path.match(regex);
+ if (matches) {
+ return matches[1];
+ }
+ }
+ }
+
+ } else {
+
+ // for workers, assume current directory
+ // if not a worker, too bad.
+ return '';
+
+ }
+ }
+
+ OGVLoader = {
+ base: defaultBase(),
+
+ loadClass: function(className, callback, options) {
+ options = options || {};
+ if (options.worker) {
+ this.workerProxy(className, callback);
+ } else if (typeof global[className] === 'function') {
+ // already loaded!
+ callback(global[className]);
+ } else if (typeof global.window === 'object') {
+ loadWebScript(urlForClass(className), function() {
+ callback(global[className]);
+ });
+ } else if (typeof global.importScripts === 'function') {
+ // worker has convenient sync importScripts
+ global.importScripts(urlForClass(className));
+ callback(global[className]);
+ }
+ },
+
+ workerProxy: function(className, callback) {
+ var proxyClass = proxyMap[className],
+ workerScript = workerMap[proxyClass];
+
+ if (!proxyClass) {
+ throw new Error('Requested worker for class with no proxy: ' + className);
+ }
+ if (!workerScript) {
+ throw new Error('Requested worker for class with no worker: ' + className);
+ }
+
+ this.loadClass(proxyClass, function(classObj) {
+ var construct = function(options) {
+ var worker = new Worker(urlForScript(workerScript));
+ return new classObj(worker, className, options);
+ };
+ callback(construct);
+ });
+ }
+ };
+})();
+
+
+// -- StreamFile.js
+
+/**
+ * Quickie wrapper around XHR to fetch a file as array buffer chunks.
+ *
+ * Call streamFile.readBytes() after an onread event's data has been
+ * processed to trigger the next read.
+ *
+ * IE 10: uses MSStream / MSStreamReader for true streaming
+ * Firefox: uses moz-chunked-arraybuffer to buffer & deliver during download
+ * Safari, Chrome: uses binary string to buffer & deliver during download
+ *
+ * @author Brion Vibber <brion@pobox.com>
+ * @copyright 2014
+ * @license MIT-style
+ */
+function StreamFile(options) {
+ var self = this,
+ url = options.url,
+ started = false,
+ onstart = options.onstart || function(){},
+ onbuffer = options.onbuffer || function(){},
+ onread = options.onread || function(){},
+ ondone = options.ondone || function(){},
+ onerror = options.onerror || function(){},
+ bufferSize = options.bufferSize || 8192,
+ minBufferSize = options.minBufferSize || 65536,
+ seekPosition = options.seekPosition || 0,
+ bufferPosition = seekPosition,
+ chunkSize = options.chunkSize || 1024 * 1024, // read/buffer up to a megabyte at a time
+ waitingForInput = false,
+ doneBuffering = false,
+ bytesTotal = 0,
+ bytesRead = 0,
+ buffers = [],
+ cachever = 0,
+ responseHeaders = {};
+
+
+
+ // -- internal private methods
+ var internal = {
+ /**
+ * @var {XMLHttpRequest}
+ */
+ xhr: null,
+
+ /**
+ * Test if a given responseType value is valid on an XHR
+ *
+ * @return boolean
+ */
+ tryMethod: function(rt) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", url);
+ try {
+ // Set the response type and see if it explodes!
+ xhr.responseType = rt;
+ } catch (e) {
+ // Safari 6 throws a DOM Exception on invalid setting
+ return false;
+ }
+ // Other browsers just don't accept the setting, so check
+ // whether it made it through.
+ return (xhr.responseType == rt);
+ },
+
+ setBytesTotal: function(xhr) {
+ if (xhr.status == 206) {
+ bytesTotal = internal.getXHRRangeTotal(xhr);
+ } else {
+ var contentLength = xhr.getResponseHeader('Content-Length');
+ if (contentLength === null || contentLength === '') {
+ // Unknown file length... maybe streaming live?
+ bytesTotal = 0;
+ } else {
+ bytesTotal = parseInt(contentLength, 10);
+ }
+ }
+ },
+
+ // Save HTTP response headers from the HEAD request for later
+ processResponseHeaders: function(xhr) {
+ responseHeaders = {};
+ var allResponseHeaders = xhr.getAllResponseHeaders(),
+ headerLines = allResponseHeaders.split(/\n/);
+ headerLines.forEach(function(line) {
+ var bits = line.split(/:\s*/, 2);
+ if (bits.length > 1) {
+ var name = bits[0].toLowerCase(),
+ value = bits[1];
+ responseHeaders[name] = value;
+ }
+ });
+ },
+
+ openXHR: function() {
+ var getUrl = url;
+ if (cachever) {
+ //
+ // Safari sometimes messes up and gives us the wrong chunk.
+ // Seems to be a general problem with Safari and cached XHR ranges.
+ //
+ // Interestingly, it allows you to request _later_ ranges successfully,
+ // but when requesting _earlier_ ranges it returns the latest one retrieved.
+ // So we only need to update the cache-buster when we rewind.
+ //
+ // https://bugs.webkit.org/show_bug.cgi?id=82672
+ //
+ getUrl += '?ogvjs_cachever=' + cachever;
+ }
+
+ var xhr = internal.xhr = new XMLHttpRequest();
+ xhr.open("GET", getUrl);
+
+ internal.setXHROptions(xhr);
+
+ var range = null;
+ if (seekPosition || chunkSize) {
+ range = 'bytes=' + seekPosition + '-';
+ }
+ if (chunkSize) {
+ if (bytesTotal) {
+ range += Math.min(seekPosition + chunkSize, bytesTotal) - 1;
+ } else {
+ range += (seekPosition + chunkSize) - 1;
+ }
+ }
+ if (range !== null) {
+ xhr.setRequestHeader('Range', range);
+ }
+
+ bytesRead = 0;
+
+ xhr.onreadystatechange = function(event) {
+ if (xhr.readyState == 2) {
+ if (xhr.status == 206) {
+ var foundPosition = internal.getXHRRangeStart(xhr);
+ if (seekPosition != foundPosition) {
+ //
+ // Safari sometimes messes up and gives us the wrong chunk.
+ // Seems to be a general problem with Safari and cached XHR ranges.
+ //
+ // Interestingly, it allows you to request _later_ ranges successfully,
+ // but when requesting _earlier_ ranges it returns the latest one retrieved.
+ // So we only need to update the cache-buster when we rewind and actually
+ // get an incorrect range.
+ //
+ // https://bugs.webkit.org/show_bug.cgi?id=82672
+ //
+ console.log('Expected start at ' + seekPosition + ' but got ' + foundPosition +
+ '; working around Safari range caching bug: https://bugs.webkit.org/show_bug.cgi?id=82672');
+ cachever++;
+ internal.abortXHR(xhr);
+ internal.openXHR();
+ return;
+ }
+ }
+ if (!started) {
+ internal.setBytesTotal(xhr);
+ internal.processResponseHeaders(xhr);
+ started = true;
+ onstart();
+ }
+ //internal.onXHRHeadersReceived(xhr);
+ // @todo check that partial content was supported if relevant
+ } else if (xhr.readyState == 3) {
+ internal.onXHRLoading(xhr);
+ } else if (xhr.readyState == 4) {
+ // Complete.
+ internal.onXHRDone(xhr);
+ }
+ };
+
+ xhr.send();
+ },
+
+ getXHRRangeMatches: function(xhr) {
+ // Note Content-Range must be whitelisted for CORS requests
+ var contentRange = xhr.getResponseHeader('Content-Range');
+ return contentRange && contentRange.match(/^bytes (\d+)-(\d+)\/(\d+)/);
+ },
+
+ getXHRRangeStart: function(xhr) {
+ var matches = internal.getXHRRangeMatches(xhr);
+ if (matches) {
+ return parseInt(matches[1], 10);
+ } else {
+ return 0;
+ }
+ },
+
+ getXHRRangeTotal: function(xhr) {
+ var matches = internal.getXHRRangeMatches(xhr);
+ if (matches) {
+ return parseInt(matches[3], 10);
+ } else {
+ return 0;
+ }
+ },
+
+ setXHROptions: function(xhr) {
+ throw new Error('abstract function');
+ },
+
+ /*
+ onXHRHeadersReceived: function(xhr) {
+ if (xhr.status >= 400) {
+ // errrorrrrrrr
+ console.log("HTTP " + xhr.status + ": " +xhr.statusText);
+ onerror();
+ xhr.abort();
+ } else {
+ internal.setBytesTotal(xhr);
+ internal.processResponseHeaders(xhr);
+ started = true;
+ onstart();
+ }
+ },
+ */
+
+ onXHRLoading: function(xhr) {
+ throw new Error('abstract function');
+ },
+
+ onXHRDone: function(xhr) {
+ doneBuffering = true;
+ },
+
+ abortXHR: function(xhr) {
+ xhr.onreadystatechange = null;
+ xhr.abort();
+ },
+
+ bufferData: function(buffer) {
+ if (buffer) {
+ buffers.push(buffer);
+ onbuffer();
+
+ internal.readNextChunk();
+ }
+ },
+
+ bytesBuffered: function() {
+ var bytes = 0;
+ buffers.forEach(function(buffer) {
+ bytes += buffer.byteLength;
+ });
+ return bytes;
+ },
+
+ dataToRead: function() {
+ return internal.bytesBuffered() > 0;
+ },
+
+ popBuffer: function() {
+ var bufferOut = new ArrayBuffer(bufferSize),
+ bytesOut = new Uint8Array(bufferOut),
+ byteLength = 0;
+
+ function stuff(bufferIn) {
+ var bytesIn = new Uint8Array(bufferIn);
+ bytesOut.set(bytesIn, byteLength);
+ byteLength += bufferIn.byteLength;
+ }
+
+ while (byteLength < minBufferSize) {
+ var needBytes = minBufferSize - byteLength,
+ nextBuffer = buffers.shift();
+ if (!nextBuffer) {
+ break;
+ }
+
+ if (needBytes >= nextBuffer.byteLength) {
+ // if it fits, it sits
+ stuff(nextBuffer);
+ } else {
+ // Split the buffer and requeue the rest
+ var croppedBuffer = nextBuffer.slice(0, needBytes),
+ remainderBuffer = nextBuffer.slice(needBytes);
+ buffers.unshift(remainderBuffer);
+ stuff(croppedBuffer);
+ break;
+ }
+ }
+
+ bytesRead += byteLength;
+ bufferPosition += byteLength;
+ return bufferOut.slice(0, byteLength);
+ },
+
+ clearReadState: function() {
+ bytesRead = 0;
+ doneBuffering = false;
+ waitingForInput = true;
+ },
+
+ clearBuffers: function() {
+ internal.clearReadState();
+ buffers.splice(0, buffers.length);
+ bufferPosition = seekPosition;
+ },
+
+ // Read the next binary buffer out of the buffered data
+ readNextChunk: function() {
+ if (waitingForInput) {
+ waitingForInput = false;
+ onread(internal.popBuffer());
+ if (doneBuffering && !internal.dataToRead()) {
+ internal.onReadDone();
+ }
+ }
+ },
+
+ onReadDone: function() {
+ ondone();
+ },
+
+ // See if we can seek within already-buffered data
+ quickSeek: function(pos) {
+ return false;
+ }
+
+ };
+
+ // -- Public methods
+ self.readBytes = function() {
+ if (internal.dataToRead()) {
+ var buffer = internal.popBuffer();
+ onread(buffer);
+ if (doneBuffering && self.bytesBuffered < Math.min(bufferPosition + chunkSize, self.bytesTotal)) {
+ seekPosition += chunkSize;
+ internal.clearReadState();
+ internal.openXHR();
+ }
+ } else if (doneBuffering) {
+ // We're out of data!
+ internal.onReadDone();
+ } else {
+ // Nothing queued...
+ waitingForInput = true;
+ }
+ };
+
+ self.abort = function() {
+ if (internal.xhr) {
+ internal.abortXHR(internal.xhr);
+ internal.xhr = null;
+ internal.clearBuffers();
+ }
+ };
+
+ self.seek = function(bytePosition) {
+ if (internal.quickSeek(bytePosition)) {
+ //console.log('quick seek successful');
+ } else {
+ self.abort();
+ seekPosition = bytePosition;
+ internal.clearBuffers();
+ internal.openXHR();
+ }
+ };
+
+ self.getResponseHeader = function(headerName) {
+ var lowerName = headerName.toLowerCase(),
+ value = responseHeaders[lowerName];
+ if (value === undefined) {
+ return null;
+ } else {
+ return value;
+ }
+ };
+
+ // -- public properties
+ Object.defineProperty(self, 'bytesTotal', {
+ get: function() {
+ return bytesTotal;
+ }
+ });
+
+ Object.defineProperty(self, 'bytesBuffered', {
+ get: function() {
+ return bufferPosition + internal.bytesBuffered();
+ }
+ });
+
+ Object.defineProperty(self, 'bytesRead', {
+ get: function() {
+ return seekPosition + bytesRead;
+ }
+ });
+
+ Object.defineProperty(self, 'seekable', {
+ get: function() {
+ return (self.bytesTotal > 0);
+ }
+ });
+
+ // Handy way to call super functions
+ var orig = {};
+ for (var prop in internal) {
+ orig[prop] = internal[prop];
+ }
+
+ // -- Backend selection and method overrides
+ if (internal.tryMethod('moz-chunked-arraybuffer')) {
+ internal.setXHROptions = function(xhr) {
+ xhr.responseType = 'moz-chunked-arraybuffer';
+
+ xhr.onprogress = function() {
+ // xhr.response is a per-chunk ArrayBuffer
+ internal.bufferData(xhr.response);
+ };
+ };
+
+ internal.abortXHR = function(xhr) {
+ xhr.onprogress = null;
+ orig.abortXHR(xhr);
+ };
+
+ internal.onXHRLoading = function(xhr) {
+ // we have to get from the 'progress' event
+ };
+
+ } else if (internal.tryMethod('ms-stream')) {
+ // IE 10 supports returning a Stream from XHR.
+
+ // Don't bother reading in chunks, MSStream handles it for us
+ chunkSize = 0;
+
+ var stream, streamReader;
+ var restarted = false;
+
+ internal.setXHROptions = function(xhr) {
+ xhr.responseType = 'ms-stream';
+ };
+
+ internal.abortXHR = function(xhr) {
+ restarted = true;
+ if (streamReader) {
+ streamReader.abort();
+ streamReader = null;
+ }
+ if (stream) {
+ stream.msClose();
+ stream = null;
+ }
+ orig.abortXHR(xhr);
+ };
+
+ internal.onXHRLoading = function(xhr) {
+ // Transfer us over to the StreamReader...
+ stream = xhr.response;
+ xhr.onreadystatechange = null;
+ if (waitingForInput) {
+ waitingForInput = false;
+ self.readBytes();
+ }
+ };
+
+ internal.bytesBuffered = function() {
+ // We don't know how much ahead is buffered, it's opaque.
+ // Just return what we've read.
+ return 0;
+ };
+
+ self.readBytes = function() {
+ if (stream) {
+ streamReader = new MSStreamReader();
+ streamReader.onload = function(event) {
+ var buffer = event.target.result,
+ len = buffer.byteLength;
+ if (len > 0) {
+ bytesRead += len;
+ bufferPosition += len;
+ onread(buffer);
+ } else {
+ // Zero length means end of stream.
+ ondone();
+ }
+ };
+ streamReader.onerror = function(event) {
+ onerror('mystery error streaming');
+ };
+ streamReader.readAsArrayBuffer(stream, bufferSize);
+ } else {
+ waitingForInput = true;
+ }
+ };
+
+ } else if ((new XMLHttpRequest()).overrideMimeType !== undefined) {
+
+ // Use old binary string method since we can read reponseText
+ // progressively and extract ArrayBuffers from that.
+
+ internal.setXHROptions = function(xhr) {
+ xhr.responseType = "text";
+ xhr.overrideMimeType('text/plain; charset=x-user-defined');
+ };
+
+ var lastPosition = 0;
+
+ // Is there a better way to do this conversion? :(
+ var stringToArrayBuffer = function(chunk) {
+ var len = chunk.length,
+ buffer = new ArrayBuffer(len),
+ bytes = new Uint8Array(buffer);
+ for (var i = 0; i < len; i++) {
+ bytes[i] = chunk.charCodeAt(i);
+ }
+ return buffer;
+ };
+
+ internal.clearReadState = function() {
+ orig.clearReadState();
+ lastPosition = 0;
+ };
+
+ internal.onXHRLoading = function(xhr) {
+ // xhr.responseText is a binary string of entire file so far
+ var str = xhr.responseText;
+ if (lastPosition < str.length) {
+ var chunk = str.slice(lastPosition),
+ buffer = stringToArrayBuffer(chunk);
+ lastPosition = str.length;
+ internal.bufferData(buffer);
+ }
+ };
+
+ /*
+ internal.quickSeek = function(pos) {
+ var bufferedPos = pos - seekPosition;
+ if (bufferedPos < 0) {
+ return false;
+ } else if (bufferedPos >= internal.xhr.responseText.length) {
+ return false;
+ } else {
+ lastPosition = bufferedPos;
+ bytesRead = lastPosition;
+ setTimeout(function() {
+ onbuffer()
+ }, 0);
+ return true;
+ }
+ };
+ */
+ } else {
+ throw new Error("No streaming HTTP input method found.");
+ }
+
+ internal.openXHR();
+}
+
+
+// -- AudioFeeder.js
+
+var AudioFeeder;
+
+(function() {
+ var global = this,
+ AudioContext = global.AudioContext || global.webkitAudioContext;
+
+ /**
+ * Object that we can throw audio data into and have it drain out.
+ *
+ * Because changing the number of channels on the fly is hard, hardcoding
+ * to 2 output channels. That's also all we can do on IE with Flash output.
+ *
+ * @param options: dictionary of config settings:
+ * 'base' - Base URL to find additional resources in,
+ * such as the Flash audio output shim
+ */
+ AudioFeeder = function(options) {
+ var self = this;
+ options = options || {};
+
+ // Look for W3C Audio API
+ if (!AudioContext) {
+ // use Flash fallback
+ var flashOptions = {};
+ if (typeof options.base === 'string') {
+ flashOptions.swf = options.base + '/dynamicaudio.swf?version=' + OGVVersion;
+ }
+ this.flashaudio = new DynamicAudio( flashOptions );
+ }
+
+ var bufferSize = this.bufferSize = 4096,
+ channels = 0, // call init()!
+ rate = 0; // call init()!
+
+ // Always create stereo output. For iOS we have to set this stuff up
+ // before we've actually gotten the info from the codec because we
+ // must initialize from a UI event. Bah!
+ var outputChannels = 2;
+
+ function freshBuffer() {
+ var buffer = [];
+ for (var channel = 0; channel < outputChannels; channel++) {
+ buffer[channel] = new Float32Array(bufferSize);
+ }
+ return buffer;
+ }
+
+ var buffers = [],
+ context,
+ node,
+ pendingBuffer = freshBuffer(),
+ pendingPos = 0,
+ muted = false,
+ queuedTime = 0,
+ playbackTimeAtBufferTail = -1,
+ targetRate,
+ dropped = 0,
+ delayedTime = 0;
+
+ if(AudioContext) {
+ if (typeof options.audioContext !== 'undefined') {
+ // We were passed a pre-existing AudioContext object,
+ // in the hopes this gets around iOS's weird activation rules.
+ context = options.audioContext;
+ } else {
+ AudioFeeder.initSharedAudioContext();
+ context = AudioFeeder.sharedAudioContext;
+ }
+ playbackTimeAtBufferTail = context.currentTime;
+
+ if (context.createScriptProcessor) {
+ node = context.createScriptProcessor(bufferSize, 0, outputChannels);
+ } else if (context.createJavaScriptNode) {
+ node = context.createJavaScriptNode(bufferSize, 0, outputChannels);
+ } else {
+ throw new Error("Bad version of web audio API?");
+ }
+ targetRate = this.targetRate = context.sampleRate;
+ } else {
+ targetRate = this.targetRate = 44100; // flash fallback
+ }
+
+ function popNextBuffer() {
+ // hack hack
+ // fixme: grab the right number of samples
+ // and... rescale
+ if (buffers.length > 0) {
+ return buffers.shift();
+ }
+ }
+
+ function audioProcess(event) {
+ var channel, input, output, i, playbackTime;
+ if (typeof event.playbackTime === 'number') {
+ playbackTime = event.playbackTime;
+ } else {
+ // Safari 6.1 hack
+ playbackTime = context.currentTime + (bufferSize / targetRate);
+ }
+
+ var expectedTime = playbackTimeAtBufferTail;
+ if (expectedTime < playbackTime) {
+ // we may have lost some time while something ran too slow
+ delayedTime += (playbackTime - expectedTime);
+ }
+
+ var inputBuffer = popNextBuffer(bufferSize);
+ if (!inputBuffer) {
+ // We might be in a throttled background tab; go ping the decoder
+ // and let it know we need more data now!
+ if (self.onstarved) {
+ self.onstarved();
+ inputBuffer = popNextBuffer(bufferSize);
+ }
+ }
+
+ // If we haven't got enough data, write a buffer of of silence to
+ // both channels
+ if (!inputBuffer) {
+ for (channel = 0; channel < outputChannels; channel++) {
+ output = event.outputBuffer.getChannelData(channel);
+ for (i = 0; i < bufferSize; i++) {
+ output[i] = 0;
+ }
+ }
+ dropped++;
+ return;
+ }
+
+ var volume = (muted ? 0 : 1);
+ for (channel = 0; channel < outputChannels; channel++) {
+ input = inputBuffer[channel];
+ output = event.outputBuffer.getChannelData(channel);
+ for (i = 0; i < Math.min(bufferSize, input.length); i++) {
+ output[i] = input[i] * volume;
+ }
+ }
+ queuedTime += (bufferSize / context.sampleRate);
+ playbackTimeAtBufferTail = playbackTime + (bufferSize / context.sampleRate);
+ }
+
+ /**
+ * This is horribly naive and wrong.
+ * Replace me with a better algo!
+ */
+ function resample(samples) {
+ if (rate == targetRate && channels == outputChannels) {
+ return samples;
+ } else {
+ var newSamples = [];
+ for (var channel = 0; channel < outputChannels; channel++) {
+ var inputChannel = channel;
+ if (channel >= channels) {
+ inputChannel = 0;
+ }
+ var input = samples[inputChannel],
+ output = new Float32Array(Math.round(input.length * targetRate / rate));
+ for (var i = 0; i < output.length; i++) {
+ output[i] = input[(i * rate / targetRate) | 0];
+ }
+ newSamples.push(output);
+ }
+ return newSamples;
+ }
+ }
+
+ /**
+ * Resampling, scaling and reordering for the Flash fallback.
+ * The Flash fallback expects 44.1 kHz, stereo
+ * Resampling: This is horribly naive and wrong.
+ * TODO: Replace me with a better algo!
+ */
+ function resampleFlash(samples) {
+ var sampleincr = rate / 44100;
+ var samplecount = (samples[0].length * (44100 / rate)) | 0;
+ var newSamples = new Int16Array(samplecount * 2);
+ var chanLeft = samples[0];
+ var chanRight = channels > 1 ? samples[1] : chanLeft;
+ var multiplier = 16384; // smaller than 32768 to allow some headroom from those floats
+ for(var s = 0; s < samplecount; s++) {
+ var idx = (s * sampleincr) | 0;
+ var idx_out = s * 2;
+ // Use a smaller
+ newSamples[idx_out] = chanLeft[idx] * multiplier;
+ newSamples[idx_out + 1] = chanRight[idx] * multiplier;
+ }
+ return newSamples;
+ }
+
+ function resampleFlashMuted(samples) {
+ // if muted: generate fitting number of samples for audio clock
+ var samplecount = (samples[0].length * (44100 / rate)) | 0;
+ return new Int16Array(samplecount * 2);
+ }
+
+
+ function pushSamples(samples) {
+ var firstChannel = samples[0],
+ sampleCount = firstChannel.length;
+ for (var i = 0; i < sampleCount; i++) {
+ for (var channel = 0; channel < outputChannels; channel++) {
+ pendingBuffer[channel][pendingPos] = samples[channel][i];
+ }
+ if (++pendingPos == bufferSize) {
+ buffers.push(pendingBuffer);
+ pendingPos = 0;
+ pendingBuffer = freshBuffer();
+ }
+ }
+ }
+
+ this.init = function(numChannels, sampleRate) {
+ // warning: can't change channels here reliably
+ rate = sampleRate;
+ channels = numChannels;
+ pendingBuffer = freshBuffer();
+ };
+
+ var hexDigits = ['0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
+ var hexBytes = [];
+ for (var i = 0; i < 256; i++) {
+ hexBytes[i] = hexDigits[(i & 0x0f)] +
+ hexDigits[(i & 0xf0) >> 4];
+ }
+ function hexString(buffer) {
+ var samples = new Uint8Array(buffer);
+ var digits = "",
+ len = samples.length;
+ for (var i = 0; i < len; i++) {
+ // Note that in IE 11 strong concatenation is twice as fast as
+ // the traditional make-an-array-and-join here.
+ digits += hexBytes[samples[i]];
+ }
+ return digits;
+ }
+
+ var flashBuffer = '',
+ flushTimeout = null;
+ function flushFlashBuffer() {
+ var chunk = flashBuffer;
+ if (self.flashaudio.flashElement.write) {
+ self.flashaudio.flashElement.write(chunk);
+ } else {
+ self.waitUntilReady(function() {
+ self.flashaudio.flashElement.write(chunk);
+ });
+ }
+ flashBuffer = '';
+ flushTimeout = null;
+ }
+ this.bufferData = function(samplesPerChannel) {
+ if(this.flashaudio) {
+ var resamples = !muted ? resampleFlash(samplesPerChannel) : resampleFlashMuted(samplesPerChannel);
+ var flashElement = this.flashaudio.flashElement;
+ if(resamples.length > 0) {
+ var str = hexString(resamples.buffer);
+ flashBuffer += str;
+ if (!flushTimeout) {
+ // consolidate multiple consecutive tiny buffers in one pass;
+ // pushing data to Flash is relatively expensive on slow machines
+ flushTimeout = setTimeout(flushFlashBuffer, 0);
+ }
+ }
+ } else if (buffers) {
+ var samples = resample(samplesPerChannel);
+ pushSamples(samples);
+ } else {
+ console.log('no valid whatsit');
+ self.close();
+ }
+ };
+
+ function samplesQueued() {
+ if (buffers) {
+ var numSamplesQueued = 0;
+ buffers.forEach(function(buffer) {
+ numSamplesQueued += buffer[0].length;
+ });
+
+ var bufferedSamples = numSamplesQueued;
+ var remainingSamples = Math.floor(Math.max(0, (playbackTimeAtBufferTail - context.currentTime)) * context.sampleRate);
+
+ return bufferedSamples + remainingSamples;
+ } else {
+ return 0;
+ }
+ }
+
+ var cachedFlashState = null,
+ cachedFlashTime = 0,
+ cachedFlashInterval = 40; // resync state no more often than every X ms
+
+ /**
+ * @return {
+ * playbackPosition: {number} seconds, with a system-provided base time
+ * samplesQueued: {int}
+ * dropped: {int}
+ * }
+ */
+ this.getPlaybackState = function() {
+ if (this.flashaudio) {
+ var flashElement = this.flashaudio.flashElement;
+ if (flashElement.write) {
+ var now = Date.now(),
+ delta = now - cachedFlashTime,
+ state;
+ if (cachedFlashState && delta < cachedFlashInterval) {
+ state = {
+ playbackPosition: cachedFlashState.playbackPosition + delta / 1000,
+ samplesQueued: cachedFlashState.samplesQueued - delta * targetRate / 1000,
+ dropped: cachedFlashState.dropped,
+ delayed: cachedFlashState.delayed
+ };
+ } else {
+ state = flashElement.getPlaybackState();
+ cachedFlashState = state;
+ cachedFlashTime = now;
+ }
+ state.samplesQueued += flashBuffer.length / 2;
+ return state;
+ } else {
+ //console.log('getPlaybackState USED TOO EARLY');
+ return {
+ playbackPosition: 0,
+ samplesQueued: 0,
+ dropped: 0,
+ delayed: 0
+ };
+ }
+ } else {
+ return {
+ playbackPosition: queuedTime - Math.max(0, playbackTimeAtBufferTail - context.currentTime),
+ samplesQueued: samplesQueued(),
+ dropped: dropped,
+ delayed: delayedTime
+ };
+ }
+ };
+
+ this.mute = function() {
+ this.muted = muted = true;
+ };
+
+ this.unmute = function() {
+ this.muted = muted = false;
+ };
+
+ this.close = function() {
+ this.stop();
+
+ if(this.flashaudio) {
+ var wrapper = this.flashaudio.flashWrapper;
+ wrapper.parentNode.removeChild(wrapper);
+ this.flashaudio = null;
+ }
+
+ context = null;
+ buffers = null;
+ };
+
+ this.waitUntilReady = function(callback) {
+ var times = 0,
+ maxTimes = 100;
+ function pingFlashPlugin() {
+ setTimeout(function doPingFlashPlugin() {
+ times++;
+ if (self.flashaudio && self.flashaudio.flashElement.write) {
+ callback(this);
+ } else if (times > maxTimes) {
+ console.log("Failed to initialize Flash audio shim");
+ self.close();
+ callback(null);
+ } else {
+ pingFlashPlugin();
+ }
+ }, 20);
+ }
+ if (self.flashaudio) {
+ pingFlashPlugin();
+ } else {
+ setTimeout(callback, 0);
+ }
+ };
+
+ this.start = function() {
+ if (this.flashaudio) {
+ this.flashaudio.flashElement.start();
+ } else {
+ node.onaudioprocess = audioProcess;
+ node.connect(context.destination);
+ playbackTimeAtBufferTail = context.currentTime;
+ }
+ };
+
+ this.stop = function() {
+ if (this.flashaudio) {
+ this.flashaudio.flashElement.stop();
+ } else {
+ if (node) {
+ node.onaudioprocess = null;
+ node.disconnect();
+ }
+ }
+ };
+
+ /**
+ * A callback when we find we're out of buffered data.
+ */
+ this.onstarved = null;
+ };
+
+ AudioFeeder.sharedAudioContext = null;
+ AudioFeeder.initSharedAudioContext = function() {
+ if (AudioFeeder.sharedAudioContext === null) {
+ if ( AudioContext ) {
+ // We're only allowed 4 contexts on many browsers
+ // and there's no way to discard them (!)...
+ var context = AudioFeeder.sharedAudioContext = new AudioContext(),
+ node;
+ if ( context.createScriptProcessor ) {
+ node = context.createScriptProcessor( 1024, 0, 2 );
+ } else if ( context.createJavaScriptNode ) {
+ node = context.createJavaScriptNode( 1024, 0, 2 );
+ } else {
+ throw new Error( "Bad version of web audio API?" );
+ }
+
+ // Don't actually run any audio, just start & stop the node
+ node.connect( context.destination );
+ node.disconnect();
+ }
+ }
+ };
+
+
+ /** Flash fallback **/
+
+ /*
+ The Flash fallback is based on https://github.com/an146/dynamicaudio.js
+
+ This is the contents of the LICENSE file:
+
+ Copyright (c) 2010, Ben Firshman
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * The names of its contributors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+ function DynamicAudio(args) {
+ if (this instanceof arguments.callee) {
+ if (typeof this.init === "function") {
+ this.init.apply(this, (args && args.callee) ? args : arguments);
+ }
+ } else {
+ return new arguments.callee(arguments);
+ }
+ }
+
+
+ DynamicAudio.nextId = 1;
+
+ DynamicAudio.prototype = {
+ nextId: null,
+ swf: 'dynamicaudio.swf?' + Math.random(),
+
+ flashWrapper: null,
+ flashElement: null,
+
+ init: function(opts) {
+ var self = this;
+ self.id = DynamicAudio.nextId++;
+
+ if (opts && typeof opts.swf !== 'undefined') {
+ self.swf = opts.swf;
+ }
+
+
+ self.flashWrapper = document.createElement('div');
+ self.flashWrapper.id = 'dynamicaudio-flashwrapper-'+self.id;
+ // Credit to SoundManager2 for this:
+ var s = self.flashWrapper.style;
+ s.position = 'fixed';
+ s.width = '11px'; // must be at least 6px for flash to run fast
+ s.height = '11px';
+ s.bottom = s.left = '0px';
+ s.overflow = 'hidden';
+ self.flashElement = document.createElement('div');
+ self.flashElement.id = 'dynamicaudio-flashelement-'+self.id;
+ self.flashWrapper.appendChild(self.flashElement);
+
+ document.body.appendChild(self.flashWrapper);
+
+ var id = self.flashElement.id;
+
+ self.flashWrapper.innerHTML = "<object id='"+id+"' width='10' height='10' type='application/x-shockwave-flash' data='"+self.swf+"' style='visibility: visible;'><param name='allowscriptaccess' value='always'></object>";
+ self.flashElement = document.getElementById(id);
+ },
+ };
+
+})();
+
+
+// -- FrameSink.js
+
+/**
+ * @param HTMLCanvasElement canvas
+ * @constructor
+ */
+function FrameSink(canvas, videoInfo) {
+ var self = this,
+ ctx = canvas.getContext('2d'),
+ imageData = null,
+ resampleCanvas = null,
+ resampleContext = null;
+
+
+/**
+ * Basic YCbCr->RGB conversion
+ *
+ * @author Brion Vibber <brion@pobox.com>
+ * @copyright 2014
+ * @license MIT-style
+ *
+ * @param ybcbr {bytesY, bytesCb, bytesCr, strideY, strideCb, strideCr, width, height, hdec, vdec}
+ * @param TypedArray output: CanvasPixelArray or Uint8ClampedArray to draw RGBA into
+ * Assumes that the output array already has alpha channel set to opaque.
+ */
+function convertYCbCr(ybcbr, output) {
+ var width = ybcbr.width,
+ height = ybcbr.height,
+ hdec = ybcbr.hdec,
+ vdec = ybcbr.vdec,
+ bytesY = ybcbr.bytesY,
+ bytesCb = ybcbr.bytesCb,
+ bytesCr = ybcbr.bytesCr,
+ strideY = ybcbr.strideY,
+ strideCb = ybcbr.strideCb,
+ strideCr = ybcbr.strideCr,
+ outStride = 4 * width,
+ YPtr = 0, Y0Ptr = 0, Y1Ptr = 0,
+ CbPtr = 0, CrPtr = 0,
+ outPtr = 0, outPtr0 = 0, outPtr1 = 0,
+ colorCb = 0, colorCr = 0,
+ multY = 0, multCrR = 0, multCbCrG = 0, multCbB = 0,
+ x = 0, y = 0, xdec = 0, ydec = 0;
+
+ if (hdec == 1 && vdec == 1) {
+ // Optimize for 4:2:0, which is most common
+ outPtr0 = 0;
+ outPtr1 = outStride;
+ ydec = 0;
+ for (y = 0; y < height; y += 2) {
+ Y0Ptr = y * strideY;
+ Y1Ptr = Y0Ptr + strideY;
+ CbPtr = ydec * strideCb;
+ CrPtr = ydec * strideCr;
+ for (x = 0; x < width; x += 2) {
+ colorCb = bytesCb[CbPtr++];
+ colorCr = bytesCr[CrPtr++];
+
+ // Quickie YUV conversion
+ // https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.2020_conversion
+ // multiplied by 256 for integer-friendliness
+ multCrR = (409 * colorCr) - 57088;
+ multCbCrG = (100 * colorCb) + (208 * colorCr) - 34816;
+ multCbB = (516 * colorCb) - 70912;
+
+ multY = (298 * bytesY[Y0Ptr++]);
+ output[outPtr0++] = (multY + multCrR) >> 8;
+ output[outPtr0++] = (multY - multCbCrG) >> 8;
+ output[outPtr0++] = (multY + multCbB) >> 8;
+ outPtr0++;
+
+ multY = (298 * bytesY[Y0Ptr++]);
+ output[outPtr0++] = (multY + multCrR) >> 8;
+ output[outPtr0++] = (multY - multCbCrG) >> 8;
+ output[outPtr0++] = (multY + multCbB) >> 8;
+ outPtr0++;
+
+ multY = (298 * bytesY[Y1Ptr++]);
+ output[outPtr1++] = (multY + multCrR) >> 8;
+ output[outPtr1++] = (multY - multCbCrG) >> 8;
+ output[outPtr1++] = (multY + multCbB) >> 8;
+ outPtr1++;
+
+ multY = (298 * bytesY[Y1Ptr++]);
+ output[outPtr1++] = (multY + multCrR) >> 8;
+ output[outPtr1++] = (multY - multCbCrG) >> 8;
+ output[outPtr1++] = (multY + multCbB) >> 8;
+ outPtr1++;
+ }
+ outPtr0 += outStride;
+ outPtr1 += outStride;
+ ydec++;
+ }
+ } else {
+ outPtr = 0;
+ for (y = 0; y < height; y++) {
+ xdec = 0;
+ ydec = y >> vdec;
+ YPtr = y * strideY;
+ CbPtr = ydec * strideCb;
+ CrPtr = ydec * strideCr;
+
+ for (x = 0; x < width; x++) {
+ xdec = x >> hdec;
+ colorCb = bytesCb[CbPtr + xdec];
+ colorCr = bytesCr[CrPtr + xdec];
+
+ // Quickie YUV conversion
+ // https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.2020_conversion
+ // multiplied by 256 for integer-friendliness
+ multCrR = (409 * colorCr) - 57088;
+ multCbCrG = (100 * colorCb) + (208 * colorCr) - 34816;
+ multCbB = (516 * colorCb) - 70912;
+
+ multY = 298 * bytesY[YPtr++];
+ output[outPtr++] = (multY + multCrR) >> 8;
+ output[outPtr++] = (multY - multCbCrG) >> 8;
+ output[outPtr++] = (multY + multCbB) >> 8;
+ outPtr++;
+ }
+ }
+ }
+}
+
+
+ function initImageData(width, height) {
+ imageData = ctx.createImageData(width, height);
+
+ // Prefill the alpha to opaque
+ var data = imageData.data,
+ pixelCount = width * height * 4;
+ for (var i = 0; i < pixelCount; i += 4) {
+ data[i + 3] = 255;
+ }
+ }
+
+ function initResampleCanvas() {
+ resampleCanvas = document.createElement('canvas');
+ resampleCanvas.width = videoInfo.picWidth;
+ resampleCanvas.height = videoInfo.picHeight;
+ resampleContext = resampleCanvas.getContext('2d');
+ }
+
+ /**
+ * Actually draw a frame into the canvas.
+ */
+ self.drawFrame = function drawFrame(yCbCrBuffer) {
+ if (imageData === null ||
+ imageData.width != yCbCrBuffer.width ||
+ imageData.height != yCbCrBuffer.height) {
+ initImageData(yCbCrBuffer.width, yCbCrBuffer.height);
+ }
+ convertYCbCr(yCbCrBuffer, imageData.data);
+
+ var resample = (videoInfo.picWidth != videoInfo.displayWidth || videoInfo.picHeight != videoInfo.displayHeight);
+ if (resample) {
+ // hack for non-square aspect-ratio
+ // putImageData doesn't resample, so we have to draw in two steps.
+ if (!resampleCanvas) {
+ initResampleCanvas();
+ }
+ drawContext = resampleContext;
+ } else {
+ drawContext = ctx;
+ }
+
+ drawContext.putImageData(imageData,
+ 0, 0,
+ videoInfo.picX, videoInfo.picY,
+ videoInfo.picWidth, videoInfo.picHeight);
+
+ if (resample) {
+ ctx.drawImage(resampleCanvas, 0, 0, videoInfo.displayWidth, videoInfo.displayHeight);
+ }
+ };
+
+ return self;
+}
+
+
+
+// -- WebGLFrameSink.js
+
+
+/**
+ * Warning: canvas must not have been used for 2d drawing prior!
+ *
+ * @param HTMLCanvasElement canvas
+ * @constructor
+ */
+function WebGLFrameSink(canvas, videoInfo) {
+ var self = this,
+ gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'),
+ debug = false; // swap this to enable more error checks, which can slow down rendering
+
+ if (gl === null) {
+ throw new Error('WebGL unavailable');
+ }
+
+ // GL!
+ function checkError() {
+ if (debug) {
+ err = gl.getError();
+ if (err !== 0) {
+ throw new Error("GL error " + err);
+ }
+ }
+ }
+
+ function compileShader(type, source) {
+ var shader = gl.createShader(type);
+ gl.shaderSource(shader, source);
+ gl.compileShader(shader);
+
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
+ var err = gl.getShaderInfoLog(shader);
+ gl.deleteShader(shader);
+ throw new Error('GL shader compilation for ' + type + ' failed: ' + err);
+ }
+
+ return shader;
+ }
+
+
+ var vertexShader,
+ fragmentShader,
+ program,
+ buffer,
+ err;
+
+ // In the world of GL there are no rectangles.
+ // There are only triangles.
+ // THERE IS NO SPOON.
+ var rectangle = new Float32Array([
+ // First triangle (top left, clockwise)
+ -1.0, -1.0,
+ +1.0, -1.0,
+ -1.0, +1.0,
+
+ // Second triangle (bottom right, clockwise)
+ -1.0, +1.0,
+ +1.0, -1.0,
+ +1.0, +1.0
+ ]);
+
+ var textures = {};
+ function attachTexture(name, register, index, width, height, data) {
+ var texture,
+ texWidth = WebGLFrameSink.stripe ? (width / 4) : width,
+ format = WebGLFrameSink.stripe ? gl.RGBA : gl.LUMINANCE,
+ filter = WebGLFrameSink.stripe ? gl.NEAREST : gl.LINEAR;
+
+ if (textures[name]) {
+ // Reuse & update the existing texture
+ texture = textures[name];
+ } else {
+ textures[name] = texture = gl.createTexture();
+ checkError();
+
+ gl.uniform1i(gl.getUniformLocation(program, name), index);
+ checkError();
+ }
+ gl.activeTexture(register);
+ checkError();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ checkError();
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ checkError();
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ checkError();
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
+ checkError();
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
+ checkError();
+
+ gl.texImage2D(
+ gl.TEXTURE_2D,
+ 0, // mip level
+ format, // internal format
+ texWidth,
+ height,
+ 0, // border
+ format, // format
+ gl.UNSIGNED_BYTE, //type
+ data // data!
+ );
+ checkError();
+
+ return texture;
+ }
+
+ function buildStripe(width, height) {
+ var len = width * height,
+ out = new Uint32Array(len);
+ for (var i = 0; i < len; i += 4) {
+ out[i ] = 0x000000ff;
+ out[i + 1] = 0x0000ff00;
+ out[i + 2] = 0x00ff0000;
+ out[i + 3] = 0xff000000;
+ }
+ return new Uint8Array(out.buffer);
+ }
+
+ function init(yCbCrBuffer) {
+ vertexShader = compileShader(gl.VERTEX_SHADER, "attribute vec2 aPosition;\nattribute vec2 aLumaPosition;\nattribute vec2 aChromaPosition;\nvarying vec2 vLumaPosition;\nvarying vec2 vChromaPosition;\nvoid main() {\n gl_Position = vec4(aPosition, 0, 1);\n vLumaPosition = aLumaPosition;\n vChromaPosition = aChromaPosition;\n}\n");
+ if (WebGLFrameSink.stripe) {
+ fragmentShader = compileShader(gl.FRAGMENT_SHADER, "// inspired by https://github.com/mbebenita/Broadway/blob/master/Player/canvas.js\n// extra 'stripe' texture fiddling to work around IE 11's poor performance on gl.LUMINANCE and gl.ALPHA textures\n\nprecision mediump float;\nuniform sampler2D uStripeLuma;\nuniform sampler2D uStripeChroma;\nuniform sampler2D uTextureY;\nuniform sampler2D uTextureCb;\nuniform sampler2D uTextureCr;\nvarying vec2 vLumaPosition;\nvarying vec2 vChromaPosition;\nvoid main() {\n // Y, Cb, and Cr planes are mapped into a pseudo-RGBA texture\n // so we can upload them without expanding the bytes on IE 11\n // which doesn\\'t allow LUMINANCE or ALPHA textures.\n // The stripe textures mark which channel to keep for each pixel.\n vec4 vStripeLuma = texture2D(uStripeLuma, vLumaPosition);\n vec4 vStripeChroma = texture2D(uStripeChroma, vChromaPosition);\n\n // Each texture extraction will contain the relevant value in one\n // channel only.\n vec4 vY = texture2D(uTextureY, vLumaPosition) * vStripeLuma;\n vec4 vCb = texture2D(uTextureCb, vChromaPosition) * vStripeChroma;\n vec4 vCr = texture2D(uTextureCr, vChromaPosition) * vStripeChroma;\n\n // Now assemble that into a YUV vector, and premultipy the Y...\n vec3 YUV = vec3(\n (vY.x + vY.y + vY.z + vY.w) * 1.1643828125,\n (vCb.x + vCb.y + vCb.z + vCb.w),\n (vCr.x + vCr.y + vCr.z + vCr.w)\n );\n // And convert that to RGB!\n gl_FragColor = vec4(\n YUV.x + 1.59602734375 * YUV.z - 0.87078515625,\n YUV.x - 0.39176171875 * YUV.y - 0.81296875 * YUV.z + 0.52959375,\n YUV.x + 2.017234375 * YUV.y - 1.081390625,\n 1\n );\n}\n");
+ } else {
+ fragmentShader = compileShader(gl.FRAGMENT_SHADER, "// inspired by https://github.com/mbebenita/Broadway/blob/master/Player/canvas.js\n\nprecision mediump float;\nuniform sampler2D uTextureY;\nuniform sampler2D uTextureCb;\nuniform sampler2D uTextureCr;\nvarying vec2 vLumaPosition;\nvarying vec2 vChromaPosition;\nvoid main() {\n // Y, Cb, and Cr planes are uploaded as LUMINANCE textures.\n float fY = texture2D(uTextureY, vLumaPosition).x;\n float fCb = texture2D(uTextureCb, vChromaPosition).x;\n float fCr = texture2D(uTextureCr, vChromaPosition).x;\n\n // Premultipy the Y...\n float fYmul = fY * 1.1643828125;\n\n // And convert that to RGB!\n gl_FragColor = vec4(\n fYmul + 1.59602734375 * fCr - 0.87078515625,\n fYmul - 0.39176171875 * fCb - 0.81296875 * fCr + 0.52959375,\n fYmul + 2.017234375 * fCb - 1.081390625,\n 1\n );\n}\n");
+ }
+
+ program = gl.createProgram();
+ gl.attachShader(program, vertexShader);
+ checkError();
+
+ gl.attachShader(program, fragmentShader);
+ checkError();
+
+ gl.linkProgram(program);
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
+ var err = gl.getProgramInfoLog(program);
+ gl.deleteProgram(program);
+ throw new Error('GL program linking failed: ' + err);
+ }
+
+ gl.useProgram(program);
+ checkError();
+
+ if (WebGLFrameSink.stripe) {
+ attachTexture(
+ 'uStripeLuma',
+ gl.TEXTURE3,
+ 3,
+ yCbCrBuffer.strideY * 4,
+ yCbCrBuffer.height,
+ buildStripe(yCbCrBuffer.strideY, yCbCrBuffer.height)
+ );
+ checkError();
+
+ attachTexture(
+ 'uStripeChroma',
+ gl.TEXTURE4,
+ 4,
+ yCbCrBuffer.strideCb * 4,
+ yCbCrBuffer.height >> yCbCrBuffer.vdec,
+ buildStripe(yCbCrBuffer.strideCb, yCbCrBuffer.height >> yCbCrBuffer.vdec)
+ );
+ checkError();
+ }
+ }
+
+ self.drawFrame = function(yCbCrBuffer) {
+ if (!program) {
+ init(yCbCrBuffer);
+ }
+
+ // Set up the rectangle and draw it
+
+ //
+ // Set up geometry
+ //
+
+ buffer = gl.createBuffer();
+ checkError();
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ checkError();
+
+ gl.bufferData(gl.ARRAY_BUFFER, rectangle, gl.STATIC_DRAW);
+ checkError();
+
+ var positionLocation = gl.getAttribLocation(program, 'aPosition');
+ checkError();
+
+ gl.enableVertexAttribArray(positionLocation);
+ checkError();
+
+ gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
+ checkError();
+
+
+ // Set up the texture geometry...
+ function setupTexturePosition(varname, texWidth, texHeight) {
+ // Warning: assumes that the stride for Cb and Cr is the same size in output pixels
+ var textureX0 = videoInfo.picX / texWidth;
+ var textureX1 = (videoInfo.picX + videoInfo.picWidth) / texWidth;
+ var textureY0 = (videoInfo.picY + videoInfo.picHeight) / texHeight;
+ var textureY1 = videoInfo.picY / texHeight;
+ var textureRectangle = new Float32Array([
+ textureX0, textureY0,
+ textureX1, textureY0,
+ textureX0, textureY1,
+ textureX0, textureY1,
+ textureX1, textureY0,
+ textureX1, textureY1
+ ]);
+
+ var texturePositionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, texturePositionBuffer);
+ checkError();
+
+ gl.bufferData(gl.ARRAY_BUFFER, textureRectangle, gl.STATIC_DRAW);
+ checkError();
+
+ var texturePositionLocation = gl.getAttribLocation(program, varname);
+ checkError();
+
+ gl.enableVertexAttribArray(texturePositionLocation);
+ checkError();
+
+ gl.vertexAttribPointer(texturePositionLocation, 2, gl.FLOAT, false, 0, 0);
+ checkError();
+ }
+ setupTexturePosition('aLumaPosition', yCbCrBuffer.strideY, yCbCrBuffer.height);
+ setupTexturePosition('aChromaPosition', yCbCrBuffer.strideCb << yCbCrBuffer.hdec, yCbCrBuffer.height);
+
+ // Create the textures...
+ var textureY = attachTexture(
+ 'uTextureY',
+ gl.TEXTURE0,
+ 0,
+ yCbCrBuffer.strideY,
+ yCbCrBuffer.height,
+ yCbCrBuffer.bytesY
+ );
+ var textureCb = attachTexture(
+ 'uTextureCb',
+ gl.TEXTURE1,
+ 1,
+ yCbCrBuffer.strideCb,
+ yCbCrBuffer.height >> yCbCrBuffer.vdec,
+ yCbCrBuffer.bytesCb
+ );
+ var textureCr = attachTexture(
+ 'uTextureCr',
+ gl.TEXTURE2,
+ 2,
+ yCbCrBuffer.strideCr,
+ yCbCrBuffer.height >> yCbCrBuffer.vdec,
+ yCbCrBuffer.bytesCr
+ );
+
+ // Aaaaand draw stuff.
+ gl.drawArrays(gl.TRIANGLES, 0, rectangle.length / 2);
+ checkError();
+ };
+
+ return self;
+}
+
+// For Windows; luminance and alpha textures are ssllooww to upload,
+// so we pack into RGBA and unpack in the shaders.
+//
+// This seems to affect all browsers on Windows, probably due to fun
+// mismatches between GL and D3D.
+WebGLFrameSink.stripe = (function() {
+ if (navigator.userAgent.indexOf('Windows') !== -1) {
+ return true;
+ }
+ return false;
+})();
+
+/**
+ * Static function to check if WebGL will be available with appropriate features.
+ *
+ * @return boolean
+ */
+WebGLFrameSink.isAvailable = function() {
+ var canvas = document.createElement('canvas'),
+ gl;
+ canvas.width = 1;
+ canvas.height = 1;
+ var options = {
+ failIfMajorPerformanceCaveat: true
+ };
+ try {
+ gl = canvas.getContext('webgl', options) || canvas.getContext('experimental-webgl', options);
+ } catch (e) {
+ return false;
+ }
+ if (gl) {
+ var register = gl.TEXTURE0,
+ width = 4,
+ height = 4,
+ texture = gl.createTexture(),
+ data = new Uint8Array(width * height),
+ texWidth = WebGLFrameSink.stripe ? (width / 4) : width,
+ format = WebGLFrameSink.stripe ? gl.RGBA : gl.LUMINANCE,
+ filter = WebGLFrameSink.stripe ? gl.NEAREST : gl.LINEAR;
+
+ gl.activeTexture(register);
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
+ gl.texImage2D(
+ gl.TEXTURE_2D,
+ 0, // mip level
+ format, // internal format
+ texWidth,
+ height,
+ 0, // border
+ format, // format
+ gl.UNSIGNED_BYTE, //type
+ data // data!
+ );
+
+ var err = gl.getError();
+ if (err) {
+ // Doesn't support luminance textures?
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
+};
+
+
+
+// -- Bisector.js
+
+/**
+ * Give as your 'process' function something that will trigger an async
+ * operation, then call the left() or right() methods to run another
+ * iteration, bisecting to the given direction.
+ *
+ * Caller is responsible for determining when done.
+ *
+ * @params options object {
+ * start: number,
+ * end: number,
+ * process: function(start, position, end)
+ * }
+ */
+function Bisector(options) {
+ var start = options.start,
+ end = options.end,
+ position = 0,
+ self = this,
+ n = 0;
+
+ function iterate() {
+ n++;
+ position = Math.floor((start + end) / 2);
+ return options.process(start, end, position);
+ }
+
+ self.start = function() {
+ iterate();
+ return self;
+ };
+
+ self.left = function() {
+ end = position;
+ return iterate();
+ };
+
+ self.right = function() {
+ start = position;
+ return iterate();
+ };
+}
+
+
+// -- OGVMediaType.js
+
+function OGVMediaType(contentType) {
+ contentType = '' + contentType;
+
+ var self = this;
+ self.major = null;
+ self.minor = null;
+ self.codecs = null;
+
+ function trim(str) {
+ return str.replace(/^\s+/, '').replace(/\s+$/, '');
+ }
+
+ function split(str, sep, limit) {
+ var bits = str.split(sep, limit).map(function(substr) {
+ return trim(substr);
+ });
+ if (typeof limit === 'number') {
+ while (bits.length < limit) {
+ bits.push(null);
+ }
+ }
+ return bits;
+ }
+
+ var parts = split(contentType, ';');
+ if (parts.length) {
+ var base = parts.shift();
+ if (base) {
+ var bits = split(base, '/', 2);
+ self.major = bits[0];
+ self.minor = bits[1];
+ }
+
+ parts.forEach(function(str) {
+ var matches = str.match(/^codecs\s*=\s*"(.*?)"$/);
+ if (matches) {
+ self.codecs = split(matches[1], ',');
+ }
+ });
+ }
+}
+
+
+// -- OGVWrapperCodec.js
+
+/**
+ * Proxy object for web worker interface for codec classes.
+ *
+ * Used by the high-level player interface.
+ *
+ * @author Brion Vibber <brion@pobox.com>
+ * @copyright 2015
+ * @license MIT-style
+ */
+OGVWrapperCodec = (function(options) {
+ options = options || {};
+ var self = this,
+ suffix = '?version=' + encodeURIComponent(OGVVersion),
+ base = (typeof options.base === 'string') ? (options.base + '/') : '',
+ type = (typeof options.type === 'string') ? options.type : 'video/ogg',
+ processing = false,
+ demuxer = null,
+ videoDecoder = null,
+ audioDecoder = null;
+
+ var loadedMetadata = false;
+ Object.defineProperty(self, 'loadedMetadata', {
+ get: function() {
+ return loadedMetadata;
+ }
+ });
+
+ Object.defineProperty(self, 'processing', {
+ get: function() {
+ return processing
+ || (videoDecoder && videoDecoder.processing)
+ || (audioDecoder && audioDecoder.processing);
+ }
+ });
+
+ Object.defineProperty(self, 'duration', {
+ get: function() {
+ if (self.loadedMetadata) {
+ return demuxer.duration;
+ } else {
+ return NaN;
+ }
+ }
+ });
+
+ Object.defineProperty(self, 'hasAudio', {
+ get: function() {
+ return self.loadedMetadata && !!audioDecoder;
+ }
+ });
+
+ Object.defineProperty(self, 'audioReady', {
+ get: function() {
+ return self.hasAudio && demuxer.audioReady;
+ }
+ });
+
+ Object.defineProperty(self, 'audioTimestamp', {
+ get: function() {
+ return demuxer.audioTimestamp;
+ }
+ });
+
+ Object.defineProperty(self, 'audioFormat', {
+ get: function() {
+ if (self.hasAudio) {
+ return audioDecoder.audioFormat;
+ } else {
+ return null;
+ }
+ }
+ });
+
+ Object.defineProperty(self, 'audioBuffer', {
+ get: function() {
+ if (self.hasAudio) {
+ return audioDecoder.audioBuffer;
+ } else {
+ return null;
+ }
+ }
+ });
+
+ Object.defineProperty(self, 'hasVideo', {
+ get: function() {
+ return self.loadedMetadata && !!videoDecoder;
+ }
+ });
+
+ Object.defineProperty(self, 'frameReady', {
+ get: function() {
+ return self.hasVideo && demuxer.frameReady;
+ }
+ });
+
+ Object.defineProperty(self, 'frameTimestamp', {
+ get: function() {
+ return demuxer.frameTimestamp;
+ }
+ });
+
+ Object.defineProperty(self, 'keyframeTimestamp', {
+ get: function() {
+ return demuxer.keyframeTimestamp;
+ }
+ });
+
+ Object.defineProperty(self, 'videoFormat', {
+ get: function() {
+ if (self.hasVideo) {
+ return videoDecoder.videoFormat;
+ } else {
+ return null;
+ }
+ }
+ });
+
+ Object.defineProperty(self, 'frameBuffer', {
+ get: function() {
+ if (self.hasVideo) {
+ return videoDecoder.frameBuffer;
+ } else {
+ return null;
+ }
+ }
+ });
+
+ Object.defineProperty(self, 'seekable', {
+ get: function() {
+ return demuxer.seekable;
+ }
+ });
+
+ // - public methods
+ self.init = function(callback) {
+ var demuxerClassName;
+ if (options.type === 'video/webm') {
+ demuxerClassName = 'OGVDemuxerWebM';
+ } else {
+ demuxerClassName = 'OGVDemuxerOgg';
+ }
+ OGVLoader.loadClass(demuxerClassName, function(demuxerClass) {
+ demuxer = new demuxerClass();
+ demuxer.init(callback);
+ });
+ };
+
+ self.destroy = function() {
+ demuxer = null;
+ videoDecoder = null;
+ audioDecoder = null;
+ };
+
+ var inputQueue = [];
+ self.receiveInput = function(data, callback) {
+ inputQueue.push(data);
+ callback();
+ };
+
+ var audioClassMap = {
+ vorbis: 'OGVDecoderAudioVorbis',
+ opus: 'OGVDecoderAudioOpus'
+ };
+ function loadAudioCodec(callback) {
+ if (demuxer.audioCodec) {
+ var className = audioClassMap[demuxer.audioCodec];
+ processing = true;
+ OGVLoader.loadClass(className, function(audioCodecClass) {
+ var audioOptions = {};
+ if (demuxer.audioFormat) {
+ audioOptions.audioFormat = demuxer.audioFormat;
+ }
+ audioDecoder = new audioCodecClass(audioOptions);
+ audioDecoder.init(function() {
+ loadedAudioMetadata = audioDecoder.loadedMetadata;
+ processing = false;
+ callback();
+ });
+ }, {
+ worker: options.worker
+ });
+ } else {
+ callback();
+ }
+ }
+
+ var videoClassMap = {
+ theora: 'OGVDecoderVideoTheora',
+ vp8: 'OGVDecoderVideoVP8',
+ vp9: 'OGVDecoderVideoVP9'
+ };
+ function loadVideoCodec(callback) {
+ if (demuxer.videoCodec) {
+ var className = videoClassMap[demuxer.videoCodec];
+ processing = true;
+ OGVLoader.loadClass(className, function(videoCodecClass) {
+ var videoOptions = {};
+ if (demuxer.videoFormat) {
+ videoOptions.videoFormat = demuxer.videoFormat;
+ }
+ videoDecoder = new videoCodecClass(videoOptions);
+ videoDecoder.init(function() {
+ loadedVideoMetadata = videoDecoder.loadedMetadata;
+ processing = false;
+ callback();
+ });
+ }, {
+ worker: options.worker
+ });
+ } else {
+ callback();
+ }
+ }
+
+ var loadedDemuxerMetadata = false,
+ loadedAudioMetadata = false,
+ loadedVideoMetadata = false;
+
+ self.process = function(callback) {
+ if (processing) {
+ throw new Error('reentrancy fail on OGVWrapperCodec.process');
+ }
+ processing = true;
+ function finish(result) {
+ processing = false;
+ callback(result);
+ }
+
+ function doProcessData() {
+ if (inputQueue.length) {
+ var data = inputQueue.shift();
+ demuxer.process(data, function(more) {
+ if (!more && inputQueue.length) {
+ // we've got more to process already
+ more = true;
+ }
+ finish(more);
+ });
+ } else {
+ // out of data! ask for more
+ finish(false);
+ }
+ }
+
+ if (demuxer.loadedMetadata && !loadedDemuxerMetadata) {
+
+ // Demuxer just reached its metadata. Load the relevant codecs!
+ loadAudioCodec(function() {
+ loadVideoCodec(function() {
+ loadedDemuxerMetadata = true;
+ loadedAudioMetadata = !audioDecoder;
+ loadedVideoMetadata = !videoDecoder;
+ loadedAllMetadata = loadedAudioMetadata && loadedVideoMetadata;
+ finish(true);
+ });
+ });
+
+ } else if (loadedDemuxerMetadata && !loadedAudioMetadata) {
+
+ if (audioDecoder.loadedMetadata) {
+
+ loadedAudioMetadata = true;
+ loadedAllMetadata = loadedAudioMetadata && loadedVideoMetadata;
+ finish(true);
+
+ } else if (demuxer.audioReady) {
+
+ demuxer.dequeueAudioPacket(function(packet) {
+ audioDecoder.processHeader(packet, function(ret) {
+ finish(true);
+ });
+ });
+
+ } else {
+
+ doProcessData();
+
+ }
+
+ } else if (loadedAudioMetadata && !loadedVideoMetadata) {
+
+ if (videoDecoder.loadedMetadata) {
+
+ loadedVideoMetadata = true;
+ loadedAllMetadata = loadedAudioMetadata && loadedVideoMetadata;
+ finish(true);
+
+ } else if (demuxer.frameReady) {
+
+ processing = true;
+ demuxer.dequeueVideoPacket(function(packet) {
+ videoDecoder.processHeader(packet, function() {
+ finish(true);
+ });
+ });
+
+ } else {
+
+ doProcessData();
+
+ }
+
+ } else if (loadedVideoMetadata && !self.loadedMetadata && loadedAllMetadata) {
+
+ // Ok we've found all the metadata there is. Enjoy.
+ loadedMetadata = true;
+ finish(true);
+
+ } else if (self.loadedMetadata && (!self.hasAudio || demuxer.audioReady) && (!self.hasVideo || demuxer.frameReady)) {
+
+ // Already queued up some packets. Go read them!
+ finish(true);
+
+ } else {
+
+ // We need to process more of the data we've already received,
+ // or ask for more if we ran out!
+ doProcessData();
+
+ }
+
+ };
+
+ self.decodeFrame = function(callback) {
+ var timestamp = self.frameTimestamp,
+ keyframeTimestamp = self.keyframeTimestamp;
+ demuxer.dequeueVideoPacket(function(packet) {
+ videoDecoder.processFrame(packet, function(ok) {
+ // hack
+ if (self.frameBuffer) {
+ self.frameBuffer.timestamp = timestamp;
+ self.frameBuffer.keyframeTimestamp = keyframeTimestamp;
+ }
+ callback(ok);
+ });
+ });
+ };
+
+ self.decodeAudio = function(callback) {
+ demuxer.dequeueAudioPacket(function(packet) {
+ audioDecoder.processAudio(packet, function(ok) {
+ callback(ok);
+ });
+ });
+ }
+
+ self.discardFrame = function(callback) {
+ demuxer.dequeueVideoPacket(function(packet) {
+ callback();
+ });
+ };
+
+ self.discardAudio = function(callback) {
+ demuxer.dequeueAudioPacket(function(packet) {
+ callback(ok);
+ });
+ };
+
+ self.flush = function(callback) {
+ inputQueue.splice(0, inputQueue.length);
+ demuxer.flush(callback);
+ };
+
+ self.getKeypointOffset = function(timeSeconds, callback) {
+ demuxer.getKeypointOffset(timeSeconds, callback);
+ };
+
+ return self;
+});
+
+
+// -- OGVProxyClass.js
+
+/**
+ * Proxy object for web worker interface for codec classes.
+ *
+ * Used by the high-level player interface.
+ *
+ * @author Brion Vibber <brion@pobox.com>
+ * @copyright 2015
+ * @license MIT-style
+ */
+function OGVProxyClass(initialProps, methods) {
+ return function(worker, className, options) {
+ options = options || {};
+ var self = this;
+
+ var transferables = (function() {
+ var buffer = new ArrayBuffer(1024),
+ bytes = new Uint8Array(buffer);
+ try {
+ worker.postMessage({
+ action: 'transferTest',
+ bytes: bytes
+ }, [buffer]);
+ if (buffer.byteLength) {
+ // No transferable support
+ return false;
+ } else {
+ return true;
+ }
+ } catch (e) {
+ return false;
+ }
+ })();
+
+ // Set up proxied property getters
+ var props = {};
+ for (var iPropName in initialProps) {
+ if (initialProps.hasOwnProperty(iPropName)) {
+ (function(propName) {
+ props[propName] = initialProps[propName];
+ Object.defineProperty(self, propName, {
+ get: function getProperty() {
+ return props[propName];
+ }
+ });
+ })(iPropName);
+ }
+ }
+
+ // Current player wants to avoid async confusion.
+ var processingQueue = 0;
+ Object.defineProperty(self, 'processing', {
+ get: function() {
+ return (processingQueue > 0);
+ }
+ });
+
+ // Set up proxied methods
+ for (var method in methods) {
+ if (methods.hasOwnProperty(method)) {
+ self[method] = methods[method];
+ }
+ }
+
+ // And some infrastructure!
+ var messageCount = 0,
+ pendingCallbacks = {};
+ this.proxy = function(action, args, callback, transfers) {
+ var callbackId = 'callback-' + (++messageCount) + '-' + action;
+ if (callback) {
+ pendingCallbacks[callbackId] = callback;
+ }
+ var out = {
+ 'action': action,
+ 'callbackId': callbackId,
+ 'args': args || []
+ };
+ processingQueue++;
+ if (transferables) {
+ worker.postMessage(out, transfers || []);
+ } else {
+ worker.postMessage(out);
+ }
+ };
+
+ worker.addEventListener('message', function proxyOnMessage(event) {
+ processingQueue--;
+ if (event.data.action !== 'callback') {
+ // ignore
+ return;
+ }
+
+ var data = event.data,
+ callbackId = data.callbackId,
+ args = data.args,
+ callback = pendingCallbacks[callbackId];
+
+ // Save any updated properties returned to us...
+ if (data.props) {
+ for (var propName in data.props) {
+ if (data.props.hasOwnProperty(propName)) {
+ props[propName] = data.props[propName];
+ }
+ }
+ }
+
+ if (callback) {
+ delete pendingCallbacks[callbackId];
+ callback.apply(this, args);
+ }
+ });
+
+ // Tell the proxy to load and initialize the appropriate class
+ self.proxy('construct', [className, options], function() {});
+
+ return self;
+ };
+}
+
+
+// -- OGVDecoderAudioProxy.js
+
+OGVDecoderAudioProxy = OGVProxyClass({
+ loadedMetadata: false,
+ audioFormat: null,
+ audioBuffer: null
+}, {
+ init: function(callback) {
+ this.proxy('init', [], callback);
+ },
+
+ processHeader: function(data, callback) {
+ this.proxy('processHeader', [data], callback, [data]);
+ },
+
+ processAudio: function(data, callback) {
+ this.proxy('processAudio', [data], callback, [data]);
+ }
+});
+
+
+// -- OGVDecoderVideoProxy.js
+
+OGVDecoderVideoProxy = OGVProxyClass({
+ loadedMetadata: false,
+ videoFormat: null,
+ frameBuffer: null
+}, {
+ init: function(callback) {
+ this.proxy('init', [], callback);
+ },
+
+ processHeader: function(data, callback) {
+ this.proxy('processHeader', [data], callback, [data]);
+ },
+
+ processFrame: function(data, callback) {
+ this.proxy('processFrame', [data], callback, [data]);
+ }
+});
+
+
+// -- OGVPlayer.js
+
+/**
+ * Constructor for an analogue of the TimeRanges class
+ * returned by various HTMLMediaElement properties
+ *
+ * Pass an array of two-element arrays, each containing a start and end time.
+ */
+OGVTimeRanges = window.OGVTimeRanges = function(ranges) {
+ Object.defineProperty(this, 'length', {
+ get: function getLength() {
+ return ranges.length;
+ }
+ });
+ this.start = function(i) {
+ return ranges[i][0];
+ };
+ this.end = function(i) {
+ return ranges[i][1];
+ };
+ return this;
+};
+
+/**
+ * Player class -- instantiate one of these to get an 'ogvjs' HTML element
+ * which has a similar interface to the HTML audio/video elements.
+ *
+ * @param options: optional dictionary of options:
+ * 'base': string; base URL for additional resources, such as Flash audio shim
+ * 'webGL': bool; pass true to use WebGL acceleration if available
+ * 'forceWebGL': bool; pass true to require WebGL even if not detected
+ */
+OGVPlayer = window.OGVPlayer = function(options) {
+ options = options || {};
+
+ var instanceId = 'ogvjs' + (++OGVPlayer.instanceCount);
+
+ var codecClassName = null,
+ codecClass = null,
+ codecType = null;
+
+ var webGLdetected = WebGLFrameSink.isAvailable();
+ var useWebGL = (options.webGL !== false) && webGLdetected;
+ if(!!options.forceWebGL) {
+ useWebGL = true;
+ if(!webGLdetected) {
+ console.log("No support for WebGL detected, but WebGL forced on!");
+ }
+ }
+
+ // Experimental options
+ var enableWebM = !!options.enableWebM;
+
+ // Running the codec in a worker thread equals happy times!
+ var enableWorker = !!window.Worker;
+ if (typeof options.worker !== 'undefined') {
+ enableWorker = !!options.worker;
+ }
+
+ var State = {
+ INITIAL: 'INITIAL',
+ SEEKING_END: 'SEEKING_END',
+ LOADED: 'LOADED',
+ READY: 'READY',
+ PLAYING: 'PLAYING',
+ SEEKING: 'SEEKING',
+ ENDED: 'ENDED'
+ }, state = State.INITIAL;
+
+ var SeekState = {
+ NOT_SEEKING: 'NOT_SEEKING',
+ BISECT_TO_TARGET: 'BISECT_TO_TARGET',
+ BISECT_TO_KEYPOINT: 'BISECT_TO_KEYPOINT',
+ LINEAR_TO_TARGET: 'LINEAR_TO_TARGET'
+ }, seekState = SeekState.NOT_SEEKING;
+
+ var audioOptions = {},
+ codecOptions = {};
+ options.base = options.base || OGVLoader.base;
+ if (typeof options.base === 'string') {
+ // Pass the resource dir down to AudioFeeder, so it can load the dynamicaudio.swf
+ audioOptions.base = options.base;
+
+ // And to the worker thread, so it can load the codec JS
+ codecOptions.base = options.base;
+ }
+ if (typeof options.audioContext !== 'undefined') {
+ // Try passing a pre-created audioContext in?
+ audioOptions.audioContext = options.audioContext;
+ }
+ codecOptions.worker = enableWorker;
+
+ var canvas = document.createElement('canvas');
+ var frameSink;
+
+ // Return a magical custom element!
+ var self = document.createElement('ogvjs');
+ self.className = instanceId;
+
+ canvas.style.position = 'absolute';
+ canvas.style.top = '0';
+ canvas.style.left = '0';
+ canvas.style.width = '100%';
+ canvas.style.height = '100%';
+ canvas.style.objectFit = 'contain';
+ self.appendChild(canvas);
+
+ var getTimestamp;
+ if (window.performance === undefined || window.performance.now === undefined) {
+ getTimestamp = Date.now;
+ } else {
+ getTimestamp = window.performance.now.bind(window.performance);
+ }
+ function time(cb) {
+ var start = getTimestamp();
+ cb();
+ var delta = getTimestamp() - start;
+ lastFrameDecodeTime += delta;
+ return delta;
+ }
+
+ var then = getTimestamp();
+ function log(msg) {
+ if (options.debug) {
+ /*
+ var now = getTimestamp(),
+ delta = now - then;
+
+ console.log('+' + delta + 'ms proc: ' + msg);
+ then = now;
+ */
+ console.log('OGVPlayer: ' + msg);
+ }
+ }
+
+ function fireEvent(eventName, props) {
+ var event;
+ props = props || {};
+
+ if (typeof window.Event == 'function') {
+ // standard event creation
+ event = new CustomEvent(eventName);
+ } else {
+ // IE back-compat mode
+ // https://msdn.microsoft.com/en-us/library/dn905219%28v=vs.85%29.aspx
+ event = document.createEvent('Event');
+ event.initEvent(eventName, false, false);
+ }
+
+ for (var prop in props) {
+ if (props.hasOwnProperty(prop)) {
+ event[prop] = props[prop];
+ }
+ }
+
+ self.dispatchEvent(event);
+ }
+
+ var codec,
+ actionQueue = [],
+ audioFeeder;
+ var muted = false,
+ initialPlaybackPosition = 0.0,
+ initialPlaybackOffset = 0.0;
+ function initAudioFeeder() {
+ audioFeeder = new AudioFeeder( audioOptions );
+ if (muted) {
+ audioFeeder.mute();
+ }
+ audioFeeder.onstarved = function() {
+ // If we're in a background tab, timers may be throttled.
+ // When audio buffers run out, go decode some more stuff.
+ if (nextProcessingTimer) {
+ clearTimeout(nextProcessingTimer);
+ nextProcessingTimer = null;
+ pingProcessing();
+ }
+ };
+ audioFeeder.init(audioInfo.channels, audioInfo.rate);
+ }
+
+ function startPlayback(offset) {
+ if (audioFeeder) {
+ audioFeeder.start();
+ var state = audioFeeder.getPlaybackState();
+ initialPlaybackPosition = state.playbackPosition;
+ } else {
+ initialPlaybackPosition = getTimestamp() / 1000;
+ }
+ if (offset !== undefined) {
+ initialPlaybackOffset = offset;
+ }
+ log('continuing at ' + initialPlaybackPosition + ', ' + initialPlaybackOffset);
+ }
+
+ function stopPlayback() {
+ if (audioFeeder) {
+ audioFeeder.stop();
+ }
+ initialPlaybackOffset = getPlaybackTime();
+ log('pausing at ' + initialPlaybackOffset);
+ }
+
+ /**
+ * Get audio playback time position in file's units
+ *
+ * @return {number} seconds since file start
+ */
+ function getPlaybackTime(state) {
+ var position;
+ if (audioFeeder) {
+ state = state || audioFeeder.getPlaybackState();
+ position = state.playbackPosition;
+ } else {
+ position = getTimestamp() / 1000;
+ }
+ return (position - initialPlaybackPosition) + initialPlaybackOffset;
+ }
+
+ var stream,
+ byteLength = 0,
+ duration = null,
+ lastSeenTimestamp = null,
+ nextProcessingTimer,
+ started = false,
+ paused = true,
+ ended = false,
+ startedPlaybackInDocument = false,
+ waitingOnInput = false;
+
+ var framesPlayed = 0;
+ // Benchmark data, exposed via getPlaybackStats()
+ var framesProcessed = 0, // frames
+ targetPerFrameTime = 1000 / 60, // ms
+ totalFrameTime = 0, // ms
+ totalFrameCount = 0, // frames
+ playTime = 0, // ms
+ demuxingTime = 0, // ms
+ videoDecodingTime = 0, // ms
+ audioDecodingTime = 0, // ms
+ bufferTime = 0, // ms
+ drawingTime = 0, // ms
+ totalJitter = 0; // sum of ms we're off from expected frame delivery time
+ // Benchmark data that doesn't clear
+ var droppedAudio = 0, // number of times we were starved for audio
+ delayedAudio = 0; // seconds audio processing was delayed by blocked CPU
+ var poster = '', thumbnail;
+
+ function stopVideo() {
+ log("STOPPING");
+ // kill the previous video if any
+ state = State.INITIAL;
+ started = false;
+ paused = true;
+ ended = true;
+ frameEndTimestamp = 0.0;
+ audioEndTimestamp = 0.0;
+ lastFrameDecodeTime = 0.0;
+
+ if (stream) {
+ stream.abort();
+ stream = null;
+ }
+ if (codec) {
+ codec.destroy();
+ codec = null;
+ }
+ if (audioFeeder) {
+ audioFeeder.close();
+ audioFeeder = undefined;
+ }
+ if (nextProcessingTimer) {
+ clearTimeout(nextProcessingTimer);
+ nextProcessingTimer = null;
+ }
+ }
+
+ var lastFrameTime = getTimestamp(),
+ frameEndTimestamp = 0.0,
+ audioEndTimestamp = 0.0,
+ yCbCrBuffer = null;
+ var lastFrameDecodeTime = 0.0;
+ var lastFrameTimestamp = 0.0;
+
+ function doFrameComplete() {
+ if (startedPlaybackInDocument && !document.body.contains(self)) {
+ // We've been de-parented since we last ran
+ // Stop playback at next opportunity!
+ setTimeout(function() {
+ self.stop();
+ }, 0);
+ }
+
+ var newFrameTimestamp = getTimestamp(),
+ wallClockTime = newFrameTimestamp - lastFrameTimestamp,
+ jitter = Math.abs(wallClockTime - targetPerFrameTime);
+ totalJitter += jitter;
+ playTime += wallClockTime;
+
+ fireEvent('framecallback', {
+ cpuTime: lastFrameDecodeTime,
+ clockTime: wallClockTime
+ });
+ lastFrameDecodeTime = 0;
+ lastFrameTimestamp = newFrameTimestamp;
+ }
+
+
+ // -- seek functions
+ var seekTargetTime = 0.0,
+ seekTargetKeypoint = 0.0,
+ bisectTargetTime = 0.0,
+ lastSeekPosition,
+ lastFrameSkipped,
+ seekBisector;
+
+ function startBisection(targetTime) {
+ bisectTargetTime = targetTime;
+ seekBisector = new Bisector({
+ start: 0,
+ end: stream.bytesTotal - 1,
+ process: function(start, end, position) {
+ if (position == lastSeekPosition) {
+ return false;
+ } else {
+ lastSeekPosition = position;
+ lastFrameSkipped = false;
+ codec.flush(function() {
+ stream.seek(position);
+ readBytesAndWait();
+ });
+ return true;
+ }
+ }
+ });
+ seekBisector.start();
+ }
+
+ function seek(toTime) {
+ if (stream.bytesTotal === 0) {
+ throw new Error('Cannot bisect a non-seekable stream');
+ }
+ state = State.SEEKING;
+ seekTargetTime = toTime;
+ seekTargetKeypoint = -1;
+ lastFrameSkipped = false;
+ lastSeekPosition = -1;
+
+ actionQueue.push(function() {
+ stopPlayback();
+
+ codec.flush(function() {
+ codec.getKeypointOffset(toTime, function(offset) {
+ if (offset > 0) {
+ // This file has an index!
+ //
+ // Start at the keypoint, then decode forward to the desired time.
+ //
+ seekState = SeekState.LINEAR_TO_TARGET;
+ stream.seek(offset);
+ readBytesAndWait();
+ } else {
+ // No index.
+ //
+ // Bisect through the file finding our target time, then we'll
+ // have to do it again to reach the keypoint, and *then* we'll
+ // have to decode forward back to the desired time.
+ //
+ seekState = SeekState.BISECT_TO_TARGET;
+ startBisection(seekTargetTime);
+ }
+ });
+ });
+ });
+ }
+
+ function continueSeekedPlayback() {
+ seekState = SeekState.NOT_SEEKING;
+ state = State.PLAYING;
+ frameEndTimestamp = codec.frameTimestamp;
+ audioEndTimestamp = codec.audioTimestamp;
+ if (codec.hasAudio) {
+ seekTargetTime = codec.audioTimestamp;
+ } else {
+ seekTargetTime = codec.frameTimestamp;
+ }
+ startPlayback(seekTargetTime);
+ if (paused) {
+ stopPlayback(); // :P
+ } else {
+ if (isProcessing()) {
+ // wait for whatever's going on to complete
+ } else {
+ pingProcessing(0);
+ }
+ }
+ }
+
+ /**
+ * @return {boolean} true to continue processing, false to wait for input data
+ */
+ function doProcessLinearSeeking() {
+ var frameDuration;
+ if (codec.hasVideo) {
+ frameDuration = targetPerFrameTime;
+ } else {
+ frameDuration = 1 / 256; // approximate packet audio size, fake!
+ }
+
+ if (codec.hasVideo) {
+ if (!codec.frameReady) {
+ // Haven't found a frame yet, process more data
+ pingProcessing();
+ return;
+ } else if (codec.frameTimestamp < 0 || codec.frameTimestamp + frameDuration < seekTargetTime) {
+ // Haven't found a time yet, or haven't reached the target time.
+ // Decode it in case we're at our keyframe or a following intraframe...
+ codec.decodeFrame(function() {
+ pingProcessing();
+ });
+ return;
+ } else {
+ // Reached or surpassed the target time.
+ if (codec.hasAudio) {
+ // Keep processing the audio track
+ // fall through...
+ } else {
+ continueSeekedPlayback();
+ return;
+ }
+ }
+ }
+ if (codec.hasAudio) {
+ if (!codec.audioReady) {
+ // Haven't found an audio packet yet, process more data
+ pingProcessing();
+ return;
+ }
+ if (codec.audioTimestamp < 0 || codec.audioTimestamp + frameDuration < seekTargetTime) {
+ // Haven't found a time yet, or haven't reached the target time.
+ // Decode it so when we reach the target we've got consistent data.
+ codec.decodeAudio(function() {
+ pingProcessing();
+ });
+ return;
+ } else {
+ continueSeekedPlayback();
+ return;
+ }
+ }
+ }
+
+ function doProcessBisectionSeek() {
+ var frameDuration,
+ timestamp;
+ if (codec.hasVideo) {
+ if (!codec.frameReady) {
+ // Haven't found a frame yet, process more data
+ pingProcessing();
+ return;
+ }
+ timestamp = codec.frameTimestamp;
+ frameDuration = targetPerFrameTime;
+ } else if (codec.hasAudio) {
+ if (!codec.audioReady) {
+ // Haven't found an audio packet yet, process more data
+ pingProcessing();
+ return;
+ }
+ timestamp = codec.audioTimestamp;
+ frameDuration = 1 / 256; // approximate packet audio size, fake!
+ } else {
+ throw new Error('Invalid seek state; no audio or video track available');
+ }
+
+ if (timestamp < 0) {
+ // Haven't found a time yet.
+ // Decode in case we're at our keyframe or a following intraframe...
+ if (codec.frameReady) {
+ codec.decodeFrame(function() {
+ pingProcessing();
+ });
+ } else if (codec.audioReady) {
+ codec.decodeAudio(function() {
+ pingProcessing();
+ });
+ } else {
+ pingProcessing();
+ }
+ } else if (timestamp - frameDuration > bisectTargetTime) {
+ if (seekBisector.left()) {
+ // wait for new data to come in
+ } else {
+ seekTargetTime = codec.frameTimestamp;
+ continueSeekedPlayback();
+ }
+ } else if (timestamp + frameDuration < bisectTargetTime) {
+ if (seekBisector.right()) {
+ // wait for new data to come in
+ } else {
+ seekTargetTime = codec.frameTimestamp;
+ continueSeekedPlayback();
+ }
+ } else {
+ // Reached the bisection target!
+ if (seekState == SeekState.BISECT_TO_TARGET && (codec.hasVideo && codec.keyframeTimestamp < codec.frameTimestamp)) {
+ // We have to go back and find a keyframe. Sigh.
+ seekState = SeekState.BISECT_TO_KEYPOINT;
+ startBisection(codec.keyframeTimestamp);
+ } else {
+ // Switch to linear mode to find the final target.
+ seekState = SeekState.LINEAR_TO_TARGET;
+ pingProcessing();
+ }
+ }
+ }
+
+ function setupVideo() {
+ if (videoInfo.fps > 0) {
+ targetPerFrameTime = 1000 / videoInfo.fps;
+ } else {
+ targetPerFrameTime = 16.667; // recalc this later
+ }
+
+ canvas.width = videoInfo.displayWidth;
+ canvas.height = videoInfo.displayHeight;
+ OGVPlayer.styleManager.appendRule('.' + instanceId, {
+ width: videoInfo.displayWidth + 'px',
+ height: videoInfo.displayHeight + 'px'
+ });
+ OGVPlayer.updatePositionOnResize();
+
+ if (useWebGL) {
+ frameSink = new WebGLFrameSink(canvas, videoInfo);
+ } else {
+ frameSink = new FrameSink(canvas, videoInfo);
+ }
+ }
+
+ var depth = 0,
+ useImmediate = options.useImmediate && !!window.setImmediate,
+ useTailCalls = !useImmediate,
+ pendingFrame = 0,
+ pendingAudio = 0;
+
+ function tailCall(func) {
+ if (useImmediate) {
+ setImmediate(func);
+ } else if (!useTailCalls) {
+ setTimeout(func, 0);
+ } else {
+ func();
+ }
+ }
+
+ function doProcessing() {
+ nextProcessingTimer = null;
+
+ if (isProcessing()) {
+ // Called async while waiting for something else to complete...
+ // let it finish, then we'll get called again to continue.
+ return;
+ }
+
+ if (depth > 0 && !useTailCalls) {
+ throw new Error('REENTRANCY FAIL: doProcessing recursing unexpectedly');
+ }
+ depth++;
+
+ if (actionQueue.length) {
+ // data or user i/o to process in our serialized event stream
+ // The function should eventually bring us back here via pingProcessing(),
+ // directly or via further i/o.
+
+ var action = actionQueue.shift();
+ action();
+
+ } else if (state == State.INITIAL) {
+
+ codec.process(function processInitial(more) {
+ if (codec.loadedMetadata) {
+ // we just fell over from headers into content; call onloadedmetadata etc
+ if (!codec.hasVideo && !codec.hasAudio) {
+ throw new Error('No audio or video found, something is wrong');
+ }
+ if (codec.hasAudio) {
+ audioInfo = codec.audioFormat;
+ }
+ if (codec.hasVideo) {
+ videoInfo = codec.videoFormat;
+ setupVideo();
+ }
+ if (!isNaN(codec.duration)) {
+ duration = codec.duration;
+ }
+ if (duration === null) {
+ if (stream.seekable) {
+ state = State.SEEKING_END;
+ lastSeenTimestamp = -1;
+ codec.flush(function() {
+ stream.seek(Math.max(0, stream.bytesTotal - 65536 * 2));
+ readBytesAndWait();
+ });
+ } else {
+ // Stream not seekable and no x-content-duration; assuming infinite stream.
+ state = State.LOADED;
+ pingProcessing();
+ }
+ } else {
+ // We already know the duration.
+ state = State.LOADED;
+ pingProcessing();
+ }
+ } else if (!more) {
+ // Read more data!
+ log('reading more cause we are out of data');
+ readBytesAndWait();
+ } else {
+ // Keep processing headers
+ pingProcessing();
+ }
+ });
+
+ } else if (state == State.SEEKING_END) {
+
+ // Look for the last item.
+ codec.process(function processSeekingEnd(more) {
+ if (codec.hasVideo && codec.frameReady) {
+ lastSeenTimestamp = Math.max(lastSeenTimestamp, codec.frameTimestamp);
+ codec.discardFrame(function() {
+ pingProcessing();
+ });
+ } else if (codec.hasAudio && codec.audioReady) {
+ lastSeenTimestamp = Math.max(lastSeenTimestamp, codec.audioTimestamp);
+ codec.decodeAudio(function() {
+ pingProcessing();
+ });
+ } else if (!more) {
+ // Read more data!
+ if (stream.bytesRead < stream.bytesTotal) {
+ readBytesAndWait();
+ } else {
+ // We are at the end!
+ if (lastSeenTimestamp > 0) {
+ duration = lastSeenTimestamp;
+ }
+
+ // Ok, seek back to the beginning and resync the streams.
+ state = State.LOADED;
+ codec.flush(function() {
+ stream.seek(0);
+ readBytesAndWait();
+ });
+ }
+ } else {
+ // Keep processing headers
+ pingProcessing();
+ }
+ });
+
+ } else if (state == State.LOADED) {
+
+ state = State.READY;
+ if (paused) {
+ // Paused? stop here.
+ log('pausing stopping at loaded');
+ } else {
+ // Not paused? Continue on to play processing.
+ log('not paused so continuing');
+ pingProcessing(0);
+ }
+ fireEvent('loadedmetadata');
+
+ } else if (state == State.READY) {
+
+ if (paused) {
+
+ // Paused? stop here.
+ log('paused while in ready');
+
+ } else {
+
+ function finishStartPlaying() {
+ log('finishStartPlaying');
+
+ state = State.PLAYING;
+ lastFrameTimestamp = getTimestamp();
+
+ startPlayback(0.0);
+ pingProcessing(0);
+ fireEvent('play');
+ }
+
+ if (codec.hasAudio) {
+ initAudioFeeder();
+ audioFeeder.waitUntilReady(finishStartPlaying);
+ } else {
+ finishStartPlaying();
+ }
+ }
+
+ } else if (state == State.SEEKING) {
+
+ codec.process(function processSeeking(more) {
+ if (!more) {
+ readBytesAndWait();
+ } else if (seekState == SeekState.NOT_SEEKING) {
+ throw new Error('seeking in invalid state (not seeking?)');
+ } else if (seekState == SeekState.BISECT_TO_TARGET) {
+ doProcessBisectionSeek();
+ } else if (seekState == SeekState.BISECT_TO_KEYPOINT) {
+ doProcessBisectionSeek();
+ } else if (seekState == SeekState.LINEAR_TO_TARGET) {
+ doProcessLinearSeeking();
+ }
+ });
+
+ } else if (state == State.PLAYING) {
+
+ var demuxStartTime = getTimestamp();
+ codec.process(function doProcessPlay(more) {
+ var delta = getTimestamp() - demuxStartTime;
+ demuxingTime += delta;
+ lastFrameDecodeTime += delta;
+
+ //console.log(more, codec.audioReady, codec.frameReady, codec.audioTimestamp, codec.frameTimestamp);
+
+ if (!more) {
+ if (stream) {
+ // Ran out of buffered input
+ readBytesAndWait();
+ } else {
+ // Ran out of stream!
+ var finalDelay = 0;
+ if (codec.hasAudio) {
+ audioState = audioFeeder.getPlaybackState();
+ audioBufferedDuration = (audioState.samplesQueued / audioFeeder.targetRate);
+ finalDelay = audioBufferedDuration * 1000;
+ }
+ if (pendingAudio || pendingFrame || finalDelay > 0) {
+ pingProcessing(Math.max(0, finalDelay));
+ } else {
+ log("ENDING NOW");
+ stopVideo();
+ ended = true;
+ fireEvent('ended');
+ }
+ }
+ } else if (paused) {
+
+ // ok we're done for now!
+
+ } else {
+
+ if (!((codec.audioReady || !codec.hasAudio) && (codec.frameReady || !codec.frameReady))) {
+
+ log('need more data');
+
+ // Have to process some more pages to find data.
+ pingProcessing();
+
+ } else {
+
+ var audioBufferedDuration = 0,
+ audioDecodingDuration = 0,
+ audioState = null,
+ playbackPosition = 0,
+ nextDelays = [],
+ readyForAudioDecode,
+ readyForFrameDraw,
+ readyForFrameDecode;
+
+ if (codec.hasAudio && audioFeeder) {
+ // Drive on the audio clock!
+ audioState = audioFeeder.getPlaybackState();
+ playbackPosition = getPlaybackTime(audioState);
+
+ audioBufferedDuration = (audioState.samplesQueued / audioFeeder.targetRate);
+ //audioBufferedDuration = audioEndTimestamp - playbackPosition; // @fixme?
+
+ //console.log('audio buffered', audioBufferedDuration, audioDecodingDuration);
+
+ droppedAudio = audioState.dropped;
+ delayedAudio = audioState.delayed;
+ //readyForAudioDecode = audioState.samplesQueued <= (audioFeeder.bufferSize * 2);
+ var bufferDuration = (audioFeeder.bufferSize / audioFeeder.targetRate) * 2;
+ readyForAudioDecode = codec.audioReady && (audioBufferedDuration <= bufferDuration);
+
+ // Check in when all audio runs out
+ if (pendingAudio) {
+ // We'll check in when done decoding
+ } else if (!codec.audioReady) {
+ // NEED MOAR BUFFERS
+ nextDelays.push(-1);
+ } else if (codec.hasVideo && (playbackPosition - frameEndTimestamp) > bufferDuration) {
+ // don't get too far ahead of the video if it's slow!
+ readyForAudioDecode = false;
+ nextDelays.push((playbackPosition - frameEndTimestamp) * 1000);
+ } else {
+ // Check in when the audio buffer runs low again...
+ nextDelays.push((audioBufferedDuration - bufferDuration) * 1000);
+
+ // @todo figure out why the above doesn't do the job reliably
+ // with Flash audio shim on IE!
+ nextDelays.push(bufferDuration * 1000 / 4);
+ }
+ } else {
+ // No audio; drive on the general clock.
+ // @fixme account for dropped frame times...
+ playbackPosition = getPlaybackTime();
+ }
+
+ if (codec.hasVideo) {
+ var fudgeDelta = 0.1,
+ frameDelay = (frameEndTimestamp - playbackPosition) * 1000;
+
+ frameDelay = Math.max(0, frameDelay);
+ frameDelay = Math.min(frameDelay, targetPerFrameTime);
+
+ readyForFrameDraw = !!yCbCrBuffer && !pendingFrame && (frameDelay <= fudgeDelta);
+ readyForFrameDecode = !yCbCrBuffer && !pendingFrame && codec.frameReady;
+
+ if (yCbCrBuffer) {
+ // Check in when the decoded frame is due
+ nextDelays.push(frameDelay);
+ } else if (pendingFrame) {
+ // We'll check in when done decoding
+ } else if (!codec.frameReady) {
+ // need more data!
+ nextDelays.push(-1);
+ } else {
+ // Check in when the decoded frame is due
+ nextDelays.push(frameDelay);
+ }
+ }
+
+ log([playbackPosition, frameEndTimestamp, audioEndTimestamp, readyForFrameDraw, readyForFrameDecode, readyForAudioDecode].join(', '));
+
+ if (readyForFrameDraw) {
+
+ log('ready to draw frame');
+
+ // Ready to draw the decoded frame...
+ if (thumbnail) {
+ self.removeChild(thumbnail);
+ thumbnail = null;
+ }
+
+ drawingTime += time(function() {
+ frameSink.drawFrame(yCbCrBuffer);
+ });
+ yCbCrBuffer = null;
+
+ framesProcessed++;
+ framesPlayed++;
+
+ doFrameComplete();
+
+ pingProcessing(0);
+
+ } else if (readyForFrameDecode) {
+
+ log('ready to decode frame');
+
+ var videoStartTime = getTimestamp();
+ pendingFrame++;
+ if (videoInfo.fps == 0 && (codec.frameTimestamp - frameEndTimestamp) > 0) {
+ // WebM doesn't encode a frame rate
+ targetPerFrameTime = (codec.frameTimestamp - frameEndTimestamp) * 1000;
+ }
+ totalFrameTime += targetPerFrameTime;
+ totalFrameCount++;
+ frameEndTimestamp = codec.frameTimestamp;
+ var pendingFramePing = false;
+ codec.decodeFrame(function processingDecodeFrame(ok) {
+ log('decoded frame');
+ var delta = getTimestamp() - videoStartTime;
+ videoDecodingTime += delta;
+ lastFrameDecodeTime += delta;
+ if (ok) {
+ // Save the buffer until it's time to draw
+ yCbCrBuffer = codec.frameBuffer;
+ } else {
+ // Bad packet or something.
+ log('Bad video packet or something');
+ }
+ pendingFrame--;
+ if (!isProcessing()) {
+ pingProcessing();
+ }
+ });
+ if (!isProcessing()) {
+ pingProcessing();
+ }
+
+ } else if (readyForAudioDecode) {
+
+ log('ready for audio');
+
+ var audioStartTime = getTimestamp();
+ pendingAudio++;
+ audioEndTimestamp = codec.audioTimestamp;
+ codec.decodeAudio(function processingDecodeAudio(ok) {
+ log('decoded audio');
+ var delta = getTimestamp() - audioStartTime;
+ audioDecodingTime += delta;
+ lastFrameDecodeTime += delta;
+
+ if (ok) {
+ var buffer = codec.audioBuffer;
+ if (buffer) {
+ // Keep track of how much time we spend queueing audio as well
+ // This is slow when using the Flash shim on IE 10/11
+ bufferTime += time(function() {
+ audioFeeder.bufferData(buffer);
+ });
+ audioBufferedDuration += (buffer[0].length / audioInfo.rate) * 1000;
+ }
+ }
+ pendingAudio--;
+ if (!isProcessing()) {
+ pingProcessing();
+ }
+ });
+ if (!isProcessing()) {
+ pingProcessing();
+ }
+
+ } else {
+
+ var nextDelay = Math.min.apply(Math, nextDelays);
+ if (nextDelays.length > 0) {
+ log('idle: ' + nextDelay + ' - ' + nextDelays.join(','));
+ if (!codec.hasVideo) {
+ framesProcessed++; // pretend!
+ doFrameComplete();
+ }
+ pingProcessing(Math.max(0, nextDelay));
+ } else if (pendingFrame || pendingAudio) {
+ log('waiting on pending events');
+ } else {
+ log('we may be lost');
+ }
+ }
+ }
+ }
+ });
+
+ } else {
+
+ throw new Error('Unexpected OGVPlayer state ' + state);
+
+ }
+
+ depth--;
+ }
+
+ /**
+ * Are we waiting on an async operation we can't interrupt?
+ */
+ function isProcessing() {
+ return waitingOnInput || (codec && codec.processing);
+ }
+
+ function readBytesAndWait() {
+ waitingOnInput = true;
+ stream.readBytes();
+ }
+
+ function pingProcessing(delay) {
+ if (delay === undefined) {
+ delay = -1;
+ }
+ if (isProcessing()) {
+ throw new Error('REENTRANCY FAIL: asked to pingProcessing() while already waiting');
+ }
+ if (nextProcessingTimer) {
+ //log('canceling old processing timer');
+ clearTimeout(nextProcessingTimer);
+ nextProcessingTimer = null;
+ }
+ var fudge = -1 / 256;
+ if (delay > fudge) {
+ //log('pingProcessing delay: ' + delay);
+ nextProcessingTimer = setTimeout(doProcessing, delay);
+ } else {
+ //log('pingProcessing tail call (' + delay + ')');
+ tailCall(doProcessing);
+ }
+ }
+
+ var videoInfo,
+ audioInfo;
+
+ function startProcessingVideo() {
+ if (started || codec) {
+ return;
+ }
+
+ framesProcessed = 0;
+ demuxingTime = 0;
+ videoDecodingTime = 0;
+ audioDecodingTime = 0;
+ bufferTime = 0;
+ drawingTime = 0;
+ started = true;
+ ended = false;
+
+ codec = new codecClass(codecOptions);
+ codec.init(function() {
+ readBytesAndWait();
+ });
+ }
+
+ function loadCodec(callback) {
+ // @todo use the demuxer and codec interfaces directly
+ codecClassName = 'OGVWrapperCodec';
+
+ // @todo fix detection proper
+ if (enableWebM && self.src.match(/\.webm$/i)) {
+ codecOptions.type = 'video/webm';
+ } else {
+ codecOptions.type = 'video/ogg';
+ }
+
+ OGVLoader.loadClass(codecClassName, function(classObj) {
+ codecClass = classObj;
+ callback();
+ });
+ }
+
+ /**
+ * HTMLMediaElement load method
+ */
+ self.load = function() {
+ if (stream) {
+ // already loaded.
+ return;
+ }
+
+ started = false;
+ stream = new StreamFile({
+ url: self.src,
+ bufferSize: 65536 * 4,
+ onstart: function() {
+ // Fire off the read/decode/draw loop...
+ byteLength = stream.bytesTotal;
+
+ // If we get X-Content-Duration, that's as good as an explicit hint
+ var durationHeader = stream.getResponseHeader('X-Content-Duration');
+ if (typeof durationHeader === 'string') {
+ duration = parseFloat(durationHeader);
+ }
+ loadCodec(startProcessingVideo);
+ },
+ onread: function(data) {
+ log('got input');
+ waitingOnInput = false;
+
+ // Save chunk to pass into the codec's buffer
+ actionQueue.push(function doReceiveInput() {
+ codec.receiveInput(data, function() {
+ pingProcessing();
+ });
+ });
+
+ if (isProcessing()) {
+ // We're waiting on the codec already...
+ } else {
+ pingProcessing();
+ }
+ },
+ ondone: function() {
+ waitingOnInput = false;
+
+ if (state == State.SEEKING) {
+ pingProcessing();
+ } else if (state == State.SEEKING_END) {
+ pingProcessing();
+ } else {
+ log('closing stream (done)');
+ stream = null;
+
+ if (isProcessing()) {
+ // We're waiting on the codec already...
+ } else {
+ // Let the read/decode/draw loop know we're out!
+ pingProcessing();
+ }
+ }
+ },
+ onerror: function(err) {
+ console.log("reading error: " + err);
+ }
+ });
+ };
+
+ /**
+ * HTMLMediaElement canPlayType method
+ */
+ self.canPlayType = function(contentType) {
+ var type = new OGVMediaType(contentType);
+ if (type.minor === 'ogg' &&
+ (type.major === 'audio' || type.major === 'video' || type.major === 'application')) {
+ if (type.codecs) {
+ var supported = ['vorbis', 'opus', 'theora'],
+ knownCodecs = 0,
+ unknownCodecs = 0;
+ type.codecs.forEach(function(codec) {
+ if (supported.indexOf(codec) >= 0) {
+ knownCodecs++;
+ } else {
+ unknownCodecs++;
+ }
+ });
+ if (knownCodecs === 0) {
+ return '';
+ } else if (unknownCodecs > 0) {
+ return '';
+ }
+ // All listed codecs are ones we know. Neat!
+ return 'probably';
+ } else {
+ return 'maybe';
+ }
+ } else {
+ // @todo when webm support is more complete, handle it
+ return '';
+ }
+ };
+
+ /**
+ * HTMLMediaElement play method
+ */
+ self.play = function() {
+ if (!audioOptions.audioContext) {
+ OGVPlayer.initSharedAudioContext();
+ }
+
+ if (paused) {
+ startedPlaybackInDocument = document.body.contains(self);
+
+ paused = false;
+
+ if (started) {
+
+ log('.play() while already started');
+
+ actionQueue.push(function() {
+ startPlayback();
+ fireEvent('play');
+ pingProcessing(0);
+ });
+ if (isProcessing()) {
+ // waiting on the codec already
+ } else {
+ pingProcessing();
+ }
+
+ } else {
+
+ log('.play() before started');
+
+ // Let playback begin when metadata loading is complete
+ if (!stream) {
+ self.load();
+ }
+
+ }
+ }
+ };
+
+ /**
+ * custom getPlaybackStats method
+ */
+ self.getPlaybackStats = function() {
+ return {
+ targetPerFrameTime: targetPerFrameTime,
+ framesProcessed: framesProcessed,
+ playTime: playTime,
+ demuxingTime: demuxingTime,
+ videoDecodingTime: videoDecodingTime,
+ audioDecodingTime: audioDecodingTime,
+ bufferTime: bufferTime,
+ drawingTime: drawingTime,
+ droppedAudio: droppedAudio,
+ delayedAudio: delayedAudio,
+ jitter: totalJitter / framesProcessed
+ };
+ };
+ self.resetPlaybackStats = function() {
+ framesProcessed = 0;
+ playTime = 0;
+ demuxingTime = 0;
+ videoDecodingTime = 0;
+ audioDecodingTime = 0;
+ bufferTime = 0;
+ drawingTime = 0;
+ totalJitter = 0;
+ totalFrameTime = 0;
+ totalFrameCount = 0;
+ };
+
+ /**
+ * HTMLMediaElement pause method
+ */
+ self.pause = function() {
+ if (!stream) {
+ paused = true;
+ self.load();
+ } else if (!paused) {
+ clearTimeout(nextProcessingTimer);
+ nextProcessingTimer = null;
+ stopPlayback();
+ paused = true;
+ fireEvent('pause');
+ }
+ };
+
+ /**
+ * custom 'stop' method
+ */
+ self.stop = function() {
+ stopVideo();
+ };
+
+ /**
+ * HTMLMediaElement src property
+ */
+ self.src = "";
+
+ /**
+ * HTMLMediaElement buffered property
+ */
+ Object.defineProperty(self, "buffered", {
+ get: function getBuffered() {
+ var estimatedBufferTime;
+ if (stream && byteLength && duration) {
+ estimatedBufferTime = (stream.bytesBuffered / byteLength) * duration;
+ } else {
+ estimatedBufferTime = 0;
+ }
+ return new OGVTimeRanges([[0, estimatedBufferTime]]);
+ }
+ });
+
+ /**
+ * HTMLMediaElement seekable property
+ */
+ Object.defineProperty(self, "seekable", {
+ get: function getSeekable() {
+ if (self.duration < Infinity && stream && stream.seekable && codec && codec.seekable) {
+ return new OGVTimeRanges([[0, duration]]);
+ } else {
+ return new OGVTimeRanges([]);
+ }
+ }
+ });
+
+ /**
+ * HTMLMediaElement currentTime property
+ */
+ Object.defineProperty(self, "currentTime", {
+ get: function getCurrentTime() {
+ if (state == State.SEEKING) {
+ return seekTargetTime;
+ } else {
+ if (codec) {
+ if (state == State.PLAYING && !paused) {
+ return getPlaybackTime();
+ } else {
+ return initialPlaybackOffset;
+ }
+ } else {
+ return 0;
+ }
+ }
+ },
+ set: function setCurrentTime(val) {
+ if (stream && byteLength && duration) {
+ seek(val);
+ }
+ }
+ });
+
+ /**
+ * HTMLMediaElement duration property
+ */
+ Object.defineProperty(self, "duration", {
+ get: function getDuration() {
+ if (codec && codec.loadedMetadata) {
+ if (duration !== null) {
+ return duration;
+ } else {
+ return Infinity;
+ }
+ } else {
+ return NaN;
+ }
+ }
+ });
+
+ /**
+ * HTMLMediaElement paused property
+ */
+ Object.defineProperty(self, "paused", {
+ get: function getPaused() {
+ return paused;
+ }
+ });
+
+ /**
+ * HTMLMediaElement ended property
+ */
+ Object.defineProperty(self, "ended", {
+ get: function getEnded() {
+ return ended;
+ }
+ });
+
+ /**
+ * HTMLMediaElement ended property
+ */
+ Object.defineProperty(self, "seeking", {
+ get: function getEnded() {
+ return (state == State.SEEKING);
+ }
+ });
+
+ /**
+ * HTMLMediaElement muted property
+ */
+ Object.defineProperty(self, "muted", {
+ get: function getMuted() {
+ return muted;
+ },
+ set: function setMuted(val) {
+ muted = val;
+ if (audioFeeder) {
+ if (muted) {
+ audioFeeder.mute();
+ } else {
+ audioFeeder.unmute();
+ }
+ }
+ }
+ });
+
+ Object.defineProperty(self, "poster", {
+ get: function getPoster() {
+ return poster;
+ },
+ set: function setPoster(val) {
+ poster = val;
+ if (!started) {
+ if (thumbnail) {
+ self.removeChild(thumbnail);
+ }
+ thumbnail = new Image();
+ thumbnail.src = poster;
+ thumbnail.className = 'ogvjs-poster';
+ thumbnail.style.position = 'absolute';
+ thumbnail.style.top = '0';
+ thumbnail.style.left = '0';
+ thumbnail.style.width = '100%';
+ thumbnail.style.height = '100%';
+ thumbnail.style.objectFit = 'contain';
+ thumbnail.addEventListener('load', function() {
+ OGVPlayer.styleManager.appendRule('.' + instanceId, {
+ width: thumbnail.naturalWidth + 'px',
+ height: thumbnail.naturalHeight + 'px'
+ });
+ self.appendChild(thumbnail);
+ OGVPlayer.updatePositionOnResize();
+ });
+ }
+ }
+ });
+
+ // Video metadata properties...
+ Object.defineProperty(self, "videoWidth", {
+ get: function getVideoWidth() {
+ if (videoInfo) {
+ return videoInfo.displayWidth;
+ } else {
+ return 0;
+ }
+ }
+ });
+ Object.defineProperty(self, "videoHeight", {
+ get: function getVideoHeight() {
+ if (videoInfo) {
+ return videoInfo.displayHeight;
+ } else {
+ return 0;
+ }
+ }
+ });
+ Object.defineProperty(self, "ogvjsVideoFrameRate", {
+ get: function getOgvJsVideoFrameRate() {
+ if (videoInfo) {
+ if (videoInfo.fps == 0) {
+ return totalFrameCount / (totalFrameTime / 1000);
+ } else {
+ return videoInfo.fps;
+ }
+ } else {
+ return 0;
+ }
+ }
+ });
+
+ // Audio metadata properties...
+ Object.defineProperty(self, "ogvjsAudioChannels", {
+ get: function getOgvJsAudioChannels() {
+ if (audioInfo) {
+ return audioInfo.channels;
+ } else {
+ return 0;
+ }
+ }
+ });
+ Object.defineProperty(self, "ogvjsAudioSampleRate", {
+ get: function getOgvJsAudioChannels() {
+ if (audioInfo) {
+ return audioInfo.rate;
+ } else {
+ return 0;
+ }
+ }
+ });
+
+ // Display size...
+ var width = 0, height = 0;
+ Object.defineProperty(self, "width", {
+ get: function getWidth() {
+ return width;
+ },
+ set: function setWidth(val) {
+ width = parseInt(val, 10);
+ self.style.width = width + 'px';
+ }
+ });
+
+ Object.defineProperty(self, "height", {
+ get: function getHeight() {
+ return height;
+ },
+ set: function setHeight(val) {
+ height = parseInt(val, 10);
+ self.style.height = height + 'px';
+ }
+ });
+
+ // Events!
+
+ /**
+ * custom onframecallback, takes frame decode time in ms
+ */
+ self.onframecallback = null;
+
+ /**
+ * Called when all metadata is available.
+ * Note in theory we must know 'duration' at this point.
+ */
+ self.onloadedmetadata = null;
+
+ /**
+ * Called when we start playback
+ */
+ self.onplay = null;
+
+ /**
+ * Called when we get paused
+ */
+ self.onpause = null;
+
+ /**
+ * Called when playback ends
+ */
+ self.onended = null;
+
+ return self;
+};
+
+OGVPlayer.initSharedAudioContext = function() {
+ AudioFeeder.initSharedAudioContext();
+};
+
+OGVPlayer.instanceCount = 0;
+
+function StyleManager() {
+ var self = this;
+ var el = document.createElement('style');
+ el.type = 'text/css';
+ el.textContent = 'ogvjs { display: inline-block; position: relative; }';
+ document.head.appendChild(el);
+
+ var sheet = el.sheet;
+
+ self.appendRule = function(selector, defs) {
+ var bits = [];
+ for (var prop in defs) {
+ if (defs.hasOwnProperty(prop)) {
+ bits.push(prop + ':' + defs[prop]);
+ }
+ }
+ var rule = selector + '{' + bits.join(';') + '}';
+ sheet.insertRule(rule, sheet.length - 1);
+ };
+}
+OGVPlayer.styleManager = new StyleManager();
+
+// IE 10/11 and Edge 12 don't support object-fit.
+// Chrome 43 supports it but it doesn't work on <canvas>!
+// Safari for iOS 8/9 supports it but positions our <canvas> incorrectly >:(
+// Also just for fun, IE 10 doesn't support 'auto' sizing on canvas. o_O
+//OGVPlayer.supportsObjectFit = (typeof document.createElement('div').style.objectFit === 'string');
+OGVPlayer.supportsObjectFit = false;
+if (OGVPlayer.supportsObjectFit) {
+ OGVPlayer.updatePositionOnResize = function() {
+ // no-op
+ };
+} else {
+ OGVPlayer.updatePositionOnResize = function() {
+ function fixup(el, width, height) {
+ var container = el.offsetParent || el.parentNode,
+ containerAspect = container.offsetWidth / container.offsetHeight,
+ intrinsicAspect = width / height;
+ if (intrinsicAspect > containerAspect) {
+ var vsize = container.offsetWidth / intrinsicAspect,
+ vpad = (container.offsetHeight - vsize) / 2;
+ el.style.width = '100%';
+ el.style.height = vsize + 'px';
+ el.style.marginLeft = 0;
+ el.style.marginRight = 0;
+ el.style.marginTop = vpad + 'px';
+ el.style.marginBottom = vpad + 'px';
+ } else {
+ var hsize = container.offsetHeight * intrinsicAspect,
+ hpad = (container.offsetWidth - hsize) / 2;
+ el.style.width = hsize + 'px';
+ el.style.height = '100%';
+ el.style.marginLeft = hpad + 'px';
+ el.style.marginRight = hpad + 'px';
+ el.style.marginTop = 0;
+ el.style.marginBottom = 0;
+ }
+ }
+ function queryOver(selector, callback) {
+ var nodeList = document.querySelectorAll(selector),
+ nodeArray = Array.prototype.slice.call(nodeList);
+ nodeArray.forEach(callback);
+ }
+
+ queryOver('ogvjs > canvas', function(canvas) {
+ fixup(canvas, canvas.width, canvas.height);
+ });
+ queryOver('ogvjs > img', function(poster) {
+ fixup(poster, poster.naturalWidth, poster.naturalHeight);
+ });
+ };
+ var fullResizeVideo = function() {
+ // fullscreens may ping us before the resize happens
+ setTimeout(OGVPlayer.updatePositionOnResize, 0);
+ };
+
+ window.addEventListener('resize', OGVPlayer.updatePositionOnResize);
+ window.addEventListener('orientationchange', OGVPlayer.updatePositionOnResize);
+
+ document.addEventListener('fullscreenchange', fullResizeVideo);
+ document.addEventListener('mozfullscreenchange', fullResizeVideo);
+ document.addEventListener('webkitfullscreenchange', fullResizeVideo);
+ document.addEventListener('MSFullscreenChange', fullResizeVideo);
+}
+
+
+// exports
+this.OGVLoader = OGVLoader;
+this.OGVMediaType = OGVMediaType;
+this.OGVTimeRanges = OGVTimeRanges;
+this.OGVPlayer = OGVPlayer;
+
+})();
+
+this.OGVVersion = "1.0-20150904182230-dd3c8e8";
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/readme.md b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/readme.md
new file mode 100644
index 00000000..6d58ac6f
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/readme.md
@@ -0,0 +1,237 @@
+ogv.js
+======
+
+Media decoder and player for Ogg Vorbis/Opus/Theora and (experimentally) WebM video.
+
+Based around libogg, libvorbis, libtheora, libopus, libvpx, and libnestegg compiled to JavaScript with Emscripten.
+
+## Updates
+
+* 1.0 - 2015-09-04
+ * initial stable release, as used on Wikipedia
+
+## Current status
+
+As of August 2015, ogv.js can be seen in action [on Wikipedia and Wikimedia Commons](https://commons.wikimedia.org/wiki/Commons:Video) in Safari and IE/Edge where native Ogg and WebM playback is not available. (See [technical details on MediaWiki integration](https://www.mediawiki.org/wiki/Extension:TimedMediaHandler/ogv.js).)
+
+See also a standalone demo with performance metrics at https://brionv.com/misc/ogv.js/demo/
+
+* streaming: yes (with Range header)
+* seeking: yes for Ogg (with Range header), no for WebM
+* color: yes
+* audio: yes, with a/v sync (requires Web Audio or Flash)
+* background threading: yes (video, audio decoders in Workers)
+* [GPU accelerated drawing: yes (WebGL)](https://github.com/brion/ogv.js/wiki/GPU-acceleration)
+* GPU accelerated decoding: no
+* SIMD acceleration: no
+* controls: no (currently provided by demo or other UI harness)
+
+Ogg files are fairly well supported, but WebM is still very experimental.
+
+
+## Goals
+
+Long-form goal is to create a drop-in replacement for the HTML5 video and audio tags which can be used for basic playback of Ogg Theora and Vorbis or WebM media on browsers that don't support Ogg or WebM natively.
+
+The API isn't quite complete, but works pretty well.
+
+
+## Compatibility
+
+ogv.js requires a fast JS engine with typed arrays, and either Web Audio or Flash for audio playback.
+
+The primary target browsers are (testing 360p/30fps):
+* Safari 6.1/7/8 on Mac OS X 10.7-10.10
+* Safari on iOS 8 64-bit
+* Edge on Windows 10 desktop/tablet
+* Internet Explorer 10/11 on Windows 7/8/8.1 (desktop/tablet)
+
+And for lower-resolution files (testing 160p/15fps):
+* Safari on iOS 8 32-bit
+* Edge on Windows 10 Mobile
+* Internet Explorer 10/11 on Windows RT
+
+Older versions of Safari have flaky JIT compilers. IE 9 and below lack typed arrays.
+
+(Note that Windows and Mac OS X can support Ogg and WebM by installing codecs or alternate browsers with built-in support, but this is not possible on iOS, Windows RT, or Windows 10 Mobile.)
+
+Testing browsers (these support .ogv natively):
+* Firefox 40
+* Chrome 44
+
+
+## Usage
+
+The `OGVPlayer` class implements a player, and supports a subset of the events, properties and methods from [HTMLMediaElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement) and [HTMLVideoElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement).
+
+```
+ // Create a new player with the constructor
+ var player = new OGVPlayer();
+
+ // Or with options
+ var player = new OGVPlayer({
+ enableWebM: true
+ });
+
+ // Now treat it just like a video or audio element
+ containerElement.appendChild(player);
+ player.src = 'path/to/media.ogv';
+ player.play();
+ player.addEventListener('ended', function() {
+ // ta-da!
+ });
+```
+
+To check for compatibility before creating a player, include `ogv-support.js` and use the `OGVCompat` API:
+
+```
+ if (OGVCompat.supported('OGVPlayer')) {
+ // go load the full player from ogv.js and instantiate stuff
+ }
+```
+
+This will check for typed arrays, audio/Flash, blacklisted iOS versions, and super-slow/broken JIT compilers.
+
+If you need a URL versioning/cache-buster parameter for dynamic loading of `ogv.js`, you can use the `OGVVersion` symbol provided by `ogv-support.js` or the even tinier `ogv-version.js`:
+
+```
+ var script = document.createElement('script');
+ script.src = 'ogv.js?version=' + encodeURIComponent(OGVVersion);
+ document.querySelector('head').appendChild(script);
+```
+
+Usually, ogv.js will auto-detect the path to its resources based on the script element that loads ogv.js or ogv-support.js. If you load ogv.js through a non-customary bundler (such as MediaWiki's ResourceLoader) you may need to override this manually before instantiating players:
+
+```
+ // Path to ogv-demuxer-ogg.js, ogv-worker-audio.js, dynamicaudio.swf etc
+ OGVLoader.base = '/path/to/resources';
+```
+
+
+## Performance
+
+As of 2015, for SD-or-less resolution basic Ogg Theora decoding speed is reliable on desktop and newer high-end mobile devices; current high-end desktops and laptops can even reach HD resolutions. Older and low-end mobile devices may have difficulty on any but audio and the lowest-resolution video files.
+
+WebM is much slower, and remains experimental.
+
+*Low-res targets*
+
+I've gotten acceptable performance for Vorbis audio and 160p/15fps Theora files on 32-bit iOS devices: iPhone 4s, iPod Touch 5th-gen and iPad 3. These have difficulty at 240p and above, and just won't keep up with higher resolutions.
+
+Meanwhile, newer 64-bit iPhones and iPads are comparable to low-end laptops, and videos at 360p and often 480p play acceptably. Since 32-bit and 64-bit iOS devices have the same user-agent, a benchmark must be used to approximately test minimum CPU speed.
+
+(On iOS 8, Safari performs significantly better than Chrome or other alternative browsers that are unable to enable the JIT due to iOS limitations on third-party developers. Again, a benchmark must be used to detect slow performance, as the browser remains otherwise compatible.)
+
+
+Windows on 32-bit ARM platforms is similar... IE 11 on Windows RT 8.1 on a Surface tablet (NVidia Tegra 3), and Edge on Windows 10 Mobile build 10166 on a Lumia 635, perform acceptably with audio and with 160p/15fps videos but have trouble starting around 240p.
+
+
+In both cases, a native application looms as a possibly better alternative. See [OGVKit ](https://github.com/brion/OGVKit) and [OgvRt](https://github.com/brion/OgvRT) projects for experiments in those directions.
+
+
+Note that at these lower resolutions, Vorbis audio and Theora video decoding are about equally expensive operations -- dual-core phones and tablets should be able to eek out a little parallelism here thanks to audio and video being in separate Worker threads.
+
+
+*WebGL drawing acceleration*
+
+Accelerated YCbCr->RGB conversion and drawing is done using WebGL on supporting browsers (Firefox, Chrome, IE 11, Edge, and Safari for iOS 8 & OS X 10.9), and is enabled by default if available.
+
+WebGL noticeably improves playback performance at HD and SD resolutions.
+
+Early versions of IE 11 do not support luminance or alpha textures, and in IE 11 update 1 and Edge they are still unexpectedly slow on Windows (in all browsers so far). As a workaround, on Windows the data is packed into RGBA textures for faster texture upload and unpacked in the shader. See [GPU acceleration page](https://github.com/brion/ogv.js/wiki/GPU-acceleration) for more info.
+
+
+It may be possible to do further acceleration of actual decoding operations using WebGL shaders, but this could be ... tricky. WebGL is also only available on the main thread, and there are no compute shaders yet so would have to use fragment shaders.
+
+
+## Difficulties
+
+*Threading*
+
+Currently the video and audio codecs run in worker threads by default, while the demuxer
+and player logic run on the UI thread. This seems to work pretty well.
+
+There is some overhead in extracting data out of each emscripten module's heap and in the thread-to-thread communications, but the parallelism and smoother main thread makes up for it.
+
+
+*Streaming download*
+
+In IE and Edge, the (MS-prefixed) Stream/StreamReader interface is used to read data on demand into ArrayBuffer objects.
+
+In Firefox, the 'moz-chunked-array' responseType on XHR is used to read data as ArrayBuffer chunks during download. Safari and Chrome use a 'binary string' read which requires manually converting input to ArrayBuffer chunks.
+
+The Firefox and Safari/Chrome cases have been hacked up to do streaming buffering by chunking the requests at up to a megabyte each, using the HTTP Range header. For cross-site playback, this requires CORS setup to whitelist the Range header!
+
+[Safari has a bug with Range headers](https://bugs.webkit.org/show_bug.cgi?id=82672) which is worked around as necessary with a 'cache-busting' URL string parameter. Hopefully this will be fixed in future versions of Mac OS X and iOS.
+
+
+*Seeking*
+
+Seeking is implemented via the HTTP Range: header.
+
+For Ogg files with keyframe indices in a skeleton index, seeking is very fast. Otherwise, a bisection search is used to locate the target frame or audio position, which is very slow over the internet as it creates a lot of short-lived HTTP requests.
+
+For WebM files, seeking is not yet supported; this will require refactoring the demuxer modules to present a synchronous i/o abstraction to the demuxer library.
+
+As with chunked streaming, cross-site playback requires CORS support for the Range header.
+
+
+*Audio output*
+
+Firefox, Safari, Chrome, and Edge support the W3C Web Audio API.
+
+IE doesn't support Web Audio, but does bundle the Flash player in Windows 8/8.1/RT. A small Flash shim is included here and used as a fallback -- thanks to Maik Merten for hacking some pieces together and getting this working!
+
+A/V synchronization is performed on files with both audio and video, and seems to
+actually work. Yay!
+
+Note that autoplay doesn't work on iOS Safari due to limitations with starting audio playback from event handlers.
+
+
+*WebM*
+
+WebM support was added in June 2015, and is currently very experimental. Not everything works yet, and performance is pretty bad. See [issue tracker for WebM milestone](https://github.com/brion/ogv.js/milestones/WebM%20playback) on the GitHub page.
+
+The i/o model of the nestegg WebM container demuxing library is a bit different from what ogv.js was designed around so seeking is not yet supported and it may sometimes cut off partway through a file. Needs more work.
+
+To enable, set `enableWebM: true` in your `options` array.
+
+
+## Upstream library notes
+
+We've experimented with tremor (libivorbis), an integer-only variant of libvorbis. This actually does *not* decode faster, but does save about 200kb off our generated JavaScript, presumably thanks to not including an encoder in the library. However on slow devices like iPod Touch 5th-generation, it makes a significant negative impact on the decode time so we've gone back to libvorbis.
+
+The Ogg Skeleton library (libskeleton) is a bit ... unfinished and is slightly modified here.
+
+
+## Building JS components
+
+Building ogv.js is known to work on Mac OS X and Linux (tested Ubuntu 15.04).
+
+1. You will need autoconf, automake, libtool, and pkg-config. These can be installed through Homebrew on Mac OS X, or through distribution-specific methods on Linux.
+2. Install [Emscripten](http://kripken.github.io/emscripten-site/docs/getting_started/Tutorial.html); currently using the 1.34.1 SDK release for distribution builds.
+3. `git submodule update --init`
+4. Run `make js` to configure and build the libraries and the C wrapper
+
+
+## Building Flash components
+
+Rebuilding dynamicaudio.swf shim for IE 10/11:
+
+1. Install [Apache Flex SDK](http://flex.apache.org/), and put it into PATH
+2. `make swf` to rebuild src/dynamicaudio.swf
+3. `make` to rebuild the demo and update its .swf
+
+
+## Building the demo
+
+If you did all the setup above, just run `make demo` or `make`. Look in build/demo/ and enjoy!
+
+
+## License
+
+libogg, libvorbis, libtheora, libopus, nestegg, and libvpx are available under their respective licenses, and the JavaScript and C wrapper code in this repo is licensed under MIT.
+
+Based on build scripts from https://github.com/devongovett/ogg.js
+
+dynamicaudio.as and other Flash-related bits are based on code under BSD license, (c) 2010 Ben Firshman (see src/AudioFeeder.js flash fallback section).
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/af.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/af.json
new file mode 100644
index 00000000..14191ff4
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/af.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Naudefj"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Naam: $1",
+ "mwe-embedplayer-loading_plugin": "laai uitbreiding ...",
+ "mwe-embedplayer-add_to_end_of_sequence": "Voeg by aan die einde van die reeks",
+ "mwe-embedplayer-volume_control": "Volumebeheer",
+ "mwe-embedplayer-download": "Aflaai",
+ "mwe-embedplayer-share": "Deel",
+ "mwe-embedplayer-credits": "Krediete",
+ "mwe-embedplayer-menu_btn": "Keuses",
+ "mwe-embedplayer-close_btn": "Sluit",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime-uitbreiding",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-selected": "(gekies)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-embed_site_or_blog": "Voeg by jou webblad of webjoernaal"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/aln.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/aln.json
new file mode 100644
index 00000000..519ac9d6
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/aln.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mdupont"
+ ]
+ },
+ "mwe-embedplayer-share_this_video": "Share this video",
+ "mwe-embedplayer-video_credits": "kreditƫ Video",
+ "mwe-embedplayer-kaltura-platform-title": "video Kaltura me burim tƫ hapur platformƫn",
+ "mwe-embedplayer-menu_btn": "Menu",
+ "mwe-embedplayer-close_btn": "Afƫr",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC player",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 lojtar ZQM",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 lojtar H.264",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Generic Ogg plugin",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime plugin",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "lojtar Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(Zgjedhur)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "Flash Vorbis OMTK",
+ "mwe-embedplayer-for_best_experience": "Pƫr njƫ pƫrvojƫ mƫ tƫ mirƫ video rishikim tƫ kƫshillojmƫ <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">Firefox fundit</a> .",
+ "mwe-embedplayer-do_not_warn_again": "Shkarkojƫ tani pƫr tani.",
+ "mwe-embedplayer-playerSelect": "Lojtaret",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Lexoni kete</a> para se embedding.",
+ "mwe-embedplayer-embed_site_or_blog": "Embed nƫ njƫ faqe",
+ "mwe-embedplayer-related_videos": "Related videos",
+ "mwe-embedplayer-seeking": "kƫrkojnƫ",
+ "mwe-embedplayer-video-h264": "H.264 video",
+ "mwe-embedplayer-video-flv": "Flash video",
+ "mwe-embedplayer-video-ogg": "video Ogg",
+ "mwe-embedplayer-video-audio": "Ogg audio",
+ "mwe-embedplayer-missing-source": "Nuk ka video burim u gjet."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ar.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ar.json
new file mode 100644
index 00000000..8f53df42
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ar.json
@@ -0,0 +1,59 @@
+{
+ "@metadata": {
+ "authors": [
+ "Alzahrani",
+ "Meno25",
+ "OsamaK",
+ "Ų±ŁˆŲ®Łˆ"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Ų¹Ł†ŁˆŲ§Ł†: $1",
+ "mwe-embedplayer-credit-date": "ŲŖŲ§Ų±ŁŠŲ®: $1",
+ "mwe-embedplayer-credit-author": "Ų§Ł„Ł…Ų¤Ł„Ł: $1",
+ "mwe-embedplayer-loading_plugin": "ŲŖŲ­Ł…ŁŠŁ„ Ł…Ł„Ų­Ł‚...",
+ "mwe-embedplayer-select_playback": "ŲŖŲ¹ŁŠŁŠŁ† ŲŖŁŲ¶ŁŠŁ„Ų§ŲŖ Ų§Ł„ŲŖŲ“ŲŗŁŠŁ„",
+ "mwe-embedplayer-add_to_end_of_sequence": "Ų£Ų¶Ł Ų„Ł„Ł‰ Ł†Ł‡Ų§ŁŠŲ© Ų§Ł„Ų³Ł„Ų³Ł„Ų©",
+ "mwe-embedplayer-missing_video_stream": "Ł…Ł„Ł Ų§Ł„ŁŁŠŲÆŁŠŁˆ Ł„Ł‡Ų°Ų§ Ų§Ł„Ł†Ų³Ł‚ Ł…ŁŁ‚ŁˆŲÆ",
+ "mwe-embedplayer-play_clip": "Ų“ŲŗŁ‘Ł„ Ų§Ł„Ł…Ł‚Ų·Ų¹",
+ "mwe-embedplayer-pause_clip": "Ų£Ł„ŲØŲ« Ų§Ł„Ł…Ł‚Ų·Ų¹",
+ "mwe-embedplayer-volume_control": "Ų§Ł„ŲŖŲ­ŁƒŁ… ŲØŲ­Ų¬Ł… Ų§Ł„ŲµŁˆŲŖ",
+ "mwe-embedplayer-player_options": "Ų®ŁŠŲ§Ų±Ų§ŲŖ Ų§Ł„Ł…ŁŲ“ŲŗŁ‘Ł„",
+ "mwe-embedplayer-player_fullscreen": "Ų§Ł…Ł„Ų£ Ų§Ł„Ų“Ų§Ų“Ų©",
+ "mwe-embedplayer-next_clip_msg": "Ų“ŲŗŁ‘Ł„ Ų§Ł„Ł…Ł‚Ų·Ų¹ Ų§Ł„ŲŖŲ§Ł„ŁŠ",
+ "mwe-embedplayer-prev_clip_msg": "Ų“ŲŗŁ„ Ų§Ł„Ł…Ł‚Ų·Ų¹ Ų§Ł„Ų³Ų§ŲØŁ‚",
+ "mwe-embedplayer-current_clip_msg": "Ł…ŲŖŲ§ŲØŲ¹Ų© ŲŖŲ“ŲŗŁŠŁ„ Ł‡Ų°Ų§ Ų§Ł„Ł…Ł‚Ų·Ų¹",
+ "mwe-embedplayer-seek_to": "Ų§ŲØŲ­Ų« ŁŁŠ $1",
+ "mwe-embedplayer-paused": "Ų§ŁŠŁ‚Ų§Ł Ł…Ų¤Ł‚ŲŖ",
+ "mwe-embedplayer-download_segment": "Ł†Ų²Ł‘Ł„ Ų§Ł„Ł…Ų­ŲÆŲÆ:",
+ "mwe-embedplayer-download_full": "ŲŖŲ­Ł…ŁŠŁ„ ŁƒŲ§Ł…Ł„ Ł…Ł„Ł Ų§Ł„ŁŁŠŲÆŁŠŁˆ:",
+ "mwe-embedplayer-download_right_click": "Ł„ŲŖŲ­Ł…ŁŠŁ„, Ų§Ų¶ŲŗŲ· ŲØŲ²Ų± Ų§Ł„ŁŲ§Ų±Ų© Ų§Ł„Ų§ŁŠŁ…Ł† ŁˆŲ§Ų®ŲŖŲ± <i>Ų­ŁŲø Ų§Ł„Ų±Ų§ŲØŲ· ŁƒŁ€...</i>",
+ "mwe-embedplayer-download_clip": "Ł†Ų²Ł‘Ł„ Ų§Ł„ŁŁŠŲÆŁŠŁˆ",
+ "mwe-embedplayer-download_text": "ŲŖŲ­Ł…ŁŠŁ„ Ų§Ł„Ł†Ųµ",
+ "mwe-embedplayer-download": "Ł†Ų²Ł‘Ł„",
+ "mwe-embedplayer-share": "Ł…Ų“Ų§Ų±ŁƒŲ©",
+ "mwe-embedplayer-about-library": "Ų¹Ł† Ł…Ų“ŲŗŁ„ ŁƒŲ§Ł„Ų“ŁˆŲ±Ų§",
+ "mwe-embedplayer-clip_linkback": "ŲµŁŲ­Ų© Ł…ŲµŲÆŲ± Ų§Ł„Ł…Ł‚Ų·Ų¹",
+ "mwe-embedplayer-choose_player": "Ų§Ų®ŲŖŲ± Ł…Ų“ŲŗŁ„ Ų§Ł„ŁŁŠŲÆŁŠŁˆ",
+ "mwe-embedplayer-no-player": "Ł„Ų§ ŁŠŁˆŲ¬ŲÆ Ł…Ų“ŲŗŁ„ Ł„Ł€ $1",
+ "mwe-embedplayer-share_this_video": "Ų“Ų§Ų±Łƒ Ł‡Ų°Ų§ Ų§Ł„ŁŁŠŲÆŁŠŁˆ",
+ "mwe-embedplayer-kaltura-platform-title": "ŁƒŲ§Ł„Ų“ŁˆŲ±Ų§ Ł…Ł†ŲµŲ© ŁŁŠŲÆŁŠŁˆ Ł…ŁŲŖŁˆŲ­Ų© Ų§Ł„Ł…ŲµŲÆŲ±",
+ "mwe-embedplayer-menu_btn": "Ł‚Ų§Ų¦Ł…Ų©",
+ "mwe-embedplayer-close_btn": "Ų£ŲŗŁ„Ł‚",
+ "mwe-embedplayer-ogg-player-vlc-player": "Ų§Ł„Ł…Ų“ŲŗŁ„ VLC",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Ų§Ų¶Ų§ŁŲ© Ł„ŲØŲ±Ł†Ų§Ł…Ų¬ ŁƒŁˆŁŠŁƒ ŲŖŲ§ŁŠŁ…",
+ "mwe-embedplayer-ogg-player-cortado": "Ų¬Ų§ŁŲ§ ŁƒŁˆŲ±ŲŖŲ§ŲÆŁˆ",
+ "mwe-embedplayer-ogg-player-kplayer": "Ł…Ų“ŲŗŁ„ ŁƒŲ§Ł„Ų“ŁˆŲ±Ų§",
+ "mwe-embedplayer-ogg-player-selected": "(Ł…Ų®ŲŖŲ§Ų±)",
+ "mwe-embedplayer-for_best_experience": "Ł„Ł„Ų­ŲµŁˆŁ„ Ų¹Ł„Ł‰ Ų£ŁŲ¶Ł„ ŲŖŲ¬Ų±ŲØŲ© Ł„Ų¹Ų±Ų¶ Ų§Ł„ŁŁŠŲÆŁŠŁˆ Ł†Ų­Ł† Ł†Ł†ŲµŲ­ ŲØŁ€ <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">Ł…Ų³ŲŖŲ¹Ų±Ų¶ HTML5 Ł„Ł„ŁŁŠŲÆŁŠŁˆ</a>",
+ "mwe-embedplayer-fullscreen-tip": "Ų§Ų¶ŲŗŲ· <b>F11</b> Ł„ŲŖŲØŲÆŁŠŁ„ <i>Ł…ŲŖŲµŁŲ­ Ų§Ł„ŁˆŲØ</i> Ł„ŁˆŲ¶Ų¹ Ų§Ł„Ų“Ų§Ų“Ų© Ų§Ł„ŁƒŲ§Ł…Ł„Ų©",
+ "mwe-embedplayer-fullscreen-tip-osx": "Ų§Ų¶ŲŗŲ· <b>shift āŒ˜ F</b> Ł„ŁˆŲ¶Ų¹ Ų“Ų§Ų“Ų© ŁƒŲ§Ł…Ł„Ų©",
+ "mwe-embedplayer-do_not_warn_again": "Ł„Ų§ ŲŖŲøŁ‡Ų± Ł‡Ų°Ł‡ Ų§Ł„Ų±Ų³Ų§Ł„Ų© ŁŁŠ Ų§Ł„Ł…Ų±Ų© Ų§Ł„Ł‚Ų§ŲÆŁ…Ų©",
+ "mwe-embedplayer-playerSelect": "Ł„Ų§Ų¹ŲØŁˆŁ†",
+ "mwe-embedplayer-related_videos": "ŁŁŠŲÆŁŠŁˆŁ‡Ų§ŲŖ Ų°Ų§ŲŖ ŲµŁ„Ų©",
+ "mwe-embedplayer-video-h264": "ŁŁŠŲÆŁŠŁˆ ŲØŲŖŲ±Ł…Ų² H.264",
+ "mwe-embedplayer-video-webm": "ŁŁŠŲÆŁŠŁˆ ŲØŲŖŲ±Ł…Ų² WebM",
+ "mwe-embedplayer-video-flv": "ŁŁ„Ų§Ų“ ŁŁŠŲÆŁŠŁˆ",
+ "mwe-embedplayer-video-ogg": "ŁŁŠŲÆŁŠŁˆ ŲØŲŖŲ±Ł…Ų² Ogg",
+ "mwe-embedplayer-video-audio": "ŲµŁˆŲŖ ŲØŲŖŲ±Ł…Ų² Ogg",
+ "mwe-embedplayer-missing-source": "Ł„Ł… ŁŠŲ¹Ų«Ų± Ų¹Ł„Ł‰ Ł…ŲµŲÆŲ± Ų§Ł„ŁŁŠŲÆŁŠŁˆ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/arc.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/arc.json
new file mode 100644
index 00000000..ef336c30
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/arc.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Basharh"
+ ]
+ },
+ "mwe-embedplayer-credit-author": "ܣܝܘܔܐ: $1"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ast.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ast.json
new file mode 100644
index 00000000..1745c4fb
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ast.json
@@ -0,0 +1,89 @@
+{
+ "@metadata": {
+ "authors": [
+ "Xuacu"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "TĆ­tulu: $1",
+ "mwe-embedplayer-credit-date": "Data: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-nocredits": "Nun hai crƩditos disponibles",
+ "mwe-embedplayer-loading_plugin": "Cargando complementu...",
+ "mwe-embedplayer-select_playback": "Configurar preferencies de reproducciĆ³n",
+ "mwe-embedplayer-link_back": "Enllazar de vuelta",
+ "mwe-embedplayer-error_swap_vid": "Error: mwEmbed nun pudo intercambiar la etiqueta de videu pa la interfaz de mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Amestar al final de la secuencia",
+ "mwe-embedplayer-missing_video_stream": "Falta'l ficheru de videu d'esta canal",
+ "mwe-embedplayer-play_clip": "Reproducir clip",
+ "mwe-embedplayer-pause_clip": "Posar clip",
+ "mwe-embedplayer-volume_control": "Control de volume",
+ "mwe-embedplayer-player_options": "Opciones del reproductor",
+ "mwe-embedplayer-timed_text": "Testu sincronizƔu",
+ "mwe-embedplayer-player_fullscreen": "Pantalla completa",
+ "mwe-embedplayer-next_clip_msg": "Reproducir el siguiente clip",
+ "mwe-embedplayer-prev_clip_msg": "Reproducir el clip anterior",
+ "mwe-embedplayer-current_clip_msg": "Siguir reproduciendo esti clip",
+ "mwe-embedplayer-seek_to": "Buscar $1",
+ "mwe-embedplayer-paused": "en pausa",
+ "mwe-embedplayer-download_segment": "Descargar seleiciĆ³n:",
+ "mwe-embedplayer-download_full": "Descargar el ficheru de videu completu:",
+ "mwe-embedplayer-download_right_click": "Pa descargar, faiga click col botĆ³n drechu y seleicione <i>Guardar enllaz como...</i>",
+ "mwe-embedplayer-download_clip": "Descargar el videu",
+ "mwe-embedplayer-download_text": "Descargar testu",
+ "mwe-embedplayer-download": "Descargar",
+ "mwe-embedplayer-share": "Compartir",
+ "mwe-embedplayer-credits": "CrƩditos",
+ "mwe-embedplayer-about-library": "Tocante al reproductor Kaltura",
+ "mwe-embedplayer-about-library-desc": "La biblioteca HTML5 de Kaltura permite-y aprovechar gĆ¼ei les etiquetes de HTML5 &lt;video&gt; y &lt;audio&gt; con una interfaz de reproductor constante ente los navegadores mĆ”s importantes.\n\t\n[$1 MĆ”s informaciĆ³n sobro la biblioteca del reproductor Kaltura].",
+ "mwe-embedplayer-clip_linkback": "PƔxina d'orixe del clip",
+ "mwe-embedplayer-choose_player": "Escoyer el reproductor de videu",
+ "mwe-embedplayer-no-player": "Nun hai nengĆŗn reproductor disponible pa $1",
+ "mwe-embedplayer-share_this_video": "Compartir esti videu",
+ "mwe-embedplayer-video_credits": "CrƩditos del videu",
+ "mwe-embedplayer-no-video_credits": "Nun hai crƩditos disponibles",
+ "mwe-embedplayer-kaltura-platform-title": "Plataforma de videu de cĆ³digu abiertu Kaltura",
+ "mwe-embedplayer-menu_btn": "MenĆŗ",
+ "mwe-embedplayer-close_btn": "Zarrar",
+ "mwe-embedplayer-ogg-player-vlc-player": "Reproductor VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Reproductor Ogg HTML5",
+ "mwe-embedplayer-ogg-player-mp3Native": "Reproductor MP3 HTML5",
+ "mwe-embedplayer-ogg-player-aacNative": "Reproductor AAC HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "Reproductor H.264 HTML5",
+ "mwe-embedplayer-ogg-player-webmNative": "Reproductor WebM HTML5",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Complementu Ogg xenƩricu",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "app VLC pa iOS",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Complementu QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "ActiveX QuickTime",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Reproductor Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(seleicionƔu)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Pa una meyor esperiencia de reproducciĆ³n de videu recomendamos un <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">navegador de videu HTML5</a>.",
+ "mwe-embedplayer-download-warn": "Nun se detectĆ³ nengĆŗn reproductor compatible integrĆ”u col navegador: pa una reproducciĆ³n integrada nel navegador, descargue la [$1 Ćŗltima versiĆ³n de Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "Calque <b>F11</b> pa conmutar la pantalla completa del <i>navegador web</i>",
+ "mwe-embedplayer-fullscreen-tip-osx": "Calque <b>mayĆŗs āŒ˜ F</b> pa conmutar la pantalla completa",
+ "mwe-embedplayer-do_not_warn_again": "Nun amosar esti mensaxe nel futuru",
+ "mwe-embedplayer-playerSelect": "Reproductores",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Llea esto</a> enantes d'inxertar.",
+ "mwe-embedplayer-embed_site_or_blog": "Inxertar nuna pƔxina",
+ "mwe-embedplayer-embed_wiki": "Inxertar nuna wiki",
+ "mwe-embedplayer-related_videos": "Videos rellacionaos",
+ "mwe-embedplayer-seeking": "buscando",
+ "mwe-embedplayer-buffering": "cargando nel bĆŗfer",
+ "mwe-embedplayer-video-h264": "Videu H.264",
+ "mwe-embedplayer-video-webm": "Videu WebM",
+ "mwe-embedplayer-video-flv": "Videu Flash",
+ "mwe-embedplayer-video-ogg": "Videu Ogg",
+ "mwe-embedplayer-video-audio": "SonĆ­u Ogg",
+ "mwe-embedplayer-audio-mpeg": "SonĆ­u MPEG",
+ "mwe-embedplayer-video-3gp": "Videu 3GP",
+ "mwe-embedplayer-video-mpeg": "Videu MPEG",
+ "mwe-embedplayer-video-msvideo": "Videu AVI",
+ "mwe-embedplayer-missing-source": "Nun s'alcontrĆ³'l videu orixinal.",
+ "mwe-embedplayer-vlcapp-intro": "Pa ver videos d'esti sitiu nun iPhone o iPad, necesites la $1 de baldre.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "app VLC",
+ "mwe-embedplayer-vlcapp-downloadapp": "Descarga la app VLC dende la App Store",
+ "mwe-embedplayer-vlcapp-openvideo": "Abri esti videu na app VLC",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Descarga esti videu",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "Pa reproducir videos d'esti sitiu, necesites la app de baldre VLC. ĀæInstalala agora?"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/az.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/az.json
new file mode 100644
index 00000000..7ad7f7de
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/az.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cekli829"
+ ]
+ },
+ "mwe-embedplayer-credit-date": "Tarix: $1",
+ "mwe-embedplayer-credit-author": "MĆ¼É™llif: $1",
+ "mwe-embedplayer-download": "YĆ¼klə"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ba.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ba.json
new file mode 100644
index 00000000..9a304406
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ba.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "Haqmar"
+ ]
+ },
+ "mwe-embedplayer-video-h264": "H.264 Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-webm": "WebM Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-flv": "Flash Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-ogg": "Ogg Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-audio": "Ogg Š°ŃƒŠ“ŠøŠ¾",
+ "mwe-embedplayer-audio-mpeg": "MPEG Š°ŃƒŠ“ŠøŠ¾",
+ "mwe-embedplayer-video-3gp": "3GP Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-mpeg": "MPEG Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-msvideo": "AVI Š²ŠøŠ“ŠµŠ¾"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/be-tarask.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/be-tarask.json
new file mode 100644
index 00000000..6b26cd9f
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/be-tarask.json
@@ -0,0 +1,86 @@
+{
+ "@metadata": {
+ "authors": [
+ "EugeneZelenko",
+ "Jim-by",
+ "Wizardist",
+ "Zedlik"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "ŠŠ°Š·Š²Š°: $1",
+ "mwe-embedplayer-credit-date": "Š”Š°Ń‚Š°: $1",
+ "mwe-embedplayer-credit-author": "ŠŃžŃ‚Š°Ń€: $1",
+ "mwe-embedplayer-nocredits": "Š—ŃŒŠ²ŠµŃŃ‚Š°Šŗ ŠæрŠ° Š°ŃžŃ‚Š°Ń€Š°Ńž Š½ŃŠ¼Š°",
+ "mwe-embedplayer-loading_plugin": "Š—Š°Š³Ń€ŃƒŠ¶Š°ŠµŃ†Ń†Š° Š“Š°ŠæŠ°ŃžŠ½ŠµŠ½ŃŒŠ½Šµ ā€¦",
+ "mwe-embedplayer-select_playback": "Š£ŃŃ‚Š°Š½Š°Š²Ń–Ń†ŃŒ Š½Š°ŃŃ‚Ń€Š¾Š¹Šŗі ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š½ŃŒŠ½Ń",
+ "mwe-embedplayer-link_back": "ŠŠ“Š²Š°Ń€Š¾Ń‚Š½Š°Ń сŠæŠ°ŃŃ‹Š»ŠŗŠ°",
+ "mwe-embedplayer-error_swap_vid": "ŠŸŠ°Š¼Ń‹Š»ŠŗŠ°: mwEmbed Š½Ń Š·Š¼Š¾Š³ ŠæŠ°Š¼ŃŠ½ŃŃ†ŃŒ Š²Ń–Š“эŠ° тэŠ³ Š“Š»Ń іŠ½Ń‚ŃŃ€Ń„ŃŠ¹ŃŃƒ mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Š”Š°Š“Š°Ń†ŃŒ у ŠŗŠ°Š½ŠµŃ† ŠæŠ°ŃŃŒŠ»ŃŠ“Š¾ŃžŠ½Š°ŃŃŒŃ†Ń–",
+ "mwe-embedplayer-missing_video_stream": "Š’Ń–Š“эŠ°-фŠ°Š¹Š» Š“Š»Ń Š³ŃŃ‚Š°Š³Š° струŠ¼ŠµŠ½Ń Š°Š“сутŠ½Ń–чŠ°Šµ",
+ "mwe-embedplayer-play_clip": "ŠŸŃ€Š°Š¹Š³Ń€Š°Ń†ŃŒ ŠŗŠ»Ń–Šæ",
+ "mwe-embedplayer-pause_clip": "ŠŸŃ€Ń‹ŠæыŠ½Ń–Ń†ŃŒ ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š½ŃŒŠ½Šµ",
+ "mwe-embedplayer-volume_control": "Š ŃŠ³ŃƒŠ»ŃŠ²Š°Š½ŃŒŠ½Šµ Š³ŃƒŃ‡Š½Š°ŃŃŒŃ†Ń–",
+ "mwe-embedplayer-player_options": "ŠŠ°Š»Š°Š“ы ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–ŠŗŠ°",
+ "mwe-embedplayer-timed_text": "Š”ыŠ½Ń…Ń€Š°Š½Ń–Š·Š°Š²Š°Š½Ń‹ тэŠŗст",
+ "mwe-embedplayer-player_fullscreen": "ŠŠ° ўŠ²ŠµŃŃŒ эŠŗрŠ°Š½",
+ "mwe-embedplayer-next_clip_msg": "ŠŸŃ€Š°Š¹Š³Ń€Š°Ń†ŃŒ Š½Š°ŃŃ‚ŃƒŠæŠ½Ń‹ ŠŗŠ»Ń–Šæ",
+ "mwe-embedplayer-prev_clip_msg": "ŠŸŃ€Š°Š¹Š³Ń€Š°Ń†ŃŒ ŠæŠ°ŠæярэŠ“Š½Ń– ŠŗŠ»Ń–Šæ",
+ "mwe-embedplayer-current_clip_msg": "ŠŸŃ€Š°Ń†ŃŠ³Š²Š°Ń†ŃŒ ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š½ŃŒŠ½Šµ Š³ŃŃ‚Š°Š¹ чŠ°ŃŃ‚Šŗі фŠ°Š¹Š»Š°",
+ "mwe-embedplayer-seek_to": "ŠŸŠµŃ€Š°Š¹ŃŃŒŃ†Ń– Š“Š° $1",
+ "mwe-embedplayer-paused": "ŠæŠ°ŃžŠ·Š°",
+ "mwe-embedplayer-download_segment": "Š’Ń‹Š±Š°Ń€ Š·Š°Š³Ń€ŃƒŠ·Šŗі:",
+ "mwe-embedplayer-download_full": "Š—Š°Š³Ń€ŃƒŠ·Ń–Ń†ŃŒ ŠæŠ¾ŃžŠ½Ń‹ Š²Ń–Š“эŠ°-фŠ°Š¹Š»:",
+ "mwe-embedplayer-download_right_click": "Š”Š»Ń Š·Š°Š³Ń€ŃƒŠ·Šŗі Š½Š°Ń†Ń–ŃŃŒŠ½Ń–цŠµ ŠæрŠ°Š²ŃƒŃŽ ŠŗŠ½Š¾ŠæŠŗу Š¼Ń‹ŃˆŠŗі і Š²Ń‹Š±ŠµŃ€Ń‹Ń†Šµ <i>Š—Š°Ń…Š°Š²Š°Ń†ŃŒ сŠæŠ°ŃŃ‹Š»Šŗу яŠŗā€¦</i>",
+ "mwe-embedplayer-download_clip": "Š—Š°Š³Ń€ŃƒŠ·Ń–Ń†ŃŒ Š²Ń–Š“эŠ°",
+ "mwe-embedplayer-download_text": "Š—Š°Š³Ń€ŃƒŠ·Ń–Ń†ŃŒ тэŠŗст",
+ "mwe-embedplayer-download": "Š—Š°Š³Ń€ŃƒŠ·Ń–Ń†ŃŒ",
+ "mwe-embedplayer-share": "Š—Ń€Š°Š±Ń–Ń†ŃŒ Š°Š³ŃƒŠ»ŃŒŠ½Ń‹Š¼",
+ "mwe-embedplayer-credits": "Š”тŠ²Š°Ń€Š°Š»ŃŒŠ½Ń–Šŗі",
+ "mwe-embedplayer-about-library": "ŠŸŃ€Š° ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–Šŗ Kaltura",
+ "mwe-embedplayer-about-library-desc": "HTML5 Š¼ŃŠ“ыя-Š±Ń–Š±Š»Ń–ŃŃ‚ŃŠŗŠ° Kaltura Š“Š°Š·Š²Š°Š»ŃŠµ Š’Š°Š¼ Š²Ń‹ŠŗŠ°Ń€Ń‹ŃŃ‚Š¾ŃžŠ²Š°Ń†ŃŒ ŠæŠµŃ€Š°Š²Š°Š³Š°Š¼Ń– HTML5 <code><nowiki><video></nowiki></code> і <code><nowiki><audio></nowiki></code> тэŠ³Š°Ńž уŠ¶Š¾ Š·Š°Ń€Š°Š·, Š· Š°Š“Š½Š¾Š»ŃŒŠŗŠ°Š²Ń‹Š¼ іŠ½Ń‚ŃŃ€Ń„ŃŠ¹ŃŠ°Š¼ ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š½ŃŒŠ½Ń Š²Š° ўсіх Š°ŃŠ½Š¾ŃžŠ½Ń‹Ń… Š±Ń€Š°ŃžŠ·ŃŃ€Š°Ń….\n\t\n[$1 Š“Š°Š²ŠµŠ“Š°Ń†Ń†Š° Š±Š¾Š»ŠµŠ¹ ŠæрŠ° Š±Ń–Š±Š»Ń–ŃŃ‚ŃŠŗу ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–ŠŗŠ° Kaltura].",
+ "mwe-embedplayer-clip_linkback": "ŠšŃ€Ń‹Š½Ń–чŠ½Š°Ń стŠ°Ń€Š¾Š½ŠŗŠ° чŠ°ŃŃ‚Šŗі фŠ°Š¹Š»Š°",
+ "mwe-embedplayer-choose_player": "Š’Ń‹Š±ŠµŃ€Ń‹Ń†Šµ Š²Ń–Š“эŠ°-ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–Šŗ",
+ "mwe-embedplayer-no-player": "ŠŃŠ¼Š° ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–ŠŗŠ° Š“Š»Ń $1",
+ "mwe-embedplayer-share_this_video": "Š—Ń€Š°Š±Ń–Ń†ŃŒ Š³ŃŃ‚Š°Šµ Š²Ń–Š“эŠ° Š°Š³ŃƒŠ»ŃŒŠ½Ń‹Š¼",
+ "mwe-embedplayer-video_credits": "Š”тŠ²Š°Ń€Š°Š»ŃŒŠ½Ń–Šŗі Š²Ń–Š“эŠ°",
+ "mwe-embedplayer-no-video_credits": "Š—ŃŒŠ²ŠµŃŃ‚Š°Šŗ ŠæрŠ° Š°ŃžŃ‚Š°Ń€Š°Ńž Š½ŃŠ¼Š°",
+ "mwe-embedplayer-kaltura-platform-title": "Š’Ń–Š“эŠ°-ŠæŠ»ŃŃ‚Ń„Š¾Ń€Š¼Š° Š· Š²Š¾Š»ŃŒŠ½Ń‹Š¼ ŠŗрыŠ½Ń–чŠ½Ń‹Š¼ ŠŗŠ¾Š“Š°Š¼ Kaltura",
+ "mwe-embedplayer-menu_btn": "ŠœŃŠ½ŃŽ",
+ "mwe-embedplayer-close_btn": "Š—Š°Šŗрыць",
+ "mwe-embedplayer-ogg-player-vlc-player": "ŠŸŃ€Š°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–Šŗ VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "ŠŸŃ€Š°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–Šŗ HTML5 Ogg",
+ "mwe-embedplayer-ogg-player-mp3Native": "ŠŸŃ€Š°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–Šŗ HTML5 MP3",
+ "mwe-embedplayer-ogg-player-aacNative": "ŠŸŃ€Š°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–Šŗ HTML5 AAC",
+ "mwe-embedplayer-ogg-player-h264Native": "ŠŸŃ€Š°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–Šŗ HTML5 H.264",
+ "mwe-embedplayer-ogg-player-webmNative": "ŠŸŃ€Š°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–Šŗ HTML5 WebM",
+ "mwe-embedplayer-ogg-player-oggPlugin": "ŠŠ³ŃƒŠ»ŃŒŠ½Š°Šµ Š“Š°ŠæŠ°ŃžŠ½ŠµŠ½ŃŒŠ½Šµ Ogg",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Š”Š°ŠæŠ°ŃžŠ½ŠµŠ½ŃŒŠ½Šµ QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "ŠŸŃ€Š°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–Šŗ Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(Š²Ń‹Š±Ń€Š°Š½Ń‹)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Š”Š»Ń Š»ŠµŠæшŠ°Š³Š° ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š½ŃŒŠ½Ń Š²Ń–Š“эŠ° Š¼Ń‹ рэŠŗŠ°Š¼ŃŠ½Š“уŠµŠ¼ <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">Š±Ń€Š°ŃžŠ·ŃŃ€ Š· ŠæŠ°Š“трыŠ¼ŠŗŠ°Š¹ HTML5-Š²Ń–Š“эŠ°</a>.",
+ "mwe-embedplayer-download-warn": "ŠŃ Š·Š½Š¾Š¹Š“Š·ŠµŠ½Ń‹ ўŠ±ŃƒŠ“Š°Š²Š°Š½Ń‹ ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–Šŗ: Š“Š»Ń ŠæрŠ°Š³Š»ŃŠ“у ў Š±Ń€Š°ŃžŠ·ŃŃ€Ń‹ Š·Š°Š³Ń€ŃƒŠ·Ń–цŠµ [$1 Š°ŠæŠ¾ŃˆŠ½ŃŽŃŽ Š²ŃŃ€ŃŃ–ŃŽ Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "ŠšŠ»ŃŠ²Ń–ŃˆŠ° <b>F11</b> ŠæŠµŃ€Š°ŠŗŠ»ŃŽŃ‡Š°Šµ <i>Š²ŃŠ±-Š±Ń€Š°ŃžŠ·ŃŃ€</i> у ŠæŠ¾ŃžŠ½Š°ŃŠŗрŠ°Š½Š½Ń‹ рэŠ¶Ń‹Š¼",
+ "mwe-embedplayer-fullscreen-tip-osx": "ŠŠ°Ń†Ń–ŃŃŒŠ½Ń–цŠµ <b>shift āŒ˜ F</b> Š“Š»Ń ŠæŠµŃ€Š°Ń…Š¾Š“у ў ŠæŠ¾ŃžŠ½Š°ŃŠŗрŠ°Š½Š½Ń‹ рэŠ¶Ń‹Š¼",
+ "mwe-embedplayer-do_not_warn_again": "ŠŠµ ŠæŠ°ŠŗŠ°Š·Š²Š°Ń†ŃŒ Š³ŃŃ‚Š°Šµ ŠæŠ°Š²ŠµŠ“Š°Š¼Š»ŠµŠ½ŃŒŠ½Šµ ў Š±ŃƒŠ“учыŠ½Ń–",
+ "mwe-embedplayer-playerSelect": "ŠŸŃ€Š°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–Šŗі",
+ "mwe-embedplayer-read_before_embed": "ŠšŠ°Š»Ń– Š»Š°ŃŠŗŠ°, <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">ŠæрŠ°Ń‡Ń‹Ń‚Š°Š¹Ń†Šµ Š³ŃŃ‚Š°</a> ŠæŠµŃ€Š°Š“ устŠ°ŃžŠŗŠ°Š¹!",
+ "mwe-embedplayer-embed_site_or_blog": "Š£ŃŃ‚Š°Š²Ń–Ń†ŃŒ Š½Š° стŠ°Ń€Š¾Š½Šŗу",
+ "mwe-embedplayer-embed_wiki": "Š£ŃŃ‚Š°Š²Ń–Ń†ŃŒ у Š²Ń–Šŗі",
+ "mwe-embedplayer-related_videos": "Š—ŃŒŠ²ŃŠ·Š°Š½Ń‹Ń Š²Ń–Š“эŠ°",
+ "mwe-embedplayer-seeking": "ŠæŠ¾ŃˆŃƒŠŗ",
+ "mwe-embedplayer-buffering": "Š±ŃƒŃ„ŃŃ€Ń‹Š·Š°Ń†Ń‹Ń",
+ "mwe-embedplayer-video-h264": "H.264 Š²Ń–Š“эŠ°",
+ "mwe-embedplayer-video-webm": "WebM Š²Ń–Š“эŠ°",
+ "mwe-embedplayer-video-flv": "Flash-Š²Ń–Š“эŠ°",
+ "mwe-embedplayer-video-ogg": "Ogg-Š²Ń–Š“эŠ°",
+ "mwe-embedplayer-video-audio": "Ogg-Š°ŃžŠ“ыё",
+ "mwe-embedplayer-audio-mpeg": "MPEG-Š°ŃžŠ“ыё",
+ "mwe-embedplayer-video-3gp": "3GP-Š²Ń–Š“эŠ°",
+ "mwe-embedplayer-video-mpeg": "MPEG-Š²Ń–Š“эŠ°",
+ "mwe-embedplayer-video-msvideo": "AVI-Š²Ń–Š“эŠ°",
+ "mwe-embedplayer-missing-source": "ŠŃ Š·Š½Š¾Š¹Š“Š·ŠµŠ½Š° ŠŗрыŠ½Ń–чŠ½Š°Šµ Š²Ń–Š“эŠ°."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bg.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bg.json
new file mode 100644
index 00000000..3402ed3f
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bg.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ",
+ "DCLXVI"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Š—Š°Š³Š»Š°Š²ŠøŠµ: $1",
+ "mwe-embedplayer-credit-date": "Š”Š°Ń‚Š°: $1",
+ "mwe-embedplayer-credit-author": "ŠŠ²Ń‚Š¾Ń€: $1",
+ "mwe-embedplayer-close_btn": "Š—Š°Ń‚Š²Š°Ń€ŃŠ½Šµ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bho.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bho.json
new file mode 100644
index 00000000..e19056b0
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bho.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Nepaboy"
+ ]
+ },
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "ą¤†ą¤ˆą¤“ą¤ą¤ø ą¤ą¤Ŗą„ą¤²ą„€ą¤•ą„‡ą¤¶ą¤Ø ą¤–ą¤¾ą¤¤ą¤æą¤° ą¤µą¤æą¤ą¤²ą¤øą„€",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "ą¤µą¤æą¤ą¤²ą¤øą„€ ą¤ą¤Ŗą„ą¤²ą„€ą¤•ą„‡ą¤¶ą¤Ø",
+ "mwe-embedplayer-vlcapp-downloadapp": "ą¤ą¤Ŗą„¦ ą¤øą„ą¤Ÿą„‹ą¤° ą¤øą„‡ ą¤µą¤æą¤ą¤²ą¤øą„€ ą¤ą¤Ŗą„¦ ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤” ą¤•ą¤°ą„€ą¤‚",
+ "mwe-embedplayer-vlcapp-openvideo": "ą¤µą¤æą¤ą¤²ą¤øą„€ ą¤ą¤Ŗą„¦ ą¤®ą„‡ą¤‚ ą¤‡ ą¤µą„€ą¤”ą¤æą¤Æą„‹ ą¤–ą„‹ą¤²ą„€ą¤‚",
+ "mwe-embedplayer-vlcapp-downloadvideo": "ą¤‡ ą¤µą¤æą¤”ą¤æą¤Æą„‹ ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤” ą¤•ą¤°ą„€ą¤‚",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "ą¤‡ ą¤øą¤¾ą¤ˆą¤Ÿ ą¤Ŗą¤° ą¤µą„€ą¤”ą¤æą¤Æą„‹ ą¤šą¤²ą¤¾ą¤µą„‡ ą¤–ą¤¾ą¤¤ą¤æą¤°, ą¤†ą¤Ŗ ą¤•ą„‡ ą¤µą¤æą¤ą¤²ą¤øą„€ ą¤ą¤Ŗą„¦ ą¤•ą„‡ ą¤œą¤°ą„ą¤°ą¤¤ ą¤Ŗą¤”ą¤¼ą„€ą„¤ ą¤…ą¤­ą„€ ą¤‡ą¤Øą¤øą„ą¤Ÿą„‰ą¤² ą¤•ą¤°ą¤¬?"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bn.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bn.json
new file mode 100644
index 00000000..063989dc
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bn.json
@@ -0,0 +1,74 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aftab1995",
+ "Aftabuzzaman"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "ą¦¶ą¦æą¦°ą§‹ą¦Øą¦¾ą¦®: $1",
+ "mwe-embedplayer-credit-date": "ą¦¤ą¦¾ą¦°ą¦æą¦–: $1",
+ "mwe-embedplayer-credit-author": "ą¦Ŗą§ą¦°ą¦£ą§‡ą¦¤ą¦¾: $1",
+ "mwe-embedplayer-nocredits": "ą¦•ą§‹ą¦Ø ą¦•ą§ą¦°ą§‡ą¦”ą¦æą¦Ÿ ą¦‰ą¦Ŗą¦²ą¦¬ą§ą¦§ ą¦Øą¦Æą¦¼",
+ "mwe-embedplayer-loading_plugin": "ą¦Ŗą§ą¦²ą¦¾ą¦—ą¦‡ą¦Ø ą¦²ą§‹ą¦” ą¦¹ą¦šą§ą¦›ą§‡ ...",
+ "mwe-embedplayer-select_playback": "ą¦Ŗą§ą¦²ą§‡ą¦¬ą§ą¦Æą¦¾ą¦• ą¦Ŗą¦›ą¦Øą§ą¦¦ ą¦Øą¦æą¦°ą§ą¦§ą¦¾ą¦°ą¦£ ą¦•ą¦°ą§ą¦Ø",
+ "mwe-embedplayer-play_clip": "ą¦•ą§ą¦²ą¦æą¦Ŗ ą¦šą¦¾ą¦²ą¦¾ą¦Ø",
+ "mwe-embedplayer-pause_clip": "ą¦•ą§ą¦²ą¦æą¦Ŗ ą¦„ą¦¾ą¦®ą¦¾ą¦Ø",
+ "mwe-embedplayer-volume_control": "ą¦­ą¦²ą¦æą¦‰ą¦® ą¦Øą¦æą¦Æą¦¼ą¦Øą§ą¦¤ą§ą¦°ą¦£",
+ "mwe-embedplayer-player_options": "ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦° ą¦…ą¦Ŗą¦¶ą¦Ø",
+ "mwe-embedplayer-timed_text": "ą¦Ÿą¦¾ą¦‡ą¦®ą¦” ą¦Ÿą§‡ą¦•ą§ą¦øą¦Ÿ",
+ "mwe-embedplayer-player_fullscreen": "ą¦Ŗą§‚ą¦°ą§ą¦£ ą¦øą§ą¦•ą§ą¦°ą¦æą¦Ø",
+ "mwe-embedplayer-next_clip_msg": "ą¦Ŗą¦°ą¦¬ą¦°ą§ą¦¤ą§€ ą¦•ą§ą¦²ą¦æą¦Ŗ ą¦šą¦¾ą¦²ą¦¾ą¦Ø",
+ "mwe-embedplayer-prev_clip_msg": "ą¦Ŗą§‚ą¦°ą§ą¦¬ą¦¬ą¦°ą§ą¦¤ą§€ ą¦•ą§ą¦²ą¦æą¦Ŗ ą¦šą¦¾ą¦²ą¦¾ą¦Ø",
+ "mwe-embedplayer-current_clip_msg": "ą¦ą¦‡ ą¦•ą§ą¦²ą¦æą¦Ŗ ą¦…ą¦¬ą¦æą¦°ą¦¤ ą¦šą¦¾ą¦²ą¦¾ą¦Ø",
+ "mwe-embedplayer-paused": "ą¦„ą¦¾ą¦®ą¦¾ą¦Øą§‹ ą¦¹ą¦Æą¦¼ą§‡ą¦›ą§‡",
+ "mwe-embedplayer-download_segment": "ą¦”ą¦¾ą¦‰ą¦Øą¦²ą§‹ą¦” ą¦Øą¦æą¦°ą§ą¦¬ą¦¾ą¦šą¦Ø:",
+ "mwe-embedplayer-download_full_video": "ą¦øą¦®ą§ą¦Ŗą§‚ą¦°ą§ą¦£ ą¦­ą¦æą¦”ą¦æą¦“ ą¦«ą¦¾ą¦‡ą¦² ą¦”ą¦¾ą¦‰ą¦Øą¦²ą§‹ą¦” ą¦•ą¦°ą§ą¦Ø:",
+ "mwe-embedplayer-download_full_audio": "ą¦øą¦®ą§ą¦Ŗą§‚ą¦°ą§ą¦£ ą¦…ą¦”ą¦æą¦“ ą¦«ą¦¾ą¦‡ą¦² ą¦”ą¦¾ą¦‰ą¦Øą¦²ą§‹ą¦” ą¦•ą¦°ą§ą¦Ø:",
+ "mwe-embedplayer-download_right_click": "ą¦”ą¦¾ą¦‰ą¦Øą¦²ą§‹ą¦” ą¦•ą¦°ą¦¤ą§‡, ą¦”ą¦¾ą¦Ø ą¦•ą§ą¦²ą¦æą¦• ą¦•ą¦°ą§‡ <i>Save link as...</i> ą¦Øą¦æą¦°ą§ą¦¬ą¦¾ą¦šą¦Ø ą¦•ą¦°ą§ą¦Ø",
+ "mwe-embedplayer-download_clip": "ą¦­ą¦æą¦”ą¦æą¦“ ą¦”ą¦¾ą¦‰ą¦Øą¦²ą§‹ą¦” ą¦•ą¦°ą§ą¦Ø",
+ "mwe-embedplayer-download_text": "ą¦²ą§‡ą¦–ą¦¾ ą¦”ą¦¾ą¦‰ą¦Øą¦²ą§‹ą¦” ą¦•ą¦°ą§ą¦Ø",
+ "mwe-embedplayer-download": "ą¦”ą¦¾ą¦‰ą¦Øą¦²ą§‹ą¦”",
+ "mwe-embedplayer-share": "ą¦¶ą§‡ą¦Æą¦¼ą¦¾ą¦°",
+ "mwe-embedplayer-credits": "ą¦•ą§ƒą¦¤ą¦æą¦¤ą§ą¦¬",
+ "mwe-embedplayer-about-library": "Kaltura ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦° ą¦øą¦®ą§ą¦Ŗą¦°ą§ą¦•ą§‡",
+ "mwe-embedplayer-choose_player": "ą¦­ą¦æą¦”ą¦æą¦“ ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦° ą¦šą¦Æą¦¼ą¦Ø ą¦•ą¦°ą§ą¦Ø",
+ "mwe-embedplayer-no-player": "$1-ą¦ą¦° ą¦œą¦Øą§ą¦Æ ą¦•ą§‹ą¦Ø ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦° ą¦‰ą¦Ŗą¦²ą¦¬ą§ą¦§ ą¦Øą§‡ą¦‡",
+ "mwe-embedplayer-video_credits": "ą¦­ą¦æą¦”ą¦æą¦“ ą¦•ą§ƒą¦¤ą¦æą¦¤ą§ą¦¬",
+ "mwe-embedplayer-no-video_credits": "ą¦•ą§‹ą¦Ø ą¦•ą§ƒą¦¤ą¦æą¦¤ą§ą¦¬ ą¦‰ą¦Ŗą¦²ą¦¬ą§ą¦§ ą¦Øą¦Æą¦¼",
+ "mwe-embedplayer-menu_btn": "ą¦®ą§‡ą¦Øą§",
+ "mwe-embedplayer-close_btn": "ą¦¬ą¦Øą§ą¦§",
+ "mwe-embedplayer-ogg-player-vlc-player": "ą¦­ą¦æą¦ą¦²ą¦øą¦æ ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦°",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦°",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3 ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦°",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AAC ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦°",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦°",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦°",
+ "mwe-embedplayer-ogg-player-oggPlugin": "ą¦œą§‡ą¦Øą§‡ą¦°ą¦æą¦• ą¦…ą¦— ą¦Ŗą§ą¦²ą¦¾ą¦—ą¦‡ą¦Ø",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "iOS ą¦…ą§ą¦Æą¦¾ą¦Ŗą§‡ą¦° ą¦œą¦Øą§ą¦Æ VLC",
+ "mwe-embedplayer-ogg-player-flowplayer": "ą¦«ą§ą¦²ą§‹ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦°",
+ "mwe-embedplayer-ogg-player-kplayer": "ą¦•ą¦¾ą¦²ą¦Ÿą§ą¦°ą¦¾ ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦°",
+ "mwe-embedplayer-ogg-player-selected": "(ą¦Øą¦æą¦°ą§ą¦¬ą¦¾ą¦šą¦æą¦¤)",
+ "mwe-embedplayer-do_not_warn_again": "ą¦­ą¦¬ą¦æą¦·ą§ą¦Æą¦¤ą§‡, ą¦ą¦‡ ą¦¬ą¦¾ą¦°ą§ą¦¤ą¦¾ ą¦Ŗą§ą¦°ą¦¦ą¦°ą§ą¦¶ą¦Ø ą¦•ą¦°ą¦¬ą§‡ą¦Ø ą¦Øą¦¾",
+ "mwe-embedplayer-playerSelect": "ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦°ą¦—ą§ą¦²ą¦æ",
+ "mwe-embedplayer-read_before_embed": "ą¦ą¦®ą§ą¦¬ą§‡ą¦” ą¦•ą¦°ą¦¾ą¦° ą¦†ą¦—ą§‡ <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">ą¦ą¦Ÿą¦æ ą¦Ŗą¦”ą¦¼ą§ą¦Ø</a>ą„¤",
+ "mwe-embedplayer-embed_site_or_blog": "ą¦ą¦•ą¦Ÿą¦æ ą¦Ŗą¦¾ą¦¤ą¦¾ą¦Æą¦¼ ą¦ą¦®ą§ą¦¬ą§‡ą¦” ą¦•ą¦°ą§ą¦Ø",
+ "mwe-embedplayer-embed_wiki": "ą¦ą¦•ą¦Ÿą¦æ ą¦‰ą¦‡ą¦•ą¦æą¦¤ą§‡ ą¦ą¦®ą§ą¦¬ą§‡ą¦” ą¦•ą¦°ą§ą¦Ø",
+ "mwe-embedplayer-related_videos": "ą¦øą¦®ą§ą¦Ŗą¦°ą§ą¦•ą¦æą¦¤ ą¦­ą¦æą¦”ą¦æą¦“",
+ "mwe-embedplayer-buffering": "ą¦¬ą¦¾ą¦«ą¦¾ą¦°ą¦æą¦‚",
+ "mwe-embedplayer-video-h264": "H.264 ą¦­ą¦æą¦”ą¦æą¦“",
+ "mwe-embedplayer-video-webm": "WebM ą¦­ą¦æą¦”ą¦æą¦“",
+ "mwe-embedplayer-video-flv": "ą¦«ą§ą¦²ą§ą¦Æą¦¾ą¦¶ ą¦­ą¦æą¦”ą¦æą¦“",
+ "mwe-embedplayer-video-ogg": "ą¦…ą¦— ą¦­ą¦æą¦”ą¦æą¦“",
+ "mwe-embedplayer-video-audio": "ą¦…ą¦— ą¦…ą¦”ą¦æą¦“",
+ "mwe-embedplayer-audio-mpeg": "ą¦ą¦®ą¦Ŗą¦æą¦‡ą¦œą¦æ ą¦…ą¦”ą¦æą¦“",
+ "mwe-embedplayer-video-3gp": "ą§©ą¦œą¦æą¦Ŗą¦æ ą¦­ą¦æą¦”ą¦æą¦“",
+ "mwe-embedplayer-video-mpeg": "ą¦ą¦®ą¦Ŗą¦æą¦‡ą¦œą¦æ ą¦­ą¦æą¦”ą¦æą¦“",
+ "mwe-embedplayer-video-msvideo": "ą¦ą¦­ą¦æą¦†ą¦‡ ą¦­ą¦æą¦”ą¦æą¦“",
+ "mwe-embedplayer-missing-source": "ą¦•ą§‹ą¦Ø ą¦‰ą§Žą¦ø ą¦­ą¦æą¦”ą¦æą¦“ ą¦Ŗą¦¾ą¦“ą¦Æą¦¼ą¦¾ ą¦Æą¦¾ą¦Æą¦¼ą¦Øą¦æ",
+ "mwe-embedplayer-vlcapp-intro": "ą¦ą¦•ą¦Ÿą¦æ ą¦†ą¦‡ą¦«ą§‹ą¦Ø ą¦¬ą¦¾ ą¦†ą¦‡ą¦Ŗą§ą¦Æą¦¾ą¦” ą¦„ą§‡ą¦•ą§‡ ą¦ą¦‡ ą¦øą¦¾ą¦‡ą¦Ÿą§‡ ą¦­ą¦æą¦”ą¦æą¦“ ą¦¦ą§‡ą¦–ą¦¾ą¦° ą¦œą¦Øą§ą¦Æ, ą¦†ą¦Ŗą¦Øą¦¾ą¦° ą¦¬ą¦æą¦Øą¦¾ą¦®ą§‚ą¦²ą§ą¦Æą§‡ą¦° $1 ą¦Ŗą§ą¦°ą¦Æą¦¼ą§‹ą¦œą¦Øą„¤",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "VLC ą¦…ą§ą¦Æą¦¾ą¦Ŗ",
+ "mwe-embedplayer-vlcapp-downloadapp": "ą¦…ą§ą¦Æą¦¾ą¦Ŗ ą¦øą§ą¦Ÿą§‹ą¦° ą¦„ą§‡ą¦•ą§‡ VLC ą¦…ą§ą¦Æą¦¾ą¦Ŗ ą¦”ą¦¾ą¦‰ą¦Øą¦²ą§‹ą¦” ą¦•ą¦°ą§ą¦Ø",
+ "mwe-embedplayer-vlcapp-openvideo": "ą¦­ą¦æą¦ą¦²ą¦øą¦æ ą¦…ą§ą¦Æą¦¾ą¦Ŗą§‡ ą¦ą¦‡ ą¦­ą¦æą¦”ą¦æą¦“ ą¦–ą§ą¦²ą§ą¦Ø",
+ "mwe-embedplayer-vlcapp-downloadvideo": "ą¦ą¦‡ ą¦­ą¦æą¦”ą¦æą¦“ ą¦”ą¦¾ą¦‰ą¦Øą¦²ą§‹ą¦” ą¦•ą¦°ą§ą¦Ø",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "ą¦ą¦‡ ą¦øą¦¾ą¦‡ą¦Ÿą§‡ ą¦­ą¦æą¦”ą¦æą¦“ ą¦šą¦¾ą¦²ą¦¾ą¦Øą§‹ą¦° ą¦œą¦Øą§ą¦Æ, ą¦†ą¦Ŗą¦Øą¦¾ą¦° ą¦¬ą¦æą¦Øą¦¾ą¦®ą§‚ą¦²ą§ą¦Æą§‡ą¦° ą¦­ą¦æą¦ą¦²ą¦øą¦æ ą¦…ą§ą¦Æą¦¾ą¦Ŗą¦Ÿą¦æ ą¦Ŗą§ą¦°ą¦Æą¦¼ą§‹ą¦œą¦Øą„¤ ą¦ą¦–ą¦Ø ą¦‡ą¦Øą¦øą§ą¦Ÿą¦² ą¦•ą¦°ą¦¬ą§‡ą¦Ø?"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/br.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/br.json
new file mode 100644
index 00000000..42ca1e35
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/br.json
@@ -0,0 +1,76 @@
+{
+ "@metadata": {
+ "authors": [
+ "Fulup",
+ "Y-M D"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titl : $1",
+ "mwe-embedplayer-credit-date": "Deiziad : $1",
+ "mwe-embedplayer-credit-author": "Aozer : $1",
+ "mwe-embedplayer-loading_plugin": "O kargaƱ ar plugin...",
+ "mwe-embedplayer-select_playback": "TermeniƱ ar penndibaboĆ¹ lenn",
+ "mwe-embedplayer-link_back": "Liamm distreiƱ",
+ "mwe-embedplayer-error_swap_vid": "Fazi : n'eo ket deuet a-benn mwEmbed da eskemm doareenn ar video evit an etrefas mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "OuzhpennaƱ e dibenn ar sekaƱs",
+ "mwe-embedplayer-missing_video_stream": "Mankout a ra ar restr video evit ar gwazh-maƱ",
+ "mwe-embedplayer-play_clip": "Lenn ar c'hlip",
+ "mwe-embedplayer-pause_clip": "EhanaƱ ar c'hlip",
+ "mwe-embedplayer-volume_control": "Kontrol an tregern",
+ "mwe-embedplayer-player_options": "DibarzhioĆ¹ al lenner",
+ "mwe-embedplayer-timed_text": "Testenn o tibunaƱ",
+ "mwe-embedplayer-player_fullscreen": "Skramm leun",
+ "mwe-embedplayer-next_clip_msg": "Lenn ar c'hlip da-heul",
+ "mwe-embedplayer-prev_clip_msg": "Lenn ar c'hlip kent",
+ "mwe-embedplayer-current_clip_msg": "Kenderc'hel da lenn ar c'hlip-maƱ",
+ "mwe-embedplayer-seek_to": "Mont da $1",
+ "mwe-embedplayer-paused": "ehanet",
+ "mwe-embedplayer-download_segment": "PellgargaƱ an diuzadenn",
+ "mwe-embedplayer-download_full": "PellgargaƱ ar restr video a-bezh :",
+ "mwe-embedplayer-download_right_click": "Evit pellgargaƱ, grit ur c'hlik-dehou ha diuzit <i>EnrollaƱ an ere evel...</i>",
+ "mwe-embedplayer-download_clip": "PellgargaƱ ar video",
+ "mwe-embedplayer-download_text": "EnrollaƱ an destenn",
+ "mwe-embedplayer-download": "PellgargaƱ",
+ "mwe-embedplayer-share": "RannaƱ",
+ "mwe-embedplayer-credits": "KredoĆ¹",
+ "mwe-embedplayer-about-library": "Diwar-benn al lenner Kaltura",
+ "mwe-embedplayer-about-library-desc": "Talvezout a ra al levraoueg Kaltura deoc'h d'ober ho mad eus ar balizennoĆ¹ HTML5 <code><nowiki><video></nowiki></code> ha <code><nowiki><klevet></nowiki></code> diouzhtu gant ul lenner hag un etrefas kenglotus gant ar merdeerioĆ¹ pennaƱ.\n\t\n[$1 Evit gouzout hiroc'h diwar-benn al levraoueg lenn Kaltura].",
+ "mwe-embedplayer-clip_linkback": "Pajenn mammenn ar c'hlip",
+ "mwe-embedplayer-choose_player": "Dibab al lenner video",
+ "mwe-embedplayer-no-player": "N'eus lenner ebet hag a zo dieub evit $1",
+ "mwe-embedplayer-share_this_video": "RannaƱ ar video-maƱ",
+ "mwe-embedplayer-video_credits": "KredadoĆ¹ ar video",
+ "mwe-embedplayer-no-video_credits": "N'eus tamm kred ebet",
+ "mwe-embedplayer-kaltura-platform-title": "Savenn video e mammenn digor Kaltura",
+ "mwe-embedplayer-menu_btn": "LaƱser",
+ "mwe-embedplayer-close_btn": "SerriƱ",
+ "mwe-embedplayer-ogg-player-vlc-player": "Lenner VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Lenner Ogg HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "Lenner H.264 HTML5",
+ "mwe-embedplayer-ogg-player-webmNative": "Lenner WebM HTML5",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Plugin hollek Ogg",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Plugin QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Lenner Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(diuzet)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Evit gwelet gwelloc'h e erbedadomp deoc'h : <br /><a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">Firefox 3.5</a>.",
+ "mwe-embedplayer-download-warn": "N'eo ket kenglotus ar Merdeer web detektet; evit lenn er merdeer, pellgargit [$1 stumm nevez Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "Pouezit war <b>F11</b> da wintaƱ e mod Skramm leun ar <i>merdeer web</i>",
+ "mwe-embedplayer-fullscreen-tip-osx": "Pouezit war <b>pennlizh. āŒ˜ F</b> evit gwintaƱ d'ar mod Skramm leun",
+ "mwe-embedplayer-do_not_warn_again": "Arabat diskouez ar gemennadenn-maƱ ken",
+ "mwe-embedplayer-playerSelect": "Lennerien",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Lennit an dra-maƱ</a> a-raok ober.",
+ "mwe-embedplayer-embed_site_or_blog": "EnframmaƱ en ur bajenn",
+ "mwe-embedplayer-related_videos": "VideoioĆ¹ liammet",
+ "mwe-embedplayer-seeking": "o klask",
+ "mwe-embedplayer-buffering": "o krubuilhaƱ",
+ "mwe-embedplayer-video-h264": "video H.264",
+ "mwe-embedplayer-video-webm": "Video WebM",
+ "mwe-embedplayer-video-flv": "video Flash",
+ "mwe-embedplayer-video-ogg": "video Ogg",
+ "mwe-embedplayer-video-audio": "Son Ogg",
+ "mwe-embedplayer-missing-source": "N'eus bet kavet mammenn video ebet."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bs.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bs.json
new file mode 100644
index 00000000..2a96f223
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/bs.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": [],
+ "mwe-embedplayer-player_fullscreen": "Puni ekran",
+ "mwe-embedplayer-paused": "zaustavljeno",
+ "mwe-embedplayer-download": "Učitavanje",
+ "mwe-embedplayer-share": "Dijeli",
+ "mwe-embedplayer-credits": "Zasluge",
+ "mwe-embedplayer-share_this_video": "Dijeli ovaj video",
+ "mwe-embedplayer-menu_btn": "Meni",
+ "mwe-embedplayer-close_btn": "Zatvori",
+ "mwe-embedplayer-related_videos": "Povezani snimci"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ca.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ca.json
new file mode 100644
index 00000000..e64d37b3
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ca.json
@@ -0,0 +1,46 @@
+{
+ "@metadata": {
+ "authors": [
+ "Pitort",
+ "Vriullop",
+ "Xavier Dengra"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "TĆ­tol: $1",
+ "mwe-embedplayer-credit-date": "Data: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-nocredits": "Sense crĆØdits disponibles",
+ "mwe-embedplayer-loading_plugin": "Carregant el connector...",
+ "mwe-embedplayer-play_clip": "Reprodueix el tall",
+ "mwe-embedplayer-pause_clip": "Posa en pausa",
+ "mwe-embedplayer-volume_control": "Control de volum",
+ "mwe-embedplayer-player_options": "Opcions del reproductor",
+ "mwe-embedplayer-timed_text": "Text sincronitzat",
+ "mwe-embedplayer-player_fullscreen": "Pantalla completa",
+ "mwe-embedplayer-current_clip_msg": "Continua reproduint",
+ "mwe-embedplayer-paused": "en pausa",
+ "mwe-embedplayer-download_full_video": "DescĆ rrega del fitxer audiovisual:",
+ "mwe-embedplayer-download_right_click": "Per descarregar, cliqueu el botĆ³ dret i seleccioneu <i>Desa l'enllaƧ com a...</i>",
+ "mwe-embedplayer-download": "DescĆ rrega",
+ "mwe-embedplayer-share": "Compartir",
+ "mwe-embedplayer-credits": "CrĆØdits",
+ "mwe-embedplayer-share_this_video": "Compartiu aquest multimĆØdia",
+ "mwe-embedplayer-menu_btn": "MenĆŗ",
+ "mwe-embedplayer-close_btn": "Tanca",
+ "mwe-embedplayer-for_best_experience": "Per a una millor experiĆØncia de visualitzaciĆ³ es recomana un <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download/ca\" target=\"_blank\">reproductor de vĆ­deo HTML5</a>.",
+ "mwe-embedplayer-download-warn": "No s'ha detectat cap reproductor compatible: per tenir un reproductor integrat al navegador, descarregueu la [$1 darrera versiĆ³ de Firefox]",
+ "mwe-embedplayer-do_not_warn_again": "No mostris mƩs aquest missatge en el futur",
+ "mwe-embedplayer-playerSelect": "Reproductors",
+ "mwe-embedplayer-embed_site_or_blog": "Incrustat en una pĆ gina",
+ "mwe-embedplayer-embed_wiki": "Incrustat en un wiki",
+ "mwe-embedplayer-video-h264": "VĆ­deo H.264",
+ "mwe-embedplayer-video-webm": "VĆ­deo WebM",
+ "mwe-embedplayer-video-flv": "VĆ­deo flaix",
+ "mwe-embedplayer-video-ogg": "VĆ­deo Ogg",
+ "mwe-embedplayer-video-audio": "ƀudio Ogg",
+ "mwe-embedplayer-audio-mpeg": "ƀudio MPEG",
+ "mwe-embedplayer-video-3gp": "VĆ­deo 3GP",
+ "mwe-embedplayer-video-mpeg": "VĆ­deo MPEG",
+ "mwe-embedplayer-video-msvideo": "VĆ­deo AVI",
+ "mwe-embedplayer-missing-source": "No s'ha trobat cap font de vĆ­deo"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ce.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ce.json
new file mode 100644
index 00000000..ea6a1c4f
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ce.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sasan700",
+ "Š£Š¼Š°Ń€"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Š¦Ó€Šµ: $1",
+ "mwe-embedplayer-seek_to": "Š”ŠµŃ…ŃŒŠ° Š³Ó€Š¾ $1",
+ "mwe-embedplayer-download_clip": "Š§ŃƒŃŠŗŠŗхŠ° Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-download_text": "Š§ŃƒŠ“Š°ŠŗŠŗхŠ° Š¹Š¾Š·Š°",
+ "mwe-embedplayer-download": "Š§ŃƒŃŠŗŠŗхŠ°",
+ "mwe-embedplayer-close_btn": "Š”Ó€Š°Ń‡Ó€Š°Š³Ó€Š°",
+ "mwe-embedplayer-seeking": "Š»Š°Ń…Š°Ń€"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/cs.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/cs.json
new file mode 100644
index 00000000..3170abee
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/cs.json
@@ -0,0 +1,68 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mormegil",
+ "Vks"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "NƔzev: $1",
+ "mwe-embedplayer-credit-date": "Datum: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-select_playback": "NastavenĆ­ voleb přehrĆ”vĆ”nĆ­",
+ "mwe-embedplayer-link_back": "Odkaz zpět",
+ "mwe-embedplayer-play_clip": "PřehrĆ”t klip",
+ "mwe-embedplayer-pause_clip": "Pozastavit klip",
+ "mwe-embedplayer-volume_control": "OvlƔdƔnƭ hlasitosti",
+ "mwe-embedplayer-player_options": "Možnosti přehrĆ”vače",
+ "mwe-embedplayer-timed_text": "Titulky",
+ "mwe-embedplayer-player_fullscreen": "CelĆ” obrazovka",
+ "mwe-embedplayer-next_clip_msg": "PřehrĆ”t dalÅ”Ć­ klip",
+ "mwe-embedplayer-prev_clip_msg": "PřehrĆ”t předchozĆ­ klip",
+ "mwe-embedplayer-seek_to": "Přesun na $1",
+ "mwe-embedplayer-paused": "pozastaveno",
+ "mwe-embedplayer-download_full": "StaženĆ­ celĆ©ho videosouboru:",
+ "mwe-embedplayer-download_clip": "StƔhnout video",
+ "mwe-embedplayer-download": "StƔhnout",
+ "mwe-embedplayer-share": "SdĆ­let",
+ "mwe-embedplayer-credits": "O souboru",
+ "mwe-embedplayer-about-library": "O přehrĆ”vači Kaltura",
+ "mwe-embedplayer-about-library-desc": "Knihovna mĆ©diĆ­ pro HTML5 Kaltura vĆ”m umožňuje už dnes vyuÅ¾Ć­vat značky HTML5 &lt;video&gt; a &lt;audio&gt; a mĆ­t konzistentnĆ­ rozhranĆ­ prohlĆ­Å¾eče na vÅ”ech hlavnĆ­ch prohlĆ­Å¾ečƭch.\n\n[$1 VĆ­ce informacĆ­ o přehrĆ”vacĆ­ knihovně Kaltura]",
+ "mwe-embedplayer-choose_player": "Vybrat přehrĆ”vač videa",
+ "mwe-embedplayer-no-player": "Pro $1 nenĆ­ dostupnĆ½ Å¾Ć”dnĆ½ přehrĆ”vač",
+ "mwe-embedplayer-share_this_video": "SdĆ­let toto video",
+ "mwe-embedplayer-kaltura-platform-title": "OtevřenĆ” platforma pro video Kaltura",
+ "mwe-embedplayer-menu_btn": "Menu",
+ "mwe-embedplayer-close_btn": "ZavÅ™Ć­t",
+ "mwe-embedplayer-ogg-player-vlc-player": "PřehrĆ”vač VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 přehrĆ”vač Ogg",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 přehrĆ”vač H.264",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 přehrĆ”vač WebM",
+ "mwe-embedplayer-ogg-player-oggPlugin": "GenerickĆ½ zĆ”suvnĆ½ modul Ogg",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "ZĆ”suvnĆ½ modul QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "ActiveX prvek QuickTime",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "PřehrĆ”vač Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(vybranĆ½)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Pro pÅ™Ć­jemnějÅ”Ć­ přehrĆ”vĆ”nĆ­ videa doporučujeme <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">HTML5 prohlĆ­Å¾eč videa</a>.",
+ "mwe-embedplayer-fullscreen-tip": "StisknutĆ­m <b>F11</b> přepĆ­nĆ”te celoobrazovkovĆ½ režim <i>webovĆ©ho prohlĆ­Å¾eče</i>",
+ "mwe-embedplayer-fullscreen-tip-osx": "StisknutĆ­m <b>shift āŒ˜ F</b> přepĆ­nĆ”te celoobrazovkovĆ½ režim",
+ "mwe-embedplayer-do_not_warn_again": "PÅ™Ć­Å”tě tuto zprĆ”vu nezobrazovat.",
+ "mwe-embedplayer-playerSelect": "PřehrĆ”vače",
+ "mwe-embedplayer-read_before_embed": "Před vklĆ”dĆ”nĆ­m <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">čtěte upozorněnĆ­</a>.",
+ "mwe-embedplayer-embed_site_or_blog": "VloženĆ­ na strĆ”nku",
+ "mwe-embedplayer-related_videos": "SouvisejĆ­cĆ­ videa",
+ "mwe-embedplayer-seeking": "přesun",
+ "mwe-embedplayer-buffering": "načƭtĆ”nĆ­ do paměti",
+ "mwe-embedplayer-video-h264": "Video v H.264",
+ "mwe-embedplayer-video-webm": "Video WebM",
+ "mwe-embedplayer-video-flv": "Video ve Flashi",
+ "mwe-embedplayer-video-ogg": "Video v Ogg",
+ "mwe-embedplayer-video-audio": "Zvuk v Ogg",
+ "mwe-embedplayer-audio-mpeg": "Audio MPEG",
+ "mwe-embedplayer-video-3gp": "Video 3GP",
+ "mwe-embedplayer-video-mpeg": "Video MPEG",
+ "mwe-embedplayer-video-msvideo": "Video AVI",
+ "mwe-embedplayer-missing-source": "Nebylo nalezeno zdrojovƩ video"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/cu.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/cu.json
new file mode 100644
index 00000000..8475311f
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/cu.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "ŠžŠ¹Š›"
+ ]
+ },
+ "mwe-embedplayer-credit-author": "тŠ²Š¾Ń€ŃŒŃ†ŃŒ : $1",
+ "mwe-embedplayer-close_btn": "ź™Š°Šŗрź™‘Šø"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/de.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/de.json
new file mode 100644
index 00000000..9acb4658
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/de.json
@@ -0,0 +1,98 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kghbln",
+ "Metalhead64",
+ "Purodha"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titel: $1",
+ "mwe-embedplayer-credit-date": "Datum: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-nocredits": "Keine Danksagungen verfĆ¼gbar",
+ "mwe-embedplayer-loading_plugin": "lade Plugin ā€¦",
+ "mwe-embedplayer-select_playback": "Wiedergabeeinstellungen Ƥndern",
+ "mwe-embedplayer-link_back": "Link zurĆ¼ck",
+ "mwe-embedplayer-error_swap_vid": "Fehler: mv_embed konnte nicht das Videotag fĆ¼r die mv_embed-OberflƤche auslagern",
+ "mwe-embedplayer-add_to_end_of_sequence": "Zum Ende der Sequenz hinzufĆ¼gen",
+ "mwe-embedplayer-missing_video_stream": "Die Videodatei fĆ¼r diesen Stream fehlt",
+ "mwe-embedplayer-play_clip": "Clip abspielen",
+ "mwe-embedplayer-pause_clip": "Clip pausieren",
+ "mwe-embedplayer-volume_control": "LautstƤrkeregelung",
+ "mwe-embedplayer-player_options": "Playeroptionen",
+ "mwe-embedplayer-timed_text": "Zeitbezogene Untertitel",
+ "mwe-embedplayer-player_fullscreen": "Vollbild",
+ "mwe-embedplayer-next_clip_msg": "NƤchsten Clip wiedergeben",
+ "mwe-embedplayer-prev_clip_msg": "Vorherigen Clip wiedergeben",
+ "mwe-embedplayer-current_clip_msg": "Mit der Wiedergabe dieses Clips fortfahren",
+ "mwe-embedplayer-seek_to": "Suche $1",
+ "mwe-embedplayer-paused": "pausiert",
+ "mwe-embedplayer-download_segment": "Auswahl herunterladen:",
+ "mwe-embedplayer-download_full_video": "Ganze Videodatei herunterladen:",
+ "mwe-embedplayer-download_full_audio": "Ganze Audiodatei herunterladen:",
+ "mwe-embedplayer-download_right_click": "Zum Herunterladen die rechte Maustaste nutzen und <i>Link speichern unter ā€¦</i> auswƤhlen",
+ "mwe-embedplayer-download_clip": "Video herunterladen",
+ "mwe-embedplayer-download_text": "Text herunterladen",
+ "mwe-embedplayer-download": "Herunterladen",
+ "mwe-embedplayer-share": "Teilen",
+ "mwe-embedplayer-credits": "Urheberschaft",
+ "mwe-embedplayer-about-library": "Ɯber den Kaltura-Player",
+ "mwe-embedplayer-about-library-desc": "Kalturas HTML5-Medienbibliothek ermƶglicht es die Vorteile der beiden HTML5-Tags <code><nowiki><video></nowiki></code> und <code><nowiki><audio></nowiki></code> mit einem einheitlichen Player-Interface bei allen fĆ¼hrenden Webbrowsern nutzen zu kƶnnen.\n\n[$1 Weitere Informationen zu Kalturas HTML5-Medienbibliothek].",
+ "mwe-embedplayer-clip_linkback": "Clip-Quellseite",
+ "mwe-embedplayer-choose_player": "Videoplayer auswƤhlen",
+ "mwe-embedplayer-no-player": "Es ist fĆ¼r $1 kein Player verfĆ¼gbar",
+ "mwe-embedplayer-share_this_video": "Dieses Video teilen",
+ "mwe-embedplayer-share_this_audio": "Diese Audiodatei teilen",
+ "mwe-embedplayer-video_credits": "Videocredits",
+ "mwe-embedplayer-no-video_credits": "Keine Urheberangaben verfĆ¼gbar",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura Open-Source-Video-Plattform",
+ "mwe-embedplayer-menu_btn": "MenĆ¼",
+ "mwe-embedplayer-close_btn": "SchlieƟen",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC-Player",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg-Player",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5-MP3-Player",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5-AAC-Player",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264-Player",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM-Player",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Allgemeines Ogg-Plugin",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "VLC fĆ¼r die iOS-App",
+ "mwe-embedplayer-ogg-player-IEWebMPrompt": "IE-WebM-Plugin-Downloader",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime-Plugin",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura-Player",
+ "mwe-embedplayer-ogg-player-selected": "(ausgewƤhlt)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "FĆ¼r eine bessere Videowiedergabe wird ein <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download/de\" target=\"_blank\">HTML5-Videobrowser</a> empfohlen.",
+ "mwe-embedplayer-download-warn": "Beim Browser wurde ein inkompatibles Wiedergabeprogramm erkannt. FĆ¼r eine im Browser eingebettete Wiedergabe wird die Nutzung der [$1 neuesten Version von Mozilla Firefox] empfohlen.",
+ "mwe-embedplayer-fullscreen-tip": "Die Taste <b>F11</b> drĆ¼cken, um zum Vollbildmodus des <i>Webbrowsers</i> umzuschalten.",
+ "mwe-embedplayer-fullscreen-tip-osx": "Die Tasten <b>UMSCHALT āŒ˜ F</b> drĆ¼cken, um zum Vollbildmodus des <i>Webbrowsers</i> umzuschalten.",
+ "mwe-embedplayer-do_not_warn_again": "Diese Meldung in Zukunft nicht mehr anzeigen.",
+ "mwe-embedplayer-playerSelect": "Player",
+ "mwe-embedplayer-read_before_embed": "Vor dem Einbinden die <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Sicherheitsanmerkungen</a> durchlesen!",
+ "mwe-embedplayer-embed_site_or_blog": "Auf einer Seite einbinden",
+ "mwe-embedplayer-embed_wiki": "Auf einem Wiki einbetten",
+ "mwe-embedplayer-related_videos": "Ƅhnliche Videos",
+ "mwe-embedplayer-seeking": "suchen",
+ "mwe-embedplayer-buffering": "puffert",
+ "mwe-embedplayer-video-h264": "H.264-Video",
+ "mwe-embedplayer-video-webm": "WebM-Video",
+ "mwe-embedplayer-video-flv": "Flash-Video",
+ "mwe-embedplayer-video-ogg": "Ogg-Video",
+ "mwe-embedplayer-video-audio": "Ogg-Audiodatei",
+ "mwe-embedplayer-audio-mpeg": "MPEG-Audio",
+ "mwe-embedplayer-video-3gp": "3gp-Video",
+ "mwe-embedplayer-video-mpeg": "MPEG-Video",
+ "mwe-embedplayer-video-msvideo": "AVI-Video",
+ "mwe-embedplayer-missing-source": "Es konnte kein Videoclip gefunden werden.",
+ "mwe-embedplayer-vlcapp-intro": "Um Videos von dieser Website auf einem iPhone oder iPad anzusehen, musst du die kostenlose $1 herunterladen.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "VLC-App",
+ "mwe-embedplayer-vlcapp-downloadapp": "Die VLC-App aus dem App Store herunterladen",
+ "mwe-embedplayer-vlcapp-openvideo": "Dieses Video in der VLC-App ƶffnen",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Dieses Video herunterladen",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "Um Videos auf dieser Website abzuspielen, benƶtigst du die kostenlose VLC-App. Jetzt installieren?",
+ "mwe-embedplayer-iewebmprompt-intro": "Huch! Eine weitere Sache, bevor du dieses Video abspielen kannst ā€¦",
+ "mwe-embedplayer-iewebmprompt-linktext": "Installiere WebM-Medienkomponenten fĆ¼r den Microsoft Internet Explorer",
+ "mwe-embedplayer-iewebmprompt-outro": "Lade nach der Installation diese Seite neu."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/diq.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/diq.json
new file mode 100644
index 00000000..ac3c19da
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/diq.json
@@ -0,0 +1,70 @@
+{
+ "@metadata": {
+ "authors": [
+ "Erdemaslancan",
+ "Mirzali"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Sername: $1",
+ "mwe-embedplayer-credit-date": "Tarix: $1",
+ "mwe-embedplayer-credit-author": "Nuştoğ: $1",
+ "mwe-embedplayer-loading_plugin": "loading plugin ...",
+ "mwe-embedplayer-select_playback": "tercihĆŖ kaydayişi eyar ker",
+ "mwe-embedplayer-link_back": "tepiya agĆŖrayiş re gıre bıd'",
+ "mwe-embedplayer-error_swap_vid": "xeta: qey mv_embed, mv_embed'i etiketĆŖ videoyi nĆŖşkeno teqas bıkero",
+ "mwe-embedplayer-add_to_end_of_sequence": "bıerz peyni rĆŖz",
+ "mwe-embedplayer-missing_video_stream": "qey no herikyayişi dosyaya videoyi nĆŖaseno",
+ "mwe-embedplayer-play_clip": "klib bıde kaykerdış",
+ "mwe-embedplayer-pause_clip": "klib bıde vındertış",
+ "mwe-embedplayer-volume_control": "kontrolĆŖ vengi",
+ "mwe-embedplayer-player_options": "OpsiyonĆŖ kaykerdoği",
+ "mwe-embedplayer-player_fullscreen": "Tam asenge",
+ "mwe-embedplayer-next_clip_msg": "klibo bin bıde kaykerdış",
+ "mwe-embedplayer-prev_clip_msg": "klibo verin bıde kaykerdış",
+ "mwe-embedplayer-current_clip_msg": "kaykerdışĆŖ no klibi re dewam bıker",
+ "mwe-embedplayer-seek_to": "Şo muddet ser $1",
+ "mwe-embedplayer-paused": "vındarnaye",
+ "mwe-embedplayer-download_segment": "tercihi biyar war",
+ "mwe-embedplayer-download_full_video": "dosyaya videoyi tam biya war:",
+ "mwe-embedplayer-download_right_click": "qey wari ardışi, raşt bıtıknĆŖ u <i>Hedef bıferq qeyd ker...</i> bıtıknĆŖ",
+ "mwe-embedplayer-download_clip": "video biyar war",
+ "mwe-embedplayer-download_text": "Metn biyar war",
+ "mwe-embedplayer-download": "biyar war",
+ "mwe-embedplayer-share": "Vıla ke",
+ "mwe-embedplayer-credits": "ĆŖyĆŖ ke destek dayĆŖ",
+ "mwe-embedplayer-clip_linkback": "pelĆŖ Ƨımeyi yo klibi",
+ "mwe-embedplayer-choose_player": "video player bıweƧin",
+ "mwe-embedplayer-share_this_video": "na video bare/par bıker",
+ "mwe-embedplayer-video_credits": "ĆŖyĆŖ ke destek dayĆŖ video",
+ "mwe-embedplayer-menu_btn": "menu",
+ "mwe-embedplayer-close_btn": "RacnĆŖ",
+ "mwe-embedplayer-ogg-player-vlc-player": "Kay kerdogĆŖ VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg kayker",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 kayker",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM kayker",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Cenerik olekenĆŖ Ogg'i",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime plugin",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "KaykerdoğĆŖ kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(tercih biyaye)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Seba daĆŖna rınd kaykerdışĆŖ videoy ma <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">html5 video arden</a> tewsiya kenime.",
+ "mwe-embedplayer-do_not_warn_again": "Vındero bahdo, na mesac newkĆŖ memocne",
+ "mwe-embedplayer-playerSelect": "Kaykeri",
+ "mwe-embedplayer-read_before_embed": "kerem kerĆŖ verĆŖ nımıtışi <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">derheqĆŖ dĆ»r ra nımıtışi de malumatĆŖ pawıtışan</a> bıwenĆŖ!",
+ "mwe-embedplayer-embed_site_or_blog": "ZerreyĆŖ keyepel u blogĆŖ xo de bınımnĆŖ",
+ "mwe-embedplayer-related_videos": "videoyĆŖ ke elaqedari",
+ "mwe-embedplayer-seeking": "cıgĆŖrayox",
+ "mwe-embedplayer-buffering": "tamponkerdış",
+ "mwe-embedplayer-video-h264": "H.264 video",
+ "mwe-embedplayer-video-webm": "WebM video",
+ "mwe-embedplayer-video-flv": "Flash video",
+ "mwe-embedplayer-video-ogg": "Ogg video",
+ "mwe-embedplayer-video-audio": "Ogg audio",
+ "mwe-embedplayer-audio-mpeg": "MPEG audio",
+ "mwe-embedplayer-video-3gp": "3GP video",
+ "mwe-embedplayer-video-mpeg": "MPEG video",
+ "mwe-embedplayer-video-msvideo": "AVI video"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/dsb.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/dsb.json
new file mode 100644
index 00000000..61685dad
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/dsb.json
@@ -0,0 +1,83 @@
+{
+ "@metadata": {
+ "authors": [
+ "Michawiki"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titel: $1",
+ "mwe-embedplayer-credit-date": "Datum: $1",
+ "mwe-embedplayer-credit-author": "Awtor: $1",
+ "mwe-embedplayer-nocredits": "Žadne Åŗěkowanja k dispoziciji",
+ "mwe-embedplayer-loading_plugin": "Tykac se zacytujo ...",
+ "mwe-embedplayer-select_playback": "Nastajenje za playback stajiś",
+ "mwe-embedplayer-link_back": "WĆ³tkaz slědk",
+ "mwe-embedplayer-error_swap_vid": "ZmĆ³lka: mv_embed njejo mĆ³gał wideotoflicku za pĆ³wjerch mv_embed wuměstniś",
+ "mwe-embedplayer-add_to_end_of_sequence": "KĆ³Å„coju sekwence pśidaś",
+ "mwe-embedplayer-missing_video_stream": "Wideowa dataja za toś tu tÅ”ugu felujo",
+ "mwe-embedplayer-play_clip": "Klip wĆ³tegraś",
+ "mwe-embedplayer-pause_clip": "Klip zastajiś",
+ "mwe-embedplayer-volume_control": "Regulěrowanje głosnosći",
+ "mwe-embedplayer-player_options": "Opcije wĆ³tegrawaka",
+ "mwe-embedplayer-timed_text": "Synchronizěrowany tekst",
+ "mwe-embedplayer-player_fullscreen": "Połna wobrazowka",
+ "mwe-embedplayer-next_clip_msg": "Pśiducy klip wĆ³tegraś",
+ "mwe-embedplayer-prev_clip_msg": "PjerwjejÅ”ny klip wĆ³tegraś",
+ "mwe-embedplayer-current_clip_msg": "Klip dalej wĆ³tegraś",
+ "mwe-embedplayer-seek_to": "$1 pytaś",
+ "mwe-embedplayer-paused": "zastajony",
+ "mwe-embedplayer-download_segment": "Wuběrk ześěgnuś:",
+ "mwe-embedplayer-download_full": "Dopołnu wideowu dataju ześěgnuś:",
+ "mwe-embedplayer-download_right_click": "Aby ześěgnuł, klikni z pÅ”aweju tastu a wubjeŕ <i>WĆ³tkaz składowaś ako...</i>",
+ "mwe-embedplayer-download_clip": "Wideo ześěgnuś",
+ "mwe-embedplayer-download_text": "Tekst",
+ "mwe-embedplayer-download": "Ześěgnuś",
+ "mwe-embedplayer-share": "Źěliś",
+ "mwe-embedplayer-credits": "Źěkowanje",
+ "mwe-embedplayer-about-library": "WĆ³ wĆ³tegrawaku Kaltura",
+ "mwe-embedplayer-about-library-desc": "Medijowa biblioteka HTML 5 wĆ³tgrawaka Kaltury zmĆ³Å¾nja lěpÅ”yny HTML 5-elementowu code><nowiki><video></nowiki></code> a <code><nowiki><audio></nowiki></code> z jadnotnym powjerchom wĆ³tgrawaka pśi wjeducych wĆ³tglědowakach.\n\n[$1 DalÅ”ne informacije wĆ³ bibliotece wĆ³tgrawaka Kaltura].",
+ "mwe-embedplayer-clip_linkback": "Žrědłowy bok klipow",
+ "mwe-embedplayer-choose_player": "WideowĆ³tegrawak wubraś",
+ "mwe-embedplayer-no-player": "Za $1 žeden wĆ³tgrawak k dispoziciji",
+ "mwe-embedplayer-share_this_video": "Toś to wideo Åŗěliś",
+ "mwe-embedplayer-video_credits": "Źěkowanja za napĆ³ranje wideo",
+ "mwe-embedplayer-no-video_credits": "Žedne pĆ³daśa wĆ³ awtorje k dispoziciji",
+ "mwe-embedplayer-kaltura-platform-title": "Wideowa platforma zjawnego žrědła Kaltura",
+ "mwe-embedplayer-menu_btn": "Meni",
+ "mwe-embedplayer-close_btn": "Zacyniś",
+ "mwe-embedplayer-ogg-player-vlc-player": "Grajadło VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "WĆ³tgrawak HTML5 Ogg",
+ "mwe-embedplayer-ogg-player-mp3Native": "WĆ³tgrawak HTML5 MP3",
+ "mwe-embedplayer-ogg-player-aacNative": "WĆ³tgrawak HTML5 AAC",
+ "mwe-embedplayer-ogg-player-h264Native": "WĆ³tgrawak HTML5 H.264",
+ "mwe-embedplayer-ogg-player-webmNative": "WĆ³tegrawak HTML5 WebM",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Tykac Generic Ogg",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Tykac QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "ActiveX QuickTime",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Grajadło Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(wubrany)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vobis",
+ "mwe-embedplayer-for_best_experience": "Za lěpÅ”e wideodožywjenje pĆ³rucujomy <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">wideowobglědowak HTML 5</a>.",
+ "mwe-embedplayer-download-warn": "Njekompatibelne wĆ³tegrawak we wobglědowaku namakany: za wĆ³tegrawanje we wobglědowaku ześěgni pÅ”osym [$1 nejnowÅ”u wersiju Mozilla Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "Tłoc <b>F11</b>, aby <i>webwobglědowak</i> do połneje wobrazowki pśeÅ”altował",
+ "mwe-embedplayer-fullscreen-tip-osx": "Tłoc <b>UMSCH āŒ˜ F</b>, aby pśeÅ”altował do modusa połneje wobrazowki",
+ "mwe-embedplayer-do_not_warn_again": "W pśichoÅŗe toś tu powěÅŗeńku wěcej njepokazaś",
+ "mwe-embedplayer-playerSelect": "WĆ³tgrawaki",
+ "mwe-embedplayer-read_before_embed": "PÅ”osym cytaj <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">wěstotne pśipiski wĆ³ zdalonem zasajÅŗenju</a>, nježli až napÅ”awdu zasajÅŗujoÅ”!",
+ "mwe-embedplayer-embed_site_or_blog": "Na boku zasajÅŗiś",
+ "mwe-embedplayer-embed_wiki": "We wikiju zasajÅŗiś",
+ "mwe-embedplayer-related_videos": "Pśiwuzne wideo",
+ "mwe-embedplayer-seeking": "pyta se",
+ "mwe-embedplayer-buffering": "pufrujo",
+ "mwe-embedplayer-video-h264": "Wideo H.264",
+ "mwe-embedplayer-video-webm": "WebM-wideo",
+ "mwe-embedplayer-video-flv": "Wideo Flash",
+ "mwe-embedplayer-video-ogg": "Ogg-wideo",
+ "mwe-embedplayer-video-audio": "Ogg-awdio",
+ "mwe-embedplayer-audio-mpeg": "MPEG awdio",
+ "mwe-embedplayer-video-3gp": "3GP wideo",
+ "mwe-embedplayer-video-mpeg": "MPEG wideo",
+ "mwe-embedplayer-video-msvideo": "AVI wideo",
+ "mwe-embedplayer-missing-source": "Žedno žrědłowe wideo namakane."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/el.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/el.json
new file mode 100644
index 00000000..3dcbb269
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/el.json
@@ -0,0 +1,77 @@
+{
+ "@metadata": {
+ "authors": [
+ "Geraki"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Ī¤ĪÆĻ„Ī»ĪæĻ‚: $1",
+ "mwe-embedplayer-credit-date": "Ī—Ī¼ĪµĻĪæĪ¼Ī·Ī½ĪÆĪ±: $1",
+ "mwe-embedplayer-credit-author": "Ī£Ļ…Ī³Ī³ĻĪ±Ļ†Ī­Ī±Ļ‚: $1",
+ "mwe-embedplayer-nocredits": "Ī”ĪµĪ½ Ī“Ī¹Ī±Ļ„ĪÆĪøĪµĪ½Ļ„Ī±Ī¹ Ī±Ī½Ī±Ļ†ĪæĻĪ­Ļ‚",
+ "mwe-embedplayer-loading_plugin": "Ī¦ĻŒĻĻ„Ļ‰ĻƒĪ· plugin ...",
+ "mwe-embedplayer-select_playback": "ĪŸĻĪ¹ĻƒĪ¼ĻŒĻ‚ Ļ€ĻĪæĻ„ĪÆĪ¼Ī·ĻƒĪ·Ļ‚ Ī±Ī½Ī±Ļ€Ī±ĻĪ±Ī³Ļ‰Ī³Ī®Ļ‚",
+ "mwe-embedplayer-link_back": "Ī£ĻĪ½Ī“ĪµĻƒĪ· Ļ€ĪÆĻƒĻ‰",
+ "mwe-embedplayer-error_swap_vid": "Ī£Ļ†Ī¬Ī»Ī¼Ī±: Ļ„Īæ mwEmbed Ī“ĪµĪ½ Ī®Ļ„Ī±Ī½ ĻƒĪµ ĪøĪ­ĻƒĪ· Ī½Ī± Ī±Ī½Ļ„Ī±Ī»Ī»Ī¬Ī¾ĪµĪ¹ Ļ„Ī·Ī½ ĪµĻ„Ī¹ĪŗĪ­Ļ„Ī± Ī²ĪÆĪ½Ļ„ĪµĪæ Ī³Ī¹Ī± Ļ„Ī·Ī½ Ī“Ī¹ĪµĻ€Ī±Ļ†Ī® mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Ī ĻĪæĻƒĪøĪ®ĪŗĪ· ĻƒĻ„Īæ Ļ„Ī­Ī»ĪæĻ‚ Ļ„Ī·Ļ‚ Ī±ĪŗĪæĪ»ĪæĻ…ĪøĪÆĪ±Ļ‚",
+ "mwe-embedplayer-missing_video_stream": "Ī¤Īæ Ī±ĻĻ‡ĪµĪÆĪæ Ī²ĪÆĪ½Ļ„ĪµĪæ Ī³Ī¹Ī± Ī±Ļ…Ļ„Ī® Ļ„Ī· ĻĪæĪ® Ī»ĪµĪÆĻ€ĪµĪ¹",
+ "mwe-embedplayer-play_clip": "Ī‘Ī½Ī±Ļ€Ī±ĻĪ±Ī³Ļ‰Ī³Ī® ĪŗĪ»Ī¹Ļ€",
+ "mwe-embedplayer-pause_clip": "Ī Ī±ĻĻƒĪ· ĪŗĪ»Ī¹Ļ€",
+ "mwe-embedplayer-volume_control": "ĪˆĪ»ĪµĪ³Ļ‡ĪæĻ‚ Ī­Ī½Ļ„Ī±ĻƒĪ·Ļ‚ Ī®Ļ‡ĪæĻ…",
+ "mwe-embedplayer-player_options": "Ī”Ļ…ĪøĪ¼ĪÆĻƒĪµĪ¹Ļ‚ Ī±Ī½Ī±Ļ€Ī±ĻĪ±Ī³Ļ‰Ī³Ī®Ļ‚",
+ "mwe-embedplayer-timed_text": "Ī§ĻĪæĪ½Ī¹ĻƒĪ¼Ī­Ī½Īæ ĪŗĪµĪÆĪ¼ĪµĪ½Īæ",
+ "mwe-embedplayer-player_fullscreen": "Ī Ī»Ī®ĻĪ·Ļ‚ ĪæĪøĻŒĪ½Ī·",
+ "mwe-embedplayer-next_clip_msg": "Ī‘Ī½Ī±Ļ€Ī±ĻĪ±Ī³Ļ‰Ī³Ī® ĪµĻ€ĻŒĪ¼ĪµĪ½ĪæĻ… ĪŗĪ»Ī¹Ļ€",
+ "mwe-embedplayer-prev_clip_msg": "Ī‘Ī½Ī±Ļ€Ī±ĻĪ±Ī³Ļ‰Ī³Ī® Ļ€ĻĪæĪ·Ī³ĪæĻĪ¼ĪµĪ½ĪæĻ… ĪŗĪ»Ī¹Ļ€",
+ "mwe-embedplayer-current_clip_msg": "Ī£Ļ…Ī½Ī­Ļ‡ĪµĪ¹Ī± Ī±Ī½Ī±Ļ€Ī±ĻĪ±Ī³Ļ‰Ī³Ī®Ļ‚ Ī±Ļ…Ļ„ĪæĻ Ļ„ĪæĻ… ĪŗĪ»Ī¹Ļ€",
+ "mwe-embedplayer-seek_to": "Ī‘Ī½Ī±Ī¶Ī®Ļ„Ī·ĻƒĪ· Ī³Ī¹Ī± $1",
+ "mwe-embedplayer-paused": "ĻƒĪµ Ļ€Ī±ĻĻƒĪ·",
+ "mwe-embedplayer-download_segment": "Ī›Ī®ĻˆĪ· ĪµĻ€Ī¹Ī»ĪæĪ³Ī®Ļ‚:",
+ "mwe-embedplayer-download_full": "ĪšĪ±Ļ„ĪµĪ²Ī¬ĻƒĻ„Īµ Ļ„Īæ Ļ€Ī»Ī®ĻĪµĻ‚ Ī±ĻĻ‡ĪµĪÆĪæ Ī²ĪÆĪ½Ļ„ĪµĪæ:",
+ "mwe-embedplayer-download_right_click": "Ī“Ī¹Ī± Ī½Ī± ĪŗĪ±Ļ„ĪµĪ²Ī¬ĻƒĪµĻ„Īµ, ĪŗĪ¬Ī½Ļ„Īµ Ī“ĪµĪ¾ĪÆ ĪŗĪ»Ī¹Īŗ ĪŗĪ±Ī¹ ĪµĻ€Ī¹Ī»Ī­Ī¾Ļ„Īµ <i>Ī‘Ļ€ĪæĪøĪ®ĪŗĪµĻ…ĻƒĪ· ĻƒĻ…Ī½Ī“Ī­ĻƒĪ¼ĪæĻ… Ļ‰Ļ‚ ...</i>",
+ "mwe-embedplayer-download_clip": "Ī›Ī®ĻˆĪ· Ī²ĪÆĪ½Ļ„ĪµĪæ",
+ "mwe-embedplayer-download_text": "ĪšĪ±Ļ„ĪµĪ²Ī¬ĻƒĻ„Īµ Ļ„Īæ ĪŗĪµĪÆĪ¼ĪµĪ½Īæ",
+ "mwe-embedplayer-download": "Ī›Ī®ĻˆĪ·",
+ "mwe-embedplayer-share": "Ī”Ī¹Ī±Ī¼ĪæĪ¹ĻĪ±ĻƒĪ¼ĻŒĻ‚",
+ "mwe-embedplayer-credits": "Ī£Ļ…Ī½Ļ„ĪµĪ»ĪµĻƒĻ„Ī­Ļ‚",
+ "mwe-embedplayer-about-library": "Ī£Ļ‡ĪµĻ„Ī¹ĪŗĪ¬ Ī¼Īµ Ļ„Ī·Ī½ ĪµĻ†Ī±ĻĪ¼ĪæĪ³Ī® Kaltura",
+ "mwe-embedplayer-clip_linkback": "Ī£ĪµĪ»ĪÆĪ“Ī± Ļ€ĻĪæĪ­Ī»ĪµĻ…ĻƒĪ·Ļ‚ Ī²ĪÆĪ½Ļ„ĪµĪæ",
+ "mwe-embedplayer-choose_player": "Ī•Ļ€Ī¹Ī»Ī­Ī¾Ļ„Īµ Ļ€ĻĻŒĪ³ĻĪ±Ī¼Ī¼Ī± Ī±Ī½Ī±Ļ€Ī±ĻĪ±Ī³Ļ‰Ī³Ī®Ļ‚ Ī²ĪÆĪ½Ļ„ĪµĪæ",
+ "mwe-embedplayer-no-player": "ĪšĪ±Ī½Ī­Ī½Ī± Ļ€ĻĻŒĪ³ĻĪ±Ī¼Ī¼Ī± Ī±Ī½Ī±Ļ€Ī±ĻĪ±Ī³Ļ‰Ī³Ī®Ļ‚ Ī“ĪµĪ½ Ī“Ī¹Ī±Ļ„ĪÆĪøĪµĻ„Ī±Ī¹ Ī³Ī¹Ī± Ļ„Īæ $1",
+ "mwe-embedplayer-share_this_video": "ĪœĪæĪ¹ĻĪ±ĻƒĻ„ĪµĪÆĻ„Īµ Ī±Ļ…Ļ„ĻŒ Ļ„Īæ Ī²ĪÆĪ½Ļ„ĪµĪæ",
+ "mwe-embedplayer-video_credits": "Ī£Ļ…Ī½Ļ„ĪµĪ»ĪµĻƒĻ„Ī­Ļ‚ Ī²ĪÆĪ½Ļ„ĪµĪæ",
+ "mwe-embedplayer-no-video_credits": "Ī”ĪµĪ½ Ī“Ī¹Ī±Ļ„ĪÆĪøĪµĪ½Ļ„Ī±Ī¹ Ī±Ī½Ī±Ļ†ĪæĻĪ­Ļ‚",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura open source video platform",
+ "mwe-embedplayer-menu_btn": "ĪœĪµĪ½ĪæĻ…",
+ "mwe-embedplayer-close_btn": "ĪšĪ»ĪµĪÆĻƒĪ¹Ī¼Īæ",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC player",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg player",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 player",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Ī“ĪµĪ½Ī¹ĪŗĻŒ plugin Ogg",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime plugin",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura player",
+ "mwe-embedplayer-ogg-player-selected": "(ĪµĻ€Ī¹Ī»ĪµĪ³Ī¼Ī­Ī½Īæ)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Ī“Ī¹Ī± Ī¼Ī¹Ī± ĪŗĪ±Ī»ĻĻ„ĪµĻĪ· ĪµĪ¼Ļ€ĪµĪ¹ĻĪÆĪ± Ī±Ī½Ī±Ļ€Ī±ĻĪ±Ī³Ļ‰Ī³Ī®Ļ‚ Ī²ĪÆĪ½Ļ„ĪµĪæ ĻƒĪ±Ļ‚ Ļ€ĻĪæĻ„ĪµĪÆĪ½ĪæĻ…Ī¼Īµ Ī­Ī½Ī± <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">Ļ€ĪµĻĪ¹Ī·Ī³Ī·Ļ„Ī® HTML5 video</a>.",
+ "mwe-embedplayer-fullscreen-tip": "Ī Ī±Ļ„Ī®ĻƒĻ„Īµ <b>F11</b> Ī³Ī¹Ī± ĪµĪ½Ī±Ī»Ī»Ī±Ī³Ī® <i>Ļ„ĪæĻ… Ļ€ĻĪæĪ³ĻĪ¬Ī¼Ī¼Ī±Ļ„ĪæĻ‚ Ļ€ĪµĻĪ¹Ī®Ī³Ī·ĻƒĪ·Ļ‚</i> ĻƒĪµ Ļ€Ī»Ī®ĻĪ· ĪæĪøĻŒĪ½Ī·",
+ "mwe-embedplayer-fullscreen-tip-osx": "Ī Ī±Ļ„Ī®ĻƒĻ„Īµ <b>shift āŒ˜ F</b> Ī³Ī¹Ī± Ļ„Ī·Ī½ ĪµĪ½Ī±Ī»Ī»Ī±Ī³Ī® Ļ€Ī»Ī®ĻĪæĻ…Ļ‚ ĪæĪøĻŒĪ½Ī·Ļ‚",
+ "mwe-embedplayer-do_not_warn_again": "Ī£Ļ„Īæ Ī¼Ī­Ī»Ī»ĪæĪ½, Ī½Ī± Ī¼Ī·Ī½ ĪµĪ¼Ļ†Ī±Ī½Ī¹ĻƒĻ„ĪµĪÆ Ī±Ļ…Ļ„ĻŒ Ļ„Īæ Ī¼Ī®Ī½Ļ…Ī¼Ī±",
+ "mwe-embedplayer-playerSelect": "Ī›ĪæĪ³Ī¹ĻƒĪ¼Ī¹ĪŗĻŒ Ī±Ī½Ī±Ļ€Ī±ĻĪ±Ī³Ļ‰Ī³Ī®Ļ‚",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Ī”Ī¹Ī±Ī²Ī¬ĻƒĻ„Īµ Ī±Ļ…Ļ„ĻŒ</a> Ļ€ĻĪ¹Ī½ Ī±Ļ€ĻŒ Ļ„Ī·Ī½ ĪµĪ½ĻƒĻ‰Ī¼Ī¬Ļ„Ļ‰ĻƒĪ·.",
+ "mwe-embedplayer-embed_site_or_blog": "Ī•Ī½ĻƒĻ‰Ī¼Ī¬Ļ„Ļ‰ĻƒĪ· ĻƒĻ„Īæ ĻƒĪ¬Ī¹Ļ„ Ī® Ī¼Ļ€Ī»ĪæĪ³Īŗ ĻƒĪ±Ļ‚",
+ "mwe-embedplayer-embed_wiki": "Ī•Ī½ĻƒĻ‰Ī¼Ī±Ļ„ĻŽĻƒĻ„Īµ ĻƒĪµ Ī­Ī½Ī± wiki",
+ "mwe-embedplayer-related_videos": "Ī£Ļ‡ĪµĻ„Ī¹ĪŗĪ¬ Ī²ĪÆĪ½Ļ„ĪµĪæ",
+ "mwe-embedplayer-seeking": "Ī±Ī½Ī±Ī¶Ī®Ļ„Ī·ĻƒĪ·",
+ "mwe-embedplayer-video-h264": "H.264 video",
+ "mwe-embedplayer-video-webm": "WebM Ī²ĪÆĪ½Ļ„ĪµĪæ",
+ "mwe-embedplayer-video-flv": "Flash video",
+ "mwe-embedplayer-video-ogg": "Ogg video",
+ "mwe-embedplayer-video-audio": "Ogg audio",
+ "mwe-embedplayer-audio-mpeg": "MPEG Ī®Ļ‡ĪæĻ‚",
+ "mwe-embedplayer-video-3gp": "3GP Ī²ĪÆĪ½Ļ„ĪµĪæ",
+ "mwe-embedplayer-video-mpeg": "MPEG Ī²ĪÆĪ½Ļ„ĪµĪæ",
+ "mwe-embedplayer-video-msvideo": "AVI Ī²ĪÆĪ½Ļ„ĪµĪæ",
+ "mwe-embedplayer-missing-source": "Ī”ĪµĪ½ Ī²ĻĪ­ĪøĪ·ĪŗĪµ Ļ€Ī·Ī³Ī® Ī²ĪÆĪ½Ļ„ĪµĪæ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/en-gb.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/en-gb.json
new file mode 100644
index 00000000..ca785d7b
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/en-gb.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Shirayuki"
+ ]
+ },
+ "mwe-embedplayer-do_not_warn_again": "In future, do not show this message"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/en.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/en.json
new file mode 100644
index 00000000..91041ffc
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/en.json
@@ -0,0 +1,95 @@
+{
+ "@metadata": {
+ "authors": []
+ },
+ "mwe-embedplayer-credit-title": "Title: $1",
+ "mwe-embedplayer-credit-date": "Date: $1",
+ "mwe-embedplayer-credit-author": "Author: $1",
+ "mwe-embedplayer-nocredits": "No credits available",
+ "mwe-embedplayer-loading_plugin": "Loading plugin ...",
+ "mwe-embedplayer-select_playback": "Set playback preference",
+ "mwe-embedplayer-link_back": "Link back",
+ "mwe-embedplayer-error_swap_vid": "Error: mwEmbed was unable to swap the video tag for the mwEmbed interface",
+ "mwe-embedplayer-add_to_end_of_sequence": "Add to end of sequence",
+ "mwe-embedplayer-missing_video_stream": "The video file for this stream is missing",
+ "mwe-embedplayer-play_clip": "Play clip",
+ "mwe-embedplayer-pause_clip": "Pause clip",
+ "mwe-embedplayer-volume_control": "Volume control",
+ "mwe-embedplayer-player_options": "Player options",
+ "mwe-embedplayer-timed_text": "Timed text",
+ "mwe-embedplayer-player_fullscreen": "Fullscreen",
+ "mwe-embedplayer-next_clip_msg": "Play next clip",
+ "mwe-embedplayer-prev_clip_msg": "Play previous clip",
+ "mwe-embedplayer-current_clip_msg": "Continue playing this clip",
+ "mwe-embedplayer-seek_to": "Seek $1",
+ "mwe-embedplayer-paused": "paused",
+ "mwe-embedplayer-download_segment": "Download selection:",
+ "mwe-embedplayer-download_full_video": "Download full video file:",
+ "mwe-embedplayer-download_full_audio": "Download full audio file:",
+ "mwe-embedplayer-download_right_click": "To download, right click and select <i>Save link as...</i>",
+ "mwe-embedplayer-download_clip": "Download video",
+ "mwe-embedplayer-download_text": "Download text",
+ "mwe-embedplayer-download": "Download",
+ "mwe-embedplayer-share": "Share",
+ "mwe-embedplayer-credits": "Credits",
+ "mwe-embedplayer-about-library": "About Kaltura player",
+ "mwe-embedplayer-about-library-desc": "Kaltura's HTML5 media library enables you to take advantage of the HTML5 &lt;video&gt; and &lt;audio&gt; tags today with a consistent player interface across all major browsers.\n\n[$1 More about the Kaltura player library].",
+ "mwe-embedplayer-clip_linkback": "Clip source page",
+ "mwe-embedplayer-choose_player": "Choose video player",
+ "mwe-embedplayer-no-player": "No player available for $1",
+ "mwe-embedplayer-share_this_video": "Share this video",
+ "mwe-embedplayer-share_this_audio": "Share this audio file",
+ "mwe-embedplayer-video_credits": "Video credits",
+ "mwe-embedplayer-no-video_credits": "No credits available",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura open source video platform",
+ "mwe-embedplayer-menu_btn": "Menu",
+ "mwe-embedplayer-close_btn": "Close",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC player",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg player",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3 player",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AAC player",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 player",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM player",
+ "mwe-embedplayer-ogg-player-vp9Native": "HTML5 VP9 player",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Generic Ogg plugin",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "VLC for iOS app",
+ "mwe-embedplayer-ogg-player-IEWebMPrompt": "IE WebM plugin downloader",
+ "mwe-embedplayer-ogg-player-ogvJsPlayer": "JavaScript Ogg player",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime plugin",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura player",
+ "mwe-embedplayer-ogg-player-selected": "(selected)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "For a better video playback experience we recommend an <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">HTML5 video browser</a>.",
+ "mwe-embedplayer-download-warn": "No compatible in-browser player was detected: for in-browser playback, please download the [$1 latest Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "Press <b>F11</b> toggle <i>web browser</i> fullscreen",
+ "mwe-embedplayer-fullscreen-tip-osx": "Press <b>shift āŒ˜ F</b> to toggle fullscreen",
+ "mwe-embedplayer-do_not_warn_again": "In the future, do not show this message",
+ "mwe-embedplayer-playerSelect": "Players",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Read this</a> before embedding.",
+ "mwe-embedplayer-embed_site_or_blog": "Embed on a page",
+ "mwe-embedplayer-embed_wiki": "Embed on a wiki",
+ "mwe-embedplayer-related_videos": "Related videos",
+ "mwe-embedplayer-seeking": "seeking",
+ "mwe-embedplayer-buffering": "buffering",
+ "mwe-embedplayer-video-h264": "H.264 video",
+ "mwe-embedplayer-video-webm": "WebM video",
+ "mwe-embedplayer-video-flv": "Flash video",
+ "mwe-embedplayer-video-ogg": "Ogg video",
+ "mwe-embedplayer-video-audio": "Ogg audio",
+ "mwe-embedplayer-audio-mpeg": "MPEG audio",
+ "mwe-embedplayer-video-3gp": "3GP video",
+ "mwe-embedplayer-video-mpeg": "MPEG video",
+ "mwe-embedplayer-video-msvideo": "AVI video",
+ "mwe-embedplayer-missing-source": "No source video was found",
+ "mwe-embedplayer-vlcapp-intro": "In order to view videos from this site on an iPhone or iPad, you need the free $1.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "VLC app",
+ "mwe-embedplayer-vlcapp-downloadapp": "Download the VLC app from the App Store",
+ "mwe-embedplayer-vlcapp-openvideo": "Open this video in the VLC app",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Download this video",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "To play videos on this site, you need the free VLC app. Install now?",
+ "mwe-embedplayer-iewebmprompt-intro": "Oops! One more thing before you can play this video...",
+ "mwe-embedplayer-iewebmprompt-linktext": "Install WebM media components for Microsoft Internet Explorer",
+ "mwe-embedplayer-iewebmprompt-outro": "Reload this page after installing."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/eo.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/eo.json
new file mode 100644
index 00000000..bb972255
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/eo.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Yekrats"
+ ]
+ },
+ "mwe-embedplayer-player_fullscreen": "Plenekrana",
+ "mwe-embedplayer-download_full": "Elŝuti kompletan filmetan dosieron:",
+ "mwe-embedplayer-download_clip": "Elŝuti filmeton",
+ "mwe-embedplayer-download": "Elŝuti",
+ "mwe-embedplayer-share": "Konigi",
+ "mwe-embedplayer-share_this_video": "Konigi ĉi tiun filmeton",
+ "mwe-embedplayer-menu_btn": "Menuo",
+ "mwe-embedplayer-close_btn": "Fermi",
+ "mwe-embedplayer-ogg-player-selected": "(elektita)",
+ "mwe-embedplayer-playerSelect": "Ludantoj",
+ "mwe-embedplayer-read_before_embed": "Bonvolu legi la <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">sekurecajn notojn pri ekstera enkorpigado</a> antaÅ­ fakte enkorpigado!",
+ "mwe-embedplayer-embed_site_or_blog": "Enmeti en paĝo",
+ "mwe-embedplayer-related_videos": "Rilataj videoj",
+ "mwe-embedplayer-seeking": "serĉante",
+ "mwe-embedplayer-buffering": "bufrante",
+ "mwe-embedplayer-video-h264": "H.264 video",
+ "mwe-embedplayer-video-flv": "Flash video",
+ "mwe-embedplayer-video-ogg": "Ogg video",
+ "mwe-embedplayer-video-audio": "Ogg aŭdiaĵo",
+ "mwe-embedplayer-missing-source": "Neniu fonta video estis trovita"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/es.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/es.json
new file mode 100644
index 00000000..8dd70f29
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/es.json
@@ -0,0 +1,99 @@
+{
+ "@metadata": {
+ "authors": [
+ "Armando-Martin",
+ "Crazymadlover",
+ "Translationista",
+ "Fitoschido",
+ "Koavf",
+ "Macofe",
+ "Laurenslimb"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "TĆ­tulo: $1",
+ "mwe-embedplayer-credit-date": "Fecha: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-nocredits": "No hay crƩditos disponibles",
+ "mwe-embedplayer-loading_plugin": "Cargando plugin ...",
+ "mwe-embedplayer-select_playback": "Configurar preferencia de reproducciĆ³n",
+ "mwe-embedplayer-link_back": "Referir a enlace",
+ "mwe-embedplayer-error_swap_vid": "Error: mwEmbed no pudo sustituĆ­r la etiqueta de vĆ­deo por la interfaz mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Agregar al final de la secuencia",
+ "mwe-embedplayer-missing_video_stream": "Falta el archivo de vĆ­deo de esta transmisiĆ³n",
+ "mwe-embedplayer-play_clip": "Reproducir clip",
+ "mwe-embedplayer-pause_clip": "Pausar clip",
+ "mwe-embedplayer-volume_control": "Control de volumen",
+ "mwe-embedplayer-player_options": "Opciones de reproductor",
+ "mwe-embedplayer-timed_text": "Texto sincronizado",
+ "mwe-embedplayer-player_fullscreen": "Pantalla completa",
+ "mwe-embedplayer-next_clip_msg": "Reproducir siguiente clip",
+ "mwe-embedplayer-prev_clip_msg": "Reproducir clip anterior",
+ "mwe-embedplayer-current_clip_msg": "Continuar reproduciendo este clip",
+ "mwe-embedplayer-seek_to": "Buscar $1",
+ "mwe-embedplayer-paused": "en pausa",
+ "mwe-embedplayer-download_segment": "Descargar selecciĆ³n:",
+ "mwe-embedplayer-download_full_video": "Descargar archivo de video completo:",
+ "mwe-embedplayer-download_right_click": "Para descargar, haga click con el botĆ³n derecho del ratĆ³n y seleccione <i>Guardar enlace como...</i>",
+ "mwe-embedplayer-download_clip": "Descargar archivo",
+ "mwe-embedplayer-download_text": "Descargar texto",
+ "mwe-embedplayer-download": "Descargar",
+ "mwe-embedplayer-share": "Compartir",
+ "mwe-embedplayer-credits": "CrƩditos",
+ "mwe-embedplayer-about-library": "Acerca del reproductor Kaltura",
+ "mwe-embedplayer-about-library-desc": "La biblioteca HTMl5 de Kaltura permite utilizar etiquetas de <code><nowiki><video></nowiki></code> y <code><nowiki><audio></nowiki></code> ahora con una interfaz de reproductor consistente en los navegadores mƔs usados.\n\t\n[$1 MƔs acerca de la biblioteca del reproductor Kalltura].",
+ "mwe-embedplayer-clip_linkback": "PƔgina fuente de clip",
+ "mwe-embedplayer-choose_player": "Elegir reproductor de video",
+ "mwe-embedplayer-no-player": "No hay ningĆŗn reproductor disponible para $1",
+ "mwe-embedplayer-share_this_video": "Compartir este video",
+ "mwe-embedplayer-video_credits": "CrƩditos de video",
+ "mwe-embedplayer-no-video_credits": "No hay crƩditos disponibles",
+ "mwe-embedplayer-kaltura-platform-title": "Plataforma de vĆ­deo de cĆ³digo abierto Kaltura",
+ "mwe-embedplayer-menu_btn": "MenĆŗ",
+ "mwe-embedplayer-close_btn": "Cerrar",
+ "mwe-embedplayer-ogg-player-vlc-player": "Reproductor de VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Reproductor HTML5 Ogg",
+ "mwe-embedplayer-ogg-player-mp3Native": "Reproductor de MP3 HTML5",
+ "mwe-embedplayer-ogg-player-aacNative": "Reproductor de AAC HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "Reproductor HTML5 H.264",
+ "mwe-embedplayer-ogg-player-webmNative": "Reproductor WebM HTML5",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Plugin Ogg genƩrico",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "aplicaciĆ³n VLC para iOS",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Plugin QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Reproductor Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(seleccionado)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Para una mejor experiencia de reproducciĆ³n de vĆ­deo recomendamos un <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">navegador de vĆ­deo html5</a>.",
+ "mwe-embedplayer-download-warn": "Se detectĆ³ un reproductor no compatible con el explorador: para reproducciĆ³n integrada en el navegador descargue la [$1 Ćŗltima versiĆ³n de Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "Presione <b>F11</b> para activar o desactivar la pantalla completa del <i>navegador web</i>",
+ "mwe-embedplayer-fullscreen-tip-osx": "Presione <b>shift āŒ˜ F</b> para activar o desactivarl a pantalla completa",
+ "mwe-embedplayer-do_not_warn_again": "No mostrar este mensaje en el futuro.",
+ "mwe-embedplayer-playerSelect": "Reproductores",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Leer esto</a> antes de insertar.",
+ "mwe-embedplayer-embed_site_or_blog": "Insertar en una pƔgina",
+ "mwe-embedplayer-embed_wiki": "Incrustar en un wiki",
+ "mwe-embedplayer-related_videos": "Videos relacionados",
+ "mwe-embedplayer-seeking": "buscando",
+ "mwe-embedplayer-buffering": "cargando en el bĆŗfer",
+ "mwe-embedplayer-video-h264": "Video H.264",
+ "mwe-embedplayer-video-webm": "VĆ­deo WebM",
+ "mwe-embedplayer-video-flv": "Video Flash",
+ "mwe-embedplayer-video-ogg": "Video Ogg",
+ "mwe-embedplayer-video-audio": "Audio Ogg",
+ "mwe-embedplayer-audio-mpeg": "Audio MPEG",
+ "mwe-embedplayer-video-3gp": "VĆ­deo 3GP",
+ "mwe-embedplayer-video-mpeg": "VĆ­deo MPEG",
+ "mwe-embedplayer-video-msvideo": "VĆ­deo AVI",
+ "mwe-embedplayer-missing-source": "No se encontrĆ³ ningĆŗn vĆ­deo de origen.",
+ "mwe-embedplayer-vlcapp-intro": "Para ver videos de este sitio en un iPhone o iPad, necesitas la $1 gratuita.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "aplicaciĆ³n VLC",
+ "mwe-embedplayer-vlcapp-downloadapp": "Descargar la aplicaciĆ³n VLC desde la App Store",
+ "mwe-embedplayer-vlcapp-openvideo": "Abre este video en la aplicaciĆ³n VLC",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Descarga este video",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "Para reproducir videos en este sitio, necesitas la aplicaciĆ³n gratuita VLC. ĀæInstalar ahora?",
+ "mwe-embedplayer-iewebmprompt-intro": "Ā”Espere! Una cosa mĆ”s antes de que pueda ver este vĆ­deo...",
+ "mwe-embedplayer-iewebmprompt-linktext": "Instalar componentes multimedia de WebM para Microsoft Internet Explorer",
+ "mwe-embedplayer-iewebmprompt-outro": "Recargar esta pĆ”gina despuĆ©s de la instalaciĆ³n."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/et.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/et.json
new file mode 100644
index 00000000..587c9515
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/et.json
@@ -0,0 +1,48 @@
+{
+ "@metadata": {
+ "authors": [
+ "Avjoska",
+ "Pikne"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Pealkiri: $1",
+ "mwe-embedplayer-credit-date": "KuupƤev: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-loading_plugin": "Lisa laadimine...",
+ "mwe-embedplayer-missing_video_stream": "Selle voogedastuse jaoks puudub videofail.",
+ "mwe-embedplayer-play_clip": "Esita lƵik",
+ "mwe-embedplayer-pause_clip": "Peata lƵik",
+ "mwe-embedplayer-volume_control": "Helitugevuse seadmine",
+ "mwe-embedplayer-player_options": "Esitaja seaded",
+ "mwe-embedplayer-timed_text": "Ajastatud tekst",
+ "mwe-embedplayer-player_fullscreen": "TƤisekraan",
+ "mwe-embedplayer-paused": "peatatud",
+ "mwe-embedplayer-download_full": "Laadi alla terve videofail:",
+ "mwe-embedplayer-download_clip": "Laadi video alla",
+ "mwe-embedplayer-download_text": "Laadi tekst alla",
+ "mwe-embedplayer-download": "Laadi alla",
+ "mwe-embedplayer-share": "Jaga",
+ "mwe-embedplayer-credits": "Autorsus",
+ "mwe-embedplayer-clip_linkback": "LƵigu alliklehekĆ¼lg",
+ "mwe-embedplayer-choose_player": "Videoesitaja valimine",
+ "mwe-embedplayer-share_this_video": "Selle video jagamine",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura avatud lƤhtekoodiga videoplatvorm",
+ "mwe-embedplayer-menu_btn": "MenĆ¼Ć¼",
+ "mwe-embedplayer-close_btn": "Sule",
+ "mwe-embedplayer-do_not_warn_again": "Edaspidi Ƥra seda sƵnumit nƤita",
+ "mwe-embedplayer-playerSelect": "Esitajad",
+ "mwe-embedplayer-embed_site_or_blog": "Kasuta lehekĆ¼ljel",
+ "mwe-embedplayer-embed_wiki": "Kasuta vikis",
+ "mwe-embedplayer-seeking": "otsimine",
+ "mwe-embedplayer-buffering": "puhverdamine",
+ "mwe-embedplayer-video-h264": "H.264-video",
+ "mwe-embedplayer-video-webm": "WebM-video",
+ "mwe-embedplayer-video-flv": "Flash-video",
+ "mwe-embedplayer-video-ogg": "Ogg-video",
+ "mwe-embedplayer-video-audio": "Ogg-helifail",
+ "mwe-embedplayer-audio-mpeg": "MPEG-helifail",
+ "mwe-embedplayer-video-3gp": "3GP-video",
+ "mwe-embedplayer-video-mpeg": "MPEG-video",
+ "mwe-embedplayer-video-msvideo": "AVI-video",
+ "mwe-embedplayer-missing-source": "Allikvideot ei leitud."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/eu.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/eu.json
new file mode 100644
index 00000000..ccfe919d
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/eu.json
@@ -0,0 +1,17 @@
+{
+ "@metadata": {
+ "authors": [
+ "Subi"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Izenburua: $1",
+ "mwe-embedplayer-credit-date": "Data: $1",
+ "mwe-embedplayer-credit-author": "Egilea: $1",
+ "mwe-embedplayer-player_fullscreen": "Pantaila osoan",
+ "mwe-embedplayer-paused": "pausatua",
+ "mwe-embedplayer-download": "Jaitsi",
+ "mwe-embedplayer-share": "Partekatu",
+ "mwe-embedplayer-credits": "Kredituak",
+ "mwe-embedplayer-menu_btn": "Menua",
+ "mwe-embedplayer-close_btn": "Itxi"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fa.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fa.json
new file mode 100644
index 00000000..1f4f2fe9
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fa.json
@@ -0,0 +1,87 @@
+{
+ "@metadata": {
+ "authors": [
+ "Armin1392",
+ "Ebraminio",
+ "Mjbmr",
+ "Pouyana",
+ "Reza1615",
+ "Ł¾Ų§Ł†Ų§Ų±ŁˆŁ…Ų§"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Ų¹Ł†ŁˆŲ§Ł†: $1",
+ "mwe-embedplayer-credit-date": "ŲŖŲ§Ų±ŪŒŲ®: $1",
+ "mwe-embedplayer-credit-author": "Ł†ŁˆŪŒŲ³Ł†ŲÆŁ‡ = $1",
+ "mwe-embedplayer-nocredits": "Ł‡ŪŒŚ† Ų§Ų¹ŲŖŲØŲ§Ų±ŪŒ ŲÆŲ± ŲÆŲ³ŲŖŲ±Ų³ Ł†ŪŒŲ³ŲŖ",
+ "mwe-embedplayer-loading_plugin": "ŲÆŲ± Ų­Ų§Ł„ ŲØŲ§Ų±ŚÆŪŒŲ±ŪŒ Ų§ŁŲ²Ų§ŪŒŁ‡...",
+ "mwe-embedplayer-select_playback": "ŲŖŁ†ŲøŪŒŁ… Ų§ŁˆŁ„ŁˆŪŒŲŖ Ł¾Ų®Ų“",
+ "mwe-embedplayer-link_back": "Ł¾ŪŒŁˆŁ†ŲÆ ŲØŲ§Ų²ŚÆŲ“ŲŖ",
+ "mwe-embedplayer-error_swap_vid": "Ų®Ų·Ų§: Ų§Ł…ā€ŒŲÆŲØŁ„ŪŒŁˆā€ŒŲ§ŁŁ…ŲØŲÆ Ł‚Ų§ŲÆŲ± ŲØŁ‡ ŲŖŲ¹ŁˆŪŒŲ¶ ŲØŲ±Ś†Ų³ŲØ ŁŪŒŁ„Ł… ŲØŲ±Ų§ŪŒ Ų±Ų§ŲØŲ· Ų§Ł…ā€ŒŲÆŲØŁ„ŪŒŁˆā€ŒŲ§ŁŁ…ŲØŲÆ Ł†ŲØŁˆŲÆ",
+ "mwe-embedplayer-add_to_end_of_sequence": "Ų§Ų¶Ų§ŁŁ‡ Ś©Ų±ŲÆŁ† ŲØŁ‡ Ų§Ł†ŲŖŁ‡Ų§ŪŒ ŲÆŁ†ŲØŲ§Ł„Ł‡",
+ "mwe-embedplayer-missing_video_stream": "Ł¾ŁˆŲ“Ł‡ ŲŖŲµŁˆŪŒŲ±ŪŒ ŲØŲ±Ų§ŪŒ Ų§ŪŒŁ† Ų¬Ų±ŪŒŲ§Ł† Ų§Ų² ŲÆŲ³ŲŖ Ł…ŪŒā€ŒŲ±ŁˆŲÆ",
+ "mwe-embedplayer-play_clip": "Ł†Ų“Ų§Ł† ŲÆŲ§ŲÆŁ† Ś©Ł„ŪŒŁ¾",
+ "mwe-embedplayer-pause_clip": "ŲŖŁˆŁ‚Ł Ś©Ł„ŪŒŁ¾",
+ "mwe-embedplayer-volume_control": "ŲŖŁ†ŲøŪŒŁ… ŲµŲÆŲ§",
+ "mwe-embedplayer-player_options": "ŚÆŲ²ŪŒŁ†Ł‡ā€ŒŁ‡Ų§ŪŒ ŲÆŲ³ŲŖŚÆŲ§Ł‡ Ł¾Ų®Ų“",
+ "mwe-embedplayer-timed_text": "Ł…ŲŖŁ† Ų²Ł…Ų§Ł†ā€ŒŲØŁ†ŲÆŪŒā€Œ Ų“ŲÆŁ‡",
+ "mwe-embedplayer-player_fullscreen": "ŲŖŁ…Ų§Ł… ŲµŁŲ­Ł‡",
+ "mwe-embedplayer-next_clip_msg": "Ł†Ł…Ų§ŪŒŲ“ Ś©Ł„ŪŒŁ¾ ŲØŲ¹ŲÆŪŒ",
+ "mwe-embedplayer-prev_clip_msg": "Ł†Ł…Ų§ŪŒŲ“ Ś©Ł„ŪŒŁ¾ Ł‚ŲØŁ„ŪŒ",
+ "mwe-embedplayer-current_clip_msg": "Ų§ŲÆŲ§Ł…Ł‡ ŲÆŲ§ŲÆŁ† Ł†Ł…Ų§ŪŒŲ“ Ś©Ł„ŪŒŁ¾",
+ "mwe-embedplayer-seek_to": "ŲÆŲ± Ų¬Ų³ŲŖŲ¬ŁˆŪŒ $1",
+ "mwe-embedplayer-paused": "Ł…Ś©Ų«",
+ "mwe-embedplayer-download_segment": "Ų§Ł†ŲŖŲ®Ų§ŲØ ŲÆŲ§Ł†Ł„ŁˆŲÆĖ",
+ "mwe-embedplayer-download_full": "ŲÆŲ±ŪŒŲ§ŁŲŖ Ł¾Ų±ŁˆŁ†ŲÆŁ‡Ł” ŁˆŪŒŲÆŪŒŁˆŪŒŪŒ Ś©Ų§Ł…Ł„:",
+ "mwe-embedplayer-download_right_click": "ŲØŲ±Ų§ŪŒ ŲØŲ§Ų±ŚÆŪŒŲ±ŪŒŲŒ Ś©Ł„ŪŒŚ© Ų±Ų§Ų³ŲŖ Ś©Ł†ŪŒŲÆ Łˆ Ų§ŪŒŁ† ŚÆŲ²ŪŒŁ†Ł‡ Ų±Ų§ Ų§Ł†ŲŖŲ®Ų§ŲØ Ś©Ł†ŪŒŲÆ<i>Save link as...</i>",
+ "mwe-embedplayer-download_clip": "ŲÆŲ±ŪŒŲ§ŁŲŖ ŁˆŪŒŲÆŪŒŁˆ",
+ "mwe-embedplayer-download_text": "ŲÆŲ±ŪŒŲ§ŁŲŖ Ł…ŲŖŁ†",
+ "mwe-embedplayer-download": "ŲÆŲ±ŪŒŲ§ŁŲŖ",
+ "mwe-embedplayer-share": "ŲØŁ‡ Ų§Ų“ŲŖŲ±Ų§Ś© ŚÆŲ°Ų§Ų“ŲŖŁ†",
+ "mwe-embedplayer-credits": "Ų§Ų¹ŲŖŲØŲ§Ų±",
+ "mwe-embedplayer-about-library": "ŲÆŲ±ŲØŲ§Ų±Ł‡Ł”ā€ŒŚ©Ų§Ł„ŲŖŲ±Ų§ Ł¾Ł„ŪŒŲ±",
+ "mwe-embedplayer-about-library-desc": "Ś©ŲŖŲ§ŲØŲ®Ų§Ł†Ł‡ Ų±Ų³Ų§Ł†Ł‡ Ų§Ś†ā€ŒŲŖŪŒā€ŒŲ§Ł…ā€ŒŲ§Ł„Ūµ Ś©Ų§Ł„ŲŖŁŲ±Ų§ ŲØŁ‡ Ų“Ł…Ų§Ų±Ų§ Ł‚Ų§ŲÆŲ± ŲØŁ‡ Ł…Ų²ŪŒŲŖ Ų§Ś†ā€ŒŲŖŪŒā€ŒŲ§Ł…ā€ŒŲ§Ł„ŪµŁˆ Ų§Ł„ā€ŒŲŖŪŒŲ›ŁˆŪŒŲÆŪŒŁˆŁˆ Ų¬ŪŒā€ŒŲŖŪŒŲ› Łˆ Ų§Ł„ā€ŒŲŖŪŒŲ›ŲµŁˆŲŖŪŒā€ŒŁˆŲ¬ŪŒā€ŒŲŖŪŒŲ›ŲØŲ±Ś†Ų³ŲØŁ‡Ų§ŪŒ Ų§Ł…Ų±ŁˆŲ² ŲØŲ§ Ų±Ų§ŲØŲ· ŲÆŲ³ŲŖŚÆŲ§Ł‡ Ł¾Ų®Ų“ Ų³Ų§Ų²ŚÆŲ§Ų± ŲÆŲ± Ų³Ų±Ų§Ų³Ų± Ł‡Ł…Ł‡ Ł…Ų±ŁˆŲ±ŚÆŲ±Ł‡Ų§ŪŒ Ų§ŲµŁ„ŪŒ Ł…ŪŒā€ŒŚ©Ł†ŲÆ.\n[ $1 ŲØŪŒŲ“ŲŖŲ± ŲÆŲ±ŲØŲ§Ų±Ł‡ Ś©ŲŖŲ§ŲØŲ®Ų§Ł†Ł‡ Ł¾Ų®Ų“ Ś©Ų§Ł„ŲŖŁŲ±Ų§].",
+ "mwe-embedplayer-clip_linkback": "ŲµŁŲ­Ł‡Ł” Ł…Ł†ŲØŲ¹ Ś©Ł„ŪŒŁ¾",
+ "mwe-embedplayer-choose_player": "Ų§Ł†ŲŖŲ®Ų§ŲØ ŲÆŲ³ŲŖŚÆŲ§Ł‡ Ł¾Ų®Ų“ ŁˆŪŒŲÆŪŒŁˆ",
+ "mwe-embedplayer-no-player": "ŲÆŲ³ŲŖŲ±Ų³ŪŒ ŲØŁ‡ Ł¾Ų®Ų“ā€ŒŚ©Ł†Ł†ŲÆŁ‡ ŁˆŲ¬ŁˆŲÆ Ł†ŲÆŲ§Ų±ŲÆ $1",
+ "mwe-embedplayer-share_this_video": "Ų§ŪŒŁ† ŲŖŲµŁˆŪŒŲ± Ų±Ų§ ŲØŁ‡ Ų§Ų“ŲŖŲ±Ų§Ś© ŚÆŲ°Ų§Ų±ŪŒŲÆ",
+ "mwe-embedplayer-video_credits": "Ų§Ų¹ŲŖŲØŲ§Ų±Ų§ŲŖ ŁˆŪŒŲÆŪŒŁˆ",
+ "mwe-embedplayer-no-video_credits": "Ł‡ŪŒŚ† Ų§Ų¹ŲŖŲØŲ§Ų±ŪŒ ŲÆŲ± ŲÆŲ³ŲŖŲ±Ų³ Ł†ŪŒŲ³ŲŖ",
+ "mwe-embedplayer-kaltura-platform-title": "Ł…Ł†ŲØŲ¹ ŲØŲ§Ų² ŲµŲ­Ł†Ł‡ ŁˆŪŒŲÆŪŒŁˆ Ś©Ų§Ł„ŲŖŁŲ±Ų§",
+ "mwe-embedplayer-menu_btn": "ŁŁ‡Ų±Ų³ŲŖ",
+ "mwe-embedplayer-close_btn": "ŲØŲ³ŲŖŁ†",
+ "mwe-embedplayer-ogg-player-vlc-player": "ŁˆŪŒā€ŒŲ§Ł„ā€ŒŲ³ŪŒ Ł¾Ł„ŪŒŲ±",
+ "mwe-embedplayer-ogg-player-oggNative": "Ł¾Ų®Ų“ ŲµŁˆŲŖŪŒ Ų§Ś†ā€ŒŲŖŪŒā€ŒŲ§Ł…ā€ŒŲ§Ł„Ūµ",
+ "mwe-embedplayer-ogg-player-mp3Native": "Ł¾Ų®Ų“ Ų§Ł…ā€ŒŁ¾ŪŒā€ŒŲŖŲ±ŪŒ Ų§Ś†ā€ŒŲŖŪŒā€ŒŲ§Ł…ā€ŒŲ§Ł„Ūµ",
+ "mwe-embedplayer-ogg-player-aacNative": "Ł¾Ų®Ų“ Ų§ŪŒā€ŒŲ³ŪŒā€ŒŲ³ŪŒ Ų§Ś†ā€ŒŲŖŪŒā€ŒŲ§Ł…ā€ŒŲ§Ł„Ūµ",
+ "mwe-embedplayer-ogg-player-h264Native": "Ł¾Ų®Ų“ Ų§Ś†.Ū²Ū¶Ū“ Ų§Ś†ā€ŒŲŖŪŒā€ŒŲ§Ł…ā€ŒŲ§Ł„Ūµ",
+ "mwe-embedplayer-ogg-player-webmNative": "Ł¾Ų®Ų“ ŁˆŲØā€ŒŲ§Ł… Ų§Ś†ā€ŒŲŖŪŒā€ŒŲ§Ł…ā€ŒŲ§Ł„Ūµ",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Ł¾Ł„Ų§ŚÆŪŒŁ† ŲµŁˆŲŖŪŒ Ų¹Ł…ŁˆŁ…ŪŒ",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Ł¾Ł„Ų§ŚÆŪŒŁ† Ų²Ł…Ų§Ł† Ų²ŁˆŲÆ",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "Ų§Ś©ŲŖŪŒŁˆā€ŒŲ§ŪŒŚ©Ų³ Ų²Ł…Ų§Ł† Ų²ŁˆŲÆ",
+ "mwe-embedplayer-ogg-player-flowplayer": "Ł¾Ų®Ų“ Ų¬Ų±ŪŒŲ§Ł†",
+ "mwe-embedplayer-ogg-player-kplayer": "Ł¾Ų®Ų“ Ś©Ų§Ł„ŲŖŲ±Ų§",
+ "mwe-embedplayer-ogg-player-selected": "(Ų§Ł†ŲŖŲ®Ų§ŲØ Ų“ŲÆŁ‡)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "Ų§Łā€ŒŲ§Ł…ā€ŒŲŖŪŒā€ŒŚ©Ų§ ŁŁ„Ų“ ŁˆŁŲ±ŲØŪŒŲ³",
+ "mwe-embedplayer-for_best_experience": "ŲØŲ±Ų§ŪŒ ŪŒŚ© ŲŖŲ¬Ų±ŲØŁ‡ Ł¾Ų®Ų“ ŁˆŪŒŲÆŪŒŁˆ ŲØŁ‡ŲŖŲ±ŲŒ Ł…Ų§ ŪŒŚ© <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">HTML5 video browser</a> Ų±Ų§ ŲŖŁˆŲµŪŒŁ‡ Ł…ŪŒā€ŒŚ©Ł†ŪŒŁ….",
+ "mwe-embedplayer-download-warn": "Ł‡ŪŒŚ† Ł¾Ų®Ų“ ŲÆŲ± Ł…Ų±ŁˆŲ±ŚÆŲ± Ų³Ų§Ų²ŚÆŲ§Ų±ŪŒ Ų“Ł†Ų§Ų³Ų§ŪŒŪŒ Ł†Ų“ŲÆ: ŲØŲ±Ų§ŪŒ Ł¾Ų®Ų“ ŲÆŲ± Ł…Ų±ŁˆŲ±ŚÆŲ±ŲŒ Ł„Ų·ŁŲ§Ł‹ [ $1 Ų¢Ų®Ų±ŪŒŁ† ŁŲ§ŪŒŲ±ŁŲ§Ś©Ų³] Ų±Ų§ ŲÆŲ§Ł†Ł„ŁˆŲÆ Ś©Ł†ŪŒŲÆ",
+ "mwe-embedplayer-fullscreen-tip": "ŁŲ“Ų§Ų± ŲÆŲ§ŲÆŁ† <b>F11</b> ŲÆŚ©Ł…Ł‡ <i> Ł…Ų±ŁˆŲ±ŚÆŲ± ŁˆŲØ </i> ŲŖŁ…Ų§Ł… ŲµŁŲ­Ł‡",
+ "mwe-embedplayer-fullscreen-tip-osx": "ŁŲ“Ų§Ų± ŲÆŲ§ŲÆŁ† <b> Ś©Ł„ŪŒŲÆ Ł…ŲØŲÆŁ„ āŒ˜ F</b> ŲØŁ‡ ŲÆŚ©Ł…Ł‡ ŲŖŁ…Ų§Ł… ŲµŁŲ­Ł‡",
+ "mwe-embedplayer-do_not_warn_again": "ŲÆŲ± Ų¢ŪŒŁ†ŲÆŁ‡ŲŒ Ų§ŪŒŁ† Ł¾ŪŒŲ§Ł… Ų±Ų§ Ł†Ų“Ų§Ł† Ł†ŲÆŁ‡ŪŒŲÆ",
+ "mwe-embedplayer-playerSelect": "ŲØŲ§Ų²ŪŒŚ©Ł†Ų§Ł†",
+ "mwe-embedplayer-read_before_embed": "<ahref=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\"> Ų§ŪŒŁ† Ų±Ų§ </a> Ł‚ŲØŁ„ Ų§Ų² Ų¬Ų§Ų³Ų§Ų²ŪŒ ŲØŲ®ŁˆŲ§Ł†ŪŒŲÆ.",
+ "mwe-embedplayer-embed_site_or_blog": "Ł‚Ų±Ų§Ų± ŲÆŲ§ŲÆŁ† ŲÆŲ± ŪŒŚ© ŲµŁŲ­Ł‡",
+ "mwe-embedplayer-embed_wiki": "Ł‚Ų±Ų§Ų± ŲÆŲ§ŲÆŁ† ŲÆŲ± ŪŒŚ© ŁˆŪŒŚ©ŪŒ",
+ "mwe-embedplayer-related_videos": "Ł…Ų±ŲŖŲØŲ· Ų“ŲÆŁ† ŁˆŪŒŲÆŪŒŁˆā€ŒŁ‡Ų§",
+ "mwe-embedplayer-seeking": "ŲÆŲ± Ų­Ų§Ł„ Ł¾ŪŒŚÆŲ±ŲÆ",
+ "mwe-embedplayer-buffering": "ŲÆŲ± Ų­Ų§Ł„ ŲØŲ§ŁŲ±",
+ "mwe-embedplayer-video-h264": "ŁˆŪŒŲÆŪŒŁˆ Ų§Ś†.Ū²Ū¶Ū“",
+ "mwe-embedplayer-video-webm": "ŁˆŪŒŲÆŪŒŁˆ ŁˆŲØā€ŒŲ§Ł…",
+ "mwe-embedplayer-video-flv": "ŁŁ„Ų“ ŁˆŪŒŲÆŪŒŁˆ",
+ "mwe-embedplayer-video-ogg": "ŲµŁˆŲŖŪŒ ŲŖŲµŁˆŪŒŲ±ŪŒ",
+ "mwe-embedplayer-video-audio": "Ų¢Ł‡Ł†ŚÆ ŲµŁˆŲŖŪŒ",
+ "mwe-embedplayer-audio-mpeg": "Ų§Ł…ā€ŒŁ¾ŪŒā€ŒŲ§ŪŒā€ŒŲ¬ŪŒ ŲµŁˆŲŖŪŒ",
+ "mwe-embedplayer-video-3gp": "ŁˆŪŒŲÆŪŒŁˆ Ū³ā€ŒŲ¬ŪŒā€ŒŁ¾ŪŒ",
+ "mwe-embedplayer-video-mpeg": "ŁˆŪŒŲÆŪŒŁˆ Ų§Ł…ā€ŒŁ¾ŪŒā€ŒŲ§ŪŒā€ŒŲ¬ŪŒ",
+ "mwe-embedplayer-video-msvideo": "ŁˆŪŒŲÆŪŒŁˆ Ų§ŪŒā€ŒŁˆŪŒā€ŒŲ¢ŪŒ",
+ "mwe-embedplayer-missing-source": "Ł‡ŪŒŚ† Ł…Ł†ŲØŲ¹ ŁˆŪŒŲÆŲ¦ŁˆŪŒŪŒ Ł¾ŪŒŲÆŲ§ Ł†Ų“ŲÆ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fi.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fi.json
new file mode 100644
index 00000000..21ac8482
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fi.json
@@ -0,0 +1,41 @@
+{
+ "@metadata": {
+ "authors": [
+ "Crt",
+ "Nedergard",
+ "Nike",
+ "Silvonen",
+ "Tofu II",
+ "MrTapsa"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Otsikko: $1",
+ "mwe-embedplayer-credit-date": "PƤivƤmƤƤrƤ: $1",
+ "mwe-embedplayer-credit-author": "TekijƤ: $1",
+ "mwe-embedplayer-loading_plugin": "Ladataan liitƤnnƤistƤ...",
+ "mwe-embedplayer-player_options": "Soittimen asetukset",
+ "mwe-embedplayer-timed_text": "Ajastettu teksti",
+ "mwe-embedplayer-player_fullscreen": "Koko nƤyttƶ",
+ "mwe-embedplayer-download_full_video": "Lataa koko videotiedosto:",
+ "mwe-embedplayer-download_full_audio": "Lataa koko ƤƤnitiedosto:",
+ "mwe-embedplayer-download_clip": "Lataa video",
+ "mwe-embedplayer-download_text": "Lataa teksti",
+ "mwe-embedplayer-download": "Lataa",
+ "mwe-embedplayer-share": "Jaa",
+ "mwe-embedplayer-about-library": "Tietoja Kaltura-soittimesta",
+ "mwe-embedplayer-share_this_video": "Jaa tƤmƤ video",
+ "mwe-embedplayer-share_this_audio": "Jaa tƤmƤ ƤƤnitiedosto",
+ "mwe-embedplayer-menu_btn": "Valikko",
+ "mwe-embedplayer-close_btn": "Sulje",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura-soitin",
+ "mwe-embedplayer-ogg-player-selected": "(valittu)",
+ "mwe-embedplayer-for_best_experience": "Parempaa videotoistokokemusta varten suosituksena on selain, joka <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">tukee HTML5-videota</a>.",
+ "mwe-embedplayer-video-h264": "H.264-video",
+ "mwe-embedplayer-video-webm": "WebM-video",
+ "mwe-embedplayer-video-flv": "Flash-video",
+ "mwe-embedplayer-video-ogg": "Ogg-video",
+ "mwe-embedplayer-video-3gp": "3GP-video",
+ "mwe-embedplayer-video-mpeg": "MPEG-video",
+ "mwe-embedplayer-video-msvideo": "AVI-video"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fr.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fr.json
new file mode 100644
index 00000000..c7877923
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fr.json
@@ -0,0 +1,97 @@
+{
+ "@metadata": {
+ "authors": [
+ "Brunoperel",
+ "Crochet.david",
+ "Gomoko",
+ "IAlex",
+ "Nnemo",
+ "Peter17",
+ "Windes"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titre : $1",
+ "mwe-embedplayer-credit-date": "Date : $1",
+ "mwe-embedplayer-credit-author": "Auteur : $1",
+ "mwe-embedplayer-nocredits": "Aucun crƩdit disponible",
+ "mwe-embedplayer-loading_plugin": "chargement du greffon ...",
+ "mwe-embedplayer-select_playback": "DƩfinir les prƩfƩrences de lecture",
+ "mwe-embedplayer-link_back": "Lien retour",
+ "mwe-embedplayer-error_swap_vid": "Erreur : mv_embed n'a pas rƩussi Ơ Ʃchanger l'attribut de la vidƩo pour l'interface mv_embed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Ajouter Ơ la fin de la sƩquence",
+ "mwe-embedplayer-missing_video_stream": "Le fichier vidƩo pour ce flux est manquant",
+ "mwe-embedplayer-play_clip": "Lire le clip",
+ "mwe-embedplayer-pause_clip": "Mettre le clip en pause",
+ "mwe-embedplayer-volume_control": "ContrƓle du volume",
+ "mwe-embedplayer-player_options": "Options du lecteur",
+ "mwe-embedplayer-timed_text": "Texte synchronisƩ",
+ "mwe-embedplayer-player_fullscreen": "Plein Ć©cran",
+ "mwe-embedplayer-next_clip_msg": "Lire le clip suivant",
+ "mwe-embedplayer-prev_clip_msg": "Lire le clip prƩcƩdent",
+ "mwe-embedplayer-current_clip_msg": "Poursuivre la lecture de ce clip",
+ "mwe-embedplayer-seek_to": "Atteindre $1",
+ "mwe-embedplayer-paused": "en pause",
+ "mwe-embedplayer-download_segment": "TƩlƩcharger la sƩlection :",
+ "mwe-embedplayer-download_full_video": "TĆ©lĆ©charger le fichier de la vidĆ©o complĆØte :",
+ "mwe-embedplayer-download_right_click": "Pour tƩlƩcharger, cliquez-droit et sƩlectionnez <i>Enregistrer la cible du lien sous...</i>",
+ "mwe-embedplayer-download_clip": "TƩlƩcharger la vidƩo",
+ "mwe-embedplayer-download_text": "TƩlƩcharger le texte",
+ "mwe-embedplayer-download": "TƩlƩcharger",
+ "mwe-embedplayer-share": "Partager",
+ "mwe-embedplayer-credits": "CrƩdits",
+ "mwe-embedplayer-about-library": "ƀ propos du lecteur Kaltura",
+ "mwe-embedplayer-about-library-desc": "La bibliothĆØque HTML5 de Kaltura vous permet de profiter des balises HTML5 <code><nowiki><video></nowiki></code> et <code><nowiki><audio></nowiki></code> dĆØs Ć  prĆ©sent avec un lecteur et une interface compatibles avec tous les principaux navigateurs.\n\t\n[$1 Pour en savoir plus sur la bibliothĆØque de lecture Kaltura].",
+ "mwe-embedplayer-clip_linkback": "Page source du clip",
+ "mwe-embedplayer-choose_player": "Choisir le lecteur vidƩo",
+ "mwe-embedplayer-no-player": "Aucun lecteur disponible pour $1",
+ "mwe-embedplayer-share_this_video": "Partager cette vidƩo",
+ "mwe-embedplayer-share_this_audio": "Partager ce fichier audio",
+ "mwe-embedplayer-video_credits": "CrƩdits de la vidƩo",
+ "mwe-embedplayer-no-video_credits": "Aucun crƩdit disponible",
+ "mwe-embedplayer-kaltura-platform-title": "Plateforme vidƩo en source ouverte Kaltura",
+ "mwe-embedplayer-menu_btn": "Menu",
+ "mwe-embedplayer-close_btn": "Fermer",
+ "mwe-embedplayer-ogg-player-vlc-player": "Lecteur VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Lecteur Ogg HTML5",
+ "mwe-embedplayer-ogg-player-mp3Native": "Lecteur MP3 HTML5",
+ "mwe-embedplayer-ogg-player-aacNative": "Lecteur AAC HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "Lecteur H.264 HTML5",
+ "mwe-embedplayer-ogg-player-webmNative": "Lecteur WebM HTML5",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Module gƩnƩrique Ogg",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "VLC pour application iOS",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Module QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "ActiveX QuickTime",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Lecteur Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(sƩlectionnƩ)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Pour un meilleur visionnage de la vidƩo, nous recommandons un <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">navigateur vidƩo HTML5</a>.",
+ "mwe-embedplayer-download-warn": "Aucun navigateur web compatible dĆ©tectĆ©: pour une lecteur intĆ©grĆ© au navigateur, veuillez tĆ©lĆ©charger la [$1 derniĆØre version de Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "Appuyez sur <b>F11</b> pour basculer le <i>navigateur web</i> en mode plein Ć©cran",
+ "mwe-embedplayer-fullscreen-tip-osx": "Appuyez sur <b>maj āŒ˜ F</b> pour basculer en plein Ć©cran",
+ "mwe-embedplayer-do_not_warn_again": "Ne plus afficher ce message Ć  l'avenir",
+ "mwe-embedplayer-playerSelect": "Lecteurs",
+ "mwe-embedplayer-read_before_embed": "Veuillez <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">lire ceci</a> avant de procƩder !",
+ "mwe-embedplayer-embed_site_or_blog": "IntƩgrer dans une page",
+ "mwe-embedplayer-embed_wiki": "IntƩgrƩ dans un wiki",
+ "mwe-embedplayer-related_videos": "VidƩos associƩes",
+ "mwe-embedplayer-seeking": "recherche",
+ "mwe-embedplayer-buffering": "mise en mƩmoire tampon",
+ "mwe-embedplayer-video-h264": "vidƩo H.264",
+ "mwe-embedplayer-video-webm": "VidƩo WebM",
+ "mwe-embedplayer-video-flv": "vidƩo Flash",
+ "mwe-embedplayer-video-ogg": "vidƩo Ogg",
+ "mwe-embedplayer-video-audio": "Audio Ogg",
+ "mwe-embedplayer-audio-mpeg": "Audio MPEG",
+ "mwe-embedplayer-video-3gp": "VidƩo 3GP",
+ "mwe-embedplayer-video-mpeg": "VidƩo MPEG",
+ "mwe-embedplayer-video-msvideo": "VidƩo AVI",
+ "mwe-embedplayer-missing-source": "Aucune source vidƩo n'a ƩtƩ trouvƩe.",
+ "mwe-embedplayer-vlcapp-intro": "Afin de visualiser les vidƩos de ce site sur un iPhone ou un iPad, vous avez besoin de $1, gratuite.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "Application VLC",
+ "mwe-embedplayer-vlcapp-downloadapp": "TĆ©lĆ©charger lā€™application VLC depuis lā€™App Store",
+ "mwe-embedplayer-vlcapp-openvideo": "Ouvrir cette vidĆ©o dans lā€™application VLC",
+ "mwe-embedplayer-vlcapp-downloadvideo": "TƩlƩcharger cette vidƩo",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "Pour jouer des vidĆ©os sur ce site, vous avez besoin de lā€™application gratuite VLC. Lā€™installer maintenantā€Æ?"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/frp.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/frp.json
new file mode 100644
index 00000000..d70988ea
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/frp.json
@@ -0,0 +1,76 @@
+{
+ "@metadata": {
+ "authors": [
+ "ChrisPtDe"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titro : $1",
+ "mwe-embedplayer-credit-date": "DĆ¢ta : $1",
+ "mwe-embedplayer-credit-author": "Ɣtor : $1",
+ "mwe-embedplayer-nocredits": "Gins de crĆØdit disponiblo",
+ "mwe-embedplayer-loading_plugin": "Chargement du modulo dā€™ĆØxtension ...",
+ "mwe-embedplayer-select_playback": "DĆØfenir les prĆØferences de lĆØctura",
+ "mwe-embedplayer-link_back": "Lim retƓrn",
+ "mwe-embedplayer-error_swap_vid": "ƈrror : mv_embed at pas reussi a ĆØchangiĆ©r la balisa de la vidĆØĆ“ por lā€™entĆØrface mv_embed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Apondre a la fin de la sĆØquence",
+ "mwe-embedplayer-missing_video_stream": "Lo fichiĆ©r vidĆØĆ“ por cĆ©l flux est manquent",
+ "mwe-embedplayer-play_clip": "LiƩre lo clipe",
+ "mwe-embedplayer-pause_clip": "Betar lo clipe en pousa",
+ "mwe-embedplayer-volume_control": "ContrƓlo du volumo",
+ "mwe-embedplayer-player_options": "ChouĆØx du liĆ©sor",
+ "mwe-embedplayer-timed_text": "TĆØxto sincronisĆ¢",
+ "mwe-embedplayer-player_fullscreen": "Plen ĆØcran",
+ "mwe-embedplayer-next_clip_msg": "LiƩre lo clipe aprƩs",
+ "mwe-embedplayer-prev_clip_msg": "LiƩre lo clipe devant",
+ "mwe-embedplayer-current_clip_msg": "Porsiuvre la lĆØctura de ceti clipe",
+ "mwe-embedplayer-seek_to": "AvengiƩr $1",
+ "mwe-embedplayer-paused": "en pousa",
+ "mwe-embedplayer-download_segment": "TĆØlĆØchargiĆ©r lo chouĆØx :",
+ "mwe-embedplayer-download_full": "TĆØlĆØchargiĆ©r lo fichiĆ©r vidĆØĆ“ complĆØt :",
+ "mwe-embedplayer-download_right_click": "Por tĆØlĆØchargiĆ©r, clicĆ¢d-drĆŖt et puĆ©s chouĆØsĆ©ssĆ©d <i>Encartar la ciba du lim desot...</i>",
+ "mwe-embedplayer-download_clip": "TĆØlĆØchargiĆ©r la vidĆØĆ“",
+ "mwe-embedplayer-download_text": "TĆØlĆØchargiĆ©r lo tĆØxto",
+ "mwe-embedplayer-download": "TĆØlĆØchargiĆ©r",
+ "mwe-embedplayer-share": "PartagiƩr",
+ "mwe-embedplayer-credits": "CrĆØdits",
+ "mwe-embedplayer-about-library": "Sur lo liƩsor Kaltura",
+ "mwe-embedplayer-clip_linkback": "PĆ¢ge sĆ“rsa du clipe",
+ "mwe-embedplayer-choose_player": "ChouĆØsir lo liĆ©sor vidĆØĆ“",
+ "mwe-embedplayer-no-player": "Gins de liƩsor disponiblo por $1",
+ "mwe-embedplayer-share_this_video": "PartagiĆ©r ceta vidĆØĆ“",
+ "mwe-embedplayer-video_credits": "CrĆØdits de la vidĆØĆ“",
+ "mwe-embedplayer-no-video_credits": "Gins de crĆØdit disponiblo",
+ "mwe-embedplayer-kaltura-platform-title": "PlatafĆ“rma vidĆØĆ“ a sĆ“rsa uvĆØrta Kaltura",
+ "mwe-embedplayer-menu_btn": "Menu",
+ "mwe-embedplayer-close_btn": "CllƓre",
+ "mwe-embedplayer-ogg-player-vlc-player": "LiƩsor VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "LiƩsor Ogg HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "LiƩsor H.264 HTML5",
+ "mwe-embedplayer-ogg-player-webmNative": "LiƩsor WebM HTML5",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Modulo dā€™ĆØxtension gĀ·ĆØnĆØrico Ogg",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Modulo dā€™ĆØxtension QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "ActiveX QuickTime",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "LiƩsor Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(chouĆØsi)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-fullscreen-tip": "ApoyĆ©d dessus <b>F11</b> por bascular lo <i>navigator vouĆØbe</i> en plen ĆØcran",
+ "mwe-embedplayer-fullscreen-tip-osx": "ApoyĆ©d dessus <b>granta lĆØtra (''shift'') āŒ˜ F</b> por bascular en plen ĆØcran",
+ "mwe-embedplayer-do_not_warn_again": "Pas mĆ©s fĆ¢re vĆŖre cĆ©l mĆØssĆ¢jo a lā€™avegnir.",
+ "mwe-embedplayer-playerSelect": "LiƩsors",
+ "mwe-embedplayer-read_before_embed": "VolyĆ©d <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">liĆ©re cen</a> devant quā€™apondre !",
+ "mwe-embedplayer-embed_site_or_blog": "Apondre a una pĆ¢ge",
+ "mwe-embedplayer-related_videos": "VidĆØĆ“s associyĆŖs",
+ "mwe-embedplayer-seeking": "rechĆØrche",
+ "mwe-embedplayer-buffering": "misa en mĆØmouĆØre tampon",
+ "mwe-embedplayer-video-h264": "VidĆØĆ“ H.264",
+ "mwe-embedplayer-video-webm": "VidĆØĆ“ WebM",
+ "mwe-embedplayer-video-flv": "VidĆØĆ“ Flash",
+ "mwe-embedplayer-video-ogg": "VidĆØĆ“ Ogg",
+ "mwe-embedplayer-video-audio": "ƔdiĆ“ Ogg",
+ "mwe-embedplayer-audio-mpeg": "ƔdiĆ“ MPEG",
+ "mwe-embedplayer-video-3gp": "VidĆØĆ“ 3GP",
+ "mwe-embedplayer-video-mpeg": "VidĆØĆ“ MPEG",
+ "mwe-embedplayer-video-msvideo": "VidĆØĆ“ AVI",
+ "mwe-embedplayer-missing-source": "Niona sĆ“rsa vidĆØĆ“ at Ć©tĆ¢ trovĆ¢."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fy.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fy.json
new file mode 100644
index 00000000..7c57dd3e
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/fy.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Robin0van0der0vliet"
+ ]
+ },
+ "mwe-embedplayer-player_fullscreen": "Folsleinskerm",
+ "mwe-embedplayer-close_btn": "Slute"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ga.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ga.json
new file mode 100644
index 00000000..1333c22d
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ga.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ"
+ ]
+ },
+ "mwe-embedplayer-close_btn": "DĆŗn"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/gl.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/gl.json
new file mode 100644
index 00000000..252f08a2
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/gl.json
@@ -0,0 +1,96 @@
+{
+ "@metadata": {
+ "authors": [
+ "ToliƱo",
+ "Elisardojm"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "TĆ­tulo: $1",
+ "mwe-embedplayer-credit-date": "Data: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-nocredits": "Non hai crƩditos dispoƱibles",
+ "mwe-embedplayer-loading_plugin": "Cargando o complemento...",
+ "mwe-embedplayer-select_playback": "Configurar as preferencias de reproduciĆ³n",
+ "mwe-embedplayer-link_back": "LigazĆ³n de volta",
+ "mwe-embedplayer-error_swap_vid": "Erro: mwEmbed foi incapaz de cambiar a etiqueta do vĆ­deo para a interface mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Engadir ao final da secuencia",
+ "mwe-embedplayer-missing_video_stream": "Falta o ficheiro de vĆ­deo para ese fluxo",
+ "mwe-embedplayer-play_clip": "Reproducir o vĆ­deo",
+ "mwe-embedplayer-pause_clip": "PĆ³r o vĆ­deo en pausa",
+ "mwe-embedplayer-volume_control": "Control do volume",
+ "mwe-embedplayer-player_options": "OpciĆ³ns do reprodutor",
+ "mwe-embedplayer-timed_text": "Texto sincronizado",
+ "mwe-embedplayer-player_fullscreen": "Pantalla completa",
+ "mwe-embedplayer-next_clip_msg": "Reproducir o seguinte vĆ­deo",
+ "mwe-embedplayer-prev_clip_msg": "Reproducir o vĆ­deo anterior",
+ "mwe-embedplayer-current_clip_msg": "Continuar a reproduciĆ³n deste vĆ­deo",
+ "mwe-embedplayer-seek_to": "Buscar $1",
+ "mwe-embedplayer-paused": "en pausa",
+ "mwe-embedplayer-download_segment": "Descargar a selecciĆ³n:",
+ "mwe-embedplayer-download_full_video": "Descargar o ficheiro de vĆ­deo completo:",
+ "mwe-embedplayer-download_full_audio": "Descargar o ficheiro de son completo:",
+ "mwe-embedplayer-download_right_click": "Para descargar, faga clic dereito e seleccione <i>Gardar a ligazĆ³n como...</i>",
+ "mwe-embedplayer-download_clip": "Descargar o vĆ­deo",
+ "mwe-embedplayer-download_text": "Descargar o texto",
+ "mwe-embedplayer-download": "Descargar",
+ "mwe-embedplayer-share": "Compartir",
+ "mwe-embedplayer-credits": "CrƩditos",
+ "mwe-embedplayer-about-library": "Acerca do reprodutor Kaltura",
+ "mwe-embedplayer-about-library-desc": "A biblioteca HTML5 do Kaltura permite sacar proveito das etiquetas <code><nowiki><video></nowiki></code> e <code><nowiki><audio></nowiki></code> do HTML5 cun reprodutor e unha interface compatibles cos principais navegadores.\n\t\n[$1 MĆ”is informaciĆ³n sobre a biblioteca do reprodutor Kaltura].",
+ "mwe-embedplayer-clip_linkback": "PƔxina de orixe do vƭdeo",
+ "mwe-embedplayer-choose_player": "Escolla o reprodutor de vĆ­deo",
+ "mwe-embedplayer-no-player": "Non hai ningĆŗn reprodutor dispoƱible para $1",
+ "mwe-embedplayer-share_this_video": "Compartir este vĆ­deo",
+ "mwe-embedplayer-share_this_audio": "Compartir este ficheiro de son",
+ "mwe-embedplayer-video_credits": "CrƩditos do vƭdeo",
+ "mwe-embedplayer-no-video_credits": "Non hai crƩditos dispoƱibles",
+ "mwe-embedplayer-kaltura-platform-title": "Plataforma de vĆ­deo de cĆ³digo aberto Kaltura",
+ "mwe-embedplayer-menu_btn": "MenĆŗ",
+ "mwe-embedplayer-close_btn": "Pechar",
+ "mwe-embedplayer-ogg-player-vlc-player": "Reprodutor VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Reprodutor Ogg HTML5",
+ "mwe-embedplayer-ogg-player-mp3Native": "Reprodutor MP3 HTML5",
+ "mwe-embedplayer-ogg-player-aacNative": "Reprodutor AAC HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "Reprodutor H.264 HTML5",
+ "mwe-embedplayer-ogg-player-webmNative": "Reprodutor WebM HTML5",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Complemento xenƩrico Ogg",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "VLC para aplicaciĆ³n iOS",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Complemento QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "ActiveX QuickTime",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Reprodutor Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(seleccionado)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Para unha mellor experiencia de reproduciĆ³n de vĆ­deo recomendamos un <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">navegador de vĆ­deo HTML5</a>.",
+ "mwe-embedplayer-download-warn": "Non se detectou ningĆŗn reprodutor integrado compatible co navegador: Para ter unha mellor experiencia de reproduciĆ³n de vĆ­deo recomendamos a [$1 Ćŗltima versiĆ³n do Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "Prema <b>F11</b> para activar ou desactivar a pantalla completa do <i>navegador web</i>",
+ "mwe-embedplayer-fullscreen-tip-osx": "Prema <b>maiĆŗs āŒ˜ F</b> para activar ou desactivar a pantalla completa",
+ "mwe-embedplayer-do_not_warn_again": "Non mostrar esta mensaxe no futuro.",
+ "mwe-embedplayer-playerSelect": "Reprodutores",
+ "mwe-embedplayer-read_before_embed": "Por favor, <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">olle isto</a> antes da inserciĆ³n.",
+ "mwe-embedplayer-embed_site_or_blog": "Integrar nunha pƔxina",
+ "mwe-embedplayer-embed_wiki": "Integrar nun wiki",
+ "mwe-embedplayer-related_videos": "VĆ­deos relacionados",
+ "mwe-embedplayer-seeking": "procurando",
+ "mwe-embedplayer-buffering": "cargando no bĆŗfer",
+ "mwe-embedplayer-video-h264": "VĆ­deo H.264",
+ "mwe-embedplayer-video-webm": "VĆ­deo WebM",
+ "mwe-embedplayer-video-flv": "VĆ­deo Flash",
+ "mwe-embedplayer-video-ogg": "VĆ­deo Ogg",
+ "mwe-embedplayer-video-audio": "Son Ogg",
+ "mwe-embedplayer-audio-mpeg": "Son MPEG",
+ "mwe-embedplayer-video-3gp": "VĆ­deo 3gp",
+ "mwe-embedplayer-video-mpeg": "VĆ­deo MPEG",
+ "mwe-embedplayer-video-msvideo": "VĆ­deo AVI",
+ "mwe-embedplayer-missing-source": "Non se atopou o vĆ­deo de orixe.",
+ "mwe-embedplayer-vlcapp-intro": "Para ver vĆ­deos deste sitio nun iPhone ou iPad, necesita a $1 gratuĆ­ta.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "AplicaciĆ³n VLC",
+ "mwe-embedplayer-vlcapp-downloadapp": "Descargar a aplicaciĆ³n VLC desde a App Store",
+ "mwe-embedplayer-vlcapp-openvideo": "Abrir este vĆ­deo na aplicaciĆ³n VLC",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Descargar este vĆ­deo",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "Para reproducir vĆ­deos neste sitio, necesita a aplicaciĆ³n gratuĆ­ta VLC. Instalar agora?",
+ "mwe-embedplayer-iewebmprompt-intro": "Oops! Unha cousa mƔis antes de que poida ver este vƭdeo...",
+ "mwe-embedplayer-iewebmprompt-linktext": "Instalar compoƱentes multimedia de WebM para Microsoft Internet Explorer",
+ "mwe-embedplayer-iewebmprompt-outro": "Recargar esta pĆ”xina despois da instalaciĆ³n."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/grc.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/grc.json
new file mode 100644
index 00000000..c85efb15
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/grc.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Crazymadlover"
+ ]
+ },
+ "mwe-embedplayer-credit-date": "į¼©Ī¼ĪµĻĪæĪ¼Ī·Ī½ĪÆĪ±: $1"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/gsw.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/gsw.json
new file mode 100644
index 00000000..129b03cc
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/gsw.json
@@ -0,0 +1,80 @@
+{
+ "@metadata": {
+ "authors": [
+ "Als-ChlƤmens",
+ "Als-Holder"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titel: $1",
+ "mwe-embedplayer-credit-date": "Datum: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-loading_plugin": "Am Lade vum Plugin ...",
+ "mwe-embedplayer-select_playback": "Yystellige fir s Abspile setze",
+ "mwe-embedplayer-link_back": "Link retur",
+ "mwe-embedplayer-error_swap_vid": "FƤhler: mv_embed het s Video-Tag fir d mv_embed-Oberflechi nit chenne uustusche",
+ "mwe-embedplayer-add_to_end_of_sequence": "Am Ƅnd vum Abschnitt yyfiege",
+ "mwe-embedplayer-missing_video_stream": "D Videodatei fir dƤƤ Strang fƤhlt",
+ "mwe-embedplayer-play_clip": "Clip abspile",
+ "mwe-embedplayer-pause_clip": "Clip aahalte",
+ "mwe-embedplayer-volume_control": "Yystellig fir d Lutsterki",
+ "mwe-embedplayer-player_options": "Yystellige fir s Abspilprogramm",
+ "mwe-embedplayer-timed_text": "Ƅchtzyt-Text",
+ "mwe-embedplayer-player_fullscreen": "Vollbildschrim",
+ "mwe-embedplayer-next_clip_msg": "Dr negscht Clip abspile",
+ "mwe-embedplayer-prev_clip_msg": "Dr vorig Clip abspile",
+ "mwe-embedplayer-current_clip_msg": "DƤƤ Clip wyter abspile",
+ "mwe-embedplayer-seek_to": "$1 sueche",
+ "mwe-embedplayer-paused": "pausiert",
+ "mwe-embedplayer-download_segment": "Uuswahl zum Abelade:",
+ "mwe-embedplayer-download_full": "Di ganz Videodatei abelade:",
+ "mwe-embedplayer-download_right_click": "Zum Abelade druck uf di rƤcht Muustaschte un wehl <i>Link spychere unter...</i> uus",
+ "mwe-embedplayer-download_clip": "Video abelade",
+ "mwe-embedplayer-download_text": "Tekscht abelade",
+ "mwe-embedplayer-download": "Abelade",
+ "mwe-embedplayer-share": "Ufteile",
+ "mwe-embedplayer-credits": "AnerkƤnnige",
+ "mwe-embedplayer-about-library": "Iber dr Kaltura-Player",
+ "mwe-embedplayer-about-library-desc": "D HTML5-Mediebibliothek vu Kaltura macht s megli d Vorteil vu dr beide HTML5-Tags <code><nowiki><video></nowiki></code> un <code><nowiki><audio></nowiki></code> mit eim eiheitlige Player-Interface bi allne fierende Webbrowser z bruche.\n\n[$1 Meh Informatione zue dr HTML5-Mediebibliothek vu Kaltura].",
+ "mwe-embedplayer-clip_linkback": "Clip-QuƤllsyte",
+ "mwe-embedplayer-choose_player": "Videospiler uuswehle",
+ "mwe-embedplayer-no-player": "Fir $1 isch kei Player verfiegbar",
+ "mwe-embedplayer-share_this_video": "Des Video teile",
+ "mwe-embedplayer-video_credits": "Videokredit",
+ "mwe-embedplayer-no-video_credits": "Kei UrheberrƤchtsaagabe verfiegbar",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura Open-Source-Video-Plattform",
+ "mwe-embedplayer-menu_btn": "Uuswahl",
+ "mwe-embedplayer-close_btn": "Zuemache",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC-Player",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg-Player",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264-Player",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM-Player",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Generisch Ogg-Plugin",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime-Plugin",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura-Player",
+ "mwe-embedplayer-ogg-player-selected": "(uusgwehlt)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Fir e besseri Abspilqualitet vu dƤm Video empfƤhle mir:<br /><a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">Firefox 3.5</a>.",
+ "mwe-embedplayer-download-warn": "S Wiidergabeprogramm im Browser isch nit kompatibel. Zume im Browser aaluege, due bitte d [$1 nƶisti Version vo Firefox] abelade.",
+ "mwe-embedplayer-fullscreen-tip": "D Taschte <b>F11</b> drugge, zume uff de Vollbildmodus vum <i>Webbrowsers</i> umzschalte.",
+ "mwe-embedplayer-fullscreen-tip-osx": "D Taschte <b>UMSCHALT āŒ˜ F</b> drugge, zume uff de Vollbildmodus vum <i>Webbrowsers</i> umzschalte.",
+ "mwe-embedplayer-do_not_warn_again": "Die MƤldig ab jetz nĆ¼mm aazeige.",
+ "mwe-embedplayer-playerSelect": "Player",
+ "mwe-embedplayer-read_before_embed": "Bitte lis d <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Sicherheitsnotize iber s Yyfiege</a> voreb Du s wirkli yyfiege tuesch!",
+ "mwe-embedplayer-embed_site_or_blog": "Yybunde in e Syte",
+ "mwe-embedplayer-related_videos": "Verwandti Video",
+ "mwe-embedplayer-seeking": "Am Sueche",
+ "mwe-embedplayer-buffering": "pufferet",
+ "mwe-embedplayer-video-h264": "H.264-Video",
+ "mwe-embedplayer-video-webm": "WebM-Video",
+ "mwe-embedplayer-video-flv": "Flash-Video",
+ "mwe-embedplayer-video-ogg": "Ogg-Video",
+ "mwe-embedplayer-video-audio": "Ogg-Audiodatei",
+ "mwe-embedplayer-audio-mpeg": "MPEG-Audio",
+ "mwe-embedplayer-video-3gp": "3gp-Video",
+ "mwe-embedplayer-video-mpeg": "MPEG-Video",
+ "mwe-embedplayer-video-msvideo": "AVI-Video",
+ "mwe-embedplayer-missing-source": "S isch kei Videoclip gfunde wore."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/he.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/he.json
new file mode 100644
index 00000000..f12abe37
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/he.json
@@ -0,0 +1,83 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "Guycn2",
+ "Inkbug",
+ "YaronSh"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "כו×Ŗ×Ø×Ŗ: $1",
+ "mwe-embedplayer-credit-date": "×Ŗא×Øיך: $1",
+ "mwe-embedplayer-credit-author": "יוצ×Ø: $1",
+ "mwe-embedplayer-nocredits": "אין ק×Øדיטים",
+ "mwe-embedplayer-loading_plugin": "טעינ×Ŗ ×Ŗוהף...",
+ "mwe-embedplayer-select_playback": "הגד×Ø×Ŗ העדפו×Ŗ נגינה",
+ "mwe-embedplayer-link_back": "קישו×Ø ×—×–×Øה",
+ "mwe-embedplayer-error_swap_vid": "שגיאה: mwEmbed לא היה מהוגל להחליף א×Ŗ ×Ŗג הווידאו של ממשק mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "בהוף ה×Øצף",
+ "mwe-embedplayer-missing_video_stream": "קובׄ הווידאו עבו×Ø ×–×Øם זה ×—×”×Ø",
+ "mwe-embedplayer-play_clip": "נגינ×Ŗ ×”×”×Øטון",
+ "mwe-embedplayer-pause_clip": "השהיי×Ŗ ×”×”×Øטון",
+ "mwe-embedplayer-volume_control": "בק×Ø×Ŗ עוצמ×Ŗ השמע",
+ "mwe-embedplayer-player_options": "אפש×Øויו×Ŗ הנגן",
+ "mwe-embedplayer-timed_text": "טקהט מ×Ŗוזמן",
+ "mwe-embedplayer-player_fullscreen": "מהך מלא",
+ "mwe-embedplayer-next_clip_msg": "נגינ×Ŗ ×”×”×Øטון הבא",
+ "mwe-embedplayer-prev_clip_msg": "נגינ×Ŗ ×”×”×Øטון הקודם",
+ "mwe-embedplayer-current_clip_msg": "המשך נגינ×Ŗ ×”×”×Øטון",
+ "mwe-embedplayer-seek_to": "חיפוש $1",
+ "mwe-embedplayer-paused": "מושהה",
+ "mwe-embedplayer-download_segment": "הו×Øד×Ŗ הבחי×Øה:",
+ "mwe-embedplayer-download_full": "להו×Øיד למחשב א×Ŗ קובׄ הווידאו המלא:",
+ "mwe-embedplayer-download_right_click": "כדי להו×Øיד, לחצו בכפ×Ŗו×Ø ×™×ž× ×™ של העכב×Ø ×•×‘×—×Øו באפש×Øו×Ŗ \"שמי×Øה בשם...\" (<i>Save Link As ...</i>)",
+ "mwe-embedplayer-download_clip": "הו×Øד×Ŗ הווידאו",
+ "mwe-embedplayer-download_text": "להו×Øיד למחשב א×Ŗ הטקהט",
+ "mwe-embedplayer-download": "הו×Øדה",
+ "mwe-embedplayer-share": "שי×Ŗוף",
+ "mwe-embedplayer-credits": "×Ŗודו×Ŗ",
+ "mwe-embedplayer-about-library": "על אודו×Ŗ הנגן קלטו×Øה",
+ "mwe-embedplayer-about-library-desc": "הפ×Øיי×Ŗ לנגינ×Ŗ מדיה ב×Ŗקן HTML5 של קלטו×Øה מאפש×Ø×Ŗ לכם להש×Ŗמש בפקודו×Ŗ <code><nowiki><video></nowiki></code> ו־<code><nowiki><audio></nowiki></code> של HTML5 היום עם ממשק קבוע בכל הדפדפנים הנפוצים.\n\n[$1 מידע נוהף על הפ×Øיי×Ŗ נגן המדיה של קלטו×Øה]",
+ "mwe-embedplayer-clip_linkback": "דף המקו×Ø ×©×œ ×”×”×Øטון",
+ "mwe-embedplayer-choose_player": "בחי×Ø×Ŗ נגן וידאו",
+ "mwe-embedplayer-no-player": "הנגן עבו×Ø $1 אינו זמין",
+ "mwe-embedplayer-share_this_video": "שי×Ŗוף ×”×Øט זה",
+ "mwe-embedplayer-video_credits": "יוצ×Øי ×”×”×Øט",
+ "mwe-embedplayer-no-video_credits": "הק×Øדיטים לא זמינים",
+ "mwe-embedplayer-kaltura-platform-title": "פלטפו×Øמ×Ŗ וידאו בקוד פ×Ŗוח של קלטו×Øה",
+ "mwe-embedplayer-menu_btn": "×Ŗפ×Øיט",
+ "mwe-embedplayer-close_btn": "להגו×Ø",
+ "mwe-embedplayer-ogg-player-vlc-player": "נגן VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "נגן Ogg שך HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "נגן H.264 של HTML5",
+ "mwe-embedplayer-ogg-player-webmNative": "נגן WebM של HTML5",
+ "mwe-embedplayer-ogg-player-oggPlugin": "×Ŗוהף Ogg כללי",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "×Ŗוהף QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "נגן קלטו×Øה",
+ "mwe-embedplayer-ogg-player-selected": "(נבח×Ø)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "להצג×Ŗ וידאו משופ×Ø×Ŗ אנחנו ממליצים על <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">דפדפן ש×Ŗומך בווידאו ב־html5</a>.",
+ "mwe-embedplayer-download-warn": "לא נמצא נגן ×Ŗואם בדפדפן: כדי לנגן ב×Ŗוך הדפדפן יש להו×Øיד א×Ŗ [$1 הג×Ø×”×” החדשה ביו×Ŗ×Ø ×©×œ פיי×Øפוקה].",
+ "mwe-embedplayer-fullscreen-tip": "לחצו <b>F11</b> כדי להעבי×Ø ××Ŗ הדפדפן למצב מהך מלא וחז×Øה",
+ "mwe-embedplayer-fullscreen-tip-osx": "לחיצה על <b>shift āŒ˜ F</b> מפעילה מהך מלא",
+ "mwe-embedplayer-do_not_warn_again": "לא להציג א×Ŗ ההודעה הזא×Ŗ שוב",
+ "mwe-embedplayer-playerSelect": "נגנים",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">אנא ק֓×Øאו</a> לפני הטמעה.",
+ "mwe-embedplayer-embed_site_or_blog": "הטמעה בא×Ŗ×Ø ××• בבלוג שלכם",
+ "mwe-embedplayer-embed_wiki": "להטמיע בוויקי",
+ "mwe-embedplayer-related_videos": "×”×Øטונים קשו×Øים",
+ "mwe-embedplayer-seeking": "חיפוש",
+ "mwe-embedplayer-buffering": "אגי×Øה",
+ "mwe-embedplayer-video-h264": "×”×Øט H.264",
+ "mwe-embedplayer-video-webm": "×”×Øט WebM",
+ "mwe-embedplayer-video-flv": "×”×Øט Flash",
+ "mwe-embedplayer-video-ogg": "×”×Øט Ogg",
+ "mwe-embedplayer-video-audio": "שמע Ogg",
+ "mwe-embedplayer-audio-mpeg": "שמע MPEG",
+ "mwe-embedplayer-video-3gp": "×”×Øט 3GP",
+ "mwe-embedplayer-video-mpeg": "×”×Øט MPEG",
+ "mwe-embedplayer-video-msvideo": "×”×Øט AVI",
+ "mwe-embedplayer-missing-source": "×”×”×Øט המקו×Øי לא נמצא"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/hsb.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/hsb.json
new file mode 100644
index 00000000..d52ebb0b
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/hsb.json
@@ -0,0 +1,83 @@
+{
+ "@metadata": {
+ "authors": [
+ "Michawiki"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titul: $1",
+ "mwe-embedplayer-credit-date": "Datum: $1",
+ "mwe-embedplayer-credit-author": "Awtor: $1",
+ "mwe-embedplayer-nocredits": "Žane dÅŗakprajenja k dispoziciji",
+ "mwe-embedplayer-loading_plugin": "tykač so začituje ...",
+ "mwe-embedplayer-select_playback": "Nastajenje za playback stajić",
+ "mwe-embedplayer-link_back": "Wotkaz wrĆ³Ä‡o",
+ "mwe-embedplayer-error_swap_vid": "Zmylk: mv_embed njemĆ³Å¾eÅ”e widejotafličku za powjerch mv_embed wuměnić",
+ "mwe-embedplayer-add_to_end_of_sequence": "Na kĆ³ncu sekwency přidać",
+ "mwe-embedplayer-missing_video_stream": "Widejowa dataja za tutĆ³n prud faluje",
+ "mwe-embedplayer-play_clip": "Klip wothrać",
+ "mwe-embedplayer-pause_clip": "Klip zastajić",
+ "mwe-embedplayer-volume_control": "Regulowanje sylnosće zwuka",
+ "mwe-embedplayer-player_options": "Opcije wothrawaka",
+ "mwe-embedplayer-timed_text": "Synchronizowany tekst",
+ "mwe-embedplayer-player_fullscreen": "Połna wobrazowka",
+ "mwe-embedplayer-next_clip_msg": "Přichodny klip wothrać",
+ "mwe-embedplayer-prev_clip_msg": "Předchadny klip wothrać",
+ "mwe-embedplayer-current_clip_msg": "TutĆ³n klip dale wothrać",
+ "mwe-embedplayer-seek_to": "$1 pytać",
+ "mwe-embedplayer-paused": "zastajeny",
+ "mwe-embedplayer-download_segment": "Wuběr sćahnyć:",
+ "mwe-embedplayer-download_full": "Dospołnu widejowu dataju sćahnyć:",
+ "mwe-embedplayer-download_right_click": "Zo by sćahnył, klikń z prawej tastu a wubjer <i>Wotkaz składować jako...</i>",
+ "mwe-embedplayer-download_clip": "Widejo sćahnyć",
+ "mwe-embedplayer-download_text": "Tekst",
+ "mwe-embedplayer-download": "Sćahnyć",
+ "mwe-embedplayer-share": "DÅŗělić",
+ "mwe-embedplayer-credits": "DÅŗakprajenje",
+ "mwe-embedplayer-about-library": "Wo wothrawaku Kaltura",
+ "mwe-embedplayer-about-library-desc": "Medijowa HTML5-biblioteka Kaltury zmĆ³Å¾nja lěpÅ”iny tafličkow <code><nowiki><video></code> a <code><nowiki><audio></code> dÅŗensa z jednotnym powjerchom wothrawaka ze wŔěmi načolnymi wobhladowakami wužiwać.\n\n[$1 Wjace wo bibliotece wothrawaka Kaltura]",
+ "mwe-embedplayer-clip_linkback": "Å½Ć³rłow strona klipa",
+ "mwe-embedplayer-choose_player": "Widejowy wothrawak wubrać",
+ "mwe-embedplayer-no-player": "Žadyn wothrawak za $1 k dispoziciji",
+ "mwe-embedplayer-share_this_video": "Tute widejo zhromadnje wužiwać",
+ "mwe-embedplayer-video_credits": "DÅŗakprajenja za wutworjenje wideja",
+ "mwe-embedplayer-no-video_credits": "Žane podaća wo awtorach",
+ "mwe-embedplayer-kaltura-platform-title": "Widejoplatforma Kaltura ze zjawneho Å¾Ć³rła",
+ "mwe-embedplayer-menu_btn": "Meni",
+ "mwe-embedplayer-close_btn": "Začinić",
+ "mwe-embedplayer-ogg-player-vlc-player": "Wothrawak VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Wothrawak HTML5 Ogg",
+ "mwe-embedplayer-ogg-player-mp3Native": "Wothrawak HTML5 MP3",
+ "mwe-embedplayer-ogg-player-aacNative": "Wothrawak HTML5 AAC",
+ "mwe-embedplayer-ogg-player-h264Native": "Wothrawak HTML5 H.264",
+ "mwe-embedplayer-ogg-player-webmNative": "Wothrawak za HTML5 WebM",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Tykač Generic Ogg",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Tykač QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "ActiveX QuickTime",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Wothrawak Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(wubrany)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Za lěpÅ”e wothrawanje widejow poručamy <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">widejowobhladowak za HTML 5</a>.",
+ "mwe-embedplayer-download-warn": "Njekompatibelne wothrawak we wobhladowaku namakany: za wothrawanje znutřka wobhladowaka, sćehń proÅ”u [$1 najnowÅ”u wersiju Mozilla Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "TÅ‚Ć³Ä na <b>F11</b>, zo by <i>webwobhladowak</i> do modusa połneje wobrazowki přepinał",
+ "mwe-embedplayer-fullscreen-tip-osx": "StÅ‚Ć³Ä <b>UMSCH āŒ˜ F</b>, zo by do modusa połneje wobrazowki přepinył",
+ "mwe-embedplayer-do_not_warn_again": "W přichodÅŗe tutu zdÅŗělenku wjace njepokazać",
+ "mwe-embedplayer-playerSelect": "Wothrawaki",
+ "mwe-embedplayer-read_before_embed": "ProÅ”u <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">čitaj to</a> do zasadÅŗenja!",
+ "mwe-embedplayer-embed_site_or_blog": "Na stronje zasadÅŗić",
+ "mwe-embedplayer-embed_wiki": "We wikiju zasadÅŗić",
+ "mwe-embedplayer-related_videos": "Přiwuzne wideja",
+ "mwe-embedplayer-seeking": "pyta so",
+ "mwe-embedplayer-buffering": "pufruje so",
+ "mwe-embedplayer-video-h264": "Wideo H.264",
+ "mwe-embedplayer-video-webm": "WebM-widejo",
+ "mwe-embedplayer-video-flv": "Widejo Flash",
+ "mwe-embedplayer-video-ogg": "Ogg-widejo",
+ "mwe-embedplayer-video-audio": "Ogg-awdio",
+ "mwe-embedplayer-audio-mpeg": "MPEG awdio",
+ "mwe-embedplayer-video-3gp": "3GP widejo",
+ "mwe-embedplayer-video-mpeg": "MPEG widejo",
+ "mwe-embedplayer-video-msvideo": "AVI widejo",
+ "mwe-embedplayer-missing-source": "Žane widejo namakane."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/hu.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/hu.json
new file mode 100644
index 00000000..c9c13278
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/hu.json
@@ -0,0 +1,75 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dani",
+ "Misibacsi",
+ "Tacsipacsi",
+ "Csega"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "CĆ­m: $1",
+ "mwe-embedplayer-credit-date": "DƔtum: $1",
+ "mwe-embedplayer-credit-author": "Szerző: $1",
+ "mwe-embedplayer-loading_plugin": "bővĆ­tmĆ©ny betƶltĆ©seā€¦",
+ "mwe-embedplayer-select_playback": "HasznĆ”lt lejĆ”tszĆ³ kivĆ”lasztĆ”sa",
+ "mwe-embedplayer-link_back": "VisszahivatkozƔs",
+ "mwe-embedplayer-error_swap_vid": "Hiba: az mv_embed nem tudta kicserĆ©lni a videĆ³ taget az mv_embed felĆ¼letĆ©re",
+ "mwe-embedplayer-add_to_end_of_sequence": "HozzƔadƔs a szekvencia vƩgƩhez",
+ "mwe-embedplayer-missing_video_stream": "Az adatfolyamhoz tartozĆ³ videofĆ”jl nincs meg",
+ "mwe-embedplayer-play_clip": "Klip lejƔtszƔsa",
+ "mwe-embedplayer-pause_clip": "Klip pillanatƔllj",
+ "mwe-embedplayer-volume_control": "HangerőszabĆ”lyzĆ³",
+ "mwe-embedplayer-player_options": "LejĆ”tszĆ³ beĆ”llĆ­tĆ”sai",
+ "mwe-embedplayer-timed_text": "IdőzĆ­tett szƶveg",
+ "mwe-embedplayer-player_fullscreen": "Teljes kĆ©pernyő",
+ "mwe-embedplayer-next_clip_msg": "Kƶvetkező klip lejĆ”tszĆ”sa",
+ "mwe-embedplayer-prev_clip_msg": "Előző klip lejĆ”tszĆ”sa",
+ "mwe-embedplayer-current_clip_msg": "Klip lejƔtszƔsƔnak folytatƔsa",
+ "mwe-embedplayer-seek_to": "$1 keresƩse",
+ "mwe-embedplayer-paused": "szĆ¼neteltetve",
+ "mwe-embedplayer-download_segment": "KijelƶlƩs letƶltƩse:",
+ "mwe-embedplayer-download_full_video": "Teljes videofƔjl letƶltƩse:",
+ "mwe-embedplayer-download_full_audio": "Teljes audiofƔjl letƶltƩse:",
+ "mwe-embedplayer-download_right_click": "A letƶltĆ©shez kattints jobb gombbal, Ć©s <i>CĆ©l mentĆ©se mĆ”skĆ©ntā€¦</i>",
+ "mwe-embedplayer-download_clip": "VideĆ³ letƶltĆ©se",
+ "mwe-embedplayer-download_text": "Szƶveg letƶltƩse",
+ "mwe-embedplayer-download": "LetƶltƩs",
+ "mwe-embedplayer-share": "MegosztƔs",
+ "mwe-embedplayer-credits": "KĆ©szĆ­tők",
+ "mwe-embedplayer-about-library": "A Kaltura lejĆ”tszĆ³ nĆ©vjegye",
+ "mwe-embedplayer-about-library-desc": "A Kaltura HTML5-ƶs mĆ©dialejĆ”tszĆ³ lehetővĆ© teszi, hogy kihasznĆ”ld a HTML5 <code><nowiki><video></nowiki></code> Ć©s <code><nowiki><audio></nowiki></code> elemeit azonos felĆ¼letet biztonsĆ­tva az ƶsszes lĆ©nyeges bƶngĆ©sző esetĆ©n.\n\t\n[$1 TovĆ”bbi informĆ”ciĆ³ a Kaltura lejĆ”tszĆ³rĆ³l].",
+ "mwe-embedplayer-clip_linkback": "Klip forrƔslapja",
+ "mwe-embedplayer-choose_player": "VideolejĆ”tszĆ³ vĆ”lasztĆ”sa",
+ "mwe-embedplayer-no-player": "Nincs megfelelő lejĆ”tszĆ³ a kƶvetkezőhƶz: $1",
+ "mwe-embedplayer-share_this_video": "VideĆ³ megosztĆ”sa",
+ "mwe-embedplayer-share_this_audio": "AudiofƔjl megosztƔsa",
+ "mwe-embedplayer-video_credits": "A videĆ³ kĆ©szĆ­tői",
+ "mwe-embedplayer-menu_btn": "MenĆ¼",
+ "mwe-embedplayer-close_btn": "BezƔrƔs",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC player",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg lejĆ”tszĆ³",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 lejĆ”tszĆ³",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM-lejĆ”tszĆ³",
+ "mwe-embedplayer-ogg-player-oggPlugin": "ƁltalĆ”nos Ogg bővĆ­tmĆ©ny",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime-bővĆ­tmĆ©ny",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura lejĆ”tszĆ³",
+ "mwe-embedplayer-ogg-player-selected": "(kivƔlasztva)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "A jobb videolejĆ”tszĆ”si Ć©lmĆ©nyhez <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">HTML5-ƶt tĆ”mogatĆ³ bƶngĆ©szőt</a> ajĆ”nlunk.",
+ "mwe-embedplayer-do_not_warn_again": "A jƶvőben ne jelenjen meg ez az Ć¼zenet",
+ "mwe-embedplayer-playerSelect": "LejĆ”tszĆ³k",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Olvasd el ezt</a>, mielőtt beillesztenĆ©d.",
+ "mwe-embedplayer-embed_site_or_blog": "BeƔgyazƔs egy lapra",
+ "mwe-embedplayer-related_videos": "KapcsolĆ³dĆ³ videĆ³k",
+ "mwe-embedplayer-seeking": "keresƩs",
+ "mwe-embedplayer-buffering": "pufferelƩs",
+ "mwe-embedplayer-video-h264": "H.264 videĆ³",
+ "mwe-embedplayer-video-webm": "WebM-videĆ³",
+ "mwe-embedplayer-video-flv": "Flash videĆ³",
+ "mwe-embedplayer-video-ogg": "Ogg videĆ³",
+ "mwe-embedplayer-video-audio": "Ogg hangfƔjl",
+ "mwe-embedplayer-missing-source": "Nem talĆ”lhatĆ³ forrĆ”svideĆ³"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ia.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ia.json
new file mode 100644
index 00000000..94586400
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ia.json
@@ -0,0 +1,79 @@
+{
+ "@metadata": {
+ "authors": [
+ "McDutchie"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titulo: $1",
+ "mwe-embedplayer-credit-date": "Data: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-loading_plugin": "cargamento del plug-in ...",
+ "mwe-embedplayer-select_playback": "Definir preferentia de reproduction",
+ "mwe-embedplayer-link_back": "Retroligamine",
+ "mwe-embedplayer-error_swap_vid": "Error: mv_embed non poteva excambiar le etiquetta de video pro le interfacie mv_embed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Adder al fin del sequentia",
+ "mwe-embedplayer-missing_video_stream": "Le file de video pro iste fluxo es mancante",
+ "mwe-embedplayer-play_clip": "Reproducer clip",
+ "mwe-embedplayer-pause_clip": "Pausar clip",
+ "mwe-embedplayer-volume_control": "Controlo de volumine",
+ "mwe-embedplayer-player_options": "Optiones de reproductor",
+ "mwe-embedplayer-timed_text": "Subtitulos",
+ "mwe-embedplayer-player_fullscreen": "Schermo complete",
+ "mwe-embedplayer-next_clip_msg": "Reproducer sequente clip",
+ "mwe-embedplayer-prev_clip_msg": "Reproducer precedente clip",
+ "mwe-embedplayer-current_clip_msg": "Continuar a reproducer iste clip",
+ "mwe-embedplayer-seek_to": "Ir a $1",
+ "mwe-embedplayer-paused": "in pausa",
+ "mwe-embedplayer-download_segment": "Discargar selection:",
+ "mwe-embedplayer-download_full": "Discargar file de video complete:",
+ "mwe-embedplayer-download_right_click": "Pro discargar, face clic a dextra e selige <i>Immagazinar ligamine como...</i> (Save link as...)",
+ "mwe-embedplayer-download_clip": "Discargar video",
+ "mwe-embedplayer-download_text": "Discargar texto",
+ "mwe-embedplayer-download": "Discargar",
+ "mwe-embedplayer-share": "Divider",
+ "mwe-embedplayer-credits": "Creditos",
+ "mwe-embedplayer-about-library": "A proposito del reproductor Kaltura",
+ "mwe-embedplayer-about-library-desc": "Le bibliotheca multimedia HTML5 de Kaltura te permitte traher avantage del etiquettas HTML5 <code><nowiki><video></nowiki></code> e <code><nowiki><audio></nowiki></code> jam hodie con un interfacie de reproductor consistente trans tote le major navigatores.\n\t\n[$1 Plus a proposito del bibliotheca reproductor Kaltura].",
+ "mwe-embedplayer-clip_linkback": "Pagina de fonte del clip",
+ "mwe-embedplayer-choose_player": "Seliger reproductor de video",
+ "mwe-embedplayer-no-player": "Nulle reproductor disponibile pro $1",
+ "mwe-embedplayer-share_this_video": "Divider iste video",
+ "mwe-embedplayer-video_credits": "Creditos de video",
+ "mwe-embedplayer-no-video_credits": "Nulle credito disponibile",
+ "mwe-embedplayer-kaltura-platform-title": "Platteforma video a codice aperte Kaltura",
+ "mwe-embedplayer-menu_btn": "Menu",
+ "mwe-embedplayer-close_btn": "Clauder",
+ "mwe-embedplayer-ogg-player-vlc-player": "Reproductor VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Reproductor Ogg HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "Reproductor H.264 HTML5",
+ "mwe-embedplayer-ogg-player-webmNative": "Lector WebM HTML5",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Plug-in generic pro Ogg",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Plug-in de QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Le reproductor Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(seligite)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Pro un melior experientia de reproduction de video, nos recommenda:<br /><a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">Firefox 3.5</a>.",
+ "mwe-embedplayer-download-warn": "Nulle lector compatibile esseva detegite in le navigator del web. Pro reproduction in le navigator, per favor discarga le [$1 ultime version de Firefox].",
+ "mwe-embedplayer-fullscreen-tip": "Preme <b>F11</b> pro alternar le <i>navigator del web</i> in plen schermo",
+ "mwe-embedplayer-fullscreen-tip-osx": "Preme <b>shift āŒ˜ F</b> pro alternar plen schermo",
+ "mwe-embedplayer-do_not_warn_again": "In le futuro, non monstrar iste message",
+ "mwe-embedplayer-playerSelect": "Reproductores",
+ "mwe-embedplayer-read_before_embed": "Per favor lege le <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">notas de securitate super incastramento remote</a> ante de incastrar un cosa!",
+ "mwe-embedplayer-embed_site_or_blog": "Incastrar in un pagina",
+ "mwe-embedplayer-related_videos": "Videos connexe",
+ "mwe-embedplayer-seeking": "cercante",
+ "mwe-embedplayer-buffering": "precargamento",
+ "mwe-embedplayer-video-h264": "Video H.264",
+ "mwe-embedplayer-video-webm": "Video WebM",
+ "mwe-embedplayer-video-flv": "Video Flash",
+ "mwe-embedplayer-video-ogg": "Video Ogg",
+ "mwe-embedplayer-video-audio": "Audio Ogg",
+ "mwe-embedplayer-audio-mpeg": "Audio MPEG",
+ "mwe-embedplayer-video-3gp": "Video 3gp",
+ "mwe-embedplayer-video-mpeg": "Video MPEG",
+ "mwe-embedplayer-video-msvideo": "Video AVI",
+ "mwe-embedplayer-missing-source": "Nulle video de origine ha essite trovate."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/id.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/id.json
new file mode 100644
index 00000000..58c68df9
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/id.json
@@ -0,0 +1,76 @@
+{
+ "@metadata": {
+ "authors": [
+ "Farras",
+ "IvanLanin"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Judul: $1",
+ "mwe-embedplayer-credit-date": "Tanggal: $1",
+ "mwe-embedplayer-credit-author": "Pembuat: $1",
+ "mwe-embedplayer-loading_plugin": "memuat pengaya ...",
+ "mwe-embedplayer-select_playback": "Atur preferensi pemutar",
+ "mwe-embedplayer-link_back": "Pranala balik",
+ "mwe-embedplayer-error_swap_vid": "Kesalahan: mv_embed tak dapat menukar tag video untuk antarmuka mv_embed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Tambahkan ke akhir rangkaian",
+ "mwe-embedplayer-missing_video_stream": "Berkas video untuk aliran tidak ditemukan",
+ "mwe-embedplayer-play_clip": "Mainkan klip",
+ "mwe-embedplayer-pause_clip": "Jeda klip",
+ "mwe-embedplayer-volume_control": "Kontrol volume",
+ "mwe-embedplayer-player_options": "Pilihan pemutar",
+ "mwe-embedplayer-timed_text": "Teks berjangka waktu",
+ "mwe-embedplayer-player_fullscreen": "Layar penuh",
+ "mwe-embedplayer-next_clip_msg": "Putar klip berikut",
+ "mwe-embedplayer-prev_clip_msg": "Putar klip sebelumnya",
+ "mwe-embedplayer-current_clip_msg": "Lanjutkan pemutaran klip ini",
+ "mwe-embedplayer-seek_to": "Cari $1",
+ "mwe-embedplayer-paused": "jeda",
+ "mwe-embedplayer-download_segment": "Unduh pilihan:",
+ "mwe-embedplayer-download_full": "Unduh berkas video lengkap:",
+ "mwe-embedplayer-download_right_click": "Untuk mengunduh, klik kanan dan pilih <i>Simpan tautan sebagai...</i>",
+ "mwe-embedplayer-download_clip": "Unduh video",
+ "mwe-embedplayer-download_text": "Unduh teks",
+ "mwe-embedplayer-download": "Unduh",
+ "mwe-embedplayer-share": "Bagikan",
+ "mwe-embedplayer-credits": "Kredit",
+ "mwe-embedplayer-about-library": "About pemutar Kaltura",
+ "mwe-embedplayer-about-library-desc": "Pustaka media HTML5 Kaltura memungkinkan Anda untuk mengambil keuntungan dari tag HTML5 <nowiki><video></nowiki> dan <nowiki><audio></nowiki> dengan antarmuka pemutar yang konsisten di semua peramban utama.\n\n [$1 Selengkapnya tentang pustaka pemutar Kaltura].",
+ "mwe-embedplayer-clip_linkback": "Halaman sumber klip",
+ "mwe-embedplayer-choose_player": "Pilih pemutar video",
+ "mwe-embedplayer-no-player": "Tidak ada pemutar yang tersedia untuk $1",
+ "mwe-embedplayer-share_this_video": "Bagikan video ini",
+ "mwe-embedplayer-video_credits": "Kredit video",
+ "mwe-embedplayer-no-video_credits": "Kredit tidak tersedia",
+ "mwe-embedplayer-kaltura-platform-title": "Platform video terbuka Kaltura",
+ "mwe-embedplayer-menu_btn": "Menu",
+ "mwe-embedplayer-close_btn": "Tutup",
+ "mwe-embedplayer-ogg-player-vlc-player": "Pemutar VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Pemutar Ogg HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "Pemutar H.264 HTML5",
+ "mwe-embedplayer-ogg-player-webmNative": "Pemutar WebM HTML5",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Pengaya generik Ogg",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Pengaya QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "ActiveX QuickTime",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Pemutar Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(dipilih)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Untuk pengalaman pemutaran video yang lebih baik kami menyarankan: <br /><a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">Firefox 3.5</a>.",
+ "mwe-embedplayer-download-warn": "Pemutar dalam peramban yang kompatibel tidak ditemukan. Untuk pemutaran dalam peramban silakan unduh [$1 Firefox terbaru]",
+ "mwe-embedplayer-fullscreen-tip": "Tekan <b>F11</b> untuk beralih ke layar penuh <i>peramban web</i>",
+ "mwe-embedplayer-fullscreen-tip-osx": "Tekan <b>shift āŒ˜ F</b> untuk beralih ke layar penuh",
+ "mwe-embedplayer-do_not_warn_again": "Jangan tampilkan lagi pesan ini",
+ "mwe-embedplayer-playerSelect": "Pemutar",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Baca ini</a> sebelum mengikutkan.",
+ "mwe-embedplayer-embed_site_or_blog": "Sertakan pada suatu halaman",
+ "mwe-embedplayer-related_videos": "Video yang berhubungan",
+ "mwe-embedplayer-seeking": "mencari",
+ "mwe-embedplayer-buffering": "menyinggahkan",
+ "mwe-embedplayer-video-h264": "Video H.264",
+ "mwe-embedplayer-video-webm": "Video WebM",
+ "mwe-embedplayer-video-flv": "Video flash",
+ "mwe-embedplayer-video-ogg": "Video ogg",
+ "mwe-embedplayer-video-audio": "Audio ogg",
+ "mwe-embedplayer-missing-source": "Tidak ada video sumber yang ditemukan."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ilo.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ilo.json
new file mode 100644
index 00000000..b379d2a9
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ilo.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lam-ang"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titulo: $1",
+ "mwe-embedplayer-credit-date": "Petsa: $1",
+ "mwe-embedplayer-credit-author": "Mannurat: $1",
+ "mwe-embedplayer-nocredits": "Awan dagiti pammadayaw a magun-od",
+ "mwe-embedplayer-loading_plugin": "Agikarkarga ti plugin ...",
+ "mwe-embedplayer-select_playback": "Agikabil ti preperensia ti panagy-ayam",
+ "mwe-embedplayer-link_back": "Agisilpo",
+ "mwe-embedplayer-error_swap_vid": "Biddut: Ti mwEmbed ket saan a nakaisukat ti etiketa ti video para iti interface ti mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Inayon idiay gibus ti pangsasarunuan"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/is.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/is.json
new file mode 100644
index 00000000..3a61ae5e
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/is.json
@@ -0,0 +1,64 @@
+{
+ "@metadata": {
+ "authors": [
+ "SnƦvar"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titill: $1",
+ "mwe-embedplayer-credit-date": "Dagsetning: $1",
+ "mwe-embedplayer-credit-author": "Hƶfundur: $1",
+ "mwe-embedplayer-loading_plugin": "HleĆ° viĆ°bĆ³t...",
+ "mwe-embedplayer-select_playback": "Setja afspilunar stillingar",
+ "mwe-embedplayer-link_back": "Tengja tilbaka",
+ "mwe-embedplayer-error_swap_vid": "Villa: mwEmbad gat ekki skipt myndbands tagi Ćŗt fyrir mwEmbed valmyndina",
+ "mwe-embedplayer-missing_video_stream": "MyndbandiĆ° fyrir streymiĆ° vantar",
+ "mwe-embedplayer-play_clip": "Spila myndband",
+ "mwe-embedplayer-pause_clip": "Gera hlƩ Ɣ spilun",
+ "mwe-embedplayer-volume_control": "HljĆ³Ć°styrkur",
+ "mwe-embedplayer-player_options": "Stillingar spilarans",
+ "mwe-embedplayer-player_fullscreen": "Fylla skjĆ”",
+ "mwe-embedplayer-next_clip_msg": "Spila nƦsta myndband",
+ "mwe-embedplayer-prev_clip_msg": "Spila fyrra myndband",
+ "mwe-embedplayer-current_clip_msg": "Halda Ɣfram spilun",
+ "mwe-embedplayer-seek_to": "SƦki $1",
+ "mwe-embedplayer-paused": "Ć­ biĆ°",
+ "mwe-embedplayer-download_segment": "HlaĆ°a niĆ°ur hluta:",
+ "mwe-embedplayer-download_full": "Hlaưa niưur allri skrƔnni:",
+ "mwe-embedplayer-download_right_click": "Til aư hlaưa niưur, hƦgri smelltu og veldu <i>Vista tengil sem...</i>",
+ "mwe-embedplayer-download_clip": "SƦkja myndband",
+ "mwe-embedplayer-download_text": "HlaĆ°a niĆ°ur texta",
+ "mwe-embedplayer-download": "HlaĆ°a niĆ°ur",
+ "mwe-embedplayer-share": "Deila",
+ "mwe-embedplayer-about-library": "Um Kaltura-spilarann",
+ "mwe-embedplayer-choose_player": "Velja myndbands spilara",
+ "mwe-embedplayer-no-player": "Enginn spilari til fyrir $1",
+ "mwe-embedplayer-share_this_video": "Deila Ć¾essu myndbandi",
+ "mwe-embedplayer-close_btn": "Loka",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC-spilari",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg-spilari",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264-spilari",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML WebM-spilari",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Almenn Ogg viĆ°bĆ³t",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime-viĆ°bĆ³t",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura-spilari",
+ "mwe-embedplayer-ogg-player-selected": "(valiĆ°)",
+ "mwe-embedplayer-download-warn": "Enginn samhƦfĆ°ur spilari fannst. Til Ć¾ess aĆ° spila myndbandiĆ° Ć­ \tvafranum vinsamlegst sĆ³ttu [$1 nĆ½jasta Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "Til Ć¾ess aĆ° fylla Ćŗt Ć­ skjĆ”inn, smelltu Ć” <b>F11</b>",
+ "mwe-embedplayer-fullscreen-tip-osx": "Til Ć¾ess aĆ° fylla Ćŗt Ć­ skjĆ”inn, smelltu Ć” <b>shift āŒ˜ F</b>",
+ "mwe-embedplayer-do_not_warn_again": "Ekki sĆ½na Ć¾essi skilaboĆ° framvegis",
+ "mwe-embedplayer-playerSelect": "Spilarar",
+ "mwe-embedplayer-related_videos": "Svipuư myndbƶnd",
+ "mwe-embedplayer-seeking": "sƦki",
+ "mwe-embedplayer-buffering": "hleĆ° niĆ°ur Ć­ biĆ°minni",
+ "mwe-embedplayer-video-h264": "H.264-myndband",
+ "mwe-embedplayer-video-webm": "WebM-myndband",
+ "mwe-embedplayer-video-flv": "Flash-myndband",
+ "mwe-embedplayer-video-ogg": "Ogg-myndband",
+ "mwe-embedplayer-video-audio": "Ogg-hljĆ³Ć°skrĆ”",
+ "mwe-embedplayer-audio-mpeg": "MPEG-hljĆ³Ć°skrĆ”",
+ "mwe-embedplayer-video-3gp": "3GP-myndband",
+ "mwe-embedplayer-video-mpeg": "MPEG-myndband",
+ "mwe-embedplayer-video-msvideo": "AVI-myndband"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/it.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/it.json
new file mode 100644
index 00000000..e991b7d8
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/it.json
@@ -0,0 +1,92 @@
+{
+ "@metadata": {
+ "authors": [
+ "Beta16",
+ "Darth Kule",
+ "F. Cosoleto",
+ "Gianfranco"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titolo: $1",
+ "mwe-embedplayer-credit-date": "Data: $1",
+ "mwe-embedplayer-credit-author": "Autore: $1",
+ "mwe-embedplayer-nocredits": "Crediti non disponibili",
+ "mwe-embedplayer-loading_plugin": "Caricamento plugin...",
+ "mwe-embedplayer-select_playback": "Imposta le preferenze per la riproduzione",
+ "mwe-embedplayer-link_back": "Link di ritorno",
+ "mwe-embedplayer-error_swap_vid": "Errore: mwEmbed non ĆØ riuscito a scambiare il tag video per l'interfaccia mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Aggiungi alla fine della sequenza",
+ "mwe-embedplayer-missing_video_stream": "Manca il file video per questo flusso",
+ "mwe-embedplayer-play_clip": "Riproduci clip",
+ "mwe-embedplayer-pause_clip": "Pausa clip",
+ "mwe-embedplayer-volume_control": "Controllo volume",
+ "mwe-embedplayer-player_options": "Opzioni lettore",
+ "mwe-embedplayer-timed_text": "Sottotitoli",
+ "mwe-embedplayer-player_fullscreen": "Schermo intero",
+ "mwe-embedplayer-next_clip_msg": "Riproduci clip successivo",
+ "mwe-embedplayer-prev_clip_msg": "Riproduci clip precedente",
+ "mwe-embedplayer-current_clip_msg": "Continuare a riprodurre questa clip",
+ "mwe-embedplayer-seek_to": "Salta a $1",
+ "mwe-embedplayer-paused": "in pausa",
+ "mwe-embedplayer-download_segment": "Scarica selezione:",
+ "mwe-embedplayer-download_full": "Scarica file video completo:",
+ "mwe-embedplayer-download_right_click": "Per scaricare, fare clic col destro e selezionare <i>Salva link con nome...</i>",
+ "mwe-embedplayer-download_clip": "Scarica video",
+ "mwe-embedplayer-download_text": "Scarica testo",
+ "mwe-embedplayer-download": "Scarica",
+ "mwe-embedplayer-share": "Condividi",
+ "mwe-embedplayer-credits": "Crediti",
+ "mwe-embedplayer-about-library": "Informazioni su Kaltura player",
+ "mwe-embedplayer-about-library-desc": "La libreria multimediale HTML5 di Kaltura consente adesso di utilizzare l'etichette HTML5 &lt;video&gt; and &lt;audio&gt; con una interfaccia del media player coerente in tutti i principali browser.\n\n[$1 Maggiori informazioni sulla libreria Kaltura].",
+ "mwe-embedplayer-clip_linkback": "Pagina di origine clip",
+ "mwe-embedplayer-choose_player": "Scegli riproduttore video",
+ "mwe-embedplayer-no-player": "Nessun lettore disponibile per $1",
+ "mwe-embedplayer-share_this_video": "Condividi questo video",
+ "mwe-embedplayer-video_credits": "Crediti video",
+ "mwe-embedplayer-no-video_credits": "Crediti non disponibili",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura - piattaforma video open source",
+ "mwe-embedplayer-menu_btn": "Menu",
+ "mwe-embedplayer-close_btn": "Chiudi",
+ "mwe-embedplayer-ogg-player-vlc-player": "Lettore VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Lettore HTML5 Ogg",
+ "mwe-embedplayer-ogg-player-mp3Native": "Lettore HTML5 MP3",
+ "mwe-embedplayer-ogg-player-aacNative": "Lettore HTML5 AAC",
+ "mwe-embedplayer-ogg-player-h264Native": "Lettore HTML5 H.264",
+ "mwe-embedplayer-ogg-player-webmNative": "Lettore HTML5 WebM",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Plugin generico Ogg",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "VLC per iOS app",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime plugin",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Player Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(selezionato)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Per una migliore esperienza di riproduzione dei video si consiglia un <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">browser che supporti i video HTML5</a>.",
+ "mwe-embedplayer-download-warn": "Rilevato lettore integrato non compatibile: per la riproduzione tramite browser scaricare [$1 l'ultima versione di Firefox].",
+ "mwe-embedplayer-fullscreen-tip": "Premere <b>F11</b> attiva/disattiva la modalitĆ  a schermo intero del <i>browser web</i>",
+ "mwe-embedplayer-fullscreen-tip-osx": "Premere <b>Maiusc āŒ˜ F</b> attiva/disattiva la modalitĆ  a schermo intero",
+ "mwe-embedplayer-do_not_warn_again": "In futuro, non mostrare questo messaggio",
+ "mwe-embedplayer-playerSelect": "Lettori",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Leggi questo</a> prima di incorporare.",
+ "mwe-embedplayer-embed_site_or_blog": "Incorpora in una pagina",
+ "mwe-embedplayer-embed_wiki": "Incorpora su un wiki",
+ "mwe-embedplayer-related_videos": "Video correlati",
+ "mwe-embedplayer-seeking": "cerca",
+ "mwe-embedplayer-buffering": "Riempimento buffer",
+ "mwe-embedplayer-video-h264": "Video H.264",
+ "mwe-embedplayer-video-webm": "Video WebM",
+ "mwe-embedplayer-video-flv": "Video Flash",
+ "mwe-embedplayer-video-ogg": "Video Ogg",
+ "mwe-embedplayer-video-audio": "Audio Ogg",
+ "mwe-embedplayer-audio-mpeg": "Audio MPEG",
+ "mwe-embedplayer-video-3gp": "Video 3GP",
+ "mwe-embedplayer-video-mpeg": "Video MPEG",
+ "mwe-embedplayer-video-msvideo": "Video AVI",
+ "mwe-embedplayer-missing-source": "Non ĆØ stata trovata alcuna sorgente video",
+ "mwe-embedplayer-vlcapp-intro": "Per poter visualizzare i video da questo sito su un iPhone o iPad, ĆØ necessaria $1 gratuita.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "VLC app",
+ "mwe-embedplayer-vlcapp-downloadapp": "Scarica l'app VLC da App Store",
+ "mwe-embedplayer-vlcapp-openvideo": "Apri questo video nell'app VLC",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Scarica questo video",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "Per riprodurre i video su questo sito, ĆØ necessaria l'app VLC. Installarla ora?"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ja.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ja.json
new file mode 100644
index 00000000..d65876b9
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ja.json
@@ -0,0 +1,84 @@
+{
+ "@metadata": {
+ "authors": [
+ "Shirayuki",
+ "é’å­å®ˆę­Œ"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "ć‚æć‚¤ćƒˆćƒ«: $1",
+ "mwe-embedplayer-credit-date": "ę—„ä»˜: $1",
+ "mwe-embedplayer-credit-author": "ä½œč€…: $1",
+ "mwe-embedplayer-nocredits": "č‘—ä½œč€…ęƒ…å ±ćÆć‚ć‚Šć¾ć›ć‚“",
+ "mwe-embedplayer-loading_plugin": "ćƒ—ćƒ©ć‚°ć‚¤ćƒ³ć‚’čŖ­ćæč¾¼ćæäø­ ...",
+ "mwe-embedplayer-select_playback": "再ē”Ÿē’°å¢ƒć‚’čح定",
+ "mwe-embedplayer-link_back": "惈惩惃ć‚Æ惐惃ć‚Æ",
+ "mwe-embedplayer-error_swap_vid": "ć‚Øćƒ©ćƒ¼: mv_embed å½¢å¼ć«ć‚ć£ćŸå‹•ē”»ć‚æ悰恫ē½®ę›ć§ćć¾ć›ć‚“ć§ć—ćŸć€‚",
+ "mwe-embedplayer-add_to_end_of_sequence": "ć‚·ćƒ¼ć‚±ćƒ³ć‚¹ć®ēµ‚ć‚ć‚Šć«čæ½åŠ ",
+ "mwe-embedplayer-missing_video_stream": "ć“ć®ć‚¹ćƒˆćƒŖćƒ¼ćƒ ć«åæ…要ćŖ動ē”»ćƒ•ć‚”ć‚¤ćƒ«ćŒč¦‹ć¤ć‹ć‚Šć¾ć›ć‚“",
+ "mwe-embedplayer-play_clip": "ć‚ÆćƒŖćƒƒćƒ—ć‚’å†ē”Ÿ",
+ "mwe-embedplayer-pause_clip": "ć‚ÆćƒŖ惃惗悒äø€ę™‚åœę­¢",
+ "mwe-embedplayer-volume_control": "音量čŖæēƀ",
+ "mwe-embedplayer-player_options": "ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼ć®čح定",
+ "mwe-embedplayer-timed_text": "字幕",
+ "mwe-embedplayer-player_fullscreen": "å…Øē”»é¢č”Øē¤ŗ",
+ "mwe-embedplayer-next_clip_msg": "ꬔ恮ć‚ÆćƒŖćƒƒćƒ—ć‚’å†ē”Ÿ",
+ "mwe-embedplayer-prev_clip_msg": "å‰ć®ć‚ÆćƒŖćƒƒćƒ—ć‚’å†ē”Ÿ",
+ "mwe-embedplayer-current_clip_msg": "恓恮ć‚ÆćƒŖćƒƒćƒ—ć®å†ē”Ÿć‚’ē¶šć‘ć‚‹",
+ "mwe-embedplayer-seek_to": "$1 ćøć‚·ćƒ¼ć‚Æ",
+ "mwe-embedplayer-paused": "äø€ę™‚åœę­¢äø­",
+ "mwe-embedplayer-download_segment": "ćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰ę–¹ę³•ć‚’éøꊞ:",
+ "mwe-embedplayer-download_full": "動ē”»ćƒ•ć‚”ć‚¤ćƒ«å…Øä½“ć‚’ćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰:",
+ "mwe-embedplayer-download_right_click": "ćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰ć™ć‚‹ć«ćÆć€å³ć‚ÆćƒŖ惃ć‚Æ恗恦<i>åå‰ć‚’ä»˜ć‘ć¦ćƒŖćƒ³ć‚Æå…ˆć‚’äæå­˜</i>悒éø悓恧恏恠恕恄",
+ "mwe-embedplayer-download_clip": "動ē”»ć‚’ćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰",
+ "mwe-embedplayer-download_text": "ćƒ†ć‚­ć‚¹ćƒˆć‚’ćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰",
+ "mwe-embedplayer-download": "ćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰",
+ "mwe-embedplayer-share": "å…±ęœ‰",
+ "mwe-embedplayer-credits": "ć‚Æ惬ć‚ø惃惈",
+ "mwe-embedplayer-about-library": "Kaltura ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼ć«ć¤ć„ć¦",
+ "mwe-embedplayer-about-library-desc": "Kaltura 恮 HTML5 ćƒ”ćƒ‡ć‚£ć‚¢ ćƒ©ć‚¤ćƒ–ćƒ©ćƒŖćÆć€ć™ć¹ć¦ć®äø»č¦ćƒ–ćƒ©ć‚¦ć‚¶ćƒ¼é–“ć§äø€č²«ę€§ć®ć‚ć‚‹å†ē”Ÿć‚¤ćƒ³ć‚æćƒ¼ćƒ•ć‚§ć‚¤ć‚¹ć‚’ HTML5 恮 <code><nowiki><video></nowiki></code> ć‚æ悰ćØ <code><nowiki><audio></nowiki></code> ć‚æ悰恧ꓻē”Øć§ćć¾ć™ć€‚\n\n[$1 Kaltura ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼ ćƒ©ć‚¤ćƒ–ćƒ©ćƒŖć«ć¤ć„ć¦ć®č©³ē“°ęƒ…å ±]怂",
+ "mwe-embedplayer-clip_linkback": "ć‚ÆćƒŖćƒƒćƒ—ć®ęƒ…å ±ćƒšćƒ¼ć‚ø",
+ "mwe-embedplayer-choose_player": "動ē”»ć®ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼ć‚’éøꊞ",
+ "mwe-embedplayer-no-player": "$1 ć‚’å†ē”Ÿć§ćć‚‹ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼ćÆć‚ć‚Šć¾ć›ć‚“",
+ "mwe-embedplayer-share_this_video": "ć“ć®å‹•ē”»ć‚’å…±ęœ‰ć™ć‚‹",
+ "mwe-embedplayer-video_credits": "動ē”»ć®ć‚Æ惬ć‚ø惃惈",
+ "mwe-embedplayer-no-video_credits": "č‘—ä½œč€…ęƒ…å ±ćÆć‚ć‚Šć¾ć›ć‚“",
+ "mwe-embedplayer-kaltura-platform-title": "Kalturać‚Ŗćƒ¼ćƒ—ćƒ³ć‚½ćƒ¼ć‚¹å‹•ē”»ćƒ—ćƒ©ćƒƒćƒˆćƒ•ć‚©ćƒ¼ćƒ ",
+ "mwe-embedplayer-menu_btn": "ćƒ”ćƒ‹ćƒ„ćƒ¼",
+ "mwe-embedplayer-close_btn": "閉恘悋",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3 ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AAC ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼",
+ "mwe-embedplayer-ogg-player-oggPlugin": "걎ē”Ø恮 Ogg ćƒ—ćƒ©ć‚°ć‚¤ćƒ³",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTimećƒ—ćƒ©ć‚°ć‚¤ćƒ³",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼",
+ "mwe-embedplayer-ogg-player-selected": "(éøꊞęøˆćæ)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "動ē”»å†ē”Ÿå“č³Ŗć®å‘äøŠć®ćŸć‚ć«ć€<a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">HTML5 動ē”»åƾåæœć®ćƒ–ćƒ©ć‚¦ć‚¶ćƒ¼</a>ć‚’ćŠå‹§ć‚ć—ć¾ć™ć€‚",
+ "mwe-embedplayer-download-warn": "äŗ’ę›ę€§ćŒćŖć„ćƒ–ćƒ©ć‚¦ć‚¶ćƒ¼å†…ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼ć‚’ę¤œå‡ŗć—ć¾ć—ćŸ: ćƒ–ćƒ©ć‚¦ć‚¶ćƒ¼å†…ć§å†ē”Ÿć™ć‚‹ć«ćÆ态[$1 ꜀ꖰē‰ˆć® Firefox] ć‚’ćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰ć—ć¦ćć ć•ć„",
+ "mwe-embedplayer-fullscreen-tip": "<i>ć‚¦ć‚§ćƒ– ćƒ–ćƒ©ć‚¦ć‚¶ćƒ¼</i>恮å…Øē”»é¢č”Øē¤ŗć‚’åˆ‡ć‚Šę›æćˆć‚‹ć«ćÆ <b>F11</b> ć‚­ćƒ¼ć‚’ęŠ¼ć—ć¦ćć ć•ć„",
+ "mwe-embedplayer-fullscreen-tip-osx": "å…Øē”»é¢č”Øē¤ŗć‚’åˆ‡ć‚Šę›æćˆć‚‹ć«ćÆ <b>shift &#x2318; F</b> ć‚’ęŠ¼ć—ć¦ćć ć•ć„",
+ "mwe-embedplayer-do_not_warn_again": "ä»Šå¾Œć€ć“ć®ćƒ”ćƒƒć‚»ćƒ¼ć‚ø悒č”Øē¤ŗ恗ćŖ恄",
+ "mwe-embedplayer-playerSelect": "ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼",
+ "mwe-embedplayer-read_before_embed": "åŸ‹ć‚č¾¼ć‚€å‰ć«<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">ę³Øꄏäŗ‹é …</a>悒恊čŖ­ćæ恏恠恕恄怂",
+ "mwe-embedplayer-embed_site_or_blog": "ćƒšćƒ¼ć‚øć«åŸ‹ć‚č¾¼ć‚€",
+ "mwe-embedplayer-embed_wiki": "ć‚¦ć‚£ć‚­ć«åŸ‹ć‚č¾¼ć‚€",
+ "mwe-embedplayer-related_videos": "é–¢é€£ć™ć‚‹å‹•ē”»",
+ "mwe-embedplayer-seeking": "ć‚·ćƒ¼ć‚Æäø­",
+ "mwe-embedplayer-buffering": "ćƒćƒƒćƒ•ć‚”ćƒŖćƒ³ć‚°",
+ "mwe-embedplayer-video-h264": "H.264 動ē”»",
+ "mwe-embedplayer-video-webm": "WebM 動ē”»",
+ "mwe-embedplayer-video-flv": "Flash 動ē”»",
+ "mwe-embedplayer-video-ogg": "Ogg 動ē”»",
+ "mwe-embedplayer-video-audio": "Ogg 音声",
+ "mwe-embedplayer-audio-mpeg": "MPEG 音声",
+ "mwe-embedplayer-video-3gp": "3GP 動ē”»",
+ "mwe-embedplayer-video-mpeg": "MPEG 動ē”»",
+ "mwe-embedplayer-video-msvideo": "AVI 動ē”»",
+ "mwe-embedplayer-missing-source": "ć‚½ćƒ¼ć‚¹ćØćŖć‚‹å‹•ē”»ćŒč¦‹ć¤ć‹ć‚Šć¾ć›ć‚“ć§ć—ćŸ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ka.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ka.json
new file mode 100644
index 00000000..95c48673
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ka.json
@@ -0,0 +1,73 @@
+{
+ "@metadata": {
+ "authors": [
+ "David1010",
+ "MIKHEIL"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "įƒ”įƒįƒ—įƒįƒ£įƒ įƒ˜: $1",
+ "mwe-embedplayer-credit-date": "įƒ—įƒįƒ įƒ˜įƒ¦įƒ˜: $1",
+ "mwe-embedplayer-credit-author": "įƒįƒ•įƒ¢įƒįƒ įƒ˜: $1",
+ "mwe-embedplayer-loading_plugin": "įƒ˜įƒ¢įƒ•įƒ˜įƒ įƒ—įƒ”įƒ‘įƒ įƒžįƒšįƒįƒ’įƒ˜įƒœįƒ˜ ...",
+ "mwe-embedplayer-link_back": "įƒ£įƒ™įƒ£įƒ‘įƒ›įƒ£įƒšįƒ˜",
+ "mwe-embedplayer-add_to_end_of_sequence": "įƒ—įƒįƒœįƒ›įƒ˜įƒ›įƒ“įƒ”įƒ•įƒ įƒįƒ‘įƒ˜įƒ” įƒ‘įƒįƒšįƒįƒØįƒ˜ įƒ“įƒįƒ›įƒįƒ¢įƒ”įƒ‘įƒ",
+ "mwe-embedplayer-play_clip": "įƒ™įƒšįƒ˜įƒžįƒ˜įƒ” įƒ“įƒįƒ™įƒ•įƒ įƒ",
+ "mwe-embedplayer-pause_clip": "įƒ™įƒšįƒ˜įƒžįƒ˜įƒ” įƒØįƒ”įƒ©įƒ”įƒ įƒ”įƒ‘įƒ",
+ "mwe-embedplayer-volume_control": "įƒ®įƒ›įƒ˜įƒ” įƒ™įƒįƒœįƒ¢įƒ įƒįƒšįƒ˜",
+ "mwe-embedplayer-player_options": "įƒ“įƒįƒ›įƒ™įƒ•įƒ įƒ”įƒšįƒ˜įƒ” įƒžįƒįƒ įƒįƒ›įƒ”įƒ¢įƒ įƒ”įƒ‘įƒ˜",
+ "mwe-embedplayer-timed_text": "įƒ”įƒ˜įƒœįƒ„įƒ įƒįƒœįƒ˜įƒ–įƒ˜įƒ įƒ”įƒ‘įƒ£įƒšįƒ˜ įƒ¢įƒ”įƒ„įƒ”įƒ¢įƒ˜",
+ "mwe-embedplayer-player_fullscreen": "įƒ›įƒ—įƒ”įƒš įƒ”įƒ™įƒ įƒįƒœįƒ–įƒ”",
+ "mwe-embedplayer-next_clip_msg": "įƒØįƒ”įƒ›įƒ“įƒ”įƒ’įƒ˜ įƒ™įƒšįƒ˜įƒžįƒ˜įƒ” įƒ“įƒįƒ™įƒ•įƒ įƒ",
+ "mwe-embedplayer-prev_clip_msg": "įƒ¬įƒ˜įƒœįƒ įƒ™įƒšįƒ˜įƒžįƒ˜įƒ” įƒ“įƒįƒ™įƒ•įƒ įƒ",
+ "mwe-embedplayer-current_clip_msg": "įƒįƒ› įƒ™įƒšįƒ˜įƒžįƒ˜įƒ” įƒ“įƒįƒ™įƒ•įƒ įƒ˜įƒ” įƒ’įƒįƒ’įƒ įƒ«įƒ”įƒšįƒ”įƒ‘įƒ",
+ "mwe-embedplayer-seek_to": "įƒ’įƒįƒ“įƒįƒ”įƒ•įƒšįƒ $1",
+ "mwe-embedplayer-paused": "įƒØįƒ”įƒ©įƒ”įƒ įƒ”įƒ‘įƒ£įƒšįƒ˜įƒ",
+ "mwe-embedplayer-download_segment": "įƒįƒ įƒ©įƒ”įƒ£įƒšįƒ˜įƒ” įƒ©įƒįƒ›įƒįƒ¢įƒ•įƒ˜įƒ įƒ—įƒ•įƒ:",
+ "mwe-embedplayer-download_full_video": "įƒ›įƒ—įƒšįƒ˜įƒįƒœįƒ˜ įƒ•įƒ˜įƒ“įƒ”įƒ-įƒ¤įƒįƒ˜įƒšįƒ˜įƒ” įƒ©įƒįƒ›įƒįƒ¢įƒ•įƒ˜įƒ įƒ—įƒ•įƒ:",
+ "mwe-embedplayer-download_full_audio": "įƒ›įƒ—įƒšįƒ˜įƒįƒœįƒ˜ įƒįƒ£įƒ“įƒ˜įƒ-įƒ¤įƒįƒ˜įƒšįƒ˜įƒ” įƒ©įƒįƒ›įƒįƒ¢įƒ•įƒ˜įƒ įƒ—įƒ•įƒ:",
+ "mwe-embedplayer-download_clip": "įƒ•įƒ˜įƒ“įƒ”įƒįƒ” įƒ©įƒįƒ›įƒįƒ¢įƒ•įƒ˜įƒ įƒ—įƒ•įƒ",
+ "mwe-embedplayer-download_text": "įƒ¢įƒ”įƒ„įƒ”įƒ¢įƒ˜įƒ” įƒ©įƒįƒ›įƒįƒ¢įƒ•įƒ˜įƒ įƒ—įƒ•įƒ",
+ "mwe-embedplayer-download": "įƒ©įƒįƒ›įƒįƒ¢įƒ•įƒ˜įƒ įƒ—įƒ•įƒ",
+ "mwe-embedplayer-share": "įƒ’įƒįƒ–įƒ˜įƒįƒ įƒ”įƒ‘įƒ",
+ "mwe-embedplayer-credits": "įƒØįƒ”įƒ›įƒ„įƒ›įƒœįƒ”įƒšįƒ”įƒ‘įƒ˜",
+ "mwe-embedplayer-about-library": "Kaltura player-įƒ˜įƒ” įƒØįƒ”įƒ”įƒįƒ®įƒ”įƒ‘",
+ "mwe-embedplayer-clip_linkback": "įƒ™įƒšįƒ˜įƒžįƒ˜įƒ” įƒ¬įƒ§įƒįƒ įƒįƒ” įƒ’įƒ•įƒ”įƒ įƒ“įƒ˜",
+ "mwe-embedplayer-choose_player": "įƒįƒ˜įƒ įƒ©įƒ˜įƒ”įƒ— įƒ•įƒ˜įƒ“įƒ”įƒįƒ“įƒįƒ›įƒ™įƒ•įƒ įƒ”įƒšįƒ˜",
+ "mwe-embedplayer-share_this_video": "įƒįƒ› įƒ•įƒ˜įƒ“įƒ”įƒįƒ” įƒ’įƒįƒ–įƒ˜įƒįƒ įƒ”įƒ‘įƒ",
+ "mwe-embedplayer-share_this_audio": "įƒįƒ› įƒįƒ£įƒ“įƒ˜įƒ-įƒ¤įƒįƒ˜įƒšįƒ˜įƒ” įƒ’įƒįƒ–įƒ˜įƒįƒ įƒ”įƒ‘įƒ",
+ "mwe-embedplayer-video_credits": "įƒ•įƒ˜įƒ“įƒ”įƒįƒ” įƒØįƒ”įƒ›įƒ„įƒ›įƒœįƒ”įƒšįƒ”įƒ‘įƒ˜",
+ "mwe-embedplayer-menu_btn": "įƒ›įƒ”įƒœįƒ˜įƒ£",
+ "mwe-embedplayer-close_btn": "įƒ“įƒįƒ®įƒ£įƒ įƒ•įƒ",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC player",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg player",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3 įƒ“įƒįƒ›įƒ™įƒ•įƒ įƒ”įƒšįƒ˜",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AAC įƒ“įƒįƒ›įƒ™įƒ•įƒ įƒ”įƒšįƒ˜",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 player",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM player",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Ogg-įƒ˜įƒ” įƒ”įƒįƒ”įƒ įƒ—įƒ įƒžįƒšįƒįƒ’įƒ˜įƒœįƒ˜",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime-įƒ˜įƒ” įƒžįƒšįƒįƒ’įƒ˜įƒœįƒ˜",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura player",
+ "mwe-embedplayer-ogg-player-selected": "(įƒįƒ įƒ©įƒ”įƒ£įƒšįƒ˜įƒ)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-fullscreen-tip": "įƒ¦įƒ˜įƒšįƒįƒ™įƒ” <b>F11</b> įƒ’įƒįƒ“įƒįƒ°įƒ§įƒįƒ•įƒ” <i>įƒ•įƒ”įƒ‘-įƒ‘įƒ įƒįƒ£įƒ–įƒ”įƒ įƒ˜</i> įƒ”įƒ įƒ£įƒšįƒ”įƒ™įƒ įƒįƒœįƒ˜įƒįƒœ įƒ įƒ”įƒŸįƒ˜įƒ›įƒØįƒ˜",
+ "mwe-embedplayer-fullscreen-tip-osx": "įƒ“įƒįƒįƒ­įƒ˜įƒ įƒ”įƒ— <b>shift āŒ˜ F</b> įƒ”įƒ įƒ£įƒšįƒ”įƒ™įƒ įƒįƒœįƒ˜įƒįƒœ įƒ įƒ”įƒŸįƒ˜įƒ›įƒ–įƒ” įƒ’įƒįƒ“įƒįƒ”įƒįƒ”įƒ•įƒšįƒ”įƒšįƒįƒ“",
+ "mwe-embedplayer-do_not_warn_again": "įƒ›įƒįƒ›įƒįƒ•įƒįƒšįƒØįƒ˜ įƒįƒ¦įƒįƒ  įƒįƒ©įƒ•įƒ”įƒœįƒ įƒ”įƒ” įƒØįƒ”įƒ¢įƒ§įƒįƒ‘įƒ˜įƒœįƒ”įƒ‘įƒ",
+ "mwe-embedplayer-playerSelect": "įƒ“įƒįƒ›įƒ™įƒ•įƒ įƒ”įƒšįƒ”įƒ‘įƒ˜",
+ "mwe-embedplayer-read_before_embed": "įƒ’įƒ—įƒ®įƒįƒ•įƒ—, <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">įƒ¬įƒįƒ˜įƒ™įƒ˜įƒ—įƒ®įƒ”įƒ— įƒ”įƒ”</a> įƒ©įƒįƒØįƒ”įƒœįƒ”įƒ‘įƒįƒ›įƒ“įƒ”!",
+ "mwe-embedplayer-embed_site_or_blog": "įƒ’įƒ•įƒ”įƒ įƒ“įƒØįƒ˜ įƒ©įƒįƒ“įƒ’įƒ›įƒ",
+ "mwe-embedplayer-related_videos": "įƒ“įƒįƒ™įƒįƒ•įƒØįƒ˜įƒ įƒ”įƒ‘įƒ£įƒšįƒ˜ įƒ•įƒ˜įƒ“įƒ”įƒįƒ”įƒ‘įƒ˜",
+ "mwe-embedplayer-seeking": "įƒ«įƒ˜įƒ”įƒ‘įƒ",
+ "mwe-embedplayer-buffering": "įƒ‘įƒ£įƒ¤įƒ”įƒ įƒ˜įƒ–įƒįƒŖįƒ˜įƒ",
+ "mwe-embedplayer-video-h264": "H.264 įƒ•įƒ˜įƒ“įƒ”įƒ",
+ "mwe-embedplayer-video-webm": "WebM įƒ•įƒ˜įƒ“įƒ”įƒ",
+ "mwe-embedplayer-video-flv": "Flash įƒ•įƒ˜įƒ“įƒ”įƒ",
+ "mwe-embedplayer-video-ogg": "Ogg įƒ•įƒ˜įƒ“įƒ”įƒ",
+ "mwe-embedplayer-video-audio": "Ogg įƒįƒ£įƒ“įƒ˜įƒ",
+ "mwe-embedplayer-audio-mpeg": "MPEG įƒįƒ£įƒ“įƒ˜įƒ",
+ "mwe-embedplayer-video-3gp": "3GP įƒ•įƒ˜įƒ“įƒ”įƒ",
+ "mwe-embedplayer-video-mpeg": "MPEG įƒ•įƒ˜įƒ“įƒ”įƒ",
+ "mwe-embedplayer-video-msvideo": "AVI įƒ•įƒ˜įƒ“įƒ”įƒ",
+ "mwe-embedplayer-missing-source": "įƒ•įƒ˜įƒ“įƒ”įƒįƒ” įƒ¬įƒ§įƒįƒ įƒ įƒ•įƒ”įƒ  įƒ›įƒįƒ˜įƒ«įƒ”įƒ‘įƒœįƒ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ko.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ko.json
new file mode 100644
index 00000000..75e9374d
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ko.json
@@ -0,0 +1,83 @@
+{
+ "@metadata": {
+ "authors": [
+ "Priviet",
+ "ģ•„ė¼"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "ģ œėŖ©: $1",
+ "mwe-embedplayer-credit-date": "ė‚ ģ§œ: $1",
+ "mwe-embedplayer-credit-author": "ģ €ģž: $1",
+ "mwe-embedplayer-nocredits": "ģ‚¬ģš© ź°€ėŠ„ķ•œ ģ œģž‘ģ§„ģ“ ģ—†ģŠµė‹ˆė‹¤",
+ "mwe-embedplayer-loading_plugin": "ķ”ŒėŸ¬ź·øģøģ„ ė¶ˆėŸ¬ģ˜¤ėŠ” ģ¤‘...",
+ "mwe-embedplayer-select_playback": "ģž¬ģƒ ķ™˜ź²½ ģ„¤ģ •",
+ "mwe-embedplayer-link_back": "ė§ķ¬ ė°±",
+ "mwe-embedplayer-error_swap_vid": "ģ˜¤ė„˜: mwEmbedėŠ” mwEmbed ģøķ„°ķŽ˜ģ“ģŠ¤ģ— ėŒ€ķ•œ ė™ģ˜ģƒ ķƒœź·øė„¼ ģ „ķ™˜ķ•  ģˆ˜ ģ—†ģŠµė‹ˆė‹¤",
+ "mwe-embedplayer-add_to_end_of_sequence": "ģ‹œķ€€ģŠ¤ģ˜ ėģ— ģ¶”ź°€",
+ "mwe-embedplayer-missing_video_stream": "ģ“ ģŠ¤ķŠøė¦¼ģ— ėŒ€ķ•œ ė™ģ˜ģƒ ķŒŒģ¼ģ“ ģ—†ģŠµė‹ˆė‹¤",
+ "mwe-embedplayer-play_clip": "ķ“ė¦½ ģž¬ģƒ",
+ "mwe-embedplayer-pause_clip": "ķ“ė¦½ ģ¼ģ‹œ ģ •ģ§€",
+ "mwe-embedplayer-volume_control": "ģŒėŸ‰ ģ»ØķŠøė”¤",
+ "mwe-embedplayer-player_options": "ķ”Œė ˆģ“ģ–“ ģ„¤ģ •",
+ "mwe-embedplayer-timed_text": "ģžė§‰",
+ "mwe-embedplayer-player_fullscreen": "ģ „ģ²“ ķ™”ė©“",
+ "mwe-embedplayer-next_clip_msg": "ė‹¤ģŒ ķ“ė¦½ ģž¬ģƒ",
+ "mwe-embedplayer-prev_clip_msg": "ģ“ģ „ ķ“ė¦½ ģž¬ģƒ",
+ "mwe-embedplayer-current_clip_msg": "ģ“ ķ“ė¦½ ģž¬ģƒ ź³„ģ†ķ•˜źø°",
+ "mwe-embedplayer-seek_to": "$1 ķƒģƒ‰",
+ "mwe-embedplayer-paused": "ģ¼ģ‹œ ģ •ģ§€ķ•Ø",
+ "mwe-embedplayer-download_segment": "ģ„ ķƒ ė‹¤ģš“ė”œė“œ:",
+ "mwe-embedplayer-download_full_video": "ģ „ģ²“ ė™ģ˜ģƒ ķŒŒģ¼ ė‹¤ģš“ė”œė“œ:",
+ "mwe-embedplayer-download_right_click": "ė‹¤ģš“ė”œė“œķ•˜ė ¤ė©“ ģ˜¤ė„øģŖ½ģ„ ķ“ė¦­ķ•˜ź³  <i>ė‹¤ė„ø ģ“ė¦„ģœ¼ė”œ ė§ķ¬ ģ €ģž„...</i>ģ„ ģ„ ķƒķ•˜ģ„øģš”",
+ "mwe-embedplayer-download_clip": "ė™ģ˜ģƒ ė‹¤ģš“ė”œė“œ",
+ "mwe-embedplayer-download_text": "ķ…ģŠ¤ķŠø ė‹¤ģš“ė”œė“œ",
+ "mwe-embedplayer-download": "ė‹¤ģš“ė”œė“œ",
+ "mwe-embedplayer-share": "ź³µģœ ",
+ "mwe-embedplayer-credits": "ģ œģž‘ģ§„",
+ "mwe-embedplayer-about-library": "Kaltura ķ”Œė ˆģ“ģ–“ ģ •ė³“",
+ "mwe-embedplayer-about-library-desc": "Kalturaģ˜ HTML5 ėÆøė””ģ–“ ė¼ģ“ėøŒėŸ¬ė¦¬ėŠ” ėŖØė“  ģ£¼ģš” ėøŒė¼ģš°ģ €ģ—ģ„œ ģ¼ź“€ėœ ķ”Œė ˆģ“ģ–“ ģøķ„°ķŽ˜ģ“ģŠ¤ė”œ ģ˜¤ėŠ˜ė‚  HTML5ģ˜ &lt;video&gt; ė° &lt;audio&gt; ķƒœź·øė„¼ ģ“ģš©ķ•  ģˆ˜ ģžˆģŠµė‹ˆė‹¤.\n\n[$1 Kaltura ķ”Œė ˆģ“ģ–“ ė¼ģ“ėøŒėŸ¬ė¦¬ģ— ėŒ€ķ•“ ģžģ„øķžˆ ģ•Œģ•„ė“…ė‹ˆė‹¤].",
+ "mwe-embedplayer-clip_linkback": "ķ“ė¦½ ģ›ė³ø ķŽ˜ģ“ģ§€",
+ "mwe-embedplayer-choose_player": "ė™ģ˜ģƒ ķ”Œė ˆģ“ģ–“ ģ„ ķƒ",
+ "mwe-embedplayer-no-player": "$1ģ— ėŒ€ķ•“ ģ‚¬ģš© ź°€ėŠ„ķ•œ ķ”Œė ˆģ“ģ–“ź°€ ģ—†ģŠµė‹ˆė‹¤",
+ "mwe-embedplayer-share_this_video": "ģ“ ė™ģ˜ģƒ ź³µģœ ķ•˜źø°",
+ "mwe-embedplayer-video_credits": "ė™ģ˜ģƒ ģ œģž‘ģ§„",
+ "mwe-embedplayer-no-video_credits": "ģ‚¬ģš© ź°€ėŠ„ķ•œ ģ œģž‘ģ§„ģ“ ģ—†ģŠµė‹ˆė‹¤",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura ģ˜¤ķ”ˆ ģ†ŒģŠ¤ ė™ģ˜ģƒ ķ”Œėž«ķ¼",
+ "mwe-embedplayer-menu_btn": "ė©”ė‰“",
+ "mwe-embedplayer-close_btn": "ė‹«źø°",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC ķ”Œė ˆģ“ģ–“",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg ķ”Œė ˆģ“ģ–“",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3 ķ”Œė ˆģ“ģ–“",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AAC ķ”Œė ˆģ“ģ–“",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 ķ”Œė ˆģ“ģ–“",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM ķ”Œė ˆģ“ģ–“",
+ "mwe-embedplayer-ogg-player-oggPlugin": "ģ¼ė°˜ Ogg ķ”ŒėŸ¬ź·øģø",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime ķ”ŒėŸ¬ź·øģø",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura ķ”Œė ˆģ“ģ–“",
+ "mwe-embedplayer-ogg-player-selected": "(ģ„ ķƒėØ)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK ķ”Œė ˆģ‹œ ė³“ė¹„ģŠ¤",
+ "mwe-embedplayer-for_best_experience": "ė” ė‚˜ģ€ ė™ģ˜ģƒ ģž¬ģƒģ„ ģœ„ķ•“ģ„œėŠ”<a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">html5 ė™ģ˜ģƒ ėøŒė¼ģš°ģ €</a>ė„¼ ź¶Œģž„ķ•©ė‹ˆė‹¤.",
+ "mwe-embedplayer-download-warn": "ķ˜øķ™˜ė˜ģ§€ ģ•ŠėŠ” ėøŒė¼ģš°ģ € ģ•ˆģ˜ ķ”Œė ˆģ“ģ–“ė„¼ ź°ģ§€ķ–ˆģŠµė‹ˆė‹¤: ėøŒė¼ģš°ģ € ģ•ˆģ— ģž¬ģƒģ„ ķ•˜ė ¤ė©“ [$1 ģµœģ‹  Firefox]ė„¼ ė‹¤ģš“ė”œė“œķ•˜ģ„øģš”",
+ "mwe-embedplayer-fullscreen-tip": "<i>ģ›¹ ėøŒė¼ģš°ģ €</i>ė„¼ ģ „ģ²“ ķ™”ė©“ģœ¼ė”œ ģ „ķ™˜ķ•˜ė ¤ė©“ <b>F11</b>ģ„ ėˆ„ė„“ģ„øģš”",
+ "mwe-embedplayer-fullscreen-tip-osx": "ģ „ģ²“ ķ™”ė©“ģœ¼ė”œ ģ „ķ™˜ķ•˜ė ¤ė©“ <b>shift āŒ˜ F</b>ė„¼ ėˆ„ė„“ģ„øģš”",
+ "mwe-embedplayer-do_not_warn_again": "ė‚˜ģ¤‘ģ— ģ“ ė©”ģ‹œģ§€ė„¼ ė³“ģ—¬ģ£¼ģ§€ ģ•ŠģŒ",
+ "mwe-embedplayer-playerSelect": "ķ”Œė ˆģ“ģ–“",
+ "mwe-embedplayer-read_before_embed": "ķ¬ķ•Øķ•˜źø° ģ „ģ— <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">ģ“ źø€ģ„ ģ½ģœ¼ģ„øģš”</a>.",
+ "mwe-embedplayer-embed_site_or_blog": "ė¬øģ„œģ— ķ¬ķ•Ø",
+ "mwe-embedplayer-embed_wiki": "ģœ„ķ‚¤ģ— ķ¬ķ•Ø",
+ "mwe-embedplayer-related_videos": "ź“€ė Ø ė™ģ˜ģƒ",
+ "mwe-embedplayer-seeking": "ķƒģƒ‰ ģ¤‘",
+ "mwe-embedplayer-buffering": "ė²„ķ¼ė§",
+ "mwe-embedplayer-video-h264": "H.264 ė™ģ˜ģƒ",
+ "mwe-embedplayer-video-webm": "WebM ė™ģ˜ģƒ",
+ "mwe-embedplayer-video-flv": "ķ”Œėž˜ģ‹œ ė™ģ˜ģƒ",
+ "mwe-embedplayer-video-ogg": "Ogg ė™ģ˜ģƒ",
+ "mwe-embedplayer-video-audio": "Ogg ģ†Œė¦¬",
+ "mwe-embedplayer-audio-mpeg": "MPEG ģ†Œė¦¬",
+ "mwe-embedplayer-video-3gp": "3GP ė™ģ˜ģƒ",
+ "mwe-embedplayer-video-mpeg": "MPEG ė™ģ˜ģƒ",
+ "mwe-embedplayer-video-msvideo": "AVI ė™ģ˜ģƒ",
+ "mwe-embedplayer-missing-source": "ģ›ė³ø ė™ģ˜ģƒģ„ ģ°¾ģ„ ģˆ˜ ģ—†ģŠµė‹ˆė‹¤"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ksh.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ksh.json
new file mode 100644
index 00000000..91f9beb5
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ksh.json
@@ -0,0 +1,84 @@
+{
+ "@metadata": {
+ "authors": [
+ "Purodha"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Tittel: $1",
+ "mwe-embedplayer-credit-date": "Dattum: $1",
+ "mwe-embedplayer-credit-author": "Schriever: $1",
+ "mwe-embedplayer-nocredits": "Mer han kein Dangksaaronge ze jriefe",
+ "mwe-embedplayer-loading_plugin": "Ben dat Ongerprojramm aam laade&nbsp;ā€¦",
+ "mwe-embedplayer-select_playback": "Enstellunge fƶr et Affshpelle maache",
+ "mwe-embedplayer-link_back": "Lengk retuur",
+ "mwe-embedplayer-error_swap_vid": "FƤhler: <code lang=\"en\">mv_embed</code> kunnt de EtikƤtte fƶr dƤ Viddejo fƶr <code lang=\"en\">mv_embed</code> sing SchnetshtƤl nit uƟtuusche.",
+ "mwe-embedplayer-add_to_end_of_sequence": "Aam Engk vun dƤ AfschpellleƟ aanfƶƶje",
+ "mwe-embedplayer-missing_video_stream": "De Viddejodattei fƶr heh dƤ Daateshrom fƤhlt",
+ "mwe-embedplayer-play_clip": "Donn dƤ UƟschnedd afshpelle",
+ "mwe-embedplayer-pause_clip": "Donn dƤ UƟschnedd aanhallde",
+ "mwe-embedplayer-volume_control": "Enshtellung fƶr de LoutshtƤrk",
+ "mwe-embedplayer-player_options": "Enschtellunge fƶr Affshpellprojramme",
+ "mwe-embedplayer-timed_text": "Ongertitele met Zigge",
+ "mwe-embedplayer-player_fullscreen": "Op der janze Beldscherm jonn",
+ "mwe-embedplayer-next_clip_msg": "Donn dƤ UƟschnedd donoh shpelle",
+ "mwe-embedplayer-prev_clip_msg": "Donn dƤ UƟschnedd dovƶƶr shpelle",
+ "mwe-embedplayer-current_clip_msg": "Donn dƤ UƟschnedd wigger shpelle",
+ "mwe-embedplayer-seek_to": "Sƶhk bes: $1",
+ "mwe-embedplayer-paused": "aanjehallde",
+ "mwe-embedplayer-download_segment": "UƟwahl fƶr erunger ze laade:",
+ "mwe-embedplayer-download_full_video": "Donn dƤ janze Viddejo erunge laade:",
+ "mwe-embedplayer-download_right_click": "Zom Eronger laade, kleck met dƤ rƤƤschte TaƟd_aan Dinge MuuƟ, un sƶhk ā€žAfshpeishere onger&nbsp;ā€¦ā€œ uƟ",
+ "mwe-embedplayer-download_clip": "Viddejo erunger lade",
+ "mwe-embedplayer-download_text": "Tex erungerlaade",
+ "mwe-embedplayer-download": "Eronger laade",
+ "mwe-embedplayer-share": "Wigger jƤvve",
+ "mwe-embedplayer-credits": "Aanerkennunge fƶr BeidrƤƤsch",
+ "mwe-embedplayer-about-library": "Ɩvver der Kaltuura Schpeller",
+ "mwe-embedplayer-clip_linkback": "DƤm UƟschnett singe QuƤllsigg",
+ "mwe-embedplayer-choose_player": "Donn en Affshpellprojramm fƶr Viddejos uƟsƶhke",
+ "mwe-embedplayer-no-player": "Mer han keine Afschpeller fƶr $1",
+ "mwe-embedplayer-share_this_video": "Donn dƤ Viddejo wigger jƤvve",
+ "mwe-embedplayer-video_credits": "Aanerkennunge fƶr BeidrƤƤsch aan dƤmm Viddejo",
+ "mwe-embedplayer-no-video_credits": "Mer han kein Dangksaaronge ze jriefe",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltuura - Viddejo Projramme med offe QuƤlle",
+ "mwe-embedplayer-menu_btn": "UƟwahl",
+ "mwe-embedplayer-close_btn": "Zohmaache",
+ "mwe-embedplayer-ogg-player-vlc-player": "DƤ <i lang=\"en\">VLC</i>-Affschpeller",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5-<i lang=\"en\">Ogg</i>-Affschpeller",
+ "mwe-embedplayer-ogg-player-mp3Native": "<i lang=\"en\">MP3</i> Speller fƶr <i lang=\"en\">HTML5</i>",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5-<i lang=\"en\">MP3</i>-Affschpeller",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5-<i lang=\"en\">H.264</i>-Affschpeller",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5-<i lang=\"en\">WebM</i>-Affschpeller",
+ "mwe-embedplayer-ogg-player-oggPlugin": "DƤm <i lang=\"en\">Ogg</i>-Shpeller sing Stanndatt-<i lang=\"en\">plugin</i>",
+ "mwe-embedplayer-ogg-player-IEWebMPrompt": "Et Zohsaprojramm <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"WebM\">WebM</i> fƶr der <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Microsoft Internet Explorer\">IE</i> eronger lahde",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "DƤ <i lang=\"en\">QuickTime</i>-Shpeller als <i lang=\"en\">plugin</i>",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "DƤ <i lang=\"en\">QuickTime</i>-Shpeller ƶvver <i lang=\"en\">ActiveX</i>",
+ "mwe-embedplayer-ogg-player-cortado": "DƤ <i lang=\"en\">Java Cortado</i> Shpeller",
+ "mwe-embedplayer-ogg-player-flowplayer": "DƤ <i lang=\"en\">Flow</i>shpeller",
+ "mwe-embedplayer-ogg-player-kplayer": "DƤ <i lang=\"en\">Kaltura</i> Afshpeller",
+ "mwe-embedplayer-ogg-player-selected": "(uƟjesƶhk)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "<i lang=\"en\">OMTK Flash Vorbis</i> Shpeller",
+ "mwe-embedplayer-for_best_experience": "ƶm en bƤƟere Qualliteit fƶr dƤ Viddejo ze krijje, dom_mer der <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">HTML5-Viddejo-Browser</a> ƤmfƤhle.",
+ "mwe-embedplayer-fullscreen-tip": "Met dƤm <b>F11</b>-Knopp schalldt mer dƤ <i>Brauser</i> op der kumplƤtte Beldscherrem ƶm, un widder retuur.",
+ "mwe-embedplayer-fullscreen-tip-osx": "Met <b>Ɩmschallde-āŒ˜-F</b> schalldt mer op der kumplƤtte Beldscherrem ƶm",
+ "mwe-embedplayer-do_not_warn_again": "Donn heh di Nohreesch en Zohkonf nit norr_ens aanzeije.",
+ "mwe-embedplayer-playerSelect": "Schpeller",
+ "mwe-embedplayer-read_before_embed": "BeƟ esu joot un liƟ <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">ƶvver de Sesherheit bemm Ennfƶƶje ƶvver et Netz</a> iih dat De jet ennfƶƶschƟ!",
+ "mwe-embedplayer-embed_site_or_blog": "En en Websigg udder <i lang=\"en\">Blog</i>_erinndonn",
+ "mwe-embedplayer-embed_wiki": "En e Wiki enboue",
+ "mwe-embedplayer-related_videos": "Verwandte Viddejos",
+ "mwe-embedplayer-seeking": "aam Sƶhke",
+ "mwe-embedplayer-video-h264": "En <i lang=\"en\">H.264</i>-Viddejo-Dattei",
+ "mwe-embedplayer-video-webm": "En <i lang=\"en\">WebM</i>-Viddejo-Dattei",
+ "mwe-embedplayer-video-flv": "En <i lang=\"en\">Flash</i>-Viddejo-Dattei",
+ "mwe-embedplayer-video-ogg": "En <i lang=\"en\">Ogg</i>-Viddejo-Dattei",
+ "mwe-embedplayer-video-audio": "En <i lang=\"en\">Ogg</i>-Tohn-Dattei",
+ "mwe-embedplayer-audio-mpeg": "En <i lang=\"en\">MPEG </i>-Tohn-Dattei",
+ "mwe-embedplayer-video-3gp": "En <i lang=\"en\">3GP</i>-Viddejo-Dattei",
+ "mwe-embedplayer-video-mpeg": "En <i lang=\"en\">MPEG</i>-Viddejo-Dattei",
+ "mwe-embedplayer-video-msvideo": "En <i lang=\"en\">AVI</i>-Viddejo-Dattei",
+ "mwe-embedplayer-missing-source": "Mer han kein Viddejo-QuƤlle-Dattei jefonge",
+ "mwe-embedplayer-iewebmprompt-intro": "Eine Schrett mih, ih dat De dƤ Viddejo afschpelle kanns&nbsp;ā€¦",
+ "mwe-embedplayer-iewebmprompt-linktext": "Donn de Ongerstƶzong fƶr <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"WebM\">WebM</i> em <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\">Microsoft Internet Explorer</i> eronger lahde un enschtallehre",
+ "mwe-embedplayer-iewebmprompt-outro": "Donn heh di Sigg nohm Enschtallehre norr_ens neu lahde."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ku-latn.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ku-latn.json
new file mode 100644
index 00000000..c51aa6ca
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ku-latn.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gomada"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Sernav: $1",
+ "mwe-embedplayer-credit-date": "DƮrok: $1",
+ "mwe-embedplayer-credit-author": "XwedĆ®: $1"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ky.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ky.json
new file mode 100644
index 00000000..9098a14a
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ky.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Growingup"
+ ]
+ },
+ "mwe-embedplayer-menu_btn": "ŠœŠµŠ½ŃŽ",
+ "mwe-embedplayer-close_btn": "Š–Š°Š±ŃƒŃƒ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/lb.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/lb.json
new file mode 100644
index 00000000..b3811f5d
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/lb.json
@@ -0,0 +1,55 @@
+{
+ "@metadata": {
+ "authors": [
+ "Robby",
+ "Soued031"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titel: $1",
+ "mwe-embedplayer-credit-date": "Datum: $1",
+ "mwe-embedplayer-credit-author": "Auteur: $1",
+ "mwe-embedplayer-loading_plugin": "Plugin lueden ...",
+ "mwe-embedplayer-select_playback": "Astellunge vum Ofspillen festleeƫn",
+ "mwe-embedplayer-link_back": "Link zrƩck",
+ "mwe-embedplayer-add_to_end_of_sequence": "Um Schluss vun der Sequenz derbƤisetzen",
+ "mwe-embedplayer-missing_video_stream": "De Video-Fichier fir dƫse Stream feelt",
+ "mwe-embedplayer-play_clip": "Clip spillen",
+ "mwe-embedplayer-pause_clip": "Clip Ć«nnerbriechen",
+ "mwe-embedplayer-player_options": "Optioune vum Player",
+ "mwe-embedplayer-player_fullscreen": "Ganzen Ecran",
+ "mwe-embedplayer-next_clip_msg": "NƤchste Clip spillen",
+ "mwe-embedplayer-prev_clip_msg": "Virege Clip spillen",
+ "mwe-embedplayer-current_clip_msg": "DĆ«se Clip weiderspillen",
+ "mwe-embedplayer-seek_to": "No $1 sichen",
+ "mwe-embedplayer-paused": "Ć«nnerbrach",
+ "mwe-embedplayer-download_segment": "Dat wat erausgesicht ass eroflueden:",
+ "mwe-embedplayer-download_full_video": "Ganze Videofichier eroflueden:",
+ "mwe-embedplayer-download_full_audio": "Ganzen Audiofichier eroflueden:",
+ "mwe-embedplayer-download_right_click": "Fir erofzelueden, klickt op dƩi riets Maustast a wielt <i>Link spƤicheren als...</i>",
+ "mwe-embedplayer-download_clip": "Video eroflueden",
+ "mwe-embedplayer-download_text": "Text eroflueden",
+ "mwe-embedplayer-download": "Eroflueden",
+ "mwe-embedplayer-share": "Deelen",
+ "mwe-embedplayer-clip_linkback": "QuellsƤit vum Clip",
+ "mwe-embedplayer-share_this_video": "DĆ«se Video deelen",
+ "mwe-embedplayer-share_this_audio": "DĆ«sen Audio-Fichier deelen",
+ "mwe-embedplayer-menu_btn": "MenĆ¼",
+ "mwe-embedplayer-close_btn": "Zoumaachen",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC-Player",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "VLC fir iOS-App",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime-Plugin",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura-Player",
+ "mwe-embedplayer-ogg-player-selected": "(erausgesicht)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-do_not_warn_again": "Dƫse Message an Zukunft net mƩi weisen.",
+ "mwe-embedplayer-playerSelect": "Player",
+ "mwe-embedplayer-read_before_embed": "Liest w.e.g. virum Abannen d'<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">SĆ©cherheetsinformatiounen iwwer d'Abannen iwwer Remote</a> ier Dir mam Abanne weidermaacht!",
+ "mwe-embedplayer-embed_site_or_blog": "An Ƅr SƤit abauen",
+ "mwe-embedplayer-related_videos": "Ƅhnlech Videoen",
+ "mwe-embedplayer-seeking": "sichen",
+ "mwe-embedplayer-missing-source": "Et gouf kee Video fonnt",
+ "mwe-embedplayer-vlcapp-downloadvideo": "DĆ«se Video eroflueden",
+ "mwe-embedplayer-iewebmprompt-outro": "No der Installatioun dƫs sƤit nei lueden."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/lt.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/lt.json
new file mode 100644
index 00000000..3a3b6f50
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/lt.json
@@ -0,0 +1,90 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hugo.arg",
+ "Gediminas",
+ "Pofka"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Pavadinimas: $1",
+ "mwe-embedplayer-credit-date": "Data: $1",
+ "mwe-embedplayer-credit-author": "Autorius: $1",
+ "mwe-embedplayer-nocredits": "Nėra duomenų apie kūrėjus",
+ "mwe-embedplayer-loading_plugin": "Kraunamas ÄÆskiepis...",
+ "mwe-embedplayer-select_playback": "Nustatyti grojimo nustatymus",
+ "mwe-embedplayer-link_back": "Atgalinė nuoroda",
+ "mwe-embedplayer-error_swap_vid": "Klaida: mwEmbed negali pakeisti video žymės mwEmbed aplinkai",
+ "mwe-embedplayer-add_to_end_of_sequence": "Pridėti ÄÆ sekos galą",
+ "mwe-embedplayer-missing_video_stream": "Nėra vaizdo ÄÆraÅ”o rinkmenos Å”iam srautui",
+ "mwe-embedplayer-play_clip": "Leisti ÄÆraŔą",
+ "mwe-embedplayer-pause_clip": "Pristabdyti ÄÆraŔą",
+ "mwe-embedplayer-volume_control": "Garso valdymas",
+ "mwe-embedplayer-player_options": "Grotuvo parinktys",
+ "mwe-embedplayer-timed_text": "Priskirtas tekstas",
+ "mwe-embedplayer-player_fullscreen": "Per visą ekraną",
+ "mwe-embedplayer-next_clip_msg": "Leisti kitą ÄÆraŔą",
+ "mwe-embedplayer-prev_clip_msg": "Leisti praeitą ÄÆraŔą",
+ "mwe-embedplayer-current_clip_msg": "Tęsti Å”io ÄÆraÅ”o atlikimą",
+ "mwe-embedplayer-seek_to": "Siekti $1",
+ "mwe-embedplayer-paused": "pristabdyta",
+ "mwe-embedplayer-download_segment": "Atsisiuntimo būdas:",
+ "mwe-embedplayer-download_full_video": "Atsisiųsti visą vaizdo ÄÆraÅ”o rinkmeną:",
+ "mwe-embedplayer-download_right_click": "Atsisiuntimui spauskite deÅ”iniuoju pelės mygtuku ir pasirinkite <i>IÅ”saugoti nuorodą kaip...</i>",
+ "mwe-embedplayer-download_clip": "Atsisiųsti vaizdo ÄÆraŔą",
+ "mwe-embedplayer-download_text": "Atsisiųsti tekstą",
+ "mwe-embedplayer-download": "Atsisiųsti",
+ "mwe-embedplayer-share": "Dalintis",
+ "mwe-embedplayer-credits": "Rinkmenos duomenys",
+ "mwe-embedplayer-about-library": "Apie Kaltura grotuvą",
+ "mwe-embedplayer-clip_linkback": "ĮraŔo iŔeities puslapis",
+ "mwe-embedplayer-choose_player": "Pasirinkite vaizdo grotuvą",
+ "mwe-embedplayer-no-player": "Nėra $1 tinkamo grotuvo",
+ "mwe-embedplayer-share_this_video": "Dalintis Å”iuo ÄÆraÅ”u",
+ "mwe-embedplayer-video_credits": "Apie ÄÆraÅ”o kÅ«rėjus",
+ "mwe-embedplayer-no-video_credits": "Nėra duomenų apie kūrėjus",
+ "mwe-embedplayer-kaltura-platform-title": "ā€žKalturaā€œ atvirojo kodo ÄÆraŔų grotuvo platforma",
+ "mwe-embedplayer-menu_btn": "Parinktys",
+ "mwe-embedplayer-close_btn": "Uždaryti",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC grotuvas",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg grotuvas",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3 grotuvas",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AAC grotuvas",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 grotuvas",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM grotuvas",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Bendrasis Ogg ÄÆskiepis",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "VLC, skirtas iOS taikomajai programai",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime ÄÆskiepis",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura grotuvas",
+ "mwe-embedplayer-ogg-player-selected": "(pasirinkta)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Geresnei vaizdo ÄÆraÅ”o peržiÅ«ros kokybei siÅ«lome <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">HTML5 palaikančią narÅ”yklę</a>.",
+ "mwe-embedplayer-fullscreen-tip": "Spauskite <b>F11</b> mygtuką, kuris nustatys <i>narÅ”yklę</i> pilno ekrano režimui",
+ "mwe-embedplayer-fullscreen-tip-osx": "Spauskite <b>shift āŒ˜ F</b>, kad pereitumėte ÄÆ pilno ekrano režimą",
+ "mwe-embedplayer-do_not_warn_again": "Ateityje nerodyti Ŕio praneŔimo",
+ "mwe-embedplayer-playerSelect": "Grotuvai",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Perskaitykite tai</a> prieÅ” talpinant.",
+ "mwe-embedplayer-embed_site_or_blog": "Įterpti puslapyje",
+ "mwe-embedplayer-embed_wiki": "Talpinti wiki svetainėje",
+ "mwe-embedplayer-related_videos": "Susiję vaizdo ÄÆraÅ”ai",
+ "mwe-embedplayer-seeking": "ieŔkoma",
+ "mwe-embedplayer-buffering": "duomenų kaupimas",
+ "mwe-embedplayer-video-h264": "H.264 video",
+ "mwe-embedplayer-video-webm": "WebM video",
+ "mwe-embedplayer-video-flv": "Flash video",
+ "mwe-embedplayer-video-ogg": "Ogg video",
+ "mwe-embedplayer-video-audio": "Ogg audio",
+ "mwe-embedplayer-audio-mpeg": "MPEG audio",
+ "mwe-embedplayer-video-3gp": "3GP video",
+ "mwe-embedplayer-video-mpeg": "MPEG video",
+ "mwe-embedplayer-video-msvideo": "AVI video",
+ "mwe-embedplayer-missing-source": "Nerastas vaizdo ÄÆraÅ”o Å”altinis",
+ "mwe-embedplayer-vlcapp-intro": "Kad galėtumėte peržiÅ«rėti vaizdo ÄÆraÅ”us iPhone ar iPad ÄÆrenginiuose, jums reikia nemokamo $1.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "VLC programėlė",
+ "mwe-embedplayer-vlcapp-downloadapp": "Atsisiųsti VLC taikomąją programą iÅ” App Store internetinės krautuvės",
+ "mwe-embedplayer-vlcapp-openvideo": "Atverti Å”ÄÆ vaizdo ÄÆraŔą VLC taikomąja programa",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Atsisiųsti Å”ÄÆ vaizdo ÄÆraŔą",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "Kad galėtumėte peržiÅ«rėti vaizdo ÄÆraÅ”us Å”ioje svetainėje jums reikia nemokamos VLC taikomosios programos. Ar ją ÄÆraÅ”yti dabar?",
+ "mwe-embedplayer-iewebmprompt-intro": "Oi! Dar vienas dalykas prieÅ” paleidžiant Å”ÄÆ vaizdo ÄÆraŔą..."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/lv.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/lv.json
new file mode 100644
index 00000000..6a9d9d01
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/lv.json
@@ -0,0 +1,60 @@
+{
+ "@metadata": {
+ "authors": [
+ "Papuass"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Nosaukums: $1",
+ "mwe-embedplayer-credit-date": "Datums: $1",
+ "mwe-embedplayer-credit-author": "Autors: $1",
+ "mwe-embedplayer-loading_plugin": "Ielādē spraudni...",
+ "mwe-embedplayer-play_clip": "Atskaņot ierakstu",
+ "mwe-embedplayer-pause_clip": "Pauzēt ierakstu",
+ "mwe-embedplayer-volume_control": "Skaļuma regulÄ“Å”ana",
+ "mwe-embedplayer-player_options": "Atskaņotāja iespējas",
+ "mwe-embedplayer-player_fullscreen": "Pilnekrāna režīms",
+ "mwe-embedplayer-next_clip_msg": "Atskaņot nākamo ierakstu",
+ "mwe-embedplayer-prev_clip_msg": "Atskaņot iepriekŔējo ierakstu",
+ "mwe-embedplayer-current_clip_msg": "Turpināt atskaņot Å”o klipu",
+ "mwe-embedplayer-paused": "nopauzēts",
+ "mwe-embedplayer-download_segment": "Lejupielādes izvēle:",
+ "mwe-embedplayer-download_full": "Lejupielādēt pilnu video failu:",
+ "mwe-embedplayer-download_clip": "Lejupielādēt video",
+ "mwe-embedplayer-download_text": "Lejupielādēt tekstu",
+ "mwe-embedplayer-download": "Lejupielādēt",
+ "mwe-embedplayer-share": "Dalīties",
+ "mwe-embedplayer-about-library": "Par Kaltura atskaņotāju",
+ "mwe-embedplayer-choose_player": "Izvēlieties video atskaņotāju",
+ "mwe-embedplayer-share_this_video": "Dalīties ar Ŕo video",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura atvērtā koda video platforma",
+ "mwe-embedplayer-menu_btn": "Izvēlne",
+ "mwe-embedplayer-close_btn": "Aizvērt",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC atskaņotājs",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg atskaņotājs",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 atskaņotājs",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM atskaņotājs",
+ "mwe-embedplayer-ogg-player-oggPlugin": "VienkārŔs Ogg spraudnis",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime spraudnis",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura atskaņotājs",
+ "mwe-embedplayer-ogg-player-selected": "(izvēlēts)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-fullscreen-tip": "Nospiediet <b>F11</b>, lai pārslēgtu <i>tīmekļa pārlūku</i> pilnekrāna režīmā",
+ "mwe-embedplayer-fullscreen-tip-osx": "Nospiediet <b>shift āŒ˜ F</b>, lai pārslēgtos pilnekrāna režīmā",
+ "mwe-embedplayer-do_not_warn_again": "Turpmāk nerādÄ«t Å”o ziņojumu",
+ "mwe-embedplayer-playerSelect": "Atskaņotāji",
+ "mwe-embedplayer-embed_site_or_blog": "Iekļaut lapā",
+ "mwe-embedplayer-related_videos": "Saistītie video",
+ "mwe-embedplayer-seeking": "meklē",
+ "mwe-embedplayer-buffering": "buferizācija",
+ "mwe-embedplayer-video-h264": "H.264 video",
+ "mwe-embedplayer-video-webm": "WebM video",
+ "mwe-embedplayer-video-flv": "Flash video",
+ "mwe-embedplayer-video-ogg": "Ogg video",
+ "mwe-embedplayer-video-audio": "Ogg audio",
+ "mwe-embedplayer-audio-mpeg": "MPEG audio",
+ "mwe-embedplayer-video-3gp": "3GP video",
+ "mwe-embedplayer-video-mpeg": "MPEG video",
+ "mwe-embedplayer-video-msvideo": "AVI video"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/mk.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/mk.json
new file mode 100644
index 00000000..a31ed300
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/mk.json
@@ -0,0 +1,95 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bjankuloski06"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "ŠŠ°ŃŠ»Š¾Š²: $1",
+ "mwe-embedplayer-credit-date": "Š”Š°Ń‚ŃƒŠ¼: $1",
+ "mwe-embedplayer-credit-author": "ŠŠ²Ń‚Š¾Ń€: $1",
+ "mwe-embedplayer-nocredits": "ŠŠµŠ¼Š° Š°Š²Ń‚Š¾Ń€ŃŠŗŠø ŠæŠ¾Š“Š°Ń‚Š¾Ń†Šø",
+ "mwe-embedplayer-loading_plugin": "Š“Š¾ Š²Ń‡ŠøтуŠ²Š°Š¼ ŠæрŠøŠŗŠ»ŃƒŃ‡Š¾ŠŗŠ¾Ń‚...",
+ "mwe-embedplayer-select_playback": "ŠŸŠ¾ŃŃ‚Š°Š²Šø ŠøŠ·Š²ŠµŠ“Š±ŠµŠ½Šø Š½Š°Š³Š¾Š“уŠ²Š°ŃšŠ°",
+ "mwe-embedplayer-link_back": "ŠžŠ±Ń€Š°Ń‚Š½Š° Š²Ń€ŃŠŗŠ°",
+ "mwe-embedplayer-error_swap_vid": "Š“Ń€ŠµŃˆŠŗŠ°: mwEmbed Š½Šµ Š¼Š¾Š¶ŠµŃˆŠµ Š“Š° јŠ° сŠ¼ŠµŠ½Šø Š²ŠøŠ“ŠµŠ¾-Š¾Š·Š½Š°ŠŗŠ°Ń‚Š° Š·Š° mwEmbed-ŠæŠ¾ŃŃ€ŠµŠ“Š½ŠøŠŗŠ¾Ń‚",
+ "mwe-embedplayer-add_to_end_of_sequence": "Š”Š¾Š“Š°Ń˜ Š½Š° ŠŗрŠ°Ń˜Š¾Ń‚ Š¾Š“ Š½ŠøŠ·Š°Ń‚Š°",
+ "mwe-embedplayer-missing_video_stream": "Š’ŠøŠ“ŠµŠ¾-ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°Ń‚Š° Š·Š° Š¾Š²Š¾Ń˜ ŠŗŠ°Š½Š°Š» Š½ŠµŠ“Š¾ŃŃ‚Š°ŃŃƒŠ²Š°",
+ "mwe-embedplayer-play_clip": "ŠŸŃƒŃˆŃ‚Šø јŠ° сŠ½ŠøŠ¼ŠŗŠ°Ń‚Š°",
+ "mwe-embedplayer-pause_clip": "ŠŸŠ°ŃƒŠ·ŠøрŠ°Ń˜ сŠ½ŠøŠ¼ŠŗŠ°",
+ "mwe-embedplayer-volume_control": "Š ŠµŠ³ŃƒŠ»ŠøрŠ°ŃšŠµ Š³Š»Š°ŃŠ½Š¾ŃŃ‚",
+ "mwe-embedplayer-player_options": "ŠŠ°Š³Š¾Š“уŠ²Š°ŃšŠ° Š½Š° ŠøŠ·Š²ŠµŠ“уŠ²Š°Ń‡Š¾Ń‚",
+ "mwe-embedplayer-timed_text": "Š”ŠøŠ½Ń…Ń€Š¾Š½ŠøŠ·ŠøрŠ°Š½ тŠµŠŗст",
+ "mwe-embedplayer-player_fullscreen": "ŠŠ° цŠµŠ» ŠµŠŗрŠ°Š½",
+ "mwe-embedplayer-next_clip_msg": "ŠŸŃƒŃˆŃ‚Šø сŠ»ŠµŠ“Š½Š° сŠ½ŠøŠ¼ŠŗŠ°",
+ "mwe-embedplayer-prev_clip_msg": "ŠŸŃƒŃˆŃ‚Šø ŠæрŠµŃ‚Ń…Š¾Š“Š½Š° сŠ½ŠøŠ¼ŠŗŠ°",
+ "mwe-embedplayer-current_clip_msg": "ŠŸŃ€Š¾Š“Š¾Š»Š¶Šø сŠ¾ ŠøŠ·Š²ŠµŠ“Š±Š° Š½Š° сŠ½ŠøŠ¼ŠŗŠ°Š²Š°",
+ "mwe-embedplayer-seek_to": "ŠŸŃ€ŠµŃ˜Š“Šø Š½Š° $1",
+ "mwe-embedplayer-paused": "ŠæŠ°ŃƒŠ·ŠøрŠ°Š½Š¾",
+ "mwe-embedplayer-download_segment": "ŠŸŃ€ŠµŠ·ŠµŠ¼Šø ŠøŠ·Š±Ń€Š°Š½Š¾:",
+ "mwe-embedplayer-download_full_video": "ŠŸŃ€ŠµŠ·ŠµŠ¼ŠµŃ‚Šµ јŠ° ŠæŠ¾Š»Š½Š°Ń‚Š° Š²ŠøŠ“ŠµŠ¾-ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°:",
+ "mwe-embedplayer-download_full_audio": "ŠŸŃ€ŠµŠ·ŠµŠ¼ŠµŃ‚Šµ јŠ° ŠæŠ¾Š»Š½Š°Ń‚Š° Š°ŃƒŠ“ŠøŠ¾-ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°:",
+ "mwe-embedplayer-download_right_click": "Š—Š° Š“Š° ŠæрŠµŠ·ŠµŠ¼ŠµŃ‚Šµ, стŠøсŠ½ŠµŃ‚Šµ Š³Š¾ Š“ŠµŃŠ½Š¾Ń‚Š¾ ŠŗŠ¾ŠæчŠµ Šø Š¾Š“Š±ŠµŃ€ŠµŃ‚Šµ ā€žŠ”Š½ŠøŠ¼Šø јŠ° Š²Ń€ŃŠŗŠ°Ń‚Š° ŠŗŠ°ŠŗŠ¾...ā€œ",
+ "mwe-embedplayer-download_clip": "ŠŸŃ€ŠµŠ·ŠµŠ¼Šø Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-download_text": "ŠŸŃ€ŠµŠ·ŠµŠ¼Šø тŠµŠŗст",
+ "mwe-embedplayer-download": "ŠŸŃ€ŠµŠ·ŠµŠ¼Šø",
+ "mwe-embedplayer-share": "Š”ŠæŠ¾Š“ŠµŠ»Šø",
+ "mwe-embedplayer-credits": "ŠŠ²Ń‚Š¾Ń€Šø",
+ "mwe-embedplayer-about-library": "Š—Š° ŠøŠ·Š²ŠµŠ“уŠ²Š°Ń‡Š¾Ń‚ Kaltura",
+ "mwe-embedplayer-about-library-desc": "HTML5-Š¼ŃƒŠ»Ń‚ŠøŠ¼ŠµŠ“ŠøјŠ°Š»Š½Š°Ń‚Š° Š±ŠøŠ±Š»ŠøŠ¾Ń‚ŠµŠŗŠ° Š½Š° Kaltura Š²Šø Š¾Š²Š¾Š·Š¼Š¾Š¶ŃƒŠ²Š° уштŠµ Š²ŠµŠ“Š½Š°Ńˆ Š“Š° ŠŗŠ¾Ń€ŠøстŠøтŠµ HTML5-Š¾Š·Š½Š°ŠŗŠø <code><nowiki><video></nowiki></code> Šø <code><nowiki><audio></nowiki></code> сŠ¾ ŠµŠ“Š½Š¾Š¾Š±Ń€Š°Š·ŠµŠ½ Šø стŠ°Š½Š“Š°Ń€Š“ŠµŠ½ ŠæŠ¾ŃŃ€ŠµŠ“Š½ŠøŠŗ Š·Š° ŠøŠ·Š²ŠµŠ“уŠ²Š°Ń‡Š¾Ń‚ ŠŗŠ°Ń˜ сŠøтŠµ Š½Š°Ń˜Š·Š°ŃŃ‚Š°ŠæŠµŠ½Šø ŠæрŠµŠ»ŠøстуŠ²Š°Ń‡Šø.\n\n[$1 ŠŸŠ¾Š²ŠµŃœŠµ Š·Š° Š±ŠøŠ±Š»ŠøŠ¾Ń‚ŠµŠŗŠ°Ń‚Š° Š½Š° ŠøŠ·Š²ŠµŠ“уŠ²Š°Ń‡Š¾Ń‚ Kaltura].",
+ "mwe-embedplayer-clip_linkback": "Š˜Š·Š²Š¾Ń€Š½Š° стрŠ°Š½ŠøцŠ° Š½Š° сŠ½ŠøŠ¼ŠŗŠ°Ń‚Š°",
+ "mwe-embedplayer-choose_player": "ŠžŠ“Š±ŠµŃ€ŠµŃ‚Šµ Š²ŠøŠ“ŠµŠ¾-ŠøŠ·Š²ŠµŠ“уŠ²Š°Ń‡",
+ "mwe-embedplayer-no-player": "ŠŠµŠ¼Š° Š“Š¾ŠæстŠ°ŠæŠµŠ½ ŠøŠ·Š²ŠµŠ“уŠ²Š°Ń‡ Š·Š° $1",
+ "mwe-embedplayer-share_this_video": "Š”ŠæŠ¾Š“ŠµŠ»Šø јŠ° сŠ½ŠøŠ¼ŠŗŠ°Š²Š°",
+ "mwe-embedplayer-share_this_audio": "Š”ŠæŠ¾Š“ŠµŠ»Šø јŠ° Š°ŃƒŠ“Š¾-ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°Š²Š°",
+ "mwe-embedplayer-video_credits": "Š—Š° Š°Š²Ń‚Š¾Ń€ŠøтŠµ Š½Š° сŠ½ŠøŠ¼ŠŗŠ°Ń‚Š°",
+ "mwe-embedplayer-no-video_credits": "ŠŠµŠ¼Š° Š°Š²Ń‚Š¾Ń€ŃŠŗŠø ŠæŠ¾Š“Š°Ń‚Š¾Ń†Šø",
+ "mwe-embedplayer-kaltura-platform-title": "ŠžŃ‚Š²Š¾Ń€ŠµŠ½Š° Š²ŠøŠ“ŠµŠ¾-ŠæŠ»Š°Ń‚Ń„Š¾Ń€Š¼Š° Kaltura",
+ "mwe-embedplayer-menu_btn": "ŠœŠµŠ½Šø",
+ "mwe-embedplayer-close_btn": "Š”ŠŗрŠøј",
+ "mwe-embedplayer-ogg-player-vlc-player": "Š˜Š·Š²ŠµŠ“уŠ²Š°Ń‡ VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg-ŠøŠ·Š²ŠµŠ“уŠ²Š°Ń‡",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3-ŠøŠ·Š²ŠµŠ“уŠ²Š°Ń‡",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AAC-ŠøŠ·Š²ŠµŠ“уŠ²Š°Ń‡",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264-ŠøŠ·Š²ŠµŠ“уŠ²Š°Ń‡",
+ "mwe-embedplayer-ogg-player-webmNative": "Š˜Š·Š²ŠµŠ“уŠ²Š°Ń‡ WebM (HTML5)",
+ "mwe-embedplayer-ogg-player-oggPlugin": "ŠžŠæшт Ogg-ŠæрŠøŠŗŠ»ŃƒŃ‡Š¾Šŗ",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "Š˜Š·Š²Ń€ŃˆŠ½ŠøŠŗ VLC Š·Š° iOS",
+ "mwe-embedplayer-ogg-player-IEWebMPrompt": "ŠŸŃ€ŠµŠ·ŠµŠ¼Š°Ń‡ Š½Š° WebM-Š“Š¾Š“Š°Ń‚Š¾Šŗ Š·Š° Internet Explorer",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "ŠŸŃ€ŠøŠŗŠ»ŃƒŃ‡Š¾Šŗ QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Š˜Š·Š²ŠµŠ“уŠ²Š°Ń‡ Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(ŠøŠ·Š±Ń€Š°Š½Š¾)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Š—Š° ŠæŠ¾ŠŗŠ²Š°Š»ŠøтŠµŃ‚Š½Š¾ ŠæрŠµŠ³Š»ŠµŠ“уŠ²Š°ŃšŠµ Š½Š° сŠ½ŠøŠ¼ŠŗŠøтŠµ Š²Šø Š³Š¾ ŠæрŠµŠæŠ¾Ń€Š°Ń‡ŃƒŠ²Š°Š¼Šµ <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">Š²ŠøŠ“ŠµŠ¾ŠæрŠµŠ»ŠøстуŠ²Š°Ń‡Š¾Ń‚ сŠ¾ HTML5</a>.",
+ "mwe-embedplayer-download-warn": "ŠŠµ Š½Š°Ń˜Š“Š¾Š² ŠæрŠøŠŗŠ»Š°Š“ŠµŠ½ ŠøŠ·Š²ŠµŠ“уŠ²Š°Ń‡ Š·Š° ŠæуштŠ°ŃšŠµ Š¾Š“ ŠæрŠµŠ»ŠøстуŠ²Š°Ń‡ ŠŠŗŠ¾ сŠ°ŠŗŠ°Ń‚Šµ Š“Š° ŠæуштŠ°Ń‚Šµ Š¾Š“ ŠæрŠµŠ»ŠøстуŠ²Š°Ń‡, ŠæрŠµŠ·ŠµŠ¼ŠµŃ‚Šµ Š³Š¾ [$1 Š½Š°Ń˜Š½Š¾Š²ŠøŠ¾Ń‚ Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "ŠŸŃ€ŠøтŠøсŠ½ŠµŃ‚Šµ <b>F11</b> Š·Š° Š“Š° Š³Š¾ ŠæрŠµŃ„Ń€Š»ŠøтŠµ <i>ŠæрŠµŠ»ŠøстуŠ²Š°Ń‡Š¾Ń‚</i> Š½Š° ŠæŠ¾Š»Š½ ŠµŠŗрŠ°Š½",
+ "mwe-embedplayer-fullscreen-tip-osx": "ŠŸŃ€ŠøтŠøсŠ½ŠµŃ‚Šµ <b>shift āŒ˜ F</b> Š·Š° ŠæрŠµŠ³Š»ŠµŠ“ Š½Š° цŠµŠ» ŠµŠŗрŠ°Š½",
+ "mwe-embedplayer-do_not_warn_again": "ŠžŃ‚сŠµŠ³Š° Š½Šµ јŠ° ŠæрŠøŠŗŠ°Š¶ŃƒŠ²Š°Ń˜ Š¾Š²Š°Š° ŠæŠ¾Ń€Š°ŠŗŠ°",
+ "mwe-embedplayer-playerSelect": "Š˜Š·Š²ŠµŠ“уŠ²Š°Ń‡",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">ŠŸŃ€Š¾Ń‡ŠøтŠ°Ń˜Ń‚Šµ Š³Š¾ Š¾Š²Š°</a> ŠæрŠµŠ“ Š“Š° Š²Š¼ŠµŃ‚Š½ŃƒŠ²Š°Ń‚Šµ.",
+ "mwe-embedplayer-embed_site_or_blog": "Š’Š¼ŠµŃ‚Š½Šø Š²Š¾ стрŠ°Š½ŠøцŠ°",
+ "mwe-embedplayer-embed_wiki": "Š’Š¼ŠµŃ‚Š½Šø Š²Š¾ Š²ŠøŠŗŠø",
+ "mwe-embedplayer-related_videos": "ŠŸŠ¾Š²Ń€Š·Š°Š½Šø Š²ŠøŠ“ŠµŠ°",
+ "mwe-embedplayer-seeking": "Š±Š°Ń€Š°Š¼",
+ "mwe-embedplayer-buffering": "Š¼ŠµŃ“ŃƒŃŠŗŠ»Š°Š“ŠøрŠ°ŃšŠµ",
+ "mwe-embedplayer-video-h264": "H.264 Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-webm": "WebM-Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-flv": "Flash Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-ogg": "Ogg Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-audio": "Ogg Š°ŃƒŠ“ŠøŠ¾",
+ "mwe-embedplayer-audio-mpeg": "MPEG Š°ŃƒŠ“ŠøŠ¾",
+ "mwe-embedplayer-video-3gp": "3gp Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-mpeg": "MPEG Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-msvideo": "AVI Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-missing-source": "ŠŠµ Šµ ŠæрŠ¾Š½Š°Ń˜Š“ŠµŠ½ ŠøŠ·Š²Š¾Ń€ Š½Š° сŠ½ŠøŠ¼ŠŗŠ°Ń‚Š°.",
+ "mwe-embedplayer-vlcapp-intro": "Š—Š° Š“Š° Š³Šø Š³Š»ŠµŠ“Š°Ń‚Šµ Š²ŠøŠ“ŠµŠ°Ń‚Š° Š½Š° Š¾Š²Š°Š° стрŠ°Š½ŠøцŠ° Š½Š° iPhone ŠøŠ»Šø iPad, ќŠµ Š²Šø трŠµŠ±Š° Š±ŠµŃŠæŠ»Š°Ń‚Š½ŠøŠ¾Ń‚ ŠøŠ·Š²Ń€ŃˆŠ½ŠøŠŗ $1.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "Š˜Š·Š²Ń€ŃˆŠ½ŠøŠŗ VLC",
+ "mwe-embedplayer-vlcapp-downloadapp": "ŠŸŃ€ŠµŠ·ŠµŠ¼ŠµŃ‚Šµ Š³Š¾ ŠøŠ·Š²Ń€ŃˆŠ½ŠøŠŗŠ¾Ń‚ VLC Š¾Š“ ŠŸŃ€Š¾Š“Š°Š²Š½ŠøцŠ°Ń‚Š° Š·Š° ŠæрŠøŠ»Š¾Š·Šø (App Store)",
+ "mwe-embedplayer-vlcapp-openvideo": "ŠžŃ‚Š²Š¾Ń€Šø Š³Š¾ Š²ŠøŠ“ŠµŠ¾Š²Š¾ Š²Š¾ ŠøŠ·Š²Ń€ŃˆŠ½ŠøŠŗŠ¾Ń‚ VLC",
+ "mwe-embedplayer-vlcapp-downloadvideo": "ŠŸŃ€ŠµŠ·ŠµŠ¼Šø Š³Š¾ Š²ŠøŠ“ŠµŠ¾Š²Š¾",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "Š—Š° Š“Š° Š³Š»ŠµŠ“Š°Ń‚Šµ Š²ŠøŠ“ŠµŠ° Š½Š° стрŠ°Š½Ń†Š°Š²Š°, ќŠµ Š²Šø трŠµŠ±Š° Š±ŠµŃŠæŠ»Š°Ń‚Š½ŠøŠ¾Ń‚ ŠøŠ·Š²Ń€ŃˆŠ½ŠøŠŗ VLC. Š”Š° Š³Š¾ ŠæрŠµŠ·ŠµŠ¼Š°Š¼ сŠµŠ³Š°?",
+ "mwe-embedplayer-iewebmprompt-intro": "Š£Šæс! Š£ŃˆŃ‚Šµ Š½ŠµŃˆŃ‚Š¾ ŠæрŠµŠ“ Š“Š° Š³Š¾ ŠæуштŠøтŠµ Š²ŠøŠ“ŠµŠ¾Ń‚Š¾...",
+ "mwe-embedplayer-iewebmprompt-linktext": "Š’Š¾ŃŠæŠ¾ŃŃ‚Š°Š²ŠµŃ‚Šµ Š³Šø Š¼ŠµŠ“ŠøуŠ¼ŃŠŗŠøтŠµ Š“ŠµŠ»Š¾Š²Šø Š½Š° WebM Š·Š° Internet Explorer",
+ "mwe-embedplayer-iewebmprompt-outro": "ŠŸŃ€ŠµŠ²Ń‡ŠøтŠ°Ń˜ јŠ° стрŠ°Š½ŠøцŠ°Ń‚Š° ŠæŠ¾ Š²Š¾ŃŠæŠ¾ŃŃ‚Š°Š²ŠŗŠ°Ń‚Š°."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ml.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ml.json
new file mode 100644
index 00000000..03c562be
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ml.json
@@ -0,0 +1,96 @@
+{
+ "@metadata": {
+ "authors": [
+ "Praveenp"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "ą“¤ą“²ą“•ąµą“•ąµ†ą“Ÿąµą“Ÿąµ: $1",
+ "mwe-embedplayer-credit-date": "ą“¤ąµ€ą“Æą“¤ą“æ: $1",
+ "mwe-embedplayer-credit-author": "ą“øąµą“°ą“·ąµą“Ÿą“¾ą“µąµ: $1",
+ "mwe-embedplayer-nocredits": "ą“•ą“Ÿą“Ŗąµą“Ŗą“¾ą“Ÿąµą“•ąµ¾ ą“²ą“­ąµą“Æą“®ą“²ąµą“²",
+ "mwe-embedplayer-loading_plugin": "ą“Ŗąµą“²ą“—ąµą“—ą“æąµ» ą“¶ąµ‡ą“–ą“°ą“æą“•ąµą“•ąµą“Øąµą“Øąµ...",
+ "mwe-embedplayer-select_playback": "ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“Øąµ‹ą“Ŗą“¾ą“§ą“æą“•ąµ¾ ą“øą“œąµą“œąµ€ą“•ą“°ą“æą“•ąµą“•ąµą“•",
+ "mwe-embedplayer-link_back": "ą“Ŗą“æą“Øąµą“Øą“æą“²ąµ‡ą“Æąµą“•ąµą“•ąµ ą“•ą“£ąµą“£ą“æ ą“øąµƒą“·ąµą“Ÿą“æą“•ąµą“•ąµą“•",
+ "mwe-embedplayer-error_swap_vid": "ą“Ŗą“æą““ą“µąµ: mwEmbed ą“øą“®ąµą“Ŗąµ¼ą“•ąµą“•ą“®ąµą“–ą“¤ąµą“¤ą“æą“Øą“¾ą“Æąµą“³ąµą“³ ą“šą“²ą“šąµą“šą“æą“¤ąµą“° ą“Ÿą“¾ą“—ąµ ą“®ą“¾ą“±ąµą“±ą“¾ąµ» mwEmbed-ą“Øąµ ą“øą“¾ą“§ą“æą“šąµą“šą“æą“²ąµą“²",
+ "mwe-embedplayer-add_to_end_of_sequence": "ą“Ŗą“°ą“®ąµą“Ŗą“°ą“Æąµą“Ÿąµ† ą“’ą“Ÿąµą“µą“æąµ½ ą“šąµ‡ąµ¼ą“•ąµą“•ąµą“•",
+ "mwe-embedplayer-missing_video_stream": "ą“ˆ ą“øąµą“Ÿąµą“°ąµ€ą“®ą“æą“Øą“¾ą“Æąµą“³ąµą“³ ą“šą“²ą“šąµą“šą“æą“¤ąµą“° ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚ ą“•ą“¾ą“£ąµą“Øąµą“Øą“æą“²ąµą“²",
+ "mwe-embedplayer-play_clip": "ą“®ąµ€ą“”ą“æą“Æą“¾ą“¶ą“•ą“²ą“‚ ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“æą“Ŗąµą“Ŗą“æą“•ąµą“•ąµą“•",
+ "mwe-embedplayer-pause_clip": "ą“®ąµ€ą“”ą“æą“Æą“¾ą“¶ą“•ą“²ą“‚ ą“¤ą“¤ąµą“•ą“¾ą“²ą“‚ ą“Øą“æąµ¼ą“¤ąµą“¤ąµą“•",
+ "mwe-embedplayer-volume_control": "ą“¶ą“¬ąµą“¦ ą“Øą“æą“Æą“Øąµą“¤ąµą“°ą“£ą“‚",
+ "mwe-embedplayer-player_options": "ą“Ŗąµą“²ąµ‡ą“Æąµ¼ ą“ą“šąµą“›ą“æą“•ą“™ąµą“™ąµ¾",
+ "mwe-embedplayer-timed_text": "ą“øą“®ą“Æą“®ą“Øąµą“øą“°ą“æą“šąµą“šąµą“³ąµą“³ ą“Žą““ąµą“¤ąµą“¤ąµ",
+ "mwe-embedplayer-player_fullscreen": "ą“Ŗąµ‚ąµ¼ą“£ąµą“£ą“øąµą“•ąµą“°ąµ€ąµ»",
+ "mwe-embedplayer-next_clip_msg": "ą“…ą“Ÿąµą“¤ąµą“¤ ą“®ąµ€ą“”ą“æą“Æą“¾ą“¶ą“•ą“²ą“‚ ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“æą“Ŗąµą“Ŗą“æą“•ąµą“•ąµą“•",
+ "mwe-embedplayer-prev_clip_msg": "ą“®ąµąµ» ą“®ąµ€ą“”ą“æą“Æą“¾ą“¶ą“•ą“²ą“‚ ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“æą“Ŗąµą“Ŗą“æą“•ąµą“•ąµą“•",
+ "mwe-embedplayer-current_clip_msg": "ą“ˆ ą“®ąµ€ą“”ą“æą“Æą“¾ą“¶ą“•ą“²ą“‚ ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“æą“Ŗąµą“Ŗą“æą“•ąµą“•ąµą“Øąµą“Øą“¤ąµ ą“¤ąµą“Ÿą“°ąµą“•",
+ "mwe-embedplayer-seek_to": "$1 ą“Øąµ‹ą“•ąµą“•ąµą“•",
+ "mwe-embedplayer-paused": "ą“¤ą“¤ąµą“•ą“¾ą“²ą“‚ ą“Øą“æąµ¼ą“¤ąµą“¤ą“æą“µąµ†ą“šąµą“šą“æą“°ą“æą“•ąµą“•ąµą“Øąµą“Øąµ",
+ "mwe-embedplayer-download_segment": "ą“¤ą“æą“°ą“žąµą“žąµ†ą“Ÿąµą“¤ąµą“¤ą“¤ąµ ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“•:",
+ "mwe-embedplayer-download_full_video": "ą“Ŗąµ‚ąµ¼ą“£ąµą“£ ą“šą“²ą“šąµą“šą“æą“¤ąµą“° ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚ ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“•:",
+ "mwe-embedplayer-download_full_audio": "ą“Ŗąµ‚ąµ¼ą“£ąµą“£ ą“¶ą“¬ąµą“¦ ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚ ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“•:",
+ "mwe-embedplayer-download_right_click": "ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“µą“¾ą“Øą“¾ą“Æą“æ, ą“±ąµˆą“±ąµą“±ąµ ą“•ąµą“²ą“æą“•ąµą“•ąµ ą“šąµ†ą“Æąµą“¤ą“¶ąµ‡ą“·ą“‚ <i>Save link as...</i> ą“Žą“Øąµą“Øą“¤ąµą“Ŗą“Æąµ‹ą“—ą“æą“•ąµą“•ąµą“•",
+ "mwe-embedplayer-download_clip": "ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚ ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“•",
+ "mwe-embedplayer-download_text": "ą“Žą““ąµą“¤ąµą“¤ąµ ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“•",
+ "mwe-embedplayer-download": "ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“•",
+ "mwe-embedplayer-share": "ą“Ŗą“™ąµą“•ąµ ą“µąµ†ą“Æąµą“•ąµą“•ąµą“•",
+ "mwe-embedplayer-credits": "ą“•ą“Ÿą“Ŗąµą“Ŗą“¾ą“Ÿąµą“•ąµ¾",
+ "mwe-embedplayer-about-library": "ą“•ąµ½ą“Ÿąµ‚ą“± ą“Ŗąµą“²ąµ‡ą“Æąµ¼ ą“µą“æą“µą“°ą“£ą“‚",
+ "mwe-embedplayer-about-library-desc": "ą“•ąµ½ą“Ÿąµ‚ą“±ą“Æąµą“Ÿąµ† ą“Žą“šąµą“šąµ.ą“±ąµą“±ą“æ.ą“Žą“‚.ą“Žąµ½.5 ą“®ąµ€ą“”ą“æą“Æ ą“²ąµˆą“¬ąµą“°ą“±ą“æ, ą“‡ą“Øąµą“Øą“¤ąµą“¤ąµ† ą“Žą“²ąµą“²ą“¾ ą“Ŗąµą“°ą“§ą“¾ą“Ø ą“¬ąµą“°ąµ—ą“øą“±ąµą“•ą“³ą“æą“²ąµą“‚ ą“øąµą“øąµą“„ą“æą“°ą“®ą“¾ą“Æ ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“Øąµ‹ą“Ŗą“¾ą“§ą“æą“Æąµą“•ąµą“•ąµą“³ąµą“³ ą“øą“®ąµą“Ŗąµ¼ą“•ąµą“•ą“®ąµą“–ą“¤ąµą“¤ąµ‹ą“Ÿąµ† ą“Žą“šąµą“šąµ.ą“±ąµą“±ą“æ.ą“Žą“‚.ą“Žąµ½.5-ą“²ąµ† &lt;video&gt;, &lt;audio&gt; ą“Žą“Øąµą“Øąµ€ ą“Ÿą“¾ą“—ąµą“•ąµ¾ ą“‰ą“Ŗą“Æąµ‹ą“—ą“æą“•ąµą“•ą“¾ąµ» ą“¤ą“¾ą“™ąµą“•ą“³ąµ† ą“…ą“Øąµą“µą“¦ą“æą“•ąµą“•ąµą“Øąµą“Øąµ.\n\n[$1 ą“•ąµ½ą“Ÿąµ‚ą“± ą“Ŗąµą“²ąµ‡ą“Æąµ¼ ą“²ąµˆą“¬ąµą“°ą“±ą“æą“Æąµ†ą“•ąµą“•ąµą“±ą“æą“šąµą“šąµ ą“•ąµ‚ą“Ÿąµą“¤ąµ½].",
+ "mwe-embedplayer-clip_linkback": "ą“®ąµ€ą“”ą“æą“Æą“¾ą“¶ą“•ą“²ą“¤ąµą“¤ą“æą“Øąµą“±ąµ† ą“øąµą“°ąµ‹ą“¤ą“øąµ ą“¤ą“¾ąµ¾",
+ "mwe-embedplayer-choose_player": "ą“šą“²ą“šąµą“šą“æą“¤ąµą“° ą“Ŗąµą“²ąµ‡ą“Æąµ¼ ą“¤ą“æą“°ą“žąµą“žąµ†ą“Ÿąµą“•ąµą“•ąµą“•",
+ "mwe-embedplayer-no-player": "$1 ą“Žą“Øąµą“Øą“¤ą“æą“Øąµą“³ąµą“³ ą“Ŗąµą“²ąµ‡ą“Æą“±ąµą“•ąµ¾ ą“²ą“­ąµą“Æą“®ą“²ąµą“²",
+ "mwe-embedplayer-share_this_video": "ą“ˆ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚ ą“Ŗą“™ąµą“•ąµ ą“µąµ†ą“Æąµą“•ąµą“•ąµą“•",
+ "mwe-embedplayer-share_this_audio": "ą“ˆ ą“¶ą“¬ąµą“¦ ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚ ą“Ŗą“™ąµą“•ąµ ą“µąµ†ą“Æąµą“•ąµą“•ąµą“•",
+ "mwe-embedplayer-video_credits": "ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“¤ąµą“¤ą“æą“Øąµą“³ąµą“³ ą“•ą“Ÿą“Ŗąµą“Ŗą“¾ą“Ÿąµą“•ąµ¾",
+ "mwe-embedplayer-no-video_credits": "ą“•ą“Ÿą“Ŗąµą“Ŗą“¾ą“Ÿąµą“•ąµ¾ ą“²ą“­ąµą“Æą“®ą“²ąµą“²",
+ "mwe-embedplayer-kaltura-platform-title": "ą“•ąµ½ą“Ÿąµ‚ą“± ą““ą“Ŗąµą“Ŗąµŗ ą“øąµ‹ą““ąµą“øąµ ą“šą“²ą“šąµą“šą“æą“¤ąµą“° ą“Ŗąµą“²ą“¾ą“±ąµą“±ąµā€Œą“«ąµ‹ą“‚",
+ "mwe-embedplayer-menu_btn": "ą“‰ą“³ąµą“³ą“Ÿą“•ąµą“•ą“‚",
+ "mwe-embedplayer-close_btn": "ą“…ą“Ÿą“Æąµą“•ąµą“•ąµą“•",
+ "mwe-embedplayer-ogg-player-vlc-player": "ą“µą“æ.ą“Žąµ½.ą“øą“æ. ą“Ŗąµą“²ąµ‡ą“Æąµ¼",
+ "mwe-embedplayer-ogg-player-oggNative": "ą“Žą“šąµą“šąµ.ą“±ąµą“±ą“æ.ą“Žą“‚.ą“Žąµ½.5 ą““ą“—ąµ ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“Øąµ‹ą“Ŗą“•ą“°ą“£ą“‚",
+ "mwe-embedplayer-ogg-player-mp3Native": "ą“Žą“šąµą“šąµ.ą“±ąµą“±ą“æ.ą“Žą“‚.ą“Žąµ½.5 ą“Žą“‚.ą“Ŗą“æ.3 ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“Øąµ‹ą“Ŗą“•ą“°ą“£ą“‚",
+ "mwe-embedplayer-ogg-player-aacNative": "ą“Žą“šąµą“šąµ.ą“±ąµą“±ą“æ.ą“Žą“‚.ą“Žąµ½.5 ą“Ž.ą“Ž.ą“øą“æ. ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“Øąµ‹ą“Ŗą“•ą“°ą“£ą“‚",
+ "mwe-embedplayer-ogg-player-h264Native": "ą“Žą“šąµą“šąµ.ą“±ąµą“±ą“æ.ą“Žą“‚.ą“Žąµ½.5 ą“Žą“šąµą“šąµ.264 ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“Øąµ‹ą“Ŗą“•ą“°ą“£ą“‚",
+ "mwe-embedplayer-ogg-player-webmNative": "ą“Žą“šąµą“šąµ.ą“±ąµą“±ą“æ.ą“Žą“‚.ą“Žąµ½.5 ą“µąµ†ą“¬ąµā€Œą“Žą“‚ ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“Øąµ‹ą“Ŗą“•ą“°ą“£ą“‚",
+ "mwe-embedplayer-ogg-player-oggPlugin": "ą“œąµ†ą“Øą“±ą“æą“•ąµ ą““ą“—ąµ ą“Ŗąµą“²ą“—ą“æąµ»",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "ą“ą“’ą“Žą“øąµ ą“†ą“Ŗą“æą“Øąµą“³ąµą“³ ą“µą“æ.ą“Žąµ½.ą“øą“æ.",
+ "mwe-embedplayer-ogg-player-IEWebMPrompt": "ą“.ą“‡. ą“µąµ†ą“¬ąµą“Žą“‚ ą“Ŗąµą“²ą“—ą“æąµ» ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ¼",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "ą“•ąµą“µą“æą“•ąµą“•ąµą“±ąµą“±ąµˆą“‚ ą“Ŗąµą“²ą“—ą“æąµ»",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "ą“•ąµą“µą“æą“•ąµą“•ąµą“±ąµą“±ąµˆą“‚ ą“†ą“•ąµą“±ąµą“±ąµ€ą“µąµā€Œā€Œą“Žą“•ąµą“øąµ",
+ "mwe-embedplayer-ogg-player-cortado": "ą“œą“¾ą“µ ą“•ąµ‹ąµ¼ą“±ąµą“±ą“¾ą“”ąµ‹",
+ "mwe-embedplayer-ogg-player-flowplayer": "ą“«ąµą“²ąµ‹ą“Ŗąµą“²ąµ‡ą“Æąµ¼",
+ "mwe-embedplayer-ogg-player-kplayer": "ą“•ąµ½ą“Ÿąµ‚ą“± ą“Ŗąµą“²ąµ‡ą“Æąµ¼",
+ "mwe-embedplayer-ogg-player-selected": "(ą“¤ą“æą“°ą“žąµą“žąµ†ą“Ÿąµą“¤ąµą“¤ą“µ)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "ą““ā€Œā€Œą“Žą“‚ą“±ąµą“±ą“æą“•ąµ† ą“«ąµą“²ą“¾ą“·ąµ ą“µąµ‹ąµ¼ą“¬ą“æą“øąµ",
+ "mwe-embedplayer-for_best_experience": "ą“®ąµ†ą“šąµą“šą“Ŗąµą“Ŗąµ†ą“Ÿąµą“Ÿ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“¾ą“øąµą“µą“¾ą“¦ą“Øą“¤ąµą“¤ą“æą“Øąµ ą“žą“™ąµą“™ąµ¾ ą“Øą“æąµ¼ą“¦ąµą“¦ąµ‡ą“¶ą“æą“•ąµą“•ąµą“Øąµą“Øą“¤ąµ <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">ą“Žą“šąµą“šąµ.ą“±ąµą“±ą“æ.ą“Žą“‚.ą“Žąµ½.5 ą“µąµ€ą“”ą“æą“Æąµ‹ ą“¬ąµą“°ąµ—ą“øąµ¼</a> ą“†ą“£ąµ.",
+ "mwe-embedplayer-download-warn": "ą“¬ąµą“°ąµ—ą“øą“±ą“æą“Øąµą“³ąµą“³ą“æąµ½ ą“…ą“Øąµą“°ąµ‚ą“Ŗą“®ą“¾ą“Æ ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“Øąµ‹ą“Ŗą“•ą“°ą“£ą“‚ ą“•ą“£ąµą“Ÿąµ†ą“¤ąµą“¤ą“¾ą“Øą“¾ą“Æą“æą“²ąµą“²: ą“¬ąµą“°ąµ—ą“øą“±ą“æą“Øąµą“³ąµą“³ą“æąµ½ ą“¤ą“Øąµą“Øąµ† ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“æą“Ŗąµą“Ŗą“æą“•ąµą“•ą“¾ąµ», ą“¦ą“Æą“µą“¾ą“Æą“æ [$1 ą“ą“±ąµą“±ą“µąµą“‚ ą“Ŗąµą“¤ą“æą“Æ ą“«ą“Æąµ¼ą“«ąµ‹ą“•ąµą“øąµ] ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“•",
+ "mwe-embedplayer-fullscreen-tip": " <i>ą“µąµ†ą“¬ąµ ą“¬ąµą“°ąµ—ą“øąµ¼</i> ą“øąµą“•ąµą“°ąµ€ąµ» ą“Øą“æą“±ą“žąµą“žąµ ą“•ą“¾ą“£ą“¾ą“Øąµą“‚ ą“®ą“¾ą“±ąµą“±ą“¾ą“Øąµą“‚ <b>F11</b> ą“…ą“®ąµ¼ą“¤ąµą“¤ąµą“•",
+ "mwe-embedplayer-fullscreen-tip-osx": "ą“øąµą“•ąµą“°ąµ€ąµ» ą“Øą“æą“±ą“žąµą“žąµ ą“•ą“¾ą“£ą“¾ą“Øąµą“‚ ą“®ą“¾ą“±ąµą“±ą“¾ą“Øąµą“‚ <b>ą“·ą“æą“«ąµą“±ąµą“±ąµ āŒ˜ F</b> ą“…ą“®ąµ¼ą“¤ąµą“¤ąµą“•",
+ "mwe-embedplayer-do_not_warn_again": "ą“­ą“¾ą“µą“æą“Æą“æąµ½ ą“ˆ ą“øą“Øąµą“¦ąµ‡ą“¶ą“‚ ą“•ą“¾ą“£ą“æą“•ąµą“•ąµ‡ą“£ąµą“Ÿą“¤ą“æą“²ąµą“²",
+ "mwe-embedplayer-playerSelect": "ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“Øąµ‹ą“Ŗą“¾ą“§ą“æą“•ąµ¾",
+ "mwe-embedplayer-read_before_embed": "ą“‰ąµ¾ą“Ŗąµą“Ŗąµ†ą“Ÿąµą“¤ąµą“¤ąµą“Øąµą“Øą“¤ą“æą“Øąµ ą“®ąµą“®ąµą“Ŗąµ <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">ą“‡ą“¤ąµ ą“µą“¾ą“Æą“æą“•ąµą“•ąµą“•</a>.",
+ "mwe-embedplayer-embed_site_or_blog": "ą“’ą“°ąµ ą“¤ą“¾ą“³ą“æąµ½ ą“‰ąµ¾ą“Ŗąµą“Ŗąµ†ą“Ÿąµą“¤ąµą“¤ąµą“•",
+ "mwe-embedplayer-embed_wiki": "ą“’ą“°ąµ ą“µą“æą“•ąµą“•ą“æą“Æą“æąµ½ ą“‰ąµ¾ą“Ŗąµą“Ŗąµ†ą“Ÿąµą“¤ąµą“¤ąµą“•",
+ "mwe-embedplayer-related_videos": "ą“¬ą“Øąµą“§ą“Ŗąµą“Ŗąµ†ą“Ÿąµą“Ÿ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“™ąµą“™ąµ¾",
+ "mwe-embedplayer-seeking": "ą“Øąµ‹ą“•ąµą“•ąµą“Øąµą“Øąµ",
+ "mwe-embedplayer-buffering": "ą“¬ą“«ą“±ą“æą“™ąµ",
+ "mwe-embedplayer-video-h264": "ą“Žą“šąµą“šąµ.264 ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚",
+ "mwe-embedplayer-video-webm": "ą“µąµ†ą“¬ąµā€Œą“Žą“‚ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚",
+ "mwe-embedplayer-video-flv": "ą“«ąµą“²ą“¾ą“·ąµ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚",
+ "mwe-embedplayer-video-ogg": "ą““ą“—ąµ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚",
+ "mwe-embedplayer-video-audio": "ą““ą“—ąµ ą“¶ą“¬ąµą“¦ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚",
+ "mwe-embedplayer-audio-mpeg": "ą“Žą“‚ą“Ŗąµ†ą“—ąµ ą“¶ą“¬ąµą“¦ą“‚",
+ "mwe-embedplayer-video-3gp": "3ą“œą“æ.ą“Ŗą“æ. ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚",
+ "mwe-embedplayer-video-mpeg": "ą“Žą“‚ą“Ŗąµ†ą“—ąµ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚",
+ "mwe-embedplayer-video-msvideo": "ą“Ž.ą“µą“æ.ą“. ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚",
+ "mwe-embedplayer-missing-source": "ą“øąµą“°ąµ‹ą“¤ą“øąµą“øąµ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚ ą“•ą“£ąµą“Ÿąµ†ą“¤ąµą“¤ą“¾ą“Øą“¾ą“Æą“æą“²ąµą“²",
+ "mwe-embedplayer-vlcapp-intro": "ą“ˆ ą“øąµˆą“±ąµą“±ą“æąµ½ ą“Øą“æą“Øąµą“Øąµą“®ąµą“³ąµą“³ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“™ąµą“™ąµ¾ ą“ą“«ąµ‹ą“£ą“æą“²ąµ‹ ą“ą“Ŗą“¾ą“”ą“æą“²ąµ‹ ą“•ą“¾ą“£ąµą“Øąµą“Øą“¤ą“æą“Øą“¾ą“Æą“æ ą“øąµ—ą“œą“Øąµą“Æ $1 ą“†ą“µą“¶ąµą“Æą“®ą“¾ą“£ąµ.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "ą“µą“æ.ą“Žąµ½.ą“øą“æ. ą“†ą“Ŗąµ",
+ "mwe-embedplayer-vlcapp-downloadapp": "ą“†ą“Ŗąµ ą“øąµą“±ąµą“±ąµ‹ą“±ą“æąµ½ ą“Øą“æą“Øąµą“Øąµą“‚ ą“µą“æ.ą“Žąµ½.ą“øą“æ. ą“†ą“Ŗąµ ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“•",
+ "mwe-embedplayer-vlcapp-openvideo": "ą“ˆ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚ ą“µą“æ.ą“Žąµ½.ą“øą“æ. ą“†ą“Ŗą“æąµ½ ą“¤ąµą“±ą“•ąµą“•ąµą“•",
+ "mwe-embedplayer-vlcapp-downloadvideo": "ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚ ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“•",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "ą“ˆ ą“øąµˆą“±ąµą“±ą“æąµ½ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“™ąµą“™ąµ¾ ą“Ŗąµą“°ą“¦ąµ¼ą“¶ą“æą“Ŗąµą“Ŗą“æą“•ąµą“•ą“¾ąµ», ą“øąµ—ą“œą“Øąµą“Æ ą“µą“æ.ą“Žąµ½.ą“øą“æ. ą“†ą“Ŗąµ ą“†ą“µą“¶ąµą“Æą“®ą“¾ą“£ąµ. ą“‡ąµ»ą“øąµą“±ąµą“±ąµ‹ąµ¾ ą“šąµ†ą“Æąµą“Æą“£ąµ‹?",
+ "mwe-embedplayer-iewebmprompt-intro": "ą“…ą“Æąµą“Æąµ‹! ą“ˆ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚ ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“æą“•ąµą“•ąµą“Øąµą“Øą“¤ą“æą“Øąµ ą“®ąµą“®ąµą“Ŗąµ ą“šąµ†ą“Æąµą“Æąµ‡ą“£ąµą“Ÿ ą“’ą“°ąµ ą“•ą“¾ą“°ąµą“Æą“‚ ą“•ąµ‚ą“Ÿą“æ...",
+ "mwe-embedplayer-iewebmprompt-linktext": "ą“‡ą“Øąµą“±ąµ¼ą“Øąµ†ą“±ąµą“±ąµ ą“Žą“•ąµą“øąµą“Ŗąµą“²ąµ‹ą“±ą“±ą“æą“Øąµą“³ąµą“³ ą“µąµ†ą“¬ąµą“Žą“‚ ą“®ąµ€ą“”ą“æą“Æ ą“­ą“¾ą“—ą“™ąµą“™ąµ¾ ą“‡ąµ»ą“øąµą“±ąµą“±ąµ‹ąµ¾ ą“šąµ†ą“Æąµą“Æąµą“•",
+ "mwe-embedplayer-iewebmprompt-outro": "ą“‡ąµ»ą“øąµą“±ąµą“±ąµ‹ąµ¾ ą“šąµ†ą“Æąµą“¤ ą“¶ąµ‡ą“·ą“‚ ą“ˆ ą“¤ą“¾ąµ¾ ą“µąµ€ą“£ąµą“Ÿąµą“®ąµ†ą“Ÿąµą“•ąµą“•ąµą“•."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ms.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ms.json
new file mode 100644
index 00000000..f19d2f22
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ms.json
@@ -0,0 +1,82 @@
+{
+ "@metadata": {
+ "authors": [
+ "Anakmalaysia"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Tajuk: $1",
+ "mwe-embedplayer-credit-date": "Tarikh: $1",
+ "mwe-embedplayer-credit-author": "Pengarang: $1",
+ "mwe-embedplayer-nocredits": "Tidak terdapat kredit",
+ "mwe-embedplayer-loading_plugin": "Plugin sedang dimuatkan...",
+ "mwe-embedplayer-select_playback": "Tetapan tayangan video",
+ "mwe-embedplayer-link_back": "Paut balik",
+ "mwe-embedplayer-error_swap_vid": "Ralat: mwEmbed tidak dapat menukar teg video untuk antaramuka mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Tambah pada hujung urutan",
+ "mwe-embedplayer-missing_video_stream": "Fail video untuk strim ini tidak dijumpai",
+ "mwe-embedplayer-play_clip": "Putarkan klip",
+ "mwe-embedplayer-pause_clip": "Hentikan klip sejenak",
+ "mwe-embedplayer-volume_control": "Kawalan kelantangan bunyi",
+ "mwe-embedplayer-player_options": "Pilihan pemain",
+ "mwe-embedplayer-timed_text": "Teks bermasa",
+ "mwe-embedplayer-player_fullscreen": "Skrin penuh",
+ "mwe-embedplayer-next_clip_msg": "Putarkan klip seterusnya",
+ "mwe-embedplayer-prev_clip_msg": "Putarkan klip sebelumnya",
+ "mwe-embedplayer-current_clip_msg": "Sambung putarkan klip ini",
+ "mwe-embedplayer-seek_to": "Cari $1",
+ "mwe-embedplayer-paused": "dihentikan sejenak",
+ "mwe-embedplayer-download_segment": "Muat turun pilihan:",
+ "mwe-embedplayer-download_full": "Muat turun fail video selengkapnya:",
+ "mwe-embedplayer-download_right_click": "Untuk memuat turun, klik kanan dan pilih <i>Save link as...</i>",
+ "mwe-embedplayer-download_clip": "Muat turun video",
+ "mwe-embedplayer-download_text": "Muat turun teks",
+ "mwe-embedplayer-download": "Muat turun",
+ "mwe-embedplayer-share": "Kongsi",
+ "mwe-embedplayer-credits": "Kredit",
+ "mwe-embedplayer-about-library": "Tentang pemain Kaltura",
+ "mwe-embedplayer-about-library-desc": "Pustaka media HTML5 Kaltura kini membolehkan anda untuk memanfaatkan teg-teg HTML5 &lt;video&gt; dan &lt;audio&gt; dengan antaramuka pemain yang konsisten di semua pelayar utama.\n\n[$1 Maklumat lanjut tentang pustaka Kaltura].",
+ "mwe-embedplayer-clip_linkback": "Halaman sumber klip",
+ "mwe-embedplayer-choose_player": "Pilih pemain video",
+ "mwe-embedplayer-no-player": "Tidak terdapat pemain untuk $1",
+ "mwe-embedplayer-share_this_video": "Kongsi video ini",
+ "mwe-embedplayer-video_credits": "Kredit video",
+ "mwe-embedplayer-no-video_credits": "Tidak terdapat kredit",
+ "mwe-embedplayer-kaltura-platform-title": "Platform video sumber terbuka Kaltura",
+ "mwe-embedplayer-menu_btn": "Menu",
+ "mwe-embedplayer-close_btn": "Tutup",
+ "mwe-embedplayer-ogg-player-vlc-player": "Pemain VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Pemain Ogg HTML5",
+ "mwe-embedplayer-ogg-player-mp3Native": "Pemain MP3 HTML5",
+ "mwe-embedplayer-ogg-player-aacNative": "Pemain AAC HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "Pemain H.264 HTML5",
+ "mwe-embedplayer-ogg-player-webmNative": "Pemain WebM HTML5",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Plugin Ogg am",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Plugin QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(dipilih)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Untuk tontonan video yang lebih baik, kami mencadangkan <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">pelayar video HTML5</a>.",
+ "mwe-embedplayer-download-warn": "Tiada pemain dalam pelayar serasi yang dikesan: untuk menayangkan video dalam pelayar, sila muat turun [$1 Firefox terbaru]",
+ "mwe-embedplayer-fullscreen-tip": "Tekan <b>F11</b> untuk menogol <i>pelayar web</i> ke skrin penuh",
+ "mwe-embedplayer-fullscreen-tip-osx": "Tekan <b>shift āŒ˜ F</b> untuk ke skrin penuh",
+ "mwe-embedplayer-do_not_warn_again": "Jangan paparkan mesej ini lagi",
+ "mwe-embedplayer-playerSelect": "Pemain",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Baca ini</a> sebelum menyiratkan video.",
+ "mwe-embedplayer-embed_site_or_blog": "Siratkan pada halaman",
+ "mwe-embedplayer-embed_wiki": "Siratkan pada wiki",
+ "mwe-embedplayer-related_videos": "Video-video berkaitan",
+ "mwe-embedplayer-seeking": "mencari",
+ "mwe-embedplayer-buffering": "menimbal",
+ "mwe-embedplayer-video-h264": "video H.264",
+ "mwe-embedplayer-video-webm": "video WebM",
+ "mwe-embedplayer-video-flv": "video Flash",
+ "mwe-embedplayer-video-ogg": "video Ogg",
+ "mwe-embedplayer-video-audio": "audio Ogg",
+ "mwe-embedplayer-audio-mpeg": "audio MPEG",
+ "mwe-embedplayer-video-3gp": "video 3GP",
+ "mwe-embedplayer-video-mpeg": "video MPEG",
+ "mwe-embedplayer-video-msvideo": "video AVI",
+ "mwe-embedplayer-missing-source": "Video sumber tidak dijumpai"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/mt.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/mt.json
new file mode 100644
index 00000000..9414549e
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/mt.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chrisportelli"
+ ]
+ },
+ "mwe-embedplayer-close_btn": "Agħlaq",
+ "mwe-embedplayer-ogg-player-selected": "(magħżul)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-do_not_warn_again": "Fil-futur, turix dan il-messaĔĔ",
+ "mwe-embedplayer-playerSelect": "Plejers",
+ "mwe-embedplayer-related_videos": "Vidjows relatati",
+ "mwe-embedplayer-video-h264": "Vidjow H.264",
+ "mwe-embedplayer-video-webm": "Vidjow WebM",
+ "mwe-embedplayer-video-flv": "Vidjow Flash",
+ "mwe-embedplayer-video-ogg": "Vidjow Ogg",
+ "mwe-embedplayer-video-audio": "Awdjo Ogg",
+ "mwe-embedplayer-audio-mpeg": "Awdjo MPEG",
+ "mwe-embedplayer-video-3gp": "Vidjow 3GP",
+ "mwe-embedplayer-video-mpeg": "Vidjow MPEG",
+ "mwe-embedplayer-video-msvideo": "Vidjow AVI",
+ "mwe-embedplayer-missing-source": "L-ebda sors ta' vidjow ma nstab"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nb.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nb.json
new file mode 100644
index 00000000..00a6c126
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nb.json
@@ -0,0 +1,92 @@
+{
+ "@metadata": {
+ "authors": [
+ "Danmichaelo",
+ "Nghtwlkr"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Tittel: $1",
+ "mwe-embedplayer-credit-date": "Dato: $1",
+ "mwe-embedplayer-credit-author": "Opphavsperson: $1",
+ "mwe-embedplayer-nocredits": "Ingen kreditering tilgjengelig",
+ "mwe-embedplayer-loading_plugin": "Laster utvidelse ...",
+ "mwe-embedplayer-select_playback": "Angi avspillingsinnstillinger",
+ "mwe-embedplayer-link_back": "Lenk tilbake",
+ "mwe-embedplayer-error_swap_vid": "Feil: mwEmbed kunne ikke bytte ut videoelementet for mwEmbed-grensesnittet",
+ "mwe-embedplayer-add_to_end_of_sequence": "Legg til pƄ slutten av sekvensen",
+ "mwe-embedplayer-missing_video_stream": "Videofilen for denne strĆømmen mangler",
+ "mwe-embedplayer-play_clip": "Spill av klipp",
+ "mwe-embedplayer-pause_clip": "Pause klipp",
+ "mwe-embedplayer-volume_control": "Volumkontroll",
+ "mwe-embedplayer-player_options": "Avspillerinnstillinger",
+ "mwe-embedplayer-timed_text": "Tidsbestemt tekst",
+ "mwe-embedplayer-player_fullscreen": "Fullskjerm",
+ "mwe-embedplayer-next_clip_msg": "Spill av neste klipp",
+ "mwe-embedplayer-prev_clip_msg": "Spill av forrige klipp",
+ "mwe-embedplayer-current_clip_msg": "Fortsett Ć„ spille av dette klippet",
+ "mwe-embedplayer-seek_to": "SĆøk $1",
+ "mwe-embedplayer-paused": "pauset",
+ "mwe-embedplayer-download_segment": "Last ned utvalg:",
+ "mwe-embedplayer-download_full_video": "Last ned hele videofilen:",
+ "mwe-embedplayer-download_full_audio": "Last ned hele lydfilen:",
+ "mwe-embedplayer-download_right_click": "For Ć„ laste ned, hĆøyreklikk og velg <i>Lagre lenke som...</i>",
+ "mwe-embedplayer-download_clip": "Last ned video",
+ "mwe-embedplayer-download_text": "Last ned tekst",
+ "mwe-embedplayer-download": "Last ned",
+ "mwe-embedplayer-share": "Del",
+ "mwe-embedplayer-credits": "Info",
+ "mwe-embedplayer-about-library": "Om Kaltura-avspilleren",
+ "mwe-embedplayer-about-library-desc": "Kaltura HTML5-biblioteket gir muligheten til Ƅ ta i bruk HTML5-taggene &lt;video&gt; og &lt;audio&gt; i dag med et konsistent avspillingsgrensesnitt pƄ tvers av alle de viktigste nettleserne.\n\n[$1 Mer om Kaltura avspillingsbiblioteket].",
+ "mwe-embedplayer-clip_linkback": "Kildesiden for klippet",
+ "mwe-embedplayer-choose_player": "Velg videospiller",
+ "mwe-embedplayer-no-player": "Ingen spiller tilgjengelig for $1",
+ "mwe-embedplayer-share_this_video": "Del denne videoen",
+ "mwe-embedplayer-share_this_audio": "Del denne lydfilen",
+ "mwe-embedplayer-video_credits": "Kreditering",
+ "mwe-embedplayer-no-video_credits": "Ingen kreditering tilgjengelig",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura Ć„pen kildekode-videoplattform",
+ "mwe-embedplayer-menu_btn": "Meny",
+ "mwe-embedplayer-close_btn": "Lukk",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC-spiller",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg-spiller",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3-spiller",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AAC-spiller",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264-spiller",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM-avspiller",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Generisk Ogg-utvidelse",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "appen VLC for iOS",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime-utvidelse",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura-spiller",
+ "mwe-embedplayer-ogg-player-selected": "(valgt)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "For en bedre avspillingsopplevelse anbefaler vi en <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">HTML5-videofremviser</a>.",
+ "mwe-embedplayer-download-warn": "Ingen kompatibel mediespiller for nettleseren ble funnet: for avspilling i nettleseren kan du laste ned [$1 nyeste utgave av Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "Trykk <b>F11</b> for Ć„ sette <i>nettleseren</i> i fullskjermmodus",
+ "mwe-embedplayer-fullscreen-tip-osx": "Trykk <b>shift āŒ˜ F</b> for Ć„ vise i fullskjerm",
+ "mwe-embedplayer-do_not_warn_again": "Ikke vis denne meldingen i fremtiden",
+ "mwe-embedplayer-playerSelect": "Spillere",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Les dette</a> fĆør du bygger inn.",
+ "mwe-embedplayer-embed_site_or_blog": "Bygg inn pƄ en side",
+ "mwe-embedplayer-embed_wiki": "Bygg inn pƄ en wiki",
+ "mwe-embedplayer-related_videos": "Relaterte videoer",
+ "mwe-embedplayer-seeking": "sĆøker",
+ "mwe-embedplayer-buffering": "mellomlagrer",
+ "mwe-embedplayer-video-h264": "H.264-video",
+ "mwe-embedplayer-video-webm": "WebM-video",
+ "mwe-embedplayer-video-flv": "Flash-video",
+ "mwe-embedplayer-video-ogg": "Ogg-video",
+ "mwe-embedplayer-video-audio": "Ogg-audio",
+ "mwe-embedplayer-audio-mpeg": "MPEG-lyd",
+ "mwe-embedplayer-video-3gp": "3GP-video",
+ "mwe-embedplayer-video-mpeg": "MPEG-video",
+ "mwe-embedplayer-video-msvideo": "AVI-video",
+ "mwe-embedplayer-missing-source": "Ingen kildevideo ble funnet",
+ "mwe-embedplayer-vlcapp-intro": "For Ƅ spille av videoer fra dette nettstedet pƄ en iPhone eller iPad, trenger du $1 (gratis).",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "appen VLC",
+ "mwe-embedplayer-vlcapp-downloadapp": "Last ned appen VLC fra App Store",
+ "mwe-embedplayer-vlcapp-openvideo": "ƅpne denne videoen i VLC-appen",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Last ned denne videoen",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "For Ƅ spille av videoer pƄ dette nettstedet, trenger du appen VLC (gratis). Vil du installere nƄ?"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nds-nl.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nds-nl.json
new file mode 100644
index 00000000..36e62cdb
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nds-nl.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Servien"
+ ]
+ },
+ "mwe-embedplayer-play_clip": "Klip aofspeulen"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nl.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nl.json
new file mode 100644
index 00000000..66fef83a
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nl.json
@@ -0,0 +1,85 @@
+{
+ "@metadata": {
+ "authors": [
+ "Arent",
+ "Siebrand",
+ "Southparkfan"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Naam: $1",
+ "mwe-embedplayer-credit-date": "Datum: $1",
+ "mwe-embedplayer-credit-author": "Auteur: $1",
+ "mwe-embedplayer-nocredits": "Geen auteursgegevens beschikbaar",
+ "mwe-embedplayer-loading_plugin": "Bezig met het laden van de uitbreiding...",
+ "mwe-embedplayer-select_playback": "Afspeelinstellingen instellen",
+ "mwe-embedplayer-link_back": "Terugverwijzen",
+ "mwe-embedplayer-error_swap_vid": "Fout: mvEmbed kon de videotag voor de mwEmbed-interface niet wisselen",
+ "mwe-embedplayer-add_to_end_of_sequence": "Aan het einde van de reeks toevoegen",
+ "mwe-embedplayer-missing_video_stream": "Het videobestand voor deze stream is niet aanwezig",
+ "mwe-embedplayer-play_clip": "Clip afspelen",
+ "mwe-embedplayer-pause_clip": "Clip pauzeren",
+ "mwe-embedplayer-volume_control": "Volumebeheer",
+ "mwe-embedplayer-player_options": "Mediaspelerinstellingen",
+ "mwe-embedplayer-timed_text": "Ondertitels",
+ "mwe-embedplayer-player_fullscreen": "Volledig scherm",
+ "mwe-embedplayer-next_clip_msg": "Volgende clip afspelen",
+ "mwe-embedplayer-prev_clip_msg": "Vorige clip afspelen",
+ "mwe-embedplayer-current_clip_msg": "Doorgaan met het afspelen van deze clip",
+ "mwe-embedplayer-seek_to": "Zoeken naar $1",
+ "mwe-embedplayer-paused": "gepauzeerd",
+ "mwe-embedplayer-download_segment": "Selectie downloaden:",
+ "mwe-embedplayer-download_full": "Volledig videobestand downloaden:",
+ "mwe-embedplayer-download_right_click": "Klik rechts en selecteer <i>Koppeling opslaan als...</i> om het bestand te downloaden",
+ "mwe-embedplayer-download_clip": "Video downloaden",
+ "mwe-embedplayer-download_text": "Tekst downloaden",
+ "mwe-embedplayer-download": "Downloaden",
+ "mwe-embedplayer-share": "Delen",
+ "mwe-embedplayer-credits": "Vermeldingen",
+ "mwe-embedplayer-about-library": "Over de Kalturaspeler",
+ "mwe-embedplayer-about-library-desc": "De HTML5-bibliotheek van Kaltura zorgt dat u nu kunt profiteren van de HTML5-labels <nowiki><video></nowiki> en <nowiki><audio></nowiki> met een consistent uiterlijk van de speler in alle veelgebruikte browsers.\n\n[$1 Meer over de bibliotheek van de Kaltura-speler].",
+ "mwe-embedplayer-clip_linkback": "Bronpagina van de clip",
+ "mwe-embedplayer-choose_player": "Mediaspeler kiezen",
+ "mwe-embedplayer-no-player": "Geen speler beschikbaar voor $1",
+ "mwe-embedplayer-share_this_video": "Deze video delen",
+ "mwe-embedplayer-video_credits": "Naamsvermeldingen video",
+ "mwe-embedplayer-no-video_credits": "Geen auteursinformatie beschikbaar",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura open source videoplatform",
+ "mwe-embedplayer-menu_btn": "Menu",
+ "mwe-embedplayer-close_btn": "Sluiten",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC-mediaspeler",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg-speler",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3-speler",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AAC-speler",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264-speler",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM-speler",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Algemene Ogg-plugin",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime-plugin",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura mediaspeler",
+ "mwe-embedplayer-ogg-player-selected": "(geselecteerd)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Voor een betere kwaliteitsbeleving adviseren we een <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">HTML5 videobrowser</a>.",
+ "mwe-embedplayer-download-warn": "Er is geen compatibele speler in de browser aangetroffen. Download de [$1 meest recente versie van Firefox] om dit bestand in de browser af te kunnen spelen.",
+ "mwe-embedplayer-fullscreen-tip": "Druk op <b>F11</b> om de <i>web browser</i> in het volledige scherm weer te geven",
+ "mwe-embedplayer-fullscreen-tip-osx": "Typ <b>SHIRT+āŒ˜+F</b> voor volledig scherm of terug",
+ "mwe-embedplayer-do_not_warn_again": "Dit bericht niet meer weergeven.",
+ "mwe-embedplayer-playerSelect": "Spelers",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Lees dit</a> voordat u gaat embedden (Engels)!",
+ "mwe-embedplayer-embed_site_or_blog": "Toevoegen aan een pagina",
+ "mwe-embedplayer-embed_wiki": "Toevoegen aan een pagina",
+ "mwe-embedplayer-related_videos": "Gerelateerde video's",
+ "mwe-embedplayer-seeking": "bezig met zoeken",
+ "mwe-embedplayer-buffering": "bufferen",
+ "mwe-embedplayer-video-h264": "H.264-video",
+ "mwe-embedplayer-video-webm": "WebM video",
+ "mwe-embedplayer-video-flv": "Flash-video",
+ "mwe-embedplayer-video-ogg": "Ogg-video",
+ "mwe-embedplayer-video-audio": "Ogg-audio",
+ "mwe-embedplayer-audio-mpeg": "MPEG-audio",
+ "mwe-embedplayer-video-3gp": "3GP-video",
+ "mwe-embedplayer-video-mpeg": "MPEG-video",
+ "mwe-embedplayer-video-msvideo": "AVI-video",
+ "mwe-embedplayer-missing-source": "Er is geen bronvideo gevonden."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nn.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nn.json
new file mode 100644
index 00000000..c96be9d4
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/nn.json
@@ -0,0 +1,84 @@
+{
+ "@metadata": {
+ "authors": [
+ "Nghtwlkr",
+ "Njardarlogar",
+ "Gaute",
+ "Ranveig"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Tittel: $1",
+ "mwe-embedplayer-credit-date": "Dato: $1",
+ "mwe-embedplayer-credit-author": "Forfattar: $1",
+ "mwe-embedplayer-nocredits": "Inga godskriving tilgjengeleg",
+ "mwe-embedplayer-loading_plugin": "Lastar inn utviding ā€¦",
+ "mwe-embedplayer-select_playback": "Set avspelingsinnstillingar",
+ "mwe-embedplayer-link_back": "Lenkja attende",
+ "mwe-embedplayer-error_swap_vid": "Feil: mwEmbed kunne ikkje byta videomerket for mwEmbed-grensesnittet",
+ "mwe-embedplayer-add_to_end_of_sequence": "Legg til ved enden av sekvensen",
+ "mwe-embedplayer-missing_video_stream": "Videofila for strĆøyminga manglar",
+ "mwe-embedplayer-play_clip": "Spel av klipp",
+ "mwe-embedplayer-pause_clip": "Stogg klipp",
+ "mwe-embedplayer-volume_control": "Volumstyring",
+ "mwe-embedplayer-player_options": "Spelarval",
+ "mwe-embedplayer-timed_text": "Tidbunden tekst",
+ "mwe-embedplayer-player_fullscreen": "Fullskjerm",
+ "mwe-embedplayer-next_clip_msg": "Spel av neste klippet",
+ "mwe-embedplayer-prev_clip_msg": "Spel av fĆørre klippet",
+ "mwe-embedplayer-current_clip_msg": "Haldt fram med Ć„ spela av klippet",
+ "mwe-embedplayer-seek_to": "SĆøk $1",
+ "mwe-embedplayer-paused": "stogga",
+ "mwe-embedplayer-download_segment": "Last ned utval:",
+ "mwe-embedplayer-download_full_video": "Last ned heile videofila:",
+ "mwe-embedplayer-download_full_audio": "Last ned heile lydfila:",
+ "mwe-embedplayer-download_right_click": "For Ć„ lasta ned, hĆøgreklikk og vel <i>Lagra lenkje som...</i>",
+ "mwe-embedplayer-download_clip": "Last ned video",
+ "mwe-embedplayer-download_text": "Last ned tekst",
+ "mwe-embedplayer-download": "Last ned",
+ "mwe-embedplayer-share": "Del",
+ "mwe-embedplayer-credits": "Godskriving",
+ "mwe-embedplayer-about-library": "Om Kaltura-spelaren",
+ "mwe-embedplayer-about-library-desc": "HTML5-mediebiblioteket i Kaltura tillĆØt deg Ć„ utnytta fĆøremonene til HTML5-merka &lt;video&gt; og &lt;audio&gt; i dag med eit konsistent spelargrensesnitt gjennom alle dei stĆørrre nettlesarane.\n\n[$1 Meir om spelarbiblioteket Kaltura]",
+ "mwe-embedplayer-clip_linkback": "Kjeldesida til klippet",
+ "mwe-embedplayer-choose_player": "Vel videospelar",
+ "mwe-embedplayer-no-player": "Ingen spelar tilgjengeleg for $1",
+ "mwe-embedplayer-share_this_video": "Del videoen",
+ "mwe-embedplayer-share_this_audio": "Del denne lydfila",
+ "mwe-embedplayer-video_credits": "Videogodskriving",
+ "mwe-embedplayer-no-video_credits": "Inga godskriving tilgjengeleg",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura, videoplattform med open kjeldekode",
+ "mwe-embedplayer-menu_btn": "Meny",
+ "mwe-embedplayer-close_btn": "Lat att",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC-spelar",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg-spelar",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264-spelar",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM-spelar",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Generisk Ogg-utviding",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime-utviding",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura-spelar",
+ "mwe-embedplayer-ogg-player-selected": "(vald)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "For ei betre videoavspelingsoppleving tilrƄr me ein <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">html5-videolesar</a>.",
+ "mwe-embedplayer-download-warn": "Det vart ikkje funne nokon kompatibel spelar i nettlesaren; for Ć„ spela av i nettlesaren bĆør du lasta ned [$1 siste utgĆ„va av Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "Trykk <b>F11</b> for Ƅ slƄ pƄ fullskjermen til <i>nettlesaren</i>",
+ "mwe-embedplayer-fullscreen-tip-osx": "Trykk pĆ„ <b>shift āŒ˜ F</b> for Ć„ slĆ„ pĆ„ fullskjerm",
+ "mwe-embedplayer-do_not_warn_again": "Ikkje vis meldinga i framtida.",
+ "mwe-embedplayer-playerSelect": "Avspelarar",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Les dette</a> fĆør du byggjer inn.",
+ "mwe-embedplayer-embed_site_or_blog": "Bygg inn i ei side",
+ "mwe-embedplayer-related_videos": "Skylde videoar",
+ "mwe-embedplayer-seeking": "sĆøkjer",
+ "mwe-embedplayer-buffering": "buffrar",
+ "mwe-embedplayer-video-h264": "H.264-video",
+ "mwe-embedplayer-video-webm": "WebM-video",
+ "mwe-embedplayer-video-flv": "Flash-video",
+ "mwe-embedplayer-video-ogg": "Ogg-video",
+ "mwe-embedplayer-video-audio": "Ogg-ljod",
+ "mwe-embedplayer-audio-mpeg": "MPEG-ljod",
+ "mwe-embedplayer-video-3gp": "3GP-video",
+ "mwe-embedplayer-video-mpeg": "MPEG-video",
+ "mwe-embedplayer-video-msvideo": "AVI-video",
+ "mwe-embedplayer-missing-source": "Ingen kjeldevideo vart funnen"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/oc.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/oc.json
new file mode 100644
index 00000000..c481affa
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/oc.json
@@ -0,0 +1,50 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cedric31"
+ ]
+ },
+ "mwe-embedplayer-loading_plugin": "cargament del plugin ...",
+ "mwe-embedplayer-select_playback": "Definir las preferƩncias de lectura",
+ "mwe-embedplayer-link_back": "Ligam retorn",
+ "mwe-embedplayer-error_swap_vid": "Erreur : mv_embed a pas capitat d'escambiar l'atribut de la vidĆØo per l'interfĆ cia mv_embed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Apondre a la fin de la sequƩncia",
+ "mwe-embedplayer-missing_video_stream": "Lo fichiĆØr vidĆØo per aqueste flus es mancant",
+ "mwe-embedplayer-play_clip": "Legir lo clip",
+ "mwe-embedplayer-pause_clip": "Metre lo clip en pausa",
+ "mwe-embedplayer-volume_control": "ContrarĆ²tle del volum",
+ "mwe-embedplayer-player_options": "Opcions del lector",
+ "mwe-embedplayer-player_fullscreen": "Ecran plen",
+ "mwe-embedplayer-next_clip_msg": "Legir lo clip seguent",
+ "mwe-embedplayer-prev_clip_msg": "Legir lo clip precedent",
+ "mwe-embedplayer-current_clip_msg": "Perseguir la lectura d'aqueste clip",
+ "mwe-embedplayer-seek_to": "AtƩnher $1",
+ "mwe-embedplayer-paused": "en pausa",
+ "mwe-embedplayer-download_segment": "Telecargar la seleccion :",
+ "mwe-embedplayer-download_full": "Telecargar lo fichiĆØr de la vidĆØo completa :",
+ "mwe-embedplayer-download_right_click": "Per telecargar, clicatz-drech e seleccionatz <i>Enregistrar la cibla del ligam jos...</i>",
+ "mwe-embedplayer-download_clip": "Telecargar la vidĆØo",
+ "mwe-embedplayer-download_text": "Telecargar lo tĆØxte",
+ "mwe-embedplayer-download": "Telecargar",
+ "mwe-embedplayer-share": "Partejar",
+ "mwe-embedplayer-credits": "Credits",
+ "mwe-embedplayer-clip_linkback": "Pagina font del clip",
+ "mwe-embedplayer-choose_player": "Causir lo lector vidĆØo",
+ "mwe-embedplayer-share_this_video": "Partejar aquesta vidĆØo",
+ "mwe-embedplayer-video_credits": "Credits de la vidĆØo",
+ "mwe-embedplayer-menu_btn": "MenĆŗ",
+ "mwe-embedplayer-close_btn": "Tampar",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Modul generic Ogg",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Modul QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "ActiveX QuickTime",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-selected": "(seleccionat)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Per un melhor visionatge recomandam un <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">navigador vidĆØo HTML5</a>.",
+ "mwe-embedplayer-do_not_warn_again": "Afichar pas mai aqueste messatge a l'avenir",
+ "mwe-embedplayer-read_before_embed": "LegissĆØtz <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">aquĆ²</a> abans de procedir !",
+ "mwe-embedplayer-embed_site_or_blog": "Integrar dins una pagina",
+ "mwe-embedplayer-related_videos": "VidĆØos associadas",
+ "mwe-embedplayer-seeking": "recĆØrca"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pam.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pam.json
new file mode 100644
index 00000000..bb3f6794
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pam.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Leeheonjin"
+ ]
+ },
+ "mwe-embedplayer-iewebmprompt-intro": "Ui! Atin pang metung a bage bayu me pa i-play ing video a ini..."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pdc.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pdc.json
new file mode 100644
index 00000000..b78c9b0a
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pdc.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Xqt"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titel: $1",
+ "mwe-embedplayer-seek_to": "Guck uff $1"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pl.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pl.json
new file mode 100644
index 00000000..97e49986
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pl.json
@@ -0,0 +1,81 @@
+{
+ "@metadata": {
+ "authors": [
+ "BeginaFelicysym",
+ "Sp5uhe"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Tytuł ā€“ $1",
+ "mwe-embedplayer-credit-date": "Data: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-nocredits": "Informacja o twĆ³rcach nie jest dostępna",
+ "mwe-embedplayer-loading_plugin": "trwa ładowanie wtyczki...",
+ "mwe-embedplayer-select_playback": "Ustaw preferencje odtwarzania",
+ "mwe-embedplayer-link_back": "Link powrotny",
+ "mwe-embedplayer-error_swap_vid": "Błąd ā€“ mv_embed nie był w stanie zamieniać znacznika filmu dla interfejsu mv_embed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Dodaj na koniec sekwencji",
+ "mwe-embedplayer-missing_video_stream": "Brak pliku z filmem dla tego strumienia",
+ "mwe-embedplayer-play_clip": "OdtwĆ³rz klip",
+ "mwe-embedplayer-pause_clip": "Wstrzymaj odtwarzanie klipu",
+ "mwe-embedplayer-volume_control": "Regulacja głośności",
+ "mwe-embedplayer-player_options": "Opcje odtwarzacza",
+ "mwe-embedplayer-timed_text": "Lista dialogowa",
+ "mwe-embedplayer-player_fullscreen": "Pełny ekran",
+ "mwe-embedplayer-next_clip_msg": "OdtwĆ³rz następny klip",
+ "mwe-embedplayer-prev_clip_msg": "OdtwĆ³rz poprzedni klip",
+ "mwe-embedplayer-current_clip_msg": "Kontynuuj odtwarzanie tego klipu",
+ "mwe-embedplayer-seek_to": "Przewiń $1",
+ "mwe-embedplayer-paused": "wstrzymane",
+ "mwe-embedplayer-download_segment": "WybĆ³r pobierania",
+ "mwe-embedplayer-download_full": "Pobierz pełny plik z filmem",
+ "mwe-embedplayer-download_right_click": "Aby pobrać, kliknij prawym przyciskiem myszy i wybierz <i>Zapisz link jako...</i>",
+ "mwe-embedplayer-download_clip": "Pobierz film",
+ "mwe-embedplayer-download_text": "Pobierz tekst",
+ "mwe-embedplayer-download": "Pobierz",
+ "mwe-embedplayer-share": "Udostępnij",
+ "mwe-embedplayer-credits": "TwĆ³rcy",
+ "mwe-embedplayer-about-library": "O odtwarzaczu Kaltura",
+ "mwe-embedplayer-about-library-desc": "Biblioteka Kaltura obsługi mediĆ³w dla HTML5 pozwala na użycie znacznikĆ³w HTML5 <code><nowiki><video></nowiki></code> i <code><nowiki><audio></nowiki></code> ze spĆ³jnym interfejsem odtwarzacza we wszystkich najpopularniejszych przeglądarkach.\n\n[$1 Więcej na temat biblioteki odtwarzacza Kaltura].",
+ "mwe-embedplayer-clip_linkback": "Strona ÅŗrĆ³dłowa klipu",
+ "mwe-embedplayer-choose_player": "Wybierz odtwarzacz wideo",
+ "mwe-embedplayer-no-player": "Brak dostępnych odtwarzaczy dla $1",
+ "mwe-embedplayer-share_this_video": "Udostępnij ten film",
+ "mwe-embedplayer-video_credits": "TwĆ³rcy filmu",
+ "mwe-embedplayer-no-video_credits": "Informacja o twĆ³rcach nie jest dostępna",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura ā€“ platforma filmĆ³w z otwartym kodem",
+ "mwe-embedplayer-menu_btn": "Menu",
+ "mwe-embedplayer-close_btn": "Zamknij",
+ "mwe-embedplayer-ogg-player-vlc-player": "Odtwarzacz VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Odtwarzacz HTML5 Ogg",
+ "mwe-embedplayer-ogg-player-h264Native": "Odtwarzacz HTML5 H.264",
+ "mwe-embedplayer-ogg-player-webmNative": "Odtwarzacz HTML5 WebM",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Pierwotna wtyczka Ogg",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Wtyczka QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Cortado w Java",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Odtwarzacz Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(zaznaczone)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Dla lepszego odtwarzania filmĆ³w polecamy [przeglądarkę video html5 $1</a>.",
+ "mwe-embedplayer-download-warn": "Nie odnaleziono zgodnego odtwarzacza dla przeglądarki, aby odtworzyć tą zawartość w przeglądarce należy pobrać [$1 najnowszą wersjęFirefox]",
+ "mwe-embedplayer-fullscreen-tip": "Naciśnij klawisz <b>F11</b> by przełączyć <i>przeglądarkę</i> w tryb pełnoekranowy",
+ "mwe-embedplayer-fullscreen-tip-osx": "Naciśnij klawisze <b>shift āŒ˜ f</b> aby przełączyć w tryb pełnoekranowy",
+ "mwe-embedplayer-do_not_warn_again": "W przyszłości nie pokazuj tego komunikatu",
+ "mwe-embedplayer-playerSelect": "Odtwarzacze",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Przeczytaj to</a> przed wstawieniem.",
+ "mwe-embedplayer-embed_site_or_blog": "Umieść na swojej stronie lub blogu",
+ "mwe-embedplayer-related_videos": "Podobne filmy",
+ "mwe-embedplayer-seeking": "przewijanie",
+ "mwe-embedplayer-buffering": "buforowanie",
+ "mwe-embedplayer-video-h264": "Wideo w H.264",
+ "mwe-embedplayer-video-webm": "Wideo WebM",
+ "mwe-embedplayer-video-flv": "Wideo we Flash",
+ "mwe-embedplayer-video-ogg": "Wideo w Ogg",
+ "mwe-embedplayer-video-audio": "DÅŗwięk w Ogg",
+ "mwe-embedplayer-audio-mpeg": "Wideo MPEG",
+ "mwe-embedplayer-video-3gp": "Wideo 3GP",
+ "mwe-embedplayer-video-mpeg": "Wideo MPEG",
+ "mwe-embedplayer-video-msvideo": "Wideo AVI",
+ "mwe-embedplayer-missing-source": "Nie ustalono ÅŗrĆ³dła obrazu."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pms.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pms.json
new file mode 100644
index 00000000..b667b89e
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pms.json
@@ -0,0 +1,80 @@
+{
+ "@metadata": {
+ "authors": [
+ "BorichĆØt",
+ "DragonĆ²t"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "TƬtol: $1",
+ "mwe-embedplayer-credit-date": "Data: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-nocredits": "Gnun arconossiment ƫd paternitƠ disponƬbil",
+ "mwe-embedplayer-loading_plugin": "CariƩ plugin...",
+ "mwe-embedplayer-select_playback": "AmpostƩ gust ƫd letura",
+ "mwe-embedplayer-link_back": "Anliura andrƩ",
+ "mwe-embedplayer-error_swap_vid": "Eror: mwEmbed a l'Ʃ pa stƠit bon a cangƩ la tichƫtta dƫl filmƠ pƫr l'antƫrfacia mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "GiontƩ a la fin ƫd la sequensa",
+ "mwe-embedplayer-missing_video_stream": "L'archivi dƫl filmƠ pr'ƫs fluss a manca",
+ "mwe-embedplayer-play_clip": "FĆ  parte Ć«l curtmetragi",
+ "mwe-embedplayer-pause_clip": "Ferma Ć«l curtmetragi",
+ "mwe-embedplayer-volume_control": "ContrĆ²l dĆ«l volum",
+ "mwe-embedplayer-player_options": "Opsion dƫl letor",
+ "mwe-embedplayer-timed_text": "Test sincronisĆ ",
+ "mwe-embedplayer-player_fullscreen": "A scren pien",
+ "mwe-embedplayer-next_clip_msg": "FĆ  parte Ć«l curtmetragi ch'a ven",
+ "mwe-embedplayer-prev_clip_msg": "FĆ  parte Ć«l curtmetragi prima",
+ "mwe-embedplayer-current_clip_msg": "Continua a fƩ girƩ sto curtmetragi",
+ "mwe-embedplayer-seek_to": "Serca $1",
+ "mwe-embedplayer-paused": "an pĆ usa",
+ "mwe-embedplayer-download_segment": "DƫscariƩ la selession:",
+ "mwe-embedplayer-download_full": "DƫscariƩ l'archivi antregh dƫl filmƠ:",
+ "mwe-embedplayer-download_right_click": "Pƫr dƫscariƩ, sgnaca con ƫl tast drit dƫl rat e selession-a <i>Salva ƫl colegament com...</i>",
+ "mwe-embedplayer-download_clip": "DƫscariƩ ƫl filmƠ",
+ "mwe-embedplayer-download_text": "DƫscariƩ ƫl test",
+ "mwe-embedplayer-download": "DĆ«scaria",
+ "mwe-embedplayer-share": "Condivid",
+ "mwe-embedplayer-credits": "Arconossiment",
+ "mwe-embedplayer-about-library": "A propĆ²sit dĆ«l riprodutor Kaltura",
+ "mwe-embedplayer-about-library-desc": "La librarƬa dĆ«l mojen HTML5 Ć«d Kaltura a lo abƬlita a sfrutĆ© ancheuj le tichĆ«tte HTML5 <code><nowiki><video></nowiki></code> e <code><nowiki><audio></nowiki></code> con n'antĆ«rfacia Ć«d riprodussion coerenta con tĆ¹it ij navigador prinsipaj.\n\n[$1 PĆ«r savĆØjne Ć«d pi a propĆ²sit Ć«d la librarƬa dĆ«l riprodutor Kaltura]",
+ "mwe-embedplayer-clip_linkback": "PƠgina sorgiss dƫl curt-metragi",
+ "mwe-embedplayer-choose_player": "Serne Ć«l letor dij filmĆ ",
+ "mwe-embedplayer-no-player": "Pa gnun letor disponƬbij pƫr $1",
+ "mwe-embedplayer-share_this_video": "PartagƩ ƫs filmƠ",
+ "mwe-embedplayer-video_credits": "Arconossiment dƫl filmƠ",
+ "mwe-embedplayer-no-video_credits": "Pa gnun crƩdit disponƬbij",
+ "mwe-embedplayer-kaltura-platform-title": "Piataforma pƫr filmƠ a sorgiss duverta Kaltura",
+ "mwe-embedplayer-menu_btn": "Lista",
+ "mwe-embedplayer-close_btn": "Sara",
+ "mwe-embedplayer-ogg-player-vlc-player": "Letor VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Letor HTML5 Ogg",
+ "mwe-embedplayer-ogg-player-h264Native": "Letor HTML5 H.264",
+ "mwe-embedplayer-ogg-player-webmNative": "Letor HTML5 WebM",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Plugin Generic Ogg",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Plugin QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Letor Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(selessionĆ )",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Per n'esperiensa Ć«d vision pi bon-a i arcomandoma un <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">navigador adat ai filmĆ  html5</a>.",
+ "mwe-embedplayer-download-warn": "A l'Ć© trovasse che Ć«l navigador a l'Ć© nen compatƬbil, pĆ«r na letura ant Ć«l navigador, pĆ«r piasƬ ch'a dĆ«scaria l'[$1 Ć¹ltim Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "SgnachƩ <b>F11</b> pƫr passƩ al <i>navigador dl'aragnƠ</i> a scren antregh",
+ "mwe-embedplayer-fullscreen-tip-osx": "Ch'a sgnaca <b>majĆ¹scole āŒ˜ F</b> pĆ«r passĆ© a scren antregh",
+ "mwe-embedplayer-do_not_warn_again": "Ant l'avnƬ, mostrƩ pa pi ƫs mƫssagi",
+ "mwe-embedplayer-playerSelect": "Letor",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Les sossƬ</a> prima d'ancorporƩ.",
+ "mwe-embedplayer-embed_site_or_blog": "AncorporƩ an sna pƠgina",
+ "mwe-embedplayer-related_videos": "FilmĆ  assossiĆ ",
+ "mwe-embedplayer-seeking": "arserca",
+ "mwe-embedplayer-buffering": "an camin a butĆ© ant la memĆ²ria tampon",
+ "mwe-embedplayer-video-h264": "filmĆ  H.264",
+ "mwe-embedplayer-video-webm": "FilmĆ  WebM",
+ "mwe-embedplayer-video-flv": "filmĆ  Flash",
+ "mwe-embedplayer-video-ogg": "filmĆ  Ogg",
+ "mwe-embedplayer-video-audio": "ƀudio Ogg",
+ "mwe-embedplayer-audio-mpeg": "Sonor MPEG",
+ "mwe-embedplayer-video-3gp": "FilmĆ  3GP",
+ "mwe-embedplayer-video-mpeg": "FilmĆ  MPEG",
+ "mwe-embedplayer-video-msvideo": "FilmĆ  AVI",
+ "mwe-embedplayer-missing-source": "Gnun filmĆ  sorgiss a l'Ć© stĆ it trovĆ ."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ps.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ps.json
new file mode 100644
index 00000000..7bb42723
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ps.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ahmed-Najib-Biabani-Ibrahimkhel"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Ų³Ų±Ł„ŁŠŚ©: $1",
+ "mwe-embedplayer-credit-date": "Ł†ŪŁ¼Ł‡: $1",
+ "mwe-embedplayer-credit-author": "Ł„ŁŠŚ©ŁˆŲ§Ł„: $1",
+ "mwe-embedplayer-download_clip": "ŁˆŁŠŚ‰ŁŠŁˆ ŚšŚ©ŲŖŁ‡ Ś©ŁˆŁ„",
+ "mwe-embedplayer-download_text": "Ł…ŲŖŁ† ŚšŚ©ŲŖŁ‡ Ś©ŁˆŁ„",
+ "mwe-embedplayer-download": "ŚšŚ©ŲŖŁ‡ Ś©ŁˆŁ„",
+ "mwe-embedplayer-share": "Ų“Ų±ŁŠŚ©ŁˆŁ„",
+ "mwe-embedplayer-close_btn": "ŲŖŚ“Ł„",
+ "mwe-embedplayer-ogg-player-selected": "(Ł¼Ų§Ś©Ł„ Ų“ŁˆŪŒ)",
+ "mwe-embedplayer-playerSelect": "ŲŗŚ–ŁˆŁ†Ś©ŁŠ",
+ "mwe-embedplayer-audio-mpeg": "MPEG ŲŗŚ–",
+ "mwe-embedplayer-video-3gp": "3GP ŁˆŁŠŚ‰ŁŠŁˆ",
+ "mwe-embedplayer-video-mpeg": "MPEG ŁˆŁŠŚ‰ŁŠŁˆ",
+ "mwe-embedplayer-video-msvideo": "AVI ŁˆŁŠŚ‰ŁŠŁˆ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pt-br.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pt-br.json
new file mode 100644
index 00000000..830e4dce
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pt-br.json
@@ -0,0 +1,86 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cainamarques",
+ "Dianakc",
+ "Giro720",
+ "Luckas",
+ "Luckas Blade"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "TĆ­tulo: $1",
+ "mwe-embedplayer-credit-date": "Data: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-nocredits": "CrĆ©ditos nĆ£o disponĆ­veis",
+ "mwe-embedplayer-loading_plugin": "Carregando plugin ...",
+ "mwe-embedplayer-select_playback": "Definir preferĆŖncias de reproduĆ§Ć£o",
+ "mwe-embedplayer-link_back": "Criar link de volta",
+ "mwe-embedplayer-error_swap_vid": "Erro: o mv_embed nĆ£o conseguiu trocar o elemento de vĆ­deo pela interface mv_embed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Adicionar ao fim da sequĆŖncia",
+ "mwe-embedplayer-missing_video_stream": "O arquivo de vĆ­deo para esta transmissĆ£o estĆ” em falta",
+ "mwe-embedplayer-play_clip": "Tocar videoclipe",
+ "mwe-embedplayer-pause_clip": "Pausar clipe",
+ "mwe-embedplayer-volume_control": "Controle de volume",
+ "mwe-embedplayer-player_options": "OpƧƵes do tocador",
+ "mwe-embedplayer-timed_text": "Legendas",
+ "mwe-embedplayer-player_fullscreen": "Tela inteira",
+ "mwe-embedplayer-next_clip_msg": "Tocar o clipe seguinte",
+ "mwe-embedplayer-prev_clip_msg": "Tocar o clipe anteiror",
+ "mwe-embedplayer-current_clip_msg": "Continue a tocar este clipe",
+ "mwe-embedplayer-seek_to": "Procurar $1",
+ "mwe-embedplayer-paused": "pausado",
+ "mwe-embedplayer-download_segment": "Download da seleĆ§Ć£o:",
+ "mwe-embedplayer-download_full": "Donwload do arquivo completo:",
+ "mwe-embedplayer-download_right_click": "Para fazer donwload, clique com o botĆ£o direito e selecione <i>Salvar link como...</i>",
+ "mwe-embedplayer-download_clip": "Download de vĆ­deo",
+ "mwe-embedplayer-download_text": "Download do texto",
+ "mwe-embedplayer-download": "Download",
+ "mwe-embedplayer-share": "Compartilhar",
+ "mwe-embedplayer-credits": "CrƩditos",
+ "mwe-embedplayer-about-library": "Sobre o reprodutor Kaltura",
+ "mwe-embedplayer-about-library-desc": "A biblioteca de mĆ­dia HTML5 da Kaltura permite que vocĆŖ tira vantagem hoje das marcaƧƵes HTML5 <code><nowiki><video></nowiki></code> e <code><nowiki><audio></nowiki></code> com uma interface de reprodutor consistente em todos os principais navegadores.\n\n[$1 Mais sobre a biblioteca de reproduĆ§Ć£o Kaltura].\n\nenables you to take advantage of the HTML5 <code><nowiki><video></nowiki></code> and <code><nowiki><audio></nowiki></code> tags today with a consistent player interface across all major browsers.\n\t\n[$1 More about the Kaltura player library].",
+ "mwe-embedplayer-clip_linkback": "PƔgina da fonte do clipe",
+ "mwe-embedplayer-choose_player": "Escolher leitor de vĆ­deo",
+ "mwe-embedplayer-no-player": "NĆ£o hĆ” nenhum leitor disponĆ­vel para $1",
+ "mwe-embedplayer-share_this_video": "Compartilhar este vĆ­deo",
+ "mwe-embedplayer-video_credits": "CrƩditos do vƭdeo",
+ "mwe-embedplayer-no-video_credits": "CrĆ©ditos nĆ£o disponĆ­veis",
+ "mwe-embedplayer-kaltura-platform-title": "Plataforma de vĆ­deo em cĆ³digo aberto Kaltura",
+ "mwe-embedplayer-menu_btn": "Menu",
+ "mwe-embedplayer-close_btn": "Fechar",
+ "mwe-embedplayer-ogg-player-vlc-player": "Leitor VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Leitor Ogg HTML5",
+ "mwe-embedplayer-ogg-player-mp3Native": "Tocador de MP3 em HTML5",
+ "mwe-embedplayer-ogg-player-aacNative": "Tocador de ACC em HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "Tocador de H.264 em HTML5",
+ "mwe-embedplayer-ogg-player-webmNative": "Tocador WebM em HTML5",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Plugin Ogg genƩrico",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Plugin QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Tocador Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(selecionado)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Para uma melhor experiĆŖncia de reproduĆ§Ć£o de vĆ­deo recomendamos um <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">navegador que suporta HTML5</a>.",
+ "mwe-embedplayer-download-warn": "NĆ£o foi detetado nenhum leitor compatĆ­vel integrado ao browser: para reproduzir pelo browser, faƧa o download da [$1 Ćŗltima versĆ£o do Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "Aperte <b>F11</b> para ativar ou desativar o modo de tela inteira no <i>browser</i>",
+ "mwe-embedplayer-fullscreen-tip-osx": "Aperte <b>shift āŒ˜ F</b> para ativar ou desativar o modo de tela inteira",
+ "mwe-embedplayer-do_not_warn_again": "No futuro, nĆ£o mostrar esta mensagem",
+ "mwe-embedplayer-playerSelect": "Tocadores",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Leia isto</a> antes de incorporar.",
+ "mwe-embedplayer-embed_site_or_blog": "Incorporar em uma pƔgina",
+ "mwe-embedplayer-embed_wiki": "Incorporar em uma wiki",
+ "mwe-embedplayer-related_videos": "VĆ­deos relacionados",
+ "mwe-embedplayer-seeking": "procurando",
+ "mwe-embedplayer-buffering": "criando buffer",
+ "mwe-embedplayer-video-h264": "VĆ­deo H.264",
+ "mwe-embedplayer-video-webm": "VĆ­deo WebM",
+ "mwe-embedplayer-video-flv": "VĆ­deo Flash",
+ "mwe-embedplayer-video-ogg": "VĆ­deo Ogg",
+ "mwe-embedplayer-video-audio": "Ɓudio Ogg",
+ "mwe-embedplayer-audio-mpeg": "Ɓudio MPEG",
+ "mwe-embedplayer-video-3gp": "VĆ­deo 3GP",
+ "mwe-embedplayer-video-mpeg": "VĆ­deo MPEG",
+ "mwe-embedplayer-video-msvideo": "VĆ­deo AVI",
+ "mwe-embedplayer-missing-source": "Nenhum vĆ­deo foi encontrado"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pt.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pt.json
new file mode 100644
index 00000000..b5b83814
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/pt.json
@@ -0,0 +1,101 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cainamarques",
+ "Hamilton Abreu",
+ "Imperadeiro98",
+ "Luckas",
+ "Malafaya",
+ "SandroHc",
+ "Vitorvicentevalente",
+ "Waldir"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "TĆ­tulo: $1",
+ "mwe-embedplayer-credit-date": "Data: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-nocredits": "Sem crƩditos disponƭveis",
+ "mwe-embedplayer-loading_plugin": "A carregar o ''plugin'' ...",
+ "mwe-embedplayer-select_playback": "Definir a preferĆŖncia de reproduĆ§Ć£o",
+ "mwe-embedplayer-link_back": "Ligar atrƔs",
+ "mwe-embedplayer-error_swap_vid": "Erro: o mv_embed nĆ£o conseguiu trocar o elemento de vĆ­deo pela interface mv_embed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Adicionar ao fim da sequĆŖncia",
+ "mwe-embedplayer-missing_video_stream": "O ficheiro vĆ­deo para esta transmissĆ£o estĆ” em falta",
+ "mwe-embedplayer-play_clip": "Reproduzir clipe",
+ "mwe-embedplayer-pause_clip": "Pausar clipe",
+ "mwe-embedplayer-volume_control": "Controlo de volume",
+ "mwe-embedplayer-player_options": "OpƧƵes do leitor",
+ "mwe-embedplayer-timed_text": "Legendas",
+ "mwe-embedplayer-player_fullscreen": "EcrĆ£ inteiro",
+ "mwe-embedplayer-next_clip_msg": "Reproduzir clipe seguinte",
+ "mwe-embedplayer-prev_clip_msg": "Reproduzir clipe anterior",
+ "mwe-embedplayer-current_clip_msg": "Continuar a reproduzir este clipe",
+ "mwe-embedplayer-seek_to": "Procurar $1",
+ "mwe-embedplayer-paused": "em pausa",
+ "mwe-embedplayer-download_segment": "Descarga da selecĆ§Ć£o:",
+ "mwe-embedplayer-download_full_video": "Descarga do ficheiro vĆ­deo completo:",
+ "mwe-embedplayer-download_full_audio": "Descarregar ficheiro de Ɣudio completo:",
+ "mwe-embedplayer-download_right_click": "Para descarregar, clique no botĆ£o direito do rato e seleccione <i>Guardar ligaĆ§Ć£o como...</i>",
+ "mwe-embedplayer-download_clip": "Descarga do vĆ­deo",
+ "mwe-embedplayer-download_text": "Descarga do texto",
+ "mwe-embedplayer-download": "Descarga",
+ "mwe-embedplayer-share": "Partilhar",
+ "mwe-embedplayer-credits": "CrƩditos",
+ "mwe-embedplayer-about-library": "Sobre o leitor Kaltura",
+ "mwe-embedplayer-about-library-desc": "A biblioteca multimƩdia HTML5 do Kaltura permite-lhe utilizar jƔ hoje os elementos <code><nowiki><video></nowiki></code> e <code><nowiki><audio></nowiki></code> do HTML5 com uma interface consistente do leitor em todos os navegadores principais.\n\t\n[$1 Mais sobre a biblioteca do leitor Kaltura].",
+ "mwe-embedplayer-clip_linkback": "PƔgina fonte do clipe",
+ "mwe-embedplayer-choose_player": "Escolher leitor de vĆ­deo",
+ "mwe-embedplayer-no-player": "NĆ£o hĆ” nenhum leitor disponĆ­vel para $1",
+ "mwe-embedplayer-share_this_video": "Partilhar este vĆ­deo",
+ "mwe-embedplayer-share_this_audio": "Partilhar ficheiro de Ɣudio",
+ "mwe-embedplayer-video_credits": "CrƩditos do vƭdeo",
+ "mwe-embedplayer-no-video_credits": "Sem crƩditos disponƭveis",
+ "mwe-embedplayer-kaltura-platform-title": "Plataforma de vĆ­deo em cĆ³digo aberto Kaltura",
+ "mwe-embedplayer-menu_btn": "Menu",
+ "mwe-embedplayer-close_btn": "Fechar",
+ "mwe-embedplayer-ogg-player-vlc-player": "Leitor VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Leitor Ogg HTML5",
+ "mwe-embedplayer-ogg-player-mp3Native": "Leitor MP3 HTML5",
+ "mwe-embedplayer-ogg-player-aacNative": "Leitor AAC HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "Leitor H.264 HTML5",
+ "mwe-embedplayer-ogg-player-webmNative": "Leitor WebM HTML5",
+ "mwe-embedplayer-ogg-player-oggPlugin": "''Plugin'' Ogg genƩrico",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "VLC para aplicaĆ§Ć£o iOS",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "''Plugin'' QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Leitor Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(seleccionado)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Para uma melhor experiĆŖncia de reproduĆ§Ć£o de vĆ­deo recomendamos um <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">navegador de vĆ­deo HTML5</a>.",
+ "mwe-embedplayer-download-warn": "NĆ£o foi detectado nenhum leitor compatĆ­vel integrado no navegador: para reproduzir no navegador, faƧa a descarga da [$1 Ćŗltima versĆ£o do Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "Carregue em <b>F11</b> para activar ou desactivar o modo de ecrĆ£ inteiro no navegador",
+ "mwe-embedplayer-fullscreen-tip-osx": "Carregue em <b>shift āŒ˜ F</b> para activar ou dcesativar o modo de ecrĆ£ inteiro",
+ "mwe-embedplayer-do_not_warn_again": "No futuro, nĆ£o mostrar esta mensagem",
+ "mwe-embedplayer-playerSelect": "Leitores",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Leia isto</a> antes de incorporar.",
+ "mwe-embedplayer-embed_site_or_blog": "Incorporar numa pƔgina",
+ "mwe-embedplayer-embed_wiki": "Incorporar numa wiki",
+ "mwe-embedplayer-related_videos": "VĆ­deos relacionados",
+ "mwe-embedplayer-seeking": "a procurar",
+ "mwe-embedplayer-buffering": "a carregar",
+ "mwe-embedplayer-video-h264": "VĆ­deo H.264",
+ "mwe-embedplayer-video-webm": "VĆ­deo WebM",
+ "mwe-embedplayer-video-flv": "VĆ­deo Flash",
+ "mwe-embedplayer-video-ogg": "VĆ­deo Ogg",
+ "mwe-embedplayer-video-audio": "Ɓudio Ogg",
+ "mwe-embedplayer-audio-mpeg": "Ɓudio MPEG",
+ "mwe-embedplayer-video-3gp": "VĆ­deo 3GP",
+ "mwe-embedplayer-video-mpeg": "VĆ­deo MPEG",
+ "mwe-embedplayer-video-msvideo": "VĆ­deo AVI",
+ "mwe-embedplayer-missing-source": "NĆ£o foi encontrado nenhum vĆ­deo.",
+ "mwe-embedplayer-vlcapp-intro": "Para conseguir ver vĆ­deos a partir deste sĆ­tio num iPhone ou iPad, precisa da gratuita $1.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "AplicaĆ§Ć£o VLC",
+ "mwe-embedplayer-vlcapp-downloadapp": "Descarregar a aplicaĆ§Ć£o VLC a partir da App Store",
+ "mwe-embedplayer-vlcapp-openvideo": "Abrir este vĆ­deo na aplicaĆ§Ć£o VLC",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Descarregar este vĆ­deo",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "Para reproduzir vĆ­deos neste sĆ­tio, precisa da aplicaĆ§Ć£o gratuita VLC. Instalar agora?",
+ "mwe-embedplayer-iewebmprompt-intro": "Ops! SĆ³ mais uma coisa antes de poder ver o vĆ­deo...",
+ "mwe-embedplayer-iewebmprompt-outro": "Recarregar esta pĆ”gina apĆ³s a instalaĆ§Ć£o."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/qqq.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/qqq.json
new file mode 100644
index 00000000..7d0939c3
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/qqq.json
@@ -0,0 +1,50 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "EugeneZelenko",
+ "Shirayuki",
+ "Umherirrender"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Used as a part of the credit. Parameters:\n* $1 - title\nThis message is followed by the following messages:\n* {{msg-mw|mwe-embedplayer-credit-author}}\n* {{msg-mw|mwe-embedplayer-credit-date}}",
+ "mwe-embedplayer-credit-date": "Parameters:\n* $1 - date\n{{Identical|Date}}",
+ "mwe-embedplayer-credit-author": "Parameters:\n* $1 - author\n{{Identical|Author}}",
+ "mwe-embedplayer-player_fullscreen": "{{Identical|Full screen}}",
+ "mwe-embedplayer-seek_to": "Used as the Player status string. Parameters:\n* $1 - a time in the NPT format. NPT (Normal play time) is defined in [//www.ietf.org/rfc/rfc2326.txt RFC 2326].",
+ "mwe-embedplayer-paused": "{{Identical|Paused}}",
+ "mwe-embedplayer-download_full_video": "Header for the Download tab in the menu, when it's a video file.",
+ "mwe-embedplayer-download_full_audio": "Header for the Download tab in the menu, when it's an audio file.",
+ "mwe-embedplayer-download": "{{Identical|Download}}",
+ "mwe-embedplayer-share": "{{Identical|Share}}",
+ "mwe-embedplayer-credits": "{{Identical|Credit}}",
+ "mwe-embedplayer-about-library-desc": "Parameters:\n* $1 - URL",
+ "mwe-embedplayer-no-player": "This message means that there are no available players to play $1.\n* $1 - source media title",
+ "mwe-embedplayer-share_this_video": "Header for the Share tab in the menu, when it's a video file.",
+ "mwe-embedplayer-share_this_audio": "Header for the Share tab in the menu, when it's an audio file.",
+ "mwe-embedplayer-menu_btn": "{{Identical|Menu}}",
+ "mwe-embedplayer-close_btn": "{{Identical|Close}}",
+ "mwe-embedplayer-ogg-player-mp3Native": "name of mp3 player in configuration screen",
+ "mwe-embedplayer-ogg-player-aacNative": "name of AAC player in configuration screen",
+ "mwe-embedplayer-ogg-player-webmNative": "name of WebM player in configuration screen",
+ "mwe-embedplayer-ogg-player-vp9Native": "name of VP9 player in configuration screen",
+ "mwe-embedplayer-ogg-player-IEWebMPrompt": "name of IE WebM plugin installer helper in configuration screen",
+ "mwe-embedplayer-ogg-player-selected": "{{Identical|Selected}}",
+ "mwe-embedplayer-ogg-player-IEWebMPrompt": "name of IE WebM plugin installer helper in configuration screen",
+ "mwe-embedplayer-ogg-player-ogvJsPlayer": "name of ogv.js Ogg JavaScript player in configuration screen",
+ "mwe-embedplayer-for_best_experience": "Shown when user's browser doesn't support playing videos. Parameters:\n* $1 - An empty &lt;a&gt; tag. Don't use this parameter.",
+ "mwe-embedplayer-download-warn": "Parameters:\n* $1 - URL",
+ "mwe-embedplayer-do_not_warn_again": "Standard message for disabling\nfuture identical warnings messages",
+ "mwe-embedplayer-playerSelect": "{{Identical|Player}}",
+ "mwe-embedplayer-embed_site_or_blog": "title for iframe embed code in share dialog",
+ "mwe-embedplayer-embed_wiki": "title for wiki embed code in share dialog",
+ "mwe-embedplayer-vlcapp-intro": "Shown where a video would be on the page, on iPhones/iPads. Parameter $1 is a link to the App store page for the vlc app, with the text contianed in the mwe-embedplayer-vlcapp-vlcapplinktext message. This message is followed by a bulleted list of links consisting of the messages: mwe-embedplayer-vlcapp-downloadapp, mwe-embedplayer-vlcapp-openvideo, mwe-embedplayer-vlcapp-openvideo. See also the related mwe-embedplayer-vlcapp-vlcapppopup message.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "Text of the $1 parameter of mwe-embedplayer-vlcapp-intro. Will be linked to https://itunes.apple.com/us/app/vlc-for-ios/id650377962?mt=8 (the download page for the vlc app).",
+ "mwe-embedplayer-vlcapp-downloadapp": "First bullet point after the mwe-embedplayer-vlcapp-intro. Links to the download page for installing the vlc app ( https://itunes.apple.com/us/app/vlc-for-ios/id650377962?mt=8 ).",
+ "mwe-embedplayer-vlcapp-openvideo": "Second bullet point after the mwe-embedplayer-vlcapp-intro. Link will open the video in the VLC app, if the app is installed",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Third bullet point after the mwe-embedplayer-vlcapp-intro. Linked directly to the video file",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "Popup dialog box shown to user if they do not have the VLC app installed when trying to play a video on iPhone/iPad. Box will be presented with this message and two buttons (OK and cancel. Actual text of buttons may vary.) If user presses ok, they are redirected to https://itunes.apple.com/us/app/vlc-for-ios/id650377962?mt=8.",
+ "mwe-embedplayer-iewebmprompt-intro": "Shown where a video would be on the page, on IE with no WebM or Ogg support. Followed by mwe-embedplayer-iewebmprompt-linktext",
+ "mwe-embedplayer-iewebmprompt-linktext": "Shown where a video would be on the page, on IE with no WebM or Ogg support. When clicked links to https://tools.google.com/dlpage/webmmf/",
+ "mwe-embedplayer-iewebmprompt-outro": "Shown where a video would be on the page, on IE with no WebM or Ogg support. Follows mwe-embedplayer-iewebmprompt-linktext"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/qu.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/qu.json
new file mode 100644
index 00000000..6f0d1346
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/qu.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "AlimanRuna"
+ ]
+ },
+ "mwe-embedplayer-credit-date": "P'unchaw: $1"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ro.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ro.json
new file mode 100644
index 00000000..1742edd2
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ro.json
@@ -0,0 +1,83 @@
+{
+ "@metadata": {
+ "authors": [
+ "Minisarm",
+ "Stelistcristi"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titlu: $1",
+ "mwe-embedplayer-credit-date": "Data: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-nocredits": "Niciun credit disponibil",
+ "mwe-embedplayer-loading_plugin": "Se Ʈncarcă modulul...",
+ "mwe-embedplayer-select_playback": "Setează preferințele de redare",
+ "mwe-embedplayer-link_back": "Legătură către Ʈnapoi",
+ "mwe-embedplayer-error_swap_vid": "Eroare: mwEmbed nu a putut schimba eticheta videoului pentru interfața mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Adaugă la sfĆ¢rșitul secvenței",
+ "mwe-embedplayer-missing_video_stream": "Fișierul video pentru acest flux lipsește",
+ "mwe-embedplayer-play_clip": "Redă clipul",
+ "mwe-embedplayer-pause_clip": "Pauză",
+ "mwe-embedplayer-volume_control": "Control de volum",
+ "mwe-embedplayer-player_options": "Opțiunile playerului",
+ "mwe-embedplayer-timed_text": "Subtitrare sincronizată",
+ "mwe-embedplayer-player_fullscreen": "Ecran complet",
+ "mwe-embedplayer-next_clip_msg": "Redă clipul următor",
+ "mwe-embedplayer-prev_clip_msg": "Redă clip precedent",
+ "mwe-embedplayer-current_clip_msg": "Continuă redarea acestui clip",
+ "mwe-embedplayer-seek_to": "Derulează la $1",
+ "mwe-embedplayer-paused": "Ʈn pauză",
+ "mwe-embedplayer-download_segment": "Descarcă selecția:",
+ "mwe-embedplayer-download_full": "Descărcare videoclip Ʈntreg:",
+ "mwe-embedplayer-download_right_click": "Pentru a descărca, faceți clic dreapta și selectați <i>Salvează legătura ca...</i>",
+ "mwe-embedplayer-download_clip": "Descarcă videoclipul",
+ "mwe-embedplayer-download_text": "Descărcare subtitrare",
+ "mwe-embedplayer-download": "Descărcare",
+ "mwe-embedplayer-share": "Distribuire",
+ "mwe-embedplayer-credits": "Credite",
+ "mwe-embedplayer-about-library": "Despre playerul Kaltura",
+ "mwe-embedplayer-about-library-desc": "Biblioteca HTML5 de la Kaltura vă ajută să profitați de avantajele atributelor &lt;video&gt; și &lt;audio&gt; prezente astăzi Ć®n HTML5 cu o interfață de player consistentă și compatibilă cu cele mai populare navigatoare.\n\n[$1 Mai multe despre biblioteca playerului Kaltura].",
+ "mwe-embedplayer-clip_linkback": "Pagina sursă a clipului",
+ "mwe-embedplayer-choose_player": "Alegere player video",
+ "mwe-embedplayer-no-player": "Niciun player disponibil pentru $1",
+ "mwe-embedplayer-share_this_video": "Distribuire videoclip",
+ "mwe-embedplayer-video_credits": "Creditele videoclipului",
+ "mwe-embedplayer-no-video_credits": "Niciun credit disponibil",
+ "mwe-embedplayer-kaltura-platform-title": "Platforma video cu sursă deschisă de la Kaltura",
+ "mwe-embedplayer-menu_btn": "Meniu",
+ "mwe-embedplayer-close_btn": "Ǝnchide",
+ "mwe-embedplayer-ogg-player-vlc-player": "Player VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Player HTML5 Ogg",
+ "mwe-embedplayer-ogg-player-mp3Native": "Player MP3 HTML5",
+ "mwe-embedplayer-ogg-player-aacNative": "Player AAC HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "Player HTML5 H.264",
+ "mwe-embedplayer-ogg-player-webmNative": "Player HTML5 WebM",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Modul generic Ogg",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Modul QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "ActiveX QuickTime",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Player Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(selectat)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Pentru o vizionare mai bună a videoclipului vă recomandăm un <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">navigator compatibil cu modulul video din HTML5</a>.",
+ "mwe-embedplayer-download-warn": "Nu s-a detectat niciun player integrat Ć®n navigator compatibil: pentru a reda Ć®n navigator, vă rugăm să descărcați [$1 ultima versiune de Firefox].",
+ "mwe-embedplayer-fullscreen-tip": "Apăsați <b>F11</b> pentru a comuta <i>navigatorul</i> Ć®n modul ecran complet",
+ "mwe-embedplayer-fullscreen-tip-osx": "Apăsați <b>shift āŒ˜ F</b> pentru a comuta Ć®n modul ecran complet",
+ "mwe-embedplayer-do_not_warn_again": "Nu mai afișa acest mesaj Ć®n viitor",
+ "mwe-embedplayer-playerSelect": "Playere",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Citiți aici</a> Ć®nainte de a Ć®ncorpora.",
+ "mwe-embedplayer-embed_site_or_blog": "Ǝncorporare pe o pagină",
+ "mwe-embedplayer-embed_wiki": "Ǝncorporare pe un wiki",
+ "mwe-embedplayer-related_videos": "Videoclipuri similare",
+ "mwe-embedplayer-seeking": "derulare",
+ "mwe-embedplayer-buffering": "Ʈncărcare Ʈn memoria tampon",
+ "mwe-embedplayer-video-h264": "Video H.264",
+ "mwe-embedplayer-video-webm": "Video WebM",
+ "mwe-embedplayer-video-flv": "Video Flash",
+ "mwe-embedplayer-video-ogg": "Video Ogg",
+ "mwe-embedplayer-video-audio": "Audio Ogg",
+ "mwe-embedplayer-audio-mpeg": "Audio MPEG",
+ "mwe-embedplayer-video-3gp": "Video 3GP",
+ "mwe-embedplayer-video-mpeg": "Video MPEG",
+ "mwe-embedplayer-video-msvideo": "Video AVI",
+ "mwe-embedplayer-missing-source": "Nu s-a găsit niciun videoclip sursă."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/roa-tara.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/roa-tara.json
new file mode 100644
index 00000000..698f8860
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/roa-tara.json
@@ -0,0 +1,33 @@
+{
+ "@metadata": {
+ "authors": [
+ "Joetaras"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titole: $1",
+ "mwe-embedplayer-credit-date": "Date: $1",
+ "mwe-embedplayer-credit-author": "Autore: $1",
+ "mwe-embedplayer-download_clip": "Scareche 'u video",
+ "mwe-embedplayer-download_text": "Scareche 'u teste",
+ "mwe-embedplayer-download": "Scareche",
+ "mwe-embedplayer-share": "Condivide",
+ "mwe-embedplayer-credits": "Credite",
+ "mwe-embedplayer-menu_btn": "MenĆ¹",
+ "mwe-embedplayer-close_btn": "Chiude",
+ "mwe-embedplayer-ogg-player-vlc-player": "Visualizzatore VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Visualizzatore Ogg de HTML5",
+ "mwe-embedplayer-ogg-player-mp3Native": "Visualizzatore MP3 de HTML5",
+ "mwe-embedplayer-ogg-player-aacNative": "Visualizzatore AAC de HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "Visualizzatore H.264 de HTML5",
+ "mwe-embedplayer-ogg-player-webmNative": "Visualizzatore WebM de HTML5",
+ "mwe-embedplayer-ogg-player-selected": "(scacchiate)",
+ "mwe-embedplayer-video-h264": "Video H.264",
+ "mwe-embedplayer-video-webm": "Video WebM",
+ "mwe-embedplayer-video-flv": "Video Flash",
+ "mwe-embedplayer-video-ogg": "Video Ogg",
+ "mwe-embedplayer-video-audio": "Audio Ogg",
+ "mwe-embedplayer-audio-mpeg": "Audio MPEG",
+ "mwe-embedplayer-video-3gp": "Video 3GP",
+ "mwe-embedplayer-video-mpeg": "Video MPEG",
+ "mwe-embedplayer-video-msvideo": "Video AVI"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ru.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ru.json
new file mode 100644
index 00000000..899217a0
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ru.json
@@ -0,0 +1,100 @@
+{
+ "@metadata": {
+ "authors": [
+ "Eleferen",
+ "MaxSem",
+ "Okras",
+ "ŠŠ»ŠµŠŗсŠ°Š½Š“р Š”ŠøŠ³Š°Ń‡Ń‘Š²",
+ "Kaganer"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "ŠŠ°Š·Š²Š°Š½ŠøŠµ: $1",
+ "mwe-embedplayer-credit-date": "Š”Š°Ń‚Š°: $1",
+ "mwe-embedplayer-credit-author": "ŠŠ²Ń‚Š¾Ń€: $1",
+ "mwe-embedplayer-nocredits": "ŠŠµŃ‚ сŠ²ŠµŠ“ŠµŠ½ŠøŠ¹ Š¾ сŠ¾Š·Š“Š°Ń‚ŠµŠ»ŃŃ…",
+ "mwe-embedplayer-loading_plugin": "Š·Š°Š³Ń€ŃƒŠ·ŠŗŠ° ŠæŠ»Š°Š³ŠøŠ½Š° ...",
+ "mwe-embedplayer-select_playback": "Š£ŃŃ‚Š°Š½Š¾Š²Šøть Š½Š°ŃŃ‚Ń€Š¾Š¹ŠŗŠø Š²Š¾ŃŠæрŠ¾ŠøŠ·Š²ŠµŠ“ŠµŠ½Šøя",
+ "mwe-embedplayer-link_back": "ŠžŠ±Ń€Š°Ń‚Š½Š°Ń ссыŠ»ŠŗŠ°",
+ "mwe-embedplayer-error_swap_vid": "ŠžŃˆŠøŠ±ŠŗŠ°: mv_embed Š½Šµ Š¼Š¾Š¶ŠµŃ‚ ŠæŠ¾Š¼ŠµŠ½ŃŃ‚ŃŒ тŠµŠ³ Š²ŠøŠ“ŠµŠ¾ Š“Š»Ń ŠøŠ½Ń‚ŠµŃ€Ń„ŠµŠ¹ŃŠ° mv_embed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Š”Š¾Š±Š°Š²Šøть Š² ŠŗŠ¾Š½ŠµŃ† ŠæŠ¾ŃŠ»ŠµŠ“Š¾Š²Š°Ń‚ŠµŠ»ŃŒŠ½Š¾ŃŃ‚Šø",
+ "mwe-embedplayer-missing_video_stream": "Š’ŠøŠ“ŠµŠ¾Ń„Š°Š¹Š» Š“Š»Ń этŠ¾Š³Š¾ ŠæŠ¾Ń‚Š¾ŠŗŠ° Š¾Ń‚ŃŃƒŃ‚ŃŃ‚Š²ŃƒŠµŃ‚",
+ "mwe-embedplayer-play_clip": "Š’Š¾ŃŠæрŠ¾ŠøŠ·Š²ŠµŃŃ‚Šø ŠŗŠ»ŠøŠæ",
+ "mwe-embedplayer-pause_clip": "ŠŸŃ€ŠøŠ¾ŃŃ‚Š°Š½Š¾Š²Šøть ŠŗŠ»ŠøŠæ",
+ "mwe-embedplayer-volume_control": "Š ŠµŠ³ŃƒŠ»ŠøрŠ¾Š²ŠŗŠ° Š³Ń€Š¾Š¼ŠŗŠ¾ŃŃ‚Šø",
+ "mwe-embedplayer-player_options": "ŠŠ°ŃŃ‚Ń€Š¾Š¹ŠŗŠø ŠæрŠ¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»Ń",
+ "mwe-embedplayer-timed_text": "Š”ŠøŠ½Ń…Ń€Š¾Š½ŠøŠ·ŠøрŠ¾Š²Š°Š½Š½Ń‹Š¹ тŠµŠŗст",
+ "mwe-embedplayer-player_fullscreen": "ŠŠ° Š²ŠµŃŃŒ эŠŗрŠ°Š½",
+ "mwe-embedplayer-next_clip_msg": "Š’Š¾ŃŠæрŠ¾ŠøŠ·Š²ŠµŃŃ‚Šø сŠ»ŠµŠ“ующŠøŠ¹ ŠŗŠ»ŠøŠæ",
+ "mwe-embedplayer-prev_clip_msg": "Š’Š¾ŃŠæрŠ¾ŠøŠ·Š²ŠµŃŃ‚Šø ŠæрŠµŠ“ыŠ“ущŠøŠ¹ ŠŗŠ»ŠøŠæ",
+ "mwe-embedplayer-current_clip_msg": "ŠŸŃ€Š¾Š“Š¾Š»Š¶Šøть Š²Š¾ŃŠæрŠ¾ŠøŠ·Š²ŠµŠ“ŠµŠ½ŠøŠµ этŠ¾Š³Š¾ ŠŗŠ»ŠøŠæŠ°",
+ "mwe-embedplayer-seek_to": "ŠŸŠµŃ€ŠµŠ¹Ń‚Šø Šŗ $1",
+ "mwe-embedplayer-paused": "ŠæŠ°ŃƒŠ·Š°",
+ "mwe-embedplayer-download_segment": "Š’Ń‹Š±Š¾Ń€ Š·Š°Š³Ń€ŃƒŠ·ŠŗŠø:",
+ "mwe-embedplayer-download_full_video": "Š—Š°Š³Ń€ŃƒŠ·Šøть ŠæŠ¾Š»Š½Ń‹Š¹ Š²ŠøŠ“ŠµŠ¾-фŠ°Š¹Š»:",
+ "mwe-embedplayer-download_full_audio": "Š—Š°Š³Ń€ŃƒŠ·Šøть ŠæŠ¾Š»Š½Ń‹Š¹ Š°ŃƒŠ“ŠøŠ¾-фŠ°Š¹Š»:",
+ "mwe-embedplayer-download_right_click": "Š§Ń‚Š¾Š±Ń‹ Š·Š°Š³Ń€ŃƒŠ·Šøть, Š½Š°Š¶Š¼ŠøтŠµ ŠæрŠ°Š²ŃƒŃŽ ŠŗŠ½Š¾ŠæŠŗу Šø Š²Ń‹Š±ŠµŃ€ŠøтŠµ Ā«Š”Š¾Ń…Ń€Š°Š½Šøть Š¾Š±ŃŠŠµŠŗт ŠŗŠ°Šŗā€¦Ā»",
+ "mwe-embedplayer-download_clip": "Š—Š°Š³Ń€ŃƒŠ·Šøть Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-download_text": "Š—Š°Š³Ń€ŃƒŠ·Šøть тŠµŠŗст",
+ "mwe-embedplayer-download": "Š”ŠŗŠ°Ń‡Š°Ń‚ŃŒ",
+ "mwe-embedplayer-share": "ŠŸŠ¾Š“ŠµŠ»Šøться",
+ "mwe-embedplayer-credits": "Š”Š¾Š·Š“Š°Ń‚ŠµŠ»Šø",
+ "mwe-embedplayer-about-library": "Šž ŠæрŠ¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»Šµ Kaltura",
+ "mwe-embedplayer-about-library-desc": "HTML5 Š¼ŠµŠ“ŠøŠ°-Š±ŠøŠ±Š»ŠøŠ¾Ń‚ŠµŠŗŠ° Kaltura ŠæŠ¾Š·Š²Š¾Š»ŃŠµŃ‚ Š²Š°Š¼ уŠ¶Šµ сŠµŠ¹Ń‡Š°Ń ŠæŠ¾Š»ŃŒŠ·Š¾Š²Š°Ń‚ŃŒŃŃ тŠµŠ³Š°Š¼Šø HTML5 <code><nowiki><video></nowiki></code> Šø <code><nowiki><audio></nowiki></code> сŠ¾ стŠ°Š½Š“Š°Ń€Ń‚Š½Ń‹Š¼ ŠøŠ½Ń‚ŠµŃ€Ń„ŠµŠ¹ŃŠ¾Š¼ Š²Š¾ŃŠæрŠ¾ŠøŠ·Š²ŠµŠ“ŠµŠ½Šøя Š²Š¾ Š²ŃŠµŃ… Š¾ŃŠ½Š¾Š²Š½Ń‹Ń… Š±Ń€Š°ŃƒŠ·ŠµŃ€Š°Ń….\n\n[$1 ŠŸŠ¾Š“рŠ¾Š±Š½ŠµŠµ Š¾ Š±ŠøŠ±Š»ŠøŠ¾Ń‚ŠµŠŗŠµ ŠæрŠ¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»Ń Kaltura].",
+ "mwe-embedplayer-clip_linkback": "Š˜ŃŃ…Š¾Š“Š½Š°Ń стрŠ°Š½ŠøцŠ° ŠŗŠ»ŠøŠæŠ°",
+ "mwe-embedplayer-choose_player": "Š’Ń‹Š±Š¾Ń€ ŠæрŠ¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»Ń",
+ "mwe-embedplayer-no-player": "ŠŠµŃ‚ ŠæрŠ¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»Ń Š“Š»Ń $1",
+ "mwe-embedplayer-share_this_video": "ŠŸŠ¾Š“ŠµŠ»Šøться этŠøŠ¼ Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-share_this_audio": "ŠŸŠ¾Š“ŠµŠ»Šøться этŠøŠ¼ Š°ŃƒŠ“ŠøŠ¾-фŠ°Š¹Š»Š¾Š¼",
+ "mwe-embedplayer-video_credits": "Šž сŠ¾Š·Š“Š°Ń‚ŠµŠ»ŃŃ… Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-no-video_credits": "ŠŠµŃ‚ сŠ²ŠµŠ“ŠµŠ½ŠøŠ¹ Š¾ сŠ¾Š·Š“Š°Ń‚ŠµŠ»ŃŃ…",
+ "mwe-embedplayer-kaltura-platform-title": "Š’ŠøŠ“ŠµŠ¾-ŠæŠ»Š°Ń‚Ń„Š¾Ń€Š¼Š° с Š¾Ń‚ŠŗрытыŠ¼ ŠøсхŠ¾Š“Š½Ń‹Š¼ ŠŗŠ¾Š“Š¾Š¼ Kaltura",
+ "mwe-embedplayer-menu_btn": "ŠœŠµŠ½ŃŽ",
+ "mwe-embedplayer-close_btn": "Š—Š°Šŗрыть",
+ "mwe-embedplayer-ogg-player-vlc-player": "ŠŸŃ€Š¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»ŃŒ VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "ŠŸŃ€Š¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»ŃŒ HTML5 Ogg",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3-ŠæрŠ¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»ŃŒ",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AAC-ŠæрŠ¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»ŃŒ",
+ "mwe-embedplayer-ogg-player-h264Native": "ŠŸŃ€Š¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»ŃŒ HTML5 H.264",
+ "mwe-embedplayer-ogg-player-webmNative": "ŠŸŃ€Š¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»ŃŒ HTML5 WebM",
+ "mwe-embedplayer-ogg-player-oggPlugin": "ŠžŠ±Ń‰ŠøŠ¹ ŠæŠ»Š°Š³ŠøŠ½ Ogg",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "ŠŸŃ€ŠøŠ»Š¾Š¶ŠµŠ½ŠøŠµ VLC Š“Š»Ń iOS",
+ "mwe-embedplayer-ogg-player-IEWebMPrompt": "Š—Š°Š³Ń€ŃƒŠ·Ń‡ŠøŠŗ ŠæŠ»Š°Š³ŠøŠ½Š° IE WebM",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "ŠŸŠ»Š°Š³ŠøŠ½ QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "ŠŸŃ€Š¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»ŃŒ Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(Š²Ń‹Š±Ń€Š°Š½Š¾)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Š”Š»Ń Š»ŃƒŃ‡ŃˆŠµŠ³Š¾ Š²Š¾ŃŠæрŠ¾ŠøŠ·Š²ŠµŠ“ŠµŠ½Šøя Š²ŠøŠ“ŠµŠ¾ Š¼Ń‹ рŠµŠŗŠ¾Š¼ŠµŠ½Š“уŠµŠ¼ <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">Š±Ń€Š°ŃƒŠ·ŠµŃ€, ŠæŠ¾Š“Š“ŠµŃ€Š¶ŠøŠ²Š°ŃŽŃ‰ŠøŠ¹ HTML5</a>.",
+ "mwe-embedplayer-download-warn": "ŠŠµ Š½Š°Š¹Š“ŠµŠ½Š¾ Š²ŃŃ‚Ń€Š¾ŠµŠ½Š½Š¾Š³Š¾ Š² Š±Ń€Š°ŃƒŠ·ŠµŃ€ ŠæрŠ¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»Ń, Š“Š»Ń Š²Š¾ŃŠæрŠ¾ŠøŠ·Š²ŠµŠ“ŠµŠ½ŠøŠø Š² Š±Ń€Š°ŃƒŠ·ŠµŃ€Šµ Š·Š°Š³Ń€ŃƒŠ·ŠøтŠµ [$1 ŠæŠ¾ŃŠ»ŠµŠ“Š½ŠøŠ¹ Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "ŠšŠ»Š°Š²ŠøшŠ° <b>F11</b> ŠæŠµŃ€ŠµŠ²Š¾Š“Šøт <i>Š²ŠµŠ±-Š±Ń€Š°ŃƒŠ·ŠµŃ€</i> Š² ŠæŠ¾Š»Š½Š¾ŃŠŗрŠ°Š½Š½Ń‹Š¹ рŠµŠ¶ŠøŠ¼",
+ "mwe-embedplayer-fullscreen-tip-osx": "ŠŠ°Š¶Š¼ŠøтŠµ <b>shift āŒ˜ F</b> Š“Š»Ń ŠæŠµŃ€ŠµŃ…Š¾Š“Š° Š² ŠæŠ¾Š»Š½Š¾ŃŠŗрŠ°Š½Š½Ń‹Š¹ рŠµŠ¶ŠøŠ¼",
+ "mwe-embedplayer-do_not_warn_again": "ŠŠµ ŠæŠ¾ŠŗŠ°Š·Ń‹Š²Š°Ń‚ŃŒ этŠ¾ сŠ¾Š¾Š±Ń‰ŠµŠ½ŠøŠµ Š² Š±ŃƒŠ“ущŠµŠ¼",
+ "mwe-embedplayer-playerSelect": "ŠŸŃ€Š¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»Šø",
+ "mwe-embedplayer-read_before_embed": "ŠŸŠ¾Š¶Š°Š»ŃƒŠ¹ŃŃ‚Š°, <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">ŠæрŠ¾Ń‡Ń‚ŠøтŠµ этŠ¾</a> ŠæŠµŃ€ŠµŠ“ Š²ŃŃ‚Ń€Š°ŠøŠ²Š°Š½ŠøŠµŠ¼!",
+ "mwe-embedplayer-embed_site_or_blog": "Š’стŠ°Š²Šøть Š½Š° стрŠ°Š½Šøцу",
+ "mwe-embedplayer-embed_wiki": "Š’Š½ŠµŠ“рёŠ½ Š² Š²ŠøŠŗŠø",
+ "mwe-embedplayer-related_videos": "Š”Š²ŃŠ·Š°Š½Š½Ń‹Šµ Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-seeking": "ŠæŠ¾ŠøсŠŗ",
+ "mwe-embedplayer-buffering": "Š±ŃƒŃ„ŠµŃ€ŠøŠ·Š°Ń†Šøя",
+ "mwe-embedplayer-video-h264": "Š’ŠøŠ“ŠµŠ¾ H.264",
+ "mwe-embedplayer-video-webm": "Š’ŠøŠ“ŠµŠ¾ WebM",
+ "mwe-embedplayer-video-flv": "Flash-Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-ogg": "Ogg-Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-audio": "Ogg-Š°ŃƒŠ“ŠøŠ¾",
+ "mwe-embedplayer-audio-mpeg": "MPEG-Š°ŃƒŠ“ŠøŠ¾",
+ "mwe-embedplayer-video-3gp": "3GP-Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-mpeg": "MPEG-Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-msvideo": "AVI-Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-missing-source": "ŠŠµ Š½Š°Š¹Š“ŠµŠ½ ŠøстŠ¾Ń‡Š½ŠøŠŗ Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-vlcapp-intro": "Š”Š»Ń ŠæрŠ¾ŃŠ¼Š¾Ń‚Ń€Š° Š²ŠøŠ“ŠµŠ¾ с этŠ¾Š³Š¾ сŠ°Š¹Ń‚Š° Š½Š° iPhone ŠøŠ»Šø iPad Š²Š°Š¼ Š½ŃƒŠ¶Š½Š¾ Š±ŠµŃŠæŠ»Š°Ń‚Š½Š¾Šµ ŠæрŠøŠ»Š¾Š¶ŠµŠ½ŠøŠµ $1.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "ŠŸŃ€ŠøŠ»Š¾Š¶ŠµŠ½ŠøŠµ VLC",
+ "mwe-embedplayer-vlcapp-downloadapp": "Š—Š°Š³Ń€ŃƒŠ·Šøть ŠæрŠøŠ»Š¾Š¶ŠµŠ½ŠøŠµ VLC ŠøŠ· App Store",
+ "mwe-embedplayer-vlcapp-openvideo": "ŠžŃ‚Šŗрыть этŠ¾ Š²ŠøŠ“ŠµŠ¾ Š² ŠæрŠøŠ»Š¾Š¶ŠµŠ½ŠøŠø VLC",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Š”ŠŗŠ°Ń‡Š°Ń‚ŃŒ этŠ¾ Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "Š”Š»Ń Š²Š¾ŃŠæрŠ¾ŠøŠ·Š²ŠµŠ“ŠµŠ½Šøя Š²ŠøŠ“ŠµŠ¾ Š½Š° этŠ¾Š¼ сŠ°Š¹Ń‚Šµ Š²Š°Š¼ Š½ŠµŠ¾Š±Ń…Š¾Š“ŠøŠ¼Š¾ Š±ŠµŃŠæŠ»Š°Ń‚Š½Š¾Šµ ŠæрŠøŠ»Š¾Š¶ŠµŠ½ŠøŠµ VLC. Š£ŃŃ‚Š°Š½Š¾Š²Šøть сŠµŠ¹Ń‡Š°Ń?",
+ "mwe-embedplayer-iewebmprompt-intro": "Š£Šæс! Š•Ń‰Ń‘ ŠŗŠ¾Šµ-чтŠ¾, ŠæрŠµŠ¶Š“Šµ чŠµŠ¼ Š²Ń‹ сŠ¼Š¾Š¶ŠµŃ‚Šµ ŠæрŠ¾ŃŠ¼Š¾Ń‚Ń€ŠµŃ‚ŃŒ этŠ¾ Š²ŠøŠ“ŠµŠ¾ā€¦",
+ "mwe-embedplayer-iewebmprompt-linktext": "Š£ŃŃ‚Š°Š½Š¾Š²ŠøтŠµ Š¼ŠµŠ“ŠøŠ°-ŠŗŠ¾Š¼ŠæŠ¾Š½ŠµŠ½Ń‚Ń‹ WebM Š“Š»Ń Microsoft Internet Explorer",
+ "mwe-embedplayer-iewebmprompt-outro": "ŠŸŠ¾ŃŠ»Šµ устŠ°Š½Š¾Š²ŠŗŠø ŠæŠµŃ€ŠµŠ·Š°Š³Ń€ŃƒŠ·ŠøтŠµ эту стрŠ°Š½Šøцу."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/rue.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/rue.json
new file mode 100644
index 00000000..86c2c343
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/rue.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gazeb"
+ ]
+ },
+ "mwe-embedplayer-close_btn": "Š—Š°ŠæŠµŃ€Ń‚Šø",
+ "mwe-embedplayer-ogg-player-vlc-player": "ŠŸŠµŃ€ŠµŠ³Ń€Š°Š²Š°Ń‡ VLC"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/si.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/si.json
new file mode 100644
index 00000000..76991f4a
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/si.json
@@ -0,0 +1,78 @@
+{
+ "@metadata": {
+ "authors": [
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ",
+ "Susith Chandira Gts"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "ą¶øą·ą¶­ą·˜ą¶šą·ą·€: $1",
+ "mwe-embedplayer-credit-date": "ą¶Æą·’ą¶±ą¶ŗ: $1",
+ "mwe-embedplayer-credit-author": "ą¶šą¶­ą·˜: $1",
+ "mwe-embedplayer-nocredits": "ą·ƒą·Šą¶­ą·–ą¶­ą·’ ą¶šą·’ą·ƒą·’ą·€ą¶šą·Š ą¶½ą¶¶ą· ą¶œą¶­ ą¶±ą·œą·„ą·ą¶š",
+ "mwe-embedplayer-loading_plugin": "ą¶“ą·Šą¶½ą¶œą·“ą¶±ą¶ŗ ą¶“ą·–ą¶»ą¶«ą¶ŗ ą·€ą·™ą¶øą·’ą¶±ą·Š ...",
+ "mwe-embedplayer-select_playback": "ą¶“ą·’ą·…ą·’ą·€ą·ą¶ŗą·’ą¶øą·Š ą¶…ą¶·ą·’ą¶»ą·”ą¶ ą·’ą¶ŗ ą·ƒą¶šą·ƒą¶±ą·Šą¶±",
+ "mwe-embedplayer-link_back": "ą¶±ą·ą·€ą¶­ ą·ƒą¶øą·Šą¶¶ą¶±ą·Šą¶° ą¶šą¶»ą¶±ą·Šą¶±",
+ "mwe-embedplayer-add_to_end_of_sequence": "ą¶…ą¶±ą·”ą¶šą·Šā€ą¶»ą¶øą¶ŗą·š ą¶…ą·€ą·ƒą·ą¶±ą¶ŗą¶§ ą¶‘ą¶šą·Š ą¶šą¶»ą¶±ą·Šą¶±",
+ "mwe-embedplayer-missing_video_stream": "ą¶øą·™ą¶ø ą¶“ą·Šā€ą¶»ą·€ą·ą·„ą¶ŗ ą·ƒą¶³ą·„ą· ą·€ą·“ą¶©ą·’ą¶ŗą· ą¶œą·œą¶±ą·”ą·€ ą¶Æą¶šą·Šą¶±ą¶§ ą¶±ą·œą¶øą·ą¶­",
+ "mwe-embedplayer-play_clip": "ą¶šą·Šą¶½ą·’ą¶“ą¶ŗ ą·€ą¶ŗą¶±ą·Šą¶±",
+ "mwe-embedplayer-pause_clip": "ą¶šą·Šą¶½ą·’ą¶“ą¶ŗ ą·€ą·’ą¶»ą·ą¶øą¶œą¶­ ą¶šą¶»ą¶±ą·Šą¶±",
+ "mwe-embedplayer-volume_control": "ą·ą¶¶ą·Šą¶Æ ą¶“ą·Šā€ą¶»ą¶øą·ą¶« ą¶“ą·ą¶½ą¶šą¶ŗ",
+ "mwe-embedplayer-player_options": "ą·€ą·ą¶Æą¶š ą·€ą·’ą¶šą¶½ą·Šą¶“ą¶ŗą¶±ą·Š",
+ "mwe-embedplayer-timed_text": "ą¶šą·ą¶½ą·’ą¶­ ą¶“ą·™ą·…",
+ "mwe-embedplayer-player_fullscreen": "ą¶“ą·–ą¶»ą·Šą¶« ą¶­ą·’ą¶»ą¶ŗ",
+ "mwe-embedplayer-next_clip_msg": "ą¶øą·“ą·…ą¶Ÿ ą¶šą·Šą¶½ą·’ą¶“ą¶ŗ ą·€ą¶ŗą¶±ą·Šą¶±",
+ "mwe-embedplayer-prev_clip_msg": "ą¶“ą·™ą¶» ą¶šą·Šą¶½ą·’ą¶“ą¶ŗ ą·€ą¶ŗą¶±ą·Šą¶±",
+ "mwe-embedplayer-current_clip_msg": "ą¶øą·™ą¶ø ą¶šą·Šą¶½ą·’ą¶“ą¶ŗ ą¶Æą·’ą¶œą¶§ą¶ø ą·€ą¶ŗą¶±ą·Šą¶±",
+ "mwe-embedplayer-seek_to": "$1 ą¶‰ą¶½ą·’ą¶ŗą¶±ą·Šą¶±",
+ "mwe-embedplayer-paused": "ą·€ą·’ą¶»ą·ą¶øą¶œą¶­ą¶ŗą·’",
+ "mwe-embedplayer-download_segment": "ą¶­ą·šą¶»ą·“ą¶ø ą¶¶ą·ą¶œą¶±ą·Šą¶±:",
+ "mwe-embedplayer-download_full_video": "ą·ƒą¶øą·Šą¶“ą·–ą¶»ą·Šą¶« ą·€ą·“ą¶©ą·’ą¶ŗą· ą¶œą·œą¶±ą·”ą·€ ą¶¶ą·ą¶œą¶±ą·Šą¶±:",
+ "mwe-embedplayer-download_full_audio": "ą¶“ą·–ą¶»ą·Šą¶« ą·ƒą¶‚ą¶œą·“ą¶­ ą¶œą·œą¶±ą·”ą·€ ą¶¶ą·ą¶œą¶±ą·Šą¶±:",
+ "mwe-embedplayer-download_right_click": "ą¶¶ą·ą¶œą¶­ ą¶šą·’ą¶»ą·“ą¶ø ą·ƒą¶³ą·„ą·, ą¶Æą¶šą·”ą¶« ą¶šą·Šą¶½ą·’ą¶šą·Š ą¶šą¶» <i>Save link as...</i> ą¶­ą·ą¶»ą¶±ą·Šą¶±",
+ "mwe-embedplayer-download_clip": "ą·€ą·“ą¶©ą·’ą¶ŗą·ą·€ ą¶¶ą·ą¶œą¶±ą·Šą¶±",
+ "mwe-embedplayer-download_text": "ą¶“ą·ą¶Øą¶ŗ ą¶¶ą·ą¶œą¶±ą·Šą¶±",
+ "mwe-embedplayer-download": "ą¶¶ą·ą¶œą¶±ą·Šą¶±",
+ "mwe-embedplayer-share": "ą·„ą·”ą·€ą¶øą·ą¶»ą·” ą¶šą¶»ą¶±ą·Šą¶±",
+ "mwe-embedplayer-credits": "ą·ƒą·Šą¶­ą·”ą¶­ą·’ą¶ŗ",
+ "mwe-embedplayer-about-library": "Kaltura ą·€ą·ą¶Æą¶šą¶ŗ ą¶“ą·’ą·…ą·’ą¶¶ą¶³",
+ "mwe-embedplayer-clip_linkback": "ą¶šą·Šą¶½ą·’ą¶“ą¶ŗą·š ą¶øą·–ą¶½ą·ą·ą·Šā€ą¶» ą¶“ą·’ą¶§ą·”ą·€",
+ "mwe-embedplayer-choose_player": "ą·€ą·“ą¶©ą·’ą¶ŗą· ą·€ą·ą¶Æą¶šą¶ŗ ą¶­ą·ą¶»ą¶±ą·Šą¶±",
+ "mwe-embedplayer-no-player": "$1 ą·ƒą¶³ą·„ą· ą·€ą·ą¶Æą¶šą¶ŗą¶šą·Š ą¶½ą¶¶ą· ą¶œą¶­ ą¶±ą·œą·„ą·ą¶š",
+ "mwe-embedplayer-share_this_video": "ą¶øą·™ą¶ø ą·€ą·“ą¶©ą·’ą¶ŗą·ą·€ ą·„ą·”ą·€ą¶øą·ą¶»ą·” ą¶šą¶»ą¶±ą·Šą¶±",
+ "mwe-embedplayer-share_this_audio": "ą¶øą·™ą¶ø ą·ƒą¶‚ą¶œą·“ą¶­ ą¶œą·œą¶±ą·”ą·€ ą·„ą·”ą·€ą¶øą·ą¶»ą·” ą¶šą¶»ą¶±ą·Šą¶±",
+ "mwe-embedplayer-video_credits": "ą·€ą·“ą¶©ą·’ą¶ŗą· ą·ƒą·Šą¶­ą·–ą¶­ą·’ą¶ŗ",
+ "mwe-embedplayer-no-video_credits": "ą·ƒą·Šą¶­ą·–ą¶­ą·’ą¶ŗ ą¶½ą¶¶ą· ą¶œą¶­ ą¶±ą·œą·„ą·ą¶š",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura ą·€ą·’ą·€ą·˜ą¶­ ą¶øą·–ą¶½ą·ą·ą·Šā€ą¶» ą·€ą·’ą¶Æą·˜ą·ą·Šā€ą¶ŗ ą¶šą¶»ą·…ą·’ą¶ŗ",
+ "mwe-embedplayer-menu_btn": "ą¶øą·™ą¶±ą·”ą·€",
+ "mwe-embedplayer-close_btn": "ą·€ą·ƒą¶±ą·Šą¶±",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC ą·€ą·ą¶Æą¶šą¶ŗ",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg ą·€ą·ą¶Æą¶šą¶ŗ",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 ą·€ą·ą¶Æą¶šą¶ŗ",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM ą·€ą·ą¶Æą¶šą¶ŗ",
+ "mwe-embedplayer-ogg-player-oggPlugin": "ą¶“ą·Šā€ą¶»ą¶¢ą·ą¶­ą·“ą¶ŗ Ogg ą¶“ą·Šą¶½ą¶œą·“ą¶±ą¶ŗ",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime ą¶“ą·Šą¶½ą¶œą·“ą¶±ą¶ŗ",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "ą·†ą·Šą¶½ą·œą·€ą·Šą·€ą·ą¶Æą¶šą¶ŗ",
+ "mwe-embedplayer-ogg-player-kplayer": "ą¶šą¶½ą·Šą¶­ą·”ą¶»ą· ą·€ą·ą¶Æą¶šą¶ŗ",
+ "mwe-embedplayer-ogg-player-selected": "(ą¶­ą·ą¶»ą·ą¶œą¶­ą·Š)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK ą·†ą·Šą¶½ą·‘ą·‚ą·Š Vorbis",
+ "mwe-embedplayer-fullscreen-tip": "ą¶§ą·œą¶œą¶½ <i>ą·€ą·™ą¶¶ą·Š ą¶œą·€ą·šą·‚ą¶š</i> ą¶“ą·–ą¶»ą·Šą¶« ą¶­ą·’ą¶»ą¶ŗ ą·ƒą¶³ą·„ą· <b>F11</b> ą¶”ą¶¶ą¶±ą·Šą¶±",
+ "mwe-embedplayer-fullscreen-tip-osx": "ą¶§ą·œą¶œą¶½ ą¶“ą·–ą¶»ą·Šą¶« ą¶­ą·’ą¶»ą¶ŗ ą·ƒą¶³ą·„ą· <b>shift āŒ˜ F</b> ą¶”ą¶¶ą¶±ą·Šą¶±",
+ "mwe-embedplayer-do_not_warn_again": "ą¶‰ą¶Æą·’ą¶»ą·’ą¶ŗą·šą¶Æą·“, ą¶øą·™ą¶ø ą¶“ą¶«ą·’ą·€ą·”ą¶©ą¶ŗ ą¶“ą·™ą¶±ą·Šą·€ą¶±ą·Šą¶± ą¶‘ą¶“ą·",
+ "mwe-embedplayer-playerSelect": "ą·€ą·ą¶Æą¶š",
+ "mwe-embedplayer-read_before_embed": "ą¶‘ą¶¶ą·Šą¶¶ą·“ą¶ø ą¶“ą·™ą¶» <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">ą¶øą·™ą¶ŗ ą¶šą·’ą¶ŗą·€ą¶±ą·Šą¶±</a>.",
+ "mwe-embedplayer-embed_site_or_blog": "ą¶“ą·’ą¶§ą·”ą·€ą¶š ą¶”ą¶¶ą·Šą¶¶ą·€ą¶±ą·Šą¶±",
+ "mwe-embedplayer-related_videos": "ą¶†ą·ą·Šā€ą¶»ą·’ą¶­ ą·€ą·“ą¶©ą·’ą¶ŗą·",
+ "mwe-embedplayer-seeking": "ą¶‰ą¶½ą·’ą¶ŗą¶øą·’ą¶±ą·Š",
+ "mwe-embedplayer-buffering": "ą¶…ą·€ą¶»ą·ą¶°ą·“ą¶šą¶»ą¶«ą¶ŗ ą¶šą¶»ą¶øą·’ą¶±ą·Š",
+ "mwe-embedplayer-video-h264": "H.264 ą·€ą·“ą¶©ą·’ą¶ŗą·",
+ "mwe-embedplayer-video-webm": "ą·€ą·™ą¶¶ą·Šą¶‘ą¶øą·Š ą·€ą·“ą¶©ą·’ą¶ŗą·",
+ "mwe-embedplayer-video-flv": "ą·†ą·Šą¶½ą·‘ą·‚ą·Š ą·€ą·“ą¶©ą·’ą¶ŗą·",
+ "mwe-embedplayer-video-ogg": "Ogg ą·€ą·“ą¶©ą·’ą¶ŗą·",
+ "mwe-embedplayer-video-audio": "Ogg ą·ą·Šā€ą¶»ą·€ą·Šā€ą¶ŗ",
+ "mwe-embedplayer-audio-mpeg": "MPEG ą·€ą·“ą¶©ą·’ą¶ŗą·",
+ "mwe-embedplayer-video-3gp": "3GP ą·€ą·“ą¶©ą·’ą¶ŗą·",
+ "mwe-embedplayer-video-mpeg": "MPEG ą·€ą·“ą¶©ą·’ą¶ŗą·",
+ "mwe-embedplayer-video-msvideo": "AVI ą·€ą·“ą¶©ą·’ą¶ŗą·",
+ "mwe-embedplayer-missing-source": "ą¶øą·–ą¶½ą·ą·ą·Šā€ą¶» ą·€ą·“ą¶©ą·’ą¶ŗą·ą·€ą¶šą·Š ą·„ą¶øą·” ą¶±ą·œą·€ą·”ą¶«ą·’"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sk.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sk.json
new file mode 100644
index 00000000..fee61f56
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sk.json
@@ -0,0 +1,6 @@
+{
+ "@metadata": [],
+ "mwe-embedplayer-download": "Stiahnuń",
+ "mwe-embedplayer-close_btn": "Zavrień",
+ "mwe-embedplayer-do_not_warn_again": "Nateraz nezobrazovań"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sr-ec.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sr-ec.json
new file mode 100644
index 00000000..fa893c4a
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sr-ec.json
@@ -0,0 +1,78 @@
+{
+ "@metadata": {
+ "authors": [
+ "Milicevic01",
+ "Rancher",
+ "ŠœŠøхŠ°Ń˜Š»Š¾ ŠŠ½Ń’ŠµŠ»ŠŗŠ¾Š²Šøћ"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "ŠŠ°ŃŠ»Š¾Š²: $1",
+ "mwe-embedplayer-credit-date": "Š”Š°Ń‚ŃƒŠ¼: $1",
+ "mwe-embedplayer-credit-author": "ŠŃƒŃ‚Š¾Ń€: $1",
+ "mwe-embedplayer-loading_plugin": "Š£Ń‡ŠøтŠ°Š²Š°Š¼ Š“Š¾Š“Š°Ń‚Š°Šŗā€¦",
+ "mwe-embedplayer-select_playback": "ŠŸŠ¾ŃŃ‚Š°Š²Šø ŠæŠ¾Š“ŠµŃˆŠ°Š²Š°ŃšŠ° Š·Š° ŠøŠ·Š²Š¾Ń’ŠµŃšŠµ",
+ "mwe-embedplayer-link_back": "ŠžŠ±Ń€Š½ŃƒŃ‚Š° Š²ŠµŠ·Š°",
+ "mwe-embedplayer-error_swap_vid": "Š“Ń€ŠµŃˆŠŗŠ°: mwEmbed Š½Šµ Š¼Š¾Š¶Šµ Š“Š° Š·Š°Š¼ŠµŠ½Šø Š²ŠøŠ“ŠµŠ¾-Š¾Š·Š½Š°Šŗу Š·Š° Š¾ŠŗруŠ¶ŠµŃšŠµ mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Š”Š¾Š“Š°Ń˜ Š½Š° ŠŗрŠ°Ń˜ Š½ŠøŠ·Š°",
+ "mwe-embedplayer-missing_video_stream": "ŠŠµŠ“Š¾ŃŃ‚Š°Ń˜Šµ Š²ŠøŠ“ŠµŠ¾-сŠ½ŠøŠ¼Š°Šŗ Š·Š° Š¾Š²Š°Ń˜ тŠ¾Šŗ",
+ "mwe-embedplayer-play_clip": "ŠŸŃƒŃŃ‚Šø ŠŗŠ»ŠøŠæ",
+ "mwe-embedplayer-pause_clip": "ŠŸŠ°ŃƒŠ·ŠøрŠ°Ń˜ ŠŗŠ»ŠøŠæ",
+ "mwe-embedplayer-volume_control": "ŠšŠ¾Š½Ń‚Ń€Š¾Š»Š° јŠ°Ń‡ŠøŠ½Šµ Š·Š²ŃƒŠŗŠ°",
+ "mwe-embedplayer-player_options": "ŠŸŠ¾ŃŃ‚Š°Š²ŠŗŠµ ŠøŠ·Š²Š¾Ń’Š°Ń‡Š°",
+ "mwe-embedplayer-timed_text": "Š£ŃŠŗŠ»Š°Ń’ŠµŠ½ тŠµŠŗст",
+ "mwe-embedplayer-player_fullscreen": "Š¦ŠµŠ¾ ŠµŠŗрŠ°Š½",
+ "mwe-embedplayer-next_clip_msg": "ŠŸŃƒŃŃ‚Šø сŠ»ŠµŠ“ŠµŃ›Šø ŠŗŠ»ŠøŠæ",
+ "mwe-embedplayer-prev_clip_msg": "ŠŸŃƒŃŃ‚Šø ŠæрŠµŃ‚Ń…Š¾Š“Š½Šø ŠŗŠ»ŠøŠæ",
+ "mwe-embedplayer-current_clip_msg": "ŠŠ°ŃŃ‚Š°Š²Šø с ŠøŠ·Š²Š¾Ń’ŠµŃšŠµŠ¼ Š¾Š²Š¾Š³ сŠ½ŠøŠ¼ŠŗŠ°",
+ "mwe-embedplayer-seek_to": "Š”ŠŗŠ¾Ń‡Šø Š½Š° $1",
+ "mwe-embedplayer-paused": "ŠæŠ°ŃƒŠ·ŠøрŠ°Š½Š¾",
+ "mwe-embedplayer-download_segment": "Š˜Š·Š±Š¾Ń€ Š·Š° ŠæрŠµŃƒŠ·ŠøŠ¼Š°ŃšŠµ:",
+ "mwe-embedplayer-download_full": "ŠŸŃ€ŠµŃƒŠ·Š¼ŠøтŠµ цŠµŠ¾ Š²ŠøŠ“ŠµŠ¾-сŠ½ŠøŠ¼Š°Šŗ:",
+ "mwe-embedplayer-download_right_click": "Š—Š° ŠæрŠµŃƒŠ·ŠøŠ¼Š°ŃšŠµ, ŠæрŠøтŠøсŠ½ŠøтŠµ Š“ŠµŃŠ½Šø ŠŗŠ»ŠøŠŗ Šø ŠøŠ·Š°Š±ŠµŃ€ŠøтŠµ <i>Š”Š°Ń‡ŃƒŠ²Š°Ń˜ Š²ŠµŠ·Ńƒ ŠŗŠ°Š¾ā€¦</i>",
+ "mwe-embedplayer-download_clip": "ŠŸŃ€ŠµŃƒŠ·Š¼Šø Š²ŠøŠ“ŠµŠ¾-сŠ½ŠøŠ¼Š°Šŗ",
+ "mwe-embedplayer-download_text": "ŠŸŃ€ŠµŃƒŠ·Š¼Šø тŠµŠŗст",
+ "mwe-embedplayer-download": "ŠŸŃ€ŠµŃƒŠ·Š¼Šø",
+ "mwe-embedplayer-share": "Š”ŠµŠ»Šø",
+ "mwe-embedplayer-credits": "Š—Š°ŃŠ»ŃƒŠ³Šµ",
+ "mwe-embedplayer-about-library": "Šž ŠøŠ·Š²Š¾Ń’Š°Ń‡Ńƒ ŠšŠ°Š»Ń‚ŃƒŃ€Š°",
+ "mwe-embedplayer-about-library-desc": "ŠšŠ°Š»Ń‚ŃƒŃ€ŠøŠ½Š° Š¼ŃƒŠ»Ń‚ŠøŠ¼ŠµŠ“ŠøјŠ°Š»Š½Š° Š±ŠøŠ±Š»ŠøŠ¾Ń‚ŠµŠŗŠ° HTML5 Š²Š°Š¼ Š¾Š¼Š¾Š³ŃƒŃ›Š°Š²Š° Š“Š° ŠŗŠ¾Ń€ŠøстŠøтŠµ HTML5 Š¾Š·Š½Š°ŠŗŠµ &lt;video&gt; Šø &lt;audio&gt; сŠ° стŠ°Š½Š“Š°Ń€Š“Š½ŠøŠ¼ сучŠµŃ™ŠµŠ¼ Š·Š° ŠøŠ·Š²Š¾Ń’ŠµŃšŠµ ŠæрŠµŠŗŠ¾ Š½Š°Ń˜Š·Š°ŃŃ‚ŃƒŠæљŠµŠ½ŠøјŠøх ŠæрŠµŠ³Š»ŠµŠ“Š°Ń‡Š°.\n\n[$1 Š’ŠøшŠµ Š¾ ŠšŠ°Š»Ń‚ŃƒŃ€ŠøŠ½Š¾Ń˜ Š±ŠøŠ±Š»ŠøŠ¾Ń‚ŠµŃ†Šø Š·Š° ŠøŠ·Š²Š¾Ń’ŠµŃšŠµ].",
+ "mwe-embedplayer-clip_linkback": "Š˜Š·Š²Š¾Ń€Š½Š° стрŠ°Š½ŠøцŠ° сŠ½ŠøŠ¼ŠŗŠ°",
+ "mwe-embedplayer-choose_player": "Š˜Š·Š°Š±ŠµŃ€ŠøтŠµ Š²ŠøŠ“ŠµŠ¾-ŠæŠ»ŠµŃ˜ŠµŃ€",
+ "mwe-embedplayer-no-player": "ŠŠµŠ¼Š° Š“Š¾ŃŃ‚ŃƒŠæŠ½Šøх ŠøŠ·Š²Š¾Ń’Š°Ń‡Š° Š·Š° $1",
+ "mwe-embedplayer-share_this_video": "Š”ŠµŠ»Šø Š¾Š²Š°Ń˜ сŠ½ŠøŠ¼Š°Šŗ",
+ "mwe-embedplayer-video_credits": "ŠŃƒŃ‚Š¾Ń€Šø сŠ½ŠøŠ¼ŠŗŠ°",
+ "mwe-embedplayer-no-video_credits": "ŠŠµŠ¼Š° Š°ŃƒŃ‚Š¾Ń€ŃŠŗŠøх ŠæŠ¾Š“Š°Ń‚Š°ŠŗŠ°",
+ "mwe-embedplayer-kaltura-platform-title": "ŠšŠ°Š»Ń‚ŃƒŃ€ŠøŠ½Š° Š¾Ń‚Š²Š¾Ń€ŠµŠ½Š° Š²ŠøŠ“ŠµŠ¾-ŠæŠ»Š°Ń‚Ń„Š¾Ń€Š¼Š°",
+ "mwe-embedplayer-menu_btn": "ŠœŠµŠ½Šø",
+ "mwe-embedplayer-close_btn": "Š—Š°Ń‚Š²Š¾Ń€Šø",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC ŠæŠ»ŠµŃ˜ŠµŃ€",
+ "mwe-embedplayer-ogg-player-oggNative": "Š˜Š·Š²Š¾Ń’Š°Ń‡ .ogg (HTML5)",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 ŠæŠ»ŠµŃ˜ŠµŃ€",
+ "mwe-embedplayer-ogg-player-webmNative": "Š˜Š·Š²Š¾Ń’Š°Ń‡ WebM (HTML5)",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Š“ŠµŠ½ŠµŃ€ŠøчŠŗŠø Ogg ŠæŠ»Š°Š³ŠøŠ½",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime ŠæŠ»Š°Š³ŠøŠ½",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "ŠšŠ²ŠøŠŗтŠ°Ń˜Š¼ (ŠŠŗтŠøŠ²ŠøŠŗс)",
+ "mwe-embedplayer-ogg-player-cortado": "ŠšŠ¾Ń€Ń‚Š°Š“Š¾ (ŠˆŠ°Š²Š°)",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Š˜Š·Š²Š¾Ń’Š°Ń‡ ŠšŠ°Š»Ń‚ŃƒŃ€Š°",
+ "mwe-embedplayer-ogg-player-selected": "(ŠøŠ·Š°Š±Ń€Š°Š½Š¾)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Š—Š° ŠŗŠ²Š°Š»ŠøтŠµŃ‚Š½ŠøјŠµ ŠæрŠµŠ³Š»ŠµŠ“Š°ŃšŠµ сŠ½ŠøŠ¼Š°ŠŗŠ°, ŠæрŠµŠæŠ¾Ń€ŃƒŃ‡ŃƒŃ˜ŠµŠ¼Š¾ Š²Š°Š¼ <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">HTML5 Š²ŠøŠ“ŠµŠ¾ ŠæрŠµŠ³Š»ŠµŠ“Š°Ń‡</a>.",
+ "mwe-embedplayer-download-warn": "ŠŠøјŠµ ŠæрŠ¾Š½Š°Ń’ŠµŠ½ ŠæрŠøŠŗŠ»Š°Š“Š°Š½ ŠøŠ·Š²Š¾Ń’Š°Ń‡ Š·Š° ŠæуштŠ°ŃšŠµ ŠæрŠµŠŗŠ¾ ŠæрŠµŠ³Š»ŠµŠ“Š°Ń‡Š°. ŠŸŃ€ŠµŃƒŠ·Š¼ŠøтŠµ [$1 Š½Š°Ń˜Š½Š¾Š²ŠøјŠø Š¤Š°Ń˜ŠµŃ€Ń„Š¾Šŗс]",
+ "mwe-embedplayer-fullscreen-tip": "ŠŸŃ€ŠøтŠøсŠ½ŠøтŠµ <b>F11</b> Š“Š° ŠæрŠµŠ±Š°Ń†ŠøтŠµ <i>ŠæрŠµŠ³Š»ŠµŠ“Š°Ń‡</i> Š½Š° цŠµŠ¾ ŠµŠŗрŠ°Š½",
+ "mwe-embedplayer-fullscreen-tip-osx": "ŠŸŃ€ŠøтŠøсŠ½ŠøтŠµ <b>Shift āŒ˜ F</b> Š·Š° ŠæрŠµŠ±Š°Ń†ŠøŠ²Š°ŃšŠµ Š½Š° цŠµŠ¾ ŠµŠŗрŠ°Š½",
+ "mwe-embedplayer-do_not_warn_again": "ŠŠµ ŠæрŠøŠŗŠ°Š·ŃƒŃ˜ Š¾Š²Ńƒ ŠæŠ¾Ń€ŃƒŠŗу ŠæŠ¾Š½Š¾Š²Š¾",
+ "mwe-embedplayer-playerSelect": "Š˜Š·Š²Š¾Ń’Š°Ń‡Šø",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">ŠŸŃ€Š¾Ń‡ŠøтŠ°Ń˜Ń‚Šµ Š¾Š²Š¾</a> ŠæрŠµ уŠ³Ń€Š°Ń’ŠøŠ²Š°ŃšŠ°.",
+ "mwe-embedplayer-embed_site_or_blog": "Š£Š³Ń€Š°Š“Šø у стрŠ°Š½Šøцу",
+ "mwe-embedplayer-related_videos": "Š”рŠ¾Š“Š½Šø Š²ŠøŠ“ŠµŠ¾-сŠ½ŠøŠ¼Ń†Šø",
+ "mwe-embedplayer-seeking": "трŠ°Š¶ŠøŠ¼",
+ "mwe-embedplayer-buffering": "учŠøтŠ°Š²Š°Š¼",
+ "mwe-embedplayer-video-h264": "H.264 Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-webm": "WebM Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-flv": "Š¤Š»ŠµŃˆ Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-ogg": "Ogg Š²ŠøŠ“ŠµŠ¾",
+ "mwe-embedplayer-video-audio": "Ogg Š°ŃƒŠ“ŠøŠ¾",
+ "mwe-embedplayer-missing-source": "ŠŠøјŠµ ŠæрŠ¾Š½Š°Ń’ŠµŠ½ ŠøŠ·Š²Š¾Ń€ сŠ½ŠøŠ¼ŠŗŠ°.",
+ "mwe-embedplayer-vlcapp-downloadvideo": "ŠŸŃ€ŠµŃƒŠ·Š¼Šø Š¾Š²Š°Ń˜ Š²ŠøŠ“ŠµŠ¾"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sr-el.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sr-el.json
new file mode 100644
index 00000000..84f4cb21
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sr-el.json
@@ -0,0 +1,77 @@
+{
+ "@metadata": {
+ "authors": [
+ "Rancher",
+ "Milicevic01"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Naslov: $1",
+ "mwe-embedplayer-credit-date": "Datum: $1",
+ "mwe-embedplayer-credit-author": "Autor: $1",
+ "mwe-embedplayer-loading_plugin": "Učitavam dodatakā€¦",
+ "mwe-embedplayer-select_playback": "Postavi podeÅ”avanja za izvođenje",
+ "mwe-embedplayer-link_back": "Obrnuta veza",
+ "mwe-embedplayer-error_swap_vid": "GreŔka: mwEmbed ne može da zameni video-oznaku za sučelje mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Dodaj na kraj niza",
+ "mwe-embedplayer-missing_video_stream": "Nedostaje video-snimak za ovaj tok",
+ "mwe-embedplayer-play_clip": "Pusti klip",
+ "mwe-embedplayer-pause_clip": "Pauziraj klip",
+ "mwe-embedplayer-volume_control": "Kontrola jačine zvuka",
+ "mwe-embedplayer-player_options": "Postavke izvođača",
+ "mwe-embedplayer-timed_text": "Usklađen tekst",
+ "mwe-embedplayer-player_fullscreen": "Ceo ekran",
+ "mwe-embedplayer-next_clip_msg": "Pusti sledeći klip",
+ "mwe-embedplayer-prev_clip_msg": "Pusti prethodni klip",
+ "mwe-embedplayer-current_clip_msg": "Nastavi s izvođenjem ovog snimka",
+ "mwe-embedplayer-seek_to": "Skoči na $1",
+ "mwe-embedplayer-paused": "pauzirano",
+ "mwe-embedplayer-download_segment": "Izbor za preuzimanje:",
+ "mwe-embedplayer-download_full": "Preuzmite ceo video-snimak:",
+ "mwe-embedplayer-download_right_click": "Za preuzimanje, pritisnite desni klik i izaberite <i>Sačuvaj vezu kaoā€¦</i>",
+ "mwe-embedplayer-download_clip": "Preuzmi video-snimak",
+ "mwe-embedplayer-download_text": "Preuzmi tekst",
+ "mwe-embedplayer-download": "Preuzmi",
+ "mwe-embedplayer-share": "Deli",
+ "mwe-embedplayer-credits": "Zasluge",
+ "mwe-embedplayer-about-library": "O izvođaču Kaltura",
+ "mwe-embedplayer-about-library-desc": "Kalturina multimedijalna biblioteka HTML5 vam omogućava da koristite HTML5 oznake &lt;video&gt; i &lt;audio&gt; sa standardnim sučeljem za izvođenje preko najzastupljenijih pregledača.\n\n[$1 ViÅ”e o Kalturinoj biblioteci za izvođenje].",
+ "mwe-embedplayer-clip_linkback": "Izvorna stranica snimka",
+ "mwe-embedplayer-choose_player": "Izaberite video-plejer",
+ "mwe-embedplayer-no-player": "Nema dostupnih izvođača za $1",
+ "mwe-embedplayer-share_this_video": "Deli ovaj snimak",
+ "mwe-embedplayer-video_credits": "Autori snimka",
+ "mwe-embedplayer-no-video_credits": "Nema autorskih podataka",
+ "mwe-embedplayer-kaltura-platform-title": "Kalturina otvorena video-platforma",
+ "mwe-embedplayer-menu_btn": "Meni",
+ "mwe-embedplayer-close_btn": "Zatvori",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC plejer",
+ "mwe-embedplayer-ogg-player-oggNative": "Izvođač .ogg (HTML5)",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 plejer",
+ "mwe-embedplayer-ogg-player-webmNative": "Izvođač WebM (HTML5)",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Generički Ogg plagin",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime plagin",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "Kviktajm (Aktiviks)",
+ "mwe-embedplayer-ogg-player-cortado": "Kortado (Java)",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Izvođač Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(izabrano)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Za kvalitetnije pregledanje snimaka, preporučujemo vam <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">najnoviji Fajerfoks</a>.",
+ "mwe-embedplayer-download-warn": "Nije pronađen prikladan izvođač za puÅ”tanje preko pregledača. Preuzmite [$1 najnoviji Fajerfoks]",
+ "mwe-embedplayer-fullscreen-tip": "Pritisnite <b>F11</b> da prebacite <i>pregledač</i> na ceo ekran",
+ "mwe-embedplayer-fullscreen-tip-osx": "Pritisnite <b>Shift āŒ˜ F</b> za prebacivanje na ceo ekran",
+ "mwe-embedplayer-do_not_warn_again": "Ne prikazuj ovu poruku ponovo",
+ "mwe-embedplayer-playerSelect": "Izvođači",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Pročitajte ovo</a> pre ugrađivanja.",
+ "mwe-embedplayer-embed_site_or_blog": "Ugradi u stranicu",
+ "mwe-embedplayer-related_videos": "Srodni video-snimci",
+ "mwe-embedplayer-seeking": "tražim",
+ "mwe-embedplayer-buffering": "učitavam",
+ "mwe-embedplayer-video-h264": "H.264 video",
+ "mwe-embedplayer-video-webm": "WebM video",
+ "mwe-embedplayer-video-flv": "FleÅ” video",
+ "mwe-embedplayer-video-ogg": "Ogg video",
+ "mwe-embedplayer-video-audio": "Ogg audio",
+ "mwe-embedplayer-missing-source": "Nije pronađen izvor snimka.",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Preuzmi ovaj video"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sv.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sv.json
new file mode 100644
index 00000000..d34d25d2
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/sv.json
@@ -0,0 +1,96 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ainali",
+ "Dafer45",
+ "Lokal Profil",
+ "WikiPhoenix",
+ "Jenniesarina"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Titel: $1",
+ "mwe-embedplayer-credit-date": "Datum: $1",
+ "mwe-embedplayer-credit-author": "Fƶrfattare: $1",
+ "mwe-embedplayer-nocredits": "Inga erkƤnnanden tillgƤngliga",
+ "mwe-embedplayer-loading_plugin": "laddar insticksmodul...",
+ "mwe-embedplayer-select_playback": "Ange uppspelningsinstƤllningar",
+ "mwe-embedplayer-link_back": "LƤnka tillbaka",
+ "mwe-embedplayer-error_swap_vid": "Fel: mwEmbed kunde inte att byta videoetiketten fƶr mwEmbed-grƤnssnittet",
+ "mwe-embedplayer-add_to_end_of_sequence": "LƤgg till i slutet av sekvens",
+ "mwe-embedplayer-missing_video_stream": "Videofil fƶr den hƤr datastrƶmmen saknas",
+ "mwe-embedplayer-play_clip": "Spela klipp",
+ "mwe-embedplayer-pause_clip": "Pausa klipp",
+ "mwe-embedplayer-volume_control": "Volymkontroll",
+ "mwe-embedplayer-player_options": "Spelaralternativ",
+ "mwe-embedplayer-timed_text": "TidsbestƤmd text",
+ "mwe-embedplayer-player_fullscreen": "FullskƤrm",
+ "mwe-embedplayer-next_clip_msg": "Spela nƤsta klipp",
+ "mwe-embedplayer-prev_clip_msg": "Spela fƶregƄende klipp",
+ "mwe-embedplayer-current_clip_msg": "FortsƤtt spela detta klipp",
+ "mwe-embedplayer-seek_to": "Sƶk $1",
+ "mwe-embedplayer-paused": "pausad",
+ "mwe-embedplayer-download_segment": "HƤmta urval:",
+ "mwe-embedplayer-download_full_video": "Ladda ner den fullstƤndiga videofilen:",
+ "mwe-embedplayer-download_full_audio": "Ladda ned fullstƤndig ljudfil:",
+ "mwe-embedplayer-download_right_click": "Fƶr att ladda ner, hƶgerklicka och vƤlj <i>Spara lƤnk som ...</i>",
+ "mwe-embedplayer-download_clip": "Ladda ner video",
+ "mwe-embedplayer-download_text": "Ladda ner text",
+ "mwe-embedplayer-download": "Ladda ner",
+ "mwe-embedplayer-share": "Dela",
+ "mwe-embedplayer-credits": "ErkƤnnanden",
+ "mwe-embedplayer-about-library": "Om Kaltura player",
+ "mwe-embedplayer-about-library-desc": "Kaltura's HTML5 mediabibliotek ger dig mƶjlighet att utnyttja HTML5 &lt;video&gt; och &lt;audio&gt; taggar idag med ett konsekvent spelargrƤnssnitt ƶver alla stƶrre webblƤsare.\n\n[$1 Mer om Kaltura spelarbiblioteket].",
+ "mwe-embedplayer-clip_linkback": "KlippkƤllsidan",
+ "mwe-embedplayer-choose_player": "VƤlj videouppspelare",
+ "mwe-embedplayer-no-player": "Ingen spelare tillgƤnglig fƶr $1",
+ "mwe-embedplayer-share_this_video": "Dela denna video",
+ "mwe-embedplayer-share_this_audio": "Dela denna ljudfil",
+ "mwe-embedplayer-video_credits": "VideoerkƤnnanden",
+ "mwe-embedplayer-no-video_credits": "Inga erkƤnnanden tillgƤngliga",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura ƶppen kƤllkod videoplattform",
+ "mwe-embedplayer-menu_btn": "Meny",
+ "mwe-embedplayer-close_btn": "StƤng",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC spelare",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg spelare",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3-spelare",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AAC-spelare",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 spelare",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM spelare",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Generiella Ogg-tillƤgg",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "VLC fƶr iOS-app",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime-insticksmodul",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura spelare",
+ "mwe-embedplayer-ogg-player-selected": "(vald)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Fƶr en bƤttre videouppspelningsupplevelse rekommenderar vi en <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">HTML5 videowebblƤsare</a>.",
+ "mwe-embedplayer-download-warn": "Ingen kompatibel mediaspelare i webblƤsaren upptƤcktes: fƶr webblƤsaruppspelning, hƤmta [$1 senaste Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "Tryck pƄ <b>F11</b> fƶr att vƤxla <i>webblƤsaren</i> till helskƤrm",
+ "mwe-embedplayer-fullscreen-tip-osx": "Tryck pĆ„ <b>SKIFT āŒ˜ f</b> fƶr att vƤxla till helskƤrm",
+ "mwe-embedplayer-do_not_warn_again": "Visa inte detta meddelande fortsƤttningsvis",
+ "mwe-embedplayer-playerSelect": "Spelare",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">LƤs detta</a> innan inbƤddning.",
+ "mwe-embedplayer-embed_site_or_blog": "BƤdda in pƄ en sida",
+ "mwe-embedplayer-embed_wiki": "BƤdda in pƄ en wiki",
+ "mwe-embedplayer-related_videos": "Relaterade videos",
+ "mwe-embedplayer-seeking": "sƶker",
+ "mwe-embedplayer-buffering": "buffring",
+ "mwe-embedplayer-video-h264": "H.264 video",
+ "mwe-embedplayer-video-webm": "WebM video",
+ "mwe-embedplayer-video-flv": "Flash-video",
+ "mwe-embedplayer-video-ogg": "Ogg video",
+ "mwe-embedplayer-video-audio": "Ogg ljud",
+ "mwe-embedplayer-audio-mpeg": "MPEG audio",
+ "mwe-embedplayer-video-3gp": "3GP video",
+ "mwe-embedplayer-video-mpeg": "MPEG video",
+ "mwe-embedplayer-video-msvideo": "AVI video",
+ "mwe-embedplayer-missing-source": "Ingen kƤllvideo hittades",
+ "mwe-embedplayer-vlcapp-intro": "I fƶr att visa video frƄn denna webbplats pƄ en iPhone eller iPad, behƶver du den kostnadsfria $1.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "VLC-app",
+ "mwe-embedplayer-vlcapp-downloadapp": "Ladda ner VLC-appen frƄn App Store",
+ "mwe-embedplayer-vlcapp-openvideo": "Ɩppna denna video i VLC-appen",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Ladda ner denna video",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "Fƶr att spela upp video pƄ denna webbplats, behƶver du den kostnadsfria VLC-appen. Installera nu?",
+ "mwe-embedplayer-iewebmprompt-intro": "Oops! En sak till innan du kan spela denna video..."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ta.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ta.json
new file mode 100644
index 00000000..5e8d84a9
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ta.json
@@ -0,0 +1,40 @@
+{
+ "@metadata": {
+ "authors": [
+ "Karthi.dr",
+ "Shanmugamp7",
+ "ą®®ą®¤ą®©ą®¾ą®¹ą®°ą®©ąÆ"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "ą®¤ą®²ąÆˆą®ŖąÆą®ŖąÆ: $1",
+ "mwe-embedplayer-credit-date": "ą®¤ąÆ‡ą®¤ą®æ: $1",
+ "mwe-embedplayer-credit-author": "ą®†ą®•ąÆą®•ąÆą®©ą®°ąÆ: $1",
+ "mwe-embedplayer-play_clip": "ą®¤ąÆą®£ąÆą®ŸąÆˆ ą®‡ą®Æą®•ąÆą®•ąÆ",
+ "mwe-embedplayer-player_fullscreen": "ą®®ąÆą®“ąÆą®¤ąÆą®¤ą®æą®°ąÆˆ",
+ "mwe-embedplayer-next_clip_msg": "ą®…ą®ŸąÆą®¤ąÆą®¤ ą®¤ąÆą®£ąÆą®ŸąÆˆ ą®‡ą®Æą®•ąÆą®•ąÆ",
+ "mwe-embedplayer-prev_clip_msg": "ą®®ąÆą®ØąÆą®¤ąÆˆą®Æ ą®¤ąÆą®£ąÆą®ŸąÆˆ ą®‡ą®Æą®•ąÆą®•ąÆ",
+ "mwe-embedplayer-current_clip_msg": "ą®‡ą®¤ąÆą®¤ąÆą®£ąÆą®ŸąÆˆ ą®‡ą®Æą®•ąÆą®•ąÆą®µą®¤ąÆˆą®¤ąÆ ą®¤ąÆŠą®Ÿą®°ąÆ",
+ "mwe-embedplayer-paused": "ą®‡ą®ŸąÆˆą®Øą®æą®±ąÆą®¤ąÆą®¤ą®ŖąÆą®Ŗą®ŸąÆą®Ÿą®¤ąÆ",
+ "mwe-embedplayer-download_segment": "ą®¤ąÆ†ą®°ą®æą®µąÆˆą®¤ąÆ ą®¤ą®°ą®µą®æą®±ą®•ąÆą®•ąÆ:",
+ "mwe-embedplayer-download_full": "ą®®ąÆą®“ąÆą®•ąÆ ą®•ą®¾ą®£ąÆŠą®³ą®æą®•ąÆ ą®•ąÆ‹ą®ŖąÆą®ŖąÆˆą®¤ąÆ ą®¤ą®°ą®µą®æą®±ą®•ąÆą®•ąÆ:",
+ "mwe-embedplayer-download_clip": "ą®•ą®¾ą®£ąÆŠą®³ą®æą®ÆąÆˆą®¤ąÆ ą®¤ą®°ą®µą®æą®±ą®•ąÆą®•ąÆ",
+ "mwe-embedplayer-download_text": "ą®‰ą®°ąÆˆą®ÆąÆˆą®¤ąÆ ą®¤ą®°ą®µą®æą®±ą®•ąÆą®•ąÆ",
+ "mwe-embedplayer-download": "ą®Ŗą®¤ą®æą®µą®æą®±ą®•ąÆą®•ą®®ąÆ ą®šąÆ†ą®ÆąÆ",
+ "mwe-embedplayer-share": "ą®Ŗą®•ą®æą®°ąÆ",
+ "mwe-embedplayer-choose_player": "ą®•ą®¾ą®£ąÆŠą®³ą®æ ą®‡ą®Æą®•ąÆą®•ą®æą®ÆąÆˆą®¤ąÆ ą®¤ąÆ†ą®°ą®æ",
+ "mwe-embedplayer-share_this_video": "ą®‡ą®•ąÆ ą®•ą®¾ą®£ąÆŠą®³ą®æą®ÆąÆˆą®ŖąÆ ą®Ŗą®•ą®æą®°ąÆą®•",
+ "mwe-embedplayer-menu_btn": "ą®Ŗą®ŸąÆą®Ÿą®æ",
+ "mwe-embedplayer-close_btn": "ą®®ąÆ‚ą®ŸąÆ",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC ą®Šą®Ÿą®• ą®‡ą®Æą®•ąÆą®•ą®æ",
+ "mwe-embedplayer-do_not_warn_again": "ą®µą®°ąÆą®™ąÆą®•ą®¾ą®²ą®¤ąÆą®¤ą®æą®²ąÆ ą®‡ą®šąÆą®šąÆ†ą®ÆąÆą®¤ą®æą®ÆąÆˆą®•ąÆ ą®•ą®¾ą®ŸąÆą®Ÿ ą®µąÆ‡ą®£ąÆą®Ÿą®¾ą®®ąÆ",
+ "mwe-embedplayer-playerSelect": "ą®‡ą®Æą®•ąÆą®•ą®æą®•ą®³ąÆ",
+ "mwe-embedplayer-related_videos": "ą®¤ąÆŠą®Ÿą®°ąÆą®ŖąÆą®³ąÆą®³ ą®•ą®¾ą®£ąÆŠą®³ą®æą®•ą®³ąÆ",
+ "mwe-embedplayer-video-h264": "H.264 ą®•ą®¾ą®£ąÆŠą®³ą®æ",
+ "mwe-embedplayer-video-webm": "WebM ą®•ą®¾ą®£ąÆŠą®³ą®æ",
+ "mwe-embedplayer-video-flv": "ą®Ŗą®æą®³ą®¾ą®·ąÆ ą®•ą®¾ą®£ąÆŠą®³ą®æ",
+ "mwe-embedplayer-video-ogg": "Ogg ą®•ą®¾ą®£ąÆŠą®³ą®æ",
+ "mwe-embedplayer-video-3gp": "3GP ą®•ą®¾ą®£ąÆŠą®³ą®æ",
+ "mwe-embedplayer-video-mpeg": "MPEG ą®•ą®¾ą®£ąÆŠą®³ą®æ",
+ "mwe-embedplayer-video-msvideo": "AVI ą®•ą®¾ą®£ąÆŠą®³ą®æ",
+ "mwe-embedplayer-missing-source": "ą®®ąÆ‚ą®²ą®•ąÆ ą®•ą®¾ą®£ąÆŠą®³ą®æą®ÆąÆ‡ą®¤ąÆą®®ąÆ ą®•ą®£ąÆą®ŸąÆą®Ŗą®æą®Ÿą®æą®•ąÆą®•ą®ŖąÆą®Ŗą®Ÿą®µą®æą®²ąÆą®²ąÆˆ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/te.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/te.json
new file mode 100644
index 00000000..3c69d4f7
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/te.json
@@ -0,0 +1,17 @@
+{
+ "@metadata": {
+ "authors": [
+ "Veeven"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "ą°¶ą±€ą°°ą±ą°·ą°æą°•: $1",
+ "mwe-embedplayer-credit-date": "ą°¤ą±‡ą°¦ą±€: $1",
+ "mwe-embedplayer-player_fullscreen": "ą°Øą°æą°‚ą°”ą±ą°¤ą±†ą°°",
+ "mwe-embedplayer-download": "ą°¦ą°æą°‚ą°Ŗą±ą°•ą±‹ą°²ą±",
+ "mwe-embedplayer-share": "ą°Ŗą°‚ą°šą±ą°•ą±‹ą°‚ą°”ą°æ",
+ "mwe-embedplayer-share_this_video": "ą°ˆ ą°µą±€ą°”ą°æą°Æą±‹ą°Øą°æ ą°Ŗą°‚ą°šą±ą°•ą±‹ą°‚ą°”ą°æ",
+ "mwe-embedplayer-menu_btn": "ą°®ą±†ą°Øą±‚",
+ "mwe-embedplayer-close_btn": "ą°®ą±‚ą°øą°æą°µą±‡ą°Æą°æ",
+ "mwe-embedplayer-ogg-player-selected": "(ą°Žą°‚ą°šą±ą°•ą±ą°Øą±ą°Øą°¾ą°°ą±)",
+ "mwe-embedplayer-related_videos": "ą°øą°‚ą°¬ą°‚ą°§ą°æą°¤ ą°¦ą±ƒą°¶ą±ą°Æą°•ą°¾ą°²ą±"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tet.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tet.json
new file mode 100644
index 00000000..3e73c4ed
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tet.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "MF-Warburg"
+ ]
+ },
+ "mwe-embedplayer-credit-author": "AutĆ³r: $1"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tl.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tl.json
new file mode 100644
index 00000000..78eb2b06
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tl.json
@@ -0,0 +1,83 @@
+{
+ "@metadata": {
+ "authors": [
+ "AnakngAraw",
+ "Sky Harbor",
+ "Leeheonjin"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Pamagat: $1",
+ "mwe-embedplayer-credit-date": "Petsa: $1",
+ "mwe-embedplayer-credit-author": "May-akda: $1",
+ "mwe-embedplayer-nocredits": "Walang makuhang mga pagbanggit",
+ "mwe-embedplayer-loading_plugin": "Ikinakarga ang pampasak ...",
+ "mwe-embedplayer-select_playback": "Itakda ang nais sa pagpapaandar",
+ "mwe-embedplayer-link_back": "Ikawing pabalik",
+ "mwe-embedplayer-error_swap_vid": "Kamalian: hindi nagawang pagpalitin ng mwEmbed ang tatak ng bidyo para sa hangganang-mukha ng mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Idagdag sa huli ng sunuran",
+ "mwe-embedplayer-missing_video_stream": "Nawawala ang talaksan ng biyo para sa daloy na ito",
+ "mwe-embedplayer-play_clip": "Palaruin ang klip",
+ "mwe-embedplayer-pause_clip": "Pahintuin ang klip",
+ "mwe-embedplayer-volume_control": "Pangtaban ng lakas ng tunog",
+ "mwe-embedplayer-player_options": "Pagpipiliang pangpampaandar",
+ "mwe-embedplayer-timed_text": "Tekstong inoorasan",
+ "mwe-embedplayer-player_fullscreen": "Buong panooran",
+ "mwe-embedplayer-next_clip_msg": "Paandarin ang susunod na putol",
+ "mwe-embedplayer-prev_clip_msg": "Paandarin ang nakaraang putol",
+ "mwe-embedplayer-current_clip_msg": "Ipagpatuloy ang pagpapaandar ng putol na ito",
+ "mwe-embedplayer-seek_to": "Hanapin ang $1",
+ "mwe-embedplayer-paused": "hininto",
+ "mwe-embedplayer-download_segment": "Ikargang pababa ang napili:",
+ "mwe-embedplayer-download_full_video": "Ikargang pababa ang buong talaksan ng bidyo:",
+ "mwe-embedplayer-download_right_click": "Upang maikargang paibaba, pindutin ang kanan at piliin ang <i>Sagipin ang kawing bilang...</i>",
+ "mwe-embedplayer-download_clip": "Ikargang pababa ang bidyo",
+ "mwe-embedplayer-download_text": "Ikargang paibaba ang teksto",
+ "mwe-embedplayer-download": "Ikargang pababa",
+ "mwe-embedplayer-share": "Ipamahagi",
+ "mwe-embedplayer-credits": "Mga banggit-pagkilala",
+ "mwe-embedplayer-about-library": "Tungkol sa pampaandar na Kaltura",
+ "mwe-embedplayer-about-library-desc": "Ang aklatan ng midyang HTML5 ng Kaltura ay nagpapahintulot sa iyong samantalahin ang mga tatak na <code><nowiki><bidyo></nowiki></code> na HTML5 at <code><nowiki><audio></nowiki></code> ngayon ng isang ugnayang-mukha ng palagiang pampaandar sa kahabaan ng lahat ng pangunahing mga pantingin-tingin.\n\n[$1 Marami pang hinggil sa aklatan ng pampaandar ng Kaltura].",
+ "mwe-embedplayer-clip_linkback": "Pahinang batayan ng klip",
+ "mwe-embedplayer-choose_player": "Piliin ang pampaandar ng bidyo",
+ "mwe-embedplayer-no-player": "Walang makuhang pampaandar para sa $1",
+ "mwe-embedplayer-share_this_video": "Ipamahagi ang bidyong ito",
+ "mwe-embedplayer-video_credits": "Mga banggit-pagkilala ng bidyo",
+ "mwe-embedplayer-no-video_credits": "Walang makuhang mga pagbanggit",
+ "mwe-embedplayer-kaltura-platform-title": "Plataporma ng bukas na pinagmulan ng bidyo ng Kaltura",
+ "mwe-embedplayer-menu_btn": "Menu",
+ "mwe-embedplayer-close_btn": "Isara",
+ "mwe-embedplayer-ogg-player-vlc-player": "Pampaandar ng VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "Pampaandar ng HTML5 Ogg",
+ "mwe-embedplayer-ogg-player-h264Native": "Pampaandar ng HTML5 H.264",
+ "mwe-embedplayer-ogg-player-webmNative": "Pampaandar ng HTML5 WebM",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Panlahatang pamasak ng Ogg",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Pampasak ng QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "ActiveX ng QuickTime",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Pampaandar na Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Pampaandar ng Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(napili na)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Para sa mas mainam na karanasan ng pagpapaandar ng bidyo iminumungkahi namin ang <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">pantingin-tingin ng bidyo na html5</a>.",
+ "mwe-embedplayer-download-warn": "Walang napansin na kaugmang pampaandar ng pantingin-tingin, para sa pag-uulit ng pagpapaandar ng pantingin-tingin ikargang paibaba ang [$1 pinakahuling Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "Pindutin ang <b>F11</b> pampalit-lipat ng <i>pantingin-tingin sa web</i> na buo ang panooran",
+ "mwe-embedplayer-fullscreen-tip-osx": "Pindutin ang <b>shift āŒ˜ F</b> upang mapalitan at malipatan ang buong panooran",
+ "mwe-embedplayer-do_not_warn_again": "Sa hinaharap, huwag ipakita ang mensaheng ito",
+ "mwe-embedplayer-playerSelect": "Mga pampaandar",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">Basahin ito</a> bago ibaon.",
+ "mwe-embedplayer-embed_site_or_blog": "Ibaon sa isang pahina",
+ "mwe-embedplayer-related_videos": "Kaugnay na mga bidyo",
+ "mwe-embedplayer-seeking": "hinahanap",
+ "mwe-embedplayer-buffering": "pinapakinis",
+ "mwe-embedplayer-video-h264": "Bidyong H.264",
+ "mwe-embedplayer-video-webm": "Bidyong WebM",
+ "mwe-embedplayer-video-flv": "Bidyong Flash",
+ "mwe-embedplayer-video-ogg": "Bidyong Ogg",
+ "mwe-embedplayer-video-audio": "Tunog na Ogg",
+ "mwe-embedplayer-audio-mpeg": "Tunog na MPEG",
+ "mwe-embedplayer-video-3gp": "Bidyong 3GP",
+ "mwe-embedplayer-video-mpeg": "Bidyong MPEG",
+ "mwe-embedplayer-video-msvideo": "Bidyong AVI",
+ "mwe-embedplayer-missing-source": "Walang natagpuang batayang bidyo",
+ "mwe-embedplayer-iewebmprompt-intro": "Ui! Isa pang bagay bago mo i-play itong video..."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tr.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tr.json
new file mode 100644
index 00000000..e76ebff4
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tr.json
@@ -0,0 +1,85 @@
+{
+ "@metadata": {
+ "authors": [
+ "Emperyan",
+ "Sayginer"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Başlık: $1",
+ "mwe-embedplayer-credit-date": "Tarih: $1",
+ "mwe-embedplayer-credit-author": "Yazar: $1",
+ "mwe-embedplayer-loading_plugin": "Eklenti yĆ¼kleniyor ...",
+ "mwe-embedplayer-select_playback": "Tekrar oynatma tercihini ayarla",
+ "mwe-embedplayer-link_back": "Geri bağlantı ver",
+ "mwe-embedplayer-error_swap_vid": "Hata: mwEmbed, mwEmbed arayĆ¼zĆ¼ iƧin video etiketini değiş tokuş yapamıyor",
+ "mwe-embedplayer-add_to_end_of_sequence": "Sıranın sonuna ekle",
+ "mwe-embedplayer-missing_video_stream": "Bu akış iƧin video dosyası kayıp",
+ "mwe-embedplayer-play_clip": "Klibi oynat",
+ "mwe-embedplayer-pause_clip": "Klibi durdur",
+ "mwe-embedplayer-volume_control": "Ses denetimi",
+ "mwe-embedplayer-player_options": "Oynatıcı seƧenekleri",
+ "mwe-embedplayer-timed_text": "Zamanlanmış metin",
+ "mwe-embedplayer-player_fullscreen": "Tam ekran",
+ "mwe-embedplayer-next_clip_msg": "Sonraki klibi oynat",
+ "mwe-embedplayer-prev_clip_msg": "Ɩnceki klibi oynat",
+ "mwe-embedplayer-current_clip_msg": "Bu klibi oynatmaya devam et",
+ "mwe-embedplayer-seek_to": "$1 sĆ¼resine git",
+ "mwe-embedplayer-paused": "durduruldu",
+ "mwe-embedplayer-download_segment": "SeƧimi indir:",
+ "mwe-embedplayer-download_full_video": "Tam video dosyasını indir:",
+ "mwe-embedplayer-download_full_audio": "Ses dosyasının tamamını indir:",
+ "mwe-embedplayer-download_right_click": "Ä°ndirmek iƧin, sağ tıklayın ve <i>Bağlantıyı farklı kaydet...</i>'i seƧin",
+ "mwe-embedplayer-download_clip": "Videoyu indir",
+ "mwe-embedplayer-download_text": "Metni indir",
+ "mwe-embedplayer-download": "Ä°ndir",
+ "mwe-embedplayer-share": "Paylaş",
+ "mwe-embedplayer-credits": "Katkıda bulunanlar",
+ "mwe-embedplayer-about-library": "Kaltura oynatıcısı hakkında",
+ "mwe-embedplayer-clip_linkback": "Klip kaynak sayfası",
+ "mwe-embedplayer-choose_player": "Video oynatıcı seƧ",
+ "mwe-embedplayer-no-player": "$1 iƧin oynatıcı mevcut değil",
+ "mwe-embedplayer-share_this_video": "Bu videoyu paylaş",
+ "mwe-embedplayer-share_this_audio": "Bu ses dosyasını paylaş",
+ "mwe-embedplayer-video_credits": "Videoya katkıda bulunanlar",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura aƧık kaynak kodlu video platformu",
+ "mwe-embedplayer-menu_btn": "MenĆ¼",
+ "mwe-embedplayer-close_btn": "Kapat",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC player",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg oynatıcı",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3 oynatıcı",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AAC oynatıcı",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 oynatıcı",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebM oynatıcı",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Jenerik Ogg eklentisi",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime eklentisi",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kaltura oynatıcısı",
+ "mwe-embedplayer-ogg-player-selected": "(seƧili)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Daha iyi bir video oynatma deneyimi iƧin ƶnerimiz:<br /><a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">Firefox 3.5</a>.",
+ "mwe-embedplayer-do_not_warn_again": "Gelecekte bu iletiyi gƶsterme",
+ "mwe-embedplayer-playerSelect": "Oynatıcılar",
+ "mwe-embedplayer-read_before_embed": "LĆ¼tfen gerƧekten gƶmmeden <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">uzaktan gƶmme hakkındaki gĆ¼venlik notlarını</a> okuyun!",
+ "mwe-embedplayer-embed_site_or_blog": "Bir sayfaya gƶmĆ¼n",
+ "mwe-embedplayer-embed_wiki": "Bir viki Ć¼zerinde gƶm",
+ "mwe-embedplayer-related_videos": "Ä°lgili videolar",
+ "mwe-embedplayer-seeking": "aranıyor",
+ "mwe-embedplayer-buffering": "ara belleğe alınıyor",
+ "mwe-embedplayer-video-h264": "H.264 video",
+ "mwe-embedplayer-video-webm": "WebM video",
+ "mwe-embedplayer-video-flv": "Flash, video",
+ "mwe-embedplayer-video-ogg": "Ogg video",
+ "mwe-embedplayer-video-audio": "Ogg ses",
+ "mwe-embedplayer-audio-mpeg": "MPEG ses",
+ "mwe-embedplayer-video-3gp": "3GP video",
+ "mwe-embedplayer-video-mpeg": "MPEG video",
+ "mwe-embedplayer-video-msvideo": "AVI video",
+ "mwe-embedplayer-missing-source": "Video kaynağı bulunamadı",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "VLC uygulaması",
+ "mwe-embedplayer-vlcapp-downloadapp": "VLC uygulamasını App Store'dan indir",
+ "mwe-embedplayer-vlcapp-openvideo": "Bu videoyu VLC uygulamasıyla aƧ",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Bu videoyu indir",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "Bu sitedeki videoları oynatmak iƧin, Ć¼cretsiz olan VLC uygulaması gerekiyor. Şimdi yĆ¼klensin mi?"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tzm.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tzm.json
new file mode 100644
index 00000000..8a49fbb4
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/tzm.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Tifinaghes"
+ ]
+ },
+ "mwe-embedplayer-share": "ā“¼āµ™ā“»āµ”",
+ "mwe-embedplayer-video-h264": "H.264 video",
+ "mwe-embedplayer-video-flv": "ā“¼āµā“°āµ› video",
+ "mwe-embedplayer-video-ogg": "Ogg video"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/uk.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/uk.json
new file mode 100644
index 00000000..5089e774
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/uk.json
@@ -0,0 +1,92 @@
+{
+ "@metadata": {
+ "authors": [
+ "Andriykopanytsia",
+ "Base",
+ "ŠŃ‚Š°",
+ "Š¢ŠµŃŃ‚"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "ŠŠ°Š·Š²Š°: $1",
+ "mwe-embedplayer-credit-date": "Š”Š°Ń‚Š°: $1",
+ "mwe-embedplayer-credit-author": "ŠŠ²Ń‚Š¾Ń€: $1",
+ "mwe-embedplayer-nocredits": "ŠŠµŠ¼Š° Š²Ń–Š“Š¾Š¼Š¾ŃŃ‚ŠµŠ¹ ŠæрŠ¾ Š°Š²Ń‚Š¾Ń€Š°",
+ "mwe-embedplayer-loading_plugin": "Š—Š°Š²Š°Š½Ń‚Š°Š¶ŠµŠ½Š½Ń Š“Š¾Š“Š°Ń‚ŠŗŠ° ...",
+ "mwe-embedplayer-select_playback": "Š’стŠ°Š½Š¾Š²ŠøтŠø Š½Š°Š»Š°ŃˆŃ‚ŃƒŠ²Š°Š½Š½Ń Š²Ń–Š“тŠ²Š¾Ń€ŠµŠ½Š½Ń",
+ "mwe-embedplayer-link_back": "Š—Š²Š¾Ń€Š¾Ń‚Š½Ń” ŠæŠ¾ŃŠøŠ»Š°Š½Š½Ń",
+ "mwe-embedplayer-error_swap_vid": "ŠŸŠ¾Š¼ŠøŠ»ŠŗŠ°: mwEmbed Š½Šµ Š²Š“Š°Š»Š¾ŃŃ Š·Š°Š¼Ń–Š½ŠøтŠø тŠµŠ³ Š²Ń–Š“ŠµŠ¾ Š“Š»Ń іŠ½Ń‚ŠµŃ€Ń„ŠµŠ¹ŃŃƒ mwEmbed",
+ "mwe-embedplayer-add_to_end_of_sequence": "Š”Š¾Š“Š°Ń‚Šø у ŠŗіŠ½ŠµŃ†ŃŒ ŠæŠ¾ŃŠ»Ń–Š“Š¾Š²Š½Š¾ŃŃ‚Ń–",
+ "mwe-embedplayer-missing_video_stream": "Š’Ń–Š“ŠµŠ¾Ń„Š°Š¹Š» Š“Š»Ń цьŠ¾Š³Š¾ ŠæŠ¾Ń‚Š¾Šŗу Š²Ń–Š“сутŠ½Ń–Š¹",
+ "mwe-embedplayer-play_clip": "Š’Ń–Š“тŠ²Š¾Ń€ŠøтŠø ŠŗŠ»Ń–Šæ",
+ "mwe-embedplayer-pause_clip": "ŠŸŃ€ŠøŠ·ŃƒŠæŠøŠ½ŠøтŠø ŠŗŠ»Ń–Šæ",
+ "mwe-embedplayer-volume_control": "Š ŠµŠ³ŃƒŠ»ŃŽŠ²Š°Š½Š½Ń Š³ŃƒŃ‡Š½Š¾ŃŃ‚Ń–",
+ "mwe-embedplayer-player_options": "ŠŠ°Š»Š°ŃˆŃ‚ŃƒŠ²Š°Š½Š½Ń ŠæрŠ¾Š³Ń€Š°Š²Š°Ń‡Š°",
+ "mwe-embedplayer-timed_text": "Š”уŠ±Ń‚ŠøтрŠø",
+ "mwe-embedplayer-player_fullscreen": "ŠŠ° Š²ŠµŃŃŒ ŠµŠŗрŠ°Š½",
+ "mwe-embedplayer-next_clip_msg": "Š’Ń–Š“тŠ²Š¾Ń€ŠøтŠø Š½Š°ŃŃ‚ŃƒŠæŠ½ŠøŠ¹ ŠŗŠ»Ń–Šæ",
+ "mwe-embedplayer-prev_clip_msg": "Š’Ń–Š“тŠ²Š¾Ń€ŠøтŠø ŠæŠ¾ŠæŠµŃ€ŠµŠ“Š½Ń–Š¹ ŠŗŠ»Ń–Šæ",
+ "mwe-embedplayer-current_clip_msg": "ŠŸŃ€Š¾Š“Š¾Š²Š¶ŠøтŠø Š²Ń–Š“тŠ²Š¾Ń€ŠµŠ½Š½Ń цьŠ¾Š³Š¾ ŠŗŠ»Ń–Šæу",
+ "mwe-embedplayer-seek_to": "ŠŸŠµŃ€ŠµŠ¹Ń‚Šø Š“Š¾ $1",
+ "mwe-embedplayer-paused": "ŠæŠ°ŃƒŠ·Š°",
+ "mwe-embedplayer-download_segment": "Š’ŠøŠ±Ń–Ń€ Š·Š°Š²Š°Š½Ń‚Š°Š¶ŠµŠ½Š½Ń:",
+ "mwe-embedplayer-download_full": "Š—Š°Š²Š°Š½Ń‚Š°Š¶ŠøтŠø Š²ŠµŃŃŒ Š²Ń–Š“ŠµŠ¾-фŠ°Š¹Š»:",
+ "mwe-embedplayer-download_right_click": "Š”Š»Ń Š·Š°Š²Š°Š½Ń‚Š°Š¶ŠµŠ½Š½Ń, Š½Š°Ń‚ŠøсŠ½Ń–Ń‚ŃŒ ŠæрŠ°Š²Ńƒ ŠŗŠ½Š¾ŠæŠŗу Š¼Šøші і Š¾Š±ŠµŃ€Ń–Ń‚ŃŒ Ā«Š—Š±ŠµŃ€ŠµŠ³Ń‚Šø Š¾Š±'єŠŗт яŠŗā€¦Ā»",
+ "mwe-embedplayer-download_clip": "Š—Š°Š²Š°Š½Ń‚Š°Š¶ŠøтŠø Š²Ń–Š“ŠµŠ¾",
+ "mwe-embedplayer-download_text": "Š—Š°Š²Š°Š½Ń‚Š°Š¶ŠøтŠø тŠµŠŗст",
+ "mwe-embedplayer-download": "Š—Š°Š²Š°Š½Ń‚Š°Š¶ŠøтŠø",
+ "mwe-embedplayer-share": "ŠŸŠ¾Š“іŠ»ŠøтŠøсь",
+ "mwe-embedplayer-credits": "Š”тŠ²Š¾Ń€ŃŽŠ²Š°Ń‡Ń–",
+ "mwe-embedplayer-about-library": "ŠŸŃ€Š¾ ŠæрŠ¾Š³Ń€Š°Š²Š°Ń‡ Kaltura",
+ "mwe-embedplayer-about-library-desc": "HTML5 Š¼ŠµŠ“іŠ°-Š±Ń–Š±Š»Ń–Š¾Ń‚ŠµŠŗŠ° Kaltura Š“Š¾Š·Š²Š¾Š»ŃŃ” Š’Š°Š¼ ŠŗŠ¾Ń€ŠøстуŠ²Š°Ń‚Šøсь HTML5 тŠµŠ³Š°Š¼Šø &lt;Š²Ń–Š“ŠµŠ¾&gt; тŠ° &lt;Š°ŃƒŠ“іŠ¾&gt; Š²Š¶Šµ сьŠ¾Š³Š¾Š“Š½Ń– Š·Ń– стŠ°Š½Š“Š°Ń€Ń‚Š½ŠøŠ¼ іŠ½Ń‚ŠµŃ€Ń„ŠµŠ¹ŃŠ¾Š¼ Š²Ń–Š“тŠ²Š¾Ń€ŠµŠ½Š½Ń у ріŠ·Š½Šøх Š±Ń€Š°ŃƒŠ·ŠµŃ€Š°Ń….\n\n[$1 Š‘Ń–Š»ŃŒŃˆŠµ ŠæрŠ¾ Š±Ń–Š±Š»Ń–Š¾Ń‚ŠµŠŗу ŠæрŠ¾Š³Ń€Š°Š²Š°Ń‡Š° Kaltura].",
+ "mwe-embedplayer-clip_linkback": "Š’ŠøхіŠ“Š½Š° стŠ¾Ń€Ń–Š½ŠŗŠ° ŠŗŠ»Ń–Šæу",
+ "mwe-embedplayer-choose_player": "Š’ŠøŠ±ŠµŃ€Ń–Ń‚ŃŒ Š²Ń–Š“ŠµŠ¾ ŠæŠ»ŠµŃ”Ń€",
+ "mwe-embedplayer-no-player": "ŠŠµŠ¼Š° ŠæрŠ¾Š³Ń€Š°Š²Š°Ń‡Š° Š“Š»Ń $1",
+ "mwe-embedplayer-share_this_video": "ŠŸŠ¾Š“іŠ»ŠøтŠøсь цŠøŠ¼ Š²Ń–Š“ŠµŠ¾",
+ "mwe-embedplayer-video_credits": "ŠŸŃ€Š¾ стŠ²Š¾Ń€ŃŽŠ²Š°Ń‡Ń–Š² Š²Ń–Š“ŠµŠ¾",
+ "mwe-embedplayer-no-video_credits": "ŠŠµŠ¼Š° Š²Ń–Š“Š¾Š¼Š¾ŃŃ‚ŠµŠ¹ ŠæрŠ¾ Š°Š²Ń‚Š¾Ń€Š°",
+ "mwe-embedplayer-kaltura-platform-title": "Š’Ń–Š“ŠµŠ¾-ŠæŠ»Š°Ń‚Ń„Š¾Ń€Š¼Š° Š· Š²Ń–Š“ŠŗрŠøтŠøŠ¼ ŠŗŠ¾Š“Š¾Š¼ Kaltura",
+ "mwe-embedplayer-menu_btn": "ŠœŠµŠ½ŃŽ",
+ "mwe-embedplayer-close_btn": "Š—Š°ŠŗрŠøтŠø",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLC ŠæрŠ¾Š³Ń€Š°Š²Š°Ń‡",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Ogg ŠæрŠ¾Š³Ń€Š°Š²Š°Ń‡",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3-ŠæрŠ¾Š³Ń€Š°Š²Š°Ń‡",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AAC-ŠæрŠ¾Š³Ń€Š°Š²Š°Ń‡",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264 ŠæрŠ¾Š³Ń€Š°Š²Š°Ń‡",
+ "mwe-embedplayer-ogg-player-webmNative": "ŠŸŃ€Š¾Š³Ń€Š°Š²Š°Ń‡ HTML5 WebM",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Š—Š°Š³Š°Š»ŃŒŠ½ŠøŠ¹ ŠæŠ»Š°Ņ‘Ń–Š½ Ogg",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "ŠŸŃ€Š¾Š³Ń€Š°Š¼Š° VLC Š“Š»Ń iOS",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Š”Š¾Š“Š°Ń‚Š¾Šŗ QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "ŠŸŃ€Š¾Š³Ń€Š°Š²Š°Ń‡ Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(Š¾Š±Ń€Š°Š½Š¾)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "Š”Š»Ń ŠŗрŠ°Ń‰Š¾Š³Š¾ Š²Ń–Š“тŠ²Š¾Ń€ŠµŠ½Š½Ń Š²Ń–Š“ŠµŠ¾ рŠµŠŗŠ¾Š¼ŠµŠ½Š“уєŠ¼Š¾ <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">html5 Š²Ń–Š“ŠµŠ¾ Š±Ń€Š°ŃƒŠ·ŠµŃ€</a>.",
+ "mwe-embedplayer-download-warn": "ŠŠµ Š·Š½Š°Š¹Š“ŠµŠ½Š¾ Š²Š±ŃƒŠ“Š¾Š²Š°Š½Š¾Š³Š¾ ŠæрŠ¾Š³Ń€Š°Š²Š°Ń‡Š° Š“Š»Ń Š±Ń€Š°ŃƒŠ·ŠµŃ€Š°, Š“Š»Ń Š²Ń–Š“тŠ²Š¾Ń€ŠµŠ½Š½Ń Š² Š±Ń€Š°ŃƒŠ·ŠµŃ€Ń– Š·Š°Š²Š°Š½Ń‚Š°Š¶Ń‚Šµ, Š±ŃƒŠ“ь Š»Š°ŃŠŗŠ°, [$1 Š¾ŃŃ‚Š°Š½Š½Ń–Š¹ Firefox]",
+ "mwe-embedplayer-fullscreen-tip": "ŠŠ°Ń‚ŠøсŠ½Ń–Ń‚ŃŒ ŠŗŠ½Š¾ŠæŠŗу <b>F11</b> Š“Š»Ń ŠæŠµŃ€ŠµŠ¼ŠøŠŗŠ°Š½Š½Ń <i>Š²ŠµŠ±-Š±Ń€Š°ŃƒŠ·ŠµŃ€Ńƒ</i> у ŠæŠ¾Š²Š½Š¾ŠµŠŗрŠ°Š½Š½ŠøŠ¹ рŠµŠ¶ŠøŠ¼",
+ "mwe-embedplayer-fullscreen-tip-osx": "ŠŠ°Ń‚ŠøсŠ½Ń–Ń‚ŃŒ ŠŗŠ½Š¾ŠæŠŗу <b>shift āŒ˜ F</b> Š“Š»Ń ŠæŠµŃ€ŠµŃ…Š¾Š“у у ŠæŠ¾Š²Š½Š¾ŠµŠŗрŠ°Š½Š½ŠøŠ¹ рŠµŠ¶ŠøŠ¼",
+ "mwe-embedplayer-do_not_warn_again": "ŠŠµ ŠæŠ¾ŠŗŠ°Š·ŃƒŠ²Š°Ń‚Šø цŠµ ŠæŠ¾Š²Ń–Š“Š¾Š¼Š»ŠµŠ½Š½Ń у Š¼Š°Š¹Š±ŃƒŃ‚Š½ŃŒŠ¾Š¼Ńƒ",
+ "mwe-embedplayer-playerSelect": "ŠŸŃ€Š¾Š³Ń€Š°Š²Š°Ń‡Ń–",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">ŠŸŃ€Š¾Ń‡ŠøтŠ°Š¹Ń‚Šµ цŠµ</a> ŠæŠµŃ€ŠµŠ“ Š²ŠŗŠ»ŃŽŃ‡ŠµŠ½Š½ŃŠ¼.",
+ "mwe-embedplayer-embed_site_or_blog": "Š’ŠŗŠ»ŃŽŃ‡ŠøтŠø Š½Š° стŠ¾Ń€Ń–Š½Šŗу",
+ "mwe-embedplayer-embed_wiki": "Š’Š±ŃƒŠ“Š¾Š²Š°Š½ŠøŠ¹ у Š²Ń–Šŗі",
+ "mwe-embedplayer-related_videos": "ŠŸŠ¾Š²'яŠ·Š°Š½Ń– Š²Ń–Š“ŠµŠ¾",
+ "mwe-embedplayer-seeking": "ŠæŠ¾ŃˆŃƒŠŗ",
+ "mwe-embedplayer-buffering": "Š±ŃƒŃ„ŠµŃ€ŠøŠ·Š°Ń†Ń–я",
+ "mwe-embedplayer-video-h264": "H.264 Š²Ń–Š“ŠµŠ¾",
+ "mwe-embedplayer-video-webm": "Š’Ń–Š“ŠµŠ¾ WebM",
+ "mwe-embedplayer-video-flv": "Š¤Š»ŠµŃˆ Š²Ń–Š“ŠµŠ¾",
+ "mwe-embedplayer-video-ogg": "Ogg Š²Ń–Š“ŠµŠ¾",
+ "mwe-embedplayer-video-audio": "Ogg Š°ŃƒŠ“іŠ¾",
+ "mwe-embedplayer-audio-mpeg": "MPEG-Š°ŃƒŠ“іŠ¾",
+ "mwe-embedplayer-video-3gp": "3GP-Š²Ń–Š“ŠµŠ¾",
+ "mwe-embedplayer-video-mpeg": "MPEG-Š²Ń–Š“ŠµŠ¾",
+ "mwe-embedplayer-video-msvideo": "AVI-Š²Ń–Š“ŠµŠ¾",
+ "mwe-embedplayer-missing-source": "ŠŠµ Š·Š½Š°Š¹Š“ŠµŠ½Š¾ Š“Š¶ŠµŃ€ŠµŠ»Š¾ Š²Ń–Š“ŠµŠ¾",
+ "mwe-embedplayer-vlcapp-intro": "Š”Š»Ń ŠæŠµŃ€ŠµŠ³Š»ŃŠ“у Š²Ń–Š“ŠµŠ¾ Š· цьŠ¾Š³Š¾ сŠ°Š¹Ń‚Ńƒ Š½Š° iPhone Š°Š±Š¾ iPad Š²Š°Š¼ ŠæŠ¾Ń‚ріŠ±Š½Š° Š±ŠµŠ·ŠŗŠ¾ŃˆŃ‚Š¾Š²Š½Š° ŠæрŠ¾Š³Ń€Š°Š¼Š° $1.",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "ŠŸŃ€Š¾Š³Ń€Š°Š¼Š° VLC",
+ "mwe-embedplayer-vlcapp-downloadapp": "Š—Š°Š²Š°Š½Ń‚Š°Š¶ŠøтŠø ŠæрŠ¾Š³Ń€Š°Š¼Ńƒ VLC іŠ· App Store",
+ "mwe-embedplayer-vlcapp-openvideo": "Š’Ń–Š“ŠŗрŠøтŠø цŠµ Š²Ń–Š“ŠµŠ¾ у ŠæрŠ¾Š³Ń€Š°Š¼Ń– VLC",
+ "mwe-embedplayer-vlcapp-downloadvideo": "Š—Š°Š²Š°Š½Ń‚Š°Š¶ŠøтŠø цŠµ Š²Ń–Š“ŠµŠ¾",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "Š”Š»Ń Š²Ń–Š“тŠ²Š¾Ń€ŠµŠ½Š½Ń Š²Ń–Š“ŠµŠ¾ Š½Š° цьŠ¾Š¼Ńƒ сŠ°Š¹Ń‚Ń– ŠæŠ¾Ń‚ріŠ±Š½Š° Š±ŠµŠ·ŠŗŠ¾ŃˆŃ‚Š¾Š²Š½Š° ŠæрŠ¾Š³Ń€Š°Š¼Š° VLC. Š’стŠ°Š½Š¾Š²ŠøтŠø Š·Š°Ń€Š°Š·?"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ur.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ur.json
new file mode 100644
index 00000000..2136b2ba
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/ur.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ"
+ ]
+ },
+ "mwe-embedplayer-download": "ŚˆŲ§Ų¤Ł† Ł„ŁˆŚˆ ŲŒ Ų§ŲŖŲ§Ų±Ł†Ų§",
+ "mwe-embedplayer-share": "Ų­ŲµŪ",
+ "mwe-embedplayer-credits": "Ś©Ų±ŪŒŚˆŁ¹",
+ "mwe-embedplayer-menu_btn": "Ł…ŪŒŁ†Łˆ",
+ "mwe-embedplayer-close_btn": "ŲØŁ†ŲÆ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/vec.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/vec.json
new file mode 100644
index 00000000..6c166455
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/vec.json
@@ -0,0 +1,38 @@
+{
+ "@metadata": [],
+ "mwe-embedplayer-credit-title": "Titolo: $1",
+ "mwe-embedplayer-loading_plugin": "so' drio cargar el plugin...",
+ "mwe-embedplayer-link_back": "ColĆØga indrƬo",
+ "mwe-embedplayer-add_to_end_of_sequence": "Taca in fondo a la sequensa",
+ "mwe-embedplayer-play_clip": "Riprodusi",
+ "mwe-embedplayer-pause_clip": "Meti in pausa",
+ "mwe-embedplayer-volume_control": "Controlo volume",
+ "mwe-embedplayer-player_fullscreen": "Schermo intiero",
+ "mwe-embedplayer-seek_to": "Serca $1",
+ "mwe-embedplayer-paused": "en pausa",
+ "mwe-embedplayer-download_segment": "Descarga la selession:",
+ "mwe-embedplayer-download_full": "Descarga tuto el file video:",
+ "mwe-embedplayer-download_right_click": "Par descargar, struca el boton destro e selessiona <i>Salva colegamento come...</i>",
+ "mwe-embedplayer-download_clip": "Descarga el video",
+ "mwe-embedplayer-download": "Descarga",
+ "mwe-embedplayer-share": "Spartissi",
+ "mwe-embedplayer-credits": "Riconossimenti",
+ "mwe-embedplayer-choose_player": "Siegli el letor multimedial",
+ "mwe-embedplayer-share_this_video": "Condividi sto video",
+ "mwe-embedplayer-video_credits": "Riconossimenti del video",
+ "mwe-embedplayer-menu_btn": "MenĆ¹",
+ "mwe-embedplayer-close_btn": "Sara",
+ "mwe-embedplayer-ogg-player-vlc-player": "Letor VLC",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Plugin Ogg generico",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Plugin QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Letor Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(selessionĆ )",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-read_before_embed": "<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">LĆØzi qua</a> prima de 'ndar vanti.",
+ "mwe-embedplayer-embed_site_or_blog": "Inserissi drento na pagina",
+ "mwe-embedplayer-related_videos": "Video ligĆ  a sto qua",
+ "mwe-embedplayer-seeking": "so' drio sercar"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/vep.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/vep.json
new file mode 100644
index 00000000..c90787dd
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/vep.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": [],
+ "mwe-embedplayer-link_back": "Kosketuz tagaze",
+ "mwe-embedplayer-play_clip": "VƤta klip",
+ "mwe-embedplayer-credits": "Tegijad",
+ "mwe-embedplayer-menu_btn": "MenĆ¼",
+ "mwe-embedplayer-close_btn": "Saubata",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTime-plagin",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-selected": "(valitud)"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/vi.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/vi.json
new file mode 100644
index 00000000..a88dd46d
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/vi.json
@@ -0,0 +1,77 @@
+{
+ "@metadata": {
+ "authors": [
+ "Minh Nguyen"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "Tį»±a: $1",
+ "mwe-embedplayer-credit-date": "NgĆ y: $1",
+ "mwe-embedplayer-credit-author": "TĆ”c giįŗ£: $1",
+ "mwe-embedplayer-nocredits": "KhĆ“ng cĆ³ sįŗµn lį»i ghi cĆ“ng",
+ "mwe-embedplayer-loading_plugin": "đang tįŗ£i phįŗ§n bį»• trį»£ ā€¦",
+ "mwe-embedplayer-select_playback": "Cįŗ„u hƬnh phĆ”t lįŗ”i",
+ "mwe-embedplayer-missing_video_stream": "Tįŗ­p tin video cį»§a luį»“ng nĆ y bį»‹ mįŗ„t",
+ "mwe-embedplayer-play_clip": "Chʔi clip",
+ "mwe-embedplayer-pause_clip": "Tįŗ”m ngį»«ng clip",
+ "mwe-embedplayer-volume_control": "Điį»u khiį»ƒn Ć¢m lĘ°į»£ng",
+ "mwe-embedplayer-player_options": "TĆ¹y chį»n trƬnh chĘ”i",
+ "mwe-embedplayer-timed_text": "Văn bįŗ£n đį»“ng bį»™",
+ "mwe-embedplayer-player_fullscreen": "ToƠn mƠn hƬnh",
+ "mwe-embedplayer-next_clip_msg": "Chʔi clip sau",
+ "mwe-embedplayer-prev_clip_msg": "ChĘ”i clip trĘ°į»›c",
+ "mwe-embedplayer-current_clip_msg": "ChĘ”i clip nĆ y tiįŗæp",
+ "mwe-embedplayer-seek_to": "Nhįŗ£y tį»›i $1",
+ "mwe-embedplayer-paused": "đang tįŗ”m ngį»«ng",
+ "mwe-embedplayer-download_segment": "Tįŗ£i vį» lį»±a chį»n:",
+ "mwe-embedplayer-download_full": "Tįŗ£i vį» cįŗ£ tįŗ­p tin video:",
+ "mwe-embedplayer-download_right_click": "Đį»ƒ tįŗ£i vį», hĆ£y nhįŗ„n chuį»™t phįŗ£i vĆ  chį»n <i>LĘ°u LiĆŖn Kįŗæt dĘ°į»›i dįŗ”ngā€¦</i> (<i>Save Link Asā€¦</i>)",
+ "mwe-embedplayer-download_clip": "Tįŗ£i vį» video",
+ "mwe-embedplayer-download_text": "Tįŗ£i vį» văn bįŗ£n",
+ "mwe-embedplayer-download": "Tįŗ£i vį»",
+ "mwe-embedplayer-share": "Chia sįŗ»",
+ "mwe-embedplayer-credits": "Ghi cƓng",
+ "mwe-embedplayer-about-library": "Giį»›i thiį»‡u trƬnh chĘ”i Kaltura",
+ "mwe-embedplayer-clip_linkback": "Trang nguį»“n clip",
+ "mwe-embedplayer-choose_player": "Chį»n trƬnh chĘ”i video",
+ "mwe-embedplayer-no-player": "KhĆ“ng cĆ³ sįŗµn trƬnh chĘ”i cho $1",
+ "mwe-embedplayer-share_this_video": "Chia sįŗ» video nĆ y",
+ "mwe-embedplayer-video_credits": "Ghi cĆ“ng vį» video",
+ "mwe-embedplayer-no-video_credits": "KhĆ“ng cĆ³ sįŗµn lį»i ghi cĆ“ng",
+ "mwe-embedplayer-kaltura-platform-title": "Nį»n tįŗ£ng video nguį»“n mį»Ÿ Kaltura",
+ "mwe-embedplayer-menu_btn": "TrƬnh Ä‘Ę”n",
+ "mwe-embedplayer-close_btn": "ÄĆ³ng",
+ "mwe-embedplayer-ogg-player-vlc-player": "TrƬnh chʔi VLC",
+ "mwe-embedplayer-ogg-player-oggNative": "TrƬnh chʔi Ogg HTML5",
+ "mwe-embedplayer-ogg-player-mp3Native": "TrƬnh chʔi MP3 HTML5",
+ "mwe-embedplayer-ogg-player-aacNative": "TrƬnh chʔi AAC HTML5",
+ "mwe-embedplayer-ogg-player-h264Native": "TrƬnh chʔi HTML5 H.264",
+ "mwe-embedplayer-ogg-player-webmNative": "TrƬnh chʔi WebM HTML5",
+ "mwe-embedplayer-ogg-player-oggPlugin": "Phįŗ§n bį»• trį»£ Ogg thĘ°į»ng",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "Phįŗ§n bį»• trį»£ QuickTime",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-cortado": "Java Cortado",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "TrƬnh chʔi Kaltura",
+ "mwe-embedplayer-ogg-player-selected": "(đʰį»£c chį»n)",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-fullscreen-tip": "Bįŗ„m <b>F11</b> đį»ƒ bįŗ­t/tįŗÆt chįŗæ đį»™ toĆ n mĆ n hƬnh <i>cį»§a trƬnh duyį»‡t</i>",
+ "mwe-embedplayer-fullscreen-tip-osx": "Bįŗ„m tį»• hį»£p <b>ā‡§āŒ˜F</b> đį»ƒ bįŗ­t/tįŗÆt chįŗæ đį»™ toĆ n mĆ n hƬnh",
+ "mwe-embedplayer-do_not_warn_again": "Tį»« nay khĆ“ng hiį»ƒn thį»‹ thĆ“ng bĆ”o nĆ y",
+ "mwe-embedplayer-playerSelect": "TrƬnh chʔi",
+ "mwe-embedplayer-read_before_embed": "HĆ£y <a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding?uselang=vi\" target=\"new\">đį»c cįŗ£nh bĆ”o</a> trĘ°į»›c khi nhĆŗng.",
+ "mwe-embedplayer-embed_site_or_blog": "NhĆŗng vĆ o trang",
+ "mwe-embedplayer-embed_wiki": "NhĆŗng vĆ o trang wiki",
+ "mwe-embedplayer-related_videos": "Video liĆŖn quan",
+ "mwe-embedplayer-seeking": "đang nhįŗ£y",
+ "mwe-embedplayer-buffering": "đang đį»‡m",
+ "mwe-embedplayer-video-h264": "Video H.264",
+ "mwe-embedplayer-video-webm": "Video WebM",
+ "mwe-embedplayer-video-flv": "Video Flash",
+ "mwe-embedplayer-video-ogg": "Video Ogg",
+ "mwe-embedplayer-video-audio": "Ƃm thanh Ogg",
+ "mwe-embedplayer-audio-mpeg": "Ƃm thanh MPEG",
+ "mwe-embedplayer-video-3gp": "Video 3GP",
+ "mwe-embedplayer-video-mpeg": "Video MPEG",
+ "mwe-embedplayer-video-msvideo": "Video AVI",
+ "mwe-embedplayer-missing-source": "KhĆ“ng tƬm thįŗ„y video gį»‘c"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/yi.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/yi.json
new file mode 100644
index 00000000..ce1af5d6
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/yi.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "פוילישע×Ø",
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ"
+ ]
+ },
+ "mwe-embedplayer-credit-date": "דאַטע: $1",
+ "mwe-embedplayer-close_btn": "שליהן"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/zh-hans.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/zh-hans.json
new file mode 100644
index 00000000..debfbc6e
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/zh-hans.json
@@ -0,0 +1,102 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hydra",
+ "Shizhao",
+ "Xiaomingyan",
+ "Yfdyh000",
+ "ä¹Œę‹‰č·Øę°Ŗ",
+ "NigelSoft",
+ "Liuxinyu970226",
+ "Duolaimi"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "ę ‡é¢˜ļ¼š$1",
+ "mwe-embedplayer-credit-date": "ę—„ęœŸļ¼š$1",
+ "mwe-embedplayer-credit-author": "ä½œč€…ļ¼š$1",
+ "mwe-embedplayer-nocredits": "ę²”ęœ‰åˆ¶ä½œäŗŗ员名单",
+ "mwe-embedplayer-loading_plugin": "ę­£åœØč½½å…„ę’ä»¶...",
+ "mwe-embedplayer-select_playback": "č®¾ē½®ę’­ę”¾åå„½",
+ "mwe-embedplayer-link_back": "é“¾ęŽ„å›ž",
+ "mwe-embedplayer-error_swap_vid": "å‡ŗ错ļ¼šmwEmbedę— ę³•å°†č§†é¢‘ę ‡ē­¾č½¬ę¢äøŗmwEmbedē•Œé¢",
+ "mwe-embedplayer-add_to_end_of_sequence": "ę·»åŠ č‡³é˜Ÿåˆ—ęœ«å°¾",
+ "mwe-embedplayer-missing_video_stream": "čÆ„č§†é¢‘ęµēš„č§†é¢‘ę–‡ä»¶äø¢å¤±",
+ "mwe-embedplayer-play_clip": "ę’­ę”¾ē‰‡ę®µ",
+ "mwe-embedplayer-pause_clip": "ęš‚åœē‰‡ę®µ",
+ "mwe-embedplayer-volume_control": "č°ƒę•“éŸ³é‡",
+ "mwe-embedplayer-player_options": "ę’­ę”¾å™Ø选锹",
+ "mwe-embedplayer-timed_text": "字幕",
+ "mwe-embedplayer-player_fullscreen": "å…Ø屏",
+ "mwe-embedplayer-next_clip_msg": "ę’­ę”¾äø‹äø€ē‰‡ę®µ",
+ "mwe-embedplayer-prev_clip_msg": "ę’­ę”¾äøŠäø€ē‰‡ę®µ",
+ "mwe-embedplayer-current_clip_msg": "ē»§ē»­ę’­ę”¾ęœ¬ē‰‡ę®µ",
+ "mwe-embedplayer-seek_to": "åÆ»ę‰¾$1",
+ "mwe-embedplayer-paused": "å·²ęš‚åœ",
+ "mwe-embedplayer-download_segment": "äø‹č½½čŠ‚选ē‰‡ę®µļ¼š",
+ "mwe-embedplayer-download_full_video": "äø‹č½½å®Œę•“č§†é¢‘ę–‡ä»¶ļ¼š",
+ "mwe-embedplayer-download_full_audio": "äø‹č½½å®Œę•“éŸ³é¢‘ę–‡ä»¶ļ¼š",
+ "mwe-embedplayer-download_right_click": "äø‹č½½čÆ·å•å‡»é¼ ę ‡å³é”®å¹¶é€‰ę‹©ā€œé“¾ęŽ„另存äøŗ...ā€",
+ "mwe-embedplayer-download_clip": "äø‹č½½č§†é¢‘",
+ "mwe-embedplayer-download_text": "äø‹č½½å­—幕",
+ "mwe-embedplayer-download": "äø‹č½½",
+ "mwe-embedplayer-share": "分äŗ«",
+ "mwe-embedplayer-credits": "制作äŗŗ员",
+ "mwe-embedplayer-about-library": "关äŗŽKalturaę’­ę”¾å™Ø",
+ "mwe-embedplayer-about-library-desc": "Kalturaēš„HTML5åŖ’体åŗ“åÆä»„č®©ä½ åœØꉀ꜉ēš„äø»ęµęµč§ˆå™Øä½æē”Øäø€č‡“ēš„ę’­ę”¾å™Øē•Œé¢äŗ«å—HTML5&lt;video&gt;和&lt;audio&gt;ꠇē­¾ēš„ä¾æåˆ©ć€‚\n\n[$1 ę›“å¤šå…³äŗŽKalturaę’­ę”¾å™Øåŗ“ēš„äæ”ęÆ]怂",
+ "mwe-embedplayer-clip_linkback": "ē‰‡ę®µęŗé”µé¢",
+ "mwe-embedplayer-choose_player": "é€‰ę‹©č§†é¢‘ę’­ę”¾å™Ø",
+ "mwe-embedplayer-no-player": "ę²”ęœ‰é€‚ē”ØäŗŽ$1ēš„ę’­ę”¾å™Ø",
+ "mwe-embedplayer-share_this_video": "分äŗ«čÆ„č§†é¢‘",
+ "mwe-embedplayer-share_this_audio": "分äŗ«čæ™äøŖéŸ³é¢‘ę–‡ä»¶",
+ "mwe-embedplayer-video_credits": "č§†é¢‘åˆ¶ä½œäŗŗ员",
+ "mwe-embedplayer-no-video_credits": "ę²”ęœ‰åˆ¶ä½œäŗŗ员名单",
+ "mwe-embedplayer-kaltura-platform-title": "Kaltura开ęŗč§†é¢‘平台",
+ "mwe-embedplayer-menu_btn": "čœå•",
+ "mwe-embedplayer-close_btn": "关闭",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLCę’­ę”¾å™Ø",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Oggę’­ę”¾å™Ø",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3ę’­ę”¾å™Ø",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AACę’­ę”¾å™Ø",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264ę’­ę”¾å™Ø",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebMę’­ę”¾å™Ø",
+ "mwe-embedplayer-ogg-player-oggPlugin": "通ē”ØOggę’ä»¶",
+ "mwe-embedplayer-ogg-player-vlcAppPlayer": "ē”ØäŗŽiOSēš„VLCåŗ”ē”Øē؋åŗ",
+ "mwe-embedplayer-ogg-player-IEWebMPrompt": "IE WebMę’ä»¶äø‹č½½å™Ø",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTimeę’ä»¶",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kalturaę’­ę”¾å™Ø",
+ "mwe-embedplayer-ogg-player-selected": "ļ¼ˆå·²é€‰ļ¼‰",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "äøŗäŗ†å¾—åˆ°ę›“儽ēš„č§†é¢‘ę’­ę”¾ä½“éŖŒļ¼Œęˆ‘们ęŽØ荐<a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">HTML5č§†é¢‘ęµč§ˆå™Ø</a>怂",
+ "mwe-embedplayer-download-warn": "ę£€ęµ‹åˆ°ę’­ę”¾å™Øå’Œęµč§ˆå™Øäøå…¼å®¹ļ¼šäøŗäŗ†čƒ½åœØęµč§ˆå™Øäø­ę’­ę”¾ļ¼ŒčÆ·äø‹č½½[$1 ꜀ꖰFirefox]",
+ "mwe-embedplayer-fullscreen-tip": "ꌉ<b>F11</b>åˆ‡ę¢ęµč§ˆå™Øč‡³å…Ø屏",
+ "mwe-embedplayer-fullscreen-tip-osx": "ꌉ<b>Shift āŒ˜ F</b>åˆ‡ę¢č‡³å…Ø屏",
+ "mwe-embedplayer-do_not_warn_again": "仄后äøå†ę˜¾ē¤ŗčÆ„äæ”ęÆ",
+ "mwe-embedplayer-playerSelect": "ę’­ę”¾å™Ø",
+ "mwe-embedplayer-read_before_embed": "嵌兄前čÆ·<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">阅čÆ»ęœ¬ę–‡</a>怂",
+ "mwe-embedplayer-embed_site_or_blog": "嵌兄锵面",
+ "mwe-embedplayer-embed_wiki": "嵌兄wiki",
+ "mwe-embedplayer-related_videos": "ē›øå…³č§†é¢‘",
+ "mwe-embedplayer-seeking": "ę­£åœØåÆ»ę‰¾",
+ "mwe-embedplayer-buffering": "ę­£åœØē¼“冲",
+ "mwe-embedplayer-video-h264": "H.264č§†é¢‘",
+ "mwe-embedplayer-video-webm": "WebMč§†é¢‘",
+ "mwe-embedplayer-video-flv": "Flashč§†é¢‘",
+ "mwe-embedplayer-video-ogg": "Oggč§†é¢‘",
+ "mwe-embedplayer-video-audio": "Ogg音频",
+ "mwe-embedplayer-audio-mpeg": "MPEG音频",
+ "mwe-embedplayer-video-3gp": "3GPč§†é¢‘",
+ "mwe-embedplayer-video-mpeg": "MPEGč§†é¢‘",
+ "mwe-embedplayer-video-msvideo": "AVIč§†é¢‘",
+ "mwe-embedplayer-missing-source": "ęœŖę‰¾åˆ°ęŗč§†é¢‘",
+ "mwe-embedplayer-vlcapp-intro": "äøŗäŗ†åœØiPhoneꈖiPadäøŠč§‚ēœ‹ę­¤ē«™ēš„č§†é¢‘ļ¼Œę‚Øéœ€č¦å…č“¹ēš„$1怂",
+ "mwe-embedplayer-vlcapp-vlcapplinktext": "VLCåŗ”ē”Øē؋åŗ",
+ "mwe-embedplayer-vlcapp-downloadapp": "从App Storeäø‹č½½VLCåŗ”ē”Øē؋åŗ",
+ "mwe-embedplayer-vlcapp-openvideo": "ä½æē”ØVLCåŗ”ē”Øē؋åŗę‰“å¼€ę­¤č§†é¢‘",
+ "mwe-embedplayer-vlcapp-downloadvideo": "äø‹č½½čæ™äøŖč§†é¢‘",
+ "mwe-embedplayer-vlcapp-vlcapppopup": "要åœØčÆ„ē½‘ē«™ę’­ę”¾č§†é¢‘ļ¼Œę‚Øéœ€č¦å…č“¹ēš„VLCåŗ”ē”Øē؋åŗć€‚ēŽ°åœØå®‰č£…ļ¼Ÿ",
+ "mwe-embedplayer-iewebmprompt-intro": "哎呀ļ¼åœØę‚ØåÆä»„ę’­ę”¾čÆ„č§†é¢‘å‰ę‚Øčæ˜éœ€č¦åšäø€ä»¶äŗ‹ā€¦ā€¦",
+ "mwe-embedplayer-iewebmprompt-linktext": "äøŗMicrosoft Internet Explorerå®‰č£…WebMåŖ’体ē»„件",
+ "mwe-embedplayer-iewebmprompt-outro": "åœØå®‰č£…åŽé‡ę–°åŠ č½½ę­¤é”µé¢ć€‚"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/zh-hant.json b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/zh-hant.json
new file mode 100644
index 00000000..5dceb76e
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/i18n/zh-hant.json
@@ -0,0 +1,86 @@
+{
+ "@metadata": {
+ "authors": [
+ "Justincheng12345",
+ "Mark85296341",
+ "Simon Shek",
+ "StephDC",
+ "LNDDYL"
+ ]
+ },
+ "mwe-embedplayer-credit-title": "ęؙ锌ļ¼š$1",
+ "mwe-embedplayer-credit-date": "ę—„ęœŸļ¼š$1",
+ "mwe-embedplayer-credit-author": "ä½œč€…ļ¼š$1",
+ "mwe-embedplayer-nocredits": "ęœŖē½²å",
+ "mwe-embedplayer-loading_plugin": "ę­£åœØč¼‰å…„å¤–ęŽ›ē؋式...",
+ "mwe-embedplayer-select_playback": "čØ­å®šå›žę”¾åå„½",
+ "mwe-embedplayer-link_back": "反連",
+ "mwe-embedplayer-error_swap_vid": "éŒÆčŖ¤ļ¼šmwEmbedē„”ę³•č½‰ę›ē”Øę–¼mwEmbed介面ēš„å½±ē‰‡ęؙē±¤",
+ "mwe-embedplayer-add_to_end_of_sequence": "ę·»åŠ č‡³åŗåˆ—ęœ«å°¾",
+ "mwe-embedplayer-missing_video_stream": "ę­¤äø²ęµēš„å½±ē‰‡ęŖ”ę”ˆå·²éŗ失",
+ "mwe-embedplayer-play_clip": "ę’­ę”¾å‰Ŗč¼Æ",
+ "mwe-embedplayer-pause_clip": "ęš«åœå‰Ŗč¼Æ",
+ "mwe-embedplayer-volume_control": "éŸ³é‡ęŽ§åˆ¶",
+ "mwe-embedplayer-player_options": "ę’­ę”¾å™Øéø項",
+ "mwe-embedplayer-timed_text": "字幕",
+ "mwe-embedplayer-player_fullscreen": "å…Øčž¢å¹•",
+ "mwe-embedplayer-next_clip_msg": "ę’­ę”¾äø‹äø€å‰Ŗč¼Æ",
+ "mwe-embedplayer-prev_clip_msg": "ę’­ę”¾å‰äø€å‰Ŗč¼Æ",
+ "mwe-embedplayer-current_clip_msg": "ē¹¼ēŗŒę’­ę”¾ę­¤å‰Ŗč¼Æ",
+ "mwe-embedplayer-seek_to": "å°‹ę‰¾$1",
+ "mwe-embedplayer-paused": "ęš«åœ",
+ "mwe-embedplayer-download_segment": "äø‹č¼‰éøꮵļ¼š",
+ "mwe-embedplayer-download_full": "äø‹č¼‰å®Œę•“ēš„å½±ē‰‡ęŖ”ļ¼š",
+ "mwe-embedplayer-download_right_click": "äø‹č¼‰č«‹ęŒ‰å³éµäø¦éø꓇<i>連ēµå¦å­˜ē‚ŗ...</i>",
+ "mwe-embedplayer-download_clip": "äø‹č¼‰å½±ē‰‡",
+ "mwe-embedplayer-download_text": "äø‹č¼‰å­—幕",
+ "mwe-embedplayer-download": "äø‹č¼‰",
+ "mwe-embedplayer-share": "分äŗ«",
+ "mwe-embedplayer-credits": "ē½²å",
+ "mwe-embedplayer-about-library": "é—œę–¼Kalturaę’­ę”¾å™Ø",
+ "mwe-embedplayer-about-library-desc": "Kalturaēš„HTML5åŖ’é«”ę«ƒč®“ę‚ØåœØē•¶ä»Ščƒ½č·Øč¶Šę‰€ęœ‰äø»ęµē€č¦½å™Ø充分地利ē”ØHTML5å½±ē‰‡å’ŒéŸ³č؊ęؙē±¤ć€‚\n\n[$1 ę›“å¤šé—œę–¼Kalturaę’­ę”¾å™Ø꫃ēš„č³‡č؊]怂",
+ "mwe-embedplayer-clip_linkback": "å‰Ŗč¼Æęŗé é¢",
+ "mwe-embedplayer-choose_player": "éøę“‡å½±ē‰‡ę’­ę”¾å™Ø",
+ "mwe-embedplayer-no-player": "$1ę²’ęœ‰åÆē”Øę’­ę”¾å™Ø",
+ "mwe-embedplayer-share_this_video": "分äŗ«č©²å½±ē‰‡",
+ "mwe-embedplayer-video_credits": "å½±ē‰‡ē½²å",
+ "mwe-embedplayer-no-video_credits": "ē„”ē½²å",
+ "mwe-embedplayer-kaltura-platform-title": "Kalturaé–‹ę”¾åŽŸå§‹ē¢¼å½±ē‰‡å¹³å°",
+ "mwe-embedplayer-menu_btn": "éø單",
+ "mwe-embedplayer-close_btn": "關閉",
+ "mwe-embedplayer-ogg-player-vlc-player": "VLCę’­ę”¾å™Ø",
+ "mwe-embedplayer-ogg-player-oggNative": "HTML5 Oggę’­ę”¾å™Ø",
+ "mwe-embedplayer-ogg-player-mp3Native": "HTML5 MP3 ę’­ę”¾ę©Ÿ",
+ "mwe-embedplayer-ogg-player-aacNative": "HTML5 AAC ę’­ę”¾ę©Ÿ",
+ "mwe-embedplayer-ogg-player-h264Native": "HTML5 H.264ę’­ę”¾å™Ø",
+ "mwe-embedplayer-ogg-player-webmNative": "HTML5 WebMę’­ę”¾å™Ø",
+ "mwe-embedplayer-ogg-player-oggPlugin": "ęœŖę³Ø冊Oggę’ä»¶",
+ "mwe-embedplayer-ogg-player-quicktime-mozilla": "QuickTimeå¤–ęŽ›ē؋式",
+ "mwe-embedplayer-ogg-player-quicktime-activex": "QuickTime ActiveX",
+ "mwe-embedplayer-ogg-player-flowplayer": "Flowplayer",
+ "mwe-embedplayer-ogg-player-kplayer": "Kalturaę’­ę”¾å™Ø",
+ "mwe-embedplayer-ogg-player-selected": "ļ¼ˆå·²éø取ļ¼‰",
+ "mwe-embedplayer-ogg-player-omtkplayer": "OMTK Flash Vorbis",
+ "mwe-embedplayer-for_best_experience": "ē‚ŗå–å¾—ę›“å„½å½±ē‰‡ę’­ę”¾é«”é©—ļ¼Œęˆ‘們ęŽØč–¦<a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\" target=\"_blank\">HTML5å½±ē‰‡ē€č¦½å™Ø</a>怂",
+ "mwe-embedplayer-download-warn": "ęŖ¢ęø¬åˆ°ę’­ę”¾å™Ø與ē€č¦½å™Øäøē›ø容ļ¼Œå¦‚åøŒęœ›ę–¼ē€č¦½å™Øäø­ę’­ę”¾č«‹äø‹č¼‰[$1 ꜀ꖰē‰ˆęœ¬Firefoxē€č¦½å™Ø]",
+ "mwe-embedplayer-fullscreen-tip": "ꌉ<b>F11</b>ꊊē€č¦½å™ØčØ­ē‚ŗå…Øčž¢å¹•",
+ "mwe-embedplayer-fullscreen-tip-osx": "ꌉ<b>Shift āŒ˜ F</b>čØ­ē‚ŗå…Øčž¢å¹•",
+ "mwe-embedplayer-do_not_warn_again": "仄後äøå†é”Æē¤ŗę­¤č؊ęÆ",
+ "mwe-embedplayer-playerSelect": "ę’­ę”¾å™Ø",
+ "mwe-embedplayer-read_before_embed": "åµŒå…„å‰č«‹å…ˆ<a href=\"https://www.mediawiki.org/wiki/Security_Notes_on_Remote_Embedding\" target=\"new\">é–±č®€ęœ¬ę–‡</a>怂",
+ "mwe-embedplayer-embed_site_or_blog": "嵌兄頁面",
+ "mwe-embedplayer-embed_wiki": "åœØ wiki äøŠåµŒå…„",
+ "mwe-embedplayer-related_videos": "ē›ø關影ē‰‡",
+ "mwe-embedplayer-seeking": "ę­£åœØęœå°‹",
+ "mwe-embedplayer-buffering": "ē·©č”äø­",
+ "mwe-embedplayer-video-h264": "H.264å½±ē‰‡",
+ "mwe-embedplayer-video-webm": "WebMå½±ē‰‡",
+ "mwe-embedplayer-video-flv": "Flashå½±ē‰‡",
+ "mwe-embedplayer-video-ogg": "Oggå½±ē‰‡",
+ "mwe-embedplayer-video-audio": "Ogg音č؊",
+ "mwe-embedplayer-audio-mpeg": "MPEG音č؊",
+ "mwe-embedplayer-video-3gp": "3GPå½±ē‰‡",
+ "mwe-embedplayer-video-mpeg": "MPEGå½±ē‰‡",
+ "mwe-embedplayer-video-msvideo": "AVIå½±ē‰‡",
+ "mwe-embedplayer-missing-source": "ęœŖę‰¾åˆ°åŽŸå§‹å½±ē‰‡"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/blackvideo.mp4 b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/blackvideo.mp4
new file mode 100644
index 00000000..cf86d1a8
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/blackvideo.mp4
Binary files differ
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayer.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayer.js
new file mode 100644
index 00000000..131302a2
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayer.js
@@ -0,0 +1,2760 @@
+/**
+* embedPlayer is the base class for html5 video tag javascript abstraction library
+* embedPlayer include a few subclasses:
+*
+* mediaPlayer Media player embed system ie: java, vlc or native.
+* mediaElement Represents source media elements
+* mw.PlayerControlBuilder Handles skinning of the player controls
+*/
+( function( mw, $ ) {"use strict";
+ /**
+ * Merge in the default video attributes supported by embedPlayer:
+ */
+ mw.mergeConfig('EmbedPlayer.Attributes', {
+ /*
+ * Base html element attributes:
+ */
+
+ // id: Auto-populated if unset
+ "id" : null,
+
+ // Width: alternate to "style" to set player width
+ "width" : null,
+
+ // Height: alternative to "style" to set player height
+ "height" : null,
+
+ /*
+ * Base html5 video element attributes / states also see:
+ * http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
+ */
+
+ // Media src URI, can be relative or absolute URI
+ "src" : null,
+
+ // Poster attribute for displaying a place holder image before loading
+ // or playing the video
+ "poster" : null,
+
+ // Autoplay if the media should start playing
+ "autoplay" : false,
+
+ // Loop attribute if the media should repeat on complete
+ "loop" : false,
+
+ // If the player controls should be displayed
+ "controls" : true,
+
+ // Video starts "paused"
+ "paused" : true,
+
+ // ReadyState an attribute informs clients of video loading state:
+ // see: http://www.whatwg.org/specs/web-apps/current-work/#readystate
+ "readyState" : 0,
+
+ // Loading state of the video element
+ "networkState" : 0,
+
+ // Current playback position
+ "currentTime" : 0,
+
+ // Previous player set time
+ // Lets javascript use $('#videoId')[0].currentTime = newTime;
+ "previousTime" : 0,
+
+ // Previous player set volume
+ // Lets javascript use $('#videoId')[0].volume = newVolume;
+ "previousVolume" : 1,
+
+ // Initial player volume:
+ "volume" : 0.75,
+
+ // Caches the volume before a mute toggle
+ "preMuteVolume" : 0.75,
+
+ // Media duration: Value is populated via
+ // custom data-durationhint attribute or via the media file once its played
+ "duration" : null,
+
+ // A hint to the duration of the media file so that duration
+ // can be displayed in the player without loading the media file
+ 'data-durationhint': null,
+
+ // to disable menu or timedText for a given embed
+ 'data-disablecontrols': null,
+
+ // Also support direct durationHint attribute ( backwards compatibly )
+ // @deprecated please use data-durationhint instead.
+ 'durationHint' : null,
+
+ // Mute state
+ "muted" : false,
+
+ /**
+ * Custom attributes for embedPlayer player: (not part of the html5
+ * video spec)
+ */
+
+ // Default video aspect ratio
+ 'videoAspect' : '4:3',
+
+ // Start time of the clip
+ "start" : 0,
+
+ // End time of the clip
+ "end" : null,
+
+ // If the player controls should be overlaid
+ // ( Global default via config EmbedPlayer.OverlayControls in module
+ // loader.js)
+ "overlaycontrols" : true,
+
+ // Attribute to use 'native' controls
+ "usenativecontrols" : false,
+
+ // If the player should include an attribution button:
+ 'attributionbutton' : true,
+
+ // A player error object (Includes title and message)
+ // * Used to display an error instead of a play button
+ // * The full player api available
+ 'playerError' : {},
+
+ // A flag to hide the player gui and disable autoplay
+ // * Used for empty players or a player where you want to dynamically set sources, then play.
+ // * The player API remains active.
+ 'data-blockPlayerDisplay': null,
+
+ // If serving an ogg_chop segment use this to offset the presentation time
+ // ( for some plugins that use ogg page time rather than presentation time )
+ "startOffset" : 0,
+
+ // If the download link should be shown
+ "downloadLink" : true,
+
+ // Content type of the media
+ "type" : null
+
+ } );
+
+
+ /**
+ * The base source attribute checks also see:
+ * http://dev.w3.org/html5/spec/Overview.html#the-source-element
+ */
+ mw.mergeConfig( 'EmbedPlayer.SourceAttributes', [
+ // source id
+ 'id',
+
+ // media url
+ 'src',
+
+ // Title string for the source asset
+ 'title',
+
+ // The html5 spec uses label instead of 'title' for naming sources
+ 'label',
+
+ // boolean if we support temporal url requests on the source media
+ 'URLTimeEncoding',
+
+ // Media has a startOffset ( used for plugins that
+ // display ogg page time rather than presentation time
+ 'startOffset',
+
+ // Media start time
+ 'start',
+
+ // Media end time
+ 'end',
+
+ // If the source is the default source
+ 'default',
+
+ // Title of the source
+ 'title',
+
+ // titleKey ( used for api lookups TODO move into mediaWiki specific support
+ 'titleKey'
+ ] );
+
+
+ /**
+ * Base embedPlayer object
+ *
+ * @param {Element}
+ * element, the element used for initialization.
+ * @constructor
+ */
+ mw.EmbedPlayer = function( element ) {
+ return this.init( element );
+ };
+
+ mw.EmbedPlayer.prototype = {
+
+ // The mediaElement object containing all mediaSource objects
+ 'mediaElement' : null,
+
+ // Object that describes the supported feature set of the underling plugin /
+ // Support list is described in PlayerControlBuilder components
+ 'supports': { },
+
+ // If the player is done loading ( does not guarantee playability )
+ // for example if there is an error playerReadyFlag is still set to true once
+ // no more loading is to be done
+ 'playerReadyFlag' : false,
+
+ // Stores the loading errors
+ 'loadError' : false,
+
+ // Thumbnail updating flag ( to avoid rewriting an thumbnail thats already
+ // being updated)
+ 'thumbnailUpdatingFlag' : false,
+
+ // Stopped state flag
+ 'stopped' : true,
+
+ // Local variable to hold CMML meeta data about the current clip
+ // for more on CMML see: http://wiki.xiph.org/CMML
+ 'cmmlData': null,
+
+ // Stores the seek time request, Updated by the seek function
+ 'serverSeekTime' : 0,
+
+ // If the embedPlayer is current 'seeking'
+ 'seeking' : false,
+
+ // Percent of the clip buffered:
+ 'bufferedPercent' : 0,
+
+ // Holds the timer interval function
+ 'monitorTimerId' : null,
+
+ // Buffer flags
+ 'bufferStartFlag' : false,
+ 'bufferEndFlag' : false,
+
+ // For supporting media fragments stores the play end time
+ 'pauseTime' : null,
+
+ // On done playing
+ 'donePlayingCount' : 0
+ ,
+ // if player events should be Propagated
+ '_propagateEvents': true,
+
+ // If the onDone interface should be displayed
+ 'onDoneInterfaceFlag': true,
+
+ // if we should check for a loading spinner in the monitor function:
+ '_checkHideSpinner' : false,
+
+ // If pause play controls click controls should be active:
+ '_playContorls' : true,
+
+ // If player should be displayed (in some caused like audio, we don't need the player to be visible
+ 'displayPlayer': true,
+
+ // Widget loaded should only fire once
+ 'widgetLoaded': false,
+
+ /**
+ * embedPlayer
+ *
+ * @constructor
+ *
+ * @param {Element}
+ * element DOM element that we are building the player interface for.
+ */
+ init: function( element ) {
+ var _this = this;
+ mw.log('EmbedPlayer: initEmbedPlayer: ' + $(element).width() );
+
+ var playerAttributes = mw.config.get( 'EmbedPlayer.Attributes' );
+
+ // Store the rewrite element tag type
+ this.rewriteElementTagName = element.tagName.toLowerCase();
+
+ this.noPlayerFallbackHTML = $( element ).html();
+
+ // Setup the player Interface from supported attributes:
+ for ( var attr in playerAttributes ) {
+ // We can't use $(element).attr( attr ) because we have to check for boolean attributes:
+ if ( element.getAttribute( attr ) != null ) {
+ // boolean attributes
+ if( element.getAttribute( attr ) == '' ){
+ this[ attr ] = true;
+ } else {
+ this[ attr ] = element.getAttribute( attr );
+ }
+ } else {
+ this[attr] = playerAttributes[attr];
+ }
+ // string -> boolean
+ if( this[ attr ] == "false" ) this[attr] = false;
+ if( this[ attr ] == "true" ) this[attr] = true;
+ }
+
+ // Hide "controls" if using native player controls:
+ if( this.useNativePlayerControls() ){
+ _this.controls = true;
+ }
+ // Set the skin name from the class
+ var sn = $(element).attr( 'class' );
+
+ if ( sn && sn != '' ) {
+ var skinList = mw.config.get('EmbedPlayer.SkinList');
+ for ( var n = 0; n < skinList.length; n++ ) {
+ if ( sn.indexOf( skinList[n].toLowerCase() ) !== -1 ) {
+ this.skinName = skinList[ n ];
+ }
+ }
+ }
+ // Set the default skin if unset:
+ if ( !this.skinName ) {
+ this.skinName = mw.config.get( 'EmbedPlayer.DefaultSkin' );
+ }
+
+ // Support custom monitorRate Attribute ( if not use default )
+ if( !this.monitorRate ){
+ this.monitorRate = mw.config.get( 'EmbedPlayer.MonitorRate' );
+ }
+
+ // Make sure startOffset is cast as an float:
+ if ( this.startOffset && this.startOffset.split( ':' ).length >= 2 ) {
+ this.startOffset = parseFloat( mw.npt2seconds( this.startOffset ) );
+ }
+
+ // Make sure offset is in float:
+ this.startOffset = parseFloat( this.startOffset );
+
+ // Set the source duration
+ if ( $( element ).attr( 'duration' ) ) {
+ _this.duration = $( element ).attr( 'duration' );
+ }
+ // Add durationHint property form data-durationhint:
+ if( _this['data-durationhint']){
+ _this.durationHint = _this['data-durationhint'];
+ }
+ // Update duration from provided durationHint
+ if ( _this.durationHint && ! _this.duration){
+ _this.duration = mw.npt2seconds( _this.durationHint );
+ }
+
+ // Make sure duration is a float:
+ this.duration = parseFloat( this.duration );
+ mw.log( 'EmbedPlayer::init:' + this.id + " duration is: " + this.duration );
+
+ // Add disablecontrols property form data-disablecontrols:
+ if( _this['data-disablecontrols'] ){
+ _this.disablecontrols = _this['data-disablecontrols'];
+ }
+
+ // Set the playerElementId id
+ this.pid = 'pid_' + this.id;
+
+ // Add the mediaElement object with the elements sources:
+ this.mediaElement = new mw.MediaElement( element );
+
+ this.bindHelper( 'updateLayout', function() {
+ _this.updateLayout();
+ });
+ },
+ /**
+ * Bind helpers to help iOS retain bind context
+ *
+ * Yes, iOS will fail when you run $( embedPlayer ).bind()
+ * but "work" when you run embedPlayer.bind() if the script urls are from diffrent "resources"
+ */
+ bindHelper: function( name, callback ){
+ $( this ).bind( name, callback );
+ return this;
+ },
+ unbindHelper: function( bindName ){
+ if( bindName ) {
+ $( this ).unbind( bindName );
+ }
+ return this;
+ },
+ triggerQueueCallback: function( name, callback ){
+ $( this ).triggerQueueCallback( name, callback );
+ },
+ triggerHelper: function( name, obj ){
+ try{
+ $( this ).trigger( name, obj );
+ } catch( e ){
+ // ignore try catch calls
+ // mw.log( "EmbedPlayer:: possible error in trgger: " + name + " " + e.toString() );
+ }
+ },
+ /**
+ * Stop events from Propagation and blocks interface updates and trigger events.
+ * @return
+ */
+ stopEventPropagation: function(){
+ mw.log("EmbedPlayer:: stopEventPropagation");
+ this.stopMonitor();
+ this._propagateEvents = false;
+ },
+
+ /**
+ * Restores event propagation
+ * @return
+ */
+ restoreEventPropagation: function(){
+ mw.log("EmbedPlayer:: restoreEventPropagation");
+ this._propagateEvents = true;
+ this.startMonitor();
+ },
+
+ /**
+ * Enables the play controls ( for example when an ad is done )
+ */
+ enablePlayControls: function(){
+ mw.log("EmbedPlayer:: enablePlayControls" );
+ if( this.useNativePlayerControls() ){
+ return ;
+ }
+ this._playContorls = true;
+ // re-enable hover:
+ this.getInterface().find( '.play-btn' )
+ .buttonHover()
+ .css('cursor', 'pointer' );
+
+ this.controlBuilder.enableSeekBar();
+ /*
+ * We should pass an array with enabled components, and the controlBuilder will listen
+ * to this event and handle the layout changes. we should not call to this.controlBuilder inside embedPlayer.
+ * [ 'playButton', 'seekBar' ]
+ */
+ $( this ).trigger( 'onEnableInterfaceComponents');
+ },
+
+ /**
+ * Disables play controls, for example when an ad is playing back
+ */
+ disablePlayControls: function(){
+ if( this.useNativePlayerControls() ){
+ return ;
+ }
+ this._playContorls = false;
+ // turn off hover:
+ this.getInterface().find( '.play-btn' )
+ .unbind('mouseenter mouseleave')
+ .css('cursor', 'default' );
+
+ this.controlBuilder.disableSeekBar();
+ /**
+ * We should pass an array with disabled components, and the controlBuilder will listen
+ * to this event and handle the layout changes. we should not call to this.controlBuilder inside embedPlayer.
+ * [ 'playButton', 'seekBar' ]
+ */
+ $( this ).trigger( 'onDisableInterfaceComponents');
+ },
+
+ /**
+ * For plugin-players to update supported features
+ */
+ updateFeatureSupport: function(){
+ $( this ).trigger('updateFeatureSupportEvent', this.supports );
+ return ;
+ },
+ /**
+ * Apply Intrinsic Aspect ratio of a given image to a poster image layout
+ */
+ applyIntrinsicAspect: function(){
+ var $this = $( this );
+ // Check if a image thumbnail is present:
+ if( this.getInterface().find('.playerPoster').length ){
+ var img = this.getInterface().find('.playerPoster')[0];
+ var pHeight = $this.height();
+ // Check for intrinsic width and maintain aspect ratio
+ if( img.naturalWidth && img.naturalHeight ){
+ var pWidth = parseInt( img.naturalWidth / img.naturalHeight * pHeight);
+ if( pWidth > $this.width() ){
+ pWidth = $this.width();
+ pHeight = parseInt( img.naturalHeight / img.naturalWidth * pWidth );
+ }
+ $( img ).css({
+ 'height' : pHeight + 'px',
+ 'width': pWidth + 'px',
+ 'left': ( ( $this.width() - pWidth ) * .5 ) + 'px',
+ 'top': ( ( $this.height() - pHeight ) * .5 ) + 'px',
+ 'position' : 'absolute'
+ });
+ }
+ }
+ },
+ /**
+ * Set the width & height from css style attribute, element attribute, or by
+ * default value if no css or attribute is provided set a callback to
+ * resize.
+ *
+ * Updates this.width & this.height
+ *
+ * @param {Element}
+ * element Source element to grab size from
+ */
+ loadPlayerSize: function( element ) {
+ // check for direct element attribute:
+ this.height = element.height > 0 ? element.height + '' : $(element).css( 'height' );
+ this.width = element.width > 0 ? element.width + '' : $(element).css( 'width' );
+
+ // Special check for chrome 100% with re-mapping to 32px
+ // Video embed at 32x32 will have to wait for intrinsic video size later on
+ if( this.height == '32px' || this.height =='32px' ){
+ this.width = '100%';
+ this.height = '100%';
+ }
+ mw.log('EmbedPlayer::loadPlayerSize: css size:' + this.width + ' h: ' + this.height);
+
+ // Set to parent size ( resize events will cause player size updates)
+ if( this.height.indexOf('100%') != -1 || this.width.indexOf('100%') != -1 ){
+ var $relativeParent = $(element).parents().filter(function() {
+ // reduce to only relative position or "body" elements
+ return $( this ).is('body') || $( this ).css('position') == 'relative';
+ }).slice(0,1); // grab only the "first"
+ this.width = $relativeParent.width();
+ this.height = $relativeParent.height();
+ }
+ // Make sure height and width are a number
+ this.height = parseInt( this.height );
+ this.width = parseInt( this.width );
+
+ // Set via attribute if CSS is zero or NaN and we have an attribute value:
+ this.height = ( this.height==0 || isNaN( this.height )
+ && $(element).attr( 'height' ) ) ?
+ parseInt( $(element).attr( 'height' ) ): this.height;
+ this.width = ( this.width == 0 || isNaN( this.width )
+ && $(element).attr( 'width' ) )?
+ parseInt( $(element).attr( 'width' ) ): this.width;
+
+
+ // Special case for audio
+
+ // Firefox sets audio height to "0px" while webkit uses 32px .. force zero:
+ if( this.isAudio() && this.height == '32' ) {
+ this.height = 20;
+ }
+
+ // Use default aspect ration to get height or width ( if rewriting a non-audio player )
+ if( this.isAudio() && this.videoAspect ) {
+ var aspect = this.videoAspect.split( ':' );
+ if( this.height && !this.width ) {
+ this.width = parseInt( this.height * ( aspect[0] / aspect[1] ) );
+ }
+ if( this.width && !this.height ) {
+ var apectRatio = ( aspect[1] / aspect[0] );
+ this.height = parseInt( this.width * ( aspect[1] / aspect[0] ) );
+ }
+ }
+
+ // On load sometimes attr is temporally -1 as we don't have video metadata yet.
+ // or in IE we get NaN for width height
+ //
+ // NOTE: browsers that do support height width should set "waitForMeta" flag in addElement
+ if( ( isNaN( this.height )|| isNaN( this.width ) ) ||
+ ( this.height == -1 || this.width == -1 ) ||
+ // Check for firefox defaults
+ // Note: ideally firefox would not do random guesses at css
+ // values
+ ( (this.height == 150 || this.height == 64 ) && this.width == 300 )
+ ) {
+ var defaultSize = mw.config.get( 'EmbedPlayer.DefaultSize' ).split( 'x' );
+ if( isNaN( this.width ) ){
+ this.width = defaultSize[0];
+ }
+
+ // Special height default for audio tag ( if not set )
+ if( this.isAudio() ) {
+ this.height = 20;
+ }else{
+ this.height = defaultSize[1];
+ }
+ }
+ },
+
+ /**
+ * Get the player pixel width not including controls
+ *
+ * @return {Number} pixel height of the video
+ */
+ getPlayerWidth: function() {
+ var profile = $.client.profile();
+
+ if ( profile.name === 'firefox' && profile.versionNumber < 2 ) {
+ return ( $( this ).parent().parent().width() );
+ }
+ return $( this ).width();
+ },
+
+ /**
+ * Get the player pixel height not including controls
+ *
+ * @return {Number} pixel height of the video
+ */
+ getPlayerHeight: function() {
+ return $( this ).height();
+ },
+
+ /**
+ * Check player for sources. If we need to get media sources form an
+ * external file that request is issued here
+ */
+ checkPlayerSources: function() {
+ mw.log( 'EmbedPlayer::checkPlayerSources: ' + this.id );
+ var _this = this;
+ // Allow plugins to listen to a preCheckPlayerSources ( for registering the source loading point )
+ $( _this ).trigger( 'preCheckPlayerSources' );
+
+ // Allow plugins to block on sources lookup ( cases where we just have an api key for example )
+ $( _this ).triggerQueueCallback( 'checkPlayerSourcesEvent', function(){
+ _this.setupSourcePlayer();
+ });
+ },
+
+ /**
+ * Get text tracks from the mediaElement
+ */
+ getTextTracks: function(){
+ if( !this.mediaElement ){
+ return [];
+ }
+ return this.mediaElement.getTextTracks();
+ },
+ /**
+ * Empty the player sources
+ */
+ emptySources: function(){
+ if( this.mediaElement ){
+ this.mediaElement.sources = [];
+ this.mediaElement.selectedSource = null;
+ }
+ // setup pointer to old source:
+ this.prevPlayer = this.selectedPlayer;
+ // don't null out the selected player on empty sources
+ //this.selectedPlayer =null;
+ },
+
+ /**
+ * Switch and play a video source
+ *
+ * Checks if the target source is the same playback mode and does player switch if needed.
+ * and calls playerSwitchSource
+ */
+ switchPlaySource: function( source, switchCallback, doneCallback ){
+ var _this = this;
+ var targetPlayer = mw.EmbedTypes.getMediaPlayers().defaultPlayer( source.mimeType ) ;
+ if( targetPlayer.library != this.selectedPlayer.library ){
+ this.selectedPlayer = targetPlayer;
+ this.updatePlaybackInterface( function(){
+ _this.playerSwitchSource( source, switchCallback, doneCallback );
+ });
+ } else {
+ // Call the player switch directly:
+ _this.playerSwitchSource( source, switchCallback, doneCallback );
+ }
+ },
+ /**
+ * abstract function player interface must support actual source switch
+ */
+ playerSwitchSource: function( source, switchCallback, doneCallback ){
+ mw.log( "Error player interface must support actual source switch");
+ },
+
+ /**
+ * Set up the select source player
+ *
+ * issues autoSelectSource call
+ *
+ * Sets load error if no source is playable
+ */
+ setupSourcePlayer: function() {
+ var _this = this;
+ mw.log("EmbedPlayer::setupSourcePlayer: " + this.id + ' sources: ' + this.mediaElement.sources.length );
+
+ // Check for source replace configuration:
+ if( mw.config.get('EmbedPlayer.ReplaceSources' ) ){
+ this.emptySources();
+ $.each( mw.config.get('EmbedPlayer.ReplaceSources' ), function( inx, source ){
+ _this.mediaElement.tryAddSource( source );
+ });
+ }
+
+ // Autoseletct the media source
+ this.mediaElement.autoSelectSource();
+
+ // Auto select player based on default order
+ if( this.mediaElement.selectedSource ){
+ this.selectedPlayer = mw.EmbedTypes.getMediaPlayers().defaultPlayer( this.mediaElement.selectedSource.mimeType );
+ // Check if we need to switch player rendering libraries:
+ if ( this.selectedPlayer && ( !this.prevPlayer || this.prevPlayer.library != this.selectedPlayer.library ) ) {
+ // Inherit the playback system of the selected player:
+ this.updatePlaybackInterface();
+ return ;
+ }
+ }
+
+ // Check if no player is selected
+ if( !this.selectedPlayer || !this.mediaElement.selectedSource ){
+ this.showPlayerError();
+ mw.log( "EmbedPlayer:: setupSourcePlayer > player ready ( but with errors ) ");
+ } else {
+ // Trigger layout ready event
+ $( this ).trigger( 'layoutReady' );
+ // Show the interface:
+ this.getInterface().find( '.control-bar').show();
+ this.addLargePlayBtn();
+ }
+ // We still do the playerReady sequence on errors to provide an api
+ // and player error events
+ this.playerReadyFlag = true;
+ // trigger the player ready event;
+ $( this ).trigger( 'playerReady' );
+ this.triggerWidgetLoaded();
+ },
+
+ /**
+ * Updates the player interface
+ *
+ * Loads and inherit methods from the selected player interface.
+ *
+ * @param {Function}
+ * callback Function to be called once playback-system has been
+ * inherited
+ */
+ updatePlaybackInterface: function( callback ) {
+ var _this = this;
+ mw.log( "EmbedPlayer::updatePlaybackInterface: duration is: " + this.getDuration() + ' playerId: ' + this.id );
+ // Clear out any non-base embedObj methods:
+ if ( this.instanceOf ) {
+ // Update the prev instance var used for swiching interfaces to know the previous instance.
+ $( this ).data( 'previousInstanceOf', this.instanceOf );
+ var tmpObj = window['mw.EmbedPlayer' + this.instanceOf ];
+ for ( var i in tmpObj ) {
+ // Restore parent into local location
+ if ( typeof this[ 'parent_' + i ] != 'undefined' ) {
+ this[i] = this[ 'parent_' + i];
+ } else {
+ this[i] = null;
+ }
+ }
+ }
+ // Set up the new embedObj
+ mw.log( 'EmbedPlayer::updatePlaybackInterface: embedding with ' + this.selectedPlayer.library );
+ this.selectedPlayer.load( function() {
+ _this.updateLoadedPlayerInterface( callback );
+ });
+ },
+ /**
+ * Update a loaded player interface by setting local methods to the
+ * updated player prototype methods
+ *
+ * @parma {function}
+ * callback function called once player has been loaded
+ */
+ updateLoadedPlayerInterface: function( callback ){
+ var _this = this;
+ mw.log( 'EmbedPlayer::updateLoadedPlayerInterface ' + _this.selectedPlayer.library + " player loaded for " + _this.id );
+
+ // Get embed library player Interface
+ var playerInterface = mw[ 'EmbedPlayer' + _this.selectedPlayer.library ];
+
+ // Build the player interface ( if the interface includes an init )
+ if( playerInterface.init ){
+ playerInterface.init();
+ }
+
+ for ( var method in playerInterface ) {
+ if ( typeof _this[method] != 'undefined' && !_this['parent_' + method] ) {
+ _this['parent_' + method] = _this[method];
+ }
+ _this[ method ] = playerInterface[ method ];
+ }
+ // Update feature support
+ _this.updateFeatureSupport();
+ // Update duration
+ _this.getDuration();
+ // show player inline
+ _this.showPlayer();
+ // Run the callback if provided
+ if ( callback && $.isFunction( callback ) ){
+ callback();
+ }
+ },
+
+ /**
+ * Select a player playback system
+ *
+ * @param {Object}
+ * player Player playback system to be selected player playback
+ * system include vlc, native, java etc.
+ */
+ selectPlayer: function( player ) {
+ mw.log("EmbedPlayer:: selectPlayer " + player.id );
+ var _this = this;
+ if ( this.selectedPlayer.id != player.id ) {
+ this.selectedPlayer = player;
+ this.updatePlaybackInterface( function(){
+ // Hide / remove track container
+ _this.getInterface().find( '.track' ).remove();
+ // We have to re-bind hoverIntent ( has to happen in this scope )
+ if( !_this.useNativePlayerControls() && _this.controls && _this.controlBuilder.isOverlayControls() ){
+ _this.controlBuilder.showControlBar();
+ _this.getInterface().hoverIntent({
+ 'sensitivity': 4,
+ 'timeout' : 2000,
+ 'over' : function(){
+ _this.controlBuilder.showControlBar();
+ },
+ 'out' : function(){
+ _this.controlBuilder.hideControlBar();
+ }
+ });
+ }
+ });
+ }
+ },
+
+ /**
+ * Get a time range from the media start and end time
+ *
+ * @return startNpt and endNpt time if present
+ */
+ getTimeRange: function() {
+ var end_time = ( this.controlBuilder.longTimeDisp )? '/' + mw.seconds2npt( this.getDuration() ) : '';
+ var defaultTimeRange = '0:00' + end_time;
+ if ( !this.mediaElement ){
+ return defaultTimeRange;
+ }
+ if ( !this.mediaElement.selectedSource ){
+ return defaultTimeRange;
+ }
+ if ( !this.mediaElement.selectedSource.endNpt ){
+ return defaultTimeRange;
+ }
+ return this.mediaElement.selectedSource.startNpt + this.mediaElement.selectedSource.endNpt;
+ },
+
+ /**
+ * Get the duration of the embed player
+ */
+ getDuration: function() {
+ if ( isNaN(this.duration) && this.mediaElement && this.mediaElement.selectedSource &&
+ typeof this.mediaElement.selectedSource.durationHint != 'undefined' ){
+ this.duration = this.mediaElement.selectedSource.durationHint;
+ }
+ return this.duration;
+ },
+
+ /**
+ * Get the player height
+ */
+ getHeight: function() {
+ return this.getInterface().height();
+ },
+
+ /**
+ * Get the player width
+ */
+ getWidth: function(){
+ return this.getInterface().width();
+ },
+
+ /**
+ * Check if the selected source is an audio element:
+ */
+ isAudio: function(){
+ return ( this.rewriteElementTagName == 'audio'
+ ||
+ ( this.mediaElement && this.mediaElement.selectedSource && this.mediaElement.selectedSource.mimeType.indexOf('audio/') !== -1 )
+ );
+ },
+
+ /**
+ * Get the plugin embed html ( should be implemented by embed player interface )
+ */
+ embedPlayerHTML: function() {
+ return 'Error: function embedPlayerHTML should be implemented by embed player interface ';
+ },
+
+ /**
+ * Seek function ( should be implemented by embedPlayer interface
+ * playerNative, playerKplayer etc. ) embedPlayer seek only handles URL
+ * time seeks
+ * @param {Float}
+ * percent of the video total length to seek to
+ */
+ seek: function( percent ) {
+ var _this = this;
+ this.seeking = true;
+ // Trigger preSeek event for plugins that want to store pre seek conditions.
+ $( this ).trigger( 'preSeek', percent );
+
+ // Do argument checking:
+ if( percent < 0 ){
+ percent = 0;
+ }
+
+ if( percent > 1 ){
+ percent = 1;
+ }
+ // set the playhead to the target position
+ this.updatePlayHead( percent );
+
+ // See if we should do a server side seek ( player independent )
+ if ( this.supportsURLTimeEncoding() ) {
+ mw.log( 'EmbedPlayer::seek:: updated serverSeekTime: ' + mw.seconds2npt ( this.serverSeekTime ) +
+ ' currentTime: ' + _this.currentTime );
+ // make sure we need to seek:
+ if( _this.currentTime == _this.serverSeekTime ){
+ return ;
+ }
+
+ this.stop();
+ this.didSeekJump = true;
+ // Make sure this.serverSeekTime is up-to-date:
+ this.serverSeekTime = mw.npt2seconds( this.startNpt ) + parseFloat( percent * this.getDuration() );
+ }
+ // Run the onSeeking interface update
+ // NOTE controlBuilder should really bind to html5 events rather
+ // than explicitly calling it or inheriting stuff.
+ this.controlBuilder.onSeek();
+ },
+
+ /**
+ * Seeks to the requested time and issues a callback when ready (should be
+ * overwritten by client that supports frame serving)
+ */
+ setCurrentTime: function( time, callback ) {
+ mw.log( 'Error: EmbedPlayer, setCurrentTime not overriden' );
+ if( $.isFunction( callback ) ){
+ callback();
+ }
+ },
+
+ /**
+ * On clip done action. Called once a clip is done playing
+ * TODO clean up end sequence flow
+ */
+ triggeredEndDone: false,
+ postSequence: false,
+ onClipDone: function() {
+ var _this = this;
+ // Don't run onclipdone if _propagateEvents is off
+ if( !_this._propagateEvents ){
+ return ;
+ }
+ mw.log( 'EmbedPlayer::onClipDone: propagate:' + _this._propagateEvents + ' id:' + this.id + ' doneCount:' + this.donePlayingCount + ' stop state:' +this.isStopped() );
+ // Only run stopped once:
+ if( !this.isStopped() ){
+ // set the "stopped" flag:
+ this.stopped = true;
+
+ // Show the control bar:
+ this.controlBuilder.showControlBar();
+
+ // TOOD we should improve the end event flow
+ // First end event for ads or current clip ended bindings
+ if( ! this.onDoneInterfaceFlag ){
+ this.stopEventPropagation();
+ }
+
+ mw.log("EmbedPlayer:: trigger: ended ( inteface continue pre-check: " + this.onDoneInterfaceFlag + ' )' );
+ $( this ).trigger( 'ended' );
+ mw.log("EmbedPlayer::onClipDone:Trigged ended, continue? " + this.onDoneInterfaceFlag);
+
+
+ if( ! this.onDoneInterfaceFlag ){
+ // Restore events if we are not running the interface done actions
+ this.restoreEventPropagation();
+ return ;
+ }
+
+ // A secondary end event for playlist and clip sequence endings
+ if( this.onDoneInterfaceFlag ){
+ // We trigger two end events to match KDP and ensure playbackComplete always comes before playerPlayEnd
+ // in content ends.
+ mw.log("EmbedPlayer:: trigger: playbackComplete");
+ $( this ).trigger( 'playbackComplete' );
+ // now trigger postEnd for( playerPlayEnd )
+ mw.log("EmbedPlayer:: trigger: postEnded");
+ $( this ).trigger( 'postEnded' );
+ }
+ // if the ended event did not trigger more timeline actions run the actual stop:
+ if( this.onDoneInterfaceFlag ){
+ mw.log("EmbedPlayer::onDoneInterfaceFlag=true do interface done");
+ // Prevent the native "onPlay" event from propagating that happens when we rewind:
+ this.stopEventPropagation();
+
+ // Update the clip done playing count ( for keeping track of replays )
+ _this.donePlayingCount ++;
+
+ // Rewind the player to the start:
+ // NOTE: Setting to 0 causes lags on iPad when replaying, thus setting to 0.01
+ this.setCurrentTime(0.01, function(){
+
+ // Set to stopped state:
+ _this.stop();
+
+ // Restore events after we rewind the player
+ _this.restoreEventPropagation();
+
+ // Check if we have the "loop" property set
+ if( _this.loop ) {
+ _this.stopped = false;
+ _this.play();
+ return;
+ } else {
+ // make sure we are in a paused state.
+ _this.pause();
+ }
+ // Check if have a force display of the large play button
+ if( mw.config.get('EmbedPlayer.ForceLargeReplayButton') === true ){
+ _this.addLargePlayBtn();
+ } else{
+ // Check if we should hide the large play button on end:
+ if( $( _this ).data( 'hideEndPlayButton' ) || !_this.useLargePlayBtn() ){
+ _this.hideLargePlayBtn();
+ } else {
+ _this.addLargePlayBtn();
+ }
+ }
+ // An event for once the all ended events are done.
+ mw.log("EmbedPlayer:: trigger: onEndedDone");
+ if ( !_this.triggeredEndDone ){
+ _this.triggeredEndDone = true;
+ $( _this ).trigger( 'onEndedDone', [_this.id] );
+ }
+ })
+ }
+ }
+ },
+
+
+ /**
+ * Shows the video Thumbnail, updates pause state
+ */
+ showThumbnail: function() {
+ var _this = this;
+ mw.log( 'EmbedPlayer::showThumbnail::' + this.stopped );
+
+ // Close Menu Overlay:
+ this.controlBuilder.closeMenuOverlay();
+
+ // update the thumbnail html:
+ this.updatePosterHTML();
+
+ this.paused = true;
+ this.stopped = true;
+
+ // Once the thumbnail is shown run the mediaReady trigger (if not using native controls)
+ if( !this.useNativePlayerControls() ){
+ mw.log("mediaLoaded");
+ $( this ).trigger( 'mediaLoaded' );
+ }
+ },
+
+ /**
+ * Show the player
+ */
+ showPlayer: function () {
+ mw.log( 'EmbedPlayer:: showPlayer: ' + this.id + ' interface: w:' + this.width + ' h:' + this.height );
+ var _this = this;
+
+ // Remove the player loader spinner if it exists
+ this.hideSpinnerAndPlayBtn();
+ // If a isPersistentNativePlayer ( overlay the controls )
+ if( !this.useNativePlayerControls() && this.isPersistentNativePlayer() ){
+ $( this ).show();
+ }
+ // Add controls if enabled:
+ if ( this.controls ) {
+ if( this.useNativePlayerControls() ){
+ if( this.getPlayerElement() ){
+ $( this.getPlayerElement() ).attr('controls', "true");
+ }
+ } else {
+ this.controlBuilder.addControls();
+ }
+ }
+
+ // Update Thumbnail for the "player"
+ this.updatePosterHTML();
+
+ // Update temporal url if present
+ this.updateTemporalUrl();
+
+ // Do we need to show the player?
+ if( this.displayPlayer === false ) {
+ _this.getVideoHolder().hide();
+ _this.getInterface().height( _this.getComponentsHeight() );
+ _this.triggerHelper('updateLayout');
+ }
+
+ // Update layout
+ this.updateLayout();
+
+ // Make sure we have a play btn:
+ this.addLargePlayBtn();
+
+ // Update the playerReady flag
+ this.playerReadyFlag = true;
+ mw.log("EmbedPlayer:: Trigger: playerReady");
+ // trigger the player ready event;
+ $( this ).trigger( 'playerReady' );
+ this.triggerWidgetLoaded();
+
+ // Check if we want to block the player display
+ if( this['data-blockPlayerDisplay'] ){
+ this.blockPlayerDisplay();
+ return ;
+ }
+
+ // Check if there are any errors to be displayed:
+ if( this.getError() ){
+ this.showErrorMsg( this.getError() );
+ return ;
+ }
+ // Auto play stopped ( no playerReady has already started playback ) and if not on an iPad with iOS > 3
+ if ( this.isStopped() && this.autoplay && (!mw.isIOS() || mw.isIpad3() ) ) {
+ mw.log( 'EmbedPlayer::showPlayer::Do autoPlay' );
+ _this.play();
+ }
+ },
+
+ getComponentsHeight: function() {
+ var height = 0;
+
+ // Go over all playerContainer direct children with .block class
+ this.getInterface().find('.block').each(function() {
+ height += $( this ).outerHeight( true );
+ });
+
+ // FIXME embedPlayer should know nothing about playlist layout
+ /* If we're in vertical playlist mode, and not in fullscreen add playlist height
+ if( $('#container').hasClass('vertical') && ! this.controlBuilder.isInFullScreen() && this.displayPlayer ) {
+ height += $('#playlistContainer').outerHeight( true );
+ }
+ */
+
+ //
+ var offset = (mw.isIOS()) ? 5 : 0;
+
+ return height + offset;
+ },
+ updateLayout: function() {
+ // update image layout:
+ this.applyIntrinsicAspect();
+ if( !mw.config.get('EmbedPlayer.IsIframeServer' ) ){
+ // Use intrensic container size
+ return ;
+ }
+ // Set window height if in iframe:
+ var windowHeight;
+ if( mw.isIOS() && ! this.controlBuilder.isInFullScreen() ) {
+ windowHeight = $( window.parent.document.getElementById( this.id ) ).height();
+ } else {
+ windowHeight = window.innerHeight;
+ }
+
+ var newHeight = windowHeight - this.getComponentsHeight();
+ var currentHeight = this.getVideoHolder().height();
+ // Always update videoHolder height
+ if( currentHeight !== newHeight ) {
+ mw.log('EmbedPlayer: updateLayout:: window: ' + windowHeight + ', components: ' + this.getComponentsHeight() + ', videoHolder old height: ' + currentHeight + ', new height: ' + newHeight );
+ this.getVideoHolder().height( newHeight );
+ }
+ },
+ /**
+ * Gets a refrence to the main player interface, builds if not avaliable
+ */
+ getInterface: function(){
+ if( !this.$interface ){
+ // init the control builder
+ this.controlBuilder = new mw.PlayerControlBuilder( this );
+
+ // build the interface wrapper
+ this.$interface = $( this ).wrap(
+ $('<div />')
+ .addClass( 'mwPlayerContainer ' + this.controlBuilder.playerClass )
+ .append(
+ $('<div />').addClass( 'videoHolder' )
+ )
+ ).parent().parent();
+
+ // pass along any inhereted style:
+ if( this.style.cssText ){
+ this.$interface[0].style.cssText = this.style.cssText;
+ }
+ // clear out base style
+ this.style.cssText = '';
+
+ // if not displayiung a play button, ( pass through to native player )
+ if( ! this.useLargePlayBtn() ){
+ this.$interface.css('pointer-events', 'none');
+ }
+ }
+ return this.$interface;
+ },
+
+ /**
+ * Media fragments handler based on:
+ * http://www.w3.org/2008/WebVideo/Fragments/WD-media-fragments-spec/#fragment-dimensions
+ *
+ * We support seconds and npt ( normal play time )
+ *
+ * Updates the player per fragment url info if present
+ *
+ */
+ updateTemporalUrl: function(){
+ var sourceHash = /[^\#]+$/.exec( this.getSrc() ).toString();
+ if( sourceHash.indexOf('t=') === 0 ){
+ // parse the times
+ var times = sourceHash.substr(2).split(',');
+ if( times[0] ){
+ // update the current time
+ this.currentTime = mw.npt2seconds( times[0].toString() );
+ }
+ if( times[1] ){
+ this.pauseTime = mw.npt2seconds( times[1].toString() );
+ // ignore invalid ranges:
+ if( this.pauseTime < this.currentTime ){
+ this.pauseTime = null;
+ }
+ }
+ // Update the play head
+ this.updatePlayHead( this.currentTime / this.duration );
+ // Update status:
+ this.controlBuilder.setStatus( mw.seconds2npt( this.currentTime ) );
+ }
+ },
+ /**
+ * Sets an error message on the player
+ *
+ * @param {string}
+ * errorMsg
+ */
+ setError: function( errorObj ){
+ var _this = this;
+ if ( typeof errorObj == 'string' ) {
+ this.playerError = {
+ 'title' : _this.getKalturaMsg( 'ks-GENERIC_ERROR_TITLE' ),
+ 'message' : errorObj
+ }
+ return ;
+
+ }
+ this.playerError = errorObj;
+ },
+ /**
+ * Gets the current player error
+ */
+ getError: function() {
+ if ( !$.isEmptyObject( this.playerError ) ) {
+ return this.playerError;
+ }
+ return null;
+ },
+
+ /**
+ * Show an error message on the player
+ *
+ * @param {object}
+ * errorObj
+ */
+ showErrorMsg: function( errorObj ){
+ // Remove a loading spinner
+ this.hideSpinnerAndPlayBtn();
+ if( this.controlBuilder ) {
+ if( mw.config.get("EmbedPlayer.ShowPlayerAlerts") ) {
+ var alertObj = $.extend( errorObj, {
+ 'isModal': true,
+ 'keepOverlay': true,
+ 'noButtons': true,
+ 'isError': true
+ } );
+ this.controlBuilder.displayAlert( alertObj );
+ }
+ }
+ return ;
+ },
+
+ /**
+ * Blocks the player display by invoking an empty error msg
+ */
+ blockPlayerDisplay: function(){
+ this.showErrorMsg();
+ this.getInterface().find( '.error' ).hide();
+ },
+
+ /**
+ * Get missing plugin html (check for user included code)
+ *
+ * @param {String}
+ * [misssingType] missing type mime
+ */
+ showPlayerError: function( ) {
+ var _this = this;
+ var $this = $( this );
+ mw.log("EmbedPlayer::showPlayerError");
+ // Hide loader
+ this.hideSpinnerAndPlayBtn();
+
+ // Error in loading media ( trigger the mediaLoadError )
+ $this.trigger( 'mediaLoadError' );
+
+ // We don't distiguish between mediaError and mediaLoadError right now
+ // TODO fire mediaError only on failed to recive audio/video data.
+ $this.trigger( 'mediaError' );
+
+ // Check if we want to block the player display ( no error displayed )
+ if( this['data-blockPlayerDisplay'] ){
+ this.blockPlayerDisplay();
+ return ;
+ }
+
+ // Check if there is a more specific error:
+ if( this.getError() ){
+ this.showErrorMsg( this.getError() );
+ return ;
+ }
+
+ // If no error is given assume missing sources:
+ this.showNoInlinePlabackSupport();
+ },
+
+ /**
+ * Show player missing sources method
+ */
+ showNoInlinePlabackSupport: function(){
+ var _this = this;
+ var $this = $( this);
+
+ // Check if any sources are avaliable:
+ if( this.mediaElement.sources.length == 0
+ ||
+ !mw.config.get('EmbedPlayer.NotPlayableDownloadLink') )
+ {
+ return ;
+ }
+ // Set the isLink player flag:
+ this.isLinkPlayer= true;
+ // Update the poster and html:
+ this.updatePosterHTML();
+
+ // Make sure we have a play btn:
+ this.addLargePlayBtn();
+
+ // By default set the direct download url to the first source.
+ var downloadUrl = this.mediaElement.sources[0].getSrc();
+ // Allow plugins to update the download url ( to point to server side tools to select
+ // stream based on user agent ( i.e IE8 h.264 file, blackberry 3gp file etc )
+ this.triggerHelper( 'directDownloadLink', function( dlUrl ){
+ if( dlUrl ){
+ downloadUrl = dlUrl;
+ }
+ });
+ // Set the play button to the first available source:
+ var $pBtn = this.getInterface().find('.play-btn-large')
+ .attr( 'title', mw.msg('mwe-embedplayer-play_clip') )
+ .show()
+ .unbind( 'click' )
+ .click( function() {
+ _this.triggerHelper( 'firstPlay', [ _this.id ] ); // To send stats event for play
+ _this.triggerHelper( 'playing' );
+ return true;
+ });
+ if( !$pBtn.parent('a').length ){
+ $pBtn.wrap( $( '<a />' ).attr("target", "_blank" ) );
+ }
+ $pBtn.parent('a').attr( "href", downloadUrl );
+
+ $( this ).trigger( 'showInlineDownloadLink' );
+ },
+ /**
+ * Update the video time request via a time request string
+ *
+ * @param {String}
+ * timeRequest video time to be updated
+ */
+ updateVideoTimeReq: function( timeRequest ) {
+ mw.log( 'EmbedPlayer::updateVideoTimeReq:' + timeRequest );
+ var timeParts = timeRequest.split( '/' );
+ this.updateVideoTime( timeParts[0], timeParts[1] );
+ },
+
+ /**
+ * Update Video time from provided startNpt and endNpt values
+ *
+ * @param {String}
+ * startNpt the new start time in npt format ( hh:mm:ss.ms )
+ * @param {String}
+ * endNpt the new end time in npt format ( hh:mm:ss.ms )
+ */
+ updateVideoTime: function( startNpt, endNpt ) {
+ // update media
+ this.mediaElement.updateSourceTimes( startNpt, endNpt );
+
+ // update time
+ this.controlBuilder.setStatus( startNpt + '/' + endNpt );
+
+ // reset slider
+ this.updatePlayHead( 0 );
+
+ // Reset the serverSeekTime if urlTimeEncoding is enabled
+ if ( this.supportsURLTimeEncoding() ) {
+ this.serverSeekTime = 0;
+ } else {
+ this.serverSeekTime = mw.npt2seconds( startNpt );
+ }
+ },
+
+
+ /**
+ * Update Thumb time with npt formated time
+ *
+ * @param {String}
+ * time NPT formated time to update thumbnail
+ */
+ updateThumbTimeNPT: function( time ) {
+ this.updateThumbTime( mw.npt2seconds( time ) - parseInt( this.startOffset ) );
+ },
+
+ /**
+ * Update the thumb with a new time
+ *
+ * @param {Float}
+ * floatSeconds Time to update the thumb to
+ */
+ updateThumbTime:function( floatSeconds ) {
+ // mw.log('updateThumbTime:'+floatSeconds);
+ var _this = this;
+ if ( typeof this.orgThumSrc == 'undefined' ) {
+ this.orgThumSrc = this.poster;
+ }
+ if ( this.orgThumSrc.indexOf( 't=' ) !== -1 ) {
+ this.lastThumbUrl = mw.replaceUrlParams( this.orgThumSrc,
+ {
+ 't' : mw.seconds2npt( floatSeconds + parseInt( this.startOffset ) )
+ }
+ );
+ if ( !this.thumbnailUpdatingFlag ) {
+ this.updatePoster( this.lastThumbUrl , false );
+ this.lastThumbUrl = null;
+ }
+ }
+ },
+
+ /**
+ * Updates the displayed thumbnail via percent of the stream
+ *
+ * @param {Float}
+ * percent Percent of duration to update thumb
+ */
+ updateThumbPerc:function( percent ) {
+ return this.updateThumbTime( ( this.getDuration() * percent ) );
+ },
+
+ /**
+ * Update the poster source
+ * @param {String}
+ * posterSrc Poster src url
+ */
+ updatePosterSrc: function( posterSrc ){
+ if( ! posterSrc ) {
+ posterSrc = mw.config.get( 'EmbedPlayer.BlackPixel' );
+ }
+ this.poster = posterSrc;
+ this.updatePosterHTML();
+ this.applyIntrinsicAspect();
+ },
+
+ /**
+ * Called after sources are updated, and your ready for the player to change media
+ * @return
+ */
+ changeMedia: function( callback ){
+ var _this = this;
+ var $this = $( this );
+ mw.log( 'EmbedPlayer:: changeMedia ');
+ // Empty out embedPlayer object sources
+ this.emptySources();
+
+ // onChangeMedia triggered at the start of the change media commands
+ $this.trigger( 'onChangeMedia' );
+
+ // Reset first play to true, to count that play event
+ this.firstPlay = true;
+ // reset donePlaying count on change media.
+ this.donePlayingCount = 0;
+ this.triggeredEndDone = false;
+ this.preSequence = false;
+ this.postSequence = false;
+
+ this.setCurrentTime( 0.01 );
+ // Reset the playhead
+ this.updatePlayHead( 0 );
+ // update the status:
+ this.controlBuilder.setStatus( this.getTimeRange() );
+
+ // Add a loader to the embed player:
+ this.pauseLoading();
+
+ // Clear out any player error ( both via attr and object property ):
+ this.setError( null );
+
+ // Clear out any player display blocks
+ this['data-blockPlayerDisplay'] = null
+ $this.attr( 'data-blockPlayerDisplay', '');
+
+ // Clear out the player error div:
+ this.getInterface().find('.error').remove();
+ this.controlBuilder.closeAlert();
+ this.controlBuilder.closeMenuOverlay();
+
+ // Restore the control bar:
+ this.getInterface().find('.control-bar').show();
+ // Hide the play btn
+ this.hideLargePlayBtn();
+
+ //If we are change playing media add a ready binding:
+ var bindName = 'playerReady.changeMedia';
+ $this.unbind( bindName ).bind( bindName, function(){
+ mw.log('EmbedPlayer::changeMedia playerReady callback');
+ // hide the loading spinner:
+ _this.hideSpinnerAndPlayBtn();
+ // check for an erro on change media:
+ if( _this.getError() ){
+ _this.showErrorMsg( _this.getError() );
+ return ;
+ }
+ // Always show the control bar on switch:
+ if( _this.controlBuilder ){
+ _this.controlBuilder.showControlBar();
+ }
+ // Make sure the play button reflects the original play state
+ if( _this.autoplay ){
+ _this.hideLargePlayBtn();
+ } else {
+ _this.addLargePlayBtn();
+ }
+ var source = _this.getSource();
+ if( (_this.isPersistentNativePlayer() || _this.useNativePlayerControls()) && source ){
+ // If switching a Persistent native player update the source:
+ // ( stop and play won't refresh the source )
+ _this.switchPlaySource( source, function(){
+ _this.changeMediaStarted = false;
+ $this.trigger( 'onChangeMediaDone' );
+ if( _this.autoplay ){
+ _this.play();
+ } else {
+ // pause is need to keep pause sate, while
+ // switch source calls .play() that some browsers require.
+ // to reflect source swiches.
+ _this.pause();
+ _this.addLargePlayBtn();
+ }
+ if( callback ){
+ callback()
+ }
+ });
+ // we are handling trigger and callback asynchronously return here.
+ return ;
+ }
+
+ // Reset changeMediaStarted flag
+ _this.changeMediaStarted = false;
+
+ // Stop should unload the native player
+ _this.stop();
+
+ // reload the player
+ if( _this.autoplay ){
+ _this.play();
+ } else {
+ _this.addLargePlayBtn();
+ }
+
+ $this.trigger( 'onChangeMediaDone' );
+ if( callback ) {
+ callback();
+ }
+ });
+
+ // Load new sources per the entry id via the checkPlayerSourcesEvent hook:
+ $this.triggerQueueCallback( 'checkPlayerSourcesEvent', function(){
+ // Start player events leading to playerReady
+ _this.setupSourcePlayer();
+ });
+ },
+ /**
+ * Checks if the current player / configuration is an image play screen:
+ */
+ isImagePlayScreen:function(){
+ return ( this.useNativePlayerControls() &&
+ !this.isLinkPlayer &&
+ mw.isIphone() &&
+ mw.config.get( 'EmbedPlayer.iPhoneShowHTMLPlayScreen')
+ );
+ },
+ /**
+ * Triggers widgetLoaded event - Needs to be triggered only once, at the first time playerReady is trigerred
+ */
+ triggerWidgetLoaded: function() {
+ if ( !this.widgetLoaded ) {
+ this.widgetLoaded = true;
+ mw.log( "EmbedPlayer:: Trigger: widgetLoaded");
+ this.triggerHelper( 'widgetLoaded' );
+ }
+ },
+
+ /**
+ * Updates the poster HTML
+ */
+ updatePosterHTML: function () {
+ mw.log( 'EmbedPlayer:updatePosterHTML::' + this.id );
+
+ var _this = this,
+ thumb_html = '',
+ class_atr = '',
+ style_atr = '',
+ profile = $.client.profile();
+
+ if( this.isImagePlayScreen() ){
+ this.addPlayScreenWithNativeOffScreen();
+ return ;
+ }
+
+ // Set by default thumb value if not found
+ var posterSrc = ( this.poster ) ? this.poster :
+ mw.config.get( 'EmbedPlayer.BlackPixel' );
+
+ // Update PersistentNativePlayer poster:
+ if( this.isPersistentNativePlayer() ){
+ var $vid = $( '#' + this.pid ).show();
+ $vid.attr( 'poster', posterSrc );
+ // Add a quick timeout hide / show ( firefox 4x bug with native poster updates )
+ if ( profile.name === 'firefox' ){
+ $vid.hide();
+ setTimeout( function () {
+ $vid.show();
+ }, 0);
+ }
+ } else {
+ // hide the pid if present:
+ $( '#' + this.pid ).hide();
+ // Poster support is not very consistent in browsers use a jpg poster image:
+ $( this )
+ .html(
+ $( '<img />' )
+ .css({
+ 'position': 'absolute',
+ 'top': 0,
+ 'left': 0,
+ 'right': 0,
+ 'bottom': 0
+ })
+ .attr({
+ 'src' : posterSrc
+ })
+ .addClass( 'playerPoster' )
+ .load(function(){
+ _this.applyIntrinsicAspect();
+ })
+ ).show();
+ }
+ if ( this.useLargePlayBtn() && this.controlBuilder
+ &&
+ this.height > this.controlBuilder.getComponentHeight( 'playButtonLarge' )
+ ) {
+ this.addLargePlayBtn();
+ }
+ },
+ /**
+ * Abstract method, must be set by player inteface
+ */
+ addPlayScreenWithNativeOffScreen: function(){
+ mw.log( "Error: EmbedPlayer, Must override 'addPlayScreenWithNativeOffScreen' with player inteface" );
+ return ;
+ },
+ /**
+ * Checks if a large play button should be displayed on the
+ * otherwise native player
+ */
+ useLargePlayBtn: function(){
+ if( this.isPersistantPlayBtn() ){
+ return true;
+ }
+ // If we are using native controls return false:
+ return !this.useNativePlayerControls();
+ },
+ /**
+ * Checks if the play button should stay on screen during playback,
+ * cases where a native player is dipalyed such as iPhone.
+ */
+ isPersistantPlayBtn: function(){
+ return mw.isAndroid2() ||
+ ( mw.isIphone() && mw.config.get( 'EmbedPlayer.iPhoneShowHTMLPlayScreen' ) );
+ },
+ /**
+ * Checks if native controls should be used
+ *
+ * @returns boolean true if the mwEmbed player interface should be used
+ * false if the mwEmbed player interface should not be used
+ */
+ useNativePlayerControls: function() {
+ if( this.usenativecontrols === true ){
+ return true;
+ }
+
+ if( mw.config.get('EmbedPlayer.NativeControls') === true ) {
+ return true;
+ }
+
+ // Check for special webkit property that allows inline iPhone playback:
+ if( mw.config.get('EmbedPlayer.WebKitPlaysInline') === true && mw.isIphone() ) {
+ return false;
+ }
+
+ // Do some device detection devices that don't support overlays
+ // and go into full screen once play is clicked:
+ if( mw.isAndroid2() || mw.isIpod() || mw.isIphone() ){
+ return true;
+ }
+
+ // iPad can use html controls if its a persistantPlayer in the dom before loading )
+ // else it needs to use native controls:
+ if( mw.isIpad() ){
+ if( mw.config.get('EmbedPlayer.EnableIpadHTMLControls') === true){
+ return false;
+ } else {
+ // Set warning that your trying to do iPad controls without
+ // persistent native player:
+ return true;
+ }
+ }
+ return false;
+ },
+ /**
+ * Checks if the native player is persistent in the dom since the intial page build out.
+ */
+ isPersistentNativePlayer: function(){
+ if( this.isLinkPlayer ){
+ return false;
+ }
+ // Since we check this early on sometimes the player
+ // has not yet been updated to the pid location
+ if( $('#' + this.pid ).length == 0 ){
+ return $('#' + this.id ).hasClass('persistentNativePlayer');
+ }
+ return $('#' + this.pid ).hasClass('persistentNativePlayer');
+ },
+ //
+ isTouchDevice: function(){
+ return mw.isIpad()
+ ||
+ mw.isAndroid40()
+ ||
+ mw.isMobileChrome();
+ },
+ /**
+ * Hides the large play button
+ * TODO move to player controls
+ */
+ hideLargePlayBtn: function(){
+ if( this.getInterface() ){
+ this.getInterface().find( '.play-btn-large' ).hide();
+ }
+ },
+ /**
+ * Add a play button (if not already there )
+ */
+ addLargePlayBtn: function(){
+ // check if we are pauseLoading ( i.e switching media, seeking, etc. and don't display play btn:
+ if( this.isPauseLoading ){
+ mw.log("EmbedPlayer:: addLargePlayBtn ( skip play button, during load )");
+ return;
+ }
+ // if using native controls make sure we can click the big play button by restoring
+ // interface click events:
+ if( this.useNativePlayerControls() ){
+ this.getInterface().css('pointer-events', 'auto');
+ }
+
+ // iPhone in WebKitPlaysInline mode does not support clickable overlays as of iOS 5.0
+ if( mw.config.get( 'EmbedPlayer.WebKitPlaysInline') && mw.isIphone() ) {
+ return ;
+ }
+ if( this.getInterface().find( '.play-btn-large' ).length ){
+ this.getInterface().find( '.play-btn-large' ).show();
+ } else {
+ this.getVideoHolder().append(
+ this.controlBuilder.getComponent( 'playButtonLarge' )
+ );
+ }
+ },
+
+ getVideoHolder: function() {
+ return this.getInterface().find('.videoHolder');
+ },
+
+ /**
+ * Abstract method,
+ * Get native player html ( should be set by mw.EmbedPlayerNative )
+ */
+ getNativePlayerHtml: function(){
+ return $('<div />' )
+ .css( 'width', this.getWidth() )
+ .html( 'Error: Trying to get native html5 player without native support for codec' );
+ },
+
+ /**
+ * Should be set via native embed support
+ */
+ applyMediaElementBindings: function(){
+ mw.log("Warning applyMediaElementBindings should be implemented by player interface" );
+ return ;
+ },
+
+ /**
+ * Gets code to embed the player remotely for "share" this player links
+ */
+ getSharingEmbedCode: function() {
+ switch( mw.config.get( 'EmbedPlayer.ShareEmbedMode' ) ){
+ case 'iframe':
+ return this.getShareIframeObject();
+ break;
+ case 'videojs':
+ return this.getShareEmbedVideoJs();
+ break;
+ }
+ },
+
+ /**
+ * Gets code to embed the player in a wiki
+ */
+ getWikiEmbedCode: function() {
+ if( this.apiTitleKey) {
+ return '[[File:' + this.apiTitleKey + ']]';
+ } else {
+ return false;
+ }
+ },
+
+ /**
+ * Get the iframe share code:
+ */
+ getShareIframeObject: function(){
+ // TODO move to getShareIframeSrc
+ var iframeUrl = this.getIframeSourceUrl();
+
+ // Set up embedFrame src path
+ var embedCode = '&lt;iframe src=&quot;' + mw.html.escape( iframeUrl ) + '&quot; ';
+
+ // Set width / height of embed object
+ embedCode += 'width=&quot;' + this.getPlayerWidth() +'&quot; ';
+ embedCode += 'height=&quot;' + this.getPlayerHeight() + '&quot; ';
+ embedCode += 'frameborder=&quot;0&quot; ';
+ embedCode += 'webkitAllowFullScreen mozallowfullscreen allowFullScreen';
+
+ // Close up the embedCode tag:
+ embedCode+='&gt;&lt/iframe&gt;';
+
+ // Return the embed code
+ return embedCode;
+ },
+ /**
+ * Gets the iframe source url
+ */
+ getIframeSourceUrl: function(){
+ var iframeUrl = false;
+ this.triggerHelper( 'getShareIframeSrc', [ function( localIframeSrc ){
+ if( iframeUrl){
+ mw.log("Error multiple modules binding getShareIframeSrc" );
+ }
+ iframeUrl = localIframeSrc;
+ }, this.id ]);
+ if( iframeUrl ){
+ return iframeUrl;
+ }
+ // old style embed:
+ var iframeUrl = mw.getMwEmbedPath() + 'mwEmbedFrame.php?';
+ var params = {'src[]' : []};
+
+ // Output all the video sources:
+ for( var i=0; i < this.mediaElement.sources.length; i++ ){
+ var source = this.mediaElement.sources[i];
+ if( source.src ) {
+ params['src[]'].push(mw.absoluteUrl( source.src ));
+ }
+ }
+ // Output the poster attr
+ if( this.poster ){
+ params.poster = this.poster;
+ }
+
+ // Set the skin if set to something other than default
+ if( this.skinName ){
+ params.skin = this.skinName;
+ }
+
+ if( this.duration ) {
+ params.durationHint = parseFloat( this.duration );
+ }
+ iframeUrl += $.param( params );
+ return iframeUrl;
+ },
+ /**
+ * Get the share embed Video tag html to share the embed code.
+ */
+ getShareEmbedVideoJs: function(){
+
+ // Set the embed tag type:
+ var embedtag = ( this.isAudio() )? 'audio': 'video';
+
+ // Set up the mwEmbed js include:
+ var embedCode = '&lt;script type=&quot;text/javascript&quot; ' +
+ 'src=&quot;' +
+ mw.html.escape(
+ mw.absoluteUrl(
+ mw.getMwEmbedSrc()
+ )
+ ) + '&quot;&gt;&lt;/script&gt' +
+ '&lt;' + embedtag + ' ';
+
+ if( this.poster ) {
+ embedCode += 'poster=&quot;' +
+ mw.html.escape( mw.absoluteUrl( this.poster ) ) +
+ '&quot; ';
+ }
+
+ // Set the skin if set to something other than default
+ if( this.skinName ){
+ embedCode += 'class=&quot;' +
+ mw.html.escape( this.skinName ) +
+ '&quot; ';
+ }
+
+ if( this.duration ) {
+ embedCode +='durationHint=&quot;' + parseFloat( this.duration ) + '&quot; ';
+ }
+
+ if( this.width || this.height ){
+ embedCode += 'style=&quot;';
+ embedCode += ( this.width )? 'width:' + this.width +'px;': '';
+ embedCode += ( this.height )? 'height:' + this.height +'px;': '';
+ embedCode += '&quot; ';
+ }
+
+ // Close the video attr
+ embedCode += '&gt;';
+
+ // Output all the video sources:
+ for( var i=0; i < this.mediaElement.sources.length; i++ ){
+ var source = this.mediaElement.sources[i];
+ if( source.src ) {
+ embedCode +='&lt;source src=&quot;' +
+ mw.absoluteUrl( source.src ) +
+ '&quot; &gt;&lt;/source&gt;';
+ }
+ }
+ // Close the video tag
+ embedCode += '&lt;/video&gt;';
+
+ return embedCode;
+ },
+
+
+
+ /**
+ * Base Embed Controls
+ */
+
+ /**
+ * The Play Action
+ *
+ * Handles play requests, updates relevant states:
+ * seeking =false
+ * paused =false
+ *
+ * Triggers the play event
+ *
+ * Updates pause button Starts the "monitor"
+ */
+ firstPlay : true,
+ preSequence: false,
+ inPreSequence: false,
+ replayEventCount : 0,
+ play: function() {
+ var _this = this;
+ var $this = $( this );
+ // Store the absolute play time ( to track native events that should not invoke interface updates )
+ mw.log( "EmbedPlayer:: play: " + this._propagateEvents + ' poster: ' + this.stopped );
+
+ this.absoluteStartPlayTime = new Date().getTime();
+
+ // Check if thumbnail is being displayed and embed html
+ if ( _this.isStopped() && (_this.preSequence == false || (_this.sequenceProxy && _this.sequenceProxy.isInSequence == false) )) {
+ if ( !_this.selectedPlayer ) {
+ _this.showPlayerError();
+ return false;
+ } else {
+ _this.embedPlayerHTML();
+ }
+ }
+ // playing, exit stopped state:
+ _this.stopped = false;
+
+ if( !this.preSequence ) {
+ this.preSequence = true;
+ mw.log( "EmbedPlayer:: trigger preSequence " );
+ this.triggerHelper( 'preSequence' );
+ this.playInterfaceUpdate();
+ // if we entered into ad loading return
+ if( _this.sequenceProxy && _this.sequenceProxy.isInSequence ){
+ mw.log("EmbedPlayer:: isInSequence, do NOT play content");
+ return false;
+ }
+ }
+
+ // We need first play event for analytics purpose
+ if( this.firstPlay && this._propagateEvents) {
+ this.firstPlay = false;
+ this.triggerHelper( 'firstPlay', [ _this.id ] );
+ }
+
+ if( this.paused === true ){
+ this.paused = false;
+ // Check if we should Trigger the play event
+ mw.log("EmbedPlayer:: trigger play event::" + !this.paused + ' events:' + this._propagateEvents );
+ // trigger the actual play event:
+ if( this._propagateEvents ) {
+ this.triggerHelper( 'onplay' );
+ }
+ }
+
+ // If we previously finished playing this clip run the "replay hook"
+ if( this.donePlayingCount > 0 && !this.paused && this._propagateEvents ) {
+ this.replayEventCount++;
+ // Trigger end done on replay
+ this.triggeredEndDone = false;
+ if( this.replayEventCount <= this.donePlayingCount){
+ mw.log("EmbedPlayer::play> trigger replayEvent");
+ this.triggerHelper( 'replayEvent' );
+ }
+ }
+
+ // If we have start time defined, start playing from that point
+ if( this.currentTime < this.startTime ) {
+ $this.bind('playing.startTime', function(){
+ $this.unbind('playing.startTime');
+ if( !mw.isIOS() ){
+ _this.setCurrentTime( _this.startTime );
+ _this.startTime = 0;
+ } else {
+ // iPad seeking on syncronus play event sucks
+ setTimeout( function(){
+ _this.setCurrentTime( _this.startTime, function(){
+ _this.play();
+ });
+ _this.startTime = 0;
+ }, 500 )
+ }
+ _this.startTime = 0;
+ });
+ }
+
+ this.playInterfaceUpdate();
+ // If play controls are enabled continue to video content element playback:
+ if( _this._playContorls ){
+ return true;
+ } else {
+ // return false ( Mock play event, or handled elsewhere )
+ return false;
+ }
+ },
+ /**
+ * Update the player inteface for playback
+ * TODO move to controlBuilder
+ */
+ playInterfaceUpdate: function(){
+ var _this = this;
+ mw.log( 'EmbedPlayer:: playInterfaceUpdate' );
+ // Hide any overlay:
+ if( this.controlBuilder ){
+ this.controlBuilder.closeMenuOverlay();
+ }
+ // Hide any buttons or errors if present:
+ this.getInterface().find( '.error' ).remove();
+ this.hideLargePlayBtn();
+
+ this.getInterface().find('.play-btn span')
+ .removeClass( 'ui-icon-play' )
+ .addClass( 'ui-icon-pause' );
+
+ this.hideSpinnerOncePlaying();
+
+ this.getInterface().find( '.play-btn' )
+ .unbind('click')
+ .click( function( ) {
+ if( _this._playContorls ){
+ _this.pause();
+ }
+ } )
+ .attr( 'title', mw.msg( 'mwe-embedplayer-pause_clip' ) );
+ },
+ /**
+ * Pause player, and display a loading animation
+ * @return
+ */
+ pauseLoading: function(){
+ this.pause();
+ this.addPlayerSpinner();
+ this.isPauseLoading = true;
+ },
+ /**
+ * Adds a loading spinner to the player.
+ */
+ addPlayerSpinner: function(){
+ var sId = 'loadingSpinner_' + this.id;
+ // remove any old spinner
+ $( '#' + sId ).remove();
+ // hide the play btn if present
+ this.hideLargePlayBtn();
+ // re add an absolute positioned spinner:
+ $( this ).show().getAbsoluteOverlaySpinner()
+ .attr( 'id', sId );
+ },
+ hideSpinner: function(){
+ // remove the spinner
+ $( '#loadingSpinner_' + this.id + ',.loadingSpinner' ).remove();
+ },
+ /**
+ * Hides the loading spinner
+ */
+ hideSpinnerAndPlayBtn: function(){
+ this.isPauseLoading = false;
+ this.hideSpinner();
+ // hide the play btn
+ this.hideLargePlayBtn();
+ },
+ /**
+ * Hides the loading spinner once playing.
+ */
+ hideSpinnerOncePlaying: function(){
+ this._checkHideSpinner = true;
+ },
+ /**
+ * Base embed pause Updates the play/pause button state.
+ *
+ * There is no general way to pause the video must be overwritten by embed
+ * object to support this functionality.
+ *
+ * @param {Boolean} if the event was triggered by user action or propagated by js.
+ */
+ pause: function() {
+ var _this = this;
+ // Trigger the pause event if not already paused and using native controls:
+ if( this.paused === false ){
+ this.paused = true;
+ if( this._propagateEvents ){
+ mw.log( 'EmbedPlayer:trigger pause:' + this.paused );
+ // we only trigger "onpause" to avoid event propagation to the native object method
+ // i.e in jQuery ( this ).trigger('pause') also calls: this.pause();
+ $( this ).trigger( 'onpause' );
+ }
+ }
+ _this.pauseInterfaceUpdate();
+ },
+ /**
+ * Sets the player interface to paused mode.
+ */
+ pauseInterfaceUpdate: function(){
+ var _this =this;
+ mw.log("EmbedPlayer::pauseInterfaceUpdate");
+ // Update the ctrl "paused state"
+ this.getInterface().find('.play-btn span' )
+ .removeClass( 'ui-icon-pause' )
+ .addClass( 'ui-icon-play' );
+
+ this.getInterface().find( '.play-btn' )
+ .unbind('click')
+ .click( function() {
+ if( _this._playContorls ){
+ _this.play();
+ }
+ } )
+ .attr( 'title', mw.msg( 'mwe-embedplayer-play_clip' ) );
+ },
+ /**
+ * Maps the html5 load request. There is no general way to "load" clips so
+ * underling plugin-player libs should override.
+ */
+ load: function() {
+ // should be done by child (no base way to pre-buffer video)
+ mw.log( 'Waring:: the load method should be overided by player interface' );
+ },
+
+
+ /**
+ * Base embed stop
+ *
+ * Updates the player to the stop state.
+ *
+ * Shows Thumbnail
+ * Resets Buffer
+ * Resets Playhead slider
+ * Resets Status
+ *
+ * Trigger the "doStop" event
+ */
+ stop: function() {
+ var _this = this;
+ mw.log( 'EmbedPlayer::stop:' + this.id );
+ // update the player to stopped state:
+ this.stopped = true;
+
+ // Rest the prequecne flag:
+ this.preSequence = false;
+
+ // Trigger the stop event:
+ $( this ).trigger( 'doStop' );
+
+ // no longer seeking:
+ this.didSeekJump = false;
+
+ // Reset current time and prev time and seek offset
+ this.currentTime = this.previousTime = this.serverSeekTime = 0;
+
+ this.stopMonitor();
+
+ // pause playback ( if playing )
+ if( !this.paused ){
+ this.pause();
+ }
+ // Restore the play button ( if not native controls or is android )
+ if( this.useLargePlayBtn() ){
+ this.addLargePlayBtn();
+ this.pauseInterfaceUpdate();
+ }
+
+ // Native player controls:
+ if( !this.isPersistentNativePlayer() ){
+ // Rewrite the html to thumbnail disp
+ this.showThumbnail();
+ this.bufferedPercent = 0; // reset buffer state
+ this.controlBuilder.setStatus( this.getTimeRange() );
+ }
+ // Reset the playhead
+ this.updatePlayHead( 0 );
+ // update the status:
+ this.controlBuilder.setStatus( this.getTimeRange() );
+ // reset buffer indicator:
+ this.bufferedPercent = 0;
+ this.updateBufferStatus();
+ },
+
+ /**
+ * Base Embed mute
+ *
+ * Handles interface updates for toggling mute. Plug-in / player interface
+ * must handle the actual media player action
+ */
+ toggleMute: function( userAction ) {
+ mw.log( 'EmbedPlayer::toggleMute> (old state:) ' + this.muted );
+ if ( this.muted ) {
+ this.muted = false;
+ var percent = this.preMuteVolume;
+ } else {
+ this.muted = true;
+ this.preMuteVolume = this.volume;
+ var percent = 0;
+ }
+ // Change the volume and trigger the volume change so that other plugins can listen.
+ this.setVolume( percent, true );
+ // Update the interface
+ this.setInterfaceVolume( percent );
+ // trigger the onToggleMute event
+ $( this ).trigger('onToggleMute');
+ },
+
+ /**
+ * Update volume function ( called from interface updates )
+ *
+ * @param {float}
+ * percent Percent of full volume
+ * @param {triggerChange}
+ * boolean change if the event should be triggered
+ */
+ setVolume: function( percent, triggerChange ) {
+ var _this = this;
+ // ignore NaN percent:
+ if( isNaN( percent ) ){
+ return ;
+ }
+ // Set the local volume attribute
+ this.previousVolume = this.volume;
+
+ this.volume = percent;
+
+ // Un-mute if setting positive volume
+ if( percent != 0 ){
+ this.muted = false;
+ }
+
+ // Update the playerElement volume
+ this.setPlayerElementVolume( percent );
+ //mw.log("EmbedPlayer:: setVolume:: " + percent + ' trigger volumeChanged: ' + triggerChange );
+ if( triggerChange ){
+ $( _this ).trigger('volumeChanged', percent );
+ }
+ },
+
+ /**
+ * Updates the interface volume
+ *
+ * TODO should move to controlBuilder
+ *
+ * @param {float}
+ * percent Percentage volume to update interface
+ */
+ setInterfaceVolume: function( percent ) {
+ if( this.supports[ 'volumeControl' ] &&
+ this.getInterface().find( '.volume-slider' ).length
+ ) {
+ this.getInterface().find( '.volume-slider' ).slider( 'value', percent * 100 );
+ }
+ },
+
+ /**
+ * Abstract method Update volume Method must be override by plug-in / player interface
+ *
+ * @param {float}
+ * percent Percentage volume to update
+ */
+ setPlayerElementVolume: function( percent ) {
+ mw.log('Error player does not support volume adjustment' );
+ },
+
+ /**
+ * Abstract method get volume Method must be override by plug-in / player interface
+ * (if player does not override we return the abstract player value )
+ */
+ getPlayerElementVolume: function(){
+ // mw.log(' error player does not support getting volume property' );
+ return this.volume;
+ },
+
+ /**
+ * Abstract method get volume muted property must be overwritten by plug-in /
+ * player interface (if player does not override we return the abstract
+ * player value )
+ */
+ getPlayerElementMuted: function(){
+ // mw.log(' error player does not support getting mute property' );
+ return this.muted;
+ },
+
+ /**
+ * Passes a fullscreen request to the controlBuilder interface
+ */
+ fullscreen: function() {
+ this.controlBuilder.toggleFullscreen();
+ },
+
+ /**
+ * Abstract method to be run post embedding the player Generally should be
+ * overwritten by the plug-in / player
+ */
+ postEmbedActions:function() {
+ return ;
+ },
+
+ /**
+ * Checks the player state based on thumbnail display & paused state
+ *
+ * @return {Boolean} true if playing false if not playing
+ */
+ isPlaying : function() {
+ if ( this.stopped ) {
+ // in stopped state
+ return false;
+ } else if ( this.paused ) {
+ // paused state
+ return false;
+ } else {
+ return true;
+ }
+ },
+
+ /**
+ * Get Stopped state
+ *
+ * @return {Boolean} true if stopped false if playing
+ */
+ isStopped: function() {
+ return this.stopped;
+ },
+ /**
+ * Stop the play state monitor
+ */
+ stopMonitor: function(){
+ clearInterval( this.monitorInterval );
+ this.monitorInterval = 0;
+ },
+ /**
+ * Start the play state monitor
+ */
+ startMonitor: function(){
+ this.monitor();
+ },
+
+ /**
+ * Monitor playback and update interface components. underling player classes
+ * are responsible for updating currentTime
+ */
+ monitor: function() {
+ var _this = this;
+
+ // Check for current time update outside of embed player
+ _this.syncCurrentTime();
+
+ // mw.log( "monitor:: " + this.currentTime + ' propagateEvents: ' + _this._propagateEvents );
+
+ // update player status
+ _this.updatePlayheadStatus();
+
+ // Keep volume proprties set outside of the embed player in sync
+ _this.syncVolume();
+
+ // Make sure the monitor continues to run as long as the video is not stoped
+ _this.syncMonitor()
+
+ if( _this._propagateEvents ){
+
+ // mw.log('trigger:monitor:: ' + this.currentTime );
+ $( _this ).trigger( 'monitorEvent', [ _this.id ] );
+
+ // Trigger the "progress" event per HTML5 api support
+ if( _this.progressEventData ) {
+ $( _this ).trigger( 'progress', _this.progressEventData );
+ }
+ }
+ },
+ /**
+ * Sync the monitor function
+ */
+ syncMonitor: function(){
+ var _this = this;
+ // Call monitor at this.monitorRate interval.
+ // ( use setInterval to avoid stacking monitor requests )
+ if( ! this.isStopped() ) {
+ if( !this.monitorInterval ){
+ this.monitorInterval = setInterval( function(){
+ if( _this.monitor )
+ _this.monitor();
+ }, this.monitorRate );
+ }
+ } else {
+ // If stopped "stop" monitor:
+ this.stopMonitor();
+ }
+ },
+
+ /**
+ * Sync the video volume
+ */
+ syncVolume: function(){
+ var _this = this;
+ // Check if volume was set outside of embed player function
+ // mw.log( ' this.volume: ' + _this.volume + ' prev Volume:: ' + _this.previousVolume );
+ if( Math.round( _this.volume * 100 ) != Math.round( _this.previousVolume * 100 ) ) {
+ _this.setInterfaceVolume( _this.volume );
+ }
+ // Update the previous volume
+ _this.previousVolume = _this.volume;
+
+ // Update the volume from the player element
+ _this.volume = this.getPlayerElementVolume();
+
+ // update the mute state from the player element
+ if( _this.muted != _this.getPlayerElementMuted() && ! _this.isStopped() ){
+ mw.log( "EmbedPlayer::syncVolume: muted does not mach embed player" );
+ _this.toggleMute();
+ // Make sure they match:
+ _this.muted = _this.getPlayerElementMuted();
+ }
+ },
+
+ /**
+ * Checks if the currentTime was updated outside of the getPlayerElementTime function
+ */
+ syncCurrentTime: function(){
+ var _this = this;
+
+ // Hide the spinner once we have time update:
+ if( _this._checkHideSpinner && _this.currentTime != _this.getPlayerElementTime() ){
+ _this._checkHideSpinner = false;
+ _this.hideSpinnerAndPlayBtn();
+
+ if( _this.isPersistantPlayBtn() ){
+ // add the play button likely iphone or native player that needs the play button on
+ // non-event "exit native html5 player"
+ _this.addLargePlayBtn();
+ } else{
+ // also hide the play button ( in case it was there somehow )
+ _this.hideLargePlayBtn();
+ }
+ }
+
+ // Check if a javascript currentTime change based seek has occurred
+ if( parseInt( _this.previousTime ) != parseInt( _this.currentTime ) &&
+ !this.userSlide &&
+ !this.seeking &&
+ !this.isStopped()
+ ){
+ // If the time has been updated and is in range issue a seek
+ if( _this.getDuration() && _this.currentTime <= _this.getDuration() ){
+ var seekPercent = _this.currentTime / _this.getDuration();
+ mw.log("EmbedPlayer::syncCurrentTime::" + _this.previousTime + ' != ' +
+ _this.currentTime + " javascript based currentTime update to " +
+ seekPercent + ' == ' + _this.currentTime );
+ _this.previousTime = _this.currentTime;
+ this.seek( seekPercent );
+ }
+ }
+
+ // Update currentTime via embedPlayer
+ _this.currentTime = _this.getPlayerElementTime();
+
+ // Update any offsets from server seek
+ if( _this.serverSeekTime && _this.supportsURLTimeEncoding() ){
+ _this.currentTime = parseInt( _this.serverSeekTime ) + parseInt( _this.getPlayerElementTime() );
+ }
+
+ // Update the previousTime ( so we can know if the user-javascript changed currentTime )
+ _this.previousTime = _this.currentTime;
+
+ // Check for a pauseTime to stop playback in temporal media fragments
+ if( _this.pauseTime && _this.currentTime > _this.pauseTime ){
+ _this.pause();
+ _this.pauseTime = null;
+ }
+ },
+ /**
+ * Updates the player time and playhead position based on currentTime
+ */
+ updatePlayheadStatus: function(){
+ var _this = this;
+ if ( this.currentTime >= 0 && this.duration ) {
+ if ( !this.userSlide && !this.seeking ) {
+ if ( parseInt( this.startOffset ) != 0 ) {
+ this.updatePlayHead( ( this.currentTime - this.startOffset ) / this.duration );
+ var et = ( this.controlBuilder.longTimeDisp ) ? '/' + mw.seconds2npt( parseFloat( this.startOffset ) + parseFloat( this.duration ) ) : '';
+ this.controlBuilder.setStatus( mw.seconds2npt( this.currentTime ) + et );
+ } else {
+ // use raw currentTIme for playhead updates
+ var ct = ( this.getPlayerElement() ) ? this.getPlayerElement().currentTime || this.currentTime: this.currentTime;
+ this.updatePlayHead( ct / this.duration );
+ // Only include the end time if longTimeDisp is enabled:
+ var et = ( this.controlBuilder.longTimeDisp ) ? '/' + mw.seconds2npt( this.duration ) : '';
+ this.controlBuilder.setStatus( mw.seconds2npt( this.currentTime ) + et );
+ }
+ }
+ // Check if we are "done"
+ var endPresentationTime = ( this.startOffset ) ? ( this.startOffset + this.duration ) : this.duration;
+ if ( this.currentTime >= endPresentationTime && !this.isStopped() ) {
+ mw.log( "EmbedPlayer::updatePlayheadStatus > should run clip done :: " + this.currentTime + ' > ' + endPresentationTime );
+ this.onClipDone();
+ }
+ } else {
+ // Media lacks duration just show end time
+ if ( this.isStopped() ) {
+ this.controlBuilder.setStatus( this.getTimeRange() );
+ } else if ( this.paused ) {
+ this.controlBuilder.setStatus( mw.msg( 'mwe-embedplayer-paused' ) );
+ } else if ( this.isPlaying() ) {
+ if ( this.currentTime && ! this.duration )
+ this.controlBuilder.setStatus( mw.seconds2npt( this.currentTime ) + ' /' );
+ else
+ this.controlBuilder.setStatus( " - - - " );
+ } else {
+ this.controlBuilder.setStatus( this.getTimeRange() );
+ }
+ }
+ },
+
+ /**
+ * Abstract getPlayerElementTime function
+ */
+ getPlayerElementTime: function(){
+ mw.log("Error: getPlayerElementTime should be implemented by embed library");
+ },
+
+ /**
+ * Abstract getPlayerElementTime function
+ */
+ getPlayerElement: function(){
+ mw.log("Error: getPlayerElement should be implemented by embed library, or you may be calling this event too soon");
+ },
+
+ /**
+ * Update the Buffer status based on the local bufferedPercent var
+ */
+ updateBufferStatus: function() {
+ // Get the buffer target based for playlist vs clip
+ var $buffer = this.getInterface().find( '.mw_buffer' );
+ // Update the buffer progress bar (if available )
+ if ( this.bufferedPercent != 0 ) {
+ // mw.log('Update buffer css: ' + ( this.bufferedPercent * 100 ) +
+ // '% ' + $buffer.length );
+ if ( this.bufferedPercent > 1 ){
+ this.bufferedPercent = 1;
+ }
+ $buffer.css({
+ "width" : ( this.bufferedPercent * 100 ) + '%'
+ });
+ $( this ).trigger( 'updateBufferPercent', this.bufferedPercent );
+ } else {
+ $buffer.css( "width", '0px' );
+ }
+
+ // if we have not already run the buffer start hook
+ if( this.bufferedPercent > 0 && !this.bufferStartFlag ) {
+ this.bufferStartFlag = true;
+ mw.log("EmbedPlayer::bufferStart");
+ $( this ).trigger( 'bufferStartEvent' );
+ }
+
+ // if we have not already run the buffer end hook
+ if( this.bufferedPercent == 1 && !this.bufferEndFlag){
+ this.bufferEndFlag = true;
+ $( this ).trigger( 'bufferEndEvent' );
+ }
+ },
+
+ /**
+ * Update the player playhead
+ *
+ * @param {Float}
+ * perc Value between 0 and 1 for position of playhead
+ */
+ updatePlayHead: function( perc ) {
+ //mw.log( 'EmbedPlayer: updatePlayHead: '+ perc);
+ if( this.getInterface() ){
+ var $playHead = this.getInterface().find( '.play_head' );
+ if ( !this.useNativePlayerControls() && $playHead.length != 0 ) {
+ var val = parseInt( perc * 1000 );
+ $playHead.slider( 'value', val );
+ }
+ }
+ $( this ).trigger('updatePlayHeadPercent', perc);
+ },
+
+
+ /**
+ * Helper Functions for selected source
+ */
+
+ /**
+ * Get the current selected media source or first source
+ *
+ * @param {Number}
+ * Requested time in seconds to be passed to the server if the
+ * server supports supportsURLTimeEncoding
+ * @return src url
+ */
+ getSrc: function( serverSeekTime ) {
+ if( serverSeekTime ){
+ this.serverSeekTime = serverSeekTime;
+ }
+ if( this.currentTime && !this.serverSeekTime){
+ this.serverSeekTime = this.currentTime;
+ }
+
+ // No media element we can't return src
+ if( !this.mediaElement ){
+ return false;
+ }
+
+ // If no source selected auto select the source:
+ if( !this.mediaElement.selectedSource ){
+ this.mediaElement.autoSelectSource();
+ };
+
+ // Return selected source:
+ if( this.mediaElement.selectedSource ){
+ // See if we should pass the requested time to the source generator:
+ if( this.supportsURLTimeEncoding() ){
+ // get the first source:
+ return this.mediaElement.selectedSource.getSrc( this.serverSeekTime );
+ } else {
+ return this.mediaElement.selectedSource.getSrc();
+ }
+ }
+ // No selected source return false:
+ return false;
+ },
+ /**
+ * Return the currently selected source
+ */
+ getSource: function(){
+ // update the current selected source:
+ this.mediaElement.autoSelectSource();
+ return this.mediaElement.selectedSource;
+ },
+ /**
+ * Static helper to get media sources from a set of videoFiles
+ *
+ * Uses mediaElement select logic to chose a
+ * video file among a set of sources
+ *
+ * @param videoFiles
+ * @return
+ */
+ getCompatibleSource: function( videoFiles ){
+ // Convert videoFiles json into HTML element:
+ // TODO mediaElement should probably accept JSON
+ var $media = $('<video />');
+ $.each(videoFiles, function( inx, source){
+ $media.append( $('<source />').attr({
+ 'src' : source.src,
+ 'type' : source.type
+ }));
+ mw.log("EmbedPlayer::getCompatibleSource: add " + source.src + ' of type:' + source.type );
+ });
+ var myMediaElement = new mw.MediaElement( $media[0] );
+ var source = myMediaElement.autoSelectSource();
+ if( source ){
+ mw.log("EmbedPlayer::getCompatibleSource: " + source.getSrc());
+ return source;
+ }
+ mw.log("Error:: could not find compatible source");
+ return false;
+ },
+ /**
+ * If the selected src supports URL time encoding
+ *
+ * @return {Boolean} true if the src supports url time requests false if the
+ * src does not support url time requests
+ */
+ supportsURLTimeEncoding: function() {
+ var timeUrls = mw.config.get('EmbedPlayer.EnableURLTimeEncoding') ;
+ if( timeUrls == 'none' ){
+ return false;
+ } else if( timeUrls == 'always' ){
+ return this.mediaElement.selectedSource.URLTimeEncoding;
+ } else if( timeUrls == 'flash' ){
+ if( this.mediaElement.selectedSource && this.mediaElement.selectedSource.URLTimeEncoding){
+ // see if the current selected player is flash:
+ return ( this.instanceOf == 'Kplayer' );
+ }
+ } else {
+ mw.log("Error:: invalid config value for EmbedPlayer.EnableURLTimeEncoding:: " + mw.config.get('EmbedPlayer.EnableURLTimeEncoding') );
+ }
+ return false;
+ }
+ };
+
+})( mw, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerGeneric.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerGeneric.js
new file mode 100644
index 00000000..fc8dec55
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerGeneric.js
@@ -0,0 +1,36 @@
+/*
+* Simple embed object for unknown application/ogg plugin
+*/
+
+( function( mw, $ ) { "use strict";
+
+mw.EmbedPlayerGeneric = {
+ // List of supported features of the generic plugin
+ supports: {
+ 'playHead':false,
+ 'pause':false,
+ 'stop':true,
+ 'fullscreen':false,
+ 'timeDisplay':false,
+ 'volumeControl':false
+ },
+
+ // Instance name:
+ instanceOf:'Generic',
+
+ /*
+ * Generic embed html
+ *
+ * @return {String}
+ * embed code for generic ogg plugin
+ */
+ embedPlayerHTML: function() {
+ $( this ).html(
+ '<object type="application/ogg" ' +
+ 'width="' + this.getWidth() + '" height="' + this.getHeight() + '" ' +
+ 'data="' + this.getSrc( this.seekTimeSec ) + '"></object>'
+ );
+ }
+};
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerIEWebMPrompt.css b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerIEWebMPrompt.css
new file mode 100644
index 00000000..9cf7b490
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerIEWebMPrompt.css
@@ -0,0 +1,18 @@
+.mwEmbedPlayer .iewebm-prompt {
+ position: absolute;
+ top: 100px;
+ bottom: 60px;
+ left: 20px;
+ right: 20px;
+ border-radius: 20px;
+ background-color: rgba(255, 255, 255, 0.75);
+
+ width: auto !important;
+ height: auto !important;
+
+ padding: 20px;
+}
+
+.mwEmbedPlayer .iewebm-prompt div {
+ color: black;
+} \ No newline at end of file
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerIEWebMPrompt.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerIEWebMPrompt.js
new file mode 100644
index 00000000..00694f81
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerIEWebMPrompt.js
@@ -0,0 +1,46 @@
+/**
+ * Show a prompt to install WebM plugin for IE 9+
+ */
+
+( function( mw, $ ) { "use strict";
+
+mw.EmbedPlayerIEWebMPrompt = {
+ // List of supported features (or lack thereof)
+ supports: {
+ 'playHead':false, /* The seek slider */
+ 'pause':true, /* Play pause button in control bar */
+ 'stop':true, /* Does this actually do anything?? */
+ 'fullscreen':false,
+ 'timeDisplay':false,
+ 'volumeControl':false
+ },
+
+ // Instance name:
+ instanceOf:'IEWebMPrompt',
+
+ /*
+ * Embed this "fake" player
+ *
+ * @return {String}
+ * embed code to link to WebM plugin download
+ */
+ embedPlayerHTML: function() {
+ var pluginUrl = 'https://tools.google.com/dlpage/webmmf/',
+ $link;
+
+ // Overlay the video placeholder with download plugin link.
+ $link = $( '<a></a>' )
+ .attr( 'href', pluginUrl )
+ .attr( 'target', '_blank' )
+ .text( mw.msg( 'mwe-embedplayer-iewebmprompt-linktext' ) );
+ $( this ).append( $( '<div class="iewebm-prompt"></div>' )
+ .width( this.getWidth() )
+ .height( this.getHeight() )
+ .append( $( '<div></div>' ).text( mw.msg( 'mwe-embedplayer-iewebmprompt-intro' ) ) )
+ .append( $link )
+ .append( $( '<div></div>' ).text( mw.msg( 'mwe-embedplayer-iewebmprompt-outro' ) ) )
+ );
+ }
+};
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerImageOverlay.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerImageOverlay.js
new file mode 100644
index 00000000..f6271621
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerImageOverlay.js
@@ -0,0 +1,307 @@
+/**
+ * Used to Overlay images and take over player controls
+ *
+ * extends EmbedPlayerNative object image overlay support
+ */
+
+mw.EmbedPlayerImageOverlay = {
+
+ instanceOf: 'ImageOverlay',
+
+ // If the player is "ready to play"
+ playerReady : true,
+
+ // Pause time used to track player time between pauses
+ lastPauseTime: 0,
+
+ // currentTime updated via internal clockStartTime var
+ currentTime:0,
+
+ // StartOffset support seeking into the virtual player
+ startOffset:0,
+
+ // The local clock used to emulate playback time
+ clockStartTime: 0,
+
+ /**
+ * Build the player interface:
+ */
+ init: function(){
+ // Check if features are already updated:
+ if( this['native_instaceOf'] == 'Native' ){
+ return ;
+ }
+ // inherit mw.EmbedPlayerNative (
+ for( var i in mw.EmbedPlayerNative ){
+ if( typeof mw.EmbedPlayerImageOverlay[ i ] != 'undefined' ){
+ this['native_' + i ] = mw.EmbedPlayerNative[i];
+ } else {
+ this[ i ] = mw.EmbedPlayerNative[i];
+ }
+ }
+ },
+
+ /**
+ * When on playback method switch remove imageOverlay
+ * @param {function} callback
+ */
+ updatePlaybackInterface: function( callback ){
+ mw.log( 'EmbedPlayerImageOverlay:: updatePlaybackInterface remove imageOverlay: ' + $(this).siblings( '.imageOverlay' ).length );
+ // Reset lastPauseTime
+ this.lastPauseTime = 0;
+ // Clear imageOverlay sibling:
+ $( this ).find( '.imageOverlay' ).remove();
+ // Restore the video element on screen position:
+ $( this.getPlayerElement() ).css('left', 0 );
+ // Call normal parent updatePlaybackInterface
+ this.parent_updatePlaybackInterface( callback );
+ },
+
+ /**
+ * The method called to "show the player"
+ * For image overlay we want to:
+ * Set black video urls for player source
+ * Add an image overlay
+ */
+ updatePosterHTML: function(){
+ var vid = this.getPlayerElement();
+ $( vid ).empty()
+
+ // Provide modules the opportunity to supply black sources ( for registering event click )
+ // this is need for iPad to capture the play click to auto continue after "playing an image"
+ // ( iOS requires a user gesture to initiate video playback )
+
+ // We don't just include the sources as part of core config, since it would result in
+ // a possible privacy leakage i.e hitting the kaltura servers when playing images.
+ this.triggerHelper( 'AddEmptyBlackSources', [ vid ] );
+
+ // embed the image:
+ this.embedPlayerHTML();
+
+ // add the play btn:
+ this.addLargePlayBtn();
+ },
+
+ /**
+ * Play function starts the video playback
+ */
+ play: function() {
+ mw.log( 'EmbedPlayerImageOverlay::play> lastPauseTime:' + this.lastPauseTime + ' ct: ' + this.currentTime );
+ this.applyIntrinsicAspect();
+ // Check for image duration
+
+ // Reset playback if currentTime > duration:
+ if( this.currentTime > this.getDuration() ) {
+ this.currentTime = this.pauseTime = 0;
+ }
+
+ // No longer in a stopped state:
+ this.stopped = false;
+
+ // Capture the play event on the native player: ( should just be black silent sources )
+ // This is needed so that if a playlist starts with image, it can continue to play the
+ // subsequent video without on iOS without requiring another click.
+ if( ! $( this ).data('previousInstanceOf') ){
+ // Update the previousInstanceOf flag:
+ $( this ).data('previousInstanceOf', this.instanceOf );
+ var vid = this.getPlayerElement();
+ // populate the video with black video sources:
+ this.triggerHelper( 'AddEmptyBlackSources', [ vid ] );
+ // run play:
+ vid.play();
+ // inline pause
+ setTimeout(function(){
+ vid.pause();
+ },0);
+ // add another pause request after 500 ms ( iOS sometimes does not listen the first time )
+ setTimeout(function(){
+ vid.pause();
+ }, mw.config.get( 'EmbedPlayer.MonitorRate' ) * 2 );
+ }
+ // call the parent play ( to update interface and call respective triggers )
+ this.parent_play();
+ // make sure we are in play interface:
+ this.playInterfaceUpdate();
+
+ this.clockStartTime = new Date().getTime();
+ // Start up monitor:
+ this.monitor();
+ },
+ getDuration: function(){
+ if( this.duration ){
+ return this.duration;
+ }
+ if( this.imageDuration ){
+ this.duration = this.imageDuration ;
+ } else {
+ this.duration = mw.config.get( "EmbedPlayer.DefaultImageDuration" );
+ }
+ // make sure duration has type float:
+ this.duration = parseFloat( this.duration );
+ return this.duration;
+ },
+ /**
+ * Stops the playback
+ */
+ stop: function() {
+ this.currentTime = 0;
+ this.parent_stop();
+ },
+ _onpause: function(){
+ // catch the native event ( and do nothing )
+ },
+ /**
+ * Preserves the pause time across for timed playback
+ */
+ pause: function( ) {
+ this.lastPauseTime = this.currentTime;
+ mw.log( 'EmbedPlayerImageOverlay::pause, lastPauseTime: ' + this.lastPauseTime );
+ // run parent pause;
+ this.parent_pause();
+ this.stopMonitor();
+ },
+
+ monitor: function(){
+ if( this.duration == 0 ){
+ this.disablePlayControls();
+ return ;
+ }
+ $( this ).trigger( 'timeupdate' );
+
+ if ( this.currentTime >= this.duration ) {
+ $( this ).trigger( 'ended' );
+ } else {
+ // Run the parent monitor:
+ this.parent_monitor();
+ }
+ },
+ /**
+ * Seeks to a given percent and updates the lastPauseTime
+ *
+ * @param {Float} seekPercent Percentage to seek into the virtual player
+ */
+ seek: function( seekPercent ) {
+ this.lastPauseTime = seekPercent * this.getDuration();
+ this.seeking = false;
+ // start seeking:
+ $( this ).trigger( 'seeking' );
+ // Done seeking
+ $( this ).trigger( 'seeked' );
+ this.play();
+ },
+
+ /**
+ * Sets the current Time
+ *
+ * @param {Float} perc Percentage to seek into the virtual player
+ * @param {Function} callback Function called once time has been updated
+ */
+ setCurrentTime: function( time, callback ) {
+ this.lastPauseTime = time;
+ // start seeking:
+ $( this ).trigger( 'seeking' );
+ // Done seeking
+ $( this ).trigger( 'seeked' );
+ if( callback ){
+ callback();
+ }
+ },
+ /**
+ * Switch the image playback
+ */
+ playerSwitchSource: function( source, switchCallback, doneCallback ){
+ var _this = this;
+ this.selectedSource = source;
+ this.embedPlayerHTML();
+ this.applyIntrinsicAspect();
+ this.play();
+ if( switchCallback ){
+ switchCallback( this );
+ }
+ // Wait for ended event to tr
+ $( this ).bind('ended.playerSwitchSource', function(){
+ $( _this ).unbind('ended.playerSwitchSource');
+ if( doneCallback ) {
+ doneCallback( this );
+ }
+ })
+ },
+ /**
+ * Get the embed player time
+ */
+ getPlayerElementTime: function() {
+ this.currentTime = ( ( new Date().getTime() - this.clockStartTime ) / 1000 ) + this.lastPauseTime;
+ return this.currentTime;
+ },
+ /**
+ * Get the "embed" html for the html player
+ */
+ embedPlayerHTML: function() {
+ var _this = this;
+ // remove any old imageOverlay:
+ this.$interface.find('.imageOverlay').remove();
+ mw.log( 'EmbedPlayerImageOverlay :doEmbedHTML: ' + this.id );
+
+ var currentSoruceObj = this.selectedSource;
+
+ if( !currentSoruceObj ){
+ mw.log("Error:: EmbedPlayerImageOverlay:embedPlayerHTML> missing source" );
+ return ;
+ }
+ var $image =
+ $( '<img />' )
+ .css({
+ 'position': 'relative',
+ 'width': '100%',
+ 'height': '100%'
+ })
+ .attr({
+ 'src' : currentSoruceObj.getSrc()
+ })
+ .addClass( 'imageOverlay' )
+ .load( function(){
+ // reset clock time:
+ _this.clockStartTime = new Date().getTime();
+ _this.monitor();
+ })
+
+ // move the video element off screen:
+ $( this.getPlayerElement() ).css({
+ 'left': this.getWidth()+50,
+ 'position' : 'absolute'
+ });
+
+ // Add the image before the video element or before the playerInterface
+ $( this ).html( $image );
+
+ this.applyIntrinsicAspect();
+ },
+ // wrap the parent rewize player to apply intensic apsect
+ resizePlayer: function( size , animate, callback){
+ this.parent_resizePlayer( size , animate, callback );
+ this.applyIntrinsicAspect();
+ },
+ applyIntrinsicAspect: function(){
+ var $this = this.$interface;
+ // Check if a image thumbnail is present:
+ /*if( this.$interface && this.$interface.find('.imageOverlay').length ){
+ var img = this.$interface.find('.imageOverlay')[0];
+ var pHeight = $this.height();
+ // Check for intrinsic width and maintain aspect ratio
+ if( img.naturalWidth && img.naturalHeight ){
+ var pWidth = parseInt( img.naturalWidth / img.naturalHeight * pHeight);
+ if( pWidth > $this.width() ){
+ pWidth = $this.width();
+ pHeight = parseInt( img.naturalHeight / img.naturalWidth * pWidth );
+ }
+ $( img ).css({
+ 'height' : pHeight + 'px',
+ 'width': pWidth + 'px',
+ 'left': ( ( $this.width() - pWidth ) * .5 ) + 'px',
+ 'top': ( ( $this.height() - pHeight ) * .5 ) + 'px',
+ 'position' : 'absolute'
+ });
+ }
+ }*/
+ }
+}; \ No newline at end of file
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerKplayer.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerKplayer.js
new file mode 100644
index 00000000..739a7769
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerKplayer.js
@@ -0,0 +1,485 @@
+/*
+ * The "kaltura player" embedPlayer interface for fallback h.264 and flv video format support
+ */
+( function( mw, $ ) { "use strict";
+
+// Called from the kdp.swf
+window.jsInterfaceReadyFunc = function() {
+ return true;
+}
+
+mw.EmbedPlayerKplayer = {
+
+ // Instance name:
+ instanceOf : 'Kplayer',
+
+ bindPostfix: '.kPlayer',
+
+ // List of supported features:
+ supports : {
+ 'playHead' : true,
+ 'pause' : true,
+ 'stop' : true,
+ 'timeDisplay' : true,
+ 'volumeControl' : true,
+ 'overlays' : true,
+ 'fullscreen' : true
+ },
+
+ // Stores the current time as set from flash player
+ flashCurrentTime : 0,
+
+ /*
+ * Write the Embed html to the target
+ */
+ embedPlayerHTML : function() {
+ var _this = this;
+
+ mw.log("EmbedPlayerKplayer:: embed src::" + _this.getSrc());
+ var flashvars = {};
+ flashvars.autoPlay = "true";
+ flashvars.loop = "false";
+
+ var playerPath = mw.absoluteUrl( mw.getEmbedPlayerPath() + '/binPlayers/kaltura-player' );
+ flashvars.entryId = mw.absoluteUrl( _this.getSrc() );
+
+ // Use a relative url if the protocol is file://
+ if ( new mw.Uri( document.URL ).protocol == 'file' ) {
+ playerPath = mw.getRelativeMwEmbedPath() + 'modules/EmbedPlayer/binPlayers/kaltura-player';
+ flashvars.entryId = _this.getSrc();
+ }
+
+ flashvars.debugMode = "false";
+ flashvars.fileSystemMode = "true";
+ flashvars.widgetId = "_7463";
+ flashvars.partnerId = "7463";
+ flashvars.pluginDomain = "kdp3/plugins/";
+ flashvars.kml = "local";
+ flashvars.kmlPath = playerPath + '/config.xml';
+ flashvars.sourceType = "url";
+ flashvars.jsInterfaceReadyFunc = "jsInterfaceReadyFunc";
+
+ // flashvars.host = "www.kaltura.com";
+ flashvars.externalInterfaceDisabled = "false";
+ flashvars.skinPath = playerPath + '/skin.swf';
+
+ flashvars["full.skinPath"] = playerPath + '/LightDoodleskin.swf';
+ var flashVarParam = '';
+ $.each( flashvars, function( fKey, fVal ){
+ flashVarParam += '&' + fKey + '=' + encodeURIComponent( fVal );
+ } );
+
+ var kdpPath = playerPath + "/kdp3.3.5.27.swf";
+
+ mw.log( "KPlayer:: embedPlayerHTML" );
+ // remove any existing pid ( if present )
+ $( '#' + this.pid ).remove();
+
+ var orgJsReadyCallback = window.jsCallbackReady;
+ window.jsCallbackReady = function( playerId ){
+ _this.postEmbedActions();
+ window.jsCallbackReady = orgJsReadyCallback;
+ };
+ // attributes and params:
+ flashembed( $( this ).attr('id'),
+ {
+ id : this.pid,
+ src : kdpPath,
+ height : '100%',
+ width : '100%',
+ bgcolor : "#000000",
+ allowNetworking : "all",
+ version : [10,0],
+ wmode : "opaque"
+ },
+ flashvars
+ )
+ // Remove any old bindings:
+ $(_this).unbind( this.bindPostfix );
+
+ // Flash player loses its bindings once it changes sizes::
+ $(_this).bind('onOpenFullScreen' + this.bindPostfix , function() {
+ _this.postEmbedActions();
+ });
+ $(_this).bind('onCloseFullScreen' + this.bindPostfix, function() {
+ _this.postEmbedActions();
+ });
+ },
+
+ // The number of times we have tried to bind the player
+ bindTryCount : 0,
+
+ /**
+ * javascript run post player embedding
+ */
+ postEmbedActions : function() {
+ var _this = this;
+ this.getPlayerElement();
+ if ( this.playerElement && this.playerElement.addJsListener ) {
+ var bindEventMap = {
+ 'playerPaused' : 'onPause',
+ 'playerPlayed' : 'onPlay',
+ 'durationChange' : 'onDurationChange',
+ 'playerPlayEnd' : 'onClipDone',
+ 'playerUpdatePlayhead' : 'onUpdatePlayhead',
+ 'bytesTotalChange' : 'onBytesTotalChange',
+ 'bytesDownloadedChange' : 'onBytesDownloadedChange'
+ };
+
+ $.each( bindEventMap, function( bindName, localMethod ) {
+ _this.bindPlayerFunction(bindName, localMethod);
+ });
+ this.bindTryCount = 0;
+ // Start the monitor
+ this.monitor();
+ } else {
+ this.bindTryCount++;
+ // Keep trying to get the player element
+ if( this.bindTryCount > 500 ){ // 5 seconds
+ mw.log('Error:: KDP player never ready for bindings!');
+ return ;
+ }
+ setTimeout(function() {
+ _this.postEmbedActions();
+ }, 100);
+ }
+ },
+
+ /**
+ * Bind a Player Function,
+ *
+ * Build a global callback to bind to "this" player instance:
+ *
+ * @param {String}
+ * flash binding name
+ * @param {String}
+ * function callback name
+ */
+ bindPlayerFunction : function(bindName, methodName) {
+ mw.log( 'EmbedPlayerKplayer:: bindPlayerFunction:' + bindName );
+ // The kaltura kdp can only call a global function by given name
+ var gKdpCallbackName = 'kdp_' + methodName + '_cb_' + this.id.replace(/[^a-zA-Z 0-9]+/g,'');
+
+ // Create an anonymous function with local player scope
+ var createGlobalCB = function(cName, embedPlayer) {
+ window[ cName ] = function(data) {
+ // Track all events ( except for playerUpdatePlayhead )
+ if( bindName != 'playerUpdatePlayhead' ){
+ mw.log("EmbedPlayerKplayer:: event: " + bindName);
+ }
+ if ( embedPlayer._propagateEvents ) {
+ embedPlayer[methodName](data);
+ }
+ };
+ }(gKdpCallbackName, this);
+ // Remove the listener ( if it exists already )
+ this.playerElement.removeJsListener( bindName, gKdpCallbackName );
+ // Add the listener to the KDP flash player:
+ this.playerElement.addJsListener( bindName, gKdpCallbackName);
+ },
+
+ /**
+ * on Pause callback from the kaltura flash player calls parent_pause to
+ * update the interface
+ */
+ onPause : function() {
+ this.parent_pause();
+ },
+
+ /**
+ * onPlay function callback from the kaltura flash player directly call the
+ * parent_play
+ */
+ onPlay : function() {
+ this.parent_play();
+ },
+
+ onDurationChange : function(data, id) {
+ // Update the duration ( only if not in url time encoding mode:
+ if( !this.supportsURLTimeEncoding() ){
+ this.duration = data.newValue;
+ this.triggerHelper('durationchange');
+ }
+ },
+
+ /**
+ * play method calls parent_play to update the interface
+ */
+ play: function() {
+ if ( this.playerElement && this.playerElement.sendNotification ) {
+ this.playerElement.sendNotification('doPlay');
+ }
+ this.parent_play();
+ },
+
+ /**
+ * pause method calls parent_pause to update the interface
+ */
+ pause: function() {
+ if (this.playerElement && this.playerElement.sendNotification) {
+ this.playerElement.sendNotification('doPause');
+ }
+ this.parent_pause();
+ },
+ /**
+ * playerSwitchSource switches the player source working around a few bugs in browsers
+ *
+ * @param {object}
+ * source Video Source object to switch to.
+ * @param {function}
+ * switchCallback Function to call once the source has been switched
+ * @param {function}
+ * doneCallback Function to call once the clip has completed playback
+ */
+ playerSwitchSource: function( source, switchCallback, doneCallback ){
+ var _this = this;
+ var waitCount = 0;
+ var src = source.getSrc();
+ // Check if the source is already set to the target:
+ if( !src || src == this.getSrc() ){
+ if( switchCallback ){
+ switchCallback();
+ }
+ setTimeout(function(){
+ if( doneCallback )
+ doneCallback();
+ }, 100);
+ return ;
+ }
+
+ var waitForJsListen = function( callback ){
+ if( _this.getPlayerElement() && _this.getPlayerElement().addJsListener ){
+ callback();
+ } else {
+ // waited for 2 seconds fail
+ if( waitCount > 20 ){
+ mw.log( "Error: Failed to swtich player source!");
+ if( switchCallback )
+ switchCallback();
+ if( doneCallback )
+ doneCallback();
+ return;
+ }
+
+ setTimeout(function(){
+ waitCount++;
+ waitForJsListen( callback );
+ },100)
+ }
+ };
+ // wait for jslistener to be ready:
+ waitForJsListen( function(){
+ var gPlayerReady = 'kdp_switch_' + _this.id + '_switchSrcReady';
+ var gDoneName = 'kdp_switch_' + _this.id + '_switchSrcEnd';
+ var gChangeMedia = 'kdp_switch_' + _this.id + '_changeMedia';
+ window[ gPlayerReady ] = function(){
+ mw.log("EmbedPlayerKplayer:: playerSwitchSource: " + src);
+ // remove the binding as soon as possible ( we only want this event once )
+ _this.getPlayerElement().removeJsListener( 'playerReady', gPlayerReady );
+
+ _this.getPlayerElement().sendNotification("changeMedia", { 'entryId': src } );
+
+ window[ gChangeMedia ] = function (){
+ mw.log("EmbedPlayerKplayer:: Media changed: " + src);
+ if( $.isFunction( switchCallback) ){
+ switchCallback( _this );
+ switchCallback = null
+ }
+ // restore monitor:
+ _this.monitor();
+ }
+ // Add change media binding
+ _this.getPlayerElement().removeJsListener('changeMedia', gChangeMedia);
+ _this.getPlayerElement().addJsListener( 'changeMedia', gChangeMedia);
+
+ window[ gDoneName ] = function(){
+ if( $.isFunction( doneCallback ) ){
+ doneCallback();
+ doneCallback = null;
+ }
+ };
+ _this.getPlayerElement().removeJsListener('playerPlayEnd', gDoneName);
+ _this.getPlayerElement().addJsListener( 'playerPlayEnd', gDoneName);
+ };
+ // Remove then add the event:
+ _this.getPlayerElement().removeJsListener( 'playerReady', gPlayerReady );
+ _this.getPlayerElement().addJsListener( 'playerReady', gPlayerReady );
+ });
+ },
+
+ /**
+ * Issues a seek to the playerElement
+ *
+ * @param {Float}
+ * percentage Percentage of total stream length to seek to
+ */
+ seek : function(percentage) {
+ var _this = this;
+ var seekTime = percentage * this.getDuration();
+ mw.log( 'EmbedPlayerKalturaKplayer:: seek: ' + percentage + ' time:' + seekTime );
+ if (this.supportsURLTimeEncoding()) {
+
+ // Make sure we could not do a local seek instead:
+ if (!(percentage < this.bufferedPercent
+ && this.playerElement.duration && !this.didSeekJump)) {
+ // We support URLTimeEncoding call parent seek:
+ this.parent_seek( percentage );
+ return;
+ }
+ }
+ // Add a seeked callback event:
+ var seekedCallback = 'kdp_seek_' + this.id + '_' + new Date().getTime();
+ window[ seekedCallback ] = function(){
+ _this.seeking = false;
+ _this.triggerHelper( 'seeked' );
+ if( seekInterval ) {
+ clearInterval( seekInterval );
+ }
+ };
+ this.playerElement.addJsListener('playerSeekEnd', seekedCallback );
+
+ if ( this.getPlayerElement() ) {
+ // trigger the html5 event:
+ _this.triggerHelper( 'seeking' );
+
+ // Issue the seek to the flash player:
+ this.playerElement.sendNotification('doSeek', seekTime);
+
+ // Include a fallback seek timer: in case the kdp does not fire 'playerSeekEnd'
+ var orgTime = this.flashCurrentTime;
+ var seekInterval = setInterval( function(){
+ if( _this.flashCurrentTime != orgTime ){
+ _this.seeking = false;
+ clearInterval( seekInterval );
+ this.triggerHelper( 'seeked' );
+ }
+ }, mw.config.get( 'EmbedPlayer.MonitorRate' ) );
+
+ } else {
+ // try to do a play then seek:
+ this.doPlayThenSeek(percentage);
+ }
+
+ // Run the onSeeking interface update
+ this.controlBuilder.onSeek();
+ },
+
+ /**
+ * Seek in a existing stream
+ *
+ * @param {Float}
+ * percentage Percentage of the stream to seek to between 0 and 1
+ */
+ doPlayThenSeek : function(percentage) {
+ mw.log('EmbedPlayerKplayer::doPlayThenSeek::');
+ var _this = this;
+ // issue the play request
+ this.play();
+
+ // let the player know we are seeking
+ _this.seeking = true;
+ this.triggerHelper( 'seeking' );
+
+ var getPlayerCount = 0;
+ var readyForSeek = function() {
+ _this.getPlayerElement();
+ // if we have duration then we are ready to do the seek ( flash can't
+ // seek untill there is some buffer )
+ if (_this.playerElement && _this.playerElement.sendNotification
+ && _this.getDuration() && _this.bufferedPercent) {
+ var seekTime = percentage * _this.getDuration();
+ // Issue the seek to the flash player:
+ _this.playerElement.sendNotification('doSeek', seekTime);
+ } else {
+ // Try to get player for 20 seconds:
+ if (getPlayerCount < 400) {
+ setTimeout(readyForSeek, 50);
+ getPlayerCount++;
+ } else {
+ mw.log('Error: doPlayThenSeek failed');
+ }
+ }
+ };
+ readyForSeek();
+ },
+
+ /**
+ * Issues a volume update to the playerElement
+ *
+ * @param {Float}
+ * percentage Percentage to update volume to
+ */
+ setPlayerElementVolume : function(percentage) {
+ if ( this.getPlayerElement() && this.playerElement.sendNotification ) {
+ this.playerElement.sendNotification('changeVolume', percentage);
+ }
+ },
+
+ /**
+ * function called by flash at set interval to update the playhead.
+ */
+ onUpdatePlayhead : function( playheadValue ) {
+ //mw.log('Update play head::' + playheadValue);
+ this.flashCurrentTime = playheadValue;
+ },
+
+ /**
+ * function called by flash when the total media size changes
+ */
+ onBytesTotalChange : function(data, id) {
+ this.bytesTotal = data.newValue;
+ },
+
+ /**
+ * function called by flash applet when download bytes changes
+ */
+ onBytesDownloadedChange : function(data, id) {
+ //mw.log('onBytesDownloadedChange');
+ this.bytesLoaded = data.newValue;
+ this.bufferedPercent = this.bytesLoaded / this.bytesTotal;
+
+ // Fire the parent html5 action
+ this.triggerHelper('progress', {
+ 'loaded' : this.bytesLoaded,
+ 'total' : this.bytesTotal
+ });
+ },
+
+ /**
+ * Get the embed player time
+ */
+ getPlayerElementTime : function() {
+ // update currentTime
+ return this.flashCurrentTime;
+ },
+
+ /**
+ * Get the embed fla object player Element
+ */
+ getPlayerElement : function() {
+ this.playerElement = document.getElementById( this.pid );
+ return this.playerElement;
+ }
+};
+
+} )( mediaWiki, jQuery );
+
+/*
+ * jQuery Tools 1.2.5 - The missing UI library for the Web
+ *
+ * [toolbox.flashembed]
+ *
+ * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
+ *
+ * http://flowplayer.org/tools/
+ *
+ * File generated: Fri Oct 22 13:51:38 GMT 2010
+ */
+(function(){function f(a,b){if(b)for(var c in b)if(b.hasOwnProperty(c))a[c]=b[c];return a}function l(a,b){var c=[];for(var d in a)if(a.hasOwnProperty(d))c[d]=b(a[d]);return c}function m(a,b,c){if(e.isSupported(b.version))a.innerHTML=e.getHTML(b,c);else if(b.expressInstall&&e.isSupported([6,65]))a.innerHTML=e.getHTML(f(b,{src:b.expressInstall}),{MMredirectURL:location.href,MMplayerType:"PlugIn",MMdoctitle:document.title});else{if(!a.innerHTML.replace(/\s/g,"")){a.innerHTML="<h2>Flash version "+b.version+
+" or greater is required</h2><h3>"+(g[0]>0?"Your version is "+g:"You have no flash plugin installed")+"</h3>"+(a.tagName=="A"?"<p>Click here to download latest version</p>":"<p>Download latest version from <a href='"+k+"'>here</a></p>");if(a.tagName=="A")a.onclick=function(){location.href=k}}if(b.onFail){var d=b.onFail.call(this);if(typeof d=="string")a.innerHTML=d}}if(i)window[b.id]=document.getElementById(b.id);f(this,{getRoot:function(){return a},getOptions:function(){return b},getConf:function(){return c},
+getApi:function(){return a.firstChild}})}var i=document.all,k="http://www.adobe.com/go/getflashplayer",n=typeof jQuery=="function",o=/(\d+)[^\d]+(\d+)[^\d]*(\d*)/,j={width:"100%",height:"100%",id:"_"+(""+Math.random()).slice(9),allowfullscreen:true,allowscriptaccess:"always",quality:"high",version:[3,0],onFail:null,expressInstall:null,w3c:false,cachebusting:false};window.attachEvent&&window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){}});
+window.flashembed=function(a,b,c){if(typeof a=="string")a=document.getElementById(a.replace("#",""));if(a){if(typeof b=="string")b={src:b};return new m(a,f(f({},j),b),c)}};var e=f(window.flashembed,{conf:j,getVersion:function(){var a,b;try{b=navigator.plugins["Shockwave Flash"].description.slice(16)}catch(c){try{b=(a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"))&&a.GetVariable("$version")}catch(d){try{b=(a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"))&&a.GetVariable("$version")}catch(h){}}}return(b=
+o.exec(b))?[b[1],b[3]]:[0,0]},asString:function(a){if(a===null||a===undefined)return null;var b=typeof a;if(b=="object"&&a.push)b="array";switch(b){case "string":a=a.replace(new RegExp('(["\\\\])',"g"),"\\$1");a=a.replace(/^\s?(\d+\.?\d+)%/,"$1pct");return'"'+a+'"';case "array":return"["+l(a,function(d){return e.asString(d)}).join(",")+"]";case "function":return'"function()"';case "object":b=[];for(var c in a)a.hasOwnProperty(c)&&b.push('"'+c+'":'+e.asString(a[c]));return"{"+b.join(",")+"}"}return String(a).replace(/\s/g,
+" ").replace(/\'/g,'"')},getHTML:function(a,b){a=f({},a);var c='<object width="'+a.width+'" height="'+a.height+'" id="'+a.id+'" name="'+a.id+'"';if(a.cachebusting)a.src+=(a.src.indexOf("?")!=-1?"&":"?")+Math.random();c+=a.w3c||!i?' data="'+a.src+'" type="application/x-shockwave-flash"':' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';c+=">";if(a.w3c||i)c+='<param name="movie" value="'+a.src+'" />';a.width=a.height=a.id=a.w3c=a.src=null;a.onFail=a.version=a.expressInstall=null;for(var d in a)if(a[d])c+=
+'<param name="'+d+'" value="'+a[d]+'" />';a="";if(b){for(var h in b)if(b[h]){d=b[h];a+=h+"="+(/function|object/.test(typeof d)?e.asString(d):d)+"&"}a=a.slice(0,-1);c+='<param name="flashvars" value=\''+a+"' />"}c+="</object>";return c},isSupported:function(a){return g[0]>a[0]||g[0]==a[0]&&g[1]>=a[1]}}),g=e.getVersion();if(n){jQuery.tools=jQuery.tools||{version:"1.2.5"};jQuery.tools.flashembed={conf:j};jQuery.fn.flashembed=function(a,b){return this.each(function(){$(this).data("flashembed",flashembed(this,
+a,b))})}}})();
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerNative.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerNative.js
new file mode 100644
index 00000000..8c514f70
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerNative.js
@@ -0,0 +1,1088 @@
+/**
+* Native embed library:
+*
+* Enables embedPlayer support for native html5 browser playback system
+*/
+( function( mw, $ ) { "use strict";
+
+mw.EmbedPlayerNative = {
+
+ //Instance Name
+ instanceOf: 'Native',
+
+ // Flag to only load the video ( not play it )
+ onlyLoadFlag:false,
+
+ //Callback fired once video is "loaded"
+ onLoadedCallback: null,
+
+ // The previous "currentTime" to sniff seek actions
+ // NOTE the bug where onSeeked does not seem fire consistently may no longer be applicable
+ prevCurrentTime: -1,
+
+ // Store the progress event ( updated during monitor )
+ progressEventData: null,
+
+ // If the media loaded event has been fired
+ mediaLoadedFlag: null,
+
+ // A flag to keep the video tag offscreen.
+ keepPlayerOffScreenFlag: null,
+
+ // A flag to designate the first play event, as to not propagate the native event in this case
+ isFirstEmbedPlay: null,
+
+ // A local var to store the current seek target time:
+ currentSeekTargetTime: null,
+
+ // All the native events per:
+ // http://www.w3.org/TR/html5/video.html#mediaevents
+ nativeEvents : [
+ 'loadstart',
+ 'progress',
+ 'suspend',
+ 'abort',
+ 'error',
+ 'emptied',
+ 'stalled',
+ 'play',
+ 'pause',
+ 'loadedmetadata',
+ 'loadeddata',
+ 'waiting',
+ 'playing',
+ 'canplay',
+ 'canplaythrough',
+ 'seeking',
+ 'seeked',
+ 'timeupdate',
+ 'ended',
+ 'ratechange',
+ 'durationchange',
+ 'volumechange'
+ ],
+
+ // Native player supported feature set
+ supports: {
+ 'playHead' : true,
+ 'pause' : true,
+ 'fullscreen' : true,
+ 'sourceSwitch': true,
+ 'timeDisplay' : true,
+ 'volumeControl' : true,
+ 'overlays' : true
+ },
+ /**
+ * Updates the supported features given the "type of player"
+ */
+ updateFeatureSupport: function(){
+ // The native controls function checks for overly support
+ // especially the special case of iPad in-dom or not support
+ if( this.useNativePlayerControls() ) {
+ this.supports.overlays = false;
+ this.supports.volumeControl = false;
+ }
+ // iOS does not support volume control
+ if( mw.isIpad() ){
+ this.supports.volumeControl = false;
+ }
+ // Check if we already have a selected source and a player in the page,
+ if( this.getPlayerElement() && this.getSrc() ){
+ $( this.getPlayerElement() ).attr( 'src', this.getSrc() );
+ }
+ // Check if we already have a video element an apply bindings ( for native interfaces )
+ if( this.getPlayerElement() ){
+ this.applyMediaElementBindings();
+ }
+
+ this.parent_updateFeatureSupport();
+ },
+ /**
+ * Adds an HTML screen and moves the video tag off screen, works around some iPhone bugs
+ */
+ addPlayScreenWithNativeOffScreen: function(){
+ var _this = this;
+ // Hide the player offscreen:
+ this.hidePlayerOffScreen();
+ this.keepPlayerOffScreenFlag = true;
+
+ // Add a play button on the native player:
+ this.addLargePlayBtn();
+
+ // Add a binding to show loader once clicked to show the loader
+ // bad ui to leave the play button displayed
+ this.$interface.find( '.play-btn-large' ).click( function(){
+ _this.$interface.find( '.play-btn-large' ).hide();
+ _this.addPlayerSpinner();
+ _this.hideSpinnerOncePlaying();
+ });
+
+ // Add an image poster:
+ var posterSrc = ( this.poster ) ? this.poster :
+ mw.config.get( 'EmbedPlayer.BlackPixel' );
+
+ // Check if the poster is already present:
+ if( $( this ).find( '.playerPoster' ).length ){
+ $( this ).find( '.playerPoster' ).attr('src', posterSrc );
+ } else {
+ $( this ).append(
+ $('<img />').css({
+ 'margin' : '0',
+ 'width': '100%',
+ 'height': '100%'
+ })
+ .attr( 'src', posterSrc)
+ .addClass('playerPoster')
+ )
+ }
+ $( this ).show();
+ },
+ /**
+ * Return the embed code
+ */
+ embedPlayerHTML : function () {
+ var _this = this;
+ var vid = _this.getPlayerElement();
+ this.isFirstEmbedPlay = true;
+
+ // Check if we should have a play button on the native player:
+ if( this.useLargePlayBtn() ){
+ this.addLargePlayBtn();
+ }
+
+ if( vid && $( vid ).attr('src') == this.getSrc( this.currentTime ) ){
+ _this.postEmbedActions();
+ return ;
+ }
+ mw.log( "EmbedPlayerNative::embedPlayerHTML > play url:" + this.getSrc( this.currentTime ) + ' startOffset: ' + this.start_ntp + ' end: ' + this.end_ntp );
+
+ // Check if using native controls and already the "pid" is already in the DOM
+ if( this.isPersistentNativePlayer() && vid ) {
+ _this.postEmbedActions();
+ return ;
+ }
+ // Reset some play state flags:
+ _this.bufferStartFlag = false;
+ _this.bufferEndFlag = false;
+
+ $( this ).html(
+ _this.getNativePlayerHtml()
+ );
+
+ // Directly run postEmbedActions ( if playerElement is not available it will retry )
+ _this.postEmbedActions();
+ },
+
+ /**
+ * Get the native player embed code.
+ *
+ * @param {object} playerAttributes Attributes to be override in function call
+ * @return {object} cssSet css to apply to the player
+ */
+ getNativePlayerHtml: function( playerAttributes, cssSet ){
+ if( !playerAttributes) {
+ playerAttributes = {};
+ }
+ // Update required attributes
+ if( !playerAttributes['id'] ){
+ playerAttributes['id'] = this.pid;
+ }
+ if( !playerAttributes['src'] ){
+ playerAttributes['src'] = this.getSrc( this.currentTime);
+ }
+
+ // If autoplay pass along to attribute ( needed for iPad / iPod no js autoplay support
+ if( this.autoplay ) {
+ playerAttributes['autoplay'] = 'true';
+ }
+
+ if( !cssSet ){
+ cssSet = {};
+ }
+
+ // Set default width height to 100% of parent container
+ if( !cssSet['width'] ) cssSet['width'] = '100%';
+ if( !cssSet['height'] ) cssSet['height'] = '100%';
+
+ // Also need to set the loop param directly for iPad / iPod
+ if( this.loop ) {
+ playerAttributes['loop'] = 'true';
+ }
+
+ var tagName = this.isAudio() ? 'audio' : 'video';
+
+ return $( '<' + tagName + ' />' )
+ // Add the special nativeEmbedPlayer to avoid any rewrites of of this video tag.
+ .addClass( 'nativeEmbedPlayerPid' )
+ .attr( playerAttributes )
+ .css( cssSet )
+ },
+
+ /**
+ * Post element javascript, binds event listeners and starts monitor
+ */
+ postEmbedActions: function() {
+ var _this = this;
+ // Setup local pointer:
+ var vid = this.getPlayerElement();
+ if( !vid ){
+ return ;
+ }
+ // Update the player source ( if needed )
+ if( $( vid).attr( 'src' ) != this.getSrc( this.currentTime ) ){
+ $( vid ).attr( 'src', this.getSrc( this.currentTime ) );
+ }
+ // Update the WebKitPlaysInline value
+ if( mw.config.get( 'EmbedPlayer.WebKitPlaysInline') ){
+ $( vid ).attr( 'webkit-playsinline', 1 );
+ }
+ // Update the EmbedPlayer.WebKitAllowAirplay option:
+ if( mw.config.get( 'EmbedPlayer.WebKitAllowAirplay' ) ){
+ $( vid ).attr( 'x-webkit-airplay', "allow" );
+ }
+ // make sure to display native controls if enabled:
+ if( this.useNativePlayerControls() ){
+ $( vid ).attr( 'controls', "true" );
+ }
+
+ // Apply media element bindings:
+ _this.applyMediaElementBindings();
+
+ // Make sure we start playing in the correct place:
+ if( this.currentTime != vid.currentTime ){
+ var waitReadyStateCount = 0;
+ var checkReadyState = function(){
+ if( vid.readyState > 0 ){
+ vid.currentTime = this.currentTime;
+ return ;
+ }
+ if( waitReadyStateCount > 1000 ){
+ mw.log("Error: EmbedPlayerNative: could not run native seek");
+ return ;
+ }
+ waitReadyStateCount++;
+ setTimeout( function() {
+ checkReadyState();
+ }, 10 );
+ };
+ }
+ // Some mobile devices ( iOS need a load call before play will work )
+ if ( !_this.loop ) {
+ vid.load();
+ }
+ },
+ /**
+ * Apply media element bindings
+ */
+ applyMediaElementBindings: function(){
+ var _this = this;
+ mw.log("EmbedPlayerNative::MediaElementBindings");
+ var vid = this.getPlayerElement();
+ if( ! vid ){
+ mw.log( " Error: applyMediaElementBindings without player elemnet");
+ return ;
+ }
+ $.each( _this.nativeEvents, function( inx, eventName ){
+ $( vid ).unbind( eventName + '.embedPlayerNative').bind( eventName + '.embedPlayerNative', function(){
+ if( _this._propagateEvents ){
+ var argArray = $.makeArray( arguments );
+ // always pass the current ref id as the last argument
+ // helps check against some event trigger ref issues in jQuery
+ argArray.push( _this.id );
+ // Check if there is local handler:
+ if( _this[ '_on' + eventName ] ){
+ _this[ '_on' + eventName ].apply( _this, argArray);
+ } else {
+ // No local handler directly propagate the event to the abstract object:
+ $( _this ).trigger( eventName, argArray );
+ }
+ }
+ });
+ });
+ },
+
+ // basic monitor function to update buffer
+ monitor: function(){
+ var _this = this;
+ var vid = _this.getPlayerElement();
+
+ // Update the bufferedPercent
+ if( vid && vid.buffered && vid.buffered.end && vid.duration ) {
+ try{
+ this.bufferedPercent = ( vid.buffered.end(0) / vid.duration );
+ } catch ( e ){
+ // opera does not have buffered.end zero index support ?
+ }
+ }
+ _this.parent_monitor();
+ },
+
+
+ /**
+ * Issue a seeking request.
+ *
+ * @param {Float} percent
+ * @param {bollean} stopAfterSeek if the player should stop after the seek
+ */
+ seek: function( percent, stopAfterSeek ) {
+ // bounds check
+ if( percent < 0 ){
+ percent = 0;
+ }
+
+ if( percent > 1 ){
+ percent = 1;
+ }
+ mw.log( 'EmbedPlayerNative::seek p: ' + percent + ' : ' + this.supportsURLTimeEncoding() + ' dur: ' + this.getDuration() + ' sts:' + this.seekTimeSec );
+
+ // Trigger preSeek event for plugins that want to store pre seek conditions.
+ this.triggerHelper( 'preSeek', percent );
+
+ this.seeking = true;
+ // Update the current time ( local property )
+ this.currentTime = ( percent * this.duration ).toFixed( 2 ) ;
+
+ // trigger the seeking event:
+ mw.log( 'EmbedPlayerNative::seek:trigger' );
+ this.triggerHelper( 'seeking' );
+
+ // Run the onSeeking interface update
+ this.controlBuilder.onSeek();
+
+ // @@todo check if the clip is loaded here (if so we can do a local seek)
+ if ( this.supportsURLTimeEncoding() ) {
+ // Make sure we could not do a local seek instead:
+ if ( percent < this.bufferedPercent && this.playerElement.duration && !this.didSeekJump ) {
+ mw.log( "EmbedPlayerNative::seek local seek " + percent + ' is already buffered < ' + this.bufferedPercent );
+ this.doNativeSeek( percent );
+ } else {
+ // We support URLTimeEncoding call parent seek:
+ this.parent_seek( percent );
+ }
+ } else {
+ // Try to do a play then seek:
+ this.doNativeSeek( percent );
+ }
+ },
+
+ /**
+ * Do a native seek by updating the currentTime
+ * @param {float} percent
+ * Percent to seek to of full time
+ */
+ doNativeSeek: function( percent, callback ) {
+ // If player already seeking, exit
+ var _this = this;
+ // chrome crashes with multiple seeks:
+ if( (navigator.userAgent.indexOf('Chrome') === -1) && _this.playerElement.seeking ) {
+ return ;
+ }
+
+ mw.log( 'EmbedPlayerNative::doNativeSeek::' + percent );
+ this.seeking = true;
+
+ this.seekTimeSec = 0;
+
+ // Hide iPad video off screen ( iOS shows quicktime logo during seek )
+ if( mw.isIOS() ){
+ this.hidePlayerOffScreen();
+ }
+
+ this.setCurrentTime( ( percent * this.duration ) , function(){
+ // Update the current time ( so that there is not a monitor delay in reflecting "seeked time" )
+ _this.currentTime = _this.getPlayerElement().currentTime;
+ // Done seeking ( should be a fallback trigger event ) :
+ if( _this.seeking ){
+ _this.seeking = false;
+ $( _this ).trigger( 'seeked' );
+ }
+ // restore iPad video position:
+ _this.restorePlayerOnScreen();
+
+ _this.monitor();
+ // issue the callback:
+ if( callback ){
+ callback();
+ }
+ });
+ },
+
+ /**
+ * Seek in a existing stream, we first play then seek to work around issues with iPad seeking.
+ *
+ * @param {Float} percent
+ * percent of the stream to seek to between 0 and 1
+ */
+ doPlayThenSeek: function( percent ) {
+ mw.log( 'EmbedPlayerNative::doPlayThenSeek::' + percent + ' isPaused ' + this.paused);
+ var _this = this;
+ var oldPauseState = this.paused;
+ this.play();
+ var retryCount = 0;
+ var readyForSeek = function() {
+ _this.getPlayerElement();
+ // If we have duration then we are ready to do the seek
+ if ( _this.playerElement && _this.playerElement.duration ) {
+ _this.doNativeSeek( percent, function(){
+ // restore pause if paused:
+ if( oldPauseState ){
+ _this.pause();
+ }
+ } );
+ } else {
+ // Try to get player for 30 seconds:
+ // (it would be nice if the onmetadata type callbacks where fired consistently)
+ if ( retryCount < 800 ) {
+ setTimeout( readyForSeek, 10 );
+ retryCount++;
+ } else {
+ mw.log( 'EmbedPlayerNative:: Error: doPlayThenSeek failed :' + _this.playerElement.duration);
+ }
+ }
+ };
+ readyForSeek();
+ },
+
+ /**
+ * Set the current time with a callback
+ *
+ * @param {Float} position
+ * Seconds to set the time to
+ * @param {Function} callback
+ * Function called once time has been set.
+ */
+ setCurrentTime: function( seekTime , callback, callbackCount ) {
+ var _this = this;
+ if( !callbackCount ){
+ callbackCount = 0;
+ }
+ mw.log( "EmbedPlayerNative:: setCurrentTime seekTime:" + seekTime + ' count:' + callbackCount );
+
+ // Make sure all the timeouts don't seek to an expired target:
+ $( this ).data('currentSeekTarget', seekTime );
+
+ var vid = this.getPlayerElement();
+ // add a callback handler to null out callback:
+ var callbackHandler = function(){
+ if( $.isFunction( callback ) ){
+ callback();
+ callback = null;
+ }
+ }
+ if( !vid ) {
+ callbackHandler();
+ _this.currentSeekTargetTime = seekTime.toFixed( 2 );
+ return;
+ }
+ // Check if player is ready for seek:
+ if( vid.readyState < 1 ){
+ // Try to seek for 4 seconds:
+ if( callbackCount >= 40 ){
+ mw.log("Error:: EmbedPlayerNative: with seek request, media never in ready state");
+ callbackHandler();
+ return ;
+ }
+ setTimeout( function(){
+ // Check that this seek did not expire:
+ if( $( _this ).data('currentSeekTarget') != seekTime ){
+ mw.log("EmbedPlayerNative:: expired seek target");
+ return ;
+ }
+ _this.setCurrentTime( seekTime, callback , callbackCount+1);
+ }, 100 );
+ return ;
+ }
+ // Check if currentTime is already set to the seek target:
+ if( vid.currentTime.toFixed(2) == seekTime.toFixed(2) ){
+ mw.log("EmbedPlayerNative:: setCurrentTime: current time matches seek target: " +
+ vid.currentTime.toFixed(2) + ' == ' + seekTime.toFixed(2) );
+ callbackHandler();
+ return;
+ }
+ // setup a namespaced seek bind:
+ var seekBind = 'seeked.nativeSeekBind';
+
+ // Remove any old listeners
+ $( vid ).unbind( seekBind );
+ // Bind a seeked listener for the callback
+ $( vid ).bind( seekBind, function( event ) {
+ // Remove the listener:
+ $( vid ).unbind( seekBind );
+
+ // Check if seeking to zero:
+ if( seekTime == 0 && vid.currentTime == 0 ){
+ callbackHandler();
+ return ;
+ }
+
+ // Check if we got a valid seek:
+ if( vid.currentTime > 0 ){
+ callbackHandler();
+ } else {
+ mw.log( "Error:: EmbedPlayerNative: seek callback without time updatet " + vid.currentTime );
+ }
+ });
+ setTimeout(function(){
+ // Check that this seek did not expire:
+ if( $( _this ).data('currentSeekTarget') != seekTime ){
+ mw.log("EmbedPlayerNative:: Expired seek target");
+ return ;
+ }
+
+ if( $.isFunction( callback ) ){
+ // if seek is within 5 seconds of the target assume success. ( key frame intervals can mess with seek accuracy )
+ // this only runs where the seek callback failed ( i.e broken html5 seek ? )
+ if( Math.abs( vid.currentTime - seekTime ) < 5 ){
+ mw.log( "EmbedPlayerNative:: Seek time is within 5 seconds of target, sucessfull seek");
+ callback();
+ } else {
+ mw.log( "Error:: EmbedPlayerNative: Seek still has not made a callback after 5 seconds, retry");
+ _this.setCurrentTime( seekTime, callback , callbackCount++ );
+ }
+ }
+ }, 5000);
+
+ // Try to update the playerElement time:
+ try {
+ _this.currentSeekTargetTime = seekTime.toFixed( 2 );
+ // use toFixed ( iOS issue with float seek times )
+ vid.currentTime = _this.currentSeekTargetTime;
+ } catch ( e ) {
+ mw.log("Error:: EmbedPlayerNative: Could not set video tag seekTime");
+ callbackHandler();
+ return ;
+ }
+
+ // Check for seeking state ( some player iOS / iPad can only seek while playing )
+ if(! vid.seeking ){
+ mw.log( "Error:: not entering seek state, play and wait for positive time" );
+ vid.play();
+ setTimeout(function(){
+ _this.waitForPositiveCurrentTime( function(){
+ mw.log("EmbedPlayerNative:: Got possitive time:" + vid.currentTime.toFixed(3) + ", trying to seek again");
+ _this.setCurrentTime( seekTime , callback, callbackCount+1 );
+ });
+ }, mw.config.get( 'EmbedPlayer.MonitorRate' ) );
+ }
+ },
+ waitForPositiveCurrentTime: function( callback ){
+ var _this = this;
+ var vid = this.getPlayerElement();
+ this.waitForPositiveCurrentTimeCount++;
+ // Wait for playback for 10 seconds
+ if( vid.currentTime > 0 ){
+ mw.log( 'EmbedPlayerNative:: waitForPositiveCurrentTime success' );
+ callback();
+ } else if( this.waitForPositiveCurrentTimeCount > 200 ){
+ mw.log( "Error:: waitForPositiveCurrentTime failed to reach possitve time");
+ callback();
+ } else {
+ setTimeout(function(){ _this.waitForPositiveCurrentTime( callback ) }, 50 )
+ }
+ },
+ /**
+ * Get the embed player time
+ */
+ getPlayerElementTime: function() {
+ var _this = this;
+ // Make sure we have .vid obj
+ this.getPlayerElement();
+ if ( !this.playerElement ) {
+ mw.log( 'EmbedPlayerNative::getPlayerElementTime: ' + this.id + ' not in dom ( stop monitor)' );
+ this.stop();
+ return false;
+ }
+ var ct = this.playerElement.currentTime;
+ // Return 0 or a positive number:
+ if( ! ct || isNaN( ct ) || ct < 0 || ! isFinite( ct ) ){
+ return 0;
+ }
+ // Return the playerElement currentTime
+ return this.playerElement.currentTime;
+ },
+
+ // Update the poster src ( updates the native object if in dom )
+ updatePosterSrc: function( src ){
+ if( this.getPlayerElement() ){
+ $( this.getPlayerElement() ).attr('poster', src );
+ }
+ // Also update the embedPlayer poster
+ this.parent_updatePosterSrc( src );
+ },
+ /**
+ * Empty player sources from the active video tag element
+ */
+ emptySources: function(){
+ // empty player source:
+ $( this.getPlayerElement() ).attr( 'src', null );
+ // empty out generic sources:
+ this.parent_emptySources();
+ },
+ /**
+ * playerSwitchSource switches the player source working around a few bugs in browsers
+ *
+ * @param {Object}
+ * Source object to switch to.
+ * @param {function}
+ * switchCallback Function to call once the source has been switched
+ * @param {function}
+ * doneCallback Function to call once the clip has completed playback
+ */
+ playerSwitchSource: function( source, switchCallback, doneCallback ){
+ var _this = this;
+ var src = source.getSrc();
+ var vid = this.getPlayerElement();
+ var switchBindPostfix = '.playerSwitchSource';
+ this.isPauseLoading = false;
+ // Make sure the switch source is different:
+ if( !src || src == vid.src ){
+ if( $.isFunction( switchCallback ) ){
+ switchCallback( vid );
+ }
+ // Delay done callback to allow any non-blocking switch callback code to fully execute
+ if( $.isFunction( doneCallback ) ){
+ doneCallback();
+ }
+ return ;
+ }
+
+ // only display switch msg if actually switching:
+ mw.log( 'EmbedPlayerNative:: playerSwitchSource: ' + src + ' native time: ' + vid.currentTime );
+
+ // Update some parent embedPlayer vars:
+ this.currentTime = 0;
+ this.previousTime = 0;
+ if ( vid ) {
+ try {
+ // Remove all switch player bindings
+ $( vid ).unbind( switchBindPostfix );
+
+ // pause before switching source
+ vid.pause();
+
+ var orginalControlsState = vid.controls;
+ // Hide controls ( to not display native play button while switching sources )
+ vid.removeAttribute('controls');
+
+ // dissable seeking ( if we were in a seeking state before the switch )
+ _this.seeking = false;
+
+ // add a loading indicator:
+ _this.addPlayerSpinner();
+
+ // Do the actual source switch:
+ vid.src = src;
+ // load the updated src
+ vid.load();
+
+ // hide the player offscreen while we switch
+ _this.hidePlayerOffScreen();
+ // restore position once we have metadata
+ $( vid ).bind( 'loadedmetadata' + switchBindPostfix, function(){
+ $( vid ).unbind( 'loadedmetadata' + switchBindPostfix);
+ mw.log("EmbedPlayerNative:: playerSwitchSource> loadedmetadata callback for:" + src + ' switchCallback: ' + switchCallback );
+ // Only update duration if we didn't get it server side
+ // Some browsers report bad duration (e.g. Android native browser)
+ // So avoid using the browser detected value if possible.
+ if ( !_this.duration && isFinite( vid.duration ) ) {
+ _this.duration = vid.duration;
+ }
+ // keep going towards playback! if switchCallback has not been called yet
+ // we need the "playing" event to trigger the switch callback
+ if ( $.isFunction( switchCallback ) ){
+ vid.play();
+ }
+ });
+
+ var handleSwitchCallback = function(){
+ // restore video position ( now that we are playing with metadata size )
+ _this.restorePlayerOnScreen();
+ // play hide loading spinner:
+ _this.hideSpinnerAndPlayBtn();
+ // Restore
+ vid.controls = orginalControlsState;
+ // check if we have a switch callback and issue it now:
+ if ( $.isFunction( switchCallback ) ){
+ switchCallback( vid );
+ switchCallback = null;
+ }
+ }
+
+ // once playing issue callbacks:
+ $( vid ).bind( 'playing' + switchBindPostfix, function(){
+ $( vid ).unbind( 'playing' + switchBindPostfix );
+ mw.log("EmbedPlayerNative:: playerSwitchSource> playing callback");
+ handleSwitchCallback();
+ });
+
+ // Add the end binding if we have a post event:
+ if( $.isFunction( doneCallback ) ){
+ $( vid ).bind( 'ended' + switchBindPostfix , function( event ) {
+ // remove end binding:
+ $( vid ).unbind( switchBindPostfix );
+ // issue the doneCallback
+ doneCallback();
+
+ // Support loop for older iOS
+ // Temporarly disabled pending more testing or refactor into a better place.
+ //if ( _this.loop ) {
+ // vid.play();
+ //}
+ return false;
+ });
+ }
+
+ // issue the play request:
+ vid.play();
+
+ // check if ready state is loading or doing anything ( iOS play restriction )
+ // give iOS 5 seconds to ~start~ loading media
+ setTimeout(function(){
+ // Check that the player got out of readyState 0
+ if( vid.readyState === 0 && $.isFunction( switchCallback ) ){
+ mw.log("EmbedPlayerNative:: possible iOS play without gesture failed, issue callback");
+ // hand off to the swtich callback method.
+ handleSwitchCallback();
+ // make sure we are in a pause state ( failed to change and play media );
+ _this.pause();
+ // show the big play button so the user can give us a user gesture:
+ if( ! _this.useLargePlayBtn() ){
+ _this.addLargePlayBtn();
+ }
+ }
+ }, 5000 );
+
+
+ } catch (e) {
+ mw.log("Error: EmbedPlayerNative Error in switching source playback");
+ }
+ }
+ },
+ hidePlayerOffScreen:function( vid ){
+ var vid = this.getPlayerElement();
+ // Move the video offscreen while it switches ( hides quicktime logo only applies to iPad )
+ $( vid ).css( {
+ 'position' : 'absolute',
+ 'left': '-4048px'
+ });
+ },
+ restorePlayerOnScreen: function( vid ){
+ var vid = this.getPlayerElement();
+ if( this.keepPlayerOffScreenFlag ){
+ return ;
+ }
+
+ // Remove any poster div ( that would overlay the player )
+ $( this ).find( '.playerPoster' ).remove();
+ // Restore video pos before calling sync syze
+ $( vid ).css( {
+ 'left': '0px'
+ });
+ },
+ /**
+ * Pause the video playback
+ * calls parent_pause to update the interface
+ */
+ pause: function( ) {
+ this.getPlayerElement();
+ this.parent_pause(); // update interface
+ if ( this.playerElement ) { // update player
+ this.playerElement.pause();
+ }
+ },
+
+ /**
+ * Play back the video stream
+ * calls parent_play to update the interface
+ */
+ play: function() {
+ var _this = this;
+ // if starting playback from stoped state and not in an ad or otherise blocked controls state:
+ // restore player:
+ if( this.isStopped() && this._playContorls ){
+ this.restorePlayerOnScreen();
+ }
+ // Run parent play:
+ if( _this.parent_play() ){
+ if ( this.getPlayerElement() && this.getPlayerElement().play ) {
+ mw.log( "EmbedPlayerNative:: issue native play call" );
+ // If in pauseloading state make sure the loading spinner is present:
+ if( this.isPauseLoading ){
+ this.hideSpinnerOncePlaying();
+ }
+ // issue a play request
+ this.getPlayerElement().play();
+ // re-start the monitor:
+ this.monitor();
+ }
+ } else {
+ mw.log( "EmbedPlayerNative:: parent play returned false, don't issue play on native element");
+ }
+ },
+
+ /**
+ * Stop the player ( end all listeners )
+ */
+ stop: function(){
+ var _this = this;
+ if( this.playerElement && this.playerElement.currentTime){
+ this.playerElement.currentTime = 0;
+ this.playerElement.pause();
+ }
+ this.parent_stop();
+ },
+
+ /**
+ * Toggle the Mute
+ * calls parent_toggleMute to update the interface
+ */
+ toggleMute: function() {
+ this.parent_toggleMute();
+ this.getPlayerElement();
+ if ( this.playerElement )
+ this.playerElement.muted = this.muted;
+ },
+
+ /**
+ * Update Volume
+ *
+ * @param {Float} percent Value between 0 and 1 to set audio volume
+ */
+ setPlayerElementVolume : function( percent ) {
+ if ( this.getPlayerElement() ) {
+ // Disable mute if positive volume
+ if( percent != 0 ) {
+ this.playerElement.muted = false;
+ }
+ this.playerElement.volume = percent;
+ }
+ },
+
+ /**
+ * get Volume
+ *
+ * @return {Float}
+ * Audio volume between 0 and 1.
+ */
+ getPlayerElementVolume: function() {
+ if ( this.getPlayerElement() ) {
+ return this.playerElement.volume;
+ }
+ },
+ /**
+ * get the native muted state
+ */
+ getPlayerElementMuted: function(){
+ if ( this.getPlayerElement() ) {
+ return this.playerElement.muted;
+ }
+ },
+
+ /**
+ * Get the native media duration
+ */
+ getNativeDuration: function() {
+ if ( this.playerElement ) {
+ return this.playerElement.duration;
+ }
+ },
+
+ /**
+ * Load the video stream with a callback fired once the video is "loaded"
+ *
+ * @parma {Function} callbcak Function called once video is loaded
+ */
+ load: function( callback ) {
+ this.getPlayerElement();
+ if ( !this.playerElement ) {
+ // No vid loaded
+ mw.log( 'EmbedPlayerNative::load() ... doEmbed' );
+ this.onlyLoadFlag = true;
+ this.embedPlayerHTML();
+ this.onLoadedCallback = callback;
+ } else {
+ // Should not happen offten
+ this.playerElement.load();
+ if( callback ){
+ callback();
+ }
+ }
+ },
+
+ /**
+ * Get /update the playerElement value
+ */
+ getPlayerElement: function () {
+ this.playerElement = $( '#' + this.pid ).get( 0 );
+ return this.playerElement;
+ },
+
+ /**
+ * Bindings for the Video Element Events
+ */
+
+ /**
+ * Local method for seeking event
+ * fired when "seeking"
+ */
+ _onseeking: function() {
+ mw.log( "EmbedPlayerNative::onSeeking " + this.seeking + ' new time: ' + this.getPlayerElement().currentTime );
+ if( this.seeking && Math.round( this.getPlayerElement().currentTime - this.currentSeekTargetTime ) > 2 ){
+ mw.log( "Error:: EmbedPlayerNative Seek time missmatch: target:" + this.getPlayerElement().currentTime +
+ ' actual ' + this.currentSeekTargetTime + ', note apple HLS can only seek to 10 second targets');
+ }
+ // Trigger the html5 seeking event
+ //( if not already set from interface )
+ if( !this.seeking ) {
+ this.currentSeekTargetTime = this.getPlayerElement().currentTime;
+ this.seeking = true;
+ // Run the onSeeking interface update
+ this.controlBuilder.onSeek();
+
+ // Trigger the html5 "seeking" trigger
+ mw.log("EmbedPlayerNative::seeking:trigger:: " + this.seeking);
+ if( this._propagateEvents ){
+ this.triggerHelper( 'seeking' );
+ }
+ }
+ },
+
+ /**
+ * Local method for seeked event
+ * fired when done seeking
+ */
+ _onseeked: function() {
+ mw.log("EmbedPlayerNative::onSeeked " + this.seeking + ' ct:' + this.playerElement.currentTime );
+ // sync the seek checks so that we don't re-issue the seek request
+ this.previousTime = this.currentTime = this.playerElement.currentTime;
+
+ // Trigger the html5 action on the parent
+ if( this.seeking ){
+
+ // HLS safari triggers onseek when its not even close to the target time,
+ // we don't want to trigger the seek event for these "fake" onseeked triggers
+ if( Math.abs( this.currentSeekTargetTime - this.getPlayerElement().currentTime ) > 2 ){
+ mw.log( "Error:: EmbedPlayerNative:seeked triggred with time mismatch: target:" +
+ this.currentSeekTargetTime +
+ ' actual:' + this.getPlayerElement().currentTime );
+ return ;
+ }
+ this.seeking = false;
+ if( this._propagateEvents ){
+ mw.log( "EmbedPlayerNative:: trigger: seeked" );
+ this.triggerHelper( 'seeked' );
+ }
+ }
+ this.hideSpinner();
+ // update the playhead status
+ if( this.isStopped() ){
+ this.addLargePlayBtn();
+ }
+ this.monitor();
+ },
+
+ /**
+ * Handle the native paused event
+ */
+ _onpause: function(){
+ var _this = this;
+ var timeSincePlay = Math.abs( this.absoluteStartPlayTime - new Date().getTime() );
+ mw.log( "EmbedPlayerNative:: OnPaused:: propagate:" + this._propagateEvents + ' time since play: ' + timeSincePlay + ' isNative=true' );
+ // Only trigger parent pause if more than MonitorRate time has gone by.
+ // Some browsers trigger native pause events when they "play" or after a src switch
+ if( timeSincePlay > mw.config.get( 'EmbedPlayer.MonitorRate' ) ){
+ _this.parent_pause();
+ } else {
+ // continue playback:
+ this.getPlayerElement().play();
+ }
+ },
+
+ /**
+ * Handle the native play event
+ */
+ _onplay: function(){
+ mw.log("EmbedPlayerNative:: OnPlay:: propogate:" + this._propagateEvents + ' paused: ' + this.paused);
+ // if using native controls make sure the inteface does not block the native controls interface:
+ if( this.useNativePlayerControls() ){
+ this.$interface.css('pointer-events', 'none');
+ }
+
+ // Update the interface ( if paused )
+ if( ! this.isFirstEmbedPlay && this._propagateEvents && this.paused ){
+ this.parent_play();
+ } else {
+ // make sure the interface reflects the current play state if not calling parent_play()
+ this.playInterfaceUpdate();
+ }
+ // Set firstEmbedPlay state to false to avoid initial play invocation :
+ this.isFirstEmbedPlay = false;
+ },
+
+ /**
+ * Local method for metadata ready
+ * fired when metadata becomes available
+ *
+ * Used to update the media duration to
+ * accurately reflect the src duration
+ */
+ _onloadedmetadata: function() {
+ this.getPlayerElement();
+
+ if ( this.playerElement && !isNaN( this.playerElement.duration ) && isFinite( this.playerElement.duration) ) {
+ mw.log( 'EmbedPlayerNative :onloadedmetadata metadata ready Update duration:' + this.playerElement.duration + ' old dur: ' + this.getDuration() );
+ // Only update duration if we didn't get it server side
+ // Some browsers report bad duration (e.g. Android native browser)
+ // So avoid using the browser detected value if possible.
+ if( !this.duration && this.playerElement && isFinite( this.playerElement.duration ) ) {
+ this.duration = this.playerElement.duration;
+ }
+ }
+
+ // Check if in "playing" state and we are _propagateEvents events and continue to playback:
+ if( !this.paused && this._propagateEvents ){
+ this.getPlayerElement().play();
+ }
+
+ //Fire "onLoaded" flags if set
+ if( typeof this.onLoadedCallback == 'function' ) {
+ this.onLoadedCallback();
+ }
+
+ // Trigger "media loaded"
+ if( ! this.mediaLoadedFlag ){
+ $( this ).trigger( 'mediaLoaded' );
+ this.mediaLoadedFlag = true;
+ }
+ },
+
+ /**
+ * Local method for end of media event
+ */
+ _onended: function( event ) {
+ var _this = this;
+ if( this.getPlayerElement() ){
+ mw.log( 'EmbedPlayer:native: onended:' + this.playerElement.currentTime + ' real dur:' + this.getDuration() + ' ended ' + this._propagateEvents );
+ if( this._propagateEvents ){
+ this.onClipDone();
+ }
+ }
+ },
+ /**
+ * Local onClip done function for native player.
+ */
+ onClipDone: function(){
+ var _this = this;
+ // add clip done binding ( will only run on sequence complete )
+ $(this).unbind('onEndedDone.onClipDone').bind( 'onEndedDone.onClipDone', function(){
+ _this.addPlayScreenWithNativeOffScreen();
+ // if not a legitmate play screen don't keep the player offscreen when playback starts:
+ if( !_this.isImagePlayScreen() ){
+ _this.keepPlayerOffScreenFlag =false;
+ }
+ });
+ this.parent_onClipDone();
+ }
+};
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerOgvJs.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerOgvJs.js
new file mode 100644
index 00000000..791459f3
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerOgvJs.js
@@ -0,0 +1,222 @@
+( function( mw, $ ) { "use strict";
+
+var support = mw.OgvJsSupport;
+
+mw.EmbedPlayerOgvJs = {
+
+ // Instance name:
+ instanceOf: 'OgvJs',
+
+ // Supported feature set of the OGVPlayer widget:
+ supports: {
+ 'playHead' : true,
+ 'pause' : true,
+ 'stop' : true,
+ 'fullscreen' : true,
+ 'sourceSwitch': true,
+ 'timeDisplay' : true,
+ 'volumeControl' : false,
+ 'overlays': true,
+ 'timedText': true
+ },
+
+ /**
+ * Perform setup in response to a play start command.
+ * This means loading the code asynchronously if needed,
+ * and enabling web audio for iOS Safari inside the event
+ * handler.
+ *
+ * @return jQuery.Deferred
+ */
+ _ogvJsPreInit: function() {
+ if( mw.isIOS() ) {
+ this._initializeAudioForiOS();
+ }
+ return support.loadOgvJs();
+ },
+
+ /**
+ * Actually initialize the player.
+ *
+ * @return OGVPlayer
+ */
+ _ogvJsInit: function() {
+ var options = {};
+ if ( this._iOSAudioContext ) {
+ // Reuse the audio context we opened earlier
+ options.audioContext = this._iOSAudioContext;
+ }
+ return new OGVPlayer( options );
+ },
+
+ _iOSAudioContext: undefined,
+
+ _initializeAudioForiOS: function() {
+ // iOS Safari Web Audio API must be initialized from an input event handler
+ if ( this._iOSAudioContext ) {
+ return;
+ }
+ this._iOSAudioContext = support.initAudioContext();
+ },
+
+ /**
+ * Output the the embed html
+ */
+ embedPlayerHTML: function (optionalCallback) {
+
+ $( this )
+ .empty()
+ .append( $.createSpinner( {
+ size: 'large',
+ type: 'block'
+ } ) );
+
+ var _this = this;
+ if( mw.isIOS() ) {
+ _this._initializeAudioForiOS();
+ }
+ support.loadOgvJs().done( function() {
+
+ var player = _this._ogvJsInit();
+ player.id = _this.pid;
+ player.style.width = '100%';
+ player.style.height = '100%';
+ player.src = _this.getSrc();
+ if ( _this.getDuration() ) {
+ player.durationHint = parseFloat( _this.getDuration() );
+ }
+ player.addEventListener('ended', function() {
+ _this.onClipDone();
+ });
+
+ // simulate timeupdate events, needed for subtitles
+ // @todo switch this to native timeupdate event when available upstream
+ var lastTime = 0,
+ timeupdateInterval = 0.25;
+ player.addEventListener( 'framecallback', function( event ) {
+ var player = _this.getPlayerElement(),
+ now = player ? player.currentTime : lastTime;
+ // Don't spam time updates on every frame
+ if ( Math.abs( now - lastTime ) >= timeupdateInterval ) {
+ lastTime = now;
+ $( _this ).trigger( 'timeupdate', [event, _this.id] );
+ }
+ });
+
+ $( _this ).empty().append( player );
+ player.play();
+
+ // Start the monitor:
+ _this.monitor();
+
+ if ( optionalCallback ) {
+ optionalCallback();
+ }
+ });
+ },
+
+ /**
+ * Get the embed player time
+ */
+ getPlayerElementTime: function() {
+ this.getPlayerElement();
+ var currentTime = 0;
+ if ( this.playerElement ) {
+ currentTime = this.playerElement.currentTime;
+ } else {
+ mw.log( "EmbedPlayerOgvJs:: Could not find playerElement" );
+ }
+ return currentTime;
+ },
+
+ /**
+ * Update the playerElement instance with a pointer to the embed object
+ */
+ getPlayerElement: function() {
+ // this.pid is in the form 'pid_mwe_player_<number>'; inherited from mw.EmbedPlayer.js
+ var $el = $( '#' + this.pid );
+ if( !$el.length ) {
+ return false;
+ }
+ this.playerElement = $el.get( 0 );
+ return this.playerElement;
+ },
+
+ /**
+ * Issue the doPlay request to the playerElement
+ * calls parent_play to update interface
+ */
+ play: function() {
+ this.getPlayerElement();
+ this.parent_play();
+ if ( this.playerElement ) {
+ this.playerElement.play();
+ // Restart the monitor if on second playthrough
+ this.monitor();
+ }
+ },
+
+ /**
+ * Pause playback
+ * calls parent_pause to update interface
+ */
+ pause: function() {
+ this.getPlayerElement();
+ // Update the interface
+ this.parent_pause();
+ // Call the pause function if it exists:
+ if ( this.playerElement ) {
+ this.playerElement.pause();
+ }
+ },
+
+ /**
+ * Switch the source!
+ * For simplicity we just replace the player here.
+ */
+ playerSwitchSource: function( source, switchCallback, doneCallback ){
+ var _this = this;
+ var src = source.getSrc();
+ var vid = this.getPlayerElement();
+ if ( typeof vid.stop !== 'undefined' ) {
+ vid.stop();
+ }
+
+ switchCallback();
+
+ // Currently have to tear down the player and make a new one
+ this.embedPlayerHTML( doneCallback );
+ },
+
+ /**
+ * Seek in the ogg stream
+ * @param {Float} percentage Percentage to seek into the stream
+ */
+ seek: function( percentage ) {
+ this.setCurrentTime( percentage * parseFloat( this.getDuration() ) );
+ },
+
+ setCurrentTime: function( time, callback ) {
+ this.getPlayerElement();
+
+ if ( this.playerElement ) {
+ this.playerElement.currentTime = time;
+ }
+
+ this.currentTime = time;
+ this.previousTime = time; // prevent weird double-seek. MwEmbedPlyer is weird!
+
+ // Run the onSeeking interface update
+ this.controlBuilder.onSeek();
+ // @todo add proper events upstream
+ if( this.seeking ){
+ this.seeking = false;
+ $( this ).trigger( 'seeked' );
+ }
+ if ( $.isFunction( callback ) ) {
+ callback();
+ }
+ }
+};
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerVLCApp.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerVLCApp.js
new file mode 100644
index 00000000..5fa6c6f8
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerVLCApp.js
@@ -0,0 +1,101 @@
+/**
+ * Play the video using the vlc app on iOS
+ */
+
+( function( mw, $ ) { "use strict";
+
+mw.EmbedPlayerVLCApp = {
+ // List of supported features (or lack thereof)
+ supports: {
+ 'playHead':false, /* The seek slider */
+ 'pause':true, /* Play pause button in control bar */
+ 'stop':true, /* Does this actually do anything?? */
+ 'fullscreen':false,
+ 'timeDisplay':false,
+ 'volumeControl':false
+ },
+
+ // Instance name:
+ instanceOf:'VLCApp',
+
+ /*
+ * Embed this "fake" player
+ *
+ * @return {String}
+ * embed code to link to VLC app
+ */
+ embedPlayerHTML: function() {
+ var fileUrl = this.getSrc( this.seekTimeSec ),
+ vlcUrl = 'vlc://' + (new mw.Uri( fileUrl )).toString(),
+ appStoreUrl = '//itunes.apple.com/us/app/vlc-for-ios/id650377962',
+ appInstalled = false,
+ promptInstallTimeout,
+ $link,
+ startTime;
+
+ // Replace video with download in vlc link.
+ // the <span> ends up being not used as we get the html via .html()
+ $link = $( '<span></span>' ).append( $( '<a></a>' ).attr( 'href', appStoreUrl ).append(
+ mw.html.escape( mw.msg( 'mwe-embedplayer-vlcapp-vlcapplinktext' ) )
+ ) );
+ $( this ).html( $( '<div class="vlcapp-player"></div>' )
+ .width( this.getWidth() )
+ .height( this.getHeight() )
+ .append(
+ // mw.msg doesn't have rawParams() equivalent. Lame.
+ mw.html.escape(
+ mw.msg( 'mwe-embedplayer-vlcapp-intro' )
+ ).replace( /\$1/g, $link.html() )
+ ).append( $( '<ul></ul>' )
+ .append( $( '<li></li>' ).append( $( '<a></a>' ).attr( 'href', appStoreUrl )
+ .text( mw.msg( 'mwe-embedplayer-vlcapp-downloadapp' ) ) )
+ ).append( $( '<li></li>' ).append( $( '<a></a>' ).attr( 'href', vlcUrl )
+ .text( mw.msg( 'mwe-embedplayer-vlcapp-openvideo' ) ) )
+ ).append( $( '<li></li>' ).append( $( '<a></a>' ).attr( 'href', fileUrl )
+ .text( mw.msg( 'mwe-embedplayer-vlcapp-downloadvideo' ) ) )
+ )
+ )
+ );
+
+ // Try to auto-open in vlc.
+ // Based on http://stackoverflow.com/questions/627916/check-if-url-scheme-is-supported-in-javascript
+
+ $( window ).one( 'pagehide', function() {
+ appInstalled = true;
+ if ( promptInstallTimeout ) {
+ window.clearTimeout( promptInstallTimeout );
+ }
+ } );
+ startTime = (new Date).getTime();
+ try {
+ window.location = vlcUrl;
+ } catch( e ) {
+ // Just to be safe, ignore any exceptions
+ // However, it appears iOS doesn't throw any. Other browsers do.
+ }
+ promptInstallTimeout = window.setTimeout( function() {
+ var install;
+ if ( appInstalled ) {
+ return;
+ }
+ if ( document.hidden || document.webkitHidden ) {
+ // browser still running, but in background.
+ // probably means an App was opened up.
+ return;
+ }
+ if ( (new Date).getTime() - 15000 > startTime ) {
+ // We switched to VLC more than fifteen seconds ago.
+ // Probably we succesfully switched and the other detection
+ // methods failed.
+ return;
+ }
+ install = confirm( mw.msg( 'mwe-embedplayer-vlcapp-vlcapppopup' ) );
+ if ( install ) {
+ window.location = appStoreUrl;
+ }
+ // Note about timeout: iPad air needs longer than an iPhone
+ }, 1000 );
+ }
+};
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerVlc.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerVlc.js
new file mode 100644
index 00000000..c668cf40
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedPlayerVlc.js
@@ -0,0 +1,358 @@
+/*
+* VLC embed based on: http://people.videolan.org/~damienf/plugin-0.8.6.html
+* javascript api: http://www.videolan.org/doc/play-howto/en/ch04.html
+* assume version > 0.8.5.1
+*/
+( function( mw, $ ) { "use strict";
+
+mw.EmbedPlayerVlc = {
+
+ //Instance Name:
+ instanceOf : 'Vlc',
+
+ //What the vlc player / plug-in supports:
+ supports : {
+ 'playHead':true,
+ 'pause':true,
+ 'stop':true,
+ 'fullscreen':true,
+ 'timeDisplay':true,
+ 'volumeControl':true,
+
+ 'playlist_driver':true, // if the object supports playlist functions
+ 'overlay':false
+ },
+
+ // The previous state of the player instance
+ prevState : 0,
+
+ // Counter for waiting for vlc embed to be ready
+ waitForVlcCount:0,
+
+ // Store the current play time for vlc
+ vlcCurrentTime: 0,
+
+ /**
+ * Get embed HTML
+ */
+ embedPlayerHTML: function() {
+ var _this = this;
+ $( this ).html(
+ '<object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" ' +
+ 'codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab#Version=0,8,6,0" ' +
+ 'id="' + this.pid + '" events="True" height="' + this.getPlayerHeight() + '" width="' + this.getPlayerWidth() + '"' +
+ '>' +
+ '<param name="MRL" value="">' +
+ '<param name="ShowDisplay" value="True">' +
+ '<param name="AutoLoop" value="False">' +
+ '<param name="AutoPlay" value="False">' +
+ '<param name="Volume" value="50">' +
+ '<param name="StartTime" value="0">' +
+ '<embed pluginspage="http://www.videolan.org" type="application/x-vlc-plugin" ' +
+ 'progid="VideoLAN.VLCPlugin.2" name="' + this.pid + '" ' +
+ 'height="' + this.getHeight() + '" width="' + this.getWidth() + '" ' +
+ // Set the style for IE layout issues )
+ 'style="width:' + this.getWidth() + 'px;height:' + this.getHeight() + 'px;" ' +
+ '>' +
+ '</object>'
+ )
+ // Call postEmbedActions directly ( postEmbedJs will wait for player ready )
+ _this.postEmbedActions();
+ },
+
+ /**
+ * Javascript to run post vlc embedding
+ * Inserts the requested src to the embed instance
+ */
+ postEmbedActions: function() {
+ var _this = this;
+ // Load a pointer to the vlc into the object (this.playerElement)
+ this.getPlayerElement();
+ if ( this.playerElement && this.playerElement.playlist) {
+ // manipulate the dom object to make sure vlc has the correct size:
+ this.playerElement.style.width = this.getWidth();
+ this.playerElement.style.height = this.getHeight();
+ this.playerElement.playlist.items.clear();
+
+ // VLC likes absolute urls:
+ var src = mw.absoluteUrl( this.getSrc() ) ;
+
+ mw.log( "EmbedPlayerVlc:: postEmbedActions play src:" + src );
+ var itemId = this.playerElement.playlist.add( src );
+ if ( itemId != -1 ) {
+ // Play
+ this.playerElement.playlist.playItem( itemId );
+ } else {
+ mw.log( "Error:: EmbedPlayerVlc can not play" );
+ }
+ setTimeout( function() {
+ _this.monitor();
+ }, 100 );
+ } else {
+ mw.log( 'EmbedPlayerVlc:: postEmbedActions: vlc not ready' );
+ this.waitForVlcCount++;
+ if ( this.waitForVlcCount < 10 ) {
+ setTimeout( function() {
+ _this.postEmbedActions();
+ }, 100 );
+ } else {
+ mw.log( 'EmbedPlayerVlc:: vlc never ready' );
+ }
+ }
+ },
+
+ /**
+ * Handles seek requests based on temporal media source type support
+ *
+ * @param {Float} percent Seek to this percent of the stream
+ */
+ seek : function( percent ) {
+ this.getPlayerElement();
+ // Use the parent (re) embed with new seek url method if urlTimeEncoding is supported.
+ if ( this.supportsURLTimeEncoding() ) {
+ this.parent_seek( percent );
+ } else if ( this.playerElement ) {
+ this.seeking = true;
+ mw.log( "EmbedPlayerVlc:: seek to: " + percent )
+ if ( ( this.playerElement.input.state == 3 ) && ( this.playerElement.input.position != percent ) )
+ {
+ this.playerElement.input.position = percent;
+ this.controlBuilder.setStatus( mw.msg('mwe-embedplayer-seeking') );
+ }
+ } else {
+ this.doPlayThenSeek( percent );
+ }
+ this.parent_monitor();
+ },
+
+ /**
+ * Issues a play request then seeks to a given time
+ *
+ * @param {Float} percent Seek to this percent of the stream after playing
+ */
+ doPlayThenSeek:function( percent ) {
+ mw.log( 'EmbedPlayerVlc:: doPlayThenSeek' );
+ var _this = this;
+ this.play();
+ var seekCount = 0;
+ var readyForSeek = function() {
+ _this.getPlayerElement();
+ var newState = _this.playerElement.input.state;
+ // If playing we are ready to do the seek
+ if ( newState == 3 ) {
+ _this.seek( percent );
+ } else {
+ // Try to get player for 10 seconds:
+ if ( seekCount < 200 ) {
+ setTimeout( readyForSeek, 50 );
+ rfsCount++;
+ } else {
+ mw.log( 'Error: EmbedPlayerVlc doPlayThenSeek failed' );
+ }
+ }
+ }
+ readyForSeek();
+ },
+
+ /**
+ * Updates the status time and player state
+ */
+ monitor: function() {
+ this.getPlayerElement();
+ if ( ! this.playerElement ){
+ return ;
+ }
+ // Try to get relay vlc log messages to the console.
+ try{
+ if ( this.playerElement.log.messages.count > 0 ) {
+ // there is one or more messages in the log
+ var iter = this.playerElement.log.messages.iterator();
+ while ( iter.hasNext ) {
+ var msg = iter.next();
+ var msgtype = msg.type.toString();
+ if ( ( msg.severity == 1 ) && ( msgtype == "input" ) )
+ {
+ mw.log( msg.message );
+ }
+ }
+ // clear the log once finished to avoid clogging
+ this.playerElement.log.messages.clear();
+ }
+
+ var newState = this.playerElement.input.state;
+ if ( this.prevState != newState ) {
+ if ( newState == 0 )
+ {
+ // current media has stopped
+ this.onStop();
+ }
+ else if ( newState == 1 )
+ {
+ // current media is opening/connecting
+ this.onOpen();
+ }
+ else if ( newState == 2 )
+ {
+ // current media is buffering data
+ this.onBuffer();
+ }
+ else if ( newState == 3 )
+ {
+ // current media is now playing
+ this.onPlay();
+ }
+ else if ( this.playerElement.input.state == 4 ) {
+ // current media is now paused
+ this.onPause();
+ }
+ this.prevState = newState;
+ } else if ( newState == 3 ) {
+ // current media is playing
+ this.onPlaying();
+ }
+ } catch( e ){
+ mw.log("EmbedPlayerVlc:: Monitor error");
+ }
+ // Update the status and check timer via universal parent monitor
+ this.parent_monitor();
+ },
+
+ /**
+ * Events:
+ */
+ onOpen: function() {
+ // Open is considered equivalent to other players buffer status:
+ this.controlBuilder.setStatus( mw.msg('mwe-embedplayer-buffering') );
+ },
+ onBuffer: function() {
+ this.controlBuilder.setStatus( mw.msg('mwe-embedplayer-buffering') );
+ },
+ onPlay: function() {
+ this.onPlaying();
+ },
+ onPlaying: function() {
+ this.seeking = false;
+ // For now trust the duration from url over vlc input.length
+ if ( !this.getDuration() && this.playerElement.input.length > 0 )
+ {
+ // mw.log('setting duration to ' + this.playerElement.input.length /1000);
+ this.duration = this.playerElement.input.length / 1000;
+ }
+ this.vlcCurrentTime = this.playerElement.input.time / 1000;
+ },
+
+ /**
+ * Get the embed player time
+ */
+ getPlayerElementTime: function(){
+ return this.vlcCurrentTime;
+ },
+
+ onPause: function() {
+ // Update the interface if paused via native plugin
+ this.parent_pause();
+ },
+ onStop: function() {
+ mw.log( 'EmbedPlayerVlc:: onStop' );
+ if ( !this.seeking ){
+ this.onClipDone();
+ }
+ },
+
+ /**
+ * Handles play requests
+ */
+ play: function() {
+ mw.log( 'EmbedPlayerVlc:: play' );
+ // Update the interface
+ this.parent_play();
+ if ( this.getPlayerElement() ) {
+ // plugin is already being present send play call:
+ // clear the message log and enable error logging
+ if ( this.playerElement.log ) {
+ this.playerElement.log.messages.clear();
+ }
+ if ( this.playerElement.playlist && typeof this.playerElement.playlist.play == 'function')
+ this.playerElement.playlist.play();
+
+ if( typeof this.playerElement.play == 'function' )
+ this.playerElement.play();
+
+ this.paused = false;
+
+ // re-start the monitor:
+ this.monitor();
+ }
+ },
+
+ /**
+ * Passes the Pause request to the plugin.
+ * calls parent "pause" to update interface
+ */
+ pause: function() {
+ this.parent_pause(); // update the interface if paused via native control
+ if ( this.getPlayerElement() ) {
+ try{
+ this.playerElement.playlist.togglePause();
+ } catch( e ){
+ mw.log("EmbedPlayerVlc:: Could not pause video " + e);
+ }
+ }
+ },
+
+ /**
+ * Mutes the video
+ * calls parent "toggleMute" to update interface
+ */
+ toggleMute:function() {
+ this.parent_toggleMute();
+ if ( this.getPlayerElement() ){
+ this.playerElement.audio.toggleMute();
+ }
+ },
+
+ /**
+ * Update the player volume
+ * @parm {Float} percent Percent of total volume
+ */
+ setPlayerElementVolume: function ( percent ) {
+ if ( this.getPlayerElement() && this.playerElement.audio ) {
+ this.playerElement.audio.volume = percent * 100;
+ }
+ },
+
+ /**
+ * Gets the current volume
+ * @return {Float} percent percent of total volume
+ */
+ getVolumen:function() {
+ if ( this.getPlayerElement() ){
+ return this.playerElement.audio.volume / 100;
+ }
+ },
+
+ /**
+ * Passes fullscreen request to plugin
+ */
+ fullscreen : function() {
+ if ( this.playerElement ) {
+ if ( this.playerElement.video ){
+ try{
+ this.playerElement.video.toggleFullscreen();
+ } catch ( e ){
+ mw.log("EmbedPlayerVlc:: toggle fullscreen : possible error: " + e);
+ }
+ }
+ }
+ },
+
+ /**
+ * Get the embed vlc object
+ */
+ getPlayerElement : function() {
+ this.playerElement = $( '#' + this.pid )[0];
+ return this.playerElement;
+ }
+};
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedTypes.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedTypes.js
new file mode 100644
index 00000000..21b2f452
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.EmbedTypes.js
@@ -0,0 +1,360 @@
+/**
+ * mw.EmbedTypes object handles setting and getting of supported embed types:
+ * closely mirrors OggHandler so that its easier to share efforts in this area:
+ * http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/OggHandler/OggPlayer.js
+ */
+( function( mw, $ ) { "use strict";
+
+/**
+ * Setup local players and supported mime types In an ideal world we would query the plugin
+ * to get what mime types it supports in practice not always reliable/available
+ *
+ * We can't cleanly store these values per library since player library is sometimes
+ * loaded post player detection
+ */
+// Flash based players:
+var kplayer = new mw.MediaPlayer('kplayer', [
+ 'video/x-flv',
+ 'video/h264',
+ 'video/mp4; codecs="avc1.42E01E"',
+ 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',
+ 'audio/mpeg'
+], 'Kplayer');
+
+// Native html5 players
+var oggNativePlayer = new mw.MediaPlayer( 'oggNative', [
+ 'video/ogg',
+ 'video/ogg; codecs="theora"',
+ 'video/ogg; codecs="theora, vorbis"',
+ 'audio/ogg',
+ 'audio/ogg; codecs="vorbis"',
+ 'application/ogg'
+], 'Native' );
+// Native html5 players
+var opusNativePlayer = new mw.MediaPlayer( 'opusNative', [
+ 'audio/ogg; codecs="opus"',
+], 'Native' );
+var h264NativePlayer = new mw.MediaPlayer( 'h264Native', [
+ 'video/h264',
+ 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
+], 'Native' );
+var appleVdnPlayer = new mw.MediaPlayer( 'appleVdn', [
+ 'application/vnd.apple.mpegurl',
+ 'application/vnd.apple.mpegurl; codecs="avc1.42E01E"'
+], 'Native');
+var mp3NativePlayer = new mw.MediaPlayer( 'mp3Native', [
+ 'audio/mpeg',
+ 'audio/mp3'
+], 'Native' );
+var aacNativePlayer = new mw.MediaPlayer( 'aacNative', [
+ 'audio/mp4',
+ 'audio/mp4; codecs="mp4a.40.5"'
+], 'Native' );
+var webmNativePlayer = new mw.MediaPlayer( 'webmNative', [
+ 'video/webm',
+ 'video/webm; codecs="vp8"',
+ 'video/webm; codecs="vp8, vorbis"',
+ 'audio/webm',
+ 'audio/webm; codecs="vorbis"'
+], 'Native' );
+var vp9NativePlayer = new mw.MediaPlayer( 'vp9Native', [
+ 'video/webm; codecs="vp9"',
+ 'video/webm; codecs="vp9, opus"',
+ 'video/webm; codecs="vp9, vorbis"',
+ 'audio/webm; codecs="opus"'
+], 'Native' );
+
+// Image Overlay player ( extends native )
+var imageOverlayPlayer = new mw.MediaPlayer( 'imageOverlay', [
+ 'image/jpeg',
+ 'image/png'
+], 'ImageOverlay' );
+
+// VLC player
+//var vlcMimeList = ['video/ogg', 'audio/ogg', 'audio/mpeg', 'application/ogg', 'video/x-flv', 'video/mp4', 'video/h264', 'video/x-msvideo', 'video/mpeg', 'video/3gp'];
+//var vlcPlayer = new mw.MediaPlayer( 'vlc-player', vlcMimeList, 'Vlc' );
+
+var vlcAppPlayer = new mw.MediaPlayer( 'vlcAppPlayer', [
+ 'video/ogg',
+ 'video/ogg; codecs="theora"',
+ 'video/ogg; codecs="theora, vorbis"',
+ 'audio/ogg',
+ 'audio/ogg; codecs="vorbis"',
+ 'audio/ogg; codecs="opus"',
+ 'application/ogg',
+ 'video/webm',
+ 'video/webm; codecs="vp8"',
+ 'video/webm; codecs="vp8, vorbis"',
+], 'VLCApp' );
+
+var IEWebMPrompt = new mw.MediaPlayer( 'IEWebMPrompt', [
+ 'video/webm',
+ 'video/webm; codecs="vp8"',
+ 'video/webm; codecs="vp8, vorbis"'
+], 'IEWebMPrompt' );
+
+var ogvJsPlayer = new mw.MediaPlayer( 'ogvJsPlayer', [
+ 'video/ogg',
+ 'video/ogg; codecs="theora"',
+ 'video/ogg; codecs="theora, vorbis"',
+ 'video/ogg; codecs="theora, opus"',
+ 'audio/ogg',
+ 'audio/ogg; codecs="vorbis"',
+ 'audio/ogg; codecs="opus"',
+ 'application/ogg'
+], 'OgvJs' );
+
+// Generic plugin
+//var oggPluginPlayer = new mw.MediaPlayer( 'oggPlugin', ['video/ogg', 'application/ogg'], 'Generic' );
+
+
+mw.EmbedTypes = {
+
+ // MediaPlayers object ( supports methods for quering set of browser players )
+ mediaPlayers: null,
+
+ // Detect flag for completion
+ detect_done:false,
+
+ /**
+ * Runs the detect method and update the detect_done flag
+ *
+ * @constructor
+ */
+ init: function() {
+ // detect supported types
+ this.detect();
+ this.detect_done = true;
+ },
+
+ getMediaPlayers: function(){
+ if( this.mediaPlayers ){
+ return this.mediaPlayers;
+ }
+ this.mediaPlayers = new mw.MediaPlayers();
+ // detect available players
+ this.detectPlayers();
+ return this.mediaPlayers;
+ },
+
+ /**
+ * If the browsers supports a given mimetype
+ *
+ * @param {String}
+ * mimeType Mime type for browser plug-in check
+ */
+ supportedMimeType: function( mimeType ) {
+ for ( var i =0; i < navigator.plugins.length; i++ ) {
+ var plugin = navigator.plugins[i];
+ if ( typeof plugin[ mimeType ] != "undefined" ){
+ return true;
+ }
+ }
+ return false;
+ },
+ addFlashPlayer: function(){
+ if( !mw.config.get( 'EmbedPlayer.DisableHTML5FlashFallback' ) ){
+ this.mediaPlayers.addPlayer( kplayer );
+ }
+ },
+ /**
+ * Detects what plug-ins the client supports
+ */
+ detectPlayers: function() {
+ mw.log( "EmbedTypes::detectPlayers running detect" );
+
+ // All players support for playing "images"
+ this.mediaPlayers.addPlayer( imageOverlayPlayer );
+
+ // Some browsers filter out duplicate mime types, hiding some plugins
+ var uniqueMimesOnly = $.client.test( { opera: null, safari: null } );
+
+ // Use core mw.supportsFlash check:
+ if( mw.supportsFlash() ){
+ this.addFlashPlayer();
+ }
+
+ // ActiveX plugins
+ if ( $.client.profile().name === 'msie' ) {
+ // VLC
+ //if ( this.testActiveX( 'VideoLAN.VLCPlugin.2' ) ) {
+ // this.mediaPlayers.addPlayer( vlcPlayer );
+ //}
+
+ // quicktime (currently off)
+ // if ( this.testActiveX(
+ // 'QuickTimeCheckObject.QuickTimeCheck.1' ) )
+ // this.mediaPlayers.addPlayer(quicktimeActiveXPlayer);
+ }
+ // <video> element
+ if ( ! mw.config.get('EmbedPlayer.DisableVideoTagSupport' ) // to support testing limited / old browsers
+ &&
+ (
+ typeof HTMLVideoElement == 'object' // Firefox, Safari
+ ||
+ typeof HTMLVideoElement == 'function' // Opera
+ )
+ ){
+ // Test what codecs the native player supports:
+ try {
+ var dummyvid = document.createElement( "video" );
+ if( dummyvid.canPlayType ) {
+ // Add the webm player
+ if( dummyvid.canPlayType('video/webm; codecs="vp8, vorbis"') ){
+ this.mediaPlayers.addPlayer( webmNativePlayer );
+ }
+ if( dummyvid.canPlayType('video/webm; codecs="vp9, opus"') ){
+ this.mediaPlayers.addPlayer( vp9NativePlayer );
+ }
+
+ // Test for MP3:
+ if ( this.supportedMimeType('audio/mpeg') ) {
+ this.mediaPlayers.addPlayer( mp3NativePlayer );
+ }
+
+ // Test for AAC:
+ if ( dummyvid.canPlayType( 'audio/mp4; codecs="mp4a.40.5"' ) ) {
+ this.mediaPlayers.addPlayer( aacNativePlayer );
+ }
+
+ // Test for h264:
+ if ( dummyvid.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"' ) ) {
+ this.mediaPlayers.addPlayer( h264NativePlayer );
+ // Check for iOS for vdn player support ( apple adaptive ) or vdn canPlayType != '' ( ie maybe/probably )
+ if( mw.isIOS() || dummyvid.canPlayType('application/vnd.apple.mpegurl; codecs="avc1.42E01E"' ) ){
+ // Android 3x lies about HLS support ( only add if not Android 3.x )
+ if( navigator.userAgent.indexOf( 'Android 3.') == -1 ){
+ this.mediaPlayers.addPlayer( appleVdnPlayer );
+ }
+ }
+
+ }
+ // For now if Android assume we support h264Native (FIXME
+ // test on real devices )
+ if ( mw.isAndroid2() ){
+ this.mediaPlayers.addPlayer( h264NativePlayer );
+ }
+
+ // Test for ogg
+ if ( dummyvid.canPlayType( 'video/ogg; codecs="theora, vorbis"' ) ||
+ dummyvid.canPlayType( 'audio/ogg; codecs="vorbis"' )
+ ) {
+ this.mediaPlayers.addPlayer( oggNativePlayer );
+ }
+
+ // Test for opus
+ if ( dummyvid.canPlayType( 'audio/ogg; codecs="opus"' ).replace(/maybe/, '') ) {
+ this.mediaPlayers.addPlayer( opusNativePlayer );
+ }
+ }
+ } catch ( e ) {
+ mw.log( 'could not run canPlayType ' + e );
+ }
+ }
+
+ // "navigator" plugins
+ if ( navigator.mimeTypes && navigator.mimeTypes.length > 0 ) {
+ for ( var i = 0; i < navigator.mimeTypes.length; i++ ) {
+ var type = navigator.mimeTypes[i].type;
+ var semicolonPos = type.indexOf( ';' );
+ if ( semicolonPos > -1 ) {
+ type = type.substr( 0, semicolonPos );
+ }
+ // mw.log( 'on type: ' + type );
+ var pluginName = navigator.mimeTypes[i].enabledPlugin ? navigator.mimeTypes[i].enabledPlugin.name : '';
+ if ( !pluginName ) {
+ // In case it is null or undefined
+ pluginName = '';
+ }
+ //if ( pluginName.toLowerCase() == 'vlc multimedia plugin' || pluginName.toLowerCase() == 'vlc multimedia plug-in' ) {
+ // this.mediaPlayers.addPlayer( vlcPlayer );
+ // continue;
+ //}
+
+ if ( (type == 'video/mpeg' || type == 'video/x-msvideo') ){
+ //pluginName.toLowerCase() == 'vlc multimedia plugin' ) {
+ //this.mediaPlayers.addPlayer( vlcMozillaPlayer );
+ }
+
+ if ( type == 'application/ogg' ) {
+ //if ( pluginName.toLowerCase() == 'vlc multimedia plugin' ) {
+ //this.mediaPlayers.addPlayer( vlcMozillaPlayer );
+ //else if ( pluginName.indexOf( 'QuickTime' ) > -1 )
+ //this.mediaPlayers.addPlayer(quicktimeMozillaPlayer);
+ //} else {
+ //this.mediaPlayers.addPlayer( oggPluginPlayer );
+ //}
+ continue;
+ } else if ( uniqueMimesOnly ) {
+ if ( type == 'application/x-vlc-player' ) {
+ // this.mediaPlayers.addPlayer( vlcMozillaPlayer );
+ continue;
+ } else if ( type == 'video/quicktime' ) {
+ // this.mediaPlayers.addPlayer(quicktimeMozillaPlayer);
+ continue;
+ }
+ }
+ }
+ }
+
+ if ( mw.isIOS() ) {
+ this.mediaPlayers.addPlayer( vlcAppPlayer );
+ }
+
+ // Note IE 11 doesn't identify itself as 'MSIE'.
+ // For simplicity just check for the rendering engine codename 'Trident'.
+ if ( navigator.userAgent.indexOf( 'Trident' ) != -1 ) {
+ if ( this.mediaPlayers.isSupportedPlayer( 'webmNative' ) ) {
+ // IE has the WebM components already, leave it be!
+ } else if ( navigator.userAgent.indexOf( 'ARM' ) != -1 ) {
+ // Windows RT doesn't allow installation of the WebM components.
+ // Don't tease the poor user.
+ } else {
+ // Prompt user to install the WebM media components for IE 9+
+ this.mediaPlayers.addPlayer( IEWebMPrompt );
+ }
+ }
+
+ // ogv.js compatibility detection...
+ if ( OGVCompat.supported( 'OGVPlayer' ) ) {
+ // ogv.js emscripten version
+ //
+ // Works in:
+ // * Safari 6.1+ on Mac OS X
+ // * Safari on iOS 8+ (best on 64-bit devices)
+ // * IE 10/11 on Windows 7/8/8.1 (requires Flash for audio)
+ // * Edge on Windows 10 (no plugins needed)
+ //
+ // Current Firefox, Chrome, Opera all work great too, but use
+ // native playback by default of course!
+ //
+ this.mediaPlayers.addPlayer( ogvJsPlayer );
+ }
+
+ // Allow extensions to detect and add their own "players"
+ mw.log("EmbedPlayer::trigger:embedPlayerUpdateMediaPlayersEvent");
+ $( mw ).trigger( 'embedPlayerUpdateMediaPlayersEvent' , this.mediaPlayers );
+
+ },
+
+ /**
+ * Test IE for activeX by name
+ *
+ * @param {String}
+ * name Name of ActiveXObject to look for
+ */
+ testActiveX : function ( name ) {
+ mw.log("EmbedPlayer::detect: test testActiveX: " + name);
+ var hasObj = true;
+ try {
+ // No IE, not a class called "name", it's a variable
+ var obj = new ActiveXObject( '' + name );
+ } catch ( e ) {
+ hasObj = false;
+ }
+ return hasObj;
+ }
+};
+
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaElement.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaElement.js
new file mode 100644
index 00000000..9af48998
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaElement.js
@@ -0,0 +1,491 @@
+/**
+ * A media element corresponding to a <video> element.
+ *
+ * It is implemented as a collection of mediaSource objects. The media sources
+ * will be initialized from the <video> element, its child <source> elements,
+ * and/or the ROE file referenced by the <video> element.
+ *
+ * @param {element}
+ * videoElement <video> element used for initialization.
+ * @constructor
+ */
+( function( mw, $ ) { "use strict";
+
+mw.MediaElement = function( element ) {
+ this.init( element );
+};
+
+mw.MediaElement.prototype = {
+
+ // The array of mediaSource elements.
+ sources: null,
+
+ // flag for ROE data being added.
+ addedROEData: false,
+
+ // Selected mediaSource element.
+ selectedSource: null,
+
+ /**
+ * Media Element constructor
+ *
+ * Sets up a mediaElement from a provided top level "video" element adds any
+ * child sources that are found
+ *
+ * @param {Element}
+ * videoElement Element that has src attribute or has children
+ * source elements
+ */
+ init: function( videoElement ) {
+ var _this = this;
+ mw.log( "EmbedPlayer::mediaElement:init:" + videoElement.id );
+ this.parentEmbedId = videoElement.id;
+ this.sources = new Array();
+
+ // Process the videoElement as a source element:
+ if( videoElement ){
+ if ( $( videoElement ).attr( "src" ) ) {
+ _this.tryAddSource( videoElement );
+ }
+ // Process elements source children
+ $( videoElement ).find( 'source,track' ).each( function( ) {
+ _this.tryAddSource( this );
+ } );
+ }
+ },
+
+ /**
+ * Updates the time request for all sources that have a standard time
+ * request argument (ie &t=start_time/end_time)
+ *
+ * @param {String}
+ * startNpt Start time in npt format
+ * @param {String}
+ * endNpt End time in npt format
+ */
+ updateSourceTimes: function( startNpt, endNpt ) {
+ var _this = this;
+ $.each( this.sources, function( inx, mediaSource ) {
+ mediaSource.updateSrcTime( startNpt, endNpt );
+ } );
+ },
+
+ /**
+ * Get Text tracks
+ */
+ getTextTracks: function(){
+ var textTracks = [];
+ $.each( this.sources, function(inx, source ){
+ if ( source.nodeName == 'track' || ( source.mimeType && source.mimeType.indexOf('text/') !== -1 )){
+ textTracks.push( source );
+ }
+ });
+ return textTracks;
+ },
+ /**
+ * Returns the array of mediaSources of this element.
+ *
+ * @param {String}
+ * [mimeFilter] Filter criteria for set of mediaSources to return
+ * @return {Array} mediaSource elements.
+ */
+ getSources: function( mimeFilter ) {
+ if ( !mimeFilter ) {
+ return this.sources;
+ }
+ // Apply mime filter:
+ var source_set = new Array();
+ for ( var i = 0; i < this.sources.length ; i++ ) {
+ if ( this.sources[i].mimeType &&
+ this.sources[i].mimeType.indexOf( mimeFilter ) != -1 )
+ {
+ source_set.push( this.sources[i] );
+ }
+ }
+ return source_set;
+ },
+
+ /**
+ * Selects a source by id
+ *
+ * @param {String}
+ * sourceId Id of the source to select.
+ * @return {MediaSource} The selected mediaSource or null if not found
+ */
+ getSourceById:function( sourceId ) {
+ for ( var i = 0; i < this.sources.length ; i++ ) {
+ if ( this.sources[i].id == sourceId ) {
+ return this.sources[i];
+ }
+ }
+ return null;
+ },
+
+ /**
+ * Selects a particular source for playback updating the "selectedSource"
+ *
+ * @param {Number}
+ * index Index of source element to set as selectedSource
+ */
+ setSourceByIndex: function( index ) {
+ mw.log( 'EmbedPlayer::mediaElement:selectSource: ' + index );
+ var oldSrc = this.selectedSource.getSrc();
+ var playableSources = this.getPlayableSources();
+ for ( var i = 0; i < playableSources.length; i++ ) {
+ if ( i == index ) {
+ this.selectedSource = playableSources[i];
+ break;
+ }
+ }
+ if( oldSrc != this.selectedSource.getSrc() ){
+ $( '#' + this.parentEmbedId ).trigger( 'SourceChange');
+ }
+ },
+ /**
+ * Sets a the selected source to passed in source object
+ * @param {Object} Source
+ */
+ setSource: function( source ){
+ var oldSrc = this.selectedSource.getSrc();
+ this.selectedSource = source;
+ if( oldSrc != this.selectedSource.getSrc() ){
+ $( '#' + this.parentEmbedId ).trigger( 'SourceChange');
+ }
+ },
+
+
+ /**
+ * Selects the default source via cookie preference, default marked, or by
+ * id order
+ */
+ autoSelectSource: function() {
+ mw.log( 'EmbedPlayer::mediaElement::autoSelectSource' );
+ var _this = this;
+ // Select the default source
+ var playableSources = this.getPlayableSources();
+ var flash_flag = false, ogg_flag = false;
+ // Check if there are any playableSources
+ if( playableSources.length == 0 ){
+ return false;
+ }
+ var setSelectedSource = function( source ){
+ _this.selectedSource = source;
+ return _this.selectedSource;
+ };
+
+ // Set via module driven preference:
+ $( this ).trigger( 'onSelectSource', playableSources );
+
+ if( _this.selectedSource ){
+ mw.log('MediaElement::autoSelectSource: Set via trigger::' + _this.selectedSource.getTitle() );
+ return _this.selectedSource;
+ }
+
+ // Set via marked default:
+ $.each( playableSources, function( inx, source ){
+ if ( source.markedDefault ) {
+ mw.log( 'MediaElement::autoSelectSource: Set via marked default: ' + source.markedDefault );
+ return setSelectedSource( source );;
+ }
+ });
+
+ // Set apple adaptive ( if available )
+ var vndSources = this.getPlayableSources('application/vnd.apple.mpegurl')
+ if( vndSources.length && mw.EmbedTypes.getMediaPlayers().getMIMETypePlayers( 'application/vnd.apple.mpegurl' ).length ){
+ // Check for device flags:
+ var desktopVdn, mobileVdn;
+ $.each( vndSources, function( inx, source) {
+ // Kaltura tags vdn sources with iphonenew
+ if( source.getFlavorId() && source.getFlavorId().toLowerCase() == 'iphonenew' ){
+ mobileVdn = source;
+ } else {
+ desktopVdn = source;
+ }
+ })
+ // NOTE: We really should not have two VDN sources the point of vdn is to be a set of adaptive streams.
+ // This work around is a result of Kaltura HLS stream tagging
+ if( mw.isIphone() && mobileVdn ){
+ setSelectedSource( mobileVdn );
+ } else if( desktopVdn ){
+ setSelectedSource( desktopVdn );
+ }
+ }
+ if ( this.selectedSource ) {
+ mw.log('MediaElement::autoSelectSource: Set via Adaptive HLS: source flavor id:' + _this.selectedSource.getFlavorId() + ' src: ' + _this.selectedSource.getSrc() );
+ return this.selectedSource;
+ }
+
+ // Set via user bandwidth pref will always set source to closest bandwidth allocation while not going over EmbedPlayer.UserBandwidth
+ if( $.cookie('EmbedPlayer.UserBandwidth') ){
+ var bandwidthDelta = 999999999;
+ var bandwidthTarget = $.cookie('EmbedPlayer.UserBandwidth');
+ $.each( playableSources, function(inx, source ){
+ if( source.bandwidth ){
+ // Check if a native source ( takes president over bandwidth selection )
+ var player = mw.EmbedTypes.getMediaPlayers().defaultPlayer( source.mimeType );
+ if ( !player || player.library != 'Native' ) {
+ // continue
+ return true;
+ }
+
+ if( Math.abs( source.bandwidth - bandwidthTarget ) < bandwidthDelta ){
+ bandwidthDelta = Math.abs( source.bandwidth - bandwidthTarget );
+ setSelectedSource( source );
+ }
+ }
+ });
+ }
+
+ if ( this.selectedSource ) {
+ mw.log('MediaElement::autoSelectSource: Set via bandwidth prefrence: source ' + this.selectedSource.bandwidth + ' user: ' + $.cookie('EmbedPlayer.UserBandwidth') );
+ return this.selectedSource;
+ }
+
+
+ // If we have at least one native source, throw out non-native sources
+ // for size based source selection:
+ var nativePlayableSources = [];
+ $.each( playableSources, function(inx, source ){
+ var mimeType = source.mimeType;
+ var player = mw.EmbedTypes.getMediaPlayers().defaultPlayer( mimeType );
+ if ( player && player.library == 'Native' ) {
+ nativePlayableSources.push( source );
+ }
+ });
+
+ // Prefer native playback ( and prefer WebM over ogg and h.264 )
+ var namedSourceSet = {};
+ var useBogoSlow = false; // use benchmark only for ogv.js
+ $.each( playableSources, function(inx, source ){
+ var mimeType = source.mimeType;
+ var player = mw.EmbedTypes.getMediaPlayers().defaultPlayer( mimeType );
+ if ( player && ( player.library == 'Native' || player.library == 'OgvJs' ) ) {
+ switch( player.id ){
+ case 'mp3Native':
+ var shortName = 'mp3';
+ break;
+ case 'aacNative':
+ var shortName = 'aac';
+ break;
+ case 'oggNative':
+ var shortName = 'ogg';
+ break;
+ case 'ogvJsPlayer':
+ useBogoSlow = true;
+ var shortName = 'ogg';
+ break;
+ case 'webmNative':
+ var shortName = 'webm';
+ break;
+ case 'vp9Native':
+ var shortName = 'vp9';
+ break;
+ case 'h264Native':
+ var shortName = 'h264';
+ break;
+ case 'appleVdn':
+ var shortName = 'appleVdn';
+ break;
+ }
+ if( !namedSourceSet[ shortName ] ){
+ namedSourceSet[ shortName ] = [];
+ }
+ namedSourceSet[ shortName ].push( source );
+ }
+ });
+
+ var codecPref = mw.config.get( 'EmbedPlayer.CodecPreference');
+
+ // if on android 4 use mp4 over webm
+ if( mw.isAndroid40() ){
+ if( codecPref && codecPref[0] == 'webm' ){
+ codecPref[0] = 'h264';
+ codecPref[1] = 'webm';
+ }
+ }
+
+ if( codecPref ){
+ for(var i =0; i < codecPref.length; i++){
+ var codec = codecPref[ i ];
+ if( ! namedSourceSet[ codec ] ){
+ continue;
+ }
+ if( namedSourceSet[ codec ].length == 1 ){
+ mw.log('MediaElement::autoSelectSource: Set 1 source via EmbedPlayer.CodecPreference: ' + namedSourceSet[ codec ][0].getTitle() );
+ return setSelectedSource( namedSourceSet[ codec ][0] );
+ } else if( namedSourceSet[ codec ].length > 1 ) {
+ // select based on size:
+ // Set via embed resolution closest to relative to display size
+ var minSizeDelta = null;
+
+ // unless we're really slow...
+ var isBogoSlow = useBogoSlow && OGVCompat.isSlow();
+
+ if( this.parentEmbedId ){
+ var displayWidth = $('#' + this.parentEmbedId).width();
+ $.each( namedSourceSet[ codec ], function(inx, source ){
+ if ( ( isBogoSlow && source.height > 240 )
+ || (useBogoSlow && source.height > 360 ) ) {
+ // On iOS or slow Windows devices, large videos decoded in JavaScript are a bad idea!
+ // continue
+ return true;
+ }
+ if( source.width && displayWidth ){
+ var sizeDelta = Math.abs( source.width - displayWidth );
+ mw.log('MediaElement::autoSelectSource: size delta : ' + sizeDelta + ' for s:' + source.width );
+ if( minSizeDelta == null || sizeDelta < minSizeDelta){
+ minSizeDelta = sizeDelta;
+ setSelectedSource( source );
+ }
+ }
+ });
+ }
+ // If we found a source via display size return:
+ if ( this.selectedSource ) {
+ mw.log('MediaElement::autoSelectSource: from ' + this.selectedSource.mimeType + ' because of resolution:' + this.selectedSource.width + ' close to: ' + displayWidth );
+ return this.selectedSource;
+ }
+ // if no size info is set just select the first source:
+ if( namedSourceSet[ codec ][0] ){
+ return setSelectedSource( namedSourceSet[ codec ][0] );
+ }
+ }
+ };
+ }
+
+ // Set h264 via native or flash fallback
+ $.each( playableSources, function(inx, source ){
+ var mimeType = source.mimeType;
+ var player = mw.EmbedTypes.getMediaPlayers().defaultPlayer( mimeType );
+ if ( mimeType == 'video/h264'
+ && player
+ && (
+ player.library == 'Native'
+ ||
+ player.library == 'Kplayer'
+ )
+ ) {
+ if( source ){
+ mw.log('MediaElement::autoSelectSource: Set h264 via native or flash fallback:' + source.getTitle() );
+ return setSelectedSource( source );
+ }
+ }
+ });
+
+ // Else just select the first playable source
+ if ( !this.selectedSource && playableSources[0] ) {
+ mw.log( 'MediaElement::autoSelectSource: Set via first source: ' + playableSources[0].getTitle() + ' mime: ' + playableSources[0].getMIMEType() );
+ return setSelectedSource( playableSources[0] );
+ }
+ // No Source found so no source selected
+ return false;
+ },
+
+ /**
+ * check if the mime is ogg
+ */
+ isOgg: function( mimeType ){
+ if ( mimeType == 'video/ogg'
+ || mimeType == 'ogg/video'
+ || mimeType == 'video/annodex'
+ || mimeType == 'application/ogg'
+ ) {
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Returns the thumbnail URL for the media element.
+ *
+ * @returns {String} thumbnail URL
+ */
+ getPosterSrc: function( ) {
+ return this.poster;
+ },
+
+ /**
+ * Checks whether there is a stream of a specified MIME type.
+ *
+ * @param {String}
+ * mimeType MIME type to check.
+ * @return {Boolean} true if sources include MIME false if not.
+ */
+ hasStreamOfMIMEType: function( mimeType )
+ {
+ for ( var i = 0; i < this.sources.length; i++ )
+ {
+ if ( this.sources[i].getMIMEType() == mimeType ){
+ return true;
+ }
+ }
+ return false;
+ },
+
+ /**
+ * Checks if media is a playable type
+ */
+ isPlayableType: function( mimeType ) {
+ // mw.log("isPlayableType:: " + mimeType);
+ if ( mw.EmbedTypes.getMediaPlayers().defaultPlayer( mimeType ) ) {
+ mw.log("isPlayableType:: " + mimeType);
+ return true;
+ } else {
+ return false;
+ }
+ },
+
+ /**
+ * Adds a single mediaSource using the provided element if the element has a
+ * 'src' attribute.
+ *
+ * @param {Element}
+ * element <video>, <source> or <mediaSource> <text> element.
+ */
+ tryAddSource: function( element ) {
+ //mw.log( 'mw.MediaElement::tryAddSource:' + $( element ).attr( "src" ) );
+ var newSrc = $( element ).attr( 'src' );
+ if ( newSrc ) {
+ // Make sure an existing element with the same src does not already exist:
+ for ( var i = 0; i < this.sources.length; i++ ) {
+ if ( this.sources[i].src == newSrc ) {
+ // Source already exists update any new attr:
+ this.sources[i].updateSource( element );
+ return this.sources[i];
+ }
+ }
+ }
+ // Create a new source
+ var source = new mw.MediaSource( element );
+
+ this.sources.push( source );
+ //mw.log( 'tryAddSource: added source ::' + source + 'sl:' + this.sources.length );
+ return source;
+ },
+
+ /**
+ * Get playable sources
+ *
+ *@pram mimeFilter {=string} (optional) Filter the playable sources set by mime filter
+ *
+ * @returns {Array} of playable media sources
+ */
+ getPlayableSources: function( mimeFilter ) {
+ var playableSources = [];
+ for ( var i = 0; i < this.sources.length; i++ ) {
+ if ( this.isPlayableType( this.sources[i].mimeType )
+ &&
+ ( !mimeFilter || this.sources[i].mimeType.indexOf( mimeFilter) != -1 )
+ ){
+ playableSources.push( this.sources[i] );
+ }
+ };
+ mw.log( "MediaElement::GetPlayableSources mimeFilter:" + mimeFilter + " " +
+ playableSources.length + ' sources playable out of ' + this.sources.length );
+
+ return playableSources;
+ }
+};
+
+} )( mediaWiki, jQuery );
+
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaPlayer.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaPlayer.js
new file mode 100644
index 00000000..94ef9708
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaPlayer.js
@@ -0,0 +1,85 @@
+/**
+ * mediaPlayer represents a media player plugin.
+ *
+ * @param {String}
+ * id id used for the plugin.
+ * @param {Array}
+ * supportedTypes an array of supported MIME types.
+ * @param {String}
+ * library external script containing the plugin interface code.
+ * @constructor
+ */
+( function( mw, $ ) { "use strict";
+
+mw.MediaPlayer = function( id, supportedTypes, library )
+{
+ this.id = id;
+ this.supportedTypes = supportedTypes;
+ this.library = library;
+ this.loaded = false;
+ this.loading_callbacks = new Array();
+ return this;
+};
+mw.MediaPlayer.prototype = {
+ // Id of the mediaPlayer
+ id:null,
+
+ // Mime types supported by this player
+ supportedTypes:null,
+
+ // Player library ie: native, vlc etc.
+ library:null,
+
+ // Flag stores the mediaPlayer load state
+ loaded:false,
+
+ /**
+ * Checks support for a given MIME type
+ *
+ * @param {String}
+ * type Mime type to check against supportedTypes
+ * @return {Boolean} true if mime type is supported false if mime type is
+ * unsupported
+ */
+ supportsMIMEType: function( type ) {
+ for ( var i = 0; i < this.supportedTypes.length; i++ ) {
+ if ( this.supportedTypes[i] == type )
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Get the "name" of the player from a predictable msg key
+ */
+ getName: function() {
+ // Give grep a chance to find the usages:
+ // mwe-embedplayer-ogg-player-vlc-player, mwe-embedplayer-ogg-player-oggNative, mwe-embedplayer-ogg-player-mp3Native,
+ // mwe-embedplayer-ogg-player-aacNative, mwe-embedplayer-ogg-player-h264Native, mwe-embedplayer-ogg-player-webmNative,
+ // mwe-embedplayer-ogg-player-oggPlugin, mwe-embedplayer-ogg-player-quicktime-mozilla,
+ // mwe-embedplayer-ogg-player-quicktime-activex, mwe-embedplayer-ogg-player-cortado,
+ // mwe-embedplayer-ogg-player-flowplayer, mwe-embedplayer-ogg-player-kplayer, mwe-embedplayer-ogg-player-selected,
+ // mwe-embedplayer-ogg-player-omtkplayer
+ return mw.msg( 'mwe-embedplayer-ogg-player-' + this.id );
+ },
+
+ /**
+ * Loads the player library & player skin config ( if needed ) and then
+ * calls the callback.
+ *
+ * @param {Function}
+ * callback Function to be called once player library is loaded.
+ */
+ load: function( callback ) {
+ // Load player library ( upper case the first letter of the library )
+ mw.load( [
+ 'mw.EmbedPlayer' + this.library.substr(0,1).toUpperCase() + this.library.substr(1)
+ ], function() {
+ if( callback ){
+ callback();
+ }
+ } );
+ }
+};
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaPlayers.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaPlayers.js
new file mode 100644
index 00000000..9d1e34f4
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaPlayers.js
@@ -0,0 +1,195 @@
+/**
+ * mediaPlayers is a collection of mediaPlayer objects supported by the client.
+ *
+ * @constructor
+ */
+( function( mw, $ ) { "use strict";
+
+mw.MediaPlayers = function(){
+ this.init();
+};
+
+mw.MediaPlayers.prototype = {
+ // The list of players supported
+ players : null,
+
+ // Store per mime-type preferences for players
+ preference : { },
+
+ // Stores the default set of players for a given mime type
+ defaultPlayers : { },
+
+ /**
+ * Initializartion function sets the default order for players for a given
+ * mime type
+ */
+ init: function() {
+ this.players = new Array();
+ this.loadPreferences();
+
+ // Set up default players order for each library type
+ this.defaultPlayers['video/x-flv'] = ['Kplayer', 'Vlc'];
+ this.defaultPlayers['video/h264'] = ['Native', 'Kplayer', 'Vlc'];
+
+ this.defaultPlayers['application/vnd.apple.mpegurl'] = ['Native'];
+
+ this.defaultPlayers['video/ogg'] = ['Native', 'Vlc', 'OgvJs', 'Generic', 'VLCApp'];
+ this.defaultPlayers['audio/webm'] = ['Native', 'Vlc', 'VLCApp', 'IEWebMPrompt'];
+ this.defaultPlayers['video/webm'] = ['Native', 'Vlc', 'VLCApp', 'IEWebMPrompt'];
+ this.defaultPlayers['application/ogg'] = ['Native', 'Vlc', 'OgvJs', 'Generic', 'VLCApp'];
+ this.defaultPlayers['audio/ogg'] = ['Native', 'Vlc', 'OgvJs', 'VLCApp'];
+ this.defaultPlayers['audio/mpeg']= ['Native', 'Kplayer'];
+ this.defaultPlayers['audio/mp3']= ['Native', 'Kplayer'];
+ this.defaultPlayers['audio/mp4']= ['Native'];
+ this.defaultPlayers['video/mp4'] = ['Native', 'Vlc'];
+ this.defaultPlayers['video/mpeg'] = ['Vlc'];
+ this.defaultPlayers['video/x-msvideo'] = ['Vlc'];
+
+ // this.defaultPlayers['text/html'] = ['Html'];
+ //this.defaultPlayers['image/svg'] = ['ImageOverlay'];
+
+ this.defaultPlayers['image/jpeg'] = ['ImageOverlay'];
+ this.defaultPlayers['image/png'] = ['ImageOverlay'];
+
+ },
+
+ /**
+ * Adds a Player to the player list
+ *
+ * @param {Object}
+ * player Player object to be added
+ */
+ addPlayer: function( player ) {
+ for ( var i = 0; i < this.players.length; i++ ) {
+ if ( this.players[i].id == player.id ) {
+ // Player already found
+ return ;
+ }
+ }
+ // Add the player:
+ this.players.push( player );
+ },
+
+ /**
+ * Checks if a player is supported by id
+ */
+ isSupportedPlayer: function( playerId ){
+ for( var i=0; i < this.players.length; i++ ){
+ if( this.players[i].id == playerId ){
+ return true;
+ }
+ }
+ return false;
+ },
+
+ /**
+ * get players that support a given mimeType
+ *
+ * @param {String}
+ * mimeType Mime type of player set
+ * @return {Array} Array of players that support a the requested mime type
+ */
+ getMIMETypePlayers: function( mimeType ) {
+ var mimePlayers = new Array();
+ var _this = this;
+ var baseMimeType = mimeType.split( ';' )[0];
+ if ( this.defaultPlayers[ baseMimeType ] ) {
+ $.each( this.defaultPlayers[ baseMimeType ], function( d, lib ) {
+ var library = _this.defaultPlayers[ baseMimeType ][ d ];
+ for ( var i = 0; i < _this.players.length; i++ ) {
+ if ( _this.players[i].library == library && _this.players[i].supportsMIMEType( mimeType ) ) {
+ mimePlayers.push( _this.players[i] );
+ }
+ }
+ } );
+ }
+ return mimePlayers;
+ },
+
+ /**
+ * Default player for a given mime type
+ *
+ * @param {String}
+ * mimeType Mime type of the requested player
+ * @return Player for mime type null if no player found
+ */
+ defaultPlayer : function( mimeType ) {
+ // mw.log( "get defaultPlayer for " + mimeType );
+ var mimePlayers = this.getMIMETypePlayers( mimeType );
+ if ( mimePlayers.length > 0 )
+ {
+ // Select the default player:
+ for ( var i = 0; i < mimePlayers.length; i++ ) {
+ // Check for native:
+ if( mimePlayers[i].librayr == 'Native' ){
+ return mimePlayers[i];
+ }
+ // else check for preference
+ if ( mimePlayers[i].id == this.preference[mimeType] ){
+ return mimePlayers[i];
+ }
+ }
+ // Otherwise just return the first compatible player
+ // (it will be chosen according to the defaultPlayers list
+ return mimePlayers[0];
+ }
+ // mw.log( 'No default player found for ' + mimeType );
+ return null;
+ },
+
+ /**
+ * Sets the format preference.
+ *
+ * @param {String}
+ * mimeFormat Prefered format
+ */
+ setFormatPreference : function ( mimeFormat ) {
+ this.preference['formatPreference'] = mimeFormat;
+ $.cookie( 'EmbedPlayer.Preference', JSON.stringify( this.preference) );
+ },
+
+ /**
+ * Loads the user preference settings from a cookie
+ */
+ loadPreferences : function ( ) {
+ this.preference = { };
+ // See if we have a cookie set to a clientSupported type:
+ if( $.cookie( 'EmbedPlayer.Preference' ) ) {
+ this.preference = JSON.parse( $.cookie( 'EmbedPlayer.Preference' ) );
+ }
+ },
+
+ /**
+ * Sets the player preference
+ *
+ * @param {String}
+ * playerId Preferred player id
+ * @param {String}
+ * mimeType Mime type for the associated player stream
+ */
+ setPlayerPreference : function( playerId, mimeType ) {
+ var selectedPlayer = null;
+ for ( var i = 0; i < this.players.length; i++ ) {
+ if ( this.players[i].id == playerId ) {
+ selectedPlayer = this.players[i];
+ mw.log( 'EmbedPlayer::setPlayerPreference: choosing ' + playerId + ' for ' + mimeType );
+ this.preference[ mimeType ] = playerId;
+ $.cookie( 'EmbedPlayer.Preference', JSON.stringify( this.preference ) );
+ break;
+ }
+ }
+ // Update All the player instances on the page
+ if ( selectedPlayer ) {
+ $('.mwEmbedPlayer').each(function(inx, playerTarget ){
+ var embedPlayer = $( playerTarget ).get( 0 );
+ if ( embedPlayer.mediaElement.selectedSource
+ && ( embedPlayer.mediaElement.selectedSource.mimeType == mimeType ) )
+ {
+ embedPlayer.selectPlayer( selectedPlayer );
+ }
+ });
+ }
+ }
+};
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaSource.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaSource.js
new file mode 100644
index 00000000..9449a5d4
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.MediaSource.js
@@ -0,0 +1,490 @@
+/**
+ * mediaSource class represents a source for a media element.
+ *
+ * @param {Element}
+ * element: MIME type of the source.
+ * @constructor
+ */
+
+/**
+ * The base source attribute checks also see:
+ * http://dev.w3.org/html5/spec/Overview.html#the-source-element
+ */
+
+( function( mw, $ ) { "use strict";
+
+mw.mergeConfig( 'EmbedPlayer.SourceAttributes', [
+ // source id
+ 'id',
+
+ // media url
+ 'src',
+
+ // Title string for the source asset
+ 'title',
+
+ // boolean if we support temporal url requests on the source media
+ 'URLTimeEncoding',
+
+ // Store the node name for type identification
+ 'nodeName',
+
+ /**
+ * data- attributes ( not yet standards )
+ */
+
+ // Media has a startOffset ( used for plugins that
+ // display ogg page time rather than presentation time
+ 'data-startoffset',
+
+ // A hint to the duration of the media file so that duration
+ // can be displayed in the player without loading the media file
+ 'data-durationhint',
+
+ // Source stream qualities
+ // NOTE data- is striped from the attribute as we build out the "mediaSource" object
+ 'data-shorttitle', // short title for stream ( useful for stream switching control bar widget)
+ 'data-width', // the width of the stream
+ 'data-height', // the height of the stream
+ 'data-bandwidth', // the overall bitrate of the stream in bytes
+ 'data-sizebytes', // the size of the stream in bytes
+ 'data-framerate', // the framereate of the stream
+ 'data-flavorid', // a source flavor id ( useful for targeting devices )
+ 'data-aspect', // the aspect ratio, useful for adaptive protocal urls that don't have a strict height / width
+
+ // Used as title in download panel
+ 'data-title',
+
+ // Used for download attribute on mediawiki
+ 'data-mwtitle',
+ // used for setting the api provider for mediawiki
+ 'data-mwprovider',
+
+ // to disable menu or timedText for a given embed
+ 'data-disablecontrols',
+
+ // used for language direction of subtitles
+ 'data-dir',
+
+ // Media start time
+ 'start',
+
+ // Media end time
+ 'end',
+
+ // If the source is the default source
+ 'default'
+] );
+
+mw.MediaSource = function( element ) {
+ this.init( element );
+};
+
+mw.MediaSource.prototype = {
+ // MIME type of the source.
+ mimeType:null,
+
+ // URI of the source.
+ uri:null,
+
+ // Title of the source.
+ title: null,
+
+ // True if the source has been marked as the default.
+ markedDefault: false,
+
+ // True if the source supports url specification of offset and duration
+ URLTimeEncoding:false,
+
+ // Start offset of the requested segment
+ startOffset: 0,
+
+ // Duration of the requested segment (0 if not known)
+ duration:0,
+
+ // source id
+ id: null,
+
+ // Start time in npt format
+ startNpt: null,
+
+ // End time in npt format
+ endNpt: null,
+
+ // Language of the file
+ srclang: null,
+ /**
+ * MediaSource constructor:
+ */
+ init : function( element ) {
+ var _this = this;
+ // mw.log('EmbedPlayer::adding mediaSource: ' + element);
+ this.src = $( element ).attr( 'src' );
+
+ // Set default URLTimeEncoding if we have a time url:
+ // not ideal way to discover if content is on an oggz_chop server.
+ // should check some other way.
+ var pUrl = new mw.Uri ( this.src );
+ if ( typeof pUrl.query[ 't' ] != 'undefined' ) {
+ this.URLTimeEncoding = true;
+ }
+
+ var sourceAttr = mw.config.get( 'EmbedPlayer.SourceAttributes' );
+ $.each( sourceAttr, function( inx, attr ){
+ if ( $( element ).attr( attr ) ) {
+ // strip data- from the attribute name
+ var attrName = ( attr.indexOf('data-') === 0) ? attr.substr(5) : attr
+ _this[ attrName ] = $( element ).attr( attr );
+ }
+ });
+
+ // Normalize "label" to "title" ( label is the actual spec so use that over title )
+ if( this.label ){
+ this.title = this.label;
+ }
+
+ // Set the content type:
+ if ( $( element ).attr( 'type' ) ) {
+ this.mimeType = $( element ).attr( 'type' );
+ }else if ( $( element ).attr( 'content-type' ) ) {
+ this.mimeType = $( element ).attr( 'content-type' );
+ }else if( $( element )[0].tagName.toLowerCase() == 'audio' ){
+ // If the element is an "audio" tag set audio format
+ this.mimeType = 'audio/ogg';
+ } else {
+ this.mimeType = this.detectType( this.src );
+ }
+
+ // Conform the mime type to ogg
+ if( this.mimeType == 'video/theora') {
+ this.mimeType = 'video/ogg';
+ }
+
+ if( this.mimeType == 'audio/vorbis') {
+ this.mimeType = 'audio/ogg';
+ }
+
+ // Check for parent elements ( supplies categories in "track" )
+ if( $( element ).parent().attr('category') ) {
+ this.category = $( element ).parent().attr('category');
+ }
+
+ if( $( element ).attr( 'default' ) ){
+ this.markedDefault = true;
+ }
+
+ // Get the url duration ( if applicable )
+ this.getURLDuration();
+ },
+
+ /**
+ * Update Source title via Element
+ *
+ * @param {Element}
+ * element Source element to update attributes from
+ */
+ updateSource: function( element ) {
+ // for now just update the title:
+ if ( $( element ).attr( "title" ) ) {
+ this.title = $( element ).attr( "title" );
+ }
+ },
+
+ /**
+ * Updates the src time and start & end
+ *
+ * @param {String}
+ * start_time: in NPT format
+ * @param {String}
+ * end_time: in NPT format
+ */
+ updateSrcTime: function ( startNpt, endNpt ) {
+ // mw.log("f:updateSrcTime: "+ startNpt+'/'+ endNpt + ' from org: ' +
+ // this.startNpt+ '/'+this.endNpt);
+ // mw.log("pre uri:" + this.src);
+ // if we have time we can use:
+ if ( this.URLTimeEncoding ) {
+ // make sure its a valid start time / end time (else set default)
+ if ( !mw.npt2seconds( startNpt ) ) {
+ startNpt = this.startNpt;
+ }
+
+ if ( !mw.npt2seconds( endNpt ) ) {
+ endNpt = this.endNpt;
+ }
+
+ this.src = mw.replaceUrlParams( this.src, {
+ 't': startNpt + '/' + endNpt
+ });
+
+ // update the duration
+ this.getURLDuration();
+ }
+ },
+
+ /**
+ * Sets the duration and sets the end time if unset
+ *
+ * @param {Float}
+ * duration: in seconds
+ */
+ setDuration: function ( duration ) {
+ this.duration = duration;
+ if ( !this.endNpt ) {
+ this.endNpt = mw.seconds2npt( this.startOffset + duration );
+ }
+ },
+
+ /**
+ * MIME type accessor function.
+ *
+ * @return {String} the MIME type of the source.
+ */
+ getMIMEType: function() {
+ if( this.mimeType ) {
+ return this.mimeType;
+ }
+ this.mimeType = this.detectType( this.src );
+ return this.mimeType;
+ },
+ /**
+ * Update the local src
+ * @param {String}
+ * src The URL to the media asset
+ */
+ setSrc: function( src ){
+ this.src = src;
+ },
+
+ /**
+ * URI function.
+ *
+ * @param {Number}
+ * serverSeekTime Int: Used to adjust the URI for url based
+ * seeks)
+ * @return {String} the URI of the source.
+ */
+ getSrc: function( serverSeekTime ) {
+ if ( !serverSeekTime || !this.URLTimeEncoding ) {
+ return this.src;
+ }
+ var endvar = '';
+ if ( this.endNpt ) {
+ endvar = '/' + this.endNpt;
+ }
+ return mw.replaceUrlParams( this.src,
+ {
+ 't': mw.seconds2npt( serverSeekTime ) + endvar
+ }
+ );
+ },
+ /**
+ * Title accessor function.
+ *
+ * @return {String} Title of the source.
+ */
+ getTitle : function() {
+ if( this.title ){
+ return this.title;
+ }
+ // Text tracks use "label" instead of "title"
+ if( this.label ){
+ return this.label;
+ }
+
+ // Return a Title based on mime type:
+ var mimeType = this.getMIMEType().split( ';' )[0];
+ switch( mimeType ) {
+ case 'video/h264' :
+ case 'video/mp4' :
+ return mw.msg( 'mwe-embedplayer-video-h264' );
+ break;
+ case 'video/x-flv' :
+ return mw.msg( 'mwe-embedplayer-video-flv' );
+ break;
+ case 'video/webm' :
+ return mw.msg( 'mwe-embedplayer-video-webm');
+ break;
+ case 'video/ogg' :
+ return mw.msg( 'mwe-embedplayer-video-ogg' );
+ break;
+ case 'audio/ogg' :
+ return mw.msg( 'mwe-embedplayer-video-audio' );
+ break;
+ case 'audio/mpeg' :
+ return mw.msg('mwe-embedplayer-audio-mpeg');
+ break;
+ case 'video/3gp' :
+ return mw.msg('mwe-embedplayer-video-3gp');
+ break;
+ case 'video/mpeg' :
+ return mw.msg('mwe-embedplayer-video-mpeg');
+ break;
+ case 'video/x-msvideo' :
+ return mw.msg('mwe-embedplayer-video-msvideo' );
+ break;
+ }
+
+ // Return title based on file name:
+ try{
+ var fileName = new mw.Uri( mw.absoluteUrl( this.getSrc() ) ).path.split('/').pop();
+ if( fileName ){
+ return fileName;
+ }
+ } catch(e){}
+
+ // Return the mime type string if not known type.
+ return this.mimeType;
+ },
+ /**
+ * Get a short title for the stream
+ */
+ getShortTitle: function(){
+ var _this =this;
+ if( this.shorttitle ){
+ return this.shorttitle;
+ }
+ // Just use a short "long title"
+ var longTitle = this.getTitle();
+ if(longTitle.length > 20) {
+ longTitle = longTitle.substring(0,17)+"...";
+ }
+ return longTitle
+ },
+ /**
+ *
+ * Get Duration of the media in milliseconds from the source url.
+ *
+ * Supports media_url?t=ntp_start/ntp_end url request format
+ */
+ getURLDuration : function() {
+ // check if we have a URLTimeEncoding:
+ if ( this.URLTimeEncoding ) {
+ var annoURL = new mw.Uri( this.src );
+ if ( annoURL.query.t ) {
+ var times = annoURL.query.t.split( '/' );
+ this.startNpt = times[0];
+ this.endNpt = times[1];
+ this.startOffset = mw.npt2seconds( this.startNpt );
+ this.duration = mw.npt2seconds( this.endNpt ) - this.startOffset;
+ } else {
+ // look for this info as attributes
+ if ( this.startOffset ) {
+ this.startNpt = mw.seconds2npt( this.startOffset );
+ }
+ if ( this.duration ) {
+ this.endNpt = mw.seconds2npt( parseInt( this.duration ) + parseInt( this.startOffset ) );
+ }
+ }
+ }
+ },
+ /**
+ * Get the extension of a url
+ * @param String uri
+ */
+ getExt : function( uri ){
+ var urlParts = new mw.Uri( uri );
+ // Get the extension from the url or from the relative name:
+ var ext = ( urlParts.file ) ? /[^.]+$/.exec( urlParts.file ) : /[^.]+$/.exec( uri );
+ // remove the hash string if present
+ ext = /[^#]*/g.exec( ext.toString() );
+ ext = ext || '';
+ return ext.toString().toLowerCase();
+ },
+ /**
+ * Get the flavorId if available.
+ */
+ getFlavorId: function(){
+ if( this.flavorid ){
+ return this.flavorid;
+ }
+ return ;
+ },
+
+ /**
+ * Attempts to detect the type of a media file based on the URI.
+ *
+ * @param {String}
+ * uri URI of the media file.
+ * @return {String} The guessed MIME type of the file.
+ */
+ detectType: function( uri ) {
+ // NOTE: if media is on the same server as the javascript
+ // we can issue a HEAD request and read the mime type of the media...
+ // ( this will detect media mime type independently of the url name )
+ // http://www.jibbering.com/2002/4/httprequest.html
+ switch( this.getExt( uri ) ) {
+ case 'smil':
+ case 'sml':
+ return 'application/smil';
+ break;
+ case 'm4v':
+ case 'mp4':
+ return 'video/h264';
+ break;
+ case 'm3u8':
+ return 'application/vnd.apple.mpegurl';
+ break;
+ case 'webm':
+ return 'video/webm';
+ break;
+ case '3gp':
+ return 'video/3gp';
+ break;
+ case 'srt':
+ return 'text/x-srt';
+ break;
+ case 'flv':
+ return 'video/x-flv';
+ break;
+ case 'ogg':
+ case 'ogv':
+ return 'video/ogg';
+ break;
+ case 'oga':
+ return 'audio/ogg';
+ break;
+ case 'mp3':
+ return 'audio/mpeg';
+ case 'm4a':
+ return 'audio/mp4';
+ break;
+ case 'anx':
+ return 'video/ogg';
+ break;
+ case 'xml':
+ return 'text/xml';
+ break;
+ case 'avi':
+ return 'video/x-msvideo';
+ break;
+ case 'mpg':
+ return 'video/mpeg';
+ break;
+ case 'mpeg':
+ return 'video/mpeg';
+ break;
+ }
+ mw.log( "Error: could not detect type of media src: " + uri );
+ },
+ /**
+ * bitrate is mesured in kbs rather than bandwith bytes per second
+ */
+ getBitrate: function() {
+ if( this.bandwidth ){
+ return this.bandwidth / 1024;
+ }
+ return 0;
+ },
+ /**
+ * Get the size of the stream in bytes
+ */
+ getSize: function(){
+ if( this.sizebytes ){
+ return this.sizebytes;
+ }
+ return 0;
+ }
+};
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.processEmbedPlayers.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.processEmbedPlayers.js
new file mode 100644
index 00000000..0748ccd0
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.processEmbedPlayers.js
@@ -0,0 +1,353 @@
+/**
+ * Selector based embedPlayer processing
+ *
+ * @param {Function=}
+ * callback Optional Function to be called once video interfaces
+ * are ready
+ *
+ */
+
+( function( mw, $ ) { "use strict";
+
+mw.processEmbedPlayers = function( playerSet, callback ) {
+ mw.log( 'processEmbedPlayers:: playerSet: ', playerSet);
+ // The player id list container
+ var playerIdList = [];
+
+ // Check if the selected player set is ready if ready issue the parent callback
+ var areSelectedPlayersReady = function(){
+ var playersLoaded = true;
+ $.each( playerIdList, function(inx, playerId){
+ if( ! $( '#' + playerId )[0].playerReadyFlag ){
+ playersLoaded = false;
+ return false;
+ }
+ })
+ if( playersLoaded ){
+ if( callback ){
+ callback();
+ }
+ }
+ }
+
+ /**
+ * Adds a player element for the embedPlayer to rewrite
+ *
+ * uses embedPlayer interface on audio / video elements uses mvPlayList
+ * interface on playlist elements
+ *
+ * Once a player interface is established the following chain of functions
+ * are called;
+ *
+ * _this.checkPlayerSources()
+ * _this.setupSourcePlayer()
+ * _this.updatePlaybackInterface()
+ * _this.selectedPlayer.load()
+ * _this.showPlayer()
+ *
+ * @param {Element}
+ * playerElement DOM element to be swapped
+ */
+ var addPlayerElement = function( playerElement ) {
+ var _this = this;
+ mw.log('EmbedPlayer:: addElement:: ' + playerElement.id );
+
+ // Be sure to "stop" the target ( Firefox 3x keeps playing
+ // the video even though its been removed from the DOM )
+ if( playerElement.pause ){
+ playerElement.pause();
+ }
+
+ // Allow modules to override the wait for metadata flag:
+ $( mw ).trigger( 'EmbedPlayerWaitForMetaCheck', playerElement );
+
+ // DOM *could* load height, width and duration eventually, in some browsers
+ // By default, don't bother waiting for this.
+ var waitForMeta = false;
+
+ // if a plugin has told us not to waitForMeta, don't
+ if ( playerElement.waitForMeta !== false ) {
+ // Check if we should wait for metadata, after all
+ waitForMeta = waitForMetaCheck( playerElement );
+ }
+
+ var ranPlayerSwapFlag = false;
+
+ // Local callback to runPlayer swap once playerElement has metadata
+ var runPlayerSwap = function () {
+ // Don't run player swap twice
+ if( ranPlayerSwapFlag ){
+ return ;
+ }
+ ranPlayerSwapFlag = true;
+ mw.log( "processEmbedPlayers::runPlayerSwap::" + $( playerElement ).attr('id') );
+
+ var playerInterface = new mw.EmbedPlayer( playerElement );
+ var inDomPlayer = swapEmbedPlayerElement( playerElement, playerInterface );
+
+ // IE/Edge with WebM components re-triggers autoplay after removal as well.
+ if( playerElement.pause ){
+ playerElement.pause();
+ }
+
+ // Trigger the EmbedPlayerNewPlayer for embedPlayer interface
+ mw.log("processEmbedPlayers::trigger:: EmbedPlayerNewPlayer " + inDomPlayer.id );
+
+ // Allow plugins to add bindings to the inDomPlayer
+ $( mw ).trigger ( 'EmbedPlayerNewPlayer', inDomPlayer );
+
+ // Add a player ready binding:
+ $( inDomPlayer ).bind( 'playerReady.swap', function(event, id){
+ $( inDomPlayer ).unbind( 'playerReady.swap' );
+ areSelectedPlayersReady();
+ });
+
+ //
+ // Allow modules to block player build out
+ //
+ // this is needed in cases where you need to do an asynchronous
+ // player interface setup. like iframes asynchronous announcing its ready for
+ // bindings that can affect player setup.
+ mw.log("EmbedPlayer::addPlayerElement :trigger startPlayerBuildOut:" + inDomPlayer.id );
+ $( '#' + inDomPlayer.id ).triggerQueueCallback( 'startPlayerBuildOut', function(){
+ // Issue the checkPlayerSources call to the new player
+ // interface: make sure to use the element that is in the DOM:
+ inDomPlayer.checkPlayerSources();
+ });
+ };
+
+ if( waitForMeta && mw.config.get('EmbedPlayer.WaitForMeta' ) ) {
+ mw.log('processEmbedPlayers::WaitForMeta ( video missing height (' +
+ $( playerElement ).attr('height') + '), width (' +
+ $( playerElement ).attr('width') + ') or duration: ' +
+ $( playerElement ).attr('duration')
+ );
+ $( playerElement ).bind( "loadedmetadata", runPlayerSwap );
+
+ // Time-out of 5 seconds ( maybe still playable but no timely metadata )
+ setTimeout( runPlayerSwap, 5000 );
+ return ;
+ } else {
+ runPlayerSwap();
+ return ;
+ }
+ };
+
+ /**
+ * Check if we should wait for metadata.
+ *
+ * @return true if the size is "likely" to be updated by waiting for metadata
+ * false if the size has been set via an attribute or is already loaded
+ */
+ var waitForMetaCheck = function( playerElement ){
+ var waitForMeta = false;
+
+ // Don't wait for metadata for non html5 media elements
+ if( !playerElement ){
+ return false;
+ }
+ if( !playerElement.tagName || ( playerElement.tagName.toLowerCase() != 'audio' && playerElement.tagName.toLowerCase() != 'video' ) ){
+ return false;
+ }
+ // If we don't have a native player don't wait for metadata
+ if( !mw.EmbedTypes.getMediaPlayers().isSupportedPlayer( 'oggNative') &&
+ !mw.EmbedTypes.getMediaPlayers().isSupportedPlayer( 'webmNative') &&
+ !mw.EmbedTypes.getMediaPlayers().isSupportedPlayer( 'h264Native' ) &&
+ !mw.EmbedTypes.getMediaPlayers().isSupportedPlayer( 'appleVdnPlayer' ) )
+ {
+ return false;
+ }
+
+
+ var width = $( playerElement ).css( 'width' );
+ var height = $( playerElement ).css( 'height' );
+ // Css video defaults ( firefox )
+ if( $( playerElement ).css( 'width' ) == '300px' &&
+ $( playerElement ).css( 'height' ) == '150px'
+ ){
+ waitForMeta = true;
+ } else {
+ // Check if we should wait for duration:
+ if( $( playerElement ).attr( 'duration') ||
+ $( playerElement ).attr( 'durationHint') ||
+ $( playerElement ).attr('data-durationhint')
+ ){
+ // height, width and duration set; do not wait for meta data:
+ return false;
+ } else {
+ waitForMeta = true;
+ }
+ }
+
+ // Firefox ~ sometimes~ gives -1 for unloaded media
+ if ( $(playerElement).attr( 'width' ) == -1 || $(playerElement).attr( 'height' ) == -1 ) {
+ waitForMeta = true;
+ }
+
+ // Google Chrome / safari gives 0 width height for unloaded media
+ if( $(playerElement).attr( 'width' ) === 0 ||
+ $(playerElement).attr( 'height' ) === 0
+ ) {
+ waitForMeta = true;
+ }
+
+ // Firefox default width height is ~sometimes~ 150 / 300
+ if( playerElement.height == 150 && playerElement.width == 300 ){
+ waitForMeta = true;
+ }
+
+ // Make sure we have a src attribute or source child
+ // ( i.e not a video tag to be dynamically populated or looked up from
+ // xml resource description )
+ if( waitForMeta &&
+ (
+ $( playerElement ).attr('src') ||
+ $( playerElement ).find("source[src]").length !== 0
+ )
+ ) {
+ // Detect src type ( if no type set )
+ return true;
+ } else {
+ // playerElement is not likely to update its meta data ( no src )
+ return false;
+ }
+ };
+
+ /**
+ * swapEmbedPlayerElement
+ *
+ * Takes a video element as input and swaps it out with an embed player interface
+ *
+ * @param {Element}
+ * targetElement Element to be swapped
+ * @param {Object}
+ * playerInterface Interface to swap into the target element
+ */
+ var swapEmbedPlayerElement = function( targetElement, playerInterface ) {
+ mw.log( 'processEmbedPlayers::swapEmbedPlayerElement: ' + targetElement.id );
+ // Create a new element to swap the player interface into
+ var swapPlayerElement = document.createElement('div');
+
+ // Add a class that identifies all embedPlayers:
+ $( swapPlayerElement ).addClass( 'mwEmbedPlayer' );
+
+ // Get properties / methods from playerInterface:
+ for ( var method in playerInterface ) {
+ if ( method != 'readyState' ) { // readyState crashes IE ( don't include )
+ swapPlayerElement[ method ] = playerInterface[ method ];
+ }
+ }
+ // copy over css text:
+ swapPlayerElement.style.cssText = targetElement.style.cssText;
+ // player element must always be relative to host video and image layout
+ swapPlayerElement.style.position = 'relative';
+
+ // Copy any data attributes from the target player element over to the swapPlayerElement
+ var dataAttributes = mw.config.get("EmbedPlayer.DataAttributes");
+ if( dataAttributes ){
+ $.each( dataAttributes, function( attrName, na ){
+ if( $( targetElement ).data( attrName ) ){
+ $( swapPlayerElement ).data( attrName, $( targetElement ).data( attrName ) );
+ }
+ });
+ }
+ // Check for Persistent native player ( should keep the video embed around )
+ if( playerInterface.isPersistentNativePlayer()
+ ||
+ // Also check for native controls on a video or audio tag
+ ( playerInterface.useNativePlayerControls()
+ &&
+ ( targetElement.nodeName == 'video' || targetElement.nodeName == 'audio' )
+ )
+ ) {
+
+ $( targetElement )
+ .attr( 'id', playerInterface.pid )
+ .addClass( 'nativeEmbedPlayerPid' )
+ .show()
+ .after(
+ $( swapPlayerElement ).css( 'display', 'none' )
+ );
+
+ } else {
+ $( targetElement ).replaceWith( swapPlayerElement );
+ }
+
+ // If we don't already have a loadSpiner add one:
+ if( $('#loadingSpinner_' + playerInterface.id ).length == 0 && $.client.profile().name !== 'firefox' ){
+ if( playerInterface.useNativePlayerControls() || playerInterface.isPersistentNativePlayer() ) {
+ var $spinner = $( targetElement )
+ .getAbsoluteOverlaySpinner();
+ }else{
+ var $spinner = $( swapPlayerElement ).getAbsoluteOverlaySpinner();
+ }
+ $spinner.attr('id', 'loadingSpinner_' + playerInterface.id );
+ }
+ return swapPlayerElement;
+ };
+
+ // Add a loader for <div /> embed player rewrites:
+ $( playerSet ).each( function( index, playerElement) {
+
+ // Make sure the playerElement has an id:
+ if( !$( playerElement ).attr('id') ){
+ $( playerElement ).attr( "id", 'mwe_vid' + ( index ) );
+ }
+ // Add the player Id to the playerIdList
+ playerIdList.push( $( playerElement ).attr( "id") );
+
+ // If we are dynamically embedding on a "div" check if we can
+ // add a poster image behind the loader:
+ if( playerElement.nodeName.toLowerCase() == 'div'
+ &&
+ $(playerElement).attr( 'poster' ) )
+ {
+ var posterSrc = $(playerElement).attr( 'poster' );
+
+ // Set image size:
+ var width = $( playerElement ).width();
+ var height = $( playerElement ).height();
+ if( !width ){
+ var width = '100%';
+ }
+ if( !height ){
+ var height = '100%';
+ }
+
+ mw.log('EmbedPlayer:: set loading background: ' + posterSrc);
+ $( playerElement ).append(
+ $( '<img />' )
+ .attr( 'src', posterSrc)
+ .css({
+ 'position' : 'absolute',
+ 'width' : width,
+ 'height' : height
+ })
+ );
+ }
+ });
+
+ // Make sure we have user preference setup for setting preferences on video selection
+ var addedPlayersFlag = false;
+ mw.log("processEmbedPlayers:: Do: " + $( playerSet ).length + ' players ');
+ // Add each selected element to the player manager:
+ $( playerSet ).each( function( index, playerElement) {
+ // Make sure the video tag was not generated by our library:
+ if( $( playerElement ).hasClass( 'nativeEmbedPlayerPid' ) ){
+ $( '#loadingSpinner_' + $( playerElement ).attr('id') ).remove();
+ mw.log( 'processEmbedPlayers::$.embedPlayer skip embedPlayer gennerated video: ' + playerElement );
+ } else {
+ addedPlayersFlag = true;
+ // Add the player
+ addPlayerElement( playerElement );
+ }
+ });
+ if( !addedPlayersFlag ){
+ // Run the callback directly if no players were added
+ if( callback ){
+ callback();
+ }
+ }
+};
+
+})( mw, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/EmbedPlayer.css b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/EmbedPlayer.css
new file mode 100644
index 00000000..9699c2e9
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/EmbedPlayer.css
@@ -0,0 +1,166 @@
+.ui-dialog-content .mediaContainer { margin: 0 auto; }
+.mwPlayerContainer, video { width: 100%; height: 100%; }
+.mwPlayerContainer { position: relative; height: 100%; background: #000; }
+.videoHolder {
+ position: absolute;
+ top: 0px;
+ left:0px;
+ right:0px;
+ bottom:0px;
+ overflow: hidden;
+}
+.mwPlayerContainer.fullscreen {
+ position: absolute !important;
+ width: 100% !important;
+ height: 100%! important;
+ z-index: 9999;
+ min-height: 100%;
+ top: 0;
+ left: 0;
+ margin: 0;
+}
+
+.mwEmbedPlayer { width: 100%; height: 100%; overflow: hidden; position: absolute; top: 0; left: 0; }
+
+
+.player_select_list {
+ color:white;
+ font-size:10pt;
+/* display:none;*/
+}
+.player_select_list a:visited {
+ color:white;
+}
+.mv_playhead {
+ position:absolute;
+ top:0;
+ left:0;
+ width:17px;
+ height:21px;
+ /*http://art.gnome.org/themes/gtk2*/
+}
+
+.mv_status {
+ font-family:"Times New Roman", Times, serif;
+ font-size:14px;
+ float:left;
+}
+.set_ogg_player_pref{
+ text-align:left;
+}
+
+.large_play_button {
+ display:block;
+ width: 130px;
+ height: 96px;
+ margin: auto;
+/* margin: -202px 0 0 154px;*/
+ position: absolute;
+ z-index: 3;
+ cursor: pointer;
+}
+
+/* jquery.ui overrides */
+
+.ui-icon_link {
+ padding: .4em 1em .4em 20px;
+ text-decoration: none;
+ position: relative;
+}
+.ui-icon_link span.ui-icon {
+ margin: 0 5px 0 0;
+ position: absolute;
+ left: 0.2em;
+ right: auto;
+ top: 50%;
+ margin-top: -8px;
+ zoom: 1;
+}
+.ui-icon_link span.ui-text {
+ position: absolute;
+ left: 0.2em;
+ right: auto;
+ margin-top: -3px;
+ zoom: 1;
+}
+
+.ui-progressbar-value{
+ background-image: none;
+}
+
+.kplayer .ui-widget-overlay {
+ background: black; opacity: .40; filter: Alpha(Opacity=40);
+}
+
+.kplayer .ui-widget-content input {
+ padding: 5px;
+}
+.kplayer .ui-widget-content a {
+ color: #222;
+}
+
+ul.ui-provider-selection {
+ list-style-type: none;
+ margin: 0 0 0.6em 0;
+ overflow: hidden;
+ padding: 0;
+ text-align: center;
+}
+
+ul.ui-provider-selection li {
+ border-left: 1px solid black;
+ float: left;
+ line-height: 1.1em;
+ margin: 0 0.5em 0 -0.5em;
+ padding: 0 0.5em;
+ color: blue;
+ list-style-image:none;
+ cursor:pointer;
+}
+
+ul.ui-provider-selection li .ui-selected {
+ color: black;
+ font-weight: bold;
+}
+
+ul.ui-provider-selection li a.ui-active {
+ color: black;
+ font-weight: bold;
+}
+
+ul.ui-provider-selection li a {
+ color: blue;
+ text-decoration: none;
+}
+.fg-menu .ui-icon{
+ position:relative;
+ top:-1px;
+}
+
+.ui-dialog-buttonpane a{
+ float: right;
+ margin-right: 10px;
+}
+
+
+/* Custom */
+.mv-player .overlay-win { background: transparent; border: 0; } /* Custom */
+.mv-player .overlay-content { padding: 10px; }
+.mv-player .overlay-content h3 { display: block; font-size: 16px; font-weight: bold; color: #fff; font-family: arial; }
+.mv-player .overlay-win h2 { font-size: 18px; margin-top: 0; }
+.mv-player .overlay-content div { font-size: 12px; color: #fff; font-weight: bold; }
+.mv-player .overlay-content div a { color: #00a8ff }
+.mv-player .overlay-content div a:hover { color: #3abcff }
+.mv-player .overlay-content ul { list-style: none; margin: 0 0 10px 0; padding: 0; }
+.mv-player .vol_container {
+ background: #272727;
+ opacity: .80;
+ filter:Alpha(Opacity=80);
+ position:absolute;
+ left:0px;
+}
+.mv-player .ui-icon ui-icon-closethick { border: 1px solid #606060; background: #222;font-weight: normal; color: #EEE; }
+.mv-player .overlay-win textarea { background: #e4e4e4; height: 35px; padding: 6px; color: #666; border: 0; }
+.mv-player .overlay-content .copycode { padding: 8px 12px; font-weight: bold; float: right; cursor: pointer; }
+.control-bar .ui-icon_link { border: 0; }
+.control-bar .ui-state-hover { border: 0; }
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/PlayerSkinKskin.css b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/PlayerSkinKskin.css
new file mode 100644
index 00000000..f6c675d7
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/PlayerSkinKskin.css
@@ -0,0 +1,484 @@
+/*
+* K-skin player
+*/
+.k-player {
+ color: #FFF;
+ background-color: #000;
+}
+.k-player .videoHolder a {
+ color: #0645AD;
+}
+.k-player .videoHolder a:visited {
+ color: #0B0080;
+}
+.k-player .ui-widget-content {
+ color: #555;
+ z-index: 1503;
+}
+.k-player .ui-widget-content a{
+ color: #555;
+}
+/* large play button */
+.k-player .play-btn-large {
+ width: 70px;
+ height: 55px;
+ background: url(images/ksprite.png) no-repeat 0px -433px;
+ position: absolute;
+ cursor: pointer;
+ border: none;
+}
+@print {
+ .k-player .play-btn-large {
+ display: none;
+ }
+}
+/*.ui-state-default */
+.k-player .play-btn-large:hover {
+ background: url(images/ksprite.png) no-repeat 0px -377px;
+}
+
+/* control icons: */
+.k-player .control-bar .ui-icon,.k-player .control-bar .ui-icon{
+ background: transparent url(images/ksprite.png) no-repeat scroll 0 -48px;
+}
+
+.k-player .ui-state-default .ui-icon-arrow-4-diag {
+ background-position: 0 -32px;
+}
+/* fullscreen */
+.k-player .ui-state-hover .ui-icon-arrow-4-diag {
+ background-position: -16px -32px;
+}
+
+.k-player .ui-state-hover .ui-icon-volume-on{
+ background-position: -16px -48px;
+}
+
+/* cc icon */
+.k-player .ui-state-default .ui-icon-comment {
+ background-position: 0px -65px;
+}
+
+.k-player .ui-state-default .ui-icon-play {
+ background: url(images/ksprite.png) no-repeat 0 0;
+}
+
+.k-player .ui-state-hover .ui-icon-play {
+ background-position: -16px 0;
+}
+
+.k-player .ui-state-default .ui-icon-pause {
+ background: url(images/ksprite.png) no-repeat 0 -17px;
+}
+
+.k-player .ui-state-hover .ui-icon-pause {
+ background-position: -16px -17px;
+}
+
+.k-player .control-bar {
+ border:1px solid #c8c8c8;
+ border-top: 0px;
+ border-right: 0px;
+ height: 21px;
+ padding: 2px 0 0 6px;
+ margin-top: 0px;
+ background: url(images/ksprite.png) repeat-x 0 -81px;
+ font: normal 11px arial, sans-serif;
+ color: #555;
+
+ position:absolute;
+ bottom:0px;
+ left:0px;
+ right:0px;
+
+ z-index: 2;
+}
+
+.k-player .play_head {
+ background: url("images/ksprite.png") repeat-x scroll 0 -350px
+ transparent;
+ display: inline;
+ /* @noflip */
+ float: left;
+ margin-left: 10px;
+ border: 1px solid #EEEEEE;
+ height: 8px;
+ margin: 5px 2px 0 0px;
+ position: relative;
+ /* @noflip */
+ direction: ltr;
+}
+
+.k-player .play_head .ui-slider-handle {
+ background: url("images/ksprite.png") no-repeat scroll -67px -341px
+ transparent !important;
+ border: 1px solid #888888;
+ display: block;
+ height: 8px;
+ margin: -1px 0 0 -5px;
+ position: absolute;
+ top: 0;
+ width: 8px;
+ cursor: pointer;
+ -moz-border-radius:5px 5px 5px 5px;
+ border-radius:5px 5px 5px 5px;
+ -webkit-border-radius:5px 5px 5px 5px;
+}
+
+.k-player .ui-corner-all {
+ border-radius:5px 5px 5px 5px !important;
+ -webkit-border-radius:5px 5px 5px 5px !important;
+ -moz-border-radius:5px 5px 5px 5px !important;
+}
+.k-player ul.fg-menu{
+ margin: 0.3em 0 0 .3em;
+ font-size: 1.2em;
+ padding: 0px;
+}
+.k-player .fg-menu-container{
+ padding: 0px;
+ /* @noflip */
+ right: 16px;
+ /* Add scroll bar to list */
+ overflow: auto;
+}
+
+.ui-dialog-content .k-player ul.fg-menu{
+ font-size: 1.2em;
+}
+
+.k-player .time-disp {
+ border: medium none;
+ display: inline;
+ color: #555555;
+ font: 11px arial, sans-serif;
+ line-height: 20px;
+ overflow: hidden;
+ width: 39px;
+ /* @noflip */
+ float: right;
+}
+
+.k-player .source-switch {
+ border: medium none;
+ display: inline;
+ color: #555;
+ font: 11px arial, sans-serif;
+ line-height: 20px;
+ overflow: hidden;
+ width: 70px;
+ cursor: pointer;
+ /* @noflip */
+ float: right;
+ text-align: center;
+}
+
+.k-player .lButton {
+ cursor: pointer;
+ /* @noflip */
+ float: left;
+ list-style: none outside none;
+ margin: 2px;
+ padding: 0px 0;
+ width: 19px;
+ height: 16px;
+ position: relative;
+ background: none repeat scroll 0 0 transparent !important;
+ border: medium none;
+}
+
+.k-player .rButton {
+ cursor: pointer;
+ /* @noflip */
+ float: right;
+ list-style: none outside none;
+ margin-top: 2px;
+ padding: 0px 0;
+ width: 22px;
+ height: 16px;
+ position: relative;
+ background: none repeat scroll 0 0 transparent !important;
+ border: medium none;
+}
+
+.k-player .k-options {
+ border: 1px solid #AAAAAA !important;
+ color: #555555 !important;
+ /* @noflip */
+ float: right;
+ height: 21px;
+ margin-top: -2px;
+ margin-right: 0px;
+ width: 50px;
+ background: none repeat scroll 0 0 transparent !important;
+ font-family: Lucida Grande, Lucida Sans, Arial, sans-serif;
+ font-size: 11px;
+ text-transform: uppercase;
+ text-align: center;
+}
+
+.k-player .k-options span {
+ position: relative;
+ top: 4px;
+}
+
+.k-player .k-menu-screens {
+ /* @noflip */
+ float: left;
+ font-size: 14px;
+ text-align: left;
+ padding: 5px 5px 10px 5px;
+}
+
+.k-player ul.k-menu-bar {
+ background: url("images/ksprite.png") no-repeat scroll -99px -104px
+ transparent;
+ bottom: 5px;
+ height: 128px;
+ list-style: none outside none;
+ padding: 0 0 5px;
+ position: absolute;
+ /* @noflip */
+ right: 0;
+ margin-left: 0;
+}
+
+.k-player .k-menu {
+ background: none repeat scroll 0 0 #181818;
+ border: medium none;
+ display: none;
+ left: 0;
+ position: absolute;
+ top: 0;
+}
+
+.k-player .k-menu-bar li a {
+ background: url("images/ksprite.png") no-repeat scroll -51px -110px
+ transparent;
+ display: block;
+ height: 32px;
+ margin-left: 1px;
+ overflow: hidden;
+ text-indent: 99999px;
+ width: 49px;
+}
+
+.k-menu-bar li a:hover {
+ background-position: -1px -110px;
+}
+
+.k-menu-bar li.k-download-btn a {
+ background-position: -51px -203px;
+}
+
+.k-menu-bar li.k-download-btn a:hover {
+ background-position: -1px -203px;
+}
+
+.k-menu-bar li.k-share-btn a {
+ background-position: -51px -172px;
+}
+
+.k-menu-bar li.k-share-btn a:hover {
+ background-position: -1px -172px;
+}
+
+.k-menu-bar li.k-credits-btn a {
+ background-position: -51px -141px;
+}
+
+.k-menu-bar li.k-credits-btn a:hover {
+ background-position: -1px -141px;
+}
+
+
+
+.k-menu-screens p {
+ margin: 6px 0;
+}
+
+.k-menu-screens a img {
+ border: none;
+}
+
+.k-menu-screens ul {
+ padding: 0;
+ margin: 6px 0 0;
+ list-style: none outside none;
+}
+
+.k-edit-screen {
+ width: 370px;
+ height: 223px;
+ padding-top: 77px;
+ text-align: center;
+ background: #181818;
+ color: #fff;
+}
+
+.k-edit-screen div {
+
+}
+
+.k-edit-screen a {
+ color: #7BB8FC;
+}
+
+.k-edit-screen a img {
+ border: none;
+}
+
+
+.k-menu-screens h2, .k-menu-screens h3 {
+ padding: 0 0 5px 15px;
+ clear: both;
+ font-size: 12px;
+ color: #999;
+ border-bottom: 0;
+}
+
+.k-menu-screens p {
+ margin: 6px 0;
+}
+
+.k-menu-screens a img {
+ border: none;
+}
+
+.k-menu-screens ul {
+ padding: 0;
+ margin: 6px 0 0;
+ list-style: none outside none;
+}
+
+.k-menu-screens li {
+ margin-bottom: 6px;
+}
+
+.k-menu-screens li a {
+ padding-left: 22px;
+ padding-right: 22px;
+ background: url(images/ksprite.png) no-repeat -85px -274px;
+ text-decoration: none;
+ color: #BBB;
+}
+
+.k-menu-screens li a.active,.k-menu-screens li a:hover .active {
+ background-position: -85px -245px;
+}
+
+.k-menu-screens li a:hover {
+ background-position: -85px -259px;
+}
+
+.k-menu textarea {
+ background: none repeat scroll 0 0 transparent;
+ border-color: #000000 -moz-use-text-color -moz-use-text-color #000000;
+ border-style: solid none none solid;
+ border-width: 2px medium medium 2px;
+ color: #CCCCCC;
+ font: 11px arial, sans-serif;
+ overflow: hidden;
+ padding-left: 2px;
+ width: 95%;
+}
+
+.menu-screen.menu-share button {
+ background: url("images/ksprite.png") no-repeat scroll 0 -81px #D4D4D4;
+ border: 1px solid #000000;
+ color: #000000;
+ float: right;
+ height: 34px;
+ padding: 0 5px 3px;
+ font-size: 1em;
+}
+
+.k-player .menu-screen {
+ height: 100%;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+
+.k-player .menu-screen.menu-share div.ui-state-highlight {
+ background: none repeat scroll 0 0 transparent;
+ border-color: #554926;
+ color: #FFE96E;
+ float: left;
+ padding: 2px 5px;
+}
+
+.k-player .menu-screen.menu-share div.ui-state-highlight a {
+ color: #FFE96E;
+ font-weight: bold;
+}
+
+.k-player .volume_control {
+ /* @noflip */
+ margin-right: 2px;
+ width: 16px;
+}
+
+.k-player .volume_control span {
+ margin-right: 0px;
+}
+
+.k-player .volume-slider {
+ width: 20px;
+ /* @noflip */
+ direction: ltr;
+}
+
+.k-player .volume-slider .ui-slider-range {
+ -moz-border-radius: 0 0 0 0;
+ background: url("images/ksprite.png") repeat-x scroll -66px -306px transparent !important;
+ height: 17px;
+ position: absolute;
+}
+
+.k-player .volume-slider a.ui-slider-handle {
+ background: none repeat scroll 0 0 transparent;
+ border: medium none;
+ display: block;
+ height: 18px;
+ margin: -3px 5px 0 -1px;
+ position: absolute;
+ width: 8px;
+}
+
+.k-player .ui-slider-horizontal .ui-slider-range-min {
+ /* @noflip */
+ left: 0;
+}
+
+.k-player .credits_box {
+ background-attachment:scroll;
+ background-color:white;
+ background-image:none;
+ background-position:0 0;
+ bottom: 20px;
+ left: 20px;
+ position:absolute;
+ right: 20px;
+ top: 30px;
+ overflow:hidden;
+}
+.k-player .credits_box a{
+ color:#666;
+ text-decoration: underline;
+}
+.k-player .creditline img {
+ float: left;
+ width: 90px;
+ margin: 4px;
+}
+
+.k-player .k-attribution{
+ position:absolute;
+ bottom: 5px;
+ right : 20px;
+ background: url("images/kaltura_open_source_video_platform.png");
+ width : 51px;
+ height : 12px;
+ cursor: pointer;
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/images/kaltura_open_source_video_platform.gif b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/images/kaltura_open_source_video_platform.gif
new file mode 100644
index 00000000..cf05af25
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/images/kaltura_open_source_video_platform.gif
Binary files differ
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/images/kaltura_open_source_video_platform.png b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/images/kaltura_open_source_video_platform.png
new file mode 100644
index 00000000..77f2a32a
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/images/kaltura_open_source_video_platform.png
Binary files differ
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/images/ksprite.png b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/images/ksprite.png
new file mode 100644
index 00000000..53c772eb
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/images/ksprite.png
Binary files differ
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/mw.PlayerSkinKskin.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/mw.PlayerSkinKskin.js
new file mode 100644
index 00000000..39b43834
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/kskin/mw.PlayerSkinKskin.js
@@ -0,0 +1,394 @@
+/**
+* Skin js allows you to override contrlBuilder html/class output
+*/
+
+( function( mw, $ ) {"use strict";
+
+mw.PlayerSkinKskin = {
+
+ // The parent class for all kskin css:
+ playerClass: 'k-player',
+
+ // Display time string length
+ longTimeDisp: false,
+
+ // Default control bar height
+ height: 20,
+
+ // Volume control layout is horizontal
+ volumeLayout: 'horizontal',
+
+ // Skin "kskin" is specific for wikimedia we have an
+ // api Title key so the "credits" menu item can be showed.
+ supportedMenuItems: {
+ 'credits': true
+ },
+ // Stores the current menu item id
+ currentMenuItem: null,
+
+ // Extends base components with kskin specific options:
+ components: {
+ 'pause': {
+ 'w': 28
+ },
+ 'volumeControl': {
+ 'w': 40
+ },
+ 'playButtonLarge' : {
+ 'h' : 55
+ },
+ 'options': {
+ 'w': 52,
+ 'o': function( ctrlObj ) {
+ return $( '<div />' )
+ .attr( 'title', mw.msg( 'mwe-embedplayer-player_options' ) )
+ .addClass( "ui-state-default ui-corner-bl rButton k-options" )
+ .append(
+ $( '<span />' )
+ .text( mw.msg( 'mwe-embedplayer-menu_btn' ) )
+ );
+ }
+ },
+ // No attributionButton component for kSkin ( its integrated into the credits screen )
+ 'attributionButton' : false,
+
+ // Time display:
+ 'timeDisplay': {
+ 'w': 52
+ },
+ 'optionsMenu': {
+ 'w' : 0,
+ 'o' : function( ctrlObj ) {
+ var embedPlayer = ctrlObj.embedPlayer;
+ var $menuOverlay = $( '<div />')
+ .addClass( 'overlay-win k-menu ui-widget-content' )
+ .css( {
+ 'width' : '100%',
+ 'position': 'absolute',
+ 'top' : '0px',
+ 'bottom' : ( ctrlObj.getHeight() + 2 ) + 'px'
+ } );
+
+ // Note safari can't display video overlays with text:
+ // see bug https://bugs.webkit.org/show_bug.cgi?id=48379
+
+ var userAgent = navigator.userAgent.toLowerCase();
+ if( userAgent.indexOf('safari') != -1 ){
+ $menuOverlay.css('opacity', '0.9');
+ }
+ // Setup menu offset ( if player height < getOverlayHeight )
+ // This displays the menu outside of the player on small embeds
+ if ( embedPlayer.getPlayerHeight() < ctrlObj.getOverlayHeight() ) {
+ var topPos = ( ctrlObj.isOverlayControls() )
+ ? embedPlayer.getPlayerHeight()
+ : embedPlayer.getPlayerHeight() + ctrlObj.getHeight();
+
+ if( embedPlayer.isAudio() ){
+ topPos = ctrlObj.embedPlayer.getInterface().height();
+ }
+
+ $menuOverlay.css( {
+ 'top' : topPos + 'px',
+ 'bottom' : null,
+ 'width' : ctrlObj.getOverlayWidth(),
+ 'height' : ctrlObj.getOverlayHeight() + 'px'
+ } );
+ // Special common overflow hack for thumbnail display of player
+ $( embedPlayer ).parents( '.thumbinner' ).css( 'overflow', 'visible' );
+ }
+
+ var $menuBar = $( '<ul />' )
+ .addClass( 'k-menu-bar' );
+
+ // Don't include about player menu item ( FIXME should be moved to a init function )
+ delete ctrlObj.supportedMenuItems['aboutPlayerLibrary'];
+
+ // Output menu item containers:
+ for ( var menuItem in ctrlObj.supportedMenuItems ) {
+ // Give grep a chance to find the usages:
+ // mwe-embedplayer-playerSelect, mwe-embedplayer-download,
+ // mwe-embedplayer-share, mwe-embedplayer-credits
+ $menuBar.append(
+ $( '<li />')
+ // Add the menu item class:
+ .addClass( 'k-' + menuItem + '-btn' )
+ .attr( 'rel', menuItem )
+ .append(
+ $( '<a />' )
+ .attr( {
+ 'title' : mw.msg( 'mwe-embedplayer-' + menuItem ),
+ 'href' : '#'
+ })
+ )
+ );
+ }
+
+ // Add the menuBar to the menuOverlay
+ $menuOverlay.append( $menuBar );
+
+ var $menuScreens = $( '<div />' )
+ .addClass( 'k-menu-screens' )
+ .css( {
+ 'position' : 'absolute',
+ 'top' : '0px',
+ 'left' : '0px',
+ 'bottom' : '0px',
+ 'right' : '45px',
+ 'overflow' : 'hidden'
+ } );
+ for ( var menuItem in ctrlObj.supportedMenuItems ) {
+ $menuScreens.append(
+ $( '<div />' )
+ .addClass( 'menu-screen menu-' + menuItem )
+ );
+ }
+
+ // Add the menuScreens to the menuOverlay
+ $menuOverlay.append( $menuScreens );
+
+ return $menuOverlay;
+
+ }
+ }
+ },
+
+ /**
+ * Get minimal width for interface overlay
+ */
+ getOverlayWidth: function(){
+ return ( this.embedPlayer.getPlayerWidth() < 220 )? 220 : this.embedPlayer.getPlayerWidth();
+ },
+
+ /**
+ * Get minimal height for interface overlay
+ */
+ getOverlayHeight: function(){
+ return ( this.embedPlayer.getPlayerHeight() < 160 )? 160 : this.embedPlayer.getPlayerHeight();
+ },
+
+ /**
+ * Adds the skin Control Bindings
+ */
+ addSkinControlBindings: function() {
+ var embedPlayer = this.embedPlayer;
+ var _this = this;
+
+ // Set up control bar pointer
+ this.$playerTarget = embedPlayer.$interface;
+ // Set the menu target:
+
+
+ // Options menu display:
+ this.$playerTarget.find( '.k-options' )
+ .unbind()
+ .click( function() {
+ _this.checkMenuOverlay();
+ var $kmenu = _this.$playerTarget.find( '.k-menu' );
+ if ( $kmenu.is( ':visible' ) ) {
+ _this.closeMenuOverlay( );
+ } else {
+ _this.showMenuOverlay();
+ // no other item is selected by default show the media credits:
+ if ( !_this.currentMenuItem ){
+ _this.showMenuItem('credits');
+ // Hide the others
+ _this.$playerTarget.find( '.menu-screen' ).hide();
+ // Show credits
+ _this.$playerTarget.find( '.menu-credits' ).fadeIn( "fast" );
+ }
+ }
+ } );
+
+ },
+
+ /**
+ * checks for menu overlay and runs menu bindings if unset
+ */
+ checkMenuOverlay: function(){
+ var _this = this;
+ var embedPlayer = this.embedPlayer;
+ if ( _this.$playerTarget.find( '.k-menu' ).length == 0 ) {
+ // Stop the player if it does not support overlays:
+ if ( !embedPlayer.supports['overlays'] ) {
+ embedPlayer.stop();
+ }
+
+ // Add the menu binding
+ _this.addMenuBinding();
+ }
+ },
+
+ /**
+ * Close the menu overlay
+ */
+ closeMenuOverlay: function() {
+ mw.log("PlayerSkinKskin:: close menu overlay" );
+ var embedPlayer = this.embedPlayer;
+ var $optionsMenu = embedPlayer.getInterface().find( '.k-options' );
+ var $kmenu = embedPlayer.getInterface().find( '.k-menu' );
+ $kmenu.fadeOut( "fast", function() {
+ $optionsMenu.find( 'span' )
+ .text ( mw.msg( 'mwe-embedplayer-menu_btn' ) );
+ } );
+ // show the play button if not playing
+ if( !embedPlayer.isPlaying() ){
+ embedPlayer.getInterface().find( '.play-btn-large' ).fadeIn( 'fast' );
+ }
+
+ // re-display the control bar if hidden:
+ this.showControlBar();
+
+ // Set close overlay menu flag:
+ this.displayOptionsMenuFlag = false;
+ },
+
+ /**
+ * Show the menu overlay
+ */
+ showMenuOverlay: function( $ktxt ) {
+ var $optionsMenu = this.$playerTarget.find( '.k-options' );
+ var $kmenu = this.$playerTarget.find( '.k-menu' );
+
+ $kmenu.fadeIn( "fast", function() {
+ $optionsMenu.find( 'span' )
+ .text ( mw.msg( 'mwe-embedplayer-close_btn' ) );
+ } );
+ this.$playerTarget.find( '.play-btn-large' ).fadeOut( 'fast' );
+
+ $(this.embedPlayer).trigger( 'displayMenuOverlay' );
+
+ // Set the Options Menu display flag to true:
+ this.displayOptionsMenuFlag = true;
+ },
+
+ /**
+ * Adds binding for the options menu
+ *
+ * @param {Object} $tp Target video container for
+ */
+ addMenuBinding: function() {
+ var _this = this;
+ var embedPlayer = this.embedPlayer;
+ // Set local player target pointer:
+ var $playerTarget = embedPlayer.$interface;
+
+ // Check if k-menu already exists:
+ if ( $playerTarget.find( '.k-menu' ).length != 0 )
+ return false;
+
+ // Add options menu to top of player target children:
+ $playerTarget.append(
+ _this.getComponent( 'optionsMenu' )
+ );
+
+ // By default its hidden:
+ $playerTarget.find( '.k-menu' ).hide();
+
+ // Add menu-items bindings:
+ for ( var menuItem in _this.supportedMenuItems ) {
+ $playerTarget.find( '.k-' + menuItem + '-btn' ).click( function( ) {
+
+ // Grab the context from the "clicked" menu item
+ var mk = $( this ).attr( 'rel' );
+
+ // hide all menu items
+ var $targetItem = $playerTarget.find( '.menu-' + mk );
+
+ // call the function showMenuItem
+ _this.showMenuItem( mk );
+
+ // Hide the others
+ $playerTarget.find( '.menu-screen' ).hide();
+
+ // Show the target menu item:
+ $targetItem.fadeIn( "fast" );
+
+ // Don't follow the # link
+ return false;
+ } );
+ }
+ },
+
+ /**
+ * Shows a selected menu_item
+ *
+ * NOTE: this should be merged with parent mw.PlayerControlBuilder optionMenuItems
+ * binding mode
+ *
+ * @param {String} menu_itme Menu item key to display
+ */
+ showMenuItem:function( menuItem ) {
+ var embedPlayer = this.embedPlayer;
+ this.currentMenuItem = menuItem;
+ //handle special k-skin specific display;
+ switch( menuItem ){
+ case 'credits':
+ this.showCredits();
+ break;
+ case 'playerSelect':
+ embedPlayer.$interface.find( '.menu-playerSelect').html(
+ this.getPlayerSelect()
+ );
+ break;
+ case 'download' :
+ embedPlayer.$interface.find( '.menu-download').text(
+ mw.msg('mwe-loading_txt' )
+ );
+ // Call show download with the target to be populated
+ this.showDownload(
+ embedPlayer.$interface.find( '.menu-download')
+ );
+ break;
+ case 'share':
+ embedPlayer.$interface.find( '.menu-share' ).html(
+ this.getShare()
+ );
+ break;
+ }
+ },
+
+ /**
+ * Show the credit screen ( presently specific to kaltura skin )
+ */
+ showCredits: function() {
+ // Set up the shortcuts:
+ var embedPlayer = this.embedPlayer;
+ var _this = this;
+ var $target = embedPlayer.$interface.find( '.menu-credits' );
+
+ $target.empty().append(
+ $('<h2 />')
+ .text( mw.msg( 'mwe-embedplayer-credits' ) ),
+ $('<div />')
+ .addClass( "credits_box ui-corner-all" )
+ .append(
+ $('<div/>')
+ .loadingSpinner()
+ .css({'position':'absolute','top':'50%','left':'50%'})
+ )
+ );
+
+ if( mw.config.get( 'EmbedPlayer.KalturaAttribution' ) == true ){
+ $target.append(
+ $( '<div />' )
+ .addClass( 'k-attribution' )
+ .attr({
+ 'title': mw.msg('mwe-embedplayer-kaltura-platform-title')
+ })
+ .click( function( ) {
+ window.location = 'http://html5video.org';
+ })
+ );
+ }
+ var $creditBox = $target.find('.credits_box');
+ $creditBox.data( 'playerId', embedPlayer.id );
+ $( embedPlayer ).triggerQueueCallback('showCredits', $creditBox, function( addedCredits ){
+ if( !addedCredits ){
+ $creditBox.find('.credits_box').text( mw.msg( 'mwe-embedplayer-nocredits') )
+ }
+ });
+ }
+
+};
+
+} )( mw, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mvpcf/PlayerSkinMvpcf.css b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mvpcf/PlayerSkinMvpcf.css
new file mode 100644
index 00000000..a9664ec5
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mvpcf/PlayerSkinMvpcf.css
@@ -0,0 +1,194 @@
+/**
+ * reference player skin
+ */
+
+
+/*.ui-state-default */
+.mv-player a:link {color: #2060c1; text-decoration: underline;}
+.mv-player a:visited {color: #2060c1; text-decoration: underline;}
+/*a:visited {color: #75a5e4; text-decoration: underline;}*/ /*Not sure if you want this*/
+.mv-player a:hover {color: #75a5e4; text-decoration: underline;}
+.mv-player img, .mv-player img a, .mv-player img a:hover {border: 0;}
+
+
+.mv-player .video {
+ display: block;
+ position: relative;
+ font-size: 1px;
+ height: 305px;
+}
+.mv-player .control-bar {
+ overflow: hidden;
+ height: 29px;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ z-index: 2;
+}
+.mv-player .controlInnerSmall {
+/* width: 430px;*/
+ height: 29px;
+ float: left;
+ display: inline;
+}
+
+.mv-player .lButton {
+ cursor:pointer;
+ float:left;
+ list-style:none outside none;
+ margin:2px;
+ padding:4px 0;
+ width: 24px;
+ height:16px;
+ position:relative;
+}
+.mv-player .rButton {
+ cursor:pointer;
+ float:right;
+ list-style:none outside none;
+ margin:2px;
+ padding:4px 0;
+ width: 23px;
+ height:16px;
+ position:relative;
+}
+
+.mv-player .volume_icon {
+ float: right;
+ display: inline;
+ width: 22px;
+ height: 29px;
+ padding: 0 0 0 0;
+
+}
+
+.mv-player .vol_container{
+ z-index:99;
+ width:23px;
+ height:75px;
+ width:23px;
+ position:absolute;
+ left:0px;
+ background: #CCC;
+}
+.mv-player .vol_container_below{
+ top:30px;
+}
+.mv-player .vol_container_top{
+ top:-77px;
+}
+.mv-player .vol_container .volume-slider{
+ margin-top:5px;
+ height:65px;
+ width:10px;
+ margin-left: auto ;
+ margin-right: auto ;
+}
+.mv-player .vol_container .ui-slider-handle{
+ cursor : pointer;
+ width:10px;
+ height:10px;
+ position:absolute;
+ left:-1px;
+}
+
+.mv-player .time-disp {
+ line-height: 32px;
+ height: 29px;
+ overflow: visible;
+ font-size: 10.2px;
+ float: right;
+ display: inline;
+ border:none;
+ padding-right:4px;
+}
+
+.mv-player .source-switch {
+ border: medium none;
+ display: inline;
+ color: #eee;
+ font: 11px arial, sans-serif;
+ line-height: 20px;
+ overflow: hidden;
+ width: 70px;
+ cursor: pointer;
+ float: right;
+ text-align: center;
+ padding-top:6px;
+}
+
+
+.mv-player .play_head{
+ float: left;
+ display: inline;
+ height: 10px;
+ margin-left:8px;
+ margin-top:10px;
+ margin-right: 8px;
+ position:relative;
+}
+
+.mv-player .play_head .ui-slider-handle{
+ width:10px;
+ height:15px;
+ margin-left:-5px;
+ margin-top: -0px;
+ z-index: 2;
+}
+
+.mv-player .inOutSlider .ui-slider-handle{
+ width:8px;
+ cusror: move;
+}
+
+.mv-player .overlay-win textarea {
+ background:none repeat scroll 0 0 transparent;
+ border: 2px solid #333;
+ color: #fff;
+ font: 11px arial,sans-serif;
+ height:15px;
+ overflow:hidden;
+ padding-left:2px;
+ width:97%;
+}
+
+.mv-player .overlay-win div.ui-state-highlight {
+ background:none repeat scroll 0 0 transparent;
+ border-color:#554926;
+ color:#FFE96E;
+ float:left;
+ padding:2px 5px;
+}
+
+.mv-player .videoOptionsComplete div.ui-state-highlight a {
+ color:#eee;
+ font-weight:bold;
+}
+
+.mv-player .overlay-win h2{
+ font-size: 115%;
+}
+
+.mv-player .overlay-win{
+ font-family : arial,sans-serif;
+ font-size : 85%;
+}
+.mv-player .overlay-win a{
+ text-decoration: none;
+}
+
+.mv-player .overlay-win ul{
+ padding-left: 15px;
+}
+
+.mv-player a:hover {}
+
+.mv-player .overlay-win ul li span { font-weight:bold; color:#fff;}
+
+.mv-player .overlay-win h2 { font-size:16px;}
+.mv-player .overlay-win h3 { font-size:14px;}
+
+.active { font-size: 12px; }
+
+.ui-slider-horizontal.volume-slider { width: 44px; height: 2px; top: 7px; }
+.ui-slider-horizontal.volume-slider .ui-slider-handle { border-width: 1px; }
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mvpcf/images/player_big_play_button.png b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mvpcf/images/player_big_play_button.png
new file mode 100644
index 00000000..155f15e1
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mvpcf/images/player_big_play_button.png
Binary files differ
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mvpcf/mw.PlayerSkinMvpcf.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mvpcf/mw.PlayerSkinMvpcf.js
new file mode 100644
index 00000000..4b270418
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mvpcf/mw.PlayerSkinMvpcf.js
@@ -0,0 +1,7 @@
+/*
+mvpcf skin config
+*/
+
+mw.PlayerSkinMvpcf = {
+ playerClass : 'mv-player'
+}; \ No newline at end of file
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mw.PlayerControlBuilder.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mw.PlayerControlBuilder.js
new file mode 100644
index 00000000..5ef54d4f
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/skins/mw.PlayerControlBuilder.js
@@ -0,0 +1,2721 @@
+/**
+* Msg text is inherited from embedPlayer
+*/
+
+( function( mw, $ ) { "use strict";
+/**
+* mw.PlayerControlBuilder object
+* @param the embedPlayer element we are targeting
+*/
+mw.PlayerControlBuilder = function( embedPlayer, options ) {
+ return this.init( embedPlayer, options );
+};
+
+/**
+ * ControlsBuilder prototype:
+ */
+mw.PlayerControlBuilder.prototype = {
+ //Default Local values:
+
+ // Parent css Class name
+ playerClass : 'mv-player',
+
+ // Long string display of time value
+ longTimeDisp: true,
+
+ // Default volume layout is "vertical"
+ volumeLayout : 'vertical',
+
+ // Default control bar height
+ height: mw.config.get( 'EmbedPlayer.ControlsHeight' ),
+
+ // Default supported components is merged with embedPlayer set of supported types
+ supportedComponents: {
+ // All playback types support options
+ 'options': true
+ },
+
+ // Default supported menu items is merged with skin menu items
+ supportedMenuItems: {
+ // Player Select
+ 'playerSelect' : true,
+
+ // Download the file menu
+ 'download' : true,
+
+ // Share the video menu
+ 'share' : true,
+
+ // Player library link
+ 'aboutPlayerLibrary': true
+ },
+
+ // Flag to store the current fullscreen mode
+ inFullScreen: false,
+
+ // Flag to store if a warning binding has been added
+ addWarningFlag: false,
+
+ // Flag to store state of overlay on player
+ displayOptionsMenuFlag: false,
+
+ // Local storage of ControlBar Callback
+ hideControlBarCallback: false,
+
+ // Flag to store controls status (disabled/enabled)
+ controlsDisabled: false,
+
+ // binding postfix
+ bindPostfix: '.controlBuilder',
+
+ /**
+ * Initialization Object for the control builder
+ *
+ * @param {Object} embedPlayer EmbedPlayer interface
+ */
+ init: function( embedPlayer ) {
+ var _this = this;
+ this.embedPlayer = embedPlayer;
+ // Check for skin overrides for controlBuilder
+ var skinClass = embedPlayer.skinName.substr(0,1).toUpperCase() + embedPlayer.skinName.substr( 1 );
+ if ( mw['PlayerSkin' + skinClass ] ) {
+ // Clone as to not override prototype with the skin config
+ _this = $.extend( true, { }, this, mw['PlayerSkin' + skinClass ] );
+ }
+ if ( _this.embedPlayer.mediaElement.getPlayableSources().length <= 1
+ && _this.supportedMenuItems.playerSelect ) {
+ delete _this.supportedMenuItems.playerSelect;
+ }
+ // Return the controlBuilder Object:
+ return _this;
+ },
+
+ /**
+ * Get the control bar height
+ * @return {Number} control bar height
+ */
+ getHeight: function(){
+ return this.height;
+ },
+
+
+ /**
+ * Add the controls html to player interface
+ */
+ addControls: function() {
+ // Set up local pointer to the embedPlayer
+ var embedPlayer = this.embedPlayer,
+ profile = $.client.profile();
+
+ // Set up local controlBuilder
+ var _this = this;
+
+ // Remove any old controls & old overlays:
+ embedPlayer.getInterface().find( '.control-bar,.overlay-win' ).remove();
+
+ // Reset flags:
+ _this.displayOptionsMenuFlag = false;
+
+ // Setup the controlBar container ( starts hidden )
+ var $controlBar = $('<div />')
+ .addClass( 'ui-state-default ui-widget-header ui-helper-clearfix control-bar' )
+ .css( 'height', this.height );
+
+ // Controls are hidden by default if overlaying controls:
+ if( _this.isOverlayControls() ){
+ $controlBar.hide();
+ } else {
+ // Include the control bar height when calculating the layout
+ $controlBar.addClass('block');
+ }
+
+ // Make room for audio controls in the interface:
+ if( embedPlayer.isAudio() && embedPlayer.getInterface().height() == 0 ){
+ embedPlayer.getInterface().css( {
+ 'height' : this.height
+ } );
+ }
+
+ // Add the controls to the interface
+ embedPlayer.getInterface().append( $controlBar );
+
+ if ( profile.name === 'firefox' && profile.versionNumber < 2 ) {
+ embedPlayer.triggerHelper( 'resizeIframeContainer', [ {'height' : embedPlayer.height + $controlBar.height() - 1} ] );
+ }
+
+ // Add the Controls Component
+ this.addControlComponents();
+
+ // Add top level Controls bindings
+ this.addControlBindings();
+ },
+
+ /**
+ * Add control components as defined per this.components
+ */
+ addControlComponents: function( ) {
+ var _this = this;
+
+ // Set up local pointer to the embedPlayer
+ var embedPlayer = this.embedPlayer;
+
+ //Set up local var to control container:
+ var $controlBar = embedPlayer.getInterface().find( '.control-bar' );
+
+ this.availableWidth = embedPlayer.getPlayerWidth();
+
+ mw.log( 'PlayerControlsBuilder:: addControlComponents into:' + this.availableWidth );
+ // Build the supportedComponents list
+ this.supportedComponents = $.extend( this.supportedComponents, embedPlayer.supports );
+
+ // Check for Attribution button
+ if( mw.config.get( 'EmbedPlayer.AttributionButton' ) && embedPlayer.attributionbutton ){
+ this.supportedComponents[ 'attributionButton' ] = true;
+ }
+ // Check global fullscreen enabled flag
+ if( mw.config.get( 'EmbedPlayer.EnableFullscreen' ) === false ){
+ this.supportedComponents[ 'fullscreen'] = false;
+ }
+ // Check if the options item is available
+ if( mw.config.get( 'EmbedPlayer.EnableOptionsMenu' ) === false ){
+ this.supportedComponents[ 'options'] = false;
+ }
+ // Check for volume control
+ if( mw.config.get( 'EmbedPlayer.EnableVolumeControl') === false ){
+ this.supportedComponents[ 'volumeControl'] = false;
+ }
+
+ // Check if we have multiple playable sources ( if only one source don't display source switch )
+
+ if( embedPlayer.mediaElement.getPlayableSources().length == 1 ){
+ this.supportedComponents[ 'sourceSwitch' ] = false;
+
+ }
+
+ // Give embeds option to explicitly disable components via flag
+ var source = embedPlayer.mediaElement.getPlayableSources()[0];
+ if ( !embedPlayer.disablecontrols && source ) {
+ embedPlayer.disablecontrols = source.disablecontrols;
+ }
+ if ( embedPlayer.disablecontrols ) {
+ embedPlayer.disablecontrols.split(',').forEach(function( key ) {
+ mw.log( 'PlayerControlBuilder:: disabled component via flag:' + key );
+ _this.supportedComponents[ key ] = false;
+ });
+ }
+
+ $( embedPlayer ).trigger( 'addControlBarComponent', this );
+
+ var components = [];
+ var largestPos = 0;
+ var addComponent = function( componentId ){
+ if ( _this.supportedComponents[ componentId ] ) {
+ if ( _this.availableWidth >= _this.components[ componentId ].w ) {
+ _this.availableWidth -= _this.components[ componentId ].w;
+ // Check if position is defined, if not, place at end of known positions
+ var position = _this.components[ componentId ].position ?
+ _this.components[ componentId ].position:
+ largestPos+1
+ if( position > largestPos ){
+ largestPos = position;
+ }
+ components.push({
+ 'id': componentId,
+ 'position': position
+ });
+ //mw.log(" availableWidth:" + _this.availableWidth + ' ' + componentId + ' took: ' + _this.components[ componentId ].w )
+ } else {
+ mw.log( 'PlayerControlBuilder:: Not enough space for control component:' + componentId );
+ }
+ }
+ };
+
+ var addComponents = function() {
+ components.sort(function(a, b) {
+ return b.position - a.position;
+ });
+ for(var i=0;i<components.length;i++) {
+ $controlBar.append(
+ _this.getComponent( components[ i ]['id'] )
+ );
+ }
+ }
+
+ // Output components
+ for ( var componentId in this.components ) {
+ // Check for (component === false ) and skip
+ if( this.components[ componentId ] === false ){
+ continue;
+ }
+
+ // Special case with playhead and time ( to make sure they are to the left of everything else )
+ if ( componentId == 'playHead' ){
+ continue;
+ }
+ if( componentId == 'timeDisplay' && !mw.config.get( 'EmbedPlayer.EnableTimeDisplay' ) ){
+ continue;
+ }
+
+ // Skip "fullscreen" button for assets or where height is 0px ( audio )
+ if( componentId == 'fullscreen' && this.embedPlayer.isAudio() ){
+ continue;
+ }
+ // Skip sourceSwitch if width < smalles derivative
+ if ( componentId == 'sourceSwitch' && this.availableWidth < 320) {
+ continue;
+ }
+ addComponent( componentId );
+ }
+ if( this.availableWidth > 30 ){
+ addComponent( 'playHead' );
+ }
+ addComponents();
+ $(embedPlayer).trigger( 'controlBarBuildDone' );
+ },
+
+ /**
+ * Get a window size for the player while preserving aspect ratio:
+ *
+ * @@TODO This has similar logic to mw.embedPlayerNative applyIntrinsicAspect we should look
+ * at merging their functionality.
+ *
+ * @param {object} windowSize
+ * object that set { 'width': {width}, 'height':{height} } of target window
+ * @return {object}
+ * css settings for fullscreen player
+ */
+ getAspectPlayerWindowCss: function( windowSize ) {
+ var embedPlayer = this.embedPlayer;
+ var _this = this;
+ // Setup target height width based on max window size
+ if( !windowSize ){
+ var windowSize = {
+ 'width' : $( window ).width(),
+ 'height' : $( window ).height()
+ };
+ }
+ windowSize.width = parseInt( windowSize.width );
+ windowSize.height = parseInt( windowSize.height );
+ // See if we need to leave space for control bar
+ if( !_this.isOverlayControls() ){
+ //targetHeight = targetHeight - this.height;
+ windowSize.height = windowSize.height - this.height;
+ }
+
+ // Set target width
+ var targetWidth = windowSize.width;
+ var targetHeight = targetWidth * ( 1 / _this.getIntrinsicAspect() );
+ // Check if it exceeds the height constraint:
+ if( targetHeight > windowSize.height ){
+ targetHeight = windowSize.height;
+ targetWidth = parseInt( targetHeight * _this.getIntrinsicAspect() );
+ }
+ var offsetTop = 0;
+ // Move the video down 1/2 of the difference of window height
+ offsetTop+= ( targetHeight < windowSize.height )? ( windowSize.height- targetHeight ) / 2 : 0;
+ // if the video is very tall in a short window adjust the size:
+ var offsetLeft = ( targetWidth < windowSize.width )? parseInt( windowSize.width- targetWidth ) / 2 : 0;
+
+ var position = (mw.isIOS4() && mw.isIphone()) ? 'static' : 'absolute';
+ mw.log( 'PlayerControlBuilder::getAspectPlayerWindowCss: ' + ' h:' + targetHeight + ' w:' + targetWidth + ' t:' + offsetTop + ' l:' + offsetLeft );
+ return {
+ 'position' : position,
+ 'height': parseInt( targetHeight ),
+ 'width' : parseInt( targetWidth ),
+ 'top' : parseInt( offsetTop ),
+ 'left': parseInt( offsetLeft)
+ };
+ },
+
+ /**
+ * Get the intrinsic aspect ratio of media ( width / height )
+ * @return {float}
+ * size object with width and height
+ */
+ getIntrinsicAspect: function(){
+ var vid = this.embedPlayer.getPlayerElement();
+ // Check for raw intrinsic media size:
+ if( vid && vid.videoWidth && vid.videoHeight ){
+ return vid.videoWidth / vid.videoHeight;
+ }
+
+ // See if we have source data attributes available:
+ if( this.embedPlayer.mediaElement &&
+ this.embedPlayer.mediaElement.selectedSource )
+ {
+ var ss = this.embedPlayer.mediaElement.selectedSource;
+ // See if we have a hardcoded aspect to the source ( Adaptive streams don't have width / height )
+ if( ss.aspect ){
+ return ss.aspect;
+ }
+
+ if( ss.width && ss.height ){
+ return ss.width / ss.height
+ }
+ }
+
+ // check for posterImage size: ( should have Intrinsic aspect size as well )
+ var img = this.embedPlayer.getInterface().find('.playerPoster')[0];
+ if( img && img.naturalWidth && img.naturalHeight){
+ return img.naturalWidth / img.naturalHeight
+ }
+
+ // if all else fails use embedPlayer.getWidth()
+ return this.embedPlayer.getWidth() / this.embedPlayer.getHeight()
+ },
+
+ /**
+ * Get the play button css
+ */
+ getPlayButtonPosition: function() {
+ var _this = this;
+ return {
+ 'position' : 'absolute',
+ 'left' : '50%',
+ 'top' : '50%',
+ 'margin-left' : - .5 * this.getComponentWidth( 'playButtonLarge' ),
+ 'margin-top' : - .5 * this.getComponentHeight( 'playButtonLarge' )
+ };
+ },
+
+ /**
+ * Check if we're in Fullscreen
+ * @return {boolean)
+ */
+ isInFullScreen: function() {
+ return this.inFullScreen;
+ },
+
+ /**
+ * Toggles full screen by calling
+ * doFullScreenPlayer to enable fullscreen mode
+ * restoreWindowPlayer to restore window mode
+ */
+ toggleFullscreen: function( forceClose ) {
+ var _this = this;
+ // Do normal in-page fullscreen handling:
+ if( this.isInFullScreen() ){
+ this.restoreWindowPlayer();
+ }else {
+ this.doFullScreenPlayer();
+ }
+ // Don't follow the # link:
+ return false;
+ },
+
+ /**
+ * Do full-screen mode
+ */
+ doFullScreenPlayer: function( callback ) {
+ mw.log("PlayerControlBuilder:: doFullScreenPlayer" );
+ // Setup pointer to control builder :
+ var _this = this,
+ profile = $.client.profile();
+
+ // Store the page vertical scroll
+ var doc = window.document;
+ var context = window;
+ this.verticalScrollPosition = doc.all ? doc.scrollTop : context.pageYOffset;
+
+ // Setup local reference to embed player:
+ var embedPlayer = this.embedPlayer;
+
+ // Setup a local reference to the player interface:
+ var $interface = embedPlayer.getInterface();
+ // Check fullscreen state ( if already true do nothing )
+ if( this.isInFullScreen() == true ){
+ return ;
+ }
+ this.inFullScreen = true;
+
+ // Add fullscreen class to interface:
+ $interface.addClass( 'fullscreen' );
+
+ // if overlaying controls add hide show player binding.
+ if( _this.isOverlayControls() && !embedPlayer.isTouchDevice() ){
+ _this.addFullscreenMouseMoveHideShowControls();
+ }
+
+ // Store the current scroll location on the iframe:
+ $( embedPlayer ).trigger( 'fullScreenStoreVerticalScroll' );
+
+ if( window.fullScreenApi.supportsFullScreen ) {
+ _this.preFullscreenPlayerSize = this.getPlayerSize();
+ var fullscreenHeight = null;
+ var fsTarget = this.getFsTarget();
+
+ var escapeFullscreen = function( event ) {
+ // grab the correct document target to check for fullscreen
+ if ( ! window.fullScreenApi.isFullScreen( window.document ) ) {
+ _this.restoreWindowPlayer();
+ }
+ }
+ // remove any old binding:
+ fsTarget.removeEventListener( fullScreenApi.fullScreenEventName, escapeFullscreen );
+ // Add a binding to catch "escape" fullscreen
+ fsTarget.addEventListener( fullScreenApi.fullScreenEventName, escapeFullscreen );
+ // Make the iframe fullscreen:
+ window.fullScreenApi.requestFullScreen( fsTarget );
+
+ // There is a bug with mozfullscreenchange event in all versions of firefox with supportsFullScreen
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=724816
+ // so we have to have an extra binding to check for size change and then restore.
+ if( profile.name === 'firefox' ){
+ _this.fullscreenRestoreCheck = setInterval( function(){
+ if( fullscreenHeight && $(window).height() < fullscreenHeight ){
+ // Mozilla triggered size change:
+ clearInterval ( _this.fullscreenRestoreCheck );
+ _this.restoreWindowPlayer();
+ }
+ // set fullscreen height:
+ if( ! fullscreenHeight && _this.preFullscreenPlayerSize.height != $(window).height() ){
+ fullscreenHeight = $(window).height();
+ }
+ }, 250 );
+ }
+ } else {
+ // Check for hybrid html controls / native fullscreen support:
+ var vid = this.embedPlayer.getPlayerElement();
+ if( mw.config.get('EmbedPlayer.EnableIpadNativeFullscreen')
+ &&
+ vid && vid.webkitSupportsFullscreen
+ ){
+ this.doHybridNativeFullscreen();
+ return ;
+ } else {
+ // make the player traget or iframe fullscreen
+ this.doContextTargetFullscreen();
+ }
+ }
+
+ // Bind escape to restore in page clip ( IE9 needs a secondary escape binding )
+ $( window ).keyup( function( event ) {
+ // Escape check
+ if( event.keyCode == 27 ){
+ _this.restoreWindowPlayer();
+ }
+ } );
+
+ // trigger the open fullscreen event:
+ $( embedPlayer ).trigger( 'onOpenFullScreen' );
+
+ // re draw the controls after a timeout ( to allow the screen dom to update )
+ setTimeout( function(){
+ _this.addControls();
+ },100)
+ },
+
+ /**
+ * Make the target player interface or iframe fullscreen
+ */
+ doContextTargetFullscreen: function() {
+ var
+ _this = this,
+ doc = window.document,
+ $doc = $( doc ),
+ $target = $( this.getFsTarget() ),
+ context = window;
+
+ // update / reset local restore properties
+ this.parentsAbsoluteList = [];
+ this.parentsRelativeList = [];
+
+ // Set the original parent page scale if possible:
+ this.orginalParnetViewPortContent = $doc.find( 'meta[name="viewport"]' ).attr( 'content' );
+ this.orginalTargetElementLayout = {
+ 'style' : $target[0].style.cssText,
+ 'width' : $target.width(),
+ 'height' : $target.height()
+ };
+
+ mw.log("PlayerControls:: doParentIframeFullscreen> verticalScrollPosition:" + this.verticalScrollPosition);
+ context.scroll(0, 0);
+
+ // Make sure the parent page page has a zoom of 1:
+ if( ! $doc.find('meta[name="viewport"]').length ){
+ $doc.find('head').append( $( '<meta />' ).attr('name', 'viewport') );
+ }
+ $doc.find('meta[name="viewport"]').attr('content', 'initial-scale=1; maximum-scale=1; minimum-scale=1;' );
+
+ // iPad 5 supports fixed position in a bad way, use absolute pos for iOS
+ var playerCssPosition = ( mw.isIOS() ) ? 'absolute': 'fixed';
+
+ // Remove absolute css of the $target's parents
+ $target.parents().each( function() {
+ var $parent = $( this );
+ if( $parent.css( 'position' ) == 'absolute' ) {
+ _this.parentsAbsoluteList.push( $parent );
+ $parent.css( 'position', 'static' );
+ }
+ if( $parent.css( 'position' ) == 'relative' ) {
+ _this.parentsRelativeList.push( $parent );
+ $parent.css( 'position', 'static' );
+ }
+ });
+
+ // Make the $target fullscreen
+ $target
+ .css({
+ 'z-index': mw.config.get( 'EmbedPlayer.FullScreenZIndex' ),
+ 'position': playerCssPosition,
+ 'top' : '0px',
+ 'left' : '0px',
+ 'margin': 0
+ })
+ .data(
+ 'isFullscreen', true
+ );
+
+ var updateTargetSize = function() {
+ context.scroll(0, 0);
+ $target.css({
+ 'width' : context.innerWidth,
+ 'height' : context.innerHeight
+ });
+ // update player size if needed:
+ _this.embedPlayer.applyIntrinsicAspect();
+ };
+
+ updateTargetSize();
+
+ // Bind orientation change to resize player ( if fullscreen )
+ $( context ).bind( 'orientationchange', function(e){
+ if( _this.isInFullScreen() ){
+ updateTargetSize();
+ }
+ });
+
+ // prevent scrolling when in fullscreen: ( both iframe and dom target use document )
+ document.ontouchmove = function( e ){
+ if( _this.isInFullScreen() ){
+ e.preventDefault();
+ }
+ };
+ },
+ /**
+ * Restore the player interface or iframe to a window player
+ */
+ restoreContextPlayer: function(){
+ var
+ _this = this,
+ doc = window.document,
+ $doc = $( doc ),
+ $target = $( this.getFsTarget() ),
+ context = window;
+
+ mw.log("PlayerControlsBuilder:: restoreContextPlayer> verticalScrollPosition:" + this.verticalScrollPosition );
+
+ // Restore document zoom:
+ if( this.orginalParnetViewPortContent ){
+ $doc.find('meta[name="viewport"]').attr('content', this.orginalParnetViewPortContent );
+ } else {
+ // Restore user zoom: ( NOTE, there does not appear to be a way to know the
+ // initial scale, so we just restore to 1 in the absence of explicit viewport tag )
+ // In order to restore zoom, we must set maximum-scale to a valid value
+ $doc.find('meta[name="viewport"]').attr('content', 'initial-scale=1; maximum-scale=8; minimum-scale=1;' );
+ }
+ if( this.orginalTargetElementLayout ) {
+ $target[0].style.cssText = this.orginalTargetElementLayout.style;
+ $target.attr({
+ 'width': this.orginalTargetElementLayout.width,
+ 'height': this.orginalTargetElementLayout.height
+ });
+ // update player size if needed:
+ _this.embedPlayer.applyIntrinsicAspect();
+ }
+ // Restore any parent absolute pos:
+ $doc.find( _this.parentsAbsoluteList ).each( function() {
+ $( this ).css( 'position', 'absolute' );
+ } );
+ $doc.find( _this.parentsRelativeList ).each( function() {
+ $( this ).css( 'position', 'relative' );
+ } );
+ },
+
+ /**
+ * Supports hybrid native fullscreen, player html controls, and fullscreen is native
+ */
+ doHybridNativeFullscreen: function(){
+ var vid = this.embedPlayer.getPlayerElement();
+ var _this = this;
+ vid.webkitEnterFullscreen();
+ // start to pull for exit fullscreen:
+ this.fsIntervalID = setInterval( function(){
+ var currentFS = vid.webkitDisplayingFullscreen;
+ // Check if we have entered fullscreen but the player
+ // has exited fullscreen with native controls click
+ if( _this.isInFullScreen() && !currentFS ){
+ // restore non-fullscreen player state
+ _this.inFullScreen = false;
+ // Trigger the onCloseFullscreen event:
+ $( _this.embedPlayer ).trigger( 'onCloseFullScreen' );
+ // stop polling for state change.
+ clearInterval( _this.fsIntervalID );
+ }
+ }, 250 );
+ },
+ getWindowSize: function(){
+ return {
+ 'width' : $(window).width(),
+ 'height' : $(window).height()
+ };
+ },
+ doDomFullscreen: function(){
+ var _this = this;
+ var embedPlayer = this.embedPlayer;
+ var $interface = embedPlayer.getInterface();
+ // Remove any old mw-fullscreen-overlay
+ $( '.mw-fullscreen-overlay' ).remove();
+
+ _this.preFullscreenPlayerSize = this.getPlayerSize();
+
+ // Add the css fixed fullscreen black overlay as a sibling to the video element
+ // iOS4 does not respect z-index
+ $interface.after(
+ $( '<div />' )
+ .addClass( 'mw-fullscreen-overlay' )
+ // Set some arbitrary high z-index
+ .css('z-index', mw.config.get( 'EmbedPlayer.FullScreenZIndex' ) )
+ .hide()
+ .fadeIn("slow")
+ );
+
+ // get the original interface to absolute positioned:
+ if( ! this.windowPositionStyle ){
+ this.windowPositionStyle = $interface.css( 'position' );
+ }
+ if( !this.windowZindex ){
+ this.windowZindex = $interface.css( 'z-index' );
+ }
+ // Get the base offset:
+ this.windowOffset = this.getWindowOffset();
+
+ // Change the z-index of the interface
+ $interface.css( {
+ 'position' : 'fixed',
+ 'z-index' : mw.config.get( 'EmbedPlayer.FullScreenZIndex' ) + 1,
+ 'top' : this.windowOffset.top,
+ 'left' : this.windowOffset.left
+ } );
+
+ // If native persistent native player update z-index:
+ if( embedPlayer.isPersistentNativePlayer() ){
+ $( embedPlayer.getPlayerElement() ).css( {
+ 'z-index': mw.config.get( 'EmbedPlayer.FullScreenZIndex' ) + 1,
+ 'position': 'absolute'
+ });
+ }
+
+ // Empty out the parent absolute index
+ _this.parentsAbsolute = [];
+
+ // Hide the body scroll bar
+ $('body').css( 'overflow', 'hidden' );
+
+ var topOffset = '0px';
+ var leftOffset = '0px';
+
+ // Check if we have an offsetParent
+ if( $interface.offsetParent()[0].tagName
+ &&
+ $interface.offsetParent()[0].tagName.toLowerCase() != 'body' )
+ {
+ topOffset = -this.windowOffset.top + 'px';
+ leftOffset = -this.windowOffset.left + 'px';
+ }
+
+ // Overflow hidden in fullscreen:
+ $interface.css( 'overlow', 'hidden' );
+
+ // Remove absolute css of the interface parents
+ $interface.parents().each( function() {
+ //mw.log(' parent : ' + $( this ).attr('id' ) + ' class: ' + $( this ).attr('class') + ' pos: ' + $( this ).css( 'position' ) );
+ if( $( this ).css( 'position' ) == 'absolute' ) {
+ _this.parentsAbsolute.push( $( this ) );
+ $( this ).css( 'position', null );
+ mw.log( 'PlayerControlBuilder:: should update position: ' + $( this ).css( 'position' ) );
+ }
+ });
+
+ // Bind escape to restore in page clip
+ $( window ).keyup( function( event ) {
+ // Escape check
+ if( event.keyCode == 27 ){
+ _this.restoreWindowPlayer();
+ }
+ } );
+ },
+ addFullscreenMouseMoveHideShowControls:function(){
+ var _this = this;
+ // Bind mouse move in interface to hide control bar
+ _this.mouseMovedFlag = false;
+ _this.embedPlayer.getInterface().mousemove( function(e){
+ _this.mouseMovedFlag = true;
+ });
+
+ // Check every 2 seconds reset flag status if controls are overlay
+ var checkMovedMouse = function(){
+ if( _this.isInFullScreen() ){
+ if( _this.mouseMovedFlag ){
+ _this.mouseMovedFlag = false;
+ _this.showControlBar();
+ // Once we move the mouse keep displayed for 3 seconds
+ setTimeout(checkMovedMouse, 3000);
+ } else {
+ // Check for mouse movement every 250ms
+ _this.hideControlBar();
+ setTimeout(checkMovedMouse, 250 );
+ }
+ return;
+ }
+ };
+ // always initially show the control bar:
+ _this.showControlBar();
+ // start monitoring for moving mouse
+ checkMovedMouse();
+ },
+ getWindowOffset: function(){
+ var windowOffset = this.embedPlayer.getInterface().offset();
+ windowOffset.top = windowOffset.top - $(document).scrollTop();
+ windowOffset.left = windowOffset.left - $(document).scrollLeft();
+ this.windowOffset = windowOffset;
+ return this.windowOffset;
+ },
+ // Display a fullscreen tip if configured to do and the browser supports it.
+ displayFullscreenTip: function(){
+ var _this = this;
+ // Mobile devices don't have f11 key
+ if( mw.isMobileDevice() ){
+ return ;
+ }
+ // Safari does not have a DOM fullscreen ( no subtitles, no controls )
+ if ( $.client.profile().name === 'safari' ) {
+ return;
+ }
+
+ // OSX has a different short cut than windows and liux
+ var toolTipMsg = ( navigator.userAgent.indexOf('Mac OS X') != -1 )?
+ mw.msg( 'mwe-embedplayer-fullscreen-tip-osx') :
+ mw.msg( 'mwe-embedplayer-fullscreen-tip');
+
+ var $targetTip = this.addWarningBinding( 'EmbedPlayer.FullscreenTip',
+ $('<h3/>').html(
+ toolTipMsg
+ )
+ );
+
+ // Display the target warning:
+ $targetTip.show();
+
+ var hideTip = function(){
+ mw.setConfig('EmbedPlayer.FullscreenTip', false );
+ $targetTip.fadeOut('fast');
+ };
+
+ // Hide fullscreen tip if:
+ // We leave fullscreen,
+ $( this.embedPlayer ).bind( 'onCloseFullScreen', hideTip );
+ // After 5 seconds,
+ setTimeout( hideTip, 5000 );
+ // Or if we catch an f11 button press
+ $( document ).keyup( function( event ){
+ if( event.keyCode == 122 ){
+ hideTip();
+ }
+ return true;
+ });
+ },
+ // TOOD fullscreen iframe vs inpage object abstraction
+ //( avoid repatiave conditionals in getters )
+ getPlayerSize: function(){
+ var height = $(window).height() - this.getHeight();
+ if( mw.config.get('EmbedPlayer.IsIframeServer' ) ){
+ return {
+ 'height' : height,
+ 'width' : $(window).width()
+ }
+ } else {
+ return {
+ 'height' : this.embedPlayer.getInterface().height(),
+ 'width' : this.embedPlayer.getInterface().width()
+ }
+ }
+ },
+ getFsTarget: function(){
+ var $interface = this.embedPlayer.getInterface();
+ return $interface[0];
+ },
+ /**
+ * Restore the window player
+ */
+ restoreWindowPlayer: function() {
+ var _this = this;
+ mw.log("PlayerControlBuilder :: restoreWindowPlayer" );
+ var embedPlayer = this.embedPlayer;
+
+ // Check if fullscreen mode is already restored:
+ if( this.isInFullScreen() === false ){
+ return ;
+ }
+ // Set fullscreen mode to false
+ this.inFullScreen = false;
+
+ // remove the fullscreen interface
+ embedPlayer.getInterface().removeClass( 'fullscreen' );
+
+ // Check for native support for fullscreen and support native fullscreen restore
+ if ( window.fullScreenApi.supportsFullScreen ) {
+ var fsTarget = this.getFsTarget();
+ window.fullScreenApi.cancelFullScreen( fsTarget );
+ }
+
+ // Restore the iFrame context player
+ this.restoreContextPlayer();
+
+ // Restore scrolling on iPad
+ $( document ).unbind( 'touchend.fullscreen' );
+
+ // Trigger the onCloseFullscreen event:
+ $( embedPlayer ).trigger( 'onCloseFullScreen' );
+
+ // Scroll back to the previews position ( do in async call to allow dom fullscreen restore )
+ setTimeout( function(){
+ window.scroll( 0, _this.verticalScrollPosition );
+ }, 100 );
+
+ // re draw the controls after a timeout ( to allow the screen dom to update )
+ setTimeout( function(){
+ _this.addControls();
+ },100)
+ },
+ restoreDomPlayer: function(){
+ var _this = this;
+ // local ref to embedPlayer:
+ var embedPlayer = this.embedPlayer;
+
+ var $interface = embedPlayer.$interface;
+ var interfaceHeight = ( _this.isOverlayControls() )
+ ? embedPlayer.getHeight()
+ : embedPlayer.getHeight() + _this.getHeight();
+
+ mw.log( 'restoreWindowPlayer:: h:' + interfaceHeight + ' w:' + embedPlayer.getWidth());
+ $('.mw-fullscreen-overlay').remove( 'slow' );
+
+ mw.log( 'restore embedPlayer:: ' + embedPlayer.getWidth() + ' h: ' + embedPlayer.getHeight() );
+
+ // Restore the player:
+ embedPlayer.getInterface().css( {
+ 'width' : _this.preFullscreenPlayerSize.width,
+ 'height' : _this.preFullscreenPlayerSize.height
+ });
+ var topPos = {
+ 'position' : _this.windowPositionStyle,
+ 'z-index' : _this.windowZindex,
+ 'overlow' : 'visible',
+ 'top' : '0px',
+ 'left' : '0px'
+ };
+ // Restore non-absolute layout:
+ $( [ $interface, $interface.find('.playerPoster'), embedPlayer ] ).css( topPos );
+ if( embedPlayer.getPlayerElement() ){
+ $( embedPlayer.getPlayerElement() )
+ .css( topPos )
+ }
+ // Restore the body scroll bar
+ $('body').css( 'overflow', 'auto' );
+
+ // If native player restore z-index:
+ if( embedPlayer.isPersistentNativePlayer() ){
+ $( embedPlayer.getPlayerElement() ).css( {
+ 'z-index': 'auto'
+ });
+ }
+ },
+ /**
+ * Get minimal width for interface overlay
+ */
+ getOverlayWidth: function( ) {
+ return ( this.embedPlayer.getPlayerWidth() < 300 )? 300 : this.embedPlayer.getPlayerWidth();
+ },
+
+ /**
+ * Get minimal height for interface overlay
+ */
+ getOverlayHeight: function( ) {
+ return ( this.embedPlayer.getPlayerHeight() < 200 )? 200 : this.embedPlayer.getPlayerHeight();
+ },
+
+ /**
+ * addControlBindings
+ * Adds control hooks once controls are in the DOM
+ */
+ addControlBindings: function( ) {
+ // Set up local pointer to the embedPlayer
+ var embedPlayer = this.embedPlayer,
+ _this = this,
+ $interface = embedPlayer.getInterface(),
+ profile = $.client.profile();
+
+ _this.onControlBar = false;
+
+ // Remove any old interface bindings
+ $( embedPlayer ).unbind( this.bindPostfix );
+
+ var bindFirstPlay = false;
+ _this.addRightClickBinding();
+
+ // add the player click bindings
+ _this.addPlayerClickBindings();
+
+ // Bind into play.ctrl namespace ( so we can unbind without affecting other play bindings )
+ $( embedPlayer ).bind( 'onplay' + this.bindPostfix, function() { //Only bind once played
+ // add right click binding again ( in case the player got swaped )
+ embedPlayer.controlBuilder.addRightClickBinding();
+ });
+
+ $( embedPlayer ).bind( 'timeupdate' + this.bindPostfix, function(){
+ embedPlayer.updatePlayheadStatus()
+ });
+
+ // Update buffer information
+ $( embedPlayer ).bind( 'progress' + this.bindPostfix, function( event, jEvent, id){
+ // regain scope
+ var embedPlayer = $( '#' + id )[0];
+ embedPlayer.updateBufferStatus();
+ });
+
+ // Bind to EnableInterfaceComponents
+ $( embedPlayer ).bind( 'onEnableInterfaceComponents' + this.bindPostfix, function() {
+ embedPlayer.controlBuilder.controlsDisabled = false;
+ embedPlayer.controlBuilder.addPlayerClickBindings();
+ });
+
+ // Bind to DisableInterfaceComponents
+ $( embedPlayer ).bind( 'onDisableInterfaceComponents' + this.bindPostfix, function() {
+ embedPlayer.controlBuilder.controlsDisabled = true;
+ embedPlayer.controlBuilder.removePlayerClickBindings();
+ });
+
+
+ // TODO select a player on the page
+ var bindSpaceUp = function(){
+ $(window).bind('keyup' + _this.bindPostfix, function(e) {
+ if( e.keyCode == 32 ) {
+ if(embedPlayer.paused) {
+ embedPlayer.play();
+ } else {
+ embedPlayer.pause();
+ }
+ return false;
+ }
+ });
+ };
+
+ var bindSpaceDown = function() {
+ $(window).unbind( 'keyup' + _this.bindPostfix );
+ };
+
+ // Bind to resize event
+ /*
+ var triggerUpdate;
+ $( window ).resize(function() {
+ // We use setTimeout because of iOS 4.2 issues
+ clearTimeout(triggerUpdate);
+ triggerUpdate = setTimeout(function() {
+ //embedPlayer.triggerHelper('updateLayout');
+ }, 100);
+ });
+ */
+
+ $(window).on("debouncedresize", function() {
+ embedPlayer.triggerHelper('updateLayout');
+ });
+
+ // Add hide show bindings for control overlay (if overlay is enabled )
+ if( ! _this.isOverlayControls() ) {
+ $interface
+ .show()
+ .hover( bindSpaceUp, bindSpaceDown );
+
+ // include touch start pause binding
+ $( embedPlayer).bind( 'touchstart' + this.bindPostfix, function() {
+ embedPlayer._playContorls = true;
+ mw.log( "PlayerControlBuilder:: touchstart:" + ' isPause:' + embedPlayer.paused);
+ if( embedPlayer.paused ) {
+ embedPlayer.play();
+ } else {
+ embedPlayer.pause();
+ }
+ });
+ } else { // hide show controls:
+ // Bind a startTouch to show controls
+ $( embedPlayer).bind( 'touchstart' + this.bindPostfix, function() {
+ if ( embedPlayer.getInterface().find( '.control-bar' ).is( ':visible' ) ) {
+ if( embedPlayer.paused ) {
+ embedPlayer.play();
+ } else {
+ embedPlayer.pause();
+ }
+ } else {
+ _this.showControlBar();
+ }
+ clearTimeout( _this.hideControlBarCallback );
+ _this.hideControlBarCallback = setTimeout( function() {
+ _this.hideControlBar();
+ }, 60000 );
+ // ( Once the user touched the video "don't hide" )
+ return true;
+ } );
+
+ var hoverIntentConfig = {
+ 'sensitivity': 100,
+ 'timeout' : 1000,
+ 'over' : function(e){
+ // Clear timeout on IE9
+ if( mw.isIE9() ) {
+ clearTimeout(_this.hideControlBarCallback);
+ _this.hideControlBarCallback = false;
+ }
+ // Show controls with a set timeout ( avoid fade in fade out on short mouse over )
+ _this.showControlBar();
+ bindSpaceUp();
+ },
+ 'out' : function(e){
+ _this.hideControlBar();
+ bindSpaceDown();
+ }
+ };
+
+ // Check if we should display the interface:
+ // special check for IE9 ( does not count hover on non-visiable inerface div
+ if( mw.isIE9() ){
+ $( embedPlayer.getPlayerElement() ).hoverIntent( hoverIntentConfig );
+
+ // Add hover binding to control bar
+ embedPlayer.getInterface().find( '.control-bar' ).hover( function(e) {
+ _this.onControlBar = true;
+ embedPlayer.getInterface().find( '.control-bar' ).show();
+ }, function( e ) {
+ if (!_this.hideControlBarCallback) {
+ _this.hideControlBarCallback = setTimeout(function(){
+ _this.hideControlBar();
+ },1000);
+ }
+ _this.onControlBar = false;
+ });
+
+ } else {
+ if ( !mw.isIpad() ) {
+ $interface.hoverIntent( hoverIntentConfig );
+ }
+ }
+
+ }
+
+ // Add recommend firefox if we have non-native playback:
+ if ( _this.checkNativeWarning( ) ) {
+ _this.addWarningBinding(
+ 'EmbedPlayer.ShowNativeWarning',
+ mw.msg( 'mwe-embedplayer-for_best_experience',
+ $('<div>').append(
+ $('<a />')
+ .attr({
+ 'href': 'http://www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download',
+ 'target' : '_new'
+ })
+ )[0].innerHTML
+ )
+ );
+ }
+
+ // Do png fix for ie6
+ if ( profile.name === 'msie' && profile.versionNumber <= 6 ) {
+ $( '#' + embedPlayer.id + ' .play-btn-large' ).pngFix();
+ }
+
+ this.doVolumeBinding();
+
+ // Check if we have any custom skin Bindings to run
+ if ( this.addSkinControlBindings && typeof( this.addSkinControlBindings ) == 'function' ){
+ this.addSkinControlBindings();
+ }
+
+ mw.log( 'trigger::addControlBindingsEvent' );
+ $( embedPlayer ).trigger( 'addControlBindingsEvent' );
+ },
+ removePlayerClickBindings: function(){
+ $( this.embedPlayer )
+ .unbind( "click" + this.bindPostfix )
+ .unbind( "dblclick" + this.bindPostfix );
+ },
+ addPlayerClickBindings: function(){
+
+ var _this = this;
+ var embedPlayer = this.embedPlayer;
+
+ // prevent scrolling when in fullscreen:
+ document.ontouchmove = function( e ){
+ if( _this.isInFullScreen() ){
+ e.preventDefault();
+ }
+ };
+ // Remove old click bindings before adding:
+ this.removePlayerClickBindings();
+
+ // Setup "dobuleclick" fullscreen binding to embedPlayer ( if enabled )
+ if ( this.supportedComponents['fullscreen'] ){
+ $( embedPlayer ).bind( "dblclick" + _this.bindPostfix, function(){
+ embedPlayer.fullscreen();
+ });
+ }
+
+ var dblClickTime = 300;
+ var lastClickTime = 0;
+ var didDblClick = false;
+
+ var playerClickCb = function( event ) {
+ // make sure the event matches:
+ if( event.currentTarget.id != embedPlayer.id ){
+ embedPlayer = $( '#' + event.currentTarget.id )[0];
+ }
+ mw.log( "PlayerControlBuilder:: click:" + embedPlayer.id + ' isPause:' + embedPlayer.paused);
+ // Don't do anything if touch interface or native controls are shown
+ if( embedPlayer.useNativePlayerControls()
+ ||
+ _this.isControlsDisabled()
+ ||
+ embedPlayer.isTouchDevice()
+ ) {
+ return true;
+ }
+ var clickTime = new Date().getTime();
+ if( clickTime -lastClickTime < dblClickTime ) {
+ didDblClick = true;
+ setTimeout( function(){
+ didDblClick = false;
+ }, dblClickTime + 10 );
+ }
+ lastClickTime = clickTime;
+ setTimeout( function(){
+ // check if no click has since the time we called the setTimeout
+ if( !didDblClick ){
+ if( embedPlayer.paused ) {
+ embedPlayer.play();
+ } else {
+ embedPlayer.pause();
+ }
+ }
+ }, dblClickTime );
+ return true;
+ };
+ // Add click binding: ( $(embedPlayer).click ) has scope issues )
+ if ( embedPlayer.attachEvent ) {
+ embedPlayer.attachEvent("onclick", playerClickCb);
+ } else{
+ // Firefox 3.5 requires third argument to addEventListener
+ embedPlayer.addEventListener('click', playerClickCb, false );
+ }
+
+ },
+ addRightClickBinding: function(){
+ var embedPlayer = this.embedPlayer;
+ // check config:
+ if( mw.config.get( 'EmbedPlayer.EnableRightClick') === false ){
+ document.oncontextmenu= function(e){return false;};
+ $(embedPlayer).mousedown(function(e){
+ if( e.button == 2 ) {
+ return false;
+ }
+ });
+ }
+ },
+ /**
+ * Hide the control bar.
+ */
+ hideControlBar : function(){
+ var animateDuration = 'fast';
+ var _this = this;
+
+ // Do not hide control bar if overlay menu item is being displayed:
+ if( _this.displayOptionsMenuFlag || _this.keepControlBarOnScreen ) {
+ setTimeout( function(){
+ _this.hideControlBar();
+ }, 200 );
+ return ;
+ }
+
+ // IE9: If the user mouse is on the control bar, don't hide it
+ if( this.onControlBar === true ) {
+ return ;
+ }
+
+ // Hide the control bar
+ this.embedPlayer.getInterface().find( '.control-bar')
+ .fadeOut( animateDuration );
+ //mw.log('about to trigger hide control bar')
+ // Allow interface items to update:
+ $( this.embedPlayer ).trigger('onHideControlBar', [ {'bottom' : 15}, this.embedPlayer.id ] );
+
+ },
+ restoreControlsHover:function(){
+ if( this.isOverlayControls() ){
+ this.keepControlBarOnScreen = false;
+ }
+ },
+ /**
+ * Show the control bar
+ */
+ showControlBar: function( keepOnScreen ){
+ var animateDuration = 'fast';
+ if(! this.embedPlayer )
+ return ;
+
+ if( this.embedPlayer.getPlayerElement && ! this.embedPlayer.isPersistentNativePlayer() ){
+ $( this.embedPlayer.getPlayerElement() ).css( 'z-index', '1' );
+ }
+ mw.log( 'PlayerControlBuilder:: ShowControlBar, keep on screen: ' + keepOnScreen );
+
+ // Show interface controls
+ this.embedPlayer.getInterface().find( '.control-bar' )
+ .fadeIn( animateDuration );
+
+ if( keepOnScreen ){
+ this.keepControlBarOnScreen = true;
+ }
+
+ // Trigger the screen overlay with layout info:
+ $( this.embedPlayer ).trigger( 'onShowControlBar', [{
+ 'bottom' : this.getHeight() + 15
+ }, this.embedPlayer.id ] );
+ },
+
+ /**
+ * Checks if the browser supports overlays and the controlsOverlay is
+ * set to true for the player or via config
+ */
+ isOverlayControls: function(){
+ //if the player "supports" overlays:
+ if( ! this.embedPlayer.supports['overlays'] ){
+ return false;
+ }
+
+ // If disabled via the player
+ if( this.embedPlayer.overlaycontrols === false ){
+ return false;
+ }
+
+ // Don't overlay controls if in audio mode:
+ if( this.embedPlayer.isAudio() ){
+ return false;
+ }
+
+
+ // If the config is false
+ if( mw.config.get( 'EmbedPlayer.OverlayControls' ) === false){
+ return false;
+ }
+
+ if( this.embedPlayer.controls === false ){
+ return false;
+ }
+
+ // Past all tests OverlayControls is true:
+ return true;
+ },
+
+ /* Check if the controls are disabled */
+
+ isControlsDisabled: function() {
+ return this.controlsDisabled;
+ },
+
+ /**
+ * Check if a warning should be issued to non-native playback systems
+ *
+ * dependent on mediaElement being setup
+ */
+ checkNativeWarning: function( ) {
+ if( mw.config.get( 'EmbedPlayer.ShowNativeWarning' ) === false ){
+ return false;
+ }
+
+ // Don't show for imageOverlay player:
+ if( this.embedPlayer.instanceOf == 'ImageOverlay' ){
+ return false;
+ }
+
+ // If the resolution is too small don't display the warning
+ if( parseInt( this.embedPlayer.getPlayerHeight() ) < 199 ){
+ return false;
+ }
+
+ // See if we have we have native support
+ if( this.embedPlayer.instanceOf == 'Native' ){
+ return false;
+ }
+
+ // Not a lot of good options for an iPhone
+ if( this.embedPlayer.instanceOf == 'VLCApp' ){
+ return false;
+ }
+ if( this.embedPlayer.instanceOf == 'OgvJs' ){
+ return false;
+ }
+
+ // Chrome's webM support is oky though:
+ if( /chrome/.test(navigator.userAgent.toLowerCase() ) &&
+ mw.EmbedTypes.getMediaPlayers().getMIMETypePlayers( 'video/webm' ).length ){
+ return false;
+ }
+
+
+ // Check for h264 and or flash/flv source and playback support and don't show warning
+ if(
+ ( mw.EmbedTypes.getMediaPlayers().getMIMETypePlayers( 'video/h264' ).length
+ && this.embedPlayer.mediaElement.getSources( 'video/h264' ).length )
+ ||
+ ( mw.EmbedTypes.getMediaPlayers().getMIMETypePlayers( 'video/x-flv' ).length
+ && this.embedPlayer.mediaElement.getSources( 'video/x-flv' ).length )
+ ||
+ ( mw.EmbedTypes.getMediaPlayers().getMIMETypePlayers( 'application/vnd.apple.mpegurl' ).length
+ && this.embedPlayer.mediaElement.getSources( 'application/vnd.apple.mpegurl' ).length )
+ ||
+ ( mw.EmbedTypes.getMediaPlayers().getMIMETypePlayers( 'audio/mpeg' ).length
+ && this.embedPlayer.mediaElement.getSources( 'audio/mpeg' ).length )
+ ){
+ // No firefox link if a h.264 or flash/flv stream is present
+ return false;
+ }
+
+ // Should issue the native warning
+ return true;
+ },
+
+ /**
+ * Does a native warning check binding to the player on mouse over.
+ * @param {string} preferenceId The preference Id
+ * @param {object} warningMsg The jQuery object warning message to be displayed.
+ *
+ */
+ /**
+ * Display a warning message on the player
+ * checks a preference Id to enable or disable it.
+ * @param {string} preferenceId The preference Id
+ * @param {object} warningMsg The jQuery object warning message to be displayed.
+ * @param {boolean} if the hide ui should be exposed
+ *
+ */
+ addWarningBinding: function( preferenceId, warningMsg, hideDisableUi ) {
+ mw.log( 'mw.PlayerControlBuilder: addWarningBinding: ' + preferenceId + ' wm: ' + warningMsg);
+ // Set up local pointer to the embedPlayer
+ var embedPlayer = this.embedPlayer;
+ var _this = this;
+ // make sure the player is large enough
+ if( embedPlayer.getWidth() < 200 ){
+ return false;
+ }
+
+ // Can be uncommented to reset hide prefrence
+ //$.cookie( preferenceId, '' );
+
+ // Check if a cookie has been set to hide the warning:
+ if ( mw.config.get( preferenceId ) === true && $.cookie( preferenceId ) == 'hidewarning' ){
+ return ;
+ }
+
+ var warnId = "warningOverlay_" + embedPlayer.id;
+ $( '#' + warnId ).remove();
+
+ // Add the targetWarning:
+ var $targetWarning = $('<div />')
+ .attr( {
+ 'id': warnId
+ } )
+ .addClass( 'ui-corner-all' )
+ .css({
+ 'position' : 'absolute',
+ 'background' : '#FFF',
+ 'color' : '#111',
+ 'top' : '10px',
+ 'left' : '10px',
+ 'right' : '10px',
+ 'padding' : '4px',
+ // z-index should be > than play button, as well as greater
+ // than the dialog box (in pop up video), or link won't work.
+ 'z-index' : '1502',
+ })
+ .html( warningMsg );
+
+ embedPlayer.getInterface().append(
+ $targetWarning
+ );
+
+ $targetWarning.append(
+ $('<br />')
+ );
+ // check if we should show the checkbox
+ if( !hideDisableUi ){
+
+ $targetWarning.append(
+ $( '<input type="checkbox" />' )
+ .attr({
+ 'id' : 'ffwarn_' + embedPlayer.id,
+ 'name' : 'ffwarn_' + embedPlayer.id
+ })
+ .click( function() {
+ mw.log("WarningBindinng:: set " + preferenceId + ' to hidewarning ' );
+ // Set up a cookie for 30 days:
+ $.cookie( preferenceId, 'hidewarning', {expires: 30} );
+ // Set the current instance
+ mw.setConfig( preferenceId, false );
+ $( '#warningOverlay_' + embedPlayer.id ).fadeOut( 'slow' );
+ // set the local preference to false
+ _this.addWarningFlag = false;
+ } )
+ );
+ $targetWarning.append(
+ $('<label />')
+ .text( mw.msg( 'mwe-embedplayer-do_not_warn_again' ) )
+ .attr( 'for', 'ffwarn_' + embedPlayer.id )
+ );
+ }
+
+ return $targetWarning;
+ },
+
+ /**
+ * Binds the volume controls
+ */
+ doVolumeBinding: function( ) {
+ var embedPlayer = this.embedPlayer;
+ var _this = this;
+ embedPlayer.getInterface().find( '.volume_control' ).unbind().buttonHover().click( function() {
+ mw.log( 'Volume control toggle' );
+ embedPlayer.toggleMute();
+ } );
+
+ // Add vertical volume display hover
+ if ( this.volumeLayout == 'vertical' ) {
+ // Default volume binding:
+ var hoverOverDelay = false;
+ var $targetvol = embedPlayer.getInterface().find( '.vol_container' ).hide();
+ embedPlayer.getInterface().find( '.volume_control' ).hover(
+ function() {
+ $targetvol.addClass( 'vol_container_top' );
+ // Set to "below" if playing and embedType != native
+ if ( embedPlayer && embedPlayer.isPlaying && embedPlayer.isPlaying() && !embedPlayer.supports['overlays'] ) {
+ $targetvol.removeClass( 'vol_container_top' ).addClass( 'vol_container_below' );
+ }
+ $targetvol.fadeIn( 'fast' );
+ hoverOverDelay = true;
+ },
+ function() {
+ hoverOverDelay = false;
+ setTimeout( function() {
+ if ( !hoverOverDelay ) {
+ $targetvol.fadeOut( 'fast' );
+ }
+ }, 500 );
+ }
+ );
+ }
+ var userSlide=false;
+ // Setup volume slider:
+ var sliderConf = {
+ range: "min",
+ value: 80,
+ min: 0,
+ max: 100,
+ slide: function( event, ui ) {
+ var percent = ui.value / 100;
+ mw.log('PlayerControlBuilder::slide:update volume:' + percent);
+ embedPlayer.setVolume( percent );
+ userSlide = true;
+ },
+ change: function( event, ui ) {
+ var percent = ui.value / 100;
+ if ( percent == 0 ) {
+ embedPlayer.getInterface().find( '.volume_control span' ).removeClass( 'ui-icon-volume-on' ).addClass( 'ui-icon-volume-off' );
+ } else {
+ embedPlayer.getInterface().find( '.volume_control span' ).removeClass( 'ui-icon-volume-off' ).addClass( 'ui-icon-volume-on' );
+ }
+ mw.log('PlayerControlBuilder::change:update volume:' + percent);
+ embedPlayer.setVolume( percent, userSlide );
+ userSlide = false;
+ }
+ };
+
+ if ( this.volumeLayout == 'vertical' ) {
+ sliderConf[ 'orientation' ] = "vertical";
+ }
+
+ embedPlayer.getInterface().find( '.volume-slider' ).slider( sliderConf );
+ },
+
+ /**
+ * Get the options menu ul with li menu items
+ */
+ getOptionsMenu: function( ) {
+ var $optionsMenu = $( '<ul />' );
+ for( var menuItemKey in this.optionMenuItems ){
+
+ // Make sure its supported in the current controlBuilder config:
+ if( $.inArray( menuItemKey, mw.config.get( 'EmbedPlayer.EnabledOptionsMenuItems' ) ) === -1 ) {
+ continue;
+ }
+
+ $optionsMenu.append(
+ this.optionMenuItems[ menuItemKey ]( this )
+ );
+ }
+ return $optionsMenu;
+ },
+
+ /**
+ * Allow the controlBuilder to do interface actions onDone
+ */
+ onClipDone: function(){
+ // Related videos could be shown here
+ },
+
+ /**
+ * The ctrl builder updates the interface on seeking
+ */
+ onSeek: function(){
+ //mw.log( "controlBuilder:: onSeek" );
+ // Update the interface:
+ this.setStatus( mw.msg( 'mwe-embedplayer-seeking' ) );
+ // add a loading spinner:
+ this.embedPlayer.addPlayerSpinner();
+ // hide once playing again:
+ this.embedPlayer.hideSpinnerOncePlaying();
+ },
+
+ /**
+ * Updates the player status that displays short text msgs and the play clock
+ * @param {String} value Status string value to update
+ */
+ setStatus: function( value ) {
+ // update status:
+ if( this.embedPlayer.getInterface() ){
+ this.embedPlayer.getInterface().find( '.time-disp' ).text( value );
+ }
+ },
+
+ /**
+ * Option menu items
+ *
+ * @return
+ * 'li' a li line item with click action for that menu item
+ */
+ optionMenuItems: {
+ // Share the video menu
+ 'share': function( ctrlObj ) {
+ return $.getLineItem(
+ mw.msg( 'mwe-embedplayer-share' ),
+ 'mail-closed',
+ function( ) {
+ ctrlObj.displayMenuOverlay(
+ ctrlObj.getShare()
+ );
+ $( ctrlObj.embedPlayer ).trigger( 'showShareEvent' );
+ }
+ );
+ },
+
+ 'aboutPlayerLibrary' : function( ctrlObj ){
+ return $.getLineItem(
+ mw.msg( 'mwe-embedplayer-about-library' ),
+ 'info',
+ function( ) {
+ ctrlObj.displayMenuOverlay(
+ ctrlObj.aboutPlayerLibrary()
+ );
+ $( ctrlObj.embedPlayer ).trigger( 'aboutPlayerLibrary' );
+ }
+ );
+ }
+ },
+
+ /**
+ * Close a menu overlay
+ */
+ closeMenuOverlay: function(){
+ var _this = this;
+ var embedPlayer = this.embedPlayer;
+ var $overlay = embedPlayer.getInterface().find( '.overlay-win,.ui-widget-overlay,.ui-widget-shadow' );
+
+ this.displayOptionsMenuFlag = false;
+ //mw.log(' closeMenuOverlay: ' + this.displayOptionsMenuFlag);
+
+ $overlay.fadeOut( "slow", function() {
+ $overlay.remove();
+ } );
+
+ // Show the big play button: ( if not in an ad .. TODO clean up )
+ if( embedPlayer.isStopped() &&
+ (
+ embedPlayer.sequenceProxy &&
+ embedPlayer.sequenceProxy.isInSequence == false
+ )
+ ){
+ embedPlayer.getInterface().find( '.play-btn-large' ).fadeIn( 'slow' );
+ }
+
+ $(embedPlayer).trigger( 'closeMenuOverlay' );
+
+ return false; // onclick action return false
+ },
+
+ /**
+ * Generic function to display custom HTML overlay on video.
+ *
+ * @param {String} overlayContent content to be displayed
+ */
+ displayMenuOverlay: function( overlayContent, closeCallback, hideCloseButton ) {
+ var _this = this;
+ var embedPlayer = this.embedPlayer;
+ mw.log( 'PlayerControlBuilder:: displayMenuOverlay' );
+ // set the overlay display flag to true:
+ this.displayOptionsMenuFlag = true;
+
+ if ( !this.supportedComponents[ 'overlays' ] ) {
+ embedPlayer.stop();
+ }
+
+
+ // Hide the big play button:
+ embedPlayer.hideLargePlayBtn();
+
+ // Check if overlay window is already present:
+ if ( embedPlayer.getInterface().find( '.overlay-win' ).length != 0 ) {
+ //Update the content
+ embedPlayer.getInterface().find( '.overlay-content' ).html(
+ overlayContent
+ );
+ return ;
+ }
+
+ // Add an overlay
+ embedPlayer.getInterface().append(
+ $('<div />')
+ .addClass( 'ui-widget-overlay' )
+ .css( {
+ 'height' : '100%',
+ 'width' : '100%',
+ 'z-index' : 2
+ } )
+ );
+
+ var $closeButton = [];
+
+ if ( !hideCloseButton ) {
+ // Setup the close button
+ $closeButton = $('<div />')
+ .addClass( 'ui-state-default ui-corner-all ui-icon_link rButton')
+ .css({
+ 'position': 'absolute',
+ 'cursor' : 'pointer',
+ 'top' : '2px',
+ 'right' : '2px'
+ })
+ .click( function() {
+ _this.closeMenuOverlay();
+ if( closeCallback ){
+ closeCallback();
+ }
+ } )
+ .append(
+ $('<span />')
+ .addClass( 'ui-icon ui-icon-closethick' )
+ );
+ }
+
+ var controlBarHeight = embedPlayer.getInterface().find( '.control-bar' ).height();
+ var overlayWidth = (embedPlayer.getWidth() - 30);
+ var overlayHeight = (embedPlayer.getHeight() - (controlBarHeight + 30));
+ var overlayTop = (( (embedPlayer.getInterface().height() - controlBarHeight) - overlayHeight) / 2);
+ var overlayLeft = ((embedPlayer.getInterface().width() - overlayWidth) / 2);
+
+ var overlayMenuCss = {
+ 'height' : overlayHeight + 'px',
+ 'width' : overlayWidth + 'px',
+ 'position' : 'absolute',
+ 'top' : overlayTop + 'px',
+ 'left': overlayLeft + 'px',
+ 'margin': '0 10px 10px 0',
+ 'overflow' : 'auto',
+ 'padding' : '4px',
+ 'z-index' : 3
+ };
+ var $overlayMenu = $('<div />')
+ .addClass( 'overlay-win ui-state-default ui-widget-header ui-corner-all' )
+ .css( overlayMenuCss )
+ .append(
+ $closeButton,
+ $('<div />')
+ .addClass( 'overlay-content' )
+ .append( overlayContent )
+ );
+
+
+ // Append the overlay menu to the player interface
+ embedPlayer.getInterface().prepend(
+ $overlayMenu
+ )
+ .find( '.overlay-win' )
+ .fadeIn( "slow" );
+
+ // Trigger menu overlay display
+ $( embedPlayer ).trigger( 'displayMenuOverlay' );
+
+ return false; // onclick action return false
+ },
+
+ /**
+ * Close an alert
+ */
+ closeAlert: function( keepOverlay ) {
+ var embedPlayer = this.embedPlayer;
+ var $alert = $( '#alertContainer' );
+
+ mw.log( 'mw.PlayerControlBuilder::closeAlert' );
+ if ( !keepOverlay || ( mw.isIpad() && this.inFullScreen ) ) {
+ embedPlayer.controlBuilder.closeMenuOverlay();
+ if ( mw.isIpad() ) {
+ embedPlayer.disablePlayControls();
+ }
+ }
+
+ $alert.remove();
+
+ return false; // onclick action return false;
+ },
+
+ /**
+ * Generic function to display custom alert overlay on video.
+ *
+ * @param (Object) Object which includes:
+ * title Alert Title
+ * body Alert body
+ * buttonSet[label,callback] Array of buttons
+ * style CSS object
+ */
+ displayAlert: function( alertObj ) {
+ var embedPlayer = this.embedPlayer;
+ var callback;
+ mw.log( 'PlayerControlBuilder::displayAlert:: ' + alertObj.title );
+ // Check if callback is external or internal (Internal by default)
+
+ // Check if overlay window is already present:
+ if ( embedPlayer.getInterface().find( '.overlay-win' ).length != 0 ) {
+ return;
+ }
+ if( typeof alertObj.callbackFunction == 'string' ) {
+ if ( alertObj.isExternal ) {
+ // TODO better support of running external JS functions, instead of window.parent
+ try{
+ callback = window.parent[ alertObj.callbackFunction ];
+ } catch ( e ){
+ // could not call parent method
+ }
+ } else {
+ callback = window[ alertObj.callbackFunction ];
+ }
+ } else if( typeof alertObj.callbackFunction == 'function' ) {
+ // Make life easier for internal usage of the listener mapping by supporting
+ // passing a callback by function ref
+ callback = alertObj.callbackFunction;
+ } else {
+ mw.log( "PlayerControlBuilder :: displayAlert :: Error: bad callback type" );
+ callback = function() {};
+ }
+
+ var $container = $( '<div />' ).attr( 'id', 'alertContainer' ).addClass( 'alert-container' );
+ var $title = $( '<div />' ).text( alertObj.title ).addClass( 'alert-title alert-text' );
+ if ( alertObj.props && alertObj.props.titleTextColor ) {
+ $title.removeClass( 'alert-text' );
+ $title.css( 'color', mw.getHexColor( alertObj.props.titleTextColor ) );
+ }
+ var $message = $( '<div />' ).text( alertObj.message ).addClass( 'alert-message alert-text' );
+ if ( alertObj.isError ) {
+ $message.addClass( 'error' );
+ }
+ if ( alertObj.props && alertObj.props.textColor ) {
+ $message.removeClass( 'alert-text' );
+ $message.css( 'color', mw.getHexColor( alertObj.props.textColor ) );
+ }
+ var $buttonsContainer = $( '<div />' ).addClass( 'alert-buttons-container' );
+ if ( alertObj.props && alertObj.props.buttonRowSpacing ) {
+ $buttonsContainer.css( 'margin-top', alertObj.props.buttonRowSpacing );
+ }
+ var $buttonSet = alertObj.buttons || [];
+
+ // If no button was passed display just OK button
+ var buttonsNum = $buttonSet.length;
+ if ( buttonsNum == 0 && !alertObj.noButtons ) {
+ $buttonSet = ["OK"];
+ buttonsNum++;
+ }
+
+ $.each( $buttonSet, function(i) {
+ var label = this.toString();
+ var $currentButton = $( '<button />' )
+ .addClass( 'alert-button' )
+ .text( label )
+ .click( function( eventObject ) {
+ callback( eventObject );
+ embedPlayer.controlBuilder.closeAlert( alertObj.keepOverlay );
+ } );
+ if ( alertObj.props && alertObj.props.buttonHeight ) {
+ $currentButton.css( 'height', alertObj.props.buttonHeight );
+ }
+ // Apply buttons spacing only when more than one is present
+ if (buttonsNum > 1) {
+ if (i < buttonsNum-1) {
+ if ( alertObj.props && alertObj.props.buttonSpacing ) {
+ $currentButton.css( 'margin-right', alertObj.props.buttonSpacing );
+ }
+ }
+ }
+ $buttonsContainer.append( $currentButton );
+ } )
+ $container.append( $title, $message, $buttonsContainer );
+ return embedPlayer.controlBuilder.displayMenuOverlay( $container, false, true );
+ },
+
+ aboutPlayerLibrary: function(){
+ return $( '<div />' )
+ .append(
+ $( '<h2 />' )
+ .text(
+ mw.msg('mwe-embedplayer-about-library')
+ )
+ ,
+ $( '<span />')
+ .append(
+ mw.msg('mwe-embedplayer-about-library-desc',
+ $('<div>').append(
+ $('<a />').attr({
+ 'href' : mw.config.get( 'EmbedPlayer.LibraryPage' ),
+ 'target' : '_new'
+ })
+ )[0].innerHTML
+ )
+ )
+ );
+ },
+ /**
+ * Get the "share" interface
+ *
+ * TODO share should be enabled via <embed> tag usage to be compatible
+ * with sites social networking sites that allow <embed> tags but not js
+ *
+ * @param {Object} $target Target jQuery object to set share html
+ */
+ getShare: function( ) {
+ var embedPlayer = this.embedPlayer;
+ var embed_code = embedPlayer.getSharingEmbedCode();
+ var embed_wiki_code = embedPlayer.getWikiEmbedCode();
+ var _this = this;
+
+ var $shareInterface = $('<div />');
+
+ var $shareList = $( '<ul />' );
+
+ $shareList
+ .append(
+ $('<li />').text(
+ mw.msg( 'mwe-embedplayer-embed_site_or_blog' )
+ )
+ /*
+ .append(
+ $('<a />')
+ .attr('href', '#')
+ .addClass( 'active' )
+ .text(
+ mw.msg( 'mwe-embedplayer-embed_site_or_blog' )
+ )
+ )
+ */
+ );
+
+ $shareInterface.append(
+ $( '<h2 />' )
+ .text( embedPlayer.isAudio() ?
+ mw.msg( 'mwe-embedplayer-share_this_audio' ) :
+ mw.msg( 'mwe-embedplayer-share_this_video' ) )
+ );
+
+ if ( embed_wiki_code ) {
+ $shareInterface.append(
+ $('<ul />').append(
+ $('<li />').text(
+ mw.msg( 'mwe-embedplayer-embed_wiki' )
+ )
+ ),
+ $( '<textarea />' )
+ .attr( 'rows', 1 )
+ .html( embed_wiki_code )
+ .click( function() {
+ $( this ).select();
+ }),
+ $('<br />')
+ );
+ }
+
+ $shareInterface.append(
+ $shareList
+ );
+
+ $shareInterface.append(
+
+ $( '<textarea />' )
+ .attr( 'rows', 4 )
+ .html( embed_code )
+ .click( function() {
+ $( this ).select();
+ }),
+
+ $('<br />'),
+ $('<br />')
+ );
+ return $shareInterface;
+ },
+
+ /**
+ * Shows the Player Select interface
+ *
+ * @param {Object} $target jQuery target for output
+ */
+ getPlayerSelect: function( ) {
+ mw.log('PlayerControlBuilder::getPlayerSelect: source:' +
+ this.embedPlayer.mediaElement.selectedSource.getSrc() +
+ ' player: ' + this.embedPlayer.selectedPlayer.id );
+
+ var embedPlayer = this.embedPlayer;
+
+ var _this = this;
+
+ var $playerSelect = $('<div />')
+ .append(
+ $( '<h2 />' )
+ .text( mw.msg( 'mwe-embedplayer-choose_player' ) )
+ );
+
+ $.each( embedPlayer.mediaElement.getPlayableSources(), function( sourceId, source ) {
+
+ var isPlayable = (typeof mw.EmbedTypes.getMediaPlayers().defaultPlayer( source.getMIMEType() ) == 'object' );
+ var isSelected = ( source.getSrc() == embedPlayer.mediaElement.selectedSource.getSrc() );
+
+ $playerSelect.append(
+ $( '<h3 />' )
+ .text( source.getTitle() )
+ );
+
+ if ( isPlayable ) {
+ var $playerList = $('<ul />');
+ // output the player select code:
+
+ var supportingPlayers = mw.EmbedTypes.getMediaPlayers().getMIMETypePlayers( source.getMIMEType() );
+
+ for ( var i = 0; i < supportingPlayers.length ; i++ ) {
+ // Add link to select the player if not already selected )
+ if( embedPlayer.selectedPlayer.id == supportingPlayers[i].id && isSelected ) {
+ // Active player ( no link )
+ var $playerLine = $( '<span />' )
+ .append(
+ $('<a />')
+ .attr({
+ 'href' : '#'
+ })
+ .addClass( 'active')
+ .text(
+ supportingPlayers[i].getName()
+ ).click( function(){
+ embedPlayer.controlBuilder.closeMenuOverlay();
+ // Don't follow the # link:
+ return false;
+ })
+ );
+ //.addClass( 'ui-state-highlight ui-corner-all' ); removed by ran
+ } else {
+ // Non active player add link to select:
+ $playerLine = $( '<a />')
+ .attr({
+ 'href' : '#',
+ 'id' : 'sc_' + sourceId + '_' + supportingPlayers[i].id
+ })
+ .addClass( 'ui-corner-all')
+ .text( supportingPlayers[i].getName() )
+ .click( function() {
+ var iparts = $( this ).attr( 'id' ).replace(/sc_/ , '' ).split( '_' );
+ var sourceId = iparts[0];
+ var player_id = iparts[1];
+ mw.log( 'PlayerControlBuilder:: source id: ' + sourceId + ' player id: ' + player_id );
+
+ embedPlayer.controlBuilder.closeMenuOverlay();
+
+ // Close fullscreen if we are in fullscreen mode
+ if( _this.isInFullScreen() ){
+ _this.restoreWindowPlayer();
+ }
+
+ embedPlayer.mediaElement.setSourceByIndex( sourceId );
+ var playableSources = embedPlayer.mediaElement.getPlayableSources();
+
+ mw.EmbedTypes.getMediaPlayers().setPlayerPreference(
+ player_id,
+ playableSources[ sourceId ].getMIMEType()
+ );
+
+ // Issue a stop
+ embedPlayer.stop();
+
+ // Don't follow the # link:
+ return false;
+ } )
+ .hover(
+ function(){
+ $( this ).addClass('active');
+ },
+ function(){
+ $( this ).removeClass('active');
+ }
+ );
+ }
+
+ // Add the player line to the player list:
+ $playerList.append(
+ $( '<li />' ).append(
+ $playerLine
+ )
+ );
+ }
+
+ // Append the player list:
+ $playerSelect.append( $playerList );
+
+ } else {
+ // No player available:
+ $playerSelect.append( mw.msg( 'mwe-embedplayer-no-player', source.getTitle() ) );
+ }
+ } );
+
+ // Return the player select elements
+ return $playerSelect;
+ },
+
+ /**
+ * Loads sources and calls showDownloadWithSources
+ * @param {Object} $target jQuery target to output to
+ */
+ showDownload: function( $target ) {
+ var _this = this;
+ var embedPlayer = this.embedPlayer;
+ _this.showDownloadWithSources( $target );
+ },
+
+ /**
+ * Shows the download interface with sources loaded
+ * @param {Object} $target jQuery target to output to
+ */
+ showDownloadWithSources : function( $target ) {
+ var _this = this;
+ mw.log( 'PlayerControlBuilder:: showDownloadWithSources::' + $target.length );
+ var embedPlayer = this.embedPlayer;
+ // Empty the target:
+ $target.empty();
+ $target.append( $('<div />') );
+ $target = $target.find('div');
+
+ var $mediaList = $( '<ul />' );
+ var $textList = $( '<ul />' );
+ $.each( embedPlayer.mediaElement.getSources(), function( index, source ) {
+ if( source.getSrc() ) {
+ mw.log("showDownloadWithSources:: Add src: " + source.getTitle() );
+ var fileName = source.mwtitle;
+ if ( !fileName ) {
+ var path = new mw.Uri( source.getSrc() ).path;
+ var pathParts = path.split( '/' );
+ fileName = pathParts[ pathParts.length -1 ];
+ }
+ var $dlLine = $( '<li />').append(
+ $('<a />')
+ .attr( {
+ 'href': source.getSrc(),
+ 'download': fileName
+ })
+ .text( source.getTitle() )
+ );
+ // Add link to correct "bucket"
+
+ //Add link to time segment:
+ if ( source.getSrc().indexOf( '?t=' ) !== -1 ) {
+ $target.append( $dlLine );
+ } else if ( this.getMIMEType().indexOf('text') === 0 ) {
+ // Add link to text list
+ $textList.append( $dlLine );
+ } else {
+ // Add link to media list
+ $mediaList.append( $dlLine );
+ }
+
+ }
+ } );
+ if( $mediaList.find('li').length != 0 ) {
+ $target.append(
+ $('<h2 />')
+ .text( embedPlayer.isAudio() ?
+ mw.msg( 'mwe-embedplayer-download_full_audio' ) :
+ mw.msg( 'mwe-embedplayer-download_full_video' ) ),
+ $mediaList
+ );
+ }
+
+ if( $textList.find('li').length != 0 ) {
+ $target.append(
+ $('<h2 />')
+ .html( mw.msg( 'mwe-embedplayer-download_text' ) ),
+ $textList
+ );
+ }
+ },
+ getSwitchSourceMenu: function(){
+ var _this = this;
+ var embedPlayer = this.embedPlayer;
+ // for each source with "native playback"
+ var $sourceMenu = $('<ul />');
+
+ // Local function to closure the "source" variable scope:
+ function addToSourceMenu( source ){
+ // Check if source is selected:
+ var icon = ( source.getSrc() == embedPlayer.mediaElement.selectedSource.getSrc() ) ? 'bullet' : 'radio-on';
+ $sourceMenu.append(
+ $.getLineItem( source.getShortTitle() , icon, function(){
+ mw.log( 'PlayerControlBuilder::SwitchSourceMenu: ' + source.getSrc() );
+ // update menu selecting parent li siblings
+ $( this ).parent().siblings().find('span.ui-icon').removeClass( 'ui-icon-bullet').addClass( 'ui-icon-radio-on' );
+ $( this ).find('span.ui-icon').removeClass( 'ui-icon-radio-on').addClass( 'ui-icon-bullet' );
+ // update control bar text
+ embedPlayer.getInterface().find( '.source-switch' ).text( source.getShortTitle() );
+
+
+ // TODO this logic should be in mw.EmbedPlayer
+ embedPlayer.mediaElement.setSource( source );
+ if( ! _this.embedPlayer.isStopped() ){
+ // Get the exact play time from the video element ( instead of parent embed Player )
+ var oldMediaTime = _this.embedPlayer.getPlayerElement().currentTime;
+ var oldPaused = _this.embedPlayer.paused;
+ // Do a live switch
+ embedPlayer.playerSwitchSource( source, function( vid ){
+ // issue a seek
+ embedPlayer.setCurrentTime( oldMediaTime, function(){
+ // reflect pause state
+ if( oldPaused ){
+ embedPlayer.pause();
+ }
+ } );
+ });
+ }
+ })
+ );
+ }
+ var addedSources = {};
+ $.each( this.embedPlayer.mediaElement.getPlayableSources(), function( sourceIndex, source ) {
+ // Output the player select code:
+ var supportingPlayers = mw.EmbedTypes.getMediaPlayers().getMIMETypePlayers( source.getMIMEType() );
+ for ( var i = 0; i < supportingPlayers.length ; i++ ) {
+ var lib = supportingPlayers[i].library;
+ if( lib === 'Native' || lib === 'OgvJs' ){ // @fixme use supports.sourceSwitch ... if preloaded?
+ if ( !( source.getSrc() in addedSources ) ) {
+ addedSources[source.getSrc()] = true;
+ addToSourceMenu( source );
+ }
+ }
+ }
+ });
+ return $sourceMenu;
+ },
+
+ /**
+ * Get component
+ *
+ * @param {String} componentId Component key to grab html output
+ */
+ getComponent: function( componentId ) {
+ if ( this.components[ componentId ] ) {
+ return this.components[ componentId ].o( this );
+ } else {
+ return false;
+ }
+ },
+
+ /**
+ * Get a component height
+ *
+ * @param {String} componentId Component key to grab height
+ * @return height or false if not set
+ */
+ getComponentHeight: function( componentId ) {
+ if ( this.components[ componentId ]
+ && this.components[ componentId ].h )
+ {
+ return this.components[ componentId ].h;
+ }
+ return 0;
+ },
+
+ /**
+ * Get a component width
+ * @param {String} componentId Component key to grab width
+ * @return width or false if not set
+ */
+ getComponentWidth: function( componentId ){
+ if ( this.components[ componentId ]
+ && this.components[ componentId ].w )
+ {
+ return this.components[ componentId ].w;
+ }
+ return 0;
+ },
+
+ // Set up the disable playhead function:
+ // TODO this will move into the disableSeekBar binding in the new theme framework
+ disableSeekBar : function(){
+ var $playHead = this.embedPlayer.getInterface().find( ".play_head" );
+ if( $playHead.length ){
+ $playHead.slider( "option", "disabled", true );
+ }
+ },
+ enableSeekBar : function(){
+ var $playHead = this.embedPlayer.getInterface().find( ".play_head" );
+ if( $playHead.length ){
+ $playHead.slider( "option", "disabled", false);
+ }
+ },
+
+ /**
+ * Components Object
+ * Take in the embedPlayer and return some html for the given component.
+ *
+ * components can be overwritten by skin javascript
+ *
+ * Component JSON structure is as follows:
+ * 'o' Function to return a binded jQuery object ( accepts the ctrlObject as a parameter )
+ * 'w' The width of the component
+ * 'h' The height of the component ( if height is undefined the height of the control bar is used )
+ * 'position' elements are inserted into the dom based on component order and available space.
+ * if the element is inserted, position is then used to set relative dom insert order.
+ */
+ components: {
+ /**
+ * The pause / play button
+ */
+ 'pause': {
+ 'w': 28,
+ 'position': 1,
+ 'o': function( ctrlObj ) {
+ return $( '<div />' )
+ .attr( 'title', mw.msg( 'mwe-embedplayer-play_clip' ) )
+ .addClass ( "ui-state-default ui-corner-all ui-icon_link lButton play-btn" )
+ .append(
+ $( '<span />' )
+ .addClass( "ui-icon ui-icon-play" )
+ )
+ // Play / pause binding
+ .buttonHover()
+ .click( function() {
+ ctrlObj.embedPlayer.play();
+ // Don't follow the # link:
+ return false;
+ });
+ }
+ },
+
+ /**
+ * The volume control interface html
+ */
+ 'volumeControl': {
+ 'w' : 28,
+ 'position': 7,
+ 'o' : function( ctrlObj ) {
+ mw.log( 'PlayerControlBuilder::Set up volume control for: ' + ctrlObj.embedPlayer.id );
+ var $volumeOut = $( '<span />' );
+ if ( ctrlObj.volumeLayout == 'horizontal' ) {
+ $volumeOut.append(
+ $( '<div />' )
+ .addClass( "ui-slider ui-slider-horizontal rButton volume-slider" )
+ );
+ }
+
+ // Add the volume control icon
+ $volumeOut.append(
+ $('<div />')
+ .attr( 'title', mw.msg( 'mwe-embedplayer-volume_control' ) )
+ .addClass( "ui-state-default ui-corner-all ui-icon_link rButton volume_control" )
+ .append(
+ $( '<span />' )
+ .addClass( "ui-icon ui-icon-volume-on" )
+ )
+ );
+ if ( ctrlObj.volumeLayout == 'vertical' ) {
+ $volumeOut.find('.volume_control').append(
+ $( '<div />' )
+ .hide()
+ .addClass( "vol_container ui-corner-all" )
+ .append(
+ $( '<div />' )
+ .addClass ( "volume-slider" )
+ )
+ );
+ }
+ //Return the inner html
+ return $volumeOut.html();
+ }
+ },
+
+ /**
+ * The large play button in center of the player
+ */
+ 'playButtonLarge': {
+ 'w' : 70,
+ 'h' : 53,
+ 'position': 2,
+ 'o' : function( ctrlObj ) {
+ return $( '<div />' )
+ .attr( {
+ 'title' : mw.msg( 'mwe-embedplayer-play_clip' ),
+ 'class' : "play-btn-large"
+ } )
+ // Get dynamic position for big play button
+ .css( ctrlObj.getPlayButtonPosition() )
+ // Add play hook:
+ .click( function() {
+ ctrlObj.embedPlayer.play();
+ return false; // Event Stop Propagation
+ } );
+ }
+ },
+
+ /**
+ * The Attribution button ( by default this is kaltura-icon
+ */
+ 'attributionButton' : {
+ 'w' : 28,
+ 'position': 3,
+ 'o' : function( ctrlObj ){
+ var buttonConfig = mw.config.get( 'EmbedPlayer.AttributionButton');
+ // Check for source ( by configuration convention this is a 16x16 image
+ if( buttonConfig.iconurl ){
+ var $icon = $('<img />')
+ .attr('src', buttonConfig.iconurl );
+ } else {
+ var $icon = $('<span />')
+ .addClass( 'ui-icon' );
+ if( buttonConfig['class'] ){
+ $icon.addClass( buttonConfig['class'] );
+ }
+ }
+ if( typeof buttonConfig.style != 'object'){
+ buttonConfig.style = {};
+ }
+ // update the configured size of the attribution button if we have a specific width configured
+ if( buttonConfig.style.width ){
+ this.w = parseInt( buttonConfig.style.width );
+ } else {
+ buttonConfig.style.width = parseInt( this.w ) + 'px';
+ }
+
+ return $( '<div />' )
+ .addClass( 'rButton' )
+ .css({
+ 'top' : '1px',
+ 'left' : '2px'
+ })
+ // Allow button config style to override
+ .css( buttonConfig.style )
+ .append(
+ $('<a />')
+ .attr({
+ 'href': buttonConfig.href,
+ 'title' : buttonConfig.title,
+ 'target' : '_new'
+ })
+ .append( $icon )
+ );
+ }
+ },
+
+ /*
+ * The time display area
+ */
+ 'timeDisplay': {
+ 'w' : mw.config.get( 'EmbedPlayer.TimeDisplayWidth' ),
+ 'position': 6,
+ 'o' : function( ctrlObj ) {
+ return $( '<div />' )
+ .addClass( "ui-widget time-disp" )
+ .append(
+ ctrlObj.embedPlayer.getTimeRange()
+ );
+ }
+ },
+
+ /**
+ * The options button, invokes display of the options menu
+ */
+ 'options': {
+ 'w': 28,
+ 'position': 10,
+ 'o': function( ctrlObj ) {
+ return $( '<div />' )
+ .attr( 'title', mw.msg( 'mwe-embedplayer-player_options' ) )
+ .addClass( 'ui-state-default ui-corner-all ui-icon_link rButton options-btn' )
+ .append(
+ $('<span />')
+ .addClass( 'ui-icon ui-icon-wrench' )
+ )
+ .buttonHover()
+ // Options binding:
+ .embedMenu( {
+ 'content' : ctrlObj.getOptionsMenu(),
+ 'zindex' : mw.config.get( 'EmbedPlayer.FullScreenZIndex' ) + 2,
+ 'positionOpts': {
+ 'directionV' : 'up',
+ 'offsetY' : 30,
+ 'directionH' : 'left',
+ 'offsetX' : -28
+ }
+ } );
+ }
+ },
+
+ /**
+ * The fullscreen button for displaying the video fullscreen
+ */
+ 'fullscreen': {
+ 'w': 24,
+ 'position': 8,
+ 'o': function( ctrlObj ) {
+ var $btn = $( '<div />' )
+ .attr( 'title', mw.msg( 'mwe-embedplayer-player_fullscreen' ) )
+ .addClass( "ui-state-default ui-corner-all ui-icon_link rButton fullscreen-btn" )
+ .append(
+ $( '<span />' )
+ .addClass( "ui-icon ui-icon-arrow-4-diag" )
+ )
+ // Fullscreen binding:
+ .buttonHover();
+ // Link out to another window if iPad 3x ( broken iframe resize )
+ if( (
+ mw.config.get('EmbedPlayer.IsIframeServer')
+ &&
+ mw.isIpad3()
+ )
+ ||
+ mw.config.get( "EmbedPlayer.NewWindowFullscreen" )
+ ||
+ ( mw.config.get('EmbedPlayer.IsIframeServer') && mw.config.get('EmbedPlayer.EnableIframeApi') === false )
+ ){
+ // Get the iframe url:
+ var url = ctrlObj.embedPlayer.getIframeSourceUrl();
+ // Change button into new window ( of the same url as the iframe ) :
+ return $('<a />').attr({
+ 'href': url,
+ 'target' : '_new'
+ })
+ .click(function(){
+ // Update the url:
+ var url = $(this).attr('href');
+ var iframeMwConfig = {};
+
+ iframeMwConfig['EmbedPlayer.IsFullscreenIframe'] = true;
+ // add a seek offset:
+ iframeMwConfig['EmbedPlayer.IframeCurrentTime'] = ctrlObj.embedPlayer.currentTime;
+ // add play state:
+ iframeMwConfig['EmbedPlayer.IframeIsPlaying'] = ctrlObj.embedPlayer.isPlaying();
+
+ // Append the configuration and request domain to the iframe hash:
+
+ // Add the parentUrl to the iframe config:
+ iframeMwConfig['EmbedPlayer.IframeParentUrl'] = document.URL;
+
+ url += '#' + encodeURIComponent(
+ JSON.stringify({
+ 'mwConfig' :iframeMwConfig,
+ 'playerId' : playerId
+ })
+ );
+ ctrlObj.embedPlayer.pause();
+ // try and do a browser popup:
+ var newwin = window.open(
+ url,
+ ctrlObj.embedPlayer.id,
+ // Fullscreen window params:
+ 'width=' + screen.width +
+ ', height=' + ( screen.height - 90 ) +
+ ', top=0, left=0' +
+ ', fullscreen=yes'
+ );
+ // if for some reason we could not open the window run the href link:
+ if( newwin === null){
+ return true;
+ }
+ if ( window.focus ) {
+ newwin.focus();
+ }
+ // Else do not follow the href link
+ return false;
+ })
+ .append($btn);
+ } else {
+ return $btn.click( function() {
+ ctrlObj.embedPlayer.fullscreen();
+ } );
+ }
+ }
+ },
+
+ 'sourceSwitch' : {
+ 'w' : 70,
+ 'position': 9,
+ 'o' : function( ctrlObj ){
+ var $menuContainer = $('<div />').addClass( 'swMenuContainer' ).hide();
+ ctrlObj.embedPlayer.getInterface().append(
+ $menuContainer
+ )
+ // Stream switching widget ( display the current selected stream text )
+ return $( '<div />' )
+ .addClass('ui-widget source-switch')
+ .append(
+ ctrlObj.embedPlayer.mediaElement.selectedSource.getShortTitle()
+ ).embedMenu( {
+ 'content' : ctrlObj.getSwitchSourceMenu(),
+ 'zindex' : mw.config.get( 'EmbedPlayer.FullScreenZIndex' ) + 2,
+ 'keepPosition' : true,
+ 'targetMenuContainer' : $menuContainer,
+ 'width' : 130,
+ 'showSpeed': 0,
+ 'createMenuCallback' : function(){
+ var $interface = ctrlObj.embedPlayer.getInterface();
+ var $sw = $interface.find( '.source-switch' );
+ var $swMenuContainer = $interface.find('.swMenuContainer');
+ var height = $swMenuContainer.find( 'li' ).length * 30;
+ // position from top ( unkown why we can't use bottom here )
+ var top = $interface.height() - height - ctrlObj.getHeight() - 6;
+ $menuContainer.css({
+ 'position' : 'absolute',
+ 'left': $sw[0].offsetLeft,
+ 'top' : top,
+ 'bottom': ctrlObj.getHeight(),
+ 'height' : height
+ })
+ ctrlObj.showControlBar( true );
+ },
+ 'closeMenuCallback' : function(){
+ ctrlObj.restoreControlsHover()
+ }
+ } );
+ }
+ },
+
+ /**
+ * The playhead component
+ */
+ 'playHead': {
+ 'w':0, // special case (takes up remaining space)
+ 'position': 5,
+ 'o':function( ctrlObj ) {
+
+ var sliderConfig = {
+ range: "min",
+ value: 0,
+ min: 0,
+ max: 1000,
+ start: function( event, ui ) {
+ var id = ( embedPlayer.pc != null ) ? embedPlayer.pc.pp.id:embedPlayer.id;
+ embedPlayer.userSlide = true;
+ $( id + ' .play-btn-large' ).fadeOut( 'fast' );
+ // If playlist always start at 0
+ embedPlayer.startTimeSec = ( embedPlayer.instanceOf == 'mvPlayList' ) ? 0:
+ mw.npt2seconds( embedPlayer.getTimeRange().split( '/' )[0] );
+ },
+ slide: function( event, ui ) {
+ var perc = ui.value / 1000;
+ embedPlayer.jumpTime = mw.seconds2npt( parseFloat( parseFloat( embedPlayer.getDuration() ) * perc ) + embedPlayer.startTimeSec );
+ // mw.log('perc:' + perc + ' * ' + embedPlayer.getDuration() + ' jt:'+ this.jumpTime);
+ if ( _this.longTimeDisp ) {
+ ctrlObj.setStatus( mw.msg( 'mwe-embedplayer-seek_to', embedPlayer.jumpTime ) );
+ } else {
+ ctrlObj.setStatus( embedPlayer.jumpTime );
+ }
+ // Update the thumbnail / frame
+ if ( embedPlayer.isPlaying == false ) {
+ embedPlayer.updateThumbPerc( perc );
+ }
+ },
+ change: function( event, ui ) {
+ // Only run the onChange event if done by a user slide
+ // (otherwise it runs times it should not)
+ if ( embedPlayer.userSlide ) {
+ embedPlayer.userSlide = false;
+ embedPlayer.seeking = true;
+
+ var perc = ui.value / 1000;
+ // set seek time (in case we have to do a url seek)
+ embedPlayer.seekTimeSec = mw.npt2seconds( embedPlayer.jumpTime, true );
+ mw.log( 'PlayerControlBuilder:: seek to: ' + embedPlayer.jumpTime + ' perc:' + perc + ' sts:' + embedPlayer.seekTimeSec );
+ ctrlObj.setStatus( mw.msg( 'mwe-embedplayer-seeking' ) );
+ if( embedPlayer.isStopped() ){
+ embedPlayer.play();
+ }
+ embedPlayer.seek( perc );
+ }
+ }
+ };
+
+ var embedPlayer = ctrlObj.embedPlayer;
+ var _this = this;
+ var $playHead = $( '<div />' )
+ .addClass ( "play_head" )
+ .css({
+ "position" : 'absolute',
+ "left" : '33px',
+ "right" : ( ( embedPlayer.getPlayerWidth() - ctrlObj.availableWidth - 33 ) ) + 'px'
+ })
+ // Playhead binding
+ .slider( sliderConfig );
+
+ // Up the z-index of the default status indicator:
+ $playHead.find( '.ui-slider-handle' ).css( 'z-index', 4 );
+ $playHead.find( '.ui-slider-range' ).addClass( 'ui-corner-all' ).css( 'z-index', 2 );
+
+ // Add buffer html:
+ $playHead.append(
+ $('<div />')
+ .addClass( "ui-slider-range ui-slider-range-min ui-widget-header")
+ .addClass( "ui-state-highlight ui-corner-all mw_buffer")
+ );
+
+ // Show video timeline position on hover and when dragging playhead
+ function showPosition(event) {
+ var pos = ( event.clientX - $playHead.offset().left ) / $playHead.width();
+ var time = mw.seconds2npt( parseFloat( embedPlayer.getDuration() ) * pos + (embedPlayer.startTimeSec || 0) );
+ $playHead.attr('title', time);
+ }
+ $playHead.on({
+ mouseenter: showPosition,
+ mouseleave: function(event) {
+ $playHead.attr({title: ''});
+ },
+ mousemove: showPosition
+ });
+
+ return $playHead;
+ }
+ }
+ }
+};
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Audio.html b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Audio.html
new file mode 100644
index 00000000..e0d0c19e
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Audio.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <!-- <script type="text/javascript" src="../../../ResourceLoader.php?class=window.jQuery,mwEmbed&&debug=true"></script> -->
+ <script type="text/javascript" src="../../../mwEmbedStartup.php"></script>
+<title>Audio Player sample</title>
+</head>
+<body>
+<h3> Audio Player </h3>
+<audio class="kskin" src="http://upload.wikimedia.org/wikipedia/commons/4/4c/Faurepiece.ogg" durationHint="164"></audio>
+<h3> Audio Player mp3 </h3>
+<audio src="http://ia600300.us.archive.org/35/items/tube122/tube122-02-entia_non_-_perfunctory_jousting.mp3" durationHint="133"></audio>
+
+</body>
+</html> \ No newline at end of file
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_DynamicEmbed.html b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_DynamicEmbed.html
new file mode 100644
index 00000000..135e1713
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_DynamicEmbed.html
@@ -0,0 +1,24 @@
+<html>
+ <head>
+ <script type="text/javascript" src="../../../mwEmbedStartup.php"></script>
+ </head>
+<body>
+
+ <div style="width:640px; height:480px;" id="mwplayer"></div>
+
+ <script>
+ mw.ready(function(){
+
+ mw.load('EmbedPlayer', function(){
+ // seems to trip a bug in IE8/win7
+ $('#mwplayer').embedPlayer({
+ 'poster' : "http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/bbb480.jpg",
+ 'sources':[{
+ 'src':'http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/bbb_trailer_iphone.m4v',
+ 'type':'video/h264'}]
+ });
+ });
+ });
+ </script>
+
+</body>
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_IncludeJQuery.html b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_IncludeJQuery.html
new file mode 100644
index 00000000..ebe3bac9
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_IncludeJQuery.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Player sources</title>
+
+<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js" type="text/javascript"></script>
+<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7/jquery-ui.min.js" type="text/javascript"></script>
+<script type="text/javascript" src="../../../mwEmbedStartup.php"></script>
+<script type="text/javascript">
+ $(document).ready(function(){
+ $('#test').text('jQuery $ supported' );
+ });
+</script>
+</head>
+<body>
+<div id="test"></div>
+
+<video poster="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/elephants-dream.jpg"
+ duration="10:53" preload="auto">
+ <source type="video/webm" src="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/elephants-dream_400p.webm" />
+ <source type="video/h264" src="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/elephants-dream_iphone.m4v" />
+ <source type="video/ogg" src="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/elephants-dream_400p.ogv" />
+</video>
+
+
+</body>
+</html> \ No newline at end of file
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Native_Bindings.html b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Native_Bindings.html
new file mode 100644
index 00000000..433ffa21
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Native_Bindings.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Native Player html5 bindings </title>
+
+
+</head>
+<body>
+<div style="position:absolute;display:block; left: 500px; width:300px; background: #eee; border:solid thin black">
+ <table style="font-size:.8em">
+ <tr>
+ <td colspan="2">
+ <b>Media Events:</b>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2"><textarea style="width:288px" rows="10" id="mediaeventlog"></textarea></td>
+ </tr>
+
+
+ <tr>
+ <td colspan="2">
+ <b>Events logging: (not quite there yet)</b>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2"><div id="eventSelectors"> </div></td>
+ </tr>
+
+ </table>
+</div>
+
+<div style="width:500px;height:300px;display:block;position:relative">
+ <video id="myVid" poster="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/elephants-dream.jpg"
+ duration="10:53" preload="auto" controls>
+ <source type="video/h264" src="http://www.archive.org/download/ElephantsDream/ed_1024_512kb.mp4" >
+ <source type="video/ogg" src="http://www.archive.org/download/ElephantsDream/ed_hd.ogv" >
+ </video>
+</div>
+
+
+<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.3.min.js"></script>
+<script type="text/javascript" src="../../../mwEmbedStartup.php"></script>
+<script type="text/javascript">
+ /*
+ Media Event Bindings
+ from http://www.w3.org/TR/html5/video.html
+ 4.8.9.12 Event summary
+ The following events fire on media elements as part of the processing model described above:
+ */
+ var vid,
+ mediaEvents = [
+ { event: 'loadstart', logMessage: 'The user agent has begun looking for media data, as part of the resource selection algorithm.' },
+ { event: 'progress', logMessage: 'The user agent is fetching media data.' },
+ { event: 'suspend', logMessage: 'The user agent is intentionally not currently fetching media data, but does not have the entire media resource downloaded.' },
+ { event: 'abort', logMessage: 'The user agent stops fetching the media data before it is completely downloaded, but not due to an error.' },
+ { event: 'error', logMessage: 'An error occurs while fetching the media data.' },
+ { event: 'emptied', logMessage: "A media element whose networkState was previously not in the NETWORK_EMPTY state has just switched to that state (either because of a fatal error during load that's about to be reported, or because the load() method was invoked while the resource selection algorithm was already running)." },
+ { event: 'stalled', logMessage: 'The user agent is trying to fetch media data, but data is unexpectedly not forthcoming.' },
+ { event: 'play', logMessage: 'Playback has begun. Fired after the play() method has returned, or when the autoplay attribute has caused playback to begin.' },
+ { event: 'pause', logMessage: 'Playback has been paused. Fired after the pause() method has returned.' },
+ { event: 'loadedmetadata', logMessage: 'The user agent has just determined the duration and dimensions of the media resource' },
+ { event: 'loadeddata', logMessage: 'The user agent can render the media data at the current playback position for the first time.' },
+ { event: 'waiting', logMessage: 'Playback has stopped because the next frame is not available, but the user agent expects that frame to become available in due course.' },
+ { event: 'playing', logMessage: 'Playback has started.' },
+ { event: 'canplay', logMessage: 'The user agent can resume playback of the media data, but estimates that if playback were to be started now, the media resource could not be rendered at the current playback rate up to its end without having to stop for further buffering of content.' },
+ { event: 'canplaythrough', logMessage: 'The user agent estimates that if playback were to be started now, the media resource could be rendered at the current playback rate all the way to its end without having to stop for further buffering.' },
+ { event: 'seeking', logMessage: 'The seeking IDL attribute changed to true and the seek operation is taking long enough that the user agent has time to fire the event.' },
+ { event: 'seeked', logMessage: 'The seeking IDL attribute changed to false.' },
+ { event: 'timeupdate', logMessage: 'The current playback position changed as part of normal playback or in an especially interesting way, for example discontinuously.' },
+ { event: 'ended', logMessage: 'Playback has stopped because the end of the media resource was reached.' },
+ { event: 'ratechange', logMessage: 'Either the defaultPlaybackRate or the playbackRate attribute has just been updated.' },
+ { event: 'durationchange', logMessage: 'The duration attribute has just been updated.' },
+ { event: 'volumechange', logMessage: 'Either the volume attribute or the muted attribute has changed.' }
+ ];
+
+// log to textarea
+function logME(event) {
+ $('#mediaeventlog').append(event+'\n');
+}
+
+
+// setup logging for an event or tear it down
+function setLogging(event, isActive, message) {
+ if ( isActive === true ) {
+ $(mediaEvents).each(function (i, e) {
+ if ( e.event === event ) {
+ message = e.logMessage;
+ }
+ });
+ $j('#myVid').bind( event, function() { logME('* ' + event + ' fired: ' + message); });
+ } else {
+ $j('#myVid').unbind( event );
+ }
+
+}
+
+mw.ready(function() {
+
+ var vid = $j('#myVid');
+
+ // setup checkboxes to control logging
+ $(mediaEvents).each(function (i, e) {
+ var event = e.event;
+ var message = e.logMessage;
+ $('#eventSelectors').append('<input class="eventSelector" type=checkbox checked name="' + event +'">' + event + '</input><br />');
+ setLogging(event, true, message);
+ });
+
+ //$('.eventSelector').each(function(i, s) { //change(console.log('changed'));
+
+//
+//console.log(s);
+// $(s).change('click');
+//});
+
+ //disable logging for timeupdate
+ setLogging('timeupdate', false);
+ $('input[name=timeupdate]').prop( 'checked', false );
+
+ logME('* the media player is ready');
+
+});
+
+
+</script>
+
+</body>
+</html>
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Seek.html b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Seek.html
new file mode 100644
index 00000000..8c0f8e9d
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Seek.html
@@ -0,0 +1,35 @@
+<html>
+ <head>
+ <script type="text/javascript" src="../../../mwEmbedStartup.php"></script>
+ </head>
+ <body>
+ <h2>mwEmbed / archive.org server side seek</h2>
+ Start Playing at <input id="startTime" size="5" value ="50"></input> seconds. <input value="go" type="button" id="doPageSeek"></input></br>
+ <video id="vid1" poster="http://www.archive.org/download/night_of_the_living_dead/format=Thumbnail&x.jpg"
+ style="width:400px;height:300px" durationHint="5717.21">
+ <source src="http://www.archive.org/download/night_of_the_living_dead/night_of_the_living_dead_512kb.mp4"/>
+ <source src="http://www.archive.org/download/night_of_the_living_dead/night_of_the_living_dead.ogv"/>
+ </video>
+ <script type="text/javascript">
+ mw.ready( function(){
+ // check for hash:
+ var urlParts = new mw.Uri ( document.URL);
+ if( urlParts.anchor ){
+ // run the start offset:
+ var startTime = urlParts.anchor.split('=')[1];
+
+ //update the input box:
+ $j('#startTime').val( startTime );
+
+ // update current time then play:
+ $j('#vid1')[0].currentTime = startTime;
+ $j('#vid1')[0].play();
+ }
+ // bind button:
+ $j('#doPageSeek').click(function(){
+ document.location = 'Player_Seek.html?' + Math.random(1) + '#start=' + $j("#startTime").val();
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_ServerSeek.html b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_ServerSeek.html
new file mode 100644
index 00000000..6a9d7d04
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_ServerSeek.html
@@ -0,0 +1,35 @@
+<html>
+ <head>
+ <script type="text/javascript" src="../../../mwEmbedStartup.php"></script>
+ </head>
+ <body>
+ <h2>mwEmbed / archive.org server side seek</h2>
+ Start Playing at <input id="startTime" size="5" value="50"></input> seconds. <input value="go" type="button" id="doPageSeek"></input></br>
+ <video id="vid1" poster="http://www.archive.org/download/night_of_the_living_dead/format=Thumbnail&x.jpg"
+ style="width:400px;height:300px" durationHint="5717.21">
+ <source URLTimeEncoding='true' src="http://www.archive.org/download/night_of_the_living_dead/night_of_the_living_dead_512kb.mp4"/>
+ <source URLTimeEncoding='true' src="http://www.archive.org/download/night_of_the_living_dead/night_of_the_living_dead.ogv"/>
+ </video>
+ <script type="text/javascript">
+ mw.ready( function(){
+ // check for hash:
+ var urlParts = new mw.Uri( document.URL);
+ if( urlParts.anchor ){
+ // run the start offset:
+ var startTime = urlParts.anchor.split('=')[1];
+
+ //update the input box:
+ $j('#startTime').val( startTime );
+
+ // update current time then play:
+ $j('#vid1')[0].currentTime = startTime;
+ $j('#vid1')[0].play();
+ }
+ // bind button:
+ $j('#doPageSeek').click(function(){
+ document.location = 'Player_ServerSeek.html?' + Math.random(1) + '#start=' + $j("#startTime").val();
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_ServerSideSeek.html b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_ServerSideSeek.html
new file mode 100644
index 00000000..26c87a6a
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_ServerSideSeek.html
@@ -0,0 +1,14 @@
+<html>
+ <head>
+ <script type="text/javascript" src="../../../mwEmbedStartup.php"></script>
+ </head>
+ <body>
+ <h2>mwEmbed / archive.org server side seek</h2>
+
+ <video poster="http://www.archive.org/download/night_of_the_living_dead/format=Thumbnail&x.jpg"
+ style="width:400px;height:300px" durationHint="5717.21">
+ <source URLTimeEncoding="true" src="http://www.archive.org/download/night_of_the_living_dead/night_of_the_living_dead_512kb.mp4"/>
+ <source URLTimeEncoding="true" src="http://www.archive.org/download/night_of_the_living_dead/night_of_the_living_dead.ogv"/>
+ </video>
+ </body>
+</html>
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Sources.html b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Sources.html
new file mode 100644
index 00000000..244ae1fa
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Sources.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Player sources</title>
+
+ <script type="text/javascript" src="../../../mwEmbedStartup.php"></script>
+<!-- <script type="text/javascript" src="http://html5.kaltura.org/js"></script>-->
+
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+
+</head>
+<body>
+
+<video id="vid1" width="480" height="267"
+ poster="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/bbb480.jpg"
+ durationHint="33"
+ controls >
+ <source type="video/h264" src="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/bbb_trailer_iphone.m4v"></source>
+ <source type="video/ogg" src="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/bbb_trailer_400p.ogv"></source>
+</video>
+
+</body>
+</html>
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Themable.html b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Themable.html
new file mode 100644
index 00000000..d70b4084
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/tests/Player_Themable.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title> Sample Themed Player </title>
+ Pre-loading demo ( stuff ) likely needed for video display
+ <!-- <script type="text/javascript" src="../../../ResourceLoader.php?debug=true&class=mwEmbed"></script> -->
+ <script type="text/javascript" src="../../../mwEmbedStartup.php"></script>
+
+</head>
+<script type="text/javascript">
+ // Show the controls ( this is a theme demo )
+ mw.setConfig( 'EmbedPlayer.OverlayControls', false );
+</script>
+<body>
+
+<h3> Sample Themable Player:</h3>
+To play with dynamic Themes install <a href="http://jqueryui.com/themeroller/developertool/">Themeroller</a><p><p>
+
+<div style="width:450px;float:left">
+<video
+ style="width:400px;height:300px"
+ src="http://upload.wikimedia.org/wikipedia/commons/2/29/Charles_Lindbergh_flight_to_Brussels.ogg"
+ poster="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Charles_Lindbergh_flight_to_Brussels.ogg/mid-Charles_Lindbergh_flight_to_Brussels.ogg.jpg"
+ apiTitleKey="Charles_Lindbergh_flight_to_Brussels.ogg"
+ apiProvider="commons"
+ durationHint="60" >
+</video>
+
+<video
+ style="width:208px;height:160px;float:left"
+ src="http://upload.wikimedia.org/wikipedia/commons/2/29/Charles_Lindbergh_flight_to_Brussels.ogg"
+ apiTitleKey="Charles_Lindbergh_flight_to_Brussels.ogg"
+ apiProvider="commons"
+ poster="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Charles_Lindbergh_flight_to_Brussels.ogg/mid-Charles_Lindbergh_flight_to_Brussels.ogg.jpg"
+ durationHint="60">
+ </video>
+
+<b>Source Code used:</b><br>
+<textarea cols="50" rows="7"><video style="width:400px;height:288px" poster="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Charles_Lindbergh_flight_to_Brussels.ogg/mid-Charles_Lindbergh_flight_to_Brussels.ogg.jpg"
+src="http://upload.wikimedia.org/wikipedia/commons/2/29/Charles_Lindbergh_flight_to_Brussels.ogg"></video></textarea>
+</div>
+
+<div style="width:450px;float:left">
+<video
+ class="kskin"
+ style="width:400px;height:300px"
+ src="http://upload.wikimedia.org/wikipedia/commons/2/29/Charles_Lindbergh_flight_to_Brussels.ogg"
+ apiTitleKey="Charles_Lindbergh_flight_to_Brussels.ogg"
+ apiProvider="commons"
+ poster="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Charles_Lindbergh_flight_to_Brussels.ogg/mid-Charles_Lindbergh_flight_to_Brussels.ogg.jpg"
+ durationHint="60">
+</video>
+<video
+ class="kskin"
+ apiTitleKey="Charles_Lindbergh_flight_to_Brussels.ogg"
+ apiProvider="commons"
+ style="width:208px;height:160px;float:left;" src="http://upload.wikimedia.org/wikipedia/commons/2/29/Charles_Lindbergh_flight_to_Brussels.ogg"
+ poster="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Charles_Lindbergh_flight_to_Brussels.ogg/mid-Charles_Lindbergh_flight_to_Brussels.ogg.jpg"
+ durationHint="60">
+</video>
+
+<b>(kskin) Source Code used:</b><br>
+<textarea cols="50" rows="7"><video class="kskin" style="width:400px;height:288px" poster="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Charles_Lindbergh_flight_to_Brussels.ogg/mid-Charles_Lindbergh_flight_to_Brussels.ogg.jpg"
+src="http://upload.wikimedia.org/wikipedia/commons/2/29/Charles_Lindbergh_flight_to_Brussels.ogg"></video></textarea>
+</div>
+
+
+</body>
+</html>
+
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.config.php b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.config.php
new file mode 100644
index 00000000..46547697
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.config.php
@@ -0,0 +1,31 @@
+<?php
+ /**
+ * Do not edit this file instead use LocalSettings.php and
+ * $wgMwEmbedModuleConfig[ {configuration name} ] = value; format
+ */
+
+ return array(
+ // If the Timed Text interface should be displayed:
+ // 'always' Displays link and call to contribute always
+ // 'auto' Looks for child timed text elements or "apiTitleKey" & load interface
+ // 'off' Does not display the timed text interface
+ "TimedText.ShowInterface" => "auto",
+
+ /**
+ * If the "add timed text" link / interface should be exposed
+ * allows usere to upload text files to the wiki
+ */
+ 'TimedText.ShowAddTextLink' => false,
+
+ // If the link to request a transcript should be shown on video files
+ 'TimedText.ShowRequestTranscript' => false,
+
+ // The category for listing videos that need transcription:
+ 'TimedText.NeedsTranscriptCategory' => 'Videos needing subtitles',
+
+ // The default bottom text padding
+ 'TimedText.BottomPadding' => 10,
+
+ // Height of black box below video.
+ 'TimedText.BelowVideoBlackBoxHeight' => 40
+ );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.loader.js b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.loader.js
new file mode 100644
index 00000000..bbd62d0e
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.loader.js
@@ -0,0 +1,52 @@
+/**
+* TimedText loader.
+*/
+// Scope everything in "mw" ( keeps the global namespace clean )
+( function( mw, $ ) {
+
+ /**
+ * Check if the video tags in the page support timed text
+ * this way we can add our timed text libraries to the player
+ * library request.
+ */
+ // Update the player loader request with timedText library if the embedPlayer
+ // includes timedText tracks.
+ $( mw ).bind( 'EmbedPlayerUpdateDependencies', function( event, playerElement, classRequest ) {
+ if( mw.isTimedTextSupported( playerElement ) ) {
+ classRequest = $.merge( classRequest, ['mw.TimedText'] );
+ }
+ } );
+ // On new embed player check if we need to add timedText
+ $( mw ).bind( 'EmbedPlayerNewPlayer', function( event, embedPlayer ){
+ if( mw.isTimedTextSupported( embedPlayer ) ){
+ embedPlayer.timedText = new mw.TimedText( embedPlayer );
+ }
+ });
+
+ /**
+ * Check timedText is active for a given embedPlayer
+ * @param {object} embedPlayer The player to be checked for timedText properties
+ */
+ mw.isTimedTextSupported = function( embedPlayer ) {
+ //EmbedPlayerNewPlayer passes a div with data-mwprovider set,
+ //EmbedPlayerUpdateDependencies passes video element with data attribute
+ //catch both
+ var mwprovider = embedPlayer['data-mwprovider'] || $( embedPlayer ).data('mwprovider');
+ var showInterface = mw.config.get( 'TimedText.ShowInterface.' + mwprovider ) ||
+ mw.config.get( 'TimedText.ShowInterface' );
+
+ if ( showInterface == 'always' ) {
+ return true;
+ } else if ( showInterface == 'off' ) {
+ return false;
+ }
+
+ // Check for standard 'track' attribute:
+ if ( $( embedPlayer ).find( 'track' ).length != 0 ) {
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.php b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.php
new file mode 100644
index 00000000..57f50043
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.php
@@ -0,0 +1,21 @@
+<?php
+
+ // Register all the timedText modules
+ return array(
+ "mw.TimedText" => array(
+ 'scripts' => "resources/mw.TimedText.js",
+ 'styles' => "resources/mw.style.TimedText.css",
+ 'dependencies' => array(
+ 'mw.EmbedPlayer',
+ 'mw.TextSource'
+ ),
+ 'messageDir' => 'i18n',
+ ),
+ "mw.TextSource" => array(
+ 'scripts' => "resources/mw.TextSource.js",
+ 'dependencies' => array(
+ 'mediawiki.UtilitiesTime',
+ "mw.ajaxProxy",
+ )
+ )
+ );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/af.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/af.json
new file mode 100644
index 00000000..0024412a
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/af.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Naudefj"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Terug",
+ "mwe-timedtext-textcat-cc": "Onderskrifte",
+ "mwe-timedtext-textcat-lrc": "Lirieke"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ar.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ar.json
new file mode 100644
index 00000000..48597e00
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ar.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Meno25",
+ "Ų±ŁˆŲ®Łˆ"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Ų±Ų¬ŁˆŲ¹",
+ "mwe-timedtext-layout-off": "Ų„Ų®ŁŲ§Ų” Ų§Ł„ŲŖŲ±Ų¬Ł…Ų§ŲŖ",
+ "mwe-timedtext-loading-text": "Ų¬Ų§Ų±ŁŠ ŲŖŲ­Ł…ŁŠŁ„ Ų§Ł„Ł†Ųµ...",
+ "mwe-timedtext-textcat-cc": "Ł†ŲµŁˆŲµ ŲŖŁˆŲ¶ŁŠŲ­ŁŠŲ©",
+ "mwe-timedtext-textcat-cue": "Ł†Ł‚Ų§Ų· ŲŖŁ„Ł…ŁŠŲ­",
+ "mwe-timedtext-upload-timed-text": "Ų„Ų¶Ų§ŁŲ© Ų§Ł„ŲŖŲ±Ų¬Ł…Ų§ŲŖ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ast.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ast.json
new file mode 100644
index 00000000..9df51f24
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ast.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Xuacu"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Anterior",
+ "mwe-timedtext-layout-off": "Tapecer subtĆ­tulos",
+ "mwe-timedtext-loading-text": "Cargando'l testu...",
+ "mwe-timedtext-textcat-cc": "Lleendes",
+ "mwe-timedtext-textcat-sub": "SubtĆ­tulos",
+ "mwe-timedtext-textcat-tad": "DescripciĆ³n del sonĆ­u",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Testu en movimientu",
+ "mwe-timedtext-textcat-ar": "Rexones actives",
+ "mwe-timedtext-textcat-nb": "AnotaciĆ³n",
+ "mwe-timedtext-textcat-meta": "Metadatos cronometraos",
+ "mwe-timedtext-textcat-trx": "TrescripciĆ³n",
+ "mwe-timedtext-textcat-lrc": "Lletra",
+ "mwe-timedtext-textcat-lin": "Formatu llingĆ¼Ć­sticu",
+ "mwe-timedtext-textcat-cue": "Puntos de referencia",
+ "mwe-timedtext-no-subs": "Nun hai pistes de testu disponibles",
+ "mwe-timedtext-language-subtitles-for-clip": "SubtĆ­tulos en $1 pal videu: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Nun s'alcontraron los subtĆ­tulos en $1 pal videu: $2",
+ "mwe-timedtext-upload-timed-text": "AƱadir subtƭtulos"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/be-tarask.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/be-tarask.json
new file mode 100644
index 00000000..5c25527d
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/be-tarask.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "EugeneZelenko",
+ "Jim-by",
+ "Wizardist"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Š’ŃŃ€Š½ŃƒŃ†Ń†Š°",
+ "mwe-timedtext-layout-off": "Š”хŠ°Š²Š°Ń†ŃŒ суŠ±Ń‚ытры",
+ "mwe-timedtext-loading-text": "Š—Š°Š³Ń€ŃƒŠ·ŠŗŠ° тэŠŗстуā€¦",
+ "mwe-timedtext-textcat-cc": "Š”уŠ±Ń‚ытры",
+ "mwe-timedtext-textcat-sub": "Š”уŠ±Ń‚ытры:",
+ "mwe-timedtext-textcat-tad": "ŠŃžŠ“ыя-Š°ŠæісŠ°Š½ŃŒŠ½Šµ",
+ "mwe-timedtext-textcat-ktv": "ŠšŠ°Ń€Š°Š¾ŠŗŠµ",
+ "mwe-timedtext-textcat-tik": "Š¢ŃŠŗстŠ°Š²Ń‹Ń ŠŗŠ°Ń€Ń‚Šŗі",
+ "mwe-timedtext-textcat-ar": "ŠŠŗтыўŠ½Ń‹Ń рэŠ³Ń–Ń‘Š½Ń‹",
+ "mwe-timedtext-textcat-nb": "ŠŠ½Š°Ń‚Š°Ń†Ń‹Ń",
+ "mwe-timedtext-textcat-meta": "Š”ыŠ½Ń…Ń€Š°Š½Ń–Š·Š°Š²Š°Š½Ń‹Ń Š¼ŠµŃ‚Š°-Š·ŃŒŠ²ŠµŃŃ‚Šŗі",
+ "mwe-timedtext-textcat-trx": "Š”тэŠ½Š°Š³Ń€Š°Š¼Š°",
+ "mwe-timedtext-textcat-lrc": "Š”Š»Š¾Š²Ń‹",
+ "mwe-timedtext-textcat-lin": "Š›Ń–Š½Š³Š²Ń–стычŠ½Š°Ń рŠ°Š·ŃŒŠ¼ŠµŃ‚ŠŗŠ°",
+ "mwe-timedtext-textcat-cue": "Š”ыŠ³Š½Š°Š»ŃŒŠ½Ń‹Ń ŠŗрŠ¾ŠæŠŗі",
+ "mwe-timedtext-no-subs": "Š”уŠ±Ń‚Ń‹Ń‚Ń€Š°Ńž Š½ŃŠ¼Š°",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 суŠ±Ń‚ытры Š“Š»Ń ŠŗŠ»Ń–Šæу: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Š”уŠ±Ń‚ытры $1 Š“Š»Ń ŠŗŠ»Ń–Šæу Š½Ń Š·Š½Š¾Š¹Š“Š·ŠµŠ½Ń‹Ń: $2",
+ "mwe-timedtext-upload-timed-text": "Š”Š°Š“Š°Ń†ŃŒ суŠ±Ń‚ытры"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bg.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bg.json
new file mode 100644
index 00000000..b88de95d
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bg.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ŠŠ°Š·Š°Š“"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bn.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bn.json
new file mode 100644
index 00000000..395fbe7b
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bn.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aftab1995",
+ "Bellayet"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ą¦Ŗą¦æą¦›ą¦Øą§‡",
+ "mwe-timedtext-layout-off": "ą¦‰ą¦Ŗą¦¶ą¦æą¦°ą§‹ą¦Øą¦¾ą¦® ą¦²ą§ą¦•ą¦¾ą¦“",
+ "mwe-timedtext-loading-text": "ą¦Ÿą§‡ą¦•ą§ą¦øą¦Ÿ ą¦²ą§‹ą¦” ą¦¹ą¦šą§ą¦›ą§‡ ...",
+ "mwe-timedtext-textcat-cc": "ą¦Ŗą¦°ą¦æą¦šą¦Æą¦¼ą¦²ą¦æą¦Ŗą¦æ",
+ "mwe-timedtext-textcat-sub": "ą¦‰ą¦Ŗą¦¶ą¦æą¦°ą§‹ą¦Øą¦¾ą¦®",
+ "mwe-timedtext-textcat-tad": "ą¦…ą¦”ą¦æą¦“ ą¦¬ą¦æą¦¬ą¦°ą¦£",
+ "mwe-timedtext-upload-timed-text": "ą¦‰ą¦Ŗą¦¶ą¦æą¦°ą§‹ą¦Øą¦¾ą¦® ą¦Æą§ą¦•ą§ą¦¤ ą¦•ą¦°ą§ą¦Ø"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/br.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/br.json
new file mode 100644
index 00000000..eacd0f20
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/br.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Fulup",
+ "Y-M D"
+ ]
+ },
+ "mwe-timedtext-back-btn": "DistreiƱ",
+ "mwe-timedtext-layout-off": "Kuzhat an istitloĆ¹",
+ "mwe-timedtext-loading-text": "O kargaƱ an destenn...",
+ "mwe-timedtext-textcat-cc": "Alc'hwezioĆ¹",
+ "mwe-timedtext-textcat-sub": "IstitloĆ¹",
+ "mwe-timedtext-textcat-tad": "Deskrivadur son",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Barenn titouroĆ¹",
+ "mwe-timedtext-textcat-ar": "RannvroioĆ¹ oberiant",
+ "mwe-timedtext-textcat-nb": "Notennadur",
+ "mwe-timedtext-textcat-meta": "MetaroadennoĆ¹ sinkronelaet",
+ "mwe-timedtext-textcat-trx": "TreuzskrivaƱ",
+ "mwe-timedtext-textcat-lrc": "KomzoĆ¹",
+ "mwe-timedtext-textcat-lin": "BalizennoĆ¹ yezhel",
+ "mwe-timedtext-textcat-cue": "Poent lec'hiaƱ",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 istitl evit ar c'hlip : $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "N'eo ket bet kavet $1 istitl evit ar c'hlip : $2",
+ "mwe-timedtext-upload-timed-text": "EnporzhiaƱ istitloĆ¹"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bs.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bs.json
new file mode 100644
index 00000000..f8d0cd23
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bs.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "CERminator"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Nazad",
+ "mwe-timedtext-textcat-sub": "Podnaslovi",
+ "mwe-timedtext-textcat-tad": "Opis zvuka"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ca.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ca.json
new file mode 100644
index 00000000..ce45bfb5
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ca.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Pitort"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Enrere",
+ "mwe-timedtext-textcat-sub": "SubtĆ­tols"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ce.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ce.json
new file mode 100644
index 00000000..f1580f0d
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ce.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Š£Š¼Š°Ń€"
+ ]
+ },
+ "mwe-timedtext-textcat-tad": "ŠŃƒŠ“ŠøŠ¾-хŠ°Š°Š¼"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/cs.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/cs.json
new file mode 100644
index 00000000..94a5e7eb
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/cs.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mormegil",
+ "Vks"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Zpět",
+ "mwe-timedtext-layout-off": "SkrĆ½t titulky",
+ "mwe-timedtext-loading-text": "NačƭtĆ” se textā€¦",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-nb": "Anotace",
+ "mwe-timedtext-textcat-trx": "Přepis",
+ "mwe-timedtext-language-subtitles-for-clip": "Titulky ke klipu $2 v jazyce $1",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Ke klipu $2 nebyly nalezeny titulky v jazyce $1"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/cy.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/cy.json
new file mode 100644
index 00000000..fd0eea45
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/cy.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lloffiwr",
+ "Robin Owain"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Yn Ć“l",
+ "mwe-timedtext-layout-off": "Cuddio'r isdeitlau",
+ "mwe-timedtext-loading-text": "Yn llwytho'r testun...",
+ "mwe-timedtext-textcat-cc": "Geiriad",
+ "mwe-timedtext-textcat-sub": "Isdeitlau",
+ "mwe-timedtext-textcat-tad": "Disgrifiad o'r sain",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Testun",
+ "mwe-timedtext-textcat-ar": "Ardaloedd gweithredolo",
+ "mwe-timedtext-textcat-nb": "Anodiad",
+ "mwe-timedtext-textcat-meta": "Metadata a amserwyd",
+ "mwe-timedtext-textcat-trx": "Trawsysgrif",
+ "mwe-timedtext-textcat-lrc": "Geiriau",
+ "mwe-timedtext-textcat-cue": "Cerrig milltir",
+ "mwe-timedtext-no-subs": "Dim traciau testun ar gael",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 isdeitl ar gael ar gyfer clip: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Dim $1 isdeitl ar gael ar gyfer: $2",
+ "mwe-timedtext-upload-timed-text": "Ychwanegu isdeitlau"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/de-formal.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/de-formal.json
new file mode 100644
index 00000000..10c9c650
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/de-formal.json
@@ -0,0 +1,7 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kghbln"
+ ]
+ }
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/de.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/de.json
new file mode 100644
index 00000000..35d1cef9
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/de.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kghbln",
+ "Metalhead64",
+ "Purodha"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ZurĆ¼ck",
+ "mwe-timedtext-layout-off": "Untertitel ausblenden",
+ "mwe-timedtext-loading-text": "Text wird geladen ā€¦",
+ "mwe-timedtext-textcat-cc": "Legenden",
+ "mwe-timedtext-textcat-sub": "Untertitel",
+ "mwe-timedtext-textcat-tad": "Beschreibung (Audio)",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Text-Ticker",
+ "mwe-timedtext-textcat-ar": "Aktive Regionen",
+ "mwe-timedtext-textcat-nb": "Annotation",
+ "mwe-timedtext-textcat-meta": "ā€žTimed Textā€œ-Metadaten",
+ "mwe-timedtext-textcat-trx": "Abschrift",
+ "mwe-timedtext-textcat-lrc": "Liedtext",
+ "mwe-timedtext-textcat-lin": "Sprachliche Beschreibung",
+ "mwe-timedtext-textcat-cue": "Cue-Punkte",
+ "mwe-timedtext-no-subs": "Es sind keine Untertitel verfĆ¼gbar",
+ "mwe-timedtext-language-subtitles-for-clip": "Untertitel auf $1 fĆ¼r den Videoclip: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Keine Untertitel auf $1 fĆ¼r den Videoclip gefunden: $2",
+ "mwe-timedtext-upload-timed-text": "Untertitel hinzufĆ¼gen"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/diq.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/diq.json
new file mode 100644
index 00000000..ee86ed2c
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/diq.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Erdemaslancan",
+ "Mirzali"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Peyser",
+ "mwe-timedtext-textcat-cc": "Bınnuşte",
+ "mwe-timedtext-textcat-sub": "Sernuştey bıni",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-nb": "Ole şınasiye"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/dsb.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/dsb.json
new file mode 100644
index 00000000..362d95c8
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/dsb.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Derbeth",
+ "Michawiki"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Slědk",
+ "mwe-timedtext-layout-off": "PĆ³dtitele schowaś",
+ "mwe-timedtext-loading-text": "Tekst se zacytujo...",
+ "mwe-timedtext-textcat-cc": "Wopisanja",
+ "mwe-timedtext-textcat-sub": "PĆ³dtitele",
+ "mwe-timedtext-textcat-tad": "Awdiowopisanje",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Běžecy tekst",
+ "mwe-timedtext-textcat-ar": "Aktiwne regiony",
+ "mwe-timedtext-textcat-nb": "Anotacija",
+ "mwe-timedtext-textcat-meta": "Synchronizěrowane metadaty",
+ "mwe-timedtext-textcat-trx": "Pśepisaś",
+ "mwe-timedtext-textcat-lrc": "Spiwny tekst",
+ "mwe-timedtext-textcat-lin": "Rěcywědne wopisanje",
+ "mwe-timedtext-textcat-cue": "Zastupne dypki",
+ "mwe-timedtext-no-subs": "Žedne pĆ³dtitele k dispoziciji",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 {{PLURAL:$1|pĆ³dtitel|pĆ³dtitela|pĆ³dtitele|oĆ³dtitelow}} za klip: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Žedne pĆ³dtitele $1 su se za klip namakali: $2",
+ "mwe-timedtext-upload-timed-text": "PĆ³dtitele pśidaś"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/el.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/el.json
new file mode 100644
index 00000000..9de04eff
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/el.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Geraki"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Ī•Ļ€Ī¹ĻƒĻ„ĻĪæĻ†Ī®",
+ "mwe-timedtext-layout-off": "Ī‘Ļ€ĻŒĪŗĻĻ…ĻˆĪ· Ļ…Ļ€ĻŒĻ„Ī¹Ļ„Ī»Ļ‰Ī½",
+ "mwe-timedtext-loading-text": "Ī¦ĻŒĻĻ„Ļ‰ĻƒĪ· ĪŗĪµĪÆĪ¼ĪµĪ½ĪæĻ…...",
+ "mwe-timedtext-textcat-cc": "Ī›ĪµĪ¶Ī¬Ī½Ļ„ĪµĻ‚",
+ "mwe-timedtext-textcat-sub": "Ī„Ļ€ĻŒĻ„Ī¹Ļ„Ī»ĪæĪ¹",
+ "mwe-timedtext-textcat-tad": "Ī‘ĪŗĪæĻ…ĻƒĻ„Ī¹ĪŗĪ® Ļ€ĪµĻĪ¹Ī³ĻĪ±Ļ†Ī®",
+ "mwe-timedtext-textcat-ktv": "ĪšĪ±ĻĪ±ĻŒĪŗĪµ",
+ "mwe-timedtext-textcat-tik": "ĪšĻ…Ī»Ī¹ĻŒĪ¼ĪµĪ½Īæ ĪŗĪµĪÆĪ¼ĪµĪ½Īæ",
+ "mwe-timedtext-textcat-ar": "Ī•Ī½ĪµĻĪ³Ī­Ļ‚ Ļ€ĪµĻĪ¹ĪæĻ‡Ī­Ļ‚",
+ "mwe-timedtext-textcat-nb": "Ī£Ļ‡ĻŒĪ»Ī¹Īæ",
+ "mwe-timedtext-textcat-meta": "Ī§ĻĪæĪ½Ī¹ĻƒĪ¼Ī­Ī½Ī± Ī¼ĪµĻ„Ī±Ī“ĪµĪ“ĪæĪ¼Ī­Ī½Ī±",
+ "mwe-timedtext-textcat-trx": "ĪœĪµĻ„Ī±Ī³ĻĪ±Ļ†Ī®",
+ "mwe-timedtext-textcat-lrc": "Ī£Ļ„ĪÆĻ‡ĪæĪ¹",
+ "mwe-timedtext-textcat-lin": "Ī“Ī»Ļ‰ĻƒĻƒĪæĪ»ĪæĪ³Ī¹ĪŗĪ® ĻƒĻĪ½Ļ„Ī±Ī¾Ī·",
+ "mwe-timedtext-textcat-cue": "Cue points",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 Ļ…Ļ€ĻŒĻ„Ī¹Ļ„Ī»ĪæĪ¹ Ī³Ī¹Ī± Ļ„Īæ Ī²ĪÆĪ½Ļ„ĪµĪæ: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Ī”ĪµĪ½ Ī²ĻĪ­ĪøĪ·ĪŗĪ±Ī½ Ļ…Ļ€ĻŒĻ„Ī¹Ļ„Ī»ĪæĪ¹ $1 Ī³Ī¹Ī± Ļ„Īæ Ī²ĪÆĪ½Ļ„ĪµĪæ: $2"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/en.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/en.json
new file mode 100644
index 00000000..0505d5b7
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/en.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": []
+ },
+ "mwe-timedtext-back-btn": "Back",
+ "mwe-timedtext-layout-off": "Hide subtitles",
+ "mwe-timedtext-loading-text": "Loading text ...",
+ "mwe-timedtext-key-language": "$1, $2",
+ "mwe-timedtext-textcat-cc": "Captions",
+ "mwe-timedtext-textcat-sub": "Subtitles",
+ "mwe-timedtext-textcat-tad": "Audio description",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Ticker text",
+ "mwe-timedtext-textcat-ar": "Active regions",
+ "mwe-timedtext-textcat-nb": "Annotation",
+ "mwe-timedtext-textcat-meta": "Timed metadata",
+ "mwe-timedtext-textcat-trx": "Transcript",
+ "mwe-timedtext-textcat-lrc": "Lyrics",
+ "mwe-timedtext-textcat-lin": "Linguistic markup",
+ "mwe-timedtext-textcat-cue": "Cue points",
+ "mwe-timedtext-no-subs": "No text tracks available",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 subtitles for clip: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "No $1 subtitles were found for clip: $2",
+ "mwe-timedtext-upload-timed-text": "Add subtitles"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/eo.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/eo.json
new file mode 100644
index 00000000..f787b8a6
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/eo.json
@@ -0,0 +1,7 @@
+{
+ "@metadata": {
+ "authors": [
+ "Yekrats"
+ ]
+ }
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/es.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/es.json
new file mode 100644
index 00000000..e753ece1
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/es.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Armando-Martin",
+ "Crazymadlover",
+ "Locos epraix",
+ "Pertile",
+ "Translationista"
+ ]
+ },
+ "mwe-timedtext-back-btn": "AtrƔs",
+ "mwe-timedtext-layout-off": "Ocultar subtĆ­tulos",
+ "mwe-timedtext-loading-text": "Cargando texto ...",
+ "mwe-timedtext-textcat-cc": "Leyendas",
+ "mwe-timedtext-textcat-sub": "SubtĆ­tulos",
+ "mwe-timedtext-textcat-tad": "DescripciĆ³n de audio",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Texto desplazable",
+ "mwe-timedtext-textcat-ar": "Regiones activas",
+ "mwe-timedtext-textcat-nb": "AnotaciĆ³n",
+ "mwe-timedtext-textcat-meta": "Metadatos sincronizados",
+ "mwe-timedtext-textcat-trx": "Transcribir",
+ "mwe-timedtext-textcat-lrc": "Letra",
+ "mwe-timedtext-textcat-lin": "Marcador lingĆ¼Ć­stico",
+ "mwe-timedtext-textcat-cue": "Puntos de referencia",
+ "mwe-timedtext-no-subs": "No hay pistas de texto disponibles",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 subtĆ­tulos para el clip: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "No se ha encontrado subtĆ­tulos $1 para el clip: $2",
+ "mwe-timedtext-upload-timed-text": "AƱadir subtƭtulos"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/et.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/et.json
new file mode 100644
index 00000000..a57273aa
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/et.json
@@ -0,0 +1,18 @@
+{
+ "@metadata": {
+ "authors": [
+ "Avjoska",
+ "Pikne"
+ ]
+ },
+ "mwe-timedtext-layout-off": "Peida alltiitrid",
+ "mwe-timedtext-loading-text": "Teksti laadimine...",
+ "mwe-timedtext-textcat-sub": "Alltiitrid",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-meta": "Ajastatud metaandmed",
+ "mwe-timedtext-textcat-lrc": "LaulusƵnad",
+ "mwe-timedtext-no-subs": "Alltiitreid pole saadaval",
+ "mwe-timedtext-language-subtitles-for-clip": "LƵigu $2 $1 alltiitrid",
+ "mwe-timedtext-language-no-subtitles-for-clip": "LƵigu $2 jaoks ei leitud $1 alltiitreid",
+ "mwe-timedtext-upload-timed-text": "Lisa alltiitrid"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/eu.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/eu.json
new file mode 100644
index 00000000..5c30fe9d
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/eu.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ",
+ "Subi"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Atzera",
+ "mwe-timedtext-textcat-ktv": "Karaokea"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fa.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fa.json
new file mode 100644
index 00000000..c6fa166e
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fa.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Armin1392",
+ "Ebraminio",
+ "Pouyana",
+ "Reza1615",
+ "Ł¾Ų§Ł†Ų§Ų±ŁˆŁ…Ų§"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ŲØŲ§Ų²ŚÆŲ“ŲŖ",
+ "mwe-timedtext-layout-off": "Ł¾Ł†Ł‡Ų§Ł† Ś©Ų±ŲÆŁ† Ų²ŪŒŲ±Ł†ŁˆŪŒŲ³",
+ "mwe-timedtext-loading-text": "ŲÆŲ± Ų­Ų§Ł„ ŲØŲ§Ų±ŚÆŪŒŲ±ŪŒ Ł…ŲŖŁ† ...",
+ "mwe-timedtext-textcat-cc": "Ų¹Ł†Ų§ŁˆŪŒŁ†:",
+ "mwe-timedtext-textcat-sub": "Ų²ŪŒŲ±Ł†ŁˆŪŒŲ³",
+ "mwe-timedtext-textcat-tad": "ŲŖŁˆŲ¶ŪŒŲ­ ŲµŁˆŲŖŪŒ",
+ "mwe-timedtext-textcat-ktv": "Ś©Ų§Ų±Ų§Ų¦ŁˆŚ©Ł‡",
+ "mwe-timedtext-textcat-tik": "Ł…ŲŖŁ† ŲŖŪŒŚ©Ų±",
+ "mwe-timedtext-textcat-ar": "Ł…Ł†Ų§Ų·Ł‚ ŁŲ¹Ų§Ł„",
+ "mwe-timedtext-textcat-nb": "ŪŒŲ§ŲÆŲÆŲ§Ų“ŲŖ",
+ "mwe-timedtext-textcat-meta": "ŁŲ±Ų§ŲÆŲ§ŲÆŁ‡Ł” ŲØŁ‡ Ł‡Ł†ŚÆŲ§Ł…",
+ "mwe-timedtext-textcat-trx": "Ų±ŁˆŁ†ŁˆŲ“ŲŖ",
+ "mwe-timedtext-textcat-lrc": "Ł…ŲŖŁ† ŲŖŲ±Ų§Ł†Ł‡ā€ŒŁ‡Ų§",
+ "mwe-timedtext-textcat-lin": "Ų²ŲØŲ§Ł† Ł†Ų“Ų§Ł†Ł‡ā€ŒŚÆŲ°Ų§Ų±ŪŒ",
+ "mwe-timedtext-textcat-cue": "Ł†Ł‚Ų§Ų· Ł†Ų“Ų§Ł†Ł‡",
+ "mwe-timedtext-no-subs": "Ł‡ŪŒŚ† Ų¢Ł‡Ł†ŚÆ Ł…ŲŖŁ†ŪŒ ŲÆŲ±ŲÆŲ³ŲŖŲ±Ų³ Ł†ŪŒŲ³ŲŖ",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 Ų²ŪŒŲ±Ł†ŁˆŪŒŲ³ ŲØŲ±Ų§ŪŒ Ś©Ł„ŪŒŁ¾: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Ł‡ŪŒŚ† $1 Ų²ŪŒŲ±Ł†ŁˆŪŒŲ³ŪŒ ŲØŲ±Ų§ŪŒ Ś©Ł„ŪŒŁ¾ Ł¾ŪŒŲÆŲ§ Ł†Ų“ŲÆ: $2",
+ "mwe-timedtext-upload-timed-text": "Ų§Ų¶Ų§ŁŁ‡ Ś©Ų±ŲÆŁ† Ų²ŪŒŲ±Ł†ŁˆŪŒŲ³"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fi.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fi.json
new file mode 100644
index 00000000..e0fa5944
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fi.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "Nedergard",
+ "Nike",
+ "Silvonen"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Takaisin",
+ "mwe-timedtext-layout-off": "Piilota tekstitys",
+ "mwe-timedtext-loading-text": "Ladataan tekstiƤ...",
+ "mwe-timedtext-textcat-cc": "Kuvatekstit",
+ "mwe-timedtext-textcat-sub": "Tekstitykset",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-upload-timed-text": "LisƤƤ tekstitys"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fr.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fr.json
new file mode 100644
index 00000000..4e74e546
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fr.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "IAlex",
+ "Peter17",
+ "Tititou36",
+ "Verdy p"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ArriĆØre",
+ "mwe-timedtext-layout-off": "Masquer les sous-titres",
+ "mwe-timedtext-loading-text": "Chargement du texte ...",
+ "mwe-timedtext-textcat-cc": "LĆ©gendes",
+ "mwe-timedtext-textcat-sub": "Sous-titres",
+ "mwe-timedtext-textcat-tad": "Description audio",
+ "mwe-timedtext-textcat-ktv": "KaraokƩ",
+ "mwe-timedtext-textcat-tik": "Barre d'informations",
+ "mwe-timedtext-textcat-ar": "RĆ©gions actives",
+ "mwe-timedtext-textcat-nb": "Annotation",
+ "mwe-timedtext-textcat-meta": "mƩtadonnƩes synchronisƩes",
+ "mwe-timedtext-textcat-trx": "Transcription",
+ "mwe-timedtext-textcat-lrc": "Paroles",
+ "mwe-timedtext-textcat-lin": "Balisage linguistique",
+ "mwe-timedtext-textcat-cue": "Points de repĆØre",
+ "mwe-timedtext-no-subs": "Aucun texte de piste disponible",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 sous-titres pour clip : $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Aucun sous-titre $1 n'a ƩtƩ trouvƩ pour le clip : $2",
+ "mwe-timedtext-upload-timed-text": "Ajouter des sous-titres"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/frp.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/frp.json
new file mode 100644
index 00000000..eeb629b9
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/frp.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "ChrisPtDe"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Tornar",
+ "mwe-timedtext-layout-off": "CachiƩr los sot-titros",
+ "mwe-timedtext-loading-text": "Chargement du tĆØxto ...",
+ "mwe-timedtext-textcat-cc": "LĆØgendes",
+ "mwe-timedtext-textcat-sub": "Sot-titros",
+ "mwe-timedtext-textcat-tad": "DĆØscripcion Ć“diĆ“",
+ "mwe-timedtext-textcat-ktv": "CaraoquĆØ",
+ "mwe-timedtext-textcat-tik": "BĆ¢rra dā€™enformacions",
+ "mwe-timedtext-textcat-ar": "RĆØgĀ·ions actives",
+ "mwe-timedtext-textcat-nb": "Nota",
+ "mwe-timedtext-textcat-meta": "MĆØtabalyĆŖs sincronisĆ¢s",
+ "mwe-timedtext-textcat-trx": "Transcripcion",
+ "mwe-timedtext-textcat-lrc": "Paroles",
+ "mwe-timedtext-textcat-lin": "BalisĆ¢jo lengouistico",
+ "mwe-timedtext-textcat-cue": "Pouents de repĆØro",
+ "mwe-timedtext-no-subs": "Gins de pista de tĆØxto disponibla",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 sot-titros por clipe : $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Nion sot-titro $1 at Ć©tĆ¢ trovĆ¢ por lo clipe : $2",
+ "mwe-timedtext-upload-timed-text": "Apondre des sot-titros"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fy.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fy.json
new file mode 100644
index 00000000..69f89218
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fy.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Robin0van0der0vliet"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Foarige"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/gl.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/gl.json
new file mode 100644
index 00000000..df9d0409
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/gl.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "ToliƱo"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Volver",
+ "mwe-timedtext-layout-off": "Agochar os subtĆ­tulos",
+ "mwe-timedtext-loading-text": "Cargando o texto...",
+ "mwe-timedtext-textcat-cc": "PĆ©s de foto",
+ "mwe-timedtext-textcat-sub": "SubtĆ­tulos",
+ "mwe-timedtext-textcat-tad": "DescriciĆ³n do son",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Barra de informaciĆ³n",
+ "mwe-timedtext-textcat-ar": "RexiĆ³ns activas",
+ "mwe-timedtext-textcat-nb": "AnotaciĆ³n",
+ "mwe-timedtext-textcat-meta": "Metadatos sincronizados",
+ "mwe-timedtext-textcat-trx": "TranscriciĆ³n",
+ "mwe-timedtext-textcat-lrc": "Letra",
+ "mwe-timedtext-textcat-lin": "Formato lingĆ¼Ć­stico",
+ "mwe-timedtext-textcat-cue": "Puntos de sinal",
+ "mwe-timedtext-no-subs": "Non hai pistas de texto dispoƱibles",
+ "mwe-timedtext-language-subtitles-for-clip": "SubtĆ­tulos en $1 para o vĆ­deo: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Non se atoparon os subtĆ­tulos en $1 para o vĆ­deo: $2",
+ "mwe-timedtext-upload-timed-text": "Engadir subtĆ­tulos"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/gsw.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/gsw.json
new file mode 100644
index 00000000..c48c3c0c
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/gsw.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Als-ChlƤmens",
+ "Als-Holder"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Zruck",
+ "mwe-timedtext-layout-off": "Untertitel uusblƤnde",
+ "mwe-timedtext-loading-text": "Am Lade vum Text ...",
+ "mwe-timedtext-textcat-cc": "Bschryybige",
+ "mwe-timedtext-textcat-sub": "Untertitel",
+ "mwe-timedtext-textcat-tad": "Audio-Bschryybig",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Text-Ticker",
+ "mwe-timedtext-textcat-ar": "Aktivi Regione",
+ "mwe-timedtext-textcat-nb": "Aamerkig",
+ "mwe-timedtext-textcat-meta": "Ƅchtzyt-Metadate",
+ "mwe-timedtext-textcat-trx": "Abschrift",
+ "mwe-timedtext-textcat-lrc": "Liedtext",
+ "mwe-timedtext-textcat-lin": "Sprochwisseschaftligi Bschryybig",
+ "mwe-timedtext-textcat-cue": "Cue-Pinkt",
+ "mwe-timedtext-no-subs": "Untertitel sin nit verfiegbar",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 Untertitel gfunde fir dr Videoclip: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Kei $1 Untertitel gfunde fir dr Videoclip: $2",
+ "mwe-timedtext-upload-timed-text": "Untertitel uffelade"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/he.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/he.json
new file mode 100644
index 00000000..5137aa27
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/he.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "Guycn2",
+ "YaronSh"
+ ]
+ },
+ "mwe-timedtext-back-btn": "חז×Øה",
+ "mwe-timedtext-layout-off": "×”×”×Ŗ×Ø×Ŗ כ×Ŗוביו×Ŗ",
+ "mwe-timedtext-loading-text": "טעינ×Ŗ טקהט...",
+ "mwe-timedtext-textcat-cc": "כו×Ŗ×Øו×Ŗ",
+ "mwe-timedtext-textcat-sub": "כ×Ŗוביו×Ŗ",
+ "mwe-timedtext-textcat-tad": "×Ŗיאו×Ø ×”×©×ž×¢",
+ "mwe-timedtext-textcat-ktv": "ק×Øאוקה",
+ "mwe-timedtext-textcat-tik": "שפ×Ŗ השו×Øה ה×Øצה",
+ "mwe-timedtext-textcat-ar": "אזו×Øים פעילים",
+ "mwe-timedtext-textcat-nb": "פ×Øשנו×Ŗ",
+ "mwe-timedtext-textcat-meta": "מטא־מ×Ŗונים מ×Ŗוזמנים",
+ "mwe-timedtext-textcat-trx": "×Ŗמליל",
+ "mwe-timedtext-textcat-lrc": "מילו×Ŗ השי×Ø",
+ "mwe-timedtext-textcat-lin": "הימון בלשני",
+ "mwe-timedtext-textcat-cue": "נקודו×Ŗ הימני×Ŗ",
+ "mwe-timedtext-no-subs": "אין ×Øצוע×Ŗ ×Ŗמליל זמינה",
+ "mwe-timedtext-language-subtitles-for-clip": "כ×Ŗוביו×Ŗ ב{{grammar:×Ŗחילי×Ŗ|$1}} עבו×Ø ×”×”×Øטון $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "לא נמצאו כ×Ŗוביו×Ŗ ב{{grammar:×Ŗחילי×Ŗ|$1}} עבו×Ø $2",
+ "mwe-timedtext-upload-timed-text": "הוהפ×Ŗ כ×Ŗוביו×Ŗ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/hsb.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/hsb.json
new file mode 100644
index 00000000..325044d8
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/hsb.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Michawiki"
+ ]
+ },
+ "mwe-timedtext-back-btn": "WrĆ³Ä‡o",
+ "mwe-timedtext-layout-off": "Podtitule schować",
+ "mwe-timedtext-loading-text": "Tekst so začituje...",
+ "mwe-timedtext-textcat-cc": "Nadpisma",
+ "mwe-timedtext-textcat-sub": "Podtitule",
+ "mwe-timedtext-textcat-tad": "Awdiowopisanje",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Tekstowy běžacy pask",
+ "mwe-timedtext-textcat-ar": "Aktiwne regiony",
+ "mwe-timedtext-textcat-nb": "Anotacija",
+ "mwe-timedtext-textcat-meta": "Synchronizowane metadaty",
+ "mwe-timedtext-textcat-trx": "Přepis",
+ "mwe-timedtext-textcat-lrc": "Spěwowy tekst",
+ "mwe-timedtext-textcat-lin": "Rěčespytne wopisanje",
+ "mwe-timedtext-textcat-cue": "Zastupne dypki",
+ "mwe-timedtext-no-subs": "Žane podtitule k dispoziciji",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 {{PLURAL:$1|podtitul|podtitulej|podtitule|podtitulow}} za klip: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Žane podtitule $1 za klip namakane: $2",
+ "mwe-timedtext-upload-timed-text": "Podtitule přidać"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/hu.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/hu.json
new file mode 100644
index 00000000..a5eb9692
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/hu.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dani",
+ "Glanthor Reviol",
+ "Misibacsi"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Vissza",
+ "mwe-timedtext-layout-off": "Feliratok elrejtƩse",
+ "mwe-timedtext-loading-text": "Szƶveg betƶltĆ©seā€¦",
+ "mwe-timedtext-textcat-cc": "Feliratok",
+ "mwe-timedtext-textcat-sub": "Felirat",
+ "mwe-timedtext-textcat-tad": "Hang leƭrƔsa",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-ar": "AktĆ­v rĆ©giĆ³k",
+ "mwe-timedtext-textcat-nb": "AnnotĆ”ciĆ³",
+ "mwe-timedtext-textcat-meta": "IdőzĆ­tett metaadatok",
+ "mwe-timedtext-textcat-trx": "Ɓtirat",
+ "mwe-timedtext-textcat-lrc": "Dalszƶveg",
+ "mwe-timedtext-textcat-lin": "Nyelvi jelƶlƩs",
+ "mwe-timedtext-upload-timed-text": "Felirat hozzƔadƔsa"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ia.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ia.json
new file mode 100644
index 00000000..624dc45d
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ia.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "McDutchie"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Retornar",
+ "mwe-timedtext-layout-off": "Celar subtitulos",
+ "mwe-timedtext-loading-text": "Carga textoā€¦",
+ "mwe-timedtext-textcat-cc": "Subtitulos",
+ "mwe-timedtext-textcat-sub": "Subtitulos",
+ "mwe-timedtext-textcat-tad": "Description audio",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Barra de information",
+ "mwe-timedtext-textcat-ar": "Regiones active",
+ "mwe-timedtext-textcat-nb": "Annotation",
+ "mwe-timedtext-textcat-meta": "Metadatos de synchronisation",
+ "mwe-timedtext-textcat-trx": "Transcription",
+ "mwe-timedtext-textcat-lrc": "Lyricos",
+ "mwe-timedtext-textcat-lin": "Marcation lingusitic",
+ "mwe-timedtext-textcat-cue": "Punctos de entrata",
+ "mwe-timedtext-no-subs": "Subtitulos non disponibile",
+ "mwe-timedtext-language-subtitles-for-clip": "Subtitulos in $1 pro le clip: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Nulle subtitulos in $1 ha essite trovate pro le clip: $2",
+ "mwe-timedtext-upload-timed-text": "Adder subtitulos"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/id.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/id.json
new file mode 100644
index 00000000..12a35bd7
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/id.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Farras",
+ "IvanLanin"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Kembali",
+ "mwe-timedtext-layout-off": "Sembunyikan subjudul",
+ "mwe-timedtext-loading-text": "Memuat teks ...",
+ "mwe-timedtext-textcat-cc": "Keterangan",
+ "mwe-timedtext-textcat-sub": "Subjudul",
+ "mwe-timedtext-textcat-tad": "Deskripsi audio",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Teks tik",
+ "mwe-timedtext-textcat-ar": "Wilayah aktif",
+ "mwe-timedtext-textcat-nb": "Anotasi",
+ "mwe-timedtext-textcat-meta": "Data meta berjangka waktu",
+ "mwe-timedtext-textcat-trx": "Transkrip",
+ "mwe-timedtext-textcat-lrc": "Lirik",
+ "mwe-timedtext-textcat-lin": "Ubahan linguistik",
+ "mwe-timedtext-textcat-cue": "Titik acuan",
+ "mwe-timedtext-no-subs": "Jalur teks tidak tersedia",
+ "mwe-timedtext-language-subtitles-for-clip": "Subjudul $1 untuk klip: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Tidak ada subjudul $1 yang ditemukan untuk klip: $2",
+ "mwe-timedtext-upload-timed-text": "Unggah teks film"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/it.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/it.json
new file mode 100644
index 00000000..4e2fad3a
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/it.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Beta16",
+ "Darth Kule",
+ "F. Cosoleto",
+ "Gianfranco"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Indietro",
+ "mwe-timedtext-layout-off": "Nascondi sottotitoli",
+ "mwe-timedtext-loading-text": "Caricamento testo...",
+ "mwe-timedtext-textcat-cc": "Didascalie",
+ "mwe-timedtext-textcat-sub": "Sottotitoli",
+ "mwe-timedtext-textcat-tad": "Descrizione audio",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Testo in movimento",
+ "mwe-timedtext-textcat-ar": "Regioni attive",
+ "mwe-timedtext-textcat-nb": "Annotazione",
+ "mwe-timedtext-textcat-meta": "Metadati temporizzati",
+ "mwe-timedtext-textcat-trx": "Trascrizione",
+ "mwe-timedtext-textcat-lrc": "Testi",
+ "mwe-timedtext-textcat-lin": "Markup linguistico",
+ "mwe-timedtext-textcat-cue": "Punti d'entrata",
+ "mwe-timedtext-no-subs": "Nessuna traccia di testo disponibile",
+ "mwe-timedtext-language-subtitles-for-clip": "sottotitoli in $1 per il filmato: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Sottotitoli in $1 non trovati per il filmato: $2",
+ "mwe-timedtext-upload-timed-text": "Aggiungi sottotitoli"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ja.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ja.json
new file mode 100644
index 00000000..7e048693
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ja.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aotake",
+ "Hosiryuhosi",
+ "Shirayuki",
+ "Yanajin66",
+ "é’å­å®ˆę­Œ"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ęˆ»ć‚‹",
+ "mwe-timedtext-layout-off": "å­—å¹•ć‚’éš ć™",
+ "mwe-timedtext-loading-text": "ćƒ†ć‚­ć‚¹ćƒˆć®čŖ­ćæč¾¼ćæäø­...",
+ "mwe-timedtext-textcat-cc": "見å‡ŗ恗",
+ "mwe-timedtext-textcat-sub": "字幕",
+ "mwe-timedtext-textcat-tad": "éŸ³å£°ć®čŖ¬ę˜Ž",
+ "mwe-timedtext-textcat-ktv": "ć‚«ćƒ©ć‚Ŗ悱",
+ "mwe-timedtext-textcat-tik": "ćƒ†ć‚£ćƒƒć‚«ćƒ¼ę–‡ē« ",
+ "mwe-timedtext-textcat-ar": "ć‚¢ć‚Æćƒ†ć‚£ćƒ–ćŖ領域",
+ "mwe-timedtext-textcat-nb": "ę³Ø釈",
+ "mwe-timedtext-textcat-meta": "ę™‚é–“ćƒ”ć‚æćƒ‡ćƒ¼ć‚æ",
+ "mwe-timedtext-textcat-trx": "č¤‡å†™",
+ "mwe-timedtext-textcat-lrc": "ę­Œč©ž",
+ "mwe-timedtext-textcat-lin": "č؀čŖžćƒžćƒ¼ć‚Æ",
+ "mwe-timedtext-textcat-cue": "ć‚­ćƒ„ćƒ¼ćƒć‚¤ćƒ³ćƒˆ",
+ "mwe-timedtext-language-subtitles-for-clip": "ć‚ÆćƒŖ惃惗 $2 恮$1字幕",
+ "mwe-timedtext-language-no-subtitles-for-clip": "ć‚ÆćƒŖ惃惗 $2 恫ćÆ$1å­—å¹•ćŒć‚ć‚Šć¾ć›ć‚“",
+ "mwe-timedtext-upload-timed-text": "å­—å¹•ć‚’čæ½åŠ "
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ka.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ka.json
new file mode 100644
index 00000000..05eb95f5
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ka.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "David1010"
+ ]
+ },
+ "mwe-timedtext-back-btn": "įƒ£įƒ™įƒįƒœ",
+ "mwe-timedtext-layout-off": "įƒ”įƒ£įƒ‘įƒ¢įƒ˜įƒ¢įƒ įƒ”įƒ‘įƒ˜įƒ” įƒ“įƒįƒ›įƒįƒšįƒ•įƒ",
+ "mwe-timedtext-loading-text": "įƒ˜įƒ¢įƒ•įƒ˜įƒ įƒ—įƒ”įƒ‘įƒ įƒ¢įƒ”įƒ„įƒ”įƒ¢įƒ˜ ...",
+ "mwe-timedtext-textcat-cc": "įƒ¬įƒįƒ įƒ¬įƒ”įƒ įƒ”įƒ‘įƒ˜",
+ "mwe-timedtext-textcat-sub": "įƒ”įƒ£įƒ‘įƒ¢įƒ˜įƒ¢įƒ įƒ”įƒ‘įƒ˜",
+ "mwe-timedtext-textcat-tad": "įƒįƒ£įƒ“įƒ˜įƒ įƒįƒ¦įƒ¬įƒ”įƒ įƒ",
+ "mwe-timedtext-textcat-ktv": "įƒ™įƒįƒ įƒįƒįƒ™įƒ”",
+ "mwe-timedtext-textcat-tik": "įƒ¢įƒ”įƒ„įƒ”įƒ¢įƒ£įƒ įƒ˜ įƒ‘įƒįƒ įƒįƒ—įƒ”įƒ‘įƒ˜",
+ "mwe-timedtext-textcat-ar": "įƒįƒ„įƒ¢įƒ˜įƒ£įƒ įƒ˜ įƒ įƒ”įƒ’įƒ˜įƒįƒœįƒ”įƒ‘įƒ˜",
+ "mwe-timedtext-textcat-nb": "įƒįƒœįƒįƒ¢įƒįƒŖįƒ˜įƒ",
+ "mwe-timedtext-textcat-meta": "įƒ”įƒ˜įƒœįƒ„įƒ įƒįƒœįƒ˜įƒ–įƒ˜įƒ įƒ”įƒ‘įƒ£įƒšįƒ˜ įƒ›įƒ”įƒ¢įƒįƒ›įƒįƒœįƒįƒŖįƒ”įƒ›įƒ”įƒ‘įƒ˜",
+ "mwe-timedtext-textcat-trx": "įƒ”įƒ¢įƒ”įƒœįƒįƒ’įƒ įƒįƒ›įƒ",
+ "mwe-timedtext-textcat-lrc": "įƒ”įƒ˜įƒ›įƒ¦įƒ”įƒ įƒ˜įƒ” įƒ¢įƒ”įƒ„įƒ”įƒ¢įƒ”įƒ‘įƒ˜",
+ "mwe-timedtext-textcat-lin": "įƒšįƒ˜įƒœįƒ’įƒ•įƒ˜įƒ”įƒ¢įƒ£įƒ įƒ˜ įƒ“įƒįƒœįƒįƒ›įƒįƒ¢įƒ˜",
+ "mwe-timedtext-textcat-cue": "įƒœįƒ˜įƒØįƒœįƒ£įƒšįƒ˜ įƒ¬įƒ”įƒ įƒ¢įƒ˜įƒšįƒ”įƒ‘įƒ˜",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 įƒ”įƒ£įƒ‘įƒ¢įƒ˜įƒ¢įƒ įƒ”įƒ‘įƒ˜ įƒ™įƒšįƒ˜įƒžįƒ˜įƒ”įƒįƒ—įƒ•įƒ˜įƒ”: $2",
+ "mwe-timedtext-upload-timed-text": "įƒ”įƒ£įƒ‘įƒ¢įƒ˜įƒ¢įƒ įƒ”įƒ‘įƒ˜įƒ” įƒ“įƒįƒ›įƒįƒ¢įƒ”įƒ‘įƒ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ko.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ko.json
new file mode 100644
index 00000000..9b4faaf5
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ko.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "ģ•„ė¼"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ė’¤ė”œ",
+ "mwe-timedtext-layout-off": "ģžė§‰ ģˆØźø°źø°",
+ "mwe-timedtext-loading-text": "ķ…ģŠ¤ķŠø ė¶ˆėŸ¬ģ˜¤ėŠ” ģ¤‘ ...",
+ "mwe-timedtext-textcat-cc": "ģ„¤ėŖ…",
+ "mwe-timedtext-textcat-sub": "ģžė§‰",
+ "mwe-timedtext-textcat-tad": "ģ†Œė¦¬ ģ„¤ėŖ…",
+ "mwe-timedtext-textcat-ktv": "ź°€ė¼ģ˜¤ģ¼€",
+ "mwe-timedtext-textcat-tik": "ķ‘œģ‹œźø° ė¬øģž",
+ "mwe-timedtext-textcat-ar": "ķ™œģ„± ģ˜ģ—­",
+ "mwe-timedtext-textcat-nb": "ģ£¼ģ„",
+ "mwe-timedtext-textcat-meta": "ģ‹œź°„ ė©”ķƒ€ė°ģ“ķ„°",
+ "mwe-timedtext-textcat-trx": "ė³µģ‚¬",
+ "mwe-timedtext-textcat-lrc": "ź°€ģ‚¬",
+ "mwe-timedtext-textcat-lin": "ģ–øģ–“ ė§ˆķ¬ģ—…",
+ "mwe-timedtext-textcat-cue": "ķ ķ¬ģøķŠø",
+ "mwe-timedtext-no-subs": "ģ‚¬ģš©ķ•  ģˆ˜ ģžˆėŠ” ķ…ģŠ¤ķŠø ķŠøėž™ģ“ ģ—†ģŠµė‹ˆė‹¤",
+ "mwe-timedtext-language-subtitles-for-clip": "ķ“ė¦½ģ— ėŒ€ķ•œ $1 ģžė§‰: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "ķ“ė¦½ģ— ėŒ€ķ•œ $1 ģžė§‰ģ„ ģ°¾ģ„ ģˆ˜ ģ—†ģŠµė‹ˆė‹¤: $2",
+ "mwe-timedtext-upload-timed-text": "ģžė§‰ ģ¶”ź°€"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ksh.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ksh.json
new file mode 100644
index 00000000..13036810
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ksh.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Purodha"
+ ]
+ },
+ "mwe-timedtext-language-no-subtitles-for-clip": "Mer han kei $1 Ongertittelle jefonge fƶr dat Shtƶck: $2"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lb.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lb.json
new file mode 100644
index 00000000..ad8d40e7
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lb.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Robby",
+ "Soued031"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ZrƩck",
+ "mwe-timedtext-layout-off": "Ƌnnertitele verstoppen",
+ "mwe-timedtext-loading-text": "Text gƫtt gelueden ...",
+ "mwe-timedtext-textcat-sub": "Ƌnnertitelen",
+ "mwe-timedtext-textcat-tad": "Audio-Beschreiwung",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Text-Ticker",
+ "mwe-timedtext-textcat-ar": "Aktiv Regiounen",
+ "mwe-timedtext-textcat-nb": "Notiz",
+ "mwe-timedtext-textcat-lrc": "Liddertext",
+ "mwe-timedtext-textcat-lin": "Linguistesch MarkƩierung",
+ "mwe-timedtext-textcat-cue": "Referenz-Punkten",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 Ƌnnertitele fir de Clip: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Keng $1 Ƌnnertitele goufe fonnt fir de Clip: $2",
+ "mwe-timedtext-upload-timed-text": "Ƌnnertitelen derbƤisetzen"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lt.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lt.json
new file mode 100644
index 00000000..af653701
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lt.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hugo.arg"
+ ]
+ },
+ "mwe-timedtext-no-subs": "Nėra tekstinių takelių",
+ "mwe-timedtext-upload-timed-text": "Pridėti subtitrus"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lv.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lv.json
new file mode 100644
index 00000000..55f99f5a
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lv.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Papuass"
+ ]
+ },
+ "mwe-timedtext-textcat-nb": "Anotācija",
+ "mwe-timedtext-textcat-trx": "Transkripts"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/mk.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/mk.json
new file mode 100644
index 00000000..1dd29c01
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/mk.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bjankuloski06"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ŠŠ°Š·Š°Š“",
+ "mwe-timedtext-layout-off": "Š”ŠŗрŠøј тŠøтŠ»Š¾Š²Šø",
+ "mwe-timedtext-loading-text": "Š“Š¾ Š²Ń‡ŠøтуŠ²Š°Š¼ тŠµŠŗстŠ¾Ń‚...",
+ "mwe-timedtext-textcat-cc": "ŠžŠæŠøс",
+ "mwe-timedtext-textcat-sub": "Š¢ŠøтŠ»Š¾Š²Šø",
+ "mwe-timedtext-textcat-tad": "ŠŃƒŠ“ŠøŠ¾-Š¾ŠæŠøс",
+ "mwe-timedtext-textcat-ktv": "ŠšŠ°Ń€Š°Š¾ŠŗŠµ",
+ "mwe-timedtext-textcat-tik": "Š¢ŠµŠŗст-ŠŗŠ°Ń€Ń‚ŠøчŠŗŠø",
+ "mwe-timedtext-textcat-ar": "ŠŠŗтŠøŠ²Š½Šø рŠµŠ³ŠøŠ¾Š½Šø",
+ "mwe-timedtext-textcat-nb": "ŠŸŃ€ŠøŠ±ŠµŠ»ŠµŃˆŠŗŠ°",
+ "mwe-timedtext-textcat-meta": "Š”ŠøŠ½Ń…Ń€Š¾Š½ŠøŠ·ŠøрŠ°Š½Šø Š¼ŠµŃ‚Š°ŠæŠ¾Š“Š°Ń‚Š¾Ń†Šø",
+ "mwe-timedtext-textcat-trx": "Š”тŠµŠ½Š¾Š³Ń€Š°Š¼",
+ "mwe-timedtext-textcat-lrc": "Š¢ŠµŠŗст Š½Š° ŠæŠµŃŠ½Š°Ń‚Š°",
+ "mwe-timedtext-textcat-lin": "Š›ŠøŠ½Š³Š²ŠøстŠøчŠŗŠ¾ Š¾Š·Š½Š°Ń‡ŃƒŠ²Š°ŃšŠµ",
+ "mwe-timedtext-textcat-cue": "ŠœŠ¾Š¼ŠµŠ½Ń‚Š½Šø тŠ¾Ń‡ŠŗŠø",
+ "mwe-timedtext-no-subs": "ŠŠµŠ¼Š° тŠøтŠ»Š¾Š²Šø Š½Š° рŠ°ŃŠæŠ¾Š»Š°Š³Š°ŃšŠµ",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 ā€” тŠøтŠ»Š¾Š²Šø Š·Š° сŠ½ŠøŠ¼ŠŗŠ°Ń‚Š°: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "ŠŠµŠ¼Š° ŠæрŠ¾Š½Š°Ń˜Š“ŠµŠ½Š¾ тŠøтŠ»Š¾Š²Šø Š½Š° $1 Š·Š° сŠ½ŠøŠ¼ŠŗŠ°Ń‚Š°: $2",
+ "mwe-timedtext-upload-timed-text": "Š”тŠ°Š²Šø тŠøтŠ»Š¾Š²Šø"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ml.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ml.json
new file mode 100644
index 00000000..a8d34824
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ml.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Praveenp"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ą“Ŗąµą“±ą“•ąµ‹ą“Ÿąµą“Ÿąµ",
+ "mwe-timedtext-layout-off": "ą“øą“‚ą“­ą“¾ą“·ą“£ą“°ąµ‡ą“– ą“®ą“±ą“Æąµą“•ąµą“•ąµą“•",
+ "mwe-timedtext-loading-text": "ą“Žą““ąµą“¤ąµą“¤ąµ ą“¶ąµ‡ą“–ą“°ą“æą“•ąµą“•ąµą“Øąµą“Øąµ...",
+ "mwe-timedtext-textcat-cc": "ą“¤ą“²ą“µą“¾ą“•ąµą“Æą“‚",
+ "mwe-timedtext-textcat-sub": "ą“øą“‚ą“­ą“¾ą“·ą“£ą“°ąµ‡ą“–ą“•ąµ¾",
+ "mwe-timedtext-textcat-tad": "ą“¶ą“¬ąµą“¦ą“¤ąµą“¤ą“æą“Øąµą“±ąµ† ą“µą“æą“µą“°ą“£ą“‚",
+ "mwe-timedtext-textcat-ktv": "ą“•ą“°ąµ‹ą“•ąµą“•ąµ‡",
+ "mwe-timedtext-textcat-tik": "ą“®ą“æą“Øąµą“Øą“æą“µą“°ąµą“Øąµą“Ø ą“Žą““ąµą“¤ąµą“¤ąµ",
+ "mwe-timedtext-textcat-ar": "ą“øą“œąµ€ą“µą“®ą“¾ą“Æ ą“Ŗąµą“°ą“¦ąµ‡ą“¶ą“™ąµą“™ąµ¾",
+ "mwe-timedtext-textcat-nb": "ą“Ÿą“æą“Ŗąµą“Ŗą“£ą“æ",
+ "mwe-timedtext-textcat-meta": "ą“øą“®ą“Æą“®ą“Øąµą“øą“°ą“æą“šąµą“šąµą“³ąµą“³ ą“®ąµ†ą“±ąµą“±ą“¾ą“”ąµ‡ą“±ąµą“±",
+ "mwe-timedtext-textcat-trx": "ą“Ŗą“•ąµ¼ą“¤ąµą“¤ą“æą“Æąµ†ą““ąµą“¤ąµą“¤ąµ",
+ "mwe-timedtext-textcat-lrc": "ą“µą“°ą“æą“•ąµ¾",
+ "mwe-timedtext-textcat-lin": "ą“­ą“¾ą“·ą“¾ą“øą“‚ą“¬ą“Øąµą“§ą“æą“Æą“¾ą“Æ ą“…ą“Ÿą“Æą“¾ą“³ą“­ą“¾ą“·",
+ "mwe-timedtext-textcat-cue": "ą“øąµ‚ą“šą“• ą“¬ą“æą“Øąµą“¦ąµą“•ąµą“•ąµ¾",
+ "mwe-timedtext-no-subs": "ą“Žą““ąµą“¤ąµą“¤ąµą“•ą“³ąµą“Ÿąµ† ą“µą“°ą“æ ą“²ą“­ąµą“Æą“®ą“²ąµą“²",
+ "mwe-timedtext-language-subtitles-for-clip": "ą“ˆ ą“®ąµ€ą“”ą“æą“Æą“¶ą“•ą“²ą“¤ąµą“¤ą“æą“Øąµ $1 ą“­ą“¾ą“·ą“Æą“æą“²ąµą“³ąµą“³ ą“øą“‚ą“­ą“¾ą“·ą“£ą“°ąµ‡ą“–: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "ą“ˆ ą“®ąµ€ą“”ą“æą“Æą“¶ą“•ą“²ą“¤ąµą“¤ą“æą“Øąµ $1 ą“­ą“¾ą“·ą“Æą“æą“²ąµą“³ąµą“³ ą“øą“‚ą“­ą“¾ą“·ą“£ą“°ąµ‡ą“–ą“ÆąµŠą“Øąµą“Øąµą“‚ ą“•ą“£ąµą“Ÿąµ†ą“¤ąµą“¤ą“¾ą“Øą“¾ą“Æą“æą“²ąµą“²: $2",
+ "mwe-timedtext-upload-timed-text": "ą“øą“‚ą“­ą“¾ą“·ą“£ą“°ąµ‡ą“– ą“•ąµ‚ą“Ÿąµą“Ÿą“æą“šąµą“šąµ‡ąµ¼ą“•ąµą“•ąµą“•"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ms.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ms.json
new file mode 100644
index 00000000..712fff27
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ms.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Anakmalaysia"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Kembali",
+ "mwe-timedtext-layout-off": "Sorokkan sari kata",
+ "mwe-timedtext-loading-text": "Teks sedang dimuatkan...",
+ "mwe-timedtext-textcat-cc": "Kapsyen",
+ "mwe-timedtext-textcat-sub": "Sari kata",
+ "mwe-timedtext-textcat-tad": "Keterangan audio",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Teks ticker",
+ "mwe-timedtext-textcat-ar": "Kawasan aktif",
+ "mwe-timedtext-textcat-nb": "Anotasi",
+ "mwe-timedtext-textcat-meta": "Metadata bermasa",
+ "mwe-timedtext-textcat-trx": "Transkrip",
+ "mwe-timedtext-textcat-lrc": "Lirik",
+ "mwe-timedtext-textcat-lin": "Penanda linguistik",
+ "mwe-timedtext-textcat-cue": "Titik kiu",
+ "mwe-timedtext-no-subs": "Tidak terdapat runut teks",
+ "mwe-timedtext-language-subtitles-for-clip": "Sari kata $1 untuk klip: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Tidak terdapat sari kata $1 untuk klip: $2",
+ "mwe-timedtext-upload-timed-text": "Letak sari kata"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nb.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nb.json
new file mode 100644
index 00000000..a273d46b
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nb.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Danmichaelo",
+ "Nghtwlkr"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Tilbake",
+ "mwe-timedtext-layout-off": "Gjem undertekster",
+ "mwe-timedtext-loading-text": "Laster tekst ...",
+ "mwe-timedtext-textcat-cc": "Undertektster",
+ "mwe-timedtext-textcat-sub": "Undertekster",
+ "mwe-timedtext-textcat-tad": "Lydbeskrivelse",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Tekst-ticker",
+ "mwe-timedtext-textcat-ar": "Aktive regioner",
+ "mwe-timedtext-textcat-nb": "Merknad",
+ "mwe-timedtext-textcat-meta": "Tidsbestemt metadata",
+ "mwe-timedtext-textcat-trx": "Transkripsjon",
+ "mwe-timedtext-textcat-lrc": "Tekster",
+ "mwe-timedtext-no-subs": "Ingen tekstspor finnes",
+ "mwe-timedtext-language-subtitles-for-clip": "Undertekster pƄ $1 for klippet: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Ingen undertekster pƄ $1 ble funnet for klippet: $2",
+ "mwe-timedtext-upload-timed-text": "Legg til undertekster"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nl.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nl.json
new file mode 100644
index 00000000..7b225402
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nl.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Siebrand"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Terug",
+ "mwe-timedtext-layout-off": "Ondertitels verbergen",
+ "mwe-timedtext-loading-text": "Bezig met het laden van de tekst...",
+ "mwe-timedtext-textcat-cc": "Ondertitels",
+ "mwe-timedtext-textcat-sub": "Ondertitels",
+ "mwe-timedtext-textcat-tad": "Audiobeschrijving",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Informatiebalk",
+ "mwe-timedtext-textcat-ar": "Actieve gebieden",
+ "mwe-timedtext-textcat-nb": "Annotatie",
+ "mwe-timedtext-textcat-meta": "Tijdgebaseerde metadata",
+ "mwe-timedtext-textcat-trx": "Transcriptie",
+ "mwe-timedtext-textcat-lrc": "Songteksten",
+ "mwe-timedtext-textcat-lin": "Taalkundige markup",
+ "mwe-timedtext-textcat-cue": "Richtpunten",
+ "mwe-timedtext-no-subs": "Er zijn geen teksttracks beschikbaar",
+ "mwe-timedtext-language-subtitles-for-clip": "Ondertitels in het $1 voor clip: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Er zijn geen ondertitels in de taal $1 gevonden voor clip: $2",
+ "mwe-timedtext-upload-timed-text": "Ondertitels toevoegen"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nn.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nn.json
new file mode 100644
index 00000000..696c63d4
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nn.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Njardarlogar"
+ ]
+ },
+ "mwe-timedtext-layout-off": "GĆøym undertekstar",
+ "mwe-timedtext-textcat-sub": "Undertekstar",
+ "mwe-timedtext-textcat-lrc": "Tekstar",
+ "mwe-timedtext-no-subs": "Ingen tekstspor er tilgjengelege",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 undertekstar for klippet: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Ingen undertekster pƄ $1 vart funne for klippet: $2",
+ "mwe-timedtext-upload-timed-text": "Legg til undertekstar"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pdc.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pdc.json
new file mode 100644
index 00000000..56c9fe84
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pdc.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Xqt"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Zerrick"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pfl.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pfl.json
new file mode 100644
index 00000000..2e41e363
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pfl.json
@@ -0,0 +1,7 @@
+{
+ "@metadata": {
+ "authors": [
+ "Manuae"
+ ]
+ }
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pl.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pl.json
new file mode 100644
index 00000000..544812d0
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pl.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "BeginaFelicysym",
+ "Leinad",
+ "Shadown",
+ "Sp5uhe"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Wstecz",
+ "mwe-timedtext-layout-off": "Ukryj napisy",
+ "mwe-timedtext-loading-text": "Ładowanie tekstu...",
+ "mwe-timedtext-textcat-cc": "Podpisy",
+ "mwe-timedtext-textcat-sub": "Napisy do filmu",
+ "mwe-timedtext-textcat-tad": "Opis ścieżki dÅŗwiękowej",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Notatka",
+ "mwe-timedtext-textcat-ar": "Aktywne regiony",
+ "mwe-timedtext-textcat-nb": "Adnotacja",
+ "mwe-timedtext-textcat-meta": "Metadane ze znacznikami czasu",
+ "mwe-timedtext-textcat-trx": "Rozpisz",
+ "mwe-timedtext-textcat-lrc": "Teksty piosenek",
+ "mwe-timedtext-textcat-lin": "Znaczniki językowe",
+ "mwe-timedtext-textcat-cue": "Punkty kontrolne",
+ "mwe-timedtext-no-subs": "Nie ma dostępnych ścieżek tekstowych",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 napisy do filmu: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Nie odnaleziono $1 napisĆ³w do filmu: $2",
+ "mwe-timedtext-upload-timed-text": "Dodaj napisy"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pms.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pms.json
new file mode 100644
index 00000000..7ffca36c
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pms.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "BorichĆØt",
+ "DragonĆ²t"
+ ]
+ },
+ "mwe-timedtext-back-btn": "AndrƩ",
+ "mwe-timedtext-layout-off": "StƫrmƩ ij sot-tƬtoj",
+ "mwe-timedtext-loading-text": "Cariament dƫl test...",
+ "mwe-timedtext-textcat-cc": "Descrission",
+ "mwe-timedtext-textcat-sub": "Sot-tƬtoj",
+ "mwe-timedtext-textcat-tad": "Descrission Ć udio",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Test Ć«d la telescrivent",
+ "mwe-timedtext-textcat-ar": "Region ative",
+ "mwe-timedtext-textcat-nb": "NĆ²ta",
+ "mwe-timedtext-textcat-meta": "Metadat sincronisĆ ",
+ "mwe-timedtext-textcat-trx": "Trascrission",
+ "mwe-timedtext-textcat-lrc": "LƬriche",
+ "mwe-timedtext-textcat-lin": "Marcador lenghƬstich",
+ "mwe-timedtext-textcat-cue": "Pont d'arferiment",
+ "mwe-timedtext-no-subs": "Gnun-e marche ƫd test disponƬbij",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 sot-tƬtoj pĆ«r Ć«l tĆ²ch: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "A l'Ć© trovasse gnun sot-tƬtoj $1 per Ć«l tĆ²ch: $2",
+ "mwe-timedtext-upload-timed-text": "GiontƩ dij sot-tƬtoj"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ps.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ps.json
new file mode 100644
index 00000000..fd556365
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ps.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ahmed-Najib-Biabani-Ibrahimkhel"
+ ]
+ },
+ "mwe-timedtext-textcat-ktv": "Ś©Ų§Ų±Ų§Ų§ŁˆŚ©Ł‡"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pt-br.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pt-br.json
new file mode 100644
index 00000000..008c55ba
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pt-br.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dianakc",
+ "Giro720",
+ "Luckas",
+ "Luckas Blade",
+ "555"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Voltar",
+ "mwe-timedtext-layout-off": "Ocultar legendas",
+ "mwe-timedtext-loading-text": "Carregando o texto ...",
+ "mwe-timedtext-textcat-cc": "TĆ­tulos",
+ "mwe-timedtext-textcat-sub": "Legendas",
+ "mwe-timedtext-textcat-tad": "DescriĆ§Ć£o do Ć”udio",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Texto deslizante",
+ "mwe-timedtext-textcat-ar": "RegiƵes ativas",
+ "mwe-timedtext-textcat-nb": "AnotaĆ§Ć£o",
+ "mwe-timedtext-textcat-meta": "Metadados sincronizados",
+ "mwe-timedtext-textcat-trx": "TranscriĆ§Ć£o",
+ "mwe-timedtext-textcat-lrc": "Letra",
+ "mwe-timedtext-textcat-lin": "MarcaĆ§Ć£o linguĆ­stica",
+ "mwe-timedtext-textcat-cue": "Pontos de entrada",
+ "mwe-timedtext-no-subs": "NĆ£o hĆ” nenhum texto disponĆ­vel",
+ "mwe-timedtext-language-subtitles-for-clip": "Legendas em $1 para o clipe: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "NĆ£o foram encontradas legendas em $1 para o clipe: $2",
+ "mwe-timedtext-upload-timed-text": "Adicionar legendas"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pt.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pt.json
new file mode 100644
index 00000000..4917da79
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pt.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Giro720",
+ "Hamilton Abreu",
+ "Luckas",
+ "SandroHc",
+ "Vitorvicentevalente"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Voltar",
+ "mwe-timedtext-layout-off": "Ocultar legendas",
+ "mwe-timedtext-loading-text": "A carregar o texto ...",
+ "mwe-timedtext-textcat-cc": "TĆ­tulos",
+ "mwe-timedtext-textcat-sub": "Legendas",
+ "mwe-timedtext-textcat-tad": "DescriĆ§Ć£o de Ć”udio",
+ "mwe-timedtext-textcat-ktv": "Caraoque",
+ "mwe-timedtext-textcat-tik": "CotaƧƵes",
+ "mwe-timedtext-textcat-ar": "RegiƵes activas",
+ "mwe-timedtext-textcat-nb": "AnotaĆ§Ć£o",
+ "mwe-timedtext-textcat-meta": "Metadados de sincronizaĆ§Ć£o",
+ "mwe-timedtext-textcat-trx": "TranscriĆ§Ć£o",
+ "mwe-timedtext-textcat-lrc": "Letra",
+ "mwe-timedtext-textcat-lin": "MarcaĆ§Ć£o linguĆ­stica",
+ "mwe-timedtext-textcat-cue": "Pontos de entrada",
+ "mwe-timedtext-no-subs": "NĆ£o hĆ” nenhuma faixa de texto disponĆ­vel",
+ "mwe-timedtext-language-subtitles-for-clip": "Legendas em $1 para o clipe: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "NĆ£o foram encontradas legendas em $1 para o clipe: $2",
+ "mwe-timedtext-upload-timed-text": "Adicionar legendas"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/qqq.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/qqq.json
new file mode 100644
index 00000000..4714d5b1
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/qqq.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "EugeneZelenko",
+ "Shirayuki",
+ "Siebrand",
+ "Umherirrender"
+ ]
+ },
+ "mwe-timedtext-back-btn": "{{Identical|Back}}",
+ "mwe-timedtext-key-language": "{{optional}}\nParameters:\n* $1 - language key. e.g. \"en\"\n* $2 - language name",
+ "mwe-timedtext-textcat-cc": "{{Identical|Caption}}",
+ "mwe-timedtext-textcat-sub": "{{Identical|Subtitle}}",
+ "mwe-timedtext-textcat-ktv": "See [[w:Karaoke]].",
+ "mwe-timedtext-textcat-nb": "{{Identical|Annotation}}",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 is language name for subtitles (e.g. \"English\"), $2 is title of file that timed text is for.\nShown as the page title on a TimedText namespace page when the page exists. See also mwe-timedtext-language-no-subtitles-for-clip.",
+ "mwe-timedtext-language-no-subtitles-for-clip": "$1 is language name, $2 is title of file that timed text is for.\nShown as the page title on a TimedText namespace page when the page does not exist. See also mwe-timedtext-language-subtitles-for-clip",
+ "mwe-timedtext-upload-timed-text": "After clicking the 'CC' button on the video player, the button on the resulting menu to add subtitles to a video file."
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ro.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ro.json
new file mode 100644
index 00000000..77892ab4
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ro.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Minisarm",
+ "Stelistcristi"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Ǝnapoi",
+ "mwe-timedtext-layout-off": "Ascunde subtitrările",
+ "mwe-timedtext-loading-text": "Se Ʈncarcă textul...",
+ "mwe-timedtext-textcat-cc": "Legende",
+ "mwe-timedtext-textcat-sub": "Subtitrări",
+ "mwe-timedtext-textcat-tad": "Descriere audio",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Text mai gros",
+ "mwe-timedtext-textcat-ar": "Regiuni active",
+ "mwe-timedtext-textcat-nb": "Adnotare",
+ "mwe-timedtext-textcat-meta": "Metadate sincronizate",
+ "mwe-timedtext-textcat-trx": "Transcripție",
+ "mwe-timedtext-textcat-lrc": "Versuri",
+ "mwe-timedtext-textcat-lin": "Etichete lingvistice",
+ "mwe-timedtext-textcat-cue": "Puncte de tac",
+ "mwe-timedtext-no-subs": "Niciun text de piesă disponibil",
+ "mwe-timedtext-language-subtitles-for-clip": "Subtitrare Ʈn limba $1 pentru clip: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Nu s-a găsit nicio subtitrare Ʈn limba $1 pentru clip: $2",
+ "mwe-timedtext-upload-timed-text": "Adaugă subtitrări"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/roa-tara.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/roa-tara.json
new file mode 100644
index 00000000..a26678a4
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/roa-tara.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Joetaras"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Rrete",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-nb": "Annotazione",
+ "mwe-timedtext-textcat-meta": "Metadate temborizzate",
+ "mwe-timedtext-textcat-trx": "Trascrive",
+ "mwe-timedtext-textcat-lrc": "Teste",
+ "mwe-timedtext-upload-timed-text": "Aggiunge le sottotitole"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ru.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ru.json
new file mode 100644
index 00000000..8b3ff81c
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ru.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "MaxSem",
+ "Okras",
+ "ŠŠ»ŠµŠŗсŠ°Š½Š“р Š”ŠøŠ³Š°Ń‡Ń‘Š²",
+ "Kaganer"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ŠŠ°Š·Š°Š“",
+ "mwe-timedtext-layout-off": "Š”Šŗрыть суŠ±Ń‚Šøтры",
+ "mwe-timedtext-loading-text": "Š—Š°Š³Ń€ŃƒŠ·ŠŗŠ° тŠµŠŗстŠ°ā€¦",
+ "mwe-timedtext-textcat-cc": "Š”уŠ±Ń‚Šøтры-Š¾ŠæŠøсŠ°Š½Šøя",
+ "mwe-timedtext-textcat-sub": "Š”уŠ±Ń‚Šøтры",
+ "mwe-timedtext-textcat-tad": "ŠžŠæŠøсŠ°Š½ŠøŠµ Š°ŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š»Š°",
+ "mwe-timedtext-textcat-ktv": "ŠšŠ°Ń€Š°Š¾ŠŗŠµ",
+ "mwe-timedtext-textcat-tik": "Š¢ŠµŠŗстŠ¾Š²Ń‹Šµ ŠŗŠ°Ń€Ń‚Š¾Ń‡ŠŗŠø",
+ "mwe-timedtext-textcat-ar": "ŠŠŗтŠøŠ²Š½Ń‹Šµ Š¾Š±Š»Š°ŃŃ‚Šø",
+ "mwe-timedtext-textcat-nb": "ŠŠ½Š½Š¾Ń‚Š°Ń†Šøя",
+ "mwe-timedtext-textcat-meta": "Š”ŠøŠ½Ń…Ń€Š¾Š½ŠøŠ·ŠøрŠ¾Š²Š°Š½Š½Ń‹Šµ Š¼ŠµŃ‚Š°Š“Š°Š½Š½Ń‹Šµ",
+ "mwe-timedtext-textcat-trx": "Š”тŠµŠ½Š¾Š³Ń€Š°Š¼Š¼Š°",
+ "mwe-timedtext-textcat-lrc": "Š”Š»Š¾Š²Š° ŠæŠµŃŠ½Šø",
+ "mwe-timedtext-textcat-lin": "Š›ŠøŠ½Š³Š²ŠøстŠøчŠµŃŠŗŠ°Ń рŠ°Š·Š¼ŠµŃ‚ŠŗŠ°",
+ "mwe-timedtext-textcat-cue": "Š—Š½Š°ŠŗŠ¾Š²Ń‹Šµ тŠ¾Ń‡ŠŗŠø",
+ "mwe-timedtext-no-subs": "ŠŠµŃ‚ тŠµŠŗстŠ¾Š²Ń‹Ń… Š“Š¾Ń€Š¾Š¶ŠµŠŗ",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 ā€” суŠ±Ń‚Šøтры Š“Š»Ń ŠŗŠ»ŠøŠæŠ°: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "ŠŠµ Š½Š°Š¹Š“ŠµŠ½Š¾ суŠ±Ń‚ŠøтрŠ¾Š² Š½Š° $1 Š“Š»Ń ŠŗŠ»ŠøŠæŠ°: $2",
+ "mwe-timedtext-upload-timed-text": "Š”Š¾Š±Š°Š²Šøть суŠ±Ń‚Šøтры"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/rue.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/rue.json
new file mode 100644
index 00000000..1cc92d6f
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/rue.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gazeb"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ŠŠ°Š·Š°Š“"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/si.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/si.json
new file mode 100644
index 00000000..8af0327f
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/si.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ą¶†ą¶“ą·ƒą·”",
+ "mwe-timedtext-layout-off": "ą¶‹ą¶“ą·ą·“ą¶»ą·Šą·‚ ą·ƒą¶Ÿą·€ą¶±ą·Šą¶±",
+ "mwe-timedtext-loading-text": "ą¶“ą·™ą·… ą¶“ą·–ą¶»ą¶«ą¶ŗ ą·€ą·™ą¶øą·’ą¶±ą·Š ...",
+ "mwe-timedtext-textcat-cc": "ą¶‹ą¶“ą¶±ą·Šā€ą¶ŗą·ą·ƒ",
+ "mwe-timedtext-textcat-sub": "ą¶‹ą¶“ą·ą·“ą¶»ą·Šą·‚",
+ "mwe-timedtext-textcat-tad": "ą·ą·Šā€ą¶»ą·€ą·Šā€ą¶ŗ ą·€ą·’ą·ƒą·Šą¶­ą¶»ą¶ŗ",
+ "mwe-timedtext-textcat-ktv": "ą¶šą·ą¶»ą·ą¶šą·š",
+ "mwe-timedtext-textcat-tik": "ą¶”ą¶»ą¶½ą·ą·ƒą·” ą¶“ą·™ą·…",
+ "mwe-timedtext-textcat-ar": "ą·ƒą¶šą·Šā€ą¶»ą·’ą¶ŗ ą¶“ą·Šā€ą¶»ą¶Æą·šą·",
+ "mwe-timedtext-textcat-nb": "ą¶§ą·“ą¶šą·ą·€",
+ "mwe-timedtext-textcat-meta": "ą¶šą·ą¶½ą·’ą¶­ ą¶“ą·ą¶»ą¶Æą¶­ą·Šą¶­",
+ "mwe-timedtext-textcat-trx": "ą¶“ą·Šā€ą¶»ą¶­ą·’ą¶½ą·šą¶›ą¶±ą¶ŗ",
+ "mwe-timedtext-textcat-lrc": "ą¶œą·“ą¶“ą¶Æą·€ą·ą¶½ą·Š",
+ "mwe-timedtext-textcat-lin": "ą¶·ą·ą·‚ą·ą¶øą¶ŗ ą¶…ą¶°ą·’ą¶šą¶ŗ",
+ "mwe-timedtext-textcat-cue": "ą¶‰ą¶‚ą¶œą·’ą¶­ ą¶œą¶­ą·’ą¶œą·”ą¶«",
+ "mwe-timedtext-no-subs": "ą¶øą·“ą·…ą¶Ÿ ą¶“ą¶® ą¶½ą¶¶ą·ą¶œą¶­ ą¶±ą·œą·„ą·ą¶š",
+ "mwe-timedtext-language-subtitles-for-clip": "ą¶šą·Šą¶½ą·’ą¶“ą¶ŗ ą·ƒą¶³ą·„ą· $1 ą¶‹ą¶“ą·ƒą·’ą¶»ą·”ą·ƒ: $2",
+ "mwe-timedtext-upload-timed-text": "ą¶‹ą¶“ą·ą·“ą¶»ą·Šą·‚ ą¶‘ą¶šą·Š ą¶šą¶»ą¶±ą·Šą¶±"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sl.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sl.json
new file mode 100644
index 00000000..8df43558
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sl.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dbc334"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Nazaj"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/so.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/so.json
new file mode 100644
index 00000000..6a979a8b
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/so.json
@@ -0,0 +1,7 @@
+{
+ "@metadata": {
+ "authors": [
+ "Abshirdheere"
+ ]
+ }
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sr-ec.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sr-ec.json
new file mode 100644
index 00000000..f3dfbbc6
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sr-ec.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Rancher",
+ "ŠœŠøхŠ°Ń˜Š»Š¾ ŠŠ½Ń’ŠµŠ»ŠŗŠ¾Š²Šøћ"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ŠŠ°Š·Š°Š“",
+ "mwe-timedtext-layout-off": "Š”Š°ŠŗрŠøј сŠ°Š±Ń‚Š°Ń˜Ń‚Š»Š¾Š²Šµ",
+ "mwe-timedtext-loading-text": "Š£Ń‡ŠøтŠ°Š²Š° сŠµ тŠµŠŗст ...",
+ "mwe-timedtext-key-language": "$1, $2",
+ "mwe-timedtext-textcat-cc": "ŠžŠ·Š½Š°ŠŗŠµ",
+ "mwe-timedtext-textcat-sub": "ŠŸŠ¾Š“Š½Š°ŃŠ»Š¾Š²Šø",
+ "mwe-timedtext-textcat-trx": "Š¢Ń€Š°Š½ŃŠŗрŠøŠæт"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sr-el.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sr-el.json
new file mode 100644
index 00000000..100a6fc3
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sr-el.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Rancher"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Nazad",
+ "mwe-timedtext-layout-off": "Sakrij sabtajtlove",
+ "mwe-timedtext-loading-text": "Učitava se tekst ...",
+ "mwe-timedtext-key-language": "$1, $2",
+ "mwe-timedtext-textcat-cc": "Oznake",
+ "mwe-timedtext-textcat-sub": "Podnaslovi",
+ "mwe-timedtext-textcat-trx": "Transkript"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sv.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sv.json
new file mode 100644
index 00000000..a0b693cd
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sv.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ainali",
+ "Dafer45"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Tillbaka",
+ "mwe-timedtext-layout-off": "Dƶlj undertexter",
+ "mwe-timedtext-loading-text": "Laddar text ...",
+ "mwe-timedtext-textcat-cc": "Undertexter",
+ "mwe-timedtext-textcat-sub": "Undertexter",
+ "mwe-timedtext-textcat-tad": "Ljudbeskrivning",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Rullande text",
+ "mwe-timedtext-textcat-ar": "Aktiva regioner",
+ "mwe-timedtext-textcat-nb": "AnmƤrkning",
+ "mwe-timedtext-textcat-meta": "TidsbestƤmd metadata",
+ "mwe-timedtext-textcat-trx": "Transkription",
+ "mwe-timedtext-textcat-lrc": "Texter",
+ "mwe-timedtext-textcat-lin": "SprƄkliga markeringar",
+ "mwe-timedtext-textcat-cue": "Referenspunkter",
+ "mwe-timedtext-no-subs": "Inga textspƄr finns",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 undertexter fƶr klipp: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Inga $1 undertexter hittades fƶr klipp: $2",
+ "mwe-timedtext-upload-timed-text": "LƤgga till undertexter"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ta.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ta.json
new file mode 100644
index 00000000..6e9ef3e8
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ta.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "Karthi.dr",
+ "Shanmugamp7",
+ "ą®®ą®¤ą®©ą®¾ą®¹ą®°ą®©ąÆ"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ą®Ŗą®æą®©ąÆą®šąÆ†ą®²ąÆ",
+ "mwe-timedtext-layout-off": "ą®¤ąÆą®£ąÆˆą®¤ąÆą®¤ą®²ąÆˆą®ŖąÆą®ŖąÆą®•ąÆą®•ą®³ąÆˆ ą®®ą®±ąÆˆ",
+ "mwe-timedtext-loading-text": "ą®‰ą®°ąÆˆą®ÆąÆˆ ą®ą®±ąÆą®±ąÆą®•ą®æą®±ą®¤ąÆ ...",
+ "mwe-timedtext-textcat-sub": "ą®¤ąÆą®£ąÆˆą®¤ąÆą®¤ą®²ąÆˆą®ŖąÆą®ŖąÆą®•ąÆą®•ą®³ąÆ",
+ "mwe-timedtext-textcat-tad": "ą®’ą®²ą®æą®¤ ą®µą®æą®µą®°ą®£ą®®ąÆ",
+ "mwe-timedtext-textcat-lrc": "ą®Ŗą®¾ą®Ÿą®²ąÆ ą®µą®°ą®æą®•ą®³ąÆ",
+ "mwe-timedtext-upload-timed-text": "ą®¤ąÆą®£ąÆˆą®¤ąÆą®¤ą®²ąÆˆą®ŖąÆą®ŖąÆą®•ąÆą®•ą®³ąÆˆą®šąÆ ą®šąÆ‡ą®°ąÆ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/te.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/te.json
new file mode 100644
index 00000000..50688138
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/te.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Veeven"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ą°µą±†ą°Øą°•ą±ą°•ą°æ",
+ "mwe-timedtext-textcat-sub": "ą°‰ą°Ŗą°¶ą±€ą°°ą±ą°·ą°æą°•ą°²ą±"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/tl.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/tl.json
new file mode 100644
index 00000000..971a8f30
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/tl.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "AnakngAraw"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Bumalik",
+ "mwe-timedtext-layout-off": "Itago ang kabahaging mga pamagat",
+ "mwe-timedtext-loading-text": "Ikinakarga ang teksto ...",
+ "mwe-timedtext-key-language": "$1, $2",
+ "mwe-timedtext-textcat-cc": "Mga paliwanag",
+ "mwe-timedtext-textcat-sub": "Kabahaging mga pamagat",
+ "mwe-timedtext-textcat-tad": "Paglalarawan ng naririnig",
+ "mwe-timedtext-textcat-ktv": "Karaoke",
+ "mwe-timedtext-textcat-tik": "Teksto ng pampulso",
+ "mwe-timedtext-textcat-ar": "Masisiglang mga rehiyon",
+ "mwe-timedtext-textcat-nb": "Paliwanag",
+ "mwe-timedtext-textcat-meta": "Inorasang metadato",
+ "mwe-timedtext-textcat-trx": "Sipi ng salin",
+ "mwe-timedtext-textcat-lrc": "Titik ng awit",
+ "mwe-timedtext-textcat-lin": "Markang-pantaas ng lingguwistika",
+ "mwe-timedtext-textcat-cue": "Mga tuldok ng pahiwatig",
+ "mwe-timedtext-no-subs": "Walang makukuhang mga bakas ng teksto",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 kabahaging mga pamagat para sa putol na: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Walang natagpuang $1 kabahaging mga pamagat para sa putol na: $2",
+ "mwe-timedtext-upload-timed-text": "Magdagdag ng kabahaging mga pamagat"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/tr.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/tr.json
new file mode 100644
index 00000000..8b26730a
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/tr.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Emperyan"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Geri",
+ "mwe-timedtext-textcat-sub": "Alt yazılar",
+ "mwe-timedtext-no-subs": "ParƧa metni yok",
+ "mwe-timedtext-upload-timed-text": "Alt yazı ekle"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/uk.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/uk.json
new file mode 100644
index 00000000..916f0395
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/uk.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Base",
+ "Š¢ŠµŃŃ‚"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ŠŠ°Š·Š°Š“",
+ "mwe-timedtext-layout-off": "ŠŸŃ€ŠøхŠ¾Š²Š°Ń‚Šø суŠ±Ń‚ŠøтрŠø",
+ "mwe-timedtext-loading-text": "Š—Š°Š²Š°Š½Ń‚Š°Š¶ŠµŠ½Š½Ń тŠµŠŗстуā€¦",
+ "mwe-timedtext-textcat-cc": "Š”уŠ±Ń‚ŠøтрŠø-ŠæіŠ“ŠæŠøсŠø",
+ "mwe-timedtext-textcat-sub": "Š”уŠ±Ń‚ŠøтрŠø",
+ "mwe-timedtext-textcat-tad": "ŠŃƒŠ“іŠ¾-Š¾ŠæŠøс",
+ "mwe-timedtext-textcat-ktv": "ŠšŠ°Ń€Š°Š¾ŠŗŠµ",
+ "mwe-timedtext-textcat-tik": "Š¢ŠµŠŗстŠ¾Š²Ń– ŠŗŠ°Ń€Ń‚ŠŗŠø",
+ "mwe-timedtext-textcat-ar": "ŠŠŗтŠøŠ²Š½Ń– Š¾Š±Š»Š°ŃŃ‚Ń–",
+ "mwe-timedtext-textcat-nb": "ŠŠ½Š¾Ń‚Š°Ń†Ń–я",
+ "mwe-timedtext-textcat-meta": "Š”ŠøŠ½Ń…Ń€Š¾Š½Ń–Š·Š¾Š²Š°Š½Ń– Š¼ŠµŃ‚Š°Š“Š°Š½Ń–",
+ "mwe-timedtext-textcat-trx": "Š”тŠµŠ½Š¾Š³Ń€Š°Š¼Š°",
+ "mwe-timedtext-textcat-lrc": "Š”Š»Š¾Š²Š° ŠæісŠ½Ń–",
+ "mwe-timedtext-textcat-lin": "Š›Ń–Š½Š³Š²Ń–стŠøчŠ½Š° рŠ¾Š·Š¼Ń–Ń‚ŠŗŠ°",
+ "mwe-timedtext-textcat-cue": "Š—Š½Š°ŠŗŠ¾Š²Ń– тŠ¾Ń‡ŠŗŠø",
+ "mwe-timedtext-no-subs": "ŠŠµŠ¼Š°Ń” тŠµŠŗстŠ¾Š²Šøх Š“Š¾Ń€Ń–Š¶Š¾Šŗ",
+ "mwe-timedtext-language-subtitles-for-clip": "$1 ā€” суŠ±Ń‚ŠøтрŠø Š“Š»Ń ŠŗŠ»Ń–Šæу: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "ŠŠµ Š·Š½Š°Š¹Š“ŠµŠ½Š¾ суŠ±Ń‚ŠøтріŠ² $1 Š“Š»Ń ŠŗŠ»Ń–Šæу: $2",
+ "mwe-timedtext-upload-timed-text": "Š”Š¾Š“Š°Ń‚Šø суŠ±Ń‚ŠøтрŠø"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ur.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ur.json
new file mode 100644
index 00000000..baafae32
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ur.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ"
+ ]
+ },
+ "mwe-timedtext-back-btn": "ŁˆŲ§Ł¾Ų³",
+ "mwe-timedtext-textcat-sub": "Ų±ŁˆŁ…Ų§Ł†ŪŒŪ"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/vi.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/vi.json
new file mode 100644
index 00000000..5ee9bb9b
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/vi.json
@@ -0,0 +1,18 @@
+{
+ "@metadata": {
+ "authors": [
+ "Minh Nguyen",
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ"
+ ]
+ },
+ "mwe-timedtext-back-btn": "Quay lįŗ”i",
+ "mwe-timedtext-layout-off": "įŗØn phį»„ đį»",
+ "mwe-timedtext-loading-text": "Đang tįŗ£i văn bįŗ£nā€¦",
+ "mwe-timedtext-textcat-sub": "Phį»„ đį»",
+ "mwe-timedtext-textcat-tad": "Lį»i miĆŖu tįŗ£ Ć¢m thanh",
+ "mwe-timedtext-textcat-ktv": "KaraĆ“kĆŖ",
+ "mwe-timedtext-textcat-meta": "SiĆŖu dį»Æ liį»‡u đį»“ng bį»™",
+ "mwe-timedtext-textcat-lrc": "Lį»i hĆ”t",
+ "mwe-timedtext-textcat-lin": "ĐƔnh dįŗ„u ngĆ“n ngį»Æ hį»c",
+ "mwe-timedtext-upload-timed-text": "ThĆŖm phį»„ đį»"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/wa.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/wa.json
new file mode 100644
index 00000000..c8d2fdf6
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/wa.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Srtxg"
+ ]
+ },
+ "mwe-timedtext-layout-off": "CatchĆ® les dzo-tites",
+ "mwe-timedtext-loading-text": "Dji tchedje li tecse...",
+ "mwe-timedtext-textcat-cc": "Ledjindes",
+ "mwe-timedtext-textcat-sub": "Dizo-tites",
+ "mwe-timedtext-textcat-lrc": "Paroles",
+ "mwe-timedtext-textcat-lin": "Etiketes di lingaedje",
+ "mwe-timedtext-language-subtitles-for-clip": "Dizo-tites e $1 pol clip: $2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "Nou dzo-tite $1 di trovƩ pol clip: $2"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/yi.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/yi.json
new file mode 100644
index 00000000..c05e1576
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/yi.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "פוילישע×Ø"
+ ]
+ },
+ "mwe-timedtext-back-btn": "צו×Øיק",
+ "mwe-timedtext-textcat-cc": "באש×Øייבונגען"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/zh-hans.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/zh-hans.json
new file mode 100644
index 00000000..d13683e9
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/zh-hans.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Shizhao",
+ "Simon Shek",
+ "Wilsonmess",
+ "Xiaomingyan",
+ "Yfdyh000"
+ ]
+ },
+ "mwe-timedtext-back-btn": "čæ”回",
+ "mwe-timedtext-layout-off": "éšč—å­—å¹•",
+ "mwe-timedtext-loading-text": "ę­£åœØč½½å…„ę–‡ęœ¬...",
+ "mwe-timedtext-textcat-cc": "čÆ“ę˜Ž",
+ "mwe-timedtext-textcat-sub": "å‰Æę ‡é¢˜",
+ "mwe-timedtext-textcat-tad": "声音čÆ“ę˜Ž",
+ "mwe-timedtext-textcat-ktv": "å”ę‹‰OK",
+ "mwe-timedtext-textcat-tik": "껚åŠØę–‡ęœ¬",
+ "mwe-timedtext-textcat-ar": "作ē”ØåŒŗ域",
+ "mwe-timedtext-textcat-nb": "ę³Ø释",
+ "mwe-timedtext-textcat-meta": "å­—å¹•å…ƒę•°ę®",
+ "mwe-timedtext-textcat-trx": "字幕",
+ "mwe-timedtext-textcat-lrc": "ꭌčƍ",
+ "mwe-timedtext-textcat-lin": "čÆ­čØ€ę ‡č®°",
+ "mwe-timedtext-textcat-cue": "ꏐē¤ŗē‚¹",
+ "mwe-timedtext-no-subs": "ę²”ęœ‰åÆē”Øēš„字幕",
+ "mwe-timedtext-language-subtitles-for-clip": "ē‰‡ę®µ$2ēš„$1字幕",
+ "mwe-timedtext-language-no-subtitles-for-clip": "ę²”ęœ‰ę‰¾åˆ°ē‰‡ę®µ$2ēš„$1字幕",
+ "mwe-timedtext-upload-timed-text": "ę·»åŠ å­—å¹•"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/zh-hant.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/zh-hant.json
new file mode 100644
index 00000000..b653aeb1
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/zh-hant.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Justincheng12345",
+ "Mark85296341",
+ "Simon Shek",
+ "LNDDYL"
+ ]
+ },
+ "mwe-timedtext-back-btn": "čæ”回",
+ "mwe-timedtext-layout-off": "éš±č—å­—å¹•",
+ "mwe-timedtext-loading-text": "ę­£åœØč®€å–ę–‡å­—ā€¦ā€¦",
+ "mwe-timedtext-textcat-cc": "ęؙ锌",
+ "mwe-timedtext-textcat-sub": "å‰Æęؙ锌",
+ "mwe-timedtext-textcat-tad": "音č؊čŖŖ꘎",
+ "mwe-timedtext-textcat-ktv": "å”ę‹‰OK",
+ "mwe-timedtext-textcat-tik": "ę»¾å‹•ę–‡ęœ¬",
+ "mwe-timedtext-textcat-ar": "ęœ‰ę•ˆå€åŸŽ",
+ "mwe-timedtext-textcat-nb": "čØ»č§£",
+ "mwe-timedtext-textcat-meta": "å­—å¹•å…ƒč³‡ę–™",
+ "mwe-timedtext-textcat-trx": "字幕",
+ "mwe-timedtext-textcat-lrc": "ę­Œč©ž",
+ "mwe-timedtext-textcat-lin": "čŖžč؀ęؙčؘ",
+ "mwe-timedtext-textcat-cue": "ꚗ點",
+ "mwe-timedtext-no-subs": "ē„”åÆē”Ø字幕",
+ "mwe-timedtext-language-subtitles-for-clip": "ē‰‡ę®µēš„$1å­—å¹•ę–‡ä»¶ļ¼š$2",
+ "mwe-timedtext-language-no-subtitles-for-clip": "ę²’ęœ‰ę‰¾åˆ°ē‰‡ę®µēš„$1å­—å¹•ę–‡ä»¶ļ¼š$2",
+ "mwe-timedtext-upload-timed-text": "ę·»åŠ å­—å¹•"
+}
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.TextSource.js b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.TextSource.js
new file mode 100644
index 00000000..cce8310f
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.TextSource.js
@@ -0,0 +1,504 @@
+/**
+ * Base mw.TextSource object
+ *
+ * @param {Object} source Source object to extend
+ * @param {Object} textProvider [Optional] The text provider interface ( to load source from api )
+ */
+( function( mw, $ ) { "use strict";
+
+ mw.TextSource = function( source ) {
+ return this.init( source );
+ };
+ mw.TextSource.prototype = {
+
+ //The load state:
+ loaded: false,
+
+ // Container for the captions
+ // captions include "start", "end" and "content" fields
+ captions: [],
+
+ // The css style for captions ( some file formats specify display types )
+ styleCss: {},
+
+ // The previous index of the timed text served
+ // Avoids searching the entire array on time updates.
+ prevIndex: 0,
+
+ /**
+ * @constructor Inherits mediaSource from embedPlayer
+ * @param {source} Base source element
+ * @param {Object} Pointer to the textProvider
+ */
+ init: function( source , textProvider) {
+ // Inherits mediaSource
+ for( var i in source){
+ this[ i ] = source[ i ];
+ }
+
+ // Set default category to subtitle if unset:
+ if( ! this.kind ) {
+ this.kind = 'subtitle';
+ }
+ //Set the textProvider if provided
+ if( textProvider ) {
+ this.textProvider = textProvider;
+ }
+ return this;
+ },
+
+ /**
+ * Function to load and parse the source text
+ * @param {Function} callback Function called once text source is loaded
+ */
+ load: function( callback ) {
+ var _this = this;
+ mw.log("TextSource:: load src "+ _this.getSrc() );
+
+ // Setup up a callback ( in case it was not defined )
+ if( !callback ){
+ callback = function(){ return ; };
+ }
+
+ // Check if the captions have already been loaded:
+ if( this.loaded ){
+ return callback();
+ }
+
+ // Try to load src via XHR source
+ if( !this.getSrc() ) {
+ mw.log( "Error: TextSource no source url for text track");
+ return callback();
+ }
+
+ // Check type for special loaders:
+ $( mw ).triggerQueueCallback( 'TimedText_LoadTextSource', _this, function(){
+ if( _this.loaded ){
+ callback();
+ } else {
+ // if no module loaded the text source use the normal ajax proxy:
+ new mw.ajaxProxy({
+ url: _this.getSrc(),
+ success: function( resultXML ) {
+ _this.captions = _this.getCaptions( resultXML );
+ _this.loaded = true;
+ mw.log("mw.TextSource :: loaded from " + _this.getSrc() + " Found: " + _this.captions.length + ' captions' );
+ callback();
+ },
+ error: function() {
+ mw.log("Error: TextSource Error with http response");
+ _this.loaded = true;
+ callback();
+ }
+ });
+ }
+ })
+ },
+ /**
+ * Returns the text content for requested time
+ *
+ * @param {Number} time Time in seconds
+ */
+ getCaptionForTime: function ( time ) {
+ var prevCaption = this.captions[ this.prevIndex ];
+ var captionSet = {};
+
+ // Setup the startIndex:
+ if( prevCaption && time >= prevCaption.start ) {
+ var startIndex = this.prevIndex;
+ }else{
+ // If a backwards seek start searching at the start:
+ var startIndex = 0;
+ }
+ var firstCapIndex = 0;
+ // Start looking for the text via time, add all matches that are in range
+ for( var i = startIndex ; i < this.captions.length; i++ ) {
+ var caption = this.captions[ i ];
+ // Don't handle captions with 0 or -1 end time:
+ if( caption.end == 0 || caption.end == -1)
+ continue;
+
+ if( time >= caption.start &&
+ time <= caption.end ) {
+ // set the earliest valid time to the current start index:
+ if( !firstCapIndex ){
+ firstCapIndex = caption.start;
+ }
+
+ //mw.log("Start cap time: " + caption.start + ' End time: ' + caption.end );
+ captionSet[i] = caption ;
+ }
+ // captions are stored in start order stop search if we get larger than time
+ if( caption.start > time ){
+ break;
+ }
+ }
+ // Update the prevIndex:
+ this.prevIndex = firstCapIndex;
+ //Return the set of captions in range:
+ return captionSet;
+ },
+
+ /**
+ * Check if the caption is an overlay format ( and must be ontop of the player )
+ */
+ isOverlay: function(){
+ return this.mimeType == 'text/xml';
+ },
+
+ getCaptions: function( data ){
+ // Detect caption data type:
+ switch( this.mimeType ){
+ case 'text/mw-srt':
+ return this.getCaptiosnFromMediaWikiSrt( data );
+ break;
+ case 'text/x-srt':
+ return this.getCaptionsFromSrt( data);
+ break;
+ case 'text/xml':
+ return this.getCaptionsFromTMML( data );
+ break;
+ }
+ // caption mime not found return empty set:
+ return [];
+ },
+
+ getStyleCssById: function( styleId ){
+ if( this.styleCss[ styleId ] ){
+ return this.styleCss[ styleId ];
+ }
+ return {};
+ },
+ /**
+ * Grab timed text from TMML format
+ *
+ * @param data
+ * @return
+ */
+ getCaptionsFromTMML: function( data ){
+ var _this = this;
+ mw.log("TextSource::getCaptionsFromTMML", data);
+ // set up display information:
+ var captions = [];
+ var xml = ( $( data ).find("tt").length ) ? data : $.parseXML( data );
+
+ // Check for parse error:
+ try {
+ if( !xml || $( xml ).find('parsererror').length ){
+ mw.log("Error: close caption parse error: " + $( xml ).find('parsererror').text() );
+ return captions;
+ }
+ } catch ( e ) {
+ mw.log( "Error: close caption parse error: " + e.toString() );
+ return captions;
+ }
+
+ // Set the body Style
+ var bodyStyleId = $( xml ).find('body').attr('style');
+
+ // Set style translate ttml to css
+ $( xml ).find( 'style').each( function( inx, style){
+ var cssObject = {};
+ // Map CamelCase css properties:
+ $( style.attributes ).each(function(inx, attr){
+ var attrName = attr.name;
+ if( attrName.substr(0, 4) !== 'tts:' ){
+ // skip
+ return true;
+ }
+ var cssName = '';
+ for( var c = 4; c < attrName.length; c++){
+ if( attrName[c].toLowerCase() != attrName[c] ){
+ cssName += '-' + attrName[c].toLowerCase();
+ } else {
+ cssName+= attrName[c]
+ }
+ }
+ cssObject[ cssName ] = attr.nodeValue;
+ });
+ // for(var i =0; i< style.length )
+ _this.styleCss[ $( style).attr('id') ] = cssObject;
+ });
+
+ $( xml ).find( 'p' ).each( function( inx, p ){
+ // Get text content by converting ttml node to html
+ var content = '';
+ $.each( p.childNodes, function(inx, node){
+ content+= _this.convertTTML2HTML( node );
+ });
+ // Get the end time:
+ var end = null;
+ if( $( p ).attr( 'end' ) ){
+ end = mw.npt2seconds( $( p ).attr( 'end' ) );
+ }
+ // Look for dur
+ if( !end && $( p ).attr( 'dur' )){
+ end = mw.npt2seconds( $( p ).attr( 'begin' ) ) +
+ mw.npt2seconds( $( p ).attr( 'dur' ) );
+ }
+
+ // Create the caption object :
+ var captionObj ={
+ 'start': mw.npt2seconds( $( p ).attr( 'begin' ) ),
+ 'end': end,
+ 'content': content
+ };
+
+ // See if we have custom metadata for position of this caption object
+ // there are 35 columns across and 15 rows high
+ var $meta = $(p).find( 'metadata' );
+ if( $meta.length ){
+ captionObj['css'] = {
+ 'position': 'absolute'
+ };
+ if( $meta.attr('cccol') ){
+ captionObj['css']['left'] = ( $meta.attr('cccol') / 35 ) * 100 +'%';
+ // also means the width has to be reduced:
+ //captionObj['css']['width'] = 100 - parseInt( captionObj['css']['left'] ) + '%';
+ }
+ if( $meta.attr('ccrow') ){
+ captionObj['css']['top'] = ( $meta.attr('ccrow') / 15 ) * 100 +'%';
+ }
+ }
+ if( $(p).attr('tts:textAlign') ){
+ if( !captionObj['css'] ){
+ captionObj['css'] = {};
+ }
+ captionObj['css']['text-align'] = $(p).attr('tts:textAlign');
+
+ // Remove text align is "right" flip the css left:
+ if( captionObj['css']['text-align'] == 'right' && captionObj['css']['left'] ){
+ //captionObj['css']['width'] = captionObj['css']['left'];
+ captionObj['css']['left'] = null;
+ }
+ }
+
+ // check if this p has any style else use the body parent
+ if( $(p).attr('style') ){
+ captionObj['styleId'] = $(p).attr('style') ;
+ } else {
+ captionObj['styleId'] = bodyStyleId;
+ }
+ captions.push( captionObj);
+ });
+ return captions;
+ },
+ convertTTML2HTML: function( node ){
+ var _this = this;
+
+ // look for text node:
+ if( node.nodeType == 3 ){
+ return node.textContent;
+ }
+ // skip metadata nodes:
+ if( node.nodeName == 'metadata' ){
+ return '';
+ }
+ // if a br just append
+ if( node.nodeName == 'br' ){
+ return '<br />';
+ }
+ // Setup tts mappings TODO should be static property of a ttmlSource object.
+ var ttsStyleMap = {
+ 'tts:color' : 'color',
+ 'tts:fontWeight' : 'font-weight',
+ 'tts:fontStyle' : 'font-style'
+ };
+ if( node.childNodes.length ){
+ var nodeString = '';
+ var styleVal = '';
+ for( var attr in ttsStyleMap ){
+ if( node.getAttribute( attr ) ){
+ styleVal+= ttsStyleMap[ attr ] + ':' + node.getAttribute( attr ) + ';';
+ }
+ }
+ nodeString += '<' + node.nodeName + ' style="' + styleVal + '" >';
+ $.each( node.childNodes, function( inx, childNode ){
+ nodeString += _this.convertTTML2HTML( childNode );
+ });
+ nodeString += '</' + node.nodeName + '>';
+ return nodeString;
+ }
+ },
+ /**
+ * srt timed text parse handle:
+ * @param {String} data Srt string to be parsed
+ */
+ getCaptionsFromSrt: function ( data ){
+ mw.log("TextSource::getCaptionsFromSrt");
+ var _this = this;
+ // Check if the "srt" parses as an XML
+ try{
+ var xml = $.parseXML( data );
+ if( xml && $( xml ).find('parsererror').length == 0 ){
+ return this.getCaptionsFromTMML( data );
+ }
+ } catch ( e ){
+ // srt should not be xml
+ }
+ // Remove dos newlines
+ var srt = data.replace(/\r+/g, '');
+
+ // Trim white space start and end
+ srt = srt.replace(/^\s+|\s+$/g, '');
+
+ // Remove all html tags for security reasons
+ srt = srt.replace(/<[a-zA-Z\/][^>]*>/g, '');
+
+ // Get captions
+ var captions = [];
+ var caplist = srt.split('\n\n');
+ for (var i = 0; i < caplist.length; i++) {
+ var captionText = "";
+ var caption = false;
+ captionText = caplist[i];
+ var s = captionText.split(/\n/);
+ if (s.length < 2) {
+ // file format error or comment lines
+ continue;
+ }
+ if (s[0].match(/^\d+$/) && s[1].match(/\d+:\d+:\d+/)) {
+ // ignore caption number in s[0]
+ // parse time string
+ var m = s[1].match(/(\d+):(\d+):(\d+)(?:,(\d+))?\s*--?>\s*(\d+):(\d+):(\d+)(?:,(\d+))?/);
+ if (m) {
+ caption = _this.match2caption( m );
+ } else {
+ // Unrecognized timestring
+ continue;
+ }
+ if( caption ){
+ // concatenate text lines to html text
+ caption['content'] = s.slice(2).join("<br>");
+ }
+ } else {
+ // file format error or comment lines
+ continue;
+ }
+ // Add the current caption to the captions set:
+ captions.push( caption );
+ }
+
+ return captions;
+ },
+
+ /**
+ * Get srts from a mediawiki html / srt string
+ *
+ * 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
+ *
+ * Also see https://bugzilla.wikimedia.org/show_bug.cgi?id=29126
+ *
+ * TODO move to mediaWiki specific module.
+ */
+ getCaptiosnFromMediaWikiSrt: function( data ){
+ mw.log("TimedText::getCaptiosnFromMediaWikiSrt:");
+ var _this = this;
+ var captions = [ ];
+ var curentCap = {
+ 'content': ''
+ };
+ var parseNextAsTime = false;
+ // Note this string concatenation and html error wrapping sometimes causes
+ // parse issues where the wikitext includes many native <p /> tags without child
+ // subtitles. In prating this is not a deal breakers because the wikitext for
+ // TimedText namespace and associated srts already has a specific format.
+ // Long term we will move to server side parsing.
+ $( '<div>' + data + '</div>' ).find('p').each( function() {
+ var currentPtext = $(this).html();
+ //mw.log( 'pText: ' + currentPtext );
+
+ // We translate raw wikitext gennerated html into a matched srt time sample.
+ // The raw html looks like:
+ // #
+ // hh:mm:ss,ms --&gt hh:mm:ss,ms
+ // text
+ //
+ // You can read more about the srt format here:
+ // http://en.wikipedia.org/wiki/SubRip
+ //
+ // We attempt to be fairly robust in our regular expression to catch a few
+ // srt variations such as omition of commas and empty text lines.
+ var m = currentPtext
+ .replace('--&gt;', '-->') // restore --&gt with --> for easier srt parsing:
+ .match(/\d+\s([\d\-]+):([\d\-]+):([\d\-]+)(?:,([\d\-]+))?\s*--?>\s*([\d\-]+):([\d\-]+):([\d\-]+)(?:,([\d\-]+))?\n?(.*)/);
+
+ if (m) {
+ captions.push(
+ _this.match2caption( m )
+ );
+ return true;
+ }
+
+ /***
+ * Handle multi line sytle output
+ *
+ * Handles cases parse cases where an entire line can't be parsed in the single
+ * regular expression above, Since the diffrent captions pars are outputed in
+ * diffrent <p /> tags by the wikitext parser output.
+ */
+
+ // Check if we have reached the end of a multi line match
+ if( parseInt( currentPtext ) == currentPtext ) {
+ if( curentCap.content != '' ) {
+ captions.push( curentCap );
+ }
+ // Clear out the current caption content
+ curentCap = {
+ 'content': ''
+ };
+ return true;
+ }
+ // Check only for time match:
+ var m = currentPtext
+ .replace('--&gt;', '-->')
+ .match(/(\d+):(\d+):(\d+)(?:,(\d+))?\s*--?>\s*(\d+):(\d+):(\d+)(?:,(\d+))?/);
+ if (m) {
+ // Update the currentCap:
+ curentCap = _this.match2caption( m );
+ return true;
+ }
+ // Else append contnet for the curentCap
+ if( currentPtext != '<br>' ) {
+ curentCap['content'] += currentPtext;
+ }
+ });
+ //Push last subtitle:
+ if( curentCap.length != 0) {
+ captions.push( curentCap );
+ }
+ mw.log( "TimedText::getCaptiosnFromMediaWikiSrt found " + captions.length + ' captions');
+ return captions;
+ },
+ /**
+ * Takes a regular expresion match and converts it to a caption object
+ */
+ match2caption: function( m ){
+ var caption = {};
+ // Look for ms:
+ var startMs = (m[4]) ? parseInt(m[4], 10) : 0;
+ var endMs = (m[8]) ? parseInt(m[8], 10) : 0;
+ caption['start'] = this.timeParts2seconds( m[1], m[2], m[3], startMs );
+ caption['end'] = this.timeParts2seconds( m[5], m[6], m[7], endMs );
+ if( m[9] ){
+ caption['content'] = $.trim( m[9] );
+ }
+ return caption;
+ },
+ /**
+ * Takes time parts in hours, min, seconds and milliseconds and coverts to float seconds.
+ */
+ timeParts2seconds: function( hours, min, sec, ms ){
+ return mw.measurements2seconds({
+ 'hours': hours,
+ 'minutes': min,
+ 'seconds' : sec,
+ 'milliseconds': ms
+ });
+ }
+ };
+
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.TimedText.js b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.TimedText.js
new file mode 100644
index 00000000..2a69343e
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.TimedText.js
@@ -0,0 +1,1313 @@
+/**
+ * The Core timed Text interface object
+ *
+ * handles class mappings for:
+ * menu display ( jquery.ui themeable )
+ * timed text loading request
+ * timed text edit requests
+ * timed text search & seek interface ( version 2 )
+ *
+ * @author: Michael Dale
+ *
+ */
+
+( function( mw, $ ) {"use strict";
+
+ // Merge in timed text related attributes:
+ mw.mergeConfig( 'EmbedPlayer.SourceAttributes', [
+ 'srclang',
+ 'kind',
+ 'label'
+ ]);
+
+ /**
+ * Timed Text Object
+ * @param embedPlayer Host player for timedText interfaces
+ */
+ mw.TimedText = function( embedPlayer ) {
+ return this.init( embedPlayer );
+ };
+
+ mw.TimedText.prototype = {
+
+ /**
+ * Preferences config order is presently:
+ * 1) user cookie
+ * 2) defaults provided in this config var:
+ */
+ config: {
+ // Layout for basic "timedText" type can be 'ontop', 'off', 'below'
+ 'layout' : 'ontop',
+
+ //Set the default local ( should be grabbed from the browser )
+ 'userLanguage' : mw.config.get( 'wgUserLanguage' ) || 'en',
+
+ //Set the default kind of timedText to display ( un-categorized timed-text is by default "subtitles" )
+ 'userKind' : 'subtitles'
+ },
+
+ // The default display mode is 'ontop'
+ defaultDisplayMode : 'ontop',
+
+ // Save last layout mode
+ lastLayout : 'ontop',
+
+ // The bind prefix:
+ bindPostFix: '.timedText',
+
+ // Default options are empty
+ options: {},
+
+ /**
+ * The list of enabled sources
+ */
+ enabledSources: [],
+
+ // First loading flag - To set the layout at first load
+ firstLoad: true,
+
+ /**
+ * The current language key
+ */
+ currentLangKey : null,
+
+ /**
+ * The direction of the current language
+ */
+ currentLangDir : null,
+
+ /**
+ * Stores the last text string per kind to avoid dom checks for updated text
+ */
+ prevText: [],
+
+ /**
+ * Text sources ( a set of textSource objects )
+ */
+ textSources: [],
+
+ /**
+ * Valid "Track" categories
+ */
+ validCategoriesKeys: [
+ "CC",
+ "SUB",
+ "TAD",
+ "KTV",
+ "TIK",
+ "AR",
+ "NB",
+ "META",
+ "TRX",
+ "LRC",
+ "LIN",
+ "CUE"
+ ],
+
+ /**
+ * @constructor
+ * @param {Object} embedPlayer Host player for timedText interfaces
+ */
+ init: function( embedPlayer ) {
+ var _this = this;
+ mw.log("TimedText: init() ");
+ this.embedPlayer = embedPlayer;
+ // don't display captions on native player:
+ if( embedPlayer.useNativePlayerControls() ){
+ return this;
+ }
+
+ // Load user preferences config:
+ var preferenceConfig = $.cookie( 'TimedText.Preferences' );
+ if( preferenceConfig !== "false" && preferenceConfig != null ) {
+ this.config = JSON.parse( preferenceConfig );
+ }
+ // remove any old bindings on change media:
+ $( this.embedPlayer ).bind( 'onChangeMedia' + this.bindPostFix , function(){
+ _this.destroy();
+ });
+
+ // Remove any old bindings before we add the current bindings:
+ _this.destroy();
+
+ // Add player bindings
+ _this.addPlayerBindings();
+ return this;
+ },
+ destroy: function(){
+ // remove any old player bindings;
+ $( this.embedPlayer ).unbind( this.bindPostFix );
+ // Clear out enabled sources:
+ this.enabledSources = [];
+ // Clear out text sources:
+ this.textSources = [];
+ },
+ /**
+ * Add timed text related player bindings
+ * @return
+ */
+ addPlayerBindings: function(){
+ var _this = this;
+ var embedPlayer = this.embedPlayer;
+
+ // Check for timed text support:
+ _this.addInterface();
+
+ $( embedPlayer ).bind( 'timeupdate' + this.bindPostFix, function( event, jEvent, id ) {
+ // regain scope
+ _this = $('#' + id)[0].timedText;
+ // monitor text updates
+ _this.monitor();
+ } );
+
+ $( embedPlayer ).bind( 'firstPlay' + this.bindPostFix, function(event, id ) {
+ // regain scope
+ _this = $('#' + id)[0].timedText;
+ // Will load and setup timedText sources (if not loaded already loaded )
+ _this.setupTextSources();
+ // Hide the caption menu if presently displayed
+ $( '#textMenuContainer_' + _this.embedPlayer.id ).hide();
+ } );
+
+ // Re-Initialize when changing media
+ $( embedPlayer ).bind( 'onChangeMedia' + this.bindPostFix, function() {
+ _this.destroy();
+ _this.updateLayout();
+ _this.setupTextSources();
+ $( '#textMenuContainer_' + embedPlayer.id ).hide();
+ } );
+
+ // Resize the timed text font size per window width
+ $( embedPlayer ).bind( 'onCloseFullScreen' + this.bindPostFix + ' onOpenFullScreen' + this.bindPostFix, function() {
+ // Check if we are in fullscreen or not, if so add an additional bottom offset of
+ // double the default bottom padding.
+ var textOffset = _this.embedPlayer.controlBuilder.inFullScreen ?
+ mw.config.get("TimedText.BottomPadding") * 2 :
+ mw.config.get("TimedText.BottomPadding");
+
+ var textCss = _this.getInterfaceSizeTextCss({
+ 'width' : embedPlayer.getInterface().width(),
+ 'height' : embedPlayer.getInterface().height()
+ });
+
+ mw.log( 'TimedText::set text size for: : ' + embedPlayer.getInterface().width() + ' = ' + textCss['font-size'] );
+ if ( embedPlayer.controlBuilder.isOverlayControls() && !embedPlayer.getInterface().find( '.control-bar' ).is( ':hidden' ) ) {
+ textOffset += _this.embedPlayer.controlBuilder.getHeight();
+ }
+ embedPlayer.getInterface().find( '.track' )
+ .css( textCss )
+ .css({
+ // Get the text size scale then set it to control bar height + TimedText.BottomPadding;
+ 'bottom': textOffset + 'px'
+ });
+ });
+
+ // Update the timed text size
+ $( embedPlayer ).bind( 'updateLayout'+ this.bindPostFix, function() {
+ // If the the player resize action is an animation, animate text resize,
+ // else instantly adjust the css.
+ var textCss = _this.getInterfaceSizeTextCss( {
+ 'width': embedPlayer.getPlayerWidth(),
+ 'height': embedPlayer.getPlayerHeight()
+ });
+ mw.log( 'TimedText::updateLayout: ' + textCss['font-size']);
+ embedPlayer.getInterface().find( '.track' ).css( textCss );
+ });
+
+ // Setup display binding
+ $( embedPlayer ).bind( 'onShowControlBar'+ this.bindPostFix, function(event, layout, id ){
+ // update embedPlayer ref:
+ var embedPlayer = $('#' + id )[0];
+ if ( embedPlayer.controlBuilder.isOverlayControls() ) {
+ // Move the text track if present
+ embedPlayer.getInterface().find( '.track' )
+ .stop()
+ .animate( layout, 'fast' );
+ }
+ });
+
+ $( embedPlayer ).bind( 'onHideControlBar' + this.bindPostFix, function(event, layout, id ){
+ var embedPlayer = $('#' + id )[0];
+ if ( embedPlayer.controlBuilder.isOverlayControls() ) {
+ // Move the text track down if present
+ embedPlayer.getInterface().find( '.track' )
+ .stop()
+ .animate( layout, 'fast' );
+ }
+ });
+
+ $( embedPlayer ).bind( 'AdSupport_StartAdPlayback' + this.bindPostFix, function() {
+ if ( $( '#textMenuContainer_' + embedPlayer.id ).length ) {
+ $( '#textMenuContainer_' + embedPlayer.id ).hide();
+ }
+ var $textButton = embedPlayer.getInterface().find( '.timed-text' );
+ if ( $textButton.length ) {
+ $textButton.unbind( 'click' );
+ }
+ _this.lastLayout = _this.getLayoutMode();
+ _this.setLayoutMode( 'off' );
+ } );
+
+ $( embedPlayer ).bind( 'AdSupport_EndAdPlayback' + this.bindPostFix, function() {
+ var $textButton = embedPlayer.getInterface().find( '.timed-text' );
+ if ( $textButton.length ) {
+ _this.bindTextButton( $textButton );
+ }
+ _this.setLayoutMode( _this.lastLayout );
+ } );
+
+ },
+ addInterface: function(){
+ var _this = this;
+ // By default we include a button in the control bar.
+ $( _this.embedPlayer ).bind( 'addControlBarComponent' + this.bindPostFix, function(event, controlBar ){
+ if( controlBar.supportedComponents['timedText'] !== false &&
+ _this.includeCaptionButton() ) {
+ controlBar.supportedComponents['timedText'] = true;
+ controlBar.components['timedText'] = _this.getTimedTextButton();
+ }
+ });
+ },
+ includeCaptionButton:function(){
+ return mw.config.get( 'TimedText.ShowInterface' ) == 'always' ||
+ this.embedPlayer.getTextTracks().length;
+ },
+ /**
+ * Get the current language key
+ * @return
+ * @type {string}
+ */
+ getCurrentLangKey: function(){
+ return this.currentLangKey;
+ },
+ /**
+ * Get the current language direction
+ * @return
+ * @type {string}
+ */
+ getCurrentLangDir: function(){
+ if ( !this.currentLangDir ) {
+ var source = this.getSourceByLanguage( this.getCurrentLangKey() );
+ this.currentLangDir = source.dir;
+ }
+ return this.currentLangDir;
+ },
+
+ /**
+ * The timed text button to be added to the interface
+ */
+ getTimedTextButton: function(){
+ var _this = this;
+ /**
+ * The closed captions button
+ */
+ return {
+ 'w': 30,
+ 'position': 6.9,
+ 'o': function( ctrlObj ) {
+ var $textButton = $( '<div />' )
+ .attr( 'title', mw.msg( 'mwe-embedplayer-timed_text' ) )
+ .addClass( "ui-state-default ui-corner-all ui-icon_link rButton timed-text" )
+ .append(
+ $( '<span />' )
+ .addClass( "ui-icon ui-icon-comment" )
+ )
+ // Captions binding:
+ .buttonHover();
+ _this.bindTextButton( $textButton );
+ return $textButton;
+
+ }
+ };
+ },
+ bindTextButton: function( $textButton ){
+ var _this = this;
+ $textButton.unbind('click.textMenu').bind('click.textMenu', function() {
+ _this.showTextMenu();
+ return true;
+ } );
+ },
+
+ /**
+ * Get the fullscreen text css
+ */
+ getInterfaceSizeTextCss: function( size ) {
+ //mw.log(' win size is: ' + $( window ).width() + ' ts: ' + textSize );
+ return {
+ 'font-size' : this.getInterfaceSizePercent( size ) + '%'
+ };
+ },
+
+ /**
+ * Show the text interface library and show the text interface near the player.
+ */
+ showTextMenu: function() {
+ var embedPlayer = this.embedPlayer;
+ var loc = embedPlayer.getInterface().find( '.rButton.timed-text' ).offset();
+ mw.log('TimedText::showTextMenu:: ' + embedPlayer.id + ' location: ', loc);
+ // TODO: Fix menu animation
+ var $menuButton = this.embedPlayer.getInterface().find( '.timed-text' );
+ // Check if a menu has already been built out for the menu button:
+ if ( $menuButton[0].m ) {
+ $menuButton.embedMenu( 'show' );
+ } else {
+ // Bind the text menu:
+ this.buildMenu( true );
+ }
+ },
+ getTextMenuContainer: function(){
+ var textMenuId = 'textMenuContainer_' + this.embedPlayer.id;
+ if( !$( '#' + textMenuId ).length ){
+ //Setup the menu:
+ this.embedPlayer.getInterface().append(
+ $('<div>')
+ .addClass('ui-widget ui-widget-content ui-corner-all')
+ .attr( 'id', textMenuId )
+ .css( {
+ 'position' : 'absolute',
+ 'height' : '180px',
+ 'width' : '180px',
+ 'font-size' : '12px',
+ 'display' : 'none',
+ 'overflow' : 'auto'
+ } )
+
+ );
+ }
+ return $( '#' + textMenuId );
+ },
+ /**
+ * Gets a text size percent relative to about 30 columns of text for 400
+ * pixel wide player, at 100% text size.
+ *
+ * @param size {object} The size of the target player area width and height
+ */
+ getInterfaceSizePercent: function( size ) {
+ // This is a ugly hack we should read "original player size" and set based
+ // on some standard ish normal 31 columns 15 rows
+ var sizeFactor = 4;
+ if( size.height / size.width < .7 ){
+ sizeFactor = 6;
+ }
+ var textSize = size.width / sizeFactor;
+ if( textSize < 95 ){
+ textSize = 95;
+ }
+ if( textSize > 150 ){
+ textSize = 150;
+ }
+ return textSize;
+ },
+
+ /**
+ * Setups available text sources
+ * loads text sources
+ * auto-selects a source based on the user language
+ * @param {Function} callback Function to be called once text sources are setup.
+ */
+ setupTextSources: function( callback ) {
+ mw.log( 'TimedText::setupTextSources');
+ var _this = this;
+ // Load textSources
+ _this.loadTextSources( function() {
+ // Enable a default source and issue a request to "load it"
+ _this.autoSelectSource();
+
+ // Load and parse the text value of enabled text sources:
+ _this.loadEnabledSources();
+
+ if( callback ) {
+ callback();
+ }
+ } );
+ },
+
+ /**
+ * Binds the timed text menu
+ * and updates its content from "getMainMenu"
+ *
+ * @param {Object} target to display the menu
+ * @param {Boolean} autoShow If the menu should be displayed
+ */
+ buildMenu: function( autoShow ) {
+ var _this = this;
+ var embedPlayer = this.embedPlayer;
+ // Setup text sources ( will callback inline if already loaded )
+ _this.setupTextSources( function() {
+ var $menuButton = _this.embedPlayer.getInterface().find( '.timed-text' );
+
+ var positionOpts = { };
+ if( _this.embedPlayer.supports[ 'overlays' ] ){
+ var positionOpts = {
+ 'directionV' : 'up',
+ 'offsetY' : _this.embedPlayer.controlBuilder.getHeight(),
+ 'directionH' : 'left',
+ 'offsetX' : -28
+ };
+ }
+
+ if( !_this.embedPlayer.getInterface() ){
+ mw.log("TimedText:: interface called before interface ready, just wait for interface");
+ return ;
+ }
+ var $menuButton = _this.embedPlayer.getInterface().find( '.timed-text' );
+ var ctrlObj = _this.embedPlayer.controlBuilder;
+ // NOTE: Button target should be an option or config
+ $menuButton.embedMenu( {
+ 'content' : _this.getMainMenu(),
+ 'zindex' : mw.config.get( 'EmbedPlayer.FullScreenZIndex' ) + 2,
+ 'crumbDefaultText' : ' ',
+ 'autoShow': autoShow,
+ 'keepPosition' : true,
+ 'showSpeed': 0,
+ 'height' : 100,
+ 'width' : 300,
+ 'targetMenuContainer' : _this.getTextMenuContainer(),
+ 'positionOpts' : positionOpts,
+ 'backLinkText' : mw.msg( 'mwe-timedtext-back-btn' ),
+ 'createMenuCallback' : function(){
+ var $interface = _this.embedPlayer.getInterface();
+ var $textContainer = _this.getTextMenuContainer();
+ var textHeight = 130;
+ var top = $interface.height() - textHeight - ctrlObj.getHeight() - 6;
+ if( top < 0 ){
+ top = 0;
+ }
+ // check for audio
+ if( _this.embedPlayer.isAudio() ){
+ top = _this.embedPlayer.controlBuilder.getHeight() + 4;
+ }
+ $textContainer.css({
+ 'top' : top,
+ 'height': textHeight,
+ 'position' : 'absolute',
+ 'left': $menuButton[0].offsetLeft - 165,
+ 'bottom': ctrlObj.getHeight()
+ })
+ ctrlObj.showControlBar( true );
+ },
+ 'closeMenuCallback' : function(){
+ ctrlObj.restoreControlsHover();
+ }
+ });
+ });
+ },
+
+ /**
+ * Monitor video time and update timed text filed[s]
+ */
+ monitor: function() {
+ //mw.log(" timed Text monitor: " + this.enabledSources.length );
+ var embedPlayer = this.embedPlayer;
+ // Setup local reference to currentTime:
+ var currentTime = embedPlayer.currentTime;
+
+ // Get the text per kind
+ var textCategories = [ ];
+
+ var source = this.enabledSources[ 0 ];
+ if( source ) {
+ this.updateSourceDisplay( source, currentTime );
+ }
+ },
+
+ /**
+ * Load all the available text sources from the inline embed
+ * @param {Function} callback Function to call once text sources are loaded
+ */
+ loadTextSources: function( callback ) {
+ var _this = this;
+ // check if text sources are already loaded ( not em )
+ if( this.textSources.length ){
+ callback( this.textSources );
+ return ;
+ }
+ this.textSources = [];
+ // load inline text sources:
+ $.each( this.embedPlayer.getTextTracks(), function( inx, textSource ){
+ _this.textSources.push( new mw.TextSource( textSource ) );
+ });
+ // return the callback with sources
+ callback( _this.textSources );
+ },
+
+ /**
+ * Get the layout mode
+ *
+ * Takes into consideration:
+ * Playback method overlays support ( have to put subtitles below video )
+ *
+ */
+ getLayoutMode: function() {
+ // Re-map "ontop" to "below" if player does not support
+ if( this.config.layout == 'ontop' && !this.embedPlayer.supports['overlays'] ) {
+ this.config.layout = 'below';
+ }
+ return this.config.layout;
+ },
+
+ /**
+ * Auto selects a source given the local configuration
+ *
+ * NOTE: presently this selects a "single" source.
+ * In the future we could support multiple "enabled sources"
+ */
+ autoSelectSource: function() {
+ var _this = this;
+ // If a source is enabled then don't auto select
+ if ( this.enabledSources.length ) {
+ return false;
+ }
+ this.enabledSources = [];
+
+ var setDefault = false;
+ // Check if any source is marked default:
+ $.each( this.textSources, function(inx, source){
+ if( source['default'] ){
+ _this.enableSource( source );
+ setDefault = true;
+ return false;
+ }
+ });
+ if ( setDefault ) {
+ return true;
+ }
+
+ var setLocalPref = false;
+ // Check if any source matches our "local" pref
+ $.each( this.textSources, function(inx, source){
+ if( _this.config.userLanguage == source.srclang.toLowerCase()
+ &&
+ _this.config.userKind == source.kind
+ ) {
+ _this.enableSource( source );
+ setLocalPref = true;
+ return false;
+ }
+ });
+ if ( setLocalPref ) {
+ return true;
+ }
+
+ var setEnglish = false;
+ // If no userLang, source try enabling English:
+ if( this.enabledSources.length == 0 ) {
+ for( var i=0; i < this.textSources.length; i++ ) {
+ var source = this.textSources[ i ];
+ if( source.srclang.toLowerCase() == 'en' ) {
+ _this.enableSource( source );
+ setEnglish = true;
+ return false;
+ }
+ }
+ }
+ if ( setEnglish ) {
+ return true;
+ }
+
+ var setFirst = false;
+ // If still no source try the first source we get;
+ if( this.enabledSources.length == 0 ) {
+ for( var i=0; i < this.textSources.length; i++ ) {
+ var source = this.textSources[ i ];
+ _this.enableSource( source );
+ setFirst = true;
+ return false;
+ }
+ }
+ if ( setFirst ) {
+ return true;
+ }
+
+ return false;
+ },
+ /**
+ * Enable a source and update the currentLangKey
+ * @param {object} source
+ * @return
+ */
+ enableSource: function( source ){
+ var _this = this;
+ // check if we have any source set yet:
+ if( !_this.enabledSources.length ){
+ _this.enabledSources.push( source );
+ _this.currentLangKey = source.srclang;
+ _this.currentLangDir = null;
+ return ;
+ }
+ var sourceEnabled = false;
+ // Make sure the source is not already enabled
+ $.each( this.enabledSources, function( inx, enabledSource ){
+ if( source.id == enabledSource.id ){
+ sourceEnabled = true;
+ }
+ });
+ if ( !sourceEnabled ) {
+ _this.enabledSources.push( source );
+ _this.currentLangKey = source.srclang;
+ _this.currentLangDir = null;
+ }
+ },
+
+ /**
+ * Get the current source sub captions
+ * @param {function} callback function called once source is loaded
+ */
+ loadCurrentSubSource: function( callback ){
+ mw.log("loadCurrentSubSource:: enabled source:" + this.enabledSources.length);
+ for( var i =0; i < this.enabledSources.length; i++ ){
+ var source = this.enabledSources[i];
+ if( source.kind == 'SUB' ){
+ source.load( function(){
+ callback( source);
+ return ;
+ });
+ }
+ }
+ return false;
+ },
+
+ /**
+ * Get sub captions by language key:
+ *
+ * @param {string} langKey Key of captions to load
+ * @pram {function} callback function called once language key is loaded
+ */
+ getSubCaptions: function( langKey, callback ){
+ for( var i=0; i < this.textSources.length; i++ ) {
+ var source = this.textSources[ i ];
+ if( source.srclang.toLowerCase() === langKey ) {
+ var source = this.textSources[ i ];
+ source.load( function(){
+ callback( source.captions );
+ });
+ }
+ }
+ },
+
+ /**
+ * Issue a request to load all enabled Sources
+ * Should be called anytime enabled Source list is updated
+ */
+ loadEnabledSources: function() {
+ var _this = this;
+ mw.log( "TimedText:: loadEnabledSources " + this.enabledSources.length );
+ $.each( this.enabledSources, function( inx, enabledSource ) {
+ // check if the source requires ovelray ( ontop ) layout mode:
+ if( enabledSource.isOverlay() && _this.config.layout== 'ontop' ){
+ _this.setLayoutMode( 'ontop' );
+ }
+ enabledSource.load(function(){
+ // Trigger the text loading event:
+ $( _this.embedPlayer ).trigger('loadedTextSource', enabledSource);
+ });
+ });
+ },
+ /**
+ * Checks if a source is "on"
+ * @return {Boolean}
+ * true if source is on
+ * false if source is off
+ */
+ isSourceEnabled: function( source ) {
+ // no source is "enabled" if subtitles are "off"
+ if( this.getLayoutMode() == 'off' ){
+ return false;
+ }
+ var isEnabled = false;
+ $.each( this.enabledSources, function( inx, enabledSource ) {
+ if( source.id ) {
+ if( source.id === enabledSource.id ){
+ isEnabled = true;
+ }
+ }
+ if( source.src ){
+ if( source.src == enabledSource.src ){
+ isEnabled = true;
+ }
+ }
+ });
+ return isEnabled;
+ },
+
+ /**
+ * Marks the active captions in the menu
+ */
+ markActive: function( source ) {
+ var $menu = $( '#textMenuContainer_' + this.embedPlayer.id );
+ if ( $menu.length ) {
+ var $captionRows = $menu.find( '.captionRow' );
+ if ( $captionRows.length ) {
+ $captionRows.each( function() {
+ $( this ).removeClass( 'ui-icon-bullet ui-icon-radio-on' );
+ var iconClass = ( $( this ).data( 'caption-id' ) === source.id ) ? 'ui-icon-bullet' : 'ui-icon-radio-on';
+ $( this ).addClass( iconClass );
+ } );
+ }
+ }
+ },
+
+ /**
+ * Marks the active layout mode in the menu
+ */
+ markLayoutActive: function ( layoutMode ) {
+ var $menu = $( '#textMenuContainer_' + this.embedPlayer.id );
+ if ( $menu.length ) {
+ var $layoutRows = $menu.find( '.layoutRow' );
+ if ( $layoutRows.length ) {
+ $layoutRows.each( function() {
+ $( this ).removeClass( 'ui-icon-bullet ui-icon-radio-on' );
+ var iconClass = ( $( this ).data( 'layoutMode' ) === layoutMode ) ? 'ui-icon-bullet' : 'ui-icon-radio-on';
+ $( this ).addClass( iconClass );
+ } );
+ }
+ }
+ },
+
+ /**
+ * Get a source object by language, returns "false" if not found
+ * @param {string} langKey The language key filter for selected source
+ */
+ getSourceByLanguage: function ( langKey ) {
+ for(var i=0; i < this.textSources.length; i++) {
+ var source = this.textSources[ i ];
+ if( source.srclang == langKey ){
+ return source;
+ }
+ }
+ return false;
+ },
+
+ /**
+ * Builds the core timed Text menu and
+ * returns the binded jquery object / dom set
+ *
+ * Assumes text sources have been setup: ( _this.setupTextSources() )
+ *
+ * calls a few sub-functions:
+ * Basic menu layout:
+ * Chose Language
+ * All Subtiles here ( if we have categories list them )
+ * Layout
+ * Below video
+ * Ontop video ( only available to supported plugins )
+ * TODO features:
+ * [ Search Text ]
+ * [ This video ]
+ * [ All videos ]
+ * [ Chapters ] seek to chapter
+ */
+ getMainMenu: function() {
+ var _this = this;
+
+ // Set the menut to avaliable languages:
+ var $menu = _this.getLanguageMenu();
+
+ if( _this.textSources.length == 0 ){
+ $menu.append(
+ $.getLineItem( mw.msg( 'mwe-timedtext-no-subs'), 'close' )
+ );
+ } else {
+ // Layout Menu option if not in an iframe and we can expand video size:
+ $menu.append(
+ $.getLineItem(
+ mw.msg( 'mwe-timedtext-layout-off'),
+ ( _this.getLayoutMode() == 'off' ) ? 'bullet' : 'radio-on',
+ function() {
+ _this.setLayoutMode( 'off' );
+ },
+ 'layoutRow',
+ { 'layoutMode' : 'off' }
+ )
+ )
+ }
+ // Allow other modules to add to the timed text menu:
+ $( _this.embedPlayer ).trigger( 'TimedText_BuildCCMenu', [ $menu, _this.embedPlayer.id ] ) ;
+
+ // Test if only one menu item move its children to the top level
+ if( $menu.children('li').length == 1 ){
+ $menu.find('li > ul > li').detach().appendTo( $menu );
+ $menu.find('li').eq(0).remove();
+ }
+
+ return $menu;
+ },
+
+ /**
+ * Utility function to assist in menu build out:
+ * Get menu line item (li) html: <li><a> msgKey </a></li>
+ *
+ * @param {String} msgKey Msg key for menu item
+ */
+
+ /**
+ * Get line item (li) from source object
+ * @param {Object} source Source to get menu line item from
+ */
+ getLiSource: function( source ) {
+ var _this = this;
+ //See if the source is currently "on"
+ var sourceIcon = ( this.isSourceEnabled( source ) )? 'bullet' : 'radio-on';
+ if( source.title ) {
+ return $.getLineItem( source.title, sourceIcon, function() {
+ _this.selectTextSource( source );
+ }, 'captionRow', { 'caption-id' : source.id } );
+ }
+ if( source.srclang ) {
+ var langKey = source.srclang.toLowerCase();
+ return $.getLineItem(
+ mw.msg('mwe-timedtext-key-language', langKey, _this.getLanguageName ( langKey ) ),
+ sourceIcon,
+ function() {
+ // select the current text source:
+ _this.selectTextSource( source );
+ },
+ 'captionRow',
+ { 'caption-id' : source.id }
+ );
+ }
+ },
+
+ /**
+ * Get language name from language key
+ * @param {String} lang_key Language key
+ */
+ getLanguageName: function( lang_key ) {
+ if( mw.Language.names[ lang_key ]) {
+ return mw.Language.names[ lang_key ];
+ }
+ return false;
+ },
+
+
+ /**
+ * set the layout mode
+ * @param {Object} layoutMode The selected layout mode
+ */
+ setLayoutMode: function( layoutMode ) {
+ var _this = this;
+ mw.log("TimedText:: setLayoutMode: " + layoutMode + ' ( old mode: ' + _this.config.layout + ' )' );
+ if( ( layoutMode != _this.config.layout ) || _this.firstLoad ) {
+ // Update the config and redraw layout
+ _this.config.layout = layoutMode;
+ // Update the display:
+ _this.updateLayout();
+ _this.firstLoad = false;
+ }
+ _this.markLayoutActive( layoutMode );
+ },
+
+ toggleCaptions: function(){
+ mw.log( "TimedText:: toggleCaptions was:" + this.config.layout );
+ if( this.config.layout == 'off' ){
+ this.setLayoutMode( this.defaultDisplayMode );
+ } else {
+ this.setLayoutMode( 'off' );
+ }
+ },
+ /**
+ * Updates the timed text layout ( should be called when config.layout changes )
+ */
+ updateLayout: function() {
+ mw.log( "TimedText:: updateLayout " );
+ var $playerTarget = this.embedPlayer.getInterface();
+ if( $playerTarget ) {
+ // remove any existing caption containers:
+ $playerTarget.find('.captionContainer,.captionsOverlay').remove();
+ }
+ this.refreshDisplay();
+ },
+
+ /**
+ * Select a new source
+ *
+ * @param {Object} source Source object selected
+ */
+ selectTextSource: function( source ) {
+ var _this = this;
+ mw.log("TimedText:: selectTextSource: select lang: " + source.srclang );
+
+ // enable last non-off layout:
+ _this.setLayoutMode( _this.lastLayout );
+
+ // For some reason we lose binding for the menu ~sometimes~ re-bind
+ this.bindTextButton( this.embedPlayer.getInterface().find('timed-text') );
+
+ this.currentLangKey = source.srclang;
+ this.currentLangDir = null;
+
+ // Update the config language if the source includes language
+ if( source.srclang ){
+ this.config.userLanguage = source.srclang;
+ }
+
+ if( source.kind ){
+ this.config.userKind = source.kind;
+ }
+
+ // (@@todo update kind & setup kind language buckets? )
+
+ // Remove any other sources selected in sources kind
+ this.enabledSources = [];
+
+ this.enabledSources.push( source );
+
+ // Set any existing text target to "loading"
+ if( !source.loaded ) {
+ var $playerTarget = this.embedPlayer.getInterface();
+ $playerTarget.find('.track').text( mw.msg('mwe-timedtext-loading-text') );
+ // Load the text:
+ source.load( function(){
+ // Refresh the interface:
+ _this.refreshDisplay();
+ });
+ } else {
+ _this.refreshDisplay();
+ }
+
+ _this.markActive( source );
+
+ // Trigger the event
+ $( this.embedPlayer ).trigger( 'TimedText_ChangeSource' );
+ },
+
+ /**
+ * Refresh the display, updates the timedText layout, menu, and text display
+ * also updates the cookie preference.
+ *
+ * Called after a user option change
+ */
+ refreshDisplay: function() {
+ // Update the configuration object
+ $.cookie( 'TimedText.Preferences', JSON.stringify( this.config ) );
+
+ // Empty out previous text to force an interface update:
+ this.prevText = [];
+
+ // Refresh the Menu (if it has a target to refresh)
+ mw.log( 'TimedText:: bind menu refresh display' );
+ this.buildMenu();
+ this.resizeInterface();
+
+ // add an empty catption:
+ this.displayTextTarget( $( '<span /> ').text( '') );
+
+ // Issues a "monitor" command to update the timed text for the new layout
+ this.monitor();
+ },
+
+ /**
+ * Builds the language source list menu
+ * Cehck if the "track" tags had the "kind" attribute.
+ *
+ * The kind attribute forms "categories" of text tracks like "subtitles",
+ * "audio description", "chapter names". We check for these categories
+ * when building out the language menu.
+ */
+ getLanguageMenu: function() {
+ var _this = this;
+
+ // See if we have categories to worry about
+ // associative array of SUB etc categories. Each kind contains an array of textSources.
+ var categorySourceList = {};
+ var sourcesWithCategoryCount = 0;
+
+ // ( All sources should have a kind (depreciate )
+ var sourcesWithoutCategory = [ ];
+ for( var i=0; i < this.textSources.length; i++ ) {
+ var source = this.textSources[ i ];
+ if( source.kind ) {
+ var categoryKey = source.kind ;
+ // Init Category menu item if it does not already exist:
+ if( !categorySourceList[ categoryKey ] ) {
+ // Set up catList pointer:
+ categorySourceList[ categoryKey ] = [];
+ sourcesWithCategoryCount++;
+ }
+ // Append to the source kind key menu item:
+ categorySourceList[ categoryKey ].push(
+ _this.getLiSource( source )
+ );
+ }else{
+ sourcesWithoutCategory.push( _this.getLiSource( source ) );
+ }
+ }
+ var $langMenu = $('<ul>');
+ // Check if we have multiple categories ( if not just list them under the parent menu item)
+ if( sourcesWithCategoryCount > 1 ) {
+ for(var categoryKey in categorySourceList) {
+ var $catChildren = $('<ul>');
+ for(var i=0; i < categorySourceList[ categoryKey ].length; i++) {
+ $catChildren.append(
+ categorySourceList[ categoryKey ][i]
+ );
+ }
+ // Append a cat menu item for each kind list
+ // Give grep a chance to find the usages:
+ // mwe-timedtext-textcat-cc, mwe-timedtext-textcat-sub, mwe-timedtext-textcat-tad,
+ // mwe-timedtext-textcat-ktv, mwe-timedtext-textcat-tik, mwe-timedtext-textcat-ar,
+ // mwe-timedtext-textcat-nb, mwe-timedtext-textcat-meta, mwe-timedtext-textcat-trx,
+ // mwe-timedtext-textcat-lrc, mwe-timedtext-textcat-lin, mwe-timedtext-textcat-cue
+ $langMenu.append(
+ $.getLineItem( mw.msg( 'mwe-timedtext-textcat-' + categoryKey.toLowerCase() ) ).append(
+ $catChildren
+ )
+ );
+ }
+ } else {
+ for(var categoryKey in categorySourceList) {
+ for(var i=0; i < categorySourceList[ categoryKey ].length; i++) {
+ $langMenu.append(
+ categorySourceList[ categoryKey ][i]
+ );
+ }
+ }
+ }
+ // Add any remaning sources that did nto have a category
+ for(var i=0; i < sourcesWithoutCategory.length; i++) {
+ $langMenu.append( sourcesWithoutCategory[i] );
+ }
+
+ return $langMenu;
+ },
+
+ /**
+ * Updates a source display in the interface for a given time
+ * @param {object} source Source to update
+ * @param {number} time Caption time used to add and remove active captions.
+ */
+ updateSourceDisplay: function ( source, time ) {
+ var _this = this;
+ if( this.timeOffset ){
+ time = time + parseInt( this.timeOffset );
+ }
+
+ // Get the source text for the requested time:
+ var activeCaptions = source.getCaptionForTime( time );
+ var addedCaption = false;
+ // Show captions that are on:
+ $.each( activeCaptions, function( capId, caption ){
+ var $cap = _this.embedPlayer.getInterface().find( '.track[data-capId="' + capId +'"]');
+ if( caption.content != $cap.html() ){
+ // remove old
+ $cap.remove();
+ // add the updated value:
+ _this.addCaption( source, capId, caption );
+ addedCaption = true;
+ }
+ });
+
+ // hide captions that are off:
+ _this.embedPlayer.getInterface().find( '.track' ).each(function( inx, caption){
+ if( !activeCaptions[ $( caption ).attr('data-capId') ] ){
+ if( addedCaption ){
+ $( caption ).remove();
+ } else {
+ $( caption ).fadeOut( mw.config.get('EmbedPlayer.MonitorRate'), function(){$(this).remove();} );
+ }
+ }
+ });
+ },
+ addCaption: function( source, capId, caption ){
+ if( this.getLayoutMode() == 'off' ){
+ return ;
+ }
+
+ // use capId as a class instead of id for easy selections and no conflicts with
+ // multiple players on page.
+ var $textTarget = $('<div />')
+ .addClass( 'track' )
+ .attr( 'data-capId', capId )
+ .hide();
+
+ // Update text ( use "html" instead of "text" so that subtitle format can
+ // include html formating
+ // TOOD we should scrub this for non-formating html
+ $textTarget.append(
+ $('<span>')
+ .addClass( 'ttmlStyled' )
+ .css( 'pointer-events', 'auto')
+ .css( this.getCaptionCss() )
+ .append(
+ $('<span>')
+ // Prevent background (color) overflowing TimedText
+ // http://stackoverflow.com/questions/9077887/avoid-overlapping-rows-in-inline-element-with-a-background-color-applied
+ .css( 'position', 'relative' )
+ .html( caption.content )
+ )
+ );
+
+
+ // Add/update the lang option
+ $textTarget.attr( 'lang', source.srclang.toLowerCase() );
+
+ // Update any links to point to a new window
+ $textTarget.find( 'a' ).attr( 'target', '_blank' );
+
+ // Add TTML or other complex text styles / layouts if we have ontop captions:
+ if( this.getLayoutMode() == 'ontop' ){
+ if( caption.css ){
+ $textTarget.css( caption.css );
+ } else {
+ $textTarget.css( this.getDefaultStyle() );
+ }
+ }
+ // Apply any custom style ( if we are ontop of the video )
+ this.displayTextTarget( $textTarget );
+
+ // apply any interface size adjustments:
+ $textTarget.css( this.getInterfaceSizeTextCss({
+ 'width' : this.embedPlayer.getInterface().width(),
+ 'height' : this.embedPlayer.getInterface().height()
+ })
+ );
+
+ // Update the style of the text object if set
+ if( caption.styleId ){
+ var capCss = source.getStyleCssById( caption.styleId );
+ $textTarget.find('span.ttmlStyled').css(
+ capCss
+ );
+ }
+ $textTarget.fadeIn('fast');
+ },
+ displayTextTarget: function( $textTarget ){
+ var embedPlayer = this.embedPlayer;
+ var $interface = embedPlayer.getInterface();
+ var controlBarHeight = embedPlayer.controlBuilder.getHeight();
+
+ if( this.getLayoutMode() == 'off' ){
+ // sync player size per audio player:
+ if( embedPlayer.isAudio() ){
+ $interface.find( '.overlay-win' ).css( 'top', controlBarHeight );
+ $interface.css( 'height', controlBarHeight );
+ }
+ return;
+ }
+
+ if( this.getLayoutMode() == 'ontop' ){
+ this.addTextOverlay(
+ $textTarget
+ );
+ } else if( this.getLayoutMode() == 'below' ){
+ this.addTextBelowVideo( $textTarget );
+ } else {
+ mw.log("Possible Error, layout mode not recognized: " + this.getLayoutMode() );
+ }
+
+ // sync player size per audio player:
+ if( embedPlayer.isAudio() && embedPlayer.getInterface().height() < 80 ){
+ $interface.find( '.overlay-win' ).css( 'top', 80);
+ $interface.css( 'height', 80 );
+
+ $interface.find('.captionsOverlay' )
+ .css('bottom', embedPlayer.controlBuilder.getHeight() )
+ }
+
+ },
+ getDefaultStyle: function(){
+ var defaultBottom = 15;
+ if( this.embedPlayer.controlBuilder.isOverlayControls() && !this.embedPlayer.getInterface().find( '.control-bar' ).is( ':hidden' ) ) {
+ defaultBottom += this.embedPlayer.controlBuilder.getHeight();
+ }
+ var baseCss = {
+ 'position':'absolute',
+ 'bottom': defaultBottom,
+ 'width': '100%',
+ 'display': 'block',
+ 'opacity': .8,
+ 'text-align': 'center'
+ };
+ baseCss =$.extend( baseCss, this.getInterfaceSizeTextCss({
+ 'width' : this.embedPlayer.getInterface().width(),
+ 'height' : this.embedPlayer.getInterface().height()
+ }));
+ return baseCss;
+ },
+ addTextOverlay: function( $textTarget ){
+ var _this = this;
+ var $captionsOverlayTarget = this.embedPlayer.getInterface().find('.captionsOverlay');
+ var layoutCss = {
+ 'left': 0,
+ 'top': 0,
+ 'bottom': 0,
+ 'right': 0,
+ 'position': 'absolute',
+ 'direction': this.getCurrentLangDir(),
+ 'z-index': mw.config.get( 'EmbedPlayer.FullScreenZIndex' )
+ };
+
+ if( $captionsOverlayTarget.length == 0 ){
+ // TODO make this look more like addBelowVideoCaptionsTarget
+ $captionsOverlayTarget = $( '<div />' )
+ .addClass( 'captionsOverlay' )
+ .css( layoutCss )
+ .css('pointer-events', 'none');
+ this.embedPlayer.getVideoHolder().append( $captionsOverlayTarget );
+ }
+ // Append the text:
+ $captionsOverlayTarget.append( $textTarget );
+
+ },
+ /**
+ * Applies the default layout for a text target
+ */
+ addTextBelowVideo: function( $textTarget ) {
+ var $playerTarget = this.embedPlayer.getInterface();
+ // Get the relative positioned player class from the controlBuilder:
+ this.embedPlayer.controlBuilder.keepControlBarOnScreen = true;
+ if( !$playerTarget.find('.captionContainer').length || this.embedPlayer.useNativePlayerControls() ) {
+ this.addBelowVideoCaptionContainer();
+ }
+ $playerTarget.find('.captionContainer').html(
+ $textTarget.css( {
+ 'color':'white'
+ } )
+ );
+ },
+ addBelowVideoCaptionContainer: function(){
+ var _this = this;
+ mw.log( "TimedText:: addBelowVideoCaptionContainer" );
+ var $playerTarget = this.embedPlayer.getInterface();
+ if( $playerTarget.find('.captionContainer').length ) {
+ return ;
+ }
+ // Append after video container
+ this.embedPlayer.getVideoHolder().after(
+ $('<div>').addClass( 'captionContainer block' )
+ .css({
+ 'width' : '100%',
+ 'height' : mw.config.get( 'TimedText.BelowVideoBlackBoxHeight' ) + 'px',
+ 'background-color' : '#000',
+ 'text-align' : 'center',
+ 'padding-top' : '5px'
+ } )
+ );
+
+ _this.embedPlayer.triggerHelper('updateLayout');
+ },
+ /**
+ * Resize the interface for layoutMode == 'below' ( if not in full screen)
+ */
+ resizeInterface: function(){
+ var _this = this;
+ if( !_this.embedPlayer.controlBuilder ){
+ // too soon
+ return ;
+ }
+ if( !_this.embedPlayer.controlBuilder.inFullScreen && _this.originalPlayerHeight ){
+ _this.embedPlayer.triggerHelper( 'resizeIframeContainer', [{'height' : _this.originalPlayerHeight}] );
+ } else {
+ // removed resize on container content, since syncPlayerSize calls now handle keeping player aspect.
+ _this.embedPlayer.triggerHelper('updateLayout');
+ }
+ },
+ /**
+ * Build css for caption using this.options
+ */
+ getCaptionCss: function() {
+ return {};
+ }
+ };
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.style.TimedText.css b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.style.TimedText.css
new file mode 100644
index 00000000..e924ba34
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.style.TimedText.css
@@ -0,0 +1,18 @@
+.ttmlStyled {
+ color: white;
+ letter-spacing: 0.04em;
+ text-align: center;
+ padding: 0.2em;
+ /*
+ // Text shadow is too slow with current browsers use background-color
+ text-shadow:0 2px 1px #000000, -1px 3px 1px #000000, -2px 2px 1px #000000, -2px 1px 1px #000000, -2px 0 1px #000000, 2px 2px 1px #000000, 1px 2px 1px #000000, 0 -2px 1px #000000, 2px -2px 1px #000000, -2px -1px 1px #000000, -1px -3px 1px #000000, -3px -2px 1px #000000, 0 0 25px #000000, 0 0 35px #000000, 0 0 35px #000000, 0 0 31px #FFFFFF, 0 0 31px #FFFFFF, 0 0 31px #FFFFFF;
+ */
+ background-color: #333;
+}
+.ttmlStyled a {
+ text-decoration: none;
+ color : #BBF;
+}
+.ttmlStyled a:visited{
+ color : #BBF;
+}
diff --git a/extensions/TimedMediaHandler/README b/extensions/TimedMediaHandler/README
new file mode 100644
index 00000000..c37c5ad8
--- /dev/null
+++ b/extensions/TimedMediaHandler/README
@@ -0,0 +1,127 @@
+== TimedMediaHandler ==
+
+This extension provides a media handler for the Ogg, WebM, mp4 container format.
+When enabled, a player will be automatically embedded in the file description
+page, or any wiki page while still using the same syntax as for images.
+
+* Broad support for input file formats
+* Transcoder to make video at web resolutions when embedding clips in a page
+* include support for timed Text per the w3c "track" recommendation
+* use embedPlayer mwEmbed javascript module for playback
+
+To install this extension, add the following to the end of your
+LocalSettings.php:
+
+ // You need mwEmbedSupport ( if not already added )
+ require( "$IP/extensions/MwEmbedSupport/MwEmbedSupport.php" );
+
+ // TimedMediaHandler
+ require( "$IP/extensions/TimedMediaHandler/TimedMediaHandler.php" );
+
+
+== Running Transcodes ==
+
+Transcoding a video to another resolution or format takes a good amount which
+prevents that processing to be handled as a web service. Instead, the extension
+implements an asynchronous job, named webVideoTranscode, which you must be
+running regularly as your web server user.
+
+The job can be run using the MediaWiki maintenance/runJobs.php utility (do not
+forget to su as a webserver user):
+
+ php runJobs.php --type webVideoTranscode --maxjobs 1
+
+
+== Kaltura HTML5 player library ==
+
+TimedMediaHandler uses the Kaltura HTML5 player library for video playback, it
+relies on the <video> element as well as JavaScript.
+
+For more information about the player library visit:
+ http://www.html5video.org/kaltura-player/docs
+
+
+== Libav ==
+
+We use Libav for two purposes:
+ - creating still images of videos (aka thumbnails)
+ - transcoding WebM, H.264 videos
+
+Wikimedia currently uses libav as shipped in Ubuntu 12.04 (libav 0.8.x).
+For best experience use that or any later release from http://libav.org.
+
+On Ubuntu/Debian:
+ apt-get install libav-tools
+
+For H.264 support:
+ apt-get install libav-tools libavcodec-extra-53
+
+If you operating system does not include the required libav software,
+you can download static builds for multiple platforms at:
+ http://firefogg.org/nightly/
+
+You can also build libav/ffmpeg from source.
+Guide for building ffmpeg with H.264 for Ubuntu:
+https://ffmpeg.org/trac/ffmpeg/wiki/UbuntuCompilationGuide
+
+Some old versions of FFmpeg had a bug which made it extremely slow to seek in
+large theora videos in order to generate a thumbnail. If you are using an old
+version of FFmpeg and find that performance is extremely poor (tens of seconds)
+to generate thumbnails of theora videos that are several minutes or more in
+length. Please update to a more recent version.
+
+In MediaWiki configuration, after the require line in LocalSettings.php, you
+will have to specify the FFmpeg binary location with:
+
+ $wgFFmpegLocation = '/path/to/ffmpeg';
+
+Default being `/usr/bin/avconv`.
+
+
+== ffmpeg2theora ==
+
+We use ffmpeg2theora for extract metadata from videos, you will need a copy on
+your server. For best experience, use the latest release of ffmpeg2theora. At a
+minimum you need to use ffmpeg2thoera 0.27.
+
+You can download static ffmpeg2theora builds for multiple platforms at:
+http://firefogg.org/nightly/
+
+Set the ffmpeg2theora binary location with:
+
+ $wgFFmpeg2theoraLocation = '/path/to/ffmpeg2theora';
+
+Default being `/usr/bin/ffmpeg2theora`.
+
+oggThumb
+-------
+
+We use oggvideotools for creating still images of videos, you will need a copy on your
+server.
+
+Set the oggThumb binary location with:
+
+ $wgOggThumbLocation = '/path/to/oggThumb';
+
+Download oggThumb from: http://dev.streamnik.de/oggvideotools.html
+
+== PEAR File_Ogg ==
+
+Tim Starling, a Wikimedia developer, forked the PEAR File_Ogg package and
+improved it significantly to support this extension.
+
+The PEAR bundle is licensed under the LGPL, you can get informations about
+this package on the pear webpage:
+
+ http://pear.php.net/package/File_Ogg
+
+== getID3 ==
+
+getID3 is used for metadata of WebM files.
+
+getID3() by James Heinrich <info@getid3.org>
+available at http://getid3.sourceforge.net
+or http://www.getid3.org/
+
+getID3 code is released under the GNU GPL:
+http://www.gnu.org/copyleft/gpl.html
diff --git a/extensions/TimedMediaHandler/SpecialOrphanedTimedText.php b/extensions/TimedMediaHandler/SpecialOrphanedTimedText.php
new file mode 100644
index 00000000..52e86bf4
--- /dev/null
+++ b/extensions/TimedMediaHandler/SpecialOrphanedTimedText.php
@@ -0,0 +1,258 @@
+<?php
+/**
+ * Implements Special:OrphanedTimedText
+ *
+ * @author Brian Wolff
+ * @file
+ * @ingroup SpecialPage
+ */
+
+/**
+ * Lists TimedText pages that don't have a corresponding video.
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialOrphanedTimedText extends PageQueryPage {
+
+ /** @var Array with keys being names of valid files */
+ private $existingFiles;
+
+ public function __construct( $name = 'OrphanedTimedText' ) {
+ parent::__construct( $name );
+ }
+
+ /**
+ * This is alphabetical, so sort ascending.
+ */
+ public function sortDescending() {
+ return false;
+ }
+
+ /**
+ * Should this be cached?
+ *
+ * This query is actually almost cheap given the current
+ * number of things in TimedText namespace.
+ */
+ public function isExpensive() {
+ return true;
+ }
+
+ /**
+ * Main execution function
+ *
+ * @param $par String subpage
+ */
+ public function execute( $par ) {
+ global $wgEnableLocalTimedText;
+
+ if ( !$wgEnableLocalTimedText ) {
+ $this->setHeaders();
+ $this->getOutput()->addWikiMsg( 'orphanedtimedtext-notimedtext' );
+ return;
+ } elseif ( !$this->canExecuteQuery() ) {
+ $this->setHeaders();
+ $this->outputHeader();
+ $this->getOutput()->addWikiMsg( 'orphanedtimedtext-unsupported' );
+ return;
+ }
+ return parent::execute( $par );
+ }
+
+ /**
+ * Can we cache the results of this query?
+ *
+ * Only if we support the query.
+ * @return bool
+ */
+ public function isCacheable() {
+ return $this->canExecute();
+ }
+
+ /**
+ * List in Special:SpecialPages?
+ *
+ * @return bool
+ */
+ public function isListed() {
+ return $this->canExecute();
+ }
+
+ /**
+ * Can we execute this special page?
+ *
+ * The query uses a mysql specific feature (substring_index), so disable on non mysql dbs.
+ *
+ * @return bool
+ */
+ private function canExecuteQuery() {
+ $dbr = wfGetDB( DB_SLAVE );
+ return $dbr->getType() === 'mysql';
+ }
+
+ /**
+ * Can we execute this special page
+ *
+ * That is, db is mysql, and TimedText namespace enabled.
+ */
+ private function canExecute() {
+ global $wgEnableLocalTimedText;
+
+ return $this->canExecuteQuery() && $wgEnableLocalTimedText;
+ }
+
+ /**
+ * Get query info
+ *
+ * The query here is meant to retrieve all pages in the TimedText namespace,
+ * such that if you strip the last two extensions (e.g. Foo.bar.baz.en.srt -> Foo.bar.baz)
+ * there is no corresponding img_name in image table. So if there is a page in TimedText
+ * namespace named TimedText:My.Dog.webm.ceb.srt, it will include it in the list provided
+ * that File:My.Dog.webm is not uploaded.
+ *
+ * TimedText does not support file redirects or foreign files, so we don't have
+ * to worry about those.
+ *
+ * Potentially this should maybe also include pages not ending in
+ * .<valid lang code>.srt . However, determining what a valid lang code
+ * is, is pretty hard (although perhaps it could check if its [a-z]{2,3}
+ * however then we've got things like roa-tara, cbk-zam, etc)
+ * and TimedText throws away the final .srt extension and will work with
+ * any extension, so things not ending in .srt arguably aren't oprhaned.
+ *
+ * @note This uses "substring_index" which is a mysql extension.
+ * @return Array Standard query info values.
+ */
+ function getQueryInfo() {
+ $tables = array( 'page', 'image' );
+ $fields = array(
+ 'namespace' => 'page_namespace',
+ 'title' => 'page_title',
+ 'value' => 0,
+ );
+ $conds = array(
+ 'img_name' => null,
+ 'page_namespace' => NS_TIMEDTEXT,
+ );
+
+ // Now for the complicated bit
+ // Note: This bit is mysql specific. Probably could do something
+ // equivalent in postgress via split_part or regex substr,
+ // but my sql-fu is not good enough to figure out how to do
+ // this in standard sql, or in sqlite.
+ $baseCond = 'substr( page_title, 1, length( page_title ) - '
+ . "length( substring_index( page_title, '.' ,-2 ) ) - 1 )";
+ $joinConds = array(
+ 'image' => array(
+ 'LEFT OUTER JOIN',
+ $baseCond . ' = img_name'
+ )
+ );
+ return array(
+ 'tables' => $tables,
+ 'fields' => $fields,
+ 'conds' => $conds,
+ 'join_conds' => $joinConds
+ );
+ }
+
+ public function getOrderFields() {
+ return array( 'namespace', 'title' );
+ }
+
+ /**
+ * Is the TimedText page really orphaned?
+ *
+ * Given a title like "TimedText:Some bit here.webm.en.srt"
+ * check to see if "File:Some bit here.webm" really exists (locally).
+ * @return bool True if we should cross out the line.
+ */
+ protected function existenceCheck( Title $title ) {
+ $fileTitle = $this->getCorrespondingFile( $title );
+ if ( !$fileTitle ) {
+ return $title && !$title->isKnown();
+ }
+ return !$title->isKnown() ||
+ ( isset( $this->existingFiles[ $fileTitle->getDBKey() ] )
+ && $this->existingFiles[$fileTitle->getDBKey()]->getHandler()
+ && $this->existingFiles[$fileTitle->getDBKey()]->getHandler() instanceof TimedMediaHandler );
+ }
+
+ /**
+ * Given a TimedText title, get the File title
+ *
+ * @return Title|null Title in File namespace. null on error.
+ */
+ private function getCorrespondingFile( Title $timedText ) {
+ if ( !$timedText ) {
+ return false;
+ }
+ $titleParts = explode( '.', $timedText->getDBkey() );
+ array_pop( $titleParts );
+ array_pop( $titleParts );
+ $fileTitle = Title::makeTitleSafe( NS_FILE, implode( '.', $titleParts ) );
+ return $fileTitle;
+ }
+
+ /**
+ * What group to include this page in on Special:SpecialPages
+ * @return String
+ */
+ protected function getGroupName() {
+ return 'media';
+ }
+
+ /**
+ * Preprocess result to do existence checks all at once.
+ *
+ * @param $db Database
+ * @param $res ResultWraper
+ */
+ public function preprocessResults( $db, $res ) {
+ parent::preprocessResults( $db, $res );
+
+ if ( !$res->numRows() ) {
+ return;
+ }
+
+ $filesToLookFor = array();
+ foreach( $res as $row ) {
+ $title = Title::makeTitle( $row->namespace, $row->title );
+ $fileTitle = $this->getCorrespondingFile( $title );
+ if ( !$fileTitle ) {
+ continue;
+ }
+ $filesToLookFor[] = array( 'title' => $fileTitle, 'ignoreRedirect' => true );
+ }
+ $this->existingFiles = RepoGroup::singleton()->getLocalRepo()->findFiles( $filesToLookFor );
+ $res->seek( 0 );
+ }
+
+ /**
+ * Format the result as a simple link to the page
+ *
+ * Based on parent class but with an existence check added.
+ *
+ * @param Skin $skin
+ * @param object $row Result row
+ * @return string
+ */
+ public function formatResult( $skin, $row ) {
+ global $wgContLang;
+
+ $title = Title::makeTitleSafe( $row->namespace, $row->title );
+
+ if ( $title instanceof Title ) {
+ $text = $wgContLang->convert( $title->getPrefixedText() );
+ $link = Linker::link( $title, htmlspecialchars( $text ) );
+ if ( $this->existenceCheck( $title ) ) {
+ // File got uploaded since this page was cached
+ $link = '<del>' . $link . '</del>';
+ }
+ return $link;
+ } else {
+ return Html::element( 'span', array( 'class' => 'mw-invalidtitle' ),
+ Linker::getInvalidTitleDescription( $this->getContext(), $row->namespace, $row->title ) );
+ }
+ }
+}
diff --git a/extensions/TimedMediaHandler/SpecialTimedMediaHandler.php b/extensions/TimedMediaHandler/SpecialTimedMediaHandler.php
new file mode 100644
index 00000000..46f2fef8
--- /dev/null
+++ b/extensions/TimedMediaHandler/SpecialTimedMediaHandler.php
@@ -0,0 +1,235 @@
+<?php
+/**
+ * Special:TimedMediaHandler
+ *
+ * Show some information about unprocessed jobs
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+class SpecialTimedMediaHandler extends SpecialPage {
+ private $transcodeStates = array(
+ 'active' => 'transcode_time_startwork IS NOT NULL AND transcode_time_success IS NULL AND transcode_time_error IS NULL',
+ 'failed' => 'transcode_error != "" AND transcode_time_success IS NULL',
+ 'queued' => 'transcode_time_startwork IS NULL AND transcode_time_success IS NULL AND transcode_time_error IS NULL',
+
+ );
+ private $formats = array(
+ 'ogg' => 'img_major_mime="application" AND img_minor_mime = "ogg"',
+ 'webm' => 'img_major_mime="video" AND img_minor_mime = "webm"',
+ );
+ private $audioFormats = array(
+ 'ogg' => 'img_major_mime="application" AND img_minor_mime = "ogg"',
+ 'webm' => 'img_major_mime="audio" AND img_minor_mime = "webm"',
+ 'flac' => 'img_major_mime="audio" AND img_minor_mime="x-flac"',
+ 'wav' => 'img_major_mime="audio" AND img_minor_mime="wav"',
+ );
+
+ public function __construct( $request = null, $par = null ) {
+ parent::__construct( 'TimedMediaHandler', 'transcode-status' );
+ }
+
+ public function execute( $par ) {
+ $this->setHeaders();
+ $out = $this->getOutput();
+
+ $out->addModuleStyles( 'mediawiki.special' );
+
+ $stats = $this->getStats();
+
+ foreach( array( 'audios', 'videos' ) as $type ) {
+ // for grep timedmedia-audios, timedmedia-videos
+ $out->addHTML(
+ "<h2>"
+ . $this->msg( 'timedmedia-' . $type )->numParams( $stats[$type]['total'] )->escaped()
+ . "</h2>"
+ );
+ // Give grep a chance to find the usages: timedmedia-ogg-videos, timedmedia-webm-videos,
+ // timedmedia-ogg-audios, timedmedia-flac-audios, timedmedia-wav-audios
+ $formats = $type == 'audios' ? $this->audioFormats : $this->formats;
+ foreach ( $formats as $format => $condition ) {
+ if ( $stats[ $type ][ $format ] ) {
+ $out->addHTML(
+ $this->msg( "timedmedia-$format-$type" )->numParams( $stats[ $type ][ $format ] )->escaped()
+ . Html::element( 'br' )
+ );
+ }
+ }
+ }
+
+ $states = $this->getStates();
+ $this->renderState( $out, 'transcodes', $states, false );
+ foreach ( $this->transcodeStates as $state => $condition ) {
+ $this->renderState( $out, $state, $states );
+ }
+ }
+
+ /**
+ * @param OutputPage $out
+ * @param $state
+ * @param $states
+ * @param bool $showTable
+ */
+ private function renderState ( $out, $state, $states, $showTable = true ) {
+ global $wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet;
+ $allTranscodes = array_merge( $wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet );
+ if ( $states[ $state ][ 'total' ] ) {
+ // Give grep a chance to find the usages:
+ // timedmedia-derivative-state-transcodes, timedmedia-derivative-state-active,
+ // timedmedia-derivative-state-queued, timedmedia-derivative-state-failed
+ $out->addHTML(
+ "<h2>"
+ . $this->msg( 'timedmedia-derivative-state-' . $state )->numParams( $states[ $state ]['total'] )->escaped()
+ . "</h2>"
+ );
+ foreach( $allTranscodes as $key ) {
+ if ( isset( $states[ $state ] )
+ && isset( $states[ $state ][ $key ] )
+ && $states[ $state ][ $key ] ) {
+ $out->addHTML(
+ htmlspecialchars( $this->getLanguage()->formatNum( $states[ $state ][ $key ] ) )
+ . ' '
+ . $this->msg( 'timedmedia-derivative-desc-' . $key )->escaped()
+ . "<br>" );
+ }
+ }
+ if ( $showTable ) {
+ $out->addHTML( $this->getTranscodesTable( $state ) );
+ }
+ }
+ }
+
+ private function getTranscodes ( $state, $limit = 50 ) {
+ global $wgMemc;
+ $memcKey = wfMemcKey( 'TimedMediaHandler', 'files', $state );
+ $files = $wgMemc->get( $memcKey );
+ if ( !$files ) {
+ $dbr = wfGetDB( DB_SLAVE );
+ $files = array();
+ $res = $dbr->select(
+ 'transcode',
+ '*',
+ $this->transcodeStates[ $state ],
+ __METHOD__,
+ array( 'LIMIT' => $limit, 'ORDER BY' => 'transcode_time_error DESC' )
+ );
+ foreach( $res as $row ) {
+ $transcode = array();
+ foreach( $row as $k => $v ){
+ $transcode[ str_replace( 'transcode_', '', $k ) ] = $v;
+ }
+ $files[] = $transcode;
+ }
+ $wgMemc->add( $memcKey, $files, 60 );
+ }
+ return $files;
+ }
+
+ private function getTranscodesTable ( $state, $limit = 50 ) {
+ $table = '<table class="wikitable">' . "\n"
+ . '<tr>'
+ . '<th>' . $this->msg( 'timedmedia-transcodeinfo' )->escaped() . '</th>'
+ . '<th>' . $this->msg( 'timedmedia-file' )->escaped() . '</th>'
+ . '</tr>'
+ . "\n";
+
+ foreach( $this->getTranscodes( $state, $limit ) as $transcode ) {
+ $title = Title::newFromText( $transcode[ 'image_name' ], NS_FILE );
+ $table .= '<tr>'
+ . '<td>' . $this->msg('timedmedia-derivative-desc-' . $transcode[ 'key' ] )->escaped() . '</td>'
+ . '<td>' . Linker::link( $title, $transcode[ 'image_name' ] ) . '</td>'
+ . '</tr>'
+ . "\n";
+ }
+ $table .= '</table>';
+ return $table;
+ }
+
+ private function getStats() {
+ global $wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet, $wgMemc;
+ $allTranscodes = array_merge( $wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet );
+
+ $memcKey= wfMemcKey( 'TimedMediaHandler', 'stats', '1' /* version */ );
+ $stats = $wgMemc->get( $memcKey );
+ if ( !$stats ) {
+ $dbr = wfGetDB( DB_SLAVE );
+ $stats = array();
+ $stats[ 'videos' ] = array( 'total' => 0 );
+ foreach( $this->formats as $format => $condition ) {
+ $stats[ 'videos' ][ $format ] = (int)$dbr->selectField(
+ 'image',
+ 'COUNT(*)',
+ 'img_media_type = "VIDEO" AND (' . $condition . ')',
+ __METHOD__
+ );
+ $stats[ 'videos' ][ 'total' ] += $stats[ 'videos' ][ $format ];
+ }
+ $stats[ 'audios' ] = array( 'total' => 0 );
+ foreach( $this->audioFormats as $format => $condition ) {
+ $stats[ 'audios' ][ $format ] = (int)$dbr->selectField(
+ 'image',
+ 'COUNT(*)',
+ 'img_media_type = "AUDIO" AND (' . $condition . ')',
+ __METHOD__
+ );
+ $stats[ 'audios' ][ 'total' ] += $stats[ 'audios' ][ $format ];
+ }
+ }
+ return $stats;
+ }
+
+ private function getStates() {
+ global $wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet, $wgMemc;
+ $allTranscodes = array_merge( $wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet );
+
+ $memcKey = wfMemcKey( 'TimedMediaHandler', 'states' );
+ $states = $wgMemc->get( $memcKey );
+ if ( !$states ) {
+ $dbr = wfGetDB( DB_SLAVE );
+ $states = array();
+ $states[ 'transcodes' ] = array( 'total' => 0 );
+ foreach ( $this->transcodeStates as $state => $condition ) {
+ $states[ $state ] = array( 'total' => 0 );
+ foreach( $allTranscodes as $type ) {
+ // Important to pre-initialize, as can give
+ // warnings if you don't have a lot of things in transcode table.
+ $states[ $state ][ $type ] = 0;
+ }
+ }
+ foreach ( $this->transcodeStates as $state => $condition ) {
+ $cond = array( 'transcode_key' => $allTranscodes );
+ $cond[] = $condition;
+ $res = $dbr->select( 'transcode',
+ array('COUNT(*) as count', 'transcode_key'),
+ $cond,
+ __METHOD__,
+ array( 'GROUP BY' => 'transcode_key' )
+ );
+ foreach( $res as $row ) {
+ $key = $row->transcode_key;
+ $states[ $state ][ $key ] = $row->count;
+ $states[ $state ][ 'total' ] += $states[ $state ][ $key ];
+ }
+ }
+ $res = $dbr->select( 'transcode',
+ array( 'COUNT(*) as count', 'transcode_key' ),
+ array( 'transcode_key' => $allTranscodes ),
+ __METHOD__,
+ array( 'GROUP BY' => 'transcode_key' )
+ );
+ foreach( $res as $row ) {
+ $key = $row->transcode_key;
+ $states[ 'transcodes' ][ $key ] = $row->count;
+ $states[ 'transcodes' ][ $key ] -= $states[ 'queued' ][ $key ];
+ $states[ 'transcodes' ][ 'total' ] += $states[ 'transcodes' ][ $key ];
+ }
+ $wgMemc->add( $memcKey, $states, 60 );
+ }
+ return $states;
+ }
+
+ protected function getGroupName() {
+ return 'media';
+ }
+}
diff --git a/extensions/TimedMediaHandler/TimedMediaHandler.hooks.php b/extensions/TimedMediaHandler/TimedMediaHandler.hooks.php
new file mode 100644
index 00000000..70768479
--- /dev/null
+++ b/extensions/TimedMediaHandler/TimedMediaHandler.hooks.php
@@ -0,0 +1,485 @@
+<?php
+
+/**
+ * Hooks for TimedMediaHandler extension
+ *
+ * @file
+ * @ingroup Extensions
+ */
+
+class TimedMediaHandlerHooks {
+
+ // Register TimedMediaHandler namespace IDs
+ // These are configurable due to Commons history: T123823
+ // These need to be before registerhooks due to: T123695
+ public static function onSetupAfterCache() {
+ global $wgEnableLocalTimedText, $wgExtraNamespaces, $wgTimedTextNS;
+ if ( $wgEnableLocalTimedText ) {
+ define( "NS_TIMEDTEXT", $wgTimedTextNS );
+ define( "NS_TIMEDTEXT_TALK", $wgTimedTextNS +1 );
+
+ $wgExtraNamespaces[NS_TIMEDTEXT] = "TimedText";
+ $wgExtraNamespaces[NS_TIMEDTEXT_TALK] = "TimedText_talk";
+ } else {
+ $wgTimedTextNS = false;
+ }
+ return true;
+ }
+
+ // Register TimedMediaHandler Hooks
+ public static function register() {
+ global $wgHooks, $wgJobClasses, $wgJobTypesExcludedFromDefaultQueue, $wgMediaHandlers,
+ $wgResourceModules, $wgExcludeFromThumbnailPurge, $wgParserOutputHooks,
+ $wgFileExtensions, $wgTmhEnableMp4Uploads, $wgExtensionAssetsPath,
+ $wgMwEmbedModuleConfig, $timedMediaDir, $wgEnableLocalTimedText,
+ $wgTmhFileExtensions, $wgTmhTheoraTwoPassEncoding, $wgTmhWebPlayer;
+
+ // Remove mp4 if not enabled:
+ if( $wgTmhEnableMp4Uploads === false ){
+ $index = array_search( 'mp4', $wgFileExtensions );
+ if ( $index !== false ) {
+ array_splice( $wgFileExtensions, $index, 1 );
+ }
+ }
+
+ if( !class_exists( 'MwEmbedResourceManager' ) ) {
+ echo "TimedMediaHandler requires the MwEmbedSupport extension.\n";
+ exit( 1 );
+ }
+
+ // Register the Timed Media Handler javascript resources ( MwEmbed modules )
+ MwEmbedResourceManager::register( 'extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer' );
+ MwEmbedResourceManager::register( 'extensions/TimedMediaHandler/MwEmbedModules/TimedText' );
+
+ // Set the default webPath for this embed player extension
+ $wgMwEmbedModuleConfig['EmbedPlayer.WebPath'] = $wgExtensionAssetsPath .
+ '/' . basename ( $timedMediaDir ) . '/MwEmbedModules/EmbedPlayer';
+
+ // Setup media Handlers:
+ $wgMediaHandlers['application/ogg'] = 'OggHandlerTMH';
+ $wgMediaHandlers['audio/webm'] = 'WebMHandler';
+ $wgMediaHandlers['video/webm'] = 'WebMHandler';
+ $wgMediaHandlers['video/mp4'] = 'Mp4Handler';
+ $wgMediaHandlers['audio/x-flac'] = 'FLACHandler';
+ $wgMediaHandlers['audio/flac'] = 'FLACHandler';
+ $wgMediaHandlers['audio/wav'] = 'WAVHandler';
+
+ // Add transcode job class:
+ $wgJobClasses['webVideoTranscode'] = 'WebVideoTranscodeJob';
+
+ // Transcode jobs must be explicitly requested from the job queue:
+ $wgJobTypesExcludedFromDefaultQueue[] = 'webVideoTranscode';
+
+ $baseExtensionResource = array(
+ 'localBasePath' => __DIR__,
+ 'remoteExtPath' => 'TimedMediaHandler',
+ );
+
+ // Add the PopUpMediaTransform module ( specific to timedMedia handler ( no support in mwEmbed modules )
+ $wgResourceModules+= array(
+ 'mw.PopUpMediaTransform' => $baseExtensionResource + array(
+ 'scripts' => 'resources/mw.PopUpThumbVideo.js',
+ 'dependencies' => array( 'mw.MwEmbedSupport', 'mediawiki.Title' ),
+ ),
+ 'mw.PopUpMediaTransform.styles' => $baseExtensionResource + array(
+ 'position' => 'top',
+ 'styles' => 'resources/PopUpThumbVideo.css',
+ ),
+ 'mw.TMHGalleryHook.js' => $baseExtensionResource + array(
+ 'scripts' => 'resources/mw.TMHGalleryHook.js',
+ // position top needed as it needs to load before mediawiki.page.gallery
+ 'position' => 'top',
+ ),
+ 'embedPlayerIframeStyle'=> $baseExtensionResource + array(
+ 'styles' => 'resources/embedPlayerIframe.css',
+ ),
+ 'ext.tmh.transcodetable' => $baseExtensionResource + array(
+ 'scripts' => 'resources/ext.tmh.transcodetable.js',
+ 'styles' => 'resources/transcodeTable.css',
+ 'dependencies' => array(
+ 'mediawiki.api.edit',
+ 'mw.MwEmbedSupport',
+ ),
+ 'messages'=> array(
+ 'mwe-ok',
+ 'mwe-cancel',
+ 'timedmedia-reset-error',
+ 'timedmedia-reset',
+ 'timedmedia-reset-confirm'
+ )
+ ),
+ 'ext.tmh.TimedTextSelector' => $baseExtensionResource + array(
+ 'scripts' => 'resources/ext.tmh.TimedTextSelector.js',
+ ),
+ "mw.MediaWikiPlayerSupport" => $baseExtensionResource + array(
+ 'scripts' => 'resources/mw.MediaWikiPlayerSupport.js',
+ 'dependencies'=> 'mw.Api',
+ ),
+ // adds support MediaWikiPlayerSupport player bindings
+ "mw.MediaWikiPlayer.loader" => $baseExtensionResource + array(
+ 'loaderScripts' => 'resources/mw.MediaWikiPlayer.loader.js',
+ ),
+ );
+
+ // Add OgvJs-related modules for Safari/IE/Edge Ogg playback
+ $wgResourceModules += array(
+ 'ext.tmh.OgvJsSupport' => $baseExtensionResource + array(
+ 'scripts' => array(
+ 'MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv-support.js',
+ 'resources/ext.tmh.OgvJsSupport.js',
+ ),
+ 'targets' => array( 'mobile', 'desktop' ),
+ ),
+ 'ext.tmh.OgvJs' => $baseExtensionResource + array(
+ 'scripts' => array(
+ 'MwEmbedModules/EmbedPlayer/binPlayers/ogv.js/ogv.js',
+ ),
+ 'dependencies' => 'ext.tmh.OgvJsSupport',
+ 'targets' => array( 'mobile', 'desktop' ),
+ ),
+ );
+
+ // Setup a hook for iframe embed handling:
+ $wgHooks['ArticleFromTitle'][] = 'TimedMediaIframeOutput::iframeHook';
+
+ // When an upload completes ( check clear any existing transcodes )
+ $wgHooks['UploadComplete'][] = 'TimedMediaHandlerHooks::checkUploadComplete';
+
+ // When an image page is moved:
+ $wgHooks['TitleMove'][] = 'TimedMediaHandlerHooks::checkTitleMove';
+
+ // When image page is deleted so that we remove transcode settings / files.
+ $wgHooks['FileDeleteComplete'][] = 'TimedMediaHandlerHooks::onFileDeleteComplete';
+
+ // Add parser hook
+ $wgParserOutputHooks['TimedMediaHandler'] = array( 'TimedMediaHandler', 'outputHook' );
+
+ // Use a BeforePageDisplay hook to load the styles in pages that pull in media dynamically.
+ // (Special:Upload, for example, when there is an "existing file" warning.)
+ $wgHooks['BeforePageDisplay'][] = 'TimedMediaHandlerHooks::pageOutputHook';
+
+ // Make sure modules are loaded on image pages that don't have a media file in the wikitext.
+ $wgHooks['ImageOpenShowImageInlineBefore'][] = 'TimedMediaHandlerHooks::onImageOpenShowImageInlineBefore';
+
+ // Exclude transcoded assets from normal thumbnail purging
+ // ( a maintenance script could handle transcode asset purging)
+ if ( isset( $wgExcludeFromThumbnailPurge ) ) {
+ $wgExcludeFromThumbnailPurge = array_merge( $wgExcludeFromThumbnailPurge, $wgTmhFileExtensions );
+ // Also add the .log file ( used in two pass encoding )
+ // ( probably should move in-progress encodes out of web accessible directory )
+ $wgExcludeFromThumbnailPurge[] = 'log';
+ }
+
+ $wgHooks['LoadExtensionSchemaUpdates'][] = 'TimedMediaHandlerHooks::loadExtensionSchemaUpdates';
+
+ // Add unit tests
+ $wgHooks['UnitTestsList'][] = 'TimedMediaHandlerHooks::registerUnitTests';
+
+ /**
+ * Add support for the "TimedText" NameSpace
+ */
+ if ( $wgEnableLocalTimedText ) {
+ // Check for timed text page:
+ $wgHooks[ 'ArticleFromTitle' ][] = 'TimedMediaHandlerHooks::checkForTimedTextPage';
+ $wgHooks[ 'ArticleContentOnDiff' ][] = 'TimedMediaHandlerHooks::checkForTimedTextDiff';
+ } else {
+ // overwrite TimedText.ShowInterface for video with mw-provider=local
+ $wgMwEmbedModuleConfig['TimedText.ShowInterface.local'] = 'off';
+ }
+
+ // Add transcode status to video asset pages:
+ $wgHooks[ 'ImagePageAfterImageLinks' ][] = 'TimedMediaHandlerHooks::checkForTranscodeStatus';
+ $wgHooks[ 'NewRevisionFromEditComplete' ][] = 'TimedMediaHandlerHooks::onNewRevisionFromEditComplete';
+ $wgHooks[ 'ArticlePurge' ][] = 'TimedMediaHandlerHooks::onArticlePurge';
+
+ $wgHooks['LoadExtensionSchemaUpdates'][] = 'TimedMediaHandlerHooks::checkSchemaUpdates';
+ $wgHooks['wgQueryPages'][] = 'TimedMediaHandlerHooks::onwgQueryPages';
+ return true;
+ }
+
+ /**
+ * @param $imagePage ImagePage
+ * @param $wgOut OutputPage
+ * @return bool
+ */
+ public static function onImageOpenShowImageInlineBefore( $imagePage, $out ) {
+ $handler = $imagePage->getDisplayedFile()->getHandler();
+ if ( $handler !== false && $handler instanceof TimedMediaHandler ) {
+ TimedMediaHandler::outputHook( $out, null, null );
+ }
+ return true;
+ }
+
+ /**
+ * @param $title Title
+ * @param $article Article
+ * @return bool
+ */
+ public static function checkForTimedTextPage( &$title, &$article ){
+ global $wgTimedTextNS;
+ if ( $title->getNamespace() === $wgTimedTextNS ) {
+ $article = new TimedTextPage( $title );
+ }
+ return true;
+ }
+
+ /**
+ * @param $diffEngine DifferenceEngine
+ * @param $output OutputPage
+ * @return bool
+ */
+ public static function checkForTimedTextDiff( $diffEngine, $output ) {
+ global $wgTimedTextNS;
+ if ( $output->getTitle()->getNamespace() === $wgTimedTextNS ) {
+ $article = new TimedTextPage( $output->getTitle() );
+ $article->renderOutput( $output );
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Wraps the isTranscodableFile function
+ * @param $title Title
+ * @return bool
+ */
+ public static function isTranscodableTitle( $title ){
+ if( $title->getNamespace() != NS_FILE ){
+ return false;
+ }
+ $file = wfFindFile( $title );
+ return self::isTranscodableFile( $file );
+ }
+
+ /**
+ * Utility function to check if a given file can be "transcoded"
+ * @param $file File object
+ * @return bool
+ */
+ public static function isTranscodableFile( & $file ){
+ global $wgEnableTranscode, $wgEnabledAudioTranscodeSet;
+
+ // don't show the transcode table if transcode is disabled
+ if( !$wgEnableTranscode && !$wgEnabledAudioTranscodeSet ){
+ return false;
+ }
+ // Can't find file
+ if( !$file ){
+ return false;
+ }
+ // We can only transcode local files
+ if( !$file->isLocal() ){
+ return false;
+ }
+
+ $handler = $file->getHandler();
+ // Not able to transcode files without handler
+ if( !$handler ) {
+ return false;
+ }
+ $mediaType = $handler->getMetadataType( $file );
+ // If ogg or webm format and not audio we can "transcode" this file
+ $isAudio = $handler instanceof TimedMediaHandler && $handler->isAudio( $file );
+ if( ( $mediaType == 'webm' || $mediaType == 'ogg' || $mediaType =='mp4' )
+ && !$isAudio
+ ){
+ return true;
+ }
+ if( $isAudio && count( $wgEnabledAudioTranscodeSet ) ) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @param $article Article
+ * @param $html string
+ * @return bool
+ */
+ public static function checkForTranscodeStatus( $article, &$html ){
+ // load the file:
+ $file = wfFindFile( $article->getTitle() );
+ if( self::isTranscodableFile( $file ) ){
+ $html .= TranscodeStatusTable::getHTML( $file );
+ }
+ return true;
+ }
+
+ /**
+ * @param $image UploadBase
+ * @return bool
+ */
+ public static function checkUploadComplete( $upload ){
+ $file = $upload->getLocalFile();
+ // Check that the file is a transcodable asset:
+ if( $file && self::isTranscodableFile( $file ) ){
+ // Remove all the transcode files and db states for this asset
+ WebVideoTranscode::removeTranscodes( $file );
+ WebVideoTranscode::startJobQueue( $file );
+ }
+ return true;
+ }
+ /**
+ * Handle moved titles
+ *
+ * For now we just remove all the derivatives for the oldTitle. In the future we could
+ * look at moving the files, but right now thumbs are not moved, so I don't want to be
+ * inconsistent.
+ * @param $title Title
+ * @param $newTitle Title
+ * @param $user User
+ * @return bool
+ */
+ public static function checkTitleMove( $title, $newTitle, $user ){
+ if( self::isTranscodableTitle( $title ) ){
+ // Remove all the transcode files and db states for this asset
+ // ( will be re-added the first time the asset is displayed with its new title )
+ $file = wfFindFile( $title );
+ WebVideoTranscode::removeTranscodes( $file );
+ }
+ return true;
+ }
+
+ /**
+ * Hook to FileDeleteComplete
+ * remove transcodes on delete
+ * @param $file File
+ * @param $oldimage
+ * @param $article Article
+ * @param $user User
+ * @param $reason string
+ * @return bool
+ */
+ public static function onFileDeleteComplete( $file, $oldimage, $article, $user, $reason ) {
+ if ( !$oldimage ) {
+ if( self::isTranscodableFile( $file ) ){
+ WebVideoTranscode::removeTranscodes( $file );
+ }
+ }
+ return true;
+ }
+
+ /*
+ * If file gets reverted to a previous version, reset transcodes.
+ */
+ public static function onNewRevisionFromEditComplete( $article, Revision $rev, $baseID, User $user ) {
+ if ( $baseID !== false ) {
+ // Check if the article is a file and remove transcode files:
+ if( $article->getTitle()->getNamespace() == NS_FILE ) {
+ $file = wfFindFile( $article->getTitle() );
+ if( self::isTranscodableFile( $file ) ){
+ WebVideoTranscode::removeTranscodes( $file );
+ WebVideoTranscode::startJobQueue( $file );
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * When a user asks for a purge, perhaps through our handy "update transcode status"
+ * link, make sure we've got the updated set of transcodes. This'll allow a user or
+ * automated process to see their status and reset them.
+ */
+ public static function onArticlePurge( $article ) {
+ if( $article->getTitle()->getNamespace() == NS_FILE ) {
+ $file = wfFindFile( $article->getTitle() );
+ if( self::isTranscodableFile( $file ) ){
+ WebVideoTranscode::cleanupTranscodes( $file );
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Adds the transcode sql
+ * @param $updater DatabaseUpdater
+ * @return bool
+ */
+ public static function loadExtensionSchemaUpdates( $updater ){
+ $updater->addExtensionTable( 'transcode', __DIR__ . '/TimedMediaHandler.sql' );
+ return true;
+ }
+
+ /**
+ * Hook to add list of PHPUnit test cases.
+ * @param $files Array of files
+ * @return bool
+ */
+ public static function registerUnitTests( array &$files ) {
+ $testDir = __DIR__ . '/tests/phpunit/';
+ $testFiles = array(
+ 'TestTimeParsing.php',
+ 'TestApiUploadVideo.php',
+ 'TestVideoThumbnail.php',
+ 'TestVideoTranscode.php',
+ 'TestOggHandler.php',
+ 'TestTimedMediaTransformOutput.php',
+ 'TestTimedMediaHandler.php'
+ );
+ foreach( $testFiles as $fileName ){
+ $files[] = $testDir . $fileName;
+ }
+ return true;
+ }
+
+ /**
+ * Add JavaScript and CSS for special pages that may include timed media
+ * but which will not fire the parser hook.
+ *
+ * FIXME: There ought to be a better interface for determining whether the
+ * page is liable to contain timed media.
+ *
+ * @param $out OutputPage
+ * @param $sk
+ * @return bool
+ */
+ static function pageOutputHook( &$out, &$sk ){
+ global $wgTimedTextNS;
+
+ $title = $out->getTitle();
+ $namespace = $title->getNamespace();
+ $addModules = false;
+
+ if ( $namespace === NS_CATEGORY || $namespace === $wgTimedTextNS ) {
+ $addModules = true;
+ }
+
+ if ( $title->isSpecialPage() ) {
+ list( $name, /* subpage */ ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
+ if ( stripos( $name, 'file' ) !== false || stripos( $name, 'image' ) !== false
+ || $name === 'Search' || $name === 'GlobalUsage' ) {
+ $addModules = true;
+ }
+ }
+
+ if ( $addModules ) {
+ $out->addModuleScripts( 'mw.PopUpMediaTransform' );
+ $out->addModuleStyles( 'mw.PopUpMediaTransform.styles' );
+ }
+
+ return true;
+ }
+
+ public static function checkSchemaUpdates( DatabaseUpdater $updater ) {
+ $base = __DIR__ ;
+
+ switch ( $updater->getDB()->getType() ) {
+ case 'mysql':
+ case 'sqlite':
+ $updater->addExtensionTable( 'transcode', "$base/TimedMediaHandler.sql" ); // Initial install tables
+ $updater->addExtensionUpdate( array( 'addIndex', 'transcode', 'transcode_name_key',
+ "$base/archives/transcode_name_key.sql", true ) );
+ break;
+ case 'postgres':
+ //TODO
+ break;
+ }
+ return true;
+ }
+
+ public static function onwgQueryPages( $qp ) {
+ $qp[] = array( 'SpecialOrphanedTimedText', 'OrphanedTimedText' );
+ return true;
+ }
+}
diff --git a/extensions/TimedMediaHandler/TimedMediaHandler.i18n.alias.php b/extensions/TimedMediaHandler/TimedMediaHandler.i18n.alias.php
new file mode 100644
index 00000000..35c28ad8
--- /dev/null
+++ b/extensions/TimedMediaHandler/TimedMediaHandler.i18n.alias.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Aliases for special pages for extension TimedMediaHandler
+ *
+ * @file
+ * @ingroup Extensions
+ */
+// @codingStandardsIgnoreFile
+
+$specialPageAliases = array();
+
+/** English (English) */
+$specialPageAliases['en'] = array(
+ 'TimedMediaHandler' => array( 'TimedMediaHandler' ),
+ 'OrphanedTimedText' => array( 'OrphanedTimedText' ),
+);
+
+/** Arabic (Ų§Ł„Ų¹Ų±ŲØŁŠŲ©) */
+$specialPageAliases['ar'] = array(
+ 'TimedMediaHandler' => array( 'Ł…Ų¹Ų§Ł„Ų¬_Ų§Ł„Ł…ŁŠŲÆŁŠŲ§_Ų§Ł„Ų²Ł…Ł†ŁŠŲ©' ),
+ 'OrphanedTimedText' => array( 'Ł†Ųµ_Ų²Ł…Ł†ŁŠ_ŁŠŲŖŁŠŁ…' ),
+);
+
+/** Egyptian Arabic (Ł…ŲµŲ±Ł‰) */
+$specialPageAliases['arz'] = array(
+ 'TimedMediaHandler' => array( 'Ł…Ų¹Ų§Ł„Ų¬_Ų§Ł„Ł…ŁŠŲÆŁŠŲ§-Ų§Ł„Ų²Ł…Ł†ŁŠŁ‡' ),
+);
+
+/** German (Deutsch) */
+$specialPageAliases['de'] = array(
+ 'TimedMediaHandler' => array( 'TimedMedia-Steuerungsprogramm' ),
+ 'OrphanedTimedText' => array( 'Verwaister_TimedText' ),
+);
+
+/** Zazaki (Zazaki) */
+$specialPageAliases['diq'] = array(
+ 'TimedMediaHandler' => array( 'MısnayoÄŸĆ©MedyayaZemanın' ),
+);
+
+/** Estonian (eesti) */
+$specialPageAliases['et'] = array(
+ 'TimedMediaHandler' => array( 'Ajastatud_meediafailide_tƶƶtleja' ),
+);
+
+/** Hebrew (עב×Øי×Ŗ) */
+$specialPageAliases['he'] = array(
+ 'TimedMediaHandler' => array( 'מדיה_מ×Ŗוזמנ×Ŗ' ),
+ 'OrphanedTimedText' => array( 'טקהט_מ×Ŗוזמן_י×Ŗום' ),
+);
+
+/** Korean (ķ•œźµ­ģ–“) */
+$specialPageAliases['ko'] = array(
+ 'TimedMediaHandler' => array( 'ģžė§‰ėÆøė””ģ–“ķ•øė“¤ėŸ¬' ),
+);
+
+/** Macedonian (Š¼Š°ŠŗŠµŠ“Š¾Š½ŃŠŗŠø) */
+$specialPageAliases['mk'] = array(
+ 'TimedMediaHandler' => array( 'Š”ŠøŠ½Ń…Ń€Š¾Š½ŠøŠ·ŠøрŠ°Š½ŠøŠ”Š½ŠøŠ¼ŠŗŠø' ),
+ 'OrphanedTimedText' => array( 'ŠžŃŠ°Š¼ŠµŠ½ŠøŠ”ŠøŠ½Ń…Ń€Š¾Š½ŠøŠ·Š°Ń†ŠøŠø' ),
+);
+
+/** Malayalam (ą“®ą“²ą“Æą“¾ą“³ą“‚) */
+$specialPageAliases['ml'] = array(
+ 'TimedMediaHandler' => array( 'ą“øą“®ą“Æą“¾ą“§ą“æą“·ąµą“ ą“æą“¤ą“®ąµ€ą“”ą“æą“Æą“•ąµˆą“•ą“¾ą“°ąµą“Æąµ‹ą“Ŗą“•ą“°ą“£ą“‚' ),
+);
+
+/** Vietnamese (Tiįŗæng Viį»‡t) */
+$specialPageAliases['vi'] = array(
+ 'TimedMediaHandler' => array( 'Bį»™_xį»­_lĆ½_phĘ°Ę”ng_tiį»‡n_đį»“ng_bį»™', 'Bį»™_xį»­_lĆ­_phĘ°Ę”ng_tiį»‡n_đį»“ng_bį»™' ),
+);
+
+/** Simplified Chinese (äø­ę–‡ļ¼ˆē®€ä½“ļ¼‰ā€Ž) */
+$specialPageAliases['zh-hans'] = array(
+ 'TimedMediaHandler' => array( 'å®šę—¶åŖ’体处ē†å™Ø' ),
+ 'OrphanedTimedText' => array( 'å­¤ē«‹å®šę—¶ę–‡ęœ¬' ),
+); \ No newline at end of file
diff --git a/extensions/TimedMediaHandler/TimedMediaHandler.i18n.magic.php b/extensions/TimedMediaHandler/TimedMediaHandler.i18n.magic.php
new file mode 100644
index 00000000..878ceb17
--- /dev/null
+++ b/extensions/TimedMediaHandler/TimedMediaHandler.i18n.magic.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Internationalisation file for extension TimedMediaHandler.
+ *
+ * @file
+ * @ingroup Extensions
+ */
+
+$magicWords = array();
+
+$magicWords['en'] = array(
+ 'timedmedia_noplayer' => array( 0, 'noplayer' ),
+ 'timedmedia_noicon' => array( 0, 'noicon' ),
+ 'timedmedia_thumbtime' => array( 0, 'thumbtime=$1' ),
+ 'timedmedia_starttime' => array( 0, 'start=$1'),
+ 'timedmedia_endtime' => array( 0, 'end=$1'),
+ 'timedmedia_disablecontrols' => array( 0, 'disablecontrols=$1'),
+);
+
+$magicWords['af'] = array(
+ 'timedmedia_noplayer' => array( '0', 'geenspeler', 'noplayer' ),
+ 'timedmedia_noicon' => array( '0', 'geenikoon', 'noicon' ),
+ 'timedmedia_starttime' => array( '0', 'begin=$1', 'start=$1' ),
+ 'timedmedia_endtime' => array( '0', 'einde=$1', 'end=$1' ),
+);
+
+$magicWords['ar'] = array(
+ 'timedmedia_noplayer' => array( '0', 'Ł„Ų§ŲØŲ±Ł†Ų§Ł…Ų¬', 'noplayer' ),
+ 'timedmedia_noicon' => array( '0', 'Ł„Ų§Ų£ŁŠŁ‚ŁˆŁ†Ų©', 'noicon' ),
+ 'timedmedia_thumbtime' => array( '0', 'ŁˆŁ‚ŲŖ_Ų§Ł„ŲŖŲµŲŗŁŠŲ±=$1', 'thumbtime=$1' ),
+ 'timedmedia_starttime' => array( '0', 'ŲØŲÆŲ§ŁŠŲ©=$1', 'start=$1' ),
+ 'timedmedia_endtime' => array( '0', 'Ł†Ł‡Ų§ŁŠŲ©=$1', 'end=$1' ),
+);
+
+$magicWords['arc'] = array(
+ 'timedmedia_starttime' => array( '0', 'ܫܘÜŖܝܐ=', 'start=$1' ),
+ 'timedmedia_endtime' => array( '0', 'ܫܘܠܔܐ=$1', 'end=$1' ),
+);
+
+$magicWords['arz'] = array(
+ 'timedmedia_noplayer' => array( '0', 'Ł„Ų§ŲØŲ±Ł†Ų§Ł…Ų¬', 'noplayer' ),
+ 'timedmedia_noicon' => array( '0', 'Ł„Ų§Ų£ŁŠŁ‚ŁˆŁ†Ų©', 'noicon' ),
+ 'timedmedia_thumbtime' => array( '0', 'ŁˆŁ‚ŲŖ_Ų§Ł„ŲŖŲµŲŗŁŠŲ±=$1', 'thumbtime=$1' ),
+ 'timedmedia_starttime' => array( '0', 'ŲØŲÆŲ§ŁŠŲ©=$1', 'start=$1' ),
+ 'timedmedia_endtime' => array( '0', 'Ł†Ł‡Ų§ŁŠŲ©=$1', 'end=$1' ),
+);
+
+$magicWords['ko'] = array(
+ 'timedmedia_starttime' => array( '0', 'ģ‹œģž‘=$1', 'start=$1' ),
+ 'timedmedia_endtime' => array( '0', 'ė=$1', 'end=$1' ),
+);
+
+$magicWords['ml'] = array(
+ 'timedmedia_noplayer' => array( '0', 'ą“Ŗąµą“²ąµ‡ą“Æą“±ą“æą“²ąµą“²', 'noplayer' ),
+ 'timedmedia_noicon' => array( '0', 'ą“ą“•ąµ‹ą“£ą“æą“²ąµą“²', 'noicon' ),
+ 'timedmedia_thumbtime' => array( '0', 'ą“²ą“˜ąµą“°ąµ‚ą“Ŗą“øą“®ą“Æą“‚=$1', 'thumbtime=$1' ),
+ 'timedmedia_starttime' => array( '0', 'ą“¤ąµą“Ÿą“™ąµą“™ąµą“•=$1', 'start=$1' ),
+ 'timedmedia_endtime' => array( '0', 'ą“Øą“æąµ¼ą“¤ąµą“¤ąµą“•=$1', 'end=$1' ),
+);
+
+$magicWords['mr'] = array(
+ 'timedmedia_thumbtime' => array( '0', 'ą¤„ą¤‚ą¤¬ą¤Ÿą¤¾ą¤‡ą¤®=$1', 'ą¤‡ą¤µą¤²ą¤¾ą¤µą„‡ą¤³=$1', 'thumbtime=$1' ),
+ 'timedmedia_starttime' => array( '0', 'ą¤øą„ą¤°ą¤µą¤¾ą¤¤=$1', 'start=$1' ),
+ 'timedmedia_endtime' => array( '0', 'ą¤¶ą„‡ą¤µą¤Ÿ=$1', 'end=$1' ),
+);
+
+$magicWords['nds-nl'] = array(
+ 'timedmedia_noplayer' => array( '0', 'gienspeuler', 'geenspeler', 'noplayer' ),
+ 'timedmedia_noicon' => array( '0', 'gienicoon', 'geenicoon', 'noicon' ),
+ 'timedmedia_thumbtime' => array( '0', 'miniatuurtied=$1', 'miniatuurtijd=$1', 'thumbtime=$1' ),
+ 'timedmedia_endtime' => array( '0', 'einde=$1', 'eind=$1', 'end=$1' ),
+);
+
+$magicWords['nl'] = array(
+ 'timedmedia_noplayer' => array( '0', 'geenspeler', 'noplayer' ),
+ 'timedmedia_noicon' => array( '0', 'geenicoon', 'noicon' ),
+ 'timedmedia_thumbtime' => array( '0', 'miniatuurtijd=$1', 'thumbtime=$1' ),
+ 'timedmedia_endtime' => array( '0', 'eind=$1', 'end=$1' ),
+);
+
+$magicWords['ru'] = array(
+ 'timedmedia_noplayer' => array( '0', 'Š½ŠµŃ‚ŠæрŠ¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»Ń', 'noplayer' ),
+ 'timedmedia_noicon' => array( '0', 'Š½ŠµŃ‚Š·Š½Š°Ń‡ŠŗŠ°', 'noicon' ),
+ 'timedmedia_starttime' => array( '0', 'Š½Š°Ń‡Š°Š»Š¾=$1', 'start=$1' ),
+ 'timedmedia_endtime' => array( '0', 'Š¾ŠŗŠ¾Š½Ń‡Š°Š½ŠøŠµ=$1', 'end=$1' ),
+);
diff --git a/extensions/TimedMediaHandler/TimedMediaHandler.php b/extensions/TimedMediaHandler/TimedMediaHandler.php
new file mode 100644
index 00000000..2c032e6a
--- /dev/null
+++ b/extensions/TimedMediaHandler/TimedMediaHandler.php
@@ -0,0 +1,306 @@
+<?php
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+ echo "This is the TimedMediaHandler extension. Please see the README file for installation instructions.\n";
+ exit( 1 );
+}
+
+// Set up the timed media handler dir:
+$timedMediaDir = __DIR__;
+// Include WebVideoTranscode (prior to config so that its defined transcode keys can be used in configuration)
+$wgAutoloadClasses['WebVideoTranscode'] = "$timedMediaDir/WebVideoTranscode/WebVideoTranscode.php";
+
+// Add the rest transcode right:
+$wgAvailableRights[] = 'transcode-reset';
+$wgAvailableRights[] = 'transcode-status';
+
+
+
+/*** MwEmbed module configuration: *********************************/
+
+// Show a warning to the user if they are not using an html5 browser with high quality ogg support
+$wgMwEmbedModuleConfig['EmbedPlayer.DirectFileLinkWarning'] = true;
+
+// Show the options menu:
+$wgMwEmbedModuleConfig['EmbedPlayer.EnableOptionsMenu'] = true;
+
+$wgMwEmbedModuleConfig['EmbedPlayer.DisableHTML5FlashFallback' ] = true;
+
+// The text interface should always be shown
+// ( even if there are no text tracks for that asset at render time )
+$wgMwEmbedModuleConfig['TimedText.ShowInterface'] = 'always';
+
+// Show the add text link:
+$wgMwEmbedModuleConfig['TimedText.ShowAddTextLink'] = true;
+
+/*** Timed Media Handler configuration ****************************/
+
+// Which users can restart failed or expired transcode jobs:
+$wgGroupPermissions['sysop']['transcode-reset'] = true;
+$wgGroupPermissions['autoconfirmed']['transcode-reset'] = true;
+
+// Which users can see Special:TimedMediaHandler
+$wgGroupPermissions['sysop']['transcode-status'] = true;
+
+// How long you have to wait between transcode resets for non-error transcodes
+$wgWaitTimeForTranscodeReset = 3600;
+
+// The minimum size for an embed video player ( smaller than this size uses a pop-up player )
+$wgMinimumVideoPlayerSize = 200;
+
+// Set the supported ogg codecs:
+$wgMediaVideoTypes = array( 'Theora', 'VP8' );
+$wgMediaAudioTypes = array( 'Vorbis', 'Speex', 'FLAC', 'Opus' );
+
+// Default skin for mwEmbed player
+$wgVideoPlayerSkinModule = 'mw.PlayerSkinKskin';
+
+// Support iframe for remote embedding
+$wgEnableIframeEmbed = true;
+
+// If transcoding is enabled for this wiki (if disabled, no transcode jobs are added and no
+// transcode status is displayed). Note if remote embedding an asset we will still check if
+// the remote repo has transcoding enabled and associated flavors for that media embed.
+$wgEnableTranscode = true;
+
+// If the job runner should run transcode commands in a background thread and monitor the
+// transcoding progress. This enables more fine grain control of the transcoding process, wraps
+// encoding commands in a lower priority 'nice' call, and kills long running transcodes that are
+// not making any progress. If set to false, the job runner will use the more compatible
+// php blocking shell exec command.
+$wgEnableNiceBackgroundTranscodeJobs = false;
+
+// The priority to be used with the nice transcode commands.
+$wgTranscodeBackgroundPriority = 19;
+
+// The total amout of time a transcoding shell command can take:
+$wgTranscodeBackgroundTimeLimit = 3600 * 8;
+// Maximum amount of virtual memory available to transcoding processes in KB
+$wgTranscodeBackgroundMemoryLimit = 2 * 1024 * 1024; // 2GB avconv, ffmpeg2theora mmap resources so virtual memory needs to be high enough
+// Maximum file size transcoding processes can create, in KB
+$wgTranscodeBackgroundSizeLimit = 3 * 1024 * 1024; // 3GB
+
+// Number of threads to use in avconv for transcoding
+$wgFFmpegThreads = 1;
+
+// The location of ffmpeg2theora (transcoding)
+// Set to false to use avconv/ffmpeg to produce Ogg Theora transcodes instead;
+// beware this will disable Ogg skeleton metadata generation.
+$wgFFmpeg2theoraLocation = '/usr/bin/ffmpeg2theora';
+
+// Location of oggThumb binary ( used instead of ffmpeg )
+$wgOggThumbLocation = '/usr/bin/oggThumb';
+
+// Location of the avconv/ffmpeg binary (used to encode WebM and for thumbnails)
+$wgFFmpegLocation = '/usr/bin/avconv';
+
+// The NS for TimedText (registered on MediaWiki.org)
+// http://www.mediawiki.org/wiki/Extension_namespace_registration
+// Note commons pre-dates TimedMediaHandler and should set $wgTimedTextNS = 102 in LocalSettings.php
+$wgTimedTextNS = 710;
+
+// Set TimedText namespace for ForeignDBViaLBRepo on a per wikiID basis
+// $wgTimedTextForeignNamespaces = array( 'commonswiki' => 102 );
+$wgTimedTextForeignNamespaces = array();
+
+// Set to false to disable local TimedText,
+// you still get subtitles for videos from foreign repos
+// to disable all TimedText, set
+// $wgMwEmbedModuleConfig['TimedText.ShowInterface'] = 'off';
+$wgEnableLocalTimedText = true;
+
+/**
+ * Default enabled transcodes
+ *
+ * -If set to empty array, no derivatives will be created
+ * -Derivative keys encode settings are defined in WebVideoTranscode.php
+ *
+ * -These transcodes are *in addition to* the source file.
+ * -Only derivatives with smaller width than the source asset size will be created
+ * -Regardless of source size at least one WebM and Ogg source will be created from the $wgEnabledTranscodeSet
+ * -Derivative jobs are added to the MediaWiki JobQueue the first time the asset is displayed
+ * -Derivative should be listed min to max
+ */
+$wgEnabledTranscodeSet = array(
+
+ // WebM VP8/Vorbis
+ // primary free/open video format
+ // supported by Chrome/Firefox/Opera but not Safari/IE/Edge
+
+ // Medium-bitrate web streamable WebM video
+ WebVideoTranscode::ENC_WEBM_360P,
+
+ // Moderate-bitrate web streamable WebM video
+ WebVideoTranscode::ENC_WEBM_480P,
+
+ // A high quality WebM stream
+ WebVideoTranscode::ENC_WEBM_720P,
+
+ // A full-HD high quality WebM stream
+ WebVideoTranscode::ENC_WEBM_1080P,
+
+ // A 4K full high quality WebM stream
+ // WebVideoTranscode::ENC_WEBM_2160P,
+
+
+ // Ogg Theora/Vorbis
+ // Fallback for Safari/IE/Edge with ogv.js
+ //
+ // Requires twice the bitrate for same quality as VP8,
+ // and JS decoder can be slow, so shift to smaller sizes.
+
+ // Low-bitrate Ogg stream
+ WebVideoTranscode::ENC_OGV_160P,
+
+ // Medium-bitrate Ogg stream
+ WebVideoTranscode::ENC_OGV_240P,
+
+ // Moderate-bitrate Ogg stream
+ WebVideoTranscode::ENC_OGV_360P,
+
+ // High-bitrate Ogg stream
+ WebVideoTranscode::ENC_OGV_480P,
+
+/*
+ // MP4 H.264/AAC
+ // Primary format for the Apple/Microsoft world
+ //
+ // Check patent licensing issues in your country before use!
+ // Similar to WebM in quality/bitrate
+
+ // A least common denominator h.264 stream; first gen iPhone, iPods, early android etc.
+ WebVideoTranscode::ENC_H264_320P,
+
+ // A mid range h.264 stream; mid range phones and low end tables
+ WebVideoTranscode::ENC_H264_480P,
+
+ // An high quality HD stream; higher end phones, tablets, smart tvs
+ WebVideoTranscode::ENC_H264_720P,
+
+ // A full-HD high quality stream; higher end phones, tablets, smart tvs
+ WebVideoTranscode::ENC_H264_1080P,
+
+ // A 4K high quality stream; higher end phones, tablets, smart tvs
+ WebVideoTranscode::ENC_H264_2160P,
+*/
+);
+
+$wgEnabledAudioTranscodeSet = array(
+ WebVideoTranscode::ENC_OGG_VORBIS,
+
+ //opus support must be available in avconv
+ //WebVideoTranscode::ENC_OGG_OPUS,
+
+ //avconv needs libmp3lame support
+ //WebVideoTranscode::ENC_MP3,
+
+ //avconv needs libvo_aacenc support
+ //WebVideoTranscode::ENC_AAC,
+);
+
+// If mp4 source assets can be ingested:
+$wgTmhEnableMp4Uploads = false;
+
+/******************* CONFIGURATION ENDS HERE **********************/
+
+
+// List of extensions handled by Timed Media Handler since its referenced in a few places.
+// you should not modify this variable
+
+$wgTmhFileExtensions = array( 'ogg', 'ogv', 'oga', 'flac', 'wav', 'webm', 'mp4' );
+
+$wgFileExtensions = array_merge( $wgFileExtensions, $wgTmhFileExtensions );
+
+// Timed Media Handler AutoLoad Classes:
+$wgAutoloadClasses['TimedMediaHandler'] = "$timedMediaDir/TimedMediaHandler_body.php";
+$wgAutoloadClasses['TimedMediaHandlerHooks'] = "$timedMediaDir/TimedMediaHandler.hooks.php";
+$wgAutoloadClasses['TimedMediaTransformOutput'] = "$timedMediaDir/TimedMediaTransformOutput.php";
+$wgAutoloadClasses['TimedMediaIframeOutput'] = "$timedMediaDir/TimedMediaIframeOutput.php";
+$wgAutoloadClasses['TimedMediaThumbnail'] = "$timedMediaDir/TimedMediaThumbnail.php";
+// Transcode Page
+$wgAutoloadClasses['TranscodeStatusTable'] = "$timedMediaDir/TranscodeStatusTable.php";
+
+// Testing:
+$wgAutoloadClasses['ApiTestCaseVideoUpload'] = "$timedMediaDir/tests/phpunit/ApiTestCaseVideoUpload.php";
+
+// Ogg Handler
+$wgAutoloadClasses['OggHandlerTMH'] = "$timedMediaDir/handlers/OggHandler/OggHandler.php";
+$wgAutoloadClasses['OggException'] = "$timedMediaDir/handlers/OggHandler/OggException.php";
+$wgAutoloadClasses['File_Ogg'] = "$timedMediaDir/handlers/OggHandler/File_Ogg/File/Ogg.php";
+$wgAutoloadClasses['File_Ogg_Bitstream'] = "$timedMediaDir/handlers/OggHandler/File_Ogg/File/Ogg/Bitstream.php";
+$wgAutoloadClasses['File_Ogg_Flac'] = "$timedMediaDir/handlers/OggHandler/File_Ogg/File/Ogg/Flac.php";
+$wgAutoloadClasses['File_Ogg_Media'] = "$timedMediaDir/handlers/OggHandler/File_Ogg/File/Ogg/Media.php";
+$wgAutoloadClasses['File_Ogg_Opus'] = "$timedMediaDir/handlers/OggHandler/File_Ogg/File/Ogg/Opus.php";
+$wgAutoloadClasses['File_Ogg_Speex'] = "$timedMediaDir/handlers/OggHandler/File_Ogg/File/Ogg/Speex.php";
+$wgAutoloadClasses['File_Ogg_Theora'] = "$timedMediaDir/handlers/OggHandler/File_Ogg/File/Ogg/Theora.php";
+$wgAutoloadClasses['File_Ogg_Vorbis'] = "$timedMediaDir/handlers/OggHandler/File_Ogg/File/Ogg/Vorbis.php";
+
+// getID3 provides metadata for mp4 and webm files:
+$wgAutoloadClasses['getID3'] = "$timedMediaDir/libs/getid3/getid3.php";
+$wgAutoloadClasses['getid3_exception'] = "$timedMediaDir/libs/getid3/getid3.php";
+$wgAutoloadClasses['getid3_handler'] = "$timedMediaDir/libs/getid3/getid3.php";
+
+// ID3 Metadata Handler
+$wgAutoloadClasses['ID3Handler'] = "$timedMediaDir/handlers/ID3Handler/ID3Handler.php";
+// Mp4 / h264 Handler
+$wgAutoloadClasses['Mp4Handler'] = "$timedMediaDir/handlers/Mp4Handler/Mp4Handler.php";
+// WebM Handler
+$wgAutoloadClasses['WebMHandler'] = "$timedMediaDir/handlers/WebMHandler/WebMHandler.php";
+// FLAC Handler
+$wgAutoloadClasses['FLACHandler'] = "$timedMediaDir/handlers/FLACHandler/FLACHandler.php";
+// WAV Handler
+$wgAutoloadClasses['WAVHandler'] = "$timedMediaDir/handlers/WAVHandler/WAVHandler.php";
+
+// Text handler
+$wgAutoloadClasses['ForeignApiQueryAllPages'] = "$timedMediaDir/handlers/TextHandler/TextHandler.php";
+$wgAutoloadClasses['TextHandler'] = "$timedMediaDir/handlers/TextHandler/TextHandler.php";
+$wgAutoloadClasses['TimedTextPage'] = "$timedMediaDir/TimedTextPage.php";
+
+// Transcode support
+$wgAutoloadClasses['WebVideoTranscodeJob'] = "$timedMediaDir/WebVideoTranscode/WebVideoTranscodeJob.php";
+
+// API modules:
+$wgAutoloadClasses['ApiQueryVideoInfo'] = "$timedMediaDir/ApiQueryVideoInfo.php";
+$wgAPIPropModules['videoinfo'] = 'ApiQueryVideoInfo';
+
+$wgAutoloadClasses['ApiTranscodeStatus'] = "$timedMediaDir/ApiTranscodeStatus.php";
+$wgAPIPropModules['transcodestatus'] = 'ApiTranscodeStatus';
+
+$wgAutoloadClasses['ApiTranscodeReset'] = "$timedMediaDir/ApiTranscodeReset.php";
+$wgAPIModules['transcodereset'] = 'ApiTranscodeReset';
+
+// Localization
+$wgMessagesDirs['TimedMediaHandler'] = __DIR__ . '/i18n';
+$wgExtensionMessagesFiles['TimedMediaHandlerMagic'] = "$timedMediaDir/TimedMediaHandler.i18n.magic.php";
+$wgExtensionMessagesFiles['TimedMediaHandlerAliases'] = "$timedMediaDir/TimedMediaHandler.i18n.alias.php";
+// Inlcude module locationlizations
+$wgMessagesDirs['MwEmbed.EmbedPlayer'] = __DIR__ . '/MwEmbedModules/EmbedPlayer/i18n';
+$wgMessagesDirs['MwEmbed.TimedText'] = __DIR__ . '/MwEmbedModules/TimedText/i18n';
+
+// Special Pages
+$wgAutoloadClasses['SpecialTimedMediaHandler'] = "$timedMediaDir/SpecialTimedMediaHandler.php";
+$wgAutoloadClasses['SpecialOrphanedTimedText'] = "$timedMediaDir/SpecialOrphanedTimedText.php";
+
+// This way if you set a variable like $wgTimedTextNS in LocalSettings.php
+// after you include TimedMediaHandler we can still read the variable values
+// See also T123695 and T123823
+$wgHooks['SetupAfterCache'][] = 'TimedMediaHandlerHooks::onSetupAfterCache';
+
+// Register remaining Timed Media Handler hooks right after initial setup
+$wgExtensionFunctions[] = 'TimedMediaHandlerHooks::register';
+
+# add Special pages
+$wgSpecialPages['OrphanedTimedText'] = 'SpecialOrphanedTimedText';
+$wgSpecialPages['TimedMediaHandler'] = 'SpecialTimedMediaHandler';
+
+// Extension Credits
+$wgExtensionCredits['media'][] = array(
+ 'path' => __FILE__,
+ 'name' => 'TimedMediaHandler',
+ 'namemsg' => 'extensionname-timedmedia',
+ 'author' => array( 'Michael Dale', 'Tim Starling', 'James Heinrich', 'Jan Gerber', 'Brion Vibber' ),
+ 'url' => 'https://www.mediawiki.org/wiki/Extension:TimedMediaHandler',
+ 'descriptionmsg' => 'timedmedia-desc',
+ 'version' => '0.4.0',
+ 'license-name' => 'GPL-2.0+',
+);
diff --git a/extensions/TimedMediaHandler/TimedMediaHandler.sql b/extensions/TimedMediaHandler/TimedMediaHandler.sql
new file mode 100644
index 00000000..7bafe675
--- /dev/null
+++ b/extensions/TimedMediaHandler/TimedMediaHandler.sql
@@ -0,0 +1,19 @@
+-- TimedMediaHandler.sql
+-- 2011-04-05 <mdale@wikimedia.org>
+--
+CREATE TABLE /*_*/transcode (
+ transcode_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ transcode_image_name VARCHAR(255) NOT NULL,
+ transcode_key VARCHAR(48) NOT NULL,
+ transcode_error longtext NOT NULL,
+ transcode_time_addjob VARCHAR(14) NULL,
+ transcode_time_startwork VARCHAR(14) NULL,
+ transcode_time_success VARCHAR(14) NULL,
+ transcode_time_error VARCHAR(14) NULL,
+ transcode_final_bitrate INT NOT NULL
+) /*$wgDBTableOptions*/;
+
+CREATE INDEX /*i*/transcode_time_inx ON /*_*/transcode( transcode_time_addjob ,transcode_time_startwork , transcode_time_success, transcode_time_error );
+CREATE INDEX /*i*/transcode_key_idx ON /*_*/transcode( transcode_key );
+
+CREATE UNIQUE INDEX /*i*/transcode_name_key ON /*_*/transcode (transcode_image_name,transcode_key);
diff --git a/extensions/TimedMediaHandler/TimedMediaHandler_body.php b/extensions/TimedMediaHandler/TimedMediaHandler_body.php
new file mode 100644
index 00000000..cb689858
--- /dev/null
+++ b/extensions/TimedMediaHandler/TimedMediaHandler_body.php
@@ -0,0 +1,483 @@
+<?php
+
+class TimedMediaHandler extends MediaHandler {
+ static $magicDone = false;
+
+ /**
+ * @return bool
+ */
+ function isEnabled() {
+ return true;
+ }
+
+ /**
+ * Get an image size array like that returned by getimagesize(), or false if it
+ * can't be determined.
+ * @param $file File
+ * @param $path string
+ * @param $metadata bool
+ * @return array|bool
+ */
+ function getImageSize( $file, $path, $metadata = false ) {
+ /* override by handler */
+ return false;
+ }
+
+ /**
+ * Get the list of supported wikitext embed params
+ * @return array
+ */
+ function getParamMap() {
+ return array(
+ 'img_width' => 'width',
+ 'timedmedia_thumbtime' => 'thumbtime',
+ 'timedmedia_starttime' => 'start',
+ 'timedmedia_endtime' => 'end',
+ 'timedmedia_disablecontrols' => 'disablecontrols',
+ );
+ }
+
+ /**
+ * Validate a embed file parameters
+ *
+ * @param $name {String} Name of the param
+ * @param $value {Mixed} Value to validated
+ * @return bool
+ */
+ function validateParam( $name, $value ) {
+ if ( $name == 'thumbtime' || $name == 'start' || $name == 'end' ) {
+ if ( $this->parseTimeString( $value ) === false ) {
+ return false;
+ }
+ } elseif ( $name == 'disablecontrols' ) {
+ $values = explode( ',', $value);
+ foreach($values as $v) {
+ if ( !in_array( $v, array( 'options', 'timedText', 'fullscreen' ) ) ) {
+ return false;
+ }
+ }
+ } elseif( $name === 'width' || $name === 'height' ) {
+ return $value > 0;
+ }
+ return true;
+ }
+
+ /**
+ * TODO we should really have "$file" available here to validate the param string
+ * @param $params array
+ * @return string
+ */
+ function makeParamString( $params ) {
+ // Add the width param string ( same as images {width}px )
+ $paramString ='';
+ $paramString.= ( isset( $params['width'] ) )? $params['width'] . 'px' : '';
+ $paramString.= ( $paramString != '' )? '-' : '';
+
+ // Get the raw thumbTime from thumbtime or start param
+ if ( isset ( $params['thumbtime'] ) ) {
+ $thumbTime = $params['thumbtime'];
+ } elseif ( isset ( $params['start'] ) ) {
+ $thumbTime = $params['start'];
+ } else {
+ $thumbTime = false;
+ }
+
+ if ( $thumbTime !== false ) {
+ $time = $this->parseTimeString( $thumbTime );
+ if ( $time !== false ) {
+ return $paramString. 'seek=' . $time;
+ }
+ }
+
+ if ( !$paramString ) {
+ $paramString = 'mid';
+ }
+ return $paramString ;
+ }
+
+ /**
+ * Used by thumb.php to find url parameters
+ *
+ * @param $str string
+ * @return array|bool Array of thumbnail parameters, or false if string cannot be parsed
+ */
+ function parseParamString( $str ) {
+ $params = array();
+ if ( preg_match( '/^(mid|(\d*)px-)*(seek=([\d.]+))*$/', $str, $matches ) ) {
+ $size = $thumbtime = null;
+ if ( isset( $matches[2] ) ) {
+ $size = $matches[2];
+ }
+ if ( isset( $matches[4] ) ) {
+ $thumbtime = $matches[4];
+ }
+
+ if ( !is_null( $size ) && $size !== '' ) {
+ $params['width'] = (int) $size;
+ }
+ if ( !is_null( $thumbtime ) ) {
+ $params['thumbtime'] = (float) $thumbtime;
+ }
+ return $params; // valid thumbnail URL
+ } else {
+ // invalid parameter string
+ return false;
+ }
+ }
+
+ /**
+ * @param $image File
+ * @param $params array
+ * @return bool
+ */
+ function normaliseParams( $image, &$params ) {
+ $timeParam = array( 'thumbtime', 'start', 'end' );
+ // Parse time values if endtime or thumbtime can't be more than length -1
+ foreach($timeParam as $pn){
+ if ( isset( $params[$pn] ) && $params[$pn] !== false ) {
+ $length = $this->getLength( $image );
+ $time = $this->parseTimeString( $params[$pn] );
+ if ( $time === false ) {
+ return false;
+ } elseif ( $time > $length - 1 ) {
+ $params[$pn] = $length - 1;
+ } elseif ( $time <= 0 ) {
+ $params[$pn] = 0;
+ }
+ }
+ }
+
+ if ( $this->isAudio( $image ) ) {
+ // Assume a default for audio files
+ $size = array(
+ 'width' => 220,
+ 'height' => 23,
+ );
+ } else {
+ $size = array(
+ 'width' => $image->getWidth(),
+ 'height' => $image->getHeight(),
+ );
+ }
+ // Make sure we don't try and up-scale the asset:
+ if( isset( $params['width'] ) && (int)$params['width'] > $size['width'] ){
+ $params['width'] = $size['width'];
+ }
+
+ if ( isset( $params['height'] ) && $params['height'] != -1 ) {
+ if( $params['width'] * $size['height'] > $params['height'] * $size['width'] ) {
+ $params['width'] = self::fitBoxWidth( $size['width'], $size['height'], $params['height'] );
+ }
+ }
+ if ( isset( $params['width'] ) ) {
+ $params['height'] = File::scaleHeight( $size['width'], $size['height'], $params['width'] );
+ }
+
+ // Make sure start time is not > than end time
+ if( isset($params['start'])
+ && isset($params['end'] )
+ && $params['start'] !== false
+ && $params['end'] !== false
+ ) {
+ if ( $this->parseTimeString( $params['start'] ) > $this->parseTimeString( $params['end'] ) ) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $file File
+ */
+ function parserTransformHook( $parser, $file ) {
+ $parserOutput = $parser->getOutput();
+ if ( isset( $parserOutput->hasTimedMediaTransform ) ) {
+ return ;
+ }
+ $parserOutput->hasTimedMediaTransform = true;
+ $parserOutput->addOutputHook( 'TimedMediaHandler' );
+ }
+
+ /**
+ * Parser output hook only adds the PopUpMediaTransform
+ *
+ * The core embedPlayer module is part of a "loaderScript" so it does not need to
+ * be registered here.
+ *
+ * TODO move core loader to on-page script as to not include it on all pages.
+ *
+ * @param $outputPage OutputPage
+ * @param $parserOutput
+ * @param $data
+ */
+ static function outputHook( $outputPage, $parserOutput, $data ) {
+ // Add the PopUpMediaTransform code
+ $outputPage->addModuleScripts( 'mw.PopUpMediaTransform' );
+ $outputPage->addModuleStyles( 'mw.PopUpMediaTransform.styles' );
+ $outputPage->addModules( 'mw.TMHGalleryHook.js' );
+ if ( $parserOutput ) {
+ // Not present when run from outputpage hooks, like File/Category etc...
+ $parserOutput->setExtensionData( 'mw_ext_TMH_hasTimedMediaTransform', true );
+ }
+ }
+
+ /**
+ * Utility functions
+ * @param $timeString
+ * @param $length
+ * @return bool|int
+ */
+ public static function parseTimeString( $timeString, $length = false ) {
+ $parts = explode( ':', $timeString );
+ $time = 0;
+ // Check for extra :s
+ if( count( $parts ) > 3 ){
+ return false;
+ }
+ for ( $i = 0; $i < count( $parts ); $i++ ) {
+ if ( !is_numeric( $parts[$i] ) ) {
+ return false;
+ }
+ $time += floatval( $parts[$i] ) * pow( 60, count( $parts ) - $i - 1 );
+ }
+
+ if ( $time < 0 ) {
+ wfDebug( __METHOD__.": specified negative time, using zero\n" );
+ $time = 0;
+ } elseif ( $length !== false && $time > $length - 1 ) {
+ wfDebug( __METHOD__.": specified near-end or past-the-end time {$time}s, using end minus 1s\n" );
+ $time = $length - 1;
+ }
+ return $time;
+ }
+
+ /**
+ * @static
+ * @param $timePassed
+ * @return string
+ */
+ public static function getTimePassedMsg( $timePassed ){
+ $t = array();
+ $t['days'] = floor($timePassed/60/60/24);
+ $t['hours'] = floor($timePassed/60/60)%24;
+ $t['minutes'] = floor($timePassed/60)%60;
+ $t['seconds'] = $timePassed%60;
+
+ foreach( $t as $k => $v ){
+ if($v == 0 ){
+ unset( $t[$k] );
+ } else {
+ // Give grep a chance to find the usages:
+ // timedmedia-days, timedmedia-hours, timedmedia-minutes,timedmedia-seconds
+ $t[$k] = wfMessage( 'timedmedia-' . $k, $v )->text();
+ }
+ }
+ if( count( $t ) == 0 ){
+ $t = array( wfMessage( 'timedmedia-seconds', 0 )->text() ) ;
+ }
+
+ global $wgLang;
+ return $wgLang->commaList( $t );
+ }
+
+ /**
+ * Converts seconds to Normal play time (NPT) time format:
+ * consist of hh:mm:ss.ms
+ * also see: http://www.ietf.org/rfc/rfc2326.txt section 3.6
+ *
+ * @param $time Number Seconds to be converted to npt time format
+ * @return bool|string
+ */
+ public static function seconds2npt( $time ){
+ if ( !is_numeric( $time ) ) {
+ wfDebug( __METHOD__.": trying to get npt time on NaN:" + $time);
+ return false;
+ }
+ if( $time < 0 ){
+ wfDebug( __METHOD__.": trying to time on negative value:" + $time);
+ return false;
+ }
+ $hours = floor( $time / 3600 );
+ $min = floor( ( $time / 60 ) % 60 );
+ $sec = ($time % 60 );
+ $ms = ( $time - round( $time, 3) != 0 ) ? '.' .( $time - round( $time, 3) ) : '';
+
+ return "{$hours}:{$min}:{$sec}{$ms}";
+ }
+
+ /**
+ * @param $metadata
+ * @return bool|mixed
+ */
+ function unpackMetadata( $metadata ) {
+ wfSuppressWarnings();
+ $unser = unserialize( $metadata );
+ wfRestoreWarnings();
+ if ( isset( $unser['version'] ) ) {
+ return $unser;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * @param $image
+ * @param $metadata
+ * @return bool
+ */
+ function isMetadataValid( $image, $metadata ) {
+ return $this->unpackMetadata( $metadata ) !== false;
+ }
+
+ /**
+ * @param $ext
+ * @param $mime
+ * @param null $params
+ * @return array
+ */
+ function getThumbType( $ext, $mime, $params = null ) {
+ return array( 'jpg', 'image/jpeg' );
+ }
+
+ /**
+ * checks if a given file is an audio file
+ * @param $file File
+ * @return bool
+ */
+ function isAudio( $file ){
+ return ( $file->getWidth() == 0 && $file->getHeight() == 0 );
+ }
+
+ /**
+ * @param $file File
+ * @param $dstPath String
+ * @param $dstUrl String
+ * @param $params array
+ * @param $flags int
+ * @return bool|MediaTransformError|MediaTransformOutput|TimedMediaTransformOutput
+ */
+ function doTransform( $file, $dstPath, $dstUrl, $params, $flags = 0 ) {
+ # Important or height handling is wrong.
+ if ( !$this->normaliseParams( $file, $params ) ) {
+ return new TransformParameterError( $params );
+ }
+
+ $srcWidth = $file->getWidth();
+ $srcHeight = $file->getHeight();
+
+ // Audio should not be transformed by size, give it a default width and height
+ if( $this->isAudio( $file ) ){
+ $srcWidth = 220;
+ $srcHeight = 23;
+ }
+
+ $params['width'] = isset( $params['width'] ) ? $params['width'] : $srcWidth;
+
+ // if height overtakes width use height as max:
+ $targetWidth = $params['width'];
+ $targetHeight = $srcWidth == 0 ? $srcHeight : round( $params['width'] * $srcHeight / $srcWidth );
+ if( isset( $params['height'] ) && $targetHeight > $params['height'] ){
+ $targetHeight = $params['height'];
+ $targetWidth = round( $params['height'] * $srcWidth / $srcHeight );
+ }
+ $options = array(
+ 'file' => $file,
+ 'length' => $this->getLength( $file ),
+ 'offset' => $this->getOffset( $file ),
+ 'width' => $targetWidth,
+ 'height' => $targetHeight,
+ 'isVideo' => !$this->isAudio( $file ),
+ 'thumbtime' => isset( $params['thumbtime'] ) ? $params['thumbtime'] : intval( $file->getLength() / 2 ),
+ 'start' => isset( $params['start'] ) ? $params['start'] : false,
+ 'end' => isset( $params['end'] ) ? $params['end'] : false,
+ 'fillwindow' => isset( $params['fillwindow'] ) ? $params['fillwindow'] : false,
+ 'disablecontrols' => isset ( $params['disablecontrols'] ) ? $params['disablecontrols'] : false
+ );
+
+ // No thumbs for audio
+ if( !$options['isVideo'] ){
+ return new TimedMediaTransformOutput( $options );
+ }
+
+ // Setup pointer to thumb arguments
+ $options[ 'thumbUrl' ] = $dstUrl;
+ $options[ 'dstPath' ] = $dstPath;
+ $options[ 'path' ] = $dstPath;
+
+ // Check if transform is deferred:
+ if ( $flags & self::TRANSFORM_LATER ) {
+ return new TimedMediaTransformOutput($options);
+ }
+
+ // Generate thumb:
+ $thumbStatus = TimedMediaThumbnail::get( $options );
+ if( $thumbStatus !== true ){
+ return $thumbStatus;
+ }
+
+ return new TimedMediaTransformOutput( $options );
+ }
+
+ /**
+ * @param $file
+ * @return bool
+ */
+ function canRender( $file ) { return true; }
+
+ /**
+ * @param $file
+ * @return bool
+ */
+ function mustRender( $file ) { return true; }
+
+ /**
+ * Get a stream offset time
+ * @param $file
+ * @return int
+ */
+ function getOffset( $file ){
+ return 0;
+ }
+
+ /**
+ * Get length of a file
+ * @param $file
+ * @return int
+ */
+ function getLength( $file ){
+ return $file->getLength();
+ }
+
+ /**
+ * @param $file File
+ * @return String
+ */
+ function getDimensionsString( $file ) {
+ global $wgLang;
+
+ if ( $file->getWidth() ) {
+ return wfMessage( 'video-dims', $wgLang->formatTimePeriod( $this->getLength( $file ) ) )
+ ->numParams( $file->getWidth(), $file->getHeight() )->text();
+ } else {
+ return $wgLang->formatTimePeriod( $this->getLength( $file ) );
+ }
+ }
+
+ public function filterThumbnailPurgeList( &$files, $options ) {
+ global $wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet;
+
+ $transcodeSet = array_merge($wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet);
+
+ //dont remove derivatives on normal purge
+ foreach(array_slice($files, 1) as $key => $file) {
+ foreach( $transcodeSet as $transcodeKey ) {
+ if ( preg_match('/' . preg_quote($transcodeKey) . '$/', $file) ) {
+ unset($files[$key]);
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/extensions/TimedMediaHandler/TimedMediaIframeOutput.php b/extensions/TimedMediaHandler/TimedMediaIframeOutput.php
new file mode 100644
index 00000000..a0e2920b
--- /dev/null
+++ b/extensions/TimedMediaHandler/TimedMediaIframeOutput.php
@@ -0,0 +1,152 @@
+<?php
+/**
+ * Adds iframe output ( bug 25862 )
+ *
+ * This enables iframe based embeds of the wikimeia player with the following syntax:
+ *
+ * <iframe src="http://commons.wikimedia.org/wiki/File:Folgers.ogv?embedplayer=yes"
+ * width="240" height="180" frameborder="0" ></iframe>
+ *
+ */
+
+class TimedMediaIframeOutput {
+ /**
+ * The iframe hook check file pages embedplayer=yes
+ * @param $title Title
+ * @param $article Article
+ * @param bool $doOutput
+ * @return bool
+ */
+ static function iframeHook( &$title, &$article, $doOutput = true ) {
+ global $wgRequest, $wgOut, $wgEnableIframeEmbed;
+ if( !$wgEnableIframeEmbed )
+ return true; //continue normal output iframes are "off" (maybe throw a warning in the future)
+
+ // Make sure we are in the right namespace and iframe=true was called:
+ if( is_object( $title ) && $title->getNamespace() == NS_FILE &&
+ $wgRequest->getVal('embedplayer') == 'yes' &&
+ $wgEnableIframeEmbed &&
+ $doOutput ){
+
+ if ( self::outputIframe( $title ) ) {
+ // Turn off output of anything other than the iframe
+ $wgOut->disable();
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Output an iframe
+ * @param $title Title
+ * @throws Exception
+ */
+ static function outputIframe( $title ) {
+ global $wgEnableIframeEmbed, $wgOut, $wgUser, $wgBreakFrames;
+
+ if( !$wgEnableIframeEmbed ){
+ return false;
+ }
+
+ // Setup the render parm
+ $file = wfFindFile( $title );
+ if ( !$file ) {
+ // file was removed, show wiki page with warning
+ return false;
+ }
+ $params = array(
+ 'fillwindow' => true
+ );
+ $videoTransform = $file->transform( $params );
+
+ // Definitely do not want to break frames
+ $wgBreakFrames = false;
+ $wgOut->allowClickjacking();
+
+ $wgOut->addModules( array( 'embedPlayerIframeStyle', 'mw.EmbedPlayer' ) );
+ $wgOut->sendCacheControl();
+ ?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta charset="UTF-8" />
+<title><?php echo $title->getText() ?></title>
+ <?php
+ echo Html::element( 'meta', array( 'name' => 'ResourceLoaderDynamicStyles', 'content' => '' ) );
+ ?>
+ <?php
+ echo implode( "\n", $wgOut->getHeadLinksArray() );
+ echo implode( "\n", $wgOut->getHeadLinksArray() );
+ ?>
+ <style type="text/css">
+ html, body {
+ height: 100%;
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ overflow:hidden;
+ }
+ img#bgimage {
+ position:fixed;
+ top:0;
+ left:0;
+ width:100%;
+ height:100%;
+ }
+ .videoHolder {
+ position:relative;
+ }
+ </style>
+ <?php echo $wgOut->getHeadScripts(); ?>
+ <script>
+ window.RLQ = window.RLQ || [];
+ window.RLQ.push( function() {
+ mw.loader.using( 'mw.MwEmbedSupport', function() {
+ mw.setConfig('EmbedPlayer.RewriteSelector', '');
+ } );
+ // Turn off rewrite selector. This prevents automatic conversion of
+ // <video> tags, since we are going to do that ourselves later.
+ } );
+ </script>
+ </head>
+<body>
+ <img src="<?php echo $videoTransform->getUrl() ?>" id="bgimage" ></img>
+ <div id="videoContainer" style="visibility:hidden">
+ <?php echo $videoTransform->toHtml(); ?>
+ </div>
+ <?php echo $wgOut->getBottomScripts(); ?>
+ <script>
+ window.RLQ.push( function() {
+ mw.loader.using( 'mw.MwEmbedSupport', function() {
+ // only enable fullscreen if enabled in iframe
+ mw.setConfig('EmbedPlayer.EnableFullscreen', document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || false );
+ $('#bgimage').remove();
+
+ mw.setConfig( 'EmbedPlayer.IsIframeServer', true );
+
+ // rewrite player
+ $( '#<?php echo TimedMediaTransformOutput::PLAYER_ID_PREFIX . '0' ?>' ).embedPlayer(function(){
+
+ // Bind window resize to reize the player:
+ var fitPlayer = function(){
+ $( '#<?php echo TimedMediaTransformOutput::PLAYER_ID_PREFIX . '0' ?>' )
+ [0].updateLayout();
+ }
+
+ $( window ).resize( fitPlayer );
+ $('#videoContainer').css({
+ 'visibility':'visible'
+ } );
+ fitPlayer();
+ } );
+ } );
+ } );
+ </script>
+</body>
+</html>
+ <?php
+ return true;
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/TimedMediaThumbnail.php b/extensions/TimedMediaHandler/TimedMediaThumbnail.php
new file mode 100644
index 00000000..77757440
--- /dev/null
+++ b/extensions/TimedMediaHandler/TimedMediaThumbnail.php
@@ -0,0 +1,240 @@
+<?php
+class TimedMediaThumbnail {
+
+ /**
+ * @param $options array()
+ * @return bool|MediaTransformError
+ */
+ static function get( $options ){
+ if( !is_dir( dirname( $options['dstPath'] ) ) ){
+ wfMkdirParents( dirname( $options['dstPath'] ), null, __METHOD__ );
+ }
+
+ wfDebug( "Creating video thumbnail at " . $options['dstPath'] . "\n" );
+ if(
+ isset( $options['width'] ) && isset( $options['height'] ) &&
+ $options['width'] != $options['file']->getWidth() &&
+ $options['height'] != $options['file']->getHeight()
+ ){
+ return self::resizeThumb( $options );
+ }
+ // try OggThumb, and fallback to ffmpeg
+ $result = self::tryOggThumb( $options );
+ if ( $result === false ) {
+ return self::tryFfmpegThumb( $options );
+ }
+ return $result;
+ }
+
+ /**
+ * Run oggThumb to generate a still image from a video file, using a frame
+ * close to the given number of seconds from the start.
+ *
+ * @param $options array
+ * @return bool|MediaTransformError
+ *
+ */
+ static function tryOggThumb( $options ) {
+ global $wgOggThumbLocation;
+
+ // Check that the file is 'ogg' format
+ if( $options['file']->getHandler()->getMetadataType( $options['file'] ) != 'ogg' ){
+ return false;
+ }
+
+ // Check for $wgOggThumbLocation
+ if( !$wgOggThumbLocation || !is_file( $wgOggThumbLocation ) ){
+ return false;
+ }
+
+ $time = self::getThumbTime( $options );
+ $dstPath = $options['dstPath'];
+ $videoPath = $options['file']->getLocalRefPath();
+
+ $cmd = wfEscapeShellArg( $wgOggThumbLocation )
+ . ' -t ' . floatval( $time );
+ // Set the output size if set in options:
+ if( isset( $options['width'] ) && isset( $options['height'] ) ){
+ $cmd.= ' -s '. intval( $options['width'] ) . 'x' . intval( $options['height'] );
+ }
+ $cmd .= ' -n ' . wfEscapeShellArg( $dstPath ) .
+ ' ' . wfEscapeShellArg( $videoPath ) . ' 2>&1';
+ $retval = 0;
+ $returnText = wfShellExec( $cmd, $retval );
+
+ if ( $options['file']->getHandler()->removeBadFile( $dstPath, $retval ) || $retval ) {
+ // oggThumb spams both stderr and stdout with useless progress
+ // messages, and then often forgets to output anything when
+ // something actually does go wrong. So interpreting its output is
+ // a challenge.
+ $lines = explode( "\n", str_replace( "\r\n", "\n", $returnText ) );
+ if ( count( $lines ) > 0
+ && preg_match( '/invalid option -- \'n\'$/', $lines[0] ) )
+ {
+ $returnText = wfMessage( 'timedmedia-oggThumb-version', '0.9' )->inContentLanguage()->text();
+ } else {
+ $returnText = wfMessage( 'timedmedia-oggThumb-failed' )->inContentLanguage()->text();
+ }
+ return new MediaTransformError( 'thumbnail_error',
+ $options['width'], $options['height'], $returnText );
+ }
+ return true;
+ }
+
+ /**
+ * @param $options array
+ * @return bool|MediaTransformError
+ */
+ static function tryFfmpegThumb( $options ){
+ global $wgFFmpegLocation, $wgMaxShellMemory;
+
+ if( !$wgFFmpegLocation || !is_file( $wgFFmpegLocation ) ){
+ return false;
+ }
+
+ $cmd = wfEscapeShellArg( $wgFFmpegLocation ) . ' -threads 1 ';
+
+ $offset = intval( self::getThumbTime( $options ) );
+ /*
+ This is a workaround until ffmpegs ogg demuxer properly seeks to keyframes.
+ Seek N seconds before offset and seek in decoded stream after that.
+ -ss before input seeks without decode
+ -ss after input seeks in decoded stream
+
+ N depends on framerate of input, keyframe interval defaults
+ to 64 for most encoders, seeking a bit before that
+ */
+
+ $framerate = $options['file']->getHandler()->getFramerate( $options['file'] );
+ if ( $framerate > 0 ) {
+ $seekoffset = 1 + intval( 64 / $framerate );
+ } else {
+ $seekoffset = 3;
+ }
+
+ if($offset > $seekoffset) {
+ $cmd .= ' -ss ' . floatval($offset - $seekoffset);
+ $offset = $seekoffset;
+ }
+
+ //try to get temorary local url to file
+ $backend = $options['file']->getRepo()->getBackend();
+ // getFileHttpUrl was only added in mw 1.21, dont fail if it does not exist
+ if ( method_exists( $backend, 'getFileHttpUrl' ) ) {
+ $src = $backend->getFileHttpUrl( array(
+ 'src' => $options['file']->getPath()
+ ) );
+ } else {
+ $src = null;
+ }
+ if ( $src == null ) {
+ $src = $options['file']->getLocalRefPath();
+ }
+
+ $cmd .= ' -y -i ' . wfEscapeShellArg( $src );
+ $cmd .= ' -ss ' . $offset . ' ';
+
+ // Set the output size if set in options:
+ if( isset( $options['width'] ) && isset( $options['height'] ) ){
+ $cmd.= ' -s '. intval( $options['width'] ) . 'x' . intval( $options['height'] );
+ }
+
+ # MJPEG, that's the same as JPEG except it's supported by the windows build of ffmpeg
+ # No audio, one frame
+ $cmd .= ' -f mjpeg -an -vframes 1 ' .
+ wfEscapeShellArg( $options['dstPath'] ) . ' 2>&1';
+
+ $retval = 0;
+ $returnText = wfShellExec( $cmd, $retval );
+ // Check if it was successful
+ if ( !$options['file']->getHandler()->removeBadFile( $options['dstPath'], $retval ) ) {
+ return true;
+ }
+ $returnText = $cmd . "\nwgMaxShellMemory: $wgMaxShellMemory\n" . $returnText;
+ // Return error box
+ return new MediaTransformError( 'thumbnail_error', $options['width'], $options['height'], $returnText );
+ }
+
+ /**
+ * @param $options array
+ * @return bool|MediaTransformError
+ */
+ static function resizeThumb( $options ) {
+ $file = $options['file'];
+ $params = array();
+ foreach( array( 'start', 'thumbtime' ) as $key ) {
+ if( isset( $options[ $key ] ) ) {
+ $params[ $key ] = $options[ $key ];
+ }
+ }
+ $params["width"] = $file->getWidth();
+ $params["height"] = $file->getHeight();
+
+ $poolKey = $file->getRepo()->getSharedCacheKey( 'file', md5( $file->getName() ) );
+ $posOptions = array_flip( array( 'start', 'thumbtime' ) );
+ $poolKey = wfAppendQuery( $poolKey, array_intersect_key( $options, $posOptions ) );
+
+ if ( class_exists( 'PoolCounterWorkViaCallback' ) ) {
+ $work = new PoolCounterWorkViaCallback( 'TMHTransformFrame',
+ '_tmh:frame:' . $poolKey,
+ array( 'doWork' => function() use ($file, $params) {
+ return $file->transform( $params, File::RENDER_NOW );
+ } ) );
+ $thumb = $work->execute();
+ } else {
+ $thumb = $file->transform( $params, File::RENDER_NOW );
+ }
+
+ if ( !$thumb || $thumb->isError() ) {
+ return $thumb;
+ }
+ $src = $thumb->getStoragePath();
+ if ( !$src ) {
+ return false;
+ }
+ $thumbFile = new UnregisteredLocalFile( $file->getTitle(),
+ RepoGroup::singleton()->getLocalRepo(), $src, false );
+ $thumbParams = array(
+ "width" => $options['width'],
+ "height" => $options['height']
+ );
+ $handler = $thumbFile->getHandler();
+ if ( !$handler ) {
+ return false;
+ }
+ $scaledThumb = $handler->doTransform(
+ $thumbFile,
+ $options['dstPath'],
+ $options['dstPath'],
+ $thumbParams
+ );
+
+ if ( !$scaledThumb || $scaledThumb->isError() ) {
+ return $scaledThumb;
+ }
+ return true;
+ }
+
+ /**
+ * @param $options array
+ * @return bool|float|int
+ */
+ static function getThumbTime( $options ){
+ $length = $options['file']->getLength();
+
+ // If start time param isset use that for the thumb:
+ if( isset( $options['start'] ) ) {
+ $thumbtime = TimedMediaHandler::parseTimeString( $options['start'], $length );
+ if( $thumbtime !== false )
+ return $thumbtime;
+ }
+ // else use thumbtime
+ if ( isset( $options['thumbtime'] ) ) {
+ $thumbtime = TimedMediaHandler::parseTimeString( $options['thumbtime'], $length );
+ if( $thumbtime !== false )
+ return $thumbtime;
+ }
+ // Seek to midpoint by default, it tends to be more interesting than the start
+ return $length / 2;
+ }
+}
diff --git a/extensions/TimedMediaHandler/TimedMediaTransformOutput.php b/extensions/TimedMediaHandler/TimedMediaTransformOutput.php
new file mode 100644
index 00000000..36532093
--- /dev/null
+++ b/extensions/TimedMediaHandler/TimedMediaTransformOutput.php
@@ -0,0 +1,486 @@
+<?php
+
+class TimedMediaTransformOutput extends MediaTransformOutput {
+ static $serial = 0;
+
+ // Video file sources object lazy init in getSources()
+ var $sources = null;
+ var $textTracks = null;
+ var $hashTime = null;
+ var $textHandler = null; // lazy init in getTextHandler
+ var $disablecontrols = null;
+
+ var $start, $end, $fillwindow;
+
+ // The prefix for player ids
+ const PLAYER_ID_PREFIX = 'mwe_player_';
+
+ function __construct( $conf ){
+ $options = array( 'file', 'dstPath', 'sources', 'thumbUrl', 'start', 'end',
+ 'width', 'height', 'length', 'offset', 'isVideo', 'path', 'fillwindow',
+ 'sources', 'disablecontrols' );
+ foreach ( $options as $key ) {
+ if( isset( $conf[ $key ]) ){
+ $this->$key = $conf[$key];
+ } else {
+ $this->$key = false;
+ }
+ }
+ }
+
+ /**
+ * @return TextHandler
+ */
+ function getTextHandler(){
+ if( !$this->textHandler ){
+ // Init an associated textHandler
+ $this->textHandler = new TextHandler( $this->file );
+ }
+ return $this->textHandler;
+ }
+
+ /**
+ * Get the media transform thumbnail
+ * @return string
+ */
+ function getUrl( $sizeOverride = false ){
+ global $wgVersion, $wgResourceBasePath, $wgStylePath;
+ // Needs to be 1.24c because version_compare() works in confusing ways
+ if ( version_compare( $wgVersion, '1.24c', '>=' ) ) {
+ $url = "$wgResourceBasePath/resources/assets/file-type-icons/fileicon-ogg.png";
+ } else {
+ $url = "$wgStylePath/common/images/icons/fileicon-ogg.png";
+ }
+
+ if ( $this->isVideo ) {
+ if ( $this->thumbUrl ) {
+ $url = $this->thumbUrl;
+ }
+
+ // Update the $posterUrl to $sizeOverride ( if not an old file )
+ if( !$this->file->isOld() && $sizeOverride &&
+ $sizeOverride[0] && intval( $sizeOverride[0] ) != intval( $this->width ) ){
+ $apiUrl = $this->getPoster( $sizeOverride[0] );
+ if( $apiUrl ){
+ $url = $apiUrl;
+ }
+ }
+ }
+ return $url;
+ }
+
+ /**
+ * TODO get the local path
+ * @return mixed
+ */
+ function getPath(){
+ return $this->dstPath;
+ }
+
+ /**
+ * @return int
+ */
+ function getPlayerHeight(){
+ // Check if "video" tag output:
+ if ( $this->isVideo ) {
+ return intval( $this->height );
+ } else {
+ // Give sound files a height of 23px
+ return 23;
+ }
+ }
+
+ /**
+ * @return int
+ */
+ function getPlayerWidth(){
+ // Check if "video" tag output:
+ if ( $this->isVideo ) {
+ return intval( $this->width );
+ } else {
+ // Give sound files a width of 300px ( if unsized )
+ if( $this->width == 0 ){
+ return 300;
+ }
+ // else give the target size down to 35 px wide
+ return ( $this->width < 35 ) ? 35 : intval( $this->width ) ;
+ }
+ }
+
+ /**
+ * @return string
+ */
+ function getTagName(){
+ return ( $this->isVideo ) ? 'video' : 'audio';
+ }
+
+ /**
+ * @param $options array
+ * @return string
+ * @throws Exception
+ */
+ function toHtml( $options = array() ) {
+ if ( count( func_get_args() ) == 2 ) {
+ throw new Exception( __METHOD__ .' called in the old style' );
+ }
+
+ $oldHeight = $this->height;
+ $oldWidth = $this->width;
+ if ( isset( $options['override-height'] ) ) {
+ $this->height = $options['override-height'];
+ }
+ if ( isset( $options['override-width'] ) ) {
+ $this->width = $options['override-width'];
+ }
+
+ if ( $this->useImagePopUp() ) {
+ $res = $this->getImagePopUp();
+ } else {
+ $res = $this->getHtmlMediaTagOutput();
+ }
+ $this->width = $oldWidth;
+ $this->height = $oldHeight;
+ return $res;
+ }
+
+ /**
+ * Helper to determine if to use pop up dialog for videos
+ *
+ * @return boolean
+ */
+ private function useImagePopUp() {
+ global $wgMinimumVideoPlayerSize;
+ // Check if the video is too small to play inline ( instead do a pop-up dialog )
+ // If we're filling the window (e.g. during an iframe embed) one probably doesn't want the pop up.
+ // Also the pop up is broken in that case.
+ return $this->isVideo
+ && !$this->fillwindow
+ && $this->getPlayerWidth() < $wgMinimumVideoPlayerSize
+ // Do not do pop-up if its going to be the same size as inline player anyways
+ && $this->getPlayerWidth() < $this->getPopupPlayerWidth();
+ }
+
+ /**
+ * XXX migrate this to the mediawiki Html class as 'tagSet' helper function
+ * @param $tagName
+ * @param $tagSet
+ * @return string
+ */
+ static function htmlTagSet( $tagName, $tagSet ){
+ if( empty( $tagSet ) ){
+ return '';
+ }
+ $s = '';
+ foreach( $tagSet as $attr ){
+ $s .= Html::element( $tagName, $attr);
+ }
+ return $s;
+ }
+
+ /**
+ * @return string
+ */
+ function getImagePopUp(){
+ // pop up videos set the autoplay attribute to true:
+ $autoPlay = true;
+ return Xml::tags( 'div' , array(
+ 'id' => self::PLAYER_ID_PREFIX . TimedMediaTransformOutput::$serial++,
+ 'class' => 'PopUpMediaTransform',
+ 'style' => "width:" . $this->getPlayerWidth() . "px;",
+ 'videopayload' => $this->getHtmlMediaTagOutput( $this->getPopupPlayerSize(), $autoPlay ),
+ ),
+ Xml::tags( 'img', array(
+ 'alt' => $this->file->getTitle(),
+ 'style' => "width:" . $this->getPlayerWidth() . "px;height:" .
+ $this->getPlayerHeight() . "px",
+ 'src' => $this->getUrl(),
+ ),'')
+ .
+ // For javascript disabled browsers provide a link to the asset:
+ Xml::tags( 'a', array(
+ 'href'=> $this->file->getUrl(),
+ 'title' => wfMessage( 'timedmedia-play-media' )->escaped(),
+ 'target' => 'new'
+ ),
+ Xml::tags( 'span', array(
+ 'class' => 'play-btn-large'
+ ),
+ // Have some sort of text for lynx & screen readers.
+ Html::element(
+ 'span',
+ array( 'class' => 'mw-tmh-playtext' ),
+ wfMessage( 'timedmedia-play-media' )->text()
+ )
+ )
+ )
+ );
+ }
+
+ /**
+ * Get target popup player size
+ */
+ function getPopupPlayerSize(){
+ // Get the max width from the enabled transcode settings:
+ $maxImageSize = WebVideoTranscode::getMaxSizeWebStream();
+ return WebVideoTranscode::getMaxSizeTransform( $this->file, $maxImageSize);
+ }
+
+ /**
+ * Helper function to get pop up width
+ *
+ * Silly function because array index operations aren't allowed
+ * on function calls before php 5.4
+ */
+ private function getPopupPlayerWidth() {
+ list( $popUpWidth ) = $this->getPopupPlayerSize();
+ return $popUpWidth;
+ }
+
+ /**
+ * Sort media by bandwidth, but with things not wide enough at end
+ *
+ * The list should be in preferred source order, so we want the file
+ * with the lowest bitrate (to save bandwidth) first, but we also want
+ * appropriate resolution files before the 160p transcodes.
+ */
+ private function sortMediaByBandwidth( $a, $b ) {
+ $width = $this->getPlayerWidth();
+ $maxWidth = $this->getPopupPlayerWidth();
+ if ( $this->useImagePopUp() || $width > $maxWidth ) {
+ // If its a pop-up player than we should use the pop up player size
+ // if its a normal player, but has a bigger width than the pop-up
+ // player, then we use the pop-up players width as the target width
+ // as that is equivalent to the max transcode size. Otherwise this
+ // will suggest the original file as the best source, which seems like
+ // a potentially bad idea, as it could be anything size wise.
+ $width = $maxWidth;
+ }
+
+ if ( $a['width'] < $width && $b['width'] >= $width ) {
+ // $a is not wide enough but $b is
+ // so we consider $a > $b as we want $b before $a
+ return 1;
+ }
+ if ( $a['width'] >= $width && $b['width'] < $width ) {
+ // $b not wide enough, so $a must be preferred.
+ return -1;
+ }
+ if ( $a['width'] < $width && $b['width'] < $width && $a['width'] != $b['width'] ) {
+ // both are too small. Go with the one closer to the target width
+ return ( $a['width'] < $b['width'] ) ? -1 : 1;
+ }
+ // Both are big enough, or both equally too small. Go with the one
+ // that has a lower bit-rate (as it will be faster to download).
+ if ( isset( $a['bandwidth'] ) && isset( $b['bandwidth'] ) ) {
+ return ( $a['bandwidth'] < $b['bandwidth'] ) ? -1 : 1;
+ }
+
+ // We have no firm basis for a comparison, so consider them equal.
+ return 0;
+ }
+
+ /**
+ * Call mediaWiki xml helper class to build media tag output from
+ * supplied arrays
+ * @param $sizeOverride array
+ * @param $autoPlay boolean sets the autoplay attribute
+ * @return string
+ */
+ function getHtmlMediaTagOutput( $sizeOverride = array(), $autoPlay = false ){
+ // Try to get the first source src attribute ( usually this should be the source file )
+ $mediaSources = $this->getMediaSources();
+ reset( $mediaSources ); // do not rely on auto-resetting of arrays under HHVM
+ $firstSource = current( $mediaSources );
+
+ if( !$firstSource['src'] ){
+ // XXX media handlers don't seem to work with exceptions..
+ return 'Error missing media source';
+ };
+
+ // Sort sources by bandwidth least to greatest ( so default selection on resource constrained
+ // browsers ( without js? ) go with minimal source.
+ usort( $mediaSources, array( $this, 'sortMediaByBandwidth' ) );
+
+ // We prefix some source attributes with data- to pass along to the javascript player
+ $prefixedSourceAttr = Array( 'width', 'height', 'title', 'shorttitle', 'bandwidth', 'framerate', 'disablecontrols' );
+ foreach( $mediaSources as &$source ){
+ foreach( $source as $attr => $val ){
+ if( in_array( $attr, $prefixedSourceAttr ) ){
+ $source[ 'data-' . $attr ] = $val;
+ unset( $source[ $attr ] );
+ }
+ }
+ }
+
+ $width = $sizeOverride ? $sizeOverride[0] : $this->getPlayerWidth();
+ if( $this->fillwindow ){
+ $width = '100%';
+ } else {
+ $width .= 'px';
+ }
+ // Build the video tag output:
+ $s = Xml::tags( 'div' , array(
+ 'class' => 'mediaContainer',
+ 'style' => 'position:relative;display:block;width:'. $width
+ ),
+ Html::rawElement( $this->getTagName(), $this->getMediaAttr( $sizeOverride, $autoPlay ),
+ // The set of media sources:
+ self::htmlTagSet( 'source', $mediaSources ) .
+
+ // Timed text:
+ self::htmlTagSet( 'track',
+ $this->file ? $this->getTextHandler()->getTracks() : null ) .
+
+ // Fallback text displayed for browsers without js and without video tag support:
+ /// XXX note we may want to replace this with an image and download link play button
+ wfMessage( 'timedmedia-no-player-js', $firstSource['src'] )->text()
+ )
+ );
+ return $s;
+ }
+
+ /**
+ * Get poster.
+ * @param $width Integer width of poster. Should not equal $this->width.
+ * @throws Exception If $width is same as $this->width.
+ * @return String|bool url for poster or false
+ */
+ function getPoster ( $width ) {
+ if ( intval( $width ) === intval( $this->width ) ) {
+ // Prevent potential loop
+ throw new Exception( "Asked for poster in current size. Potential loop." );
+ }
+ $params = array( "width" => intval( $width ) );
+ $mto = $this->file->transform( $params );
+ if ( $mto ) {
+ return $mto->getUrl();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Get the media attributes
+ * @param $sizeOverride Array|bool of width and height
+ * @return array
+ */
+ function getMediaAttr( $sizeOverride = false, $autoPlay = false ){
+ global $wgVideoPlayerSkin ;
+ // Normalize values
+ $length = floatval( $this->length );
+ $offset = floatval( $this->offset );
+
+ $width = $sizeOverride ? $sizeOverride[0] : $this->getPlayerWidth();
+ $height = $sizeOverride ? $sizeOverride[1]: $this->getPlayerHeight();
+
+ // The poster url:
+ $posterUrl = $this->getUrl( $sizeOverride );
+
+ if( $this->fillwindow ){
+ $width = '100%';
+ $height = '100%';
+ } else{
+ $width .= 'px';
+ $height .= 'px';
+ }
+
+ $mediaAttr = array(
+ 'id' => self::PLAYER_ID_PREFIX . TimedMediaTransformOutput::$serial++,
+ 'style' => "width:{$width}",
+ // Get the correct size:
+ 'poster' => $posterUrl,
+
+ // Note we set controls to true ( for no-js players ) when mwEmbed rewrites the interface
+ // it updates the controls attribute of the embed video
+ 'controls'=> 'true',
+ // Since we will reload the item with javascript,
+ // tell browser to not load the video before
+ 'preload'=>'none',
+ );
+
+ if ( $this->isVideo ) {
+ $mediaAttr['style'] .= ";height:{$height}";
+ }
+
+ if( $autoPlay === true ){
+ $mediaAttr['autoplay'] = 'true';
+ }
+
+ // MediaWiki uses the kSkin class
+ $mediaAttr['class'] = 'kskin';
+
+ if ( $this->file ) {
+ // Custom data-attributes
+ $mediaAttr += array(
+ 'data-durationhint' => $length,
+ 'data-startoffset' => $offset,
+ 'data-mwtitle' => $this->file->getTitle()->getDBkey()
+ );
+
+ // Add api provider:
+ if( $this->file->isLocal() ){
+ $apiProviderName = 'local';
+ } else {
+ // Set the api provider name to "wikimediacommons" for shared ( instant commons convention )
+ // (provider names should have identified the provider instead of the provider type "shared")
+ $apiProviderName = $this->file->getRepoName();
+ if( $apiProviderName == 'shared' ) {
+ $apiProviderName = 'wikimediacommons';
+ }
+ }
+ // XXX Note: will probably migrate mwprovider to an escaped api url.
+ $mediaAttr[ 'data-mwprovider' ] = $apiProviderName;
+ } else {
+ if ( $length ) {
+ $mediaAttr[ 'data-durationhint' ] = $length;
+ }
+ if ( $offset ) {
+ $mediaAttr[ 'data-startoffset' ] = $offset;
+ }
+ }
+ if ( $this->disablecontrols ) {
+ $mediaAttr[ 'data-disablecontrols' ] = $this->disablecontrols;
+ }
+ return $mediaAttr;
+ }
+
+ /**
+ * @return null
+ */
+ function getMediaSources(){
+ if( !$this->sources ){
+ // Generate transcode jobs ( and get sources that are already transcoded)
+ // At a minimum this should return the source video file.
+ $this->sources = WebVideoTranscode::getSources( $this->file );
+ // Check if we have "start or end" times and append the temporal url fragment hash
+ foreach( $this->sources as &$source ){
+ $source['src'].= $this->getTemporalUrlHash();
+ }
+ }
+ return $this->sources;
+ }
+
+ function getTemporalUrlHash(){
+ if( $this->hashTime ){
+ return $this->hashTime;
+ }
+ $hash ='';
+ if( $this->start ){
+ $startSec = TimedMediaHandler::parseTimeString( $this->start );
+ if( $startSec !== false ){
+ $hash.= '#t=' . TimedMediaHandler::seconds2npt( $startSec );
+ }
+ }
+ if( $this->end ){
+ if( $hash == '' ){
+ $hash .= '#t=0';
+ }
+ $endSec = TimedMediaHandler::parseTimeString( $this->end );
+ if( $endSec !== false ){
+ $hash.= ',' . TimedMediaHandler::seconds2npt( $endSec );
+ }
+ }
+ $this->hashTime = $hash;
+ return $this->hashTime;
+ }
+}
diff --git a/extensions/TimedMediaHandler/TimedTextPage.php b/extensions/TimedMediaHandler/TimedTextPage.php
new file mode 100644
index 00000000..361c2eb9
--- /dev/null
+++ b/extensions/TimedMediaHandler/TimedTextPage.php
@@ -0,0 +1,187 @@
+<?php
+/**
+ * TimedText page display the current video with subtitles to the right.
+ *
+ * Future features for this page"
+ * @todo add srt download links
+ * @todo parse and validate srt files
+ * @todo link-in or include the universal subtitles editor
+ */
+class TimedTextPage extends Article {
+ // The width of the video plane:
+ static private $videoWidth = 400;
+ static private $knownTimedTextExtensions = array( 'srt', 'vtt' );
+
+ public function view() {
+ $request = $this->getContext()->getRequest();
+ $out = $this->getContext()->getOutput();
+ $user = $this->getContext()->getUser();
+
+ $diff = $request->getVal( 'diff' );
+
+ if ( $this->getTitle()->getNamespace() != NS_TIMEDTEXT || isset( $diff ) ) {
+ parent::view();
+ return;
+ }
+ $this->renderOutput( $out );
+ }
+
+ /**
+ * Render TimedText to given output
+ * @param $out OutputPage
+ */
+ public function renderOutput( $out ){
+ // parse page title:
+ $titleParts = explode( '.', $this->getTitle()->getDBkey() );
+ $timedTextExtension = array_pop( $titleParts );
+ $languageKey = array_pop( $titleParts );
+
+ $oldid = $this->getOldID();
+ # Are we looking at an old revision
+ if ( $oldid && $this->mRevision ) {
+ $this->fetchContentObject();
+ $out->setRevisionId( $this->getRevIdFetched() );
+ $this->setOldSubtitle( $oldid );
+
+ if ( !$this->showDeletedRevisionHeader() ) {
+ wfDebug( __METHOD__ . ": cannot view deleted revision\n" );
+ return;
+ }
+ }
+
+ // Check for File name without text extension:
+ // i.e TimedText:myfile.ogg
+ $fileTitle = Title::newFromText( $this->getTitle()->getDBkey(), NS_FILE );
+ $file = wfFindFile( $fileTitle );
+ // Check for a valid srt page, present redirect form for the full title match:
+ if( !in_array( $timedTextExtension, self::$knownTimedTextExtensions ) && $file && $file->exists() ){
+ if( $file->isLocal() ){
+ $this->doRedirectToPageForm( $fileTitle );
+ } else {
+ $this->doLinkToRemote( $file );
+ }
+ return;
+ }
+
+ // Check for File name with text extension ( from remaning parts of title )
+ // i.e TimedText:myfile.ogg.en.srt
+
+ $videoTitle = Title::newFromText( implode('.', $titleParts ), NS_FILE );
+
+ // Check for remote file
+ $basefile = wfFindFile( $videoTitle );
+ if ( !$basefile ) {
+ $out->addHTML( wfMessage( 'timedmedia-subtitle-no-video' )->escaped() );
+ return;
+ }
+
+ if( !$basefile->isLocal() ){
+ $this->doLinkToRemote( $basefile );
+ return;
+ }
+
+ // Look up the language name:
+ $language = $out->getLanguage()->getCode();
+ $languages = Language::fetchLanguageNames( $language, 'all' );
+ if( isset( $languages[ $languageKey ] ) ) {
+ $languageName = $languages[ $languageKey ];
+ } else {
+ $languageName = $languageKey;
+ }
+
+ // Set title
+ $message = $this->exists() ?
+ 'mwe-timedtext-language-subtitles-for-clip' :
+ 'mwe-timedtext-language-no-subtitles-for-clip';
+ $out->setPageTitle( wfMessage($message, $languageName, $videoTitle ) );
+
+ // Get the video with with a max of 600 pixel page
+ $out->addHTML(
+ xml::tags( 'table', array( 'style'=> 'border:none' ),
+ xml::tags( 'tr', null,
+ xml::tags( 'td', array( 'valign' => 'top', 'width' => self::$videoWidth ),
+ $this->getVideoHTML( $videoTitle )
+ ) .
+ xml::tags( 'td', array( 'valign' => 'top' ) , $this->getTimedTextHTML( $languageName ) )
+ )
+ )
+ );
+ }
+
+ /**
+ * Timed text or file is hosted on remote repo, Add a short description and link to foring repo
+ * @param $file File the base file
+ */
+ function doLinkToRemote( $file ){
+ $output = $this->getContext()->getOutput();
+ $output->setPageTitle( wfMessage( 'timedmedia-subtitle-remote',
+ $file->getRepo()->getDisplayName() ) );
+ $output->addHTML( wfMessage( 'timedmedia-subtitle-remote-link',
+ $file->getDescriptionUrl(), $file->getRepo()->getDisplayName() ) );
+ }
+
+ function doRedirectToPageForm(){
+ $lang = $this->getContext()->getLanguage();
+ $out = $this->getContext()->getOutput();
+
+ // Set the page title:
+ $out->setPageTitle( wfMessage( 'timedmedia-subtitle-new' ) );
+
+ // Look up the language name:
+ $language = $out->getLanguage()->getCode();
+ $attrs = array( 'id' => 'timedmedia-tt-input' );
+ $langSelect = Xml::languageSelector( $language, false, null, $attrs, null );
+
+ $out->addHTML(
+ Xml::tags('div', array( 'style' => 'text-align:center' ),
+ Xml::tags( 'div', null,
+ wfMessage( 'timedmedia-subtitle-new-desc', $lang->getCode() )->parse()
+ ) .
+ $langSelect[1] .
+ Xml::tags( 'button',
+ array( 'id' => 'timedmedia-tt-go' ),
+ wfMessage( 'timedmedia-subtitle-new-go' )->escaped()
+ )
+ )
+ );
+ $out->addModules( 'ext.tmh.TimedTextSelector' );
+ }
+
+ /**
+ * Gets the video HTML ( with the current language set as default )
+ * @param $videoTitle string
+ * @return String
+ */
+ private function getVideoHTML( $videoTitle ){
+ // Get the video embed:
+ $file = wfFindFile( $videoTitle );
+ if( !$file ){
+ return wfMessage( 'timedmedia-subtitle-no-video' )->escaped();
+ } else {
+ $videoTransform= $file->transform(
+ array(
+ 'width' => self::$videoWidth
+ )
+ );
+ return $videoTransform->toHTML();
+ }
+ }
+
+ /**
+ * Gets an HTML representation of the Timed Text
+ *
+ * @param $languageName string
+ * @return Message|string
+ */
+ private function getTimedTextHTML( $languageName ){
+ if( !$this->exists() ){
+ return wfMessage( 'timedmedia-subtitle-no-subtitles', $languageName );
+ }
+ return Xml::element(
+ 'pre',
+ array( 'style' => 'margin-top: 0px;' ),
+ $this->getContent(),
+ false
+ );
+ }
+}
diff --git a/extensions/TimedMediaHandler/TranscodeStatusTable.php b/extensions/TimedMediaHandler/TranscodeStatusTable.php
new file mode 100644
index 00000000..2220fc72
--- /dev/null
+++ b/extensions/TimedMediaHandler/TranscodeStatusTable.php
@@ -0,0 +1,236 @@
+<?php
+/**
+ * TranscodeStatusTable outputs a "transcode" status table to the ImagePage
+ *
+ * If logged in as autoconfirmed users can reset transcode states
+ * via the transcode api entry point
+ *
+ */
+class TranscodeStatusTable {
+ /**
+ * @param $file File
+ * @return string
+ */
+ public static function getHTML( $file ){
+ global $wgUser, $wgOut;
+
+ // Add transcode table css and javascript:
+ $wgOut->addModules( array( 'ext.tmh.transcodetable' ) );
+
+ $o = '<h2 id="transcodestatus">' . wfMessage( 'timedmedia-status-header' )->escaped() . '</h2>';
+ // Give the user a purge page link
+ $o.= Linker::link(
+ $file->getTitle(),
+ wfMessage('timedmedia-update-status')->escaped(),
+ array(),
+ array( 'action'=> 'purge' )
+ );
+
+ $o.= Xml::openElement( 'table', array( 'class' => 'wikitable mw-filepage-transcodestatus' ) ) . "\n"
+ . '<tr>'
+ . '<th>' . wfMessage( 'timedmedia-transcodeinfo' )->escaped() . '</th>'
+ . '<th>' . wfMessage( 'timedmedia-transcodebitrate' )->escaped() . '</th>'
+ . '<th>' . wfMessage( 'timedmedia-direct-link' )->escaped() . '</th>';
+
+ if( $wgUser->isAllowed( 'transcode-reset' ) ) {
+ $o.= '<th>' . wfMessage( 'timedmedia-actions' )->escaped() . '</th>';
+ }
+
+ $o.= '<th>' . wfMessage( 'timedmedia-status' )->escaped() . '</th>';
+ $o.= '<th>' . wfMessage( 'timedmedia-transcodeduration' )->escaped() . '</th>';
+ $o.= "</tr>\n";
+
+ $o.= self::getTranscodeRows( $file );
+
+ $o.= Xml::closeElement( 'table' );
+ return $o;
+ }
+
+ /**
+ * Get the video or audio codec for the defined transcode,
+ * for grouping/sorting purposes.
+ */
+ public static function codecFromTranscodeKey( $key ) {
+ if ( isset( WebVideoTranscode::$derivativeSettings[$key] ) ) {
+ $settings = WebVideoTranscode::$derivativeSettings[$key];
+ if ( isset( $settings['videoCodec'] ) ) {
+ return $settings['videoCodec'];
+ } else if ( isset( $settings['audioCodec'] ) ) {
+ return $settings['audioCodec'];
+ } else {
+ // this this shouldn't happen...
+ // fall through
+ }
+ } else {
+ // derivative type no longer defined or invalid def?
+ // fall through
+ }
+ return $key;
+ }
+
+ /**
+ * @param $file File
+ * @return string
+ */
+ public static function getTranscodeRows( $file ){
+ global $wgUser, $wgLang;
+ $o='';
+
+ $transcodeRows = WebVideoTranscode::getTranscodeState( $file );
+
+ uksort( $transcodeRows, function( $a, $b ) {
+ $formatOrder = array( 'vp9', 'vp8', 'h264', 'theora', 'opus', 'vorbis', 'aac' );
+
+ $aFormat = self::codecFromTranscodeKey( $a );
+ $bFormat = self::codecFromTranscodeKey( $b );
+ $aIndex = array_search( $aFormat, $formatOrder );
+ $bIndex = array_search( $bFormat, $formatOrder );
+
+ if ( $aIndex === false && $bIndex === false ) {
+ return -strnatcmp( $a, $b );
+ } else if ( $aIndex === false ) {
+ return 1;
+ } else if ( $bIndex === false ) {
+ return -1;
+ } else if ( $aIndex === $bIndex ) {
+ return -strnatcmp( $a, $b );
+ } else {
+ return ( $aIndex - $bIndex );
+ }
+ } );
+
+ foreach( $transcodeRows as $transcodeKey => $state ){
+ $o.='<tr>';
+ // Encode info:
+ $o.='<td>' . wfMessage('timedmedia-derivative-' . $transcodeKey )->escaped() . '</td>';
+ $o.='<td>' . self::getTranscodeBitrate( $file, $state ) . '</td>';
+
+ // Download file
+ $o.='<td>';
+ $o.= ( !is_null( $state['time_success'] ) ) ?
+ '<a href="'.self::getSourceUrl( $file, $transcodeKey ) .'" title="'.wfMessage
+ ('timedmedia-download' )->escaped() .'"><div class="download-btn"><span>' .
+ wfMessage('timedmedia-download' )->escaped(). '</span></div></a></td>' :
+ wfMessage('timedmedia-not-ready' )->escaped();
+ $o.='</td>';
+
+ // Check if we should include actions:
+ if( $wgUser->isAllowed( 'transcode-reset' ) ){
+ // include reset transcode action buttons
+ $o.='<td class="mw-filepage-transcodereset"><a href="#" data-transcodekey="' .
+ htmlspecialchars( $transcodeKey ). '">' . wfMessage('timedmedia-reset')->escaped() .
+ '</a></td>';
+ }
+
+ // Status:
+ $o.='<td>' . self::getStatusMsg( $file, $state ) . '</td>';
+ $o.='<td>' . self::getTranscodeDuration( $file, $state ) . '</td>';
+
+ $o.='</tr>';
+ }
+ return $o;
+ }
+
+ /**
+ * @param $file File
+ * @param $transcodeKey string
+ * @return string
+ */
+ public static function getSourceUrl( $file, $transcodeKey ){
+ return WebVideoTranscode::getTranscodedUrlForFile( $file, $transcodeKey );
+ }
+
+ /**
+ * @param $file File
+ * @param $state
+ * @return string
+ */
+ public static function getTranscodeDuration( $file, $state ) {
+ global $wgLang;
+ if( !is_null( $state['time_success'] ) ) {
+ $startTime = wfTimestamp( TS_UNIX, $state['time_startwork'] );
+ $endTime = wfTimestamp( TS_UNIX, $state['time_success'] );
+ $delta = $endTime - $startTime;
+ $duration = $wgLang->formatTimePeriod( $delta );
+ return $duration;
+ } else {
+ return '';
+ }
+ }
+
+ /**
+ * @param $file File
+ * @param $state
+ * @return string
+ */
+ public static function getTranscodeBitrate( $file, $state ) {
+ global $wgLang;
+ if( !is_null( $state['time_success'] ) ) {
+ return $wgLang->formatBitrate( $state['final_bitrate'] );
+ } else {
+ return '';
+ }
+ }
+
+ /**
+ * @param $file File
+ * @param $state
+ * @return string
+ */
+ public static function getStatusMsg( $file, $state ){
+ global $wgContLang;
+ // Check for success:
+ if( !is_null( $state['time_success'] ) ) {
+ return wfMessage( 'timedmedia-completed-on',
+ $wgContLang->timeAndDate( $state[ 'time_success' ] ) )->escaped();
+ }
+ // Check for error:
+ if( !is_null( $state['time_error'] ) ){
+ $attribs = array();
+ if( !is_null( $state['error'] ) ){
+ $attribs = array(
+ 'class' => 'mw-tmh-pseudo-error-link',
+ 'data-error' => $state['error'],
+ );
+ }
+
+ return Html::rawElement( 'span', $attribs,
+ wfMessage( 'timedmedia-error-on',
+ $wgContLang->timeAndDate( $state['time_error'] ) )->escaped()
+ );
+ }
+
+ //$db = wfGetDB( DB_SLAVE );
+ // Check for started encoding
+ if( !is_null( $state['time_startwork'] ) ){
+ $timePassed = time() - wfTimestamp ( TS_UNIX, $state['time_startwork'] );
+ // Get the rough estimate of time done: ( this is not very costly considering everything else
+ // that happens in an action=purge video page request )
+ /*$filePath = WebVideoTranscode::getTargetEncodePath( $file, $state['key'] );
+ if( is_file( $filePath ) ){
+ $targetSize = WebVideoTranscode::getProjectedFileSize( $file, $state['key'] );
+ if( $targetSize === false ){
+ $doneMsg = wfMessage( 'timedmedia-unknown-target-size', $wgLang->formatSize( filesize( $filePath ) ) )->escaped();
+ } else {
+ $doneMsg = wfMessage('timedmedia-percent-done', round( filesize( $filePath ) / $targetSize, 2 ) )->escaped();
+ }
+ } */
+ // Predicting percent done is not working well right now ( disabled for now )
+ $doneMsg = '';
+ return wfMessage(
+ 'timedmedia-started-transcode',
+ TimedMediaHandler::getTimePassedMsg( $timePassed ), $doneMsg
+ )->escaped();
+ }
+ // Check for job added ( but not started encoding )
+ if( !is_null( $state['time_addjob'] ) ){
+ $timePassed = time() - wfTimestamp ( TS_UNIX, $state['time_addjob'] );
+ return wfMessage(
+ 'timedmedia-in-job-queue',
+ TimedMediaHandler::getTimePassedMsg( $timePassed )
+ )->escaped();
+ }
+ // Return unknown status error:
+ return wfMessage('timedmedia-status-unknown')->escaped();
+ }
+}
diff --git a/extensions/TimedMediaHandler/WebVideoTranscode/WebVideoTranscode.php b/extensions/TimedMediaHandler/WebVideoTranscode/WebVideoTranscode.php
new file mode 100644
index 00000000..e4d02556
--- /dev/null
+++ b/extensions/TimedMediaHandler/WebVideoTranscode/WebVideoTranscode.php
@@ -0,0 +1,1192 @@
+<?php
+/**
+ * WebVideoTranscode provides:
+ * encode keys
+ * encode settings
+ *
+ * extends api to return all the streams
+ * extends video tag output to provide all the available sources
+ */
+
+/**
+ * Main WebVideoTranscode Class hold some constants and config values
+ */
+class WebVideoTranscode {
+ /**
+ * Key constants for the derivatives,
+ * this key is appended to the derivative file name
+ *
+ * If you update the wgDerivativeSettings for one of these keys
+ * and want to re-generate the video you should also update the
+ * key constant. ( Or just run a maintenance script to delete all
+ * the assets for a given profile )
+ *
+ * Msg keys for derivatives are set as follows:
+ * $messages['timedmedia-derivative-200_200kbs.ogv'] => 'Ogg 200';
+ */
+
+ // Ogg Profiles
+ const ENC_OGV_160P = '160p.ogv';
+ const ENC_OGV_240P = '240p.ogv';
+ const ENC_OGV_360P = '360p.ogv';
+ const ENC_OGV_480P = '480p.ogv';
+ const ENC_OGV_720P = '720p.ogv';
+ const ENC_OGV_1080P = '1080p.ogv';
+
+ // WebM VP8/Vorbis profiles:
+ const ENC_WEBM_160P = '160p.webm';
+ const ENC_WEBM_360P = '360p.webm';
+ const ENC_WEBM_480P = '480p.webm';
+ const ENC_WEBM_720P = '720p.webm';
+ const ENC_WEBM_1080P = '1080p.webm';
+ const ENC_WEBM_2160P = '2160p.webm';
+
+ // WebM VP9/Opus profiles:
+ const ENC_VP9_360P = '360p.vp9.webm';
+ const ENC_VP9_480P = '480p.vp9.webm';
+ const ENC_VP9_720P = '720p.vp9.webm';
+ const ENC_VP9_1080P = '1080p.vp9.webm';
+ const ENC_VP9_2160P = '2160p.vp9.webm';
+
+ // mp4 profiles:
+ const ENC_H264_320P = '320p.mp4';
+ const ENC_H264_480P = '480p.mp4';
+ const ENC_H264_720P = '720p.mp4';
+ const ENC_H264_1080P = '1080p.mp4';
+ const ENC_H264_2160P = '2160p.mp4';
+
+ const ENC_OGG_VORBIS = 'ogg';
+ const ENC_OGG_OPUS = 'opus';
+ const ENC_MP3 = 'mp3';
+ const ENC_AAC = 'm4a';
+
+ // Static cache of transcode state per instantiation
+ public static $transcodeState = array() ;
+
+ /**
+ * Encoding parameters are set via firefogg encode api
+ *
+ * For clarity and compatibility with passing down
+ * client side encode settings at point of upload
+ *
+ * http://firefogg.org/dev/index.html
+ */
+ public static $derivativeSettings = array(
+ WebVideoTranscode::ENC_OGV_160P =>
+ array(
+ 'maxSize' => '288x160',
+ 'videoBitrate' => '160',
+ 'framerate' => '15',
+ 'audioQuality' => '-1',
+ 'samplerate' => '44100',
+ 'channels' => '2',
+ 'noUpscaling' => 'true',
+ //'twopass' => 'true', // temporarily disabled for broken ffmpeg2theora
+ 'optimize' => 'true',
+ 'keyframeInterval' => '128',
+ 'bufDelay' => '256',
+ 'videoCodec' => 'theora',
+ 'type' => 'video/ogg; codecs="theora, vorbis"',
+ ),
+ WebVideoTranscode::ENC_OGV_240P =>
+ array(
+ 'maxSize' => '426x240',
+ 'videoBitrate' => '512',
+ 'audioQuality' => '0',
+ 'samplerate' => '44100',
+ 'channels' => '2',
+ 'noUpscaling' => 'true',
+ //'twopass' => 'true', // temporarily disabled for broken ffmpeg2theora
+ 'optimize' => 'true',
+ 'keyframeInterval' => '128',
+ 'bufDelay' => '256',
+ 'videoCodec' => 'theora',
+ 'type' => 'video/ogg; codecs="theora, vorbis"',
+ ),
+ WebVideoTranscode::ENC_OGV_360P =>
+ array(
+ 'maxSize' => '640x360',
+ 'videoBitrate' => '1024',
+ 'audioQuality' => '1',
+ 'samplerate' => '44100',
+ 'channels' => '2',
+ 'noUpscaling' => 'true',
+ //'twopass' => 'true', // temporarily disabled for broken ffmpeg2theora
+ 'optimize' => 'true',
+ 'keyframeInterval' => '128',
+ 'bufDelay' => '256',
+ 'videoCodec' => 'theora',
+ 'type' => 'video/ogg; codecs="theora, vorbis"',
+ ),
+ WebVideoTranscode::ENC_OGV_480P =>
+ array(
+ 'maxSize' => '854x480',
+ 'videoBitrate' => '2048',
+ 'audioQuality' => '2',
+ 'samplerate' => '44100',
+ 'channels' => '2',
+ 'noUpscaling' => 'true',
+ //'twopass' => 'true', // temporarily disabled for broken ffmpeg2theora
+ 'optimize' => 'true',
+ 'keyframeInterval' => '128',
+ 'bufDelay' => '256',
+ 'videoCodec' => 'theora',
+ 'type' => 'video/ogg; codecs="theora, vorbis"',
+ ),
+
+ WebVideoTranscode::ENC_OGV_720P =>
+ array(
+ 'maxSize' => '1280x720',
+ 'videoQuality' => 6,
+ 'audioQuality' => 3,
+ 'noUpscaling' => 'true',
+ //'twopass' => 'true', // temporarily disabled for broken ffmpeg2theora
+ 'optimize' => 'true',
+ 'keyframeInterval' => '128',
+ 'videoCodec' => 'theora',
+ 'type' => 'video/ogg; codecs="theora, vorbis"',
+ ),
+
+ WebVideoTranscode::ENC_OGV_1080P =>
+ array(
+ 'maxSize' => '1920x1080',
+ 'videoQuality' => 6,
+ 'audioQuality' => 3,
+ 'noUpscaling' => 'true',
+ //'twopass' => 'true', // temporarily disabled for broken ffmpeg2theora
+ 'optimize' => 'true',
+ 'keyframeInterval' => '128',
+ 'videoCodec' => 'theora',
+ 'type' => 'video/ogg; codecs="theora, vorbis"',
+ ),
+
+ // WebM transcode:
+ WebVideoTranscode::ENC_WEBM_160P =>
+ array(
+ 'maxSize' => '288x160',
+ 'videoBitrate' => '256',
+ 'audioQuality' => '-1',
+ 'samplerate' => '44100',
+ 'channels' => '2',
+ 'noUpscaling' => 'true',
+ 'twopass' => 'true',
+ 'keyframeInterval' => '128',
+ 'bufDelay' => '256',
+ 'videoCodec' => 'vp8',
+ 'type' => 'video/webm; codecs="vp8, vorbis"',
+ ),
+ WebVideoTranscode::ENC_WEBM_360P =>
+ array(
+ 'maxSize' => '640x360',
+ 'videoBitrate' => '512',
+ 'audioQuality' => '1',
+ 'samplerate' => '44100',
+ 'noUpscaling' => 'true',
+ 'twopass' => 'true',
+ 'keyframeInterval' => '128',
+ 'bufDelay' => '256',
+ 'videoCodec' => 'vp8',
+ 'type' => 'video/webm; codecs="vp8, vorbis"',
+ ),
+ WebVideoTranscode::ENC_WEBM_480P =>
+ array(
+ 'maxSize' => '854x480',
+ 'videoBitrate' => '1024',
+ 'audioQuality' => '2',
+ 'samplerate' => '44100',
+ 'noUpscaling' => 'true',
+ 'twopass' => 'true',
+ 'keyframeInterval' => '128',
+ 'bufDelay' => '256',
+ 'videoCodec' => 'vp8',
+ 'type' => 'video/webm; codecs="vp8, vorbis"',
+ ),
+ WebVideoTranscode::ENC_WEBM_720P =>
+ array(
+ 'maxSize' => '1280x720',
+ 'videoQuality' => 7,
+ 'audioQuality' => 3,
+ 'noUpscaling' => 'true',
+ 'videoCodec' => 'vp8',
+ 'type' => 'video/webm; codecs="vp8, vorbis"',
+ ),
+ WebVideoTranscode::ENC_WEBM_1080P =>
+ array(
+ 'maxSize' => '1920x1080',
+ 'videoQuality' => 7,
+ 'audioQuality' => 3,
+ 'noUpscaling' => 'true',
+ 'videoCodec' => 'vp8',
+ 'type' => 'video/webm; codecs="vp8, vorbis"',
+ ),
+ WebVideoTranscode::ENC_WEBM_2160P =>
+ array(
+ 'maxSize' => '4096x2160',
+ 'videoQuality' => 7,
+ 'audioQuality' => 3,
+ 'noUpscaling' => 'true',
+ 'videoCodec' => 'vp8',
+ 'type' => 'video/webm; codecs="vp8, vorbis"',
+ ),
+
+ // WebM VP9 transcode:
+ WebVideoTranscode::ENC_VP9_360P =>
+ array(
+ 'maxSize' => '640x360',
+ 'videoBitrate' => '256',
+ 'samplerate' => '48000',
+ 'noUpscaling' => 'true',
+ 'twopass' => 'true',
+ 'keyframeInterval' => '128',
+ 'bufDelay' => '256',
+ 'videoCodec' => 'vp9',
+ 'audioCodec' => 'opus',
+ 'type' => 'video/webm; codecs="vp9, opus"',
+ ),
+ WebVideoTranscode::ENC_VP9_480P =>
+ array(
+ 'maxSize' => '854x480',
+ 'videoBitrate' => '512',
+ 'samplerate' => '48000',
+ 'noUpscaling' => 'true',
+ 'twopass' => 'true',
+ 'keyframeInterval' => '128',
+ 'bufDelay' => '256',
+ 'videoCodec' => 'vp9',
+ 'audioCodec' => 'opus',
+ 'type' => 'video/webm; codecs="vp9, opus"',
+ ),
+ WebVideoTranscode::ENC_VP9_720P =>
+ array(
+ 'maxSize' => '1280x720',
+ 'videoBitrate' => '1024',
+ 'samplerate' => '48000',
+ 'noUpscaling' => 'true',
+ 'twopass' => 'true',
+ 'keyframeInterval' => '128',
+ 'bufDelay' => '256',
+ 'videoCodec' => 'vp9',
+ 'audioCodec' => 'opus',
+ 'tileColumns' => '2',
+ 'type' => 'video/webm; codecs="vp9, opus"',
+ ),
+ WebVideoTranscode::ENC_VP9_1080P =>
+ array(
+ 'maxSize' => '1920x1080',
+ 'videoBitrate' => '2048',
+ 'samplerate' => '48000',
+ 'noUpscaling' => 'true',
+ 'twopass' => 'true',
+ 'keyframeInterval' => '128',
+ 'bufDelay' => '256',
+ 'videoCodec' => 'vp9',
+ 'audioCodec' => 'opus',
+ 'tileColumns' => '4',
+ 'type' => 'video/webm; codecs="vp9, opus"',
+ ),
+ WebVideoTranscode::ENC_VP9_2160P =>
+ array(
+ 'maxSize' => '4096x2160',
+ 'videoBitrate' => '8192',
+ 'samplerate' => '48000',
+ 'noUpscaling' => 'true',
+ 'twopass' => 'true',
+ 'keyframeInterval' => '128',
+ 'bufDelay' => '256',
+ 'videoCodec' => 'vp9',
+ 'audioCodec' => 'opus',
+ 'tileColumns' => '4',
+ 'type' => 'video/webm; codecs="vp9, opus"',
+ ),
+
+ // Losly defined per PCF guide to mp4 profiles:
+ // https://develop.participatoryculture.org/index.php/ConversionMatrix
+ // and apple HLS profile guide:
+ // https://developer.apple.com/library/ios/#documentation/networkinginternet/conceptual/streamingmediaguide/UsingHTTPLiveStreaming/UsingHTTPLiveStreaming.html#//apple_ref/doc/uid/TP40008332-CH102-DontLinkElementID_24
+
+ WebVideoTranscode::ENC_H264_320P =>
+ array(
+ 'maxSize' => '480x320',
+ 'videoCodec' => 'h264',
+ 'preset' => 'ipod320',
+ 'videoBitrate' => '400k',
+ 'audioCodec' => 'aac',
+ 'channels' => '2',
+ 'audioBitrate' => '40k',
+ 'type' => 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',
+ ),
+
+ WebVideoTranscode::ENC_H264_480P =>
+ array(
+ 'maxSize' => '640x480',
+ 'videoCodec' => 'h264',
+ 'preset' => 'ipod640',
+ 'videoBitrate' => '1200k',
+ 'audioCodec' => 'aac',
+ 'channels' => '2',
+ 'audioBitrate' => '64k',
+ 'type' => 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',
+ ),
+
+ WebVideoTranscode::ENC_H264_720P =>
+ array(
+ 'maxSize' => '1280x720',
+ 'videoCodec' => 'h264',
+ 'preset' => '720p',
+ 'videoBitrate' => '2500k',
+ 'audioCodec' => 'aac',
+ 'channels' => '2',
+ 'audioBitrate' => '128k',
+ 'type' => 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',
+ ),
+
+ WebVideoTranscode::ENC_H264_1080P =>
+ array(
+ 'maxSize' => '1920x1080',
+ 'videoCodec' => 'h264',
+ 'videoBitrate' => '5000k',
+ 'audioCodec' => 'aac',
+ 'channels' => '2',
+ 'audioBitrate' => '128k',
+ 'type' => 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',
+ ),
+ WebVideoTranscode::ENC_H264_2160P =>
+ array(
+ 'maxSize' => '4096x2160',
+ 'videoCodec' => 'h264',
+ 'videoBitrate' => '16384k',
+ 'audioCodec' => 'aac',
+ 'channels' => '2',
+ 'audioBitrate' => '128k',
+ 'type' => 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',
+ ),
+
+ //Audio profiles
+ WebVideoTranscode::ENC_OGG_VORBIS =>
+ array(
+ 'audioCodec' => 'vorbis',
+ 'audioQuality' => '1',
+ 'samplerate' => '44100',
+ 'channels' => '2',
+ 'noUpscaling' => 'true',
+ 'novideo' => 'true',
+ 'type' => 'audio/ogg; codecs="vorbis"',
+ ),
+ WebVideoTranscode::ENC_OGG_OPUS =>
+ array(
+ 'audioCodec' => 'opus',
+ 'audioQuality' => '1',
+ 'samplerate' => '44100',
+ 'channels' => '2',
+ 'noUpscaling' => 'true',
+ 'novideo' => 'true',
+ 'type' => 'audio/ogg; codecs="opus"',
+ ),
+ WebVideoTranscode::ENC_MP3 =>
+ array(
+ 'audioCodec' => 'mp3',
+ 'audioQuality' => '1',
+ 'samplerate' => '44100',
+ 'channels' => '2',
+ 'noUpscaling' => 'true',
+ 'novideo' => 'true',
+ 'type' => 'audio/mpeg',
+ ),
+ WebVideoTranscode::ENC_AAC =>
+ array(
+ 'audioCodec' => 'aac',
+ 'audioQuality' => '1',
+ 'samplerate' => '44100',
+ 'channels' => '2',
+ 'noUpscaling' => 'true',
+ 'novideo' => 'true',
+ 'type' => 'audio/mp4; codecs="mp4a.40.5"',
+ ),
+ );
+
+ /**
+ * @param $file File
+ * @param $transcodeKey string
+ * @return string
+ */
+ static public function getDerivativeFilePath( $file, $transcodeKey ) {
+ return $file->getTranscodedPath( self::getTranscodeFileBaseName( $file, $transcodeKey ) );
+ }
+
+ /**
+ * Get the name to use as the base name for the transcode.
+ *
+ * Swift has problems where the url-encoded version of
+ * the path (ie 'filename.ogv/filename.ogv.720p.webm' )
+ * is greater that > 1024 bytes, so shorten in that case.
+ *
+ * Future versions might respect FileRepo::$abbrvThreshold.
+ *
+ * @param File $file
+ * @param String $suffix Optional suffix (e.g. transcode key).
+ * @return String File name, or the string transcode.
+ */
+ static public function getTranscodeFileBaseName( $file, $suffix = '' ) {
+ $name = $file->getName();
+ if ( strlen( urlencode( $name ) ) * 2 + 12 > 1024 ) {
+ return 'transcode' . '.' . $suffix;
+ } else {
+ return $name . '.' . $suffix;
+ }
+ }
+
+ /**
+ * Get url for a transcode.
+ *
+ * @param $file File
+ * @param $suffix string Transcode key
+ * @return string
+ */
+ static public function getTranscodedUrlForFile( $file, $suffix = '' ) {
+ return $file->getTranscodedUrl( self::getTranscodeFileBaseName( $file, $suffix ) );
+ }
+
+ /**
+ * Get temp file at target path for video encode
+ *
+ * @param $file File
+ * @param $transcodeKey String
+ *
+ * @return TempFSFile at target encode path
+ */
+ static public function getTargetEncodeFile( &$file, $transcodeKey ){
+ $filePath = self::getDerivativeFilePath( $file, $transcodeKey );
+ $ext = strtolower( pathinfo( "$filePath", PATHINFO_EXTENSION ) );
+
+ // Create a temp FS file with the same extension
+ $tmpFile = TempFSFile::factory( 'transcode_' . $transcodeKey, $ext);
+ if ( !$tmpFile ) {
+ return False;
+ }
+ return $tmpFile;
+ }
+
+ /**
+ * Get the max size of the web stream ( constant bitrate )
+ * @return int
+ */
+ static public function getMaxSizeWebStream(){
+ global $wgEnabledTranscodeSet;
+ $maxSize = 0;
+ foreach( $wgEnabledTranscodeSet as $transcodeKey ){
+ if( isset( self::$derivativeSettings[$transcodeKey]['videoBitrate'] ) ){
+ $currentSize = self::$derivativeSettings[$transcodeKey]['maxSize'];
+ if( $currentSize > $maxSize ){
+ $maxSize = $currentSize;
+ }
+ }
+ }
+ return $maxSize;
+ }
+
+ /**
+ * Give a rough estimate on file size
+ * Note this is not always accurate.. especially with variable bitrate codecs ;)
+ * @param $file File
+ * @param $transcodeKey string
+ * @return number
+ */
+ static public function getProjectedFileSize( $file, $transcodeKey ){
+ $settings = self::$derivativeSettings[$transcodeKey];
+ if( $settings[ 'videoBitrate' ] && $settings['audioBitrate'] ){
+ return $file->getLength() * 8 * (
+ self::$derivativeSettings[$transcodeKey]['videoBitrate']
+ +
+ self::$derivativeSettings[$transcodeKey]['audioBitrate']
+ );
+ }
+ // Else just return the size of the source video ( we have no idea how large the actual derivative size will be )
+ return $file->getLength() * $file->getHandler()->getBitrate( $file ) * 8;
+ }
+
+ /**
+ * Static function to get the set of video assets
+ * Checks if the file is local or remote and grabs respective sources
+ * @param $file File
+ * @param $options array
+ * @return array|mixed
+ */
+ static public function getSources( &$file , $options = array() ){
+ if( $file->isLocal() || $file->repo instanceof ForeignDBViaLBRepo ){
+ return self::getLocalSources( $file , $options );
+ } else {
+ return self::getRemoteSources( $file , $options );
+ }
+ }
+
+ /**
+ * Grabs sources from the remote repo via ApiQueryVideoInfo.php entry point.
+ *
+ * TODO: This method could use some rethinking. See comments on PS1 of
+ * <https://gerrit.wikimedia.org/r/#/c/117916/>
+ *
+ * Because this works with commons regardless of whether TimedMediaHandler is installed or not
+ * @param $file File
+ * @param $options array
+ * @return array|mixed
+ */
+ static public function getRemoteSources(&$file , $options = array() ){
+ global $wgMemc;
+ // Setup source attribute options
+ $dataPrefix = in_array( 'nodata', $options )? '': 'data-';
+
+ // Use descriptionCacheExpiry as our expire for timed text tracks info
+ if ( $file->repo->descriptionCacheExpiry > 0 ) {
+ wfDebug("Attempting to get sources from cache...");
+ $key = $file->repo->getLocalCacheKey( 'WebVideoSources', 'url', $file->getName() );
+ $sources = $wgMemc->get($key);
+ if ( $sources ) {
+ wfDebug("Success found sources in local cache\n");
+ return $sources;
+ }
+ wfDebug("source cache miss\n");
+ }
+
+ wfDebug("Get Video sources from remote api for " . $file->getName() . "\n");
+ $query = array(
+ 'action' => 'query',
+ 'prop' => 'videoinfo',
+ 'viprop' => 'derivatives',
+ 'titles' => MWNamespace::getCanonicalName( NS_FILE ) .':'. $file->getTitle()->mTextform
+ );
+
+ $data = $file->repo->fetchImageQuery( $query );
+
+ if( isset( $data['warnings'] ) && isset( $data['warnings']['query'] )
+ && $data['warnings']['query']['*'] == "Unrecognized value for parameter 'prop': videoinfo" )
+ {
+ // Commons does not yet have TimedMediaHandler.
+ // Use the normal file repo system single source:
+ return array( self::getPrimarySourceAttributes( $file, array( $dataPrefix ) ) );
+ }
+ $sources = array();
+ // Generate the source list from the data response:
+ if( isset( $data['query'] ) && $data['query']['pages'] ){
+ $vidResult = array_shift( $data['query']['pages'] );
+ if( isset( $vidResult['videoinfo'] ) ) {
+ $derResult = array_shift( $vidResult['videoinfo'] );
+ $derivatives = $derResult['derivatives'];
+ foreach( $derivatives as $derivativeSource ){
+ $sources[] = $derivativeSource;
+ }
+ }
+ }
+
+ // Update the cache:
+ if ( $sources && $file->repo->descriptionCacheExpiry > 0 ) {
+ $wgMemc->set( $key, $sources, $file->repo->descriptionCacheExpiry );
+ }
+
+ return $sources;
+
+ }
+
+ /**
+ * Based on the $wgEnabledTranscodeSet set of enabled derivatives we
+ * return sources that are ready.
+ *
+ * This will not automatically update or queue anything!
+ *
+ * @param $file File object
+ * @param $options array Options, a set of options:
+ * 'nodata' Strips the data- attribute, useful when your output is not html
+ * @return array an associative array of sources suitable for <source> tag output
+ */
+ static public function getLocalSources( &$file , $options=array() ){
+ global $wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet, $wgEnableTranscode;
+ $sources = array();
+
+ // Add the original file:
+ $sources[] = self::getPrimarySourceAttributes( $file, $options );
+
+ // If $wgEnableTranscode is false don't look for or add other local sources:
+ if( $wgEnableTranscode === false &&
+ !($file->repo instanceof ForeignDBViaLBRepo) ){
+ return $sources;
+ }
+
+ // If an "oldFile" don't look for other sources:
+ if( $file->isOld() ){
+ return $sources;
+ }
+
+ // Now Check for derivatives
+ if( $file->getHandler()->isAudio( $file ) ){
+ $transcodeSet = $wgEnabledAudioTranscodeSet;
+ } else {
+ $transcodeSet = $wgEnabledTranscodeSet;
+ }
+ foreach( $transcodeSet as $transcodeKey ){
+ if ( self::isTranscodeEnabled( $file, $transcodeKey ) ) {
+ // Try and add the source
+ self::addSourceIfReady( $file, $sources, $transcodeKey, $options );
+ }
+ }
+
+ return $sources;
+ }
+
+ /**
+ * Get the transcode state for a given filename and transcodeKey
+ *
+ * @param $fileName string
+ * @param $transcodeKey string
+ * @return bool
+ */
+ public static function isTranscodeReady( $file, $transcodeKey ){
+
+ // Check if we need to populate the transcodeState cache:
+ $transcodeState = self::getTranscodeState( $file );
+
+ // If no state is found the cache for this file is false:
+ if( !isset( $transcodeState[ $transcodeKey ] ) ) {
+ return false;
+ }
+ // Else return boolean ready state ( if not null, then ready ):
+ return !is_null( $transcodeState[ $transcodeKey ]['time_success'] );
+ }
+
+ /**
+ * Clear the transcode state cache:
+ * @param String $fileName Optional fileName to clear transcode cache for
+ */
+ public static function clearTranscodeCache( $fileName = null){
+ if( $fileName ){
+ unset( self::$transcodeState[ $fileName ] );
+ } else {
+ self::$transcodeState = array();
+ }
+ }
+
+ /**
+ * Populates the transcode table with the current DB state of transcodes
+ * if transcodes are not found in the database their state is set to "false"
+ *
+ * @param {Object} File object
+ */
+ public static function getTranscodeState( $file, $db = false ){
+ global $wgTranscodeBackgroundTimeLimit;
+ $fileName = $file->getName();
+ if( ! isset( self::$transcodeState[$fileName] ) ){
+ if ( $db === false ) {
+ $db = $file->repo->getSlaveDB();
+ }
+ // initialize the transcode state array
+ self::$transcodeState[ $fileName ] = array();
+ $res = $db->select( 'transcode',
+ '*',
+ array( 'transcode_image_name' => $fileName ),
+ __METHOD__,
+ array( 'LIMIT' => 100 )
+ );
+ $overTimeout = array();
+ $over = $db->timestamp(time() - (2 * $wgTranscodeBackgroundTimeLimit));
+ // Populate the per transcode state cache
+ foreach ( $res as $row ) {
+ // strip the out the "transcode_" from keys
+ $trascodeState = array();
+ foreach( $row as $k => $v ){
+ $trascodeState[ str_replace( 'transcode_', '', $k ) ] = $v;
+ }
+ self::$transcodeState[ $fileName ][ $row->transcode_key ] = $trascodeState;
+ if ( $row->transcode_time_startwork != NULL
+ && $row->transcode_time_startwork < $over
+ && $row->transcode_time_success == NULL
+ && $row->transcode_time_error == NULL ) {
+ $overTimeout[] = $row->transcode_key;
+ }
+ }
+ if ( $overTimeout ) {
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->update(
+ 'transcode',
+ array(
+ 'transcode_time_error' => $dbw->timestamp(),
+ 'transcode_error' => 'timeout'
+ ),
+ array(
+ 'transcode_image_name' => $fileName,
+ 'transcode_key' => $overTimeout
+ ),
+ __METHOD__,
+ array( 'LIMIT' => count( $overTimeout ) )
+ );
+ }
+ }
+ $sorted = self::$transcodeState[ $fileName ];
+ uksort( $sorted, 'strnatcmp' );
+ return $sorted;
+ }
+
+ /**
+ * Remove any transcode files and db states associated with a given $file
+ * Note that if you want to see them again, you must re-queue them by calling
+ * startJobQueue() or updateJobQueue().
+ *
+ * also remove the transcode files:
+ * @param $file File Object
+ * @param $transcodeKey String Optional transcode key to remove only this key
+ */
+ public static function removeTranscodes( &$file, $transcodeKey = false ){
+
+ // if transcode key is non-false, non-null:
+ if( $transcodeKey ){
+ // only remove the requested $transcodeKey
+ $removeKeys = array( $transcodeKey );
+ } else {
+ // Remove any existing files ( regardless of their state )
+ $res = $file->repo->getMasterDB()->select( 'transcode',
+ array( 'transcode_key' ),
+ array( 'transcode_image_name' => $file->getName() )
+ );
+ $removeKeys = array();
+ foreach( $res as $transcodeRow ){
+ $removeKeys[] = $transcodeRow->transcode_key;
+ }
+ }
+
+ // Remove files by key:
+ $urlsToPurge = array();
+ foreach ( $removeKeys as $tKey ) {
+ $urlsToPurge[] = self::getTranscodedUrlForFile( $file, $tKey );
+ $filePath = self::getDerivativeFilePath( $file, $tKey );
+ if( $file->repo->fileExists( $filePath ) ){
+ wfSuppressWarnings();
+ $res = $file->repo->quickPurge( $filePath );
+ wfRestoreWarnings();
+ if( !$res ){
+ wfDebug( "Could not delete file $filePath\n" );
+ }
+ }
+ }
+
+ SquidUpdate::purge( $urlsToPurge );
+
+ // Build the sql query:
+ $dbw = wfGetDB( DB_MASTER );
+ $deleteWhere = array( 'transcode_image_name' => $file->getName() );
+ // Check if we are removing a specific transcode key
+ if( $transcodeKey !== false ){
+ $deleteWhere['transcode_key'] = $transcodeKey;
+ }
+ // Remove the db entries
+ $dbw->delete( 'transcode', $deleteWhere, __METHOD__ );
+
+ // Purge the cache for pages that include this video:
+ $titleObj = $file->getTitle();
+ self::invalidatePagesWithFile( $titleObj );
+
+ // Remove from local WebVideoTranscode cache:
+ self::clearTranscodeCache( $titleObj->getDBkey() );
+ }
+
+ /**
+ * @param $titleObj Title
+ */
+ public static function invalidatePagesWithFile( &$titleObj ){
+ wfDebug("WebVideoTranscode:: Invalidate pages that include: " . $titleObj->getDBkey() . "\n" );
+ // Purge the main image page:
+ $titleObj->invalidateCache();
+
+ // TODO if the video is used in over 500 pages add to 'job queue'
+ // TODO interwiki invalidation ?
+ $limit = 500;
+ $dbr = wfGetDB( DB_SLAVE );
+ $res = $dbr->select(
+ array( 'imagelinks', 'page' ),
+ array( 'page_namespace', 'page_title' ),
+ array( 'il_to' => $titleObj->getDBkey(), 'il_from = page_id' ),
+ __METHOD__,
+ array( 'LIMIT' => $limit + 1 )
+ );
+ foreach ( $res as $page ) {
+ $title = Title::makeTitle( $page->page_namespace, $page->page_title );
+ $title->invalidateCache();
+ }
+ }
+
+ /**
+ * Add a source to the sources list if the transcode job is ready
+ *
+ * If the source is not found, it will not be used yet...
+ * Missing transcodes should be added by write tasks, not read tasks!
+ */
+ public static function addSourceIfReady( &$file, &$sources, $transcodeKey, $dataPrefix = '' ){
+ // Check if the transcode is ready:
+ if( self::isTranscodeReady( $file, $transcodeKey ) ){
+ $sources[] = self::getDerivativeSourceAttributes( $file, $transcodeKey, $dataPrefix );
+ }
+ }
+
+ /**
+ * Get the primary "source" asset used for other derivatives
+ * @param $file File
+ * @param $options array
+ * @return array
+ */
+ static public function getPrimarySourceAttributes( $file, $options = array() ){
+ global $wgLang;
+ $src = in_array( 'fullurl', $options)? wfExpandUrl( $file->getUrl() ) : $file->getUrl();
+
+ $bitrate = $file->getHandler()->getBitrate( $file );
+ $metadataType = $file->getHandler()->getMetadataType( $file );
+
+ // Give grep a chance to find the usages: timedmedia-ogg, timedmedia-webm,
+ // timedmedia-mp4, timedmedia-flac, timedmedia-wav
+ if( $file->getHandler()->isAudio( $file ) ){
+ $title = wfMessage( 'timedmedia-source-audio-file-desc',
+ wfMessage( 'timedmedia-' . $metadataType )->text() )
+ ->params( $wgLang->formatBitrate( $bitrate ) )->text();
+ } else {
+ $title = wfMessage( 'timedmedia-source-file-desc',
+ wfMessage( 'timedmedia-' . $metadataType )->text() )
+ ->numParams( $file->getWidth(), $file->getHeight() )
+ ->params( $wgLang->formatBitrate( $bitrate ) )->text();
+ }
+
+ // Give grep a chance to find the usages: timedmedia-ogg, timedmedia-webm,
+ // timedmedia-mp4, timedmedia-flac, timedmedia-wav
+ $source = array(
+ 'src' => $src,
+ 'type' => $file->getHandler()->getWebType( $file ),
+ 'title' => $title,
+ "shorttitle" => wfMessage(
+ 'timedmedia-source-file',
+ wfMessage( 'timedmedia-' . $metadataType )->text()
+ )->text(),
+ "width" => intval( $file->getWidth() ),
+ "height" => intval( $file->getHeight() ),
+ );
+
+ if( $bitrate ){
+ $source["bandwidth"] = round ( $bitrate );
+ }
+
+ // For video include framerate:
+ if( !$file->getHandler()->isAudio( $file ) ){
+ $framerate = $file->getHandler()->getFramerate( $file );
+ if( $framerate ){
+ $source[ "framerate" ] = floatval( $framerate );
+ }
+ }
+ return $source;
+ }
+
+ /**
+ * Get derivative "source" attributes
+ * @param $file File
+ * @param $transcodeKey string
+ * @param $options array
+ * @return array
+ */
+ static public function getDerivativeSourceAttributes($file, $transcodeKey, $options = array() ){
+ $fileName = $file->getTitle()->getDbKey();
+
+ $src = self::getTranscodedUrlForFile( $file, $transcodeKey );
+
+ if( $file->getHandler()->isAudio( $file ) ){
+ $width = $height = 0;
+ } else {
+ list( $width, $height ) = WebVideoTranscode::getMaxSizeTransform(
+ $file,
+ self::$derivativeSettings[$transcodeKey]['maxSize']
+ );
+ }
+
+ $framerate = ( isset( self::$derivativeSettings[$transcodeKey]['framerate'] ) )?
+ self::$derivativeSettings[$transcodeKey]['framerate'] :
+ $file->getHandler()->getFramerate( $file );
+ // Setup the url src:
+ $src = in_array( 'fullurl', $options) ? wfExpandUrl( $src ) : $src;
+ $fields = array(
+ 'src' => $src,
+ 'title' => wfMessage( 'timedmedia-derivative-desc-' . $transcodeKey )->text(),
+ 'type' => self::$derivativeSettings[ $transcodeKey ][ 'type' ],
+ "shorttitle" => wfMessage( 'timedmedia-derivative-' . $transcodeKey )->text(),
+ "transcodekey" => $transcodeKey,
+
+ // Add data attributes per emerging DASH / webTV adaptive streaming attributes
+ // eventually we will define a manifest xml entry point.
+ "width" => intval( $width ),
+ "height" => intval( $height ),
+ );
+
+ // a "ready" transcode should have a bitrate:
+ if ( isset( self::$transcodeState[$fileName] ) ) {
+ $fields["bandwidth"] = intval(
+ self::$transcodeState[$fileName][ $transcodeKey ]['final_bitrate']
+ );
+ }
+
+ if ( !$file->getHandler()->isAudio( $file ) ) {
+ $fields += array( "framerate" => floatval( $framerate ) );
+ }
+ return $fields;
+ }
+
+ /**
+ * Queue up all enabled transcodes if missing.
+ * @param $file File object
+ */
+ public static function startJobQueue( File $file ) {
+ global $wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet;
+ $keys = array_merge( $wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet );
+
+ // 'Natural sort' puts the transcodes in ascending order by resolution,
+ // which roughly gives us fastest-to-slowest order.
+ natsort($keys);
+
+ foreach ( $keys as $tKey ) {
+ // Note the job queue will de-duplicate and handle various errors, so we
+ // can just blast out the full list here.
+ self::updateJobQueue( $file, $tKey );
+ }
+ }
+
+ /**
+ * Make sure all relevant transcodes for the given file are tracked in the
+ * transcodes table; add entries for any missing ones.
+ *
+ * @param $file File object
+ */
+ public static function cleanupTranscodes( File $file ) {
+ global $wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet;
+
+ $fileName = $file->getTitle()->getDbKey();
+ $db = $file->repo->getMasterDB();
+
+ $transcodeState = self::getTranscodeState( $file, $db );
+
+ $keys = array_merge( $wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet );
+ foreach ( $keys as $transcodeKey ) {
+ if ( !self::isTranscodeEnabled( $file, $transcodeKey ) ) {
+ // This transcode is no longer enabled or erroneously included...
+ // Leave it in place, allowing it to be removed manually;
+ // it won't be used in playback and should be doing no harm.
+ continue;
+ }
+ if ( !isset( $transcodeState[ $transcodeKey ] ) ) {
+ $db->insert(
+ 'transcode',
+ array(
+ 'transcode_image_name' => $fileName,
+ 'transcode_key' => $transcodeKey,
+ 'transcode_time_addjob' => null,
+ 'transcode_error' => "",
+ 'transcode_final_bitrate' => 0
+ ),
+ __METHOD__,
+ array( 'IGNORE' )
+ );
+ }
+ }
+ }
+
+ /**
+ * Check if the given transcode key is appropriate for the file.
+ *
+ * @param $file File object
+ * @param $transcodeKey String transcode key
+ * @return boolean
+ */
+ public static function isTranscodeEnabled( File $file, $transcodeKey ) {
+ global $wgEnabledTranscodeSet, $wgEnabledAudioTranscodeSet;
+
+ $audio = $file->getHandler()->isAudio( $file );
+ if ( $audio ) {
+ $keys = $wgEnabledAudioTranscodeSet;
+ } else {
+ $keys = $wgEnabledTranscodeSet;
+ }
+
+ if ( in_array( $transcodeKey, $keys ) ) {
+ $settings = self::$derivativeSettings[$transcodeKey];
+ if ( $audio ) {
+ $sourceCodecs = $file->getHandler()->getStreamTypes( $file );
+ $sourceCodec = $sourceCodecs ? strtolower( $sourceCodecs[0] ) : '';
+ return ( $sourceCodec !== $settings['audioCodec'] );
+ } else if ( self::isTargetLargerThanFile( $file, $settings['maxSize'] ) ) {
+ // Are we the smallest enabled transcode for this type?
+ // Then go ahead and make a wee little transcode for compat.
+ return self::isSmallestTranscodeForCodec( $transcodeKey );
+ } else {
+ return true;
+ }
+ } else {
+ // Transcode key is invalid or has been disabled.
+ return false;
+ }
+ }
+
+ /**
+ * Update the job queue if the file is not already in the job queue:
+ * @param $file File object
+ * @param $transcodeKey String transcode key
+ */
+ public static function updateJobQueue( &$file, $transcodeKey ){
+ $fileName = $file->getTitle()->getDbKey();
+ $db = $file->repo->getMasterDB();
+
+ $transcodeState = self::getTranscodeState( $file, $db );
+
+ if ( !self::isTranscodeEnabled( $file, $transcodeKey ) ) {
+ return;
+ }
+
+ // If the job hasn't been added yet, attempt to do so
+ if ( !isset( $transcodeState[ $transcodeKey ] ) ) {
+ $db->insert(
+ 'transcode',
+ array(
+ 'transcode_image_name' => $fileName,
+ 'transcode_key' => $transcodeKey,
+ 'transcode_time_addjob' => $db->timestamp(),
+ 'transcode_error' => "",
+ 'transcode_final_bitrate' => 0
+ ),
+ __METHOD__,
+ array( 'IGNORE' )
+ );
+
+ if ( !$db->affectedRows() ) {
+ // There is already a row for that job added by another request, no need to continue
+ return;
+ }
+
+ $job = new WebVideoTranscodeJob( $file->getTitle(), array(
+ 'transcodeMode' => 'derivative',
+ 'transcodeKey' => $transcodeKey,
+ ) );
+
+ if ( $job->insert() ) {
+ // Clear the state cache ( now that we have updated the page )
+ self::clearTranscodeCache( $fileName );
+ } else {
+ // Adding job failed, update transcode row
+ $db->update(
+ 'transcode',
+ array(
+ 'transcode_time_error' => $db->timestamp(),
+ 'transcode_error' => "Failed to insert Job."
+ ),
+ array(
+ 'transcode_image_name' => $fileName,
+ 'transcode_key' => $transcodeKey,
+ ),
+ __METHOD__,
+ array( 'LIMIT' => 1 )
+ );
+ }
+ }
+ }
+
+ /**
+ * Transforms the size per a given "maxSize"
+ * if maxSize is > file, file size is used
+ * @param $file File
+ * @param $targetMaxSize int
+ * @return array
+ */
+ public static function getMaxSizeTransform( &$file, $targetMaxSize ){
+ $maxSize = self::getMaxSize( $targetMaxSize );
+ $sourceWidth = intval( $file->getWidth() );
+ $sourceHeight = intval( $file->getHeight() );
+ if ( $sourceHeight === 0 ) {
+ // Audio file
+ return array( 0, 0 );
+ }
+ $sourceAspect = $sourceWidth / $sourceHeight;
+ $targetWidth = $sourceWidth;
+ $targetHeight = $sourceHeight;
+ if ( $sourceAspect <= $maxSize['aspect'] ) {
+ if ( $sourceHeight > $maxSize['height'] ) {
+ $targetHeight = $maxSize['height'];
+ $targetWidth = intval( $targetHeight * $sourceAspect );
+ }
+ } else {
+ if ( $sourceWidth > $maxSize['width'] ) {
+ $targetWidth = $maxSize['width'];
+ $targetHeight = intval( $targetWidth / $sourceAspect );
+ //some players do not like uneven frame sizes
+ }
+ }
+ //some players do not like uneven frame sizes
+ $targetWidth += $targetWidth%2;
+ $targetHeight += $targetHeight%2;
+ return array( $targetWidth, $targetHeight );
+ }
+
+ /**
+ * Test if a given transcode target is larger than the source file
+ *
+ * @param $file File object
+ * @param $targetMaxSize string
+ * @return bool
+ */
+ public static function isTargetLargerThanFile( &$file, $targetMaxSize ){
+ $maxSize = self::getMaxSize( $targetMaxSize );
+ $sourceWidth = $file->getWidth();
+ $sourceHeight = $file->getHeight();
+ $sourceAspect = intval( $sourceWidth ) / intval( $sourceHeight );
+ if ( $sourceAspect <= $maxSize['aspect'] ) {
+ return ( $maxSize['height'] > $sourceHeight );
+ } else {
+ return ( $maxSize['width'] > $sourceWidth );
+ }
+ }
+
+ /**
+ * Is the given transcode key the smallest configured transcode for
+ * its video codec?
+ */
+ public static function isSmallestTranscodeForCodec( $transcodeKey ) {
+ global $wgEnabledTranscodeSet;
+
+ $settings = self::$derivativeSettings[$transcodeKey];
+ $vcodec = $settings['videoCodec'];
+ $maxSize = self::getMaxSize( $settings['maxSize'] );
+
+ foreach ( $wgEnabledTranscodeSet as $tKey ) {
+ $tsettings = self::$derivativeSettings[$tKey];
+ if ( $tsettings['videoCodec'] === $vcodec ) {
+ $tmaxSize = self::getMaxSize( $tsettings['maxSize'] );
+ if ( $tmaxSize['width'] < $maxSize['width'] ) {
+ return false;
+ }
+ if ( $tmaxSize['height'] < $maxSize['height'] ) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Return maxSize array for given maxSize setting
+ *
+ * @param $targetMaxSize string
+ * @return array
+ */
+ public static function getMaxSize( $targetMaxSize ){
+ $maxSize = array();
+ $targetMaxSize = explode( 'x', $targetMaxSize );
+ $maxSize['width'] = intval( $targetMaxSize[0] );
+ if ( count( $targetMaxSize ) == 1 ) {
+ $maxSize['height'] = intval( $targetMaxSize[0] );
+ } else {
+ $maxSize['height'] = intval( $targetMaxSize[1] );
+ }
+ // check for zero size ( audio )
+ if( $maxSize['width'] === 0 || $maxSize['height'] == 0 ){
+ return 0;
+ }
+ $maxSize['aspect'] = $maxSize['width'] / $maxSize['height'];
+ return $maxSize;
+ }
+}
diff --git a/extensions/TimedMediaHandler/WebVideoTranscode/WebVideoTranscodeJob.php b/extensions/TimedMediaHandler/WebVideoTranscode/WebVideoTranscodeJob.php
new file mode 100644
index 00000000..d437d9c7
--- /dev/null
+++ b/extensions/TimedMediaHandler/WebVideoTranscode/WebVideoTranscodeJob.php
@@ -0,0 +1,965 @@
+<?php
+/**
+ * Job for transcode jobs
+ *
+ * @file
+ * @ingroup JobQueue
+ */
+
+/**
+ * Job for web video transcode
+ *
+ * Support two modes
+ * 1) non-free media transcode ( delays the media file being inserted, adds note to talk page once ready)
+ * 2) derivatives for video ( makes new sources for the asset )
+ *
+ * @ingroup JobQueue
+ */
+
+class WebVideoTranscodeJob extends Job {
+ var $targetEncodeFile = null;
+ var $sourceFilePath = null;
+
+ /**
+ * @var File
+ */
+ var $file;
+
+ public function __construct( $title, $params, $id = 0 ) {
+ parent::__construct( 'webVideoTranscode', $title, $params, $id );
+ $this->removeDuplicates = true;
+ }
+
+ /**
+ * Local function to debug output ( jobs don't have access to the maintenance output class )
+ * @param $msg string
+ */
+ private function output( $msg ){
+ print $msg . "\n";
+ }
+
+ /**
+ * @return File
+ */
+ private function getFile() {
+ if( !$this->file ){
+ $this->file = wfLocalFile( $this->title );
+ }
+ return $this->file;
+ }
+
+ /**
+ * @return string
+ */
+ private function getTargetEncodePath(){
+ if( !$this->targetEncodeFile ){
+ $file = $this->getFile();
+ $transcodeKey = $this->params[ 'transcodeKey' ];
+ $this->targetEncodeFile = WebVideoTranscode::getTargetEncodeFile( $file, $transcodeKey );
+ $this->targetEncodeFile->bind( $this );
+ }
+ return $this->targetEncodeFile->getPath();
+ }
+ /**
+ * purge temporary encode target
+ */
+ private function purgeTargetEncodeFile () {
+ if ( $this->targetEncodeFile ) {
+ $this->targetEncodeFile->purge();
+ $this->targetEncodeFile = null;
+ }
+ }
+
+ /**
+ * @return string|bool
+ */
+ private function getSourceFilePath(){
+ if( !$this->sourceFilePath ){
+ $file = $this->getFile();
+ $this->source = $file->repo->getLocalReference( $file->getPath() );
+ if ( !$this->source ) {
+ $this->sourceFilePath = false;
+ } else {
+ $this->sourceFilePath = $this->source->getPath();
+ }
+ }
+ return $this->sourceFilePath;
+ }
+
+ /**
+ * Update the transcode table with failure time and error
+ * @param $transcodeKey string
+ * @param $error string
+ *
+ */
+ private function setTranscodeError( $transcodeKey, $error ){
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->update(
+ 'transcode',
+ array(
+ 'transcode_time_error' => $dbw->timestamp(),
+ 'transcode_error' => $error
+ ),
+ array(
+ 'transcode_image_name' => $this->getFile()->getName(),
+ 'transcode_key' => $transcodeKey
+ ),
+ __METHOD__
+ );
+ $this->setLastError( $error );
+ }
+
+ /**
+ * Run the transcode request
+ * @return boolean success
+ */
+ public function run() {
+ global $wgVersion, $wgFFmpeg2theoraLocation;
+ // get a local pointer to the file
+ $file = $this->getFile();
+
+ // Validate the file exists:
+ if( !$file ){
+ $this->output( $this->title . ': File not found ' );
+ return false;
+ }
+
+ // Validate the transcode key param:
+ $transcodeKey = $this->params['transcodeKey'];
+ // Build the destination target
+ if( ! isset( WebVideoTranscode::$derivativeSettings[ $transcodeKey ] )){
+ $error = "Transcode key $transcodeKey not found, skipping";
+ $this->output( $error );
+ $this->setLastError( $error );
+ return false;
+ }
+
+ // Validate the source exists:
+ if( !$this->getSourceFilePath() || !is_file( $this->getSourceFilePath() ) ){
+ $status = $this->title . ': Source not found ' . $this->getSourceFilePath();
+ $this->output( $status );
+ $this->setTranscodeError( $transcodeKey, $status );
+ return false;
+ }
+
+ $options = WebVideoTranscode::$derivativeSettings[ $transcodeKey ];
+
+ if ( isset( $options[ 'novideo' ] ) ) {
+ $this->output( "Encoding to audio codec: " . $options['audioCodec'] );
+ } else {
+ $this->output( "Encoding to codec: " . $options['videoCodec'] );
+ }
+
+ $dbw = wfGetDB( DB_MASTER );
+
+ // Check if we have "already started" the transcode ( possible error )
+ $dbStartTime = $dbw->selectField( 'transcode', 'transcode_time_startwork',
+ array(
+ 'transcode_image_name' => $this->getFile()->getName(),
+ 'transcode_key' => $transcodeKey
+ ),
+ __METHOD__
+ );
+ if( ! is_null( $dbStartTime ) ){
+ $error = 'Error, running transcode job, for job that has already started';
+ $this->output( $error );
+ return true;
+ }
+
+ // Update the transcode table letting it know we have "started work":
+ $jobStartTimeCache = $dbw->timestamp();
+ $dbw->update(
+ 'transcode',
+ array( 'transcode_time_startwork' => $jobStartTimeCache ),
+ array(
+ 'transcode_image_name' => $this->getFile()->getName(),
+ 'transcode_key' => $transcodeKey
+ ),
+ __METHOD__
+ );
+ // Avoid contention and "server has gone away" errors as
+ // the transcode will take a very long time in some cases
+ $dbw->commit( __METHOD__, 'flush' );
+
+ // Check the codec see which encode method to call;
+ if ( isset( $options[ 'novideo' ] ) ) {
+ $status = $this->ffmpegEncode( $options );
+ } elseif( $options['videoCodec'] == 'theora' && $wgFFmpeg2theoraLocation !== false ){
+ $status = $this->ffmpeg2TheoraEncode( $options );
+ } elseif( $options['videoCodec'] == 'vp8' || $options['videoCodec'] == 'vp9' || $options['videoCodec'] == 'h264' || ( $options['videoCodec'] == 'theora' && $wgFFmpeg2theoraLocation === false ) ){
+ // Check for twopass:
+ if( isset( $options['twopass'] ) ){
+ // ffmpeg requires manual two pass
+ $status = $this->ffmpegEncode( $options, 1 );
+ if( $status && !is_string($status) ){
+ $status = $this->ffmpegEncode( $options, 2 );
+ }
+ } else {
+ $status = $this->ffmpegEncode( $options );
+ }
+ } else {
+ wfDebug( 'Error unknown codec:' . $options['videoCodec'] );
+ $status = 'Error unknown target encode codec:' . $options['videoCodec'];
+ }
+
+ // Remove any log files all useful info should be in status and or we are done with 2 passs encoding
+ $this->removeFffmpgeLogFiles();
+
+ // Do a quick check to confirm the job was not restarted or removed while we were transcoding
+ // Confirm the in memory $jobStartTimeCache matches db start time
+ $dbStartTime = $dbw->selectField( 'transcode', 'transcode_time_startwork',
+ array(
+ 'transcode_image_name' => $this->getFile()->getName(),
+ 'transcode_key' => $transcodeKey
+ )
+ );
+
+ // Check for ( hopefully rare ) issue of or job restarted while transcode in progress
+ if( $dbw->timestamp( $jobStartTimeCache ) != $dbw->timestamp( $dbStartTime ) ){
+ $this->output('Possible Error, transcode task restarted, removed, or completed while transcode was in progress');
+ // if an error; just error out, we can't remove temp files or update states, because the new job may be doing stuff.
+ if( $status !== true ){
+ $this->setTranscodeError( $transcodeKey, $status );
+ return false;
+ }
+ // else just continue with db updates, and when the new job comes around it won't start because it will see
+ // that the job has already been started.
+ }
+
+ // If status is oky and target does not exist, reset status
+ if( $status === true && !is_file( $this->getTargetEncodePath() ) ) {
+ $status = 'Target does not exist: ' . $this->getTargetEncodePath();
+ }
+ // If status is ok and target is larger than 0 bytes
+ if( $status === true && filesize( $this->getTargetEncodePath() ) > 0 ){
+ $file = $this->getFile();
+ $storeOptions = null;
+ if ( version_compare( $wgVersion, '1.23c', '>' ) &&
+ strpos( $options['type'], '/ogg' ) !== false &&
+ $file->getLength()
+ ) {
+ // Ogg files need a duration header for firefox
+ $storeOptions['headers']['X-Content-Duration'] = floatval( $file->getLength() );
+ }
+
+ // Copy derivative from the FS into storage at $finalDerivativeFilePath
+ $result = $file->getRepo()->quickImport(
+ $this->getTargetEncodePath(), // temp file
+ WebVideoTranscode::getDerivativeFilePath( $file, $transcodeKey ), // storage
+ $storeOptions
+ );
+ if ( !$result->isOK() ) {
+ // no need to invalidate all pages with video. Because all pages remain valid ( no $transcodeKey derivative )
+ // just clear the file page ( so that the transcode table shows the error )
+ $this->title->invalidateCache();
+ $this->setTranscodeError( $transcodeKey, $result->getWikiText() );
+ $status = false;
+ } else {
+ $bitrate = round( intval( filesize( $this->getTargetEncodePath() ) / $file->getLength() ) * 8 );
+ //wfRestoreWarnings();
+ // Update the transcode table with success time:
+ $dbw->update(
+ 'transcode',
+ array(
+ 'transcode_error' => '',
+ 'transcode_time_success' => $dbw->timestamp(),
+ 'transcode_final_bitrate' => $bitrate
+ ),
+ array(
+ 'transcode_image_name' => $this->getFile()->getName(),
+ 'transcode_key' => $transcodeKey,
+ ),
+ __METHOD__
+ );
+ $dbw->commit( __METHOD__, 'flush' );
+ WebVideoTranscode::invalidatePagesWithFile( $this->title );
+ }
+ } else {
+ // Update the transcode table with failure time and error
+ $this->setTranscodeError( $transcodeKey, $status );
+ // no need to invalidate all pages with video. Because all pages remain valid ( no $transcodeKey derivative )
+ // just clear the file page ( so that the transcode table shows the error )
+ $this->title->invalidateCache();
+ }
+ //done with encoding target, clean up
+ $this->purgeTargetEncodeFile();
+
+ // Clear the webVideoTranscode cache ( so we don't keep out dated table cache around )
+ WebVideoTranscode::clearTranscodeCache( $this->title->getDBkey() );
+
+ $url = WebVideoTranscode::getTranscodedUrlForFile( $file, $transcodeKey );
+ SquidUpdate::purge( array( $url ) );
+
+ if ($status !== true) {
+ $this->setLastError( $status );
+ }
+ return $status === true;
+ }
+
+ function removeFffmpgeLogFiles(){
+ $path = $this->getTargetEncodePath();
+ $dir = dirname( $path );
+ if ( is_dir( $dir ) ) {
+ $dh = opendir( $dir );
+ if ( $dh ) {
+ while ( ($file = readdir($dh)) !== false ) {
+ $log_path = "$dir/$file";
+ $ext = strtolower( pathinfo( $log_path, PATHINFO_EXTENSION ) );
+ if( $ext == 'log' && substr( $log_path, 0 , strlen($path) ) == $path ){
+ wfSuppressWarnings();
+ unlink( $log_path );
+ wfRestoreWarnings();
+ }
+ }
+ closedir( $dh );
+ }
+ }
+ }
+
+ /**
+ * Utility helper for ffmpeg and ffmpeg2theora mapping
+ * @param $options array
+ * @param $pass int
+ * @return bool|string
+ */
+ function ffmpegEncode( $options, $pass=0 ){
+ global $wgFFmpegLocation, $wgTranscodeBackgroundMemoryLimit;
+
+ if( !is_file( $this->getSourceFilePath() ) ) {
+ return "source file is missing, " . $this->getSourceFilePath() . ". Encoding failed.";
+ }
+
+ // Set up the base command
+ $cmd = wfEscapeShellArg( $wgFFmpegLocation ) . ' -y -i ' . wfEscapeShellArg( $this->getSourceFilePath() );
+
+
+ if( isset( $options['vpre'] ) ){
+ $cmd.= ' -vpre ' . wfEscapeShellArg( $options['vpre'] );
+ }
+
+ if ( isset( $options['novideo'] ) ) {
+ $cmd.= " -vn ";
+ } elseif( $options['videoCodec'] == 'vp8' || $options['videoCodec'] == 'vp9' ){
+ $cmd.= $this->ffmpegAddWebmVideoOptions( $options, $pass );
+ } elseif( $options['videoCodec'] == 'h264'){
+ $cmd.= $this->ffmpegAddH264VideoOptions( $options, $pass );
+ } elseif( $options['videoCodec'] == 'theora'){
+ $cmd.= $this->ffmpegAddTheoraVideoOptions( $options, $pass );
+ }
+ // Add size options:
+ $cmd .= $this->ffmpegAddVideoSizeOptions( $options ) ;
+
+ // Check for start time
+ if( isset( $options['starttime'] ) ){
+ $cmd.= ' -ss ' . wfEscapeShellArg( $options['starttime'] );
+ } else {
+ $options['starttime'] = 0;
+ }
+ // Check for end time:
+ if( isset( $options['endtime'] ) ){
+ $cmd.= ' -t ' . intval( $options['endtime'] ) - intval($options['starttime'] ) ;
+ }
+
+ if ( $pass == 1 || isset( $options['noaudio'] ) ) {
+ $cmd.= ' -an';
+ } else {
+ $cmd.= $this->ffmpegAddAudioOptions( $options, $pass );
+ }
+
+ if ( $pass != 0 ) {
+ $cmd.=" -pass " .wfEscapeShellArg( $pass ) ;
+ $cmd.=" -passlogfile " . wfEscapeShellArg( $this->getTargetEncodePath() .'.log' );
+ }
+ // And the output target:
+ if ($pass == 1) {
+ $cmd.= ' /dev/null';
+ } else{
+ $cmd.= " " . $this->getTargetEncodePath();
+ }
+
+ $this->output( "Running cmd: \n\n" .$cmd . "\n" );
+
+ // Right before we output remove the old file
+ $retval = 0;
+ $shellOutput = $this->runShellExec( $cmd, $retval );
+
+ if( $retval != 0 ){
+ return $cmd .
+ "\n\nExitcode: $retval\nMemory: $wgTranscodeBackgroundMemoryLimit\n\n" .
+ $shellOutput;
+ }
+ return true;
+ }
+
+ /**
+ * Adds ffmpeg shell options for h264
+ *
+ * @param $options
+ * @param $pass
+ * @return string
+ */
+ function ffmpegAddH264VideoOptions( $options, $pass ){
+ global $wgFFmpegThreads;
+ // Set the codec:
+ $cmd= " -threads " . intval( $wgFFmpegThreads ) . " -vcodec libx264";
+ // Check for presets:
+ if( isset( $options['preset'] ) ){
+ // Add the two vpre types:
+ switch( $options['preset'] ){
+ case 'ipod320':
+ $cmd .= " -profile:v baseline -preset slow -coder 0 -bf 0 -weightb 1 -level 13 -maxrate 768k -bufsize 3M";
+ break;
+ case '720p':
+ case 'ipod640':
+ $cmd .= " -profile:v baseline -preset slow -coder 0 -bf 0 -refs 1 -weightb 1 -level 31 -maxrate 10M -bufsize 10M";
+ break;
+ default:
+ // in the default case just pass along the preset to ffmpeg
+ $cmd.= " -vpre " . wfEscapeShellArg( $options['preset'] );
+ break;
+ }
+ }
+ if( isset( $options['videoBitrate'] ) ){
+ $cmd.= " -b " . wfEscapeShellArg ( $options['videoBitrate'] );
+ }
+ // Output mp4
+ $cmd.=" -f mp4";
+ return $cmd;
+ }
+
+ function ffmpegAddVideoSizeOptions( $options ){
+ $cmd = '';
+ // Get a local pointer to the file object
+ $file = $this->getFile();
+
+ // Check for aspect ratio ( we don't do anything with this right now)
+ if ( isset( $options['aspect'] ) ) {
+ $aspectRatio = $options['aspect'];
+ } else {
+ $aspectRatio = $file->getWidth() . ':' . $file->getHeight();
+ }
+ if (isset( $options['maxSize'] )) {
+ // Get size transform ( if maxSize is > file, file size is used:
+
+ list( $width, $height ) = WebVideoTranscode::getMaxSizeTransform( $file, $options['maxSize'] );
+ $cmd.= ' -s ' . intval( $width ) . 'x' . intval( $height );
+ } elseif (
+ (isset( $options['width'] ) && $options['width'] > 0 )
+ &&
+ (isset( $options['height'] ) && $options['height'] > 0 )
+ ){
+ $cmd.= ' -s ' . intval( $options['width'] ) . 'x' . intval( $options['height'] );
+ }
+
+ // Handle crop:
+ $optionMap = array(
+ 'cropTop' => '-croptop',
+ 'cropBottom' => '-cropbottom',
+ 'cropLeft' => '-cropleft',
+ 'cropRight' => '-cropright'
+ );
+ foreach( $optionMap as $name => $cmdArg ){
+ if( isset($options[$name]) ){
+ $cmd.= " $cmdArg " . wfEscapeShellArg( $options[$name] );
+ }
+ }
+ return $cmd;
+ }
+ /**
+ * Adds ffmpeg shell options for webm
+ *
+ * @param $options
+ * @param $pass
+ * @return string
+ */
+ function ffmpegAddWebmVideoOptions( $options, $pass ){
+ global $wgFFmpegThreads;
+
+ // Get a local pointer to the file object
+ $file = $this->getFile();
+
+ $cmd =' -threads ' . intval( $wgFFmpegThreads );
+
+ // check for presets:
+ if( isset($options['preset']) ){
+ if ($options['preset'] == "360p") {
+ $cmd.= " -vpre libvpx-360p";
+ } elseif ( $options['preset'] == "720p" ) {
+ $cmd.= " -vpre libvpx-720p";
+ } elseif ( $options['preset'] == "1080p" ) {
+ $cmd.= " -vpre libvpx-1080p";
+ }
+ }
+
+ // Add the boiler plate vp8 ffmpeg command:
+ $cmd.=" -skip_threshold 0 -bufsize 6000k -rc_init_occupancy 4000";
+
+ // Check for video quality:
+ if ( isset( $options['videoQuality'] ) && $options['videoQuality'] >= 0 ) {
+ // Map 0-10 to 63-0, higher values worse quality
+ $quality = 63 - intval( intval( $options['videoQuality'] )/10 * 63 );
+ $cmd .= " -qmin " . wfEscapeShellArg( $quality );
+ $cmd .= " -qmax " . wfEscapeShellArg( $quality );
+ }
+
+ // Check for video bitrate:
+ if ( isset( $options['videoBitrate'] ) ) {
+ $cmd.= " -qmin 1 -qmax 51";
+ $cmd.= " -vb " . wfEscapeShellArg( $options['videoBitrate'] * 1000 );
+ }
+ // Set the codec:
+ if ( $options['videoCodec'] === 'vp9' ) {
+ $cmd.= " -vcodec libvpx-vp9";
+ if ( isset( $options['tileColumns'] ) ) {
+ $cmd.= ' -tile-columns ' . wfEscapeShellArg( $options['tileColumns'] );
+ }
+ } else {
+ $cmd.= " -vcodec libvpx";
+ }
+
+ // Check for keyframeInterval
+ if( isset( $options['keyframeInterval'] ) ){
+ $cmd.= ' -g ' . wfEscapeShellArg( $options['keyframeInterval'] );
+ $cmd.= ' -keyint_min ' . wfEscapeShellArg( $options['keyframeInterval'] );
+ }
+ if( isset( $options['deinterlace'] ) ){
+ $cmd.= ' -deinterlace';
+ }
+
+ // Output WebM
+ $cmd.=" -f webm";
+
+ return $cmd;
+ }
+
+ /**
+ * Adds ffmpeg/avconv shell options for ogg
+ *
+ * Used only when $wgFFmpeg2theoraLocation set to false.
+ * Warning: does not create Ogg skeleton metadata track.
+ *
+ * @param $options
+ * @param $pass
+ * @return string
+ */
+ function ffmpegAddTheoraVideoOptions( $options, $pass ){
+ global $wgFFmpegThreads;
+
+ // Get a local pointer to the file object
+ $file = $this->getFile();
+
+ $cmd =' -threads ' . intval( $wgFFmpegThreads );
+
+ // Check for video quality:
+ if ( isset( $options['videoQuality'] ) && $options['videoQuality'] >= 0 ) {
+ // Map 0-10 to 63-0, higher values worse quality
+ $quality = 63 - intval( intval( $options['videoQuality'] )/10 * 63 );
+ $cmd .= " -qmin " . wfEscapeShellArg( $quality );
+ $cmd .= " -qmax " . wfEscapeShellArg( $quality );
+ }
+
+ // Check for video bitrate:
+ if ( isset( $options['videoBitrate'] ) ) {
+ $cmd.= " -qmin 1 -qmax 51";
+ $cmd.= " -vb " . wfEscapeShellArg( $options['videoBitrate'] * 1000 );
+ }
+ // Set the codec:
+ $cmd.= " -vcodec theora";
+
+ // Check for keyframeInterval
+ if( isset( $options['keyframeInterval'] ) ){
+ $cmd.= ' -g ' . wfEscapeShellArg( $options['keyframeInterval'] );
+ $cmd.= ' -keyint_min ' . wfEscapeShellArg( $options['keyframeInterval'] );
+ }
+ if( isset( $options['deinterlace'] ) ){
+ $cmd.= ' -deinterlace';
+ }
+ if( isset( $options['framerate'] ) ) {
+ $cmd.= ' -r ' . wfEscapeShellArg( $options['framerate'] );
+ }
+
+ // Output Ogg
+ $cmd.=" -f ogg";
+
+ return $cmd;
+ }
+
+ /**
+ * @param $options array
+ * @param $pass
+ * @return string
+ */
+ function ffmpegAddAudioOptions( $options, $pass ){
+ $cmd ='';
+ if( isset( $options['audioQuality'] ) ){
+ $cmd.= " -aq " . wfEscapeShellArg( $options['audioQuality'] );
+ }
+ if( isset( $options['audioBitrate'] )){
+ $cmd.= ' -ab ' . intval( $options['audioBitrate'] ) * 1000;
+ }
+ if( isset( $options['samplerate'] ) ){
+ $cmd.= " -ar " . wfEscapeShellArg( $options['samplerate'] );
+ }
+ if( isset( $options['channels'] ) ){
+ $cmd.= " -ac " . wfEscapeShellArg( $options['channels'] );
+ }
+
+ if( isset( $options['audioCodec'] ) ){
+ $encoders = array(
+ 'vorbis' => 'libvorbis',
+ 'opus' => 'libopus',
+ 'mp3' => 'libmp3lame',
+ );
+ if ( isset( $encoders[ $options['audioCodec'] ] ) ) {
+ $codec = $encoders[ $options['audioCodec'] ];
+ } else {
+ $codec = $options['audioCodec'];
+ }
+ $cmd.= " -acodec " . wfEscapeShellArg( $codec );
+ if ( $codec === 'aac' ) {
+ // the aac encoder is currently "experimental" in libav 9? :P
+ $cmd .= ' -strict experimental';
+ }
+ } else {
+ // if no audio codec set use vorbis :
+ $cmd.= " -acodec libvorbis ";
+ }
+ return $cmd;
+ }
+
+ /**
+ * ffmpeg2Theora mapping is much simpler since it is the basis of the the firefogg API
+ * @param $options array
+ * @return bool|string
+ */
+ function ffmpeg2TheoraEncode( $options ){
+ global $wgFFmpeg2theoraLocation, $wgTranscodeBackgroundMemoryLimit;
+
+ if( !is_file( $this->getSourceFilePath() ) ) {
+ return "source file is missing, " . $this->getSourceFilePath() . ". Encoding failed.";
+ }
+
+ // Set up the base command
+ $cmd = wfEscapeShellArg( $wgFFmpeg2theoraLocation ) . ' ' . wfEscapeShellArg( $this->getSourceFilePath() );
+
+ $file = $this->getFile();
+
+ if( isset( $options['maxSize'] ) ){
+ list( $width, $height ) = WebVideoTranscode::getMaxSizeTransform( $file, $options['maxSize'] );
+ $options['width'] = $width;
+ $options['height'] = $height;
+ $options['aspect'] = $width . ':' . $height;
+ unset( $options['maxSize'] );
+ }
+
+ // Add in the encode settings
+ foreach( $options as $key => $val ){
+ if( isset( self::$foggMap[$key] ) ){
+ if( is_array( self::$foggMap[$key] ) ){
+ $cmd.= ' '. implode(' ', self::$foggMap[$key] );
+ } elseif ($val == 'true' || $val === true){
+ $cmd.= ' '. self::$foggMap[$key];
+ } elseif ($val == 'false' || $val === false){
+ //ignore "false" flags
+ } else {
+ //normal get/set value
+ $cmd.= ' '. self::$foggMap[$key] . ' ' . wfEscapeShellArg( $val );
+ }
+ }
+ }
+
+ // Add the output target:
+ $outputFile = $this->getTargetEncodePath();
+ $cmd.= ' -o ' . wfEscapeShellArg ( $outputFile );
+
+ $this->output( "Running cmd: \n\n" .$cmd . "\n" );
+
+ $retval = 0;
+ $shellOutput = $this->runShellExec( $cmd, $retval );
+
+ // ffmpeg2theora returns 0 status on some errors, so also check for file
+ if( $retval != 0 || !is_file( $outputFile ) || filesize( $outputFile ) === 0 ){
+ return $cmd .
+ "\n\nExitcode: $retval\nMemory: $wgTranscodeBackgroundMemoryLimit\n\n" .
+ $shellOutput;
+ }
+ return true;
+ }
+
+ /**
+ * Runs the shell exec command.
+ * if $wgEnableBackgroundTranscodeJobs is enabled will mannage a background transcode task
+ * else it just directly passes off to wfShellExec
+ *
+ * @param $cmd String Command to be run
+ * @param $retval String, refrence variable to return the exit code
+ * @return string
+ */
+ public function runShellExec( $cmd, &$retval ){
+ global $wgTranscodeBackgroundTimeLimit,
+ $wgTranscodeBackgroundMemoryLimit,
+ $wgTranscodeBackgroundSizeLimit,
+ $wgEnableNiceBackgroundTranscodeJobs;
+
+ // For profiling
+ $caller = wfGetCaller();
+
+ // Check if background tasks are enabled
+ if( $wgEnableNiceBackgroundTranscodeJobs === false ){
+ // Directly execute the shell command:
+ $limits = array(
+ "filesize" => $wgTranscodeBackgroundSizeLimit,
+ "memory" => $wgTranscodeBackgroundMemoryLimit,
+ "time" => $wgTranscodeBackgroundTimeLimit
+ );
+ return wfShellExec( $cmd . ' 2>&1', $retval , array(), $limits,
+ array( 'profileMethod' => $caller ) );
+ }
+
+ $encodingLog = $this->getTargetEncodePath() . '.stdout.log';
+ $retvalLog = $this->getTargetEncodePath() . '.retval.log';
+ // Check that we can actually write to these files
+ //( no point in running the encode if we can't write )
+ wfSuppressWarnings();
+ if( ! touch( $encodingLog) || ! touch( $retvalLog ) ){
+ wfRestoreWarnings();
+ $retval = 1;
+ return "Error could not write to target location";
+ }
+ wfRestoreWarnings();
+
+ // Fork out a process for running the transcode
+ $pid = pcntl_fork();
+ if ($pid == -1) {
+ $errorMsg = '$wgEnableNiceBackgroundTranscodeJobs enabled but failed pcntl_fork';
+ $retval = 1;
+ $this->output( $errorMsg);
+ return $errorMsg;
+ } elseif ( $pid == 0) {
+ // we are the child
+ $this->runChildCmd( $cmd, $retval, $encodingLog, $retvalLog, $caller );
+ // dont remove any temp files in the child process, this is done
+ // once the parent is finished
+ $this->targetEncodeFile->preserve();
+ if ( $this->source instanceof TempFSFile ) {
+ $this->source->preserve();
+ }
+ // exit with the same code as the transcode:
+ exit( $retval );
+ } else {
+ // we are the parent monitor and return status
+ return $this->monitorTranscode($pid, $retval, $encodingLog, $retvalLog);
+ }
+ }
+
+ /**
+ * @param $cmd
+ * @param $retval
+ * @param $encodingLog
+ * @param $retvalLog
+ * @param string $caller The calling method
+ */
+ public function runChildCmd( $cmd, &$retval, $encodingLog, $retvalLog, $caller ){
+ global $wgTranscodeBackgroundTimeLimit,
+ $wgTranscodeBackgroundMemoryLimit,
+ $wgTranscodeBackgroundSizeLimit;
+ // In theory we should use pcntl_exec but not sure how to get the stdout, ensure
+ // we don't max php memory with the same protections provided by wfShellExec.
+
+ // pcntl_exec requires a direct path to the exe and arguments as an array:
+ //$cmd = explode(' ', $cmd );
+ //$baseCmd = array_shift( $cmd );
+ //print "run:" . $baseCmd . " args: " . print_r( $cmd, true );
+ //$status = pcntl_exec($baseCmd , $cmd );
+
+ // Directly execute the shell command:
+ //global $wgTranscodeBackgroundPriority;
+ //$status = wfShellExec( 'nice -n ' . $wgTranscodeBackgroundPriority . ' '. $cmd . ' 2>&1', $retval );
+ $limits = array(
+ "filesize" => $wgTranscodeBackgroundSizeLimit,
+ "memory" => $wgTranscodeBackgroundMemoryLimit,
+ "time" => $wgTranscodeBackgroundTimeLimit
+ );
+ $status = wfShellExec( $cmd . ' 2>&1', $retval , array(), $limits,
+ array( 'profileMethod' => $caller ) );
+
+ // Output the status:
+ wfSuppressWarnings();
+ file_put_contents( $encodingLog, $status );
+ // Output the retVal to the $retvalLog
+ file_put_contents( $retvalLog, $retval );
+ wfRestoreWarnings();
+ }
+
+ /**
+ * @param $pid
+ * @param $retval
+ * @param $encodingLog
+ * @param $retvalLog
+ * @return string
+ */
+ public function monitorTranscode( $pid, &$retval, $encodingLog, $retvalLog ){
+ global $wgTranscodeBackgroundTimeLimit, $wgLang;
+ $errorMsg = '';
+ $loopCount = 0;
+ $oldFileSize = 0;
+ $startTime = time();
+ $fileIsNotGrowing = false;
+
+ $this->output( "Encoding with pid: $pid \npcntl_waitpid: " . pcntl_waitpid( $pid, $status, WNOHANG OR WUNTRACED) .
+ "\nisProcessRunning: " . self::isProcessRunningKillZombie( $pid ) . "\n" );
+
+ // Check that the child process is still running ( note this does not work well with pcntl_waitpid
+ // for some reason :(
+ while( self::isProcessRunningKillZombie( $pid ) ) {
+ //$this->output( "$pid is running" );
+
+ // Check that the target file is growing ( every 5 seconds )
+ if( $loopCount == 10 ){
+ // only run check if we are outputing to target file
+ // ( two pass encoding does not output to target on first pass )
+ clearstatcache();
+ $newFileSize = is_file( $this->getTargetEncodePath() ) ? filesize( $this->getTargetEncodePath() ) : 0;
+ // Don't start checking for file growth until we have an initial positive file size:
+ if( $newFileSize > 0 ){
+ $this->output( $wgLang->formatSize( $newFileSize ). ' Total size, encoding ' .
+ $wgLang->formatSize( ( $newFileSize - $oldFileSize ) / 5 ) . ' per second' );
+ if( $newFileSize == $oldFileSize ){
+ if( $fileIsNotGrowing ){
+ $errorMsg = "Target File is not increasing in size, kill process.";
+ $this->output( $errorMsg );
+ // file is not growing in size, kill proccess
+ $retval = 1;
+
+ //posix_kill( $pid, 9);
+ self::killProcess( $pid );
+ break;
+ }
+ // Wait an additional 5 seconds of the file not growing to confirm
+ // the transcode is frozen.
+ $fileIsNotGrowing = true;
+ } else {
+ $fileIsNotGrowing = false;
+ }
+ $oldFileSize = $newFileSize;
+ }
+ // reset the loop counter
+ $loopCount = 0;
+ }
+
+ // Check if we have global job run-time has been exceeded:
+ if ( $wgTranscodeBackgroundTimeLimit && time() - $startTime > $wgTranscodeBackgroundTimeLimit ){
+ $errorMsg = "Encoding exceeded max job run time ( "
+ . TimedMediaHandler::seconds2npt( $wgTranscodeBackgroundTimeLimit ) . " ), kill process.";
+ $this->output( $errorMsg );
+ // File is not growing in size, kill proccess
+ $retval = 1;
+ //posix_kill( $pid, 9);
+ self::killProcess( $pid );
+ break;
+ }
+
+ // Sleep for one second before repeating loop
+ $loopCount++;
+ sleep( 1 );
+ }
+
+ $returnPcntl = pcntl_wexitstatus( $status );
+ // check status
+ wfSuppressWarnings();
+ $returnCodeFile = file_get_contents( $retvalLog );
+ wfRestoreWarnings();
+ //$this->output( "TranscodeJob:: Child pcntl return:". $returnPcntl . ' Log file exit code:' . $returnCodeFile . "\n" );
+
+ // File based exit code seems more reliable than pcntl_wexitstatus
+ $retval = $returnCodeFile;
+
+ // return the encoding log contents ( will be inserted into error table if an error )
+ // ( will be ignored and removed if success )
+ if( $errorMsg!= '' ){
+ $errorMsg.="\n\n";
+ }
+ return $errorMsg . file_get_contents( $encodingLog );
+ }
+
+ /**
+ * check if proccess is running and not a zombie
+ * @param $pid int
+ * @return bool
+ */
+ public static function isProcessRunningKillZombie( $pid ){
+ exec( "ps $pid", $processState );
+ if( !isset( $processState[1] ) ){
+ return false;
+ }
+ if( strpos( $processState[1], '<defunct>' ) !== false ){
+ // posix kill does not seem to work
+ //posix_kill( $pid, 9);
+ self::killProcess( $pid );
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Kill Application PID
+ *
+ * @param $pid int
+ * @return bool
+ */
+ public static function killProcess( $pid ){
+ exec( "kill -9 $pid" );
+ exec( "ps $pid", $processState );
+ if( isset( $processState[1] ) ){
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Mapping between firefogg api and ffmpeg2theora command line
+ *
+ * This lets us share a common api between firefogg and WebVideoTranscode
+ * also see: http://firefogg.org/dev/index.html
+ */
+ public static $foggMap = array(
+ // video
+ 'width' => "--width",
+ 'height' => "--height",
+ 'maxSize' => "--max_size",
+ 'noUpscaling' => "--no-upscaling",
+ 'videoQuality'=> "-v",
+ 'videoBitrate' => "-V",
+ 'twopass' => "--two-pass",
+ 'optimize' => "--optimize",
+ 'framerate' => "-F",
+ 'aspect' => "--aspect",
+ 'starttime' => "--starttime",
+ 'endtime' => "--endtime",
+ 'cropTop' => "--croptop",
+ 'cropBottom' => "--cropbottom",
+ 'cropLeft' => "--cropleft",
+ 'cropRight' => "--cropright",
+ 'keyframeInterval'=> "--keyint",
+ 'denoise' => array("--pp", "de"),
+ 'deinterlace' => "--deinterlace",
+ 'novideo' => array("--novideo", "--no-skeleton"),
+ 'bufDelay' => "--buf-delay",
+ // audio
+ 'audioQuality' => "-a",
+ 'audioBitrate' => "-A",
+ 'samplerate' => "-H",
+ 'channels' => "-c",
+ 'noaudio' => "--noaudio",
+ // metadata
+ 'artist' => "--artist",
+ 'title' => "--title",
+ 'date' => "--date",
+ 'location' => "--location",
+ 'organization' => "--organization",
+ 'copyright' => "--copyright",
+ 'license' => "--license",
+ 'contact' => "--contact"
+ );
+
+}
diff --git a/extensions/TimedMediaHandler/archives/transcode_name_key.sql b/extensions/TimedMediaHandler/archives/transcode_name_key.sql
new file mode 100644
index 00000000..85b00858
--- /dev/null
+++ b/extensions/TimedMediaHandler/archives/transcode_name_key.sql
@@ -0,0 +1,3 @@
+-- Add unique constrain on name/key
+DROP INDEX /*i*/transcode_name_inx ON /*_*/transcode;
+CREATE UNIQUE INDEX /*i*/transcode_name_key ON /*_*/transcode (transcode_image_name,transcode_key);
diff --git a/extensions/TimedMediaHandler/composer.json b/extensions/TimedMediaHandler/composer.json
new file mode 100644
index 00000000..3d55a97d
--- /dev/null
+++ b/extensions/TimedMediaHandler/composer.json
@@ -0,0 +1,10 @@
+{
+ "require-dev": {
+ "jakub-onderka/php-parallel-lint": "0.9.*"
+ },
+ "scripts": {
+ "test": [
+ "parallel-lint . --exclude vendor"
+ ]
+ }
+}
diff --git a/extensions/TimedMediaHandler/gitinfo.json b/extensions/TimedMediaHandler/gitinfo.json
new file mode 100644
index 00000000..d26a9734
--- /dev/null
+++ b/extensions/TimedMediaHandler/gitinfo.json
@@ -0,0 +1 @@
+{"headSHA1": "7cab54e2e482d51df69e4b9c880182b23cabf0bc\n", "head": "7cab54e2e482d51df69e4b9c880182b23cabf0bc\n", "remoteURL": "https://gerrit.wikimedia.org/r/mediawiki/extensions/TimedMediaHandler", "branch": "7cab54e2e482d51df69e4b9c880182b23cabf0bc\n", "headCommitDate": "1453929642"} \ No newline at end of file
diff --git a/extensions/TimedMediaHandler/handlers/FLACHandler/FLACHandler.php b/extensions/TimedMediaHandler/handlers/FLACHandler/FLACHandler.php
new file mode 100644
index 00000000..f08c9b90
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/FLACHandler/FLACHandler.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * FLAC handler
+ */
+class FLACHandler extends ID3Handler {
+
+ /**
+ * @param $file File
+ * @return string
+ */
+ function getMetadataType( $file ) {
+ return 'flac';
+ }
+
+ /**
+ * @param $file File
+ * @return String
+ */
+ function getWebType( $file ) {
+ return 'audio/flac';
+ }
+
+ /**
+ * @param $file File
+ * @return array|bool
+ */
+ function getStreamTypes( $file ) {
+ $streamTypes = array();
+ $metadata = $this->unpackMetadata( $file->getMetadata() );
+
+ if ( !$metadata || isset( $metadata['error'] ) ) {
+ return false;
+ }
+
+ if( isset( $metadata['audio'] ) && $metadata['audio']['dataformat'] == 'flac' ){
+ $streamTypes[] = 'FLAC';
+ }
+
+ return $streamTypes;
+ }
+
+ /**
+ * @param $file File
+ * @return String
+ */
+ function getShortDesc( $file ) {
+ global $wgLang;
+
+ $streamTypes = $this->getStreamTypes( $file );
+ if ( !$streamTypes ) {
+ return parent::getShortDesc( $file );
+ }
+ return wfMessage( 'timedmedia-flac-short-audio',
+ $wgLang->formatTimePeriod( $this->getLength( $file ) ) )->text();
+ }
+
+ /**
+ * @param $file File
+ * @return String
+ */
+ function getLongDesc( $file ) {
+ global $wgLang;
+ $streamTypes = $this->getStreamTypes( $file );
+ if ( !$streamTypes ) {
+ return parent::getLongDesc( $file );
+ }
+ return wfMessage('timedmedia-flac-long-audio',
+ $wgLang->formatTimePeriod( $this->getLength($file) ),
+ $wgLang->formatBitrate( $this->getBitRate( $file ) )
+ )->text();
+
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/handlers/ID3Handler/ID3Handler.php b/extensions/TimedMediaHandler/handlers/ID3Handler/ID3Handler.php
new file mode 100644
index 00000000..1e3ae4fb
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/ID3Handler/ID3Handler.php
@@ -0,0 +1,107 @@
+<?php
+/**
+ * getID3 Metadata handler
+ */
+class ID3Handler extends TimedMediaHandler {
+ // XXX match GETID3_VERSION ( too bad version is not a getter )
+ const METADATA_VERSION = 2;
+
+ /**
+ * @param $path string
+ * @return array
+ */
+ protected function getID3( $path ) {
+ // Create new id3 object:
+ $getID3 = new getID3();
+
+ // Don't grab stuff we don't use:
+ $getID3->option_tag_id3v1 = false; // Read and process ID3v1 tags
+ $getID3->option_tag_id3v2 = false; // Read and process ID3v2 tags
+ $getID3->option_tag_lyrics3 = false; // Read and process Lyrics3 tags
+ $getID3->option_tag_apetag = false; // Read and process APE tags
+ $getID3->option_tags_process = false; // Copy tags to root key 'tags' and encode to $this->encoding
+ $getID3->option_tags_html = false; // Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities
+
+ // Analyze file to get metadata structure:
+ $id3 = $getID3->analyze( $path );
+
+ // remove file paths
+ unset( $id3['filename'] );
+ unset( $id3['filepath'] );
+ unset( $id3['filenamepath']);
+
+ // Update the version
+ $id3['version'] = self::METADATA_VERSION;
+
+ return $id3;
+ }
+
+ /**
+ * @param $file File
+ * @param $path string
+ * @return string
+ */
+ function getMetadata( $file, $path ) {
+ $id3 = $this->getID3( $path );
+ return serialize( $id3 );
+ }
+
+ /**
+ * @param $metadata
+ * @return bool|mixed
+ */
+ function unpackMetadata( $metadata ) {
+ wfSuppressWarnings();
+ $unser = unserialize( $metadata );
+ wfRestoreWarnings();
+ if ( isset( $unser['version'] ) && $unser['version'] == self::METADATA_VERSION ) {
+ return $unser;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * @param $file File
+ * @return mixed
+ */
+ function getBitrate( $file ){
+ $metadata = $this->unpackMetadata( $file->getMetadata() );
+ if ( !$metadata || isset( $metadata['error'] ) || !isset( $metadata['bitrate'] ) ) {
+ return 0;
+ } else {
+ return $metadata['bitrate'];
+ }
+ }
+
+ /**
+ * @param $file File
+ * @return int
+ */
+ function getLength( $file ) {
+ $metadata = $this->unpackMetadata( $file->getMetadata() );
+ if ( !$metadata || isset( $metadata['error'] ) || !isset( $metadata['playtime_seconds'] ) ) {
+ return 0;
+ } else {
+ return $metadata['playtime_seconds'];
+ }
+ }
+
+ /**
+ * @param $file File
+ * @return bool|int
+ */
+ function getFramerate( $file ){
+ $metadata = $this->unpackMetadata( $file->getMetadata() );
+ if ( !$metadata || isset( $metadata['error'] ) ) {
+ return 0;
+ } else {
+ // return the frame rate of the first found video stream:
+ if( isset( $metadata['video'] )
+ && isset( $metadata['video']['frame_rate'] ) ) {
+ return $metadata['video']['frame_rate'];
+ }
+ return false;
+ }
+ }
+}
diff --git a/extensions/TimedMediaHandler/handlers/Mp4Handler/Mp4Handler.php b/extensions/TimedMediaHandler/handlers/Mp4Handler/Mp4Handler.php
new file mode 100644
index 00000000..897e1017
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/Mp4Handler/Mp4Handler.php
@@ -0,0 +1,139 @@
+<?php
+/**
+ * MP4 handler
+ */
+class Mp4Handler extends ID3Handler {
+
+ /**
+ * @param $path string
+ * @return array
+ */
+ protected function getID3( $path ) {
+ $id3 = parent::getID3( $path );
+ // Unset some parts of id3 that are too detailed and matroska specific:
+ unset( $id3['quicktime'] );
+ return $id3;
+ }
+
+ /**
+ * Get the "media size"
+ * @param $file File
+ * @param $path string
+ * @param $metadata bool
+ * @return array|bool
+ */
+ function getImageSize( $file, $path, $metadata = false ) {
+ // Just return the size of the first video stream
+ if ( $metadata === false ) {
+ $metadata = $file->getMetadata();
+ }
+ $metadata = $this->unpackMetadata( $metadata );
+ if ( isset( $metadata['error'] ) ) {
+ return false;
+ }
+ if( isset( $metadata['video']['resolution_x'])
+ &&
+ isset( $metadata['video']['resolution_y'])
+ ){
+ return array (
+ $metadata['video']['resolution_x'],
+ $metadata['video']['resolution_y']
+ );
+ }
+ return array( false, false );
+ }
+
+ /**
+ * @param $image
+ * @return string
+ */
+ function getMetadataType( $image ) {
+ return 'mp4';
+ }
+ /**
+ * @param $file File
+ */
+ function getWebType( $file ) {
+ /**
+ * h.264 profile types:
+ H.264 Simple baseline profile video (main and extended video compatible) level 3 and Low-Complexity AAC audio in MP4 container:
+ type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
+
+ H.264 Extended profile video (baseline-compatible) level 3 and Low-Complexity AAC audio in MP4 container:
+ type='video/mp4; codecs="avc1.58A01E, mp4a.40.2"'
+
+ H.264 Main profile video level 3 and Low-Complexity AAC audio in MP4 container
+ type='video/mp4; codecs="avc1.4D401E, mp4a.40.2"'
+
+ H.264 ā€˜Highā€™ profile video (incompatible with main, baseline, or extended profiles) level 3 and Low-Complexity AAC audio in MP4 container
+ type='video/mp4; codecs="avc1.64001E, mp4a.40.2"'
+ */
+ // all h.264 encodes are currently simple profile
+ return 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
+ }
+ /**
+ * @param $file File
+ * @return array|bool
+ */
+ function getStreamTypes( $file ) {
+ $streamTypes = array();
+ $metadata = self::unpackMetadata( $file->getMetadata() );
+ if ( !$metadata || isset( $metadata['error'] ) ) {
+ return false;
+ }
+ if( isset( $metadata['audio'] ) && $metadata['audio']['dataformat'] == 'mp4' ){
+ if( isset( $metadata['audio']['codec'] )
+ &&
+ strpos( $metadata['audio']['codec'] , 'AAC' ) !== false
+ ){
+ $streamTypes[] = 'AAC';
+ } else {
+ $streamTypes[] = $metadata['audio']['codec'];
+ }
+ }
+ // id3 gives 'V_VP8' for what we call VP8
+ if( $metadata['video']['dataformat'] == 'quicktime' ){
+ $streamTypes[] = 'h.264';
+ }
+
+ return $streamTypes;
+ }
+
+ /**
+ * @param $file File
+ * @return String
+ */
+ function getShortDesc( $file ) {
+ $streamTypes = $this->getStreamTypes( $file );
+ if ( !$streamTypes ) {
+ return parent::getShortDesc( $file );
+ }
+ return wfMessage( 'timedmedia-mp4-short-video', implode( '/', $streamTypes )
+ )->timeperiodParams(
+ $this->getLength( $file )
+ )->text();
+ }
+
+ /**
+ * @param $file File
+ * @return String
+ */
+ function getLongDesc( $file ) {
+ $streamTypes = $this->getStreamTypes( $file );
+ if ( !$streamTypes ) {
+ return parent::getLongDesc( $file );
+ }
+ return wfMessage('timedmedia-mp4-long-video',
+ implode( '/', $streamTypes )
+ )->timeperiodParams(
+ $this->getLength( $file )
+ )->bitrateParams(
+ $this->getBitRate( $file )
+ )->numParams(
+ $file->getWidth(),
+ $file->getHeight()
+ )->text();
+
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg.php b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg.php
new file mode 100644
index 00000000..ca281e22
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg.php
@@ -0,0 +1,631 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------------+
+// | File_Ogg PEAR Package for Accessing Ogg Bitstreams |
+// | Copyright (c) 2005-2007 |
+// | David Grant <david@grant.org.uk> |
+// | Tim Starling <tstarling@wikimedia.org> |
+// +----------------------------------------------------------------------------+
+// | This library is free software; you can redistribute it and/or |
+// | modify it under the terms of the GNU Lesser General Public |
+// | License as published by the Free Software Foundation; either |
+// | version 2.1 of the License, or (at your option) any later version. |
+// | |
+// | This library is distributed in the hope that it will be useful, |
+// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
+// | Lesser General Public License for more details. |
+// | |
+// | You should have received a copy of the GNU Lesser General Public |
+// | License along with this library; if not, write to the Free Software |
+// | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
+// +----------------------------------------------------------------------------+
+
+/**
+ * @author David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org>
+ * @category File
+ * @copyright David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org>
+ * @license http://www.gnu.org/copyleft/lesser.html GNU LGPL
+ * @link http://pear.php.net/package/File_Ogg
+ * @package File_Ogg
+ * @version CVS: $Id: Ogg.php,v 1.14 2005/11/19 09:06:30 djg Exp $
+ */
+
+/**
+ * @access public
+ */
+define("OGG_STREAM_VORBIS", 1);
+/**
+ * @access public
+ */
+define("OGG_STREAM_THEORA", 2);
+/**
+ * @access public
+ */
+define("OGG_STREAM_SPEEX", 3);
+/**
+ * @access public
+ */
+define("OGG_STREAM_FLAC", 4);
+/**
+ * @access public
+ */
+define("OGG_STREAM_OPUS", 5);
+
+/**
+ * Capture pattern to determine if a file is an Ogg physical stream.
+ *
+ * @access private
+ */
+define("OGG_CAPTURE_PATTERN", "OggS");
+/**
+ * Maximum size of an Ogg stream page plus four. This value is specified to allow
+ * efficient parsing of the physical stream. The extra four is a paranoid measure
+ * to make sure a capture pattern is not split into two parts accidentally.
+ *
+ * @access private
+ */
+define("OGG_MAXIMUM_PAGE_SIZE", 65311);
+/**
+ * Capture pattern for an Ogg Vorbis logical stream.
+ *
+ * @access private
+ */
+define("OGG_STREAM_CAPTURE_VORBIS", "vorbis");
+/**
+ * Capture pattern for an Ogg Speex logical stream.
+ * @access private
+ */
+define("OGG_STREAM_CAPTURE_SPEEX", "Speex ");
+/**
+ * Capture pattern for an Ogg FLAC logical stream.
+ *
+ * @access private
+ */
+define("OGG_STREAM_CAPTURE_FLAC", "FLAC");
+/**
+ * Capture pattern for an Ogg Theora logical stream.
+ *
+ * @access private
+ */
+define("OGG_STREAM_CAPTURE_THEORA", "theora");
+/**
+ * Capture pattern for an Ogg Opus logical stream.
+ * @access private
+ */
+define("OGG_STREAM_CAPTURE_OPUS", "OpusHead");
+/**
+ * Error thrown if the file location passed is nonexistant or unreadable.
+ *
+ * @access private
+ */
+define("OGG_ERROR_INVALID_FILE", 1);
+/**
+ * Error thrown if the user attempts to extract an unsupported logical stream.
+ *
+ * @access private
+ */
+define("OGG_ERROR_UNSUPPORTED", 2);
+/**
+ * Error thrown if the user attempts to extract an logical stream with no
+ * corresponding serial number.
+ *
+ * @access private
+ */
+define("OGG_ERROR_BAD_SERIAL", 3);
+/**
+ * Error thrown if the stream appears to be corrupted.
+ *
+ * @access private
+ */
+define("OGG_ERROR_UNDECODABLE", 4);
+
+
+/**
+ * Class for parsing a ogg bitstream.
+ *
+ * This class provides a means to access several types of logical bitstreams (e.g. Vorbis)
+ * within a Ogg physical bitstream.
+ *
+ * @link http://www.xiph.org/ogg/doc/
+ * @package File_Ogg
+ */
+class File_Ogg
+{
+ /**
+ * File pointer to Ogg container.
+ *
+ * This is the file pointer used for extracting data from the Ogg stream. It is
+ * the result of a standard fopen call.
+ *
+ * @var pointer
+ * @access private
+ */
+ var $_filePointer;
+
+ /**
+ * The container for all logical streams.
+ *
+ * List of all of the unique streams in the Ogg physical stream. The key
+ * used is the unique serial number assigned to the logical stream by the
+ * encoding application.
+ *
+ * @var array
+ * @access private
+ */
+ var $_streamList = array();
+ var $_streams = array();
+
+ /**
+ * Length in seconds of each stream group
+ */
+ var $_groupLengths = array();
+
+ /**
+ * Total length in seconds of the entire file
+ */
+ var $_totalLength;
+ var $_startOffset = false;
+
+ /**
+ * Maximum number of pages to store detailed metadata for, per stream.
+ * We can't store every page because there could be millions, causing an OOM.
+ * This must be big enough so that all the codecs can get the metadata they
+ * need without re-reading the file.
+ */
+ var $_maxPageCacheSize = 4;
+
+ /**
+ * Returns an interface to an Ogg physical stream.
+ *
+ * This method takes the path to a local file and examines it for a physical
+ * ogg bitsream. After instantiation, the user should query the object for
+ * the logical bitstreams held within the ogg container.
+ *
+ * @access public
+ * @param string $fileLocation The path of the file to be examined.
+ */
+ function __construct($fileLocation)
+ {
+ clearstatcache();
+ if (! file_exists($fileLocation)) {
+ throw new OggException("Couldn't Open File. Check File Path.", OGG_ERROR_INVALID_FILE);
+ }
+
+ // Open this file as a binary, and split the file into streams.
+ $this->_filePointer = fopen($fileLocation, "rb");
+ if (!is_resource($this->_filePointer))
+ throw new OggException("Couldn't Open File. Check File Permissions.", OGG_ERROR_INVALID_FILE);
+
+ // Check for a stream at the start
+ $magic = fread($this->_filePointer, strlen(OGG_CAPTURE_PATTERN));
+ if ($magic !== OGG_CAPTURE_PATTERN) {
+ throw new OggException("Couldn't read file: Incorrect magic number.", OGG_ERROR_UNDECODABLE);
+ }
+ fseek($this->_filePointer, 0, SEEK_SET);
+
+ $this->_splitStreams();
+ fclose($this->_filePointer);
+ }
+
+ /**
+ * Little-endian equivalent for bin2hex
+ * @static
+ */
+ static function _littleEndianBin2Hex( $bin ) {
+ $bigEndian = bin2hex( $bin );
+ // Reverse entire string
+ $reversed = strrev( $bigEndian );
+ // Swap nibbles back
+ for ( $i = 0; $i < strlen( $bigEndian ); $i += 2 ) {
+ $temp = $reversed[$i];
+ $reversed[$i] = $reversed[$i+1];
+ $reversed[$i+1] = $temp;
+ }
+ return $reversed;
+ }
+
+
+ /**
+ * Read a binary structure from a file. An array of unsigned integers are read.
+ * Large integers are upgraded to floating point on overflow.
+ *
+ * Format is big-endian as per Theora bit packing convention, this function
+ * won't work for Vorbis.
+ *
+ * @param resource $file
+ * @param array $fields Associative array mapping name to length in bits
+ */
+ static function _readBigEndian($file, $fields)
+ {
+ $bufferLength = ceil(array_sum($fields) / 8);
+ $buffer = fread($file, $bufferLength);
+ if (strlen($buffer) != $bufferLength) {
+ throw new OggException('Unexpected end of file', OGG_ERROR_UNDECODABLE);
+ }
+ $bytePos = 0;
+ $bitPos = 0;
+ $byteValue = ord($buffer[0]);
+ $output = array();
+ foreach ($fields as $name => $width) {
+ if ($width % 8 == 0 && $bitPos == 0) {
+ // Byte aligned case
+ $bytes = $width / 8;
+ $endBytePos = $bytePos + $bytes;
+ $value = 0;
+ while ($bytePos < $endBytePos) {
+ $value = ($value * 256) + ord($buffer[$bytePos]);
+ $bytePos++;
+ }
+ if ($bytePos < strlen($buffer)) {
+ $byteValue = ord($buffer[$bytePos]);
+ }
+ } else {
+ // General case
+ $bitsRemaining = $width;
+ $value = 0;
+ while ($bitsRemaining > 0) {
+ $bitsToRead = min($bitsRemaining, 8 - $bitPos);
+ $byteValue <<= $bitsToRead;
+ $overflow = ($byteValue & 0xff00) >> 8;
+ $byteValue &= $byteValue & 0xff;
+
+ $bitPos += $bitsToRead;
+ $bitsRemaining -= $bitsToRead;
+ $value += $overflow * pow(2, $bitsRemaining);
+
+ if ($bitPos >= 8) {
+ $bitPos = 0;
+ $bytePos++;
+ if ($bitsRemaining <= 0) {
+ break;
+ }
+ $byteValue = ord($buffer[$bytePos]);
+ }
+ }
+ }
+ $output[$name] = $value;
+ assert($bytePos <= $bufferLength);
+ }
+ return $output;
+ }
+
+ /**
+ * Read a binary structure from a file. An array of unsigned integers are read.
+ * Large integers are upgraded to floating point on overflow.
+ *
+ * Format is little-endian as per Vorbis bit packing convention.
+ *
+ * @param resource $file
+ * @param array $fields Associative array mapping name to length in bits
+ */
+ static function _readLittleEndian( $file, $fields ) {
+ $bufferLength = ceil(array_sum($fields) / 8);
+ $buffer = fread($file, $bufferLength);
+ if (strlen($buffer) != $bufferLength) {
+ throw new OggException('Unexpected end of file', OGG_ERROR_UNDECODABLE);
+ }
+
+ $bytePos = 0;
+ $bitPos = 0;
+ $byteValue = ord($buffer[0]) << 8;
+ $output = array();
+ foreach ($fields as $name => $width) {
+ if ($width % 8 == 0 && $bitPos == 0) {
+ // Byte aligned case
+ $bytes = $width / 8;
+ $value = 0;
+ for ($i = 0; $i < $bytes; $i++, $bytePos++) {
+ $value += pow(256, $i) * ord($buffer[$bytePos]);
+ }
+ if ($bytePos < strlen($buffer)) {
+ $byteValue = ord($buffer[$bytePos]) << 8;
+ }
+ } else {
+ // General case
+ $bitsRemaining = $width;
+ $value = 0;
+ while ($bitsRemaining > 0) {
+ $bitsToRead = min($bitsRemaining, 8 - $bitPos);
+ $byteValue >>= $bitsToRead;
+ $overflow = ($byteValue & 0xff) >> (8 - $bitsToRead);
+ $byteValue &= 0xff00;
+
+ $value += $overflow * pow(2, $width - $bitsRemaining);
+ $bitPos += $bitsToRead;
+ $bitsRemaining -= $bitsToRead;
+
+ if ($bitPos >= 8) {
+ $bitPos = 0;
+ $bytePos++;
+ if ($bitsRemaining <= 0) {
+ break;
+ }
+ $byteValue = ord($buffer[$bytePos]) << 8;
+ }
+ }
+ }
+ $output[$name] = $value;
+ assert($bytePos <= $bufferLength);
+ }
+ return $output;
+ }
+
+
+ /**
+ * @access private
+ */
+ function _decodePageHeader($pageData, $pageOffset, $groupId)
+ {
+ // Extract the various bits and pieces found in each packet header.
+ if (substr($pageData, 0, 4) != OGG_CAPTURE_PATTERN)
+ return (false);
+
+ $stream_version = unpack("C1data", substr($pageData, 4, 1));
+ if ($stream_version['data'] != 0x00)
+ return (false);
+
+ $header_flag = unpack("Cdata", substr($pageData, 5, 1));
+
+ // Exact granule position
+ $abs_granule_pos = self::_littleEndianBin2Hex( substr($pageData, 6, 8));
+
+ // Approximate (floating point) granule position
+ $pos = unpack("Va/Vb", substr($pageData, 6, 8));
+ $approx_granule_pos = $pos['a'] + $pos['b'] * pow(2, 32);
+
+ // Serial number for the current datastream.
+ $stream_serial = unpack("Vdata", substr($pageData, 14, 4));
+ $page_sequence = unpack("Vdata", substr($pageData, 18, 4));
+ $checksum = unpack("Vdata", substr($pageData, 22, 4));
+ $page_segments = unpack("Cdata", substr($pageData, 26, 1));
+ $segments_total = 0;
+ for ($i = 0; $i < $page_segments['data']; ++$i) {
+ $segment_length = unpack("Cdata", substr($pageData, 26 + ($i + 1), 1));
+ $segments_total += $segment_length['data'];
+ }
+ $pageFinish = $pageOffset + 27 + $page_segments['data'] + $segments_total;
+ $page = array(
+ 'stream_version' => $stream_version['data'],
+ 'header_flag' => $header_flag['data'],
+ 'abs_granule_pos' => $abs_granule_pos,
+ 'approx_granule_pos' => $approx_granule_pos,
+ 'checksum' => sprintf("%u", $checksum['data']),
+ 'segments' => $page_segments['data'],
+ 'head_offset' => $pageOffset,
+ 'body_offset' => $pageOffset + 27 + $page_segments['data'],
+ 'body_finish' => $pageFinish,
+ 'data_length' => $pageFinish - $pageOffset,
+ 'group' => $groupId,
+ );
+ if ( !isset( $this->_streamList[$stream_serial['data']] ) ) {
+ $this->_streamList[$stream_serial['data']] = array(
+ 'pages' => array(),
+ 'data_length' => 0,
+ 'first_granule_pos' => null,
+ 'last_granule_pos' => null,
+ );
+ }
+ $stream =& $this->_streamList[$stream_serial['data']];
+ if ( count( $stream['pages'] ) < $this->_maxPageCacheSize ) {
+ $stream['pages'][$page_sequence['data']] = $page;
+ }
+ $stream['last_page'] = $page;
+ $stream['data_length'] += $page['data_length'];
+
+ # Reject -1 as a granule pos, that means no segment finished in the packet
+ if ( $abs_granule_pos !== 'ffffffffffffffff' ) {
+ if ( $stream['first_granule_pos'] === null ) {
+ $stream['first_granule_pos'] = $abs_granule_pos;
+ }
+ $stream['last_granule_pos'] = $abs_granule_pos;
+ }
+
+ $pageData = null;
+ return $page;
+ }
+
+ /**
+ * @access private
+ */
+ function _splitStreams()
+ {
+ // Loop through the physical stream until there are no more pages to read.
+ $groupId = 0;
+ $openStreams = 0;
+ $this_page_offset = 0;
+ while (!feof($this->_filePointer)) {
+ $pageData = fread($this->_filePointer, 282);
+ if (strval($pageData) === '') {
+ break;
+ }
+ $page = $this->_decodePageHeader($pageData, $this_page_offset, $groupId);
+ if ($page === false) {
+ throw new OggException("Cannot decode Ogg file: Invalid page at offset $this_page_offset", OGG_ERROR_UNDECODABLE);
+ }
+
+ // Keep track of multiplexed groups
+ if ($page['header_flag'] & 2/*bos*/) {
+ $openStreams++;
+ } elseif ($page['header_flag'] & 4/*eos*/) {
+ $openStreams--;
+ if (!$openStreams) {
+ // End of group
+ $groupId++;
+ }
+ }
+ if ($openStreams < 0) {
+ throw new OggException("Unexpected end of stream", OGG_ERROR_UNDECODABLE);
+ }
+
+ $this_page_offset = $page['body_finish'];
+ fseek( $this->_filePointer, $this_page_offset, SEEK_SET );
+ }
+ // Loop through the streams, and find out what type of stream is available.
+ $groupLengths = array();
+ foreach ($this->_streamList as $stream_serial => $streamData) {
+ fseek($this->_filePointer, $streamData['pages'][0]['body_offset'], SEEK_SET);
+ $pattern = fread($this->_filePointer, 8);
+ if (preg_match("/" . OGG_STREAM_CAPTURE_VORBIS . "/", $pattern)) {
+ $this->_streamList[$stream_serial]['stream_type'] = OGG_STREAM_VORBIS;
+ $stream = new File_Ogg_Vorbis($stream_serial, $streamData, $this->_filePointer);
+ } elseif (preg_match("/" . OGG_STREAM_CAPTURE_SPEEX . "/", $pattern)) {
+ $this->_streamList[$stream_serial]['stream_type'] = OGG_STREAM_SPEEX;
+ $stream = new File_Ogg_Speex($stream_serial, $streamData, $this->_filePointer);
+ } elseif (preg_match("/" . OGG_STREAM_CAPTURE_FLAC . "/", $pattern)) {
+ $this->_streamList[$stream_serial]['stream_type'] = OGG_STREAM_FLAC;
+ $stream = new File_Ogg_Flac($stream_serial, $streamData, $this->_filePointer);
+ } elseif (preg_match("/" . OGG_STREAM_CAPTURE_THEORA . "/", $pattern)) {
+ $this->_streamList[$stream_serial]['stream_type'] = OGG_STREAM_THEORA;
+ $stream = new File_Ogg_Theora($stream_serial, $streamData, $this->_filePointer);
+ } elseif (preg_match("/" . OGG_STREAM_CAPTURE_OPUS . "/", $pattern)) {
+ $this->_streamList[$stream_serial]['stream_type'] = OGG_STREAM_OPUS;
+ $stream = new File_Ogg_Opus($stream_serial, $streamData, $this->_filePointer);
+ } else {
+ $streamData['stream_type'] = "unknown";
+ $stream = false;
+ }
+
+ if ($stream) {
+ $this->_streams[$stream_serial] = $stream;
+ $group = $streamData['pages'][0]['group'];
+ if (isset($groupLengths[$group])) {
+ $groupLengths[$group] = max($groupLengths[$group], $stream->getLength());
+ } else {
+ $groupLengths[$group] = $stream->getLength();
+ }
+ //just store the startOffset for the first stream:
+ if( $this->_startOffset === false ){
+ $this->_startOffset = $stream->getStartOffset();
+ }
+
+ }
+ }
+ $this->_groupLengths = $groupLengths;
+ $this->_totalLength = array_sum( $groupLengths );
+ unset($this->_streamList);
+ }
+
+ /**
+ * Returns the overead percentage used by the Ogg headers.
+ *
+ * This function returns the percentage of the total stream size
+ * used for Ogg headers.
+ *
+ * @return float
+ */
+ function getOverhead() {
+ $header_size = 0;
+ $stream_size = 0;
+ foreach ($this->_streams as $serial => $stream) {
+ foreach ($stream->_streamList as $offset => $stream_data) {
+ $header_size += $stream_data['body_offset'] - $stream_data['head_offset'];
+ $stream_size = $stream_data['body_finish'];
+ }
+ }
+ return sprintf("%0.2f", ($header_size / $stream_size) * 100);
+ }
+
+ /**
+ * Returns the appropriate logical bitstream that corresponds to the provided serial.
+ *
+ * This function returns a logical bitstream contained within the Ogg physical
+ * stream, corresponding to the serial used as the offset for that bitstream.
+ * The returned stream may be Vorbis, Speex, FLAC or Theora, although the only
+ * usable bitstream is Vorbis.
+ *
+ * @return File_Ogg_Bitstream
+ */
+ function &getStream($streamSerial)
+ {
+ if (! array_key_exists($streamSerial, $this->_streams))
+ throw new OggException("The stream number is invalid.", OGG_ERROR_BAD_SERIAL);
+
+ return $this->_streams[$streamSerial];
+ }
+
+ /**
+ * This function returns true if a logical bitstream of the requested type can be found.
+ *
+ * This function checks the contents of this ogg physical bitstream for of logical
+ * bitstream corresponding to the supplied type. If one is found, the function returns
+ * true, otherwise it return false.
+ *
+ * @param int $streamType
+ * @return boolean
+ */
+ function hasStream($streamType)
+ {
+ foreach ($this->_streams as $stream) {
+ if ($stream['stream_type'] == $streamType)
+ return (true);
+ }
+ return (false);
+ }
+
+ /**
+ * Returns an array of logical streams inside this physical bitstream.
+ *
+ * This function returns an array of logical streams found within this physical
+ * bitstream. If a filter is provided, only logical streams of the requested type
+ * are returned, as an array of serial numbers. If no filter is provided, this
+ * function returns a two-dimensional array, with the stream type as the primary key,
+ * and a value consisting of an array of stream serial numbers.
+ *
+ * @param int $filter
+ * @return array
+ */
+ function listStreams($filter = null)
+ {
+ $streams = array();
+ // Loops through the streams and assign them to an appropriate index,
+ // ready for filtering the second part of this function.
+ foreach ($this->_streams as $serial => $stream) {
+ $stream_type = 0;
+ switch (get_class($stream)) {
+ case "file_ogg_flac":
+ $stream_type = OGG_STREAM_FLAC;
+ break;
+ case "file_ogg_speex":
+ $stream_type = OGG_STREAM_SPEEX;
+ break;
+ case "file_ogg_theora":
+ $stream_type = OGG_STREAM_THEORA;
+ break;
+ case "file_ogg_vorbis":
+ $stream_type = OGG_STREAM_VORBIS;
+ break;
+ }
+ if (! isset($streams[$stream_type]))
+ // Initialise the result list for this stream type.
+ $streams[$stream_type] = array();
+
+ $streams[$stream_type][] = $serial;
+ }
+
+ // Perform filtering.
+ if (is_null($filter))
+ return ($streams);
+ elseif (isset($streams[$filter]))
+ return ($streams[$filter]);
+ else
+ return array();
+ }
+ /**
+ * getStartOffset
+ *
+ * @return unknown
+ */
+ function getStartOffset(){
+ if( $this->_startOffset === false)
+ return 0;
+ return $this->_startOffset;
+ }
+ /**
+ * Get the total length of the group of streams
+ */
+ function getLength() {
+ return $this->_totalLength;
+ }
+}
+?>
diff --git a/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Bitstream.php b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Bitstream.php
new file mode 100644
index 00000000..1a462232
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Bitstream.php
@@ -0,0 +1,125 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------------+
+// | File_Ogg PEAR Package for Accessing Ogg Bitstreams |
+// | Copyright (c) 2005-2007 |
+// | David Grant <david@grant.org.uk> |
+// | Tim Starling <tstarling@wikimedia.org> |
+// +----------------------------------------------------------------------------+
+// | This library is free software; you can redistribute it and/or |
+// | modify it under the terms of the GNU Lesser General Public |
+// | License as published by the Free Software Foundation; either |
+// | version 2.1 of the License, or (at your option) any later version. |
+// | |
+// | This library is distributed in the hope that it will be useful, |
+// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
+// | Lesser General Public License for more details. |
+// | |
+// | You should have received a copy of the GNU Lesser General Public |
+// | License along with this library; if not, write to the Free Software |
+// | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
+// +----------------------------------------------------------------------------+
+
+
+/**
+ * @author David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org>
+ * @category File
+ * @copyright David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org>
+ * @license http://www.gnu.org/copyleft/lesser.html GNU LGPL
+ * @link http://pear.php.net/package/File_Ogg
+ * @package File_Ogg
+ * @version CVS: $Id: Bitstream.php,v 1.3 2005/11/08 19:36:18 djg Exp $
+ */
+class File_Ogg_Bitstream
+{
+ /**
+ * The serial number of this logical stream.
+ *
+ * @var int
+ * @access private
+ */
+ var $_streamSerial;
+ /**
+ * @access private
+ */
+ var $_streamData;
+ /**
+ * @access private
+ */
+ var $_filePointer;
+ /**
+ * The number of bits used in this stream.
+ *
+ * @var int
+ * @access private
+ */
+ var $_streamSize;
+
+ /**
+ * The last granule position in the stream
+ * @var int
+ * @access private
+ */
+ var $_lastGranulePos;
+
+ /**
+ * Constructor for a generic logical stream.
+ *
+ * @param int $streamSerial Serial number of the logical stream.
+ * @param array $streamData Data for the requested logical stream.
+ * @param string $filePath Location of a file on the filesystem.
+ * @param pointer $filePointer File pointer for the current physical stream.
+ * @access private
+ */
+ function __construct($streamSerial, $streamData, $filePointer)
+ {
+ $this->_streamSerial = $streamSerial;
+ $this->_streamData = $streamData;
+ $this->_filePointer = $filePointer;
+ $this->_firstGranulePos = $streamData['first_granule_pos'];
+ $this->_lastGranulePos = $streamData['last_granule_pos'];
+ $this->_streamSize = $streamData['data_length'];
+ $this->_group = $streamData['pages'][0]['group'];
+ }
+
+ /**
+ * Gives the serial number of this stream.
+ *
+ * The stream serial number is of fairly academic importance, as it makes little
+ * difference to the end user. The serial number is used by the Ogg physical
+ * stream to distinguish between concurrent logical streams.
+ *
+ * @return int
+ * @access public
+ */
+ function getSerial()
+ {
+ return ($this->_streamSerial);
+ }
+
+ /**
+ * Gives the size (in bits) of this stream.
+ *
+ * This function returns the size of the Vorbis stream within the Ogg
+ * physical stream.
+ *
+ * @return int
+ * @access public
+ */
+ function getSize()
+ {
+ return ($this->_streamSize);
+ }
+
+ /**
+ * Get the multiplexed group ID
+ */
+ function getGroup()
+ {
+ return $this->_group;
+ }
+
+}
+
+?>
diff --git a/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Flac.php b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Flac.php
new file mode 100644
index 00000000..6838ba68
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Flac.php
@@ -0,0 +1,133 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------------+
+// | File_Ogg PEAR Package for Accessing Ogg Bitstreams |
+// | Copyright (c) 2005-2007 |
+// | David Grant <david@grant.org.uk> |
+// | Tim Starling <tstarling@wikimedia.org> |
+// +----------------------------------------------------------------------------+
+// | This library is free software; you can redistribute it and/or |
+// | modify it under the terms of the GNU Lesser General Public |
+// | License as published by the Free Software Foundation; either |
+// | version 2.1 of the License, or (at your option) any later version. |
+// | |
+// | This library is distributed in the hope that it will be useful, |
+// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
+// | Lesser General Public License for more details. |
+// | |
+// | You should have received a copy of the GNU Lesser General Public |
+// | License along with this library; if not, write to the Free Software |
+// | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
+// +----------------------------------------------------------------------------+
+
+
+/**
+ * @author David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org>
+ * @category File
+ * @copyright David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org>
+ * @license http://www.gnu.org/copyleft/lesser.html GNU LGPL
+ * @link http://pear.php.net/package/File_Ogg
+ * @link http://flac.sourceforge.net/documentation.html
+ * @package File_Ogg
+ * @version CVS: $Id: Flac.php,v 1.9 2005/11/16 20:43:27 djg Exp $
+ */
+class File_Ogg_Flac extends File_Ogg_Media
+{
+ /**
+ * @access private
+ */
+ function __construct($streamSerial, $streamData, $filePointer)
+ {
+ parent::__construct($streamSerial, $streamData, $filePointer);
+ $this->_decodeHeader();
+ $this->_decodeCommentsHeader();
+ $this->_streamLength = $this->_streamInfo['total_samples']
+ / $this->_streamInfo['sample_rate'];
+ }
+
+ /**
+ * Get a short string describing the type of the stream
+ * @return string
+ */
+ function getType() {
+ return 'FLAC';
+ }
+
+ /**
+ * @access private
+ * @param int $packetType
+ * @param int $pageOffset
+ */
+ function _decodeHeader()
+ {
+ fseek($this->_filePointer, $this->_streamData['pages'][0]['body_offset'], SEEK_SET);
+ // Check if this is the correct header.
+ $packet = unpack("Cdata", fread($this->_filePointer, 1));
+ if ($packet['data'] != 0x7f)
+ throw new OggException("Stream Undecodable", OGG_ERROR_UNDECODABLE);
+
+ // The following four characters should be "FLAC".
+ if (fread($this->_filePointer, 4) != 'FLAC')
+ throw new OggException("Stream is undecodable due to a malformed header.", OGG_ERROR_UNDECODABLE);
+
+ $version = unpack("Cmajor/Cminor", fread($this->_filePointer, 2));
+ $this->_version = "{$version['major']}.{$version['minor']}";
+ if ($version['major'] > 1) {
+ throw new OggException("Cannot decode a version {$version['major']} FLAC stream", OGG_ERROR_UNDECODABLE);
+ }
+ $h = File_Ogg::_readBigEndian( $this->_filePointer,
+ array(
+ // Ogg-specific
+ 'num_headers' => 16,
+ 'flac_native_sig' => 32,
+ // METADATA_BLOCK_HEADER
+ 'is_last' => 1,
+ 'type' => 7,
+ 'length' => 24,
+ ));
+
+ // METADATA_BLOCK_STREAMINFO
+ // The variable names are canonical, and come from the FLAC source (format.h)
+ $this->_streamInfo = File_Ogg::_readBigEndian( $this->_filePointer,
+ array(
+ 'min_blocksize' => 16,
+ 'max_blocksize' => 16,
+ 'min_framesize' => 24,
+ 'max_framesize' => 24,
+ 'sample_rate' => 20,
+ 'channels' => 3,
+ 'bits_per_sample' => 5,
+ 'total_samples' => 36,
+ ));
+ $this->_streamInfo['md5sum'] = bin2hex(fread($this->_filePointer, 16));
+ }
+
+ /**
+ * Get an associative array containing header information about the stream
+ * @access public
+ * @return array
+ */
+ function getHeader()
+ {
+ return $this->_streamInfo;
+ }
+
+ function _decodeCommentsHeader()
+ {
+ fseek($this->_filePointer, $this->_streamData['pages'][1]['body_offset'], SEEK_SET);
+ $blockHeader = File_Ogg::_readBigEndian( $this->_filePointer,
+ array(
+ 'last_block' => 1,
+ 'block_type' => 7,
+ 'length' => 24
+ )
+ );
+ if ($blockHeader['block_type'] != 4) {
+ throw new OggException("Stream Undecodable", OGG_ERROR_UNDECODABLE);
+ }
+
+ $this->_decodeBareCommentsHeader();
+ }
+}
+?>
diff --git a/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Media.php b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Media.php
new file mode 100644
index 00000000..67ddaece
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Media.php
@@ -0,0 +1,262 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------------+
+// | File_Ogg PEAR Package for Accessing Ogg Bitstreams |
+// | Copyright (c) 2005-2007 |
+// | David Grant <david@grant.org.uk> |
+// | Tim Starling <tstarling@wikimedia.org> |
+// +----------------------------------------------------------------------------+
+// | This library is free software; you can redistribute it and/or |
+// | modify it under the terms of the GNU Lesser General Public |
+// | License as published by the Free Software Foundation; either |
+// | version 2.1 of the License, or (at your option) any later version. |
+// | |
+// | This library is distributed in the hope that it will be useful, |
+// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
+// | Lesser General Public License for more details. |
+// | |
+// | You should have received a copy of the GNU Lesser General Public |
+// | License along with this library; if not, write to the Free Software |
+// | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
+// +----------------------------------------------------------------------------+
+
+
+/**
+ * Parent class for media bitstreams
+ * Contains some functions common to various media formats
+ */
+abstract class File_Ogg_Media extends File_Ogg_Bitstream
+{
+ /**
+ * Maximum size of header comment to parse.
+ * Set to 1 MB by default. Make sure this is less than your PHP memory_limit.
+ */
+ const COMMENT_MAX_SIZE = 1000000;
+
+ /**
+ * Array to hold each of the comments.
+ *
+ * @access private
+ * @var array
+ */
+ var $_comments = array();
+
+ /**
+ * Vendor string for the stream.
+ *
+ * @access private
+ * @var string
+ */
+ var $_vendor;
+
+ /**
+ * Length of the stream in seconds
+ */
+ var $_streamLength;
+
+ /* Start offset of the stream in seconds */
+ var $_startOffset = 0;
+
+ /**
+ * Get a short string describing the type of the stream
+ * @return string
+ */
+ abstract function getType();
+
+ /**
+ * Get the 6-byte identification string expected in the common header
+ * @return string
+ */
+ function getIdentificationString()
+ {
+ return '';
+ }
+
+ /**
+ * @access private
+ * @param int $packetType
+ * @param int $pageOffset
+ */
+ function _decodeCommonHeader($packetType, $pageOffset)
+ {
+ fseek($this->_filePointer, $this->_streamData['pages'][$pageOffset]['body_offset'], SEEK_SET);
+ if ($packetType !== false) {
+ // Check if this is the correct header.
+ $packet = unpack("Cdata", fread($this->_filePointer, 1));
+ if ($packet['data'] != $packetType)
+ throw new OggException("Stream Undecodable", OGG_ERROR_UNDECODABLE);
+
+ // The following six characters should be equal to getIdentificationString()
+ $id = $this->getIdentificationString();
+ if ($id !== '' && fread($this->_filePointer, strlen($id)) !== $id)
+ throw new OggException("Stream is undecodable due to a malformed header.", OGG_ERROR_UNDECODABLE);
+ } // else seek only, no common header
+ }
+
+ /**
+ * Parse a Vorbis-style comments header.
+ *
+ * This function parses the comments header. The comments header contains a series of
+ * UTF-8 comments related to the audio encoded in the stream. This header also contains
+ * a string to identify the encoding software. More details on the comments header can
+ * be found at the following location: http://xiph.org/vorbis/doc/v-comment.html
+ *
+ * @access private
+ */
+ function _decodeBareCommentsHeader()
+ {
+ // Decode the vendor string length as a 32-bit unsigned integer.
+ $vendor_len = unpack("Vdata", fread($this->_filePointer, 4));
+ if ( $vendor_len['data'] > 0 ) {
+ // Retrieve the vendor string from the stream.
+ $this->_vendor = fread($this->_filePointer, $vendor_len['data']);
+ } else {
+ $this->_vendor = '';
+ }
+ // Decode the size of the comments list as a 32-bit unsigned integer.
+ $comment_list_length = unpack("Vdata", fread($this->_filePointer, 4));
+ // Iterate through the comments list.
+ for ($i = 0; $i < $comment_list_length['data']; ++$i) {
+ // Unpack the length of this comment.
+ $comment_length = unpack("Vdata", fread($this->_filePointer, 4));
+
+ // If the comment length is greater than specified limit, skip it.
+ if ( $comment_length['data'] > self::COMMENT_MAX_SIZE ) {
+ continue;
+ }
+
+ // Comments are in the format 'ARTIST=Super Furry Animals', so split it on the equals character.
+ // NOTE: Equals characters are strictly prohibited in either the COMMENT or DATA parts.
+ $comment = explode("=", fread($this->_filePointer, $comment_length['data']));
+ $comment_title = (string) $comment[0];
+ $comment_value = (string) $comment[1];
+
+ // Check if the comment type (e.g. ARTIST) already exists. If it does,
+ // take the new value, and the existing value (or array) and insert it
+ // into a new array. This is important, since each comment type may have
+ // multiple instances (e.g. ARTIST for a collaboration) and we should not
+ // overwrite the previous value.
+ if (isset($this->_comments[$comment_title])) {
+ if (is_array($this->_comments[$comment_title]))
+ $this->_comments[$comment_title][] = $comment_value;
+ else
+ $this->_comments[$comment_title] = array($this->_comments[$comment_title], $comment_value);
+ } else
+ $this->_comments[$comment_title] = $comment_value;
+ }
+ }
+
+ /**
+ * Number of channels used in this stream
+ *
+ * This function returns the number of channels used in this stream. This
+ * can range from 1 to 255, but will likely be 2 (stereo) or 1 (mono).
+ *
+ * @access public
+ * @return int
+ * @see File_Ogg_Vorbis::isMono()
+ * @see File_Ogg_Vorbis::isStereo()
+ * @see File_Ogg_Vorbis::isQuadrophonic()
+ */
+ function getChannels()
+ {
+ return ($this->_channels);
+ }
+
+ /**
+ * Provides a list of the comments extracted from the Vorbis stream.
+ *
+ * It is recommended that the user fully inspect the array returned by this function
+ * rather than blindly requesting a comment in false belief that it will always
+ * be present. Whilst the Vorbis specification dictates a number of popular
+ * comments (e.g. TITLE, ARTIST, etc.) for use in Vorbis streams, they are not
+ * guaranteed to appear.
+ *
+ * @access public
+ * @return array
+ */
+ function getCommentList()
+ {
+ return (array_keys($this->_comments));
+ }
+
+ /**
+ * Provides an interface to the numerous comments located with a Vorbis stream.
+ *
+ * A Vorbis stream may contain one or more instances of each comment, so the user
+ * should check the variable type before printing out the result of this method.
+ * The situation in which multiple instances of a comment occurring are not as
+ * rare as one might think, since they are conceivable at least for ARTIST comments
+ * in the situation where a track is a duet.
+ *
+ * @access public
+ * @param string $commentTitle Comment title to search for, e.g. TITLE.
+ * @param string $separator String to separate multiple values.
+ * @return string
+ */
+ function getField($commentTitle, $separator = ", ")
+ {
+ if (isset($this->_comments[$commentTitle])) {
+ if (is_array($this->_comments[$commentTitle]))
+ return (implode($separator, $this->_comments[$commentTitle]));
+ else
+ return ($this->_comments[$commentTitle]);
+ } else
+ // The comment doesn't exist in this file. The user should've called getCommentList first.
+ return ("");
+ }
+
+ /**
+ * Get the entire comments array.
+ * May return an empty array if the bitstream does not support comments.
+ *
+ * @access public
+ * @return array
+ */
+ function getComments() {
+ return $this->_comments;
+ }
+
+ /**
+ * Vendor of software used to encode this stream.
+ *
+ * Gives the vendor string for the software used to encode this stream.
+ * It is common to find libVorbis here. The majority of encoders appear
+ * to use libvorbis from Xiph.org.
+ *
+ * @access public
+ * @return string
+ */
+ function getVendor()
+ {
+ return ($this->_vendor);
+ }
+
+ /**
+ * Get an associative array containing header information about the stream
+ * @access public
+ * @return array
+ */
+ function getHeader()
+ {
+ return array();
+ }
+
+ /**
+ * Get the length of the stream in seconds
+ * @return float
+ */
+ function getLength()
+ {
+ return $this->_streamLength;
+ }
+ /**
+ * Get the start offset of the stream in seconds
+ *
+ * @return float
+ */
+ function getStartOffset(){
+ return $this->_startOffset;
+ }
+}
diff --git a/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Opus.php b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Opus.php
new file mode 100644
index 00000000..2c23d928
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Opus.php
@@ -0,0 +1,126 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------------+
+// | File_Ogg PEAR Package for Accessing Ogg Bitstreams |
+// | Copyright (c) 2013 |
+// | Jan Gerber <jgerber@wikimedia.org> |
+// +----------------------------------------------------------------------------+
+// | This library is free software; you can redistribute it and/or |
+// | modify it under the terms of the GNU Lesser General Public |
+// | License as published by the Free Software Foundation; either |
+// | version 2.1 of the License, or (at your option) any later version. |
+// | |
+// | This library is distributed in the hope that it will be useful, |
+// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
+// | Lesser General Public License for more details. |
+// | |
+// | You should have received a copy of the GNU Lesser General Public |
+// | License along with this library; if not, write to the Free Software |
+// | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
+// +----------------------------------------------------------------------------+
+
+
+define( 'OGG_OPUS_COMMENTS_PAGE_OFFSET', 1 );
+
+/**
+ * @author Jan Gerber <jgerber@wikimedia.org>
+ * @category File
+ * @copyright Jan Gerber <jgerber@wikimedia.org>
+ * @license http://www.gnu.org/copyleft/lesser.html GNU LGPL
+ * @link http://pear.php.net/package/File_Ogg
+ * @link http://www.opus-codec.org/
+ * @package File_Ogg
+ * @version 1
+ */
+class File_Ogg_Opus extends File_Ogg_Media
+{
+ /**
+ * @access private
+ */
+ function __construct($streamSerial, $streamData, $filePointer)
+ {
+ parent::__construct($streamSerial, $streamData, $filePointer);
+ $this->_decodeHeader();
+ $this->_decodeCommentsHeader();
+
+ $endSec = $this->getSecondsFromGranulePos( $this->_lastGranulePos );
+ $startSec = $this->getSecondsFromGranulePos( $this->_firstGranulePos );
+
+ if( $startSec > 1){
+ $this->_streamLength = $endSec - $startSec;
+ $this->_startOffset = $startSec;
+ }else{
+ $this->_streamLength = $endSec;
+ }
+ $this->_avgBitrate = $this->_streamLength ? ($this->_streamSize * 8) / $this->_streamLength : 0;
+ }
+
+ function getSecondsFromGranulePos( $granulePos ){
+ return (( '0x' . substr( $granulePos, 0, 8 ) ) * pow(2, 32)
+ + ( '0x' . substr( $granulePos, 8, 8 ) )
+ - $this->_header['pre_skip'])
+ / 48000;
+ }
+
+ /**
+ * Get a short string describing the type of the stream
+ * @return string
+ */
+ function getType()
+ {
+ return 'Opus';
+ }
+
+ /**
+ * Decode the stream header
+ * @access private
+ */
+ function _decodeHeader()
+ {
+ fseek($this->_filePointer, $this->_streamData['pages'][0]['body_offset'], SEEK_SET);
+ // The first 8 characters should be "OpusHead".
+ if (fread($this->_filePointer, 8) != 'OpusHead')
+ throw new OggException("Stream is undecodable due to a malformed header.", OGG_ERROR_UNDECODABLE);
+
+ $this->_header = File_Ogg::_readLittleEndian($this->_filePointer, array(
+ 'opus_version' => 8,
+ 'nb_channels' => 8,
+ 'pre_skip' => 16,
+ 'audio_sample_rate' => 32,
+ 'output_gain' => 16,
+ 'channel_mapping_family'=> 8,
+ ));
+ $this->_channels = $this->_header['nb_channels'];
+ }
+
+ /**
+ * Get an associative array containing header information about the stream
+ * @access public
+ * @return array
+ */
+ function getHeader() {
+ return $this->_header;
+ }
+
+ function getSampleRate()
+ {
+ //Opus always outputs 48kHz, the header only lists
+ //the samplerate of the source as reference
+ return 48000;
+ }
+
+ /**
+ * Decode the comments header
+ * @access private
+ */
+ function _decodeCommentsHeader()
+ {
+ $id = 'OpusTags';
+ $this->_decodeCommonHeader(false, OGG_OPUS_COMMENTS_PAGE_OFFSET);
+ if(fread($this->_filePointer, strlen($id)) !== $id)
+ throw new OggException("Stream is undecodable due to a malformed header.", OGG_ERROR_UNDECODABLE);
+ $this->_decodeBareCommentsHeader();
+ }
+}
+?>
diff --git a/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Speex.php b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Speex.php
new file mode 100644
index 00000000..42f9b0eb
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Speex.php
@@ -0,0 +1,122 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------------+
+// | File_Ogg PEAR Package for Accessing Ogg Bitstreams |
+// | Copyright (c) 2005-2007 |
+// | David Grant <david@grant.org.uk> |
+// | Tim Starling <tstarling@wikimedia.org> |
+// +----------------------------------------------------------------------------+
+// | This library is free software; you can redistribute it and/or |
+// | modify it under the terms of the GNU Lesser General Public |
+// | License as published by the Free Software Foundation; either |
+// | version 2.1 of the License, or (at your option) any later version. |
+// | |
+// | This library is distributed in the hope that it will be useful, |
+// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
+// | Lesser General Public License for more details. |
+// | |
+// | You should have received a copy of the GNU Lesser General Public |
+// | License along with this library; if not, write to the Free Software |
+// | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
+// +----------------------------------------------------------------------------+
+
+
+/**
+ * @author David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org>
+ * @category File
+ * @copyright David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org>
+ * @license http://www.gnu.org/copyleft/lesser.html GNU LGPL
+ * @link http://pear.php.net/package/File_Ogg
+ * @link http://www.speex.org/docs.html
+ * @package File_Ogg
+ * @version CVS: $Id: Speex.php,v 1.10 2005/11/16 20:43:27 djg Exp $
+ */
+class File_Ogg_Speex extends File_Ogg_Media
+{
+ /**
+ * @access private
+ */
+ function __construct($streamSerial, $streamData, $filePointer)
+ {
+ parent::__construct($streamSerial, $streamData, $filePointer);
+ $this->_decodeHeader();
+ $this->_decodeCommentsHeader();
+ $endSec =
+ (( '0x' . substr( $this->_lastGranulePos, 0, 8 ) ) * pow(2, 32)
+ + ( '0x' . substr( $this->_lastGranulePos, 8, 8 ) ))
+ / $this->_header['rate'];
+
+ $startSec =
+ (( '0x' . substr( $this->_firstGranulePos, 0, 8 ) ) * pow(2, 32)
+ + ( '0x' . substr( $this->_firstGranulePos, 8, 8 ) ))
+ / $this->_header['rate'];
+
+ //make sure the offset is worth taking into account oggz_chop related hack
+ if( $startSec > 1){
+ $this->_streamLength = $endSec - $startSec;
+ $this->_startOffset = $startSec;
+ }else{
+ $this->_streamLength = $endSec;
+ }
+ }
+
+ /**
+ * Get a short string describing the type of the stream
+ * @return string
+ */
+ function getType()
+ {
+ return 'Speex';
+ }
+
+ /**
+ * Decode the stream header
+ * @access private
+ */
+ function _decodeHeader()
+ {
+ fseek($this->_filePointer, $this->_streamData['pages'][0]['body_offset'], SEEK_SET);
+ // The first 8 characters should be "Speex ".
+ if (fread($this->_filePointer, 8) != 'Speex ')
+ throw new OggException("Stream is undecodable due to a malformed header.", OGG_ERROR_UNDECODABLE);
+
+ $this->_version = fread($this->_filePointer, 20);
+ $this->_header = File_Ogg::_readLittleEndian($this->_filePointer, array(
+ 'speex_version_id' => 32,
+ 'header_size' => 32,
+ 'rate' => 32,
+ 'mode' => 32,
+ 'mode_bitstream_version'=> 32,
+ 'nb_channels' => 32,
+ 'bitrate' => 32,
+ 'frame_size' => 32,
+ 'vbr' => 32,
+ 'frames_per_packet' => 32,
+ 'extra_headers' => 32,
+ 'reserved1' => 32,
+ 'reserved2' => 32
+ ));
+ $this->_header['speex_version'] = $this->_version;
+ }
+
+ /**
+ * Get an associative array containing header information about the stream
+ * @access public
+ * @return array
+ */
+ function getHeader() {
+ return $this->_header;
+ }
+
+ /**
+ * Decode the comments header
+ * @access private
+ */
+ function _decodeCommentsHeader()
+ {
+ fseek($this->_filePointer, $this->_streamData['pages'][1]['body_offset'], SEEK_SET);
+ $this->_decodeBareCommentsHeader();
+ }
+}
+?>
diff --git a/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Theora.php b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Theora.php
new file mode 100644
index 00000000..b801ea26
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Theora.php
@@ -0,0 +1,240 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------------+
+// | File_Ogg PEAR Package for Accessing Ogg Bitstreams |
+// | Copyright (c) 2005-2007 |
+// | David Grant <david@grant.org.uk> |
+// | Tim Starling <tstarling@wikimedia.org> |
+// +----------------------------------------------------------------------------+
+// | This library is free software; you can redistribute it and/or |
+// | modify it under the terms of the GNU Lesser General Public |
+// | License as published by the Free Software Foundation; either |
+// | version 2.1 of the License, or (at your option) any later version. |
+// | |
+// | This library is distributed in the hope that it will be useful, |
+// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
+// | Lesser General Public License for more details. |
+// | |
+// | You should have received a copy of the GNU Lesser General Public |
+// | License along with this library; if not, write to the Free Software |
+// | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
+// +----------------------------------------------------------------------------+
+
+
+define( 'OGG_THEORA_IDENTIFICATION_HEADER', 0x80 );
+define( 'OGG_THEORA_COMMENTS_HEADER', 0x81 );
+define( 'OGG_THEORA_IDENTIFICATION_PAGE_OFFSET', 0 );
+define( 'OGG_THEORA_COMMENTS_PAGE_OFFSET', 1 );
+
+
+/**
+ * @author David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org>
+ * @category File
+ * @copyright David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org>
+ * @license http://www.gnu.org/copyleft/lesser.html GNU LGPL
+ * @link http://pear.php.net/package/File_Ogg
+ * @link http://www.xiph.org/theora/
+ * @package File_Ogg
+ * @version CVS: $Id: Theora.php,v 1.9 2005/11/16 20:43:27 djg Exp $
+ */
+class File_Ogg_Theora extends File_Ogg_Media
+{
+ /**
+ * @access private
+ */
+ function __construct($streamSerial, $streamData, $filePointer)
+ {
+ parent::__construct($streamSerial, $streamData, $filePointer);
+ $this->_decodeIdentificationHeader();
+ $this->_decodeCommentsHeader();
+ $endSec = $this->getSecondsFromGranulePos( $this->_lastGranulePos );
+
+ $startSec = $this->getSecondsFromGranulePos( $this->_firstGranulePos );
+
+ //make sure the offset is worth taking into account oggz_chop related hack
+ if( $startSec > 1){
+ $this->_streamLength = $endSec - $startSec;
+ $this->_startOffset = $startSec;
+ }else{
+ $this->_streamLength = $endSec;
+ }
+
+ $this->_avgBitrate = $this->_streamLength ? ($this->_streamSize * 8) / $this->_streamLength : 0;
+ }
+ function getSecondsFromGranulePos($granulePos){
+ // Calculate GranulePos seconds
+ // First make some "numeric strings"
+ // These might not fit into PHP's integer type, but they will fit into
+ // the 53-bit mantissa of a double-precision number
+ $topWord = floatval( base_convert( substr( $granulePos, 0, 8 ), 16, 10 ) );
+ $bottomWord = floatval( base_convert( substr( $granulePos, 8, 8 ), 16, 10 ) );
+ // Calculate the keyframe position by shifting right by KFGSHIFT
+ // We don't use PHP's shift operators because they're terribly broken
+ // This is made slightly simpler by the fact that KFGSHIFT < 32
+ $keyFramePos = $topWord / pow(2, $this->_kfgShift - 32) +
+ floor( $bottomWord / pow(2, $this->_kfgShift) );
+ // Calculate the frame offset by masking off the top 64-KFGSHIFT bits
+ // This requires a bit of floating point trickery
+ $offset = fmod( $bottomWord, pow(2, $this->_kfgShift) );
+ // They didn't teach you that one at school did they?
+ // Now put it together with the frame rate to calculate time in seconds
+ return ( $keyFramePos + $offset ) / $this->_frameRate;
+ }
+ /**
+ * Get the 6-byte identification string expected in the common header
+ */
+ function getIdentificationString()
+ {
+ return OGG_STREAM_CAPTURE_THEORA;
+ }
+
+ /**
+ * Parse the identification header in a Theora stream.
+ * @access private
+ */
+ function _decodeIdentificationHeader()
+ {
+ $this->_decodeCommonHeader(OGG_THEORA_IDENTIFICATION_HEADER, OGG_THEORA_IDENTIFICATION_PAGE_OFFSET);
+ $h = File_Ogg::_readBigEndian( $this->_filePointer, array(
+ 'VMAJ' => 8,
+ 'VMIN' => 8,
+ 'VREV' => 8,
+ 'FMBW' => 16,
+ 'FMBH' => 16,
+ 'PICW' => 24,
+ 'PICH' => 24,
+ 'PICX' => 8,
+ 'PICY' => 8,
+ 'FRN' => 32,
+ 'FRD' => 32,
+ 'PARN' => 24,
+ 'PARD' => 24,
+ 'CS' => 8,
+ 'NOMBR' => 24,
+ 'QUAL' => 6,
+ 'KFGSHIFT' => 5,
+ 'PF' => 2));
+ if ( !$h ) {
+ throw new OggException("Stream is undecodable due to a truncated header.", OGG_ERROR_UNDECODABLE);
+ }
+
+ // Theora version
+ // Seems overly strict but this is what the spec says
+ // VREV is for backwards-compatible changes, apparently
+ if ( $h['VMAJ'] != 3 || $h['VMIN'] != 2 ) {
+ throw new OggException("Stream is undecodable due to an invalid theora version.", OGG_ERROR_UNDECODABLE);
+ }
+ $this->_theoraVersion = "{$h['VMAJ']}.{$h['VMIN']}.{$h['VREV']}";
+
+ // Frame height/width
+ if ( !$h['FMBW'] || !$h['FMBH'] ) {
+ throw new OggException("Stream is undecodable because it has frame size of zero.", OGG_ERROR_UNDECODABLE);
+ }
+ $this->_frameWidth = $h['FMBW'] * 16;
+ $this->_frameHeight = $h['FMBH'] * 16;
+
+ // Picture height/width
+ if ( $h['PICW'] > $this->_frameWidth || $h['PICH'] > $this->_frameHeight ) {
+ throw new OggException("Stream is undecodable because the picture width is greater than the frame width.", OGG_ERROR_UNDECODABLE);
+ }
+ $this->_pictureWidth = $h['PICW'];
+ $this->_pictureHeight = $h['PICH'];
+
+ // Picture offset
+ $this->_offsetX = $h['PICX'];
+ $this->_offsetY = $h['PICY'];
+ // Frame rate
+ $this->_frameRate = $h['FRD'] == 0 ? 0 : $h['FRN'] / $h['FRD'];
+ // Physical aspect ratio
+ if ( !$h['PARN'] || !$h['PARD'] ) {
+ $this->_physicalAspectRatio = 1;
+ } else {
+ $this->_physicalAspectRatio = $h['PARN'] / $h['PARD'];
+ }
+
+ // Color space
+ $colorSpaces = array(
+ 0 => 'Undefined',
+ 1 => 'Rec. 470M',
+ 2 => 'Rec. 470BG',
+ );
+ if ( isset( $colorSpaces[$h['CS']] ) ) {
+ $this->_colorSpace = $colorSpaces[$h['CS']];
+ } else {
+ $this->_colorSpace = 'Unknown (reserved)';
+ }
+
+ $this->_nomBitrate = $h['NOMBR'];
+
+ $this->_quality = $h['QUAL'];
+ $this->_kfgShift = $h['KFGSHIFT'];
+
+ $pixelFormats = array(
+ 0 => '4:2:0',
+ 1 => 'Unknown (reserved)',
+ 2 => '4:2:2',
+ 3 => '4:4:4',
+ );
+ $this->_pixelFormat = $pixelFormats[$h['PF']];
+
+ switch ( $h['PF'] ) {
+ case 0:
+ $h['NSBS'] =
+ floor( ($h['FMBW'] + 1) / 2 ) *
+ floor( ($h['FMBH'] + 1) / 2 ) + 2 *
+ floor( ($h['FMBW'] + 3) / 4 ) *
+ floor( ($h['FMBH'] + 3) / 4 );
+ $h['NBS'] = 6 * $h['FMBW'] * $h['FMBH'];
+ break;
+ case 2:
+ $h['NSBS'] =
+ floor( ($h['FMBW'] + 1) / 2 ) *
+ floor( ($h['FMBH'] + 1) / 2 ) + 2 *
+ floor( ($h['FMBW'] + 3) / 4 ) *
+ floor( ($h['FMBH'] + 1) / 2 );
+ $h['NBS'] = 8 * $h['FMBW'] * $h['FMBH'];
+ break;
+ case 3:
+ $h['NSBS'] =
+ 3 * floor( ($h['FMBW'] + 1) / 2 ) *
+ floor( ($h['FMBH'] + 1) / 2 );
+ $h['NBS'] = 12 * $h['FMBW'] * $h['FMBH'];
+ break;
+ default:
+ $h['NSBS'] = $h['NBS'] = 0;
+ }
+ $h['NMBS'] = $h['FMBW'] * $h['FMBH'];
+
+ $this->_idHeader = $h;
+ }
+
+ /**
+ * Get an associative array containing header information about the stream
+ * @access public
+ * @return array
+ */
+ function getHeader() {
+ return $this->_idHeader;
+ }
+
+ /**
+ * Get a short string describing the type of the stream
+ * @return string
+ */
+ function getType() {
+ return 'Theora';
+ }
+
+ /**
+ * Decode the comments header
+ * @access private
+ */
+ function _decodeCommentsHeader()
+ {
+ $this->_decodeCommonHeader(OGG_THEORA_COMMENTS_HEADER, OGG_THEORA_COMMENTS_PAGE_OFFSET);
+ $this->_decodeBareCommentsHeader();
+ }
+
+}
+?>
diff --git a/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Vorbis.php b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Vorbis.php
new file mode 100644
index 00000000..06c2c180
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Vorbis.php
@@ -0,0 +1,790 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------------+
+// | File_Ogg PEAR Package for Accessing Ogg Bitstreams |
+// | Copyright (c) 2005-2007 |
+// | David Grant <david@grant.org.uk> |
+// | Tim Starling <tstarling@wikimedia.org> |
+// +----------------------------------------------------------------------------+
+// | This library is free software; you can redistribute it and/or |
+// | modify it under the terms of the GNU Lesser General Public |
+// | License as published by the Free Software Foundation; either |
+// | version 2.1 of the License, or (at your option) any later version. |
+// | |
+// | This library is distributed in the hope that it will be useful, |
+// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
+// | Lesser General Public License for more details. |
+// | |
+// | You should have received a copy of the GNU Lesser General Public |
+// | License along with this library; if not, write to the Free Software |
+// | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
+// +----------------------------------------------------------------------------+
+
+
+/**
+ * Check number for the first header in a Vorbis stream.
+ *
+ * @access private
+ */
+define("OGG_VORBIS_IDENTIFICATION_HEADER", 1);
+/**
+ * Check number for the second header in a Vorbis stream.
+ *
+ * @access private
+ */
+define("OGG_VORBIS_COMMENTS_HEADER", 3);
+/**
+ * Check number for the third header in a Vorbis stream.
+ *
+ * @access private
+ */
+define("OGG_VORBIS_SETUP_HEADER", 5);
+/**
+ * Error thrown if the stream appears to be corrupted.
+ *
+ * @access private
+ */
+define("OGG_VORBIS_ERROR_UNDECODABLE", OGG_ERROR_UNDECODABLE);
+/**
+ * Error thrown if the user attempts to extract a comment using a comment key
+ * that does not exist.
+ *
+ * @access private
+ */
+define("OGG_VORBIS_ERROR_INVALID_COMMENT", 2);
+
+define("OGG_VORBIS_IDENTIFICATION_PAGE_OFFSET", 0);
+define("OGG_VORBIS_COMMENTS_PAGE_OFFSET", 1);
+
+/**
+ * Error thrown if the user attempts to write a comment containing an illegal
+ * character
+ *
+ * @access private
+ */
+define("OGG_VORBIS_ERROR_ILLEGAL_COMMENT", 3);
+
+/**
+ * Extract the contents of a Vorbis logical stream.
+ *
+ * This class provides an interface to a Vorbis logical stream found within
+ * a Ogg stream. A variety of information may be extracted, including comment
+ * tags, running time, and bitrate. For more information, please see the following
+ * links.
+ *
+ * @author David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org>
+ * @category File
+ * @copyright David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org>
+ * @license http://www.gnu.org/copyleft/lesser.html GNU LGPL
+ * @link http://pear.php.net/package/File_Ogg
+ * @link http://www.xiph.org/vorbis/doc/
+ * @package File_Ogg
+ * @version CVS: $Id: Vorbis.php,v 1.13 2005/11/19 09:06:32 djg Exp $
+ */
+class File_Ogg_Vorbis extends File_Ogg_Media
+{
+
+ /**
+ * Version of vorbis specification used.
+ *
+ * @access private
+ * @var int
+ */
+ var $_version;
+
+ /**
+ * Number of channels in the vorbis stream.
+ *
+ * @access private
+ * @var int
+ */
+ var $_channels;
+
+ /**
+ * Number of samples per second in the vorbis stream.
+ *
+ * @access private
+ * @var int
+ */
+ var $_sampleRate;
+
+ /**
+ * Minimum bitrate for the vorbis stream.
+ *
+ * @access private
+ * @var int
+ */
+ var $_minBitrate;
+
+ /**
+ * Maximum bitrate for the vorbis stream.
+ *
+ * @access private
+ * @var int
+ */
+ var $_maxBitrate;
+
+ /**
+ * Nominal bitrate for the vorbis stream.
+ *
+ * @access private
+ * @var int
+ */
+ var $_nomBitrate;
+
+ /**
+ * Average bitrate for the vorbis stream.
+ *
+ * @access private
+ * @var float
+ */
+ var $_avgBitrate;
+
+ /**
+ * The length of this stream in seconds.
+ *
+ * @access private
+ * @var int
+ */
+ var $_streamLength;
+
+ /**
+ * the start offset of this stream in seconds
+ */
+ var $_startOffset;
+ /**
+ * Constructor for accessing a Vorbis logical stream.
+ *
+ * This method is the constructor for the native-PHP interface to a Vorbis logical
+ * stream, embedded within an Ogg physical stream.
+ *
+ * @param int $streamSerial Serial number of the logical stream.
+ * @param array $streamData Data for the requested logical stream.
+ * @param string $filePath Location of a file on the filesystem.
+ * @param pointer $filePointer File pointer for the current physical stream.
+ * @access private
+ */
+ function __construct($streamSerial, $streamData, $filePointer)
+ {
+ parent::__construct($streamSerial, $streamData, $filePointer);
+ $this->_decodeIdentificationHeader();
+ $this->_decodeCommentsHeader(OGG_VORBIS_COMMENTS_HEADER, OGG_VORBIS_COMMENTS_PAGE_OFFSET);
+
+ $endSec = $this->getSecondsFromGranulePos( $this->_lastGranulePos );
+ $startSec = $this->getSecondsFromGranulePos( $this->_firstGranulePos );
+
+ //make sure the offset is worth taking into account oggz_chop related hack
+ if( $startSec > 1){
+ $this->_streamLength = $endSec - $startSec;
+ $this->_startOffset = $startSec;
+ }else{
+ $this->_streamLength = $endSec;
+ }
+
+ $this->_avgBitrate = $this->_streamLength ? ($this->_streamSize * 8) / $this->_streamLength : 0;
+ }
+ function getSecondsFromGranulePos( $granulePos ){
+ return (( '0x' . substr( $granulePos, 0, 8 ) ) * pow(2, 32)
+ + ( '0x' . substr( $granulePos, 8, 8 ) ))
+ / $this->_idHeader['audio_sample_rate'];
+ }
+ /**
+ * Get a short string describing the type of the stream
+ */
+ function getType()
+ {
+ return 'Vorbis';
+ }
+
+ /**
+ * Parse the identification header (the first of three headers) in a Vorbis stream.
+ *
+ * This function parses the identification header. The identification header
+ * contains simple audio characteristics, such as sample rate and number of
+ * channels. There are a number of error-checking provisions laid down in the Vorbis
+ * specification to ensure the stream is pure.
+ *
+ * @access private
+ */
+ function _decodeIdentificationHeader()
+ {
+ $this->_decodeCommonHeader(OGG_VORBIS_IDENTIFICATION_HEADER, OGG_VORBIS_IDENTIFICATION_PAGE_OFFSET);
+
+ $h = File_Ogg::_readLittleEndian($this->_filePointer, array(
+ 'vorbis_version' => 32,
+ 'audio_channels' => 8,
+ 'audio_sample_rate' => 32,
+ 'bitrate_maximum' => 32,
+ 'bitrate_nominal' => 32,
+ 'bitrate_minimum' => 32,
+ 'blocksize_0' => 4,
+ 'blocksize_1' => 4,
+ 'framing_flag' => 1
+ ));
+
+ // The Vorbis stream version must be 0.
+ if ($h['vorbis_version'] == 0)
+ $this->_version = $h['vorbis_version'];
+ else
+ throw new OggException("Stream is undecodable due to an invalid vorbis stream version.", OGG_VORBIS_ERROR_UNDECODABLE);
+
+ // The number of channels MUST be greater than 0.
+ if ($h['audio_channels'] == 0)
+ throw new OggException("Stream is undecodable due to zero channels.", OGG_VORBIS_ERROR_UNDECODABLE);
+ else
+ $this->_channels = $h['audio_channels'];
+
+ // The sample rate MUST be greater than 0.
+ if ($h['audio_sample_rate'] == 0)
+ throw new OggException("Stream is undecodable due to a zero sample rate.", OGG_VORBIS_ERROR_UNDECODABLE);
+ else
+ $this->_sampleRate = $h['audio_sample_rate'];
+
+ // Extract the various bitrates
+ $this->_maxBitrate = $h['bitrate_maximum'];
+ $this->_nomBitrate = $h['bitrate_nominal'];
+ $this->_minBitrate = $h['bitrate_minimum'];
+
+ // Powers of two between 6 and 13 inclusive.
+ $valid_block_sizes = array(64, 128, 256, 512, 1024, 2048, 4096, 8192);
+
+ // blocksize_0 MUST be a valid blocksize.
+ $blocksize_0 = pow(2, $h['blocksize_0']);
+ if (FALSE == in_array($blocksize_0, $valid_block_sizes))
+ throw new OggException("Stream is undecodable because blocksize_0 is $blocksize_0, which is not a valid size.", OGG_VORBIS_ERROR_UNDECODABLE);
+
+ // Extract bits 5 to 8 from the character data.
+ // blocksize_1 MUST be a valid blocksize.
+ $blocksize_1 = pow(2, $h['blocksize_1']);
+ if (FALSE == in_array($blocksize_1, $valid_block_sizes))
+ throw new OggException("Stream is undecodable because blocksize_1 is not a valid size.", OGG_VORBIS_ERROR_UNDECODABLE);
+
+ // blocksize 0 MUST be less than or equal to blocksize 1.
+ if ($blocksize_0 > $blocksize_1)
+ throw new OggException("Stream is undecodable because blocksize_0 is not less than or equal to blocksize_1.", OGG_VORBIS_ERROR_UNDECODABLE);
+
+ // The framing bit MUST be set to mark the end of the identification header.
+ // Some encoders are broken though -- TS
+ /*
+ if ($h['framing_flag'] == 0)
+ throw new OggException("Stream in undecodable because the framing bit is not non-zero.", OGG_VORBIS_ERROR_UNDECODABLE);
+ */
+
+ $this->_idHeader = $h;
+ }
+
+ /**
+ * Decode the comments header
+ * @access private
+ * @param int $packetType
+ * @param int $pageOffset
+ */
+ function _decodeCommentsHeader($packetType, $pageOffset)
+ {
+ $this->_decodeCommonHeader($packetType, $pageOffset);
+ $this->_decodeBareCommentsHeader();
+ // The framing bit MUST be set to mark the end of the comments header.
+ $framing_bit = unpack("Cdata", fread($this->_filePointer, 1));
+ if ($framing_bit['data'] != 1)
+ throw new OggException("Stream Undecodable", OGG_VORBIS_ERROR_UNDECODABLE);
+ }
+
+ /**
+ * Get the 6-byte identification string expected in the common header
+ */
+ function getIdentificationString() {
+ return OGG_STREAM_CAPTURE_VORBIS;
+ }
+
+ /**
+ * Version of the Vorbis specification referred to in the encoding of this stream.
+ *
+ * This method returns the version of the Vorbis specification (currently 0 (ZERO))
+ * referred to by the encoder of this stream. The Vorbis specification is well-
+ * defined, and thus one does not expect this value to change on a frequent basis.
+ *
+ * @access public
+ * @return int
+ */
+ function getEncoderVersion()
+ {
+ return ($this->_version);
+ }
+
+ /**
+ * Samples per second.
+ *
+ * This function returns the number of samples used per second in this
+ * recording. Probably the most common value here is 44,100.
+ *
+ * @return int
+ * @access public
+ */
+ function getSampleRate()
+ {
+ return ($this->_sampleRate);
+ }
+
+ /**
+ * Various bitrate measurements
+ *
+ * Gives an array of the values of four different types of bitrates for this
+ * stream. The nominal, maximum and minimum values are found within the file,
+ * whereas the average value is computed.
+ *
+ * @access public
+ * @return array
+ */
+ function getBitrates()
+ {
+ return (array("nom" => $this->_nomBitrate, "max" => $this->_maxBitrate, "min" => $this->_minBitrate, "avg" => $this->_avgBitrate));
+ }
+
+ /**
+ * Gives the most accurate bitrate measurement from this stream.
+ *
+ * This function returns the most accurate bitrate measurement for this
+ * recording, depending on values set in the stream header.
+ *
+ * @access public
+ * @return float
+ */
+ function getBitrate()
+ {
+ if ($this->_avgBitrate != 0)
+ return ($this->_avgBitrate);
+ elseif ($this->_nomBitrate != 0)
+ return ($this->_nomBitrate);
+ else
+ return (($this->_minBitrate + $this->_maxBitrate) / 2);
+ }
+
+ /**
+ * Gives the length (in seconds) of this stream.
+ *
+ * @access public
+ * @return int
+ */
+ function getLength()
+ {
+ return ($this->_streamLength);
+ }
+ /**
+ * Get the start offset of the stream in seconds
+ * @access public
+ * @return int
+ */
+ function getStartOffset(){
+ return ($this->_startOffset);
+ }
+ /**
+ * States whether this logical stream was encoded in mono.
+ *
+ * @access public
+ * @return boolean
+ */
+ function isMono()
+ {
+ return ($this->_channels == 1);
+ }
+
+ /**
+ * States whether this logical stream was encoded in stereo.
+ *
+ * @access public
+ * @return boolean
+ */
+ function isStereo()
+ {
+ return ($this->_channels == 2);
+ }
+
+ /**
+ * States whether this logical stream was encoded in quadrophonic sound.
+ *
+ * @access public
+ * @return boolean
+ */
+ function isQuadrophonic()
+ {
+ return ($this->_channels == 4);
+ }
+
+ /**
+ * The title of this track, e.g. "What's Up Pussycat?".
+ *
+ * @access public
+ * @return string
+ */
+ function getTitle()
+ {
+ return ($this->getField("TITLE"));
+ }
+
+ /**
+ * Set the title of this track.
+ *
+ * @access public
+ * @param string $title
+ * @param boolean $replace
+ */
+ function setTitle($title, $replace = true)
+ {
+ $this->setField("TITLE", $title, $replace);
+ }
+
+ /**
+ * The version of the track, such as a remix.
+ *
+ * @access public
+ * @return string
+ */
+ function getVersion()
+ {
+ return $this->getField("VERSION");
+ }
+
+ /**
+ * Set the version of this track.
+ *
+ * @access public
+ * @param string $version
+ * @param boolean $replace
+ */
+ function setVersion($version, $replace = true)
+ {
+ $this->setField("VERSION", $version, $replace);
+ }
+
+ /**
+ * The album or collection from which this track comes.
+ *
+ * @access public
+ * @return string
+ */
+ function getAlbum()
+ {
+ return ($this->getField("ALBUM"));
+ }
+
+ /**
+ * Set the album or collection for this track.
+ *
+ * @access public
+ * @param string $album
+ * @param boolean $replace
+ */
+ function setAlbum($album, $replace = true)
+ {
+ $this->setField("ALBUM", $album, $replace);
+ }
+
+ /**
+ * The number of this track if it is part of a larger collection.
+ *
+ * @access public
+ * @return string
+ */
+ function getTrackNumber()
+ {
+ return ($this->getField("TRACKNUMBER"));
+ }
+
+ /**
+ * Set the number of this relative to the collection.
+ *
+ * @access public
+ * @param int $number
+ * @param boolean $replace
+ */
+ function setTrackNumber($number, $replace = true)
+ {
+ $this->setField("TRACKNUMBER", $number, $replace);
+ }
+
+ /**
+ * The artist responsible for this track.
+ *
+ * This function returns the name of the artist responsible for this
+ * recording, which may be either a solo-artist, duet or group.
+ *
+ * @access public
+ * @return string
+ */
+ function getArtist()
+ {
+ return ($this->getField("ARTIST"));
+ }
+
+ /**
+ * Set the artist of this track.
+ *
+ * @access public
+ * @param string $artist
+ * @param boolean $replace
+ */
+ function setArtist($artist, $replace = true)
+ {
+ $this->setField("ARTIST", $artist, $replace = true);
+ }
+
+ /**
+ * The performer of this track, such as an orchestra
+ *
+ * @access public
+ * @return string
+ */
+ function getPerformer()
+ {
+ return ($this->getField("PERFORMER"));
+ }
+
+ /**
+ * Set the performer of this track.
+ *
+ * @access public
+ * @param string $performer
+ * @param boolean $replace
+ */
+ function setPerformer($performer, $replace = true)
+ {
+ $this->setField("PERFORMER", $performer, $replace);
+ }
+
+ /**
+ * The copyright attribution for this track.
+ *
+ * @access public
+ * @return string
+ */
+ function getCopyright()
+ {
+ return ($this->getField("COPYRIGHT"));
+ }
+
+ /**
+ * Set the copyright attribution for this track.
+ *
+ * @access public
+ * @param string $copyright
+ * @param boolean $replace
+ */
+ function setCopyright($copyright, $replace = true)
+ {
+ $this->setField("COPYRIGHT", $copyright, $replace);
+ }
+
+ /**
+ * The rights of distribution for this track.
+ *
+ * This funtion returns the license for this track, and may include
+ * copyright information, or a creative commons statement.
+ *
+ * @access public
+ * @return string
+ */
+ function getLicense()
+ {
+ return ($this->getField("LICENSE"));
+ }
+
+ /**
+ * Set the distribution rights for this track.
+ *
+ * @access public
+ * @param string $license
+ * @param boolean $replace
+ */
+ function setLicense($license, $replace = true)
+ {
+ $this->setField("LICENSE", $license, $replace);
+ }
+
+ /**
+ * The organisation responsible for this track.
+ *
+ * This function returns the name of the organisation responsible for
+ * the production of this track, such as the record label.
+ *
+ * @access public
+ * @return string
+ */
+ function getOrganization()
+ {
+ return ($this->getField("ORGANIZATION"));
+ }
+
+ /**
+ * Set the organisation responsible for this track.
+ *
+ * @access public
+ * @param string $organization
+ * @param boolean $replace
+ */
+ function setOrganziation($organization, $replace = true)
+ {
+ $this->setField("ORGANIZATION", $organization, $replace);
+ }
+
+ /**
+ * A short description of the contents of this track.
+ *
+ * This function returns a short description of this track, which might
+ * contain extra information that doesn't fit anywhere else.
+ *
+ * @access public
+ * @return string
+ */
+ function getDescription()
+ {
+ return ($this->getField("DESCRIPTION"));
+ }
+
+ /**
+ * Set the description of this track.
+ *
+ * @access public
+ * @param string $description
+ * @param boolean $replace
+ */
+ function setDescription($description, $replace = true)
+ {
+ $this->setField("DESCRIPTION", $replace);
+ }
+
+ /**
+ * The genre of this recording (e.g. Rock)
+ *
+ * This function returns the genre of this recording. There are no pre-
+ * defined genres, so this is completely up to the tagging software.
+ *
+ * @access public
+ * @return string
+ */
+ function getGenre()
+ {
+ return ($this->getField("GENRE"));
+ }
+
+ /**
+ * Set the genre of this track.
+ *
+ * @access public
+ * @param string $genre
+ * @param boolean $replace
+ */
+ function setGenre($genre, $replace = true)
+ {
+ $this->setField("GENRE", $genre, $replace);
+ }
+
+ /**
+ * The date of the recording of this track.
+ *
+ * This function returns the date on which this recording was made. There
+ * is no specification for the format of this date.
+ *
+ * @access public
+ * @return string
+ */
+ function getDate()
+ {
+ return ($this->getField("DATE"));
+ }
+
+ /**
+ * Set the date of recording for this track.
+ *
+ * @access public
+ * @param string $date
+ * @param boolean $replace
+ */
+ function setDate($date, $replace = true)
+ {
+ $this->setField("DATE", $date, $replace);
+ }
+
+ /**
+ * Where this recording was made.
+ *
+ * This function returns where this recording was made, such as a recording
+ * studio, or concert venue.
+ *
+ * @access public
+ * @return string
+ */
+ function getLocation()
+ {
+ return ($this->getField("LOCATION"));
+ }
+
+ /**
+ * Set the location of the recording of this track.
+ *
+ * @access public
+ * @param string $location
+ * @param boolean $replace
+ */
+ function setLocation($location, $replace = true)
+ {
+ $this->setField("LOCATION", $location, $replace);
+ }
+
+ /**
+ * @access public
+ * @return string
+ */
+ function getContact()
+ {
+ return ($this->getField("CONTACT"));
+ }
+
+ /**
+ * Set the contact information for this track.
+ *
+ * @access public
+ * @param string $contact
+ * @param boolean $replace
+ */
+ function setContact($contact, $replace = true)
+ {
+ $this->setField("CONTACT", $contact, $replace);
+ }
+
+ /**
+ * International Standard Recording Code.
+ *
+ * Returns the International Standard Recording Code. This code can be
+ * validated using the Validate_ISPN package.
+ *
+ * @access public
+ * @return string
+ */
+ function getIsrc()
+ {
+ return ($this->getField("ISRC"));
+ }
+
+ /**
+ * Set the ISRC for this track.
+ *
+ * @access public
+ * @param string $isrc
+ * @param boolean $replace
+ */
+ function setIsrc($isrc, $replace = true)
+ {
+ $this->setField("ISRC", $isrc, $replace);
+ }
+
+ /**
+ * Get an associative array containing header information about the stream
+ * @access public
+ * @return array
+ */
+ function getHeader() {
+ return $this->_idHeader;
+ }
+}
+?>
diff --git a/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/README b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/README
new file mode 100644
index 00000000..963ca07c
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/README
@@ -0,0 +1,2 @@
+This was originally a fork of the File_Ogg package in PEAR.
+
diff --git a/extensions/TimedMediaHandler/handlers/OggHandler/OggException.php b/extensions/TimedMediaHandler/handlers/OggHandler/OggException.php
new file mode 100644
index 00000000..a09d36da
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/OggHandler/OggException.php
@@ -0,0 +1,4 @@
+<?php
+
+class OggException extends Exception {
+}
diff --git a/extensions/TimedMediaHandler/handlers/OggHandler/OggHandler.php b/extensions/TimedMediaHandler/handlers/OggHandler/OggHandler.php
new file mode 100644
index 00000000..83e1a0e7
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/OggHandler/OggHandler.php
@@ -0,0 +1,379 @@
+<?php
+/**
+ * ogg handler
+ */
+class OggHandlerTMH extends TimedMediaHandler {
+ const METADATA_VERSION = 2;
+
+ /**
+ * @param $image File
+ * @param $path string
+ * @return string
+ */
+ function getMetadata( $image, $path ) {
+ $metadata = array( 'version' => self::METADATA_VERSION );
+
+ try {
+ $f = new File_Ogg( $path );
+ $streams = array();
+ foreach ( $f->listStreams() as $streamIDs ) {
+ foreach ( $streamIDs as $streamID ) {
+ $stream = $f->getStream( $streamID );
+ $streams[$streamID] = array(
+ 'serial' => $stream->getSerial(),
+ 'group' => $stream->getGroup(),
+ 'type' => $stream->getType(),
+ 'vendor' => $stream->getVendor(),
+ 'length' => $stream->getLength(),
+ 'size' => $stream->getSize(),
+ 'header' => $stream->getHeader(),
+ 'comments' => $stream->getComments()
+ );
+ }
+ }
+ $metadata['streams'] = $streams;
+ $metadata['length'] = $f->getLength();
+ // Get the offset of the file (in cases where the file is a segment copy)
+ $metadata['offset'] = $f->getStartOffset();
+ } catch ( OggException $e ) {
+ // File not found, invalid stream, etc.
+ $metadata['error'] = array(
+ 'message' => $e->getMessage(),
+ 'code' => $e->getCode()
+ );
+ }
+ return serialize( $metadata );
+ }
+
+ /**
+ * Display metadata box on file description page.
+ *
+ * This is pretty basic, it puts data from all the streams together,
+ * and only outputs a couple of the most commonly used ogg "comments",
+ * with comments from all the streams combined
+ *
+ * @param File $file
+ * @param bool|IContextSource $context Context to use (optional)
+ * @return array|bool
+ */
+ public function formatMetadata( $file, $context = false ) {
+ $meta = $this->getCommonMetaArray( $file );
+ if ( count( $meta ) === 0 ) {
+ return false;
+ }
+ return $this->formatMetadataHelper( $meta, $context );
+ }
+
+ /**
+ * Get some basic metadata properties that are common across file types.
+ *
+ * @param File $file
+ * @return array Array of metadata. See MW's FormatMetadata class for format.
+ */
+ public function getCommonMetaArray( File $file ) {
+ $metadata = $this->unpackMetadata( $file->getMetadata() );
+ if ( !$metadata || isset( $metadata['error'] ) || !isset( $metadata['streams'] ) ) {
+ return array();
+ }
+
+ // See http://www.xiph.org/vorbis/doc/v-comment.html
+ // http://age.hobba.nl/audio/mirroredpages/ogg-tagging.html
+ $metadataMap = array(
+ 'title' => 'ObjectName',
+ 'artist' => 'Artist',
+ 'performer' => 'Artist',
+ 'description' => 'ImageDescription',
+ 'license' => 'UsageTerms',
+ 'copyright' => 'Copyright',
+ 'organization' => 'dc-publisher',
+ 'date' => 'DateTimeDigitized',
+ 'location' => 'LocationDest',
+ 'contact' => 'Contact',
+ 'encoded_using' => 'Software',
+ 'encoder' => 'Software',
+ // OpenSubtitles.org hash. Identifies source video.
+ 'source_ohash' => 'OriginalDocumentID',
+ 'comment' => 'UserComment',
+ 'language' => 'LanguageCode',
+ );
+
+ $props = array();
+
+ foreach( $metadata['streams'] as $stream ) {
+ if ( isset( $stream['vendor'] ) ) {
+ if ( !isset( $props['Software'] ) ) {
+ $props['Software'] = array();
+ }
+ $props['Software'][] = trim( $stream['vendor'] );
+ }
+ if ( !isset( $stream['comments'] ) ) {
+ continue;
+ }
+ foreach( $stream['comments'] as $name => $rawValue ) {
+ // $value will be an array if the file has
+ // a multiple tags with the same name. Otherwise it
+ // is a string.
+ foreach( (array) $rawValue as $value ) {
+ $trimmedValue = trim( $value );
+ if ( $trimmedValue === '' ) {
+ continue;
+ }
+ $lowerName = strtolower( $name );
+ if ( isset( $metadataMap[$lowerName] ) ) {
+ $convertedName = $metadataMap[$lowerName];
+ if ( !isset( $props[$convertedName] ) ) {
+ $props[$convertedName] = array();
+ }
+ $props[$convertedName][] = $trimmedValue;
+ }
+ }
+ }
+
+ }
+ // properties might be duplicated across streams
+ foreach( $props as &$type ) {
+ $type = array_unique( $type );
+ $type = array_values( $type );
+ }
+
+ return $props;
+ }
+
+ /**
+ * Get the "media size"
+ *
+ * @param $file File
+ * @param $path string
+ * @param $metadata bool
+ * @return array|bool
+ */
+ function getImageSize( $file, $path, $metadata = false ) {
+ global $wgMediaVideoTypes;
+ // Just return the size of the first video stream
+ if ( $metadata === false ) {
+ $metadata = $file->getMetadata();
+ }
+ $metadata = $this->unpackMetadata( $metadata );
+ if ( isset( $metadata['error'] ) || !isset( $metadata['streams'] ) ) {
+ return false;
+ }
+ foreach ( $metadata['streams'] as $stream ) {
+ if ( in_array( $stream['type'], $wgMediaVideoTypes ) ) {
+ $pictureWidth = $stream['header']['PICW'];
+ $parNumerator = $stream['header']['PARN'];
+ $parDenominator = $stream['header']['PARD'];
+ if( $parNumerator && $parDenominator ) {
+ // Compensate for non-square pixel aspect ratios
+ $pictureWidth = $pictureWidth * $parNumerator / $parDenominator;
+ }
+ return array(
+ intval( $pictureWidth ),
+ intval( $stream['header']['PICH'] )
+ );
+ }
+ }
+ return array( false, false );
+ }
+
+ /**
+ * @param $metadata
+ * @return bool|mixed
+ */
+ function unpackMetadata( $metadata ) {
+ wfSuppressWarnings();
+ $unser = unserialize( $metadata );
+ wfRestoreWarnings();
+ if ( isset( $unser['version'] ) && $unser['version'] == self::METADATA_VERSION ) {
+ return $unser;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * @param $image
+ * @return string
+ */
+ function getMetadataType( $image ) {
+ return 'ogg';
+ }
+ /**
+ * @param $file File
+ */
+ function getWebType( $file ) {
+ $baseType = ( $file->getWidth() == 0 && $file->getHeight() == 0 )? 'audio' : 'video';
+ $baseType .= '/ogg';
+ $streamTypes = $this->getStreamTypes( $file );
+ if ( !$streamTypes ) {
+ return $baseType;
+ }
+ $codecs = strtolower( implode( ", ", $streamTypes ) );
+ return $baseType . '; codecs="' . $codecs . '"';
+ }
+ /**
+ * @param $file File
+ * @return array|bool
+ */
+ function getStreamTypes( $file ) {
+ $streamTypes = array();
+ $metadata = $this->unpackMetadata( $file->getMetadata() );
+ if ( !$metadata || isset( $metadata['error'] ) ) {
+ return false;
+ }
+ foreach ( $metadata['streams'] as $stream ) {
+ $streamTypes[] = $stream['type'];
+ }
+ return array_unique( $streamTypes );
+ }
+
+ /**
+ * @param $file File
+ * @return int
+ */
+ function getOffset( $file ){
+ $metadata = $this->unpackMetadata( $file->getMetadata() );
+ if ( !$metadata || isset( $metadata['error'] ) || !isset( $metadata['offset']) ) {
+ return 0;
+ } else {
+ return $metadata['offset'];
+ }
+ }
+
+ /**
+ * @param $file File
+ * @return int
+ */
+ function getLength( $file ) {
+ $metadata = $this->unpackMetadata( $file->getMetadata() );
+ if ( !$metadata || isset( $metadata['error'] ) ) {
+ return 0;
+ } else {
+ return $metadata['length'];
+ }
+ }
+
+ /**
+ * Get useful response headers for GET/HEAD requests for a file with the given metadata
+ * @param $metadata mixed Result this handlers getMetadata() for a file
+ * @return Array
+ */
+ public function getStreamHeaders( $metadata ) {
+ $metadata = $this->unpackMetadata( $metadata );
+ if ( $metadata && !isset( $metadata['error'] ) && isset( $metadata['length'] ) ) {
+ return array( 'X-Content-Duration' => floatval( $metadata[ 'length' ] ) );
+ }
+ return array();
+ }
+
+ /**
+ * @param $file File
+ * @return float|int
+ */
+ function getFramerate( $file ){
+ $metadata = $this->unpackMetadata( $file->getMetadata() );
+ if ( !$metadata || isset( $metadata['error'] ) ) {
+ return 0;
+ } else {
+ // Return the first found theora stream framerate:
+ foreach ( $metadata['streams'] as $stream ) {
+ if( $stream['type'] == 'Theora' ){
+ return $stream['header']['FRN'] / $stream['header']['FRD'];
+ }
+ }
+ return 0;
+ }
+ }
+
+ /**
+ * @param $file File
+ * @return String
+ */
+ function getShortDesc( $file ) {
+ global $wgLang, $wgMediaAudioTypes, $wgMediaVideoTypes;
+
+ $streamTypes = $this->getStreamTypes( $file );
+ if ( !$streamTypes ) {
+ return parent::getShortDesc( $file );
+ }
+ if ( array_intersect( $streamTypes, $wgMediaVideoTypes ) ) {
+ // Count multiplexed audio/video as video for short descriptions
+ $msg = 'timedmedia-ogg-short-video';
+ } elseif ( array_intersect( $streamTypes, $wgMediaAudioTypes ) ) {
+ $msg = 'timedmedia-ogg-short-audio';
+ } else {
+ $msg = 'timedmedia-ogg-short-general';
+ }
+ return wfMessage( $msg, implode( '/', $streamTypes ),
+ $wgLang->formatTimePeriod( $this->getLength( $file ) ) )->text();
+ }
+
+ /**
+ * @param $file File
+ * @return String
+ */
+ function getLongDesc( $file ) {
+ global $wgLang, $wgMediaVideoTypes, $wgMediaAudioTypes;
+
+ $streamTypes = $this->getStreamTypes( $file );
+ if ( !$streamTypes ) {
+ $unpacked = $this->unpackMetadata( $file->getMetadata() );
+ if ( isset( $unpacked['error']['message'] ) ) {
+ return wfMessage( 'timedmedia-ogg-long-error', $unpacked['error']['message'] )->text();
+ } else {
+ return wfMessage( 'timedmedia-ogg-long-no-streams' )->text();
+ }
+ }
+ if ( array_intersect( $streamTypes,$wgMediaVideoTypes ) ) {
+ if ( array_intersect( $streamTypes, $wgMediaAudioTypes ) ) {
+ $msg = 'timedmedia-ogg-long-multiplexed';
+ } else {
+ $msg = 'timedmedia-ogg-long-video';
+ }
+ } elseif ( array_intersect( $streamTypes, $wgMediaAudioTypes ) ) {
+ $msg = 'timedmedia-ogg-long-audio';
+ } else {
+ $msg = 'timedmedia-ogg-long-general';
+ }
+ $size = 0;
+ $unpacked = $this->unpackMetadata( $file->getMetadata() );
+ if ( !$unpacked || isset( $metadata['error'] ) ) {
+ $length = 0;
+ } else {
+ $length = $this->getLength( $file );
+ foreach ( $unpacked['streams'] as $stream ) {
+ if( isset( $stream['size'] ) )
+ $size += $stream['size'];
+ }
+ }
+ return wfMessage(
+ $msg,
+ implode( '/', $streamTypes ),
+ $wgLang->formatTimePeriod( $length ),
+ $wgLang->formatBitrate( $this->getBitRate( $file ) )
+ )->numParams(
+ $file->getWidth(),
+ $file->getHeight()
+ )->text();
+ }
+
+ /**
+ * @param $file File
+ * @return float|int
+ */
+ function getBitRate( &$file ){
+ $size = 0;
+ $unpacked = $this->unpackMetadata( $file->getMetadata() );
+ if ( !$unpacked || isset( $unpacked['error'] ) ) {
+ $length = 0;
+ } else {
+ $length = $this->getLength( $file );
+ if ( isset( $unpacked['streams'] ) ) {
+ foreach ( $unpacked['streams'] as $stream ) {
+ if( isset( $stream['size'] ) )
+ $size += $stream['size'];
+ }
+ }
+ }
+ return $length == 0 ? 0 : $size / $length * 8;
+ }
+}
diff --git a/extensions/TimedMediaHandler/handlers/TextHandler/TextHandler.php b/extensions/TimedMediaHandler/handlers/TextHandler/TextHandler.php
new file mode 100644
index 00000000..3c229d5f
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/TextHandler/TextHandler.php
@@ -0,0 +1,305 @@
+<?php
+/**
+ * Timed Text handling for mediaWiki
+ *
+ * Timed text support is presently fairly limited. Unlike Ogg and WebM handlers,
+ * timed text does not extend the TimedMediaHandler class.
+ *
+ * TODO On "new" timedtext language save purge all pages where file exists
+ */
+
+
+/**
+ * Subclass ApiMain but query other db
+ */
+class ForeignApiQueryAllPages extends ApiQueryAllPages {
+ public function __construct( $mDb, $query, $moduleName ) {
+ global $wgTimedTextForeignNamespaces;
+
+ $this->foreignDb = $mDb;
+
+ $wikiID = $this->foreignDb->getWikiID();
+ if ( isset( $wgTimedTextForeignNamespaces[ $wikiID ] ) ) {
+ $this->foreignNs = $wgTimedTextForeignNamespaces[ $wikiID ];
+ } else {
+ $this->foreignNs = NS_TIMEDTEXT;
+ }
+ parent::__construct( $query, $moduleName, 'ap' );
+ }
+
+ protected function getDB() {
+ return $this->foreignDb;
+ }
+
+ protected function parseMultiValue( $valueName, $value, $allowMultiple, $allowedValues ) {
+ // foreignnNs might not be defined localy,
+ // catch the undefined error here
+ if ( $valueName == 'apnamespace'
+ && $value == $this->foreignNs
+ && $allowMultiple == false
+ ) {
+ return $this->foreignNs;
+ }
+ return parent::parseMultiValue( $valueName, $value, $allowMultiple, $allowedValues );
+ }
+
+ /**
+ * An alternative to titleToKey() that doesn't trim trailing spaces
+ *
+ *
+ * @FIXME: I'M A BIG HACK
+ *
+ * @param string $titlePart Title part with spaces
+ * @return string Title part with underscores
+ */
+ public function titlePartToKey( $titlePart, $defaultNamespace = NS_MAIN ) {
+ return substr( $this->titleToKey( $titlePart . 'x' ), 0, -1 );
+ }
+}
+
+class TextHandler {
+ var $remoteNs = null;//lazy init remote Namespace number
+
+ /**
+ * @var File
+ */
+ protected $file;
+
+ function __construct( $file ){
+ $this->file = $file;
+ }
+
+ /**
+ * Get the timed text tracks elements as an associative array
+ * @return array|mixed
+ */
+ function getTracks(){
+ if( $this->file->isLocal() ){
+ return $this->getLocalTextSources();
+ } elseif ( $this->file->getRepo() instanceof ForeignDBViaLBRepo ){
+ return $this->getForeignDBTextSources();
+ } else {
+ return $this->getRemoteTextSources();
+ }
+ }
+
+ /**
+ * @return bool|int|null
+ */
+ function getTimedTextNamespace(){
+ global $wgEnableLocalTimedText;
+ if( $this->file->isLocal() ) {
+ if ( $wgEnableLocalTimedText ) {
+ return NS_TIMEDTEXT;
+ } else {
+ return false;
+ }
+ } elseif( $this->file->repo instanceof ForeignDBViaLBRepo ){
+ global $wgTimedTextForeignNamespaces;
+ $wikiID = $this->file->getRepo()->getSlaveDB()->getWikiID();
+ if ( isset( $wgTimedTextForeignNamespaces[ $wikiID ] ) ) {
+ return $wgTimedTextForeignNamespaces[ $wikiID ];
+ }
+ // failed to get namespace via ForeignDBViaLBRepo, return NS_TIMEDTEXT
+ return NS_TIMEDTEXT;
+ } else {
+ if( $this->remoteNs !== null ){
+ return $this->remoteNs;
+ }
+ // Get the namespace data from the image api repo:
+ // fetchImageQuery query caches results
+ $data = $this->file->getRepo()->fetchImageQuery( array(
+ 'meta' =>'siteinfo',
+ 'siprop' => 'namespaces'
+ ));
+
+ if( isset( $data['query'] ) && isset( $data['query']['namespaces'] ) ){
+ // get the ~last~ timed text namespace defined
+ foreach( $data['query']['namespaces'] as $ns ){
+ if( $ns['*'] == 'TimedText' ){
+ $this->remoteNs = $ns['id'];
+ }
+ }
+ }
+ // Return the remote Ns
+ return $this->remoteNs;
+ }
+ }
+
+ /**
+ * @return array|bool
+ */
+ function getTextPagesQuery(){
+ $ns = $this->getTimedTextNamespace();
+ if( $ns === false ){
+ wfDebug("Repo: " . $this->file->repo->getName() . " does not have a TimedText namesapce \n");
+ // No timed text namespace, don't try to look up timed text tracks
+ return false;
+ }
+ return array(
+ 'action' => 'query',
+ 'list' => 'allpages',
+ 'apnamespace' => $ns,
+ 'aplimit' => 300,
+ 'apprefix' => $this->file->getTitle()->getDBkey()
+ );
+ }
+
+ /**
+ * @return array|mixed
+ */
+ function getRemoteTextSources(){
+ global $wgMemc;
+ // Use descriptionCacheExpiry as our expire for timed text tracks info
+ if ( $this->file->getRepo()->descriptionCacheExpiry > 0 ) {
+ wfDebug("Attempting to get text tracks from cache...");
+ $key = $this->file->getRepo()->getLocalCacheKey( 'RemoteTextTracks', 'url', $this->file->getName() );
+ $obj = $wgMemc->get($key);
+ if ($obj) {
+ wfDebug("success!\n");
+ return $obj;
+ }
+ wfDebug("miss\n");
+ }
+ wfDebug("Get text tracks from remote api \n");
+ $query = $this->getTextPagesQuery();
+
+ // Error in getting timed text namespace return empty array;
+ if( $query === false ){
+ return array();
+ }
+ $data = $this->file->getRepo()->fetchImageQuery( $query );
+ $textTracks = $this->getTextTracksFromData( $data );
+ if ( $data && $this->file->repo->descriptionCacheExpiry > 0 ) {
+ $wgMemc->set( $key, $textTracks, $this->file->repo->descriptionCacheExpiry );
+ }
+ return $textTracks;
+ }
+
+ /**
+ * @return array
+ */
+ function getLocalTextSources(){
+ global $wgEnableLocalTimedText;
+ if ( $wgEnableLocalTimedText ) {
+ // Init $this->textTracks
+ $params = new FauxRequest( $this->getTextPagesQuery() );
+ $api = new ApiMain( $params );
+ $api->execute();
+ if ( defined( 'ApiResult::META_CONTENT' ) ) {
+ $data = $api->getResult()->getResultData( null, array( 'Strip' => 'all' ) );
+ } else {
+ $data = $api->getResultData();
+ }
+ wfDebug(print_r($data, true));
+ // Get the list of language Names
+ return $this->getTextTracksFromData( $data );
+ } else {
+ return array();
+ }
+ }
+
+ /**
+ * @return array|mixed
+ */
+ function getForeignDBTextSources(){
+ // Init $this->textTracks
+ $params = new FauxRequest( $this->getTextPagesQuery() );
+ $api = new ApiMain( $params );
+ $api->profileIn();
+ $query = new ApiQuery( $api, 'foo', 'bar' );
+ $query->profileIn();
+ $module = new ForeignApiQueryAllPages( $this->file->getRepo()->getSlaveDB(), $query, 'allpages' );
+ $module->profileIn();
+ $module->execute();
+ $module->profileOut();
+ $query->profileOut();
+ $api->profileOut();
+
+ if ( defined( 'ApiResult::META_CONTENT' ) ) {
+ $data = $module->getResult()->getResultData( null, array( 'Strip' => 'all' ) );
+ } else {
+ $data = $module->getResultData();
+ }
+ // Get the list of language Names
+ return $this->getTextTracksFromData( $data );
+ }
+
+ /**
+ * @param $data
+ * @return array
+ */
+ function getTextTracksFromData( $data ){
+ $textTracks = array();
+ $providerName = $this->file->repo->getName();
+ // commons is called shared in production. normalize it to wikimediacommons
+ if( $providerName == 'shared' ){
+ $providerName = 'wikimediacommons';
+ }
+ // Provider name should be the same as the interwiki map
+ // @@todo more testing with this:
+
+ $langNames = Language::fetchLanguageNames( null, 'mw' );
+ if( $data['query'] && $data['query']['allpages'] ){
+ foreach( $data['query']['allpages'] as $page ){
+ $subTitle = Title::newFromText( $page['title'] ) ;
+ $tileParts = explode( '.', $page['title'] );
+ if( count( $tileParts) >= 3 ){
+ $timedTextExtension = array_pop( $tileParts );
+ $languageKey = array_pop( $tileParts );
+ $contentType = $this->getContentType( $timedTextExtension );
+ } else {
+ continue;
+ }
+ // If there is no valid language continue:
+ if( !isset( $langNames[ $languageKey ] ) ){
+ continue;
+ }
+ $namespacePrefix = "TimedText:";
+ $textTracks[] = array(
+ 'kind' => 'subtitles',
+ 'data-mwtitle' => $namespacePrefix . $subTitle->getDBkey(),
+ 'data-mwprovider' => $providerName,
+ 'type' => $contentType,
+ // @todo Should eventually add special entry point and output proper WebVTT format:
+ // http://www.whatwg.org/specs/web-apps/current-work/webvtt.html
+ 'src' => $this->getFullURL( $page['title'], $contentType ),
+ 'srclang' => $languageKey,
+ 'data-dir' => Language::factory( $languageKey )->getDir(),
+ 'label' => wfMessage('timedmedia-subtitle-language',
+ $langNames[ $languageKey ],
+ $languageKey )->text()
+ );
+ }
+ }
+ return $textTracks;
+ }
+
+ function getContentType( $timedTextExtension ) {
+ if ( $timedTextExtension === 'srt' ) {
+ return 'text/x-srt';
+ } else if ( $timedTextExtension === 'vtt' ) {
+ return 'text/vtt';
+ }
+ return '';
+ }
+
+ function getFullURL( $pageTitle, $contentType ){
+ if( $this->file->isLocal() ) {
+ $subTitle = Title::newFromText( $pageTitle ) ;
+ return $subTitle->getFullURL( array(
+ 'action' => 'raw',
+ 'ctype' => $contentType
+ ));
+ //} elseif( $this->file->repo instanceof ForeignDBViaLBRepo ){
+ } else {
+ $query = 'title=' . wfUrlencode( $pageTitle ) . '&';
+ $query .= wfArrayToCgi( array(
+ 'action' => 'raw',
+ 'ctype' => $contentType
+ ) );
+ // Note: This will return false if scriptDirUrl is not set for repo.
+ return $this->file->repo->makeUrl( $query );
+ }
+ }
+}
diff --git a/extensions/TimedMediaHandler/handlers/WAVHandler/WAVHandler.php b/extensions/TimedMediaHandler/handlers/WAVHandler/WAVHandler.php
new file mode 100644
index 00000000..9fae12b8
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/WAVHandler/WAVHandler.php
@@ -0,0 +1,87 @@
+<?php
+/**
+ * WAV handler
+ */
+class WAVHandler extends ID3Handler {
+
+ /**
+ * @param $file File
+ * @return string
+ */
+ function getMetadataType( $file ) {
+ return 'wav';
+ }
+
+ /**
+ * @param $file File
+ * @return String
+ */
+ function getWebType( $file ) {
+ return 'audio/wav';
+ }
+
+ function verifyUpload( $filename ) {
+ $metadata = $this->getID3( $filename );
+
+ if(
+ isset( $metadata['audio'] )
+ && $metadata['audio']['dataformat'] == 'wav'
+ && ( $metadata['audio']['codec'] == 'Pulse Code Modulation (PCM)' || $metadata['audio']['codec'] == 'IEEE Float' )
+ ){
+ return Status::newGood();
+ }
+
+ return Status::newFatal( 'timedmedia-wav-pcm-required' );
+ }
+ /**
+ * @param $file File
+ * @return array|bool
+ */
+ function getStreamTypes( $file ) {
+ $streamTypes = array();
+ $metadata = $this->unpackMetadata( $file->getMetadata() );
+
+ if ( !$metadata || isset( $metadata['error'] ) ) {
+ return false;
+ }
+
+ if( isset( $metadata['audio'] ) && $metadata['audio']['dataformat'] == 'wav' ){
+ $streamTypes[] = 'WAV';
+ }
+
+ return $streamTypes;
+ }
+
+ /**
+ * @param $file File
+ * @return String
+ */
+ function getShortDesc( $file ) {
+ global $wgLang;
+
+ $streamTypes = $this->getStreamTypes( $file );
+ if ( !$streamTypes ) {
+ return parent::getShortDesc( $file );
+ }
+ return wfMessage( 'timedmedia-wav-short-audio',
+ $wgLang->formatTimePeriod( $this->getLength( $file ) ) )->text();
+ }
+
+ /**
+ * @param $file File
+ * @return String
+ */
+ function getLongDesc( $file ) {
+ global $wgLang;
+ $streamTypes = $this->getStreamTypes( $file );
+ if ( !$streamTypes ) {
+ return parent::getLongDesc( $file );
+ }
+ return wfMessage('timedmedia-wav-long-audio',
+ $wgLang->formatTimePeriod( $this->getLength($file) ),
+ $wgLang->formatBitrate( $this->getBitRate( $file ) )
+ )->text();
+
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/handlers/WebMHandler/WebMHandler.php b/extensions/TimedMediaHandler/handlers/WebMHandler/WebMHandler.php
new file mode 100644
index 00000000..ebdad0d1
--- /dev/null
+++ b/extensions/TimedMediaHandler/handlers/WebMHandler/WebMHandler.php
@@ -0,0 +1,175 @@
+<?php
+/**
+ * WebM handler
+ */
+class WebMHandler extends ID3Handler {
+
+ /**
+ * @param $path string
+ * @return array
+ */
+ protected function getID3( $path ) {
+ $id3 = parent::getID3( $path );
+ // Unset some parts of id3 that are too detailed and matroska specific:
+ unset( $id3['matroska'] );
+ return $id3;
+ }
+
+ /**
+ * Get the "media size"
+ * @param $file File
+ * @param $path string
+ * @param $metadata bool
+ * @return array|bool
+ */
+ function getImageSize( $file, $path, $metadata = false ) {
+ // Just return the size of the first video stream
+ if ( $metadata === false ) {
+ $metadata = $file->getMetadata();
+ }
+ $metadata = $this->unpackMetadata( $metadata );
+ if ( isset( $metadata['error'] ) ) {
+ return false;
+ }
+
+ $size = array( false, false );
+ // display_x/display_y is only set if DisplayUnit
+ // is pixels, otherwise display_aspect_ratio is set
+ if ( isset( $metadata['video']['display_x'] )
+ &&
+ isset( $metadata['video']['display_y'] )
+ ){
+ $size = array (
+ $metadata['video']['display_x'],
+ $metadata['video']['display_y']
+ );
+ }
+ elseif ( isset( $metadata['video']['resolution_x'] )
+ &&
+ isset( $metadata['video']['resolution_y'] )
+ ){
+ $size = array (
+ $metadata['video']['resolution_x'],
+ $metadata['video']['resolution_y']
+ );
+ if ( isset($metadata['video']['crop_top']) ) {
+ $size[1] -= $metadata['video']['crop_top'];
+ }
+ if ( isset($metadata['video']['crop_bottom']) ) {
+ $size[1] -= $metadata['video']['crop_bottom'];
+ }
+ if ( isset($metadata['video']['crop_left']) ) {
+ $size[0] -= $metadata['video']['crop_left'];
+ }
+ if ( isset($metadata['video']['crop_right']) ) {
+ $size[0] -= $metadata['video']['crop_right'];
+ }
+ }
+ if ( $size[0] && $size[1] && isset( $metadata['video']['display_aspect_ratio'] ) ) {
+ //for wide images (i.e. 16:9) take native height as base
+ if ( $metadata['video']['display_aspect_ratio'] >= 1 ) {
+ $size[0] = intval( $size[1] * $metadata['video']['display_aspect_ratio'] );
+ } else { //for tall images (i.e. 9:16) take width as base
+ $size[1] = intval( $size[0] / $metadata['video']['display_aspect_ratio'] );
+ }
+ }
+ return $size;
+ }
+
+ /**
+ * @param $file
+ * @return string
+ */
+ function getMetadataType( $file ) {
+ return 'webm';
+ }
+
+ /**
+ * @param $file File
+ * @return String
+ */
+ function getWebType( $file ) {
+ $baseType = ( $file->getWidth() == 0 && $file->getHeight() == 0 )? 'audio' : 'video';
+
+ $streams = $this->getStreamTypes( $file );
+ if ( !$streams ) {
+ return $baseType . '/webm';
+ }
+
+ $codecs = strtolower( implode( ', ', $streams ) );
+
+ return $baseType . '/webm; codecs="' . $codecs . '"';
+ }
+
+ /**
+ * @param $file File
+ * @return array|bool
+ */
+ function getStreamTypes( $file ) {
+ $streamTypes = array();
+ $metadata = $this->unpackMetadata( $file->getMetadata() );
+ if ( !$metadata || isset( $metadata['error'] ) ) {
+ return false;
+ }
+ // id3 gives 'V_VP8' for what we call VP8
+ if( isset( $metadata['video'] ) && $metadata['video']['dataformat'] == 'vp8' ){
+ $streamTypes[] = 'VP8';
+ } elseif( isset( $metadata['video'] ) &&
+ ( $metadata['video']['dataformat'] === 'vp9'
+ || $metadata['video']['dataformat'] === 'V_VP9'
+ ) ) {
+ // Currently getID3 calls it V_VP9. That will probably change to vp9
+ // once getID3 actually gets support for the codec.
+ $streamTypes[] = 'VP9';
+ }
+ if( isset( $metadata['audio'] ) && $metadata['audio']['dataformat'] == 'vorbis' ){
+ $streamTypes[] = 'Vorbis';
+ } elseif ( isset( $metadata['audio'] ) &&
+ ( $metadata['audio']['dataformat'] == 'opus'
+ || $metadata['audio']['dataformat'] == 'A_OPUS'
+ ) ) {
+ // Currently getID3 calls it A_OPUS. That will probably change to 'opus'
+ // once getID3 actually gets support for the codec.
+ $streamTypes[] = 'Opus';
+ }
+
+ return $streamTypes;
+ }
+
+ /**
+ * @param $file File
+ * @return String
+ */
+ function getShortDesc( $file ) {
+ global $wgLang;
+
+ $streamTypes = $this->getStreamTypes( $file );
+ if ( !$streamTypes ) {
+ return parent::getShortDesc( $file );
+ }
+ return wfMessage( 'timedmedia-webm-short-video', implode( '/', $streamTypes ),
+ $wgLang->formatTimePeriod( $this->getLength( $file ) ) )->text();
+ }
+
+ /**
+ * @param $file File
+ * @return String
+ */
+ function getLongDesc( $file ) {
+ global $wgLang;
+ $streamTypes = $this->getStreamTypes( $file );
+ if ( !$streamTypes ) {
+ return parent::getLongDesc( $file );
+ }
+ return wfMessage('timedmedia-webm-long-video',
+ implode( '/', $streamTypes ),
+ $wgLang->formatTimePeriod( $this->getLength($file) ),
+ $wgLang->formatBitrate( $this->getBitRate( $file ) )
+ )->numParams(
+ $file->getWidth(),
+ $file->getHeight()
+ )->text();
+
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/i18n/ady-cyrl.json b/extensions/TimedMediaHandler/i18n/ady-cyrl.json
new file mode 100644
index 00000000..a76e7faa
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ady-cyrl.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "GR44 Luc",
+ "TheRossatron"
+ ]
+ },
+ "timedmedia-no-player-js": "ŠšŃŠŃ‹Ń‚Ń„ŃŠ³ŃŠŃŠ³ŃŠŃƒ, Šµ уŠø Š±Ń€Š¾ŃƒŠ·ŠµŃ€Ń‹Š¼ Šø JavaScript Š³ŃŠŃŠŗIŠ¾ŃŠ°Š³ŃŠŃ, Šµ Š³ŃŠŃŠ»ŃŠŃŠ³ŃŠŃƒŠ°Š»ŃŠŃ тэрэŠ· тŠµŃ‚эŠæ.<br />\n<a href=\"$1\">ŠšŠ»ŠøŠæыр ŠŗъŠøŠæщэŠ½</a> Šµ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">Š³ŃŠŃŠ»ŃŠŃŠ³ŃŠŃƒŠ°Š»ŃŠŃ тŠµŠ±Š³ŃŠŃŃƒŃ†Š¾Š½</a> ŠæŠ»ŃŠŃŠŗIыщт, уŠø Š±Ń€Š¾ŃƒŠ·ŠµŃ€Ń‹Š¼ ущŠµŠæŠ»ŃŠŃ‹Š½ŃŃƒ.",
+ "timedmedia-source-file": "Š›ŃŠŠ°Šæсэу $1",
+ "timedmedia-source-audio-file-desc": "ŠžŃ€ŠøŠ³ŠøŠ½Š°Š» $1-фŠ°Š¹Š»Ń‹Ń€ ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/aeb-latn.json b/extensions/TimedMediaHandler/i18n/aeb-latn.json
new file mode 100644
index 00000000..65d57191
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/aeb-latn.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Csisc"
+ ]
+ },
+ "timedmedia-source-file": "$1 is-sūrs",
+ "timedmedia-source-audio-file-desc": "Ficyēy $1 aşlī ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/af.json b/extensions/TimedMediaHandler/i18n/af.json
new file mode 100644
index 00000000..7708e9ae
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/af.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Naudefj",
+ "SPQRobin",
+ "Arnobarnard"
+ ]
+ },
+ "timedmedia-desc": "Hanteer Ogg Theora- en Vorbis-lĆŖers met 'n JavaScript-mediaspeler",
+ "timedmedia-ogg-short-audio": "Ogg $1 klanklĆŖer, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 video lĆŖer, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 medialĆŖer, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 klanklĆŖer, lengte $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 videolĆŖer, lengte $2, $4Ɨ$5 pixels, $3",
+ "timedmedia-ogg-long-general": "Ogg medialĆŖer, lengte $2, $3",
+ "timedmedia-ogg-long-error": "Ongeldige Ogg-lĆŖer: $1",
+ "timedmedia-no-player-js": "Jammer, u blaaier het of JavaScript gedeaktiveer of het nie enige ondersteunde speler nie.<br />\nU kan <a href=\"$1\">die knipsel aflaai</a> of <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">'n speler aflaai</a> om die knipsel te speel in u blaaier.",
+ "timedmedia-more": "Meerā€¦",
+ "timedmedia-dismiss": "Sluit",
+ "timedmedia-download": "Laai lĆŖer af",
+ "timedmedia-desc-link": "Aangaande die lĆŖer",
+ "timedmedia-minutes": "{{PLURAL:$1|$1 minuut|$1 minute}}",
+ "timedmedia-source-file": "Bron van $1",
+ "timedmedia-source-audio-file-desc": "Oorspronklike $1-lĆŖer ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/akz.json b/extensions/TimedMediaHandler/i18n/akz.json
new file mode 100644
index 00000000..641c0b9f
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/akz.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ulohnanne"
+ ]
+ },
+ "timedmedia-more": "MaatĆ asasi..."
+}
diff --git a/extensions/TimedMediaHandler/i18n/aln.json b/extensions/TimedMediaHandler/i18n/aln.json
new file mode 100644
index 00000000..67645c86
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/aln.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mdupont"
+ ]
+ },
+ "timedmedia-desc": "Mbajtƫs pƫr mediat nƫ kohƫn e duhur (video, audio, timedText) me transcoding tƫ ZQM Theora / Vorbis",
+ "timedmedia-ogg-short-audio": "Ogg tingull $1 fotografi, $2",
+ "timedmedia-ogg-short-video": "video file Ogg $1, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 media file, $2",
+ "timedmedia-ogg-long-audio": "ZQM file $1 shƫndoshƫ, gjatƫ $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 video file, gjatĆ« $2, $4 Ɨ $5 pixels, $3",
+ "timedmedia-ogg-long-multiplexed": "ZQM multiplexed audio / video file, $1, gjatĆ« $2, $4 Ɨ $5 pixels, $3 e pĆ«rgjithshme",
+ "timedmedia-ogg-long-general": "Ogg media file, gjatƫ $2, $3",
+ "timedmedia-ogg-long-error": "E pavlefshme Ogg file: $1",
+ "timedmedia-no-player-js": "Na vjen keq, browser-i juaj ose ka JavaScript paaftƫ ose nuk ka asnjƫ lojtar tƫ mbƫshtetur. <br /> Ju mund tƫ <a href=\"$1\">shkarkoni clip</a> ose <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">shkarkoni njƫ lojtar</a> pƫr tƫ luajtur clip nƫ shfletuesin tuaj.",
+ "timedmedia-more": "Mƫ shumƫ ...",
+ "timedmedia-dismiss": "Afƫr",
+ "timedmedia-download": "Shkarko file",
+ "timedmedia-desc-link": "Pƫr kƫtƫ fotografi",
+ "timedmedia-oggThumb-version": "OggHandler kƫrkon version oggThumb $1 ose mƫ vonƫ.",
+ "timedmedia-oggThumb-failed": "oggThumb dƫshtuar pƫr tƫ krijuar tablo."
+}
diff --git a/extensions/TimedMediaHandler/i18n/an.json b/extensions/TimedMediaHandler/i18n/an.json
new file mode 100644
index 00000000..8bee5529
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/an.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "Juanpabl"
+ ]
+ },
+ "timedmedia-desc": "Maneyador de fichers sincronizatos (vidio, son y texto sincronizato) con transcodificaciĆ³n Ogg Theora/Vorbis",
+ "timedmedia-ogg-short-audio": "Fichero de son ogg $1, $2",
+ "timedmedia-ogg-short-video": "Fichero de vidio ogg $1, $2",
+ "timedmedia-ogg-short-general": "Fichero multimedia ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Fichero de son ogg $1, durada $2, $3",
+ "timedmedia-ogg-long-video": "Fichero de vidio ogg $1, durada $2, $4Ɨ$5 pƭxels, $3",
+ "timedmedia-ogg-long-multiplexed": "fichero ogg multiplexato audio/vidio, $1, durada $2, $4Ɨ$5 pƭxels, $3 total",
+ "timedmedia-ogg-long-general": "fichero ogg multimedia durada $2, $3",
+ "timedmedia-ogg-long-error": "Fichero ogg no conforme: $1",
+ "timedmedia-more": "MĆ”sā€¦",
+ "timedmedia-dismiss": "Zarrar",
+ "timedmedia-download": "Escargar fichero",
+ "timedmedia-desc-link": "InformaciĆ³n sobre este fichero"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ang.json b/extensions/TimedMediaHandler/i18n/ang.json
new file mode 100644
index 00000000..077e8718
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ang.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gott wisst"
+ ]
+ },
+ "timedmedia-source-file": "$1 fruma",
+ "timedmedia-source-audio-file-desc": "Frumlicu $1 ymele ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ar.json b/extensions/TimedMediaHandler/i18n/ar.json
new file mode 100644
index 00000000..bcb7c11c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ar.json
@@ -0,0 +1,67 @@
+{
+ "@metadata": {
+ "authors": [
+ "Alnokta",
+ "Asaifm",
+ "Meno25",
+ "OsamaK",
+ "Ų±ŁˆŲ®Łˆ",
+ "Abanima"
+ ]
+ },
+ "timedmedia-desc": "Ł…ŲÆŲ§ŁˆŁ„ Ł„Ł„ŲµŁˆŲŖŁŠŲ§ŲŖ ŁˆŲ§Ł„Ł…Ų±Ų¦ŁŠŲ§ŲŖ ŁˆŲ§Ł„Ł†ŲµŁˆŲµ Ų§Ł„Ł…Ų¤Ł‚ŲŖŲ© ŁˆŲ§Ł„Ų°ŁŠ Ł„ŲÆŁŠŁ‡ Ų§Ł„Ł‚ŲÆŲ±Ų© Ų¹Ł„Ł‰ ŲÆŲ¹Ł… Ł…Ł„ŁŲ§ŲŖ ŲØŲµŁŠŲŗŲ© WebM ŁˆOgg Theora ŁˆVorbis Łˆsrt",
+ "timedmedia-ogg-short-audio": "Ogg $1 Ł…Ł„Ł ŲµŁˆŲŖŲŒ $2",
+ "timedmedia-ogg-short-video": "Ogg $1 Ł…Ł„Ł ŁŁŠŲÆŁŠŁˆŲŒ $2",
+ "timedmedia-ogg-short-general": "Ogg $1 Ł…Ł„Ł Ł…ŁŠŲÆŁŠŲ§ŲŒ $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 Ł…Ł„Ł ŲµŁˆŲŖŲŒ Ų§Ł„Ų·ŁˆŁ„ $2ŲŒ $3",
+ "timedmedia-ogg-long-video": "Ogg $1 Ł…Ł„Ł ŁŁŠŲÆŁŠŁˆŲŒ Ų§Ł„Ų·ŁˆŁ„ $2ŲŒ $4Ɨ$5 ŲØŁƒŲ³Ł„ŲŒ $3",
+ "timedmedia-ogg-long-multiplexed": "Ł…Ł„Ł Ogg Ł…Ų§Ł„ŲŖŁŠ ŲØŁ„ŁŠŁƒŲ³ŲÆ Ų£ŁˆŲÆŁŠŁˆ/ŁŁŠŲÆŁŠŁˆŲŒ $1ŲŒ Ų§Ł„Ų·ŁˆŁ„ $2ŲŒ $4Ɨ$5 ŲØŁƒŲ³Ł„ŲŒ $3 Ų„Ų¬Ł…Ų§Ł„ŁŠ",
+ "timedmedia-ogg-long-general": "Ł…Ł„Ł Ł…ŁŠŲÆŁŠŲ§ OggŲŒ Ų§Ł„Ų·ŁˆŁ„ $2ŲŒ $3",
+ "timedmedia-ogg-long-error": "Ł…Ł„Ł Ogg ŲŗŁŠŲ± ŲµŲ­ŁŠŲ­: $1",
+ "timedmedia-webm-short-video": "Ł†Ų³Ł‚ WebMŲŒ $1 Ł…Ł„Ł ŁŁŠŲÆŁŠŁˆ $2",
+ "timedmedia-webm-long-video": "Ł…Ł„Ł ŲµŁˆŲŖ/ŁŁŠŲÆŁŠŁˆ ŲØŁ†Ų³Ł‚ WebM , $1, Ų§Ł„Ų·ŁˆŁ„ $2, $4Ɨ$5 ŲØŁƒŲ³Ł„ŲŒ $3 Ų„Ų¬Ł…Ų§Ł„Ų§",
+ "timedmedia-no-player-js": "Ų¹Ų°Ų±Ų§ŲŒ Ł…ŲŖŲµŁŲ­Łƒ Ų„Ł…Ų§ Ų§Ł†Ł‡ Ł„Ų§ ŁŠŲÆŲ¹Ł… Ų§Ł„Ų¬Ų§ŁŲ§ Ų³ŁƒŲ±ŁŠŲØŲŖ Ų£Łˆ Ų§Ł†Ł‡Ų§ Ł…Ų¹Ų·Ł„Ų©.<br />\nŲŖŲ³ŲŖŲ·ŁŠŲ¹ <a href=\"$1\">ŲŖŲ­Ł…ŁŠŁ„ Ų§Ł„Ł…Ł‚Ų·Ų¹</a> Ų£Łˆ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ŲŖŲ­Ł…ŁŠŁ„ Ł…Ų“ŲŗŁ„</a> ŁŠŲ³ŲŖŲ·ŁŠŲ¹ ŲŖŲ“ŲŗŁŠŁ„ Ų§Ł„Ł…Ł‚Ų·Ų¹ Ų¹Ł„Ł‰ Ł…ŲŖŲµŁŲ­Łƒ.",
+ "timedmedia-more": "Ų§Ł„Ł…Ų²ŁŠŲÆ...",
+ "timedmedia-dismiss": "Ų£ŲŗŁ„Ł‚",
+ "timedmedia-download": "Ł†Ų²Ł„ Ų§Ł„Ł…Ł„Ł",
+ "timedmedia-play-media": "ŲŖŲ“ŲŗŁŠŁ„ Ų§Ł„ŁˆŲ³Ų§Ų¦Ų·",
+ "timedmedia-desc-link": "Ų¹Ł† Ł‡Ų°Ų§ Ų§Ł„Ł…Ł„Ł",
+ "timedmedia-status": "Ų§Ł„Ų­Ų§Ł„Ų©",
+ "timedmedia-status-unknown": "Ų­Ų§Ł„Ų© ŲŗŁŠŲ± Ł…Ų¹Ų±ŁˆŁŲ©",
+ "timedmedia-actions": "Ų§Ł„Ų„Ų¬Ų±Ų§Ų”Ų§ŲŖ",
+ "timedmedia-direct-link": "ŲŖŲ­Ł…ŁŠŁ„ Ų§Ł„Ł…Ų“ŲŖŁ‚",
+ "timedmedia-not-ready": "ŲŗŁŠŲ± Ų¬Ų§Ł‡Ų²",
+ "timedmedia-percent-done": "ŁˆŲµŁ„ Ł„Ł†Ų³ŲØŲ© $1% Ų§Ł†ŲŖŁ‡Ł‰",
+ "timedmedia-in-job-queue": "ŲŖŁ…ŲŖ Ų§Ł„Ų„Ų¶Ų§ŁŲ© Ų„Ł„Ł‰ Ų·Ų§ŲØŁˆŲ± Ų§Ł„Ł…Ł‡Ų§Ł… Ł…Ł†Ų° $1",
+ "timedmedia-days": "{{PLURAL:$1|ŁŠŁˆŁ… ŁˆŲ§Ų­ŲÆ|ŁŠŁˆŁ…ŁŠŁ†|$1 Ų£ŁŠŲ§Ł…|$1 ŁŠŁˆŁ…Ų§Ł‹|$1 ŁŠŁˆŁ…}}",
+ "timedmedia-hours": "{{PLURAL:$1|Ų³Ų§Ų¹Ų© ŁˆŲ§Ų­ŲÆŲ©|Ų³Ų§Ų¹ŲŖŁŠŁ†|$1 Ų³Ų§Ų¹Ų§ŲŖ|$1 Ų³Ų§Ų¹Ų©}}",
+ "timedmedia-minutes": "{{PLURAL:$1|ŲÆŁ‚ŁŠŁ‚Ų© ŁˆŲ§Ų­ŲÆŲ©|ŲÆŁ‚ŁŠŁ‚ŲŖŁŠŁ†|$1 ŲÆŁ‚Ų§Ų¦Ł‚|$1 ŲÆŁ‚ŁŠŁ‚Ų©}}",
+ "timedmedia-seconds": "{{PLURAL:$1|Ų«Ų§Ł†ŁŠŲ© ŁˆŲ§Ų­ŲÆŲ©|Ų«Ų§Ł†ŁŠŲŖŁŠŁ†|$1 Ų«ŁˆŲ§Ł†|$1 Ų«Ų§Ł†ŁŠŲ©}}",
+ "timedmedia-ogg": "Ų£Łˆ Ų¬ŁŠ Ų¬ŁŠ",
+ "timedmedia-source-file": "$1 Ł…ŲµŲÆŲ±",
+ "timedmedia-source-file-desc": "Ų§Ł„Ų£ŲµŁ„ Ł…Ł„Ł $1ŲŒ $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Ų§Ł„Ł…Ł„Ł $1 Ų§Ł„Ų£ŲµŁ„ŁŠ ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Ų§Ł†Ų®ŁŲ§Ų¶ Ų¹Ų±Ų¶ Ų§Ł„Ł†Ų·Ų§Ł‚ Ų§Ł„ŲŖŲ±ŲÆŲÆŁŠ Ų£ŁˆŲ¬ ŁŁŠŲÆŁŠŁˆ (160P)",
+ "timedmedia-derivative-desc-720p.ogv": "ŲŖŲ­Ł…ŁŠŁ„ Ų£ŁˆŲ¬ ŁŁŠŲÆŁŠŁˆ ŲØŲ¬ŁˆŲÆŲ© Ų¹Ų§Ł„ŁŠŲ© (720P)",
+ "timedmedia-subtitle-new": "Ų£Ł†Ų“Ų¦ ŲŖŲ±Ų¬Ł…Ų© Ų¬ŲÆŁŠŲÆŲ© Ų£Łˆ Ų­Ų±Ų± ŲŖŲ±Ų¬Ł…Ų© Ł…ŁˆŲ¬ŁˆŲÆŲ©",
+ "timedmedia-subtitle-new-desc": "Ł‚Ł… ŲØŲ„Ų®ŲŖŁŠŲ§Ų± Ų§Ł„Ł„ŲŗŲ© ŁˆŲ„Ų¶ŲŗŲ· Ų¹Ł„Ł‰ Ų²Ų± '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Ų§Ų°Ł‡ŲØ",
+ "timedmedia-subtitle-language": "$1 ($2) ŲŖŲ±Ų¬Ł…Ų§ŲŖ",
+ "timedmedia-subtitle-no-video": "Ł„Ų§ ŁŠŁˆŲ¬ŲÆ ŁŁŠŲÆŁŠŁˆ Ł…Ł‚ŲŖŲ±Ł† ŲØŲµŁŲ­Ų© ŲŖŲ±Ų¬Ł…Ų© Ų£Łˆ Ł†ŲµŁˆŲµ Ų§Ł„ŁŁŠŲÆŁŠŁˆ Ų§Ł„Ų­Ų§Ł„ŁŠŲ©.",
+ "timedmedia-subtitle-no-subtitles": "Ł„Ų§ ŲŖŁˆŲ¬ŲÆ Ł†ŲµŁˆŲµ Ų£Łˆ ŲŖŲ±Ų¬Ł…Ų§ŲŖ ŁŁŠ $1 Ł„Ł‡Ų°Ų§ Ų§Ł„ŁŁŠŲÆŁŠŁˆŲŒ ŁŠŁ…ŁƒŁ†Łƒ [{{fullurl:{{FULLPAGENAME}}|action=edit}} ŲŖŲ¹ŲÆŁŠŁ„ Ł‡Ų°Ł‡ Ų§Ł„ŲµŁŲ­Ų©] ŁˆŲ„Ų¶Ų§ŁŲŖŁ‡Ł….",
+ "timedmedia-subtitle-remote-link": "ŁŠŁ…ŁƒŁ†Łƒ [$1 Ł…Ų·Ų§Ł„Ų¹Ų© ŲµŁŲ­Ų© Ų§Ł„ŁˆŲµŁ] Ł„Ł‡Ų°Ų§ Ų§Ł„Ł…Ł„Ł Ų¹Ł„Ł‰ $2",
+ "timedmediahandler": "Ł…Ų¹Ų§Ł„Ų¬ Ų§Ł„Ł…ŁŠŲÆŁŠŲ§ Ų§Ł„Ų²Ł…Ł†ŁŠŲ©",
+ "timedmedia-videos": "{{PLURAL:$1|Ł…Ł„Ł ŁŁŠŲÆŁŠŁˆ ŁˆŲ§Ų­ŲÆ|Ł…Ł„ŁŲ§ ŁŁŠŲÆŁŠŁˆ|$1 Ł…Ł„ŁŲ§ŲŖ ŁŁŠŲÆŁŠŁˆ|$1 Ł…Ł„Ł ŁŁŠŲÆŁŠŁˆ}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|Ł…Ł„Ł|Ł…Ł„ŁŲ§|$1 Ł…Ł„ŁŲ§ŲŖ|$1 Ł…Ł„Ł}} ŁŁŠŲÆŁŠŁˆ Ogg",
+ "timedmedia-webm-videos": "{{PLURAL:$1|Ł…Ł„Ł|Ł…Ł„ŁŲ§|$1 Ł…Ł„ŁŲ§ŲŖ|$1 Ł…Ł„Ł}} ŁŁŠŲÆŁŠŁˆ WebM",
+ "timedmedia-file": "Ł…Ł„Ł",
+ "timedmedia-audios": "{{PLURAL:$1|Ł…Ł„Ł ŲµŁˆŲŖŁŠ ŁˆŲ§Ų­ŲÆ|$1 Ł…Ł„Ł ŲµŁˆŲŖŁŠ}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|Ł…Ł„Ł ŲµŁˆŲŖŁŠ ŁˆŲ§Ų­ŲÆ ŲØŲµŁŠŲŗŲ© Ų£ŁˆŲŗ|$1 Ł…Ł„Ł ŲµŁˆŲŖŁŠ ŲØŲµŁŠŲŗŲ© Ų£ŁˆŲŗ}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|Ł…Ł„Ł|Ł…Ł„ŁŲ§|$1 Ł…Ł„ŁŲ§ŲŖ|$1 Ł…Ł„Ł}} ŲµŁˆŲŖŁŠ FLAC",
+ "timedmedia-wav-audios": "{{PLURAL:$1|Ł…Ł„Ł|Ł…Ł„ŁŲ§|$1 Ł…Ł„ŁŲ§ŲŖ|$1 Ł…Ł„Ł}} ŲµŁˆŲŖŁŠ WAV",
+ "orphanedtimedtext": "ŲµŁŲ­Ų§ŲŖ TimedText ŁŠŲŖŁŠŁ…Ų©",
+ "orphanedtimedtext-summary": "Ł‚Ų§Ų¦Ł…Ų© ŲØŲµŁŲ­Ų§ŲŖ [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] Ų§Ł„ŲŖŁŠ Ł„ŁŠŲ³ Ł„ŲÆŁŠŁ‡Ų§ Ł…Ł„Ł Ł…ŁˆŲ§ŁŁ‚.",
+ "orphanedtimedtext-unsupported": "Ł‡Ų°Ł‡ Ų§Ł„ŲµŁŲ­Ų© Ų§Ł„Ų®Ų§ŲµŲ© Ł„Ų§ ŲŖŲÆŲ¹Ł…Ł‡Ų§ Ų„Ł„Ų§ Ł‚ŁˆŲ§Ų¹ŲÆ ŲØŁŠŲ§Ł†Ų§ŲŖ MySQL",
+ "orphanedtimedtext-notimedtext": "TimedText ŲŗŁŠŲ± Ł…ŁŲ¹Ł„ Ų¹Ł„Ł‰ Ł‡Ų°Ų§ Ų§Ł„ŁˆŁŠŁƒŁŠ",
+ "apihelp-transcodereset-param-title": "Ų¹Ł†ŁˆŲ§Ł† Ł…Ł„Ł Ų§Ł„Ł…ŁŠŲÆŁŠŲ§."
+}
diff --git a/extensions/TimedMediaHandler/i18n/arc.json b/extensions/TimedMediaHandler/i18n/arc.json
new file mode 100644
index 00000000..7f2df877
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/arc.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Basharh"
+ ]
+ },
+ "timedmedia-more": "ܝܬܝÜŖā€¦"
+}
diff --git a/extensions/TimedMediaHandler/i18n/arq.json b/extensions/TimedMediaHandler/i18n/arq.json
new file mode 100644
index 00000000..a4b24de3
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/arq.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Oldstoneage"
+ ]
+ },
+ "timedmedia-no-player-js": "Ų§Ų¹ŲÆŁŲ±Ł†Ų§ŲŒ Ų§Ł„ŁŁ„Ł‘Ų§Łƒ ŁŁŠŁ‡ JavaScript Ł…Ų­ŲØŁ‘Ų³ ŁˆŁ„Ų§ Ł…Ų§ ŁŁŠŁ‡ Ų­ŲŖŲ§ Ł‚Ų±Ł‘Ų§ŁŠ Ł…ŁˆŲ§Ł„Ł….<br />\nŲŖŁ†Ų¬Ł… <a href=\"$1\">ŲŖŲŖŁŠŁ„ŁŠŲ“Ų§Ų±Ų¬ŁŠ Ų§Ł„ŁŁŠŲÆŁŠŁˆ</a> ŁˆŁ„Ų§ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">Ł†Ų²Ł‘Ł„ Ų¹Ł†ŲÆŁƒ Ł‚Ų±Ł‘Ų§ŁŠ ŁŠŁƒŁˆŁ† Ł…ŁˆŲ§Ł„Ł…</a> ŲØŲ§Ų“ ŲŖŁŁˆŁ‘ŲŖ Ų§Ł„ŁŁŠŲÆŁŠŁˆ ŁŁ„ ŁŁ„Ł‘Ų§Łƒ ŲŖŲ§Ų¹Łƒ.",
+ "timedmedia-source-file": "$1 Ł…ŲµŲÆŲ±",
+ "timedmedia-source-audio-file-desc": "ŁŁŠŲ“ŁŠ $1 Ų£ŲµŁ„ŁŠ ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/arz.json b/extensions/TimedMediaHandler/i18n/arz.json
new file mode 100644
index 00000000..db3b7f88
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/arz.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ghaly",
+ "Meno25",
+ "Ramsis II"
+ ]
+ },
+ "timedmedia-desc": "Ł…ŲŖŲ­ŁƒŁ… Ł„Ł…Ł„ŁŲ§ŲŖ Ų£Łˆ Ų¬Ł‰ Ų¬Ł‰ Ų«ŁŠŁˆŲ±Ų§ Łˆ ŁŁˆŲ±ŲØŁŠŲ³ŲŒ Ł…Ų¹ ŲØŁ„Ų§ŁŠŲ± Ų¬Ų§ŁŲ§Ų³ŁƒŲ±ŁŠŲØŲŖ",
+ "timedmedia-ogg-short-audio": "Ogg $1 Ł…Ł„Ł ŲµŁˆŲŖŲŒ $2",
+ "timedmedia-ogg-short-video": "Ogg $1 Ł…Ł„Ł ŁŁŠŲÆŁŠŁˆ, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 Ł…Ł„Ł Ł…ŁŠŲÆŁŠŲ§ŲŒ $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 Ł…Ł„Ł ŲµŁˆŲŖŲŒ Ų§Ł„Ų·ŁˆŁ„ $2ŲŒ $3",
+ "timedmedia-ogg-long-video": "Ogg $1 Ł…Ł„Ł ŁŁŠŲÆŁŠŁˆŲŒ Ų§Ł„Ų·ŁˆŁ„ $2ŲŒ $4Ɨ$5 ŲØŁƒŲ³Ł„ŲŒ $3",
+ "timedmedia-ogg-long-multiplexed": "Ł…Ł„Ł Ogg Ł…Ų§Ł„ŲŖŁ‰ ŲØŁ„ŁŠŁƒŲ³ŲÆ Ų£ŁˆŲÆŁŠŁˆ/ŁŁŠŲÆŁŠŁˆŲŒ $1ŲŒ Ų§Ł„Ų·ŁˆŁ„ $2ŲŒ $4Ɨ$5 ŲØŁƒŲ³Ł„ŲŒ $3 Ų„Ų¬Ł…Ų§Ł„ŁŠ",
+ "timedmedia-ogg-long-general": "Ł…Ł„Ł Ł…ŁŠŲÆŁŠŲ§ OggŲŒ Ų§Ł„Ų·ŁˆŁ„ $2ŲŒ $3",
+ "timedmedia-ogg-long-error": "Ł…Ł„Ł ogg Ł…Ų“ ŲµŲ­ŁŠŲ­: $1",
+ "timedmedia-more": "Ų£ŁƒŲŖŲ±...",
+ "timedmedia-dismiss": "Ų§Ł‚ŁŁ„",
+ "timedmedia-download": "Ł†Ų²Ł„ Ų§Ł„Ł…Ł„Ł",
+ "timedmedia-desc-link": "Ų¹Ł† Ų§Ł„Ł…Ł„Ł ŲÆŲ§",
+ "timedmedia-source-file": "$1 Ł…ŲµŲÆŲ±",
+ "timedmedia-source-audio-file-desc": "Ų§Ł„Ł…Ł„Ł $1 Ų§Ł„Ų£ŲµŁ„ ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/as.json b/extensions/TimedMediaHandler/i18n/as.json
new file mode 100644
index 00000000..519fccc6
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/as.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "IKHazarika"
+ ]
+ },
+ "timedmedia-no-player-js": "ą¦¦ą§ą¦ƒą¦–ą¦æą¦¤, ą¦†ą¦Ŗą§ą¦Øą¦¾ą§° ą¦¬ą§ą§°ą¦¾ą¦‡ą¦œą¦¾ą§°ą¦¤ ą¦Øą¦¾ą¦‡ą¦¬ą¦¾ ą¦œą¦¾ą¦­ą¦¾-ą¦øą§ą¦•ą§ą§°ą¦æą¦Ŗą§ą¦Ÿ ą¦Øą¦æą¦·ą§ą¦•ą§ą§°ą¦æą¦Æą¦¼ ą¦•ą§°ą¦¾ ą¦¹ą§ˆ ą¦†ą¦›ą§‡ ą¦…ą¦„ą¦¬ą¦¾ ą¦•ą§‹ą¦Øą§‹ ą¦øą¦®ą§°ą§ą¦„ą¦æą¦¤ ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą§° ą¦Øą¦¾ą¦‡ą„¤ </br>\ną¦†ą¦Ŗą§ą¦Øą¦¾ą§° ą¦¬ą§ą§°ą¦¾ą¦‰ą¦œą¦¾ą§°ą¦¤ ą¦•ą§ą¦²ą¦æą¦Ŗą¦Ÿą§‹ ą¦Ŗą§ą¦²ą§‡' ą¦•ą§°ą¦æą¦¬ą¦²ą§ˆ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ą¦Ŗą§ą¦²ą§‡'ą¦Æą¦¼ą¦¾ą§° ą¦ą¦Ÿą¦¾ ą¦”ą¦¾ą¦‰ą¦Øą¦²'ą¦” ą¦•ą§°ą¦•</a> ą¦…ą¦„ą¦¬ą¦¾ <a href=\"$1\">ą¦•ą§ą¦²ą¦æą¦Ŗą¦Ÿą§‹ ą¦”ą¦¾ą¦‰ą¦Øą¦²'ą¦” ą¦•ą§°ą¦•</a> ą„¤",
+ "timedmedia-source-file": "$1 ą¦‰ą§Žą¦ø",
+ "timedmedia-source-audio-file-desc": "ą¦Ŗą§ą§°ą¦•ą§ƒą¦¤ $1 ą¦«ą¦¾ą¦‡ą¦² ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ast.json b/extensions/TimedMediaHandler/i18n/ast.json
new file mode 100644
index 00000000..2ff3d0af
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ast.json
@@ -0,0 +1,122 @@
+{
+ "@metadata": {
+ "authors": [
+ "Esbardu",
+ "Xuacu"
+ ]
+ },
+ "timedmedia-desc": "Remanador de sonƭu, videu y testu cronometrƔu, con sofitu pa los formatos WebM, Ogg Theora, Vorbis y srt",
+ "timedmedia-ogg-short-audio": "Archivu de sonĆ­u ogg $1, $2",
+ "timedmedia-ogg-short-video": "Archivu de videu ogg $1, $2",
+ "timedmedia-ogg-short-general": "Archivu multimedia ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Archivu de sonĆ­u ogg $1, llonxitĆŗ $2, $3",
+ "timedmedia-ogg-long-video": "Archivu de videu ogg $1, llonxitĆŗ $2, $4Ɨ$5 pĆ­xeles, $3",
+ "timedmedia-ogg-long-multiplexed": "Ficheru de sonĆ­u/videu ogg multiplexĆ”u, $1, llonxitĆŗ $2, $4Ɨ$5 pĆ­xeles, $3",
+ "timedmedia-ogg-long-general": "Archivu multimedia ogg, llonxitĆŗ $2, $3",
+ "timedmedia-ogg-long-error": "Ficheru Ogg invƔlidu: $1",
+ "timedmedia-ogg-long-no-streams": "Ficheru multimedia Ogg. AtenciĆ³n: Nun se reconociĆ³ nengĆŗn codec de los usaos nesti ficheru.",
+ "timedmedia-webm-short-video": "Ficheru de videu WebM $1, $2",
+ "timedmedia-webm-long-video": "Ficheru de sonĆ­u/videu WebM, $1, llonxitĆŗ $2, $4 Ɨ $5 pixels, $3 total",
+ "timedmedia-flac-short-audio": "Ficheru de sonĆ­u FLAC, $1",
+ "timedmedia-flac-long-audio": "Ficheru de sonĆ­u FLAC, duraciĆ³n $1, $2 total",
+ "timedmedia-wav-short-audio": "Ficheru de sonĆ­u WAV, $1",
+ "timedmedia-wav-long-audio": "Ficheru de sonĆ­u WAV, duraciĆ³n $1, $2 total",
+ "timedmedia-wav-pcm-required": "NamƔi pue xubir WAV tipu PCM (Pulse Code Modulation).",
+ "timedmedia-mp4-short-video": "Archivu de videu MP4 $1, $2",
+ "timedmedia-mp4-long-video": "Ficheru de sonĆ­u/videu MP4, $1, llonxitĆŗ $2, $4 Ɨ $5 pixels, $3 total",
+ "timedmedia-no-player-js": "Sentimoslo, o'l to navegador tien desactivƔu JavaScript o nun tienes un reproductor compatible.<br />\nPues <a href=\"$1\">descargar el clip</a> o <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">descargar un reproductor</a> pa reproducir el clip nel to navegador.",
+ "timedmedia-more": "MƔs...",
+ "timedmedia-dismiss": "Zarrar",
+ "timedmedia-download": "Descargar archivu",
+ "timedmedia-play-media": "Reproducir el mediu",
+ "timedmedia-desc-link": "Tocante a esti archivu",
+ "timedmedia-oggThumb-version": "OggHandler requier oggThumb version $1 o mayor.",
+ "timedmedia-oggThumb-failed": "oggThumb nun pudo crear la miniatura.",
+ "timedmedia-status-header": "EstĆ”u de trescodificaciĆ³n",
+ "timedmedia-update-status": "Anovar l'estĆ”u de trescodificaciĆ³n",
+ "timedmedia-status": "EstƔu",
+ "timedmedia-status-unknown": "EstƔu desconocƭu",
+ "timedmedia-transcodebitrate": "Tasa de bits",
+ "timedmedia-transcodeduration": "Tiempu de codificaciĆ³n",
+ "timedmedia-transcodeinfo": "Formatu",
+ "timedmedia-actions": "Aiciones",
+ "timedmedia-direct-link": "Descargar",
+ "timedmedia-not-ready": "Nun ta preparƔu",
+ "timedmedia-completed-on": "Completada a les $1",
+ "timedmedia-error-on": "Error a les $1",
+ "timedmedia-started-transcode": "PrincipiĆ³ hai $1. $2",
+ "timedmedia-percent-done": "Fecho alredor del $1%",
+ "timedmedia-in-job-queue": "AmestƔu a la cola de trabayos hai $1",
+ "timedmedia-unknown-target-size": "TamaƱu del destƭn desconocƭu; $1 codificƔu",
+ "timedmedia-days": "{{PLURAL:$1|1 dĆ­a|$1 dĆ­es}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 hora|$1 hores}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minutu|$1 minutos}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 segundu|$1 segundos}}",
+ "timedmedia-reset": "Reaniciar la trescodificaciĆ³n",
+ "timedmedia-reset-confirm": "Al reaniciar esta trescodificaciĆ³n desaniciarĆ” tolos ficheros esistentes (si los hai), y volverĆ” a amestar la trescodificaciĆ³n a la cola de trabayos. LlevarĆ” un tiempu volver a trescodificar.<br /><br />\nĀæTa seguru de que quier siguir?",
+ "timedmedia-reset-error": "Error al reaniciar el trabayu de trescodificaciĆ³n.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Fonte $1",
+ "timedmedia-source-file-desc": "Ficheru $1 orixinal, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Ficheru $1 orixinal ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Videu Ogg d'anchu de banda baxu (160P)",
+ "timedmedia-derivative-desc-240p.ogv": "Videu Ogg tresmitible pela web (240P)",
+ "timedmedia-derivative-desc-360p.ogv": "Videu Ogg tresmitible pela web (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Videu Ogg tresmitible pela web (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Videu Ogg descargable d'alta calida (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "Videu Ogg descargable'n Full HD (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "Videu WebM tresmitible pela web (160P)",
+ "timedmedia-derivative-desc-360p.webm": "Videu WebM tresmitible pela web (360P)",
+ "timedmedia-derivative-desc-480p.webm": "Videu WebM tresmitible pela web (480P)",
+ "timedmedia-derivative-desc-720p.webm": "Videu WebM descargable d'alta calida (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "WebM descargable'n Full HD (1080P)",
+ "timedmedia-derivative-desc-2160p.webm": "WebM descargable'n Full 4K (2160P)",
+ "timedmedia-derivative-desc-360p.vp9.webm": "WebM VP9 tresmitible pela web (360P)",
+ "timedmedia-derivative-desc-480p.vp9.webm": "WebM VP9 tresmitible pela web (480P)",
+ "timedmedia-derivative-desc-720p.vp9.webm": "WebM VP9 tresmitible'n HD (720P)",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "WebM VP9 tresmitible'n Full HD (1080P)",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "WebM VP9 tresmitible'n Full 4K (2160P)",
+ "timedmedia-derivative-desc-320p.mp4": "MP4 compatible colos preseos (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "MP4 tresmitible pela web (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 de calidĆ” HD (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "MP4 de calidĆ” Full HD (1080P)",
+ "timedmedia-derivative-desc-2160p.mp4": "MP4 de calidĆ” Full 4K (2160P)",
+ "timedmedia-subtitle-new": "Crear una traducciĆ³n nueva o editar la esistente",
+ "timedmedia-subtitle-new-desc": "Seleicione la llingua y calque nel botĆ³n '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Dir",
+ "timedmedia-subtitle-language": "SubtĆ­tulos en $1 ($2)",
+ "timedmedia-subtitle-no-video": "Nun hai nengĆŗn videu asociĆ”u cola pĆ”xina de subtĆ­tulos actual",
+ "timedmedia-subtitle-no-subtitles": "AnguaƱo nun hai subtƭtulos en $1 pa esti videu, pue [{{fullurl:{{FULLPAGENAME}}|action=edit}} editar esta pƔxina] p'amestalos",
+ "timedmedia-subtitle-remote": "El testu cronometrƔu d'esti ficheru ta agospiƔu en $1",
+ "timedmedia-subtitle-remote-link": "Pue [$1 ver la pĆ”xina de descripciĆ³n] d'esti ficheru en $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 videu|$1 videos}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 videu|$1 videos}} Ogg",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 videu|$1 videos}} WebM",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 trescodificaciĆ³n|$1 trescodificaciones}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 trescodificaciĆ³n activa|$1 trescodificaciones actives}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 trescodificaciĆ³n|$1 trescodificaciones}} na cola",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 trescodificaciĆ³n fallida|$1 trescodificaciones fallĆ­es}}",
+ "timedmedia-file": "Ficheru",
+ "timedmedia-audios": "{{PLURAL:$1|$1 ficheru de sonĆ­u|$1 ficheros de sonĆ­u}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 ficheru de sonĆ­u Ogg|$1 ficheros de sonĆ­u Ogg}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 ficheru de sonĆ­u FLAC|$1 ficheros de sonĆ­u FLAC}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 ficheru de sonĆ­u WAV|$1 ficheros de sonĆ­u WAV}}",
+ "right-transcode-reset": "Reaniciar los videos fallĆ­os o trescodificaos pa que vuelvan a ponese na cola de trabayos.",
+ "right-transcode-status": "Ver [[Special:TimedMediaHandler|informaciĆ³n sobre l'actividĆ” de trescodificaciĆ³n actual]]",
+ "action-transcode-status": "ver l'estĆ”u actual de la trescodificaciĆ³n",
+ "orphanedtimedtext": "PĆ”xines gĆ¼Ć©rfanes de TimedText",
+ "orphanedtimedtext-summary": "Llista de pƔxines de [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] que nun tienen el correspondiente ficheru.",
+ "orphanedtimedtext-unsupported": "Esta pĆ”xina especial sĆ³lo tien sofitu con bases de datos MySQL.",
+ "orphanedtimedtext-notimedtext": "TimedText nun ta activƔu nesta wiki.",
+ "apihelp-query+transcodestatus-description": "Recibir l'estƔu de transcode pa una pƔxina de ficheru determinada.",
+ "apihelp-query+transcodestatus-example-1": "Recibir l'estƔu de transcode pa [[:File:Clip.webm]]",
+ "apihelp-query+videoinfo-description": "Estende imageinfo pa incluir la informaciĆ³n de fonte de videu (derivaos)",
+ "apihelp-query+videoinfo-param-prop": "Que informaciĆ³n de videu algamar:\n;timestamp:Amiesta la marca d'hora de la versiĆ³n xubida.\n;user:Amiesta l'usuariu que xubiĆ³ la versiĆ³n del videu.\n;userid:Amiesta la ID del usuariu que xubiĆ³ la versiĆ³n del videu.\n;comment:Comentariu de la versiĆ³n.\n;parsedcomment:Comentariu analizĆ”u na versiĆ³n.\n;canonicaltitle:Amiesta'l tĆ­tulu canĆ³nicu del ficheru de videu.\n;url:Da la URL del videu y la pĆ”xina de descripciĆ³n.\n;size:Amiesta'l tamaƱu del videu en bytes, l'altor y anchor. Si ye aplicable, amiĆ©stase la cuenta de pĆ”xines y duraciĆ³n.\n;dimensions:AlcuƱu pa \"size\".\n;sha1:Amiesta'l hash SHA-1 del videu.\n;mime:Amiesta'l tipu MIME del videu.\n;thumbmime:Amiesta'l tipu MIME de la miniatura del videu (rique url y parĆ”metru $1urlwidth).\n;mediatype:Amiesta'l tipu de mediu del videu.\n;metadata:Llista de metadatos Exif de la versiĆ³n del videu.\n;commonmetadata:Llista de metadatos xenĆ©ricos del formatu de ficheru de la versiĆ³n del videu.\n;extmetadata:Llista de metadatos con formatu combinaos dende fontes diverses. Los resultaos tĆ”n en formatu HTML.\n;archivename:Amiesta'l nome de la versiĆ³n d'archivu pa versiones distintes de la Ćŗltima.\n;bitdepth:Amiesta la fondura de bit de la versiĆ³n.\n;uploadwarning:UsĆ”u pola pĆ”xina [[Special:Upload]] p'algamar informaciĆ³n d'un ficheru esistente. Nun ta previstu pa usase fuera del nucleu de MediaWiki.\n;derivatives:Amiesta una tabla colos diferentes formatos y calidaes disponibles d'un ficheru de sonĆ­u o videu.",
+ "apihelp-query+videoinfo-example-1": "Buscar informaciĆ³n tocante a [[:File:Folgers.ogv]]",
+ "apihelp-transcodereset-description": "Los usuarios col permisu 'transcode-reset' pueden reaniciar y volver a executar un trabayu transcode.",
+ "apihelp-transcodereset-param-title": "TĆ­tulu del ficheru de multimedia.",
+ "apihelp-transcodereset-param-transcodekey": "La clave del transcode que quies reaniciar. CuƩyela de [[Special:ApiHelp/query+transcodestatus|action=query&prop=transcodestatus]].",
+ "apihelp-transcodereset-example-1": "Reaniciar tolos transcodes de [[:File:Clip.webm]]",
+ "apihelp-transcodereset-example-2": "Reaniciar la clave transcode '360_560kbs.webm' de [[:File:Clip.webm]]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/av.json b/extensions/TimedMediaHandler/i18n/av.json
new file mode 100644
index 00000000..2a3131e3
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/av.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gazimagomedov"
+ ]
+ },
+ "timedmedia-source-file": "$1 Šøцц",
+ "timedmedia-source-audio-file-desc": "ŠŃŠ»ŠøяŠ± $1-фŠ°Š¹Š» ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/avk.json b/extensions/TimedMediaHandler/i18n/avk.json
new file mode 100644
index 00000000..313cd0c9
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/avk.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sab"
+ ]
+ },
+ "timedmedia-download": "Iyeltakkalvajara",
+ "timedmedia-desc-link": "Icde bat iyeltak"
+}
diff --git a/extensions/TimedMediaHandler/i18n/awa.json b/extensions/TimedMediaHandler/i18n/awa.json
new file mode 100644
index 00000000..fe0c3d1a
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/awa.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "1AnuraagPandey"
+ ]
+ },
+ "timedmedia-no-player-js": "ą¤•ą„ą¤·ą¤®ą¤¾ ą¤•ą¤°ą„‡ą¤‚, ą¤†ą¤Ŗą¤•ą„‡ ą¤¬ą„ą¤°ą¤¾ą¤‰ą¤œą¤¼ą¤° ą¤®ą„‡ą¤‚ ą¤Æą¤¾ ą¤¤ą„‹ ą¤œą¤¾ą¤µą¤¾ą¤øą„ą¤•ą„ą¤°ą¤æą¤Ŗą„ą¤Ÿ ą¤…ą¤•ą„ą¤·ą¤® ą¤¹ą„ˆ ą¤Æą¤¾ ą¤øą¤®ą¤°ą„ą¤„ą¤æą¤¤ ą¤Ŗą„ą¤²ą„‡ą¤Æą¤° ą¤Øą¤¹ą„€ą¤‚ ą¤¹ą„ˆą„¤<br />\ną¤†ą¤Ŗ <a href=\"$1\">ą¤•ą„ą¤²ą¤æą¤Ŗ ą¤•ą„‹ ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤”</a> ą¤•ą¤° ą¤øą¤•ą¤¤ą„‡ ą¤¹ą„ˆą¤‚ ą¤…ą¤„ą¤µą¤¾ ą¤•ą„ą¤²ą¤æą¤Ŗ ą¤•ą„‹ ą¤…ą¤Ŗą¤Øą„‡ ą¤¬ą„ą¤°ą¤¾ą¤‰ą¤œą¤¼ą¤° ą¤®ą„‡ą¤‚ ą¤šą¤²ą¤¾ą¤Øą„‡ ą¤•ą„‡ ą¤²ą¤æą¤ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ą¤ą¤• ą¤Ŗą„ą¤²ą„‡ą¤Æą¤° ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤”</a> ą¤•ą¤° ą¤øą¤•ą¤¤ą„‡ ą¤¹ą„ˆą¤‚ą„¤",
+ "timedmedia-source-file": "$1 ą¤øą„ą¤°ą„‹ą¤¤",
+ "timedmedia-source-audio-file-desc": "ą¤®ą„‚ą¤² $1 ą¤«ą¤¼ą¤¾ą¤‡ą¤² ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/az.json b/extensions/TimedMediaHandler/i18n/az.json
new file mode 100644
index 00000000..f54d2aed
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/az.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cekli829",
+ "Dağlı95",
+ "Wertuose"
+ ]
+ },
+ "timedmedia-no-player-js": "Bağışlayın, sizin veb brauzeriniz JavaScript texnologiyasını dəstəkləmir və ya bu əlavə deaktiv edilib.\nSiz dinləmək istədiyiniz faylı <a href=\"$1\">yĆ¼kləyə</a> və ya brauzerinizə, <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">lazımlı əlavəni</a> quraşdıra bilərsiz.",
+ "timedmedia-status": "Status",
+ "timedmedia-source-file": "$1 mənbəyi",
+ "timedmedia-source-audio-file-desc": "Orijinal $1-fayl ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/azb.json b/extensions/TimedMediaHandler/i18n/azb.json
new file mode 100644
index 00000000..d0c5b700
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/azb.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amir a57",
+ "Koroğlu"
+ ]
+ },
+ "timedmedia-no-player-js": "Ų§ŁˆŲ²ŚÆŁˆŁ†Ł„ŁˆŚ©ā€ŒŁ„Ł‡ŲŒ Ų³ŪŒŲ²ŪŒŁ† ŲÆŲ§Ų±Ų§ŪŒŪŒŲ¬ŪŒā€ŒŁ†ŪŒŲ²ŪŒŁ† Ų¬Ų§ŁˆŲ§ Ų§ŪŒŲ³Ś©Ų±ŪŒŁ¾ŲŖ ŪŒŲ§Ų²ŪŒŁ„ŪŒŁ…ŪŒ Ś†Ų§Ł„ŪŒŲ“Ł…Ų§ŪŒŪŒŲ±ŲŒ ŪŒŲ§ ŲÆŲ§ Ų³ŪŒŲ²ŪŒŁ† ŲÆŲ§Ų±ŪŒŪŒŲ¬ŪŒā€ŒŁ†ŪŒŲ² ŲØŁˆ ŪŒŲ§Ų²ŪŒŁ„ŪŒŁ…ā€ŒŲÆŲ§Ł† Ų¢Ų±ŲÆŲ§ŲŗŁ„Ų§Ł…ŪŒŲ±.<br />\nŲ³ŪŒŲ² <a href=\"$1\">ŲØŁˆ ŁˆŪŒŲÆŪŒŁˆŁ†Łˆ Ų§ŪŒŁ†ŲÆŪŒŲ±ŪŒŲØ</a> ŪŒŲ§ ŲÆŲ§ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ŲØŪŒŲ± Ų§ŁˆŪŒŁ†Ų§ŲÆŪŒŲ¬ŪŒ</a> Ų§ŪŒŁ†ŲÆŪŒŲ±Ł‡ā€ŒŲØŪŒŁ„Ų±Ų³ŪŒŁ†ŪŒŲ².",
+ "timedmedia-source-file": "$1 Ś©ŁˆŚ©",
+ "timedmedia-source-audio-file-desc": "Ų§ŲµŁ„ŪŒ $1 ŁŲ§ŪŒŁ„ ( $2 )"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ba.json b/extensions/TimedMediaHandler/i18n/ba.json
new file mode 100644
index 00000000..10f406c5
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ba.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Haqmar",
+ "Š ŃƒŃŃ‚Š°Š¼ ŠŃƒŃ€Ń‹ŠµŠ²"
+ ]
+ },
+ "timedmedia-days": "{{PLURAL:$1|1=$1 ŠŗÓ©Š½|$1 ŠŗÓ©Š½}}",
+ "timedmedia-hours": "{{PLURAL:$1|1=$1 сәŅ“әт|$1 сәŅ“әт}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1=$1 Š¼ŠøŠ½ŃƒŃ‚|$1 Š¼ŠøŠ½ŃƒŃ‚}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1=$1 сŠµŠŗуŠ½Š“|$1 сŠµŠŗуŠ½Š“}}",
+ "timedmedia-source-file": "$1 сыŅ“Š°Š½Š°Ņ”",
+ "timedmedia-source-audio-file-desc": "ŠžŃ€ŠøŠ³ŠøŠ½Š°Š» $1-фŠ°Š¹Š» ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/bcc.json b/extensions/TimedMediaHandler/i18n/bcc.json
new file mode 100644
index 00000000..11fbd1a8
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/bcc.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mostafadaneshvar",
+ "Baloch Afghanistan"
+ ]
+ },
+ "timedmedia-desc": "ŲÆŲ³ŚÆŪŒŲ±Ł‡ Ł¾Ł‡ ŁŲ§ŪŒŁ„Ų§Ł† Ogg Theora Łˆ Vorbis, ŚÆŁˆŁ† Ł¾Ų®Ų“ Ś©Ł†ŁˆŚ© Ų¬Ų§ŁˆŲ§ Ų§Ų³Ś©Ų±Ų³ŪŒŁ¾ŲŖ",
+ "timedmedia-ogg-short-audio": "ŁŲ§ŪŒŁ„ ŲµŁˆŲŖŪŒ Ogg $1ŲŒ $2",
+ "timedmedia-ogg-short-video": "ŁŲ§ŪŒŁ„ ŲŖŲµŁˆŪŒŲ±ŪŒ Ogg $1ŲŒ $2",
+ "timedmedia-ogg-short-general": "ŁŲ§ŪŒŁ„ Ł…ŲÆŪŒŲ§ Ogg $1ŲŒ $2",
+ "timedmedia-ogg-long-audio": "Ų§ŁˆŲ¬ŪŒ Ų¬ŪŒ $1 ŁŲ§ŪŒŁ„ ŲµŁˆŲŖŪŒ, Ų·ŁˆŁ„ $2, $3",
+ "timedmedia-ogg-long-video": "Ų§ŁˆŲ¬ŪŒ Ų¬ŪŒ $1 ŁŲ§ŪŒŁ„ ŁˆŪŒŲÆŪŒŁˆ, Ų·ŁˆŁ„ $2, $4Ɨ$5 Ł¾ŪŒŚ©Ų³Ł„, $3",
+ "timedmedia-ogg-long-multiplexed": "Ų§ŁˆŲ¬ŪŒ Ų¬ŪŒ Ś†Ł†ŲÆ ŲÆŲ§ŲØŪŒ ŁŲ§ŪŒŁ„ ŲµŁˆŲŖ/ŲŖŲµŁˆŪŒŲ±, $1, Ų·ŁˆŁ„ $2, $4Ɨ$5 Ł¾ŪŒŚ©Ų³Ł„, $3 Ś©Ł„",
+ "timedmedia-ogg-long-general": "Ų§ŁˆŲ¬ŪŒ Ų¬ŪŒ ŁŲ§ŪŒŁ„ Ł…ŲÆŪŒŲ§, Ų·ŁˆŁ„ $2, $3",
+ "timedmedia-ogg-long-error": "Ł†Ų§Ł…Ų¹ŲŖŲØŲ±ŪŒŁ† ŁŲ§ŪŒŁ„ Ų§ŁˆŲ¬ŪŒ Ų¬ŪŒ: $1",
+ "timedmedia-more": "ŚÆŪŒŲ“ŲŖŪŒŲ±...",
+ "timedmedia-dismiss": "ŲØŲ³ŲŖŪŒŁ†",
+ "timedmedia-download": "Ų¦ŪŒŲ± Ś©ŁˆŲ±ŲŖŪŒŁ† Ł¾Ų§ŪŒŁ„ŪŒ",
+ "timedmedia-desc-link": "Ų§ŪŒ ŁŲ§ŪŒŁ„ ŲØŲ§Ų±Ł‡",
+ "timedmedia-subtitle-new-go": "ŲØŲ±Ų§",
+ "orphanedtimedtext": "ŪŒŲŖŪŒŁ… TimedText ŲÆŪŒŁ…Ų§Ł†",
+ "orphanedtimedtext-summary": "Ł‡Ų§ ŲÆŪŒŁ…Ų§Ł†ŪŒ Ł„ŪŒŲ³ŲŖ Ś©Ł‡ [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] Ł…ŲŖŁ†Ų§ŲøŲ±ŪŒŁ† Ł¾Ų§ŪŒŁ„ Ł†ŲÆŲ§Ų±Ł†ŲŖ ."
+}
diff --git a/extensions/TimedMediaHandler/i18n/bcl.json b/extensions/TimedMediaHandler/i18n/bcl.json
new file mode 100644
index 00000000..36042848
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/bcl.json
@@ -0,0 +1,90 @@
+{
+ "@metadata": {
+ "authors": [
+ "Filipinayzd",
+ "Geopoet"
+ ]
+ },
+ "timedmedia-desc": "Parakapot para sa audio, bidyo asin pinag-orasan na teksto, na igwa nin pormat kan suporta para sa WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Ogg $1 sagunson nin tanog, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 sagunson nin bidyo, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 sagunson nin midya, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 sagunson nin tanog, an laba $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 sagunson nin bidyo, an laba $2, $4 x $5 piksel, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg pinaghalong sagunson nin audio/bidyo, $1, an laba $2, $4 x $5 piksel, $3",
+ "timedmedia-ogg-long-general": "Ogg sagunson nin midya, an laba $2, $3",
+ "timedmedia-ogg-long-error": "Imbalidong sagunson nin Ogg: $1",
+ "timedmedia-webm-short-video": "Webm $1 sagunson nin bidyo, $2",
+ "timedmedia-webm-long-video": "WebM sagunson nin audio/bidyo, $1, an laba $2, $4 x $5 piksel, $3 sa bilog na kagabsan",
+ "timedmedia-flac-short-audio": "FLAC sagunson nin audio, $1",
+ "timedmedia-flac-long-audio": "FLAC sagunson nin audio, an laba $1, $2 sa bilog na kagabsan",
+ "timedmedia-wav-short-audio": "WAV sagunson nin audio, $1",
+ "timedmedia-wav-long-audio": "WAV sagunson nin audio, an laba $1, $2 sa bilog na kagabsan",
+ "timedmedia-wav-pcm-required": "Ika makakarga sana nin PCM (Pulse Code Modulation) WAV.",
+ "timedmedia-mp4-short-video": "MP$ $1 sagunson nin bidyo, $2",
+ "timedmedia-mp4-long-video": "MP4 sagunson nin audio/bidyo, $1, an laba $2, $4 x $5 piksel, $3 sa bilog na kagabsan",
+ "timedmedia-no-player-js": "Sori po, an saimong pangilyaw baya pinagpundo an JavaScript o mayo gayod nin arinmang pinagsuportaran na parapaandar. <br /> Ika <a href=\"$1\">makakapagkarga nin klip</a> o baya <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">magkarga nin sarong parapaandar</a> tanganing paandaron an klip kan saimong kilyawan.",
+ "timedmedia-more": "Dakolon pa..",
+ "timedmedia-dismiss": "Isara",
+ "timedmedia-download": "Ikarga an sagunson",
+ "timedmedia-play-media": "Paandaron an midya",
+ "timedmedia-desc-link": "Mapanungod kaining sagunson",
+ "timedmedia-oggThumb-version": "OggHandler minahagad sa oggThumb bersyon na $1 o kahurihi.",
+ "timedmedia-oggThumb-failed": "oggThumb nagpalya sa pagmukna kan sadit na ladawan",
+ "timedmedia-status-header": "Kamugtakan kan panggantaw na kodigo",
+ "timedmedia-update-status": "Sumpayan an kamugtakan kan panggantaw na kodigo",
+ "timedmedia-status": "Kamugtakan",
+ "timedmedia-status-unknown": "Bakong aram na kamugtakan",
+ "timedmedia-transcodeinfo": "Deribatibong deskripsyon kan panggantaw na kodigo",
+ "timedmedia-actions": "Mga aksyon",
+ "timedmedia-direct-link": "Ikarga an deribatibo",
+ "timedmedia-not-ready": "Dae pa handa",
+ "timedmedia-completed-on": "Pinagkumpletong panggantaw na kodigo $1",
+ "timedmedia-error-on": "Kasalaan sa panggantaw na kodigo sa $1",
+ "timedmedia-started-transcode": "An panggantaw na kodigo pinagpoonan mga $1 an nakaagi. $2",
+ "timedmedia-percent-done": "Haros $1% an tapos na",
+ "timedmedia-in-job-queue": "Pinagdugang sa haralatan nin Trabaho mga $1 an nakaagi",
+ "timedmedia-unknown-target-size": "Dae aram an sukol kan target, $1 pinagkodigo na",
+ "timedmedia-days": "{{PLURAL:$1|1 aldaw|$1 mga aldaw}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 oras|$1 mga oras}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minuto|$1 minutos}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 segundo|$1 segundos}}",
+ "timedmedia-reset": "Pakibaguha an panggantaw na kodigo",
+ "timedmedia-reset-confirm": "Sa pagbabago kaining panggantaw na kodigo magtatangkas nin arinman na eksistidong sagunson (kun yaon), asin magdudugang otro kan panggantaw na kodigo sa haralatan nin trabaho. Ini minakaipo nin nagkapirang oras tangani na otrong ipaggantaw an kodigo. <br /><br /> Segurado ka na muya mong magpadagos?",
+ "timedmedia-reset-error": "Kasalaan sa pagbabago kan trabaho nin panggantaw na kodigo.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 pinagkuanan",
+ "timedmedia-source-file-desc": "Orihinal $1 na sagunson, $2 x $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Orihinal $1 na sagunson ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Hababaong kalawigan Ogg bidyo (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Maantabayanan sa Web na bidyo kan Ogg (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Maantabayanan sa Web na bidyo kan Ogg (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Halangkaw na kalidad na maikakargang bidyo kan Ogg (720P)",
+ "timedmedia-derivative-desc-160p.webm": "Maantabayanan sa Web na bidyo kan WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "Maantabayanan sa Web na bidyo kan WebM (360P)",
+ "timedmedia-derivative-desc-480p.webm": "Maantabayanan sa Web na bidyo kan WebM (480P)",
+ "timedmedia-derivative-desc-720p.webm": "Halangkaw na kalidad na maikakargang bidyo kan WebM (720P)",
+ "timedmedia-derivative-desc-320p.mp4": "Masayon sa aparato MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "Maantabayanan sa Web na MP4 (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "HD na kalidad MP4 (720P)",
+ "timedmedia-subtitle-new": "Magmukna nin baguhong dakit-taramon o liwaton an eksistido na",
+ "timedmedia-subtitle-new-desc": "Magpili nin lengguwahe asin pinduton an '''{{int:Timedmedia-subtitle-new-go}}''' na dutdutan",
+ "timedmedia-subtitle-new-go": "Magduman",
+ "timedmedia-subtitle-language": "$1 ($2) mga sub-titulo",
+ "timedmedia-subtitle-no-video": "Mayo tabing bidyo na asosyado na igwa nin sa ngunyan na subtitulo kan pahina",
+ "timedmedia-subtitle-no-subtitles": "Mayo tabi nin sa ngunyan na mga subtitulo sa $1 para kaining bidyo, ika tabi [{{fullurl:{{FULLPAGENAME}}|action=edit}} makapagliwat kaining pahina] tanganing maidugang sinda",
+ "timedmedia-subtitle-remote": "Pinag-orasang teksto para kaining sagunson iyo an pinagbunsod sa $1",
+ "timedmedia-subtitle-remote-link": "Ika tabi [$1 makakatanaw sa pahina kan deskripsyon] para kaining sagunson sa $2",
+ "timedmediahandler": "Pinag-orasan na Parakapot kan Midya",
+ "timedmedia-videos": "{{PLURAL:$1|$1 bidyo|$1 mga bidyo}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg bidyo|$1 Ogg mga bidyo}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM bidyo|$1 WebM mga bidyo}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 panggantaw na kodigo|$1 panggantaw na mga kodigo}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 nagdadalagan na panggantaw na kodigo|$1 nagdadalagan na panggantaw na mga kodigo}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 pinaghahalat na panggantaw na kodigo|$1 pinaghahalat na panggantaw na mga kodigo}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 nagpalyang panggantaw na kodigo|$1 nagpalyang panggantaw na mga kodigo}}",
+ "timedmedia-file": "Sagunson",
+ "right-transcode-reset": "An pagbƔgo nagpalya o an pinaggantaw na kodigong mga bidyo kaya sinda pinagsingit giraray sa haralatan kan trabaho.",
+ "right-transcode-status": "Patanaw [[Special:TimedMediaHandler|impormasyon mapanungod sa ngunyan na aktibidad kan panggantaw na kodigo]]",
+ "action-transcode-status": "tanawon an sa ngunyan na kamugtakan kan panggangtaw na kodigo"
+}
diff --git a/extensions/TimedMediaHandler/i18n/be-tarask.json b/extensions/TimedMediaHandler/i18n/be-tarask.json
new file mode 100644
index 00000000..1bd50c1d
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/be-tarask.json
@@ -0,0 +1,71 @@
+{
+ "@metadata": {
+ "authors": [
+ "EugeneZelenko",
+ "Jim-by",
+ "Red Winged Duck",
+ "Wizardist"
+ ]
+ },
+ "timedmedia-desc": "ŠŠæрŠ°Ń†Š¾ŃžŃˆŃ‡Ń‹Šŗ Š°ŃžŠ“ыё, Š²Ń–Š“эŠ° і суŠ±Ń‚Ń‹Ń‚Ń€Š°Ńž у фŠ°Ń€Š¼Š°Ń‚Š°Ń… WebM, Ogg Theora, Vorbis і SRT",
+ "timedmedia-ogg-short-audio": "ŠŃžŠ“ыё-фŠ°Š¹Š» Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Š’Ń–Š“эŠ°-фŠ°Š¹Š» у фŠ°Ń€Š¼Š°Ń†Šµ Ogg $1, $2",
+ "timedmedia-ogg-short-general": "ŠœŃŠ“ыяфŠ°Š¹Š» Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Š°ŃžŠ“ыё-фŠ°Š¹Š» Ogg $1, Š“Š°ŃžŠ¶Ń‹Š½Ń $2, $3",
+ "timedmedia-ogg-long-video": "Š²Ń–Š“эŠ°-фŠ°Š¹Š» Ogg $1, Š“Š°ŃžŠ¶Ń‹Š½Ń $2, $4Ɨ$5 ŠæіŠŗсэŠ»ŃŃž, $3",
+ "timedmedia-ogg-long-multiplexed": "Š¼ŃƒŠ»ŃŒŃ‚Ń‹ŠæŠ»ŠµŠŗсŠ½Ń‹ Š°ŃžŠ“ыё/Š²Ń–Š“эŠ°-фŠ°Š¹Š» Ogg, $1, Š“Š°ŃžŠ¶Ń‹Š½Ń $2, $4Ɨ$5 ŠæіŠŗсэŠ»ŃŃž, усяŠ³Š¾ $3",
+ "timedmedia-ogg-long-general": "Š¼ŃŠ“ыяфŠ°Š¹Š» Ogg, Š“Š°ŃžŠ¶Ń‹Š½Ń $2, $3",
+ "timedmedia-ogg-long-error": "ŠŃŃŠ»ŃƒŃˆŠ½Ń‹ фŠ°Š¹Š» у фŠ°Ń€Š¼Š°Ń†Šµ Ogg: $1",
+ "timedmedia-webm-short-video": "WebM $1 Š²Ń–Š“эŠ°Ń„Š°Š¹Š», $2",
+ "timedmedia-webm-long-video": "ŠŃžŠ“ыё/Š²Ń–Š“эŠ°-фŠ°Š¹Š» WebM, $1, ŠæрŠ°Ń†ŃŠ³Š»Š°ŃŃŒŃ†ŃŒ $2, $4Ɨ$5 ŠæіŠŗсэŠ»Š°Ńž, усяŠ³Š¾ $3",
+ "timedmedia-flac-short-audio": "ŠŃžŠ“ыёфŠ°Š¹Š» FLAC, $1",
+ "timedmedia-flac-long-audio": "ŠŃžŠ“ыёфŠ°Š¹Š» FLAC, ŠæрŠ°Ń†ŃŠ³Š»Š°ŃŃŒŃ†ŃŒ $1, усяŠ³Š¾ $2",
+ "timedmedia-mp4-short-video": "MP4 $1 Š²Ń–Š“эŠ°Ń„Š°Š¹Š», $2",
+ "timedmedia-no-player-js": "ŠŸŃ€Š°Š±Š°Ń‡Ń†Šµ, Š°Š»Šµ ў Š’Š°ŃˆŃ‹Š¼ Š±Ń€Š°ŃžŠ·ŃŃ€Ń‹ Š°Š“ŠŗŠ»ŃŽŃ‡Š°Š½Ń‹ JavaScript Š°Š»ŃŒŠ±Š¾ Š½ŃŠ¼Š° Š½ŠµŠ°Š±Ń…Š¾Š“Š½Š°Š³Š° ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–ŠŗŠ°.<br />\nŠ’Ń‹ Š¼Š¾Š¶Š°Ń†Šµ <a href=\"$1\">Š·Š°Š³Ń€ŃƒŠ·Ń–Ń†ŃŒ ŠŗŠ»Ń–Šæ</a> ці <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">Š·Š°Š³Ń€ŃƒŠ·Ń–Ń†ŃŒ ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–Šŗ</a> Š“Š»Ń ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š½ŃŒŠ½Ń ŠŗŠ»Ń–Šæу ў Š’Š°ŃˆŃ‹Š¼ Š±Ń€Š°ŃžŠ·ŃŃ€Ń‹.",
+ "timedmedia-more": "Š‘Š¾Š»ŠµŠ¹ā€¦",
+ "timedmedia-dismiss": "ŠŠ°Š·Š°Š“",
+ "timedmedia-download": "Š—Š°Š³Ń€ŃƒŠ·Ń–Ń†ŃŒ фŠ°Š¹Š»",
+ "timedmedia-play-media": "ŠŸŃ€Š°Š¹Š³Ń€Š°Ń†ŃŒ",
+ "timedmedia-desc-link": "Š†Š½Ń„Š°Ń€Š¼Š°Ń†Ń‹Ń ŠæрŠ° Š³ŃŃ‚Ń‹ фŠ°Š¹Š»",
+ "timedmedia-oggThumb-version": "OggHandler ŠæŠ°Ń‚Ń€Š°Š±ŃƒŠµ oggThumb Š²ŃŃ€ŃŃ–Ń– $1 ці Š±Š¾Š»ŃŒŃˆ ŠæŠ¾Š·ŃŒŠ½ŃŠ¹.",
+ "timedmedia-oggThumb-failed": "oggThumb Š½Šµ Š°Ń‚рыŠ¼Š°Š»Š°ŃŃ стŠ²Š°Ń€Ń‹Ń†ŃŒ Š¼Ń–Š½Ń–ŃŃ‚ŃƒŃ€Ńƒ.",
+ "timedmedia-status-header": "Š”тŠ°Ń‚ŃƒŃ трŠ°Š½ŃŠŗŠ°Š“Š°Š²Š°Š½ŃŒŠ½Ń",
+ "timedmedia-update-status": "ŠŠ±Š½Š°Š²Ń–Ń†ŃŒ стŠ°Ń‚ŃƒŃ трŠ°Š½ŃŠŗŠ°Š“Š°Š²Š°Š½ŃŒŠ½Ń",
+ "timedmedia-status": "Š”тŠ°Ń‚ŃƒŃ",
+ "timedmedia-status-unknown": "Š”тŠ°Ń‚ŃƒŃ Š½ŠµŠ²ŃŠ“Š¾Š¼Ń‹",
+ "timedmedia-transcodeinfo": "Š¤Š°Ń€Š¼Š°Ń‚",
+ "timedmedia-actions": "Š”Š·ŠµŃŠ½ŃŒŠ½Ń–",
+ "timedmedia-direct-link": "Š”ŠæŠ°Š¼ŠæŠ°Š²Š°Ń†ŃŒ",
+ "timedmedia-not-ready": "ŠŠµ Š³Š°Ń‚Š¾Š²Ń‹",
+ "timedmedia-completed-on": "Š—Š°Š²ŠµŃ€ŃˆŠ°Š½Š° $1",
+ "timedmedia-error-on": "ŠŸŠ°Š¼Ń‹Š»ŠŗŠ° ў $1",
+ "timedmedia-started-transcode": "ŠŸŠ°Ń‡Š°Š»Š¾ŃŃ $1 тŠ°Š¼Ńƒ. $2",
+ "timedmedia-percent-done": "Š“Š°Ń‚Š¾Š²Š° ŠŗŠ°Š»Ń $1%",
+ "timedmedia-in-job-queue": "Š”Š°Š“Š°Š“Š·ŠµŠ½Š° ў чŠ°Ń€Š³Ńƒ Š·Š°Š“Š°Š½ŃŒŠ½ŃŃž $1 тŠ°Š¼Ńƒ",
+ "timedmedia-unknown-target-size": "Š’Ń‹Š½Ń–ŠŗŠ¾Š²Ń‹ ŠæŠ°Š¼ŠµŃ€ Š½ŠµŠ²ŃŠ“Š¾Š¼Ń‹, $1 Š·Š°ŠŗŠ°Š“Š°Š²Š°Š½Š°",
+ "timedmedia-days": "$1 {{PLURAL:$1|Š“Š·ŠµŠ½ŃŒ|Š“Š½Ń–|Š“Š·Ń‘Š½}}",
+ "timedmedia-hours": "$1 {{PLURAL:$1|Š³Š°Š“Š·Ń–Š½Ńƒ|Š³Š°Š“Š·Ń–Š½Ń‹|Š³Š°Š“Š·Ń–Š½Š°Ńž}}",
+ "timedmedia-minutes": "$1 {{PLURAL:$1|хŠ²Ń–Š»Ń–Š½Ńƒ|хŠ²Ń–Š»Ń–Š½Ń‹|хŠ²Ń–Š»Ń–Š½Š°Ńž}}",
+ "timedmedia-seconds": "$1 {{PLURAL:$1|сэŠŗуŠ½Š“у|сэŠŗуŠ½Š“ы|сэŠŗуŠ½Š“Š°Ńž}}",
+ "timedmedia-reset": "ŠŸŠµŃ€Š°Š·Š°Šæусьціць трŠ°Š½ŃŠŗŠ°Š“Š°Š²Š°Š½ŃŒŠ½Šµ",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "ŠšŃ€Ń‹Š½Ń–цŠ° $1",
+ "timedmedia-source-file-desc": "ŠŃ€Ń‹Š³Ń–Š½Š°Š» у $1, $2Ɨ$3 ($4)",
+ "timedmedia-source-audio-file-desc": "ŠŃ€Ń‹Š³Ń–Š½Š°Š» у $1 ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "ŠŃ–Š·ŠŗŠ°ŠæŠ°Ń‚Š¾Ń‡Š½Š°Šµ Ogg-Š²Ń–Š“эŠ° (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "ŠŸŠ°Ń‚Š¾Ń‡Š½Š°Šµ Ogg-Š²Ń–Š“эŠ° (360 ŠæŠŗс)",
+ "timedmedia-derivative-desc-480p.ogv": "ŠŸŠ°Ń‚Š¾Ń‡Š½Š°Šµ Ogg-Š²Ń–Š“эŠ° (480 ŠæŠŗс)",
+ "timedmedia-derivative-desc-720p.ogv": "Š’ысŠ°ŠŗŠ°ŃŠŗŠ°ŃŠ½Š°Šµ Ogg-Š²Ń–Š“эŠ° Š“Š»Ń Š·Š°Š³Ń€ŃƒŠ·Šŗі (720p)",
+ "timedmedia-derivative-desc-360p.webm": "ŠŸŠ°Ń‚Š¾Ń‡Š½Ń‹ WebM (360p)",
+ "timedmedia-derivative-desc-480p.webm": "ŠŸŠ°Ń‚Š¾Ń‡Š½Ń‹ WebM (480p)",
+ "timedmedia-derivative-desc-720p.webm": "Š’ысŠ°ŠŗŠ°ŃŠŗŠ°ŃŠ½Š°Šµ WebM-Š²Ń–Š“эŠ° Š“Š»Ń Š·Š°Š³Ń€ŃƒŠ·Šŗі (720p)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 HD-яŠŗŠ°ŃŃŒŃ†Ń– (720P)",
+ "timedmedia-subtitle-new": "Š”тŠ²Š°Ń€Ń‹Ń†ŃŒ Š½Š¾Š²Ń‹ ŠæŠµŃ€Š°ŠŗŠ»Š°Š“ ці рэŠ“Š°Š³Š°Š²Š°Ń†ŃŒ ісŠ½ŃƒŃŽŃ‡Ń‹",
+ "timedmedia-subtitle-new-go": "ŠŸŠ°Ń‡Š°Ń†ŃŒ",
+ "timedmedia-subtitle-language": "Š”уŠ±Ń‚ытры ($2) Š½Š° $1",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1}} Š²Ń–Š“эŠ°",
+ "timedmedia-file": "Š¤Š°Š¹Š»",
+ "right-transcode-reset": "сŠŗіŠ“Š°Š½ŃŒŠ½Šµ Š½ŃŃžŠ“Š°Š»Ń‹Ń… Š°Š±Š¾ трŠ°Š½ŃŠŗŠ°Š“Š°Š²Š°Š½Ń‹Ń… Š²Ń–Š“эŠ°, ŠŗŠ°Š± яŠ½Ń‹ іŠ·Š½Š¾Ńž трŠ°ŠæіŠ»Ń– ў чŠ°Ń€Š³Ńƒ Š·Š°Š“Š°Š½ŃŒŠ½ŃŃž",
+ "right-transcode-status": "ŠæрŠ°Š³Š»ŃŠ“ [[Special:TimedMediaHandler|Š·ŃŒŠ²ŠµŃŃ‚Š°Šŗ ŠæрŠ° Š°ŠŗтуŠ°Š»ŃŒŠ½Ń‹ стŠ°Š½ ŠæŠµŃ€Š°ŠŗŠ°Š“Š°Š²Š°Š½ŃŒŠ½Ń]]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/be.json b/extensions/TimedMediaHandler/i18n/be.json
new file mode 100644
index 00000000..d24bc36e
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/be.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Š§Š°Ń…Š¾Š²Ń–ч Š£Š»Š°Š“Š·Ń–сŠ»Š°Ńž"
+ ]
+ },
+ "timedmedia-no-player-js": "ŠŠ° Š¶Š°Š»ŃŒ, у Š²Š°ŃˆŃ‹Š¼ Š±Ń€Š°ŃžŠ·ŠµŃ€Ń‹ Š°Š“ŠŗŠ»ŃŽŃ‡Š°Š½Ń‹ JavaScript, ці Š½Šµ Š¼Š°ŠµŃ†Ń†Š° ŠæŠ°Ń‚Ń€Š°Š±Š°Š²Š°Š½Š°Š³Š° ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–ŠŗŠ°.<br />\nŠ’Ń‹ Š¼Š¾Š¶Š°Ń†Šµ <a href=\"$1\">Š·Š°Š³Ń€ŃƒŠ·Ń–Ń†ŃŒ рŠ¾Š»Ń–Šŗ</a> ці <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">Š·Š°Š³Ń€ŃƒŠ·Ń–Ń†ŃŒ ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š»ŃŒŠ½Ń–Šŗ</a> Š“Š»Ń ŠæрŠ°Š¹Š³Ń€Š°Š²Š°Š½Š½Ń рŠ¾Š»Ń–ŠŗŠ° ў Š±Ń€Š°ŃžŠ·ŠµŃ€Ń‹.",
+ "timedmedia-source-file": "ŠšŃ€Ń‹Š½Ń–цŠ° $1",
+ "timedmedia-source-audio-file-desc": "ŠŃ€Ń‹Š³Ń–Š½Š°Š»ŃŒŠ½Ń‹ $1-фŠ°Š¹Š» ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/bg.json b/extensions/TimedMediaHandler/i18n/bg.json
new file mode 100644
index 00000000..0ef16819
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/bg.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Borislav",
+ "DCLXVI",
+ "Spiritia",
+ "StanProg"
+ ]
+ },
+ "timedmedia-desc": "ŠŸŃ€ŠøŠ»Š¾Š¶ŠµŠ½ŠøŠµ Š·Š° фŠ°Š¹Š»Š¾Š²Šµ тŠøŠæ Ogg Theora Šø Vorbis, с ŠæŠ»ŠµŠ¹ŃŠŃ€ Š½Š° JavaScript",
+ "timedmedia-ogg-short-audio": "Ogg $1 Š·Š²ŃƒŠŗŠ¾Š² фŠ°Š¹Š», $2",
+ "timedmedia-ogg-short-video": "Ogg $1 Š²ŠøŠ“ŠµŠ¾ фŠ°Š¹Š», $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 Š·Š²ŃƒŠŗŠ¾Š² фŠ°Š¹Š», ŠæрŠ¾Š“ъŠ»Š¶ŠøтŠµŠ»Š½Š¾ŃŃ‚ $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 Š²ŠøŠ“ŠµŠ¾ фŠ°Š¹Š», ŠæрŠ¾Š“ъŠ»Š¶ŠøтŠµŠ»Š½Š¾ŃŃ‚ $2, $4Ɨ$5 ŠæŠøŠŗсŠµŠ»Š°, $3",
+ "timedmedia-ogg-long-general": "ŠœŃƒŠ»Ń‚ŠøŠ¼ŠµŠ“ŠøŠµŠ½ фŠ°Š¹Š» Š² ogg фŠ¾Ń€Š¼Š°Ń‚ с Š“ъŠ»Š¶ŠøŠ½Š° $2, $3",
+ "timedmedia-ogg-long-error": "ŠŠµŠ²Š°Š»ŠøŠ“ŠµŠ½ ogg фŠ°Š¹Š»: $1",
+ "timedmedia-no-player-js": "Š—Š° съŠ¶Š°Š»ŠµŠ½ŠøŠµ, Š±Ń€Š°ŃƒŠ·ŃŠŃ€Š° Š²Šø ŠøŠ¼Š° ŠøŠ·ŠŗŠ»ŃŽŃ‡ŠµŠ½ JavaScript ŠøŠ»Šø Š½Šµ рŠ°Š·ŠæŠ¾Š»Š°Š³Š° с Š½ŠµŠ¾Š±Ń…Š¾Š“ŠøŠ¼Šøя ŠæŠ»ŠµŠ¹ŃŠŃ€.<br />\nŠœŠ¾Š¶ŠµŃ‚Šµ Š“Š° <a href=\"$1\">ŠøŠ·Ń‚ŠµŠ³Š»ŠøтŠµ ŠŗŠ»ŠøŠæŠ°</a> ŠøŠ»Šø <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">Š“Š° ŠøŠ·Ń‚ŠµŠ³Š»ŠøтŠµ ŠæŠ»ŠµŠ¹ŃŠŃ€</a> Š·Š° Š“Š° ŠæусŠ½ŠµŃ‚Šµ ŠŗŠ»ŠøŠæŠ° Š² Š±Ń€Š°ŃƒŠ·ŃŠŃ€Š° сŠø.",
+ "timedmedia-more": "ŠŸŠ¾Š²ŠµŃ‡Šµ...",
+ "timedmedia-dismiss": "Š—Š°Ń‚Š²Š°Ń€ŃŠ½Šµ",
+ "timedmedia-download": "Š˜Š·Ń‚ŠµŠ³Š»ŃŠ½Šµ Š½Š° фŠ°Š¹Š»Š°",
+ "timedmedia-desc-link": "Š˜Š½Ń„Š¾Ń€Š¼Š°Ń†Šøя Š·Š° фŠ°Š¹Š»Š°",
+ "timedmedia-source-file": "Š˜Š·Ń‚Š¾Ń‡Š½ŠøŠŗ Š½Š° $1",
+ "timedmedia-source-audio-file-desc": "ŠžŃ€ŠøŠ³ŠøŠ½Š°Š»ŠµŠ½ $1-фŠ°Š¹Š» ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/bgn.json b/extensions/TimedMediaHandler/i18n/bgn.json
new file mode 100644
index 00000000..da70a08d
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/bgn.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Baloch Afghanistan",
+ "Ibrahim khashrowdi"
+ ]
+ },
+ "timedmedia-no-player-js": "ŲØŲ®Ų“Ų§ŪŒŲŖ Ų§Ū†Ś‘ŪŒŲŒ Ų“Ł…ŪŒ ŲØŲ±ŁˆŲ²ŪŒŲ± Ų¦ŪŒ Ų³Ų±Ų§ Ų¬Ų§ŁˆŲ§ Ų§Ų³Ś©Ų±ŪŒŁ¾ŲŖ Ų¦ŪŒ Ų³Ų§ŁŁ¹ Ų§ŪŒŲ± Ł¾Ų¦Ų§Ł„ Ł†Ł‡ Ų§ŪŒŁ†ŲŖ ŲŒ Łˆ ŪŒŲ§ Ś©Ł‡ Ų“Ł…ŪŒ ŲØŲ±ŁˆŲ²ŪŒŲ± Ų“Ł‡ Ų§ŪŒ Ł¾ŁˆŲ±Ł…ŲŖ Ų¦Ų§ Ł¾ŁŲ“ŲŖŪŒŁˆŲ§Ł†ŪŒ Ų¦Ł‡ Ł†Ł‡ Ś©Ł†ŲŖ .<br />\nŲ“Ł…Ų§ Ų¦Ł‡ ŲŖŁˆŲ§Ł†ŪŒŲŖ <a href=\"$1\">Ś©Ł‡ Ų§ŪŒ ŁˆŪŒŚˆŪŒŁˆ Ų¦Ų§ Ų§Ų¦ŪŒŲ± ŲØŚ©Ł†ŪŒŲŖ</a> Łˆ ŪŒŲ§ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ŪŒŚ© Ł¾Ų®Ų“ Ś©Ł†Ū†Ś©</a> Ų¦ŪŒ Ł¾Ł‡ Ų§ŪŒ ŁˆŪŒŚˆŪŒŁˆ ŪŒŪŒ Ų§Ų¬Ų±Ų§ Ų¦Ų§ Ų§Ų¦ŪŒŲ± ŲØŚ©Ł†ŪŒŲŖ.",
+ "timedmedia-source-file": "$1 Ų²Ł‡ŁŠ",
+ "timedmedia-source-audio-file-desc": "Ų§ŁˆŲ±Ų¬ŪŒŁ†Ų§Ł„ $1 ŁŲ§ŪŒŁ„ ( $2 )"
+}
diff --git a/extensions/TimedMediaHandler/i18n/bho.json b/extensions/TimedMediaHandler/i18n/bho.json
new file mode 100644
index 00000000..b562c221
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/bho.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "SatyamMishra"
+ ]
+ },
+ "timedmedia-source-audio-file-desc": "ą¤“ą¤°ą¤æą¤œą¤Øą¤² $1 ą¤«ą¤¾ą¤‡ą¤² ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/bn.json b/extensions/TimedMediaHandler/i18n/bn.json
new file mode 100644
index 00000000..d69249bb
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/bn.json
@@ -0,0 +1,48 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bellayet",
+ "Zaheen",
+ "Aftab1995",
+ "Aftabuzzaman"
+ ]
+ },
+ "timedmedia-ogg-short-audio": "ą¦…ą¦— $1 ą¦øą¦¾ą¦‰ą¦Øą§ą¦” ą¦«ą¦¾ą¦‡ą¦², $2",
+ "timedmedia-ogg-short-video": "ą¦…ą¦— $1 ą¦­ą¦æą¦”ą¦æą¦“ ą¦«ą¦¾ą¦‡ą¦², $2",
+ "timedmedia-ogg-short-general": "ą¦…ą¦— $1 ą¦®ą¦æą¦”ą¦æą¦Æą¦¼ą¦¾ ą¦«ą¦¾ą¦‡ą¦², $2",
+ "timedmedia-ogg-long-audio": "ą¦…ą¦— $1 ą¦øą¦¾ą¦‰ą¦Øą§ą¦” ą¦«ą¦¾ą¦‡ą¦², ą¦¦ą§ˆą¦°ą§ą¦˜ą§ą¦Æ $2, $3",
+ "timedmedia-ogg-long-video": "ą¦…ą¦— $1 ą¦­ą¦æą¦”ą¦æą¦“ ą¦«ą¦¾ą¦‡ą¦², ą¦¦ą§ˆą¦°ą§ą¦˜ą§ą¦Æ $2, $4Ɨ$5 ą¦Ŗą¦æą¦•ą§ą¦øą§‡ą¦², $3",
+ "timedmedia-ogg-long-multiplexed": "ą¦…ą¦— ą¦®ą¦¾ą¦²ą§ą¦Ÿą¦æą¦Ŗą§ą¦²ą§‡ą¦•ą§ą¦øą¦•ą§ƒą¦¤ ą¦…ą¦”ą¦æą¦“/ą¦­ą¦æą¦”ą¦æą¦“ ą¦«ą¦¾ą¦‡ą¦², $1, ą¦¦ą§ˆą¦°ą§ą¦˜ą§ą¦Æ $2, $4Ɨ$5 ą¦Ŗą¦æą¦•ą§ą¦øą§‡ą¦², $3 ą¦øą¦¾ą¦®ą¦—ą§ą¦°ą¦æą¦•",
+ "timedmedia-ogg-long-general": "ą¦…ą¦— ą¦®ą¦æą¦”ą¦æą¦Æą¦¼ą¦¾ ą¦«ą¦¾ą¦‡ą¦², ą¦¦ą§ˆą¦°ą§ą¦˜ą§ą¦Æ $2, $3",
+ "timedmedia-ogg-long-error": "ą¦…ą¦¬ą§ˆą¦§ ą¦…ą¦— ą¦«ą¦¾ą¦‡ą¦²: $1",
+ "timedmedia-mp4-short-video": "MP4 $1 ą¦­ą¦æą¦”ą¦æą¦“ ą¦«ą¦¾ą¦‡ą¦², $2",
+ "timedmedia-mp4-long-video": "MP4 ą¦…ą¦”ą¦æą¦“/ą¦­ą¦æą¦”ą¦æą¦“ ą¦«ą¦¾ą¦‡ą¦², $1, ą¦¦ą§ˆą¦°ą§ą¦˜ą§ą¦Æ $2, $4 Ɨ $5 ą¦Ŗą¦æą¦•ą§ą¦øą§‡ą¦², $3 ą¦øą¦¾ą¦®ą¦—ą§ą¦°ą¦æą¦•",
+ "timedmedia-no-player-js": "ą¦¦ą§ą¦ƒą¦–ą¦æą¦¤, ą¦†ą¦Ŗą¦Øą¦¾ą¦° ą¦¬ą§ą¦°ą¦¾ą¦‰ą¦œą¦¾ą¦°ą§‡ ą¦œą¦¾ą¦­ą¦¾ą¦øą§ą¦•ą§ą¦°ą¦æą¦Ŗą§ą¦Ÿ ą¦Øą¦æą¦·ą§ą¦•ą§ą¦°ą¦æą¦Æą¦¼ ą¦•ą¦°ą¦¾ ą¦†ą¦›ą§‡ ą¦…ą¦„ą¦¬ą¦¾ ą¦•ą§‹ą¦Øą§‹ ą¦øą¦®ą¦°ą§ą¦„ą¦æą¦¤ ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦° ą¦Øą§‡ą¦‡ą„¤ <br />\ną¦†ą¦Ŗą¦Øą¦æ ą¦†ą¦Ŗą¦Øą¦¾ą¦° ą¦¬ą§ą¦°ą¦¾ą¦‰ą¦œą¦¾ą¦°ą§‡ ą¦•ą§ą¦²ą¦æą¦Ŗą¦Ÿą¦æ ą¦šą¦¾ą¦²ą¦¾ą¦Øą§‹ą¦° ą¦œą¦Øą§ą¦Æ <a href=\"$1\">ą¦•ą§ą¦²ą¦æą¦Ŗą¦Ÿą¦æ ą¦”ą¦¾ą¦‰ą¦Øą¦²ą§‹ą¦” ą¦•ą¦°ą¦¤ą§‡ ą¦Ŗą¦¾ą¦°ą§‡ą¦Ø</a> ą¦¬ą¦¾ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ą¦ą¦•ą¦Ÿą¦æ ą¦Ŗą§ą¦²ą§‡ą¦Æą¦¼ą¦¾ą¦° ą¦”ą¦¾ą¦‰ą¦Øą¦²ą§‹ą¦”</a> ą¦•ą¦°ą¦¤ą§‡ ą¦Ŗą¦¾ą¦°ą§‡ą¦Øą„¤",
+ "timedmedia-more": "ą¦†ą¦°ą¦“...",
+ "timedmedia-dismiss": "ą¦¬ą¦Øą§ą¦§",
+ "timedmedia-download": "ą¦«ą¦¾ą¦‡ą¦² ą¦”ą¦¾ą¦‰ą¦Øą¦²ą§‹ą¦” ą¦•ą¦°ą§ą¦Ø",
+ "timedmedia-play-media": "ą¦®ą¦æą¦”ą¦æą¦Æą¦¼ą¦¾ ą¦šą¦¾ą¦²ą¦¾ą¦Ø",
+ "timedmedia-desc-link": "ą¦ą¦‡ ą¦«ą¦¾ą¦‡ą¦²ą§‡ą¦° ą¦¬ą§ƒą¦¤ą§ą¦¤ą¦¾ą¦Øą§ą¦¤",
+ "timedmedia-status-header": "ą¦Ÿą§ą¦°ą¦¾ą¦Øą§ą¦øą¦•ą§‹ą¦” ą¦…ą¦¬ą¦øą§ą¦„ą¦¾",
+ "timedmedia-update-status": "ą¦Ÿą§ą¦°ą¦¾ą¦Øą§ą¦øą¦•ą§‹ą¦” ą¦…ą¦¬ą¦øą§ą¦„ą¦¾ ą¦¹ą¦¾ą¦²ą¦Øą¦¾ą¦—ą¦¾ą¦¦ ą¦•ą¦°ą§ą¦Ø",
+ "timedmedia-status": "ą¦…ą¦¬ą¦øą§ą¦„ą¦¾",
+ "timedmedia-status-unknown": "ą¦…ą¦¬ą¦øą§ą¦„ą¦¾ ą¦…ą¦œą¦¾ą¦Øą¦¾",
+ "timedmedia-transcodeinfo": "ą¦¬ą§ą¦Æą§ą§Žą¦Ŗą¦Øą§ą¦Ø ą¦¬ą¦°ą§ą¦£ą¦Øą¦¾ ą¦Ÿą§ą¦°ą¦¾ą¦Øą§ą¦øą¦•ą§‹ą¦”",
+ "timedmedia-actions": "ą¦•ą¦¾ą¦°ą§ą¦Æ",
+ "timedmedia-direct-link": "ą¦¬ą§ą¦Æą§ą§Žą¦Ŗą¦Øą§ą¦Ø ą¦”ą¦¾ą¦‰ą¦Øą¦²ą§‹ą¦” ą¦•ą¦°ą§ą¦Ø",
+ "timedmedia-not-ready": "ą¦¤ą§ˆą¦°ą¦æ ą¦Øą¦Æą¦¼",
+ "timedmedia-percent-done": "ą¦Ŗą§ą¦°ą¦¾ą¦Æą¦¼ $1% ą¦•ą¦°ą¦¾ ą¦¹ą¦Æą¦¼ą§‡ą¦›ą§‡",
+ "timedmedia-days": "{{PLURAL:$1|ą§§ ą¦¦ą¦æą¦Ø|$1 ą¦¦ą¦æą¦Ø}}",
+ "timedmedia-hours": "{{PLURAL:$1|ą§§ ą¦˜ą¦£ą§ą¦Ÿą¦¾|$1 ą¦˜ą¦£ą§ą¦Ÿą¦¾}}",
+ "timedmedia-minutes": "{{PLURAL:$1|ą§§ ą¦®ą¦æą¦Øą¦æą¦Ÿ|$1 ą¦®ą¦æą¦Øą¦æą¦Ÿ}}",
+ "timedmedia-seconds": "{{PLURAL:$1|ą§§ ą¦øą§‡ą¦•ą§‡ą¦Øą§ą¦”|$1 ą¦øą§‡ą¦•ą§‡ą¦Øą§ą¦”}}",
+ "timedmedia-source-file": "$1 ą¦‰ą§Žą¦ø",
+ "timedmedia-source-audio-file-desc": "ą¦®ą§‚ą¦² $1 ą¦«ą¦¾ą¦‡ą¦² ($2)",
+ "timedmedia-derivative-desc-240p.ogv": "ą¦“ą¦Æą¦¼ą§‡ą¦¬ ą¦øą§ą¦Ÿą§ą¦°ą¦æą¦®ą¦Æą§‹ą¦—ą§ą¦Æ ą¦…ą¦— ą¦­ą¦æą¦”ą¦æą¦“ (ą§Øą§Ŗą§¦P)",
+ "timedmedia-subtitle-new-go": "ą¦Æą¦¾ą¦“",
+ "timedmedia-subtitle-language": "$1 ($2) ą¦øą¦¾ą¦¬ą¦Ÿą¦¾ą¦‡ą¦Ÿą§‡ą¦²",
+ "timedmedia-videos": "{{PLURAL:$1|$1ą¦Ÿą¦æ ą¦­ą¦æą¦”ą¦æą¦“}}",
+ "timedmedia-file": "ą¦«ą¦¾ą¦‡ą¦²",
+ "timedmedia-audios": "{{PLURAL:$1|$1ą¦Ÿą¦æ ą¦…ą¦”ą¦æą¦“ ą¦«ą¦¾ą¦‡ą¦²}}",
+ "action-transcode-status": "ą¦¬ą¦°ą§ą¦¤ą¦®ą¦¾ą¦Ø ą¦Ÿą§ą¦°ą¦¾ą¦Øą§ą¦øą¦•ą§‹ą¦”ą¦æą¦‚ą¦Æą¦¼ą§‡ą¦° ą¦…ą¦¬ą¦øą§ą¦„ą¦¾ ą¦¦ą§‡ą¦–ą§ą¦Ø"
+}
diff --git a/extensions/TimedMediaHandler/i18n/br.json b/extensions/TimedMediaHandler/i18n/br.json
new file mode 100644
index 00000000..dd74c0c5
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/br.json
@@ -0,0 +1,51 @@
+{
+ "@metadata": {
+ "authors": [
+ "Fohanno",
+ "Fulup",
+ "Y-M D"
+ ]
+ },
+ "timedmedia-desc": "Skor video, son ha testenn sinkronelaet gant ar furmadoĆ¹ WebM, Ogg Theora hag SRT skoret",
+ "timedmedia-ogg-short-audio": "Restr son Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Restr video Ogg $1, $2",
+ "timedmedia-ogg-short-general": "Restr media Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Restr son Ogg $1, pad $2, $3",
+ "timedmedia-ogg-long-video": "Restr video Ogg $1, pad $2, $4Ɨ$5 piksel, $3",
+ "timedmedia-ogg-long-multiplexed": "Restr Ogg klevet/video liesplezhet $1, pad $2, $4Ɨ$5 piksel, $3 hollad",
+ "timedmedia-ogg-long-general": "Restr media Ogg, pad $2, $3",
+ "timedmedia-ogg-long-error": "Restr ogg direizh : $1",
+ "timedmedia-webm-short-video": "Restr video WebM $1, $2",
+ "timedmedia-webm-long-video": "Restr video/son WebM, $1, pad $2, $4 Ɨ $5 piksel, $3 en holl",
+ "timedmedia-no-player-js": "Ho tigarez, pe eo diweredekaet JavaScript war ho merdeer pen n'eo ket skoret lenner ebet gantaƱ.<br />\n<a href=\"$1\">PellgargaƱ ar c'hlip</a> a c'hallit pe <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">pellgargaƱ ul lenner</a> da lenn ar c'hlip gant ho merdeer.",
+ "timedmedia-more": "Muioc'h...",
+ "timedmedia-dismiss": "SerriƱ",
+ "timedmedia-download": "PellgargaƱ ar restr",
+ "timedmedia-play-media": "Lenn ar media",
+ "timedmedia-desc-link": "Diwar-benn ar restr-maƱ",
+ "timedmedia-oggThumb-version": "Rekis eo stumm $1 oggThumb, pe nevesoc'h, evit implijout OggHandler.",
+ "timedmedia-oggThumb-failed": "N'eo ket deuet a-benn oggThumb da grouiƱ ar munud.",
+ "timedmedia-status": "Statud",
+ "timedmedia-status-unknown": "Statud dianav",
+ "timedmedia-actions": "OberoĆ¹",
+ "timedmedia-not-ready": "N'eo ket prest",
+ "timedmedia-percent-done": "War-dro $1 % zo bet graet",
+ "timedmedia-days": "{{PLURAL:$1|1 devezh|$1 devezh}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 eurvezh|$1 eurvezh}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 vunutenn|$1 munutenn}}",
+ "timedmedia-seconds": "$1 {{PLURAL:$1|eilenn|eilenn}}",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Mammenn $1",
+ "timedmedia-source-file-desc": "Orin $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Restr orin $1 ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Video Ogg izelgas (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Video Ogg lennus war-eeun war ar Gwiad (360p)",
+ "timedmedia-derivative-desc-480p.ogv": "Video Ogg lennus war-eeun war ar Gwiad (480p)",
+ "timedmedia-derivative-desc-720p.ogv": "Video Ogg da bellgargaƱ gant ur c'halite a-feson (720p)",
+ "timedmedia-derivative-desc-360p.webm": "WebM lennus war-eeun eus ar Gwiad (360p)",
+ "timedmedia-derivative-desc-480p.webm": "WebM lennus war-eeun eus ar Gwiad (480p)",
+ "timedmedia-derivative-desc-720p.webm": "Video WebM da bellgargaƱ gant ur c'halite a-feson (720p)",
+ "timedmedia-subtitle-new-go": "Mont",
+ "timedmedia-subtitle-language": "istitloĆ¹ e $1 ($2)",
+ "timedmedia-file": "Restr"
+}
diff --git a/extensions/TimedMediaHandler/i18n/bs.json b/extensions/TimedMediaHandler/i18n/bs.json
new file mode 100644
index 00000000..144f854e
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/bs.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "CERminator",
+ "Palapa",
+ "Semso98"
+ ]
+ },
+ "timedmedia-desc": "Upravljač za zvuk, video i vremenski tekst sa podrŔkom formata za WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Ogg $1 zvučna datoteka, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 video datoteka, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 medijalna datoteka, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 zvučna datoteka, dužina $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 video datoteka, dužina $2, $4Ɨ$5 piksela, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg multipleksna zvučna/video datoteka, $1, dužina $2, $4Ɨ$5 piksela, $3 sveukupno",
+ "timedmedia-ogg-long-general": "Ogg medijalna datoteka, dužina $2, $3",
+ "timedmedia-ogg-long-error": "Nevaljana ogg datoteka: $1",
+ "timedmedia-wav-long-audio": "WAV audio datoteka, dužina $1, $2 sveukupno",
+ "timedmedia-wav-pcm-required": "Možete postaviti samo PCM (Pulse Code Modulation) WAV.",
+ "timedmedia-no-player-js": "Žao nam je, vaÅ” preglednik ili je onemogućio JavaScript ili nema nijednog podržanog playera.<br />\nMožete <a href=\"$1\">učitati klip</a> ili <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">učitati player</a> za reproduciranje klipa u vaÅ”em pregledniku.",
+ "timedmedia-more": "ViŔe...",
+ "timedmedia-dismiss": "Zatvori",
+ "timedmedia-download": "Učitaj datoteku",
+ "timedmedia-desc-link": "O ovoj datoteci",
+ "timedmedia-oggThumb-version": "OggHandler zahtijeva oggThumb verziju $1 ili kasniju.",
+ "timedmedia-oggThumb-failed": "oggThumb nije uspio napraviti smanjeni pregled.",
+ "timedmedia-source-file": "$1 izvor",
+ "timedmedia-source-file-desc": "Originalna $1 datoteka, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Originalna $1 datoteka ($2)",
+ "timedmedia-subtitle-language": "$1 ($2) podnaslovi"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ca.json b/extensions/TimedMediaHandler/i18n/ca.json
new file mode 100644
index 00000000..6a72f2d0
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ca.json
@@ -0,0 +1,44 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aleator",
+ "Alvaro Vidal-Abarca",
+ "Paucabot",
+ "Pitort",
+ "SMP",
+ "Toniher",
+ "Vriullop",
+ "Joan manel",
+ "Macofe"
+ ]
+ },
+ "timedmedia-desc": "Gestor de fitxers de vĆ­deo, Ć udio i text sincronitzat amb suport pels formats WebM, Ogg Theora, Vorbi i srt",
+ "timedmedia-ogg-short-audio": "Fitxer OGG d'Ć udio $1, $2",
+ "timedmedia-ogg-short-video": "Fitxer OGG de vĆ­deo $1, $2",
+ "timedmedia-ogg-short-general": "Fitxer multimĆØdia OGG $1, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 fitxer de so, llargada $2, $3",
+ "timedmedia-ogg-long-video": "Fitxer OGG de vƭdeo $1, llargada $2, $4Ɨ$5 pƭxels, $3",
+ "timedmedia-ogg-long-multiplexed": "Arxiu Ơudio/vƭdeo multiplex, $1, llargada $2, $4Ɨ$5 pƭxels, $3 de mitjana",
+ "timedmedia-ogg-long-general": "Fitxer multimĆØdia OGG, llargada $2, $3",
+ "timedmedia-ogg-long-error": "Fitxer OGG invĆ lid: $1",
+ "timedmedia-no-player-js": "Ho sentim, el vostre navegador tĆ© el JavaScript desactivat o bĆ© no tĆ© cap reproductor compatible instalĀ·lat.<br />\nPodeu <a href=\"<span class=\" notranslate\"=\"\" translate=\"no\">$1</span>\">descarregar el clip</a> o <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">descarregar un reproductor</a> per a veure el vĆ­deo al vostre navegador.",
+ "timedmedia-more": "MĆ©s...",
+ "timedmedia-dismiss": "Tanca",
+ "timedmedia-download": "Descarrega el fitxer",
+ "timedmedia-desc-link": "InformaciĆ³ del fitxer",
+ "timedmedia-transcodeinfo": "Format",
+ "timedmedia-direct-link": "Descarregar",
+ "timedmedia-days": "{{PLURAL:$1|1 dia|$1 dies}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 hora|$1 hores}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minut|$1 minuts}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 segon|$1 segons}}",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Font $1",
+ "timedmedia-source-file-desc": "Arxiu original $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Fitxer original $1 ($2)",
+ "timedmedia-subtitle-language": "$1 ($2) subtĆ­tols",
+ "timedmedia-videos": "{{PLURAL:$1|$1 vĆ­deo|$1 vĆ­deos}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 vĆ­deo Ogg|$1 vĆ­deos Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 vĆ­deo WebM|$1 vĆ­deosWebM}}",
+ "timedmedia-file": "Fitxer"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ce.json b/extensions/TimedMediaHandler/i18n/ce.json
new file mode 100644
index 00000000..e6af995d
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ce.json
@@ -0,0 +1,85 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sasan700",
+ "Š£Š¼Š°Ń€"
+ ]
+ },
+ "timedmedia-desc": "WebM, Ogg Theora, Vorbis, srt фŠ¾Ń€Š¼Š°Ń‚Š°Ńˆ Š»Š¾Š²Ńˆ Š°ŃƒŠ“ŠøŠ¾, Š²ŠøŠ“ŠµŠ¾ Š°, суŠ±Ń‚ŠøтрŠ°Ńˆ Š° ŠŗŠµŃ‡ŠµŃ€Š³",
+ "timedmedia-ogg-short-audio": "ŠŃŒŠ·Š½ŠøŠ¹Š½ фŠ°Š¹Š» Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Š’ŠøŠ“ŠµŠ¾-фŠ°Š¹Š» Ogg $1, $2",
+ "timedmedia-ogg-short-general": "ŠœŠµŠ“ŠøŠ°-фŠ°Š¹Š» Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Š°ŃŒŠ·Š½ŠøŠ¹Š½ фŠ°Š¹Š» Ogg $1, Š“Š¾Ń…Š°Š»Š»Š° (хŠ°Š½) $2, $3",
+ "timedmedia-ogg-long-video": "Š²ŠøŠ“ŠµŠ¾-фŠ°Š¹Š» Ogg $1, Š¹Š¾Ń…Š°Š»Š»Š° $2, $4 Ɨ $5 {{PLURAL:$5|ŠæŠøŠŗсŠµŠ»ŃŒ}}, $3",
+ "timedmedia-ogg-long-multiplexed": "Š¼ŃƒŠ»ŃŒŃ‚ŠøŠæŠ»ŠµŠŗŠ°Š½ Š°ŃƒŠ“ŠøŠ¾/Š²ŠøŠ“ŠµŠ¾-фŠ°Š¹Š» Ogg, $1, Š¹Š¾Ń…Š°Š»Š»Š° $2, $4Ɨ$5 ŠæŠøŠŗсŠµŠ»ŃŒ, $3 ŠµŃ€Ń€ŠøŠ³",
+ "timedmedia-ogg-long-general": "Š¼ŠµŠ“ŠøŠ°-фŠ°Š¹Š» Ogg, Š¹Š¾Ń…Š°Š»Š»Š° $2, $3",
+ "timedmedia-ogg-long-error": "Š½ŠøŠ¹ŃŠ° Š¹Š¾Ń†Ńƒ Ogg-фŠ°Š¹Š»: $1",
+ "timedmedia-ogg-long-no-streams": "ŠœŃƒŠ»ŃŒŃ‚ŠøŠ¼ŠµŠ“ŠøŠ°-фŠ°Š¹Š» ogg. Š”Ó€Š°Ń…ŃŒŠµŠ“Š°Ń€: Š„ӀŠ¾Šŗху фŠ°Š¹Š»Š°Ń Š»ŠµŠ»Š¾Ńˆ Š¹Š¾Š»Ńƒ цхьŠ° ŠŗŠ¾Š“ŠµŠŗ Š±ŠøŠ»Š³Š°Š»Š¹ŠøŠ½Š° яц.",
+ "timedmedia-webm-short-video": "WebM $1 Š²ŠøŠ“ŠµŠ¾-фŠ°Š¹Š», $2",
+ "timedmedia-webm-long-video": "WebM Š°ŃƒŠ“ŠøŠ¾/Š²ŠøŠ“ŠµŠ¾ фŠ°Š¹Š», $1, Š¹Š¾Ń…Š°Š»Š»Š° $2, $4 Ɨ $5 {{PLURAL:$5|ŠæŠøŠŗсŠµŠ»ŃŒ}}, ŠµŃ€Ń€ŠøŠ³ $3",
+ "timedmedia-flac-short-audio": "ŠŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š» FLAC, $1",
+ "timedmedia-flac-long-audio": "ŠŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š» FLAC, Š¹Š¾Ń…Š°Š»Š»Š° ā€” $1, Š±ŠøтрŠµŠ¹Ń‚ ā€” $2",
+ "timedmedia-wav-short-audio": "ŠŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š» FLAC, $1",
+ "timedmedia-wav-long-audio": "ŠŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š» WAV, Š¹Š¾Ń…Š°Š»Š»Š° ā€” $1, Š±ŠøтрŠµŠ¹Ń‚ ā€” $2",
+ "timedmedia-wav-pcm-required": "ŠŃ…ŃŒŠ° чуяŠŗŠŗхŠ° Š¼ŠµŠ³Š° PCM (Pulse Code Modulation) WAV.",
+ "timedmedia-mp4-short-video": "WebM $1 Š²ŠøŠ“ŠµŠ¾-фŠ°Š¹Š», $2",
+ "timedmedia-mp4-long-video": "ŠŃƒŠ“ŠøŠ¾/Š²ŠøŠ“ŠµŠ¾Ń„Š°Š¹Š» MP4 $1, Š¹Š¾Ń…Š°Š»Š»Š° ā€” $2, $4 Ɨ $5 ŠæŠøŠŗсŠµŠ»ŃŒ, Š±ŠøтрŠµŠ¹Ń‚ ā€” $3",
+ "timedmedia-more": "Š”ŃƒŠŗхŠ°ā€¦",
+ "timedmedia-dismiss": "ŠšŃŠŠ°Š¹Š»Š°ŃŠŗŠŗхŠ°",
+ "timedmedia-download": "Š¤Š°Š¹Š» чуяŠŗŠŗхŠ°Ń€",
+ "timedmedia-play-media": "Š™Š¾Š»Š°ŃŠ»ŠøŠ¹Ń‚Š° Š¼ŠµŠ“ŠøŠ°-фŠ°Š¹Š»",
+ "timedmedia-desc-link": "Š„ӀŠ¾Šŗху фŠ°Š¹Š»Š°Ń… Š»Š°ŃŒŃ†Š½Š° хŠ°Š°Š¼",
+ "timedmedia-oggThumb-failed": "oggThumb тŠ°Ń€ цŠ°Š“ŠµŠ»ŠøрŠ° Š¼ŠøŠ½ŠøŠ°Ń‚ŃŽŃ€Š° ŠŗхŠ¾Š»Š»Š°.",
+ "timedmedia-status-header": "Š®Ń…Ńƒ ŠŗŠ¾Š“ярŠ°Š½ хьŠ°Š»",
+ "timedmedia-update-status": "Š®Ń…Ńƒ ŠŗŠ¾Š“ярŠ°Š½ стŠ°Ń‚ŃƒŃ ŠŗŠ°Ń€Š»Š°ŃŠŗŠŗхŠ°",
+ "timedmedia-status": "Š„ьŠ°Š»",
+ "timedmedia-status-unknown": "Š¦Š° Š“Š¾Š²Š·Š° хьŠ°Š»",
+ "timedmedia-transcodeinfo": "Š®Ń…Ńƒ ŠŗŠ¾Š“ярŠ°Ń… Š»Š°ŃŒŃ†Š½Š°",
+ "timedmedia-actions": "Š”ŠøŠ¹Ń€Š°Ńˆ",
+ "timedmedia-direct-link": "Š§ŃƒŃŠŗŠŗхŠ° Š¼Š¾Š“ŠøфŠøцŠøрŠ¾Š²Š°Ń‚ Š¹ŠøŠ½Š° Š²Š°Ń€ŠøŠ°Š½Ń‚",
+ "timedmedia-not-ready": "ŠšŠøŠ¹Ń‡Š° яц",
+ "timedmedia-completed-on": "$1 юху ŠŗŠ¾Š“яр чŠµŠŗхŠ“ŠµŠ»Šø",
+ "timedmedia-error-on": "$1 юху ŠŗŠ¾Š“ъŠµŃˆ Š³Ó€Š°Š»Š°Ń‚",
+ "timedmedia-started-transcode": "Š®Ń…Ńƒ ŠŗŠ¾Š“яр Š“Š¾Š»Š° Š“Š°Š»ŠøŠ¹Ń‚ŠøŠ½Š° $1 хьŠ°Š»Ń…Š°. $2",
+ "timedmedia-percent-done": "Š“ŠµŃ€Š³Š³Š°Ń€Š° хьŠµŃŠ°ŠæŠµŃ…ŃŒ $1% ŠŗхŠ¾Ń‡ŃƒŃˆŠ“ŠøŠ½Š°",
+ "timedmedia-in-job-queue": "Š”Š° Š“ŠµŠ·Š°Ń€Š³ $1 хьŠ°Š»Ń…Š¾ рŠ¾Š³Ó€Šµ Š“ŠøŠ»Š»ŠøŠ½Š°",
+ "timedmedia-days": "{{PLURAL:$1|$1 Š“Šµ}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 сŠ°Ń…ŃŒŃ‚}}",
+ "timedmedia-minutes": "{{PLURAL:$1|$1 Š¼ŠøŠ½Š¾Ń‚}}",
+ "timedmedia-seconds": "{{PLURAL:$1|$1 сŠµŠŗуŠ½Š“}}",
+ "timedmedia-reset": "Š®Ń…Ńƒ ŠŗŠ¾Š“яр тӀŠµŃ…Š“Š°Š»ŠøŠ¹Ń‚Š°Ń€",
+ "timedmedia-reset-error": "Š®Ń…Ńƒ ŠŗŠ¾Š“ъŠµŃˆ Š³Ó€Š°Š»Š°Ń‚.",
+ "timedmedia-source-file": "Š„ьŠ¾ŃŃ‚ $1",
+ "timedmedia-source-file-desc": "ŠžŃ€ŠøŠ³ŠøŠ½Š°Š» $1 фŠ°Š¹Š»Š°Š½, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "ŠžŃ€ŠøŠ³ŠøŠ½Š°Š»Š°Š½ $1-фŠ°Š¹Š» ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Ogg-Š²ŠøŠ“ŠµŠ¾ Š“ŠøŠŗŠ° Š¹Š¾Ń†Ńƒ (160p)",
+ "timedmedia-derivative-desc-360p.ogv": "ŠœŠ¾Š³Ó€Š°Š¼Š°Š½ Ogg-Š²ŠøŠ“ŠµŠ¾ (360p)",
+ "timedmedia-derivative-desc-480p.ogv": "ŠœŠ¾Š³Ó€Š°Š¼Š°Š½ Ogg-Š²ŠøŠ“ŠµŠ¾ (480p)",
+ "timedmedia-derivative-desc-720p.ogv": "Ogg-Š²ŠøŠ“ŠµŠ¾ Š“ŠøŠŗŠ° (720p)",
+ "timedmedia-derivative-desc-160p.webm": "ŠœŠ¾Š³Ó€Š°Š¼Š°Š½ WebM-Š²ŠøŠ“ŠµŠ¾ (160p)",
+ "timedmedia-derivative-desc-360p.webm": "ŠœŠ¾Š³Ó€Š°Š¼Š°Š½ WebM-Š²ŠøŠ“ŠµŠ¾ (360p)",
+ "timedmedia-derivative-desc-480p.webm": "ŠœŠ¾Š³Ó€Š°Š¼Š°Š½ WebM-Š²ŠøŠ“ŠµŠ¾ (480p)",
+ "timedmedia-derivative-desc-720p.webm": "WebM-Š²ŠøŠ“ŠµŠ¾ Š“ŠøŠŗŠ° (720p)",
+ "timedmedia-derivative-desc-320p.mp4": "MP4 (320P) ŠŗŠµŃ‡ŃŃ€",
+ "timedmedia-derivative-desc-480p.mp4": "ŠœŠ¾Š³Ó€Š°Š¼Š°Š½ MP4-Š²ŠøŠ“ŠµŠ¾ (480p)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 HD-Š“ŠøŠŗŠ°Š»Š»ŠøцŠ° (720P)",
+ "timedmedia-subtitle-new-go": "ŠšŃ…Š¾Ń‡ŃƒŃˆŠ“Ć©",
+ "timedmedia-subtitle-language": "$1 ($2) суŠ±Ń‚ŠøтрŠ°Ńˆ",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 Š²ŠøŠ“ŠµŠ¾-фŠ°Š¹Š»|$1 Š²ŠøŠ“ŠµŠ¾-фŠ°Š¹Š»Š°Ńˆ}}",
+ "timedmedia-ogg-videos": "$1 Ogg Š²ŠøŠ“ŠµŠ¾{{PLURAL:$1|фŠ°Š¹Š»}}",
+ "timedmedia-webm-videos": "$1 WebM Š²ŠøŠ“ŠµŠ¾{{PLURAL:$1|фŠ°Š¹Š»}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 юху ŠŗŠ¾Š“яр}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 юху ŠŗŠ¾Š“яр Š“Š¾Š»Š°Š“Š°Š»ŠøŠ¹Ń‚Š°Ń€}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 юху ŠŗŠ¾Š“ярŠ°Š½ рŠ¾Š³Ó€ŠµŃ…ŃŒ ю}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 ŠŗхŠ¾Ń‡ŃƒŃˆ цŠ° хŠøŠ»Š»Š° юху ŠŗŠ¾Š“яр}}",
+ "timedmedia-file": "Š¤Š°Š¹Š»",
+ "timedmedia-audios": "{{PLURAL:$1|$1 Š°ŃƒŠ“ŠøŠ¾-фŠ°Š¹Š»|$1 Š°ŃƒŠ“ŠøŠ¾-фŠ°Š¹Š»Š°Ńˆ}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Š°ŃƒŠ“ŠøŠ¾-фŠ°Š¹Š» Ogg|$1 Š°ŃƒŠ“ŠøŠ¾-фŠ°Š¹Š»Š°Ńˆ Ogg}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 Š°ŃƒŠ“ŠøŠ¾-фŠ°Š¹Š» FLAC|$1 Š°ŃƒŠ“ŠøŠ¾-фŠ°Š¹Š»Š°Ńˆ FLAC}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 Š°ŃƒŠ“ŠøŠ¾-фŠ°Š¹Š» WAV|$1 Š°ŃƒŠ“ŠøŠ¾-фŠ°Š¹Š»Š°Ńˆ WAV}}",
+ "right-transcode-reset": "ŠšŃ…Š¾ŃŃŠ° Š“ŠøŠŗŠ° Š¹Š¾Ń†Ńƒ Š²ŠøŠ“ŠµŠ¾Ńˆ уьш рŠ¾Š³Ó€ŠµŃ…ŃŒ хŠøŠ»ŠøŠ¹Ń‚Š°.",
+ "right-transcode-status": "Š„ьŠ°Š¶Š° [[Special:TimedMediaHandler|юху ŠŗŠ¾Š“ хŠøŠ¹Ń†Š°Ń€Š°Š½ хŠ°Š°Š¼Šµ]]",
+ "orphanedtimedtext": "ŠÆŠ¹Š½Š° Š°Š³Ó€Š¾Š½Š°Ńˆ TimedText",
+ "orphanedtimedtext-notimedtext": "TimedText хӀŠ¾Šŗху Š²ŠøŠŗŠø чŠ¾Ń…ŃŒ Š»Š°Ń‚ŠøŠ½Š° Š“Š°Ń†."
+}
diff --git a/extensions/TimedMediaHandler/i18n/ckb.json b/extensions/TimedMediaHandler/i18n/ckb.json
new file mode 100644
index 00000000..4a345dc0
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ckb.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Calak",
+ "Asoxor",
+ "Muhammed taha"
+ ]
+ },
+ "timedmedia-no-player-js": "ŲØŲØŁˆŁˆŲ±Ū•ŲŒ ŁˆŪŽŲØŚÆŪ•Ų±Ū•Ś©Ū•ŲŖ ŪŒŲ§Ł† JavaScript Ł„Ū• Ś©Ų§Ų± Ų®Ų³ŲŖŁˆŁˆŪ• ŪŒŲ§Ł† playerŪŒ Ł¾ŪŽŁˆŪŒŲ³ŲŖŪŒ Ł†ŪŒŪŒŪ•.<br />\nŲÆŪ•ŲŖŁˆŲ§Ł†ŪŒŲŖ <a href=\"$1\">Ś©Ł„ŪŒŁ¾Ū•Ś©Ū• ŲÆŲ§ŚÆŲ±ŪŒŲŖ</a> ŪŒŲ§Ł† <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">playerŪŽŚ© ŲÆŲ§ŚÆŲ±ŪŒŲŖ</a> ŲØŪ† Ų¦Ū•ŁˆŪ•ŪŒ Ł„Ū• ŁˆŪŽŲØŚÆŪ•Ś•Ū•Ś©Ū•ŲŖŲÆŲ§ ŲØŪŒŲ®Ū•ŪŒŲŖŪ• Ų³Ū•Ų±.",
+ "timedmedia-source-file": "$1 Ų³Ū•Ų±Ś†Ų§ŁˆŪ•",
+ "timedmedia-source-audio-file-desc": "Ł¾Ū•Ś•ŚÆŪ•ŪŒ $1 ŲØŁ†Ū•Ś•Ū•ŲŖŪŒ ($2)",
+ "right-transcode-reset": "Ś•ŪŽŚ©Ų®Ų³ŲŖŁ†Ū•ŁˆŪ•ŪŒ Ś¤ŪŒŲÆŪŒŪ† Ų³Ū•Ų±Ł†Ū•Ś©ŁˆŲŖŁˆŁˆŪ•Ś©Ų§Ł† ŪŒŲ§Ł† ŲŖŲ±Ų§Ł†Ų³Ś©Ū†ŲÆŚ©Ų±Ų§ŁˆŪ•Ś©Ų§Ł† Ś¾Ū•ŲŖŲ§ ŲÆŪŒŲ³Ų§Ł† ŲØŚ†Ł†Ū•ŁˆŪ• Ł†Ų§Łˆ Ś•ŪŒŲ²ŪŒ Ś©Ų§Ų±Ū•ŁˆŪ•.",
+ "right-transcode-status": "ŲÆŪŒŲŖŁ†ŪŒ [[ŲŖŲ§ŪŒŲØŪ•ŲŖ:TimedMediaHandler|Ų²Ų§Ł†ŪŒŲ§Ų±ŪŒ Ł„Ū•Ł…Ū•Ś• Ś†Ų§Ł„Ų§Ś©ŪŒŪŒ ŲŖŲ±Ų§Ł†Ų³Ś©Ū†ŲÆŪŒ Ś¾Ū•Ł†ŁˆŁˆŚ©Ū•ŪŒŪŒ]]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/cs.json b/extensions/TimedMediaHandler/i18n/cs.json
new file mode 100644
index 00000000..69a2c0ca
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/cs.json
@@ -0,0 +1,75 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chmee2",
+ "Li-sung",
+ "Matěj GrabovskĆ½",
+ "Mormegil",
+ "Paxt",
+ "Matěj SuchĆ”nek"
+ ]
+ },
+ "timedmedia-desc": "Obsluha zvukÅÆ, videa a časovanĆ©ho textu s podporou formĆ”tÅÆ WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "ZvukovĆ½ soubor ogg $1, $2",
+ "timedmedia-ogg-short-video": "Videosoubor ogg $1, $2",
+ "timedmedia-ogg-short-general": "MultimediƔlnƭ soubor ogg $1, $2",
+ "timedmedia-ogg-long-audio": "ZvukovĆ½ soubor ogg $1, dĆ©lka $2, $3",
+ "timedmedia-ogg-long-video": "Videosoubor $1, dĆ©lka $2, $4Ɨ$5 pixelÅÆ, $3",
+ "timedmedia-ogg-long-multiplexed": "multiplexovanĆ½ audio/video soubor Ogg, $1, dĆ©lka $2, $4Ɨ$5 pixelÅÆ, celkem $3",
+ "timedmedia-ogg-long-general": "Soubor mƩdia ogg, dƩlka $2, $3",
+ "timedmedia-ogg-long-error": "ChybnĆ½ soubor ogg: $1",
+ "timedmedia-webm-short-video": "Videosoubor WebM $1, $2",
+ "timedmedia-webm-long-video": "audio/video soubor WebM, $1, dĆ©lka $2, $4Ɨ$5 pixelÅÆ, celkem $3",
+ "timedmedia-wav-pcm-required": "MÅÆžete načƭtat jen WAV soubory ve formĆ”tu PCM (pulse code modulation).",
+ "timedmedia-mp4-short-video": "Videosoubor MP4 $1, $2",
+ "timedmedia-mp4-long-video": "audio/video soubor MP4, $1, dĆ©lka $2, $4Ɨ$5 pixelÅÆ, celkem $3",
+ "timedmedia-no-player-js": "Je mi lĆ­to, ale vĆ”Å” prohlĆ­Å¾eč mĆ” buď vypnutĆ½ JavaScript, nebo nemĆ”te Å¾Ć”dnĆ½ podporovanĆ½ přehrĆ”vač.<br />\nMÅÆžete si <a href=\"$1\">stĆ”hnout klip</a> nebo si <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">stĆ”hnout přehrĆ”vač</a>, kterĆ½m si klip přehrajete v prohlĆ­Å¾eči.",
+ "timedmedia-more": "VĆ­ce...",
+ "timedmedia-dismiss": "ZavÅ™Ć­t",
+ "timedmedia-download": "StƔhnout soubor",
+ "timedmedia-play-media": "PřehrĆ”t mĆ©dia",
+ "timedmedia-desc-link": "O tomto souboru",
+ "timedmedia-oggThumb-version": "OggHandler vyžaduje oggThumb verze $1 nebo novějÅ”Ć­.",
+ "timedmedia-oggThumb-failed": "oggThumb nedokĆ”zal vytvořit nĆ”hled.",
+ "timedmedia-status-header": "Stav transkĆ³dovĆ”nĆ­",
+ "timedmedia-update-status": "Aktualizovat stav transkĆ³dovĆ”nĆ­",
+ "timedmedia-status": "Stav",
+ "timedmedia-status-unknown": "NeznĆ”mĆ½ stav",
+ "timedmedia-actions": "Akce",
+ "timedmedia-not-ready": "Nepřipraveno",
+ "timedmedia-completed-on": "TranskĆ³dovĆ”nĆ­ dokončeno v $1",
+ "timedmedia-error-on": "Chyba transkĆ³dovĆ”nĆ­ v $1",
+ "timedmedia-started-transcode": "TranskĆ³dovĆ”nĆ­ začalo před $1. $2",
+ "timedmedia-percent-done": "Hotovo asi $1 %",
+ "timedmedia-in-job-queue": "Před $1 přidĆ”no do fronty",
+ "timedmedia-unknown-target-size": "NeznĆ”mĆ” vĆ½slednĆ” velikost, zakĆ³dovĆ”no $1",
+ "timedmedia-days": "$1 {{PLURAL:$1|den|dny|dnĆ­}}",
+ "timedmedia-hours": "$1 {{PLURAL:$1|hodina|hodiny|hodin}}",
+ "timedmedia-minutes": "$1 {{PLURAL:$1|minuta|minuty|minut}}",
+ "timedmedia-seconds": "$1 {{PLURAL:$1|sekunda|sekundy|sekund}}",
+ "timedmedia-reset": "Obnovit transkĆ³dovĆ”nĆ­",
+ "timedmedia-source-file": "ZdrojovĆ½ soubor $1",
+ "timedmedia-source-audio-file-desc": "PÅÆvodnĆ­ soubor $1 ($2)",
+ "timedmedia-subtitle-new": "VytvořenĆ­ novĆ©ho překladu nebo editace stĆ”vajĆ­cĆ­ho",
+ "timedmedia-subtitle-new-desc": "Zvolte jazyk a stiskněte tlačƭtko '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "PřejĆ­t",
+ "timedmedia-subtitle-language": "titulky v jazyce $1 ($2)",
+ "timedmedia-subtitle-no-video": "K aktuĆ”lnĆ­ strĆ”nce titulkÅÆ nepatÅ™Ć­ Å¾Ć”dnĆ© video.",
+ "timedmedia-subtitle-no-subtitles": "K tomuto videu momentĆ”lně neexistujĆ­ titulky v jazyce $1, přidat je mÅÆžete [{{fullurl:{{FULLPAGENAME}}|action=edit}} editacĆ­ tĆ©to strĆ”nky]",
+ "timedmedia-subtitle-remote": "SynchronizovanĆ½ text k tomuto souboru je uložen na $1",
+ "timedmedia-subtitle-remote-link": "[$1 StrĆ”nku s popisem tohoto souboru] si mÅÆžete prohlĆ©dnout na $2",
+ "timedmedia-videos": "{{PLURAL:$1|$1 video|$1 videa|$1 videĆ­}}",
+ "timedmedia-ogg-videos": "$1 {{PLURAL:$1|video|videa|videĆ­}} Ogg",
+ "timedmedia-webm-videos": "$1 {{PLURAL:$1|video|videa|videĆ­}} WebM",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transkĆ³dovĆ”nĆ­}}",
+ "timedmedia-derivative-state-active": "$1 {{PLURAL:$1|probĆ­hajĆ­cĆ­|probĆ­hajĆ­cĆ­|probĆ­hajĆ­cĆ­ch}} transkĆ³dovĆ”nĆ­",
+ "timedmedia-derivative-state-queued": "$1 {{PLURAL:$1|naplĆ”novanĆ©|naplĆ”novanĆ”|naplĆ”novanĆ½ch}} transkĆ³dovĆ”nĆ­",
+ "timedmedia-derivative-state-failed": "$1 {{PLURAL:$1|neĆŗspěŔnĆ©|neĆŗspěŔnĆ”|neĆŗspěŔnĆ½ch}} transkĆ³dovĆ”nĆ­",
+ "timedmedia-file": "Soubor",
+ "timedmedia-audios": "{{PLURAL:$1|$1 zvukovĆ½ soubor|$1 zvukovĆ© soubory|$1 zvukovĆ½ch souborÅÆ}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 zvukovĆ½ soubor|$1 zvukovĆ© soubory|$1 zvukovĆ½ch souborÅÆ}} Ogg",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 zvukovĆ½ soubor|$1 zvukovĆ© soubory|$1 zvukovĆ½ch souborÅÆ}} FLAC",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 zvukovĆ½ soubor|$1 zvukovĆ© soubory|$1 zvukovĆ½ch souborÅÆ}} WAV",
+ "right-transcode-status": "ZobrazenĆ­ [[Special:TimedMediaHandler|informacĆ­ o probĆ­hajĆ­cĆ­m transkĆ³dovĆ”nĆ­]]",
+ "action-transcode-status": "vidět aktuĆ”lnĆ­ stav transkĆ³dovĆ”nĆ­"
+}
diff --git a/extensions/TimedMediaHandler/i18n/cu.json b/extensions/TimedMediaHandler/i18n/cu.json
new file mode 100644
index 00000000..5221b9ed
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/cu.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "ŠžŠ¹Š›"
+ ]
+ },
+ "timedmedia-dismiss": "ź™Š°Šŗрź™‘Šø",
+ "timedmedia-source-file": "$1 ŠŗŠ»Š°Š“ѧź™ƒŃŒ",
+ "timedmedia-file": "Š“Ń£Š»Š¾"
+}
diff --git a/extensions/TimedMediaHandler/i18n/cv.json b/extensions/TimedMediaHandler/i18n/cv.json
new file mode 100644
index 00000000..93c188e0
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/cv.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chuvash2014"
+ ]
+ },
+ "timedmedia-more": "ŠŃƒŠ¼Š°Š¹Ń€Š°Ń…ā€¦"
+}
diff --git a/extensions/TimedMediaHandler/i18n/cy.json b/extensions/TimedMediaHandler/i18n/cy.json
new file mode 100644
index 00000000..5ffa296c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/cy.json
@@ -0,0 +1,50 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lloffiwr",
+ "Ham II",
+ "Xxglennxx"
+ ]
+ },
+ "timedmedia-ogg-short-audio": "Ffeil sain Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Ffeil fideo Ogg $1, $2",
+ "timedmedia-ogg-short-general": "Ffeil gyfrwng Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Ffeil sain Ogg $1, yn para $2, $3",
+ "timedmedia-ogg-long-video": "Ffeil fideo Ogg $1, yn para $2, $4 Ɨ $5 picsel, $3",
+ "timedmedia-ogg-long-error": "Ffeil Ogg annilys: $1",
+ "timedmedia-more": "Mwyā€¦",
+ "timedmedia-dismiss": "Caeer",
+ "timedmedia-download": "Lawrlwytho ffeil",
+ "timedmedia-play-media": "Chwarae'r ffeil gyfrwng",
+ "timedmedia-desc-link": "YnglÅ·n Ć¢'r ffeil hon",
+ "timedmedia-status-header": "Statws trawsgodio",
+ "timedmedia-update-status": "Diweddaru'r statws trawsgodio",
+ "timedmedia-status": "Statws",
+ "timedmedia-status-unknown": "Statws anhysbys",
+ "timedmedia-actions": "Gweithredoedd",
+ "timedmedia-not-ready": "Ddim yn barod",
+ "timedmedia-started-transcode": "Dechreuodd y trawsgodio $1 yn Ć“l. $2",
+ "timedmedia-percent-done": "Tua $1% wedi ei wneud",
+ "timedmedia-in-job-queue": "Ychwanegwyd i'r ciw tasgiau $1 yn Ć“l",
+ "timedmedia-unknown-target-size": "Maint anhysbys i'r gwrthrych, $1 wedi ei amgodio",
+ "timedmedia-days": "{{PLURAL:$1|$1 diwrnod|diwrnod|deuddydd|tridiau|$1 diwrnod}}",
+ "timedmedia-hours": "{{PLURAL:$1|$1 awr}}",
+ "timedmedia-minutes": "{{PLURAL:$1|$1 munud|$1 munud|$1 funud|$1 munud}}",
+ "timedmedia-seconds": "{{PLURAL:$1|$1 eiliad}}",
+ "timedmedia-reset": "Ailosod y trawsgodio",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "ffynhonnell $1",
+ "timedmedia-source-file-desc": "Y ffeil $1 gwreiddiol, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Y ffeil $1 gwreiddiol ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Fideo Ogg (160P) o led band isel",
+ "timedmedia-subtitle-new-desc": "Dewiswch iaith a gwasgu'r botwm '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Gwneler",
+ "timedmedia-subtitle-language": "Isdeitlau $1 ($2)",
+ "timedmedia-subtitle-remote-link": "Gallwch [$1 weld tudalen ddisgrifio'r] ffeil hon ar $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 fideo}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 fideo Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 fideo WebM}}",
+ "timedmedia-file": "Ffeil",
+ "action-transcode-status": "gweld statws presennol y trawsgodio"
+}
diff --git a/extensions/TimedMediaHandler/i18n/da.json b/extensions/TimedMediaHandler/i18n/da.json
new file mode 100644
index 00000000..c9864945
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/da.json
@@ -0,0 +1,100 @@
+{
+ "@metadata": {
+ "authors": [
+ "Byrial",
+ "Christian List",
+ "Fnielsen",
+ "HenrikKbh",
+ "Jon Harald SĆøby",
+ "Peter Alberti",
+ "Simeondahl",
+ "Steenth"
+ ]
+ },
+ "timedmedia-desc": "UnderstĆøttelse for lyd, video og tidsbestemt txt med formaterne WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Ogg $1 lydfil, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 videofil, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 mediafil, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 lydfil, lƦngde $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 videofil, lƦngde $2, $4Ɨ$5 pixel, $3",
+ "timedmedia-ogg-long-multiplexed": "Sammensat Ogg-lyd- og -videofil, $1, lƦngde $2, $4Ɨ$5 pixel, $3 samlet",
+ "timedmedia-ogg-long-general": "Ogg mediafil, lƦngde $2, $3",
+ "timedmedia-ogg-long-error": "Ugyldig Ogg-fil: $1",
+ "timedmedia-webm-short-video": "WebM $1 videofil, $2",
+ "timedmedia-webm-long-video": "WebM audio/video fil, $1, lƦngde $2, $4 Ɨ $5 pixel, $3 samlet",
+ "timedmedia-flac-short-audio": "FLAC lydfil, $1",
+ "timedmedia-flac-long-audio": "FLAC lydfil, varighed $1, $2 samlet",
+ "timedmedia-wav-short-audio": "WAV lydfil, $1",
+ "timedmedia-wav-long-audio": "WAV lydfil, varighed $1, $2 samlet",
+ "timedmedia-wav-pcm-required": "Du kan kun uploade PCM (Pulse Code Modulation) WAV.",
+ "timedmedia-mp4-short-video": "Mp4 $1 videofil, $2",
+ "timedmedia-mp4-long-video": "Mp4-fil for audio/video, $1, lƦngde $2, $4 Ɨ $5 pixel, $3 samlet",
+ "timedmedia-no-player-js": "Beklager, men din browser har enten deaktiveret JavaScript eller har ikke en afspiller, som vi understĆøtter.<br />\nDu kan enten <a href=\"$1\">hente klippet</a> eller <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">hente en afspiller</a> til at afspille klippet i din browser.",
+ "timedmedia-more": "Mere...",
+ "timedmedia-dismiss": "Luk",
+ "timedmedia-download": "Download fil",
+ "timedmedia-play-media": "Afspil medier",
+ "timedmedia-desc-link": "Om denne fil",
+ "timedmedia-oggThumb-version": "OggHandler krƦver oggThumb version $1 eller nyere.",
+ "timedmedia-oggThumb-failed": "oggThumb kunne ikke oprette et miniaturebillede.",
+ "timedmedia-status-header": "Transcode status",
+ "timedmedia-update-status": "Opdater transcode status",
+ "timedmedia-status": "Status",
+ "timedmedia-status-unknown": "Ukendt status",
+ "timedmedia-transcodeinfo": "Afledt transcode beskrivelse",
+ "timedmedia-actions": "Handlinger",
+ "timedmedia-direct-link": "Hent derivat",
+ "timedmedia-not-ready": "Ikke klar",
+ "timedmedia-completed-on": "GennemfĆørt transcode $1",
+ "timedmedia-error-on": "Fejl i omkodning ved $1",
+ "timedmedia-started-transcode": "Kode startet $1 siden. $2",
+ "timedmedia-percent-done": "Cirka $1 % udfĆørt",
+ "timedmedia-in-job-queue": "FĆøjet til jobkĆøen $1 siden",
+ "timedmedia-unknown-target-size": "Ukendt mĆ„l stĆørrelse, $1 kodet",
+ "timedmedia-days": "{{PLURAL:$1|$1 dag|$1 dage}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 time|$1 timer}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minut|$1 minutter}}",
+ "timedmedia-seconds": "{{PLURAL:$1|$1 sekund|$1 sekunder}}",
+ "timedmedia-reset": "Nulstil transkode",
+ "timedmedia-reset-confirm": "Nulstilling af denne omkodning vil fjerne alle eksisterende filer (hvis der er nogen), og vil genindsƦtte omkodningen i jobkĆøen. Det vil tage nogen tid at omkode forfra.<br /><br />\nEr du sikker pĆ„, du vil fortsƦtte?",
+ "timedmedia-reset-error": "Fejl ved nulstilling af kode job.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 kilde",
+ "timedmedia-source-file-desc": "Original $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Original $1 file ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Lav bƄndbredde Ogg video (160 P)",
+ "timedmedia-derivative-desc-360p.ogv": "Web streambar Ogg video (360 P)",
+ "timedmedia-derivative-desc-480p.ogv": "Web streambar Ogg video (480 P)",
+ "timedmedia-derivative-desc-720p.ogv": "HĆøjkvalitets hentbar Ogg video (720P)",
+ "timedmedia-derivative-desc-160p.webm": "Web streambar WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "Web streambar WebM (360 P)",
+ "timedmedia-derivative-desc-480p.webm": "Web streambar WebM (480 P)",
+ "timedmedia-derivative-desc-720p.webm": "HĆøjkvalitets hentbar WebM (720 P)",
+ "timedmedia-derivative-desc-320p.mp4": "enhedsvenlig MP4 (320 P)",
+ "timedmedia-derivative-desc-480p.mp4": "Web streambar MP4 (480 P)",
+ "timedmedia-derivative-desc-720p.mp4": "HD-kvalitet MP4 (720 P)",
+ "timedmedia-subtitle-new": "Opret nye oversƦttelse eller rediger eksisterende",
+ "timedmedia-subtitle-new-desc": "VƦlg sprog og tryk pƄ '''{{int:Timedmedia-undertitlen-ny-gƄ}}'' ' knappen",
+ "timedmedia-subtitle-new-go": "KĆør",
+ "timedmedia-subtitle-language": "$1( $2 ) undertekster",
+ "timedmedia-subtitle-no-video": "Der er ingen video tilknyttet den aktuelle undertitel side",
+ "timedmedia-subtitle-no-subtitles": "Der er i Ćøjeblikket ingen undertekster i $1 denne video du kan [{{fullurl: {{FULLPAGENAME}} |action = Rediger}} redigere denne side] for at tilfĆøje dem",
+ "timedmedia-subtitle-remote": "Tidsbestemte tekst for denne fil er placeret pƄ $1",
+ "timedmedia-subtitle-remote-link": "Du kan [$1 se beskrivelses siden] til denne fil pƄ $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 video|$1 videoer}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg video|$1 Ogg videoer}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM video|$1 WebM videoer}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transkode|$1 transkoder}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 kĆørende transcode|$1 kĆørende transcodes}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 transkode i kĆø|$1 transkoder i kĆø}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 transkode mislykket|$1 transkoder mislykkedes}}",
+ "timedmedia-file": "Fil",
+ "timedmedia-audios": "{{PLURAL:$1|$1 lydfil|$1 lydfiler}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ogg-lydfil|$1 Ogg-lydfiler}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 FLAC-lydfil|$1 FLAC-lydfiler}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 WAV-lydfil|$1 WAV-lydfiler}}",
+ "right-transcode-reset": "Nulstil mislykkedes eller transkodede videoer sĆ„ de er sat ind i jobkĆøen igen.",
+ "right-transcode-status": "Vis [[Special:TimedMediaHandler|information om den aktuelle omkodningsaktivitet]]",
+ "action-transcode-status": "fƄ vist den aktuelle transkode status"
+}
diff --git a/extensions/TimedMediaHandler/i18n/de-formal.json b/extensions/TimedMediaHandler/i18n/de-formal.json
new file mode 100644
index 00000000..be6d0c9d
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/de-formal.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kghbln"
+ ]
+ },
+ "timedmedia-no-player-js": "Entschuldige, aber fĆ¼r Ihren Browser ist entweder die Nutzung von JavaScript deaktiviert oder er verfĆ¼gt Ć¼ber keine unterstĆ¼tzte Abspielsoftware.<br />\nSie kƶnnen <a href=\"$1\">den Clip herunterladen</a> oder <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">eine Abspielsoftware herunterladen</a>, um den Clip im Browser abspielen zu kƶnnen."
+}
diff --git a/extensions/TimedMediaHandler/i18n/de.json b/extensions/TimedMediaHandler/i18n/de.json
new file mode 100644
index 00000000..cffaf6e2
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/de.json
@@ -0,0 +1,130 @@
+{
+ "@metadata": {
+ "authors": [
+ "Filzstift",
+ "G.Hagedorn",
+ "Geitost",
+ "Kghbln",
+ "Leithian",
+ "Les Meloures",
+ "Metalhead64",
+ "MichaelFrey",
+ "Raimond Spekking",
+ "The Evil IP address",
+ "Umherirrender"
+ ]
+ },
+ "extensionname-timedmedia": "TimedMediaHandler",
+ "timedmedia-desc": "Stellt ein Steuerungsprogramm fĆ¼r zeitgesteuerte Medien (Video, Audio, timedText) bereit, welches die Formate WebM, Ogg Theora, Ogg Vorbis und SubRip unterstĆ¼tzt",
+ "timedmedia-ogg-short-audio": "Ogg-$1-Audiodatei, $2",
+ "timedmedia-ogg-short-video": "Ogg-$1-Videodatei, $2",
+ "timedmedia-ogg-short-general": "Ogg-$1-Mediadatei, $2",
+ "timedmedia-ogg-long-audio": "Ogg-$1-Audiodatei, LƤnge: $2, $3",
+ "timedmedia-ogg-long-video": "Ogg-$1-Videodatei, LƤnge: $2, $4Ɨ$5 Pixel, $3 insgesamt",
+ "timedmedia-ogg-long-multiplexed": "Ogg-Audio-/Video-Datei, $1, LƤnge: $2, $4Ɨ$5 Pixel, $3 insgesamt",
+ "timedmedia-ogg-long-general": "Ogg-Mediadatei, LƤnge: $2, $3",
+ "timedmedia-ogg-long-error": "UngĆ¼ltige Ogg-Datei: $1",
+ "timedmedia-ogg-long-no-streams": "OGG-Mediendatei. Warnung: Keine der in dieser Datei verwendeten Codecs wurden erkannt.",
+ "timedmedia-webm-short-video": "WebM-$1-Videodatei, $2",
+ "timedmedia-webm-long-video": "WebM-Audio-/Video-Datei, $1, LƤnge: $2, $4Ɨ$5 Pixel, $3 insgesamt",
+ "timedmedia-flac-short-audio": "FLAC-Audiodatei, $1",
+ "timedmedia-flac-long-audio": "FLAC-Audiodatei, LƤnge: $1, $2 insgesamt",
+ "timedmedia-wav-short-audio": "WAV-Audiodatei, $1",
+ "timedmedia-wav-long-audio": "WAV-Audiodatei, LƤnge: $1, $2 insgesamt",
+ "timedmedia-wav-pcm-required": "Du kannst nur PCM-WAV-Dateien hochladen (Pulse Code Modulation).",
+ "timedmedia-mp4-short-video": "MP4-$1-Videodatei, $2",
+ "timedmedia-mp4-long-video": "MP4-Audio-/Video-Datei, $1, LƤnge $2, $4 Ɨ $5 Pixel, $3 insgesamt",
+ "timedmedia-no-player-js": "Entschuldige, aber fĆ¼r deinen Browser ist entweder die Nutzung von JavaScript deaktiviert oder er verfĆ¼gt Ć¼ber keine unterstĆ¼tzte Abspielsoftware.<br />\nDu kannst <a href=\"$1\">den Clip herunterladen</a> oder <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">eine Abspielsoftware herunterladen</a>, um den Clip im Browser abspielen zu kƶnnen.",
+ "timedmedia-more": "Optionen ā€¦",
+ "timedmedia-dismiss": "SchlieƟen",
+ "timedmedia-download": "Datei herunterladen",
+ "timedmedia-play-media": "Mediendatei abspielen",
+ "timedmedia-desc-link": "Ɯber diese Datei",
+ "timedmedia-oggThumb-version": "OggHandler erfordert oggThumb in der Version $1 oder hƶher.",
+ "timedmedia-oggThumb-failed": "oggThumb konnte kein Miniaturbild erstellen.",
+ "timedmedia-status-header": "Transkodierungstatus",
+ "timedmedia-update-status": "Transkodierungstatus aktualisieren",
+ "timedmedia-status": "Status",
+ "timedmedia-status-unknown": "Unbekannter Status",
+ "timedmedia-transcodebitrate": "Bitrate",
+ "timedmedia-transcodeduration": "Kodierungszeit",
+ "timedmedia-transcodeinfo": "Format",
+ "timedmedia-actions": "Aktionen",
+ "timedmedia-direct-link": "Herunterladen",
+ "timedmedia-not-ready": "Nicht bereit",
+ "timedmedia-completed-on": "Abgeschlossen um $1",
+ "timedmedia-error-on": "Fehler um $1",
+ "timedmedia-started-transcode": "Gestartet vor $1. $2",
+ "timedmedia-percent-done": "UngefƤhr $1 % sind erledigt",
+ "timedmedia-in-job-queue": "Vor $1 der Auftragswarteschlange hinzugefĆ¼gt",
+ "timedmedia-unknown-target-size": "Unbekannte ZielgrĆ¶ĆŸe, $1 codiert",
+ "timedmedia-days": "{{PLURAL:$1|1 Tag|$1 Tagen}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 Stunde|$1 Stunden}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 Minute|$1 Minuten}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 Sekunde|$1 Sekunden}}",
+ "timedmedia-reset": "UmschlĆ¼sselung zurĆ¼cksetzen",
+ "timedmedia-reset-confirm": "Das ZurĆ¼cksetzen dieser UmschlĆ¼sselung wird, sofern vorhanden, die bestehende Datei entfernen und die UmschlĆ¼sselung erneut der Auftragswarteschlange hinzufĆ¼gen. Die erneute UmschlĆ¼sselung wird einige Zeit dauern.<br /><br />Soll dies tatsƤchlich gemacht werden?",
+ "timedmedia-reset-error": "Fehler beim ZurĆ¼cksetzen der UmschlĆ¼sselung",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Quelle ($1)",
+ "timedmedia-source-file-desc": "Original $1-Datei, $2 x $3 ($4)",
+ "timedmedia-source-audio-file-desc": "UrsprĆ¼ngliche $1-Datei ($2)",
+ "timedmedia-derivative-160p.ogv": "Ogg (160p)",
+ "timedmedia-derivative-desc-160p.ogv": "Ogg-Videodatei mit niedriger DatenĆ¼bertragungsrate (160p)",
+ "timedmedia-derivative-desc-240p.ogv": "WebstreamfƤhiges OGG-Video (240p)",
+ "timedmedia-derivative-desc-360p.ogv": "WebstreamingfƤhige Ogg-Videodatei (360p)",
+ "timedmedia-derivative-desc-480p.ogv": "WebstreamingfƤhige Ogg-Videodatei (480p)",
+ "timedmedia-derivative-desc-720p.ogv": "Qualitativ hochwertige Ogg-Videodatei (720p)",
+ "timedmedia-derivative-desc-1080p.ogv": "Herunterladbares Full-HD-OGG-Video (1080p)",
+ "timedmedia-derivative-desc-160p.webm": "WebstreamingfƤhige WebM-Videodatei (160p)",
+ "timedmedia-derivative-desc-360p.webm": "WebstreamingfƤhige WebM-Videodatei (360p)",
+ "timedmedia-derivative-desc-480p.webm": "WebstreamingfƤhige WebM-Videodatei (480p)",
+ "timedmedia-derivative-desc-720p.webm": "Qualitativ hochwertige WebM-Videodatei (720p)",
+ "timedmedia-derivative-desc-1080p.webm": "Herunterladbares Full-HD-WebM-Video (1080p)",
+ "timedmedia-derivative-desc-2160p.webm": "Herunterladbares Full-4K-WebM-Video (2160P)",
+ "timedmedia-derivative-360p.vp9.webm": "VP9 360P",
+ "timedmedia-derivative-desc-360p.vp9.webm": "WebstreamfƤhiges WebM-VP9-Video (360P)",
+ "timedmedia-derivative-480p.vp9.webm": "VP9 480P",
+ "timedmedia-derivative-desc-480p.vp9.webm": "WebstreamfƤhiges WebM-VP9-Video (480P)",
+ "timedmedia-derivative-720p.vp9.webm": "VP9 720P",
+ "timedmedia-derivative-desc-720p.vp9.webm": "HD-streamfƤhiges WebM-VP9-Video (720P)",
+ "timedmedia-derivative-1080p.vp9.webm": "VP9 1080P",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "Full-HD-streamfƤhiges WebM-VP9-Video (1080P)",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "StreamfƤhiges Full-4K-WebM-VP9-Video (2160P)",
+ "timedmedia-derivative-desc-320p.mp4": "GerƤtefreundliche MP4-Datei (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "WebstreamingfƤhige MP4-Datei (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4-Datei in HD-QualitƤt (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "Full-HD-QualitƤt-MP4-Video (1080p)",
+ "timedmedia-derivative-desc-2160p.mp4": "Full-4K-QualitƤts-MP4-Video (2160P)",
+ "timedmedia-subtitle-new": "Neue Ɯbersetzung erstellen oder vorhandene bearbeiten",
+ "timedmedia-subtitle-new-desc": "WƤhle eine Sprache aus und klicke auf '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Los",
+ "timedmedia-subtitle-language": "$1 ($2) Untertitel",
+ "timedmedia-subtitle-no-video": "Der aktuellen Seite mit Untertiteln ist kein Video zugeordnet.",
+ "timedmedia-subtitle-no-subtitles": "Derzeit gibt es keine Untertitel auf $1 fĆ¼r dieses Video. Zum HinzufĆ¼gen von Untertiteln kann [{{fullurl:{{FULLPAGENAME}}|action=edit}} diese Seite] bearbeitet werden.",
+ "timedmedia-subtitle-remote": "timedText fĆ¼r diese Datei befindet sich auf $1",
+ "timedmedia-subtitle-remote-link": "Du kannst [$1 die Beschreibungsseite] fĆ¼r diese Datei auf $2 ansehen",
+ "timedmediahandler": "Steuerungsprogramm fĆ¼r zeitgesteuerte Medien",
+ "timedmedia-videos": "{{PLURAL:$1|Ein Video|$1 Videos}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|Ein Ogg-Video|$1 Ogg-Videos}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|Ein WebM-Video|$1 WebM-Videos}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|Eine UmschlĆ¼sselung|$1 UmschlĆ¼sselungen}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|Eine laufende UmschlĆ¼sselung|$1 laufende UmschlĆ¼sselungen}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|Eine UmschlĆ¼sselung|$1 UmschlĆ¼sselungen}} in der Warteschlange",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|Eine fehlgeschlagene UmschlĆ¼sselung|$1 fehlgeschlagene UmschlĆ¼sselungen}}",
+ "timedmedia-file": "Datei",
+ "timedmedia-audios": "{{PLURAL:$1|Eine Audiodatei|$1 Audiodateien}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|Eine OGG-Audiodatei|$1 OGG-Audiodateien}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|Eine FLAC-Audiodatei|$1 FLAC-Audiodateien}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|Eine WAV-Audiodatei|$1 WAV-Audiodateien}}",
+ "right-transcode-reset": "Fehlgeschlagene oder erfolgreiche UmschlĆ¼sselungen von Video-Dateien zurĆ¼cksetzen, um sie erneut in die Auftragswarteschlange einzureihen",
+ "right-transcode-status": "[[Special:TimedMediaHandler|Informationen Ć¼ber aktuelle UmschlĆ¼sselungen]] betrachten",
+ "action-transcode-status": "den aktuellen Transkodierungstatus anzusehen",
+ "orphanedtimedtext": "Verwaiste TimedText-Seiten",
+ "orphanedtimedtext-summary": "Liste der [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]]-Seiten, die keine entsprechende Datei haben.",
+ "orphanedtimedtext-unsupported": "Diese Spezialseite wird nur auf MySQL-Datenbanken unterstĆ¼tzt.",
+ "orphanedtimedtext-notimedtext": "TimedText ist auf diesem Wiki nicht aktiviert.",
+ "apihelp-query+transcodestatus-example-1": "Ruft den Transkodierungsstatus fĆ¼r [[:File:Clip.webm]] ab",
+ "apihelp-transcodereset-param-title": "Der Titel der Mediendatei.",
+ "apihelp-transcodereset-example-1": "Setzt alle UmschlĆ¼sselungen fĆ¼r [[:File:Clip.webm]] zurĆ¼ck"
+}
diff --git a/extensions/TimedMediaHandler/i18n/din.json b/extensions/TimedMediaHandler/i18n/din.json
new file mode 100644
index 00000000..194e1a5e
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/din.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dinkawiki"
+ ]
+ },
+ "timedmedia-source-file": "$1 tƫnƫyƶk"
+}
diff --git a/extensions/TimedMediaHandler/i18n/diq.json b/extensions/TimedMediaHandler/i18n/diq.json
new file mode 100644
index 00000000..1b1ba84c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/diq.json
@@ -0,0 +1,41 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aspar",
+ "Erdemaslancan",
+ "Gorizon",
+ "Marmase",
+ "Mirzali",
+ "Xoser"
+ ]
+ },
+ "timedmedia-desc": "Qen dĆŖ dosyayan dĆŖ WebM, Ogg Theora, Vorbis, srt rĆŖxo desti veng dekerdış u nuşte ronayış",
+ "timedmedia-ogg-short-audio": "Ogg $1 dosyaya vengi, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 dosyaya filmi, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 dosyaya medyayi, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 dosyaya medyayi, mudde $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 dosyaya filmi, mudde $2, $4Ɨ$5 piksel, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg dosyaya filmi/vengi yo multiexed, $1, mudde $2, $4Ɨ$5 piksel, $3 bıumumi",
+ "timedmedia-ogg-long-general": "Ogg dosyaya medyayi, mudde $2, $3",
+ "timedmedia-ogg-long-error": "dosyaya oggi yo nemeqbul: $1",
+ "timedmedia-more": "hema....",
+ "timedmedia-dismiss": "RacnĆŖ",
+ "timedmedia-download": "dosya biyar war",
+ "timedmedia-play-media": "Medya bıcıne",
+ "timedmedia-desc-link": "Heqa na dosya de",
+ "timedmedia-status": "Weziyet",
+ "timedmedia-status-unknown": "Weziyeto nĆŖzanaye",
+ "timedmedia-transcodeinfo": "Şınasiya babetĆŖ transkodi",
+ "timedmedia-actions": "Kerdışi",
+ "timedmedia-not-ready": "Hazır niyo",
+ "timedmedia-days": "{{PLURAL:$1|1 roce|$1 roci}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 seate|$1 seati}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 deqa|$1 deqey}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 saniya|$1 saniyey}}",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 Ƨıme",
+ "timedmedia-source-audio-file-desc": "Dosyaya $1 oricinale ($2)",
+ "timedmedia-subtitle-new-go": "Şo",
+ "timedmediahandler": "ProgramĆŖ kontroliĆŖ zemanĆŖ kontrolbiyayey",
+ "timedmedia-file": "Dosya"
+}
diff --git a/extensions/TimedMediaHandler/i18n/dsb.json b/extensions/TimedMediaHandler/i18n/dsb.json
new file mode 100644
index 00000000..6b65986b
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/dsb.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Michawiki"
+ ]
+ },
+ "timedmedia-desc": "WĆ³Åŗeński program za awdio, wideo a timedText, z formatoweju pĆ³dpěru za WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Ogg $1 awdiodataja, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 wideodataja, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 medijowa dataja, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 awdiodataja, dłujkosć $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 wideodataja, dłujkosć $2, $4Ɨ$5 pikselow, $3",
+ "timedmedia-ogg-long-multiplexed": "ogg multipleksowa awdio-/wideodataja, $1, dłujkosć $2, $4Ɨ$5 pikselow, $3 dogromady",
+ "timedmedia-ogg-long-general": "Ogg medijowa dataja, dłujkosć $2, $3",
+ "timedmedia-ogg-long-error": "Njepłaśiwa Ogg-dataja: $1",
+ "timedmedia-webm-short-video": "WebM $1 wideodataja, $2",
+ "timedmedia-webm-long-video": "WebM dataja awdio/wideo, $1, dłujkosć $2, $4 x $5, $3 dogromady",
+ "timedmedia-no-player-js": "TwĆ³j wobglědowak jo bĆ³Å¾ko pak JavaScript znjemĆ³Å¾nił abo njama njepĆ³dpěrany wĆ³tegrawak.<br />\nMĆ³Å¾oÅ” <a href=\"$1\">klip ześěgnuś</a> abo <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">wĆ³tgrawak ześěgnuś</a>, aby klip w swĆ³jom wobglědowaku wĆ³tegrał.",
+ "timedmedia-more": "Wěcej...",
+ "timedmedia-dismiss": "Zacyniś",
+ "timedmedia-download": "Dataju ześěgnuś",
+ "timedmedia-play-media": "Medijowu dataju wĆ³tegraś",
+ "timedmedia-desc-link": "WĆ³ toś tej dataji",
+ "timedmedia-oggThumb-version": "OggHandler trjeba wersiju $1 oggThumb abo nowŔu.",
+ "timedmedia-oggThumb-failed": "oggThumb njejo mĆ³gł wobrazk napĆ³raś.",
+ "timedmedia-source-file": "Žrědło ($1)",
+ "timedmedia-source-file-desc": "Originalna $1-dataja, $2 Ɨ $3 ($4)",
+ "timedmedia-derivative-desc-160p.ogv": "Niska Å”yrokosć pasma Ogg-widea (200p)",
+ "timedmedia-subtitle-language": "$1 ($2) pĆ³dtitele"
+}
diff --git a/extensions/TimedMediaHandler/i18n/dty.json b/extensions/TimedMediaHandler/i18n/dty.json
new file mode 100644
index 00000000..905f6b6d
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/dty.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "ą¤œą¤Øą¤• ą¤°ą¤¾ą¤œ ą¤­ą¤Ÿą„ą¤Ÿ",
+ "ą¤°ą¤®ą„‡ą¤¶ ą¤øą¤æą¤‚ą¤¹ ą¤¬ą„‹ą¤¹ą¤°ą¤¾",
+ "ą¤°ą¤¾ą¤® ą¤Ŗą„ą¤°ą¤øą¤¾ą¤¦ ą¤œą„‹ą¤¶ą„€"
+ ]
+ },
+ "timedmedia-no-player-js": "ą¤®ą¤¾ą¤« ą¤—ą¤°ą„ą¤Æą¤¾, ą¤¤ą¤®ą¤°ą„‹ ą¤¬ą„ą¤°ą¤¾ą¤‰ą¤œą¤°ą¤®ą„€ ą¤Æą¤¾ ą¤¤ ą¤œą¤¾ą¤µą¤¾ą¤øą„ą¤•ą„ą¤°ą¤æą¤Ŗą„ą¤Ÿ ą¤…ą¤•ą„ą¤·ą¤® ą¤› ą¤Æą¤¾ ą¤øą¤®ą¤°ą„ą¤„ą¤æą¤¤ ą¤Ŗą„ą¤²ą„‡ą¤Æą¤° ą¤›ą„ˆą¤Ø ą„¤<br />\ną¤¤ą¤®ą„€ <a href=\"$1\">ą¤•ą„ą¤²ą¤æą¤Ŗą¤²ą¤¾ą¤ˆ ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤”</a> ą¤—ą¤¦ą„ą¤¦ ą¤øą¤•ą„ą¤¦ą„ą¤Æą¤¾ą¤¹ą„Œ ą¤…ą¤„ą¤µą¤¾ ą¤•ą„ą¤²ą¤æą¤Ŗą¤²ą¤¾ą¤ˆ ą¤†ą¤«ą„ą¤Øą„‹ ą¤¬ą„ą¤°ą¤¾ą¤‰ą¤œą¤°ą¤®ą„€ ą¤šą¤²ą¤¾ą¤‰ą¤Øą¤•ą„‹ ą¤²ą¤¾ą¤—ą¤æ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ą¤ą¤• ą¤Ŗą„ą¤²ą„‡ą¤Æą¤° ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤”</a> ą¤—ą¤¦ą„ą¤¦ ą¤øą¤•ą„ą¤¦ą„ą¤Æą¤¾ ą¤¹ą„Œ ą„¤",
+ "timedmedia-source-file": "$1 ą¤¶ą„ą¤°ą„‹ą¤¤",
+ "timedmedia-source-audio-file-desc": "ą¤–ą¤¾ą¤ø $1 ą¤šą¤æą¤¤ą„ą¤° ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ee.json b/extensions/TimedMediaHandler/i18n/ee.json
new file mode 100644
index 00000000..993eb5df
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ee.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aguve"
+ ]
+ },
+ "timedmedia-no-player-js": "Tafltsɛ, YavaSkript mele sisi internet-dɔwɔnua dzi alo ʒonu aɖeke meli si ate ŋu aʒoe o.<br />\nƀte ŋu <a href=\"$1\">awɔ video kpui sia ʒe kɔpi le</a> alo <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">wɔ ʒonu aɖe ʒe kɔpi</a> nĆ tsɔ aʒo video kpui sia le wĆ² internet-dɔwɔnua me.",
+ "timedmedia-source-file": "Tsoʒe $1"
+}
diff --git a/extensions/TimedMediaHandler/i18n/el.json b/extensions/TimedMediaHandler/i18n/el.json
new file mode 100644
index 00000000..f1791421
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/el.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Consta",
+ "Dead3y3",
+ "Omnipaedista",
+ "ZaDiak",
+ "Evropi",
+ "Geraki"
+ ]
+ },
+ "timedmedia-desc": "Ī§ĪµĪ¹ĻĪ¹ĻƒĻ„Ī®Ļ‚ Ī³Ī¹Ī± Ī±ĻĻ‡ĪµĪÆĪ± Ogg Theora ĪŗĪ±Ī¹ Vorbis, Ī¼Īµ Ī±Ī½Ī±Ļ€Ī±ĻĪ±Ī³Ļ‰Ī³Ī­Ī± JavaScript",
+ "timedmedia-ogg-short-audio": "Ī‘ĻĻ‡ĪµĪÆĪæ Ī®Ļ‡ĪæĻ… Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Ī‘ĻĻ‡ĪµĪÆĪæ Ī²ĪÆĪ½Ļ„ĪµĪæ Ogg $1, $2",
+ "timedmedia-ogg-short-general": "Ī‘ĻĻ‡ĪµĪÆĪæ Ī¼Ī­ĻƒĻ‰Ī½ Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Ī‘ĻĻ‡ĪµĪÆĪæ Ī®Ļ‡ĪæĻ… Ogg $1, Ī“Ī¹Ī¬ĻĪŗĪµĪ¹Ī± $2, $3",
+ "timedmedia-ogg-long-video": "Ī‘ĻĻ‡ĪµĪÆĪæ Ī²ĪÆĪ½Ļ„ĪµĪæ Ogg $1, Ī“Ī¹Ī¬ĻĪŗĪµĪ¹Ī± $2, $4Ɨ$5 pixels, $3",
+ "timedmedia-ogg-long-multiplexed": "Ī‘ĻĻ‡ĪµĪÆĪæ Ļ€ĪæĪ»Ļ…Ļ€Ī»ĪµĪŗĻ„Ī¹ĪŗĪæĻ Ī®Ļ‡ĪæĻ…/Ī²ĪÆĪ½Ļ„ĪµĪæ Ogg, $1, Ī“Ī¹Ī¬ĻĪŗĪµĪ¹Ī± $2, $4Ɨ$5 pixels, $3 ĪæĪ»Ī¹ĪŗĪ¬",
+ "timedmedia-ogg-long-general": "Ī‘ĻĻ‡ĪµĪÆĪæ Ī¼Ī­ĻƒĻ‰Ī½ Ogg, Ī“Ī¹Ī¬ĻĪŗĪµĪ¹Ī± $2, $3",
+ "timedmedia-ogg-long-error": "Ī†ĪŗĻ…ĻĪæ Ī±ĻĻ‡ĪµĪÆĪæ ogg: $1",
+ "timedmedia-no-player-js": "Ī£Ļ…Ī³Ī½ĻŽĪ¼Ī·, Ļ„Īæ Ļ€ĻĻŒĪ³ĻĪ±Ī¼Ī¼Ī± Ļ€ĪµĻĪ¹Ī®Ī³Ī·ĻƒĪ®Ļ‚ ĻƒĪ±Ļ‚ ĪµĪÆĻ„Īµ Ī­Ļ‡ĪµĪ¹ Ļ„Ī·Ī½ JavaScript Ī±Ļ€ĪµĪ½ĪµĻĪ³ĪæĻ€ĪæĪ¹Ī·Ī¼Ī­Ī½Ī· Ī® Ī“ĪµĪ½ Ī­Ļ‡ĪµĪ¹ ĪæĻ€ĪæĪ¹ĪæĪ“Ī®Ļ€ĪæĻ„Īµ Ļ…Ļ€ĪæĻƒĻ„Ī·ĻĪ¹Ī¶ĻŒĪ¼ĪµĪ½Īæ player.<br />\nĪœĻ€ĪæĻĪµĪÆĻ„Īµ Ī½Ī± <a href=\"$1\">ĪŗĪ±Ļ„ĪµĪ²Ī¬ĻƒĻ„Īµ Ļ„Īæ ĪŗĪ»Ī¹Ļ€</a> Ī® Ī½Ī± <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ĪŗĪ¬Ī½ĪµĻ„Īµ Ī»Ī®ĻˆĪ· ĪµĪ½ĻŒĻ‚ player</a> Ī³Ī¹Ī± Ī½Ī± Ī±Ī½Ī±Ļ€Ī±ĻĪ¬Ī³ĪµĻ„Īµ Ļ„Īæ ĪŗĪ»Ī¹Ļ€ ĻƒĻ„ĪæĪ½ browser ĻƒĪ±Ļ‚.",
+ "timedmedia-more": "Ī ĪµĻĪ¹ĻƒĻƒĻŒĻ„ĪµĻĪ±...",
+ "timedmedia-dismiss": "ĪšĪ»ĪµĪÆĻƒĪ¹Ī¼Īæ",
+ "timedmedia-download": "ĪšĪ±Ļ„ĪµĪ²Ī¬ĻƒĻ„Īµ Ļ„Īæ Ī±ĻĻ‡ĪµĪÆĪæ",
+ "timedmedia-desc-link": "Ī£Ļ‡ĪµĻ„Ī¹ĪŗĪ¬ Ī¼Īµ Ī±Ļ…Ļ„ĻŒ Ļ„Īæ Ī±ĻĻ‡ĪµĪÆĪæ",
+ "timedmedia-source-file": "Ī Ī·Ī³Ī® $1",
+ "timedmedia-source-audio-file-desc": "Ī ĻĻ‰Ļ„ĻŒĻ„Ļ…Ļ€Īæ Ī±ĻĻ‡ĪµĪÆĪæ $1 ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/en-gb.json b/extensions/TimedMediaHandler/i18n/en-gb.json
new file mode 100644
index 00000000..001bb5cc
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/en-gb.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Shirayuki",
+ "Captaindogfish"
+ ]
+ },
+ "timedmedia-ogg-long-no-streams": "Ogg media file. Warning: None of the codecs used in this file are recognised.",
+ "timedmedia-derivative-desc-1080p.ogv": "Full HD downloadable Ogg video (1080P)",
+ "timedmedia-derivative-desc-1080p.webm": "Full HD downloadable WebM (1080P)",
+ "timedmedia-derivative-desc-1080p.mp4": "Full HD quality MP4 (1080P)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/en.json b/extensions/TimedMediaHandler/i18n/en.json
new file mode 100644
index 00000000..b17d0665
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/en.json
@@ -0,0 +1,154 @@
+{
+ "@metadata": {
+ "authors": []
+ },
+ "extensionname-timedmedia": "TimedMediaHandler",
+ "timedmedia-desc": "Handler for audio, video and timed text, with format support for WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Ogg $1 sound file, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 video file, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 media file, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 sound file, length $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 video file, length $2, $4 Ɨ $5 pixels, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg multiplexed audio/video file, $1, length $2, $4 Ɨ $5 pixels, $3 overall",
+ "timedmedia-ogg-long-general": "Ogg media file, length $2, $3",
+ "timedmedia-ogg-long-error": "Invalid Ogg file: $1",
+ "timedmedia-ogg-long-no-streams": "Ogg media file. Warning: None of the codecs used in this file are recognized.",
+ "timedmedia-webm-short-video": "WebM $1 video file, $2",
+ "timedmedia-webm-long-video": "WebM audio/video file, $1, length $2, $4 Ɨ $5 pixels, $3 overall",
+ "timedmedia-flac-short-audio": "FLAC audio file, $1",
+ "timedmedia-flac-long-audio": "FLAC audio file, length $1, $2 overall",
+ "timedmedia-wav-short-audio": "WAV audio file, $1",
+ "timedmedia-wav-long-audio": "WAV audio file, length $1, $2 overall",
+ "timedmedia-wav-pcm-required": "You can only upload PCM (Pulse Code Modulation) WAV.",
+ "timedmedia-mp4-short-video": "MP4 $1 video file, $2",
+ "timedmedia-mp4-long-video": "MP4 audio/video file, $1, length $2, $4 Ɨ $5 pixels, $3 overall",
+ "timedmedia-no-player-js": "Sorry, your browser either has JavaScript disabled or does not have any supported player.<br />\nYou can <a href=\"$1\">download the clip</a> or <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">download a player</a> to play the clip in your browser.",
+ "timedmedia-more": "Moreā€¦",
+ "timedmedia-dismiss": "Close",
+ "timedmedia-download": "Download file",
+ "timedmedia-play-media": "Play media",
+ "timedmedia-desc-link": "About this file",
+ "timedmedia-oggThumb-version": "OggHandler requires oggThumb version $1 or later.",
+ "timedmedia-oggThumb-failed": "oggThumb failed to create the thumbnail.",
+ "timedmedia-status-header": "Transcode status",
+ "timedmedia-update-status": "Update transcode status",
+ "timedmedia-status": "Status",
+ "timedmedia-status-unknown": "Unknown status",
+ "timedmedia-transcodebitrate": "Bitrate",
+ "timedmedia-transcodeduration": "Encode time",
+ "timedmedia-transcodeinfo": "Format",
+ "timedmedia-actions": "Actions",
+ "timedmedia-direct-link": "Download",
+ "timedmedia-not-ready": "Not ready",
+ "timedmedia-completed-on": "Completed $1",
+ "timedmedia-error-on": "Error on $1",
+ "timedmedia-started-transcode": "Started $1 ago. $2",
+ "timedmedia-percent-done": "About $1% done",
+ "timedmedia-in-job-queue": "Added to Job queue $1 ago",
+ "timedmedia-unknown-target-size": "Unknown target size, $1 encoded",
+ "timedmedia-days": "{{PLURAL:$1|1 day|$1 days}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 hour|$1 hours}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minute|$1 minutes}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 second|$1 seconds}}",
+ "timedmedia-reset": "Reset transcode",
+ "timedmedia-reset-confirm": "Resetting this transcode will remove any existing file (if present), and it will re-add the transcode to the job queue. It will take some time to re-transcode.<br /><br />\nAre you sure you want to proceed?",
+ "timedmedia-reset-error": "Error in resetting transcode job.",
+ "timedmedia-ogg": "Ogg",
+ "timedmedia-webm": "WebM",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-wav": "WAV",
+ "timedmedia-flac": "FLAC",
+ "timedmedia-source-file": "$1 source",
+ "timedmedia-source-file-desc": "Original $1 file, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Original $1 file ($2)",
+ "timedmedia-derivative-160p.ogv": "Ogg 160P",
+ "timedmedia-derivative-desc-160p.ogv": "Low bandwidth Ogg video (160P)",
+ "timedmedia-derivative-240p.ogv": "Ogg 240P",
+ "timedmedia-derivative-desc-240p.ogv": "Web streamable Ogg video (240P)",
+ "timedmedia-derivative-360p.ogv": "Ogg 360P",
+ "timedmedia-derivative-desc-360p.ogv": "Web streamable Ogg video (360P)",
+ "timedmedia-derivative-480p.ogv": "Ogg 480P",
+ "timedmedia-derivative-desc-480p.ogv": "Web streamable Ogg video (480P)",
+ "timedmedia-derivative-720p.ogv": "Ogg 720P",
+ "timedmedia-derivative-desc-720p.ogv": "High quality downloadable Ogg video (720P)",
+ "timedmedia-derivative-1080p.ogv": "Ogg 1080P",
+ "timedmedia-derivative-desc-1080p.ogv": "Full HD downloadable Ogg video (1080P)",
+ "timedmedia-derivative-160p.webm": "WebM 160P",
+ "timedmedia-derivative-desc-160p.webm": "Web streamable WebM (160P)",
+ "timedmedia-derivative-360p.webm": "WebM 360P",
+ "timedmedia-derivative-desc-360p.webm": "Web streamable WebM (360P)",
+ "timedmedia-derivative-480p.webm": "WebM 480P",
+ "timedmedia-derivative-desc-480p.webm": "Web streamable WebM (480P)",
+ "timedmedia-derivative-720p.webm": "WebM 720P",
+ "timedmedia-derivative-desc-720p.webm": "High quality downloadable WebM (720P)",
+ "timedmedia-derivative-1080p.webm": "WebM 1080P",
+ "timedmedia-derivative-desc-1080p.webm": "Full HD downloadable WebM (1080P)",
+ "timedmedia-derivative-2160p.webm": "WebM 2160P",
+ "timedmedia-derivative-desc-2160p.webm": "Full 4K downloadable WebM (2160P)",
+ "timedmedia-derivative-360p.vp9.webm": "VP9 360P",
+ "timedmedia-derivative-desc-360p.vp9.webm": "Web streamable WebM VP9 (360P)",
+ "timedmedia-derivative-480p.vp9.webm": "VP9 480P",
+ "timedmedia-derivative-desc-480p.vp9.webm": "Web streamable WebM VP9 (480P)",
+ "timedmedia-derivative-720p.vp9.webm": "VP9 720P",
+ "timedmedia-derivative-desc-720p.vp9.webm": "HD streamable WebM VP9 (720P)",
+ "timedmedia-derivative-1080p.vp9.webm": "VP9 1080P",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "Full HD streamable WebM VP9 (1080P)",
+ "timedmedia-derivative-2160p.vp9.webm": "VP9 2160P",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "Full 4K streamable WebM VP9 (2160P)",
+ "timedmedia-derivative-320p.mp4": "H264 320P",
+ "timedmedia-derivative-desc-320p.mp4": "Device-friendly MP4 (320P)",
+ "timedmedia-derivative-480p.mp4": "H264 480P",
+ "timedmedia-derivative-desc-480p.mp4": "Web streamable MP4 (480P)",
+ "timedmedia-derivative-720p.mp4": "H264 720P",
+ "timedmedia-derivative-desc-720p.mp4": "HD quality MP4 (720P)",
+ "timedmedia-derivative-1080p.mp4": "H264 1080P",
+ "timedmedia-derivative-desc-1080p.mp4": "Full HD quality MP4 (1080P)",
+ "timedmedia-derivative-2160p.mp4": "H264 2160P",
+ "timedmedia-derivative-desc-2160p.mp4": "Full 4K quality MP4 (2160P)",
+ "timedmedia-derivative-ogg": "Ogg Vorbis",
+ "timedmedia-derivative-desc-ogg": "Ogg Vorbis",
+ "timedmedia-derivative-opus": "Opus",
+ "timedmedia-derivative-desc-opus": "Opus",
+ "timedmedia-derivative-mp3": "MP3",
+ "timedmedia-derivative-desc-mp3": "MP3",
+ "timedmedia-derivative-m4a": "AAC",
+ "timedmedia-derivative-desc-m4a": "AAC",
+ "timedmedia-subtitle-new": "Create new translation or edit existing",
+ "timedmedia-subtitle-new-desc": "Select language and press the '''{{int:Timedmedia-subtitle-new-go}}''' button",
+ "timedmedia-subtitle-new-go": "Go",
+ "timedmedia-subtitle-language": "$1 ($2) subtitles",
+ "timedmedia-subtitle-no-video": "There is no video associated with the current subtitle page.",
+ "timedmedia-subtitle-no-subtitles": "There are currently no subtitles in $1 for this video, you can [{{fullurl:{{FULLPAGENAME}}|action=edit}} edit this page] to add them.",
+ "timedmedia-subtitle-remote": "Timed text for this file is hosted on $1",
+ "timedmedia-subtitle-remote-link": "You can [$1 view the description page] for this file on $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 video|$1 videos}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg video|$1 Ogg videos}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM video|$1 WebM videos}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transcode|$1 transcodes}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 running transcode|$1 running transcodes}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 queued transcode|$1 queued transcodes}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 failed transcode|$1 failed transcodes}}",
+ "timedmedia-file": "File",
+ "timedmedia-audios": "{{PLURAL:$1|$1 audio file|$1 audio files}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ogg audio file|$1 Ogg audio files}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 FLAC audio file|$1 FLAC audio files}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 WAV audio file|$1 WAV audio files}}",
+ "right-transcode-reset": "Reset failed or transcoded videos so they are inserted into the job queue again",
+ "right-transcode-status": "View [[Special:TimedMediaHandler|information about the current transcode activity]]",
+ "action-transcode-status": "view the current transcoding status",
+ "orphanedtimedtext": "Orphaned TimedText pages",
+ "orphanedtimedtext-summary": "List of [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] pages which do not have a corresponding file.",
+ "orphanedtimedtext-unsupported": "This special page is only supported on MySQL databases.",
+ "orphanedtimedtext-notimedtext": "TimedText is not enabled on this wiki.",
+ "apihelp-query+transcodestatus-description": "Get transcode status for a given file page.",
+ "apihelp-query+transcodestatus-example-1": "Get transcode status for [[:File:Clip.webm]]",
+ "apihelp-query+videoinfo-description": "Extends imageinfo to include video source (derivatives) information",
+ "apihelp-query+videoinfo-param-prop": "What video information to get:\n;timestamp:Adds timestamp for the uploaded version.\n;user:Adds the user who uploaded the video version.\n;userid:Add the user ID that uploaded the video version.\n;comment:Comment on the version.\n;parsedcomment:Parse the comment on the version.\n;canonicaltitle:Adds the canonical title of the video file.\n;url:Gives URL to the video and the description page.\n;size:Adds the size of the video in bytes, its height and its width. Page count and duration are added if applicable.\n;dimensions:Alias for size.\n;sha1:Adds SHA-1 hash for the video.\n;mime:Adds MIME type of the video.\n;thumbmime:Adds MIME type of the video thumbnail (requires url and param $1urlwidth).\n;mediatype:Adds the media type of the video.\n;metadata:Lists Exif metadata for the version of the video.\n;commonmetadata:Lists file format generic metadata for the version of the video.\n;extmetadata:Lists formatted metadata combined from multiple sources. Results are HTML formatted.\n;archivename:Adds the filename of the archive version for non-latest versions.\n;bitdepth:Adds the bit depth of the version.\n;uploadwarning:Used by the [[Special:Upload]] page to get information about an existing file. Not intended for use outside MediaWiki core.\n;derivatives:Adds an array of the different format and quality versions of an audio or video file that are available.",
+ "apihelp-query+videoinfo-example-1": "Fetch information about [[:File:Folgers.ogv]]",
+ "apihelp-transcodereset-description": "Users with the 'transcode-reset' right can reset and re-run a transcode job.",
+ "apihelp-transcodereset-param-title": "The media file title.",
+ "apihelp-transcodereset-param-transcodekey": "The transcode key you wish to reset. Fetch from [[Special:ApiHelp/query+transcodestatus|action=query&prop=transcodestatus]].",
+ "apihelp-transcodereset-example-1": "Reset all transcodes for [[:File:Clip.webm]]",
+ "apihelp-transcodereset-example-2": "Reset the '360_560kbs.webm' transcode key for [[:File:Clip.webm]]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/eo.json b/extensions/TimedMediaHandler/i18n/eo.json
new file mode 100644
index 00000000..436317ea
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/eo.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amikeco",
+ "ArnoLagrange",
+ "Yekrats",
+ "KuboF"
+ ]
+ },
+ "timedmedia-desc": "Traktilo por sondosieroj, videoj, kaj horloĝigita teksto, kun formatsubteno por WebM kaj Ogg Theora kaj Vobis kaj srt.",
+ "timedmedia-ogg-short-audio": "Ogg $1 sondosiero, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 videodosiero, $2",
+ "timedmedia-ogg-short-general": "Media Ogg-dosiero $1, $2",
+ "timedmedia-ogg-long-audio": "AÅ­da Ogg-dosiero $1, longeco $2, $3 entute",
+ "timedmedia-ogg-long-video": "Video Ogg-dosiero $1, longeco $2, $4Ɨ$5 pikseloj, $3 entute",
+ "timedmedia-ogg-long-multiplexed": "Kunigita aÅ­dio/video Ogg-dosiero, $1, longeco $2, $4Ɨ$5 pikseloj, $3 entute",
+ "timedmedia-ogg-long-general": "Ogg-mediodosiero, longeco $2, $3",
+ "timedmedia-ogg-long-error": "Malvalida Ogg-dosiero: $1",
+ "timedmedia-no-player-js": "Pardonu, estas malŝaltita Ĝavoskripto en via foliumilo aŭ ĝi enhavas neniun subtenatan ludilon<br />\nVi povas <a href=\"$1\">elŝuti la videaĵon</a> aŭ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">elŝuti ludilon</a> por povi ludi la videaĵon en via foliumilo.",
+ "timedmedia-more": "Pli...",
+ "timedmedia-dismiss": "Fermi",
+ "timedmedia-download": "Alŝuti dosieron",
+ "timedmedia-desc-link": "Pri ĉi tiu dosiero",
+ "timedmedia-source-file": "Fonta $1-dosiero",
+ "timedmedia-source-audio-file-desc": "Origina $1-dosiero ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/es.json b/extensions/TimedMediaHandler/i18n/es.json
new file mode 100644
index 00000000..962436fb
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/es.json
@@ -0,0 +1,117 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aleator",
+ "Armando-Martin",
+ "Ciencia Al Poder",
+ "Crazymadlover",
+ "Jewbask",
+ "Maor X",
+ "Muro de Aguas",
+ "Remember the dot",
+ "Rodrigo Molinero",
+ "Rzuwig",
+ "Sanbec",
+ "Spacebirdy",
+ "Translationista",
+ "Fitoschido",
+ "Macofe"
+ ]
+ },
+ "timedmedia-desc": "Manipulador de sonido, vĆ­deo y texto sincronizado, con soporte para los formatos WebM, Ogg Theora, Vorbis y srt",
+ "timedmedia-ogg-short-audio": "Archivo de sonido Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Archivo de video Ogg $1, $2",
+ "timedmedia-ogg-short-general": "Archivo Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Archivo de sonido Ogg $1, tamaƱo $2, $3",
+ "timedmedia-ogg-long-video": "Archivo de video Ogg $1, tamaƱo $2, $4Ɨ$5 pĆ­xeles, $3",
+ "timedmedia-ogg-long-multiplexed": "Archivo Ogg de audio/video multiplexado, $1, tamaƱo $2, $4Ɨ$5 pĆ­xeles, $3 en todo",
+ "timedmedia-ogg-long-general": "Archivo Ogg. tamaƱo $2, $3",
+ "timedmedia-ogg-long-error": "Archivo Ogg no vƔlido: $1",
+ "timedmedia-webm-short-video": "Archivo de vĆ­deo WebM $1, $2",
+ "timedmedia-webm-long-video": "Archivo de audio/vƭdeo WebM, $1 , longitud $2 , $4 Ɨ $5 pƭxeles, $3 total",
+ "timedmedia-flac-short-audio": "Archivo de audio FLAC, $1",
+ "timedmedia-flac-long-audio": "Archivo de audio FLAC, duraciĆ³n: $1, $2 en general",
+ "timedmedia-wav-short-audio": "Archivo de audio WAV, $1",
+ "timedmedia-wav-long-audio": "Archivo de audio WAV, duraciĆ³n: $1, $2 en general",
+ "timedmedia-wav-pcm-required": "Solo puedes cargar WAV del tipo PCM (''Pulse Code Modulation'', por sus siglas en inglƩs).",
+ "timedmedia-mp4-short-video": "Archivo de vĆ­deo MP4 $1, $2",
+ "timedmedia-mp4-long-video": "Archivo de audio/vƭdeo MP4, $1 , longitud $2 , $4 Ɨ $5 pƭxeles, $3 total",
+ "timedmedia-no-player-js": "Tu navegador tiene JavaScript desactivado o no tiene un reproductor compatible.<br />\nPuedes <a href=\"$1\">descargar el vĆ­deo</a> o <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">descargar un reproductor</a> para ver el vĆ­deo en tu navegador.",
+ "timedmedia-more": "Opciones...",
+ "timedmedia-dismiss": "Cerrar",
+ "timedmedia-download": "Descargar archivo",
+ "timedmedia-play-media": "Reproducir contenido multimedia",
+ "timedmedia-desc-link": "Sobre este archivo",
+ "timedmedia-oggThumb-version": "OggHandler requiere una versiĆ³n oggThumb $1 o posterior.",
+ "timedmedia-oggThumb-failed": "oggThumb no pudo crear la imagen miniatura.",
+ "timedmedia-status-header": "Estado de transcodificaciĆ³n",
+ "timedmedia-update-status": "Actualizar el estado de transcodificaciĆ³n",
+ "timedmedia-status": "Estado",
+ "timedmedia-status-unknown": "Estado desconocido",
+ "timedmedia-transcodeduration": "Tiempo de codificaciĆ³n",
+ "timedmedia-transcodeinfo": "Formato",
+ "timedmedia-actions": "Acciones",
+ "timedmedia-direct-link": "Descarga",
+ "timedmedia-not-ready": "No estĆ” listo",
+ "timedmedia-completed-on": "Completada $1",
+ "timedmedia-error-on": "Error a las $1",
+ "timedmedia-started-transcode": "Comenzada hace $1. $2",
+ "timedmedia-percent-done": "Aproximadamente $1 % completado",
+ "timedmedia-in-job-queue": "AƱadido a la cola de trabajos hace $1",
+ "timedmedia-unknown-target-size": "TamaƱo de archivo de destino desconocido, $1 codificado",
+ "timedmedia-days": "{{PLURAL:$1|1 dĆ­a|$1 dĆ­as}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 hora|$1 horas}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minuto|$1 minutos}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 segundo|$1 segundos}}",
+ "timedmedia-reset": "Reiniciar la transcodificaciĆ³n",
+ "timedmedia-reset-confirm": "Restablecer esta transcodificaciĆ³n eliminarĆ” cualquier archivo existente (si existe), y volverĆ” a aƱadir la transcodificaciĆ³n a la cola de trabajos. LlevarĆ” algĆŗn tiempo repetir la transcodificaciĆ³n.<br /><br />\nĀæEstĆ”s seguro de que quieres continuar?",
+ "timedmedia-reset-error": "Error al restablecer el trabajo de transcodificaciĆ³n.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Fuente $1",
+ "timedmedia-source-file-desc": "Archivo $1 original, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Archivo $1 original ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Video en formato Ogg de bajo ancho de banda (160 P)",
+ "timedmedia-derivative-desc-360p.ogv": "VĆ­deo Ogg para la web (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "VĆ­deo Ogg para la web (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "VĆ­deo Ogg de alta calidad que se puede descargar (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "Video ogg descargable Full HD (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "WebM para la web (160P)",
+ "timedmedia-derivative-desc-360p.webm": "WebM para la web (360P)",
+ "timedmedia-derivative-desc-480p.webm": "WebM para la web (480P)",
+ "timedmedia-derivative-desc-720p.webm": "WebM de alta calidad que se puede descargar (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "WebM descargable Full HD (1080P)",
+ "timedmedia-derivative-desc-320p.mp4": "MP4 para dispositivos mĆ³viles (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "MP4 para la web (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 de calidad HD (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "MP4 calidad Full HD (1080P)",
+ "timedmedia-subtitle-new": "Crear una nueva traducciĆ³n o editar una existente",
+ "timedmedia-subtitle-new-desc": "Selecciona el idioma y pulsa el botĆ³n '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Ir",
+ "timedmedia-subtitle-language": "SubtĆ­tulos en $1 ($2)",
+ "timedmedia-subtitle-no-video": "No hay ningĆŗn video asociado con la pĆ”gina actual de subtĆ­tulos",
+ "timedmedia-subtitle-no-subtitles": "Actualmente no hay subtƭtulos en $1 para este video, puede [{{fullurl: {{FULLPAGENAME}} |action = edit}} editar esta pƔgina] para agregarlos",
+ "timedmedia-subtitle-remote": "El texto programado para este archivo estĆ” alojado en $1",
+ "timedmedia-subtitle-remote-link": "Puedes [$1 ver la pĆ”gina de descripciĆ³n] de este archivo en $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 vĆ­deo|$1 vĆ­deos}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 vĆ­deo Ogg|$1 vĆ­deos Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 vĆ­deo WebM|$1 vĆ­deos WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transcodificaciĆ³n|$1 transcodificaciones}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 transcodificaciĆ³n activa|$1 transcodificaciones activas}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 transcodificaciĆ³n|$1 transcodificaciones}} en la cola",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 transcodificaciĆ³n fallida|$1 transcodificaciones fallidas}}",
+ "timedmedia-file": "Archivo",
+ "timedmedia-audios": "{{PLURAL:$1|$1 archivo|$1 archivos}} de audio",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 archivo|$1 archivos}} de audio Ogg",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 archivo|$1 archivos}} de audio FLAC",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 archivo|$1 archivos}} de audio WAV",
+ "right-transcode-reset": "Reiniciar los vĆ­deos errĆ³neos o transcodificados por lo que se vuelven a colocar en la cola de trabajo",
+ "right-transcode-status": "Ver [[Special:TimedMediaHandler|informaciĆ³n sobre la actividad de transcodificaciĆ³n actual]]",
+ "action-transcode-status": "ver el estado de transcodificaciĆ³n actual",
+ "orphanedtimedtext": "PƔginas TimedText huƩrfanas",
+ "orphanedtimedtext-summary": "Lista de pƔginas [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] que no tienen un archivo correspondiente.",
+ "orphanedtimedtext-unsupported": "Esta pĆ”gina especial sĆ³lo estĆ” soportada en base de datos MySQL.",
+ "orphanedtimedtext-notimedtext": "TimedText no se activĆ³ en este wiki.",
+ "apihelp-query+videoinfo-example-1": "Obtener informaciĆ³n sobre [[:File:Folgers.ogv]]",
+ "apihelp-transcodereset-param-title": "El tĆ­tulo del archivo multimedia."
+}
diff --git a/extensions/TimedMediaHandler/i18n/et.json b/extensions/TimedMediaHandler/i18n/et.json
new file mode 100644
index 00000000..ce910777
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/et.json
@@ -0,0 +1,122 @@
+{
+ "@metadata": {
+ "authors": [
+ "Avjoska",
+ "Pikne",
+ "Silvar"
+ ]
+ },
+ "timedmedia-desc": "WebM-, srt- ning Theora- ja Vorbis-tĆ¼Ć¼pi Ogg-vormingu toega heli-, video- ja ajastatud teksti kƤsitseja",
+ "timedmedia-ogg-short-audio": "$1-tĆ¼Ć¼pi Ogg-helifail, $2",
+ "timedmedia-ogg-short-video": "$1-tĆ¼Ć¼pi Ogg-videofail, $2",
+ "timedmedia-ogg-short-general": "$1-tĆ¼Ć¼pi Ogg-fail, $2",
+ "timedmedia-ogg-long-audio": "$1-tĆ¼Ć¼pi Ogg-helifail, kestus: $2, $3",
+ "timedmedia-ogg-long-video": "$1-tĆ¼Ć¼pi Ogg-videofail, kestus: $2, $4Ɨ$5 pikslit, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg-liitfail (heli ja video), $1, kestus: $2, $4Ɨ$5 pikslit, Ć¼ldbitikiirus: $3",
+ "timedmedia-ogg-long-general": "Ogg-fail, kestus: $2, $3",
+ "timedmedia-ogg-long-error": "Vigane Ogg-fail: $1",
+ "timedmedia-ogg-long-no-streams": "Ogg-meediafail. Hoiatus: Selles failis ei kasutata Ć¼htegi tuvastatud kodekit.",
+ "timedmedia-webm-short-video": "$1-tĆ¼Ć¼pi WebM-videofail, $2",
+ "timedmedia-webm-long-video": "WebM-fail (heli ja video), $1, kestus: $2, $4Ɨ$5 pikslit, Ć¼ldbitikiirus: $3",
+ "timedmedia-flac-short-audio": "FLAC-helifail, $1",
+ "timedmedia-flac-long-audio": "FLAC-helifail, kestus: $1, Ć¼ldbitikiirus: $2",
+ "timedmedia-wav-short-audio": "WAV-helifail, $1",
+ "timedmedia-wav-long-audio": "WAV-helifail, kestus: $1, Ć¼ldbitikiirus: $2",
+ "timedmedia-wav-pcm-required": "Saad Ć¼les laadida ainult impulssmodulatsiooniga (PCM) WAV-faile.",
+ "timedmedia-mp4-short-video": "$1-tĆ¼Ć¼pi MP4-videofail, $2",
+ "timedmedia-mp4-long-video": "MP4-fail (heli ja video), $1, kestus: $2, $4Ɨ$5 pikslit, Ć¼ldbitikiirus: $3",
+ "timedmedia-no-player-js": "Kahjuks on sinu veebilehitsejas JavaScript keelatud vƵi puudub sul sobiv esitustarkvara.<br />\nSaad <a href=\"$1\">lƵigu alla laadida</a> vƵi <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">laadida alla tarkvara</a>, millega lƵik veebilehitsejas esitada.",
+ "timedmedia-more": "Lisa...",
+ "timedmedia-dismiss": "Sule",
+ "timedmedia-download": "Laadi fail alla",
+ "timedmedia-play-media": "Esita meediafail",
+ "timedmedia-desc-link": "Info faili kohta",
+ "timedmedia-oggThumb-version": "OggHandleri jaoks on vaja oggThumbi versiooni $1 vƵi hilisemat.",
+ "timedmedia-oggThumb-failed": "oggThumb ei saanud pisipildi loomisega hakkama.",
+ "timedmedia-status-header": "Ɯmberkodeeringu olek",
+ "timedmedia-update-status": "VƤrskenda Ć¼mberkodeeringu olekut",
+ "timedmedia-status": "Olek",
+ "timedmedia-status-unknown": "Tundmatu olek",
+ "timedmedia-transcodebitrate": "Bitikiirus",
+ "timedmedia-transcodeduration": "Kodeerimisaeg",
+ "timedmedia-transcodeinfo": "Vorming",
+ "timedmedia-actions": "Toimingud",
+ "timedmedia-direct-link": "Allalaadimine",
+ "timedmedia-not-ready": "Ei ole valmis",
+ "timedmedia-completed-on": "Valmimisaeg: $1",
+ "timedmedia-error-on": "TƵrkeaeg: $1",
+ "timedmedia-started-transcode": "Alustatud $1 tagasi. $2",
+ "timedmedia-percent-done": "Umbes $1% valmis",
+ "timedmedia-in-job-queue": "Lisatud tƶƶjƤrge $1 tagasi",
+ "timedmedia-unknown-target-size": "Sihtsuurus teadmata, $1 kodeeritud",
+ "timedmedia-days": "{{PLURAL:$1|1 pƤev|$1 pƤeva}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 tund|$1 tundi}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minut|$1 minutit}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 sekund|$1 sekundit}}",
+ "timedmedia-reset": "LƤhtesta Ć¼mberkodeering",
+ "timedmedia-reset-confirm": "Ɯmberkodeeringu lƤhtestamisel eemaldatakse kƵik olemasolevad failid (kui neid on) ja see lisatakse uuesti tƶƶjƤrge. Uus Ć¼mberkodeering kestab mƵnda aega.<br /><br />\nKas oled kindel, et tahad jƤtkata?",
+ "timedmedia-reset-error": "Ɯmberkodeeringu lƤhtestamisel ilmnes tƵrge.",
+ "timedmedia-source-file": "Allikas ($1)",
+ "timedmedia-source-file-desc": "Algne $1-fail, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Algne $1-fail ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "VƤikse ribalaiusega Ogg-video (160P)",
+ "timedmedia-derivative-desc-240p.ogv": "VƵrgus voogedastatav Ogg-video (240P)",
+ "timedmedia-derivative-desc-360p.ogv": "VƵrgus voogedastatav Ogg-video (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "VƵrgus voogedastatav Ogg-video (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "KƵrge kvaliteediga allalaaditav Ogg-video (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "TƤiskƵrglahutusega allalaaditav Ogg-video (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "VƵrgus voogedastatav WebM-video (160P)",
+ "timedmedia-derivative-desc-360p.webm": "VƵrgus voogedastatav WebM-video (360P)",
+ "timedmedia-derivative-desc-480p.webm": "VƵrgus voogedastatav WebM-video (480P)",
+ "timedmedia-derivative-desc-720p.webm": "KƵrge kvaliteediga allalaaditav WebM-video (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "TƤiskƵrglahutusega allalaaditav WebM-video (1080P)",
+ "timedmedia-derivative-desc-2160p.webm": "Allalaaditav 4K-tƤislahutusega WebM-video (2160P)",
+ "timedmedia-derivative-desc-360p.vp9.webm": "VƵrgus voogedastatav VP9-tĆ¼Ć¼pi WebM-video (360P)",
+ "timedmedia-derivative-desc-480p.vp9.webm": "VƵrgus voogedastatav VP9-tĆ¼Ć¼pi WebM-video (480P)",
+ "timedmedia-derivative-desc-720p.vp9.webm": "KƵrglahutusega voogedastatav VP9-tĆ¼Ć¼pi WebM-video (720P)",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "TƤiskƵrglahutusega voogedastatav VP9-tĆ¼Ć¼pi WebM-video (1080P)",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "Voogedastatav 4K-tƤislahutusega VP9-tĆ¼Ć¼pi WebM-video (2160P)",
+ "timedmedia-derivative-desc-320p.mp4": "Seadmetele sobiv MP4-video (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "VƵrgus voogedastatav MP4-video (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "KƵrglahutusega MP4-video (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "TƤiskƵrglahutusega MP4-kvaliteetvideo (1080P)",
+ "timedmedia-derivative-desc-2160p.mp4": "4K-tƤislahutusega MP4-kvaliteetvideo (2160P)",
+ "timedmedia-subtitle-new": "Uue tƵlkega alustamine vƵi olemasoleva muutmine",
+ "timedmedia-subtitle-new-desc": "Vali keel ja klƵpsa nuppu '''{{int:Timedmedia-subtitle-new-go}}'''.",
+ "timedmedia-subtitle-new-go": "Mine",
+ "timedmedia-subtitle-language": "$1 ($2) alltiitrid",
+ "timedmedia-subtitle-no-video": "Puudub selle alltiitrite lehekĆ¼ljega seotud video.",
+ "timedmedia-subtitle-no-subtitles": "Selle video alltiitrid puuduvad praegu selles keeles ($1). Saad seda lehekĆ¼lge [{{fullurl:{{FULLPAGENAME}}|action=edit}} redigeerida], et need lisada.",
+ "timedmedia-subtitle-remote": "Selle faili ajastatud tekst on hoidlas $1",
+ "timedmedia-subtitle-remote-link": "Selle faili [$1 kirjelduslehekĆ¼lge] saad vaadata hoidlas $2.",
+ "timedmediahandler": "Ajastatud meediafailide tƶƶtleja",
+ "timedmedia-videos": "{{PLURAL:$1|$1 video|$1 videot}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg-video|$1 Ogg-videot}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM-video|$1 WebM-videot}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|Ɯks Ć¼mberkodeering|$1 Ć¼mberkodeeringut}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|Ɯks|$1}} tƤitmisel {{PLURAL:$1|Ć¼mberkodeering|Ć¼mberkodeeringut}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|Ɯks|$1}} ootel {{PLURAL:$1|Ć¼mberkodeering|Ć¼mberkodeeringut}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|Ɯks|$1}} ebaƵnnestunud {{PLURAL:$1|Ć¼mberkodeering|Ć¼mberkodeeringut}}",
+ "timedmedia-file": "Fail",
+ "timedmedia-audios": "{{PLURAL:$1|$1 helifail|$1 helifaili}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ogg-helifail|$1 Ogg-helifaili}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 FLAC-helifail|$1 FLAC-helifaili}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 WAV-helifail|$1 WAV-helifaili}}",
+ "right-transcode-reset": "LƤhtestada ebaƵnnestunud vƵi Ć¼mberkodeeritud videoid, nii et need lisatakse uuesti tƶƶjƤrge",
+ "right-transcode-status": "Vaadata [[Special:TimedMediaHandler|teavet praegu aktiivsete Ć¼mberkodeeringute kohta]]",
+ "action-transcode-status": "vaadata praegust Ć¼mberkodeeringute olekut",
+ "orphanedtimedtext": "Ajastatud teksti orblehekĆ¼ljed",
+ "orphanedtimedtext-summary": "Loend nimeruumi [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] lehekĆ¼lgedest, millele vastav fail puudub.",
+ "orphanedtimedtext-unsupported": "Seda erilehekĆ¼lge toetatakse ainult MySQL-andmebaasides.",
+ "orphanedtimedtext-notimedtext": "Ajastatud tekst pole selles vikis lubatud.",
+ "apihelp-query+transcodestatus-description": "Antud faili Ć¼mberkodeerimise oleku hankimine.",
+ "apihelp-query+transcodestatus-example-1": "Hangi faili [[:File:Clip.webm|Clip.webm]] Ć¼mberkodeerimise olek",
+ "apihelp-query+videoinfo-description": "Laiendab moodulit \"imageinfo\", kaasa arvatakse teave video allika (tuletiste) kohta.",
+ "apihelp-query+videoinfo-param-prop": "Millist teavet video kohta hankida:\n;timestamp: Lisab Ć¼les laaditud versiooni ajatempli.\n;user: Lisab kasutaja, kes videoversiooni Ć¼les laadis.\n;userid: Lisab videoversiooni Ć¼les laadinud kasutaja identifikaatori.\n;comment: Lisab versioonikommentaari.\n;parsedcomment: Parsib versioonikommentaari.\n;canonicaltitle: Lisab videofaili kanoonilise pealkirja.\n;url: Tagastab videofaili ja kirjelduslehekĆ¼lje internetiaadressi.\n;size: Lisab video suuruse baitides ning selle kƵrguse ja laiuse. LehekĆ¼lgede arv ja kestus lisatakse, kui see on kohane.\n;dimensions: Elemendi \"size\" rƶƶpnimi.\n;sha1: Lisab video SHA-1 rƤsivƤƤrtuse.\n;mime: Lisab video MIME tĆ¼Ć¼bi.\n;thumbmime: Lisab video pisipildi MIME tĆ¼Ć¼bi (vaja elementi \"url\" ja parameetrit \"$1urlwidth\").\n;mediatype: Lisab video meediatĆ¼Ć¼bi.\n;metadata: Loetleb videoversiooni Exif-metaandmed.\n;commonmetadata: Loetleb videoversiooni failivormingu Ć¼ldised metaandmed.\n;extmetadata: Loetleb mitme allika vormindatud Ć¼hendmetaandmed. Tulemused on HTML-vormingus.\n;archivename: Lisab praegusest versioonist vanemate arhiiviversioonide failinimed.\n;bitdepth: Lisab versiooni bitisĆ¼gavuse.\n;uploadwarning: Kasutab lehekĆ¼lg [[Special:Upload]], et saada teavet olemasoleva faili kohta. Pole mƵeldud kasutamiseks vƤljaspool MediaWiki keskosa.\n;derivatives: Lisab heli- vƵi videofaili erinevaid saadaolevaid vorminguid ja kvaliteediversioone sisaldava massiivi.",
+ "apihelp-query+videoinfo-example-1": "Faili [[:File:Folgers.ogv|Folgers.ogv]] teabe vƤljavƵtt",
+ "apihelp-transcodereset-description": "Kasutajad, kellel on Ƶigus \"transcode-reset\", saavad Ć¼mberkodeerimistƶƶd lƤhtestada ja uuesti kƤitada.",
+ "apihelp-transcodereset-param-title": "Meediafaili pealkiri.",
+ "apihelp-transcodereset-param-transcodekey": "LƤhtestatava Ć¼mberkodeerimise vƵti. Leitav pƤringuga [[Special:ApiHelp/query+transcodestatus|action=query&prop=transcodestatus]].",
+ "apihelp-transcodereset-example-1": "LƤhtesta kƵik faili [[:File:Clip.webm|Clip.webm]] Ć¼mberkodeeringud",
+ "apihelp-transcodereset-example-2": "LƤhtesta faili [[:File:Clip.webm|Clip.webm]] Ć¼mberkodeerimisvƵti '360_560kbs.webm'"
+}
diff --git a/extensions/TimedMediaHandler/i18n/eu.json b/extensions/TimedMediaHandler/i18n/eu.json
new file mode 100644
index 00000000..fb5ff526
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/eu.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "An13sa",
+ "Joxemai",
+ "Theklan",
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ",
+ "Subi",
+ "Sator"
+ ]
+ },
+ "timedmedia-desc": "Ogg Theora eta Vorbis fitxategientzako edukiontzia, JavaScript playerrarekin",
+ "timedmedia-ogg-short-audio": "Ogg $1 soinu fitxategia, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 bideo fitxategia, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 media fitxategia, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 soinu fitxategia, $2 iraupea, $3",
+ "timedmedia-ogg-long-error": "ogg fitxategi okerra: $1",
+ "timedmedia-more": "Gehiago...",
+ "timedmedia-dismiss": "Itxi",
+ "timedmedia-download": "Fitxategia jaitsi",
+ "timedmedia-desc-link": "Fitxategi honen inguruan",
+ "timedmedia-status": "Egoera",
+ "timedmedia-transcodeinfo": "Formatua",
+ "timedmedia-direct-link": "Jaitsi",
+ "timedmedia-source-file": "$1 iturri",
+ "timedmedia-source-audio-file-desc": "Jatorrizko $1 fitxategia ($2)",
+ "timedmedia-subtitle-new-go": "Joan",
+ "timedmedia-file": "Fitxategia"
+}
diff --git a/extensions/TimedMediaHandler/i18n/fa.json b/extensions/TimedMediaHandler/i18n/fa.json
new file mode 100644
index 00000000..2a3a549c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/fa.json
@@ -0,0 +1,123 @@
+{
+ "@metadata": {
+ "authors": [
+ "Alireza",
+ "Armin1392",
+ "Calak",
+ "Ebraminio",
+ "Huji",
+ "Mahdiz",
+ "Mjbmr",
+ "Reza1615",
+ "Ų¬ŁˆŲ§ŲÆ",
+ "Ł¾Ų§Ł†Ų§Ų±ŁˆŁ…Ų§",
+ "Mehran"
+ ]
+ },
+ "extensionname-timedmedia": "Ł‡ŲÆŲ§ŪŒŲŖā€ŒŚ©Ł†Ł†ŲÆŁ‡ Ų±Ų³Ų§Ł†Ł‡Ł” Ų²Ł…Ų§Ł†ā€ŒŲÆŲ§Ų±",
+ "timedmedia-desc": "ŲØŁ‡ ŲÆŲ³ŲŖ ŚÆŪŒŲ±Ł†ŲÆŁ‡Ł” Ł¾Ų±ŁˆŁ†ŲÆŁ‡ā€ŒŁ‡Ų§ŪŒ ŲµŁˆŲŖŪŒŲŒ ŲŖŲµŁˆŪŒŲ±ŪŒ Łˆ Ł…ŲŖŁ†ā€ŒŁ‡Ų§ŪŒ Ų²Ł…Ų§Ł†ā€ŒŲØŁ†ŲÆŪŒ Ų“ŲÆŁ‡ ŲØŲ§ Ł¾Ų“ŲŖŪŒŲØŲ§Ł†ŪŒ Ų§Ų² Ogg Theora ŲŒVorbis Łˆ srt",
+ "timedmedia-ogg-short-audio": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡ ŲµŁˆŲŖŪŒ Ogg $1ŲŒ $2",
+ "timedmedia-ogg-short-video": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡ ŲŖŲµŁˆŪŒŲ±ŪŒ Ogg $1ŲŒ $2",
+ "timedmedia-ogg-short-general": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡ Ogg $1ŲŒ $2",
+ "timedmedia-ogg-long-audio": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡ ŲµŁˆŲŖŪŒ Ogg $1ŲŒ Ł…ŲÆŲŖ $2ŲŒ $3",
+ "timedmedia-ogg-long-video": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡ ŲŖŲµŁˆŪŒŲ±ŪŒ Ogg $1ŲŒ Ł…ŲÆŲŖ $2 ŲŒ $4Ɨ$5 Ł¾ŪŒŚ©Ų³Ł„ŲŒ $3",
+ "timedmedia-ogg-long-multiplexed": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡ ŲµŁˆŲŖŪŒ/ŲŖŲµŁˆŪŒŲ±ŪŒ Ł¾ŪŒŚ†ŪŒŲÆŁ‡ OggŲŒ $1ŲŒ Ł…ŲÆŲŖ $2ŲŒ $4Ɨ$5 Ł¾ŪŒŚ©Ų³Ł„ŲŒ $3 ŲÆŲ± Ł…Ų¬Ł…ŁˆŲ¹",
+ "timedmedia-ogg-long-general": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡ OggŲŒ Ł…ŲÆŲŖ $2ŲŒ $3",
+ "timedmedia-ogg-long-error": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡Ł” Ogg Ł†Ų§Ł…Ų¬Ų§Ų²: $1",
+ "timedmedia-ogg-long-no-streams": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡Ł” Ų±Ų³Ų§Ł†Ł‡ā€ŒŲ§ŪŒ Ogg. Ł‡Ų“ŲÆŲ§Ų±: Ł‡ŪŒŚ†ā€ŒŪŒŚ© Ų§Ų² Ų§ŪŒŁ† Ś©ŲÆŚ©ā€ŒŁ‡Ų§ŪŒ Ų§Ų³ŲŖŁŲ§ŲÆŁ‡ā€ŒŲ“ŲÆŁ‡ ŲÆŲ± Ų§ŪŒŁ† Ł¾Ų±ŁˆŁ†ŲÆŁ‡ā€ŒŁ‡Ų§ Ų“Ł†Ų§Ų®ŲŖŁ‡ā€ŒŲ“ŲÆŁ‡ Ł†ŪŒŲ³ŲŖŁ†ŲÆ.",
+ "timedmedia-webm-short-video": "Ų±Ų³Ų§Ł†Ł‡Ł” ŁˆŲØ $1 Ł¾Ų±ŁˆŁ†ŲÆŁ‡Ł” ŁˆŪŒŲÆŲ¦ŁˆŪŒŪŒŲŒ $2",
+ "timedmedia-webm-long-video": "Ų±Ų³Ų§Ł†Ł‡Ł” ŁˆŲØ Ł¾Ų±ŁˆŁ†ŲÆŁ‡Ł” ŲµŁˆŲŖŪŒ/ŲŖŲµŁˆŪŒŲ±ŪŒŲŒ $1ŲŒ Ł…ŲÆŲŖ $2ŲŒ $4 Ɨ $5 Ł¾ŪŒŚ©Ų³Ł„ŲŒ $3 Ś©Ł„ŪŒ",
+ "timedmedia-flac-short-audio": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡Ł” ŲµŁˆŲŖŪŒ Ų§Łā€ŒŲ§Ł„ā€ŒŲ§ŪŒā€ŒŲ³ŪŒŲŒ $1",
+ "timedmedia-flac-long-audio": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡Ł” ŲµŁˆŲŖŪŒ Ų§Łā€ŒŲ§Ł„ā€ŒŲ§ŪŒā€ŒŲ³ŪŒŲŒ Ł…ŲÆŲŖ $1ŲŒ $2 Ś©Ł„ŪŒ",
+ "timedmedia-wav-short-audio": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡Ł” ŲµŁˆŲŖŪŒ WAVŲŒ $1",
+ "timedmedia-wav-long-audio": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡Ł” ŲµŁˆŲŖŪŒ WAVŲŒ Ł…ŲÆŲŖ $1ŲŒ $2 Ś©Ł„ŪŒ",
+ "timedmedia-wav-pcm-required": "Ų“Ł…Ų§ ŁŁ‚Ų· Ł…ŪŒ ŲŖŁˆŲ§Ł†ŪŒŲÆ PCM Łˆ WAV Ų±Ų§ ŲØŲ§Ų± Ś©Ł†ŪŒŲÆ.",
+ "timedmedia-mp4-short-video": "MP4 $1 Ł¾Ų±ŁˆŁ†ŲÆŁ‡Ł” ŁˆŪŒŲÆŲ¦ŁˆŪŒŪŒŲŒ $2",
+ "timedmedia-mp4-long-video": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡ā€ŒŁ‡Ų§ŪŒ ŲµŁˆŲŖŪŒ ŪŒŲ§ ŲŖŲµŁˆŪŒŲ±ŪŒ ŲØŲ§ Ł‚Ų§Ł„ŲØ $1ŲŒ Ų²Ł…Ų§Ł† $2ŲŒ $4 Ɨ $5 Ł¾ŪŒŚ©Ų³Ł„ Łˆ $3 ŲØŁ‡ Ų·ŁˆŲ±Ś©Ł„ŪŒ",
+ "timedmedia-no-player-js": "ŲØŲ§ Ų¹Ų±Ų¶ Ł¾ŁˆŲ²Ų“ŲŒ Ł†Ų±Ł… Ų§ŁŲ²Ų§Ų± Ų¬Ų§ŁˆŲ§ Ų§Ų³Ś©Ų±ŪŒŁ¾ŲŖ ŲØŲ±Ų±ŁˆŪŒ Ł…Ų±ŁˆŲ±ŚÆŲ± Ų“Ł…Ų§ ŁŲ¹Ų§Ł„ Ł†ŪŒŲ³ŲŖŲŒ Łˆ ŪŒŲ§ Ł…Ų±ŁˆŲ±ŚÆŲ± Ų“Ł…Ų§ Ų§Ų² Ų§ŪŒŁ† Ł†Ų±Ł… Ų§ŁŲ²Ų§Ų± Ł¾Ų“ŲŖŪŒŲØŲ§Ł†ŪŒ Ł†Ł…ŪŒ Ś©Ł†ŲÆ.<br />\nŲ“Ł…Ų§ Ł…ŪŒŲŖŁˆŲ§Ł†ŪŒŲÆ <a href=\"$1\">Ų§ŪŒŁ† ŁˆŪŒŲÆŪŒŁˆ Ų±Ų§ ŲÆŲ§Ł†Ł„ŁˆŲÆ</a> Łˆ ŪŒŲ§ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ŪŒŚ© Ł¾Ų®Ų“ Ś©Ł†Ł†ŲÆŁ‡</a> ŲØŲ±Ų§ŪŒ Ų§Ų¬Ų±Ų§ŪŒ Ų§ŪŒŁ† ŁˆŪŒŲÆŪŒŁˆ ŲÆŲ§Ł†Ł„ŁˆŲÆ Ł†Ł…Ų§ŪŒŪŒŲÆ.",
+ "timedmedia-more": "ŲØŪŒŲ“ŲŖŲ±...",
+ "timedmedia-dismiss": "ŲØŲ³ŲŖŁ†",
+ "timedmedia-download": "ŲÆŲ±ŪŒŲ§ŁŲŖ Ł¾Ų±ŁˆŁ†ŲÆŁ‡",
+ "timedmedia-play-media": "Ł¾Ų®Ų“ Ų±Ų³Ų§Ł†Ł‡",
+ "timedmedia-desc-link": "ŲÆŲ±ŲØŲ§Ų±Ł‡Ł” Ų§ŪŒŁ† Ł¾Ų±ŁˆŁ†ŲÆŁ‡",
+ "timedmedia-oggThumb-version": "Ł†ŚÆŁ‡ŲÆŲ§Ų±Ł†ŲÆŁ‡Ł” Ogg ŲØŁ‡ ŲØŁ†ŲÆā€ŒŲ§Ł†ŚÆŲ“ŲŖŪŒ Ogg Ł†Ų³Ų®Ł‡Ł” $1 ŪŒŲ§ ŲØŲ§Ł„Ų§ŲŖŲ± Ł†ŪŒŲ§Ų² ŲÆŲ§Ų±ŲÆ.",
+ "timedmedia-oggThumb-failed": "ŲØŁ†ŲÆŲ§Ł†ŚÆŲ“ŲŖŪŒ Ogg ŲÆŲ± Ų³Ų§Ų®ŲŖ ŲØŁ†ŲÆŲ§Ł†ŚÆŲ“ŲŖŪŒ ŲØŲ§ Ų®Ų·Ų§ Ł…ŁˆŲ§Ų¬Ł‡ Ų“ŲÆ.",
+ "timedmedia-status-header": "ŁˆŲ¶Ų¹ŪŒŲŖ ŁŲ±Ų§Ś©ŲÆ",
+ "timedmedia-update-status": "ŁˆŲ¶Ų¹ŪŒŲŖ ŲØŁ‡ā€ŒŲ±ŁˆŲ²Ų±Ų³Ų§Ł†ŪŒ ŁŲ±Ų§Ś©ŲÆ",
+ "timedmedia-status": "ŁˆŲ¶Ų¹ŪŒŲŖ",
+ "timedmedia-status-unknown": "ŁˆŲ¶Ų¹ŪŒŲŖ Ł†Ų§Ų“Ł†Ų§Ų®ŲŖŁ‡",
+ "timedmedia-transcodeinfo": "ŲŖŁˆŲ¶ŪŒŲ­Ų§ŲŖ Ų§Ų“ŲŖŁ‚Ų§Ł‚ŪŒ ŁŲ±Ų§Ś©ŲÆ",
+ "timedmedia-actions": "ŁŲ¹Ų§Ł„ŪŒŲŖā€ŒŁ‡Ų§",
+ "timedmedia-direct-link": "ŲÆŲ±ŪŒŲ§ŁŲŖ Ų§Ų“ŲŖŁ‚Ų§Ł‚ŪŒ",
+ "timedmedia-not-ready": "Ų¢Ł…Ų§ŲÆŁ‡ Ł†ŪŒŲ³ŲŖ",
+ "timedmedia-completed-on": "ŲŖŚ©Ł…ŪŒŁ„ ŁŲ±Ų§Ś©ŲÆ $1",
+ "timedmedia-error-on": "Ų®Ų·Ų§ ŲÆŲ± ŁŲ±Ų§Ś©ŲÆ ŲÆŲ± $1",
+ "timedmedia-started-transcode": "ŁŲ±Ų§Ś©ŲÆ $1 Ł¾ŪŒŲ“ Ų¢ŲŗŲ§Ų² Ų“ŲÆ. $2",
+ "timedmedia-percent-done": "Ų­ŲÆŁˆŲÆ $1% Ų§Ł†Ų¬Ų§Ł… Ų“ŲÆŁ‡",
+ "timedmedia-in-job-queue": "Ų§Ų¶Ų§ŁŁ‡ā€ŒŲ“ŲÆ ŲØŁ‡ ŲµŁ Ś©Ų§Ų± $1 Ł¾ŪŒŲ“",
+ "timedmedia-unknown-target-size": "Ų§Ł†ŲÆŲ§Ų²Ł‡Ł” Ł‡ŲÆŁ Ł†Ų§Ų“Ł†Ų§Ų®ŲŖŁ‡ŲŒ $1 Ų±Ł…Ų²ŪŒ",
+ "timedmedia-days": "{{PLURAL:$1|1 Ų±ŁˆŲ²|$1 Ų±ŁˆŲ²}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 Ų³Ų§Ų¹ŲŖ|$1 Ų³Ų§Ų¹ŲŖ}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 ŲÆŁ‚ŪŒŁ‚Ł‡|$1 ŲÆŁ‚ŪŒŁ‚Ł‡}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 Ų«Ų§Ł†ŪŒŁ‡|$1 Ų«Ų§Ł†ŪŒŁ‡}}",
+ "timedmedia-reset": "ŲŖŁ†ŲøŪŒŁ… Ł…Ų¬ŲÆŲÆ ŁŲ±Ų§Ś©ŲÆ",
+ "timedmedia-reset-confirm": "ŲŖŁ†ŲøŪŒŁ… Ł…Ų¬ŲÆŲÆ ŁŲ±Ų§Ś©ŲÆ Ł¾Ų±ŁˆŁ†ŲÆŁ‡ā€ŒŁ‡Ų§ŪŒ Ł…ŁˆŲ¬ŁˆŲÆ Ų±Ų§ Ų­Ų°Ł Ų®ŁˆŲ§Ł‡ŲÆ Ś©Ų±ŲÆ Łˆ ŁŲ±Ų§Ś©ŲÆ Ų±Ų§ ŲÆŲ± ŲµŁ Ś©Ų§Ų± Ų®ŁˆŲ§Ł‡ŲÆ Ų§ŁŲ²ŁˆŲÆ. Ų§ŪŒŁ† Ś©Ų§Ų± Ł…Ł‚ŲÆŲ§Ų±ŪŒ Ų²Ł…Ų§Ł† Ł„Ų§Ų²Ł… ŲÆŲ§Ų±ŲÆ.<br /><br />\nŲ¢ŪŒŲ§ Ł…ŪŒā€ŒŲ®ŁˆŲ§Ł‡ŪŒŲÆ Ų§ŲÆŲ§Ł…Ł‡ ŲÆŁ‡ŪŒŲÆŲŸ",
+ "timedmedia-reset-error": "Ų®Ų·Ų§ ŲÆŲ± ŲØŲ§Ų²Ł†Ų“Ų§Ł†ŪŒ Ś©Ų§Ų± ŁŲ±Ų§Ś©ŲÆ.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 Ł…ŲØŲÆŲ£",
+ "timedmedia-source-file-desc": "Ų§ŲµŁ„ŪŒ $1 Ł¾Ų±ŁˆŁ†ŲÆŁ‡ŲŒ $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Ų§ŲµŁ„ŪŒ $1 Ł¾Ų±ŁˆŁ†ŲÆŁ‡ ( $2 )",
+ "timedmedia-derivative-desc-160p.ogv": "ŁˆŪŒŲÆŲ¦Łˆ Ogg ŲØŲ§ Ł¾Ł‡Ł†Ų§ŪŒ ŲØŲ§Ł†ŲÆ Ś©Ł… (160P)",
+ "timedmedia-derivative-desc-240p.ogv": "ŁˆŪŒŲÆŪŒŁˆŪŒ Ų¢ŚÆ Ł‚Ų§ŲØŁ„ ŲØŲ®Ų“ ŲÆŲ± ŁˆŲØ (Ū²Ū“Ū° Ł†Ł‚Ų·Ł‡)",
+ "timedmedia-derivative-desc-360p.ogv": "ŁˆŪŒŲÆŲ¦Łˆ Ogg ŲØŲ§ Ł¾Ł‡Ł†Ų§ŪŒ ŁˆŲØ (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "ŁˆŪŒŲÆŲ¦Łˆ Ogg ŲØŲ§ Ł¾Ł‡Ł†Ų§ŪŒ ŁˆŲØ (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "ŁˆŪŒŲÆŲ¦Łˆ Ogg Ł‚Ų§ŲØŁ„ ŲØŲ§Ų±ŚÆŪŒŲ±ŪŒ ŲØŲ§ Ś©ŪŒŁŪŒŲŖ ŲØŲ§Ł„Ų§ (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "ŁˆŪŒŲÆŪŒŁˆŪŒ Ų¢ŚÆ Ś©Ų§Ł…Ł„Ų§Ł‹ Ų§Ś†ā€ŒŲÆŪŒ (Ū±Ū°ŪøŪ° Ł¾ŪŒŚ©Ų³Ł„)",
+ "timedmedia-derivative-desc-160p.webm": "Ų±Ų³Ų§Ł†Ł‡ ŁˆŲØ ŲØŲ§ Ł¾Ł‡Ł†Ų§ŪŒ ŁˆŲØ (160P)",
+ "timedmedia-derivative-desc-360p.webm": "Ų±Ų³Ų§Ł†Ł‡ ŁˆŲØ ŲØŲ§ Ł¾Ł‡Ł†Ų§ŪŒ ŁˆŲØ (360P)",
+ "timedmedia-derivative-desc-480p.webm": "Ų±Ų³Ų§Ł†Ł‡ ŁˆŲØ ŲØŲ§ Ł¾Ł‡Ł†Ų§ŪŒ ŁˆŲØ (480P)",
+ "timedmedia-derivative-desc-720p.webm": "Ų±Ų³Ų§Ł†Ł‡ ŁˆŲØ Ł‚Ų§ŲØŁ„ ŲØŲ§Ų±ŚÆŪŒŲ±ŪŒ ŲØŲ§ Ś©ŪŒŁŪŒŲŖ ŲØŲ§Ł„Ų§ (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "ŁˆŪŒŲÆŪŒŁˆŪŒ ŁˆŲØā€ŒŲ§Ł… Ś©Ų§Ł…Ł„Ų§Ł‹ Ų§Ś†ā€ŒŲÆŪŒ (Ū±Ū°ŪøŪ° Ł¾ŪŒŚ©Ų³Ł„)",
+ "timedmedia-derivative-desc-320p.mp4": "Ų§ŲØŲ²Ų§Ų± Ų³Ų§Ų²ŚÆŲ§Ų± ŲØŲ§ MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "Ł¾Ł‡Ł†Ų§ŪŒ ŁˆŲØ MP4 (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "Ś©ŪŒŁŪŒŲŖ ŲØŲ§Ł„Ų§ MP4 (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "ŁˆŪŒŲÆŪŒŁˆŪŒ Ų§Ł…ā€ŒŁ¾ŪŒŪ“ Ś©Ų§Ł…Ł„Ų§Ł‹ Ų§Ś†ā€ŒŲÆŪŒ (Ū±Ū°ŪøŪ° Ł¾ŪŒŚ©Ų³Ł„)",
+ "timedmedia-subtitle-new": "ŲŖŲ±Ų¬Ł…Ł‡ Ų¬ŲÆŪŒŲÆŪŒ Ų±Ų§ Ų§ŪŒŲ¬Ų§ŲÆ Ś©Ł†ŪŒŲÆ ŪŒŲ§ ŲÆŲ± ŲµŁˆŲ±ŲŖ ŁˆŲ¬ŁˆŲÆ Ų¢Ł† Ų±Ų§ ŁˆŪŒŲ±Ų§ŪŒŲ“ Ś©Ł†ŪŒŲÆ.",
+ "timedmedia-subtitle-new-desc": " Ų²ŲØŲ§Ł† Ų±Ų§ Ų§Ł†ŲŖŲ®Ų§ŲØ Ś©Ł†ŪŒŲÆ Łˆ ŲÆŚ©Ł…Ł‡Ł” '''{{int:Timedmedia-subtitle-new-go}}''' Ų±Ų§ ŲØŁŲ“Ų§Ų±ŪŒŲÆ",
+ "timedmedia-subtitle-new-go": "ŲØŲ±Łˆ",
+ "timedmedia-subtitle-language": "$1 ($2) Ų²ŪŒŲ±Ł†ŁˆŪŒŲ³ā€ŒŁ‡Ų§",
+ "timedmedia-subtitle-no-video": "Ł‡ŪŒŚ† ŁˆŪŒŲÆŲ¦ŁˆŪŒŪŒ Ł…Ų±ŲŖŲØŲ· ŲØŲ§ Ų²ŪŒŲ±Ų¹Ł†ŁˆŲ§Ł† Ų§ŪŒŁ† ŲµŁŲ­Ł‡ Ł…ŁˆŲ¬ŁˆŲÆ Ł†ŪŒŲ³ŲŖ",
+ "timedmedia-subtitle-no-subtitles": "ŲÆŲ± Ų­Ų§Ł„ Ų­Ų§Ų¶Ų± Ų²ŪŒŲ±Ł†ŁˆŪŒŲ³ŪŒ ŲØŲ±Ų§ŪŒ $1 ŲÆŲ± Ų§ŪŒŁ† ŁˆŪŒŲÆŪŒŁˆ ŁˆŲ¬ŁˆŲÆ Ł†ŲÆŲ§Ų±ŲÆŲŒ Ł…ŪŒā€ŒŲŖŁˆŲ§Ł†ŪŒŲÆ Ų§ŪŒŁ† ŲµŁŲ­Ł‡ Ų±Ų§ ŲØŲ±Ų§ŪŒ Ų§ŁŲ²ŁˆŲÆŁ† Ų¢Ł†ā€ŒŁ‡Ų§ [{{fullurl:{{FULLPAGENAME}}|action=edit}} ŁˆŪŒŲ±Ų§ŪŒŲ“ Ś©Ł†ŪŒŲÆ].",
+ "timedmedia-subtitle-remote": "Ł…ŲŖŁ† Ų²Ł…Ų§Ł†ā€ŒŲÆŲ§Ų± ŲØŲ±Ų§ŪŒ Ł¾Ų±ŁˆŁ†ŲÆŁ‡ Ų°Ų®ŪŒŲ±Ł‡ Ų“ŲÆŁ‡ ŲÆŲ± $1",
+ "timedmedia-subtitle-remote-link": "Ų“Ł…Ų§ Ł…ŪŒ ŲŖŁˆŲ§Ł†ŪŒŲÆ [$1 ŲŖŁˆŲ¶ŪŒŲ­Ų§ŲŖ ŲµŁŲ­Ł‡ Ł…Ų“Ų§Ł‡ŲÆŁ‡ Ś©Ł†ŪŒŲÆ] ŲØŲ±Ų§ŪŒ Ų§ŪŒŁ† Ł¾Ų±ŁˆŁ†ŲÆŁ‡ ŲÆŲ± $2",
+ "timedmediahandler": "Ł‡ŲÆŲ§ŪŒŲŖā€ŒŚ©Ł†Ł†ŲÆŁ‡ Ų±Ų³Ų§Ł†Ł‡Ł” Ų²Ł…Ų§Ł†ā€ŒŲÆŲ§Ų±",
+ "timedmedia-videos": "{{PLURAL:$1|$1 ŁˆŪŒŲÆŲ¦Łˆ|$1 ŁˆŪŒŲÆŲ¦Łˆ}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 ŁˆŪŒŲÆŲ¦Łˆ Ogg|$1 ŁˆŪŒŲÆŲ¦Łˆ Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 ŁˆŪŒŲÆŲ¦Łˆ WebM|$1 ŁˆŪŒŲÆŲ¦Łˆ WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 ŁŲ±Ų§Ś©ŲÆŁ‡Ų§|$1 ŁŲ±Ų§Ś©ŲÆŁ‡Ų§}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 ŲÆŲ±Ų­Ų§Ł„ Ų§Ų¬Ų±Ų§ŪŒ ŁŲ±Ų§Ś©ŲÆŁ‡Ų§|$1 ŲÆŲ± Ų­Ų§Ł„ Ų§Ų¬Ų±Ų§ŪŒ ŁŲ±Ų§Ś©ŲÆŁ‡Ų§}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 ŲµŁ ŁŲ±Ų§Ś©ŲÆŁ‡Ų§|$1 ŲµŁ ŁŲ±Ų§Ś©ŲÆŁ‡Ų§}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 ŁŲ±Ų§Ś©ŲÆŁ‡Ų§ŪŒ Ų§Ų“ŲŖŲØŲ§Ł‡|$1 ŁŲ±Ų§Ś©ŲÆŁ‡Ų§ŪŒ Ų§Ų“ŲŖŲØŲ§Ł‡}}",
+ "timedmedia-file": "Ł¾Ų±ŁˆŁ†ŲÆŁ‡",
+ "timedmedia-audios": "{{PLURAL:$1|$1 Ł¾ŁˆŲ“Ł‡Ł” ŲµŁˆŲŖŪŒ|$1 Ł¾ŁˆŲ“Ł‡ā€ŒŁ‡Ų§ŪŒ ŲµŁˆŲŖŪŒ}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ł¾ŁˆŲ“Ł‡Ł” ŲµŁˆŲŖŪŒ Ų¢ŚÆ|$1 Ł¾ŁˆŲ“Ł‡ā€ŒŁ‡Ų§ŪŒ ŲµŁˆŲŖŪŒ Ų¢ŚÆ}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1Ł¾ŁˆŲ“Ł‡ā€ŒŁ” ŲµŁˆŲŖŪŒ Ų§Łā€ŒŲ§Ł„ā€ŒŲ§ŪŒā€ŒŲ³ŪŒ|$1Ł¾ŁˆŲ“Ł‡ā€ŒŁ‡Ų§ŪŒ ŲµŁˆŲŖŪŒ Ų§Łā€ŒŲ§Ł„ā€ŒŲ§ŪŒā€ŒŲ³ŪŒ}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 Ł¾ŁˆŲ“Ł‡ā€ŒŁ” ŲµŁˆŲŖŪŒ ŲÆŲØŁ„ŪŒŁˆā€ŒŲ§ŪŒā€ŒŁˆŪŒ|$1 Ł¾ŁˆŲ“Ł‡ā€ŒŁ‡Ų§ŪŒ ŲµŁˆŲŖŪŒ ŲÆŲØŁ„ŪŒŁˆā€ŒŲ§ŪŒā€ŒŁˆŪŒ}}",
+ "right-transcode-reset": "ŲŖŁ†ŲøŪŒŁ… Ł…Ų¬ŲÆŲÆ Ų§Ł†Ų¬Ų§Ł…ā€ŒŁ†Ų“ŲÆŁ‡ā€ŒŁ‡Ų§ ŪŒŲ§ ŁˆŪŒŲÆŲ¦ŁˆŁ‡Ų§ŪŒ ŁŲ±Ų§Ś©ŲÆŲ“ŲÆŁ‡ Ų§Ų¹Ł…Ų§Ł„ Ų“ŲÆ. ŲÆŲ± Ł†ŲŖŪŒŲ¬Ł‡ Ł…Ų¬ŲÆŲÆŲ§Ł‹ Ų¢Ł†Ł‡Ų§ ŲÆŲ± ŲµŁ Ś©Ų§Ų± Ł‚Ų±Ų§Ų± ŚÆŲ±ŁŲŖŁ†ŲÆ.",
+ "right-transcode-status": "Ł…Ų“Ų§Ł‡ŲÆŁ‡Ł” [[Special:TimedMediaHandler|Ų§Ų·Ł„Ų§Ų¹Ų§ŲŖ ŲÆŲ± Ł…ŁˆŲ±ŲÆ ŁŲ¹Ų§Ł„ŪŒŲŖ ŁŲ±Ų§Ś©ŲÆ]]",
+ "action-transcode-status": "Ł†Ł…Ų§ŪŒŲ“ ŁˆŲ¶Ų¹ŪŒŲŖ ŁŲ±Ų§Ś©ŲÆŚÆŲ°Ų§Ų±ŪŒ Ś©Ł†ŁˆŁ†ŪŒ",
+ "orphanedtimedtext": "ŲµŁŲ­Ł‡ā€ŒŁ‡Ų§ŪŒ TimedText ŪŒŲŖŪŒŁ…",
+ "orphanedtimedtext-summary": "ŁŁ‡Ų±Ų³ŲŖ ŲµŁŲ­Ł‡ā€ŒŁ‡Ų§ŪŒ [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] Ś©Ł‡ ŲÆŲ§Ų±Ų§ŪŒ Ł¾Ų±ŁˆŁ†ŲÆŁ‡Ł” Ł…ŲŖŁ†Ų§ŲøŲ± Ł†ŪŒŲ³ŲŖŁ†ŲÆ.",
+ "orphanedtimedtext-unsupported": "Ų§ŪŒŁ† ŲµŁŲ­Ł‡Ł” Ų®Ų§Ųµ ŁŁ‚Ų· ŲÆŲ± Ł¾Ų§ŪŒŚÆŲ§Ł‡ ŲÆŲ§ŲÆŁ‡ā€ŒŁ‡Ų§ŪŒ Ł…Ų§ŪŒā€ŒŲ§Ų³ā€ŒŚ©ŪŒŁˆŲ§Ł„ Ų­Ł…Ų§ŪŒŲŖ Ų“ŲÆŁ‡ā€ŒŲ§Ų³ŲŖ.",
+ "orphanedtimedtext-notimedtext": "TimedText ŲÆŲ± Ų§ŪŒŁ† ŁˆŪŒŚ©ŪŒ ŁŲ¹Ų§Ł„ Ł†Ų“ŲÆŁ‡ Ų§Ų³ŲŖ.",
+ "apihelp-query+transcodestatus-description": "ŚÆŲ±ŁŲŖŁ† ŁˆŲ¶Ų¹ŪŒŲŖ Ś©Ų°ŚÆŲ°Ų§Ų±ŪŒ ŲØŲ±Ų§ŪŒ ŪŒŚ© ŲµŁŲ­Ł‡ Ł…Ų“Ų®Ųµ Ų“ŲÆŁ‡.",
+ "apihelp-query+transcodestatus-example-1": "ŚÆŲ±ŁŲŖŁ† ŁˆŲ¶Ų¹ŪŒŲŖ Ś©ŲÆŚÆŲ°Ų§Ų±ŪŒ [[:File:Clip.webm]]",
+ "apihelp-query+videoinfo-description": "ŚÆŲ³ŲŖŲ±Ų“ Ų§Ų·Ł„Ų§Ų¹Ų§ŲŖ ŲŖŲµŁˆŪŒŲ±ŪŒ ŲØŁ‡ Ų“Ų§Ł…Ł„ Ų“ŲÆŁ† Ų§Ų·Ł„Ų§Ų¹Ų§ŲŖ Ł…Ł†ŲØŲ¹ ŲŖŲµŁˆŪŒŲ± (Ų§Ų“ŲŖŁ‚Ų§Ł‚ā€ŒŲ“ŲÆŁ‡ā€ŒŁ‡Ų§)",
+ "apihelp-query+videoinfo-param-prop": "Ś†Ł‡ Ų§Ų·Ł„Ų§Ų¹Ų§ŲŖŪŒ ŲÆŲ±ŪŒŲ§ŁŲŖ Ł…ŪŒā€ŒŲ“ŁˆŲÆ:\n;timestamp:Ł…Ł‡Ų±Ų²Ł…Ų§Ł†ŪŒ ŲØŁ‡ Ł†Ų³Ų®Ł‡Ł” ŲØŲ§Ų±ŚÆŲ°Ų§Ų±ŪŒ Ų“ŲÆŁ‡ Ł…ŪŒā€ŒŲ§ŁŲ²Ų§ŪŒŲÆ.\n;user:Ś©Ų§Ų±ŲØŲ±ŪŒ Ś©Ł‡ ŲŖŲµŁˆŪŒŲ± Ų±Ų§ ŲØŲ§Ų±ŚÆŲ°Ų§Ų±ŪŒ Ś©Ų±ŲÆŁ‡ Ų±Ų§ Ł…ŪŒā€ŒŲ§ŁŲ²Ų§ŪŒŲÆ.\n;userid:Ų“Ł†Ų§Ų³Ł‡Ł” Ś©Ų§Ų±ŲØŲ±ŪŒ Ś©Ł‡ ŁˆŪŒŲÆŪŒŁˆ Ų±Ų§ ŲØŲ§Ų±ŚÆŲ°Ų§Ų±ŪŒ Ś©Ų±ŲÆŁ‡ Ų§Ų³ŲŖ Ś©Ł‡ Ł†Ų³Ų®Ł‡Ł” ŁˆŪŒŲÆŪŒŁˆŪŒŪŒ Ų±Ų§ ŲØŲ§Ų±ŚÆŲ°Ų§Ų±ŪŒ Ś©Ų±ŲÆŁ‡ Ų§Ų³ŲŖ Ł…ŪŒā€ŒŲ§ŁŲ²Ų§ŪŒŲÆ.\n;comment:ŲŖŁˆŲ¶ŪŒŲ­Ų§ŲŖ Ł†Ų³Ų®Ł‡.\n;parsedcomment:ŲŖŲ¬Ų²ŪŒŁ‡ ŲŖŁˆŲ¶ŪŒŲ­Ų§ŲŖ Ł†Ų³Ų®Ł‡.\n;canonicaltitle:Ų¹Ł†ŁˆŲ§Ł† Ł…ŲŖŁ…Ų±Ś©Ų² Ł¾Ų±ŁˆŁ†ŲÆŁ‡ ŁˆŪŒŲÆŪŒŁˆŪŒŪŒ.\n;url:Ł†Ų“Ų§Ł†ŪŒ Ų§ŪŒŁ†ŲŖŲ±Ł†ŲŖŪŒ Ų§Ų² ŁˆŪŒŲÆŪŒŁˆŪŒ Łˆ ŲµŁŲ­Ł‡Ł” ŲŖŁˆŲ¶ŪŒŲ­Ų§ŲŖ.\n;size:Ų­Ų¬Ł… ŁˆŪŒŲÆŪŒŁˆ ŲØŁ‡ ŲØŲ§ŪŒŲŖŲŒ Ų·ŁˆŁ„ Łˆ Ų¹Ų±Ų¶ Ų¢Ł† Ų±Ų§ Ł…ŪŒā€ŒŲ§ŁŲ²Ų§ŪŒŲÆ. ŲŖŲ¹ŲÆŲ§ŲÆ ŲµŁŲ­Ł‡ Łˆ Ų·ŁˆŁ„ Ų§ŚÆŲ± Ł‚Ų§ŲØŁ„ Ų§Ų·Ł„Ų§Ł‚ ŲØŲ§Ų“ŲÆ.\n;dimensions:Ł†Ų§Ł… Ł…Ų³ŲŖŲ¹Ų§Ų± ŲØŲ±Ų§ŪŒ Ų§Ł†ŲÆŲ§Ų²Ł‡.\n;sha1:Ų§ŁŲ²ŁˆŲÆ SHA-1 hash ŲØŲ±Ų§ŪŒ ŁˆŪŒŲÆŲ¦Łˆ.\n;mime:Ų§ŁŲ²ŁˆŲÆ Ł†ŁˆŲ¹ MIME ŲØŲ±Ų§ŪŒ ŁˆŪŒŲÆŲ¦Łˆ.\n;thumbmime:Ų§ŁŲ²ŁˆŲÆ Ł†ŁˆŲ¹ MIME ŲØŲ±Ų§ŪŒ ŲØŁ†ŲÆŲ§Ł†ŚÆŲ“ŲŖŪŒ ŁˆŪŒŲÆŲ¦Łˆ (Ł†ŪŒŲ§Ų²Ł…Ł†ŲÆ Ł†Ų“Ų§Ł†ŪŒ Łˆ Ł…ŲŖŲŗŪŒŪŒŲ± $1urlwidth).\n;mediatype:Ł†ŁˆŲ¹ Ų±Ų³Ų§Ł†Ł‡Ł” ŁˆŪŒŲÆŲ¦Łˆ Ų±Ų§ Ų§ŁŲ²ŁˆŲÆ.\n;metadata:ŁŲ±Ų§ŲÆŲ§ŲÆŁ‡ā€ŒŁ‡Ų§ŪŒ Exif ŲØŲ±Ų§ŪŒ Ł†Ų³Ų®Ł‡Ł” ŁˆŪŒŲÆŪŒŁˆ ŁŁ‡Ų±Ų³ŲŖ Ł…ŪŒā€ŒŚ©Ł†ŲÆ.\n;commonmetadata:ŁŲ±Ų§ŲÆŲ§ŲÆŁ‡ā€ŒŁ‡Ų§ŪŒ Ų¹Ł…ŁˆŁ…ŪŒ ŲØŲ±Ų§ŪŒ Ł†Ų³Ų®Ł‡Ł” Ł‚Ų§Ł„ŲØ Ł¾Ų±ŁˆŁ†ŲÆŁ‡ ŁˆŪŒŲÆŪŒŁˆ ŁŁ‡Ų±Ų³ŲŖ Ł…ŪŒā€ŒŚ©Ł†ŲÆ.\n;extmetadata:ŁŲ±Ų§ŲÆŲ§ŲÆŁ‡ā€ŒŁ‡Ų§ŪŒ ŲŖŲ±Ś©ŪŒŲØŪŒ Ł‚Ų§Ł„ŲØā€ŒŲÆŁ‡ŪŒ Ų“ŲÆŁ‡ Ų§Ų² Ś†Ł†ŲÆŪŒŁ† Ł…Ł†ŲØŲ¹ Ų±Ų§ ŁŁ‡Ų±Ų³ŲŖ Ł…ŪŒā€ŒŚ©Ł†ŲÆ. Ł†ŲŖŪŒŲ¬Ł‡ Ų§Ų¬ā€ŒŲŖŪŒā€ŒŲ§Ł…ā€ŒŲ§Ł„ Ł‚Ų§Ł„ŲØā€ŒŲÆŁ‡ŪŒ Ų“ŲÆŁ‡ Ų§Ų³ŲŖ.\n;archivename:Ł†Ų§Ł… Ł¾Ų±ŁˆŁ†ŲÆŁ‡ Ł†Ų³Ų®Ł‡Ł” ŲØŲ§ŪŒŚÆŲ§Ł†ŪŒā€ŒŲ“ŲÆŁ‡ Ų±Ų§ ŲØŲ±Ų§ŪŒ Ł†Ų³Ų®Ł‡ā€ŒŁ‡Ų§ŪŒ ŲŗŪŒŲ± Ų¢Ų®Ų±ŪŒŁ† Ł…ŪŒā€ŒŲ§ŁŲ²Ų§ŪŒŲÆ.\n;bitdepth:Ų¹Ł…Ł‚ ŲØŪŒŲŖŪŒ Ł†Ų³Ų®Ł‡ Ų±Ų§ Ł…ŪŒā€ŒŲ§ŁŲ²Ų§ŪŒŲÆ.\n;uploadwarning:Ų§Ų³ŲŖŁŲ§ŲÆŁ‡ Ų“ŲÆŁ‡ ŲŖŁˆŲ³Ų· ŲµŁŲ­Ł‡ [[Special:Upload]] ŲØŲ±Ų§ŪŒ ŲÆŲ±ŪŒŲ§ŁŲŖ Ų§Ų·Ł„Ų§Ų¹Ų§ŲŖŪŒ Ų§Ų² ŪŒŚ© Ł¾Ų±ŁˆŁ†ŲÆŁ‡ Ł…ŁˆŲ¬ŁˆŲÆ. ŲØŲ±Ų§ŪŒ Ų§Ų³ŲŖŁŲ§ŲÆŁ‡ ŲØŪŒŲ±ŁˆŁ† Ų§Ų² Ł‡Ų³ŲŖŁ‡Ł”ā€Œ Ł…ŲÆŪŒŲ§ŁˆŪŒŚ©ŪŒ Ł†ŪŒŲ³ŲŖ.\n;derivatives:Ų¢Ų±Ų§ŪŒŁ‡ā€ŒŲ§ŪŒ Ų§Ų² Ł‚Ų§Ł„ŲØā€ŒŁ‡Ų§ Łˆ Ś©ŪŒŁŪŒŲŖ Ł†Ų³Ų®Ł‡ā€ŒŁ‡Ų§ŪŒ ŪŒŚ© Ł¾Ų±ŁˆŁ†ŲÆŁ‡ ŲµŲÆŲ§ ŪŒŲ§ ŲŖŲµŁˆŪŒŲ±ŪŒ Ś©Ł‡ Ł¾Ų±ŁˆŁ†ŲÆŁ‡ā€ŒŲ§ŪŒ Ś©Ł‡ Ł…ŁˆŲ¬ŁˆŲÆ Ų§Ų³ŲŖ Ł…ŪŒā€ŒŲ§ŁŲ²Ų§ŪŒŲÆ.",
+ "apihelp-query+videoinfo-example-1": "ŁˆŲ§Ś©Ų“ŪŒ Ų§Ų·Ł„Ų§Ų¹Ų§ŲŖŪŒ ŲÆŲ±ŲØŲ§Ų±Ł‡ [[:File:Folgers.ogv]]",
+ "apihelp-transcodereset-description": "Ś©Ų§Ų±ŲØŲ±Ł‡ŪŒŪŒ Ś©Ł‡ ŲÆŲ³ŲŖŲ±Ų³ŪŒ 'transcode-reset' Ł…ŪŒā€ŒŲŖŁˆŲ§Ł†Ł†ŲÆ ŪŒŚ© Ś©Ų§Ų± Ś©ŲÆŚÆŲ°Ų§Ų±ŪŒ Ų±Ų§ Ų§Ų² Ł†Łˆ Ś©Ł†Ł†ŲÆ.",
+ "apihelp-transcodereset-param-title": "Ų¹Ł†ŁˆŲ§Ł† Ł¾Ų±ŁˆŁ†ŲÆŁ‡.",
+ "apihelp-transcodereset-param-transcodekey": "Ś©Ł„ŪŒŲÆ Ś©ŲÆŚÆŲ°Ų§Ų±ŪŒ Ś©Ł‡ Ł…ŪŒā€ŒŲ®ŁˆŲ§Ł‡ŪŒŲÆ Ų§Ų² Ł†Łˆ Ų“ŁˆŲÆ. ŚÆŲ±ŁŲŖŁ† Ų§Ų² [[Special:ApiHelp/query+transcodestatus|action=query&prop=transcodestatus]].",
+ "apihelp-transcodereset-example-1": "Ų§Ų² Ł†Łˆ Ś©Ų±ŲÆŁ† Ś©ŲÆŚÆŲ°Ų§Ų±ŪŒā€ŒŁ‡Ų§ ŲØŲ±Ų§ŪŒ [[:File:Clip.webm]]",
+ "apihelp-transcodereset-example-2": "Ų§Ų² Ł†Łˆ Ś©Ų±ŲÆŁ† Ś©Ł„ŪŒŲÆ Ś©ŲÆŚÆŲ°Ų§Ų±ŪŒ '360_560kbs.webm' ŲØŲ±Ų§ŪŒ [[:File:Clip.webm]]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/fi.json b/extensions/TimedMediaHandler/i18n/fi.json
new file mode 100644
index 00000000..ef19cca9
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/fi.json
@@ -0,0 +1,78 @@
+{
+ "@metadata": {
+ "authors": [
+ "Agony",
+ "Beluga",
+ "Crt",
+ "Nike",
+ "Pxos",
+ "Str4nd",
+ "VezonThunder",
+ "Pitke"
+ ]
+ },
+ "timedmedia-desc": "KƤsittelijƤ ƤƤnelle, videolle ja tekstitykselle. Tukee muotoja WebM, Ogg Theora, Vorbis ja srt.",
+ "timedmedia-ogg-short-audio": "Ogg $1 -ƤƤnitiedosto, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 -videotiedosto, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 -mediatiedosto, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 -ƤƤnitiedosto, $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 -videotiedosto, $2, $4Ɨ$5, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg-tiedosto limitetty kuva ja ƤƤni, $1, $2, $4Ɨ$5, $3",
+ "timedmedia-ogg-long-general": "Ogg-tiedosto, $2, $3",
+ "timedmedia-ogg-long-error": "Kelvoton Ogg-tiedosto: $1",
+ "timedmedia-webm-short-video": "WebM $1 -videotiedosto, $2",
+ "timedmedia-webm-long-video": "WebM-ƤƤni-/videotiedosto, $1, pituus $2, $4Ɨ$5 pikseliƤ, yhteensƤ $3",
+ "timedmedia-mp4-short-video": "MP4 $1 -videotiedosto, $2",
+ "timedmedia-mp4-long-video": "MP4-ƤƤni-/videotiedosto, $1, pituus $2, $4Ɨ$5 pikseliƤ, yhteensƤ $3",
+ "timedmedia-no-player-js": "Valitettavasti selaimessasi on joko JavaScript pois pƤƤltƤ tai sille ei ole tuettua soitinta.<br />\nVoit <a href=\"$1\">ladata leikkeen</a> tai <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ladata soittimen</a> toistaaksesi sen selaimessasi.",
+ "timedmedia-more": "LisƤƤā€¦",
+ "timedmedia-dismiss": "Sulje",
+ "timedmedia-download": "Lataa",
+ "timedmedia-play-media": "Toista mediaa",
+ "timedmedia-desc-link": "Tiedoston tiedot",
+ "timedmedia-oggThumb-version": "OggHandler vaatii oggThumbin version $1 tai uudemman.",
+ "timedmedia-oggThumb-failed": "oggThumb epƤonnistui pikkukuvan luomisessa.",
+ "timedmedia-status": "Tila",
+ "timedmedia-status-unknown": "Tuntematon tila",
+ "timedmedia-transcodeinfo": "Muoto",
+ "timedmedia-actions": "Toiminnot",
+ "timedmedia-direct-link": "Lataa",
+ "timedmedia-not-ready": "Ei valmis",
+ "timedmedia-completed-on": "Valmistui $1",
+ "timedmedia-started-transcode": "Alkoi $1 sitten. $2",
+ "timedmedia-percent-done": "Noin $1% valmiina",
+ "timedmedia-in-job-queue": "LisƤttiin tyƶjonoon $1 sitten",
+ "timedmedia-days": "{{PLURAL:$1|1 pƤivƤ|$1 pƤivƤƤ}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 tunti|$1 tuntia}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minuutti|$1 minuuttia}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 sekunti|$1 sekuntia}}",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "LƤhde $1",
+ "timedmedia-source-file-desc": "AlkuperƤinen $1-tiedosto, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "AlkuperƤinen $1-tiedosto ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Pienen kaistanleveyden Ogg-video (160p)",
+ "timedmedia-derivative-desc-240p.ogv": "Streamautuva Ogg-video (240p)",
+ "timedmedia-derivative-desc-360p.ogv": "verkossa suoratoistettavaa Ogg-videota (360p)",
+ "timedmedia-derivative-desc-480p.ogv": "Verkossa suoratoistettava Ogg-video (480p)",
+ "timedmedia-derivative-desc-720p.ogv": "Korkealaatuinen ladattava Ogg-video (720p)",
+ "timedmedia-derivative-desc-160p.webm": "Verkossa suoratoistettava WebM-video (160p)",
+ "timedmedia-derivative-desc-360p.webm": "Verkossa suoratoistettava WebM-video (360p)",
+ "timedmedia-derivative-desc-480p.webm": "Verkossa suoratoistettava WebM-video (480p)",
+ "timedmedia-derivative-desc-720p.webm": "Korkealaatuinen ladattava WebM-video (720p)",
+ "timedmedia-derivative-360p.vp9.webm": "VP9 360P",
+ "timedmedia-derivative-480p.vp9.webm": "VP9 480P",
+ "timedmedia-derivative-desc-320p.mp4": "LaiteystƤvƤllinen MP4 (320p)",
+ "timedmedia-derivative-desc-480p.mp4": "Verkossa suoratoistettava MP4 (480p)",
+ "timedmedia-derivative-desc-720p.mp4": "HD-laatuinen MP4 (720p)",
+ "timedmedia-subtitle-new": "Luo uusi kƤƤnnƶs tai muokkaa aiempaa",
+ "timedmedia-subtitle-new-desc": "Valitse kieli ja napsauta '''{{int:Timedmedia-subtitle-new-go}}'''.",
+ "timedmedia-subtitle-new-go": "Siirry",
+ "timedmedia-subtitle-language": "$1 ($2) kuvatekstit",
+ "timedmedia-subtitle-no-video": "TƤhƤn tekstityssivuun ei liity videota",
+ "timedmedia-subtitle-no-subtitles": "TƤlle videolle ei tƤllƤ hetkellƤ ole tekstityksiƤ kielellƤ $1. Voit [{{fullurl:{{FULLPAGENAME}}|action=edit}} muokata tƤtƤ sivua] lisƤtƤksesi ne.",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 video|$1 videota}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg-video|$1 Ogg-videota}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM-video|$1 WebM-videota}}",
+ "timedmedia-file": "Tiedosto"
+}
diff --git a/extensions/TimedMediaHandler/i18n/fo.json b/extensions/TimedMediaHandler/i18n/fo.json
new file mode 100644
index 00000000..a96f3de3
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/fo.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Spacebirdy",
+ "EileenSanda"
+ ]
+ },
+ "timedmedia-no-player-js": "Halt okkum til gĆ³Ć°ar, tĆ­n brovsari hevur antin gjĆørt JavaScript Ć³virkiĆ° ella hevur ongan avspƦlara iĆ° virkar her.<br />\nTĆŗ kanst <a href=\"$1\">taka klippiĆ° niĆ°ur</a> ella <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">taka niĆ°ur ein avspƦlara</a> sum kann spƦla klippiĆ° Ć­ tĆ­num internetkaga.",
+ "timedmedia-more": "Meira...",
+ "timedmedia-source-file": "$1 kelda",
+ "timedmedia-source-audio-file-desc": "Uppruna $1 fĆ­la ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/fr.json b/extensions/TimedMediaHandler/i18n/fr.json
new file mode 100644
index 00000000..e252d5c4
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/fr.json
@@ -0,0 +1,150 @@
+{
+ "@metadata": {
+ "authors": [
+ "Boniface",
+ "Brunoperel",
+ "Crochet.david",
+ "Erkethan",
+ "Gomoko",
+ "Grondin",
+ "Hashar",
+ "Hello71",
+ "IAlex",
+ "Jean-FrƩdƩric",
+ "McDutchie",
+ "Od1n",
+ "Peter17",
+ "Rzuwig",
+ "Seb35",
+ "Sherbrooke",
+ "Shirayuki",
+ "Urhixidur",
+ "Verdy p",
+ "Framafan",
+ "Wladek92"
+ ]
+ },
+ "timedmedia-desc": "Gestionnaire pour les vidƩos, enregistrements sonores et textes synchronisƩs, avec le support des formats WebM, Ogg Theora, Vorbis et srt",
+ "timedmedia-ogg-short-audio": "Fichier son Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Fichier vidƩo Ogg $1, $2",
+ "timedmedia-ogg-short-general": "Fichier mƩdia Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Fichier son Ogg $1, durƩe $2, $3",
+ "timedmedia-ogg-long-video": "Fichier vidĆ©o Ogg $1, durĆ©e $2, $4 Ɨ $5 pixels, $3",
+ "timedmedia-ogg-long-multiplexed": "Fichier multiplexĆ© audio/vidĆ©o Ogg, $1, durĆ©e $2, $4&nbsp;Ɨ&nbsp;$5 pixels, $3 au total",
+ "timedmedia-ogg-long-general": "Fichier mƩdia Ogg, durƩe $2, $3",
+ "timedmedia-ogg-long-error": "Fichier Ogg invalide : $1",
+ "timedmedia-ogg-long-no-streams": "Fichier de mĆ©dia ogg. Attention : Aucun des codecs utilisĆ©s dans ce fichier nā€™est reconnu.",
+ "timedmedia-webm-short-video": "Fichier vidƩo WebM $1, $2",
+ "timedmedia-webm-long-video": "Fichier audio/vidƩo WebM, $1, longueur $2, $4 x $5 pixels, $3 l'ensemble",
+ "timedmedia-flac-short-audio": "Fichier audio FLAC, $1",
+ "timedmedia-flac-long-audio": "Fichier audio FLAC, durĆ©e $1, dĆ©bit $2 sur lā€™ensemble",
+ "timedmedia-wav-short-audio": "Fichier audio WAV, $1",
+ "timedmedia-wav-long-audio": "Fichier audio WAV, durĆ©e $1, $2 sur lā€™ensemble",
+ "timedmedia-wav-pcm-required": "Vous ne pouvez tĆ©lĆ©charger que des WAV PCM (Modulation dā€™impulsion codĆ©e).",
+ "timedmedia-mp4-short-video": "Fichier vidƩo MP4 $1, $2",
+ "timedmedia-mp4-long-video": "Fichier audio/vidƩo MP4, $1, taille $2, $4 x $5 pixels, $3 au total",
+ "timedmedia-no-player-js": "DĆ©solĆ©, soit votre navigateur a JavaScript dĆ©sactivĆ©, soit il ne dispose dā€™aucun lecteur pris en charge.<br />\nVous pouvez <a href=\"$1\">tĆ©lĆ©charger le clip</a> ou <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">tĆ©lĆ©charger un lecteur</a> pour lire le clip dans votre navigateur.",
+ "timedmedia-more": "Plusā€¦",
+ "timedmedia-dismiss": "Fermer",
+ "timedmedia-download": "TƩlƩcharger le fichier",
+ "timedmedia-play-media": "Lire le mƩdia",
+ "timedmedia-desc-link": "ƀ propos de ce fichier",
+ "timedmedia-oggThumb-version": "OggHandler nƩcessite oggThumb, version $1 ou supƩrieure.",
+ "timedmedia-oggThumb-failed": "oggThumb nā€™a pas rĆ©ussi Ć  crĆ©er la miniature.",
+ "timedmedia-status-header": "Statut de transcodage",
+ "timedmedia-update-status": "Mettre Ć  jour le statut de transcodage",
+ "timedmedia-status": "Statut",
+ "timedmedia-status-unknown": "Ɖtat inconnu",
+ "timedmedia-transcodebitrate": "DĆ©bit en bits",
+ "timedmedia-transcodeduration": "DurƩe de l'encodage",
+ "timedmedia-transcodeinfo": "Transcode la description dƩrivƩe",
+ "timedmedia-actions": "Actions",
+ "timedmedia-direct-link": "TƩlƩcharger",
+ "timedmedia-not-ready": "Pas prĆŖt",
+ "timedmedia-completed-on": "$1 terminƩ",
+ "timedmedia-error-on": "Erreur sur $1",
+ "timedmedia-started-transcode": "DƩmarrƩ depuis $1. $2",
+ "timedmedia-percent-done": "Environ $1 % complƩtƩ",
+ "timedmedia-in-job-queue": "AjoutĆ© Ć  la file dā€™attente des travaux il y a $1",
+ "timedmedia-unknown-target-size": "Taille de la cible inconnue, $1 encodƩ",
+ "timedmedia-days": "{{PLURAL:$1|1 jour|$1 jours}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 heure|$1 heures}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minute|$1 minutes}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 seconde|$1 secondes}}",
+ "timedmedia-reset": "RĆ©initialiser le transcodage",
+ "timedmedia-reset-confirm": "Remettre Ć  zĆ©ro ce transcodage supprimera tout fichier existant (sā€™il y en a) et ajoutera de nouveau le transcodage Ć  la file de travaux. Cela prendra un certain temps pour ĆŖtre transcodĆ© de nouveau. <br /><br />\nƊtes-vous sĆ»r de vouloir continuer ?",
+ "timedmedia-reset-error": "Erreur en rƩinitialisant le travail de transcodage.",
+ "timedmedia-ogg": "Ogg",
+ "timedmedia-webm": "WebM",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Source $1",
+ "timedmedia-source-file-desc": "Original fichier $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Fichier original $1 ($2)",
+ "timedmedia-derivative-160p.ogv": "Ogg 160p",
+ "timedmedia-derivative-desc-160p.ogv": "VidƩo Ogg bas dƩbit (160P)",
+ "timedmedia-derivative-desc-240p.ogv": "VidƩo Ogg en flux continu sur le web (240P)",
+ "timedmedia-derivative-360p.ogv": "Ogg 360p",
+ "timedmedia-derivative-desc-360p.ogv": "VidƩo Ogg lisible en continu sur le Web (360p)",
+ "timedmedia-derivative-480p.ogv": "Ogg 480p",
+ "timedmedia-derivative-desc-480p.ogv": "VidƩo Ogg lisible en continu sur le web (480p)",
+ "timedmedia-derivative-720p.ogv": "Ogg 720p",
+ "timedmedia-derivative-desc-720p.ogv": "VidƩo Ogg tƩlƩchargeable de grande qualitƩ (720p)",
+ "timedmedia-derivative-desc-1080p.ogv": "VidƩo Ogg tƩlƩchargeable en HD total (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "WebM lisible en continu depuis le web (160p)",
+ "timedmedia-derivative-360p.webm": "WebM 360p",
+ "timedmedia-derivative-desc-360p.webm": "WebM lisible en continu depuis le web (360p)",
+ "timedmedia-derivative-480p.webm": "WebM 480p",
+ "timedmedia-derivative-desc-480p.webm": "WebM lisible en continu depuis le web (480p)",
+ "timedmedia-derivative-720p.webm": "WebM 720p",
+ "timedmedia-derivative-desc-720p.webm": "VidƩo WebM tƩlƩchargeable de grande qualitƩ (720p)",
+ "timedmedia-derivative-desc-1080p.webm": "WebM tƩlƩchargeable en HD total (1080P)",
+ "timedmedia-derivative-desc-2160p.webm": "WebM tƩlƩcharheable en 4K total (2160P)",
+ "timedmedia-derivative-desc-360p.vp9.webm": "WebM VP9 (360P) lisible en continu sur le web",
+ "timedmedia-derivative-desc-480p.vp9.webm": "WebM VP9 (480P) lisible en continu sur le web",
+ "timedmedia-derivative-desc-720p.vp9.webm": "WebM VP9 haute dƩfinition (720P) lisible en continu sur le web",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "WebM VP9 en haute dƩfinition totale (1080P) lisible en continu sur le web",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "WebM VP9 4K complet (2160P) lisible en continu sur le web",
+ "timedmedia-derivative-desc-320p.mp4": "MP4 compatible matƩriel (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "MP4 pour flux web (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 qualitƩ HD (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "MP4 de qualitƩ HD total (1080P)",
+ "timedmedia-derivative-desc-2160p.mp4": "MP4 de qualitƩ haute dƩfinition 4K",
+ "timedmedia-subtitle-new": "CrƩer une nouvelle traduction ou modifier une traduction existante",
+ "timedmedia-subtitle-new-desc": "SĆ©lectionnez la langue et appuyez sur le bouton '''{{int:Timedmedia-subtitle-new-go}}'''.",
+ "timedmedia-subtitle-new-go": "Aller",
+ "timedmedia-subtitle-language": "sous-titres en $1 ($2)",
+ "timedmedia-subtitle-no-video": "Il nā€™y a aucune vidĆ©o associĆ©e Ć  la page actuelle de sous-titre",
+ "timedmedia-subtitle-no-subtitles": "Il nā€™y a actuellement aucun sous-titres en $1 pour cette vidĆ©o, vous pouvez [{{fullurl: {{FULLPAGENAME}} | action=edit}} modifier cette page] pour les ajouter",
+ "timedmedia-subtitle-remote": "Le texte prƩvu pour ce fichier est hƩbergƩ sur $1",
+ "timedmedia-subtitle-remote-link": "Vous pouvez [$1 voir la page de description] de ce fichier sur $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 vidƩo|$1 vidƩos}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 vidƩo Ogg|$1 vidƩos Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 vidƩo WebM|$1 vidƩos WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transcodage|$1 transcodages}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 transcodage en cours|$1 transcodages en cours}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 transcodage en file d'attente|$1 transcodages en file d'attente}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 transcodage ƩchouƩ|$1 transcodages ƩchouƩs}}",
+ "timedmedia-file": "Fichier",
+ "timedmedia-audios": "{{PLURAL:$1|$1 fichier audio|$1 fichiers audio}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 fichier audio Ogg|$1 fichiers audio Ogg}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 fichier audio FLAC|$1 fichiers audio FLAC}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 fichier audio WAV|$1 fichiers audio WAV}}",
+ "right-transcode-reset": "RĆ©initialiser les vidĆ©os en Ć©chec ou transcodĆ©es pour quā€™elles soient de nouveau insĆ©rĆ©es dans la file des travaux",
+ "right-transcode-status": "Afficher [[Special:TimedMediaHandler|l'information sur l'activitƩ de transcodage actuelle]]",
+ "action-transcode-status": "afficher lā€™Ć©tat de transcodage actuel",
+ "orphanedtimedtext": "Pages orphelines de TimedText",
+ "orphanedtimedtext-summary": "Liste des pages [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] qui nā€™ont pas de fichier correspondant.",
+ "orphanedtimedtext-unsupported": "Cette page spĆ©ciale nā€™est supportĆ©e que sur les bases de donnĆ©es MySQL.",
+ "orphanedtimedtext-notimedtext": "TimedText nā€™est pas activĆ© sur ce wiki.",
+ "apihelp-query+transcodestatus-description": "Obtenir lā€™Ć©tat de transcodage pour une page de fichier donnĆ©.",
+ "apihelp-query+transcodestatus-example-1": "Obtenir lā€™Ć©tat de transcodage pour [[:File:Clip.webm]]",
+ "apihelp-query+videoinfo-description": "Ɖtends imageinfo pour inclure les informations sur la source (et dĆ©rivĆ©es) vidĆ©o",
+ "apihelp-query+videoinfo-param-prop": "Quelles informations obtenir sur la vidĆ©o :\n;timestamp:Ajoute lā€™horodatage pour la version tĆ©lĆ©chargĆ©e.\n;user:Ajoute lā€™utilisateur qui a tĆ©lĆ©chargĆ© la version de la vidĆ©o.\n;userid:Ajouter lā€™ID de lā€™utilisateur qui a tĆ©lĆ©chargĆ© la version de la vidĆ©o.\n;comment:Commentaire sur la version.\n;parsedcomment:Analyser le commentaire sur la version.\n;canonicaltitle:Ajoute le titre canonique du fichier vidĆ©o.\n;url:Fournit lā€™URL de la vidĆ©o et la page de description.\n;size:Ajoute la taille de la vidĆ©o en octets, sa hauteur et sa largeur. Le compteur de page et la durĆ©e sont ajoutĆ©s le cas Ć©chĆ©ant.\n;dimensions:Alias pour la taille.\n;sha1:Ajoute le hachage SHA-1 pour la vidĆ©o.\n;mime:Ajoute le type MIME de la vidĆ©o.\n;thumbmime:Ajoute le type MIME de la vignette de la vidĆ©o (nĆ©cessite lā€™URL et le paramĆØtre $1urlwidth).\n;mediatype:Ajoute le type de mĆ©dia de la vidĆ©o.\n;metadata:Liste les mĆ©tadonnĆ©es Exif pour la version de la vidĆ©o.\n;commonmetadata:Liste les mĆ©tadonnĆ©es gĆ©nĆ©riques du format de fichier pour la version de la vidĆ©o.\n;extmetadata:Liste les mĆ©tadonnĆ©es mises en forme combinĆ©es depuis plusieurs sources. Les rĆ©sultats sont au format HTML.\n;archivename:Ajoute le nom de fichier de la version dā€™archive pour les versions hors la derniĆØre.\n;bitdepth:Ajoute la profondeur en bits de la version.\n;uploadwarning:UtilisĆ© par la page [[Special:Upload]] pour obtenir des informations sur un fichier existant. Non prĆ©vu pour ĆŖtre utilisĆ© hors du cœur de MĆ©diaWiki.\n;derivatives:Ajoute un tableau des diffĆ©rentes versions de format et de qualitĆ© dā€™un fichier audio ou vidĆ©o disponibles.",
+ "apihelp-query+videoinfo-example-1": "RƩcupƩrer des informations sur [[:File:Folgers.ogv]]",
+ "apihelp-transcodereset-description": "Les utilisateurs avec le droit 'transcode-reset' peuvent rĆ©initialiser et relancer une tĆ¢che de transcodage.",
+ "apihelp-transcodereset-param-title": "Le titre du fichier mƩdia.",
+ "apihelp-transcodereset-param-transcodekey": "La clƩ du transcodage que vous voulez rƩinitialiser. RƩcupƩrƩ depuis [[Special:ApiHelp/query+transcodestatus|action=query&prop=transcodestatus]].",
+ "apihelp-transcodereset-example-1": "RĆ©initialiser tous les codes de transcodage de [[:File:Clip.webm]]",
+ "apihelp-transcodereset-example-2": "RƩinitialiser la clƩ de transcodage '360_560kbs.webm' pour [[:File:Clip.webm]]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/frp.json b/extensions/TimedMediaHandler/i18n/frp.json
new file mode 100644
index 00000000..ecf9cbc8
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/frp.json
@@ -0,0 +1,38 @@
+{
+ "@metadata": {
+ "authors": [
+ "ChrisPtDe"
+ ]
+ },
+ "timedmedia-desc": "Assistance por los fichiĆ©rs mĆØdia que dĆØfilont (Ć“diĆ“, vidĆØĆ“ et tĆØxto sincronisĆ¢) avouĆ©c transcodĆ¢jo en WebM, Ogg Theora, Vorbis et srt.",
+ "timedmedia-ogg-short-audio": "FichiƩr son Ogg $1, $2",
+ "timedmedia-ogg-short-video": "FichiĆ©r vidĆØĆ“ Ogg $1, $2",
+ "timedmedia-ogg-short-general": "FichiĆ©r mĆØdia Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "FichiƩr son Ogg $1, temps $2, $3",
+ "timedmedia-ogg-long-video": "FichiĆ©r vidĆØĆ“ Ogg $1, temps $2, $4Ɨ$5 pixĆØls, $3",
+ "timedmedia-ogg-long-multiplexed": "FichiĆ©r multiplĆØxo Ć“diĆ“ / vidĆØĆ“ Ogg, $1, temps $2, $4Ɨ$5 pixĆØls, $3",
+ "timedmedia-ogg-long-general": "FichiĆ©r mĆØdia Ogg, temps $2, $3",
+ "timedmedia-ogg-long-error": "FichiƩr Ogg envalido : $1",
+ "timedmedia-webm-short-video": "FichiĆ©r vidĆØĆ“ WebM $1, $2",
+ "timedmedia-webm-long-video": "FichiĆ©r Ć“diĆ“ / vidĆØĆ“ WebM, $1, longior $2, $4 x $5 pixĆØls, en tot $3",
+ "timedmedia-more": "De ples...",
+ "timedmedia-dismiss": "CllƓre",
+ "timedmedia-download": "TĆØlĆØchargiĆ©r lo fichiĆ©r",
+ "timedmedia-play-media": "LiĆ©re lo mĆØdia",
+ "timedmedia-desc-link": "Sur ceti fichiƩr",
+ "timedmedia-oggThumb-version": "OggHandler at fĆ“ta dā€™oggThumb, vĆØrsion $1 ou ben ples novĆØla.",
+ "timedmedia-oggThumb-failed": "oggThumb at pas reussi a fĆ¢re la figura.",
+ "timedmedia-status": "statut",
+ "timedmedia-status-unknown": "statut encognu",
+ "timedmedia-actions": "Accions",
+ "timedmedia-not-ready": "Pas prĆØst",
+ "timedmedia-percent-done": "A pou prĆ©s $1 % complĆØtĆ¢",
+ "timedmedia-days": "$1 jorn{{PLURAL:$1||s}}",
+ "timedmedia-hours": "$1 hor{{PLURAL:$1|a|es}}",
+ "timedmedia-minutes": "$1 menut{{PLURAL:$1|a|es}}",
+ "timedmedia-seconds": "$1 second{{PLURAL:$1|a|es}}",
+ "timedmedia-source-file": "SĆ“rsa $1",
+ "timedmedia-source-file-desc": "OriginĆ¢l $1, $2 Ɨ $3 ($4)",
+ "timedmedia-subtitle-language": "sot-titros en $1 ($2)",
+ "timedmedia-file": "FichiƩr"
+}
diff --git a/extensions/TimedMediaHandler/i18n/frr.json b/extensions/TimedMediaHandler/i18n/frr.json
new file mode 100644
index 00000000..8a1f77a8
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/frr.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Murma174"
+ ]
+ },
+ "timedmedia-no-player-js": "Bi dan browser as det brĆ¼ken faan JavaScript deaktiwiaret wurden of hi koon det ianfach ei ufspele.<br />\nDĆ¼ kƶnst <a href=\"$1\">det video deelloose</a> of <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">en software deelloose</a>, am det video uun dan browser uftuspelin.",
+ "timedmedia-source-file": "$1-kwel",
+ "timedmedia-source-audio-file-desc": "Originaal $1-datei ($2)",
+ "timedmediahandler": "Timed Media Handler"
+}
diff --git a/extensions/TimedMediaHandler/i18n/fur.json b/extensions/TimedMediaHandler/i18n/fur.json
new file mode 100644
index 00000000..b80405f4
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/fur.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Klenje"
+ ]
+ },
+ "timedmedia-desc": "GjestĆ“r pai files audio, video e di test cul timp, cun supuart pai formĆ¢ts WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "File audio Ogg $1, $2",
+ "timedmedia-ogg-short-video": "File video Ogg $1, $2",
+ "timedmedia-ogg-short-general": "File multimediĆ¢l Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "File audio Ogg $1, durade $2, $3",
+ "timedmedia-ogg-long-video": "File video Ogg $1, durade $2, dimensions $4Ɨ$5 pixels, $3",
+ "timedmedia-ogg-long-multiplexed": "File audio/video multiplexed Ogg $1, lungjece $2, dimensions $4Ɨ$5 pixels, in dut $3",
+ "timedmedia-ogg-long-general": "File multimediĆ¢l Ogg, durade $2, $3",
+ "timedmedia-ogg-long-error": "File ogg no valit: $1",
+ "timedmedia-webm-short-video": "File video WebM $1, $2",
+ "timedmedia-more": "Altri...",
+ "timedmedia-dismiss": "Siere",
+ "timedmedia-download": "Discjame il file",
+ "timedmedia-desc-link": "Informazions su chest file",
+ "timedmedia-status": "StĆ¢t",
+ "timedmedia-actions": "Azions"
+}
diff --git a/extensions/TimedMediaHandler/i18n/fy.json b/extensions/TimedMediaHandler/i18n/fy.json
new file mode 100644
index 00000000..747f3b0b
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/fy.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "Robin0van0der0vliet"
+ ]
+ },
+ "timedmedia-more": "Mearā€¦",
+ "timedmedia-dismiss": "Slute",
+ "timedmedia-days": "{{PLURAL:$1|1 dei|$1 dagen}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 oere|$1 oere}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minĆŗt|$1 minuten}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 sekonde|$1 sekonden}}",
+ "timedmedia-source-file": "$1 boarne",
+ "timedmedia-source-audio-file-desc": "Orizjineel $1-triem ($2)",
+ "timedmedia-file": "Triem"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ga.json b/extensions/TimedMediaHandler/i18n/ga.json
new file mode 100644
index 00000000..d59b6164
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ga.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Spacebirdy",
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ"
+ ]
+ },
+ "timedmedia-more": "NĆ­os mĆ³...",
+ "timedmedia-dismiss": "DĆŗn",
+ "timedmedia-actions": "GnĆ­omhartha",
+ "timedmedia-subtitle-new-go": "Gabh",
+ "timedmedia-file": "Comhad"
+}
diff --git a/extensions/TimedMediaHandler/i18n/gl.json b/extensions/TimedMediaHandler/i18n/gl.json
new file mode 100644
index 00000000..8c40d72d
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/gl.json
@@ -0,0 +1,125 @@
+{
+ "@metadata": {
+ "authors": [
+ "ToliƱo",
+ "XosƩ",
+ "Banjo",
+ "Elisardojm"
+ ]
+ },
+ "timedmedia-desc": "Manipulador de son, vĆ­deo e texto sincronizado, con soporte para os formatos WebM, Ogg Theora, Vorbis e srt",
+ "timedmedia-ogg-short-audio": "Ficheiro de son Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Ficheiro de vĆ­deo Ogg $1, $2",
+ "timedmedia-ogg-short-general": "Ficheiro multimedia Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Ficheiro de son Ogg $1, duraciĆ³n $2, $3",
+ "timedmedia-ogg-long-video": "Ficheiro de vĆ­deo Ogg $1, duraciĆ³n $2, $4Ɨ$5 pĆ­xeles, $3",
+ "timedmedia-ogg-long-multiplexed": "Ficheiro de son/vĆ­deo Ogg multiplex, $1, duraciĆ³n $2, $4Ɨ$5 pĆ­xeles, $3 total",
+ "timedmedia-ogg-long-general": "Ficheiro multimedia Ogg, duraciĆ³n $2, $3",
+ "timedmedia-ogg-long-error": "Ficheiro Ogg non vƔlido: $1",
+ "timedmedia-ogg-long-no-streams": "Ficheiro multimedia Ogg. AtenciĆ³n: Non se recoƱece ningĆŗn dos codecs usados neste ficheiro.",
+ "timedmedia-webm-short-video": "Ficheiro de vĆ­deo WebM $1, $2",
+ "timedmedia-webm-long-video": "Ficheiro WebM de son/vĆ­deo, $1, duraciĆ³n $2, $4Ɨ$5 pĆ­xeles, $3 total",
+ "timedmedia-flac-short-audio": "Ficheiro de son FLAC, $1",
+ "timedmedia-flac-long-audio": "Ficheiro de son FLAC, duraciĆ³n $1, $2 total",
+ "timedmedia-wav-short-audio": "Ficheiro de son WAV, $1",
+ "timedmedia-wav-long-audio": "Ficheiro de son WAV, duraciĆ³n $1, $2 total",
+ "timedmedia-wav-pcm-required": "Unicamente pode cargar WAV PCM (modulaciĆ³n por cĆ³digo de pulsos).",
+ "timedmedia-mp4-short-video": "Ficheiro de vĆ­deo MP4 $1, $2",
+ "timedmedia-mp4-long-video": "Ficheiro MP4 de son/vĆ­deo, $1, duraciĆ³n $2, $4Ɨ$5 pĆ­xeles, $3 total",
+ "timedmedia-no-player-js": "SentĆ­molo, o seu navegador ten o JavaScript desactivado ou non conta con ningĆŗn reprodutor dos soportados.<br />\nPode <a href=\"$1\">descargar o vĆ­deo</a> ou <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">descargar un reprodutor</a> para reproducir o vĆ­deo no seu navegador.",
+ "timedmedia-more": "MƔis...",
+ "timedmedia-dismiss": "Pechar",
+ "timedmedia-download": "Descargar o ficheiro",
+ "timedmedia-play-media": "Reproducir o contido",
+ "timedmedia-desc-link": "Acerca deste ficheiro",
+ "timedmedia-oggThumb-version": "O OggHandler necesita a versiĆ³n $1 ou unha posterior do oggThumb.",
+ "timedmedia-oggThumb-failed": "Houbo un erro por parte do oggThumb ao crear a miniatura.",
+ "timedmedia-status-header": "Estado da transcodificaciĆ³n",
+ "timedmedia-update-status": "Actualizar o estado de transcodificaciĆ³n",
+ "timedmedia-status": "Estado",
+ "timedmedia-status-unknown": "Estado descoƱecido",
+ "timedmedia-transcodebitrate": "Taxa de transferencia",
+ "timedmedia-transcodeduration": "Tempo de codificaciĆ³n",
+ "timedmedia-transcodeinfo": "Formato",
+ "timedmedia-actions": "AcciĆ³ns",
+ "timedmedia-direct-link": "Descargar",
+ "timedmedia-not-ready": "AĆ­nda non estĆ” preparado",
+ "timedmedia-completed-on": "Completado o $1",
+ "timedmedia-error-on": "Erro en $1",
+ "timedmedia-started-transcode": "Comezou hai $1. $2",
+ "timedmedia-percent-done": "Preto do $1% feito",
+ "timedmedia-in-job-queue": "Engadido Ć” cola de traballos hai $1",
+ "timedmedia-unknown-target-size": "TamaƱo de destino descoƱecido; $1 codificados",
+ "timedmedia-days": "{{PLURAL:$1|1 dĆ­a|$1 dĆ­as}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 hora|$1 horas}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minuto|$1 minutos}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 segundo|$1 segundos}}",
+ "timedmedia-reset": "Restablecer a transcodificaciĆ³n",
+ "timedmedia-reset-confirm": "Ao restablecer a transcodificaciĆ³n eliminarase calquera ficheiro existente e volverĆ” engadir a transcodificaciĆ³n Ć” cola de traballos. A nova transcodificaciĆ³n levarĆ” bastante tempo.<br /><br />\nEstĆ” seguro de querer continuar?",
+ "timedmedia-reset-error": "Erro no restablecemento do traballo de transcodificaciĆ³n.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Fonte $1",
+ "timedmedia-source-file-desc": "Ficheiro $1 orixinal, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Ficheiro $1 orixinal ($2)",
+ "timedmedia-derivative-160p.ogv": "Ogg 160P",
+ "timedmedia-derivative-desc-160p.ogv": "VĆ­deo Ogg de baixo ancho de banda (160P)",
+ "timedmedia-derivative-desc-240p.ogv": "VĆ­deo Ogg para a web (240P)",
+ "timedmedia-derivative-desc-360p.ogv": "VĆ­deo Ogg para a web (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "VĆ­deo Ogg para a web (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "VĆ­deo Ogg de alta calidade que se pode descargar (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "VĆ­deo Ogg descargable en Full HD (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "WebM para a web (160P)",
+ "timedmedia-derivative-desc-360p.webm": "WebM para a web (360P)",
+ "timedmedia-derivative-desc-480p.webm": "WebM para a web (480P)",
+ "timedmedia-derivative-desc-720p.webm": "WebM de alta calidade que se pode descargar (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "WebM descargable en Full HD (1080P)",
+ "timedmedia-derivative-desc-2160p.webm": "WebM descargable en 4K (2160P)",
+ "timedmedia-derivative-desc-360p.vp9.webm": "WebM VP9 (360P) visualizable na rede",
+ "timedmedia-derivative-desc-480p.vp9.webm": "WebM VP9 (480P) visualizable na rede",
+ "timedmedia-derivative-desc-720p.vp9.webm": "WebM VP9 de alta definiciĆ³n (720P) visualizable na rede",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "WebM VP9 de alta definiciĆ³n total (1080P) visualizable na rede",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "WebM VP9 4K completa (2160P) visualizable na rede",
+ "timedmedia-derivative-desc-320p.mp4": "MP4 compatible con dispositivos mĆ³biles (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "MP4 para a web (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 de calidade HD (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "MP4 de calidade Full HD (1080P)",
+ "timedmedia-derivative-desc-2160p.mp4": "MP4 de calidade de alta definiciĆ³n 4K",
+ "timedmedia-subtitle-new": "Crear unha nova traduciĆ³n ou editar a actual",
+ "timedmedia-subtitle-new-desc": "Seleccione a lingua e prema no botĆ³n \"'''{{int:Timedmedia-subtitle-new-go}}'''\"",
+ "timedmedia-subtitle-new-go": "Continuar",
+ "timedmedia-subtitle-language": "SubtĆ­tulos en $1 ($2)",
+ "timedmedia-subtitle-no-video": "Non hai ningĆŗn vĆ­deo asociado coa pĆ”xina de subtĆ­tulos actual",
+ "timedmedia-subtitle-no-subtitles": "Actualmente non hai subtƭtulos en $1 para este vƭdeo; pode [{{fullurl:{{FULLPAGENAME}}|action=edit}} editar esta pƔxina] para engadilos",
+ "timedmedia-subtitle-remote": "Os subtƭtulos deste ficheiro estƔn aloxados en $1",
+ "timedmedia-subtitle-remote-link": "Pode [$1 ollar a pĆ”xina de descriciĆ³n] deste ficheiro en $2",
+ "timedmediahandler": "ExtensiĆ³n TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 vĆ­deo|$1 vĆ­deos}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 vĆ­deo Ogg|$1 vĆ­deos Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 vĆ­deo WebM|$1 vĆ­deos WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transcodificaciĆ³n|$1 transcodificaciĆ³ns}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 transcodificaciĆ³n activa|$1 transcodificaciĆ³ns activas}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 transcodificaciĆ³n|$1 transcodificaciĆ³ns}} na cola",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 transcodificaciĆ³n fallida|$1 transcodificaciĆ³ns fallidas}}",
+ "timedmedia-file": "Ficheiro",
+ "timedmedia-audios": "{{PLURAL:$1|$1 ficheiro|$1 ficheiros}} de son",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 ficheiro|$1 ficheiros}} de son Ogg",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 ficheiro|$1 ficheiros}} de son FLAC",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 ficheiro|$1 ficheiros}} de son WAV",
+ "right-transcode-reset": "Restablecer os vĆ­deos transcodificados erroneamente para incluĆ­los de novo na cola de traballo.",
+ "right-transcode-status": "Ollar a [[Special:TimedMediaHandler|informaciĆ³n sobre a actividade de transcodificaciĆ³n actual]]",
+ "action-transcode-status": "ollar o estado da transcodificaciĆ³n actual",
+ "orphanedtimedtext": "PƔxinas orfas de TimedText",
+ "orphanedtimedtext-summary": "Lista de pƔxinas [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] que non teƱen un ficheiro correspondente.",
+ "orphanedtimedtext-unsupported": "Esta pĆ”xina especial sĆ³ estĆ” soportada en bases de datos MySQL.",
+ "orphanedtimedtext-notimedtext": "TimedText non se activou nesta wiki.",
+ "apihelp-query+transcodestatus-description": "Obter o estado de transcode para unha pƔxina de ficheiro dado.",
+ "apihelp-query+transcodestatus-example-1": "Obter o estado transcode para [[:File:Clip.webm]]",
+ "apihelp-query+videoinfo-description": "Estende a informaciĆ³n da imaxe para incluĆ­r a informaciĆ³n da fonte de vĆ­deo (derivado)",
+ "apihelp-query+videoinfo-param-prop": "Que informaciĆ³n de vĆ­deo obter:\n;timestamp:Engade o selo de tempo da versiĆ³n subida.\n;user:Engade o usuario que subiu a versiĆ³n de vĆ­deo.\n;userid:Engade o identificador de usuario que subiu a versiĆ³n de vĆ­deo.\n;comment:Comentario da versiĆ³n.\n;parsedcomment:Comentario analizado na versiĆ³n.\n;canonicaltitle:Engade o tĆ­tulo canĆ³nico do ficheiro de vĆ­deo.\n;url:Devolve a URL Ć³ vĆ­deo e a pĆ”xina de descriciĆ³n.\n;size:Engade o tamaƱo do vĆ­deo en bytes, a sĆŗa altura e anchura. O contador de pĆ”xina e duraciĆ³n tamĆ©n se engaden se Ć© aplicable.\n;dimensions:Alias para \"size\".\n;sha1:Engade a funciĆ³n hash SHA-1 do vĆ­deo.\n;mime:Engade o tipo MIME do vĆ­deo.\n;thumbmime:Engade o tipo MIME da miniatura do vĆ­deo (requie url e parĆ”metro $1urlwidth).\n;mediatype:Engade o tipo de medio multimedia do vĆ­deo.\n;metadata:Lista os metadatos Exif da versiĆ³n do vĆ­deo.\n;commonmetadata:Lista os metadatos formateados combinados desde varias fontes. Os resultados estĆ”n formateados en HTML.\n;archivename:Engade o nome de ficheiro da versiĆ³n para versiĆ³ns anteriores Ć” Ćŗltima.\n;bitdepth:Engade a profundidade de bit da versiĆ³n.\n;uploadwarning:Usado pola pĆ”xina [[Special:Upload]] para obter informaciĆ³n sobre un ficheiro xa existente. Non previsto para usar fĆ³ra do nĆŗcleo MediaWiki.\n;derivatives:Engade unha matriz dos diferentes formatos e calidades dispoƱibles dun audio ou vĆ­deo.",
+ "apihelp-query+videoinfo-example-1": "Buscar informaciĆ³n sobre [[:File:Folgers.ogv]]",
+ "apihelp-transcodereset-description": "Usuarios co permiso 'transcode-reset' poden reiniciar e reexecutar un traballo transcode.",
+ "apihelp-transcodereset-param-title": "TĆ­tulo do ficheiro multimedia.",
+ "apihelp-transcodereset-param-transcodekey": "A chave transcode que quere resetear. Collida de [[Special:ApiHelp/query+transcodestatus|action=query&prop=transcodestatus]].",
+ "apihelp-transcodereset-example-1": "Resetear todos os transcodes para [[:File:Clip.webm]]",
+ "apihelp-transcodereset-example-2": "Resetear a clave transcode '360_560kbs.webm' de [[:File:Clip.webm]]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/gom-deva.json b/extensions/TimedMediaHandler/i18n/gom-deva.json
new file mode 100644
index 00000000..f72dab88
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/gom-deva.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Darshan kandolkar",
+ "Supriya kankumbikar",
+ "Vaishali Parab"
+ ]
+ },
+ "timedmedia-no-player-js": "ą¤®ą¤¾ą¤« ą¤•ą¤°ą¤šą„‡ą¤‚, ą¤¤ą„ą¤®ą¤šą„ą¤Æą¤¾ ą¤¬ą„ą¤°ą¤¾ą¤µą¤œą¤°ą¤¾ą¤‚ą¤¤ ą¤ą¤• ą¤¤ą¤° ą¤œą¤¾ą¤µą¤¾ą¤øą„ą¤•ą„ą¤°ą¤æą¤Ŗą„ą¤Ÿ ą¤¦ą„ą¤¬ą¤³ą„‡ą¤‚ ą¤†ą¤øą¤¾ ą¤µą¤¾ ą¤øą¤®ą¤°ą„ą¤„ą„€ą¤¤ ą¤Ŗą„ą¤²ą„‡ą¤Æą¤° ą¤Øą¤¾ą„¤<br />\ną¤¤ą„ą¤®ą„€ <a href=\"$1\">ą¤•ą„ą¤²ą„€ą¤Ŗ ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤”</a> ą¤•ą¤°ą„ą¤‚ ą¤¶ą¤•ą¤¤ą¤¾ą¤¤ ą¤µą¤¾ ą¤•ą„ą¤²ą„€ą¤Ŗ ą¤¤ą„ą¤®ą¤šą„ą¤Æą¤¾ ą¤¬ą„ą¤°ą¤¾ą¤µą¤œą¤°ą¤¾ą¤Ø ą¤šą¤²ą„‹ą¤µą¤Ŗą¤¾ą¤• <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ą¤ą¤• ą¤Ŗą„ą¤²ą„‡ą¤Æą¤° ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤”</a> ą¤•ą¤°ą„ą¤‚ ą¤¶ą¤•ą¤¤ą¤¾ą¤¤.",
+ "timedmedia-source-file": "$1 ą¤‰ą¤—ą¤®",
+ "timedmedia-source-audio-file-desc": "ą¤®ą„‚ą¤³ $1 ą¤«ą¤¾ą¤Æą¤² ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/gom-latn.json b/extensions/TimedMediaHandler/i18n/gom-latn.json
new file mode 100644
index 00000000..1bffb01a
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/gom-latn.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "The Discoverer"
+ ]
+ },
+ "timedmedia-no-player-js": "Maf korchem, tujea browserant ek tor JavaScript dublem asa vo somorthit player nam.<br />\nTum <a href=\"$1\">clipik download</a> korunk shoktai vo clip tujea browseran cholovpak <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ek playerak download</a> korunk shoktai.",
+ "timedmedia-source-file": "$1 strot",
+ "timedmedia-source-file-desc": "Mul $1 fail, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Mul $1 fail ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/grc.json b/extensions/TimedMediaHandler/i18n/grc.json
new file mode 100644
index 00000000..ce201686
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/grc.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Crazymadlover",
+ "Flyax",
+ "Omnipaedista"
+ ]
+ },
+ "timedmedia-ogg-long-error": "į¼ŒĪŗĻ…ĻĪ± į¼€ĻĻ‡Īµįæ–Ī± ogg: $1",
+ "timedmedia-more": "Ļ€Ī»Ī­ĪæĪ½...",
+ "timedmedia-dismiss": "ĪšĪ»įæ„ĪµĪ¹Ī½",
+ "timedmedia-source-file": "$1 Ī Ī·Ī³Ī®"
+}
diff --git a/extensions/TimedMediaHandler/i18n/gsw.json b/extensions/TimedMediaHandler/i18n/gsw.json
new file mode 100644
index 00000000..fb38ce89
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/gsw.json
@@ -0,0 +1,62 @@
+{
+ "@metadata": {
+ "authors": [
+ "Als-ChlƤmens",
+ "Als-Holder",
+ "Melancholie"
+ ]
+ },
+ "timedmedia-desc": "Stellt e Styyrigsprogramm fir zytgstyyrti Medie (Video, Audio, timedText) zur Verfiegig, wo d Format WebM, Ogg Theora, Ogg Vorbis un SubRip unterstĆ¼tzt",
+ "timedmedia-ogg-short-audio": "Ogg-$1-Audiodatei, $2",
+ "timedmedia-ogg-short-video": "Ogg-$1-Videodatei, $2",
+ "timedmedia-ogg-short-general": "Ogg-$1-Mediadatei, $2",
+ "timedmedia-ogg-long-audio": "Ogg-$1-Audiodatei, LƤngi: $2, $3",
+ "timedmedia-ogg-long-video": "Ogg-$1-Videodatei, LƤngi: $2, $4Ɨ$5 Pixel, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg-Audio-/Video-Datei, $1, LƤngi: $2, $4Ɨ$5 Pixel, $3",
+ "timedmedia-ogg-long-general": "Ogg-Mediadatei, LƤngi: $2, $3",
+ "timedmedia-ogg-long-error": "Uugiltigi Ogg-Datei: $1",
+ "timedmedia-webm-short-video": "WebM-$1-Videodatei, $2",
+ "timedmedia-webm-long-video": "WebM-Audio-/Video-Datei, $1, LƤngei: $2, $4Ɨ$5 Pixel, $3 insgsamt",
+ "timedmedia-no-player-js": "Excusez, aber Dyy Browser het entwƤder JavaScript deaktiviert oder kei unterstitzti Abspilsoftware.<br />\nDu chasch <a href=\"$1\">dr Clip abelade</a> oder <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">e Abspielsoftware abelade</a> go dr Clip im Browser abspile.",
+ "timedmedia-more": "Meh ā€¦",
+ "timedmedia-dismiss": "Zuemache",
+ "timedmedia-download": "Datei spychere",
+ "timedmedia-play-media": "Mediedatei abspiile",
+ "timedmedia-desc-link": "Iber die Datei",
+ "timedmedia-oggThumb-version": "OggHandler brucht oggThumb in dr Version $1 oder hecher.",
+ "timedmedia-oggThumb-failed": "oggThumb het kei Miniaturbild chenne aalege.",
+ "timedmedia-status-header": "UmschlĆ¼sseligsstatus",
+ "timedmedia-update-status": "UmschlĆ¼sseligsstatus aktualisiere",
+ "timedmedia-status": "Status",
+ "timedmedia-status-unknown": "Status nit bekannt",
+ "timedmedia-transcodeinfo": "Abgleiteti Beschryybig umschlĆ¼ssle",
+ "timedmedia-actions": "Aktione",
+ "timedmedia-direct-link": "Ableitig abelade",
+ "timedmedia-not-ready": "Nit parat",
+ "timedmedia-completed-on": "UmschlĆ¼sselig vo $1 abgschlosse",
+ "timedmedia-error-on": "FƤƤler bim UmschlĆ¼ssle in $1.",
+ "timedmedia-started-transcode": "UmschlĆ¼sselig het vor $1 aagfange. $2",
+ "timedmedia-percent-done": "Ɩbe $1 % fertig",
+ "timedmedia-in-job-queue": "Vor $1 zur Ufftragswarteschlange dezuegfiegt worde",
+ "timedmedia-unknown-target-size": "Unbekannti ZiilgrĆ¶ĆŸi, $1 codiert",
+ "timedmedia-days": "{{PLURAL:$1|1 Tag|$1 TƤg}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 Stund|$1 Stunde}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 Minut|$1 Minute}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 Sekund|$1 Sekunde}}",
+ "timedmedia-reset": "UmschlĆ¼sselig zruggsetze",
+ "timedmedia-reset-confirm": "S Zruggsetze vo dere UmschlĆ¼sselig wird (wƤnn's vorhande isch), die aktuelli Datei ussenee un d UmschlĆ¼sselig no emool uff d Ufftragswarteschlange dezuefiege. E nƶii UmschlĆ¼sselig wird e Wyyl goo.<br /><br /> Sƶll des wĆ¼rkli gmacht werde?",
+ "timedmedia-reset-error": "FƤƤler bim Zruggsetze vo de UmschlĆ¼sselig.",
+ "timedmedia-source-file": "Quell ($1)",
+ "timedmedia-source-file-desc": "Original $1, $2 x $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Urspringligi $1-Datei ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Ogg-Videodatei mit niidriger DateĆ¼bertragigsrate (160p)",
+ "timedmedia-derivative-desc-360p.ogv": "WebstreamingfƤhigi Ogg-Videodatei (360p)",
+ "timedmedia-derivative-desc-480p.ogv": "WebstreamingfƤhigi Ogg-Videodatei (480p)",
+ "timedmedia-derivative-desc-720p.ogv": "Qualitativ hochwertigi Ogg-Videodatei (720p)",
+ "timedmedia-derivative-desc-360p.webm": "WebstreamingfƤhigi WebM-Videodatei (360p)",
+ "timedmedia-derivative-desc-480p.webm": "WebstreamingfƤhigi WebM-Videodatei (480p)",
+ "timedmedia-derivative-desc-720p.webm": "Qualitativ hochwertigi WebM-Videodatei (720p)",
+ "timedmedia-subtitle-language": "$1 ($2) Untertitel",
+ "timedmedia-subtitle-no-video": "Dere Untertitel-Syte isch kei Video zuegordnet.",
+ "timedmedia-subtitle-no-subtitles": "Es git uff $1 zurzit kei Untertitel fĆ¼r des Video. Bim dezuefiege vo Untertitel cha [{{fullurl:{{FULLPAGENAME}}|action=edit}} die Syte] bearbeitet werde."
+}
diff --git a/extensions/TimedMediaHandler/i18n/gu.json b/extensions/TimedMediaHandler/i18n/gu.json
new file mode 100644
index 00000000..7c73dd97
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/gu.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "KartikMistry",
+ "Arbhatt",
+ "Dsvyas",
+ "NehalDaveND",
+ "Ashok modhvadia"
+ ]
+ },
+ "timedmedia-no-player-js": "ąŖ®ąŖ¾ąŖ« ąŖ•ąŖ°ąŖ¶ą«‹, ąŖ¤ąŖ®ąŖ¾ąŖ°ąŖ¾ ąŖ¬ą«ąŖ°ąŖ¾ąŖ‰ąŖąŖ°ąŖ®ąŖ¾ąŖ‚ ąŖœąŖ¾ąŖµąŖ¾ąŖøą«ąŖ•ą«ąŖ°ąŖæąŖŖą«ąŖŸ ąŖøąŖ•ą«ąŖ°ąŖæąŖÆ ąŖØąŖ„ą«€ ąŖ…ąŖ„ąŖµąŖ¾ ąŖ¤ą«‹ ąŖøąŖŖą«‹ąŖ°ą«ąŖŸą«‡ąŖ” ąŖŖą«ąŖ²ą«‡ąŖÆąŖ° ąŖØąŖ„ą«€.<br />\nąŖ¤ąŖ®ą«‡ <a href=\"$1\">ąŖ•ą«ąŖ²ąŖæąŖŖ ąŖ”ąŖ¾ąŖ‰ąŖØąŖ²ą«‹ąŖ”</a> ąŖ•ąŖ°ą«€ ąŖ¶ąŖ•ą«‹ ąŖ›ą«‹ ąŖ…ąŖ„ąŖµąŖ¾ ąŖ† ąŖ•ą«ąŖ²ąŖæąŖŖąŖØą«‡ ąŖ¤ąŖ®ąŖ¾ąŖ°ąŖ¾ ąŖ¬ą«ąŖ°ąŖ¾ąŖ‰ąŖąŖ°ąŖ®ąŖ¾ąŖ‚ ąŖšąŖ²ąŖ¾ąŖµąŖµąŖ¾ ąŖ®ąŖ¾ąŖŸą«‡ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ąŖąŖ• ąŖŖą«ąŖ²ą«‡ąŖÆąŖ° ąŖ”ąŖ¾ąŖ‰ąŖØąŖ²ą«‹ąŖ”</a> ąŖ•ąŖ°ą«€ ąŖ¶ąŖ•ą«‹ ąŖ›ą«‹.",
+ "timedmedia-more": "ąŖµąŖ§ą«...",
+ "timedmedia-dismiss": "ąŖ¬ąŖ‚ąŖ§ ąŖ•ąŖ°ą«‹",
+ "timedmedia-download": "ąŖ«ąŖ¾ąŖˆąŖ² ąŖ”ąŖ¾ąŖ‰ąŖØąŖ²ą«‹ąŖ” ąŖ•ąŖ°ą«‹",
+ "timedmedia-status": "ąŖøą«ąŖ„ąŖæąŖ¤ąŖæ",
+ "timedmedia-status-unknown": "ąŖ…ąŖœą«ąŖžąŖ¾ąŖ¤ ąŖøą«ąŖ„ąŖæąŖ¤ąŖæ",
+ "timedmedia-actions": "ąŖ•ą«ąŖ°ąŖæąŖÆąŖ¾ąŖ“",
+ "timedmedia-not-ready": "ąŖ¤ą«ˆąŖÆąŖ¾ąŖ° ąŖØąŖ„ą«€",
+ "timedmedia-source-file": "$1 ąŖøą«ąŖ°ą«‹ąŖ¤",
+ "timedmedia-source-audio-file-desc": "ąŖ®ą«ąŖ³ ąŖ†ąŖµą«ƒąŖ¤ą«ąŖ¤ąŖæ $1 ąŖ«ąŖ¾ąŖ‡ąŖ² ($2)",
+ "timedmedia-subtitle-new-go": "ąŖœąŖ¾ąŖ“",
+ "timedmedia-file": "ąŖ«ąŖ¾ąŖ‡ąŖ²"
+}
diff --git a/extensions/TimedMediaHandler/i18n/gv.json b/extensions/TimedMediaHandler/i18n/gv.json
new file mode 100644
index 00000000..66353585
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/gv.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "MacTire02"
+ ]
+ },
+ "timedmedia-desc-link": "Mychione y choadan shoh"
+}
diff --git a/extensions/TimedMediaHandler/i18n/he.json b/extensions/TimedMediaHandler/i18n/he.json
new file mode 100644
index 00000000..29cddf15
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/he.json
@@ -0,0 +1,125 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "Guycn2",
+ "Rotem Liss",
+ "Rotemliss",
+ "YaronSh"
+ ]
+ },
+ "timedmedia-desc": "מטפל במדיה מ×Ŗוזמנ×Ŗ ā€“ וידאו, שמע, טקהט מ×Ŗוזמן ā€“ עם ×Ŗמיכה ב×Ŗהדי×Øי WebM&rlm;, Ogg Theora&rlm;, Vorbis ו־srt",
+ "timedmedia-ogg-short-audio": "קובׄ שמע $1 של Ogg, $2",
+ "timedmedia-ogg-short-video": "קובׄ וידאו $1 של Ogg, $2",
+ "timedmedia-ogg-short-general": "קובׄ מדיה $1 של Ogg, $2",
+ "timedmedia-ogg-long-audio": "קובׄ שמע $1 של Ogg, באו×Øך $2, $3",
+ "timedmedia-ogg-long-video": "קובׄ וידאו $1 של Ogg, באו×Øך $2, $4Ɨ$5 פיקהלים, $3",
+ "timedmedia-ogg-long-multiplexed": "קובׄ Ogg מ×Øובב של שמע ווידאו, $1, באו×Øך $2, $4Ɨ$5 פיקהלים, $3 בהך הכול",
+ "timedmedia-ogg-long-general": "קובׄ מדיה של Ogg, באו×Øך $2, $3",
+ "timedmedia-ogg-long-error": "קובׄ ogg בל×Ŗי ×Ŗקין: $1",
+ "timedmedia-ogg-long-no-streams": "קובׄ מדיה Ogg. אזה×Øה: אף אחד מהקודקים בקובׄ הזה אינו מוּכּ×Ø.",
+ "timedmedia-webm-short-video": "קובׄ וידאו WebM $1&rlm;, $2",
+ "timedmedia-webm-long-video": "קובׄ שמע ווידאו WebM&rlm;, $1, באו×Øך $2&rlm;, $4 Ɨ $5 פיקהלים, $3 הך הכול",
+ "timedmedia-flac-short-audio": "קובׄ שמע FLACā€, $1",
+ "timedmedia-flac-long-audio": "קובׄ שמע FLACā€, או×Øך $1, הך הכול $2",
+ "timedmedia-wav-short-audio": "קובׄ שמע WAVā€, $1",
+ "timedmedia-wav-long-audio": "קובׄ שמע WAV, או×Øך $1, הך הכול $2",
+ "timedmedia-wav-pcm-required": "אפש×Ø ×œ×”×¢×œ×•×Ŗ ×Øק קובצי WAV ב×Ŗהדי×Ø PCMā€ (Pulse Code Modulation).",
+ "timedmedia-mp4-short-video": "קובׄ וידאו MP4 $1&rlm;, $2",
+ "timedmedia-mp4-long-video": "קובׄ שמע ווידאו של MP4&rlm;, $1, באו×Øך $2, $4 Ɨ $5 פיהקלים, $3 בהך הכול",
+ "timedmedia-no-player-js": "מצטע×Øים, בדפדפן שלך לא מופעל×Ŗ ×Ŗמיכה ב־JavaScript או שאין בו נגן × ×Ŗמך.<br />\nבאפש×Øו×Ŗך <a href=\"$1\">להו×Øיד למחשב א×Ŗ ×”×”×Øטון</a> או <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">להו×Øיד נגן</a> שינגן א×Ŗ ×”×”×Øטון בדפדפן שלך.",
+ "timedmedia-more": "עודā€¦",
+ "timedmedia-dismiss": "×”×’×™×Øה",
+ "timedmedia-download": "הו×Øד×Ŗ הקובׄ",
+ "timedmedia-play-media": "לנגן א×Ŗ המדיה",
+ "timedmedia-desc-link": "אודו×Ŗ הקובׄ",
+ "timedmedia-oggThumb-version": "OggHandler דו×Øש oggThumb מג×Ø×”×” $1 או ג×Ø×”×” חדשה יו×Ŗ×Ø.",
+ "timedmedia-oggThumb-failed": "oggThumb לא הצליח ליצו×Ø ×Ŗמונה מוקטנ×Ŗ.",
+ "timedmedia-status-header": "מצב המ×Øה משני×Ŗ",
+ "timedmedia-update-status": "עדכון מצב המ×Øה משני×Ŗ",
+ "timedmedia-status": "מצב",
+ "timedmedia-status-unknown": "מצב לא ידוע",
+ "timedmedia-transcodebitrate": "קצב ביטים",
+ "timedmedia-transcodeduration": "זמן קידוד",
+ "timedmedia-transcodeinfo": "×Ŗהדי×Ø",
+ "timedmedia-actions": "פעולו×Ŗ",
+ "timedmedia-direct-link": "הו×Øדה",
+ "timedmedia-not-ready": "לא מוכן",
+ "timedmedia-completed-on": "הושלם ב־$1",
+ "timedmedia-error-on": "שגיאה ב־$1",
+ "timedmedia-started-transcode": "ה×Ŗחילה לפני $1ā€. $2",
+ "timedmedia-percent-done": "בע×Øך $1% נעשה",
+ "timedmedia-in-job-queue": "נוהף ל×Ŗו×Ø ×ž×©×™×ž×•×Ŗ לפני $1",
+ "timedmedia-unknown-target-size": "גודל יעד אינו ידוע, קודדו $1",
+ "timedmedia-days": "{{PLURAL:$1|יום אחד|יומיים|$1 ימים}}",
+ "timedmedia-hours": "{{PLURAL:$1|שעה אח×Ŗ|שע×Ŗיים|$1 שעו×Ŗ}}",
+ "timedmedia-minutes": "{{PLURAL:$1|דקה אח×Ŗ|$1 דקו×Ŗ}}",
+ "timedmedia-seconds": "{{PLURAL:$1|שנייה אח×Ŗ|$1 שניו×Ŗ}}",
+ "timedmedia-reset": "א×Ŗחול המ×Øה משני×Ŗ",
+ "timedmedia-reset-confirm": "א×Ŗחול ההמ×Øה הזא×Ŗ ימחק כל קובׄ קיים (אם יש כזה) ויוהיף שוב א×Ŗ ההמ×Øה המשני×Ŗ ל×Ŗו×Ø ×”×ž×©×™×ž×•×Ŗ. ייקח זמן כדי לבצע א×Ŗ ההמ×Øה המשני×Ŗ שוב.<br /><br />להמשיך?",
+ "timedmedia-reset-error": "שגיאה בא×Ŗחול משימ×Ŗ המ×Øה משני×Ŗ",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "ממקו×Ø $1",
+ "timedmedia-source-file-desc": "קובׄ $1 מקו×Øי, $2 Ɨ $3&rlm; ($4)",
+ "timedmedia-source-audio-file-desc": "קובׄ $1 מקו×Øי ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "וידאו Ogg (160P)&lrm; ל×Øוחב פה נמוך",
+ "timedmedia-derivative-desc-240p.ogv": "וידאו Ogg (240P)&lrm; לנגינה שוטפ×Ŗ מה×Øש×Ŗ",
+ "timedmedia-derivative-desc-360p.ogv": "וידאו Ogg (360P)&lrm; לנגינה שוטפ×Ŗ מה×Øש×Ŗ",
+ "timedmedia-derivative-desc-480p.ogv": "וידאו Ogg (480P)&lrm; לנגינה שוטפ×Ŗ מה×Øש×Ŗ",
+ "timedmedia-derivative-desc-720p.ogv": "וידאו Ogg (720P)&lrm; באיכו×Ŗ גבוהה שני×Ŗן להו×Øדה",
+ "timedmedia-derivative-desc-1080p.ogv": "וידאו Ogg שאפש×Ø ×œ×”×•×Øיד באיכו×Ŗ HD מלאה (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "WebM להז×Øמה ב×Øש×Ŗ (160P)",
+ "timedmedia-derivative-desc-360p.webm": "WebM ני×Ŗן לשידו×Ø ×©×˜×£ ב×Øש×Ŗ (360P)",
+ "timedmedia-derivative-desc-480p.webm": "וידאו WebM (480P)&lrm; לנגינה שוטפ×Ŗ מה×Øש×Ŗ",
+ "timedmedia-derivative-desc-720p.webm": "וידאו WebM (720P)&lrm; באיכו×Ŗ גבוהה שני×Ŗן להו×Øדה",
+ "timedmedia-derivative-desc-1080p.webm": "קובׄ WebM שאפש×Ø ×œ×”×•×Øיד באיכו×Ŗ HD מלאה (1080P)",
+ "timedmedia-derivative-desc-2160p.webm": "קובׄ WebM שאפש×Ø ×œ×”×•×Øיד באיכו×Ŗ 4K מלאה (2160P)",
+ "timedmedia-derivative-desc-360p.vp9.webm": "WebM VP9 ני×Ŗן להז×Øמה ב×Øש×Ŗ (360P)",
+ "timedmedia-derivative-desc-480p.vp9.webm": "WebM VP9 ני×Ŗן להז×Øמה ב×Øש×Ŗ (480P)",
+ "timedmedia-derivative-desc-720p.vp9.webm": "WebM VP9 באיכו×Ŗ HD ני×Ŗן להז×Øמה ב×Øש×Ŗ (720P)",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "WebM VP9 באיכו×Ŗ HD מלאה ני×Ŗן להז×Øמה ב×Øש×Ŗ (1080P)",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "WebM VP9 באיכו×Ŗ 4K מלאה ני×Ŗן להז×Øמה ב×Øש×Ŗ (2160P)",
+ "timedmedia-derivative-desc-320p.mp4": "MP4 ידידו×Ŗי למכשי×Ø (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "וידאו WebM (480P)&lrm; לנגינה שוטפ×Ŗ מה×Øש×Ŗ",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 באיכו×Ŗ גבוהה (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "קובׄ MP4 שאפש×Ø ×œ×”×•×Øיד באיכו×Ŗ HD מלאה (1080P)",
+ "timedmedia-derivative-desc-2160p.mp4": "MP4 באיכו×Ŗ 4K מלאה (2160P)",
+ "timedmedia-subtitle-new": "יצי×Ø×Ŗ ×Ŗ×Øגום חדש או ×¢×Øיכ×Ŗ ×Ŗ×Øגום קיים",
+ "timedmedia-subtitle-new-desc": "נא לבחו×Ø ×©×¤×” וללחוׄ על כפ×Ŗו×Ø '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "מעב×Ø",
+ "timedmedia-subtitle-language": "כ×Ŗוביו×Ŗ ב{{GRAMMAR:×Ŗחילי×Ŗ|$1}} ($2)",
+ "timedmedia-subtitle-no-video": "אין וידאו שמשויך לדף הכ×Ŗוביו×Ŗ הנוכחי",
+ "timedmedia-subtitle-no-subtitles": "אין כע×Ŗ כ×Ŗוביו×Ŗ עבו×Ø ×”×©×¤×” הבאה: $1. אפש×Ø [{{fullurl:{{FULLPAGENAME}}|action=edit}} לע×Øוך א×Ŗ הדף הזה] ולהוהיף או×Ŗן",
+ "timedmedia-subtitle-remote": "טקהט מ×Ŗוזמן עבו×Ø ×§×•×‘×„ זה מאוחהן ב{{GRAMMAR:×Ŗחילי×Ŗ|$1}}",
+ "timedmedia-subtitle-remote-link": "אפש×Ø [$1 להציג א×Ŗ דף ה×Ŗיאו×Ø] של הקובׄ הזה בדף $2",
+ "timedmediahandler": "מדיה מ×Ŗוזמנ×Ŗ",
+ "timedmedia-videos": "{{PLURAL:$1|×”×Øט אחד|$1 ×”×Øטים}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|×”×Øט Ogg אחד|$1 ×”×Øטי Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|×”×Øט WebM אחד|$1 ×”×Øטי WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|המ×Øה משני×Ŗ אח×Ŗ|$1 המ×Øו×Ŗ משניו×Ŗ}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|המ×Øה משני×Ŗ אח×Ŗ ×Øצה|$1 המ×Øו×Ŗ משניו×Ŗ ×Øצו×Ŗ}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|המ×Øה משני×Ŗ אח×Ŗ ב×Ŗו×Ø|$1 המ×Øו×Ŗ משניו×Ŗ ב×Ŗו×Ø}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|המ×Øו×Ŗ משני×Ŗ אח×Ŗ נכשלה|$1 המ×Øו×Ŗ משניו×Ŗ נכשלו}}",
+ "timedmedia-file": "קובׄ",
+ "timedmedia-audios": "{{PLURAL:$1|קובׄ שמע אחד|$1 קובצי שמע}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|קובׄ שמע Ogg אחד|$1 קובצי שמע Ogg}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|קובׄ שמע FLAC אחד|$1 קובצי שמע FLAC}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|קובׄ שמע WAV אחד|$1 קובצי שמע WAV}}",
+ "right-transcode-reset": "א×Ŗחול ×”×Øטים שקידוד המשנה שלהם הושלם או נכשל כך שהם מוכנהים מחדש ל×Ŗו×Ø ×”×ž×©×™×ž×•×Ŗ.",
+ "right-transcode-status": "הצג×Ŗ [[Special:TimedMediaHandler|מידע על פעילו×Ŗ המ×Ø×Ŗ־המשנה הנוכחי×Ŗ]]",
+ "action-transcode-status": "להציג א×Ŗ מצב המ×Ø×Ŗ־המשנה",
+ "orphanedtimedtext": "דפי טקהט מ×Ŗוזמן י×Ŗומים",
+ "orphanedtimedtext-summary": "×Øשימה של כל דפי [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] שלא משויך להם קובׄ.",
+ "orphanedtimedtext-unsupported": "הדף המיוחד הזה × ×Ŗמך ×Øק במהדי × ×Ŗונים MySQL.",
+ "orphanedtimedtext-notimedtext": "הה×Øחבה TimedText אינה מופעל×Ŗ בוויקי הזה.",
+ "apihelp-query+transcodestatus-description": "קבל×Ŗ מצב ההמ×Øה המשני×Ŗ עבו×Ø ×“×£ הקובׄ הנ×Ŗון.",
+ "apihelp-query+transcodestatus-example-1": "קבל×Ŗ מצב ההמ×Øה המשני×Ŗ עבו×Ø [[:File:Clip.webm]]",
+ "apihelp-query+videoinfo-description": "ה×Øחב×Ŗ imageinfo להכלל×Ŗ מידע על מקו×Ø ×”×•×•×™×“××• (נגז×Øו×Ŗ)",
+ "apihelp-query+videoinfo-param-prop": "איזה מידע לקבל על הווידאו:\n;timestamp:הוהפ×Ŗ חו×Ŗם זמן לג×Ø×”×” שהול×Ŗה.\n;user:הוהפ×Ŗ המש×Ŗמש שהעלה א×Ŗ ג×Ø×”×Ŗ הווידאו.\n;userid:הוהפ×Ŗ מזהה המש×Ŗמש שהעלה א×Ŗ ג×Ø×”×Ŗ הווידאו.\n;comment:הע×Øה על הג×Ø×”×”.\n;parsedcomment:פענוח ההע×Øה על הג×Ø×”×”.\n;canonicaltitle:הוהפ×Ŗ הכו×Ŗ×Ø×Ŗ הקנוני×Ŗ של שם קובׄ הווידאו.\n;url:הוהפ×Ŗ URL לווידאו ולדף ה×Ŗיאו×Ø.\n;size:הוהפ×Ŗ הגודל של הווידאו בב×Ŗים, הגובה שלו וה×Øוחב שלו. הפי×Ø×Ŗ דפים ומשך מוהפים כשזה מ×Ŗאים.\n;dimensions:או×Ŗו דב×Ø ×›×ž×• size.\n;sha1:הוהפ×Ŗ גיבוב SHA-1 של הווידאו.\n;mime:הוהפ×Ŗ הוג MIME של הווידאו.\n;thumbmime:הוהפ×Ŗ הוג MIME של ה×Ŗמונה הממוזע×Ø×Ŗ של הווידאו (נד×Øש url והפ×Øמט×Ø $1urlwidth).\n;mediatype:הוהפ×Ŗ הוג המדיה של הווידאו.\n;metadata:×Øשימ×Ŗ מטא־נ×Ŗוני EXIF לג×Ø×”×” של הווידאו.\n;commonmetadata:×Øשימ×Ŗ מטא־נ×Ŗונים כללים של ×Ŗהדי×Ø ×”×§×•×‘×„ עבו×Ø ×’×Ø×”×Ŗ הווידאו.\n;extmetadata:×Øשימ×Ŗ מטא־נ×Ŗונים מעוצבים משולבים ממהפ×Ø ×ž×§×•×Øו×Ŗ ה×Ŗוצאו×Ŗ מעוצבו×Ŗ עם HTML.\n;archivename:הוהפ×Ŗ שם הקובׄ של ג×Ø×”×Ŗ הא×Øכיון עבו×Ø ×”×’×Øהאו×Ŗ שאינן הג×Ø×”×” האח×Øונה.\n;bitdepth:עומק הביטים של הג×Ø×”×”.\n;uploadwarning:משמש א×Ŗ הדף [[Special:Upload]] כדי לקבל מידע על קובׄ קיים. לא מיועד לשימוש מחוׄ לליב×Ŗ MediaWiki.\n;derivatives:הוהפ×Ŗ מע×Øך של ג×Øהאו×Ŗ זמינו×Ŗ שונו×Ŗ מבחינ×Ŗ ×Ŗהדי×Ø ×•××™×›×•×Ŗ של קובׄ שמע או וידאו.",
+ "apihelp-query+videoinfo-example-1": "אחזו×Ø ×ž×™×“×¢ על [[:File:Folgers.ogv]]",
+ "apihelp-transcodereset-description": "מש×Ŗמשים עם הה×Øשאה 'transcode-reset' יכולים לאפה ולה×Øיׄ מלחדש משימ×Ŗ המ×Ø×Ŗ־משנה.",
+ "apihelp-transcodereset-param-title": "כו×Ŗ×Ø×Ŗ קובׄ המדיה.",
+ "apihelp-transcodereset-param-transcodekey": "מפ×Ŗח המ×Ø×Ŗ־המשנה שב×Øצונך לאפה. יש לאחז×Ø ××•×Ŗו מ־[[Special:ApiHelp/query+transcodestatus|action=query&prop=transcodestatus]].",
+ "apihelp-transcodereset-example-1": "איפוה כל המ×Øו×Ŗ־המשנה עבו×Ø [[:File:Clip.webm]]",
+ "apihelp-transcodereset-example-2": "איפוה מפ×Ŗח המ×Ø×Ŗ המשנה '<span dir=\"ltr\">360_560kbs.webm</span>' עבו×Ø [[:File:Clip.webm]]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/hi.json b/extensions/TimedMediaHandler/i18n/hi.json
new file mode 100644
index 00000000..08ef0a1d
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/hi.json
@@ -0,0 +1,39 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kaustubh",
+ "Shyam",
+ "Siddhartha Ghai",
+ "ą¤øą¤‚ą¤œą„€ą¤µ ą¤•ą„ą¤®ą¤¾ą¤°",
+ "NehalDaveND"
+ ]
+ },
+ "timedmedia-desc": "ą¤‘ą¤— ą¤„ą¤æą¤Æą„‹ą¤°ą¤¾ ą¤”ą¤° ą¤µą„‰ą¤°ą„ą¤¬ą¤æą¤ø ą¤«ą¤¼ą¤¾ą¤ˆą¤²ą„ą¤øą¤•ą„‡ ą¤²ą¤æą¤Æą„‡ ą¤šą¤¾ą¤²ą¤•, ą¤œą¤¾ą¤µą¤¾ą¤øą„ą¤•ą„ą¤°ą„€ą¤Ŗą„ą¤Ÿ ą¤Ŗą„ą¤²ą„‡ą¤Æą¤° ą¤•ą„‡ ą¤øą¤¾ą¤„",
+ "timedmedia-ogg-short-audio": "ą¤‘ą¤— $1 ą¤§ą„ą¤µą¤Øą„€ ą¤«ą¤¼ą¤¾ą¤ˆą¤², $2",
+ "timedmedia-ogg-short-video": "ą¤‘ą¤— $1 ą¤šą¤²ą¤¤ą¤šą¤æą¤¤ą„ą¤° ą¤«ą¤¼ą¤¾ą¤ˆą¤², $2",
+ "timedmedia-ogg-short-general": "ą¤‘ą¤— $1 ą¤®ą„€ą¤”ą¤æą¤Æą¤¾ ą¤«ą¤¼ą¤¾ą¤ˆą¤², $2",
+ "timedmedia-ogg-long-audio": "ą¤‘ą¤— $1 ą¤§ą„ą¤µą¤Øą„€ ą¤«ą¤¼ą¤¾ą¤ˆą¤², ą¤²ą¤‚ą¤¬ą¤¾ą¤ˆ $2, $3",
+ "timedmedia-ogg-long-video": "ą¤‘ą¤— $1 ą¤šą¤²ą¤¤ą¤šą¤æą¤¤ą„ą¤° ą¤«ą¤¼ą¤¾ą¤ˆą¤², ą¤²ą¤‚ą¤¬ą¤¾ą¤ˆ $2, $4Ɨ$5 ą¤Ŗą„€ą¤•ą„ą¤øą„‡ą¤²ą„ą¤ø, $3",
+ "timedmedia-ogg-long-multiplexed": "ą¤‘ą¤— ą¤§ą„ą¤µą¤Øą„€/ą¤šą¤æą¤¤ą„ą¤° ą¤«ą¤¼ą¤¾ą¤ˆą¤², $1, ą¤²ą¤‚ą¤¬ą¤¾ą¤ˆ $2, $4Ɨ$5 ą¤Ŗą¤æą¤•ą„ą¤øą„‡ą¤²ą„ą¤ø, $3 ą¤•ą„ą¤²",
+ "timedmedia-ogg-long-general": "ą¤‘ą¤— ą¤®ą„€ą¤”ą¤æą¤Æą¤¾ ą¤«ą¤¼ą¤¾ą¤ˆą¤², ą¤²ą¤‚ą¤¬ą¤¾ą¤ˆ $2, $3",
+ "timedmedia-ogg-long-error": "ą¤—ą¤²ą¤¤ ą¤‘ą¤— ą¤«ą¤¼ą¤¾ą¤ˆą¤²: $1",
+ "timedmedia-no-player-js": "ą¤•ą„ą¤·ą¤®ą¤¾ ą¤•ą¤°ą„‡ą¤‚, ą¤†ą¤Ŗą¤•ą„‡ ą¤¬ą„ą¤°ą¤¾ą¤‰ą¤œą¤¼ą¤° ą¤®ą„‡ą¤‚ ą¤Æą¤¾ ą¤¤ą„‹ ą¤œą¤¾ą¤µą¤¾ą¤øą„ą¤•ą„ą¤°ą¤æą¤Ŗą„ą¤Ÿ ą¤…ą¤•ą„ą¤·ą¤® ą¤¹ą„ˆ ą¤Æą¤¾ ą¤øą¤®ą¤°ą„ą¤„ą¤æą¤¤ ą¤Ŗą„ą¤²ą„‡ą¤Æą¤° ą¤Øą¤¹ą„€ą¤‚ ą¤¹ą„ˆą„¤<br />\ną¤†ą¤Ŗ <a href=\"$1\">ą¤•ą„ą¤²ą¤æą¤Ŗ ą¤•ą„‹ ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤”</a> ą¤•ą¤° ą¤øą¤•ą¤¤ą„‡ ą¤¹ą„ˆą¤‚ ą¤…ą¤„ą¤µą¤¾ ą¤•ą„ą¤²ą¤æą¤Ŗ ą¤•ą„‹ ą¤…ą¤Ŗą¤Øą„‡ ą¤¬ą„ą¤°ą¤¾ą¤‰ą¤œą¤¼ą¤° ą¤®ą„‡ą¤‚ ą¤šą¤²ą¤¾ą¤Øą„‡ ą¤•ą„‡ ą¤²ą¤æą¤ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ą¤ą¤• ą¤Ŗą„ą¤²ą„‡ą¤Æą¤° ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤”</a> ą¤•ą¤° ą¤øą¤•ą¤¤ą„‡ ą¤¹ą„ˆą¤‚ą„¤",
+ "timedmedia-more": "ą¤”ą¤°...",
+ "timedmedia-dismiss": "ą¤¬ą¤‚ą¤¦ ą¤•ą¤°ą„‡ą¤‚",
+ "timedmedia-download": "ą¤«ą¤¼ą¤¾ą¤ˆą¤² ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤” ą¤•ą¤°ą„‡ą¤‚",
+ "timedmedia-desc-link": "ą¤‡ą¤ø ą¤«ą¤¼ą¤¾ą¤ˆą¤²ą¤•ą„‡ ą¤¬ą¤¾ą¤°ą„‡ ą¤®ą„‡ą¤‚",
+ "timedmedia-status": "ą¤øą„ą¤„ą¤æą¤¤ą¤æ",
+ "timedmedia-status-unknown": "ą¤…ą¤œą„ą¤žą¤¾ą¤¤ ą¤øą„ą¤„ą¤æą¤¤ą¤æ",
+ "timedmedia-actions": "ą¤•ą„ą¤°ą¤æą¤Æą¤¾ą¤ą¤",
+ "timedmedia-source-file": "$1 ą¤øą„ą¤°ą„‹ą¤¤",
+ "timedmedia-source-audio-file-desc": "ą¤®ą„‚ą¤² $1 ą¤«ą¤¼ą¤¾ą¤‡ą¤² ($2)",
+ "timedmedia-derivative-desc-1080p.ogv": "ą¤Ŗą„‚ą¤°ą„ą¤£ ą¤‰ą¤šą„ą¤š ą¤Ŗą¤°ą¤æą¤­ą¤¾ą¤·ą¤¾ ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤” ą¤•ą¤°ą¤Øą„‡ ą¤Æą„‹ą¤—ą„ą¤Æ ą¤“ą¤œą„€ą¤œą„€ ą¤µą„€ą¤”ą¤æą¤Æą„‹ (ą„§ą„¦ą„®ą„¦ą¤Ŗą„€)",
+ "timedmedia-derivative-desc-1080p.webm": "ą¤Ŗą„‚ą¤°ą„ą¤£ ą¤‰ą¤šą„ą¤š ą¤Ŗą¤°ą¤æą¤­ą¤¾ą¤·ą¤¾ ą¤•ą„‡ ą¤øą¤¾ą¤„ ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤” ą¤•ą¤°ą¤Øą„‡ ą¤Æą„‹ą¤—ą„ą¤Æ ą¤µą„‡ą¤¬-ą¤ą¤® (ą„§ą„¦ą„®ą„¦ą¤Ŗą„€)",
+ "timedmedia-derivative-desc-1080p.mp4": "ą¤Ŗą„‚ą¤°ą„ą¤£ ą¤‰ą¤šą„ą¤š ą¤Ŗą¤°ą¤æą¤­ą¤¾ą¤·ą¤¾ ą¤—ą„ą¤£ą¤µą¤¤ą¤¾ ą¤ą¤®ą¤Ŗą„€ą„Ŗ (ą„§ą„¦ą„®ą„¦ą¤Ŗą„€)",
+ "timedmedia-subtitle-new-go": "ą¤œą¤¾ą¤ą¤",
+ "timedmedia-file": "ą¤«ą¤¼ą¤¾ą¤‡ą¤²",
+ "timedmedia-audios": "{{PLURAL:$1|$1 ą¤‘ą¤”ą¤æą¤Æą„‹ ą¤«ą¤¼ą¤¾ą¤‡ą¤²|$1 ą¤‘ą¤”ą¤æą¤Æą„‹ ą¤«ą¤¼ą¤¾ą¤‡ą¤²ą„‡ą¤‚}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ogg ą¤‘ą¤”ą¤æą¤Æą„‹ ą¤«ą¤¼ą¤¾ą¤‡ą¤²|$1 Ogg ą¤‘ą¤”ą¤æą¤Æą„‹ ą¤«ą¤¼ą¤¾ą¤‡ą¤²ą„‡ą¤‚}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 FLAC ą¤‘ą¤”ą¤æą¤Æą„‹ ą¤«ą¤¼ą¤¾ą¤‡ą¤²|$1 FLAC ą¤‘ą¤”ą¤æą¤Æą„‹ ą¤«ą¤¼ą¤¾ą¤‡ą¤²ą„‡ą¤‚}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 WAV ą¤‘ą¤”ą¤æą¤Æą„‹ ą¤«ą¤¼ą¤¾ą¤‡ą¤²|$1 WAV ą¤‘ą¤”ą¤æą¤Æą„‹ ą¤«ą¤¼ą¤¾ą¤‡ą¤²ą„‡ą¤‚}}"
+}
diff --git a/extensions/TimedMediaHandler/i18n/hr.json b/extensions/TimedMediaHandler/i18n/hr.json
new file mode 100644
index 00000000..b8d63e0f
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/hr.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "CERminator",
+ "Dalibor Bosits",
+ "Ex13",
+ "SpeedyGonsales",
+ "Roberta F.",
+ "Fraxinus",
+ "Teoo3"
+ ]
+ },
+ "timedmedia-desc": "Poslužitelj za Ogg Theora i Vorbis datoteke, s JavaScript preglednikom",
+ "timedmedia-ogg-short-audio": "Ogg $1 zvučna datoteka, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 video datoteka, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 medijska datoteka, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 zvučna datoteka, duljine $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 video datoteka, duljine $2, $4x$5 piksela, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg multipleksirana zvučna/video datoteka, $1, duljine $2, $4Ɨ$5 piksela, $3 ukupno",
+ "timedmedia-ogg-long-general": "Ogg medijska datoteka, duljine $2, $3",
+ "timedmedia-ogg-long-error": "nevaljana ogg datoteka: $1",
+ "timedmedia-no-player-js": "Nažalost, u VaŔem pregledniku isključen je JavaScript, ili nije dostupan na ovom projektu.<br />\nMožete <a href=\"<span class=\" notranslate\"=\"\" translate=\"no\">$1</span>\">preuzeti videozapis</a> ili <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">učitati player</a> za reproduciranje videozapisa u pregledniku.",
+ "timedmedia-more": "ViŔe...",
+ "timedmedia-dismiss": "Zatvori",
+ "timedmedia-download": "Snimi datoteku",
+ "timedmedia-desc-link": "O ovoj datoteci",
+ "timedmedia-source-file": "Izvor $1",
+ "timedmedia-source-audio-file-desc": "Originalna $1 datoteka ($2)",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "Full 4K streamable WebM VP9 (2160P)",
+ "timedmedia-derivative-desc-2160p.mp4": "MP4 pune 4K kvalitete (2160P)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/hrx.json b/extensions/TimedMediaHandler/i18n/hrx.json
new file mode 100644
index 00000000..80513f50
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/hrx.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Midnight Gambler"
+ ]
+ },
+ "timedmedia-source-file": "Quell ($1)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/hsb.json b/extensions/TimedMediaHandler/i18n/hsb.json
new file mode 100644
index 00000000..094def43
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/hsb.json
@@ -0,0 +1,83 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dundak",
+ "Michawiki",
+ "Reedy"
+ ]
+ },
+ "timedmedia-desc": "WodÅŗenski program za awdio, widejo a timedText z podpěru za formaty WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Awdiodataja Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Widejodataja Ogg $1, $2",
+ "timedmedia-ogg-short-general": "Ogg medijowa dataja $1, $2",
+ "timedmedia-ogg-long-audio": "Ogg-awdiodataja $1, dołhosć: $2, $3",
+ "timedmedia-ogg-long-video": "Ogg-widejodataja $1, dołhosć: $2, $4Ɨ$5 pikselow, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg multipleksna awdio-/widejodataja, $1, dołhosć: $2, $4Ɨ$5 pikselow, $3",
+ "timedmedia-ogg-long-general": "Ogg medijowa dataja, dołhosć: $2, $3",
+ "timedmedia-ogg-long-error": "Njepłaćiwa Ogg-dataja: $1",
+ "timedmedia-webm-short-video": "Widejodataja WebM $1, $2",
+ "timedmedia-webm-long-video": "Awdio-/widejodataja WebM, $1, dołhosć $2, $4 x $5 pikselow, $3 dohromady",
+ "timedmedia-mp4-short-video": "MP4 $1 widejodataja, $2",
+ "timedmedia-mp4-long-video": "MP4 awdio-/widejodataja, $1, dołhosć $2, $4 Ɨ $5 pikselow, $3 dohromady",
+ "timedmedia-no-player-js": "TwĆ³j wobhladowak je pak JavaScript znjemĆ³Å¾nił pak nima podpěrowany wothrawak.<br />\nMĆ³Å¾eÅ” <a href=\"$1\">klip sćahnyć</a> abo <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">wothrawak sćahnyć</a>, zo by klip w swojim wobhladowaku wothrawał.",
+ "timedmedia-more": "Wjace ...",
+ "timedmedia-dismiss": "Začinić",
+ "timedmedia-download": "Dataju sćahnyć",
+ "timedmedia-play-media": "Medijowu dataju wothrać",
+ "timedmedia-desc-link": "Wo tutej dataji",
+ "timedmedia-oggThumb-version": "OggHandler trjeba wersiju $1 oggThumb abo nowŔu.",
+ "timedmedia-oggThumb-failed": "oggThumb njemĆ³Å¾eÅ”e wobrazk wutworić.",
+ "timedmedia-status-header": "Překodowanski status",
+ "timedmedia-update-status": "Překodowanski status aktualizować",
+ "timedmedia-status": "Status",
+ "timedmedia-status-unknown": "Njeznaty status",
+ "timedmedia-transcodeinfo": "WotwodÅŗene wopisanje překodować",
+ "timedmedia-actions": "Akcije",
+ "timedmedia-direct-link": "WotwodÅŗenje sćahnyć",
+ "timedmedia-not-ready": "Nic hotowy",
+ "timedmedia-completed-on": "Překodowanje $1 wotzamknjene",
+ "timedmedia-error-on": "Zmylk při překodowanju $1",
+ "timedmedia-started-transcode": "Překodowanje před $1 startowane. $2",
+ "timedmedia-percent-done": "Na wŔě $1% sčinjene",
+ "timedmedia-in-job-queue": "Před $1 čakanskemu rynčkej přidaty",
+ "timedmedia-unknown-target-size": "Njeznata cilowa wulkosć, $1 kodowane",
+ "timedmedia-days": "{{PLURAL:$1|1 dÅŗeń|$1 dnjej|$1 dny|$1 dnjow}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 hodÅŗina|$1 hodÅŗinje|$1 hodÅŗiny|$1 hodÅŗin}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 mjeńŔina|$1 mjeńŔinje|$1 mjeńŔiny|$1 mjeńŔin}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 sekunda|$1 sekundÅŗe|$1 sekundy|$1 sekundow}}",
+ "timedmedia-reset": "Překodowanje wrĆ³Ä‡o stajić",
+ "timedmedia-reset-confirm": "WrĆ³Ä‡ostajenje tutoho překodowanja wotstroni eksistowacu dataju (jeli tajka eksistuje), a budÅŗe překodowanje znowa čakanskemu rynčkej přidawać. Nowe překodowanje budÅŗe někotry čas trać.<br /><br />\nChceÅ” woprawdÅŗe pokročować?",
+ "timedmedia-reset-error": "Zmylk při wrĆ³Ä‡ostajenju překodowanja.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Å½Ć³rło ($1)",
+ "timedmedia-source-file-desc": "Originalna dataja $1, $2 x $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Originalna $1-dataja ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Ogg-widejo z niskej Ŕěrokosću pasma (160p)",
+ "timedmedia-derivative-desc-360p.ogv": "Ogg-widejo (360p), kotrež da so přez Web přenjesć",
+ "timedmedia-derivative-desc-480p.ogv": "Ogg-widejo (480p), kotrež da so přez Web přenjesć",
+ "timedmedia-derivative-desc-720p.ogv": "Sćahujomne Ogg-widejo wysokeje kwality (720p)",
+ "timedmedia-derivative-desc-160p.webm": "WebM-widejo (160p), kotrež da so přez Web přenjesć",
+ "timedmedia-derivative-desc-360p.webm": "WebM-widejo (360p), kotrež da so přez Web přenjesć",
+ "timedmedia-derivative-desc-480p.webm": "WebM-widejo (480p), kotrež da so přez Web přenjesć",
+ "timedmedia-derivative-desc-720p.webm": "Sćahujomna WebM-dataja wysokeje kwality (720p)",
+ "timedmedia-derivative-desc-320p.mp4": "Gratapřećelny MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "MP4-dataja, kotraž da so přez Web přenjesć",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 w HD-kwaliće (720P)",
+ "timedmedia-subtitle-new": "Nowy přełožk wutworić abo eksistowacy wobdÅŗěłać",
+ "timedmedia-subtitle-new-desc": "Wubjer rěč a klikń na tÅ‚Ć³Äatko '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "W porjadku",
+ "timedmedia-subtitle-language": "$1 ($2) podtitule",
+ "timedmedia-subtitle-no-video": "Widejo zwjazane z aktuelnej stronu podtitulow njeje",
+ "timedmedia-subtitle-no-subtitles": "Tuchwilu podtitule w $1 zu tute widejo njejsu, mĆ³Å¾eÅ” [{{fullurl:{{FULLPAGENAME}}|action=edit}} tutu stronu wobdÅŗěłać], zo by je přidał",
+ "timedmedia-subtitle-remote": "timedText za tutu dataju je na $1",
+ "timedmedia-subtitle-remote-link": "MĆ³Å¾eÅ” sej [$1 wopisansku stronu] za tutu dataja na $2 wobhladać",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 widejo|$1 wideji|$1 wideja|$1 widejow}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg-widejo|$1 Ogg-wideji|$1 Ogg-wideja|$1 Ogg-widejow}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM-widejo|$1 WebM-wideji|$1 WebM-wideja|$1 WebM-widejow}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 překodowanje|$1 překodowani|$1 překodowanja|$1 překodowanjow}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 běžne překodowanje|$1 běžnej překodowani|$1 běžne překodowanja|$1 běžnych překodowanjow}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 překodowanje|$1 překodowani|$1 překodowanja|$1 překodowanjow}} w čakanskim rynku",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 zwrěsćene překodowanje|$1 zwrěsćenej překodowani|$1 zwrěsćene překodowanja|$1 zwrěsćenych překodowanjow}}",
+ "timedmedia-file": "Dataja"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ht.json b/extensions/TimedMediaHandler/i18n/ht.json
new file mode 100644
index 00000000..54b45469
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ht.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Tisave"
+ ]
+ },
+ "timedmedia-no-player-js": "Eskize, men swa JavaScript navigatĆØ ou deyaktive oswa li pa gen okenn mwayen pou ouvri fichye sa a.<br />\nOu ka <a href=\"$1\">telechaje fichye a</a> oswa <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">chĆØche yon lojisyĆØl</a> pou ouvri fichye a nan navigatĆØ ou.",
+ "timedmedia-source-file": "Referans $1"
+}
diff --git a/extensions/TimedMediaHandler/i18n/hu.json b/extensions/TimedMediaHandler/i18n/hu.json
new file mode 100644
index 00000000..dbe3df87
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/hu.json
@@ -0,0 +1,37 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dani",
+ "Glanthor Reviol",
+ "Tgr",
+ "Csega",
+ "Samat",
+ "Dj"
+ ]
+ },
+ "timedmedia-desc": "JavaScript nyelven Ć­rt lejĆ”tszĆ³ Ogg Theora Ć©s Vorbis fĆ”jlokhoz",
+ "timedmedia-ogg-short-audio": "Ogg $1 hangfƔjl, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 videofƔjl, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 mƩdiafƔjl, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 hangfƔjl, hossza: $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 videĆ³fĆ”jl, hossza $2, $4Ɨ$5 kĆ©ppont, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg egyesĆ­tett audiĆ³- Ć©s videĆ³fĆ”jl, $1, hossz: $2, $4Ɨ$5 kĆ©ppont, $3 ƶsszesen",
+ "timedmedia-ogg-long-general": "Ogg mƩdiafƔjl, hossza: $2, $3",
+ "timedmedia-ogg-long-error": "ƉrvĆ©nytelen ogg fĆ”jl: $1",
+ "timedmedia-no-player-js": "SajnĆ”ljuk, a bƶngĆ©sződben vagy le van tiltva a JavaScript, vagy nincs egyetlen tĆ”mogatott lejĆ”tszĆ³ja sem.<br />\n<a href=\"$1\">Letƶltheted a klipet</a>, vagy <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">letƶlthetsz egy lejĆ”tszĆ³t</a> a bƶngĆ©szőben valĆ³ megtekintĆ©shez.",
+ "timedmedia-more": "TovƔbb...",
+ "timedmedia-dismiss": "BezƔrƔs",
+ "timedmedia-download": "FƔjl letƶltƩse",
+ "timedmedia-play-media": "MƩdia lejƔtszƔsa",
+ "timedmedia-desc-link": "FĆ”jlinformĆ”ciĆ³k",
+ "timedmedia-oggThumb-version": "Az OggHandlerhez $1 vagy kĆ©sőbbi verziĆ³jĆŗ oggThumb szĆ¼ksĆ©ges.",
+ "timedmedia-oggThumb-failed": "Az oggThumb nem tudta elkƩszƭteni a bƩlyegkƩpet.",
+ "timedmedia-source-file": "ForrƔs ($1)",
+ "timedmedia-source-file-desc": "Eredeti $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Eredeti $1 fƔjl ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Alacsony sĆ”vszĆ©lessĆ©gű Ogg videĆ³ (160P)",
+ "timedmedia-derivative-desc-720p.ogv": "Magas minősĆ©gű, letƶlthető Ogg videĆ³ (720P)",
+ "timedmedia-derivative-desc-720p.webm": "Magas minősĆ©gű, letƶlthető WebM (720P)",
+ "right-transcode-status": "[[Special:TimedMediaHandler|a legutĆ³bbi Ć”tkĆ³dolĆ”si esemĆ©nyek informĆ”ciĆ³inak]] megtekintĆ©se",
+ "orphanedtimedtext": "Ɓrva TimedText lapok"
+}
diff --git a/extensions/TimedMediaHandler/i18n/hy.json b/extensions/TimedMediaHandler/i18n/hy.json
new file mode 100644
index 00000000..41aa6004
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/hy.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Xelgen",
+ "Vahe Gharakhanyan"
+ ]
+ },
+ "timedmedia-no-player-js": "Õ‘Õ”Õ¾Õøք, Õ±Õ„Ö€ Õ¾Õ„Õ¢Õ¤Õ«ÕæÕ”Ö€ÕÆÕ«Õ¹ÕøÖ‚Õ“ Õ”Õ¶Õ»Õ”ÕæÕ¾Õ”Õ® Õ§ JavaScript-ÕØ ÕÆÕ”Õ“ բՔցՔÕÆÕ”ÕµÕøÖ‚Õ“ Õ§ Õ”Õ»Õ”ÕÆցվÕøÕ² Õ¶Õ¾Õ”Õ£Õ”Ö€ÕÆÕ«Õ¹:<br />\nŌ“Õøւք ÕÆÕ”Ö€ÕøÕ² Õ„Ö„ <a href=\"<span class=\" notranslate\"=\"\" translate=\"no\">$1</span>\">Õ¶Õ„Ö€Õ¢Õ„Õ¼Õ¶Õ„Õ¬ ÕæÕ„Õ½Õ”Õ°ÕøÕ¬ÕøÕ¾Õ”ÕÆÕØ</a> ÕÆÕ”Õ“ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">Õ¶Õ¾Õ”Õ£Õ”Ö€ÕÆÕ«Õ¹</a>:",
+ "timedmedia-source-file": "$1 Õ”Õ²Õ¢ÕµÕøւր",
+ "timedmedia-source-audio-file-desc": "ՍÕÆÕ¦Õ¢Õ¶Õ”ÕÆÕ”Õ¶ $1 նիշք ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ia.json b/extensions/TimedMediaHandler/i18n/ia.json
new file mode 100644
index 00000000..a24d1b20
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ia.json
@@ -0,0 +1,92 @@
+{
+ "@metadata": {
+ "authors": [
+ "McDutchie"
+ ]
+ },
+ "timedmedia-desc": "Gestor pro audio, video e texto synchronisate, con supporto del formatos WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "File audio Ogg $1, $2",
+ "timedmedia-ogg-short-video": "File video Ogg $1, $2",
+ "timedmedia-ogg-short-general": "File media Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "File audio Ogg $1, duration $2, $3",
+ "timedmedia-ogg-long-video": "File video Ogg $1, duration $2, $4Ɨ$5 pixel, $3",
+ "timedmedia-ogg-long-multiplexed": "File multiplexate audio/video Ogg, $1, duration $2, $4Ɨ$5 pixel, $3 in total",
+ "timedmedia-ogg-long-general": "File media Ogg, duration $2, $3",
+ "timedmedia-ogg-long-error": "File Ogg invalide: $1",
+ "timedmedia-webm-short-video": "File video WebM $1, $2",
+ "timedmedia-webm-long-video": "File audio/video WebM, $1, longitude $2, $4 Ɨ $5 pixels, $3 in total",
+ "timedmedia-flac-short-audio": "File audio FLAC, $1",
+ "timedmedia-flac-long-audio": "File audio FLAC, durata $1, $2 in total",
+ "timedmedia-wav-short-audio": "File audio WAV, $1",
+ "timedmedia-wav-long-audio": "File audio WAV, durata $1, $2 in total",
+ "timedmedia-wav-pcm-required": "Tu pote solmente incargar PCM (Pulse Code Modulation) WAV.",
+ "timedmedia-mp4-short-video": "File video MP4 $1, $2",
+ "timedmedia-mp4-long-video": "File audio/video MP4 $1, durata $2, dimensiones $4Ā Ć—Ā $5 pixels, $3 in total",
+ "timedmedia-no-player-js": "Pardono, tu systema o ha JavaScript disactivate o non ha un reproductor supportate.<br />\nTu pote <a href=\"$1\">discargar le clip</a> o <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">discargar un reproductor</a> pro reproducer le clip in tu navigator.",
+ "timedmedia-more": "Plusā€¦",
+ "timedmedia-dismiss": "Clauder",
+ "timedmedia-download": "Discargar file",
+ "timedmedia-play-media": "Reproducer multimedia",
+ "timedmedia-desc-link": "A proposito de iste file",
+ "timedmedia-oggThumb-version": "OggHandler require oggThumb version $1 o plus recente.",
+ "timedmedia-oggThumb-failed": "oggThumb ha fallite de crear le miniatura.",
+ "timedmedia-status-header": "Stato de transcodification",
+ "timedmedia-update-status": "Actualisar stato de transcodification",
+ "timedmedia-status": "stato",
+ "timedmedia-status-unknown": "stato incognite",
+ "timedmedia-transcodeinfo": "Description del file transcodificate",
+ "timedmedia-actions": "actiones",
+ "timedmedia-direct-link": "Discargar file transcodificate",
+ "timedmedia-not-ready": "Non preste",
+ "timedmedia-completed-on": "Transcodification de $1 complete",
+ "timedmedia-error-on": "Error in transcodification a $1",
+ "timedmedia-started-transcode": "Le transcodification comenciava $1 retro. $2",
+ "timedmedia-percent-done": "Circa $1% complete",
+ "timedmedia-in-job-queue": "Addite al cauda de actiones $1 retro",
+ "timedmedia-unknown-target-size": "Dimension del destination incognite, $1 codificate",
+ "timedmedia-days": "{{PLURAL:$1|1 die|$1 dies}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 hora|$1 horas}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minuta|$1 minutas}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 secunda|$1 secundas}}",
+ "timedmedia-reset": "Reinitialisar transcodification",
+ "timedmedia-reset-confirm": "Reinitialisar iste transcodification removera tote le files existente (si presente), e illo re-addera le transcodification al cauda de actiones. Le transcodification prendera un tempore. <br /><br />Es tu secur de voler continuar?",
+ "timedmedia-reset-error": "Error durante le reinitialisation del action de transcodification",
+ "timedmedia-source-file": "original $1",
+ "timedmedia-source-file-desc": "File $1 original, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "File $1 original ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Video Ogg a basse largor de banda (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Video Ogg transmissibile per fluxo web (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Video Ogg transmissibile per fluxo web (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Video Ogg discargabile de alte qualitate (720P)",
+ "timedmedia-derivative-desc-160p.webm": "WebM transmissibile per fluxo web (160P)",
+ "timedmedia-derivative-desc-360p.webm": "WebM transmissibile per fluxo web (360P)",
+ "timedmedia-derivative-desc-480p.webm": "WebM transmissibile per fluxo web (480P)",
+ "timedmedia-derivative-desc-720p.webm": "WebM discargabile de alte qualitate (720P)",
+ "timedmedia-derivative-desc-320p.mp4": "MP4 pro dispositivos mobile (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "MP4 transmissibile per fluxo web (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 in qualitate HD (720P)",
+ "timedmedia-subtitle-new": "Crear un nove traduction o modificar le existente",
+ "timedmedia-subtitle-new-desc": "Selige un lingua e preme le button '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Va",
+ "timedmedia-subtitle-language": "$1 ($2) subtitulos",
+ "timedmedia-subtitle-no-video": "Il non ha video associate con le actual pagina de subtitulos",
+ "timedmedia-subtitle-no-subtitles": "Il ha actualmente nulle subtitulos in $1 pro iste video. Tu pote [{{fullurl:{{FULLPAGENAME}}|action=edit}} modificar iste pagina] pro adder los.",
+ "timedmedia-subtitle-remote": "Le subtitulos pro iste file es albergate sur $1",
+ "timedmedia-subtitle-remote-link": "Tu pote [$1 vider le pagina de description] pro iste file sur $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 video|$1 videos}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 video Ogg|$1 videos Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 video WebM|$1 videos WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transcodification|$1 transcodificationes}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 transcodification|$1 transcodificationes}} active",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 transcodification|$1 transcodificationes}} in cauda",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 transcodification|$1 transcodificationes}} fallite",
+ "timedmedia-file": "File",
+ "timedmedia-audios": "{{PLURAL:$1|$1 file audio|$1 files audio}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 file audio Ogg|$1 files audio Ogg}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 file audio FLAC|$1 files audio FLAC}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 file audio WAV|$1 files audio WAV}}",
+ "right-transcode-reset": "Reinitialisar le videos fallite o transcodificate de sorta que illos es re-inserite in le cauda de actiones",
+ "right-transcode-status": "View [[Special:TimedMediaHandler|information sur le activitate currente de transcodification]]",
+ "action-transcode-status": "vider le stato actual de transcodification"
+}
diff --git a/extensions/TimedMediaHandler/i18n/id.json b/extensions/TimedMediaHandler/i18n/id.json
new file mode 100644
index 00000000..48f6cc2a
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/id.json
@@ -0,0 +1,97 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bennylin",
+ "Farras",
+ "Irwangatot",
+ "IvanLanin",
+ "Iwan Novirion",
+ "Rex",
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ"
+ ]
+ },
+ "timedmedia-desc": "Pemroses audio, video, dan teks berwaktu, dengan dukungan format WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Berkas suara $1 ogg, $2",
+ "timedmedia-ogg-short-video": "Berkas video $1 ogg, $2",
+ "timedmedia-ogg-short-general": "Berkas media $1 ogg, $2",
+ "timedmedia-ogg-long-audio": "Berkas suara $1 ogg, panjang $2, $3",
+ "timedmedia-ogg-long-video": "Berkas video $1 ogg, panjang $2, $4Ɨ$5 piksel, $3",
+ "timedmedia-ogg-long-multiplexed": "Berkas audio/video multiplexed ogg, $1, panjang $2, $4Ɨ$5 piksel, $3 keseluruhan",
+ "timedmedia-ogg-long-general": "Berkas media ogg, panjang $2, $3",
+ "timedmedia-ogg-long-error": "Berkas ogg tak valid: $1",
+ "timedmedia-webm-short-video": "Berkas video $1 WebM, $2",
+ "timedmedia-webm-long-video": "Berkas audio/video WebM, $1, lama $2, $4 Ɨ $5 piksel, $3 keseluruhan",
+ "timedmedia-no-player-js": "Maaf, peramban Anda memiliki JavaScript yang dinonaktifkan atau tidak memiliki pemutar media apapun.<br />\nAnda dapat <a href=\"$1\">mengunduh klip</a> atau <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">mengunduh pemutar</a> untuk memutar klip di peramban Anda.",
+ "timedmedia-more": "Lainnya...",
+ "timedmedia-dismiss": "Tutup",
+ "timedmedia-download": "Unduh berkas",
+ "timedmedia-play-media": "Putar media",
+ "timedmedia-desc-link": "Mengenai berkas ini",
+ "timedmedia-oggThumb-version": "OggHandler membutuhkan oggThumb versi $1 atau terbaru.",
+ "timedmedia-oggThumb-failed": "oggThumb gagal membuat miniatur gambar.",
+ "timedmedia-status-header": "Status transkoder",
+ "timedmedia-update-status": "Memperbarui status transkoder",
+ "timedmedia-status": "Status",
+ "timedmedia-status-unknown": "Status tidak diketahui",
+ "timedmedia-transcodeinfo": "Deskripsi turunan transkoder",
+ "timedmedia-actions": "Tindakan",
+ "timedmedia-direct-link": "Unduh turunan",
+ "timedmedia-not-ready": "Belum siap",
+ "timedmedia-completed-on": "Transkoder komplit $1",
+ "timedmedia-error-on": "Kesalahan dalam transkoder pada $1 .",
+ "timedmedia-started-transcode": "Transkoder mulai $1 yang lalu. $2",
+ "timedmedia-percent-done": "Sekitar $1% selesai",
+ "timedmedia-days": "{{PLURAL:$1|$1 hari}}",
+ "timedmedia-hours": "{{PLURAL:$1|$1 jam}}",
+ "timedmedia-minutes": "{{PLURAL:$1|$1 menit}}",
+ "timedmedia-seconds": "{{PLURAL:$1|$1 detik}}",
+ "timedmedia-reset": "Reset transkoder",
+ "timedmedia-ogg": "Ogg",
+ "timedmedia-webm": "WebM",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Sumber $1",
+ "timedmedia-source-file-desc": "$1 asli, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Berkas ($2) asli $1",
+ "timedmedia-derivative-160p.ogv": "Ogg 160p",
+ "timedmedia-derivative-desc-160p.ogv": "Video Ogg lebar pita rendah (160P)",
+ "timedmedia-derivative-360p.ogv": "Ogg 360p",
+ "timedmedia-derivative-desc-360p.ogv": "Video Ogg aliran web (360P)",
+ "timedmedia-derivative-480p.ogv": "Ogg 480p",
+ "timedmedia-derivative-desc-480p.ogv": "Video Ogg aliran web (480P)",
+ "timedmedia-derivative-720p.ogv": "Ogg 720p",
+ "timedmedia-derivative-desc-720p.ogv": "Video Ogg unduhan berkualitas tinggi (720P)",
+ "timedmedia-derivative-160p.webm": "WebM 160p",
+ "timedmedia-derivative-360p.webm": "WebM 360p",
+ "timedmedia-derivative-desc-360p.webm": "WebM aliran web (360P)",
+ "timedmedia-derivative-480p.webm": "WebM 480p",
+ "timedmedia-derivative-desc-480p.webm": "WebM aliran web (480P)",
+ "timedmedia-derivative-720p.webm": "WebM 720p",
+ "timedmedia-derivative-desc-720p.webm": "WebM unduhan berkualitas tinggi (720P)",
+ "timedmedia-derivative-320p.mp4": "H264 320p",
+ "timedmedia-derivative-480p.mp4": "H264 480p",
+ "timedmedia-derivative-720p.mp4": "H264 720p",
+ "timedmedia-derivative-ogg": "Ogg Vorbis",
+ "timedmedia-derivative-desc-ogg": "Ogg Vorbis",
+ "timedmedia-derivative-opus": "Opus",
+ "timedmedia-derivative-desc-opus": "Opus",
+ "timedmedia-derivative-mp3": "MP3",
+ "timedmedia-derivative-desc-mp3": "MP3",
+ "timedmedia-derivative-m4a": "AAC",
+ "timedmedia-derivative-desc-m4a": "AAC",
+ "timedmedia-subtitle-new-go": "Lanjut",
+ "timedmedia-subtitle-language": "Teks film $1 ($2)",
+ "timedmedia-subtitle-no-video": "Tidak ada video yang terkait dengan halaman subjudul ini",
+ "timedmedia-subtitle-no-subtitles": "Saat ini tidak ada subjudul $1 untuk video ini. Anda dapat [{{fullurl: {{FULLPAGENAME}}|action=edit}} menyunting halaman ini] untuk menambahkannya",
+ "timedmediahandler": "Daftar berkas media",
+ "timedmedia-videos": "{{PLURAL:$1|$1 video}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Video ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 Video WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transkoder}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 transkoder aktif}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 antrian transkoder}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 transkoder rusak}}",
+ "timedmedia-file": "Berkas",
+ "right-transcode-reset": "Reset transkoder rusak ataupun yang tidak sehingga kembali dimasukkan dalam antrian.",
+ "right-transcode-status": "Lihat [[Special:TimedMediaHandler|informasi tentang aktifitas transkoder terkini]]",
+ "action-transcode-status": "lihat status transkoder terkini"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ilo.json b/extensions/TimedMediaHandler/i18n/ilo.json
new file mode 100644
index 00000000..11ce2be8
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ilo.json
@@ -0,0 +1,89 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lam-ang"
+ ]
+ },
+ "timedmedia-desc": "Panagtengngel para iti audio, video ken naorasan a testo, nga adda ti porma a suporta para iti WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Ogg $1 a mangeg a papeles, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 a video a papeles, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 a midia a papeles, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 a mangeg a papeles, kaatiddog $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 a video a papeles, kaatiddog $2, $4 Ɨ $5 a piksel, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg multiplexed nga audio/video a papeles, $1, kaatiddog $2, $4 Ɨ $5 a piksel, $3 amin-amin",
+ "timedmedia-ogg-long-general": "Ogg midia a papeles, kaatiddog $2, $3",
+ "timedmedia-ogg-long-error": "Imbalido nga Ogg a papeles: $1",
+ "timedmedia-webm-short-video": "WebM $1 a video a papeles, $2",
+ "timedmedia-webm-long-video": "WebM nga audio/video a papeles, $1, kaatiddog $2, $4 Ɨ $5 a piksel, $3 amin-amin",
+ "timedmedia-flac-short-audio": "Mangeg a papeles ti FLAC, $1",
+ "timedmedia-flac-long-audio": "Mangeg a papeles ti FLAC, kaatiddog $1, $2 ti amin a dagup",
+ "timedmedia-wav-short-audio": "Mangeg a papeles ti WAV, $1",
+ "timedmedia-wav-long-audio": "Mangeg a papeles ti WAV, kaatiddog $1, $2 ti amin a dagup",
+ "timedmedia-wav-pcm-required": "Mabalinmo laeng ti agikarga ti PCM (Pulse Code Modulation) WAV.",
+ "timedmedia-mp4-short-video": "MP4 $1 a video apapeles, $2",
+ "timedmedia-mp4-long-video": "MP4 nga audio/video a papeles, $1, kaatiddog $2, $4 Ɨ $5 a piksel, $3 amin-amin",
+ "timedmedia-no-player-js": "Pasensia, ti pagbasabasam ket mabalin a nabaldado ti JavaScript wenno awan ti nasuportaran a mangay-ayam.<br />\nMabalinmo ti <a href=\"$1\">agikarga ti sigpit</a> wenno <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">agikarga ti maysa a magay-ayam</a> tapno maay-ayam ti sigpit iti pagbasabasam.",
+ "timedmedia-more": "Adu pay...",
+ "timedmedia-dismiss": "Irikep",
+ "timedmedia-download": "Ikarga ti papeles",
+ "timedmedia-play-media": "Ay-ayamen ti midia",
+ "timedmedia-desc-link": "Maipanggep ti daytoy a papeles",
+ "timedmedia-oggThumb-version": "Ti OggHandler ket masapulna ti oggThumb a bersion ti $1 wenno ti naududi.",
+ "timedmedia-oggThumb-failed": "Napaay ti oggThumb nga agaramid ti imahen.",
+ "timedmedia-status-header": "Kasasaad ti transkodigo",
+ "timedmedia-update-status": "Pabaruen ti kasasaad ti transkodigo",
+ "timedmedia-status": "Kasasaad",
+ "timedmedia-status-unknown": "Di ammo a kasasaad",
+ "timedmedia-transcodeinfo": "Deribatibo a deskripsion ti transkodigo",
+ "timedmedia-actions": "Dagiti aramid",
+ "timedmedia-direct-link": "Ikarga ti deribatibo",
+ "timedmedia-not-ready": "Saan pay a sisasagana",
+ "timedmedia-completed-on": "Nakompleto ti transkodigo $1",
+ "timedmedia-error-on": "Biddut iti transkodigo iti $1",
+ "timedmedia-started-transcode": "Ti transkodigo ket nairugi di $1. $2",
+ "timedmedia-percent-done": "Agarup a $1% ti nalapasen",
+ "timedmedia-in-job-queue": "Nagnayon idiay Pagurayan ti maaramid idi $1",
+ "timedmedia-unknown-target-size": "Di ammo a kadakkel ti puntaan, $1 ti nakodigo",
+ "timedmedia-days": "{{PLURAL:$1|1 nga aldaw|$1 nga al-aldaw}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 nga oras|$1 nga or-oras}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 a minuto|$1 a minutos}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 a segundo|$1 a seg-segundo}}",
+ "timedmedia-reset": "Iyasentar manen ti transkodigo",
+ "timedmedia-reset-confirm": "Ti papangyasentar ti daytoy a transkodigo ket mangikkat ti aniaman nga adda a papeles (no adda), ket manginayonto manen ti transkodigo iti pagurayan ti maaramid. <br /><br />\nSeguradoka kadi a kayatmo ti tumuloy?",
+ "timedmedia-reset-error": "Biddut ti panangiyasentar manen ti transkodigo a maaramid.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 taudan",
+ "timedmedia-source-file-desc": "Kasisigud a $1 a papeles, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Kasisigud a $1 a papeles ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Ababa ti bandwidth a video ti Ogg (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Maiwaragawag ti web a video ti Ogg (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Maiwaragawag ti web a video ti Ogg (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Maikarga a nangato ti kalidadna a video ti Ogg (720P)",
+ "timedmedia-derivative-desc-160p.webm": "Maiwaragawag ti web a WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "Maiwaragawag ti web a WebM (360P)",
+ "timedmedia-derivative-desc-480p.webm": "Maiwaragawag ti web a WebM (480P)",
+ "timedmedia-derivative-desc-720p.webm": "Maikarga a nangato ti kalidadna a WebM (720)",
+ "timedmedia-derivative-desc-320p.mp4": "Mannakigayyem a ramit ti MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "Maiwaragawag ti web a Mp4 (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "HD ti kalidadna a MP4 (720P)",
+ "timedmedia-subtitle-new": "Agpartuat ti baro a panagipatarus wenno urnosen ti adda",
+ "timedmedia-subtitle-new-desc": "Agpili ti pagsasao ken pinduten ti '''{{int:Timedmedia-subtitle-new-go}}''' a buton",
+ "timedmedia-subtitle-new-go": "Inkan",
+ "timedmedia-subtitle-language": "Dagiti $1 ($2) a subtitulo",
+ "timedmedia-subtitle-no-video": "Awan ti video a mainanig iti agdama a subtitulo ti panid",
+ "timedmedia-subtitle-no-subtitles": "Awan dagiti agdama asubtitulo iti $1 para iti daytoy a video, mabalinmo ti [{{fullurl:{{FULLPAGENAME}}|action=edit}} agurnods ti daytoy a panid] tapno makanayonka kaniada",
+ "timedmedia-subtitle-remote": "Ti naorasan a testo para iti daytoy a papeles ket nanisangaili idiay $1",
+ "timedmedia-subtitle-remote-link": "Mabalinmo a [$1 kitaen ti deskripsion ti panid] para iti daytoy a papeles idiay $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 a video|dagiti $1 a video}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 nga Ogg a video|dagiti $1 nga Ogg a video}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 a WebM a video|dagiti $1 a WebM a video}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 a transkodigo|dagiti $1 a transkodigo}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 nga agtartaray a transkodigo|dagiti $1 nga agtartaray a transkodigo}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 a naiyur-uray a transkodigo|dagiti $1 a naiyur-uray a transkodigo}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 a napaay a transkodigo|dagiti $1 a napaay a transkodigo}}",
+ "timedmedia-file": "Papeles",
+ "right-transcode-reset": "Iyasentar manen ti napaay wenno dagiti naitranskodigo a video tapno maisengngatda manen ti pagurayan ti maaramid",
+ "right-transcode-status": "Kitaen ti [[Special:TimedMediaHandler|pakaammo a maipanggep ti agdama a tignay ti transkodigo]]",
+ "action-transcode-status": "kitaen ti agdama a kasasaad ti transkodigo"
+}
diff --git a/extensions/TimedMediaHandler/i18n/io.json b/extensions/TimedMediaHandler/i18n/io.json
new file mode 100644
index 00000000..8977382c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/io.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Malafaya"
+ ]
+ },
+ "timedmedia-ogg-long-error": "Ne-valida Ogg-arkivo: $1",
+ "timedmedia-more": "Plusā€¦",
+ "timedmedia-dismiss": "Klozar",
+ "timedmedia-desc-link": "Pri ca arkivo"
+}
diff --git a/extensions/TimedMediaHandler/i18n/is.json b/extensions/TimedMediaHandler/i18n/is.json
new file mode 100644
index 00000000..3188925c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/is.json
@@ -0,0 +1,60 @@
+{
+ "@metadata": {
+ "authors": [
+ "S.Ɩrvarr.S",
+ "SnƦvar",
+ "Spacebirdy"
+ ]
+ },
+ "timedmedia-desc": "Rekill fyrir hljĆ³Ć°, myndbƶnd og texta myndbanda meĆ° stuĆ°ningi viĆ° skrĆ”arsniĆ°in WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Ogg $1 hljĆ³Ć°skrĆ”, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 myndbandskrĆ”, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 margmiĆ°lunarskrĆ”, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 hljĆ³Ć°skrĆ”, lengd $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 myndbandskrĆ”, lengd $2, $4Ɨ$5 dĆ­lar, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg myndbandaskrĆ”, $1, lengd $2, $4 Ɨ $5 dĆ­lar, $3 samanlagt",
+ "timedmedia-ogg-long-general": "Ogg margmiĆ°lunarskrĆ”, lengd $2, $3",
+ "timedmedia-ogg-long-error": "Ɠgild Ogg skrĆ”: $1",
+ "timedmedia-webm-short-video": "WebM $1 myndbandskrĆ”, $2",
+ "timedmedia-webm-long-video": "WebM myndbandaskrĆ”, $1, lengd $2, $4 Ɨ $5 dĆ­lar, $3 samanlagt",
+ "timedmedia-mp4-short-video": "MP4 $1 myndbandaskrĆ”, $2",
+ "timedmedia-mp4-long-video": "MP4 myndbandaskrĆ”, $1, lengd $2, $4 Ɨ $5 dĆ­lar, $3 samanlagt",
+ "timedmedia-no-player-js": "ƞvĆ­ miĆ°ur hefur vafrinn Ć¾inn annaĆ°hvort Ć³virkan JavaScript eĆ°a engan studdann spilara.<br />\nƞĆŗ getur <a href=\"$1\">hlaĆ°iĆ° niĆ°ur skrĆ”nni</a> eĆ°a <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">hlaĆ°iĆ° niĆ°ur spilara</a> til Ć¾ess aĆ° spila skrĆ”nna Ć­ vafranum.",
+ "timedmedia-more": "Meira...",
+ "timedmedia-dismiss": "Loka",
+ "timedmedia-download": "SƦkja skrƔ",
+ "timedmedia-play-media": "Spila margmiĆ°lunarskrĆ”",
+ "timedmedia-desc-link": "Um Ć¾essa skrĆ”",
+ "timedmedia-oggThumb-version": "OggHandler Ć¾arfnast oggThumb ĆŗtgĆ”fu $1 eĆ°a nĆ½rri.",
+ "timedmedia-oggThumb-failed": "oggThumb mistĆ³kst aĆ° bĆŗa til smĆ”mynd.",
+ "timedmedia-status": "StaĆ°a",
+ "timedmedia-actions": "AĆ°gerĆ°ir",
+ "timedmedia-direct-link": "SƦkja eftirgerư",
+ "timedmedia-not-ready": "Ekki tilbĆŗin",
+ "timedmedia-percent-done": "Um $1% lokiĆ°",
+ "timedmedia-unknown-target-size": "Ć“Ć¾ekkt markstƦrĆ°, $1 kĆ³Ć°aĆ°",
+ "timedmedia-days": "$1 {{PLURAL:$1|dagur|dagar}}",
+ "timedmedia-hours": "$1 {{PLURAL:$1|klukkutĆ­mi|klukkutĆ­mar}}",
+ "timedmedia-minutes": "$1 {{PLURAL:$1|mĆ­nĆŗta|mĆ­nĆŗtur}}",
+ "timedmedia-seconds": "$1 {{PLURAL:$1|sekĆŗnda|sekĆŗndur}}",
+ "timedmedia-source-file": "$1 uppruni",
+ "timedmedia-source-file-desc": "Upphafleg $1 skrĆ”, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Upphafleg $1 skrĆ” ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Ogg myndband fyrir litla bandbreidd (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Ogg myndbands streymi (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Ogg myndbands streymi (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "HƔgƦưa niưurhalanlegt Ogg myndband (720P)",
+ "timedmedia-derivative-desc-160p.webm": "WebM myndbands streymi (160P)",
+ "timedmedia-derivative-desc-360p.webm": "WebM myndbands streymi (360P)",
+ "timedmedia-derivative-desc-480p.webm": "WebM myndbands streymi (480P)",
+ "timedmedia-derivative-desc-720p.webm": "HƔgƦưa niưurhalanlegt WebM myndband (720P)",
+ "timedmedia-derivative-desc-480p.mp4": "MP4 myndbands streymi (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "HƔskerpu MP4 (720P)",
+ "timedmedia-subtitle-new-desc": "Veldu tungumƔliư og smelltu Ɣ '''{{int:Timedmedia-subtitle-new-go}}''' takkann",
+ "timedmedia-subtitle-new-go": "Ɓfram",
+ "timedmedia-subtitle-no-video": "Ekkert myndband tengist Ć¾essum myndbanda texta",
+ "timedmedia-videos": "{{PLURAL:$1|$1 myndband|$1 myndbƶnd}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg myndband|$1 Ogg myndbƶnd}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM myndband|$1 WebM myndbƶnd}}",
+ "timedmedia-file": "SkrĆ”"
+}
diff --git a/extensions/TimedMediaHandler/i18n/it.json b/extensions/TimedMediaHandler/i18n/it.json
new file mode 100644
index 00000000..fe37c8b2
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/it.json
@@ -0,0 +1,108 @@
+{
+ "@metadata": {
+ "authors": [
+ ".anaconda",
+ "Beta16",
+ "BrokenArrow",
+ "Darth Kule",
+ "F. Cosoleto",
+ "Gianfranco",
+ "Raoli",
+ "Peg60"
+ ]
+ },
+ "timedmedia-desc": "Gestore per i file audio, video e con i sottotitoli; formati supportati: WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "File audio Ogg $1, $2",
+ "timedmedia-ogg-short-video": "File video Ogg $1, $2",
+ "timedmedia-ogg-short-general": "File multimediale Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "File audio Ogg $1, durata $2, $3",
+ "timedmedia-ogg-long-video": "File video Ogg $1, durata $2, dimensioni $4Ɨ$5 pixel, $3",
+ "timedmedia-ogg-long-multiplexed": "File audio/video multiplexed Ogg $1, durata $2, dimensioni $4Ɨ$5 pixel, complessivamente $3",
+ "timedmedia-ogg-long-general": "File multimediale Ogg, durata $2, $3",
+ "timedmedia-ogg-long-error": "File ogg non valido: $1",
+ "timedmedia-ogg-long-no-streams": "File multimediale Ogg. Attenzione: non ĆØ stato riconosciuto alcuno dei codec usati in questo file.",
+ "timedmedia-webm-short-video": "File video WebM $1, $2",
+ "timedmedia-webm-long-video": "File audio/video WebM $1, durata $2, dimensioni $4Ɨ$5 pixel, complessivamente $3",
+ "timedmedia-flac-short-audio": "File audio FLAC, $1",
+ "timedmedia-flac-long-audio": "File audio FLAC, durata $1, complessivamente $2",
+ "timedmedia-wav-short-audio": "File audio WAV, $1",
+ "timedmedia-wav-long-audio": "File audio WAV, durata $1, complessivamente $2",
+ "timedmedia-wav-pcm-required": "Puoi caricare solo PCM (Pulse Code Modulation) WAV.",
+ "timedmedia-mp4-short-video": "File video MP4 $1, $2",
+ "timedmedia-mp4-long-video": "File audio/video MP4 $1, durata $2, dimensioni $4Ɨ$5 pixel, complessivamente $3",
+ "timedmedia-no-player-js": "Si sta utilizzando un browser che ha JavaScript disattivato oppure non ha alcun riproduttore supportato.<br />\nƈ possibile <a href=\"$1\">scaricare il clip multimediale</a> o <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">un riproduttore</a> per riprodurre il clip nel proprio browser.",
+ "timedmedia-more": "Altro...",
+ "timedmedia-dismiss": "Chiudi",
+ "timedmedia-download": "Scarica il file",
+ "timedmedia-play-media": "Riproduci file multimediale",
+ "timedmedia-desc-link": "Informazioni su questo file",
+ "timedmedia-oggThumb-version": "OggHandler richiede la versione $1 o superiore di oggThumb.",
+ "timedmedia-oggThumb-failed": "oggThumb non ĆØ riuscito a creare la miniatura.",
+ "timedmedia-status-header": "Stato transcodifica",
+ "timedmedia-update-status": "Aggiorna stato transcodifica",
+ "timedmedia-status": "Stato",
+ "timedmedia-status-unknown": "Stato sconosciuto",
+ "timedmedia-transcodeinfo": "Formato",
+ "timedmedia-actions": "Azioni",
+ "timedmedia-direct-link": "Scarica",
+ "timedmedia-not-ready": "Non pronto",
+ "timedmedia-completed-on": "Completato $1",
+ "timedmedia-error-on": "Errore il $1",
+ "timedmedia-started-transcode": "Iniziato $1 fa. $2",
+ "timedmedia-percent-done": "$1% circa completato",
+ "timedmedia-in-job-queue": "Aggiunto alla coda di lavoro $1 fa",
+ "timedmedia-unknown-target-size": "Dimensioni di destinazione sconosciuta, $1 codificato",
+ "timedmedia-days": "{{PLURAL:$1|1 giorno|$1 giorni}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 ora|$1 ore}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minuto|$1 minuti}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 secondo|$1 secondi}}",
+ "timedmedia-reset": "Resetta transcodifica",
+ "timedmedia-reset-confirm": "Resettando questa transcodifica tutti i file esistenti (se presenti) saranno cancellati e la transcodifica sarĆ  nuovamente aggiunta alla coda di lavoro. Ci vorrĆ  qualche tempo per rieseguire la transcodifica. <br /><br />\nContinuare?",
+ "timedmedia-reset-error": "Errore nel resettaggio della transcodifica.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Fonte $1",
+ "timedmedia-source-file-desc": "File originale $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "File originale $1 ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Video Ogg a bassa larghezza di banda (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Video Ogg trasmettibile in streaming via Web (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Video Ogg trasmettibile in streaming via Web (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Video Ogg scaricabile in alta qualitĆ  (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "Video Ogg scaricabile in Full HD (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "WebM trasmettibile in streaming via Web (160P)",
+ "timedmedia-derivative-desc-360p.webm": "WebM trasmettibile in streaming via Web (360P)",
+ "timedmedia-derivative-desc-480p.webm": "WebM trasmettibile in streaming via Web (480P)",
+ "timedmedia-derivative-desc-720p.webm": "WebM scaricabile in alta qualitĆ  (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "WebM scaricabile in Full HD (1080P)",
+ "timedmedia-derivative-desc-320p.mp4": "MP4 per dispositivi compatibili (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "MP4 trasmettibile in streaming via Web (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 in qualitĆ  HD (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "MP4 di qualitĆ  Full HD (1080P)",
+ "timedmedia-subtitle-new": "Creare una nuova traduzione o modificare esistenti",
+ "timedmedia-subtitle-new-desc": "Seleziona la lingua e premi il pulsante '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Vai",
+ "timedmedia-subtitle-language": "$1 ($2) sottotitoli",
+ "timedmedia-subtitle-no-video": "Non non c'ĆØ nessun video associato all'attuale pagina dei sottotitoli",
+ "timedmedia-subtitle-no-subtitles": "Non ci sono al momento sottotitoli in $1 per questo video, ĆØ possibile [{{fullurl:{{FULLPAGENAME}}|action=edit}} modificare questa pagina] per aggiungerli",
+ "timedmedia-subtitle-remote": "I sottotitoli per questo file sono ospitati su $1",
+ "timedmedia-subtitle-remote-link": "Puoi vedere la [$1 pagina di descrizione] per questo file su $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 video}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 video Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 video WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transcodifica|$1 transcodifiche}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 transcodifica|$1 transcodifiche}} in esecuzione",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 transcodifica|$1 transcodifiche}} in coda",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 transcodifica fallita|$1 transcodifiche fallite}}",
+ "timedmedia-file": "File",
+ "timedmedia-audios": "{{PLURAL:$1|$1 file audio}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 file audio Ogg}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 file audio FLAC}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 file audio WAV}}",
+ "right-transcode-reset": "Reimposta i video difettosi o transcodificati cosƬ che possano essere inclusi nuovamente in coda di lavoro.",
+ "right-transcode-status": "Visualizza [[Special:TimedMediaHandler|informazioni sull'attuale attivitĆ  di transcodifica]]",
+ "action-transcode-status": "visualizzare l'attuale stato della transcodifica",
+ "orphanedtimedtext": "Pagine sottotitoli orfane",
+ "orphanedtimedtext-summary": "Elenco di pagine [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] che non hanno un file corrispondente.",
+ "orphanedtimedtext-unsupported": "Questa pagina speciale ĆØ supportata solo su database MySQL.",
+ "orphanedtimedtext-notimedtext": "TimedText non ĆØ abilitato su questo wiki."
+}
diff --git a/extensions/TimedMediaHandler/i18n/ja.json b/extensions/TimedMediaHandler/i18n/ja.json
new file mode 100644
index 00000000..291a5224
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ja.json
@@ -0,0 +1,91 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aotake",
+ "Fryed-peach",
+ "JtFuruhata",
+ "Kahusi",
+ "Shirayuki",
+ "é’å­å®ˆę­Œ",
+ "Otokoume"
+ ]
+ },
+ "timedmedia-desc": "WebM态Ogg Theora态Vorbis态srt å½¢å¼ć«åƾåæœć—ćŸć€å‹•ē”»ć€éŸ³å£°ć€å­—å¹•ć®ćƒćƒ³ćƒ‰ćƒ©ćƒ¼",
+ "timedmedia-ogg-short-audio": "Ogg $1 éŸ³å£°ćƒ•ć‚”ć‚¤ćƒ«ć€$2",
+ "timedmedia-ogg-short-video": "Ogg $1 動ē”»ćƒ•ć‚”ć‚¤ćƒ«ć€$2",
+ "timedmedia-ogg-short-general": "Ogg $1 ćƒ”ćƒ‡ć‚£ć‚¢ćƒ•ć‚”ć‚¤ćƒ«ć€$2",
+ "timedmedia-ogg-long-audio": "Ogg $1 éŸ³å£°ćƒ•ć‚”ć‚¤ćƒ«ć€é•·ć• $2态$3",
+ "timedmedia-ogg-long-video": "Ogg $1 動ē”»ćƒ•ć‚”ć‚¤ćƒ«ć€é•·ć• $2态$4 Ɨ $5 惔ć‚Æć‚»ćƒ«ć€$3",
+ "timedmedia-ogg-long-multiplexed": "Ogg 多重音声/動ē”»ćƒ•ć‚”ć‚¤ćƒ«ć€$1态長恕 $2态$4 Ɨ $5 惔ć‚Æć‚»ćƒ«ć€å…Øä½“ć§ $3",
+ "timedmedia-ogg-long-general": "Ogg ćƒ”ćƒ‡ć‚£ć‚¢ćƒ•ć‚”ć‚¤ćƒ«ć€é•·ć• $2态$3",
+ "timedmedia-ogg-long-error": "ē„”効ćŖ Ogg ćƒ•ć‚”ć‚¤ćƒ«: $1",
+ "timedmedia-ogg-long-no-streams": "Ogg ćƒ”ćƒ‡ć‚£ć‚¢ ćƒ•ć‚”ć‚¤ćƒ«ć€‚č­¦å‘Š: ć“ć®ćƒ•ć‚”ć‚¤ćƒ«ć§ä½æē”Øć•ć‚Œć¦ć„ć‚‹ć©ć®ć‚³ćƒ¼ćƒ‡ćƒƒć‚Æ悂čŖč­˜ć§ćć¾ć›ć‚“ć§ć—ćŸć€‚",
+ "timedmedia-webm-short-video": "WebM $1 動ē”»ćƒ•ć‚”ć‚¤ćƒ«ć€$2",
+ "timedmedia-webm-long-video": "WebM 音声/動ē”»ćƒ•ć‚”ć‚¤ćƒ«ć€$1态長恕 $2态$4 Ɨ $5 惔ć‚Æć‚»ćƒ«ć€å…Øä½“ć§ $3",
+ "timedmedia-flac-short-audio": "FLAC éŸ³å£°ćƒ•ć‚”ć‚¤ćƒ«ć€$1",
+ "timedmedia-flac-long-audio": "FLAC éŸ³å£°ćƒ•ć‚”ć‚¤ćƒ«ć€é•·ć• $1态å…Øä½“ć§ $2",
+ "timedmedia-wav-short-audio": "WAV éŸ³å£°ćƒ•ć‚”ć‚¤ćƒ«ć€$1",
+ "timedmedia-wav-long-audio": "WAV éŸ³å£°ćƒ•ć‚”ć‚¤ćƒ«ć€é•·ć• $1态å…Øä½“ć§ $2",
+ "timedmedia-wav-pcm-required": "ć‚¢ćƒƒćƒ—ćƒ­ćƒ¼ćƒ‰ć§ćć‚‹ć®ćÆ PCM (ćƒ‘ćƒ«ć‚¹ē¬¦å·å¤‰čŖæ) WAV 恮ćæ恧恙怂",
+ "timedmedia-mp4-short-video": "MP4 $1 動ē”»ćƒ•ć‚”ć‚¤ćƒ«ć€$2",
+ "timedmedia-mp4-long-video": "MP4 音声/動ē”»ćƒ•ć‚”ć‚¤ćƒ«ć€$1态長恕 $2态$4 Ɨ $5 惔ć‚Æć‚»ćƒ«ć€å…Øä½“ć§ $3",
+ "timedmedia-no-player-js": "ē”³ć—čØ³ć‚ć‚Šć¾ć›ć‚“ćŒć€ć‚ćŖćŸć®ćƒ–ćƒ©ć‚¦ć‚¶ćƒ¼ć§ćÆJavaScript恌ē„”åŠ¹ć«ćŖć£ć¦ć„ć‚‹ć‹ć€åƾåæœć—ć¦ć„ć‚‹ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼ćŒć‚ć‚Šć¾ć›ć‚“ć€‚<br />\n再ē”Ÿć™ć‚‹ć«ćÆ态<a href=\"$1\">ć‚ÆćƒŖćƒƒćƒ—ć‚’ćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰</a>恙悋恋态<a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ćƒ—ćƒ¬ćƒ¼ćƒ¤ćƒ¼ć‚’ćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰</a>恙悋åæ…č¦ćŒć‚ć‚Šć¾ć™ć€‚",
+ "timedmedia-more": "ćć®ä»–ā€¦",
+ "timedmedia-dismiss": "閉恘悋",
+ "timedmedia-download": "ćƒ•ć‚”ć‚¤ćƒ«ć‚’ćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰ć™ć‚‹",
+ "timedmedia-play-media": "ćƒ”ćƒ‡ć‚£ć‚¢ć‚’å†ē”Ÿć™ć‚‹",
+ "timedmedia-desc-link": "ćƒ•ć‚”ć‚¤ćƒ«ć®č©³ē“°",
+ "timedmedia-oggThumb-version": "OggHandler 恫ćÆ oggThumb ćƒćƒ¼ć‚øćƒ§ćƒ³ $1 ć¾ćŸćÆćć‚Œä»„é™ćŒåæ…要恧恙怂",
+ "timedmedia-oggThumb-failed": "oggThumb ć«ć‚ˆć‚‹ć‚µćƒ ćƒć‚¤ćƒ«ä½œęˆć«å¤±ę•—ć—ć¾ć—ćŸć€‚",
+ "timedmedia-status": "ēŠ¶ę…‹",
+ "timedmedia-status-unknown": "äøę˜ŽćŖēŠ¶ę…‹",
+ "timedmedia-transcodebitrate": "ćƒ“ćƒƒćƒˆćƒ¬ćƒ¼ćƒˆ",
+ "timedmedia-transcodeduration": "ć‚Øćƒ³ć‚³ćƒ¼ćƒ‰ę™‚é–“",
+ "timedmedia-transcodeinfo": "形式",
+ "timedmedia-actions": "ę“ä½œ",
+ "timedmedia-direct-link": "ćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰",
+ "timedmedia-not-ready": "ęŗ–å‚™ćŒć§ćć¦ć„ć¾ć›ć‚“",
+ "timedmedia-error-on": "$1 恧恮ć‚Øćƒ©ćƒ¼",
+ "timedmedia-percent-done": "ē“„ $1% 完äŗ†",
+ "timedmedia-in-job-queue": "$1å‰ć«ć‚ø惧惖 ć‚­ćƒ„ćƒ¼ć«čæ½åŠ ć•ć‚Œć¾ć—ćŸ",
+ "timedmedia-days": "{{PLURAL:$1|$1 ę—„}}",
+ "timedmedia-hours": "{{PLURAL:$1|$1 Ꙃ間}}",
+ "timedmedia-minutes": "{{PLURAL:$1|$1 分}}",
+ "timedmedia-seconds": "{{PLURAL:$1|$1 ē§’}}",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 ć‚½ćƒ¼ć‚¹",
+ "timedmedia-source-file-desc": "ć‚ŖćƒŖć‚øćƒŠćƒ« $1 ćƒ•ć‚”ć‚¤ćƒ«ć€$2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "ć‚ŖćƒŖć‚øćƒŠćƒ« $1 ćƒ•ć‚”ć‚¤ćƒ« ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "低åøÆ域 Ogg 動ē”» (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "ć‚¦ć‚§ćƒ– ć‚¹ćƒˆćƒŖćƒ¼ćƒŸćƒ³ć‚°åÆčƒ½ Ogg 動ē”» (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "ć‚¦ć‚§ćƒ– ć‚¹ćƒˆćƒŖćƒ¼ćƒŸćƒ³ć‚°åÆčƒ½ Ogg 動ē”» (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "高品č³Ŗćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰åÆčƒ½ Ogg 動ē”» (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "ćƒ•ćƒ« HD ćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰åÆčƒ½ Ogg 動ē”» (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "ć‚¦ć‚§ćƒ– ć‚¹ćƒˆćƒŖćƒ¼ćƒŸćƒ³ć‚°åÆčƒ½ WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "ć‚¦ć‚§ćƒ– ć‚¹ćƒˆćƒŖćƒ¼ćƒŸćƒ³ć‚°åÆčƒ½ WebM (360P)",
+ "timedmedia-derivative-desc-480p.webm": "ć‚¦ć‚§ćƒ– ć‚¹ćƒˆćƒŖćƒ¼ćƒŸćƒ³ć‚°åÆčƒ½ WebM (480P)",
+ "timedmedia-derivative-desc-720p.webm": "高品č³Ŗćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰åÆčƒ½ WebM (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "ćƒ•ćƒ« HD ćƒ€ć‚¦ćƒ³ćƒ­ćƒ¼ćƒ‰åÆčƒ½ WebM (1080P)",
+ "timedmedia-derivative-desc-320p.mp4": "ćƒ‡ćƒć‚¤ć‚¹ćƒ•ćƒ¬ćƒ³ćƒ‰ćƒŖćƒ¼ MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "ć‚¦ć‚§ćƒ– ć‚¹ćƒˆćƒŖćƒ¼ćƒŸćƒ³ć‚°åÆčƒ½ MP4 (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "HD 品č³Ŗ MP4 (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "ćƒ•ćƒ« HD 品č³Ŗ MP4 (1080P)",
+ "timedmedia-subtitle-new": "ēæ»čØ³ć®ę–°č¦ä½œęˆć€ć¾ćŸćÆę—¢å­˜ć®ēæ»čØ³ć®ē·Ø集",
+ "timedmedia-subtitle-new-desc": "č؀čŖžć‚’éøꊞ恗恦态'''{{int:Timedmedia-subtitle-new-go}}'''惜ć‚æćƒ³ć‚’ęŠ¼ć—ć¦ćć ć•ć„ć€‚",
+ "timedmedia-subtitle-new-go": "å®Ÿč”Œ",
+ "timedmedia-subtitle-language": "$1 ($2) 字幕",
+ "timedmedia-subtitle-no-video": "ē¾åœØć®å­—å¹•ćƒšćƒ¼ć‚øć«é–¢é€£ä»˜ć‘ć‚‰ć‚ŒćŸå‹•ē”»ćÆć‚ć‚Šć¾ć›ć‚“ć€‚",
+ "timedmedia-subtitle-no-subtitles": "ē¾åœØć€ć“ć®å‹•ē”»ć«ćÆ$1ć®å­—å¹•ćÆć‚ć‚Šć¾ć›ć‚“ćŒć€[{{fullurl:{{FULLPAGENAME}}|action=edit}} ć“ć®ćƒšćƒ¼ć‚ø悒ē·Ø集]恗恦čæ½åŠ ć§ćć¾ć™ć€‚",
+ "timedmedia-subtitle-remote": "ć“ć®ćƒ•ć‚”ć‚¤ćƒ«ć®å­—å¹•ćÆ$1ć§ćƒ›ć‚¹ćƒˆć•ć‚Œć¦ć„ć¾ć™",
+ "timedmedia-subtitle-remote-link": "$2 ć§ć“ć®ćƒ•ć‚”ć‚¤ćƒ«ć®[$1 č§£čŖ¬ćƒšćƒ¼ć‚øć‚’é–²č¦§]ć§ćć¾ć™",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 ä»¶ć®å‹•ē”»}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 件恮 Ogg 動ē”»}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 件恮 WebM 動ē”»}}",
+ "timedmedia-file": "ćƒ•ć‚”ć‚¤ćƒ«",
+ "timedmedia-audios": "{{PLURAL:$1|$1 ä»¶ć®éŸ³å£°ćƒ•ć‚”ć‚¤ćƒ«}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 件恮 Ogg éŸ³å£°ćƒ•ć‚”ć‚¤ćƒ«}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 件恮 FLAC éŸ³å£°ćƒ•ć‚”ć‚¤ćƒ«}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 件恮 WAV éŸ³å£°ćƒ•ć‚”ć‚¤ćƒ«}}",
+ "apihelp-transcodereset-param-title": "ćƒ”ćƒ‡ć‚£ć‚¢ćƒ•ć‚”ć‚¤ćƒ«ć®ć‚æć‚¤ćƒˆćƒ«ć€‚"
+}
diff --git a/extensions/TimedMediaHandler/i18n/jut.json b/extensions/TimedMediaHandler/i18n/jut.json
new file mode 100644
index 00000000..c8c30c29
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/jut.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "HuslƄke",
+ "Jyllanj"
+ ]
+ },
+ "timedmedia-desc": "HĆ„ndlƦr fĆør Ogg Theora og Vorbis filer, ve JavaScript spƦler",
+ "timedmedia-ogg-short-audio": "Ogg $1 lydfile, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 videofil, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 mediafil, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 lydfil, lƦngd $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 videofil, lƦngd $2, $4Ɨ$5 pixel, $3",
+ "timedmedia-ogg-long-multiplexed": "Sammelsatt Ogg-lyd- Ć„ -videofil, $1, lƦngd $2, $4Ɨ$5 pixel, $3 sammeltj",
+ "timedmedia-ogg-long-general": "Ogg mediafil, lƦngd $2, $3",
+ "timedmedia-ogg-long-error": "Udjylji Ogg-fil: $1",
+ "timedmedia-more": "Mier...",
+ "timedmedia-dismiss": "Lokk",
+ "timedmedia-download": "LƤgg fil nier",
+ "timedmedia-desc-link": "Om fili"
+}
diff --git a/extensions/TimedMediaHandler/i18n/jv.json b/extensions/TimedMediaHandler/i18n/jv.json
new file mode 100644
index 00000000..0bb2c6ee
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/jv.json
@@ -0,0 +1,65 @@
+{
+ "@metadata": {
+ "authors": [
+ "Meursault2004",
+ "NoiX180",
+ "Pras"
+ ]
+ },
+ "timedmedia-desc": "Sing ngurusi berkas Ogg Theora lan Vorbis mawa pamain JavaScript",
+ "timedmedia-ogg-short-audio": "Berkas swara $1 ogg, $2",
+ "timedmedia-ogg-short-video": "Berkas vidƩo $1 ogg, $2",
+ "timedmedia-ogg-short-general": "Berkas mƩdia $1 ogg, $2",
+ "timedmedia-ogg-long-audio": "Berkas swara $1 ogg, dawanƩ $2, $3",
+ "timedmedia-ogg-long-video": "Berkas vidĆ©o $1 ogg, dawanĆ© $2, $4Ɨ$5 piksel, $3",
+ "timedmedia-ogg-long-multiplexed": "Berkas audio/vidĆ©o multiplexed ogg, $1, dawanĆ© $2, $4Ɨ$5 piksel, $3 gunggungĆ©",
+ "timedmedia-ogg-long-general": "Berkas mƩdia ogg, dawanƩ $2, $3",
+ "timedmedia-ogg-long-error": "Berkas ogg ora absah: $1",
+ "timedmedia-more": "Luwih akĆØh...",
+ "timedmedia-dismiss": "Tutup",
+ "timedmedia-download": "Undhuh berkas",
+ "timedmedia-play-media": "Puter mƩdia",
+ "timedmedia-desc-link": "Prekara berkas iki",
+ "timedmedia-oggThumb-version": "OggHandler mbutuhakĆ© oggThumb vĆØrsi $1 utawa sakbanjurĆ©.",
+ "timedmedia-oggThumb-failed": "oggTumb gagal nggawƩ gambar mini.",
+ "timedmedia-status-header": "Status transkodhƩ",
+ "timedmedia-update-status": "Anyari status transkodhƩ",
+ "timedmedia-status": "Status",
+ "timedmedia-status-unknown": "Status ora dingertĆØni",
+ "timedmedia-transcodeinfo": "Katrangan turunan transkodhƩ",
+ "timedmedia-actions": "Laku",
+ "timedmedia-direct-link": "Undhuh turunan",
+ "timedmedia-not-ready": "Durung siap",
+ "timedmedia-completed-on": "Nglengkapi transkodhƩ $1",
+ "timedmedia-error-on": "Kasalahan nĆØng transkodhĆ© $1.",
+ "timedmedia-started-transcode": "TranskodhƩ lekas $1 kapungkur. $2",
+ "timedmedia-percent-done": "Kira-kira $1 rampung",
+ "timedmedia-in-job-queue": "NambahakĆ© nĆØng antrian Pakaryan $1 kapungkur",
+ "timedmedia-unknown-target-size": "GedhĆ© patujon oradingertĆØni, $1 kasandhĆØkakĆ©",
+ "timedmedia-days": "{{PLURAL:$1|dina|dina}}",
+ "timedmedia-hours": "{{PLURAL:$1|jam|jam}}",
+ "timedmedia-minutes": "{{PLURAL:$1|menit|menit}}",
+ "timedmedia-seconds": "{{PLURAL:$1|detik|detik}}",
+ "timedmedia-reset": "SetĆØl ulang transkodhĆ©",
+ "timedmedia-reset-error": "Kasalahan nalika nyetĆØl ulang tugas transkodhĆ©.",
+ "timedmedia-source-file": "Sumber $1",
+ "timedmedia-source-file-desc": "$1 asli, $2 Ɨ $3 ($4)",
+ "timedmedia-derivative-desc-160p.ogv": "Vidio Ogg bandwidth cilik (160P)",
+ "timedmedia-derivative-desc-720p.ogv": "Vidio Ogg sing bisa diundhuh mawa kualitas dhuwur (720P)",
+ "timedmedia-derivative-desc-720p.webm": "WebM sing bisa diundhuh mawa kualitas dhuwur (720P)",
+ "timedmedia-subtitle-new": "GawƩ terjemahan anyar utawa sunting sing wis ana",
+ "timedmedia-subtitle-new-desc": "Ganti bagĆ©yan '''$1''' nganggo [[:en:ISO 639|kodhĆ© basa]] SampĆ©yan lan pencĆØt tombol '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Nuju",
+ "timedmedia-subtitle-language": "Subjudhul $1 ($2)",
+ "timedmedia-subtitle-no-video": "Ora ana vidio sing cocok karo kaca subjudhul saiki",
+ "timedmedia-subtitle-no-subtitles": "Sawetara durung ana subjudhul nĆØng $1 kanggo vidio iki, SampĆ©yan bisa [{{fullurl:{{FULLPAGENAME}}|action=edit}} nyunting kaca iki] kanggo nambahi",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 vidio|$1 vidio}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 vidio Ogg|$1 vidio Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 vidio WebM|$1 vidio WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transkodhƩ|$1 transkodhƩ}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 transkodhƩ lumangsung|$1 transkodhƩ lumangsung}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 transkodhƩ ngantri|$1 transkodhƩ ngantri}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 transkodhƩ gagal|$1 transkodhƩ gagal}}",
+ "timedmedia-file": "Berkas"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ka.json b/extensions/TimedMediaHandler/i18n/ka.json
new file mode 100644
index 00000000..5c43ea7b
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ka.json
@@ -0,0 +1,89 @@
+{
+ "@metadata": {
+ "authors": [
+ "BRUTE",
+ "David1010",
+ "Malafaya",
+ "Tokoko",
+ "įƒ’įƒ˜įƒįƒ įƒ’įƒ˜įƒ›įƒ”įƒšįƒ"
+ ]
+ },
+ "timedmedia-desc": "įƒįƒ£įƒ“įƒ˜įƒįƒ”, įƒ•įƒ˜įƒ“įƒ”įƒįƒ” įƒ“įƒ įƒ”įƒ£įƒ‘įƒ¢įƒ˜įƒ¢įƒ įƒ”įƒ‘įƒ˜įƒ” įƒ“įƒįƒ›įƒįƒ›įƒ£įƒØįƒįƒ•įƒ”įƒ‘įƒ”įƒšįƒ˜, įƒØįƒ”įƒ›įƒ“įƒ”įƒ’įƒ˜ įƒ¤įƒįƒ įƒ›įƒįƒ¢įƒ”įƒ‘įƒ˜įƒ” įƒ›įƒ®įƒįƒ įƒ“įƒįƒ­įƒ”įƒ įƒ˜įƒ—: WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Ogg $1 įƒ®įƒ›įƒįƒ•įƒįƒœįƒ˜ įƒ¤įƒįƒ˜įƒšįƒ˜, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 įƒ•įƒ˜įƒ“įƒ”įƒ įƒ¤įƒįƒ˜įƒšįƒ˜, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 įƒ›įƒ”įƒ“įƒ˜įƒ įƒ¤įƒįƒ˜įƒšįƒ˜, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 įƒ®įƒ›įƒįƒ•įƒįƒœįƒ˜ įƒ¤įƒįƒ˜įƒšįƒ˜, įƒ”įƒ˜įƒ’įƒ įƒ«įƒ” $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 įƒ•įƒ˜įƒ“įƒ”įƒ įƒ¤įƒįƒ˜įƒšįƒ˜, įƒ”įƒ˜įƒ’įƒ įƒ«įƒ” $2, $4 Ɨ $5 įƒžįƒ˜įƒ„įƒ”įƒ”įƒšįƒ˜, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg įƒ›įƒ£įƒšįƒ¢įƒ˜įƒžįƒšįƒ”įƒ„įƒ”įƒ£įƒ įƒ˜ įƒįƒ£įƒ“įƒ˜įƒ/įƒ•įƒ˜įƒ“įƒ”įƒ įƒ¤įƒįƒ˜įƒšįƒ˜, $1, įƒ”įƒ˜įƒ’įƒ įƒ«įƒ” $2, $4 Ɨ $5 įƒžįƒ˜įƒ„įƒ”įƒ”įƒšįƒ˜, $3 įƒ”įƒ įƒ£įƒšįƒ˜",
+ "timedmedia-ogg-long-general": "Ogg įƒ›įƒ”įƒ“įƒ˜įƒ įƒ¤įƒįƒ˜įƒšįƒ˜, įƒ”įƒ˜įƒ’įƒ įƒ«įƒ” $2, $3",
+ "timedmedia-ogg-long-error": "įƒįƒ įƒįƒ”įƒ¬įƒįƒ įƒ˜ Ogg-įƒ¤įƒįƒ˜įƒšįƒ˜: $1",
+ "timedmedia-webm-short-video": "WebM $1 įƒ•įƒ˜įƒ“įƒ”įƒ įƒ¤įƒįƒ˜įƒšįƒ˜, $2",
+ "timedmedia-webm-long-video": "WebM įƒįƒ£įƒ“įƒ˜įƒ/įƒ•įƒ˜įƒ“įƒ”įƒ įƒ¤įƒįƒ˜įƒšįƒ˜, $1, įƒ”įƒ˜įƒ’įƒ įƒ«įƒ” $2, $4 Ɨ $5 įƒžįƒ˜įƒ„įƒ”įƒ”įƒšįƒ˜, $3 įƒ”įƒ įƒ£įƒšįƒ˜",
+ "timedmedia-flac-short-audio": "FLAC įƒįƒ£įƒ“įƒ˜įƒ įƒ¤įƒįƒ˜įƒšįƒ˜, $1",
+ "timedmedia-wav-short-audio": "WAV įƒįƒ£įƒ“įƒ˜įƒ įƒ¤įƒįƒ˜įƒšįƒ˜, $1",
+ "timedmedia-mp4-short-video": "MP4 $1 įƒ•įƒ˜įƒ“įƒ”įƒ įƒ¤įƒįƒ˜įƒšįƒ˜, $2",
+ "timedmedia-mp4-long-video": "MP4 įƒįƒ£įƒ“įƒ˜įƒ/įƒ•įƒ˜įƒ“įƒ”įƒ įƒ¤įƒįƒ˜įƒšįƒ˜, $1, įƒ”įƒ˜įƒ’įƒ įƒ«įƒ” $2, $4 Ɨ $5 įƒžįƒ˜įƒ„įƒ”įƒ”įƒšįƒ˜, $3 įƒ”įƒ įƒ£įƒšįƒ˜",
+ "timedmedia-no-player-js": "įƒ”įƒįƒ›įƒ¬įƒ£įƒ®įƒįƒ įƒįƒ“, įƒ—įƒ„įƒ•įƒ”įƒœ įƒ‘įƒ įƒįƒ£įƒ–įƒ”įƒ įƒØįƒ˜ įƒ’įƒįƒ›įƒįƒ įƒ—įƒ£įƒšįƒ˜įƒ JavaScript įƒįƒœ įƒįƒ  įƒįƒ įƒ˜įƒ” įƒ”įƒįƒ­įƒ˜įƒ įƒ įƒ“įƒįƒ›įƒ™įƒ•įƒ įƒ”įƒšįƒ˜.<br />\nįƒ—įƒ„įƒ•įƒ”įƒœ įƒØįƒ”įƒ’įƒ˜įƒ«įƒšįƒ˜įƒįƒ— <a href=\"$1\">įƒ’įƒįƒ“įƒ›įƒįƒ¬įƒ”įƒ įƒįƒ— įƒ™įƒšįƒ˜įƒžįƒ˜</a> įƒįƒœ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">įƒ’įƒįƒ“įƒ›įƒįƒ¬įƒ”įƒ įƒįƒ— įƒ“įƒįƒ›įƒ™įƒ•įƒ įƒ”įƒšįƒ˜</a> įƒ™įƒšįƒ˜įƒžįƒ˜įƒ” įƒ‘įƒ įƒįƒ£įƒ–įƒ”įƒ įƒØįƒ˜ įƒ“įƒįƒ”įƒįƒ™įƒ įƒįƒ•įƒįƒ“.",
+ "timedmedia-more": "įƒ›įƒ”įƒ¢įƒ˜...",
+ "timedmedia-dismiss": "įƒ“įƒįƒ®įƒ£įƒ įƒ•įƒ",
+ "timedmedia-download": "įƒ¤įƒįƒ˜įƒšįƒ˜įƒ” įƒ©įƒįƒ›įƒįƒ¢įƒ•įƒ˜įƒ įƒ—įƒ•įƒ",
+ "timedmedia-play-media": "įƒ›įƒ”įƒ“įƒ˜įƒ-įƒ¤įƒįƒ˜įƒšįƒ˜įƒ” įƒ“įƒįƒ™įƒ•įƒ įƒ",
+ "timedmedia-desc-link": "įƒįƒ› įƒ¤įƒįƒ˜įƒšįƒ˜įƒ” įƒØįƒ”įƒ”įƒįƒ®įƒ”įƒ‘",
+ "timedmedia-oggThumb-version": "OggHandler-įƒ” įƒ”įƒ­įƒ˜įƒ įƒ“įƒ”įƒ‘įƒ oggThumb-įƒ˜įƒ” įƒ•įƒ”įƒ įƒ”įƒ˜įƒ $1 įƒįƒœ įƒ£įƒ¤įƒ įƒ įƒ’įƒ•įƒ˜įƒįƒœįƒ“įƒ”įƒšįƒ˜.",
+ "timedmedia-oggThumb-failed": "oggThumb-įƒ›įƒ įƒ•įƒ”įƒ  įƒ›įƒįƒįƒ®įƒ”įƒ įƒ®įƒ įƒ›įƒ˜įƒœįƒ˜įƒįƒ¢įƒ˜įƒ£įƒ įƒ˜įƒ” įƒØįƒ”įƒ„įƒ›įƒœįƒ.",
+ "timedmedia-status-header": "įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ˜įƒ” įƒ”įƒ¢įƒįƒ¢įƒ£įƒ”įƒ˜",
+ "timedmedia-update-status": "įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ˜įƒ” įƒ”įƒ¢įƒįƒ¢įƒ£įƒ”įƒ˜įƒ” įƒ’įƒįƒœįƒįƒ®įƒšįƒ”įƒ‘įƒ",
+ "timedmedia-status": "įƒ”įƒ¢įƒįƒ¢įƒ£įƒ”įƒ˜",
+ "timedmedia-status-unknown": "įƒ£įƒŖįƒœįƒįƒ‘įƒ˜ įƒ”įƒ¢įƒįƒ¢įƒ£įƒ”įƒ˜",
+ "timedmedia-transcodeinfo": "įƒ¤įƒįƒ įƒ›įƒįƒ¢įƒ˜",
+ "timedmedia-actions": "įƒ›įƒįƒ„įƒ›įƒ”įƒ“įƒ”įƒ‘įƒ",
+ "timedmedia-direct-link": "įƒ’įƒįƒ“įƒ›įƒįƒ¬įƒ”įƒ įƒ",
+ "timedmedia-not-ready": "įƒįƒ įƒįƒ įƒ›įƒ–įƒįƒ“",
+ "timedmedia-completed-on": "$1-įƒ˜įƒ” įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ įƒ“įƒįƒ”įƒ įƒ£įƒšįƒ”įƒ‘įƒ£įƒšįƒ˜įƒ",
+ "timedmedia-error-on": "įƒØįƒ”įƒŖįƒ“įƒįƒ›įƒ įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ˜įƒ”įƒįƒ” $1-įƒ–įƒ”.",
+ "timedmedia-started-transcode": "įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ įƒ’įƒįƒØįƒ•įƒ”įƒ‘įƒ£įƒšįƒ˜įƒ $1 įƒ¬įƒ˜įƒœ. $2",
+ "timedmedia-percent-done": "įƒ“įƒįƒįƒ®įƒšįƒįƒ”įƒ‘įƒ˜įƒ— $1% įƒØįƒ”įƒ”įƒ įƒ£įƒšįƒ”įƒ‘įƒ£įƒšįƒ˜įƒ",
+ "timedmedia-in-job-queue": "įƒ“įƒįƒ›įƒįƒ¢įƒ”įƒ‘įƒ£įƒšįƒ˜įƒ įƒ“įƒįƒ•įƒįƒšįƒ”įƒ‘įƒ”įƒ‘įƒ˜įƒ” įƒ įƒ˜įƒ’įƒØįƒ˜ $1 įƒ¬įƒ˜įƒœ",
+ "timedmedia-unknown-target-size": "įƒ£įƒŖįƒœįƒįƒ‘įƒ˜ įƒ”įƒįƒ›įƒ˜įƒ–įƒœįƒ įƒ–įƒįƒ›įƒ, $1 įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ˜įƒ”įƒįƒ”",
+ "timedmedia-days": "{{PLURAL:$1|1 įƒ“įƒ¦įƒ”|$1 įƒ“įƒ¦įƒ”}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 įƒ”įƒįƒįƒ—įƒ˜|$1 įƒ”įƒįƒįƒ—įƒ˜}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 įƒ¬įƒ£įƒ—įƒ˜|$1 įƒ¬įƒ£įƒ—įƒ˜}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 įƒ¬įƒįƒ›įƒ˜|$1 įƒ¬įƒįƒ›įƒ˜}}",
+ "timedmedia-reset": "įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ˜įƒ” įƒ—įƒįƒ•įƒ˜įƒ“įƒįƒœ įƒ“įƒįƒ§įƒ”įƒœįƒ”įƒ‘įƒ",
+ "timedmedia-reset-confirm": "įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ˜įƒ” įƒ—įƒįƒ•įƒ˜įƒ“įƒįƒœ įƒ“įƒįƒ§įƒ”įƒœįƒ”įƒ‘įƒ įƒ¬įƒįƒØįƒšįƒ˜įƒ” įƒįƒ įƒ”įƒ”įƒ‘įƒ£įƒš įƒ¤įƒįƒ˜įƒšįƒ” (įƒ—įƒ£įƒ™įƒ˜ įƒ˜įƒ” įƒįƒ įƒ”įƒ”įƒ‘įƒįƒ‘įƒ”) įƒ“įƒ įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ įƒ™įƒ•įƒšįƒįƒ• įƒ“įƒįƒ”įƒ›įƒįƒ¢įƒ”įƒ‘įƒ įƒ“įƒįƒ•įƒįƒšįƒ”įƒ‘įƒ”įƒ‘įƒ˜įƒ” įƒ įƒ˜įƒ’įƒØįƒ˜. įƒ’įƒįƒœįƒ›įƒ”įƒįƒ įƒ”įƒ‘įƒ˜įƒ— įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒįƒ” įƒ“įƒįƒ­įƒ˜įƒ įƒ“įƒ”įƒ‘įƒ įƒ’įƒįƒ įƒ™įƒ•įƒ”įƒ£įƒšįƒ˜ įƒ“įƒ įƒ. <br /><br />\nįƒ“įƒįƒ įƒ¬įƒ›įƒ£įƒœįƒ”įƒ‘įƒ£įƒšįƒ˜ įƒ®įƒįƒ įƒ—, įƒ įƒįƒ› įƒ’įƒ”įƒ£įƒ įƒ— įƒ’įƒįƒįƒ’įƒ įƒ«įƒ”įƒšįƒįƒ—?",
+ "timedmedia-reset-error": "įƒØįƒ”įƒŖįƒ“įƒįƒ›įƒ įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ˜įƒ” įƒ—įƒįƒ•įƒ˜įƒ“įƒįƒœ įƒ“įƒįƒ§įƒ”įƒœįƒ”įƒ‘įƒ˜įƒ”įƒįƒ”.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "įƒ¬įƒ§įƒįƒ įƒ $1",
+ "timedmedia-source-file-desc": "įƒįƒ įƒ˜įƒ’įƒ˜įƒœįƒįƒšįƒ˜ $1 įƒ¤įƒįƒ˜įƒšįƒ˜, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "įƒįƒ įƒ˜įƒ’įƒ˜įƒœįƒįƒšįƒ˜ $1 įƒ¤įƒįƒ˜įƒšįƒ˜ ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "įƒ“įƒįƒ‘įƒįƒšįƒ˜ įƒ®įƒįƒ įƒ˜įƒ”įƒ®įƒ˜įƒ” Ogg-įƒ•įƒ˜įƒ“įƒ”įƒ (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "įƒ•įƒ”įƒ‘-įƒœįƒįƒ™įƒįƒ“įƒ£įƒ įƒ˜ Ogg-įƒ•įƒ˜įƒ“įƒ”įƒ (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "įƒ•įƒ”įƒ‘-įƒœįƒįƒ™įƒįƒ“įƒ£įƒ įƒ˜ Ogg-įƒ•įƒ˜įƒ“įƒ”įƒ (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "įƒ›įƒįƒ¦įƒįƒšįƒ˜ įƒ®įƒįƒ įƒ˜įƒ”įƒ®įƒ˜įƒ” įƒ’įƒįƒ“įƒ›įƒįƒ¬įƒ”įƒ įƒįƒ“įƒ˜ Ogg-įƒ•įƒ˜įƒ“įƒ”įƒ (720P)",
+ "timedmedia-derivative-desc-160p.webm": "įƒ•įƒ”įƒ‘-įƒœįƒįƒ™įƒįƒ“įƒ£įƒ įƒ˜ WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "įƒ•įƒ”įƒ‘-įƒœįƒįƒ™įƒįƒ“įƒ£įƒ įƒ˜ WebM (360P)",
+ "timedmedia-derivative-desc-480p.webm": "įƒ•įƒ”įƒ‘-įƒœįƒįƒ™įƒįƒ“įƒ£įƒ įƒ˜ WebM (480P)",
+ "timedmedia-derivative-desc-720p.webm": "įƒ›įƒįƒ¦įƒįƒšįƒ˜ įƒ®įƒįƒ įƒ˜įƒ”įƒ®įƒ˜įƒ” įƒ’įƒįƒ“įƒ›įƒįƒ¬įƒ”įƒ įƒįƒ“įƒ˜ WebM (720P)",
+ "timedmedia-derivative-desc-320p.mp4": "įƒ›įƒ”įƒ’įƒįƒ‘įƒ įƒ£įƒšįƒ˜-įƒ›įƒįƒ¬įƒ§įƒįƒ‘įƒ˜įƒšįƒįƒ‘įƒ MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "įƒ•įƒ”įƒ‘-įƒœįƒįƒ™įƒįƒ“įƒ£įƒ įƒ˜ MP4 (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "HD įƒ®įƒįƒ įƒ˜įƒ”įƒ®įƒ˜ MP4 (720P)",
+ "timedmedia-subtitle-new": "įƒØįƒ”įƒ„įƒ›įƒ”įƒœįƒ˜įƒ— įƒįƒ®įƒįƒšįƒ˜ įƒ—įƒįƒ įƒ’įƒ›įƒįƒœįƒ˜ įƒįƒœ įƒ“įƒįƒįƒ įƒ”įƒ“įƒįƒ„įƒ¢įƒ˜įƒ įƒ”įƒ— įƒįƒ įƒ”įƒ”įƒ‘įƒ£įƒšįƒ˜",
+ "timedmedia-subtitle-new-desc": "įƒįƒ˜įƒ įƒ©įƒ˜įƒ”įƒ— įƒ”įƒœįƒ įƒ“įƒ įƒ“įƒįƒįƒ­įƒ˜įƒ įƒ”įƒ— įƒ¦įƒ˜įƒšįƒįƒ™įƒ” '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "įƒ›įƒ˜įƒ“įƒ˜",
+ "timedmedia-subtitle-language": "$1 ($2) įƒ”įƒ£įƒ‘įƒ¢įƒ˜įƒ¢įƒ įƒ”įƒ‘įƒ˜",
+ "timedmedia-subtitle-no-video": "įƒįƒ„ įƒįƒ  įƒįƒ įƒ˜įƒ” įƒ•įƒ˜įƒ“įƒ”įƒ, įƒ įƒįƒ›įƒ”įƒšįƒ˜įƒŖ įƒ“įƒįƒ™įƒįƒ•įƒØįƒ˜įƒ įƒ”įƒ‘įƒ£įƒšįƒ˜įƒ įƒ”įƒ£įƒ‘įƒ¢įƒ˜įƒ¢įƒ įƒ”įƒ‘įƒ˜įƒ” įƒ›įƒ˜įƒ›įƒ“įƒ˜įƒœįƒįƒ įƒ” įƒ’įƒ•įƒ”įƒ įƒ“įƒ—įƒįƒœ",
+ "timedmedia-subtitle-no-subtitles": "įƒįƒ›įƒŸįƒįƒ›įƒįƒ“ $1 įƒ”įƒ£įƒ‘įƒ¢įƒ˜įƒ¢įƒ įƒ”įƒ‘įƒ˜ įƒįƒ› įƒ•įƒ˜įƒ“įƒ”įƒįƒ”įƒįƒ—įƒ•įƒ˜įƒ” įƒįƒ  įƒįƒ įƒ˜įƒ”, įƒ—įƒ„įƒ•įƒ”įƒœ įƒØįƒ”įƒ’įƒ˜įƒ«įƒšįƒ˜įƒįƒ— [{{fullurl:{{FULLPAGENAME}}|action=edit}} įƒØįƒ”įƒŖįƒ•įƒįƒšįƒįƒ— įƒ”įƒ” įƒ’įƒ•įƒ”įƒ įƒ“įƒ˜] įƒ›įƒįƒ— įƒ“įƒįƒ”įƒįƒ›įƒįƒ¢įƒ”įƒ‘įƒšįƒįƒ“",
+ "timedmedia-subtitle-remote": "įƒįƒ› įƒ¤įƒįƒ˜įƒšįƒ˜įƒ” įƒ“įƒ įƒįƒ”įƒ‘įƒ˜įƒ—įƒ˜ įƒ¢įƒ”įƒ„įƒ”įƒ¢įƒ˜ įƒ’įƒįƒœįƒ—įƒįƒ•įƒ”įƒ”įƒ‘įƒ£įƒšįƒ˜įƒ $1-įƒ–įƒ”",
+ "timedmedia-subtitle-remote-link": "įƒ—įƒ„įƒ•įƒ”įƒœ įƒØįƒ”įƒ’įƒ˜įƒ«įƒšįƒ˜įƒįƒ— [$1 įƒ˜įƒ®įƒ˜įƒšįƒįƒ— įƒįƒ› įƒ¤įƒįƒ˜įƒšįƒ˜įƒ” įƒįƒ¦įƒ¬įƒ”įƒ įƒ˜įƒ” įƒ’įƒ•įƒ”įƒ įƒ“įƒ˜] $2-įƒ–įƒ”",
+ "timedmediahandler": "įƒ“įƒ įƒįƒ£įƒšįƒ˜ įƒ›įƒ”įƒ“įƒ˜įƒ įƒ›įƒįƒ įƒ—įƒ•įƒ˜įƒ” įƒžįƒ įƒįƒ’įƒ įƒįƒ›įƒ",
+ "timedmedia-videos": "{{PLURAL:$1|$1 įƒ•įƒ˜įƒ“įƒ”įƒ|$1 įƒ•įƒ˜įƒ“įƒ”įƒ}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg įƒ•įƒ˜įƒ“įƒ”įƒ|$1 Ogg įƒ•įƒ˜įƒ“įƒ”įƒ}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM įƒ•įƒ˜įƒ“įƒ”įƒ|$1 WebM įƒ•įƒ˜įƒ“įƒ”įƒ}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ£įƒšįƒ˜|$1 įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ£įƒšįƒ˜}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|įƒ›įƒ˜įƒ›įƒ“įƒ˜įƒœįƒįƒ įƒ”įƒįƒ‘įƒ” $1 įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ|įƒ›įƒ˜įƒ›įƒ“įƒ˜įƒœįƒįƒ įƒ”įƒįƒ‘įƒ” $1 įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|įƒ įƒ˜įƒ’įƒØįƒ˜įƒ $1 įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ|įƒ įƒ˜įƒ’įƒØįƒ˜įƒ $1 įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ įƒ©įƒįƒ˜įƒØįƒįƒšįƒ|$1 įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ įƒ©įƒįƒ˜įƒØįƒįƒšįƒ}}",
+ "timedmedia-file": "įƒ¤įƒįƒ˜įƒšįƒ˜",
+ "right-transcode-status": "įƒ˜įƒ®įƒ˜įƒšįƒ”įƒ— [[Special:TimedMediaHandler|įƒ˜įƒœįƒ¤įƒįƒ įƒ›įƒįƒŖįƒ˜įƒ įƒ›įƒ˜įƒ›įƒ“įƒ˜įƒœįƒįƒ įƒ” įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ˜įƒ” įƒØįƒ”įƒ”įƒįƒ®įƒ”įƒ‘]]",
+ "action-transcode-status": "įƒ˜įƒ®įƒ˜įƒšįƒ”įƒ— įƒ›įƒ˜įƒ›įƒ“įƒ˜įƒœįƒįƒ įƒ” įƒ“įƒ”įƒ™įƒįƒ“įƒ˜įƒ įƒ”įƒ‘įƒ˜įƒ” įƒ”įƒ¢įƒįƒ¢įƒ£įƒ”įƒ˜"
+}
diff --git a/extensions/TimedMediaHandler/i18n/khw.json b/extensions/TimedMediaHandler/i18n/khw.json
new file mode 100644
index 00000000..821b2a13
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/khw.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Rachitrali"
+ ]
+ },
+ "timedmedia-no-player-js": "Ł…Ų¹Ų°Ų±ŲŖŲŒ ŲŖŪ ŲØŲ±Ų§Ų¤Ų²Ų±Ų§ Ų¬Ų§ŁˆŲ§Ų³Ś©Ų±Ł¾Ł¹ ŁŲ¹Ų§Ł„ Ł†ŪŒŚ©ŪŒ ŪŒŲ§ Ś©ŪŒŪ Ł…Ų¹Ų§ŁˆŁ† Ł¾Ł„ŪŒŲ¦Ų± Ų“Ų§Ł…Ł„ Ł†ŪŒŚ©ŪŒŪ”<br />\nŚ¾ŪŒŪ Ś©Ł„Ł¾Łˆ ŲŖŲ§Ł† ŲØŲ±Ų§Ų¤Ų²Ų±Ų§ Ś†Ł„Ų¦ŪŒŚ©Łˆ ŲØŚ†Ū’ ŲŖŁˆ Ś¾ŪŒŪ <a href=\"$1\">Ś©Ł„Ł¾Łˆ ŚˆŲ§Ų¤Ł†Ł„ŁˆŚˆ</a> Ś©ŁˆŲ±Ū’ ŪŒŲ§ </a> or <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\">Ł¾Ł„ŪŒŲ¦Ų± ŚˆŲ§Ų¤Ł†Ł„ŁˆŚˆ</a> Ś©ŁˆŲ±Ū’Ū”",
+ "timedmedia-source-file": "$1 Ł…Ų³ŁˆŲÆŪ",
+ "timedmedia-source-audio-file-desc": "Ų§ŲµŁ„ŪŒ $1 ŁŲ§Ų¦Ł„($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/kk-arab.json b/extensions/TimedMediaHandler/i18n/kk-arab.json
new file mode 100644
index 00000000..e348e4d2
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/kk-arab.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": [],
+ "timedmedia-ogg-short-audio": "Ogg $1 ŲÆŁ‰ŲØŁ‰Ų³ ŁŲ§ŁŠŁ„Ł‰, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 ŲØŪ•ŁŠŁ†Ū• ŁŲ§ŁŠŁ„Ł‰, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 ŲŖŲ§Ų³Ł¾Ų§ ŁŲ§ŁŠŁ„Ł‰, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 ŲÆŁ‰ŲØŁ‰Ų³ ŁŲ§ŁŠŁ„Ł‰, Ū‡Ų²Ų§Ł‚ŲŖŁ‰Ų¹Ł‰ $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 ŲØŪ•ŁŠŁ†Ū• ŁŲ§ŁŠŁ„Ł‰, Ū‡Ų²Ų§Ł‚ŲŖŁ‰Ų¹Ł‰ $2, $4 Ɨ $5 Ł¾Ł‰ŁŠŁƒŲ³Ū•Ł„, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg Ł‚Ū‡Ų±Ų§Ł…ŲÆŁ‰ ŲÆŁ‰ŲØŁ‰Ų³/ŲØŪ•ŁŠŁ†Ū• ŁŲ§ŁŠŁ„Ł‰, $1, Ū‡Ų²Ų§Ł‚ŲŖŁ‰Ų¹Ł‰ $2, $4 Ɨ $5 Ł¾Ł‰ŁŠŁƒŲ³Ū•Ł„, $3 Ł†Ū• ŲØŲ§Ų±Ł„Ł‰Ų¹Ł‰",
+ "timedmedia-ogg-long-general": "Ogg ŲŖŲ§Ų³Ł¾Ų§ ŁŲ§ŁŠŁ„Ł‰, Ū‡Ų²Ų§Ł‚ŲŖŁ‰Ų¹Ł‰ $2, $3",
+ "timedmedia-ogg-long-error": "Ų¬Ų§Ų±Ų§Ł…Ų³Ł‰Ų² ogg ŁŲ§ŁŠŁ„Ł‰: $1",
+ "timedmedia-more": "ŁƒŁˆŲØŁ‰Ų±Ū•Łƒ...",
+ "timedmedia-dismiss": "Ų¬Ų§ŲØŪ‹",
+ "timedmedia-download": "ŁŲ§ŁŠŁ„ŲÆŁ‰ Ų¬Ū‡ŁƒŲŖŪ•Ū‹",
+ "timedmedia-desc-link": "ŲØŪ‡Ł„ ŁŲ§ŁŠŁ„ ŲŖŪ‹Ų±Ų§Ł„Ł‰"
+}
diff --git a/extensions/TimedMediaHandler/i18n/kk-cyrl.json b/extensions/TimedMediaHandler/i18n/kk-cyrl.json
new file mode 100644
index 00000000..c378cf48
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/kk-cyrl.json
@@ -0,0 +1,56 @@
+{
+ "@metadata": {
+ "authors": [
+ "Arystanbek"
+ ]
+ },
+ "timedmedia-ogg-short-audio": "Ogg $1 Š“ыŠ±Ń‹Ń фŠ°Š¹Š»Ń‹, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 Š±ŠµŠ¹Š½Šµ фŠ°Š¹Š»Ń‹, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 тŠ°ŃŠæŠ° фŠ°Š¹Š»Ń‹, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 Š“ыŠ±Ń‹Ń фŠ°Š¹Š»Ń‹, Ņ±Š·Š°Ņ›Ń‚Ń‹Ņ“Ń‹ $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 Š±ŠµŠ¹Š½Šµ фŠ°Š¹Š»Ń‹, Ņ±Š·Š°Ņ›Ń‚Ń‹Ņ“Ń‹ $2, $4 Ɨ $5 ŠæŠøŠŗсŠµŠ», $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg Ņ›Ņ±Ń€Š°Š¼Š“ы Š“ыŠ±Ń‹Ń/Š±ŠµŠ¹Š½Šµ фŠ°Š¹Š»Ń‹, $1, Ņ±Š·Š°Ņ›Ń‚Ń‹Ņ“Ń‹ $2, $4 Ɨ $5 ŠæŠøŠŗсŠµŠ», $3 Š½Šµ Š±Š°Ń€Š»Ń‹Ņ“Ń‹",
+ "timedmedia-ogg-long-general": "Ogg тŠ°ŃŠæŠ° фŠ°Š¹Š»Ń‹, Ņ±Š·Š°Ņ›Ń‚Ń‹Ņ“Ń‹ $2, $3",
+ "timedmedia-ogg-long-error": "Š–Š°Ń€Š°Š¼ŃŃ‹Š· ogg фŠ°Š¹Š»Ń‹: $1",
+ "timedmedia-webm-short-video": "WebM $1 Š²ŠøŠ“ŠµŠ¾ фŠ°Š¹Š», $2",
+ "timedmedia-flac-short-audio": "FLAC Š°ŃƒŠ“ŠøŠ¾ фŠ°Š¹Š», $1",
+ "timedmedia-flac-long-audio": "FLAC Š°ŃƒŠ“ŠøŠ¾ фŠ°Š¹Š», Ņ±Š·Ń‹Š½Š“ыŅ“Ń‹ $1, Š±ŠøтрŠµŠ¹Ń‚ ā€” $2",
+ "timedmedia-wav-short-audio": "WAV Š°ŃƒŠ“ŠøŠ¾ фŠ°Š¹Š», $1",
+ "timedmedia-wav-long-audio": "WAV Š°ŃƒŠ“ŠøŠ¾ фŠ°Š¹Š», $1 Ņ±Š·Ń‹Š½Š“ыŅ“Ń‹ $1, Š±ŠøтрŠµŠ¹Ń‚ ā€” $2",
+ "timedmedia-mp4-short-video": "MP4 $1 Š²ŠøŠ“ŠµŠ¾ фŠ°Š¹Š», $2",
+ "timedmedia-more": "ŠšÓ©Š±Ń–Ń€ŠµŠŗ...",
+ "timedmedia-dismiss": "Š–Š°Š±Ńƒ",
+ "timedmedia-download": "Š¤Š°Š¹Š»Š“ы Š¶ŅÆŠŗтŠµŃƒ",
+ "timedmedia-play-media": "ŠœŠµŠ“ŠøŠ°Š½Ń‹ ŠŗөрсŠµŃ‚Ńƒ",
+ "timedmedia-desc-link": "Š‘Ņ±Š» фŠ°Š¹Š» турŠ°Š»Ń‹",
+ "timedmedia-status": "Š”тŠ°Ń‚ŃƒŃŃ‹",
+ "timedmedia-status-unknown": "Š‘ŠµŠ»Š³Ń–сіŠ· стŠ°Ń‚ŃƒŃ",
+ "timedmedia-actions": "ӘрŠµŠŗŠµŃ‚Ń‚ŠµŃ€",
+ "timedmedia-not-ready": "Š”Š°Š¹Ń‹Š½ ŠµŠ¼ŠµŃ",
+ "timedmedia-days": "{{PLURAL:$1|1 ŠŗŅÆŠ½|$1 ŠŗŅÆŠ½}}",
+ "timedmedia-hours": "{{PLURAL:$1|Š±Ń–Ń€ сŠ°Ņ“Š°Ń‚|$1 сŠ°Ņ“Š°Ń‚}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 Š¼ŠøŠ½ŃƒŃ‚|$1 Š¼ŠøŠ½ŃƒŃ‚}}",
+ "timedmedia-seconds": "{{PLURAL:$1|$ сŠµŠŗуŠ½Ń‚|сŠµŠŗуŠ½Ń‚}}",
+ "timedmedia-source-file": "$1 Ņ›Š°Š¹Š½Š°Ń€",
+ "timedmedia-derivative-desc-160p.ogv": "Š¢Ó©Š¼ŠµŠ½Š³Ń– сŠ°ŠæŠ°Š»Ń‹ Ogg Š²ŠøŠ“ŠµŠ¾ (160P)",
+ "timedmedia-derivative-desc-720p.ogv": "Š–Š¾Ņ“Š°Ń€Ń‹ сŠ°ŠæŠ°Š“Š°Ņ“Ń‹ Š¶ŅÆŠŗтŠµŠ»Ń–Š½ŠµŃ‚Ń–Š½ Ogg Š²ŠøŠ“ŠµŠ¾ (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "Š¢Š¾Š»Ń‹Ņ› HD Š¶Ņ±ŠŗтŠµŠ»Ń–Š½ŠµŃ‚Ń–Š½ Ogg Š²ŠøŠ“ŠµŠ¾ (1080P)",
+ "timedmedia-derivative-desc-720p.webm": "Š–Š¾Ņ“Š°Ń€Ń‹ сŠ°ŠæŠ°Š“Š°Ņ“Ń‹ Š¶ŅÆŠŗтŠµŠ»Ń–Š½ŠµŃ‚Ń–Š½ WebM (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "Š¢Š¾Š»Ń‹Ņ› HD Š¶Ņ±ŠŗтŠµŠ»Ń–Š½ŠµŃ‚Ń–Š½ WebM (1080P)",
+ "timedmedia-derivative-desc-720p.mp4": "HD сŠ°ŠæŠ° MP4 (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "Š¢Š¾Š»Ń‹Ņ› HD сŠ°ŠæŠ° MP4 (1080P)",
+ "timedmedia-subtitle-new": "Š–Š°Ņ£Š° Š°ŃƒŠ“Š°Ń€Š¼Š° Š±Š°ŃŃ‚Š°Ńƒ Š½ŠµŠ¼ŠµŃŠµ Š±Š°Ń€Ń‹Š½ Ó©Ņ£Š“ŠµŃƒ",
+ "timedmedia-subtitle-new-desc": "Š¢Ń–Š»Š“і тŠ°Ņ£Š“Š°Ņ£Ń‹Š· Š¶Ó™Š½Šµ '''{{int:Timedmedia-subtitle-new-go}}''' Š±Š°Ń‚Ń‹Ń€Š¼Š°ŃŃ‹Š½ Š±Š°ŃŃ‹Ņ£Ń‹Š·",
+ "timedmedia-subtitle-new-go": "ÓØту",
+ "timedmedia-subtitle-language": "$1 ($2) суŠ±Ń‚ŠøтрŠ»ŠµŃ€",
+ "timedmedia-videos": "{{PLURAL:$1|$1 Š²ŠøŠ“ŠµŠ¾|$1 Š²ŠøŠ“ŠµŠ¾Š»Š°Ń€}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg Š²ŠøŠ“ŠµŠ¾|$1 Ogg Š²ŠøŠ“ŠµŠ¾Š»Š°Ń€}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM Š²ŠøŠ“ŠµŠ¾|$1 WebM Š²ŠøŠ“ŠµŠ¾Š»Š°Ń€}}",
+ "timedmedia-file": "Š¤Š°Š¹Š»",
+ "timedmedia-audios": "{{PLURAL:$1|$1 Š°ŃƒŠ“ŠøŠ¾ фŠ°Š¹Š»|$1 Š°ŃƒŠ“ŠøŠ¾ фŠ°Š¹Š»Š“Š°Ń€}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ogg Š°ŃƒŠ“ŠøŠ¾ фŠ°Š¹Š»|$1 Ogg Š°ŃƒŠ“ŠøŠ¾ фŠ°Š¹Š»Š“Š°Ń€}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 FLAC Š°ŃƒŠ“ŠøŠ¾ фŠ°Š¹Š»|$1 FLAC Š°ŃƒŠ“ŠøŠ¾ фŠ°Š¹Š»Š“Š°Ń€}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 WAV Š°ŃƒŠ“ŠøŠ¾ фŠ°Š¹Š»|$1 WAV Š°ŃƒŠ“ŠøŠ¾ фŠ°Š¹Š»Š“Š°Ń€}}",
+ "right-transcode-status": "[[Special:TimedMediaHandler|information about the current transcode activity]] ŠŗÓ©Ń€Ńƒ",
+ "apihelp-transcodereset-param-title": "ŠœŠµŠ“ŠøŠ° фŠ°Š¹Š» тŠ°Ņ›Ń‹Ń€Ń‹Š±Ń‹."
+}
diff --git a/extensions/TimedMediaHandler/i18n/kk-latn.json b/extensions/TimedMediaHandler/i18n/kk-latn.json
new file mode 100644
index 00000000..ef140659
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/kk-latn.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": [],
+ "timedmedia-ogg-short-audio": "Ogg $1 dıbıs faĆ½lı, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 beĆ½ne faĆ½lı, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 taspa faĆ½lı, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 dıbıs faĆ½lı, uzaqtığı $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 beĆ½ne faĆ½lı, uzaqtığı $2, $4 Ɨ $5 pĆÆksel, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg quramdı dıbıs/beĆ½ne faĆ½lı, $1, uzaqtığı $2, $4 Ɨ $5 pĆÆksel, $3 ne barlığı",
+ "timedmedia-ogg-long-general": "Ogg taspa faĆ½lı, uzaqtığı $2, $3",
+ "timedmedia-ogg-long-error": "Jaramsız ogg faĆ½lı: $1",
+ "timedmedia-more": "Kƶbirek...",
+ "timedmedia-dismiss": "Jabw",
+ "timedmedia-download": "FaĆ½ldı jĆ¼ktew",
+ "timedmedia-desc-link": "Bul faĆ½l twralı"
+}
diff --git a/extensions/TimedMediaHandler/i18n/km.json b/extensions/TimedMediaHandler/i18n/km.json
new file mode 100644
index 00000000..47cf1d5e
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/km.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chhorran",
+ "Lovekhmer",
+ "T-Rithy",
+ "Thearith",
+ "įž‚įžøįž˜įžŸįŸŠįŸ’įžšįž»įž“"
+ ]
+ },
+ "timedmedia-desc": "įž‚įž¶įŸ†įž‘įŸ’įžšįž…įŸ†įž–įŸ„įŸ‡ Ogg Theora įž“įž·įž„ Vorbis files, įž‡įž¶įž˜įž½įž™ įž§įž”įž€įžšįžŽįŸįž¢įž¶įž“ JavaScript",
+ "timedmedia-ogg-short-audio": "įžÆįž€įžŸįž¶įžš įžŸįŸ†įž”įŸįž„ Ogg $1, $2",
+ "timedmedia-ogg-short-video": "įžÆįž€įžŸįž¶įžšįžœįžøįžŠįŸįž¢įž¼ Ogg $1, $2",
+ "timedmedia-ogg-short-general": "įžÆįž€įžŸįž¶įžšįž˜įŸįžŒįž¶Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "įžÆįž€įžŸįž¶įžšįžŸįŸ†įž”įŸįž„įž”įŸ’įžšįž—įŸįž‘Ogg $1, įžšįž™įŸˆįž–įŸįž›$2 įž“įž·įž„įž‘įŸ†įž įŸ†$3",
+ "timedmedia-ogg-long-video": "įžÆįž€įžŸįž¶įžšįžœįžøįžŠįŸįž¢įž¼įž”įŸ’įžšįž—įŸįž‘Ogg $1, įžšįž™įŸˆįž–įŸįž›$2, $4Ɨ$5px, $3",
+ "timedmedia-ogg-long-multiplexed": "įžÆįž€įžŸįž¶įžšįž¢įž¼įžŒįžøįž™įŸ‰įž¼/įžœįžøįžŠįŸįž¢įž¼įž…įž˜įŸ’įžšįž»įŸ‡įž”įŸ’įžšįž—įŸįž‘Ogg , $1, įžšįž™įŸˆįž–įŸįž›$2, $4Ɨ$5px, įž”įŸ’įžšįž įŸ‚įž›$3",
+ "timedmedia-ogg-long-general": "įžÆįž€įžŸįž¶įžšįž˜įŸįžŒįž¶įž”įŸ’įžšįž—įŸįž‘Ogg, įžšįž™įŸˆįž–įŸįž›$2, $3",
+ "timedmedia-ogg-long-error": "įžÆįž€įžŸįž¶įžš ogg įž˜įž·įž“įž˜įž¶įž“ įžŸįž»įž–įž›įž—įž¶įž– įŸ– $1",
+ "timedmedia-more": "įž”įž“įŸ’įžįŸ‚įž˜...",
+ "timedmedia-dismiss": "įž”įž·įž‘",
+ "timedmedia-download": "įž‘įž¶įž‰įž™įž€įžÆįž€įžŸįž¶įžš",
+ "timedmedia-desc-link": "įž¢įŸ†įž–įžøįžÆįž€įžŸįž¶įžšįž“įŸįŸ‡"
+}
diff --git a/extensions/TimedMediaHandler/i18n/kn.json b/extensions/TimedMediaHandler/i18n/kn.json
new file mode 100644
index 00000000..4b39e37d
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/kn.json
@@ -0,0 +1,17 @@
+{
+ "@metadata": {
+ "authors": [
+ "VASANTH S.N.",
+ "Omshivaprakash"
+ ]
+ },
+ "timedmedia-more": "ą²¹ą³†ą²šą³ą²šą³...",
+ "timedmedia-dismiss": "ą²®ą³ą²šą³ą²šą²æ",
+ "timedmedia-desc-link": "ą²ˆ ą²†ą²Ÿą²¦ ą²¬ą²—ą³ą²—ą³†",
+ "timedmedia-status": "ą²øą³ą²„ą²¾ą²Øą²®ą²¾ą²Ø",
+ "timedmedia-actions": "ą²•ą³ą²°ą²æą²Æą³†ą²—ą²³ą³",
+ "timedmedia-source-file": "$1 ą²®ą³‚ą²²",
+ "timedmedia-source-audio-file-desc": "ą²…ą²øą²²ą³ $1 ą²•ą²”ą²¤ ($2)",
+ "timedmedia-subtitle-new-go": "ą²¹ą³‹ą²—ą³",
+ "timedmedia-file": "ą²•ą²”ą²¤"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ko.json b/extensions/TimedMediaHandler/i18n/ko.json
new file mode 100644
index 00000000..b0d45e53
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ko.json
@@ -0,0 +1,104 @@
+{
+ "@metadata": {
+ "authors": [
+ "ITurtle",
+ "Kwj2772",
+ "Priviet",
+ "ToePeu",
+ "ģ•„ė¼",
+ "Hym411",
+ "Revi",
+ "IRTC1015",
+ "Hwangjy9",
+ "Kurousagi"
+ ]
+ },
+ "timedmedia-desc": "WebM, OGG Theora, Vorbis, srtė„¼ ģœ„ķ•œ ķ¬ė§· ģ§€ģ›ź³¼ ģ†Œė¦¬, ė™ģ˜ģƒź³¼ ģžė§‰ģ„ ģœ„ķ•œ ķ•øė“¤ėŸ¬",
+ "timedmedia-ogg-short-audio": "Ogg $1 ģ†Œė¦¬ ķŒŒģ¼, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 ė™ģ˜ģƒ ķŒŒģ¼, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 ėÆøė””ģ–“ ķŒŒģ¼, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 ģ†Œė¦¬ ķŒŒģ¼, źøøģ“ $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 ė™ģ˜ģƒ ķŒŒģ¼, źøøģ“ $2, $4 Ɨ $5 ķ”½ģ…€, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg ė‹¤ģ¤‘ ģ†Œė¦¬/ė™ģ˜ģƒ ķŒŒģ¼, $1, źøøģ“ $2, $4 Ɨ $5 ķ”½ģ…€, ėŒ€ėžµ $3",
+ "timedmedia-ogg-long-general": "Ogg ėÆøė””ģ–“ ķŒŒģ¼, źøøģ“ $2, $3",
+ "timedmedia-ogg-long-error": "ģž˜ėŖ»ėœ Ogg ķŒŒģ¼: $1",
+ "timedmedia-ogg-long-no-streams": "Ogg ėÆøė””ģ–“ ķŒŒģ¼ģž…ė‹ˆė‹¤. ź²½ź³ : ģ“ ķŒŒģ¼ģ— ģ‚¬ģš©ėœ ģ½”ė±ģ„ ģ•Œ ģˆ˜ ģ—†ģŠµė‹ˆė‹¤.",
+ "timedmedia-webm-short-video": "WebM $1 ė™ģ˜ģƒ ķŒŒģ¼, $2",
+ "timedmedia-webm-long-video": "WebM ģ†Œė¦¬/ė™ģ˜ģƒ ķŒŒģ¼, $1, źøøģ“ $2, $4 Ɨ $5ķ”½ģ…€, ėŒ€ėžµ $3",
+ "timedmedia-flac-short-audio": "FLAC ģ†Œė¦¬ ķŒŒģ¼, $1",
+ "timedmedia-flac-long-audio": "FLAC ģ†Œė¦¬ ķŒŒģ¼, źøøģ“ $1, ėŒ€ėžµ $2",
+ "timedmedia-wav-short-audio": "WAV ģ†Œė¦¬ ķŒŒģ¼, $1",
+ "timedmedia-wav-long-audio": "WAV ģ†Œė¦¬ ķŒŒģ¼, źøøģ“ $1, ėŒ€ėžµ $2",
+ "timedmedia-wav-pcm-required": "PCM(ķŽ„ģŠ¤ ė¶€ķ˜ø ė³€ģ”°) WAVė§Œ ģ˜¬ė¦“ ģˆ˜ ģžˆģŠµė‹ˆė‹¤.",
+ "timedmedia-mp4-short-video": "MP4 $1 ė™ģ˜ģƒ ķŒŒģ¼, $2",
+ "timedmedia-mp4-long-video": "MP4 ģ†Œė¦¬/ė™ģ˜ģƒ ķŒŒģ¼, $1, źøøģ“ $2, $4 Ɨ $5ķ”½ģ…€, ėŒ€ėžµ $3",
+ "timedmedia-no-player-js": "ģ£„ģ†”ķ•©ė‹ˆė‹¤, ģ‹œģŠ¤ķ…œģ€ ģžė°”ģŠ¤ķ¬ė¦½ķŠøė„¼ ģ§€ģ›ķ•˜ģ§€ ģ•Šź±°ė‚˜ ģ§€ģ›ķ•˜ėŠ” ėÆøė””ģ–“ ķ”Œė ˆģ“ģ–“ź°€ ģ„¤ģ¹˜ė˜ģ–“ ģžˆģ§€ ģ•ŠģŠµė‹ˆė‹¤.<br />\n<a href=\"$1\">ėÆøė””ģ–“ ķ“ė¦½ģ„ ė‹¤ģš“ė”œė“œ</a>ķ•˜ź±°ė‚˜, <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ėÆøė””ģ–“ ķ”Œė ˆģ“ģ–“ė„¼ ė‹¤ģš“ė”œė“œ</a>ķ•  ģˆ˜ ģžˆģŠµė‹ˆė‹¤.",
+ "timedmedia-more": "ė” ė³“źø°ā€¦",
+ "timedmedia-dismiss": "ė‹«źø°",
+ "timedmedia-download": "ķŒŒģ¼ ė‹¤ģš“ė”œė“œ",
+ "timedmedia-play-media": "ėÆøė””ģ–“ ģž¬ģƒ",
+ "timedmedia-desc-link": "ģ“ ķŒŒģ¼ģ— ėŒ€ķ•œ ģ •ė³“",
+ "timedmedia-oggThumb-version": "OggHandlerėŠ” oggThumb ė²„ģ „ $1 ģ“ģƒģ“ ķ•„ģš”ķ•©ė‹ˆė‹¤.",
+ "timedmedia-oggThumb-failed": "oggThumbź°€ ģ„¬ė„¤ģ¼ģ„ ė§Œė“¤ģ§€ ėŖ»ķ–ˆģŠµė‹ˆė‹¤.",
+ "timedmedia-status-header": "ģ½”ė“œ ė³€ķ™˜ ģƒķƒœ",
+ "timedmedia-update-status": "ģ½”ė“œ ė³€ķ™˜ ģƒķƒœ ģ—…ė°ģ“ķŠø",
+ "timedmedia-status": "ģƒķƒœ",
+ "timedmedia-status-unknown": "ģ•Œ ģˆ˜ ģ—†ėŠ” ģƒķƒœ",
+ "timedmedia-transcodeinfo": "ķ˜•ģ‹",
+ "timedmedia-actions": "ė™ģž‘",
+ "timedmedia-direct-link": "ė‹¤ģš“ė”œė“œ",
+ "timedmedia-not-ready": "ģ¤€ė¹„ķ•˜ģ§€ ģ•ŠģŒ",
+ "timedmedia-completed-on": "$1 ģ™„ė£Œ",
+ "timedmedia-error-on": "$1ģ— ģ˜¤ė„˜",
+ "timedmedia-started-transcode": "$1 ģ „ģ— ģ‹œģž‘ė˜ģ—ˆģŠµė‹ˆė‹¤. $2",
+ "timedmedia-percent-done": "ģ•½ $1% ģ™„ė£Œ",
+ "timedmedia-in-job-queue": "$1 ģ „ģ— ģž‘ģ—… ėŒ€źø°ģ—“ģ— ģ¶”ź°€ėØ",
+ "timedmedia-unknown-target-size": "ģ•Œ ģˆ˜ ģ—†ėŠ” ėŒ€ģƒ ķ¬źø°, $1 ģøģ½”ė“œķ•Ø",
+ "timedmedia-days": "{{PLURAL:$1|1ģ¼|$1ģ¼}}",
+ "timedmedia-hours": "{{PLURAL:$1|1ģ‹œź°„|$1ģ‹œź°„}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1ė¶„|$1ė¶„}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1ģ“ˆ|$1ģ“ˆ}}",
+ "timedmedia-reset": "ģ½”ė“œ ė³€ķ™˜ ģ“ˆźø°ķ™”",
+ "timedmedia-reset-confirm": "ģ½”ė“œ ė³€ķ™˜ģ„ ģ“ˆźø°ķ™”ķ•˜ė©“ źø°ģ”“ ķŒŒģ¼ģ“ (ģžˆėŠ” ź²½ģš°) ģ œź±°ė˜ė©°, ģž‘ģ—… ėŒ€źø°ģ—“ė”œ ģ½”ė“œ ė³€ķ™˜ģ„ ė‹¤ģ‹œ ģ¶”ź°€ķ•©ė‹ˆė‹¤. ė‹¤ģ‹œ ė³€ķ™˜ķ•˜ėŠ” ė° ė‹¤ģ†Œ ģ‹œź°„ģ“ ź±øė¦“ ź²ƒģž…ė‹ˆė‹¤. <br /><br />\nź³„ģ†ķ•˜ź² ģŠµė‹ˆź¹Œ?",
+ "timedmedia-reset-error": "ģ½”ė“œ ė³€ķ™˜ ģž‘ģ—…ģ„ ģ“ˆźø°ķ™”ķ•˜ėŠ” ė° ģ˜¤ė„˜ź°€ ė‚¬ģŠµė‹ˆė‹¤.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 ģ›ė³ø",
+ "timedmedia-source-file-desc": "ģ›ė³ø $1 ķŒŒģ¼, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "ģ›ė³ø $1 ķŒŒģ¼ ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "ė‚®ģ€ ėŒ€ģ—­ķ­ Ogg ė¹„ė””ģ˜¤ (160P)",
+ "timedmedia-derivative-desc-240p.ogv": "ģ›¹ ģŠ¤ķŠøė¦¬ė° ź°€ėŠ„ Ogg ė™ģ˜ģƒ (240P)",
+ "timedmedia-derivative-desc-360p.ogv": "ģ›¹ ģŠ¤ķŠøė¦¬ė° ź°€ėŠ„ Ogg ė™ģ˜ģƒ (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "ģ›¹ ģŠ¤ķŠøė¦¬ė° ź°€ėŠ„ Ogg ė™ģ˜ģƒ (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "ź³ ķ™”ģ§ˆ ė‹¤ģš“ė”œė“œ ź°€ėŠ„ Ogg ė™ģ˜ģƒ (720P)",
+ "timedmedia-derivative-desc-160p.webm": "ģ›¹ ģŠ¤ķŠøė¦¬ė° ź°€ėŠ„ WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "ģ›¹ ģŠ¤ķŠøė¦¬ė° ź°€ėŠ„ WebM (360P)",
+ "timedmedia-derivative-desc-480p.webm": "ģ›¹ ģŠ¤ķŠøė¦¬ė° ź°€ėŠ„ WebM (480P)",
+ "timedmedia-derivative-desc-720p.webm": "ź³ ķ™”ģ§ˆ ė‹¤ģš“ė”œė“œ ź°€ėŠ„ WebM (720P)",
+ "timedmedia-derivative-desc-320p.mp4": "ģž„ģ¹˜ ģ¹œķ™”ģ  MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "ģ›¹ ģŠ¤ķŠøė¦¬ė° ź°€ėŠ„ MP4 (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "HD ķ’ˆģ§ˆ MP4 (720P)",
+ "timedmedia-subtitle-new": "ģƒˆ ė²ˆģ—­ ė§Œė“¤źø° ė˜ėŠ” źø°ģ”“ ė²ˆģ—­ ķŽøģ§‘",
+ "timedmedia-subtitle-new-desc": "ģ–øģ–“ė„¼ ģ„ ķƒķ•˜ź³  '''{{int:Timedmedia-subtitle-new-go}}''' ė²„ķŠ¼ģ„ ėˆ„ė„“ģ„øģš”",
+ "timedmedia-subtitle-new-go": "ź°€źø°",
+ "timedmedia-subtitle-language": "$1 ($2) ģžė§‰",
+ "timedmedia-subtitle-no-video": "ķ˜„ģž¬ ģžė§‰ ķŽ˜ģ“ģ§€ģ™€ ź“€ė Øėœ ė™ģ˜ģƒģ“ ģ—†ģŠµė‹ˆė‹¤",
+ "timedmedia-subtitle-no-subtitles": "ķ˜„ģž¬ ģ“ ė™ģ˜ģƒģ— ėŒ€ķ•œ $1ģ— ģžė§‰ģ“ ģ—†ģŠµė‹ˆė‹¤, ģ¶”ź°€ķ•˜ė ¤ė©“ [{{fullurl:{{FULLPAGENAME}}|action=edit}} ģ“ ė¬øģ„œė„¼ ķŽøģ§‘ķ• ] ģˆ˜ ģžˆģŠµė‹ˆė‹¤.",
+ "timedmedia-subtitle-remote": "ģ“ ķŒŒģ¼ģ— ėŒ€ķ•œ ģžė§‰ģ€ $1ģ— ķ˜øģŠ¤ķŠøķ–ˆģŠµė‹ˆė‹¤",
+ "timedmedia-subtitle-remote-link": "$2ģ— ģ“ ķŒŒģ¼ģ— ėŒ€ķ•œ [$1 ģ„¤ėŖ… ė¬øģ„œė„¼ ė³¼] ģˆ˜ ģžˆģŠµė‹ˆė‹¤",
+ "timedmediahandler": "ģžė§‰ėÆøė””ģ–“ķ•øė“¤ėŸ¬",
+ "timedmedia-videos": "{{PLURAL:$1|ė™ģ˜ģƒ $1ź°œ}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|Ogg ė™ģ˜ģƒ $1ź°œ}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|WebM ė™ģ˜ģƒ $1ź°œ}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|ģ½”ė“œ ė³€ķ™˜ $1ź°œ}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|ģ‹¤ķ–‰ ģ¤‘ģø ģ½”ė“œ ė³€ķ™˜ $1ź°œ}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|ėŒ€źø° ģ¤‘ģø ģ½”ė“œ ė³€ķ™˜ $1ź°œ}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|ģ‹¤ķŒØķ•œ ģ½”ė“œ ė³€ķ™˜ $1ź°œ}}",
+ "timedmedia-file": "ķŒŒģ¼",
+ "timedmedia-audios": "{{PLURAL:$1|ģ˜¤ė””ģ˜¤ ķŒŒģ¼ $1ź°œ}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|Ogg ģ˜¤ė””ģ˜¤ ķŒŒģ¼ $1ź°œ}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|FLAC ģ˜¤ė””ģ˜¤ ķŒŒģ¼ $1ź°œ}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|WAV ģ˜¤ė””ģ˜¤ ķŒŒģ¼ $1ź°œ}}",
+ "right-transcode-reset": "ė³€ķ™˜ėź±°ė‚˜ ģ‹¤ķŒØķ•œ ė¹„ė””ģ˜¤ė„¼ ģž‘ģ—… ėŒ€źø°ģ—“ģ— ė‹¤ģ‹œ ģ¶”ź°€ė˜ė„ė” ģ“ˆźø°ķ™”",
+ "right-transcode-status": "[[Special:TimedMediaHandler|ķ˜„ģž¬ ģ½”ė“œ ė³€ķ™˜ ķ™œė™ģ— ėŒ€ķ•œ ģ •ė³“]] ė³“źø°",
+ "action-transcode-status": "ķ˜„ģž¬ ģ½”ė“œ ė³€ķ™˜ ģƒķƒœ ė³“źø°"
+}
diff --git a/extensions/TimedMediaHandler/i18n/krc.json b/extensions/TimedMediaHandler/i18n/krc.json
new file mode 100644
index 00000000..e27d9595
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/krc.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Iltever"
+ ]
+ },
+ "timedmedia-no-player-js": "Š”Š¶Š°Ń€ŃŃ‹ŃƒŠ³ŃŠŠ°, сŠøŠ·Š½Šø Š±Ń€Š°ŃƒŠ·ŠµŃ€ŠøŠ³ŠøŠ·Š“Šµ JavaScript Š“Š¶ŃƒŠŗъŠ»Š°Š½Ń‹Š±Š“ы Š½ŠµŠ“Š° ŠŗŠµŃ€ŠµŠŗŠ»Šø Š¾Š¹Š½Š°Ń‚Ń‹ŃƒŃ‡Ńƒ Š“Š¶Š¾ŠŗъŠ“у.<br />\nŠ”ŠøŠ· <a href=\"$1\">ŠŗŠ»ŠøŠæŠ½Šø эŠ½Š“ŠøрŠøрŠ³Šµ</a> Š½ŠµŠ“Š° ŠŗŠ»ŠøŠæŠ½Šø Š±Ń€Š°ŃƒŠ·ŠµŃ€Š“Šµ Š¾Š¹Š½Š°Ń‚Ń‹Ń€ ючюŠ½ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">Š¾Š¹Š½Š°Ń‚Ń‹ŃƒŃ‡Ńƒ эŠ½Š“ŠøрŠøрŠ³Šµ</a> Š±Š¾Š»Š»ŃƒŠŗъсуŠ·.",
+ "timedmedia-more": "Š­Š½Ń‚Š“Š°ā€¦",
+ "timedmedia-source-file": "$1 ŠŗъŠ°Š¹Š½Š°Š³ŃŠŃ‹",
+ "timedmedia-source-audio-file-desc": "ŠžŃ€ŠøŠ³ŠøŠ½Š°Š» $1-фŠ°Š¹Š» ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/krj.json b/extensions/TimedMediaHandler/i18n/krj.json
new file mode 100644
index 00000000..32fffc84
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/krj.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jose77"
+ ]
+ },
+ "timedmedia-more": "Raku pa..."
+}
diff --git a/extensions/TimedMediaHandler/i18n/ksh.json b/extensions/TimedMediaHandler/i18n/ksh.json
new file mode 100644
index 00000000..0dacd011
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ksh.json
@@ -0,0 +1,81 @@
+{
+ "@metadata": {
+ "authors": [
+ "Purodha"
+ ]
+ },
+ "timedmedia-desc": "E Projamm (<i lang=\"en\">handler</i>) fƶr Meedije met Zickaandeil\nā€” Viddejos, Tondatteieje, <i lang=\"en\">timedText</i> (Ongertittelle) ā€”\nmet Ongershtƶzung fƶr de Fommaate <i lang=\"en\">WebM</i>, <i lang=\"en\">Ogg Theora</i>, <i lang=\"en\">Vorbis</i> un <i lang=\"en\">srt</i>.",
+ "timedmedia-ogg-short-audio": "<i lang=\"en\">Ogg $1</i> Tondatei, $2",
+ "timedmedia-ogg-short-video": "<i lang=\"en\">Ogg $1</i> Viddejodatei, $2",
+ "timedmedia-ogg-short-general": "<i lang=\"en\">Ogg $1</i> Medijedatei, $2",
+ "timedmedia-ogg-long-audio": "<i lang=\"en\">Ogg $1</i> Tondatei fum Ɩmfang $2, $3",
+ "timedmedia-ogg-long-video": "<i lang=\"en\">Ogg $1</i> Viddejodatei fum Ɩmfang $2 un {{PLURAL:$4|ein Pixel|$4 Pixelle|kei Pixel}} Ɨ {{PLURAL:$5|ei Pixel|$4 Pixelle|kei Pixel}}, $3",
+ "timedmedia-ogg-long-multiplexed": "<i lang=\"en\">Ogg</i> jemultipex Ton- un Viddejodatei, $1, fum Ɩmfang $2 un {{PLURAL:$4|ein Pixel|$4 Pixelle|kei Pixel}} Ɨ {{PLURAL:$5|ei Pixel|$4 Pixelle|kei Pixel}}, $3 ennsjesammp",
+ "timedmedia-ogg-long-general": "<i lang=\"en\">Ogg</i> Medijedatei fum Ɩmfang $2, $3",
+ "timedmedia-ogg-long-error": "En kapodde <i lang=\"en\">Ogg</i>-Dattei: $1",
+ "timedmedia-webm-short-video": "En $1 Viddejo-Dattei em WebM-Fommaat vun $2",
+ "timedmedia-webm-long-video": "Ene Viddejo udder en Toondattei em WebM-Fommaat, $1, $2 jruuƟ, $4 Ɨ $5 Pixelle, $3 enƟjesammp",
+ "timedmedia-no-player-js": "Schad, Dinge Brauser hƤt entweder JavaSkrepp uƟjeschalldt udder kein zopaƟ Projramm zom Afschpelle.<br />Do kanns jƤz <a href=\"$1\">dat Stƶck eronger laade</a> udder <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">e Afspeller-Projramm eronger laade</a>, ƶm dat Schtƶk en Dingem Brauser afzeschpelle.",
+ "timedmedia-more": "Enshtelle&nbsp;ā€¦",
+ "timedmedia-dismiss": "Zohmaache!",
+ "timedmedia-download": "Dattei eronger lahde",
+ "timedmedia-play-media": "Afshpelle",
+ "timedmedia-desc-link": "Ɩvver di Dattei",
+ "timedmedia-oggThumb-version": "DƤ <code lang=\"en\">OggHandler</code> bruch <code lang=\"en\">oggThumb</code> in dƤ Version $1 udder hĆ¼Ć¼ter.",
+ "timedmedia-oggThumb-failed": "<code lang=\"en\">oggThumb</code> kunnt kei MiniBelldsche maache.",
+ "timedmedia-status": "Zohschtand",
+ "timedmedia-status-unknown": "Onbikannte Zohschtand",
+ "timedmedia-direct-link": "AfflƤhjer eronger lahde",
+ "timedmedia-not-ready": "Nit parraht",
+ "timedmedia-started-transcode": "De Ɩmwandlong hƤt vƶr $1 bejonne. $2 sin jedonn.",
+ "timedmedia-percent-done": "ƶm de $1% jedonn",
+ "timedmedia-in-job-queue": "En de Waadeschlang met de Aufjahbe jedonn vƶr $1",
+ "timedmedia-days": "{{PLURAL:$1|einem Daach|$1 DƤƤsch|keinem Daach}}",
+ "timedmedia-hours": "{{PLURAL:$1|eine Schtond|$1 Schtonde|keinem Schtond}}",
+ "timedmedia-minutes": "{{PLURAL:$1|eine Menutt|$1 Menutte|keine Menutt}}",
+ "timedmedia-seconds": "{{PLURAL:$1|eine Sekund|$1 Sekunde|keine Sekund}}",
+ "timedmedia-ogg": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"\">Ogg</i>",
+ "timedmedia-webm": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"\">WebM</i>",
+ "timedmedia-mp4": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Moving Picture Experts Group - ā€žExpƤƤtejropp fƶr bewƤƤschte Belderā€œ - VƤsjohn 4\">MP4</i>",
+ "timedmedia-wav": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"RIFF WAVE - Resource Interchange File Format - fƶr de WƤlle vun Tƶhn\">WAV</i>",
+ "timedmedia-flac": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Free Lossless Audio Codec ā€žFreije verloƟfreie Kodehrer un Dekodehrer vun Tƶhnā€œ\">FLAC</i>",
+ "timedmedia-source-file": "Quell-Dattei em $1-Fommaat",
+ "timedmedia-source-file-desc": "Ojinahl $1-Dattei, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Ojinahl $1-Dattei ($2)",
+ "timedmedia-derivative-160p.ogv": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Ogg Vorbis\">Ogg</i> 160P",
+ "timedmedia-derivative-desc-160p.ogv": "En Viddejo-Dattei met winnesch Bandbreide (160P) em <i lang=\"en\">Ogg</i>-Fommaat",
+ "timedmedia-derivative-360p.ogv": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Ogg Vorbis\">Ogg</i> 360P",
+ "timedmedia-derivative-desc-360p.ogv": "En Viddejo-Dattei em <i lang=\"en\">Ogg</i>-Fommaat (360p) fƶr ene Dahteshtrohm ƶvver et Nez",
+ "timedmedia-derivative-480p.ogv": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Ogg Vorbis\">Ogg</i> 480P",
+ "timedmedia-derivative-desc-480p.ogv": "En Viddejo-Dattei (met 480p) em <i lang=\"en\">Ogg</i>-Fommaat fƶr ene Dahteshtrohm ƶvver et Nez",
+ "timedmedia-derivative-720p.ogv": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Ogg Vorbis\">Ogg</i> 720P",
+ "timedmedia-derivative-desc-720p.ogv": "En Viddejo-Dattei met huhe Qualiteit (met 720p) em <i lang=\"en\">Ogg</i>-Fommaat zom eronger laade",
+ "timedmedia-derivative-1080p.ogv": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Ogg Vorbis\">Ogg</i> 1080P",
+ "timedmedia-derivative-desc-1080p.ogv": "Full HD downloadable <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Ogg Vorbis\">Ogg</i> video (1080P)",
+ "timedmedia-derivative-160p.webm": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"WebM\">WebM</i> 160P",
+ "timedmedia-derivative-desc-160p.webm": "Web streamable <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"WebM\">WebM</i> (160P)",
+ "timedmedia-derivative-360p.webm": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"WebM\">WebM</i> 360P",
+ "timedmedia-derivative-desc-360p.webm": "Ene WebM Viddejo (met 360p) fƶr ene Dahteshtrohm ƶvver et Nez",
+ "timedmedia-derivative-480p.webm": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"WebM\">WebM</i> 480P",
+ "timedmedia-derivative-desc-480p.webm": "Ene WebM Viddejo (met 480p) fƶr ene Dahteshtrohm ƶvver et Nez",
+ "timedmedia-derivative-720p.webm": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"WebM\">WebM</i> 720P",
+ "timedmedia-derivative-desc-720p.webm": "En <i lang=\"en\">WebM</i> Viddejo-Dattei met huhe Qualiteit (met 720p) zom eronger laade",
+ "timedmedia-derivative-1080p.webm": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"WebM\">WebM</i> 1080P",
+ "timedmedia-derivative-desc-1080p.webm": "Full HD downloadable <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"WebM\">WebM</i> (1080P)",
+ "timedmedia-derivative-desc-320p.mp4": "Device-friendly <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Moving Picture Experts Group - ā€žExpƤƤtejropp fƶr bewƤƤschte Belderā€œ - VƤsjohn 4\">MP4</i> (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "Web streamable <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Moving Picture Experts Group - ā€žExpƤƤtejropp fƶr bewƤƤschte Belderā€œ - VƤsjohn 4\">MP4</i> (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "HD quality <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Moving Picture Experts Group - ā€žExpƤƤtejropp fƶr bewƤƤschte Belderā€œ - VƤsjohn 4\">MP4</i> (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "Full HD quality <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Moving Picture Experts Group - ā€žExpƤƤtejropp fƶr bewƤƤschte Belderā€œ - VƤsjohn 4\">MP4</i> (1080P)",
+ "timedmedia-derivative-mp3": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Moving Picture Experts Group - ā€žExpƤƤtejropp fƶr bewƤƤschte Belderā€œ - VƤsjohn 3\">MP3</i>",
+ "timedmedia-derivative-desc-mp3": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Moving Picture Experts Group - ā€žExpƤƤtejropp fƶr bewƤƤschte Belderā€œ - VƤsjohn 3\">MP3</i>",
+ "timedmedia-subtitle-new": "Maach en neue ƖvversƤzong udder Ƥnder ein, di et alld jitt",
+ "timedmedia-subtitle-new-desc": "Sƶhg en Schprohch uƟ un klegg op ā€ž{{int:Timedmedia-subtitle-new-go}}ā€œ",
+ "timedmedia-subtitle-new-go": "LohƟ Jonn!",
+ "timedmedia-subtitle-language": "Ongertittele en $1 ($2)",
+ "timedmedia-file": "Dattei",
+ "timedmedia-audios": "{{PLURAL:$1|Ein Tohndattei|$1 Tohndatteije|kein Tohndattei}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|Ein Tohndattei|$1 Tohndatteije|kein Tohndattei}} em <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Ogg Vorbis\">Ogg</i>-Fommaht",
+ "timedmedia-flac-audios": "{{PLURAL:$1|Ein Tohndattei|$1 Tohndatteije|kein Tohndattei}} em <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Free Lossless Audio Codec ā€žFreije verloƟfreie Kodehrer un Dekodehrer vun Tƶhnā€œ\">FLAC</i>-Fommaht",
+ "timedmedia-wav-audios": "{{PLURAL:$1|Ein Tohndattei|$1 Tohndatteije|kein Tohndattei}} em <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"RIFF WAVE - Resource Interchange File Format - fƶr de WƤlle vun Tƶhn\">WAV</i>-Fommaht",
+ "apihelp-transcodereset-param-title": "De Ɩvverschreff vun dƤ Mehdijedattei."
+}
diff --git a/extensions/TimedMediaHandler/i18n/ku-latn.json b/extensions/TimedMediaHandler/i18n/ku-latn.json
new file mode 100644
index 00000000..48f4f644
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ku-latn.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "BikarhĆŖner",
+ "George Animal"
+ ]
+ },
+ "timedmedia-more": "ZĆŖdetir...",
+ "timedmedia-dismiss": "Bigre",
+ "timedmedia-download": "DosyeyĆŖ daxe",
+ "timedmedia-desc-link": "Di derbarĆŖ vĆŖ dosyeyĆŖ de",
+ "timedmedia-source-file": "ƧavkanƮ $1",
+ "timedmedia-source-audio-file-desc": "Dosyeye orijƮnal a $1 ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ky.json b/extensions/TimedMediaHandler/i18n/ky.json
new file mode 100644
index 00000000..79dce232
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ky.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Janatkg"
+ ]
+ },
+ "timedmedia-source-file": "$1 Š±ŃƒŠ»Š°ŠŗтŠ°Š½"
+}
diff --git a/extensions/TimedMediaHandler/i18n/la.json b/extensions/TimedMediaHandler/i18n/la.json
new file mode 100644
index 00000000..ae42c49c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/la.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "SPQRobin",
+ "UV"
+ ]
+ },
+ "timedmedia-more": "Plusā€¦"
+}
diff --git a/extensions/TimedMediaHandler/i18n/lad.json b/extensions/TimedMediaHandler/i18n/lad.json
new file mode 100644
index 00000000..082e7dcb
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/lad.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Menachem.Moreira",
+ "Universal Life"
+ ]
+ },
+ "timedmedia-subtitle-new-go": "Ir",
+ "timedmedia-file": "Dosya"
+}
diff --git a/extensions/TimedMediaHandler/i18n/lb.json b/extensions/TimedMediaHandler/i18n/lb.json
new file mode 100644
index 00000000..0a3c78c8
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/lb.json
@@ -0,0 +1,73 @@
+{
+ "@metadata": {
+ "authors": [
+ "Les Meloures",
+ "Robby"
+ ]
+ },
+ "timedmedia-desc": "Steierungsprogramm fir Audio, Video an 'timed text', mat ƋnnerstĆ«tzung vun de Formater WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Ogg-$1-Tounfichier, $2",
+ "timedmedia-ogg-short-video": "Ogg-$1-Videofichier, $2",
+ "timedmedia-ogg-short-general": "Ogg-$1-Mediefichier, $2",
+ "timedmedia-ogg-long-audio": "tmh-$1-Tounfichier, Dauer: $2, $3",
+ "timedmedia-ogg-long-video": "Ogg-$1-Videofichier, Dauer: $2, $4Ɨ$5 Pixel, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg-Toun-/Video-Fichier, $1, Dauer: $2, $4Ɨ$5 Pixel, $3",
+ "timedmedia-ogg-long-general": "Ogg Media-Fichier, Dauer $2, $3",
+ "timedmedia-ogg-long-error": "Ongƫltegen Ogg-Fichier: $1",
+ "timedmedia-webm-short-video": "WebM $1 Video Fichier, $2",
+ "timedmedia-webm-long-video": "WebM-Audio/Video-Fichier, $1, Dauer $2, $4Ɨ$5 Pixel, $3 am Ganzen",
+ "timedmedia-flac-short-audio": "FLAC-Audiofichier, $1",
+ "timedmedia-flac-long-audio": "FLAC-audiofichier, LƤngt $1, $2 am Ganzen",
+ "timedmedia-wav-short-audio": "WAV-Audiofichier, $1",
+ "timedmedia-mp4-short-video": "MP4 $1 Videofichier, $2",
+ "timedmedia-no-player-js": "Pardon, Ƅre Browser huet entweder JavaScript ausgeschalt oder en huet kee Player-Programm deen Ć«nnerstĆ«tzt gĆ«tt.<br />\nDir kĆ«nnt <a href=\"$1\"> de Clip eroflueden</a> oder <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">e Player-Programm erofluede</a> fir de Clip an Ƅrem Browser ze spillen.",
+ "timedmedia-more": "MĆ©i ...",
+ "timedmedia-dismiss": "Zoumaachen",
+ "timedmedia-download": "Fichier eroflueden",
+ "timedmedia-desc-link": "Iwwer dƫse Fichier",
+ "timedmedia-oggThumb-version": "Den OggHandler brauch d'Versioun $1 (oder mƩi eng nei Versioun) vun OggThumb.",
+ "timedmedia-oggThumb-failed": "oggThumb konnt d'Miniaturbild (thumbnail) net uleeƫn.",
+ "timedmedia-status": "Status",
+ "timedmedia-status-unknown": "Onbekannte Status",
+ "timedmedia-transcodeinfo": "Format",
+ "timedmedia-actions": "Aktiounen",
+ "timedmedia-direct-link": "Eroflueden",
+ "timedmedia-not-ready": "Net fƤerdeg",
+ "timedmedia-completed-on": "FƤerdeg den $1",
+ "timedmedia-error-on": "Feeler op $1",
+ "timedmedia-started-transcode": "Ugefaang viru(n) $1. $2",
+ "timedmedia-percent-done": "OngefƩier $1% fƤerdeg",
+ "timedmedia-days": "{{PLURAL:$1|1 Dag|$1 Deeg}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 Stonn|$1 Stonnen}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 Minutt|$1 Minutten}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 Sekonn|$1 Sekonnen}}",
+ "timedmedia-reset": "Transcode zrƩcksetzen",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Quell ($1)",
+ "timedmedia-source-file-desc": "Original $1 Fichier, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Original $1 Fichier ($2)",
+ "timedmedia-derivative-desc-240p.ogv": "Ogg-Video (240P) deen iwwer de Web gestreamt gi kann",
+ "timedmedia-derivative-360p.vp9.webm": "VP9 360P",
+ "timedmedia-derivative-480p.vp9.webm": "VP9 480P",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "Komplette streamfƤege 4K-WebM-VP9-Video (2160P)",
+ "timedmedia-derivative-desc-720p.mp4": "HD-QualitƩit MP4 (720P)",
+ "timedmedia-derivative-desc-2160p.mp4": "Komplette 4K MP4-QualitƩitsvideo (2160P)",
+ "timedmedia-subtitle-new": "Nei Iwwersetzung maachen oder eng dƩi et gƫtt Ƥnneren",
+ "timedmedia-subtitle-new-desc": "Sicht d'Sprooch eraus an drƩckt de KnƤppchen ''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Lass",
+ "timedmedia-subtitle-language": "$1 ($2) Ƌnnertitelen",
+ "timedmedia-subtitle-no-video": "Et ass kee Video mat der aktueller SƤit vun Ƌnnertitelen associĆ©iert.",
+ "timedmedia-subtitle-no-subtitles": "Et sinn elo keng Ƌnnertitelen op $1 fir dĆ«se Video, Dir kĆ«nnt [{{fullurl:{{FULLPAGENAME}}|action=edit}} dĆ«s SƤit Ƥnneren] fir se derbƤizesetzen",
+ "timedmedia-subtitle-remote-link": "Dir kƫnnt [$1 d'BeschreiwungssƤit] fir dƫse Fichier op $2 gesinn",
+ "timedmedia-videos": "{{PLURAL:$1|$1 Video|$1 Videoen}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg Video|$1 Ogg Videoen}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM Video|$1 WebM Videoen}}",
+ "timedmedia-file": "Fichier",
+ "timedmedia-audios": "{{PLURAL:$1|$1 Audio-Fichier|$1 Audio-Fichieren}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ogg Audio-Fichier|$1 Ogg Audio-Fichieren}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 FLAC Audio-Fichier|$1 FLAC Audio-Fichieren}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 WAV Audio-Fichier|$1 WAV Audio-Fichieren}}",
+ "orphanedtimedtext-unsupported": "Dƫs SpezialsƤit funktionƩiert nƫmme mat MySQL Datebanken.",
+ "orphanedtimedtext-notimedtext": "TimedText ass op dƫser Wiki net aktivƩiert.",
+ "apihelp-transcodereset-param-title": "Den Titel vum Mediefichier."
+}
diff --git a/extensions/TimedMediaHandler/i18n/lfn.json b/extensions/TimedMediaHandler/i18n/lfn.json
new file mode 100644
index 00000000..23c9c268
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/lfn.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Malafaya"
+ ]
+ },
+ "timedmedia-more": "Pluā€¦"
+}
diff --git a/extensions/TimedMediaHandler/i18n/li.json b/extensions/TimedMediaHandler/i18n/li.json
new file mode 100644
index 00000000..2f63a4cd
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/li.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "Matthias",
+ "Ooswesthoesbes"
+ ]
+ },
+ "timedmedia-desc": "Handelt Ogg Theora- en Vorbis-bestande aaf met 'n JavaScript-mediaspeler",
+ "timedmedia-ogg-short-audio": "Ogg $1 geluidsbestandj, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 videobestandj, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 mediabestandj, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 geluidsbestandj, lingdje $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 videobestandj, lingdje $2, $4Ɨ$5 pixels, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg gemultiplexeerd geluids-/videobestandj, $1, lingdje $2, $4Ɨ$5 pixels, $3 totaal",
+ "timedmedia-ogg-long-general": "Ogg mediabestandj, lingdje $2, $3",
+ "timedmedia-ogg-long-error": "Ɠngeljig oggg-bestandj: $1",
+ "timedmedia-more": "Mieƫ...",
+ "timedmedia-dismiss": "Sloet",
+ "timedmedia-download": "Bestandj downloade",
+ "timedmedia-desc-link": "Euver dit bestandj"
+}
diff --git a/extensions/TimedMediaHandler/i18n/lrc.json b/extensions/TimedMediaHandler/i18n/lrc.json
new file mode 100644
index 00000000..b897768a
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/lrc.json
@@ -0,0 +1,44 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bonevarluri",
+ "Mogoeilor"
+ ]
+ },
+ "timedmedia-ogg-short-audio": "Ų¬Ų§Ł†ŪŒŲ§ ŲÆŁ†ŚÆ Ų§ŁˆŚÆ $1ŲŒ$2",
+ "timedmedia-ogg-short-video": "Ogg $1 Ų¬Ų§Ł†ŪŒŲ§ ŁˆŪŒŲÆŪŒŁˆ, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 Ų¬Ų§Ł†ŪŒŲ§ ŁˆŲ§Ų±Ų³ŚÆŲ± , $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 Ų¬Ų§Ł†ŪŒŲ§ ŲÆŁ†ŚÆ , ŲÆŲ±Ų§Ų²Ų§ $2, $3",
+ "timedmedia-ogg-long-error": "Ų¬Ų§Ł†ŪŒŲ§ ŲÆŁ†ŚÆ Ų§ŁˆŚÆ Ł†Ų§Ł…Ų¹ŲŖŁˆŲ±:$1",
+ "timedmedia-webm-short-video": "WebM $1 Ų¬Ų§Ł†ŪŒŲ§ ŁˆŪŒŲÆŪŒŁˆ, $2",
+ "timedmedia-flac-short-audio": "FLAC Ų¬Ų§Ł†ŪŒŲ§ ŲÆŁ†ŚÆŲÆŲ§Ų± , $1",
+ "timedmedia-wav-short-audio": "WAV Ų¬Ų§Ł†ŪŒŲ§ ŲÆŁ†ŚÆŲÆŲ§Ų±, $1",
+ "timedmedia-wav-pcm-required": "Ų“Ł…Ų§ ŁŁ‚Ų· ŲŖŁˆŁ†ŪŒŲŖ Ł¾ŪŒ Ų³ŪŒ Ų§Ł… Ł†Ł‡ Ų³ŁˆŲ§Ų± ŲØŚ©ŪŒŲÆ",
+ "timedmedia-mp4-short-video": "MP4 $1 Ų¬Ų§Ł†ŪŒŲ§ ŁˆŪŒŲÆŪŒŁˆ, $2",
+ "timedmedia-no-player-js": "ŲÆ ŲØŲÆŲØŲ®ŲŖŪŒ ŲÆŁˆŲ§Ų±ŲŖŁ‡ Ł†ŪŒŲ¦Ų± ŲÆ Ł„Ų­Ų§Ųø Ų¬Ų§ŁˆŲ§ Ł†ŪŒŲ³Ų³Ł‡ Ł†Ų§Ś©Ų“ŲŖŚÆŲ± ŲØŪŒŁ‡ ŪŒŲ§ Ų“Ų§ŪŒŲŖ Ų­Ų§Ł…ŪŒŁ†ŲÆŲ§Ų± Ł‡ŪŒŚ† ŲÆŁ†ŚÆŪŒŲ§Ų±ŪŒ Ł†Ų¦.<br />\nŲ“Ł…Ų§ Ł…ŪŒ ŲŖŁˆŁ†ŪŒŲŖ<a href=\"$1\">Ś©Ł„ŪŒŁ¾ Ł†Ł‡ ŲØŚÆŲ±ŪŒŲŖ</a> ŪŒŲ§<a <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ŪŒŁ‡ ŚÆŁ„ ŲÆŁ†ŚÆŪŒŲ§Ų± Ł†Ł‡ ŲØŚÆŲ±ŪŒŲŖ</a> Ų³ŪŒ ŪŒŁ‡ Ś©Ł‡ Ś©Ł„ŪŒŁ¾ Ł†Ł‡ ŲÆ ŲÆŁˆŲ§Ų±ŲŖŁ‡ Ł†ŪŒŲ¦Ų±ŲŖŁˆ ŲØŁ‡ ŁˆŁ†ŪŒŲŖ..",
+ "timedmedia-more": "ŲØŪŒŲ“ŲŖŲ±....",
+ "timedmedia-dismiss": "ŲØŲ³Ł†",
+ "timedmedia-download": "ŚÆŲ±ŲŖŁ† Ų¬Ų§Ł†ŪŒŲ§",
+ "timedmedia-play-media": "Ų±ŁˆŲ“Ł† Ś©Ų±ŲÆŁ† ŁˆŲ§Ų±Ų³ŚÆŲ±",
+ "timedmedia-desc-link": "ŲÆŲØŲ§Ų±Ł‡ Ų§ŪŒ Ų¬Ų§Ł†ŪŒŲ§",
+ "timedmedia-status": "Ų­Ų§Ł„ ŁˆŲØŲ§Ł„",
+ "timedmedia-status-unknown": "Ų­Ų§Ł„ Łˆ ŲØŲ§Ł„ Ł†Ų§ŲÆŪŒŲ§Ų±",
+ "timedmedia-actions": "Ś©Ł†Ų“ŚÆŲ±ŪŒŲ§",
+ "timedmedia-not-ready": "Ų¢Ł…Ų§ŲÆŁ‡ Ł†Ų¦",
+ "timedmedia-percent-done": "ŲÆ Ų­ŲÆŁˆŲÆ $1% Ų§Ł†Ų¬ŁˆŁ… ŲØŪŒ",
+ "timedmedia-days": "{{PLURAL:$1|1 Ų±ŁˆŲ²|$1 Ų±ŁˆŲ²}}",
+ "timedmedia-hours": "{{PLURAL:$1|$1 Ų³Ų§Ų¹ŲŖ|$1 Ų³Ų§Ų¹ŲŖ ŪŒŲ§}}",
+ "timedmedia-minutes": "{{PLURAL:$1|$1 ŲÆŪŒŁ‚Ł‡|$1 ŲÆŪŒŁ‚Ł‡ ŪŒŲ§}}",
+ "timedmedia-seconds": "{{PLURAL:$1|$1 Ų«Ų§Ł†ŪŒŁ‡|$1 Ų«Ų§Ł†ŪŒŁ‡ ŪŒŲ§}}",
+ "timedmedia-source-file": "Ų³Ų±Ś†Ų“Ł…Ł‡ $1",
+ "timedmedia-source-file-desc": "Ų§ŲµŁ„ŪŒ $1 Ų¬Ų§Ł†ŪŒŲ§, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Ų¬Ų§Ł†ŪŒŲ§ Ų§ŲµŁ„ŪŒ$1 ($2)",
+ "timedmedia-subtitle-new-go": "Ų±Ų¤",
+ "timedmedia-subtitle-language": "$1 ($2) Ų²ŪŒŲ±Ł†ŪŒŲ³",
+ "timedmedia-videos": "{{PLURAL:$1|$1 ŁˆŪŒŲÆŪŒŁˆ|$1 ŁˆŪŒŲÆŪŒŁˆŪŒŲ§}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg ŁˆŪŒŲÆŪŒŁˆ|$1 Ogg ŁˆŪŒŲÆŪŒŁˆŪŒŲ§}}",
+ "timedmedia-file": "Ų¬Ų§Ł†ŪŒŲ§",
+ "timedmedia-audios": "{{PLURAL:$1|$1 Ų¬Ų§Ł†ŪŒŲ§ ŲÆŁ†ŚÆŲÆŲ§Ų±|$1 Ų¬Ų§Ł†ŪŒŲ§ŪŒŲ§ ŲÆŁ†ŚÆŲÆŲ§Ų±}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ų¬Ų§Ł†ŪŒŲ§ ŲÆŁ†ŚÆ Ł†ŚÆŲÆŲ§Ų± Ų§ŁŚÆ|$1 Ų¬Ų§Ł†ŪŒŲ§ŪŒŲ§ ŲÆŁ†ŚÆŲÆŲ§Ų± Ų§ŁŚÆ}}",
+ "apihelp-transcodereset-param-title": "ŲÆŲ§Ų³ŁˆŁ† Ų¬Ų§Ł†ŪŒŲ§ ŁˆŲ§Ų±Ų³ŚÆŲ±."
+}
diff --git a/extensions/TimedMediaHandler/i18n/lt.json b/extensions/TimedMediaHandler/i18n/lt.json
new file mode 100644
index 00000000..bee1ed8d
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/lt.json
@@ -0,0 +1,123 @@
+{
+ "@metadata": {
+ "authors": [
+ "Homo",
+ "Matasg",
+ "Hugo.arg",
+ "Albertas"
+ ]
+ },
+ "timedmedia-desc": "Audio, video ir teksto su laiku doroklė, kuri palaiko WebM, Ogg Theora, Vorbis, srt formatus",
+ "timedmedia-ogg-short-audio": "Ogg $1 garso byla, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 video byla, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 medija byla, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 garso byla, ilgis $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 video byla, ilgis $2, $4Ɨ$5 pikseliai, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg sutankinta audio/video byla, $1, ilgis $2, $4Ɨ$5 pikseliai, $3 viso",
+ "timedmedia-ogg-long-general": "Ogg media byla, ilgis $2, $3",
+ "timedmedia-ogg-long-error": "Bloga ogg byla: $1",
+ "timedmedia-ogg-long-no-streams": "Ogg medijos failas. Įspėjimas: nei vienas faile naudojamas kodavimo standartas nebuvo atpažintas.",
+ "timedmedia-webm-short-video": "WebM $1 video failas, $2",
+ "timedmedia-webm-long-video": "WebM audio/video failas, $1, ilgio $2, $4 Ɨ $5 pikselių, $3 iÅ”viso",
+ "timedmedia-flac-short-audio": "FLAC audio failas, $1",
+ "timedmedia-flac-long-audio": "FLAC audio failas, ilgio $1, $2 iÅ” viso",
+ "timedmedia-wav-short-audio": "WAV audio failas, $1",
+ "timedmedia-wav-long-audio": "WAV audio failas, ilgio $1, $2 iÅ” viso",
+ "timedmedia-wav-pcm-required": "Galite ÄÆkelti tik PCM (Pulse Code Modulation) WAV.",
+ "timedmedia-mp4-short-video": "MP4 $1 video failas, $2",
+ "timedmedia-mp4-long-video": "MP4 audio/video failas, $1, ilgio $2, $4 Ɨ $5 pikselių, $3 iÅ” viso",
+ "timedmedia-no-player-js": "AtsipraÅ”ome, bet jÅ«sų narÅ”yklėje arba iÅ”jungtas JavaScript, arba neturi jokio palaikomo grotuvo.<br />\nJÅ«s galite <a href=\"$1\">atsisiųsti ÄÆraŔą</a> arba <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">grotuvą</a>, kad galėtumėte leisti ÄÆraŔą savo narÅ”yklėje.",
+ "timedmedia-more": "Daugiau...",
+ "timedmedia-dismiss": "Uždaryti",
+ "timedmedia-download": "Atsisiųsti bylą",
+ "timedmedia-play-media": "Groti mediją",
+ "timedmedia-desc-link": "Apie Å”ią bylą",
+ "timedmedia-oggThumb-version": "OggHandler reikalauja oggThumb $1 versijos arba vėlesnės.",
+ "timedmedia-oggThumb-failed": "oggThumb nepavyko sukurti miniatiūros.",
+ "timedmedia-status-header": "Perkodavimo statusas",
+ "timedmedia-update-status": "Atnaujinti perkodavimo statusą",
+ "timedmedia-status": "BÅ«sena",
+ "timedmedia-status-unknown": "Nežinomas statusas",
+ "timedmedia-transcodebitrate": "Kokybė",
+ "timedmedia-transcodeduration": "Kodavimo laikas",
+ "timedmedia-transcodeinfo": "Formatas",
+ "timedmedia-actions": "Veiksmai",
+ "timedmedia-direct-link": "Atsisiųsti",
+ "timedmedia-not-ready": "NeparuoŔta",
+ "timedmedia-completed-on": "Baigta $1",
+ "timedmedia-error-on": "Klaida $1",
+ "timedmedia-started-transcode": "Pradėta prieÅ” $1. $2",
+ "timedmedia-percent-done": "Atlikta apie $1%",
+ "timedmedia-in-job-queue": "Pridėta prie darbų eilės prieÅ” $1",
+ "timedmedia-unknown-target-size": "Nežinomas rezultato dydis, $1 užkoduota",
+ "timedmedia-days": "{{PLURAL:$1|1 diena|$1 dienos}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 valanda|$1 valandos}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minutė|$1 minutės}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 sekundė|$1 sekundės}}",
+ "timedmedia-reset": "Atstatyti perkodavimą",
+ "timedmedia-reset-confirm": "Å io perkodavimo atstatymas paÅ”alins visus egzistuojančius failus (jeigu jų yra) ir vėl pridės perkodavimą ÄÆ darbų eilę. Perkodavimas užtruks kažkiek laiko.<br /><br />\nAr tikrai norite tęsti?",
+ "timedmedia-reset-error": "Klaida perkodavimo atstatymo užduotyje.",
+ "timedmedia-source-file": "$1 Ŕaltinis",
+ "timedmedia-source-file-desc": "Originalus $1 failas, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Pirminė $1 rinkmena ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Žemo pralaidumo Ogg video (160P)",
+ "timedmedia-derivative-desc-240p.ogv": "Internetu transliuotinas Ogg video (240P)",
+ "timedmedia-derivative-desc-360p.ogv": "Internetu transliuotinas Ogg video (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Internetu transliuotinas Ogg video (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "AukÅ”tos kokybės atsisiųstinas Ogg video (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "VisiÅ”kai aukÅ”tos kokybės atsisiųstinas Ogg video (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "Internetu transliuotinas WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "Internetu transliuotinas WebM (360P)",
+ "timedmedia-derivative-desc-480p.webm": "Internetu transliuotinas WebM (480P)",
+ "timedmedia-derivative-desc-720p.webm": "AukÅ”tos kokybės atsisiųstinas WebM (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "VisiÅ”kai aukÅ”tos kokybės atsisiųstinas WebM (1080P)",
+ "timedmedia-derivative-desc-2160p.webm": "Pilnai 4K atsisiųstinas WebM (2160P)",
+ "timedmedia-derivative-desc-360p.vp9.webm": "Internetu transliuotinas WebM VP9 (360P)",
+ "timedmedia-derivative-desc-480p.vp9.webm": "Internetu transliuotinas WebM VP9 (480P)",
+ "timedmedia-derivative-desc-720p.vp9.webm": "AukÅ”tos kokybės transliuotinas WebM VP9 (720P)",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "VisiÅ”kai aukÅ”tos kokybės transliuotinas WebM VP9 (1080P)",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "Pilnai 4K transliuotinas WebM VP9 (2160P)",
+ "timedmedia-derivative-desc-320p.mp4": "Įrenginiams draugiŔkas MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "Internetu transliuotinas MP4 (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "AukÅ”tos kokybės MP4 (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "VisiÅ”kai aukÅ”tos kokybės MP4 (1080P)",
+ "timedmedia-derivative-desc-2160p.mp4": "Pilnos 4K kokybės MP4 (2160P)",
+ "timedmedia-subtitle-new": "Sukurti naują vertimą arba redaguoti egzistuojantÄÆ",
+ "timedmedia-subtitle-new-desc": "Pasirinkite kalbą ir paspauskite '''{{int:Timedmedia-subtitle-new-go}}''' mygtuką",
+ "timedmedia-subtitle-new-go": "Vykdyti",
+ "timedmedia-subtitle-language": "$1 ($2) subtitrai",
+ "timedmedia-subtitle-no-video": "Nėra video, susieto su dabartiniu subtitrų puslapiu.",
+ "timedmedia-subtitle-no-subtitles": "Kol kas Å”iam video nėra subtitrų $1, bet JÅ«s galite [{{fullurl:{{FULLPAGENAME}}|action=edit}} redaguoti Å”ÄÆ puslapÄÆ], norėdami juos pridėti.",
+ "timedmedia-subtitle-remote": "Å io failo tekstas su laiku yra patalpintas $1",
+ "timedmedia-subtitle-remote-link": "Galite [$1 peržiÅ«rėti Å”io failo apraÅ”ymo puslapÄÆ] $2",
+ "timedmediahandler": "MedijosSuLaikuDoroklis",
+ "timedmedia-videos": "{{PLURAL:$1|$1 video|$1 video failai}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg video|$1 Ogg video failai}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM video|$1 WebM video failai}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 perkodavimas|$1 perkodavimai}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 vykdomas perkodavimas|$1 vykdomi perkodavimai}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 ieŔkomas perkodavimas|$1 ieŔkomi perkodavimai}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 nepavykęs perkodavimas|$1 nepavykę perkodavimai}}",
+ "timedmedia-file": "Failas",
+ "timedmedia-audios": "{{PLURAL:$1|$1 audio failas|$1 audio failai}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ogg audio failas|$1 Ogg audio failai}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 FLAC audio failas|$1 FLAC audio failai}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 WAV audio failas|$1 WAV audio failai}}",
+ "right-transcode-reset": "Atstatymas nepavyko arba video failai buvo perkoduoti, todėl jie vėl buvo pridėti ÄÆ darbų eilę",
+ "right-transcode-status": "Peržiūrėti [[Special:TimedMediaHandler|informaciją apie dabartines perkodavimo veiklas]]",
+ "action-transcode-status": "peržiūrėti dabartinę perkodavimo būseną",
+ "orphanedtimedtext": "Pamesto teksto su laiku puslapiai",
+ "orphanedtimedtext-summary": "SąraÅ”as [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] puslapių, kurie neturi atitinkamų failų.",
+ "orphanedtimedtext-unsupported": "Šis specialus puslapis palaiko tik MySQL duomenų bazes.",
+ "orphanedtimedtext-notimedtext": "Tekstas su laiku nėra aktyvuotas Å”iame vikyje.",
+ "apihelp-query+transcodestatus-description": "Gauti perkodavimo statusą pateiktajam failo puslapiui.",
+ "apihelp-query+transcodestatus-example-1": "Gauti perkodavimo būseną [[:File:Clip.webm]]",
+ "apihelp-query+videoinfo-description": "Papildo paveikslėlio informaciją, kad bÅ«tų pridėta video Å”altinio (iÅ”vestinio) informacija",
+ "apihelp-query+videoinfo-param-prop": "Kurią video informaciją norite gauti:\n;timestamp:Prideda ÄÆkeltosios versijos laiko žymę.\n;user:Prideda naudotoją, kuris ÄÆkėlė video versiją.\n;userid:Prideda ID naudotojo, kuris ÄÆkėlė video versiją.\n;comment:Versijos komentaras.\n;parsedcomment:Apdorotas versijos komentaras.\n;canonicaltitle:Prideda kanoninÄÆ video failo pavadinimą.\n;url:Pateikia URL, nukreipiantÄÆ ÄÆ video ir apraÅ”ymo puslapÄÆ.\n;size:Prideda video dydÄÆ baitais, jo aukÅ”tÄÆ ir plotÄÆ. Puslapio skaitliukas ir trukmė yra pridedami, jeigu prieinama.\n;dimensions:Dydžio alternatyva.\n;sha1:Prideda video SHA-1 maiÅ”os funkcijos reikÅ”mę.\n;mime:Prideda video MIME tipą.\n;thumbmime:Prideda video MIME tipo miniatiÅ«rą (reikalauja URL ir parametro $1urlwidth).\n;mediatype:Prideda video medijos tipą.\n;metadata:Pateikia video versijos Exif metaduomenų sąraŔą.\n;commonmetadata:Pateikia video versijos failo formatų bendrų metaduomenų sąraŔą.\n;extmetadata:Pateikia formatuotų metaduomenų sąraŔą, sukombinuotą iÅ” skirtingų Å”altinių. Rezultatas yra suformatuotas HTML.\n;archivename:Prideda ne paskutinių versijų archyvo failo vardą.\n;bitdepth:Prideda versijos bitų gilumą.\n;uploadwarning:Naudojamas [[Special:Upload]] puslapyje gauti informacijai apie egzistuojantÄÆ failą. Nėra skirtas naudojimui MediaWiki branduolio iÅ”orėje.\n;derivatives:Prideda skirtingų prieinamų audio ir video failų formatų ir kokybės versijų sąraŔą.",
+ "apihelp-query+videoinfo-example-1": "Gauti informaciją apie [[:File:Folgers.ogv]]",
+ "apihelp-transcodereset-description": "Naudotojai turintys 'perkodavimo-atsatymo' teises gali atstatyti ir pakartotinai paleisti perkodavimo užduotÄÆ.",
+ "apihelp-transcodereset-param-title": "Medijos failo pavadinimas.",
+ "apihelp-transcodereset-param-transcodekey": "Perkodavimo raktas, kurÄÆ norite atstatyti. Galite paimti iÅ” [[Special:ApiHelp/query+transcodestatus|action=query&prop=transcodestatus]].",
+ "apihelp-transcodereset-example-1": "Atstatyti visus [[:File:Clip.webm]] perkodavimus",
+ "apihelp-transcodereset-example-2": "Atstatyti '360_560kbs.webm' perkodavimo raktą [[:File:Clip.webm]]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/luz.json b/extensions/TimedMediaHandler/i18n/luz.json
new file mode 100644
index 00000000..4ab30bc0
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/luz.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ų¹Ł„ŪŒ Ų³Ų§Ś©ŪŒ Ł„Ų±Ų³ŲŖŲ§Ł†ŪŒ"
+ ]
+ },
+ "timedmedia-no-player-js": "Ū‰Ų§Ų³ŪŒ Ū‰ŲØŲ®Ų“ŪŒŲŖŲŒŁ…Ų±Ū‰Ų±ŚÆŲ± Ų§ŪŒŲ“Ų§ Ū‰Ś¾ ŲµŪ‰Ų±ŲŖ Ų¬Ų§Ū‰Ų§ Ų§Ų³Ś©Ų±ŪŒŁ¾ŲŖ ŲŗŪŒŲ±ŁŲ¹Ų§Ł„ Ū‰Ų§ŲØŪŒŲÆŚ¾ Ū‰ Ł‡ŪŒŚ† Ł¾Ł„ŪŒŲ± Ł¾Ų“ŲŖŪŒŲØŲ§Ł†ŪŒ Ł†Ų§Ų±Ś¾.<br /> Ų§ŪŒŲ“Ų§ Ū‰Ų§ Ś©Ł„ŪŒŚ˜ Ų±ŪŒ Ų§ŪŒ Ų§ŪŒŲŖŲ±ŪŒŲÆ <a href=\"$1\">download the clip</a> or <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">download a player</a> Ś©Ł„ŪŒŁ¾Ł†Ł‡ Ł…Ų¦Ł†Ł‡ Ł…Ų±Ū‰Ų±ŚÆŲ± Ų®Ū‰ŲŖŪ‰Ł† Ł¾Ų®Ų“ Ś©Ł†ŪŒŲŖ.",
+ "timedmedia-source-file": "$1 Ų³Ų±Ś†Ų“Ł…Ł‡",
+ "timedmedia-source-audio-file-desc": "Ų§ŲµŁ„ŪŒ $1 ŁŲ§ŪŒŁ„ ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/lv.json b/extensions/TimedMediaHandler/i18n/lv.json
new file mode 100644
index 00000000..9554b20b
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/lv.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Papuass",
+ "Xil",
+ "Silraks"
+ ]
+ },
+ "timedmedia-more": "Vairāk...",
+ "timedmedia-dismiss": "Aizvērt",
+ "timedmedia-download": "Lejupielādēt failu",
+ "timedmedia-desc-link": "Par Ŕo failu",
+ "timedmedia-status": "Statuss",
+ "timedmedia-status-unknown": "Nezināms statuss",
+ "timedmedia-transcodeinfo": "Formāts",
+ "timedmedia-actions": "Darbības",
+ "timedmedia-direct-link": "Lejupielādēt",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 avots",
+ "timedmedia-subtitle-new-go": "Aiziet!",
+ "timedmedia-subtitle-language": "$1 ($2) subtitri"
+}
diff --git a/extensions/TimedMediaHandler/i18n/mai.json b/extensions/TimedMediaHandler/i18n/mai.json
new file mode 100644
index 00000000..7d189ffd
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/mai.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "ą¤¬ą¤æą¤Ŗą„ą¤²ą¤¬ ą¤†ą¤Øą¤Øą„ą¤¦"
+ ]
+ },
+ "timedmedia-no-player-js": "ą¤•ą„ą¤·ą¤®ą¤¾ ą¤•ą¤°ą„‚, ą¤…ą¤¹ą¤¾ą¤ą¤•ą„‡ ą¤¬ą„ą¤°ą¤¾ą¤‰ą¤œą¤° ą¤®ą„‡ą¤‚ ą¤Æą¤¾ ą¤¤ ą¤œą¤¾ą¤µą¤¾ą¤øą„ą¤•ą„ą¤°ą¤æą¤Ŗą„ą¤Ÿ ą¤…ą¤•ą„ą¤·ą¤® ą¤…ą¤›ą¤æ ą¤Æą¤¾ ą¤øą¤®ą¤°ą„ą¤„ą¤æą¤¤ ą¤Ŗą„ą¤²ą„‡ą¤Æą¤° ą¤Øą„ˆ ą¤…ą¤›ą¤æą„¤<br />\ną¤…ą¤¹ą¤¾ą¤ <a href=\"$1\">ą¤•ą„ą¤²ą¤æą¤Ŗą¤•ą„‡ ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤”</a> ą¤•ą„ˆą¤° ą¤øą¤•ą„ˆ ą¤›ą„€ ą¤µą¤¾ ą¤•ą„ą¤²ą¤æą¤Ŗą¤•ą„‡ ą¤…ą¤Ŗą¤Ø ą¤¬ą„ą¤°ą¤¾ą¤‰ą¤œą¤°ą¤®ą„‡ą¤‚ ą¤šą¤²ą¤¾ą¤µą¤¾ą¤• ą¤²ą„‡ą¤² <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ą¤ą¤• ą¤Ŗą„ą¤²ą„‡ą¤Æą¤° ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤”</a> ą¤•ą„ˆą¤° ą¤øą¤•ą„ˆ ą¤›ą„€ą„¤",
+ "timedmedia-source-file": "$1 ą¤øą„ą¤°ą„‹ą¤¤",
+ "timedmedia-source-audio-file-desc": "ą¤®ą„‚ą¤² $1 ą¤«ą¤¾ą¤‡ą¤² ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/mg.json b/extensions/TimedMediaHandler/i18n/mg.json
new file mode 100644
index 00000000..ed53f4f9
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/mg.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jagwar"
+ ]
+ },
+ "timedmedia-no-player-js": "Miala tsiny indrindra, na tsy mampiasa JavaScript ny mpitety tranonkalanao, na tsy manana mpamaky zaka ilay izy.<br />\nAzonao atao ny <a href=\"$1\">mampidina ilay kilipy</a> na <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">mampidina mpamaky iray</a> hamakiana ilay kilipy eo amin'ny mpitetinao.",
+ "timedmedia-source-file": "Fango $1",
+ "timedmedia-source-audio-file-desc": "Rakitra niaviana $1 ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/min.json b/extensions/TimedMediaHandler/i18n/min.json
new file mode 100644
index 00000000..5b8b13a5
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/min.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Iwan Novirion"
+ ]
+ },
+ "timedmedia-transcodeinfo": "Deskripsi turunan transkoder",
+ "timedmedia-ogg": "Ogg",
+ "timedmedia-webm": "WebM",
+ "timedmedia-derivative-160p.ogv": "Ogg 160p",
+ "timedmedia-derivative-360p.ogv": "Ogg 360p",
+ "timedmedia-derivative-480p.ogv": "Ogg 480p",
+ "timedmedia-derivative-720p.ogv": "Ogg 720p",
+ "timedmedia-derivative-160p.webm": "WebM 160p",
+ "timedmedia-derivative-360p.webm": "WebM 360p",
+ "timedmedia-derivative-480p.webm": "WebM 480p",
+ "timedmedia-derivative-720p.webm": "WebM 720p",
+ "timedmedia-derivative-320p.mp4": "H264 320p",
+ "timedmedia-derivative-480p.mp4": "H264 480p",
+ "timedmedia-derivative-720p.mp4": "H264 720p",
+ "timedmedia-derivative-ogg": "Ogg Vorbis",
+ "timedmedia-derivative-desc-ogg": "Ogg Vorbis",
+ "timedmedia-derivative-opus": "Opus",
+ "timedmedia-derivative-desc-opus": "Opus",
+ "timedmedia-derivative-mp3": "MP3",
+ "timedmedia-derivative-desc-mp3": "MP3",
+ "timedmedia-derivative-m4a": "AAC",
+ "timedmedia-derivative-desc-m4a": "AAC",
+ "timedmediahandler": "Daftar berkas media"
+}
diff --git a/extensions/TimedMediaHandler/i18n/mk.json b/extensions/TimedMediaHandler/i18n/mk.json
new file mode 100644
index 00000000..69ba9495
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/mk.json
@@ -0,0 +1,144 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bjankuloski06",
+ "Brest"
+ ]
+ },
+ "extensionname-timedmedia": "Š¢ŠøтŠ»Š¾Š²Šø",
+ "timedmedia-desc": "ŠžŠ±Ń€Š°Š±Š¾Ń‚ŃƒŠ²Š°Ń‡ Š·Š° Š°ŃƒŠ“ŠøŠ¾, Š²ŠøŠ“ŠµŠ¾ Šø тŠøтŠ»Š¾Š²Šø, сŠ¾ ŠæŠ¾Š“Š“ршŠŗŠ° Š·Š° фŠ¾Ń€Š¼Š°Ń‚ŠøтŠµ WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Ogg $1 Š·Š²ŃƒŃ‡Š½Š° ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 Š²ŠøŠ“ŠµŠ¾ŃŠ½ŠøŠ¼ŠŗŠ°, $2",
+ "timedmedia-ogg-short-general": "ŠœŃƒŠ»Ń‚ŠøŠ¼ŠµŠ“ŠøјŠ°Š»Š½Š° ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ° Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 Š·Š²ŃƒŃ‡Š½Š° ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°, Š²Ń€ŠµŠ¼ŠµŃ‚Ń€Š°ŠµŃšŠµ $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 Š²ŠøŠ“ŠµŠ¾ ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°, Š²Ń€ŠµŠ¼ŠµŃ‚Ń€Š°ŠµŃšŠµ $2, $4 Ɨ $5 ŠæŠøŠŗсŠµŠ»Šø, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg Š¼ŃƒŠ»Ń‚ŠøŠæŠ»ŠµŠŗсŠøрŠ°Š½Š° Š°ŃƒŠ“ŠøŠ¾/Š²ŠøŠ“ŠµŠ¾ сŠ½ŠøŠ¼ŠŗŠ°, $1, Š²Ń€ŠµŠ¼ŠµŃ‚Ń€Š°ŠµŃšŠµ $2, $4 Ɨ $5 ŠæŠøŠŗсŠµŠ»Šø, Š²ŠŗуŠæŠ½Š¾ $3",
+ "timedmedia-ogg-long-general": "ŠœŃƒŠ»Ń‚ŠøŠ¼ŠµŠ“ŠøјŠ°Š»Š½Š° ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ° Ogg, Š²Ń€ŠµŠ¼ŠµŃ‚Ń€Š°ŠµŃšŠµ $2, $3",
+ "timedmedia-ogg-long-error": "ŠžŃˆŃ‚ŠµŃ‚ŠµŠ½Š° Ogg-ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°: $1",
+ "timedmedia-ogg-long-no-streams": "Ogg-ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°. ŠŸŃ€ŠµŠ“уŠæрŠµŠ“уŠ²Š°ŃšŠµ: ŠŠµ ŠæрŠµŠæŠ¾Š·Š½Š°Š² Š½ŠøŠµŠ“ŠµŠ½ Š¾Š“ ŠŗŠ¾Ń€ŠøстŠµŠ½ŠøтŠµ ŠŗŠ¾Š“ŠµŃ†Šø.",
+ "timedmedia-webm-short-video": "WebM $1 Š²ŠøŠ“ŠµŠ¾ŃŠ½ŠøŠ¼ŠŗŠ°, $2",
+ "timedmedia-webm-long-video": "WebM Š°ŃƒŠ“ŠøŠ¾/Š²ŠøŠ“ŠµŠ¾ сŠ½ŠøŠ¼ŠŗŠ°, $1, Š²Ń€ŠµŠ¼ŠµŃ‚Ń€Š°ŠµŃšŠµ: $2, $4 Ɨ $5 ŠæŠøŠŗсŠµŠ»Šø, Š²ŠŗуŠæŠ½Š¾ $3",
+ "timedmedia-flac-short-audio": "ŠŃƒŠ“ŠøŠ¾ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ° FLAC, $1",
+ "timedmedia-flac-long-audio": "ŠŃƒŠ“ŠøŠ¾ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ° FLAC, Š²Ń€ŠµŠ¼ŠµŃ‚Ń€Š°ŠµŃšŠµ: $1, Š²ŠŗуŠæŠ½Š¾ $2",
+ "timedmedia-wav-short-audio": "ŠŃƒŠ“ŠøŠ¾ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ° WAV, $1",
+ "timedmedia-wav-long-audio": "ŠŃƒŠ“ŠøŠ¾ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ° WAV, Š²Ń€ŠµŠ¼ŠµŃ‚Ń€Š°ŠµŃšŠµ: $1, Š²ŠŗуŠæŠ½Š¾ $2",
+ "timedmedia-wav-pcm-required": "ŠœŠ¾Š¶ŠµŃ‚Šµ Š“Š° ŠæŠ¾Š“ŠøŠ³Š°Ń‚Šµ сŠ°Š¼Š¾ WAV-ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠø сŠ¾ PCM (ŠøŠ¼ŠæуŠ»ŃŠ½Š° ŠŗŠ¾Š“Š½Š° Š¼Š¾Š“уŠ»Š°Ń†ŠøјŠ°).",
+ "timedmedia-mp4-short-video": "MP4 $1 Š²ŠøŠ“ŠµŠ¾ŃŠ½ŠøŠ¼ŠŗŠ°, $2",
+ "timedmedia-mp4-long-video": "MP4 Š°ŃƒŠ“ŠøŠ¾/Š²ŠøŠ“ŠµŠ¾ сŠ½ŠøŠ¼ŠŗŠ°, $1, Š²Ń€ŠµŠ¼ŠµŃ‚Ń€Š°ŠµŃšŠµ $2, $4 Ɨ $5 ŠæŠøŠŗсŠµŠ»Šø, Š²ŠŗуŠæŠ½Š¾ $3",
+ "timedmedia-no-player-js": "Š—Š° Š¶Š°Š», Š²Š°ŃˆŠøŠ¾Ń‚ ŠæрŠµŠ»ŠøстуŠ²Š°Ń‡ ŠøŠ»Šø ŠøŠ¼Š° Š¾Š½ŠµŠ²Š¾Š·Š¼Š¾Š¶ŠµŠ½Š¾ JavaScript, ŠøŠ»Šø Š½ŠµŠ¼Š° Š½Šøту ŠµŠ“ŠµŠ½ ŠæŠ¾Š“Š“рŠ¶Š°Š½ ŠøŠ·Š²ŠµŠ“уŠ²Š°Ń‡.<br />\nŠœŠ¾Š¶ŠµŃ‚Šµ Š“Š° Š³Š¾ <a href=\"$1\">ŠæрŠµŠ·ŠµŠ¼ŠµŃ‚Šµ ŠŗŠ»ŠøŠæŠ¾Ń‚</a> ŠøŠ»Šø <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">Š“Š° ŠæрŠµŠ·ŠµŠ¼ŠµŃ‚Šµ ŠøŠ·Š²ŠµŠ“уŠ²Š°Ń‡</a> Š·Š° Š“Š° јŠ° ŠæуштŠøтŠµ сŠ½ŠøŠ¼ŠŗŠ°Ń‚Š° Š²Š¾ Š²Š°ŃˆŠøŠ¾Ń‚ ŠæрŠµŠ»ŠøстуŠ²Š°Ń‡.",
+ "timedmedia-more": "ŠŸŠ¾Š²ŠµŃœŠµ...",
+ "timedmedia-dismiss": "Š—Š°Ń‚Š²Š¾Ń€Šø",
+ "timedmedia-download": "ŠŸŃ€ŠµŠ·ŠµŠ¼Šø ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°",
+ "timedmedia-play-media": "ŠŸŃƒŃˆŃ‚Šø сŠ½ŠøŠ¼ŠŗŠ°",
+ "timedmedia-desc-link": "Š˜Š½Ń„Š¾Ń€Š¼Š°Ń†ŠøŠø Š·Š° ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°Ń‚Š°",
+ "timedmedia-oggThumb-version": "OggHandler Š±Š°Ń€Š° oggThumb Š²ŠµŃ€Š·ŠøјŠ° $1 ŠøŠ»Šø ŠæŠ¾Š½Š¾Š²Š°.",
+ "timedmedia-oggThumb-failed": "oggThumb Š½Šµ усŠæŠµŠ° Š“Š° јŠ° сŠ¾Š·Š“Š°Š“Šµ Š¼ŠøŠ½ŠøјŠ°Ń‚ŃƒŃ€Š°Ń‚Š°.",
+ "timedmedia-status-header": "Š”тŠ°Ń‚ŃƒŃ Š½Š° ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµŃ‚Š¾",
+ "timedmedia-update-status": "ŠŸŠ¾Š“Š½Š¾Š²Šø стŠ°Ń‚ŃƒŃ Š½Š° ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµ",
+ "timedmedia-status": "стŠ°Ń‚ŃƒŃ",
+ "timedmedia-status-unknown": "ŠŠµŠæŠ¾Š·Š½Š°Ń‚ стŠ°Ń‚ŃƒŃ",
+ "timedmedia-transcodebitrate": "ŠŸŃ€Š¾ŠæусŠ½Š¾ŃŃ‚",
+ "timedmedia-transcodeduration": "Š¢Ń€Š°ŠµŃšŠµ Š½Š° ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµŃ‚Š¾",
+ "timedmedia-transcodeinfo": "Š¤Š¾Ń€Š¼Š°Ń‚",
+ "timedmedia-actions": "Š”ŠµŃ˜ŃŃ‚Š²Š°",
+ "timedmedia-direct-link": "ŠŸŃ€ŠµŠ·ŠµŠ¼Š°ŃšŠµ",
+ "timedmedia-not-ready": "ŠŠµ Šµ Š³Š¾Ń‚Š¾Š²Š¾",
+ "timedmedia-completed-on": "Š—Š°Š²Ń€ŃˆŠµŠ½Š¾ Š½Š° $1",
+ "timedmedia-error-on": "Š“Ń€ŠµŃˆŠŗŠ° Š½Š° $1",
+ "timedmedia-started-transcode": "Š—Š°ŠæŠ¾Ń‡Š½Š°Ń‚Š¾ ŠæрŠµŠ“ $1. $2",
+ "timedmedia-percent-done": "Š”рŠ°Š±Š¾Ń‚ŠµŠ½Š¾: Š¾ŠŗŠ¾Š»Ńƒ $1%",
+ "timedmedia-in-job-queue": "Š”Š¾Š“Š°Š“ŠµŠ½Š¾ Š²Š¾ рŠµŠ“ŠøцŠ°Ń‚Š° Š½Š° Š·Š°Š“Š°Ń‡Šø ŠæрŠµŠ“ $1",
+ "timedmedia-unknown-target-size": "ŠŠµŠæŠ¾Š·Š½Š°Ń‚Š° цŠµŠ»Š½Š° Š³Š¾Š»ŠµŠ¼ŠøŠ½Š°. $1 Šµ шŠøфрŠøрŠ°Š½Š¾",
+ "timedmedia-days": "{{PLURAL:$1|ŠµŠ“ŠµŠ½ Š“ŠµŠ½|$1 Š“ŠµŠ½Š°}}",
+ "timedmedia-hours": "{{PLURAL:$1|ŠµŠ“ŠµŠ½ чŠ°Ń|$1 чŠ°ŃŠ°}}",
+ "timedmedia-minutes": "{{PLURAL:$1|ŠµŠ“Š½Š° Š¼ŠøŠ½ŃƒŃ‚Š°|$1 Š¼ŠøŠ½ŃƒŃ‚Šø}}",
+ "timedmedia-seconds": "{{PLURAL:$1|ŠµŠ“Š½Š° сŠµŠŗуŠ½Š“Š°|$1 сŠµŠŗуŠ½Š“Šø}}",
+ "timedmedia-reset": "ŠžŠ“Š½Š¾Š²Š¾",
+ "timedmedia-reset-confirm": "Š’Ń€Š°ŃœŠ°Ń˜ŃœŠø Š³Š¾ Š¾Š²Š° ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµ Š¾Š“Š½Š¾Š²Š¾ ќŠµ јŠ° Š¾Ń‚стрŠ°Š½ŠøтŠµ ŠæŠ¾ŃŃ‚Š¾ŠµŃ‡ŠŗŠ°Ń‚Š° ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ° (Š°ŠŗŠ¾ јŠ° ŠøŠ¼Š°) Šø ќŠµ Š³Š¾ Š²Ń€Š°Ń‚ŠøтŠµ ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµŃ‚Š¾ Š²Š¾ рŠµŠ“ŠøцŠ°Ń‚Š° Š½Š° Š·Š°Š“Š°Ń‡Šø. ŠŸŠ¾Š²Ń‚Š¾Ń€Š½Š¾Ń‚Š¾ ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµ ќŠµ ŠæŠ¾Ń‚Ń€Š°Šµ. <br /><br />Š”Š°Š»Šø стŠµ сŠøŠ³ŃƒŃ€Š½Šø Š“ŠµŠŗŠ° сŠ°ŠŗŠ°Ń‚Šµ Š“Š° ŠæрŠ¾Š“Š¾Š»Š¶ŠøтŠµ?",
+ "timedmedia-reset-error": "Š“Ń€ŠµŃˆŠŗŠ° ŠæрŠø ŠæŠ¾Š²Ń‚Š¾Ń€Š½Š¾Ń‚Š¾ ŠæуштŠ°ŃšŠµ Š½Š° трŠ°Š½ŃŠŗŠ¾Š“ŠøрŠ°ŃšŠµŃ‚Š¾.",
+ "timedmedia-ogg": "Ogg",
+ "timedmedia-webm": "WebM",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Š˜Š·Š²Š¾Ń€ Š½Š° $1",
+ "timedmedia-source-file-desc": "ŠžŃ€ŠøŠ³ŠøŠ½Š°Š»Š½Š° $1-ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "ŠžŃ€ŠøŠ³ŠøŠ½Š°Š»Š½Š° $1-ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ° ($2)",
+ "timedmedia-derivative-160p.ogv": "Ogg 160Šæ",
+ "timedmedia-derivative-desc-160p.ogv": "ŠŠøсŠŗŠ¾ŠæрŠ¾ŠæусŠ½Š¾ Ogg-Š²ŠøŠ“ŠµŠ¾ (160Šæ)",
+ "timedmedia-derivative-240p.ogv": "Ogg 240 Šæ",
+ "timedmedia-derivative-desc-240p.ogv": "Ogg-Š²ŠøŠ“ŠµŠ¾ Š·Š° ŠµŠ¼ŠøтуŠ²Š°ŃšŠµ (240 ŠæŠøŠŗсŠµŠ»Šø)",
+ "timedmedia-derivative-360p.ogv": "Ogg 360Šæ",
+ "timedmedia-derivative-desc-360p.ogv": "Ogg-Š²ŠøŠ“ŠµŠ¾ Š·Š° ŠµŠ¼ŠøтуŠ²Š°ŃšŠµ (360 ŠæŠøŠŗсŠµŠ»Šø)",
+ "timedmedia-derivative-480p.ogv": "Ogg 480Šæ",
+ "timedmedia-derivative-desc-480p.ogv": "Ogg-Š²ŠøŠ“ŠµŠ¾ Š·Š° ŠµŠ¼ŠøтуŠ²Š°ŃšŠµ (480 ŠæŠøŠŗсŠµŠ»Šø)",
+ "timedmedia-derivative-720p.ogv": "Ogg 720Šæ",
+ "timedmedia-derivative-desc-720p.ogv": "Š’ŠøсŠ¾ŠŗŠ¾ŠŗŠ²Š°Š»ŠøтŠµŃ‚Š½Š¾ Ogg-Š²ŠøŠ“ŠµŠ¾ Š·Š° ŠæрŠµŠ·ŠµŠ¼Š°ŃšŠµ (720Šæ)",
+ "timedmedia-derivative-1080p.ogv": "Ogg 1080Šæ",
+ "timedmedia-derivative-desc-1080p.ogv": "Š’ŠøсŠ¾ŠŗŠ¾Ń€Š°Š·Š“ŠµŠ»Š½Š° Ogg-Š²ŠøŠ“ŠµŠ¾ŃŠ½ŠøŠ¼ŠŗŠ° Š·Š° ŠæрŠµŠ·ŠµŠ¼Š°ŃšŠµ (1080Šæ)",
+ "timedmedia-derivative-160p.webm": "WebM 160Šæ",
+ "timedmedia-derivative-desc-160p.webm": "WebM Š·Š° ŠŗŠ°Š½Š°Š»ŃŠŗŠ¾ ŠµŠ¼ŠøтуŠ²Š°ŃšŠµ (160Šæ)",
+ "timedmedia-derivative-360p.webm": "WebM 360Šæ",
+ "timedmedia-derivative-desc-360p.webm": "WebM Š·Š° ŠŗŠ°Š½Š°Š»ŃŠŗŠ¾ ŠµŠ¼ŠøтуŠ²Š°ŃšŠµ (360Šæ)",
+ "timedmedia-derivative-480p.webm": "WebM 480Šæ",
+ "timedmedia-derivative-desc-480p.webm": "WebM Š·Š° ŠŗŠ°Š½Š°Š»ŃŠŗŠ¾ ŠµŠ¼ŠøтуŠ²Š°ŃšŠµ (480Šæ)",
+ "timedmedia-derivative-720p.webm": "WebM 720Šæ",
+ "timedmedia-derivative-desc-720p.webm": "Š’ŠøсŠ¾ŠŗŠ¾ŠŗŠ²Š°Š»ŠøтŠµŃ‚ŠµŠ½ WebM Š·Š° ŠæрŠµŠ·ŠµŠ¼Š°ŃšŠµ (720Šæ)",
+ "timedmedia-derivative-1080p.webm": "WebM 1080Šæ",
+ "timedmedia-derivative-desc-1080p.webm": "ŠŸŠ¾Š»Š½Š¾Ń€Š°Š·Š“ŠµŠ»Š½Š° WebM-Š²ŠøŠ“ŠµŠ¾ŃŠ½ŠøŠ¼ŠŗŠ° Š·Š° ŠæрŠµŠ·ŠµŠ¼Š°ŃšŠµ (1080Šæ)",
+ "timedmedia-derivative-desc-2160p.webm": "ŠŸŠ¾Š»Š½Š¾Ń€Š°Š·Š“ŠµŠ»Š½Š° 4Šš WebM-Š²ŠøŠ“ŠµŠ¾ŃŠ½ŠøŠ¼ŠŗŠ° Š·Š° ŠæрŠµŠ·ŠµŠ¼Š°ŃšŠµ (2160Šæ)",
+ "timedmedia-derivative-360p.vp9.webm": "VP9 360Šæ",
+ "timedmedia-derivative-desc-360p.vp9.webm": "WebM Š·Š° ŠŗŠ°Š½Š°Š»ŃŠŗŠ¾ ŠµŠ¼ŠøтуŠ²Š°ŃšŠµ (360Šæ)",
+ "timedmedia-derivative-480p.vp9.webm": "VP9 480Šæ",
+ "timedmedia-derivative-desc-480p.vp9.webm": "WebM Š·Š° ŠŗŠ°Š½Š°Š»ŃŠŗŠ¾ ŠµŠ¼ŠøтуŠ²Š°ŃšŠµ (480Šæ)",
+ "timedmedia-derivative-720p.vp9.webm": "VP9 720Šæ",
+ "timedmedia-derivative-desc-720p.vp9.webm": "WebM Š·Š° Š²ŠøсŠ¾ŠŗŠ¾Ń€Š°Š·Š“ŠµŠ»Š½Š¾ ŠŗŠ°Š½Š°Š»ŃŠŗŠ¾ ŠµŠ¼ŠøтуŠ²Š°ŃšŠµ (720Šæ)",
+ "timedmedia-derivative-1080p.vp9.webm": "VP9 1080Šæ",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "WebM Š·Š° ŠæŠ¾Š»Š½Š¾Ń€Š°Š·Š“ŠµŠ»Š½Š¾ ŠŗŠ°Š½Š°Š»ŃŠŗŠ¾ ŠµŠ¼ŠøтуŠ²Š°ŃšŠµ (1080Šæ)",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "ŠŸŠ¾Š»Š½Š¾Ń€Š°Š·Š“ŠµŠ»Š½Š° 4Šš WebM VP9 Š²ŠøŠ“ŠµŠ¾ŃŠ½ŠøŠ¼ŠŗŠ° Š·Š° ŠæрŠµŠ·ŠµŠ¼Š°ŃšŠµ (2160Šæ)",
+ "timedmedia-derivative-320p.mp4": "H264 320Šæ",
+ "timedmedia-derivative-desc-320p.mp4": "MP4 Š·Š° урŠµŠ“Šø (320Šæ)",
+ "timedmedia-derivative-480p.mp4": "H264 480Šæ",
+ "timedmedia-derivative-desc-480p.mp4": "MP4 Š·Š° ŠŗŠ°Š½Š°Š»ŃŠŗŠ¾ ŠµŠ¼ŠøтуŠ²Š°ŃšŠµ (480Šæ)",
+ "timedmedia-derivative-720p.mp4": "H264 720Šæ",
+ "timedmedia-derivative-desc-720p.mp4": "MP4-сŠ½ŠøŠ¼ŠŗŠ° сŠ¾ HD-ŠŗŠ²Š°Š»ŠøтŠµŃ‚ (720Šæ)",
+ "timedmedia-derivative-1080p.mp4": "H264 1080Šæ",
+ "timedmedia-derivative-desc-1080p.mp4": "Š’ŠøсŠ¾ŠŗŠ¾Ń€Š°Š·Š“ŠµŠ»Š±Š° MP4-Š²ŠøŠ“ŠµŠ¾ŃŠ½ŠøŠ¼ŠŗŠ° (1080Šæ) Š·Š° ŠæрŠµŠ·ŠµŠ¼Š°ŃšŠµ",
+ "timedmedia-derivative-desc-2160p.mp4": "ŠŸŠ¾Š»Š½Š¾Ń€Š°Š·Š“ŠµŠ»Š½Š° 4Šš ŠŗŠ²Š°Š»ŠøтŠµŃ‚Š½Š° MP4-Š²ŠøŠ“ŠµŠ¾ŃŠ½ŠøŠ¼ŠŗŠ° (2160Šæ)",
+ "timedmedia-subtitle-new": "Š”Š¾Š·Š“Š°Ń˜ Š½Š¾Š² ŠæрŠµŠ²Š¾Š“ ŠøŠ»Šø ŠøŠ·Š¼ŠµŠ½Šø ŠæŠ¾ŃŃ‚Š¾ŠµŃ‡ŠŗŠø",
+ "timedmedia-subtitle-new-desc": "Š˜Š·Š±ŠµŃ€ŠµŃ‚Šµ јŠ°Š·ŠøŠŗ Šø стŠøсŠ½ŠµŃ‚Šµ Š½Š° ŠŗŠ¾ŠæчŠµŃ‚Š¾ '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Š”Š°Ń˜",
+ "timedmedia-subtitle-language": "$1 ($2) тŠøтŠ»Š¾Š²Šø",
+ "timedmedia-subtitle-no-video": "ŠŠµŠ¼Š° Š²ŠøŠ“ŠµŠ¾ŃŠ½ŠøŠ¼ŠŗŠ° ŠæŠ¾Š²Ń€Š·Š°Š½Š° сŠ¾ тŠµŠŗŠ¾Š²Š½Š°Ń‚Š° стрŠ°Š½ŠøцŠ° сŠ¾ тŠøтŠ»Š¾Š²Šø",
+ "timedmedia-subtitle-no-subtitles": "ŠœŠ¾Š¼ŠµŠ½Ń‚Š°Š»Š½Š¾ Š½ŠµŠ¼Š° $1 тŠøтŠ»Š¾Š²Šø Š·Š° Š¾Š²Š°Š° Š²ŠøŠ“ŠµŠ¾ŃŠ½ŠøŠ¼ŠŗŠ°. ŠœŠ¾Š¶ŠµŃ‚Šµ Š“Š° Š³Šø Š“Š¾Š“Š°Š“ŠµŃ‚Šµ [{{fullurl:{{FULLPAGENAME}}|action=edit}} урŠµŠ“уŠ²Š°Ń˜ŃœŠø јŠ° стрŠ°Š½ŠøцŠ°Š²Š°]",
+ "timedmedia-subtitle-remote": "Š¢ŠøтŠ»Š¾Š²ŠøтŠµ Š½Š° ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°Š²Š° сŠµ Š²Š“Š¾Š¼ŠµŠ½Šø Š²Š¾ $1",
+ "timedmedia-subtitle-remote-link": "ŠœŠ¾Š¶ŠµŃ‚Šµ Š“Š° јŠ° [$1 ŠæŠ¾Š³Š»ŠµŠ“Š°Ń‚Šµ Š¾ŠæŠøсŠ½Š°Ń‚Š° стрŠ°Š½ŠøцŠ°] Š½Š° ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°Š²Š° Š½Š° $2",
+ "timedmediahandler": "Š¢ŠøтŠ»Š¾Š²Šø",
+ "timedmedia-videos": "{{PLURAL:$1|$1 Š²ŠøŠ“ŠµŠ¾|$1 Š²ŠøŠ“ŠµŠ°}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg-Š²ŠøŠ“ŠµŠ¾|$1 Ogg-Š²ŠøŠ“ŠµŠ°}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM-Š²ŠøŠ“ŠµŠ¾|$1 WebM-Š²ŠøŠ“ŠµŠ°}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµ|$1 ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠ°}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµ Š²Š¾ тŠµŠŗ|$1 ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠ° Š²Š¾ тŠµŠŗ}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµ Š²Š¾ рŠµŠ“ŠøцŠ° Š½Š° чŠµŠŗŠ°ŃšŠµ|$1 ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠ° Š²Š¾ рŠµŠ“ŠøцŠ° Š½Š° чŠµŠŗŠ°ŃšŠµ}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 Š½ŠµŃƒŃŠæŠµŃˆŠ½Š¾ ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµ|$1 Š½ŠµŃƒŃŠæŠµŃˆŠ½Šø ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠ°}}",
+ "timedmedia-file": "ŠŸŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°",
+ "timedmedia-audios": "{{PLURAL:$1|Š•Š“Š½Š° Š°ŃƒŠ“ŠøŠ¾ŃŠ½ŠøŠ¼ŠŗŠ°|$1 Š°ŃƒŠ“ŠøŠ¾ŃŠ½ŠøŠ¼ŠŗŠø}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|Š•Š“Š½Š° Ogg-Š°ŃƒŠ“ŠøŠ¾ŃŠ½ŠøŠ¼ŠŗŠ°|$1 Ogg-Š°ŃƒŠ“ŠøŠ¾ŃŠ½ŠøŠ¼ŠŗŠø}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|Š•Š“Š½Š° FLAC-Š°ŃƒŠ“ŠøŠ¾ŃŠ½ŠøŠ¼ŠŗŠ°|$1 FLAC-Š°ŃƒŠ“ŠøŠ¾ŃŠ½ŠøŠ¼ŠŗŠø}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|Š•Š“Š½Š° WAV-Š°ŃƒŠ“ŠøŠ¾ŃŠ½ŠøŠ¼ŠŗŠ°|$1 WAV-Š°ŃƒŠ“ŠøŠ¾ŃŠ½ŠøŠ¼ŠŗŠø}}",
+ "right-transcode-reset": "ŠŸŃ€ŠµŠ·Š°Š“Š°Š²Š°ŃšŠµŃ‚Š¾ Š½Šµ усŠæŠµŠ° ŠøŠ»Šø ŠøŠ¼Š° ŠæрŠµŠŗŠ¾Š“ŠøрŠ°Š½Šø Š²ŠøŠ“ŠµŠ°, ŠæŠ° Š·Š°Ń‚Š¾Š° ŠæŠ¾Š²Ń‚Š¾Ń€Š½Š¾ сŠµ стŠ°Š²ŠµŠ½Šø Š²Š¾ рŠµŠ“ŠøцŠ°Ń‚Š° Š½Š° Š·Š°Š“Š°Ń‡Šø.",
+ "right-transcode-status": "ŠŸŃ€ŠµŠ³Š»ŠµŠ“ Š½Š° [[Special:TimedMediaHandler|ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŠø Š·Š° тŠµŠŗŠ¾Š²Š½ŠøтŠµ Š°ŠŗтŠøŠ²Š½Š¾ŃŃ‚Šø Š²Š¾ ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµŃ‚Š¾]]",
+ "action-transcode-status": "ŠæрŠµŠ³Š»ŠµŠ“ Š½Š° тŠµŠŗŠ¾Š²Š½ŠøŠ¾Ń‚ стŠ°Ń‚ŃƒŃ Š½Š° ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµŃ‚Š¾",
+ "orphanedtimedtext": "ŠžŃŠ°Š¼ŠµŠ½Šø стрŠ°Š½ŠøцŠø сŠ¾ тŠøтŠ»Š¾Š²Šø",
+ "orphanedtimedtext-summary": "Š”ŠæŠøсŠ¾Šŗ Š½Š° стрŠ°Š½ŠøцŠø сŠ¾ [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] штŠ¾ Š½ŠµŠ¼Š°Š°Ń‚ сŠ²Š¾Ń˜Š° ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°.",
+ "orphanedtimedtext-unsupported": "ŠžŠ²Š°Š° сŠ»ŃƒŠ¶Š±ŠµŠ½Š° стрŠ°Š½ŠøцŠ° Šµ ŠæŠ¾Š“Š“рŠ¶Š°Š½Š° сŠ°Š¼Š¾ Š½Š° MySQL-Š±Š°Š·Šø.",
+ "orphanedtimedtext-notimedtext": "Š¢ŠøтŠ»Š¾Š²ŠøтŠµ Š½Šµ сŠµ Š¾Š²Š¾Š·Š¼Š¾Š¶ŠµŠ½Šø Š½Š° Š¾Š²Š° Š²ŠøŠŗŠø.",
+ "apihelp-query+transcodestatus-description": "Š”Š°Ń˜ стŠ°Ń‚ŃƒŃ Š½Š° ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµŃ‚Š¾ Š½Š° Š“Š°Š“ŠµŠ½Š° ŠæŠ¾Š“Š°Ń‚Š¾Ń‡Š½Š° стрŠ°Š½ŠøцŠ°.",
+ "apihelp-query+transcodestatus-example-1": "Š”Š°Ń˜ стŠ°Ń‚ŃƒŃ Š½Š° ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµŃ‚Š¾ Š½Š° [[:File:Clip.webm]]",
+ "apihelp-query+videoinfo-description": "Š“Šø Š“Š¾ŠæŠ¾Š»Š½ŃƒŠ²Š° ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŠøтŠµ сŠ¾ ŠæŠ¾Š“Š°Ń‚Š¾Šŗ Š·Š° ŠøŠ·Š²Š¾Ń€Š¾Ń‚ Š½Š° Š²ŠøŠ“ŠµŠ¾Ń‚Š¾ (ŠøŠ·Š²ŠµŠ“ŠµŠ½Šø)",
+ "apihelp-query+videoinfo-param-prop": "ŠšŠ¾Šø ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŠø Š·Š° Š²ŠøŠ“ŠµŠ¾Ń‚Š¾ Š“Š° сŠµ Š“Š°Š“Š°Ń‚:\n;timestamp: Š”Š¾Š“Š°Š²Š° Š“Š°Ń‚ŃƒŠ¼ Šø Š²Ń€ŠµŠ¼Šµ Š·Š° ŠæŠ¾Š“ŠøŠ³Š½Š°Ń‚Š°Ń‚Š° Š²ŠµŃ€Š·ŠøјŠ°.\n;user: Š“Š¾ Š“Š¾Š“Š°Š²Š° ŠŗŠ¾Ń€ŠøсŠ½ŠøŠŗŠ¾Ń‚ штŠ¾ јŠ° ŠæŠ¾Š“ŠøŠ³Š½Š°Š» Š²ŠµŃ€Š·ŠøјŠ°Ń‚Š° Š½Š° Š²ŠøŠ“ŠµŠ¾Ń‚Š¾.\n;userid: ŠˆŠ° Š“Š¾Š“Š°Š²Š° Š½Š°Š·Š½Š°ŠŗŠ°Ń‚Š° Š½Š° ŠŗŠ¾Ń€ŠøсŠ½ŠøŠŗŠ¾Ń‚ штŠ¾ Š³Š¾ ŠæŠ¾Š“ŠøŠ³Š½Š°Š» Š²ŠøŠ“ŠµŠ¾Ń‚Š¾.\n;comment: ŠšŠ¾Š¼ŠµŠ½Ń‚Š°Ń€ Š½Š° Š²ŠµŃ€Š·ŠøјŠ°Ń‚Š°.\n;parsedcomment: Š Š°ŃŃ‡Š»ŠµŠ½ŃƒŠ²Š°ŃšŠµ Š½Š° ŠŗŠ¾Š¼ŠµŠ½Ń‚Š°Ń€Š¾Ń‚ Š½Š° Š²ŠµŃ€Š·ŠøјŠ°Ń‚Š°.\n;canonicaltitle: Š“Š¾ Š“Š¾Š“Š°Š²Š° ŠŗŠ°Š½Š¾Š½ŃŠŗŠøŠ¾Ń‚ Š½Š°ŃŠ»Š¾Š² Š½Š° Š²ŠøŠ“ŠµŠ¾ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°Ń‚Š°.\n;url: Š”Š°Š²Š° URL-Š°Š“рŠµŃŠ° Š½Š° Š²ŠøŠ“ŠµŠ¾Ń‚Š¾ Šø Š¾ŠæŠøсŠ½Š°Ń‚Š° стрŠ°Š½ŠøцŠ°.\n;size: ŠˆŠ° Š“Š¾Š“Š°Š²Š° Š·Š°Ń„Š°Ń‚Š½ŠøŠ½Š°Ń‚Š° Š½Š° Š²ŠøŠ“ŠµŠ¾Ń‚Š¾ Š²Š¾ Š±Š°Ń˜Ń‚Šø, Š½ŠµŠ³Š¾Š²Š°Ń‚Š° Š²ŠøсŠøŠ½Š° Šø шŠøрŠøŠ½Š°. ŠŒŠµ сŠµ Š“Š¾Š“Š°Š“Šµ Šø Š±Ń€Š¾Ń˜Š¾Ń‚ Š½Š° стрŠ°Š½ŠøцŠø Šø Š²Ń€ŠµŠ¼ŠµŃ‚Ń€Š°ŠµŃšŠµŃ‚Š¾, Š°ŠŗŠ¾ сŠµ ŠæрŠøŠ¼ŠµŠ½Š»ŠøŠ²Šø.\n;dimensions: ŠŠ»ŠøјŠ°Ń Š·Š° Š·Š°Ń„Š°Ń‚Š½ŠøŠ½Š°.\n;sha1: Š”Š¾Š“Š°Š²Š° тŠ°Ń€Š°Š±Š° SHA-1 Š·Š° Š²ŠøŠ“ŠµŠ¾Ń‚Š¾.\n;mime: Š”Š¾Š“Š°Š²Š° MIME-тŠøŠæ Š½Š° Š²ŠøŠ“ŠµŠ¾Ń‚Š¾.\n;thumbmime: Š”Š¾Š“Š°Š²Š° MIME-тŠøŠæ Š°Š½ Š¼ŠøŠ½ŠøјŠ°Ń‚ŃƒŃ€Š°Ń‚Š° Š½Š° Š²ŠøŠ“ŠµŠ¾Ń‚Š¾ (Š±Š°Ń€Š° URL-Š°Š“рŠµŃŠ° Šø ŠæŠ°Ń€Š°Š¼ŠµŃ‚Š°Ń€Š¾Ń‚ $1urlwidth).\n;mediatype: Š“Š¾ Š“Š¾Š“Š°Š²Š° Š¼ŠµŠ“ŠøуŠ¼ŃŠŗŠøŠ¾Ń‚ тŠøŠæ Š½Š° Š²ŠøŠ“ŠµŠ¾Ń‚Š¾.\n;metadata: Š˜ŃŠæŠøшуŠ²Š° Exif-Š¼ŠµŃ‚Š°ŠæŠ¾Š“Š°Ń‚Š¾Ń†Šø Š·Š° Š²ŠµŃ€Š·ŠøјŠ°Ń‚Š° Š½Š° Š²ŠøŠ“ŠµŠ¾Ń‚Š¾.\n;commonmetadata: Š˜ŃŠæŠøшуŠ²Š° Š¾ŠæштŠø Š¼ŠµŃ‚Š°ŠæŠ¾Š“Š°Ń‚Š¾Ń†Šø Š½Š° ŠæŠ¾Š“Š°Ń‚Š¾Ń‡Š½ŠøŠ¾Ń‚ фŠ¾Ń€Š¼Š°Ń‚ Š·Š° Š²ŠµŃ€Š·ŠøјŠ°Ń‚Š° Š½Š° Š²ŠøŠ“ŠµŠ¾Ń‚Š¾.\n;extmetadata: Š˜ŃŠæŠøшуŠ²Š° фŠ¾Ń€Š¼Š°Ń‚ŠøрŠ°Š½Šø Š¼ŠµŃ‚Š°ŠæŠ¾Š“Š°Ń‚Š¾Ń†Šø сŠ¾Š±Ń€Š°Š½Šø Š¾Š“ ŠæŠ¾Š²ŠµŃœŠµ ŠøŠ·Š²Š¾Ń€Šø. Š ŠµŠ·ŃƒŠ»Ń‚Š°Ń‚ŠøтŠµ сŠµ фŠ¾Ń€Š¼Š°Ń‚ŠøрŠ°Š½Šø Š²Š¾ HTML.\n;archivename: Š“Š¾ Š“Š¾Š“Š°Š²Š° ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŃ‡Š½Š¾Ń‚Š¾ ŠøŠ¼Šµ Š½Š° Š°Ń€Ń…ŠøŠ²ŃŠŗŠ°Ń‚Š° Š²ŠµŃ€Š·ŠøјŠ° Š·Š° сŠøтŠµ Š²ŠµŃ€Š·ŠøŠø Š¾ŃŠ²ŠµŠ½ Š½Š°Ń˜Š½Š¾Š²Š°Ń‚Š°.\n;bitdepth: ŠˆŠ° Š“Š¾Š“Š°Š²Š° Š±ŠøтŠ¾Š²Š°Ń‚Š° Š“Š»Š°Š±Š¾Ń‡ŠøŠ½Š° Š½Š° Š²ŠµŃ€Š·ŠøјŠ°Ń‚Š°.\n;uploadwarning: Š”Šµ ŠŗŠ¾Ń€ŠøстŠø Š½Š° стрŠ°Š½ŠøцŠ°Ń‚Š° [[Special:Upload]] Š·Š° Š“Š¾Š±ŠøŠ²Š°ŃšŠµ Š½Š° ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŠø Š·Š° ŠæŠ¾ŃŃ‚Š¾ŠµŃ‡ŠŗŠ° ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°. ŠŠµ Šµ ŠæрŠµŠ“Š²ŠøŠ“ŠµŠ½Š¾ Š·Š° уŠæŠ¾Ń‚Ń€ŠµŠ±Š° Š²Š¾Š½ јŠ°Š“рŠ¾Ń‚Š¾ Š½Š° ŠœŠµŠ“ŠøјŠ°Š’ŠøŠŗŠø.\n;derivatives: Š”Š¾Š“Š°Š²Š° Š½ŠøŠ·Š° Š¾Š“ рŠ°Š·Š»ŠøчŠ½ŠøŠ¾Ń‚ фŠ¾Ń€Š¼Š°Ń‚ Šø рŠ°ŃŠæŠ¾Š»Š¾Š¶ŠøŠ²ŠøтŠµ ŠŗŠ²Š°Š»ŠøтŠµŃ‚Šø Š½Š° Š°ŃƒŠ“ŠøŠ¾- ŠøŠ»Šø Š²ŠøŠ“ŠµŠ¾ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°Ń‚Š°.",
+ "apihelp-query+videoinfo-example-1": "Š”Š°Ń˜ ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŠø Š·Š° [[:File:Folgers.ogv]]",
+ "apihelp-transcodereset-description": "ŠšŠ¾Ń€ŠøсŠ½ŠøцŠøтŠµ сŠ¾ ŠæрŠ°Š²Š¾Ń‚Š¾ ā€žtranscode-resetā€œ Š¼Š¾Š¶Š°Ń‚ Š“Š° Š³Šø Š²Ń€Š°ŃœŠ°Š°Ń‚ ŠæŠ¾ Š¾ŃŠ½Š¾Š²Š½Š¾ ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠ°Ń‚Š° Šø Š“Š° Š³Šø Š²Ń€ŃˆŠ°Ń‚ Š¾Š“Š½Š¾Š²Š¾.",
+ "apihelp-transcodereset-param-title": "ŠŠ°ŃŠ»Š¾Š² Š½Š° ŠæŠ¾Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°Ń‚Š°.",
+ "apihelp-transcodereset-param-transcodekey": "ŠšŠ»ŃƒŃ‡Š¾Ń‚ Š½Š° ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµŃ‚Š¾ штŠ¾ сŠ°ŠŗŠ°Ń‚Šµ Š“Š° Š³Š¾ ŠæрŠµŠ·Š°Š“Š°Š“ŠµŃ‚Šµ. ŠŸŃ€ŠµŠ·ŠµŠ¼Šø Š¾Š“ [[Special:ApiHelp/query+transcodestatus|action=query&prop=transcodestatus]].",
+ "apihelp-transcodereset-example-1": "Š’Ń€Š°Ń‚Šø Š³Šø ŠæŠ¾ Š¾ŃŠ½Š¾Š²Š½Š¾ сŠøтŠµ ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠ° Š½Š° [[:File:Clip.webm]]",
+ "apihelp-transcodereset-example-2": "Š’Ń€Š°Ń‚Šø Š³Š¾ ŠæŠ¾ Š¾ŃŠ½Š¾Š²Š½Š¾ ŠŗŠ»ŃƒŃ‡Š¾Ń‚ ā€ž360_560kbs.webmā€œ Š·Š° ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµŃ‚Š¾ Š½Š° [[:File:Clip.webm]]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ml.json b/extensions/TimedMediaHandler/i18n/ml.json
new file mode 100644
index 00000000..0b04df45
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ml.json
@@ -0,0 +1,124 @@
+{
+ "@metadata": {
+ "authors": [
+ "Praveenp",
+ "Shijualex",
+ "Vssun",
+ "Santhosh.thottingal"
+ ]
+ },
+ "timedmedia-desc": "ą““ą“—ąµ ą“¤ą“æą“Æąµ‹ą“±, ą“µąµ‹ąµ¼ą“¬ą“æą“øąµ, ą“Žą“øąµ.ą“†ąµ¼.ą“Ÿą“æ, ą“µąµ†ą“¬ąµą“Žą“‚ ą“¤ąµą“Ÿą“™ąµą“™ą“æą“Æą“µą“Æąµą“•ąµą“•ąµą“³ąµą“³ ą“Ŗą“æą“Øąµą“¤ąµą“£ą“Æą“Ÿą“•ąµą“•ą“®ąµą“³ąµą“³ ą“¶ą“¬ąµą“¦, ą“šą“²ą“šąµą“šą“æą“¤ąµą“°, ą“øą“®ą“Æą“®ą“Øąµą“øą“°ą“æą“šąµą“šąµ ą“Ŗąµą“°ą“¦ąµ¼ą“¶ą“æą“Ŗąµą“Ŗą“æą“•ąµą“•ąµą“Øąµą“Ø ą“Žą““ąµą“¤ąµą“¤ąµą“•ąµ¾ ą“Žą“Øąµą“Øą“æą“µą“Æąµą“•ąµą“•ąµą“³ąµą“³ ą“•ąµˆą“•ą“¾ą“°ąµą“Æąµ‹ą“Ŗą“•ą“°ą“£ą“‚",
+ "timedmedia-ogg-short-audio": "ą““ą“—ąµ $1 ą“¶ą“¬ąµą“¦ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, $2",
+ "timedmedia-ogg-short-video": "ą““ą“—ąµ $1 ą“µąµ€ą“”ą“æą“Æąµ‹ ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, $2",
+ "timedmedia-ogg-short-general": "ą““ą“—ąµ $1 ą“®ąµ€ą“”ą“æą“Æ ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, $2",
+ "timedmedia-ogg-long-audio": "ą““ą“—ąµ $1 ą“¶ą“¬ąµą“¦ ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, ą“¦ąµˆąµ¼ą“˜ąµą“Æą“‚ $2, $3",
+ "timedmedia-ogg-long-video": "ą““ą“—ąµ $1 ą“µąµ€ą“”ą“æą“Æąµ‹ ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, ą“¦ąµˆąµ¼ą“˜ąµą“Æą“‚ $2, $4Ɨ$5 ą“¬ą“æą“Øąµą“¦ąµ, $3",
+ "timedmedia-ogg-long-multiplexed": "ą““ą“—ąµ ą“®ąµ¾ą“Ÿąµą“Ÿą“æą“Ŗąµą“²ą“•ąµą“øąµā€Œā€Œą“”ąµ ą“¶ą“¬ąµą“¦/ą“šą“²ą“šąµą“šą“æą“¤ąµą“° ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, $1, ą“¦ąµˆąµ¼ą“˜ąµą“Æą“‚ $2, $4Ɨ$5 ą“¬ą“æą“Øąµą“¦ąµ, ą“†ą“•ąµ†ą“•ąµą“•ąµ‚ą“Ÿą“æ $3",
+ "timedmedia-ogg-long-general": "ą““ą“—ąµ ą“®ąµ€ą“”ą“æą“Æ ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, ą“¦ąµˆąµ¼ą“˜ąµą“Æą“‚ $2, $3",
+ "timedmedia-ogg-long-error": "ą“…ą“øą“¾ą“§ąµą“µą“¾ą“Æ ą““ą“—ąµ ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚: $1",
+ "timedmedia-ogg-long-no-streams": "ą““ą“—ąµ ą“®ąµ€ą“”ą“æą“Æ ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚. ą“®ąµą“Øąµą“Øą“±ą“æą“Æą“æą“Ŗąµą“Ŗąµ: ą“ˆ ą“Ŗąµą“°ą“®ą“¾ą“£ą“¤ąµą“¤ą“æąµ½ ą“‰ą“Ŗą“Æąµ‹ą“—ą“æą“šąµą“šą“æą“°ą“æą“•ąµą“•ąµą“Øąµą“Ø ą“•ąµ‹ą“”ąµ†ą“•ąµą“•ą“³ąµŠą“Øąµą“Øąµą“‚ ą“¤ą“æą“°ą“æą“šąµą“šą“±ą“æą“žąµą“žą“æą“Ÿąµą“Ÿą“æą“²ąµą“².",
+ "timedmedia-webm-short-video": "ą“µąµ†ą“¬ąµą“Žą“‚ $1 ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, $2",
+ "timedmedia-webm-long-video": "ą“µąµ†ą“¬ąµą“Žą“‚ ą“¶ą“¬ąµą“¦/ą“šą“²ą“šąµą“šą“æą“¤ąµą“° ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, $1, ą“¦ąµˆąµ¼ą“˜ąµą“Æą“‚ $2, $4 Ɨ $5 ą“¬ą“æą“Øąµą“¦ąµ, ą“†ą“•ąµ†ą“•ąµą“•ąµ‚ą“Ÿą“æ $3",
+ "timedmedia-flac-short-audio": "ą“«ąµą“²ą“¾ą“•ąµ ą“¶ą“¬ąµą“¦ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, $1",
+ "timedmedia-flac-long-audio": "ą“«ąµą“²ą“¾ą“•ąµ ą“¶ą“¬ąµą“¦ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, ą“¦ąµˆąµ¼ą“˜ąµą“Æą“‚ $1, ą“†ą“•ąµ† $2",
+ "timedmedia-wav-short-audio": "ą“µąµ‡ą“µąµ ą“¶ą“¬ąµą“¦ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, $1",
+ "timedmedia-wav-long-audio": "ą“µąµ‡ą“µąµ ą“¶ą“¬ąµą“¦ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, ą“¦ąµˆąµ¼ą“˜ąµą“Æą“‚ $1, ą“†ą“•ąµ† $2",
+ "timedmedia-wav-pcm-required": "ą“Ŗą“æ.ą“øą“æ.ą“Žą“‚. (ą“Ŗąµ¾ą“øąµ ą““ą“”ą“æą“Æąµ‹ ą“®ąµ‹ą“”ąµą“²ąµ‡ą“·ąµ») ą“µąµ‡ą“µąµ ą“®ą“¾ą“¤ąµą“°ą“®ąµ‡ ą“…ą“Ŗąµā€Œą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æą“¾ą“Øą“¾ą“µąµ‚.",
+ "timedmedia-mp4-short-video": "ą“Žą“‚ą“Ŗą“æ4 $1 ą“µąµ€ą“”ą“æą“Æąµ‹ ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, $2",
+ "timedmedia-mp4-long-video": "ą“Žą“‚ą“Ŗą“æ4 ą“¶ą“¬ąµą“¦/ą“šą“²ą“šąµą“šą“æą“¤ąµą“° ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚, $1, ą“¦ąµˆąµ¼ą“˜ąµą“Æą“‚ $2, $4 Ɨ $5 ą“¬ą“æą“Øąµą“¦ąµ, ą“†ą“•ąµ†ą“•ąµą“•ąµ‚ą“Ÿą“æ $3",
+ "timedmedia-no-player-js": "ą“•ąµą“·ą“®ą“æą“•ąµą“•ąµą“•, ą“¤ą“¾ą“™ąµą“•ą“³ąµą“Ÿąµ† ą“¬ąµą“°ąµ—ą“øą“±ą“æąµ½ ą“œą“¾ą“µą“¾ą“øąµą“•ąµą“°ą“æą“Ŗąµą“±ąµą“±ąµ ą“øą“œąµą“œą“®ą“¾ą“•ąµą“•ą“æą“Æą“æą“Ÿąµą“Ÿą“æą“²ąµą“² ą“…ą“²ąµą“²ąµ†ą“™ąµą“•ą“æąµ½ ą“Ŗą“æą“Øąµą“¤ąµą“£ą“Æąµą“³ąµą“³ ą“Ŗąµą“²ąµ‡ą“Æąµ¼ ą“²ą“­ąµą“Æą“®ą“²ąµą“².<br />\ną“¤ą“¾ą“™ąµą“•ąµ¾ą“•ąµą“•ąµ <a href=\"$1\">ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“­ą“¾ą“—ą“‚ ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æą“¾ą“µąµą“Øąµą“Øą“¤ą“¾ą“£ąµ</a> ą“…ą“²ąµą“²ąµ†ą“™ąµą“•ą“æąµ½ ą“¬ąµą“°ąµ—ą“øą“±ą“æąµ½ ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“æą“Ŗąµą“Ŗą“æą“•ąµą“•ą“¾ą“Øą“¾ą“Æą“æ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ą“’ą“°ąµ ą“Ŗąµą“²ąµ‡ą“Æąµ¼ ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æą“¾ą“µąµą“Øąµą“Øą“¤ą“¾ą“£ąµ</a>.",
+ "timedmedia-more": "ą“•ąµ‚ą“Ÿąµą“¤ąµ½...",
+ "timedmedia-dismiss": "ą“…ą“Ÿą“Æąµą“•ąµą“•ąµą“•",
+ "timedmedia-download": "ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚ ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“•",
+ "timedmedia-play-media": "ą“®ąµ€ą“”ą“æą“Æ ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“æą“Ŗąµą“Ŗą“æą“•ąµą“•ąµą“•",
+ "timedmedia-desc-link": "ą“ˆ ą“Ŗąµą“°ą“®ą“¾ą“£ą“¤ąµą“¤ąµ†ą“•ąµą“•ąµą“±ą“æą“šąµą“šąµ",
+ "timedmedia-oggThumb-version": "ą““ą“—ąµ-ą“¤ą“®ąµą“Ŗąµ ą“Ŗą“¤ą“æą“Ŗąµą“Ŗąµ $1 ą“…ą“²ąµą“²ąµ†ą“™ąµą“•ą“æąµ½ ą“Ŗąµą“¤ą“æą“Æą“¤ąµ ą““ą“—ąµ-ą“¹ą“¾ąµ»ą“”ąµą“²ą“±ą“æą“Øą“¾ą“µą“¶ąµą“Æą“®ą“¾ą“£ąµ.",
+ "timedmedia-oggThumb-failed": "ą“²ą“˜ąµą“šą“æą“¤ąµą“°ą“‚ ą“øąµƒą“·ąµą“Ÿą“æą“•ąµą“•ąµą“Øąµą“Øą“¤ą“æąµ½ ą““ą“—ąµ-ą“¤ą“®ąµą“Ŗąµ ą“Ŗą“°ą“¾ą“œą“Æą“Ŗąµą“Ŗąµ†ą“Ÿąµą“Ÿąµ.",
+ "timedmedia-status-header": "ą“Ÿąµą“°ą“¾ąµ»ą“øąµā€Œą“•ąµ‹ą“”ąµ ą“øąµą“„ą“æą“¤ą“æ",
+ "timedmedia-update-status": "ą“Ÿąµą“°ą“¾ąµ»ą“øąµā€Œą“•ąµ‹ą“”ąµ ą“øąµą“„ą“æą“¤ą“æ ą“Ŗąµą“¤ąµą“•ąµą“•ąµą“•",
+ "timedmedia-status": "ą“øąµą“„ą“æą“¤ą“æ",
+ "timedmedia-status-unknown": "ą“…ą“Ŗą“°ą“æą“šą“æą“¤ą“®ą“¾ą“Æ ą“øąµą“„ą“æą“¤ą“æ",
+ "timedmedia-transcodeinfo": "ą“Ÿąµą“°ą“¾ąµ»ą“øąµā€Œą“•ąµ‹ą“”ąµ ą“µąµą“Æąµąµ½ą“Ŗąµą“Ŗą“Øąµą“Øą“¤ąµą“¤ą“æą“Øąµą“±ąµ† ą“µą“æą“µą“°ą“£ą“‚",
+ "timedmedia-actions": "ą“Ŗąµą“°ą“µąµƒą“¤ąµą“¤ą“æą“•ąµ¾",
+ "timedmedia-direct-link": "ą“µąµą“Æąµąµ½ą“Ŗąµą“Ŗą“Øąµą“Øą“‚ ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“•",
+ "timedmedia-not-ready": "ą“¤ą“Æąµą“Æą“¾ą“±ą“¾ą“Æą“æą“Ÿąµą“Ÿą“æą“²ąµą“²",
+ "timedmedia-completed-on": "ą“Ÿąµą“°ą“¾ąµ»ą“øąµā€Œą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµ½ ą“Ŗąµ‚ąµ¼ą“¤ąµą“¤ą“æą“Æą“¾ą“Æą“æ $1",
+ "timedmedia-error-on": "ą“Ÿąµą“°ą“¾ąµ»ą“øąµā€Œą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æą“²ą“æąµ½ $1 ą“Žą“Øąµą“Ø ą“øą“®ą“Æą“¤ąµą“¤ąµ ą“Ŗą“æą““ą“µąµą“£ąµą“Ÿą“¾ą“Æą“æ",
+ "timedmedia-started-transcode": "ą“Ÿąµą“°ą“¾ąµ»ą“øąµā€Œą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµ½ $1 ą“®ąµą“®ąµą“Ŗąµ ą“†ą“°ą“‚ą“­ą“æą“šąµą“šąµ. $2",
+ "timedmedia-percent-done": "ą“ą“•ą“¦ąµ‡ą“¶ą“‚ $1% ą“Ŗąµ‚ąµ¼ą“¤ąµą“¤ą“æą“Æą“¾ą“Æą“æ",
+ "timedmedia-in-job-queue": "ą“œąµ‹ą“¬ąµ ą“•ąµą“Æąµ‚ą“µą“æą“²ąµ‡ą“Æąµą“•ąµą“•ąµ $1 ą“®ąµą“®ąµą“Ŗąµ ą“šąµ‡ąµ¼ą“¤ąµą“¤ąµ",
+ "timedmedia-unknown-target-size": "ą“²ą“•ąµą“·ąµą“Æą“®ą“æą“Ÿąµą“Øąµą“Ø ą“µą“²ą“æą“Ŗąµą“Ŗą“‚ ą“…ą“±ą“æą“Æą“æą“²ąµą“², $1 ą“Žąµ»ą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“¤ąµ",
+ "timedmedia-days": "{{PLURAL:$1|ą“’ą“°ąµ ą“¦ą“æą“µą“øą“‚|$1 ą“¦ą“æą“µą“øą“‚}}",
+ "timedmedia-hours": "{{PLURAL:$1|ą“’ą“°ąµ ą“®ą“£ą“æą“•ąµą“•ąµ‚ąµ¼|$1 ą“®ą“£ą“æą“•ąµą“•ąµ‚ąµ¼}}",
+ "timedmedia-minutes": "{{PLURAL:$1|ą“’ą“°ąµ ą“®ą“æą“Øą“æą“±ąµą“±ąµ|$1 ą“®ą“æą“Øą“æą“±ąµą“±ąµ}}",
+ "timedmedia-seconds": "{{PLURAL:$1|ą“’ą“°ąµ ą“øąµ†ą“•ąµą“•ą“Øąµą“±ąµ|$1 ą“øąµ†ą“•ąµą“•ą“Øąµą“±ąµ}}",
+ "timedmedia-reset": "ą“Ÿąµą“°ą“¾ąµ»ą“øąµā€Œą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµ½ ą“Ŗąµą“Øą“ƒą“øą“œąµą“œąµ€ą“•ą“°ą“æą“•ąµą“•ąµą“•",
+ "timedmedia-reset-confirm": "ą“ˆ ą“Ÿąµą“°ą“¾ąµ»ą“øąµā€Œą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµ½ ą“Ŗąµą“Øą“ƒą“øą“œąµą“œąµ€ą“•ą“°ą“æą“•ąµą“•ąµą“®ąµą“Ŗąµ‹ąµ¾ ą“Øą“æą“²ą“µą“æą“²ąµą“³ąµą“³ ą“«ą“Æąµ½ (ą“…ą“™ąµą“™ą“Øąµ†ą“ÆąµŠą“Øąµą“Øąµą“£ąµą“Ÿąµ†ą“™ąµą“•ą“æąµ½) ą“Øąµ€ą“•ąµą“•ą“‚ ą“šąµ†ą“Æąµą“Æą“Ŗąµą“Ŗąµ†ą“Ÿąµą“‚, ą“’ą“Ŗąµą“Ŗą“‚ ą“…ą“¤ąµ ą“œąµ‹ą“¬ąµ ą“•ąµą“Æąµ‚ą“µą“æą“²ąµ‡ą“Æąµą“•ąµą“•ąµ ą“Ÿąµą“°ą“¾ąµ»ą“øąµā€Œą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æą“¾ąµ» ą“µąµ€ą“£ąµą“Ÿąµą“‚ ą“šąµ‡ąµ¼ą“•ąµą“•ą“Ŗąµą“Ŗąµ†ą“Ÿąµą“•ą“Æąµą“‚ ą“šąµ†ą“Æąµą“Æąµą“‚. ą“µąµ€ą“£ąµą“Ÿąµą“‚-ą“Ÿąµą“°ą“¾ąµ»ą“øąµā€Œą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æą“¾ąµ» ą“…ą“²ąµą“Ŗą“øą“®ą“Æą“®ąµ†ą“Ÿąµą“•ąµą“•ąµą“Øąµą“Øą“¤ą“¾ą“£ąµ. <br /><br />\ną“¤ąµą“Ÿą“°ą“£ą“®ąµ†ą“Øąµą“Øąµ ą“¤ą“¾ą“™ąµą“•ąµ¾ą“•ąµą“•ąµą“±ą“Ŗąµą“Ŗą“¾ą“£ąµ‹?",
+ "timedmedia-reset-error": "ą“Ÿąµą“°ą“¾ąµ»ą“øąµā€Œą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµ½ ą“Ŗąµą“Øą“ƒą“øą“œąµą“œąµ€ą“•ą“°ą“æą“•ąµą“•ąµą“Øąµą“Øą“¤ą“æąµ½ ą“Ŗą“æą““ą“µąµą“£ąµą“Ÿą“¾ą“Æą“æ.",
+ "timedmedia-ogg": "ą““ą“—ąµ",
+ "timedmedia-webm": "ą“µąµ†ą“¬ąµą“Žą“‚",
+ "timedmedia-mp4": "ą“Žą“‚ą“Ŗą“æ4",
+ "timedmedia-source-file": "$1 ą“øąµą“°ąµ‹ą“¤ą“øąµą“øąµ",
+ "timedmedia-source-file-desc": "ą“Æą“„ą“¾ąµ¼ą“¤ąµą“„ ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚ $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "ą“Æą“„ą“¾ąµ¼ą“¤ąµą“„ ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚ $1 ($2)",
+ "timedmedia-derivative-160p.ogv": "ą““ą“—ąµ 160ą“Ŗą“æ",
+ "timedmedia-derivative-desc-160p.ogv": "ą“•ąµą“±ą“žąµą“ž ą“¬ą“¾ąµ»ą“”ąµā€Œą“µą“æą“”ąµą“¤ąµ ą““ą“—ąµ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚ (160ą“¬ą“æ)",
+ "timedmedia-derivative-desc-240p.ogv": "ą“µąµ†ą“¬ą“æą“²ąµ‚ą“Ÿąµ† ą“Žą“Ÿąµą“•ąµą“•ą“¾ą“µąµą“Øąµą“Ø ą““ą“—ąµ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚ (240P)",
+ "timedmedia-derivative-360p.ogv": "ą““ą“—ąµ 360ą“Ŗą“æ",
+ "timedmedia-derivative-desc-360p.ogv": "ą“µąµ†ą“¬ą“æą“²ąµ‚ą“Ÿąµ† ą“Žą“Ÿąµą“•ąµą“•ą“¾ą“µąµą“Øąµą“Ø ą““ą“—ąµ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚ (360ą“¬ą“æ)",
+ "timedmedia-derivative-480p.ogv": "ą““ą“—ąµ 480ą“Ŗą“æ",
+ "timedmedia-derivative-desc-480p.ogv": "ą“µąµ†ą“¬ą“æą“²ąµ‚ą“Ÿąµ† ą“Žą“Ÿąµą“•ąµą“•ą“¾ą“µąµą“Øąµą“Ø ą““ą“—ąµ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚ (480ą“¬ą“æ)",
+ "timedmedia-derivative-720p.ogv": "ą““ą“—ąµ 720ą“Ŗą“æ",
+ "timedmedia-derivative-desc-720p.ogv": "ą“‰ą“Øąµą“Øą“¤ ą“—ąµą“£ą“®ąµ‡ą“Øąµą“®ą“Æą“æąµ½ ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æą“¾ą“µąµą“Øąµą“Ø ą““ą“—ąµ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚ (720ą“¬ą“æ)",
+ "timedmedia-derivative-desc-1080p.ogv": "ą“Ŗąµ‚ąµ¼ą“£ąµą“£ ą“Žą“šąµą“šąµ.ą“”ą“æ. ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æą“¾ą“µąµą“Øąµą“Ø ą““ą“—ąµ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚ (1080 ą“Ŗą“æ)",
+ "timedmedia-derivative-160p.webm": "ą“µąµ†ą“¬ąµą“Žą“‚ 160ą“Ŗą“æ",
+ "timedmedia-derivative-desc-160p.webm": "ą“µąµ†ą“¬ą“æą“²ąµ‚ą“Ÿąµ† ą“Žą“Ÿąµą“•ąµą“•ą“¾ą“µąµą“Øąµą“Ø ą“µąµ†ą“¬ąµą“Žą“‚ (160ą“¬ą“æ)",
+ "timedmedia-derivative-360p.webm": "ą“µąµ†ą“¬ąµą“Žą“‚ 360ą“Ŗą“æ",
+ "timedmedia-derivative-desc-360p.webm": "ą“µąµ†ą“¬ą“æą“²ąµ‚ą“Ÿąµ† ą“Žą“Ÿąµą“•ąµą“•ą“¾ą“µąµą“Øąµą“Ø ą“µąµ†ą“¬ąµą“Žą“‚ (360ą“¬ą“æ)",
+ "timedmedia-derivative-480p.webm": "ą“µąµ†ą“¬ąµą“Žą“‚ 480ą“Ŗą“æ",
+ "timedmedia-derivative-desc-480p.webm": "ą“µąµ†ą“¬ą“æą“²ąµ‚ą“Ÿąµ† ą“Žą“Ÿąµą“•ąµą“•ą“¾ą“µąµą“Øąµą“Ø ą“µąµ†ą“¬ąµą“Žą“‚ (360ą“¬ą“æ)",
+ "timedmedia-derivative-720p.webm": "ą“µąµ†ą“¬ąµą“Žą“‚ 720ą“Ŗą“æ",
+ "timedmedia-derivative-desc-720p.webm": "ą“‰ą“Øąµą“Øą“¤ ą“—ąµą“£ą“®ąµ‡ą“Øąµą“®ą“Æą“æąµ½ ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æą“¾ą“µąµą“Øąµą“Ø ą“µąµ†ą“¬ąµą“Žą“‚ (720ą“¬ą“æ)",
+ "timedmedia-derivative-desc-1080p.webm": "ą“Ŗąµ‚ąµ¼ą“£ąµą“£ ą“Žą“šąµą“šąµ.ą“”ą“æ. ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æą“¾ą“µąµą“Øąµą“Ø ą“µąµ†ą“¬ąµą“Žą“‚ (1080 ą“Ŗą“æ)",
+ "timedmedia-derivative-desc-320p.mp4": "ą“‰ą“Ŗą“•ą“°ą“£-ą“øąµą“¹ąµƒą“¦ąµ ą“Žą“‚ą“Ŗą“æ4 (320ą“¬ą“æ)",
+ "timedmedia-derivative-desc-480p.mp4": "ą“µąµ†ą“¬ą“æą“²ąµ‚ą“Ÿąµ† ą“Žą“Ÿąµą“•ąµą“•ą“¾ą“µąµą“Øąµą“Ø ą“Žą“‚ą“Ŗą“æ4 (480ą“¬ą“æ)",
+ "timedmedia-derivative-desc-720p.mp4": "ą“Žą“šąµą“šąµ.ą“”ą“æ. ą“—ąµą“£ą“®ąµ‡ą“Øąµą“®ą“Æąµą“³ąµą“³ ą“Žą“‚ą“Ŗą“æ4 (720ą“¬ą“æ)",
+ "timedmedia-derivative-desc-1080p.mp4": "ą“Ŗąµ‚ąµ¼ą“£ąµą“£ ą“Žą“šąµą“šąµ.ą“”ą“æ. ą“”ąµ—ąµŗą“²ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æą“¾ą“µąµą“Øąµą“Ø ą“Žą“‚ą“Ŗą“æ4 (1080 ą“Ŗą“æ)",
+ "timedmedia-derivative-ogg": "ą““ą“—ąµ ą“µąµ‹ąµ¼ą“¬ą“æą“øąµ",
+ "timedmedia-derivative-desc-ogg": "ą““ą“—ąµ ą“µąµ‹ąµ¼ą“¬ą“æą“øąµ",
+ "timedmedia-derivative-opus": "ą““ą“Ŗą“øąµ",
+ "timedmedia-derivative-desc-opus": "ą““ą“Ŗą“øąµ",
+ "timedmedia-derivative-mp3": "ą“Žą“‚.ą“Ŗą“æ.3",
+ "timedmedia-derivative-desc-mp3": "ą“Žą“‚.ą“Ŗą“æ.3",
+ "timedmedia-derivative-m4a": "ą“Ž.ą“Ž.ą“øą“æ.",
+ "timedmedia-derivative-desc-m4a": "ą“Ž.ą“Ž.ą“øą“æ.",
+ "timedmedia-subtitle-new": "ą“Ŗąµą“¤ą“æą“Æ ą“Ŗą“°ą“æą“­ą“¾ą“· ą“¤ąµą“Ÿą“™ąµą“™ąµą“• ą“…ą“²ąµą“²ąµ†ą“™ąµą“•ą“æąµ½ ą“Øą“æą“²ą“µą“æą“²ąµą“³ąµą“³ą“¤ąµ ą“¤ą“æą“°ąµą“¤ąµą“¤ąµą“•",
+ "timedmedia-subtitle-new-desc": "ą“­ą“¾ą“· ą“¤ą“æą“°ą“žąµą“žąµ†ą“Ÿąµą“¤ąµą“¤ąµ, '''{{int:Timedmedia-subtitle-new-go}}''' ą“¬ą“Ÿąµą“Ÿąµŗ ą“…ą“®ąµ¼ą“¤ąµą“¤ąµą“•",
+ "timedmedia-subtitle-new-go": "ą“Ŗąµ‹ą“•ąµ‚",
+ "timedmedia-subtitle-language": "$1 ($2) ą“øą“‚ą“­ą“¾ą“·ą“£ą“°ąµ‡ą“–ą“•ąµ¾",
+ "timedmedia-subtitle-no-video": "ą“‡ą“Ŗąµą“Ŗąµ‹ą““ą“¤ąµą“¤ąµ† ą“øą“‚ą“­ą“¾ą“·ą“£ą“°ąµ‡ą“–ą“¾ ą“¤ą“¾ą“³ąµą“®ą“¾ą“Æą“æ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“™ąµą“™ą“³ąµŠą“Øąµą“Øąµą“‚ ą“šąµ‡ąµ¼ą“¤ąµą“¤ą“æą“Ÿąµą“Ÿą“æą“²ąµą“²",
+ "timedmedia-subtitle-no-subtitles": "ą“ˆ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“¤ąµą“¤ą“æą“Øąµ $1 ą“­ą“¾ą“·ą“Æą“æąµ½ ą“‡ą“Ŗąµą“Ŗąµ‹ąµ¾ ą“øą“‚ą“­ą“¾ą“·ą“£ą“°ąµ‡ą“–ą“ÆąµŠą“Øąµą“Øąµą“‚ ą“‡ą“²ąµą“², ą“¤ą“¾ą“™ąµą“•ąµ¾ą“•ąµą“•ąµ [{{fullurl:{{FULLPAGENAME}}|action=edit}} ą“ˆ ą“¤ą“¾ąµ¾ ą“¤ą“æą“°ąµą“¤ąµą“¤ą“æ] ą“…ą“µ ą“•ąµ‚ą“Ÿąµą“Ÿą“æą“šąµą“šąµ‡ąµ¼ą“•ąµą“•ą“¾ą“µąµą“Øąµą“Øą“¤ą“¾ą“£ąµ",
+ "timedmedia-subtitle-remote": "ą“ˆ ą“Ŗąµą“°ą“®ą“¾ą“£ą“¤ąµą“¤ą“æą“Øąµą“³ąµą“³ ą“øą“®ą“Æą“®ą“Øąµą“øą“°ą“æą“šąµą“šąµą“³ąµą“³ ą“Žą““ąµą“¤ąµą“¤ąµ $1-ąµ½ ą“¹ąµ‹ą“øąµą“±ąµą“±ąµ ą“šąµ†ą“Æąµą“¤ą“æą“Ÿąµą“Ÿąµą“£ąµą“Ÿąµ.",
+ "timedmedia-subtitle-remote-link": "ą“ˆ ą“Ŗąµą“°ą“®ą“¾ą“£ą“¤ąµą“¤ą“æą“Øąµą“³ąµą“³ [$1 ą“µą“æą“µą“°ą“£ ą“¤ą“¾ąµ¾] $2-ąµ½ ą“¤ą“¾ą“™ąµą“•ąµ¾ą“•ąµą“•ąµ ą“•ą“¾ą“£ą“¾ą“µąµą“Øąµą“Øą“¤ą“¾ą“£ąµ",
+ "timedmediahandler": "ą“®ąµ€ą“”ą“æą“Æ ą“øą“®ą“Æą“®ą“Øąµą“øą“°ą“æą“šąµą“šąµ ą“•ąµˆą“•ą“¾ą“°ąµą“Æą“‚ ą“šąµ†ą“Æąµą“Æą“¾ą“Øąµą“³ąµą“³ą“Æąµą“Ŗą“•ą“°ą“£ą“‚",
+ "timedmedia-videos": "{{PLURAL:$1|ą“’ą“°ąµ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚|$1 ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“™ąµą“™ąµ¾}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|ą“’ą“°ąµ ą““ą“—ąµ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚|$1 ą““ą“—ąµ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“™ąµą“™ąµ¾}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|ą“’ą“°ąµ ą“µąµ†ą“¬ąµą“Žą“‚ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“‚|$1 ą“µąµ†ą“¬ąµą“Žą“‚ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“™ąµą“™ąµ¾}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|ą“’ą“°ąµ ą“Ÿąµą“°ą“¾ąµ»ą“øąµą“•ąµ‹ą“”ąµ|$1 ą“Ÿąµą“°ą“¾ąµ»ą“øąµą“•ąµ‹ą“”ąµą“•ąµ¾}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|ą“’ą“°ąµ†ą“£ąµą“£ą“‚ ą“Ÿąµą“°ą“¾ąµ»ą“øąµą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“Øąµą“Øąµ|$1 ą“Žą“£ąµą“£ą“‚ ą“Ÿąµą“°ą“¾ąµ»ą“øąµą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“Øąµą“Øąµ}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|ą“’ą“°ąµ†ą“£ąµą“£ą“‚ ą“Ÿąµą“°ą“¾ąµ»ą“øąµą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æą“¾ą“Øą“¾ą“Æą“æ ą“‰ą“£ąµą“Ÿąµ|$1 ą“Žą“£ąµą“£ą“‚ ą“Ÿąµą“°ą“¾ąµ»ą“øąµą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æą“¾ą“Øą“¾ą“Æą“æ ą“‰ą“£ąµą“Ÿąµ}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|ą“’ą“°ąµ†ą“£ąµą“£ą“‚ ą“Ÿąµą“°ą“¾ąµ»ą“øąµą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“Øąµą“Øą“¤ąµ ą“Ŗą“°ą“¾ą“œą“Æą“Ŗąµą“Ŗąµ†ą“Ÿąµą“Ÿąµ|$1 ą“Žą“£ąµą“£ą“‚ ą“Ÿąµą“°ą“¾ąµ»ą“øąµą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“Æąµą“Øąµą“Øą“¤ąµ ą“Ŗą“°ą“¾ą“œą“Æą“Ŗąµą“Ŗąµ†ą“Ÿąµą“Ÿąµ}}",
+ "timedmedia-file": "ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚",
+ "timedmedia-audios": "{{PLURAL:$1|ą“’ą“°ąµ ą“¶ą“¬ąµą“¦ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚|$1 ą“¶ą“¬ąµą“¦ą“Ŗąµą“°ą“®ą“¾ą“£ą“™ąµą“™ąµ¾}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|ą“’ą“°ąµ ą““ą“—ąµ (Ogg) ą“¶ą“¬ąµą“¦ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚|$1 ą““ą“—ąµ (Ogg) ą“¶ą“¬ąµą“¦ą“Ŗąµą“°ą“®ą“¾ą“£ą“™ąµą“™ąµ¾}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|ą“’ą“°ąµ ą“«ąµą“²ą“¾ą“•ąµ (FLAC) ą“¶ą“¬ąµą“¦ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚|$1 ą“«ąµą“²ą“¾ą“•ąµ (FLAC) ą“¶ą“¬ąµą“¦ą“Ŗąµą“°ą“®ą“¾ą“£ą“™ąµą“™ąµ¾}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|ą“’ą“°ąµ ą“µąµ‡ą“µąµ (WAV) ą“¶ą“¬ąµą“¦ą“Ŗąµą“°ą“®ą“¾ą“£ą“‚|$1 ą“µąµ‡ą“µąµ (WAV) ą“¶ą“¬ąµą“¦ą“Ŗąµą“°ą“®ą“¾ą“£ą“™ąµą“™ąµ¾}}",
+ "right-transcode-reset": "ą“Ŗąµą“Øą“ƒą“•ąµą“°ą“®ąµ€ą“•ą“°ą“£ą“‚ ą“Ŗą“°ą“¾ą“œą“Æą“Ŗąµą“Ŗąµ†ą“Ÿąµą“Ÿąµ ą“…ą“²ąµą“²ąµ†ą“™ąµą“•ą“æąµ½ ą“Ÿąµą“°ą“¾ąµ»ą“øąµą“•ąµ‹ą“”ąµ ą“šąµ†ą“Æąµą“¤ ą“šą“²ą“šąµą“šą“æą“¤ąµą“°ą“™ąµą“™ąµ¾ ą“œąµ‹ą“¬ąµ ą“•ąµą“Æąµ‚ą“µą“æą“²ąµ‡ą“Æąµą“•ąµą“•ąµ ą“µąµ€ą“£ąµą“Ÿąµą“‚ ą“šąµ‡ąµ¼ą“¤ąµą“¤ąµ",
+ "right-transcode-status": "[[Special:TimedMediaHandler|ą“‡ą“Ŗąµą“Ŗąµ‹ą““ą“¤ąµą“¤ąµ† ą“Ÿąµą“°ą“¾ąµ»ą“øąµą“•ąµ‹ą“”ąµ ą“Ŗąµą“°ą“µąµ¼ą“¤ąµą“¤ą“Øą“¤ąµą“¤ą“æą“Øąµą“±ąµ† ą“µą“æą“µą“°ą“™ąµą“™ąµ¾]] ą“•ą“¾ą“£ąµą“•",
+ "action-transcode-status": "ą“‡ą“Ŗąµą“Ŗąµ‹ą““ą“¤ąµą“¤ąµ† ą“Ÿąµą“°ą“¾ąµ»ą“øąµą“•ąµ‹ą“”ą“æą“™ąµ ą“øąµą“„ą“æą“¤ą“æ ą“•ą“¾ą“£ąµą“•",
+ "orphanedtimedtext": "ą“‰ą“Ŗą“Æąµ‹ą“—ą“æą“•ąµą“•ą“Ŗąµą“Ŗąµ†ą“Ÿą“¾ą“¤ąµą“¤ ą“øą“®ą“Æą“¾ą“Øąµą“øąµƒą“¤ą“Æąµ†ą““ąµą“¤ąµą“¤ąµ ą“¤ą“¾ą“³ąµą“•ąµ¾",
+ "orphanedtimedtext-summary": "ą“¬ą“Øąµą“§ą“Ŗąµą“Ŗąµ†ą“Ÿąµą“Ÿ ą“Ŗąµą“°ą“®ą“¾ą“£ą“™ąµą“™ąµ¾ ą“‡ą“²ąµą“²ą“¾ą“¤ąµą“¤ [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] ą“¤ą“¾ą“³ąµą“•ą“³ąµą“Ÿąµ† ą“Ŗą“Ÿąµą“Ÿą“æą“•.",
+ "orphanedtimedtext-unsupported": "ą“®ąµˆą“Žą“øąµą“•ąµą“Æąµą“Žąµ½ ą“”ąµ‡ą“±ąµą“±ą“¾ą“¬ąµ‡ą“øąµą“•ą“³ąµ† ą“®ą“¾ą“¤ąµą“°ą“®ąµ‡ ą“ˆ ą“Ŗąµą“°ą“¤ąµą“Æąµ‡ą“•ą“¤ą“¾ąµ¾ ą“Ŗą“æą“Øąµą“¤ąµą“£ą“Æąµą“•ąµą“•ąµą“Øąµą“Øąµą“³ąµą“³ąµ.",
+ "orphanedtimedtext-notimedtext": "ą“øą“®ą“Æą“¾ą“Øąµą“øąµƒą“¤ą“Æąµ†ą““ąµą“¤ąµą“¤ąµ ą“ˆ ą“µą“æą“•ąµą“•ą“æą“Æą“æąµ½ ą“øą“œąµą“œą“®ą“¾ą“•ąµą“•ą“æą“Æą“æą“Ÿąµą“Ÿą“æą“²ąµą“².",
+ "apihelp-transcodereset-param-title": "ą“®ąµ€ą“”ą“æą“Æ ą“Ŗąµą“°ą“®ą“¾ą“£ą“¤ąµą“¤ą“æą“Øąµą“±ąµ† ą“¤ą“²ą“•ąµą“•ąµ†ą“Ÿąµą“Ÿąµ."
+}
diff --git a/extensions/TimedMediaHandler/i18n/mr.json b/extensions/TimedMediaHandler/i18n/mr.json
new file mode 100644
index 00000000..0be5fe88
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/mr.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kaustubh",
+ "V.narsikar",
+ "Htt"
+ ]
+ },
+ "timedmedia-desc": "ą¤‘ą¤— ą¤„ą¤æą¤Æą„‹ą¤°ą¤¾ ą¤µ ą¤µą„‰ą¤°ą„ą¤¬ą¤æą¤ø ą¤øą¤‚ą¤šą¤æą¤•ą¤¾ą¤‚ą¤øą¤¾ą¤ ą„€ą¤šą¤¾ ą¤šą¤¾ą¤²ą¤•, ą¤œą¤¾ą¤µą¤¾ą¤øą„ą¤•ą„ą¤°ą„€ą¤Ŗą„ą¤Ÿ ą¤Ŗą„ą¤²ą„‡ą¤Æą¤° ą¤øą¤•ą¤Ÿ",
+ "timedmedia-ogg-short-audio": "ą¤‘ą¤— $1 ą¤§ą„ą¤µą¤Øą„€ ą¤øą¤‚ą¤šą¤æą¤•ą¤¾, $2",
+ "timedmedia-ogg-short-video": "ą¤‘ą¤— $1 ą¤šą¤²ą¤¤ą¤šą¤æą¤¤ą„ą¤° ą¤øą¤‚ą¤šą¤æą¤•ą¤¾, $2",
+ "timedmedia-ogg-short-general": "ą¤‘ą¤— $1 ą¤®ą„€ą¤”ą¤æą¤Æą¤¾ ą¤øą¤‚ą¤šą¤æą¤•ą¤¾, $2",
+ "timedmedia-ogg-long-audio": "ą¤‘ą¤— $1 ą¤§ą„ą¤µą¤Øą„€ ą¤øą¤‚ą¤šą¤æą¤•ą¤¾, ą¤²ą¤¾ą¤‚ą¤¬ą„€ $2, $3",
+ "timedmedia-ogg-long-video": "ą¤‘ą¤— $1 ą¤šą¤²ą¤¤ą¤šą¤æą¤¤ą„ą¤° ą¤øą¤‚ą¤šą¤æą¤•ą¤¾, ą¤²ą¤¾ą¤‚ą¤¬ą„€ $2, $4Ɨ$5 ą¤Ŗą„€ą¤•ą„ą¤øą„‡ą¤²ą„ą¤ø, $3",
+ "timedmedia-ogg-long-multiplexed": "ą¤‘ą¤— ą¤§ą„ą¤µą¤Øą„€/ą¤šą¤æą¤¤ą„ą¤° ą¤øą¤‚ą¤šą¤æą¤•ą¤¾, $1, ą¤²ą¤¾ą¤‚ą¤¬ą„€ $2, $4Ɨ$5 ą¤Ŗą¤æą¤•ą„ą¤øą„‡ą¤²ą„ą¤ø, $3 ą¤ą¤•ą„‚ą¤£",
+ "timedmedia-ogg-long-general": "ą¤‘ą¤— ą¤®ą„€ą¤”ą¤æą¤Æą¤¾ ą¤øą¤‚ą¤šą¤æą¤•ą¤¾, ą¤²ą¤¾ą¤‚ą¤¬ą„€ $2, $3",
+ "timedmedia-ogg-long-error": "ą¤šą„ą¤•ą„€ą¤šą„€ ą¤‘ą¤— ą¤øą¤‚ą¤šą¤æą¤•ą¤¾: $1",
+ "timedmedia-more": "ą¤†ą¤£ą¤–ą„€...",
+ "timedmedia-dismiss": "ą¤¬ą¤‚ą¤¦ ą¤•ą¤°ą¤¾",
+ "timedmedia-download": "ą¤øą¤‚ą¤šą¤æą¤•ą¤¾ ą¤…ą¤§ą¤æą¤­ą¤¾ą¤°ą¤£ ą¤•ą¤°ą¤¾",
+ "timedmedia-desc-link": "ą¤Æą¤¾ ą¤øą¤‚ą¤šą¤æą¤•ą„‡ą¤¬ą¤¦ą„ą¤¦ą¤²ą¤šą„€ ą¤®ą¤¾ą¤¹ą¤æą¤¤ą„€",
+ "timedmedia-source-file": "$1 ą¤øą„ą¤°ą„‹ą¤¤",
+ "timedmedia-source-audio-file-desc": "ą¤®ą„‚ą¤³ $1 ą¤øą¤‚ą¤šą¤æą¤•ą¤¾ ($2)",
+ "timedmediahandler": "ą¤Ÿą¤¾ą¤ˆą¤®ą„ą¤”ą¤®ą¤æą¤”ą¤æą¤Æą¤¾ą¤¹ą„…ą¤‚ą¤”ą¤²ą¤°",
+ "timedmedia-videos": "{{PLURAL:$1|$1 ą¤µą„ą¤¹ą„€ą¤”ą¤æą¤“}}",
+ "timedmedia-audios": "{{PLURAL:$1|$1 ą¤§ą„ą¤µą¤Øą„€ ą¤øą¤‚ą¤šą¤æą¤•ą¤¾}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ogg ą¤§ą„ą¤µą¤Øą„€ ą¤øą¤‚ą¤šą¤æą¤•ą¤¾}}"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ms.json b/extensions/TimedMediaHandler/i18n/ms.json
new file mode 100644
index 00000000..504aa6f0
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ms.json
@@ -0,0 +1,97 @@
+{
+ "@metadata": {
+ "authors": [
+ "Anakmalaysia",
+ "Aviator"
+ ]
+ },
+ "timedmedia-desc": "Pemproses audio, video dan teks bermasa, dengan sokongan format untuk WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "fail bunyi Ogg $1, $2",
+ "timedmedia-ogg-short-video": "fail video Ogg $1, $2",
+ "timedmedia-ogg-short-general": "fail media Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "fail bunyi Ogg $1, tempoh $2, $3",
+ "timedmedia-ogg-long-video": "fail video Ogg $1, tempoh $2, $4Ɨ$5 piksel, $3",
+ "timedmedia-ogg-long-multiplexed": "fail audio/video multipleks Ogg, $1, tempoh $2, $4Ɨ$5 piksel, keseluruhan $3",
+ "timedmedia-ogg-long-general": "fail media Ogg, tempoh $2, $3",
+ "timedmedia-ogg-long-error": "Fail Ogg tidak sah: $1",
+ "timedmedia-webm-short-video": "fail video WebM $1, $2",
+ "timedmedia-webm-long-video": "fail audio/video webM, $1, tempoh $2, $4Ɨ$5 piksel, $3 keseluruhannya",
+ "timedmedia-flac-short-audio": "Fail audio FLAC, $1",
+ "timedmedia-flac-long-audio": "Fail audio FLAC, tempoh $1, $2 keseluruhannya",
+ "timedmedia-wav-short-audio": "Fail audio WAV, $1",
+ "timedmedia-wav-long-audio": "Fail audio WAV, tempoh $1, $2 keseluruhannya",
+ "timedmedia-wav-pcm-required": "Anda boleh memuat naik WAV PCM (Pulse Code Modulation) sahaja.",
+ "timedmedia-mp4-short-video": "fail video MP4 $1, $2",
+ "timedmedia-mp4-long-video": "fail audio/video MP4, $1, tempoh $2, $4Ɨ$5 piksel, $3 keseluruhannya",
+ "timedmedia-no-player-js": "Maaf, pelayar anda sama ada telah dimatikan JavaScript-nya ataupun tidak mempunyai sebarang pemain yang disokong.<br />\nAnda boleh <a href=\"$1\">memuat turun sedutan</a> itu atau <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">memuat turun pemain</a> yang boleh memutarkan sedutan berkenaan dalam pelayar anda.",
+ "timedmedia-more": "Lagiā€¦",
+ "timedmedia-dismiss": "Tutup",
+ "timedmedia-download": "Muat turun fail",
+ "timedmedia-play-media": "Mainkan media",
+ "timedmedia-desc-link": "Perihal fail ini",
+ "timedmedia-oggThumb-version": "OggHandler memerlukan oggThumb versi $1 ke atas.",
+ "timedmedia-oggThumb-failed": "oggThumb gagal mencipta gambar kenit.",
+ "timedmedia-status-header": "Status transkod",
+ "timedmedia-update-status": "Kemaskinikan status transkod",
+ "timedmedia-status": "Status",
+ "timedmedia-status-unknown": "Status tidak diketahui",
+ "timedmedia-transcodeinfo": "Keterangan hasil terbitan transkod",
+ "timedmedia-actions": "Tindakan",
+ "timedmedia-direct-link": "Muat turun terbitan",
+ "timedmedia-not-ready": "Belum sedia",
+ "timedmedia-completed-on": "Pentranskodan selesai pada $1",
+ "timedmedia-error-on": "Ralat dalam transkod pada $1",
+ "timedmedia-started-transcode": "Pentranskodan bermula $1 lalu. $2",
+ "timedmedia-percent-done": "Kira-kira $1% selesai",
+ "timedmedia-in-job-queue": "Ditambahkan ke dalam baris gilir kerja $1 lalu",
+ "timedmedia-unknown-target-size": "Saiz sasaran tidak diketahui, $1 dikodkan",
+ "timedmedia-days": "$1 hari",
+ "timedmedia-hours": "$1 jam",
+ "timedmedia-minutes": "$1 minit",
+ "timedmedia-seconds": "$1 saat",
+ "timedmedia-reset": "Set semula transkod",
+ "timedmedia-reset-confirm": "Mengeset semula transkod ini akan membuang sebarang fail yang sedia ada (jika ada), lalu menambahkan semula transkod ke dalam baris gilir tugas. Pentranskodan semula akan memakan masa.<br /><br />Adakah anda tetap ingin melakukannya?",
+ "timedmedia-reset-error": "Ralat ketika mengeset semula tugas pentranskodan.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Sumber $1",
+ "timedmedia-source-file-desc": "Fail $1 asli, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Fail $1 asli ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Video Ogg lebar jalur rendah (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Video Ogg boleh strim web (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Video Ogg boleh strim web (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Video Ogg boleh muat turun bermutu tinggi (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "video Ogg HD sepenuhnya yang boleh dimuat turun (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "WebM boleh strim web (160P)",
+ "timedmedia-derivative-desc-360p.webm": "WebM boleh strim web (360P)",
+ "timedmedia-derivative-desc-480p.webm": "WebM boleh strim web (480P)",
+ "timedmedia-derivative-desc-720p.webm": "Video WebM boleh muat turun bermutu tinggi (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "WebM HD sepenuhnya yang boleh dimuat turun (1080P)",
+ "timedmedia-derivative-desc-320p.mp4": "MP4 mesra peranti (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "MP4 boleh strim web (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 bermutu HD (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "MP4 bermutu HD sepenuhnya (1080P)",
+ "timedmedia-subtitle-new": "Buat terjemahan baru atau sunting terjemahan sedia ada",
+ "timedmedia-subtitle-new-desc": "Pilih bahasa dan tekan butang '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Pergi",
+ "timedmedia-subtitle-language": "Sari kata $1 ($2)",
+ "timedmedia-subtitle-no-video": "Tiada video yang berkaitan dengan halaman sari kata ini",
+ "timedmedia-subtitle-no-subtitles": "Sekarang, tiada sari kata dalam $1 bagi video ini; anda boleh [{{fullurl:{{FULLPAGENAME}}|action=edit}} menyunting halaman ini] untuk menambahkannya",
+ "timedmedia-subtitle-remote": "Teks termasa untuk fail ini dihoskan di $1",
+ "timedmedia-subtitle-remote-link": "Anda boleh [$1 membaca halaman keterangan] untuk fail ini di $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "$1 video",
+ "timedmedia-ogg-videos": "$1 video Ogg",
+ "timedmedia-webm-videos": "$1 video WebM",
+ "timedmedia-derivative-state-transcodes": "$1 transkod",
+ "timedmedia-derivative-state-active": "$1 transkod aktif",
+ "timedmedia-derivative-state-queued": "$1 transkod berbaris",
+ "timedmedia-derivative-state-failed": "$1 transkod gagal",
+ "timedmedia-file": "Fail",
+ "timedmedia-audios": "$1 fail audio",
+ "timedmedia-ogg-audios": "$1 fail audio Ogg",
+ "timedmedia-flac-audios": "$1 fail audio FLAC",
+ "timedmedia-wav-audios": "$1 fail audio WAV",
+ "right-transcode-reset": "Mengeset semula video-video yang gagal atau ditranskodkan supaya dimasukkan semula ke dalam barisan gilir.",
+ "right-transcode-status": "Melihat [[Special:TimedMediaHandler|maklumat tentang kegiatan transkod semasa]]",
+ "action-transcode-status": "melihat status pentranskodan semasa"
+}
diff --git a/extensions/TimedMediaHandler/i18n/mt.json b/extensions/TimedMediaHandler/i18n/mt.json
new file mode 100644
index 00000000..a60fd776
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/mt.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Leli Forte"
+ ]
+ },
+ "timedmedia-no-player-js": "Jiddispjaċina li l-browser tiegħek jew m'għandux JavaScript attivat jew m'għandu l-ebda player supportat.<br />\nTista' <a href=\"$1\"> tniżżel il-vidjow</a> jew <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">tniżżel player</a> biex tara l-vidjow fuq il-browser tiegħek.",
+ "timedmedia-more": "Aktar",
+ "timedmedia-source-file": "Sors $1",
+ "timedmedia-source-audio-file-desc": "Fajl oriĔinali $1 ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/myv.json b/extensions/TimedMediaHandler/i18n/myv.json
new file mode 100644
index 00000000..35b195ae
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/myv.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Botuzhaleny-sodamo"
+ ]
+ },
+ "timedmedia-more": "Š”ŠµŠ“Šµ Š»Š°Š¼Š¾...",
+ "timedmedia-dismiss": "ŠŸŠµŠŗстŠ°Š¼Ń",
+ "timedmedia-download": "Š¢Š°Ń€Š³Š°Š¼Š¾ фŠ°Š¹Š»Š°",
+ "timedmedia-play-media": "Š”ŠµŠ“яŠ¼Š¾ Š¼ŠµŠ“Šøя",
+ "timedmedia-desc-link": "Š¢Šµ фŠ°Š¹Š»Š°Š“Š¾Š½Ń‚ŃŒ",
+ "timedmedia-source-file": "$1 Š»ŠøсьŠ¼Š°Šæря"
+}
diff --git a/extensions/TimedMediaHandler/i18n/mzn.json b/extensions/TimedMediaHandler/i18n/mzn.json
new file mode 100644
index 00000000..f383daec
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/mzn.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ł…Ų­Ś©"
+ ]
+ },
+ "timedmedia-no-player-js": "ŲØŁŽŲ®Ų“ŁŁ†Ł‘ŪŒŲŒ Ų¬Ų§ŁˆŲ§ Ų§Ų³Ś©Ų±ŪŒŁ¾ŲŖ ŁŁ†Ų±Ł… Ų§ŁŲ²Ų§Ų± Ų“Ł…Ł‡ ŲØŲ±ŁˆŲ²Ų± ŲÆŁ„Ł‡ ŁŲ¹Ų§Ł„ Ł†ŪŒā€ŒŪŒŁ‡ŲŒ ŪŒŲ§ Ų“Ł…Ł‡ ŲØŲ±ŁˆŲ²Ų± Ų§ŪŒŁ† Ł†Ų±Ł… Ų§ŁŲ²Ų§Ų± Ų±Ł‡ Ų³Ų§Ł¾ŁˆŲ±ŲŖ Ł†Ś©Ų§Ł†ŲÆŁ‡.<br />\nŲ“Ł…Ų§ ŲŖŁˆŁ†ŲÆŪŒ <a href=\"$1\">Ų§ŪŒŁ† ŁˆŪŒŲÆŪŒŁˆ Ų±Ł‡ ŲÆŲ§Ł†Ł„ŁˆŲÆ</a> Łˆ ŪŒŲ§ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">Ų§ŲŖŲ§ Ł¾Ł„ŪŒŲ±</a> Ų§ŪŒŁ† ŁˆŪŒŲÆŪŒŁˆ Ų±Ł‡ Ł‡Ų§Ų±Ų“ŪŒā€ŒŪŒŁ† ŁˆŲ³Ł‘Ł‡ ŲÆŲ§Ł†Ł„ŁˆŲÆ Ł‡Ų§Ś©Ł†ŪŒŁ†.",
+ "timedmedia-source-file": "$1 Ł…ŲØŲÆŲ£",
+ "timedmedia-source-audio-file-desc": "Ų§ŲµŁ„ŪŒ $1 Ł¾Ų±ŁˆŁ†ŲÆŁ‡ ( $2 )"
+}
diff --git a/extensions/TimedMediaHandler/i18n/nah.json b/extensions/TimedMediaHandler/i18n/nah.json
new file mode 100644
index 00000000..5c41b6ca
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/nah.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Fluence",
+ "Taresi"
+ ]
+ },
+ "timedmedia-more": "Huehca ōmpa...",
+ "timedmedia-download": "Tictemōz tlahcuilōlli",
+ "timedmedia-desc-link": "Inīn tlahcuilōltechcopa",
+ "timedmedia-source-file": "$1 mēyalli"
+}
diff --git a/extensions/TimedMediaHandler/i18n/nap.json b/extensions/TimedMediaHandler/i18n/nap.json
new file mode 100644
index 00000000..c9953c8f
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/nap.json
@@ -0,0 +1,122 @@
+{
+ "@metadata": {
+ "authors": [
+ "C.R.",
+ "Chelin",
+ "Candalua"
+ ]
+ },
+ "timedmedia-desc": "Gestore p' 'e file audio, video e teste temporizzate, cu 'e formate supportate pe WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "File audio Ogg $1, $2",
+ "timedmedia-ogg-short-video": "File video Ogg $1, $2",
+ "timedmedia-ogg-short-general": "File multimediale Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "File audio Ogg $1, durata $2, $3",
+ "timedmedia-ogg-long-video": "File video Ogg $1, durata $2, dimenziune $4Ɨ$5 pixel, $3",
+ "timedmedia-ogg-long-multiplexed": "File multiplexed audie e video Ogg $1, lunghezze $2, $4 x $5 pixel, $3 in totale",
+ "timedmedia-ogg-long-general": "File media Ogg, lunghezze $2, $3",
+ "timedmedia-ogg-long-error": "Ogg file invalide: $1",
+ "timedmedia-ogg-long-no-streams": "File multimediale Ogg. AttenziĆ²: nun ĆØ stato ricanusciuto nisciuno codec ausato ind'a stu file.",
+ "timedmedia-webm-short-video": "WebM $1 file video, $2",
+ "timedmedia-webm-long-video": "File WebM audio/video, $1, lunghezze $2, $4 Ɨ $5 pixel, $3 in totale",
+ "timedmedia-flac-short-audio": "File audio FLAC, $1",
+ "timedmedia-flac-long-audio": "File audio FLAC, lunghezze $1, in totale $2",
+ "timedmedia-wav-short-audio": "File audio WAV, $1",
+ "timedmedia-wav-long-audio": "File audio WAV, lunghezze $1, in totale $2",
+ "timedmedia-wav-pcm-required": "Putite surtanto carrecĆ  WAV 'e tipo PCM (Codece 'e Modulazione Pulsate).",
+ "timedmedia-mp4-short-video": "MP4 $1 file video, $2",
+ "timedmedia-mp4-long-video": "File MP4 audio/video, $1, lunghezze $2, $4 Ɨ $5 pixel, $3 in totale",
+ "timedmedia-no-player-js": "Spiacente, 'o browser vuosto tene 'o JavaScript stutato o nun tĆØne nu secutore suppurtato.<br />\nPutite <a href=\"$1\">scarrecĆ  'o video</a> o <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">scarrecĆ  nu secutore</a> pe' putĆØ miette 'o play Ć“ video int' 'o browser vuosto.",
+ "timedmedia-more": "Ato...",
+ "timedmedia-dismiss": "Chiure",
+ "timedmedia-download": "Scarreca 'o file",
+ "timedmedia-play-media": "Secuta 'u media",
+ "timedmedia-desc-link": "'Mfurmaziune ncopp'a stu file",
+ "timedmedia-oggThumb-version": "OggHandler vulesse 'a verziona 'e oggThumb $1 o cchiĆ¹ nnanz.",
+ "timedmedia-oggThumb-failed": "oggThumn ha fallite a ccriĆ  'e miniature.",
+ "timedmedia-status-header": "Stato d' 'a codifeca",
+ "timedmedia-update-status": "Agghiuorna 'o stato d' 'a codifeca",
+ "timedmedia-status": "Stato",
+ "timedmedia-status-unknown": "Stato scanusciuto",
+ "timedmedia-transcodebitrate": "Bitrate",
+ "timedmedia-transcodeduration": "Tiempo 'e codifeca",
+ "timedmedia-transcodeinfo": "Furmato",
+ "timedmedia-actions": "Aziune",
+ "timedmedia-direct-link": "Scarreca",
+ "timedmedia-not-ready": "Nun ĆØ pronto",
+ "timedmedia-completed-on": "$1 fernuto",
+ "timedmedia-error-on": "Errore dint' 'o $1",
+ "timedmedia-started-transcode": "Accummenciato $1 fa. $2",
+ "timedmedia-percent-done": "CchiĆ¹ o meno $1% fatto",
+ "timedmedia-in-job-queue": "Ghiuonta a 'a Fatica misa ncĆ³ra $1 fĆ ",
+ "timedmedia-unknown-target-size": "Diminziona 'e destinazione scanusciuta, $1 encoded",
+ "timedmedia-days": "{{PLURAL:$1|1 juorno|$1 ghiuorne}}",
+ "timedmedia-hours": "{{PLURAL:$1|n'ora|$1 ore}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minuto|$1 minute}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 secondo|$1 seconde}}",
+ "timedmedia-reset": "Azzere 'a transcodifeca",
+ "timedmedia-reset-confirm": "Resettanno sta transcodifica tuttuquante 'e file ch'esisteno mĆ² (si ce stanno), e po' azzeccasse 'a transcodifica int'a 'o codece d' 'a fatica. Se pigliasse nu poco 'e tiempo pe' putĆ© ffĆ  'o re-transcode. <br /><br />\nSite sicuro/a ca vulite ghƬ annanze?",
+ "timedmedia-reset-error": "Errore pe' tramente ca se steva azzeranno 'a fatica 'e transcodifeca.",
+ "timedmedia-source-file": "$1 funte",
+ "timedmedia-source-file-desc": "File origgenale $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "File origgenale $1 ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Ogg video cu banda vascia (160P)",
+ "timedmedia-derivative-desc-240p.ogv": "Ogg video ca se putesse mannĆ  pe' webstreaming (240P)",
+ "timedmedia-derivative-desc-360p.ogv": "Ogg video ca se putesse mannĆ  pe' webstreaming (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Ogg video ca se putesse mannĆ  pe' webstreaming (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Ogg video 'e qualitĆ  auta scarrecabbele (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "Video Ogg scarrecabbele 'n Full HD (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "Flusso web WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "Flusse web WebM (360P)",
+ "timedmedia-derivative-desc-480p.webm": "Flusse web WebM (480P)",
+ "timedmedia-derivative-desc-720p.webm": "Ogg video 'e qualitĆ  auta scarrecabbele WebM (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "Video Ogg scarrecabbele 'n Full HD WebM (1080P)",
+ "timedmedia-derivative-desc-2160p.webm": "WebM scarrecabbele 'n Full 4K (2160P)",
+ "timedmedia-derivative-desc-360p.vp9.webm": "Flusse web WebM VP9 (360P)",
+ "timedmedia-derivative-desc-480p.vp9.webm": "Flusse web WebM (480P)",
+ "timedmedia-derivative-desc-720p.vp9.webm": "Flusse HD WebM VP9 (720P)",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "Flusse Full HD WebM VP9 (1080P)",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "WebM VP9 'e qualitĆ  Full 4K (2160P)",
+ "timedmedia-derivative-desc-320p.mp4": "Semprice pe' ll'apparicchie MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "Flusse web WebM (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "QualitĆ  HD MP4 (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "MP4 'e qualitĆ  Full HD (1080P)",
+ "timedmedia-derivative-desc-2160p.mp4": "MP4 'e qualitĆ  Full 4K (2160P)",
+ "timedmedia-subtitle-new": "CrƬa na traduzione o cagna chella esistente",
+ "timedmedia-subtitle-new-desc": "Sceglie na lengua e clicca 'o buttone '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "VĆ je",
+ "timedmedia-subtitle-language": "$1 ($2) sottotitele",
+ "timedmedia-subtitle-no-video": "Nun ce stanno video ssuocie ch' 'e sottotitole d' 'e paggene 'e mĆ².",
+ "timedmedia-subtitle-no-subtitles": "Nun ce stanno mĆ² sottotitule dint'a $1 pe' stu video, putite [{{fullurl:{{FULLPAGENAME}}|action=cagnĆ }} 'a paggena] pe' putĆØ azzeccĆ  chiste.",
+ "timedmedia-subtitle-remote": "'O testo temporizzate pe' stu file fuje ospitato ncopp'a $1",
+ "timedmedia-subtitle-remote-link": "Putite [$1 vedƩ 'a paggena 'e descrizione] 'e stu file ncopp'a $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 video}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 video Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 video WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transcodifica|$1 transcodifiche}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 transcodifica|$1 transcodifiche}} in esecuzzione",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 transcodifica|$1 transcodifiche}} in coda",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 guastaje transcodifeca|$1 guastaje 'e transcodifiche}}",
+ "timedmedia-file": "File",
+ "timedmedia-audios": "{{PLURAL:$1|$1 file audio}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 file audio Ogg}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 file audio FLAC}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 file audio WAV}}",
+ "right-transcode-reset": "Appiccia n'ata vota 'e transcodifiche guaste 'e video ca songo state mise dint'a cĆ³ra 'e fatiche n'ata vota",
+ "right-transcode-status": "Vide [[Special:TimedMediaHandler|'e nfurmaziune ncopp' 'a transcodifeca 'e mĆ²]]",
+ "action-transcode-status": "vide 'o stato 'e transcodifeca 'e mo",
+ "orphanedtimedtext": "Paggene TimedText (sottotitule) urfanielle",
+ "orphanedtimedtext-summary": "Elenco 'e pagine [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] ca nun teneno 'o file currispunnente.",
+ "orphanedtimedtext-unsupported": "Sta paggena speciale ĆØ surtanto suppurtata dint' 'e database MySQL.",
+ "orphanedtimedtext-notimedtext": "'O TimedText (sottotitule) nun songo abbiĆ te dint'a stu wiki.",
+ "apihelp-query+transcodestatus-description": "Piglia 'o stato 'e transcodifeca pe' na paggena data.",
+ "apihelp-query+transcodestatus-example-1": "Piglia 'o stato transcode pe' [[:File:Clip.webm]]",
+ "apihelp-query+videoinfo-description": "Spanne imageinfo pe' putĆØ nzertĆ  'e nfurmaziune fonte 'e video (derivative)",
+ "apihelp-query+videoinfo-param-prop": "Che nfurmaziune se pigliasse 'o video:\n;timestamp:Azzecca 'a timestamp p' 'e verziune carrecate.\n;user:Azzecca l'utente c'avesse fatto l'upload dint'a verziona 'e video.\n;userid:Azzecca l'ID utente ca carrecaje sta verziona 'e video.\n;comment:Nu cummento ncopp' 'a verziona.\n;parsedcomment:Passa-scagna 'o cummento dint'a verziona.\n;canonicaltitle:Azzecca 'o titulo canonico 'e stu file 'e video.\n;url:Mpizzasse n'URL dint'o video e 'a paggena 'e descriziona.\n;size:Azzeccasse 'a pesantezza d' 'o file comm'a nu valore 'n byte, l'auto e 'o luongo suojo. 'O cunt' 'e paggene e 'a durata songo azzeccate si apprecabbele.\n;dimensions:Aliasse pe diminziona.\n;sha1:Azzecca nu hash SHA-1 p' 'o video video.\n;mime:Azzecca 'o tipo MIME d' 'o video.\n;thumbmime:Azzecca 'o tipo MIME p' 'o video thumbnail (servesse n'url e 'o param $1urlwidth).\n;mediatype:Azzecca 'o tipo 'e media dint' 'o video.\n;metadata:Elenca 'e metadate Exif p' 'a verziona d' 'o video.\n;commonmetadata:Elenca nu furmat' 'e file generico 'e metadate p' 'a verziona d' 'o video.\n;extmetadata:Elenca 'e date furmattate metadata cumbinate 'a fonte differente. 'E risultate songo HTML furmattate.\n;archivename:Azzecca 'o filename (nomm' 'e file) 'e sta verziona archivio pe' verziune ca nun fossero ll'urdema.\n;bitdepth:Azzecca 'o prufunno 'e bit d' 'a verziona.\n;uploadwarning:Ausato p' 'a paggena [[Special:Upload]] pe' se pigliĆ  nfurmaziune ncopp'a nu file ch'esiste mĆ². Nun ce buĆ² stu coso pe' putĆØ ausĆ  'o file for' 'o core 'e MediaWiki.\n;derivatives:Azzecca n'array 'e furmate differente cu qualitĆ  e verziune 'audio o video ca fosse mĆ² a disposizione.",
+ "apihelp-query+videoinfo-example-1": "Arrepiglia mĆ² 'e nfurmaziune ncopp' 'o [[:File:Folgers.ogv]]",
+ "apihelp-transcodereset-description": "Utente c' 'o deritto 'e 'transcode-reset' putessero resettĆ  e secutĆ  n'ata vota na fatica 'e transcodifeca.",
+ "apihelp-transcodereset-param-title": "'O titolo d' 'o file media.",
+ "apihelp-transcodereset-param-transcodekey": "'A chiave 'e transcodifeca ca vulite re-appicciĆ . Arrepiglia mĆ² [[Special:ApiHelp/query+transcodestatus|action=query&prop=transcodestatus]].",
+ "apihelp-transcodereset-example-1": "Re-appiccia tuttuquante transcodes pe' [[:File:Clip.webm]]",
+ "apihelp-transcodereset-example-2": "Re-appiccia 'a chiave 'e transcodifeca '360_560kbs.webm' pe' [[:File:Clip.webm]]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/nb.json b/extensions/TimedMediaHandler/i18n/nb.json
new file mode 100644
index 00000000..7a32ec0a
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/nb.json
@@ -0,0 +1,105 @@
+{
+ "@metadata": {
+ "authors": [
+ "Danmichaelo",
+ "Laaknor",
+ "Nghtwlkr"
+ ]
+ },
+ "timedmedia-desc": "HĆ„ndteringsprogram for lyd, video og tidsbestemt tekst, med formatstĆøtte for WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Ogg $1 lydfil, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 videofil, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 mediefil, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 lydfil, lengde $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 videofil, lengde $2, $4Ɨ$5 piksler, $3",
+ "timedmedia-ogg-long-multiplexed": "Sammensatt ogg lyd-/videofil, $1, lengde $2, $4Ɨ$5 piksler, $3 til sammen",
+ "timedmedia-ogg-long-general": "Ogg mediefil, lengde $2, $3",
+ "timedmedia-ogg-long-error": "Ugyldig Ogg-fil: $1",
+ "timedmedia-ogg-long-no-streams": "Ogg-mediafil. Advarsel: Ingen av omkoderne brukt i denne filen ble gjenkjent.",
+ "timedmedia-webm-short-video": "WebM $1 videofil, $2",
+ "timedmedia-webm-long-video": "WebM lyd-/videofil, $1, lengde $2, $4 Ɨ $5 piksler, $3 til sammen",
+ "timedmedia-flac-short-audio": "FLAC-lydfil, $1",
+ "timedmedia-flac-long-audio": "FLAC-lydfil, varighet $1, $2 totalt",
+ "timedmedia-wav-short-audio": "WAV-lydfil, $1",
+ "timedmedia-wav-long-audio": "WAV-lydfil, varighet $1, $2 totalt",
+ "timedmedia-wav-pcm-required": "Du kan kun laste opp PCM (Pulse Code Modulation) WAV.",
+ "timedmedia-mp4-short-video": "MP4 $1 videofil, $2",
+ "timedmedia-mp4-long-video": "MP4-fil for lyd/video, $1, lengde $2, $4 Ɨ $5 piksler, $3 totalt",
+ "timedmedia-no-player-js": "Beklager, nettleseren din har enten deaktivert JavaScript eller har ingen stĆøttet spiller.<br />\nDu kan <a href=\"$1\">laste ned klippet</a> eller <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">laste ned en spiller</a> for Ć„ spille av klippet i nettleseren din.",
+ "timedmedia-more": "Mer ā€¦",
+ "timedmedia-dismiss": "Lukk",
+ "timedmedia-download": "Last ned fil",
+ "timedmedia-play-media": "Spill av media",
+ "timedmedia-desc-link": "Om denne filen",
+ "timedmedia-oggThumb-version": "OggHandler krever oggThumb versjon $1 eller senere.",
+ "timedmedia-oggThumb-failed": "oggThumb klarte ikke Ć„ opprette miniatyrbildet.",
+ "timedmedia-status-header": "Omkodingsstatus",
+ "timedmedia-update-status": "Oppdater omkodingsstatus",
+ "timedmedia-status": "Status",
+ "timedmedia-status-unknown": "Ukjent status",
+ "timedmedia-transcodeinfo": "Beskrivelse",
+ "timedmedia-actions": "Handlinger",
+ "timedmedia-direct-link": "Last ned utgave",
+ "timedmedia-not-ready": "Ikke klar",
+ "timedmedia-completed-on": "Omkoding ferdig $1",
+ "timedmedia-error-on": "Omkoding feilet den $1",
+ "timedmedia-started-transcode": "Omkoding startet for $1 siden. $2",
+ "timedmedia-percent-done": "Rundt $1% ferdig",
+ "timedmedia-in-job-queue": "Lagt til i jobbkĆø for $1 siden",
+ "timedmedia-unknown-target-size": "Ukjent mĆ„lstĆørrelse, $1 ferdig kodet",
+ "timedmedia-days": "{{PLURAL:$1|1 dag|$1 dager}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 time|$1 timer}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minutt|$1 minutter}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 sekund|$1 sekunder}}",
+ "timedmedia-reset": "Nullstill omkoding",
+ "timedmedia-reset-confirm": "Nullstilling av denne omkodingsjobben vil slette eksisterende filer (hvis det er noen), og gjeninnsette omkodingsjobben i jobbkĆøen. Dette vil naturligvis ta noe tid.<br /><br />\nEr du sikker pĆ„ at du Ćønsker Ć„ fortsette?",
+ "timedmedia-reset-error": "Det oppsto en feil ved forsĆøk pĆ„ Ć„ nullstille omkodingsjobben.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 kilde",
+ "timedmedia-source-file-desc": "Original $1-fil, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Original $1-fil ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Ogg-video for lav bƄndbredde (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Nett-strĆømbar Ogg-video (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Nett-strĆømbar Ogg-video (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "HĆøykvalitets nedlastbar Ogg-video (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "Nedlastbar Ogg-video i full HD (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "Nett-strĆømbar WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "Nett-strĆømbar WebM (360P)",
+ "timedmedia-derivative-desc-480p.webm": "Nett-strĆømbar WebM (480P)",
+ "timedmedia-derivative-desc-720p.webm": "HĆøykvalitets nedlastbar WebM (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "Nedlastbar WebM-video i full HD (1080P)",
+ "timedmedia-derivative-desc-320p.mp4": "Mobilvennlig MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "Nett-strĆømbar MP4 (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "HD-kvalitet MP4 (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "MP4-video i full HD (1080P)",
+ "timedmedia-subtitle-new": "Opprett ny oversettelse eller rediger eksisterende",
+ "timedmedia-subtitle-new-desc": "Velg sprƄk eller trykk pƄ '''{{int:Timedmedia-subtitle-new-go}}'''-knappen",
+ "timedmedia-subtitle-new-go": "KjĆør",
+ "timedmedia-subtitle-language": "$1 ($2) undertekster",
+ "timedmedia-subtitle-no-video": "Det finnes ingen video koblet til den aktuelle undertekstsiden",
+ "timedmedia-subtitle-no-subtitles": "Det er for Ćøyeblikket ingen undertekster pĆ„ $1 for denne videoen. Du kan [{{fullurl:{{FULLPAGENAME}}|action=edit}} redigere denne siden] for Ć„ legge de til",
+ "timedmedia-subtitle-remote": "Undertekster (timed text) for denne filen befinner seg pƄ $1",
+ "timedmedia-subtitle-remote-link": "Du kan [$1 vise beskrivelsessiden] for denne filen pƄ $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 video|$1 videoer}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg-video|$1 Ogg-videoer}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM-video|$1 WebM-videoer}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 omkoding|$1 omkodinger}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 pƄgƄende omkoding|$1 pƄgƄende omkodinger}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 omkoding|$1 omkodinger}} i kĆø",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 omkoding|$1 omkodinger}} feilet",
+ "timedmedia-file": "Fil",
+ "timedmedia-audios": "{{PLURAL:$1|$1 lydfil|$1 lydfiler}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ogg-lydfil|$1 Ogg-lydfiler}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 FLAC-lydfil|$1 FLAC-lydfiler}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 WAV-lydfil|$1 WAV-lydfiler}}",
+ "right-transcode-reset": "Nullstill feilede eller omkodede videoer sĆ„ de blir gjeninnsatt i jobbkĆøen.",
+ "right-transcode-status": "Vis [[Special:TimedMediaHandler|informasjon om pƄgƄende omkodinger]]",
+ "action-transcode-status": "vise pƄgƄende omkodingsstatus",
+ "orphanedtimedtext": "ForeldrelĆøse TimedText-sider",
+ "orphanedtimedtext-summary": "Liste over [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]]-sider som ikke har tilknytning til noen fil.",
+ "orphanedtimedtext-unsupported": "Denne spesialsiden er kun stĆøttet for MySQL-databaser.",
+ "orphanedtimedtext-notimedtext": "TimedText er ikke pƄskrudd pƄ denne wikien.",
+ "apihelp-query+transcodestatus-description": "Hent transkodingsstatus for en gitt filside.",
+ "apihelp-query+transcodestatus-example-1": "Hent transkodingsstatus for [[:File:Clip.webm]]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/nds-nl.json b/extensions/TimedMediaHandler/i18n/nds-nl.json
new file mode 100644
index 00000000..f785cf7c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/nds-nl.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Servien"
+ ]
+ },
+ "timedmedia-desc": "Haandelt audio, video en ondertitels aof mit ondersteuning veur WebM, Ogg Theora, Vorbis en srt",
+ "timedmedia-ogg-short-audio": "Ogg $1 geluudsbestaand, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 videobestaand, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 mediabestaand, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 geluudsbestaand, lengte $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 videobestaand, lengte $2, $4Ɨ$5 pixels, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg-emultiplext geluuds-/videobestaand, $1, lengte $2, $4Ɨ$5 pixels, $3 totaal",
+ "timedmedia-ogg-long-general": "Ogg-mediabestaand, lengte $2, $3",
+ "timedmedia-ogg-long-error": "Ongeldig Ogg-bestaand: $1",
+ "timedmedia-no-player-js": "Joew systeem hef JavaScript uutstaon of der is gien ondersteunde mediaspeuler.<br />\nJe kunnen <a href=\"$1\">de klip neerlaojen</a> of <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">n mediaspeuler neerlaojen</a> um de klip aof te speulen in joew webkieker.",
+ "timedmedia-more": "Meer...",
+ "timedmedia-dismiss": "Sluten",
+ "timedmedia-download": "Bestaand neerlaojen",
+ "timedmedia-desc-link": "Over dit bestaand",
+ "timedmedia-source-file": "Bron van $1",
+ "timedmedia-source-audio-file-desc": "Oorspronkelik $1-bestaand ($2)",
+ "timedmediahandler": "Timed Media Handler"
+}
diff --git a/extensions/TimedMediaHandler/i18n/nds.json b/extensions/TimedMediaHandler/i18n/nds.json
new file mode 100644
index 00000000..b8404001
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/nds.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "Slomox"
+ ]
+ },
+ "timedmedia-desc": "StĆ¼Ć¼rprogramm fƶr Ogg-Theora- un Vorbis Datein, mitsamt en Afspeler in JavaScript",
+ "timedmedia-ogg-short-audio": "Ogg-$1-Toondatei, $2",
+ "timedmedia-ogg-short-video": "Ogg-$1-Videodatei, $2",
+ "timedmedia-ogg-short-general": "Ogg-$1-Mediendatei, $2",
+ "timedmedia-ogg-long-audio": "Ogg-$1-Toondatei, $2 lang, $3",
+ "timedmedia-ogg-long-video": "Ogg-$1-Videodatei, $2 lang, $4Ɨ$5 Pixels, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg-Multiplexed-Audio-/Video-Datei, $1, $2 lang, $4Ɨ$5 Pixels, $3 alltohoop",
+ "timedmedia-ogg-long-general": "Ogg-Mediendatei, $2 lang, $3",
+ "timedmedia-ogg-long-error": "Kaputte Ogg-Datei: $1",
+ "timedmedia-more": "Mehr...",
+ "timedmedia-dismiss": "Dichtmaken",
+ "timedmedia-download": "Datei dalladen",
+ "timedmedia-desc-link": "Ɩver disse Datei"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ne.json b/extensions/TimedMediaHandler/i18n/ne.json
new file mode 100644
index 00000000..acf3a5d1
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ne.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "ą¤øą¤°ą„‹ą¤œ ą¤•ą„ą¤®ą¤¾ą¤° ą¤¢ą¤•ą¤¾ą¤²",
+ "ą¤¬ą¤æą¤Ŗą„ą¤²ą¤¬ ą¤†ą¤Øą¤Øą„ą¤¦",
+ "NehalDaveND",
+ "ą¤°ą¤¾ą¤® ą¤Ŗą„ą¤°ą¤øą¤¾ą¤¦ ą¤œą„‹ą¤¶ą„€"
+ ]
+ },
+ "timedmedia-ogg-short-audio": "Ogg $1 ą¤§ą„ą¤µą¤Øą¤æ ą¤«ą¤¾ą¤‡ą¤², $2",
+ "timedmedia-ogg-short-video": "Ogg $1 ą¤µą¤æą¤”ą¤æą¤Æą„‹ ą¤«ą¤¾ą¤‡ą¤², $2",
+ "timedmedia-ogg-short-general": "Ogg $1 ą¤®ą„€ą¤”ą¤æą¤Æą¤¾ ą¤«ą¤¾ą¤‡ą¤², $2",
+ "timedmedia-no-player-js": "ą¤®ą¤¾ą¤« ą¤—ą¤°ą„ą¤Øą„ą¤¹ą„‹ą¤²ą¤¾, ą¤¤ą¤Ŗą¤¾ą¤ˆą¤‚ą¤•ą„‹ ą¤¬ą„ą¤°ą¤¾ą¤‰ą¤œą¤°ą¤®ą¤¾ ą¤Æą¤¾ ą¤¤ ą¤œą¤¾ą¤µą¤¾ą¤øą„ą¤•ą„ą¤°ą¤æą¤Ŗą„ą¤Ÿ ą¤…ą¤•ą„ą¤·ą¤® ą¤› ą¤Æą¤¾ ą¤øą¤®ą¤°ą„ą¤„ą¤æą¤¤ ą¤Ŗą„ą¤²ą„‡ą¤Æą¤° ą¤›ą„ˆą¤Ø ą„¤<br />\ną¤¤ą¤Ŗą¤¾ą¤ˆą¤‚ <a href=\"$1\">ą¤•ą„ą¤²ą¤æą¤Ŗą¤²ą¤¾ą¤ˆ ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤”</a> ą¤—ą¤°ą„ą¤Ø ą¤øą¤•ą„ą¤Øą„ą¤¹ą„ą¤Øą„ą¤› ą¤…ą¤„ą¤µą¤¾ ą¤•ą„ą¤²ą¤æą¤Ŗą¤²ą¤¾ą¤ˆ ą¤†ą¤«ą„ą¤Øą„‹ ą¤¬ą„ą¤°ą¤¾ą¤‰ą¤œą¤°ą¤®ą¤¾ ą¤šą¤²ą¤¾ą¤‰ą¤Øą¤•ą„‹ ą¤²ą¤¾ą¤—ą¤æ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ą¤ą¤• ą¤Ŗą„ą¤²ą„‡ą¤Æą¤° ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤”</a> ą¤—ą¤°ą„ą¤Ø ą¤øą¤•ą„ą¤Øą„ ą¤¹ą„ą¤Øą„ą¤› ą„¤",
+ "timedmedia-more": "ą¤„ą¤Ŗ...",
+ "timedmedia-dismiss": "ą¤¬ą¤Øą„ą¤§ ą¤—ą¤°ą„ą¤Øą„‡",
+ "timedmedia-download": "ą¤”ą¤¾ą¤‰ą¤Øą¤²ą„‹ą¤” ą¤—ą¤°ą„ą¤Øą„‡ ą¤«ą¤¾ą¤‡ą¤²",
+ "timedmedia-status": "ą¤øą„ą¤„ą¤æą¤¤ą¤æ",
+ "timedmedia-status-unknown": "ą¤…ą¤œą„ą¤žą¤¾ą¤¤ ą¤øą„ą¤„ą¤æą¤¤ą¤æ",
+ "timedmedia-actions": "ą¤•ą¤¾ą¤°ą„ą¤Æą¤¹ą¤°ą„",
+ "timedmedia-source-file": "$1 ą¤¶ą„ą¤°ą„‹ą¤¤",
+ "timedmedia-source-file-desc": "ą¤®ą„‚ą¤² $1 ą¤«ą¤¾ą¤ˆą¤², $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "ą¤®ą„‚ą¤² $1 ą¤«ą¤¾ą¤ˆą¤² ($2)",
+ "timedmedia-subtitle-new-go": "ą¤œą¤¾ą¤Øą„‡",
+ "timedmedia-file": "ą¤«ą¤¾ą¤‡ą¤²"
+}
diff --git a/extensions/TimedMediaHandler/i18n/nl.json b/extensions/TimedMediaHandler/i18n/nl.json
new file mode 100644
index 00000000..cfe2115f
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/nl.json
@@ -0,0 +1,108 @@
+{
+ "@metadata": {
+ "authors": [
+ "McDutchie",
+ "SPQRobin",
+ "Siebrand",
+ "Romaine"
+ ]
+ },
+ "timedmedia-desc": "Handelt audio, video en ondertitels af met ondersteuning voor WebM, Ogg Theora, Vorbis en srt",
+ "timedmedia-ogg-short-audio": "Ogg $1 geluidsbestand, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 videobestand, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 mediabestand, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 geluidsbestand, lengte $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 videobestand, lengte $2, $4Ɨ$5 pixels, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg gemultiplexed geluids/videobestand, $1, lengte $2, $4Ɨ$5 pixels, $3 totaal",
+ "timedmedia-ogg-long-general": "Ogg mediabestand, lengte $2, $3",
+ "timedmedia-ogg-long-error": "Ongeldig Ogg-bestand: $1",
+ "timedmedia-webm-short-video": "WebM $1 videobestand, $2",
+ "timedmedia-webm-long-video": "WebM audio/videobestand, $1, lengte $2, $4x$5 pixels, $3 totaal",
+ "timedmedia-flac-short-audio": "FLAC-audiobestand, $1",
+ "timedmedia-flac-long-audio": "FLAC-audiobestand, lengte $1, $2 gemiddeld",
+ "timedmedia-wav-short-audio": "WAV-audiobestand, $1",
+ "timedmedia-wav-long-audio": "WAV-audiobestand, lengte $1, $2 gemiddeld",
+ "timedmedia-wav-pcm-required": "U kunt alleen PCM (Pulse Code Modulation) WAV uploaden.",
+ "timedmedia-mp4-short-video": "MP4 $1 videobestand, $2",
+ "timedmedia-mp4-long-video": "MP4 audio/videobestand, $1, lengte $2, $4x$5 pixels, $3 totaal",
+ "timedmedia-no-player-js": "Uw systeem heeft JavaScript uitgeschakeld of er is geen ondersteunde mediaspeler.<br />\nU kunt <a href=\"$1\">de clip downloaden</a> of <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">een mediaspeler downloaden</a> om de clip af te spelen in uw browser.",
+ "timedmedia-more": "Meerā€¦",
+ "timedmedia-dismiss": "Sluiten",
+ "timedmedia-download": "Bestand downloaden",
+ "timedmedia-play-media": "Media afspelen",
+ "timedmedia-desc-link": "Over dit bestand",
+ "timedmedia-oggThumb-version": "OggHandler vereist oggThumb versie $1 of hoger.",
+ "timedmedia-oggThumb-failed": "oggThumb kon geen miniatuur aanmaken.",
+ "timedmedia-status-header": "Conversiestatus",
+ "timedmedia-update-status": "Conversiestatus bijwerken",
+ "timedmedia-status": "Status",
+ "timedmedia-status-unknown": "Onbekende status",
+ "timedmedia-transcodeinfo": "Beschrijving van afgeleide conversie",
+ "timedmedia-actions": "Handelingen",
+ "timedmedia-direct-link": "Afgeleid werk downloaden",
+ "timedmedia-not-ready": "Niet klaar",
+ "timedmedia-completed-on": "Conversie voltooid op $1",
+ "timedmedia-error-on": "Fout in de conversie om $1",
+ "timedmedia-started-transcode": "De conversie is $1 geleden begonnen. $2",
+ "timedmedia-percent-done": "Ongeveer $1% afgerond",
+ "timedmedia-in-job-queue": "$1 geleden toegevoegd aan de Job queue",
+ "timedmedia-unknown-target-size": "Onbekende doelgrootte, $1 gecodeerd",
+ "timedmedia-days": "{{PLURAL:$1|1 dag|$1 dagen}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 uur|$1 uur}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minuut|$1 minuten}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 seconde|$1 seconden}}",
+ "timedmedia-reset": "Transcodering opnieuw instellen",
+ "timedmedia-reset-confirm": "Door de transcodering opnieuw in te stellen worden alle bestanden bestanden (als aanwezig) verwijderd en de transcodering wordt opnieuw toegevoegd aan de wachtrij. Transcoderen kost tijd.<br /><br />\nWeet u zeker dat u wilt doorgaan?",
+ "timedmedia-reset-error": "Er is een fout opgetreden tijdens het opnieuw instellen van de transcoderingstaak.",
+ "timedmedia-ogg": "Ogg",
+ "timedmedia-webm": "WebM",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Bron van $1",
+ "timedmedia-source-file-desc": "Origineel $1-bestand, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Origineel $1-bestand ($2)",
+ "timedmedia-derivative-160p.ogv": "Ogg 160P",
+ "timedmedia-derivative-desc-160p.ogv": "Lage bandbreedte Ogg video (160P)",
+ "timedmedia-derivative-360p.ogv": "Ogg 360P",
+ "timedmedia-derivative-desc-360p.ogv": "Te webstreamen Ogg video (360P)",
+ "timedmedia-derivative-480p.ogv": "Ogg 480P",
+ "timedmedia-derivative-desc-480p.ogv": "Te webstreamen Ogg video (480P)",
+ "timedmedia-derivative-720p.ogv": "Ogg 720P",
+ "timedmedia-derivative-desc-720p.ogv": "Hoge kwaliteit downloadbare Ogg video (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "Full HD downloadbare Ogg video (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "Web streamable WebM (160P)",
+ "timedmedia-derivative-360p.webm": "WebM 360P",
+ "timedmedia-derivative-desc-360p.webm": "Te webstreamen WebM (360P)",
+ "timedmedia-derivative-480p.webm": "WebM 480P",
+ "timedmedia-derivative-desc-480p.webm": "Te webstreamen WebM (480P)",
+ "timedmedia-derivative-720p.webm": "WebM 720P",
+ "timedmedia-derivative-desc-720p.webm": "Hoge kwaliteit downloadbare WebM (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "Full HD downloadbare WebM (1080P)",
+ "timedmedia-derivative-desc-320p.mp4": "Apparaatvriendelijke MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "Te webstreamen MP4 (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "HD-kwaliteit MP4 (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "Full HD-kwaliteit MP4 (1080P)",
+ "timedmedia-subtitle-new": "Nieuw vertaling maken of bestaande bewerken",
+ "timedmedia-subtitle-new-desc": "Selecteer een taal en klik op de knop '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "OK",
+ "timedmedia-subtitle-language": "Ondertitels in $1 ($2)",
+ "timedmedia-subtitle-no-video": "Er is geen video gekoppeld aan de huidige ondertitelpagina",
+ "timedmedia-subtitle-no-subtitles": "Er zijn op het moment geen ondertitels in het $1 voor deze video. U kunt [{{fullurl:{{FULLPAGENAME}}|action=edit}} deze pagina bewerken] om ze toe te voegen",
+ "timedmedia-subtitle-remote": "De ondertitels voor dit bestand komen van $1",
+ "timedmedia-subtitle-remote-link": "U kunt de [$1 beschrijvingspagina voor dit bestand] bekijken op $2",
+ "timedmediahandler": "Timed Media Handler",
+ "timedmedia-videos": "{{PLURAL:$1|Ć©Ć©n video|$1 video's}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|Ć©Ć©n Oggvideo|$1 Oggvideo's}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|Ć©Ć©n WebM-video|$1 WebM-video's}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|Ć©Ć©n transcodering|$1 transcoderingen}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|Ć©Ć©n lopende transcodering|$1 lopende transcoderingen}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|Ć©Ć©n transcodering|$1 transcoderingen}} in de wachtrij",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|Ć©Ć©n mislukte transcodering|$1 mislukte transcoderingen}}",
+ "timedmedia-file": "Bestand",
+ "timedmedia-audios": "{{PLURAL:$1|$1 audiobestand|$1 audiobestanden}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ogg audiobestand|$1 Ogg audiobestanden}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 FLAC audiobestand|$1 FLAC audiobestanden}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 WAV audiobestand|$1 WAV audiobestanden}}",
+ "right-transcode-reset": "Video's waarvoor transcoderen mislukt is of die al getranscodeerd zijn opnieuw in de jobqueue plaatsen.",
+ "right-transcode-status": "[[Special:TimedMediaHandler|Gegevens over de huidige transcoderingsactiviteit]] bekijken",
+ "action-transcode-status": "huidige transcoderingsstatus te bekijken"
+}
diff --git a/extensions/TimedMediaHandler/i18n/nn.json b/extensions/TimedMediaHandler/i18n/nn.json
new file mode 100644
index 00000000..cc6a3761
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/nn.json
@@ -0,0 +1,41 @@
+{
+ "@metadata": {
+ "authors": [
+ "Eirik",
+ "Harald Khan",
+ "Njardarlogar",
+ "Ranveig"
+ ]
+ },
+ "timedmedia-desc": "Handteringsprogram for ljod, video og tidbunden tekst, med formatstĆøtte for WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Ogg $1-lydfil, $2",
+ "timedmedia-ogg-short-video": "Ogg $1-videofil, $2",
+ "timedmedia-ogg-short-general": "Ogg $1-mediafil, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1-lydfil, lengd $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1-videofil, lengd $2, $4Ɨ$5 pikslar, $3",
+ "timedmedia-ogg-long-multiplexed": "Samansett ogg lyd-/videofil, $1, lengd $2, $4Ɨ$5 pikslar, $3 til saman",
+ "timedmedia-ogg-long-general": "Ogg mediafil, lengd $2, $3",
+ "timedmedia-ogg-long-error": "Ugyldig Ogg-fil: $1",
+ "timedmedia-no-player-js": "Orsak. Nettleseren din har anten ikkje JavaScript aktiv eller har ingen stĆøtta spelar.<br />\nDu kan <a href=\"$1\">laste ned klippet</a> eller <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">laste ned ein spelar</a> for Ć„ spele av klippet i nettlesaren din.",
+ "timedmedia-more": "Meir...",
+ "timedmedia-dismiss": "Lat att",
+ "timedmedia-download": "Last ned fila",
+ "timedmedia-play-media": "Spel av media",
+ "timedmedia-desc-link": "Om denne fila",
+ "timedmedia-actions": "Handlingar",
+ "timedmedia-not-ready": "Ikkje ferdig",
+ "timedmedia-days": "{{PLURAL:$1|1 dag|$1 dagar}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 time|$1 timar}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minutt|$1 minutt}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 sekund|$1 sekund}}",
+ "timedmedia-source-file": "$1-kjelde",
+ "timedmedia-source-file-desc": "Opphavleg $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Opphavleg $1-fil ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Ogg-video med lƄg bandbreidd (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Ogg-video som kan strĆøymast pĆ„ nett (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Ogg-video som kan strĆøymast pĆ„ nett (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Ogg-video av hĆøg kvalitet som kan lastast ned (720P)",
+ "timedmedia-subtitle-new": "Lag ny omsetjing eller endra eksisterande",
+ "timedmedia-subtitle-new-desc": "Byt ut '''$1'''-delen med [[:en:ISO 639|sprƄkkoden]] din og trykk pƄ '''{{int:Timedmedia-subtitle-new-go}}'''-knappen",
+ "timedmedia-subtitle-new-go": "GĆ„"
+}
diff --git a/extensions/TimedMediaHandler/i18n/oc.json b/extensions/TimedMediaHandler/i18n/oc.json
new file mode 100644
index 00000000..892307d8
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/oc.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cedric31"
+ ]
+ },
+ "timedmedia-desc": "SupĆ²rt pels fichiĆØrs Ogg Theora e Vorbis, amb un lector Javascript",
+ "timedmedia-ogg-short-audio": "FichiĆØr son Ogg $1, $2",
+ "timedmedia-ogg-short-video": "FichiĆØr vidĆØo Ogg $1, $2",
+ "timedmedia-ogg-short-general": "FichiĆØr mĆØdia Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "FichiĆØr son Ogg $1, durada $2, $3",
+ "timedmedia-ogg-long-video": "FichiĆØr vidĆØo Ogg $1, durada $2, $4Ɨ$5 pixĆØls, $3",
+ "timedmedia-ogg-long-multiplexed": "FichiĆØr multiplexat Ć udio/vidĆØo Ogg, $1, durada $2, $4Ɨ$5 pixĆØls, $3",
+ "timedmedia-ogg-long-general": "FichiĆØr mĆØdia Ogg, durada $2, $3",
+ "timedmedia-ogg-long-error": "FichiĆØr Ogg invalid : $1",
+ "timedmedia-webm-short-video": "FichiĆØr vidĆØo WebM $1, $2",
+ "timedmedia-webm-long-video": "FichiĆØr Ć udio/vidĆØo WebM, $1, longor $2, $4 x $5 pixĆØls, $3 l'ensemble",
+ "timedmedia-flac-short-audio": "FichiĆØr Ć udio FLAC, $1",
+ "timedmedia-flac-long-audio": "FichiĆØr Ć udio FLAC, durada $1, debit $2 sus lā€™ensemble",
+ "timedmedia-wav-short-audio": "FichiĆØr Ć udio WAV, $1",
+ "timedmedia-no-player-js": "O planhĆØm, siĆ” vĆ²stre navigador a JavaScript de desactivat, siĆ” dispausa pas de cap de lector de pres en carga.<br />\nPodĆØtz <a href=\"$1\">telecargar lo clip</a> o <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">telecargar un lector</a> per legir lo clip dins vĆ²stre navigador.",
+ "timedmedia-more": "Maiā€¦",
+ "timedmedia-dismiss": "Tampar",
+ "timedmedia-download": "Telecargar lo fichiĆØr",
+ "timedmedia-desc-link": "A prepaus d'aqueste fichiĆØr",
+ "timedmedia-source-file": "Font $1",
+ "timedmedia-source-audio-file-desc": "FichiĆØr original $1 ($2)",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-file": "FichiĆØr",
+ "right-transcode-reset": "ReĆÆnicializar las vidĆØos en fracĆ s o transcodadas per que siĆ”n inseridas tornamai dins la fila dels trabalhs"
+}
diff --git a/extensions/TimedMediaHandler/i18n/olo.json b/extensions/TimedMediaHandler/i18n/olo.json
new file mode 100644
index 00000000..7e3ad6b5
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/olo.json
@@ -0,0 +1,18 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mashoi7"
+ ]
+ },
+ "timedmedia-no-player-js": "Pahakse mielekse sinun livaimes libo JavaScript ei ole kƤytƶs, libo sit ei ole tuvettuu soitindu.<br />\nVoit <a href=\"$1\">lad'd'ata palan</a> libo <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">lad'd'ata soittimen</a> ku soittua pala sinun livaimes.",
+ "timedmedia-more": "EnƤmbi...",
+ "timedmedia-dismiss": "Salbua",
+ "timedmedia-play-media": "Soita medii",
+ "timedmedia-desc-link": "TƤh failah nƤh",
+ "timedmedia-status": "Stuatussu",
+ "timedmedia-status-unknown": "Tundematoi stuatussu",
+ "timedmedia-source-file": "$1 lƤhteh",
+ "timedmedia-source-audio-file-desc": "AlguperƤine $1 failu ($2)",
+ "timedmedia-subtitle-new-go": "Mene",
+ "timedmedia-file": "Failu"
+}
diff --git a/extensions/TimedMediaHandler/i18n/or.json b/extensions/TimedMediaHandler/i18n/or.json
new file mode 100644
index 00000000..c2df361d
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/or.json
@@ -0,0 +1,85 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jnanaranjan Sahu",
+ "Psubhashish"
+ ]
+ },
+ "timedmedia-desc": "ą¬…ą¬”ą¬æą¬“, ą¬­ą¬æą¬”ą¬¼ą¬æą¬“ ą¬ą¬¬ą¬‚ ą¬øą¬¾ą¬®ą­Ÿą¬æą¬• ą¬²ą­‡ą¬–ą¬¾ ą¬—ą­ą¬”ą¬æą¬• ą¬Ŗą¬¾ą¬‡ą¬ ą­±ą­‡ą¬¬ą¬ą¬®, ą¬“ą¬œą¬æą¬œą¬æ ą¬„ą¬æą¬“ą¬°ą¬¾, ą¬­ą­‹ą¬°ą¬¬ą¬æą¬ø, ą¬ą¬øą¬†ą¬°ą¬Ÿą¬æ (WebM, Ogg Theora, Vorbis, srt) ą¬øą¬¹ą¬¾ą­Ÿą¬¤ą¬¾ ą¬„ą¬æą¬¬ą¬¾ ą¬Ŗą¬°ą¬æą¬šą¬¾ą¬³ą¬Øą¬¾ ą¬•ą¬¾ą¬°ą­€",
+ "timedmedia-ogg-short-audio": "Ogg $1 ą¬¶ą¬¬ą­ą¬¦ ą¬«ą¬¾ą¬‡ą¬², $2",
+ "timedmedia-ogg-short-video": "Ogg $1 ą¬­ą¬æą¬”ą¬¼ą¬æą¬“ ą¬«ą¬¾ą¬‡ą¬², $2",
+ "timedmedia-ogg-short-general": "Ogg $1 ą¬®ą¬æą¬”ą¬¼ą¬æą¬† ą¬«ą¬¾ą¬‡ą¬², $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 ą¬¶ą¬¬ą­ą¬¦ ą¬«ą¬¾ą¬‡ą¬², ą¬²ą¬®ą­ą¬¬ $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 ą¬­ą¬æą¬”ą¬¼ą¬æą¬“, ą¬²ą¬®ą­ą¬¬ $2, $4Ɨ$5 ą¬Ŗą¬æą¬•ą­ą¬øą­‡ą¬², $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg ą¬®ą¬²ą¬Ÿą¬æą¬Ŗą­ą¬²ą­‡ą¬•ą­ą¬ø ą¬§ą­ą­±ą¬Øą¬æ/ą¬šą¬æą¬¤ą­ą¬° ą¬«ą¬¾ą¬‡ą¬², $1, ą¬²ą¬®ą­ą¬¬ $2, $4Ɨ$5 ą¬Ŗą¬æą¬•ą­ą¬øą­‡ą¬², ą¬®ą­‹ą¬Ÿ $3",
+ "timedmedia-ogg-long-general": "Ogg ą¬®ą¬æą¬”ą¬¼ą¬æą¬† ą¬«ą¬¾ą¬‡ą¬², ą¬²ą¬®ą­ą¬¬ $2, $3",
+ "timedmedia-ogg-long-error": "ą¬…ą¬¬ą­ˆą¬§ ogg ą¬«ą¬¾ą¬‡ą¬²: $1",
+ "timedmedia-webm-short-video": "Ogg $1 ą¬­ą¬æą¬”ą¬¼ą¬æą¬“ ą¬«ą¬¾ą¬‡ą¬², $2",
+ "timedmedia-webm-long-video": "ogg ą¬…ą¬”ą¬æą¬“/ą¬­ą¬æą¬”ą¬¼ą¬æą¬“ ą¬«ą¬¾ą¬‡ą¬², $1, ą¬²ą¬®ą­ą¬¬ $2, $4Ɨ$5 ą¬Ŗą¬æą¬•ą­ą¬øą­‡ą¬², ą¬®ą­‹ą¬Ÿ $3",
+ "timedmedia-mp4-short-video": "MP4 $1 ą¬­ą¬æą¬”ą¬¼ą¬æą¬“ ą¬«ą¬¾ą¬‡ą¬², $2",
+ "timedmedia-mp4-long-video": "MP4 ą¬…ą¬”ą¬æą¬“/ą¬­ą¬æą¬”ą¬¼ą¬æą¬“ ą¬«ą¬¾ą¬‡ą¬², $1, ą¬²ą¬®ą­ą¬¬ $2, $4Ɨ$5 ą¬Ŗą¬æą¬•ą­ą¬øą­‡ą¬², ą¬®ą­‹ą¬Ÿ $3",
+ "timedmedia-no-player-js": "ą¬¦ą­ą¬–ą­€ą¬¤ą¬ƒ, ą¬†ą¬Ŗą¬£ą¬™ą­ą¬• ą¬¬ą­ą¬°ą¬¾ą¬‰ą¬œą¬°ą¬°ą­‡ ą¬œą¬¾ą¬­ą¬¾ą¬øą­ą¬•ą­ą¬°ą¬æą¬Ŗą­ą¬Ÿ ą¬…ą¬šą¬³ ą¬¹ą­‹ą¬‡ą¬Æą¬¾ą¬‡ą¬›ą¬æ ą¬•ą¬æą¬®ą­ą¬¬ą¬¾ ą¬•ą¬æą¬›ą¬æ ą¬–ą¬¾ą¬Ŗą¬–ą¬¾ą¬‰ą¬„ą¬æą¬¬ą¬¾ ą¬Ŗą­ą¬²ą­‡ą¬†ą¬° ą¬Øą¬¾ą¬¹ą¬æą¬ ą„¤ <br />\ną¬†ą¬Ŗą¬£ ą¬ą¬¹ą¬æ ą¬­ą¬æą¬”ą¬¼ą¬æą¬“ą¬Ÿą¬æą¬•ą­ ą¬†ą¬Ŗą¬£ą¬™ą­ą¬• ą¬¬ą­ą¬°ą¬¾ą¬‰ą¬œą¬°ą¬°ą­‡ ą¬šą¬²ą¬¾ą¬‡ą¬¬ą¬¾ ą¬Ŗą¬¾ą¬‡ą¬<a href=\"$1\">ą¬­ą¬æą¬”ą¬æą¬“ ą¬•ą­ą¬²ą¬æą¬Ŗą¬Ÿą¬æą¬•ą­ ą¬”ą¬¾ą¬‰ą¬Øą¬²ą­‹ą¬” ą¬•ą¬°ą¬æą¬Ŗą¬¾ą¬°ą¬æą¬¬ą­‡</a> ą¬•ą¬æą¬®ą­ą¬¬ą¬¾ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ą¬­ą¬æą¬”ą¬¼ą¬æą¬“ ą¬Ŗą­ą¬²ą­‡ą­Ÿą¬¾ą¬° ą¬®ą¬§ą­ą­Ÿ ą¬”ą¬¾ą¬‰ą¬Øą¬²ą­‹ą¬” ą¬•ą¬°ą¬æą¬Ŗą¬¾ą¬°ą¬æą¬¬ą­‡</a> ą„¤",
+ "timedmedia-more": "ą¬…ą¬§ą¬æą¬•...",
+ "timedmedia-dismiss": "ą¬¬ą¬Øą­ą¬¦ ą¬•ą¬°ą¬æą¬¬ą­‡",
+ "timedmedia-download": "ą¬«ą¬¾ą¬‡ą¬² ą¬”ą¬¾ą¬‰ą¬Øą¬²ą­‹ą¬”ą¬¼",
+ "timedmedia-play-media": "ą¬®ą­‡ą¬”ą¬æą¬†ą¬Ÿą¬æą¬•ą­ ą¬šą¬²ą­‡ą¬‡ą¬¬ą­‡",
+ "timedmedia-desc-link": "ą¬ą¬¹ą¬æ ą¬«ą¬¾ą¬‡ą¬² ą¬¬ą¬æą¬·ą­Ÿą¬°ą­‡",
+ "timedmedia-oggThumb-version": "oggą¬Ŗą¬°ą¬æą¬šą¬¾ą¬³ą¬Øą¬¾ą¬•ą¬¾ą¬°ą­€ $1 ą¬øą¬‚ą¬øą­ą¬•ą¬°ą¬£ ą¬•ą¬æą¬®ą­ą¬¬ą¬¾ ą¬¤ą¬¾ą¬ ą­ ą¬Øą­‚ą¬¤ą¬Øą¬¤ą¬® oggą¬„ą¬®ą­ą¬¬ą¬Øą­‡ą¬² ą¬†ą¬¬ą¬¶ą­ą­Ÿą¬• ą¬•ą¬°ą­‡",
+ "timedmedia-oggThumb-failed": "oggThumb ą¬›ą­‹ą¬Ÿą¬›ą¬¬ą¬æ ą¬¤ą¬æą¬†ą¬°ą¬æ ą¬•ą¬°ą¬æą¬Ŗą¬¾ą¬°ą¬æą¬²ą¬¾ ą¬Øą¬¾ą¬¹ą¬æą¬ ą„¤",
+ "timedmedia-status-header": "ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬” ą¬…ą¬¬ą¬øą­ą¬„ą¬¾",
+ "timedmedia-update-status": "ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬” ą¬…ą¬¬ą¬øą­ą¬„ą¬¾ ą¬…ą¬Ŗą¬”ą­‡ą¬Ÿ ą¬•ą¬°ą¬æą¬¬ą­‡",
+ "timedmedia-status": "ą¬…ą¬¬ą¬øą­ą¬„ą¬¾",
+ "timedmedia-status-unknown": "ą¬…ą¬œą¬£ą¬¾ ą¬…ą¬¬ą¬øą­ą¬„ą¬¾",
+ "timedmedia-transcodeinfo": "ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬” ą¬­ą¬œą¬Øą¬° ą¬¬ą¬æą¬¬ą¬°ą¬£ą­€",
+ "timedmedia-actions": "ą¬•ą¬¾ą¬®ą¬øą¬¬ą­",
+ "timedmedia-direct-link": "ą¬­ą¬¾ą¬œą¬•ą¬—ą­ą¬”ą¬æą¬•ą­ ą¬”ą¬¾ą¬‰ą¬Øą¬²ą­‹ą¬” ą¬•ą¬°ą¬æą¬¬ą­‡",
+ "timedmedia-not-ready": "ą¬Ŗą­ą¬°ą¬øą­ą¬¤ą­ą¬¤ ą¬¹ą­‹ą¬‡ą¬Øą¬¾ą¬¹ą¬æą¬",
+ "timedmedia-completed-on": "$1 ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬” ą¬¶ą­‡ą¬·ą¬¹ą­‡ą¬²ą¬¾",
+ "timedmedia-error-on": "$1 ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬”ą¬°ą­‡ ą¬…ą¬øą­ą¬¬ą¬æą¬§ą¬¾ ą„¤",
+ "timedmedia-started-transcode": "ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬” $1ą¬°ą­ ą¬†ą¬°ą¬®ą­ą¬­ ą¬¹ą­‡ą¬²ą¬¾ ą„¤ $2",
+ "timedmedia-percent-done": "ą¬¹ą¬¾ą¬°ą¬¾ą¬¹ą¬¾ą¬°ą¬æ $1% ą¬øą¬°ą¬æą¬›ą¬æ",
+ "timedmedia-in-job-queue": "$1 ą¬Ŗą­ƒą¬°ą­ą¬¬ą¬°ą­ ą¬•ą¬¾ą¬®ą¬°ą­‡ ą¬Æą­‹ą¬”ą¬¾ą¬—ą¬²ą¬¾",
+ "timedmedia-unknown-target-size": "ą¬…ą¬œą¬£ą¬¾ ą¬†ą¬•ą¬¾ą¬°, $1 ą¬ą¬Øą¬•ą­‹ą¬” ą¬¹ą­‡ą¬²ą¬¾",
+ "timedmedia-days": "{{PLURAL:$1|$1 ą¬¦ą¬æą¬Ø|$1 ą¬¦ą¬æą¬Øą¬—ą­ą¬”ą¬æą¬•}}",
+ "timedmedia-hours": "($1 {{PLURAL:$1|ą¬˜ą¬£ą­ą¬Ÿą¬¾| ą¬˜ą¬£ą­ą¬Ÿą¬¾}})",
+ "timedmedia-minutes": "$1 {{PLURAL:$1|ą¬®ą¬æą¬Øą¬æą¬Ÿ|ą¬®ą¬æą¬Øą¬æą¬Ÿą¬—ą­ą¬”ą¬æą¬•}}",
+ "timedmedia-seconds": "{{PLURAL:$1|ą¬øą­‡ą¬•ą­‡ą¬£ą­ą¬”|ą¬øą­‡ą¬•ą¬£ą­ą¬”}}",
+ "timedmedia-reset": "ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬” ą¬Ŗą­ą¬Øą¬ƒą¬øą­ą¬„ą¬¾ą¬Ŗą¬Ø ą¬•ą¬°ą¬æą¬¬ą­‡",
+ "timedmedia-reset-confirm": "ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬” ą¬Ŗą­ą¬Øą¬ƒą¬øą­ą¬„ą¬¾ą¬Ŗą¬Øą¬¾ ą¬•ą¬°ą¬æą¬¬ą¬¾ą¬¦ą­ą¬µą¬¾ą¬°ą¬¾ ą¬…ą¬—ą¬°ą­ą¬„ą¬æą¬¬ą¬¾ ą¬«ą¬¾ą¬‡ą¬² ą¬¹ą¬Ÿą¬æą¬Æą¬æą¬¬, ą¬ą¬¬ą¬‚ ą¬ą¬¹ą¬¾ ą¬Ŗą­ą¬°ą¬•ą­ą¬°ą¬æą­Ÿą¬¾ą¬°ą­‡ ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬”ą¬•ą­ ą¬†ą¬‰ą¬„ą¬°ą­‡ ą¬Æą­‹ą¬”ą¬æą¬¦ą­‡ą¬¬ ą„¤ ą¬ą¬¹ą¬¾ ą¬Ŗą­ą¬Øą¬ƒ ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬” ą¬Ŗą¬¾ą¬‡ą¬ ą¬•ą¬æą¬›ą¬æ ą¬øą¬®ą­Ÿ ą¬Øą­‡ą¬¬ ą„¤\ną¬†ą¬Ŗą¬£ ą¬Ŗą­ą¬°ą¬•ą­ą¬°ą¬æą­Ÿą¬¾ą¬•ą­ ą¬šą¬¾ą¬²ą­ą¬°ą¬–ą¬æą¬¬ą¬¾ ą¬Ŗą¬¾ą¬‡ą¬ ą¬Øą¬æą¬¶ą­ą¬šą¬æą¬¤ ?",
+ "timedmedia-reset-error": "ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬” ą¬Ŗą­ą¬Øą¬ƒą¬øą­ą¬„ą¬¾ą¬Ŗą¬Ø ą¬•ą¬°ą¬æą¬¬ą¬¾ą¬°ą­‡ ą¬…ą¬øą­ą¬¬ą¬§ą¬¾ ą¬‰ą¬Ŗą­ą¬œą¬æą¬²ą¬¾",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 ą¬‰ą¬¤ą­ą¬ø",
+ "timedmedia-source-file-desc": "ą¬®ą­‚ą¬³ $1 ą¬«ą¬¾ą¬‡ą¬², $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "ą¬®ą­‚ą¬³ $1 ą¬«ą¬¾ą¬‡ą¬² ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "ą¬•ą¬® ą¬¬ą­ą­Ÿą¬¾ą¬£ą­ą¬”ą­±ą¬æą¬„ ogg ą¬­ą¬æą¬”ą¬¼ą¬æą¬“ (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "ą­±ą­‡ą¬¬ą¬°ą­‡ ą¬øą¬æą¬§ą¬¾ą¬šą¬¾ą¬²ą¬æą¬²ą¬¾ ą¬­ą¬³ą¬æ Ogg ą¬­ą¬æą¬”ą¬æą¬“ (360p)",
+ "timedmedia-derivative-desc-480p.ogv": "ą­±ą­‡ą¬¬ą¬°ą­‡ ą¬øą¬æą¬§ą¬¾ą¬šą¬¾ą¬²ą¬æą¬²ą¬¾ ą¬­ą¬³ą¬æ Ogg ą¬­ą¬æą¬”ą¬æą¬“ (480p)",
+ "timedmedia-derivative-desc-720p.ogv": "ą­±ą­‡ą¬¬ą¬°ą­‡ ą¬øą¬æą¬§ą¬¾ą¬šą¬¾ą¬²ą¬æą¬²ą¬¾ ą¬­ą¬³ą¬æ Ogg ą¬­ą¬æą¬”ą¬æą¬“ (720p)",
+ "timedmedia-derivative-desc-160p.webm": "ą­±ą­‡ą¬¬ą¬°ą­‡ ą¬øą¬æą¬§ą¬¾ą¬šą¬¾ą¬²ą¬æą¬²ą¬¾ ą¬­ą¬³ą¬æ WebM ą¬­ą¬æą¬”ą¬æą¬“ (160p)",
+ "timedmedia-derivative-desc-360p.webm": "ą­±ą­‡ą¬¬ą¬°ą­‡ ą¬øą¬æą¬§ą¬¾ą¬šą¬¾ą¬²ą¬æą¬²ą¬¾ ą¬­ą¬³ą¬æ WebM ą¬­ą¬æą¬”ą¬æą¬“ (360p)",
+ "timedmedia-derivative-desc-480p.webm": "ą­±ą­‡ą¬¬ą¬°ą­‡ ą¬øą¬æą¬§ą¬¾ą¬šą¬¾ą¬²ą¬æą¬²ą¬¾ ą¬­ą¬³ą¬æ WebM ą¬­ą¬æą¬”ą¬æą¬“ (480p)",
+ "timedmedia-derivative-desc-720p.webm": "ą¬­ą¬² ą¬Ŗą­ą¬°ą¬•ą¬¾ą¬°ą¬„ą¬æą¬¬ą¬¾ ą¬ą¬¬ą¬‚ ą¬”ą¬¾ą¬‰ą¬Øą¬²ą­‹ą¬” ą¬¹ą­‹ą¬‡ą¬Ŗą¬¾ą¬°ą­ą¬„ą¬æą¬¬ą¬¾ WebM(720P)",
+ "timedmedia-derivative-desc-320p.mp4": "ą¬Æą¬Øą­ą¬¤ą­ą¬°-ą¬øą¬¹ą¬¾ą­Ÿą¬• ą¬ą¬®ą¬Ŗą¬æ4(320P)",
+ "timedmedia-derivative-desc-480p.mp4": "ą­±ą­‡ą¬¬ą¬°ą­‡ ą¬øą¬æą¬§ą¬¾ą¬šą¬¾ą¬²ą¬æą¬²ą¬¾ ą¬­ą¬³ą¬æ MP4 ą¬­ą¬æą¬”ą¬æą¬“ (480p)",
+ "timedmedia-derivative-desc-720p.mp4": "ą¬ą¬šą¬”ą¬¼ą¬æ ą¬Ŗą­ą¬°ą¬•ą¬¾ą¬°ą¬° MP4 (720P)",
+ "timedmedia-subtitle-new": "ą¬Øą­‚ą¬† ą¬…ą¬Øą­ą¬¬ą¬¾ą¬¦ ą¬†ą¬°ą¬®ą­ą¬­ ą¬•ą¬°ą¬æą¬¬ą­‡ ą¬•ą¬æą¬®ą­ą¬¬ą¬¾ ą¬†ą¬—ą¬°ą­ą¬„ą¬æą¬¬ą¬¾ ą¬…ą¬Øą­ą¬¬ą¬¾ą¬¦ą¬•ą­ ą¬¬ą¬¦ą¬³ą¬¾ą¬‡ą¬¬ą­‡",
+ "timedmedia-subtitle-new-desc": "ą¬­ą¬¾ą¬·ą¬¾ ą¬šą­Ÿą¬Ø ą¬•ą¬°ą¬Øą­ą¬¤ą­ ą¬ą¬¬ą¬‚ {{int:Timedmedia-subtitle-new-go}}'''ą¬¬ą¬Ÿą¬Ø ą¬¦ą¬¬ą¬¾ą¬Øą­ą¬¤ą­",
+ "timedmedia-subtitle-new-go": "ą¬Æą¬æą¬¬ą­‡",
+ "timedmedia-subtitle-language": "$1 ($2) ą¬øą¬¬ą¬Ÿą¬¾ą¬‡ą¬Ÿą¬²",
+ "timedmedia-subtitle-no-video": "ą¬¬ą¬°ą­ą¬¤ą¬®ą¬¾ą¬Øą¬° ą¬øą¬¬ą¬Ÿą¬¾ą¬‡ą¬Ÿą¬² ą¬Ŗą­ƒą¬·ą­ą¬ ą¬¾ ą¬øą¬¹ ą¬•ą­Œą¬£ą¬øą¬æ ą¬­ą¬æą¬”ą¬æą¬“ ą¬øą¬‚ą¬¶ą­ą¬³ą¬æą¬·ą­ą¬Ÿ ą¬Øą¬¾ą¬¹ą¬æą¬",
+ "timedmedia-subtitle-no-subtitles": "ą¬¬ą¬°ą­ą¬¤ą¬®ą¬¾ą¬Ø $1ą¬°ą­‡ ą¬ą¬¹ą¬æ ą¬­ą¬æą¬”ą¬æą¬“ ą¬Ŗą¬¾ą¬‡ą¬ ą¬•ą­Œą¬£ą¬øą¬æ ą¬øą¬¬ą¬Ÿą¬¾ą¬‡ą¬Ÿą¬² ą¬Øą¬¾ą¬¹ą¬æą¬, ą¬†ą¬Ŗą¬£ [{{fullurl:{{FULLPAGENAME}}|action=edit}} ą¬¬ą¬¦ą¬³ą¬¾ą¬‡] ą¬ą¬¹ą¬¾ą¬•ą­ ą¬Æą­‹ą¬”ą¬æ ą¬Ŗą¬¾ą¬°ą¬æą¬¬ą­‡",
+ "timedmedia-subtitle-remote": "ą¬ą¬¹ą¬æ ą¬«ą¬¾ą¬‡ą¬² ą¬Ŗą¬¾ą¬‡ą¬ ą¬øą¬¾ą¬®ą­Ÿą¬æą¬• ą¬²ą­‡ą¬–ą¬¾ą¬—ą­ą¬”ą¬æą¬• $1ą¬°ą­‡ ą¬…ą¬›ą¬æ",
+ "timedmedia-subtitle-remote-link": "ą¬†ą¬Ŗą¬£ $2ą¬°ą­‡ ą¬„ą¬æą¬¬ą¬¾ ą¬ą¬¹ą¬æ ą¬«ą¬¾ą¬‡ą¬² ą¬Ŗą¬¾ą¬‡ą¬ [$1 ą¬¬ą¬æą¬¬ą¬°ą¬£ą­€ ą¬Ŗą­ƒą¬·ą­ą¬ ą¬¾ ą¬¦ą­‡ą¬–ą¬æą¬Ŗą¬¾ą¬°ą¬æą¬¬ą­‡]",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 ą¬­ą¬æą¬”ą¬æą¬“|$1 ą¬­ą¬æą¬”ą¬æą¬“ ą¬—ą­ą¬”ą¬æą¬•}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg ą¬­ą¬æą¬”ą¬æą¬“|$1 Ogg ą¬­ą¬æą¬”ą¬æą¬“ ą¬—ą­ą¬”ą¬æą¬•}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM ą¬­ą¬æą¬”ą¬æą¬“|$1 WebM ą¬­ą¬æą¬”ą¬æą¬“ ą¬—ą­ą¬”ą¬æą¬•}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬”|$1 ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬”ą¬—ą­ą¬”ą¬æą¬•}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 ą¬šą¬¾ą¬²ą­ą¬„ą¬æą¬¬ą¬¾ ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬”|$1 ą¬šą¬¾ą¬²ą­ą¬„ą¬æą¬¬ą¬¾ ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬”ą¬—ą­ą¬”ą¬æą¬•}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 ą¬§ą¬¾ą¬”ą¬æą¬°ą­‡ ą¬„ą¬æą¬¬ą¬¾ ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬”|$1 ą¬§ą¬¾ą¬”ą¬æą¬°ą­‡ ą¬„ą¬æą¬¬ą¬¾ ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬”ą¬—ą­ą¬”ą¬æą¬•}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 ą¬¬ą¬æą¬«ą¬³ ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬”|$1 ą¬¬ą¬æą¬«ą¬³ ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬”ą¬—ą­ą¬”ą¬æą¬•}}",
+ "timedmedia-file": "ą¬«ą¬¾ą¬‡ą¬²",
+ "right-transcode-reset": "ą¬¬ą¬æą¬«ą¬³ ą¬¹ą­‹ą¬‡ą¬„ą¬æą¬¬ą¬¾ ą¬•ą¬æą¬®ą­ą¬¬ą¬¾ ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬” ą¬­ą¬æą¬”ą¬æą¬“ą¬—ą­ą¬”ą¬æą¬• ą¬Ŗą­ą¬Øą¬ƒą¬øą­ą¬„ą¬¾ą¬Ŗą¬Ø ą¬•ą¬°ą¬æą¬¬ą­‡ ą¬Æą¬¾ą¬¹ą¬¾ą¬«ą¬³ą¬°ą­‡ą¬•ą¬æ ą¬øą­‡ą¬—ą­ą¬”ą¬æą¬• ą¬Ŗą­ą¬£ą¬æ ą¬Ŗą­ą¬°ą¬•ą­ą¬°ą¬æą­Ÿą¬¾ą¬•ą¬°ą¬£ ą¬¹ą­‡ą¬¬ ą„¤",
+ "right-transcode-status": "[[Special:TimedMediaHandler|ą¬ą¬¬ą­‡ą¬•ą¬¾ą¬° ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬” ą¬—ą¬¤ą¬æą¬¬ą¬æą¬§ą¬æ]] ą¬¦ą­‡ą¬–ą¬æą¬¬ą­‡",
+ "action-transcode-status": "ą¬ą¬¬ą­‡ą¬•ą¬¾ą¬° ą¬Ÿą­ą¬°ą¬¾ą¬Øą­ą¬øą¬•ą­‹ą¬” ą¬øą­ą¬„ą¬æą¬¤ą¬æ ą¬¦ą­‡ą¬–ą¬æą¬¬ą­‡"
+}
diff --git a/extensions/TimedMediaHandler/i18n/os.json b/extensions/TimedMediaHandler/i18n/os.json
new file mode 100644
index 00000000..b5da6ba3
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/os.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amikeco"
+ ]
+ },
+ "timedmedia-more": "Š¤Ń‹Š»Š“Ʀрā€¦",
+ "timedmedia-download": "Š¤Š°Š¹Š» ƦрŠ±Š°Š²Š³Ć¦Š½"
+}
diff --git a/extensions/TimedMediaHandler/i18n/pa.json b/extensions/TimedMediaHandler/i18n/pa.json
new file mode 100644
index 00000000..80ffc841
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/pa.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gman124",
+ "Babanwalia",
+ "Satdeep gill"
+ ]
+ },
+ "timedmedia-no-player-js": "ąØ®ą©ąØ†ąØ«ąØ¼ ąØ•ąØ°ąØØąØ¾, ąØœąØ¾ąØ‚ ąØ¤ąØ¾ąØ‚ ąØ¤ą©ąØ¹ąØ¾ąØ”ą©‡ ąØ¬ąØ°ąØ¾ąØŠąØœąØ¼ąØ° ąØ‰ą©±ąØ¤ą©‡ ąØœąØ¾ąØµąØ¾ąØøąØ•ą©ąØ°ąØæąØŖąØŸ ąØšąØ¾ąØ²ą©‚ ąØØąØ¹ą©€ąØ‚ ąØœąØ¾ąØ‚ ąØ«ąØ¼ąØæąØ° ąØ•ą©‹ąØˆ ąØ¹ą©‹ąØ° ąØøąØ¹ąØ¾ąØ‡ąØ• ąØŖąØ²ą©‡ąØ…ąØ° ąØ®ą©ŒąØœą©‚ąØ¦ ąØØąØ¹ą©€ąØ‚ ąØ¹ą©ˆą„¤<br />\nąØ¤ą©ąØøą©€ąØ‚ <a href=\"$1\">ąØ•ąØ²ąØæą©±ąØŖ ąØ”ąØ¾ąØŠąØØąØ²ą©‹ąØ” ąØ•ąØ° ąØøąØ•ąØ¦ą©‡ ąØ¹ą©‹</a> ąØœąØ¾ąØ‚ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ąØ•ą©‹ąØˆ ąØŖąØ²ą©‡ąØ…ąØ° ąØ”ąØ¾ąØŠąØØąØ²ą©‹ąØ” ąØ•ąØ°ąØ•ą©‡</a> ąØ‡ąØ¹ ąØ•ąØ²ąØæą©±ąØŖ ąØ†ąØŖąØ£ą©‡ ąØ¬ąØ°ąØ¾ąØŠąØœąØ¼ąØ° ąØµąØæą©±ąØš ąØšąØ²ąØ¾ ąØøąØ•ąØ¦ą©‡ ąØ¹ą©‹ą„¤",
+ "timedmedia-more": "ąØ¹ą©‹ąØ°...",
+ "timedmedia-source-file": "$1 ąØøąØ°ą©‹ąØ¤",
+ "timedmedia-source-audio-file-desc": "ąØ®ą©‚ąØ² $1 ąØ«ąØ¼ąØ¾ąØˆąØ² ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/pdc.json b/extensions/TimedMediaHandler/i18n/pdc.json
new file mode 100644
index 00000000..d213f28c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/pdc.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Xqt"
+ ]
+ },
+ "timedmedia-more": "Mehrā€¦",
+ "timedmedia-download": "Feil runnerlaade"
+}
diff --git a/extensions/TimedMediaHandler/i18n/pfl.json b/extensions/TimedMediaHandler/i18n/pfl.json
new file mode 100644
index 00000000..f4d3bbb6
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/pfl.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Manuae"
+ ]
+ },
+ "timedmedia-no-player-js": "Endwedda hoschd JavaScript abgschdeld odda de Browsa hodd kƤ unnaschdizdi Abschbielsofdwaa.<br />\nKonschd <a href=\"$1\">de Glibb runnalaade</a> odda Ƥ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">Abschbielsofdwaa</a> umde Glibb oagugge zu kenne.",
+ "timedmedia-source-file": "$1 Gwell",
+ "timedmedia-source-audio-file-desc": "Uaschbringlischi $1-Dadai ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/pl.json b/extensions/TimedMediaHandler/i18n/pl.json
new file mode 100644
index 00000000..cbd0fac5
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/pl.json
@@ -0,0 +1,101 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ankry",
+ "Chrumps",
+ "Derbeth",
+ "Faren",
+ "Leinad",
+ "Matma Rex",
+ "Przemub",
+ "Rzuwig",
+ "Sp5uhe"
+ ]
+ },
+ "timedmedia-desc": "Obsługa plikĆ³w audio, wideo i napisĆ³w filmowych w formatach WebM, Ogg Theora, Vorbis i srt",
+ "timedmedia-ogg-short-audio": "Plik dÅŗwiękowy Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Plik wideo Ogg $1, $2",
+ "timedmedia-ogg-short-general": "Plik multimedialny Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "plik dÅŗwiękowy Ogg $1, długość $2, $3",
+ "timedmedia-ogg-long-video": "plik wideo Ogg $1, długość $2, rozdzielczość $4Ɨ$5, $3",
+ "timedmedia-ogg-long-multiplexed": "plik audio/wideo Ogg, $1, długość $2, rozdzielczość $4Ɨ$5, ogĆ³Å‚em $3",
+ "timedmedia-ogg-long-general": "plik multimedialny Ogg, długość $2, $3",
+ "timedmedia-ogg-long-error": "niepoprawny plik Ogg: $1",
+ "timedmedia-webm-short-video": "WebM $1 plik wideo, $2",
+ "timedmedia-webm-long-video": "WebM plik audio-wideo, $1, długość $2, $4 Ɨ $5 pikseli, ogĆ³Å‚em $3",
+ "timedmedia-flac-short-audio": "Plik audio FLAC, $1",
+ "timedmedia-flac-long-audio": "Plik dÅŗwiękowy FLAC, długość $1, przepływność $2",
+ "timedmedia-wav-short-audio": "Plik audio WAV, $1",
+ "timedmedia-wav-long-audio": "Plik dÅŗwiękowy WAV, długość $1, przepływność $2",
+ "timedmedia-no-player-js": "Niestety, Twoja przeglądarka ma wyłączoną obsługę JavaScript lub nie wspiera odtwarzania.<br />\nMożesz <a href=\"$1\">pobrać plik</a> lub <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">pobrać odtwarzacz</a> pozwalający oglądać wideo w przeglądarce.",
+ "timedmedia-more": "Więcej...",
+ "timedmedia-dismiss": "Zamknij",
+ "timedmedia-download": "Pobierz plik",
+ "timedmedia-play-media": "OdtwĆ³rz plik multimedialny",
+ "timedmedia-desc-link": "Właściwości pliku",
+ "timedmedia-oggThumb-version": "OggHandler wymaga oggThumb w wersji $1 lub pĆ³Åŗniejszej.",
+ "timedmedia-oggThumb-failed": "oggThumb nie udało się utworzyć miniaturki.",
+ "timedmedia-status-header": "Status konwersji",
+ "timedmedia-update-status": "Zaktualizuj status konwersji",
+ "timedmedia-status": "Status",
+ "timedmedia-status-unknown": "Status nieznany",
+ "timedmedia-transcodeduration": "Czas kodowania",
+ "timedmedia-transcodeinfo": "Format",
+ "timedmedia-actions": "Operacje",
+ "timedmedia-direct-link": "Pobierz",
+ "timedmedia-not-ready": "Niegotowe",
+ "timedmedia-completed-on": "Ukończono $1",
+ "timedmedia-error-on": "Błąd o $1",
+ "timedmedia-started-transcode": "Konwersja rozpoczęła się $1 temu. $2",
+ "timedmedia-percent-done": "Ukończono ok. $1%",
+ "timedmedia-in-job-queue": "Dodano do kolejki $1 temu",
+ "timedmedia-unknown-target-size": "Rozmiar docelowy nieznany, $1 zakodowane",
+ "timedmedia-days": "$1 {{PLURAL:$1|dzień|dni}}",
+ "timedmedia-hours": "$1 {{PLURAL:$1|godzina|godziny|godzin}}",
+ "timedmedia-minutes": "$1 {{PLURAL:$1|minuta|minuty|minut}}",
+ "timedmedia-seconds": "$1 {{PLURAL:$1|sekunda|sekundy|sekund}}",
+ "timedmedia-reset": "Resetuj konwersję",
+ "timedmedia-reset-confirm": "Reset konwersji spowoduje usunięcie obecnego pliku (jeżeli takowy istnieje) i doda ją ponownie do kolejki. Zabierze to trochę czasu. <br /><br />\nCzy na pewno chcesz kontynuować?",
+ "timedmedia-reset-error": "Błąd w resecie konwersji.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "ŹrĆ³dło $1",
+ "timedmedia-source-file-desc": "Oryginalny plik $1, $2 x $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Oryginalny plik $1 ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Ogg video o niskiej przepustowości (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Ogg video o przepustowości sieciowej (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Ogg video o przepustowości sieciowej (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Ogg video o wysokiej jakości (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "Do pobrania wideo Ogg z Full HD (1080p)",
+ "timedmedia-derivative-desc-160p.webm": "WebM w jakości sieciowej (160P)",
+ "timedmedia-derivative-desc-360p.webm": "WebM w jakości sieciowej (360P)",
+ "timedmedia-derivative-desc-480p.webm": "WebM w jakości sieciowej (480P)",
+ "timedmedia-derivative-desc-720p.webm": "WebM o wysokiej jakości (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "Do pobrania WebM Full HD (1080p)",
+ "timedmedia-derivative-desc-320p.mp4": "MP4 odpowiednie dla tego urządzenia (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "MP4 w jakości sieciowej (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 w jakości HD (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "Jakości Full HD (1080p) MP4",
+ "timedmedia-subtitle-new": "UtwĆ³rz nowe tłumaczenie lub edytuj istniejące",
+ "timedmedia-subtitle-new-go": "PrzejdÅŗ",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 film|$1 filmy|$1 filmĆ³w}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 film Ogg|$1 filmy Ogg|$1 filmĆ³w Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 film WebM|$1 filmy WebM|$1 filmĆ³w WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transkodowanie|$1 transkodowania|$1 transkodowań}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 trwające transkodowanie|$1 trwające transkodowania|$1 trwających transkodowań}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 transkodowanie|$1 transkodowania|$1 transkodowań}} w kolejce",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 nieudane transkodowanie|$1 nieudane transkodowania|$1 nieudanych transkodowań}}",
+ "timedmedia-file": "Plik",
+ "timedmedia-audios": "{{PLURAL:$1|$1 plik dÅŗwiękowy|$1 pliki dÅŗwiękowe|plikĆ³w dÅŗwiękowych}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 plik dÅŗwiękowy|$1 pliki dÅŗwiękowe|plikĆ³w dÅŗwiękowych}} Ogg",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 plik dÅŗwiękowy|$1 pliki dÅŗwiękowe|plikĆ³w dÅŗwiękowych}} FLAC",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 plik dÅŗwiękowy|$1 pliki dÅŗwiękowe|plikĆ³w dÅŗwiękowych}} WAV",
+ "right-transcode-reset": "Resetowanie błędnych lub transkodowanych filmĆ³w, ktĆ³re zostały ponownie umieszczone w kolejce zadań",
+ "right-transcode-status": "Podgląd [[Special:TimedMediaHandler|informacji o aktualnym statusie transkodowania]]",
+ "action-transcode-status": "zobaczenia aktualnego statusu transkodowania",
+ "orphanedtimedtext": "Osierocone strony TimedText",
+ "orphanedtimedtext-unsupported": "To strona specjalna jest obsługiwana tylko przez bazy danych MySQL.",
+ "orphanedtimedtext-notimedtext": "TimedText nie jest włączony w tej wiki.",
+ "apihelp-query+videoinfo-example-1": "Pobierz informacji o [[:File:Folgers.ogv]]",
+ "apihelp-transcodereset-param-title": "Tytuł pliku multimedialnego."
+}
diff --git a/extensions/TimedMediaHandler/i18n/pms.json b/extensions/TimedMediaHandler/i18n/pms.json
new file mode 100644
index 00000000..62681327
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/pms.json
@@ -0,0 +1,96 @@
+{
+ "@metadata": {
+ "authors": [
+ "BorichĆØt",
+ "BĆØrto 'd SĆØra",
+ "DragonĆ²t",
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ"
+ ]
+ },
+ "timedmedia-desc": "Gestor pƫr ij son, filmƠ e test a sincronisƠ, con manteniment dij formƠ pƫr WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Registrassion Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Film Ogg $1, $2",
+ "timedmedia-ogg-short-general": "Archivi Multimojen Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Registrassion Ogg $1, ch'a dura $2, $3",
+ "timedmedia-ogg-long-video": "Film Ogg $1, ch'a dura $2, formƠ $4Ɨ$5 px, $3",
+ "timedmedia-ogg-long-multiplexed": "Archivi audio/video multiplessƠ Ogg, $1, ch'a dura $2, formƠ $4Ɨ$5 px, $3 an tut",
+ "timedmedia-ogg-long-general": "Archivi multimojen Ogg, ch'a dura $2, $3",
+ "timedmedia-ogg-long-error": "Archivi ogg nen bon: $1",
+ "timedmedia-webm-short-video": "Archivi filmĆ  WebM $1, $2",
+ "timedmedia-webm-long-video": "WebM archivi sonor/filmĆ , $1, longheur $2, $4 x $5 pontin, $3 an tut",
+ "timedmedia-flac-short-audio": "Archivi sonor FLAC, $1",
+ "timedmedia-flac-long-audio": "Archivi sonor FLAC, durƠ $1, ritm $2 an sƫl total",
+ "timedmedia-wav-short-audio": "Archivi sonor WAV, $1",
+ "timedmedia-wav-long-audio": "Archivi sonor WAV, durƠ $1, $2 sƫl total",
+ "timedmedia-wav-pcm-required": "A peul mach cariƩ dij WAV PCM (Modolassion d'ampulsion codificƠ).",
+ "timedmedia-mp4-short-video": "Archivi filmĆ  MP4 $1, $2",
+ "timedmedia-mp4-long-video": "MP4 archivi sonor/filmĆ , $1, longheur $2, $4 x $5 pontin, $3 an tut",
+ "timedmedia-no-player-js": "Darmagi, sĆ² navigador a l'ha JavaScript disabilitĆ  o a manten pa Ć«l riprodutor.<br />\nA peul <a href=\"$1\">dĆ«scariĆ© la senĆ«tta</a> o <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">dĆ«scariĆ© un riprodutor</a> pĆ«r visualisĆ© la senĆ«tta su sĆ² navigador.",
+ "timedmedia-more": "Dƫ pƬ...",
+ "timedmedia-dismiss": "sƫrƩ",
+ "timedmedia-download": "DƫscariƩ l'archivi",
+ "timedmedia-play-media": "Lese Ć«l mojen",
+ "timedmedia-desc-link": "RĆ«sgoard a st'archivi",
+ "timedmedia-oggThumb-version": "OggHandler a ciama la version $1 d'oggThumb o pi agiornĆ .",
+ "timedmedia-oggThumb-failed": "oggThumb a l'ha falƬ a creƩ la figurin-a.",
+ "timedmedia-status-header": "StatĆ¹ Ć«d trascodƬfica",
+ "timedmedia-update-status": "AgiornĆ© lĆ« statĆ¹ Ć«d trascodƬfica",
+ "timedmedia-status": "Stat",
+ "timedmedia-status-unknown": "Stat pa conossĆ¹",
+ "timedmedia-transcodeinfo": "Descrission derivƠ da la trascodƬfica",
+ "timedmedia-actions": "Assion",
+ "timedmedia-direct-link": "DƫscariƩ ƫl derivƠ",
+ "timedmedia-not-ready": "Pa pront",
+ "timedmedia-completed-on": "TrascodƬfica completƠ $1",
+ "timedmedia-error-on": "Eror ant la trascodƬfica ƫd $1",
+ "timedmedia-started-transcode": "TrascodƬfica ancaminƠ $1 fƠ. $2",
+ "timedmedia-percent-done": "Sirca $1% fĆ it",
+ "timedmedia-in-job-queue": "GiontĆ  a la coa dij Travaj $1 fĆ ",
+ "timedmedia-unknown-target-size": "Dimension Ć«d la destinassion pa conossĆ¹a, $1 codificĆ ",
+ "timedmedia-days": "{{PLURAL:$1|1 di|$1 di}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 ora|$1 ore}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minuta|$1 minute}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 second|$1 second}}",
+ "timedmedia-reset": "AmpostƩ torna la trascodƬfica",
+ "timedmedia-reset-confirm": "AmpostĆ© torna sa trascodƬfica a tramuderĆ  tut archivi esistent (s'a-i na j'Ć©) e a gionterĆ  torna la trascodƬfica a la coa dij travaj. A-i andrĆ  dĆ«l temp a trascodifichĆ© torna. <br /><br />\nƉ-lo sigur Ć«d vorĆØj continuĆ©?",
+ "timedmedia-reset-error": "Eror an ampostand torna ƫl travaj ƫd trascodƬfica.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 sorziss",
+ "timedmedia-source-file-desc": "Archivi original $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Archivi original $1 ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Larghƫssa ƫd banda bassa Ogg video (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Web streamable Ogg video (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "FilmƠ Ogg lesƬbil an continuƠ an sl'aragnƠ (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "FilmƠ Ogg dƫscariƠbil d'Ơuta qualitƠ (720P)",
+ "timedmedia-derivative-desc-160p.webm": "WebM lesƬbil an continuƠ an sl'aragnƠ (160P)",
+ "timedmedia-derivative-desc-360p.webm": "WebM lesƬbil an continuƠ an sl'aragnƠ (360P)",
+ "timedmedia-derivative-desc-480p.webm": "WebM lesƬbil an continuƠ an sl'aragnƠ (480P)",
+ "timedmedia-derivative-desc-720p.webm": "WebM dƫscariƠbil d'Ơuta qualitƠ (720P)",
+ "timedmedia-derivative-desc-320p.mp4": "Dispositiv compatƬbil MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "MP4 lesƬbil an continuƠ an sl'aragnƠ (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 an qualitĆ  HD (720P)",
+ "timedmedia-subtitle-new": "CreƩ na neuva tradussion o modifichene un-a esistenta",
+ "timedmedia-subtitle-new-desc": "Ch'a selession-a la lenga e ch'a sgnaca an sƫl boton '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Va",
+ "timedmedia-subtitle-language": "$1 ($2) sot-tƬtoj",
+ "timedmedia-subtitle-no-video": "A-i Ʃ gnun filmƠ associƠ con la pagina corenta dƫl sot-tƬtol",
+ "timedmedia-subtitle-no-subtitles": "A-i Ʃ al moment gnun sot-tƬtoj an $1 pƫr ƫs filmƠ, a peul [{{fullurl:{{FULLPAGENAME}}|action=edit}} modifichƩ costa pƠgina] pƫr gionteje",
+ "timedmedia-subtitle-remote": "Ƌl test previst pĆ«r cost archivi a l'Ć© ospitĆ  dzor $1",
+ "timedmedia-subtitle-remote-link": "A peul [$1 vƫdde la pƠgina ƫd descrission] ƫd s'archivi dzor $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 filmĆ }}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 filmĆ  Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 filmĆ  WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 trascodƬfica|$1 trascodƬfiche}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 trascodƬfica|$1 trascodƬfiche}} an esecussion",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 trascodƬfica|$1 trascodƬfiche}} an coa",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 trascodƬfica falƬa|$1 trascodƬfiche falƬe}}",
+ "timedmedia-file": "Archivi",
+ "timedmedia-audios": "{{PLURAL:$1|$1 archivi sonor}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 archivi sonor Ogg}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 archivi sonor FLAC}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 archivi sonor WAV}}",
+ "right-transcode-reset": "AmpostƩ torna ij filmƠ falƬ o trascodificƠ pƫr ch'a sio torna anserƬ ant la coa dij travaj.",
+ "right-transcode-status": "Smon-e [[Special:TimedMediaHandler|l'anformassion a propĆ²sit Ć«d l'ativitĆ  corenta Ć«d trascodƬfica]]",
+ "action-transcode-status": "varda lƫ stat ƫd trascodƬfica corent"
+}
diff --git a/extensions/TimedMediaHandler/i18n/pnb.json b/extensions/TimedMediaHandler/i18n/pnb.json
new file mode 100644
index 00000000..3ff940e9
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/pnb.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Khalid Mahmood"
+ ]
+ },
+ "timedmedia-no-player-js": "ŲŖŁˆŲ§ŚˆŪ’ ŲØŲ±Ų§Ų¤Ų²Ų± ŲŖŪ’ Ų¬Ų§ŁˆŲ§Ų³Ś©Ų±Ł¾Ł¹ Ś©Ł… Ł†ŪŪŒŚŗ Ś©Ų± Ų±ŪŒŲ§ ŪŒŲ§ ŁŪŒŲ± ŪŁˆŲ± Ł¾Ł„Ų¦ŪŒŲ± Ł†ŪŪŒŚŗ <br />\nŲŖŲ³ŪŒŚŗ <a href=\"$1\">Ś©Ł„Ł¾ ŚˆŲ§Ų¤Ł†Ł„ŁˆŚˆ Ś©Ų±Ų³Ś©ŲÆŪ’ Ų§Łˆ</a> ŪŒŲ§ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ŪŒŲ§ Ų§Ł¾Ł†Ū’ ŲØŲ±Ų§Ų¤Ų²Ų± ŁˆŚ† Ś©Ł„Ł¾ Ś†Ł„Ų§Ł† Ł„Ų¦ŪŒ Ł¾Ł„ŪŒŲ¦Ų± ŚˆŲ§Ų¤Ł†Ł„ŁˆŚˆ Ś©Ų±Łˆ</a> .",
+ "timedmedia-source-file": "$1 Ł…ŚˆŚ¾",
+ "timedmedia-source-audio-file-desc": "Ų§ŲµŁ„ŪŒ$1 ŁŲ§Ų¦Ł„ ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ps.json b/extensions/TimedMediaHandler/i18n/ps.json
new file mode 100644
index 00000000..f602ceb3
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ps.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ahmed-Najib-Biabani-Ibrahimkhel"
+ ]
+ },
+ "timedmedia-ogg-short-audio": "Ogg $1 ŲŗŚ–ŁŠŲ²Ł‡ ŲÆŁˆŲŖŁ†Ł‡ŲŒ $2",
+ "timedmedia-ogg-short-video": "Ogg $1 ŁˆŁŠŚ‰ŁŠŁˆŁŠŁŠ ŲÆŁˆŲŖŁ†Ł‡ŲŒ $2",
+ "timedmedia-ogg-short-general": "Ogg $1 Ų±Ų³Ł†ŁŠŲ²Ł‡ ŲÆŁˆŲŖŁ†Ł‡ŲŒ $2",
+ "timedmedia-no-player-js": "ŲØŲ®ŚšŁ†Ł‡ ŲÆŪ ŁˆŁŠŲŒ ŁŠŲ§ Ų®Łˆ Ų³ŲŖŲ§Ų³Ū Ł¾Ł‡ Ś©ŲŖŁ†Ł…Ł„ ŲØŲ§Ł†ŲÆŪ Ų¬Ų§ŁˆŲ§Ų³Ś©Ų±ŪŁ¾Ł¼ Ł†Ų§Ś†Ų§Ų±Ł† ŲÆŪŒ Ų§Łˆ ŁŠŲ§ Ł‡Ł… ŲŖŲ§Ų³Ū Ś©ŁˆŁ… Ł…Ł„Ų§ŲŖŚ“Ł„ŪŒ ŲŗŚ–ŁˆŁ†Ś©ŪŒ Ł†Ł‡ Ł„Ų±ŪŒ.<br />\nŲŖŲ§Ų³Ū <a href=\"$1\">Ś©Ł„ŪŁ¾ ŚšŚ©ŲŖŁ‡ Ś©ŁˆŁ„ŪŒ Ų“Ų¦</a> Ų§Łˆ ŁŠŲ§ Ł‡Ł… ŁŠŁˆ ŲÆŲ§Ų³Ū <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ŲŗŚ–ŁˆŁ†Ś©ŪŒ ŚšŚ©ŲŖŁ‡ Ś©Ś“Ų¦</a> Ś†Ū Ś©Ł„ŪŁ¾ Ł¾Ł‡ Ś©ŲŖŁ†Ł…Ł„ ŲØŲ§Ł†ŲÆŪ ŁˆŲŗŚ–ŁˆŁŠ.",
+ "timedmedia-more": "Ł†ŁˆŲ±...",
+ "timedmedia-dismiss": "ŲŖŚ“Ł„",
+ "timedmedia-download": "ŲÆŁˆŲŖŁ†Ł‡ ŚšŚ©ŲŖŁ‡ Ś©ŁˆŁ„",
+ "timedmedia-play-media": "Ų±Ų³Ł†Ū ŲŗŚ–ŁˆŁ„",
+ "timedmedia-desc-link": "ŲÆ Ł‡Ł…ŲÆŪ ŲÆŁˆŲŖŁ†Ū Ł¾Ł‡ Ų§Ś“Ł‡",
+ "timedmedia-status": "ŲÆŲ±ŁŠŚ",
+ "timedmedia-transcodeinfo": "ŲØŚ¼Ł‡",
+ "timedmedia-actions": "Ś†Ų§Ų±Ū",
+ "timedmedia-direct-link": "ŚšŚ©ŲŖŁ‡ Ś©ŁˆŁ„",
+ "timedmedia-days": "{{PLURAL:$1|1 ŁˆŲ±Ś|$1 ŁˆŲ±ŚŪ}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 ŚÆŚ“Ū|$1 ŚÆŚ“Ū}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 ŲÆŁ‚ŁŠŁ‚Ł‡|ŲÆŁ‚ŁŠŁ‚Ū}}",
+ "timedmedia-source-file": "$1 Ų³Ų±Ś†ŁŠŁ†Ł‡",
+ "timedmedia-source-audio-file-desc": "Ų§ŲµŁ„ŁŠ $1 ŲÆŁˆŲŖŁ†Ł‡ ($2)",
+ "timedmedia-subtitle-new-go": "ŁˆŲ±ŚŁ‡",
+ "timedmedia-videos": "{{PLURAL:$1|$1 ŁˆŁŠŚ‰ŁŠŁˆ|$1 ŁˆŁŠŚ‰ŁŠŁˆŚÆŲ§Ł†Ū}}",
+ "timedmedia-file": "ŲÆŁˆŲŖŁ†Ł‡",
+ "timedmedia-audios": "{{PLURAL:$1|$1 ŲŗŚ–ŁŠŲ²Ł‡ ŲÆŁˆŲŖŁ†Ł‡|$1 ŲŗŚ–ŁŠŲ²Ū ŲÆŁˆŲŖŁ†Ū}}"
+}
diff --git a/extensions/TimedMediaHandler/i18n/pt-br.json b/extensions/TimedMediaHandler/i18n/pt-br.json
new file mode 100644
index 00000000..99b96b5e
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/pt-br.json
@@ -0,0 +1,40 @@
+{
+ "@metadata": {
+ "authors": [
+ "Eduardo.mps",
+ "Giro720",
+ "Luckas",
+ "Opraco",
+ "Guilhermemau",
+ "Fasouzafreitas"
+ ]
+ },
+ "timedmedia-desc": "Manipulador para arquivos Ogg Theora e Vorbis, com reprodutor JavaScript",
+ "timedmedia-ogg-short-audio": "Arquivo de Ɣudio Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Arquivo de vĆ­deo Ogg $1, $2",
+ "timedmedia-ogg-short-general": "Arquivo multimĆ­dia Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "arquivo de Ć”udio Ogg $1, $2 de duraĆ§Ć£o, $3",
+ "timedmedia-ogg-long-video": "VĆ­deo Ogg $1, $2 de duraĆ§Ć£o, $4Ɨ$5 pixels, $3",
+ "timedmedia-ogg-long-multiplexed": "Ɓudio/vĆ­deo Ogg multifacetado, $1, $2 de duraĆ§Ć£o, $4Ɨ$5 pixels, $3 no todo",
+ "timedmedia-ogg-long-general": "MultimĆ­dia Ogg, $2 de duraĆ§Ć£o, $3",
+ "timedmedia-ogg-long-error": "Arquivo ogg invƔlido: $1",
+ "timedmedia-no-player-js": "Desculpe, seu navegador ou estĆ” com JavaScript desabilitado ou nĆ£o tem nenhum \"player\" suportado.<br />\nVocĆŖ pode <a href=\"$1\">descarregar o clipe</a> ou <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">descarregar um \"player\"</a> para executar o clipe em seu navegador.",
+ "timedmedia-more": "Mais...",
+ "timedmedia-dismiss": "Fechar",
+ "timedmedia-download": "Descarregar arquivo",
+ "timedmedia-desc-link": "Sobre este arquivo",
+ "timedmedia-oggThumb-version": "O oggHandler requer o oggThumb versĆ£o $1 ou posterior.",
+ "timedmedia-oggThumb-failed": "O oggThumb nĆ£o conseguiu criar a miniatura.",
+ "timedmedia-actions": "AƧƵes",
+ "timedmedia-days": "{{PLURAL:$1|1 dia|$1 dias}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 hora|$1 horas}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minuto|$1 minutos}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 segundo|$1 segundos}}",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Fonte $1",
+ "timedmedia-source-audio-file-desc": "Arquivo $1 original ($2)",
+ "timedmedia-derivative-desc-1080p.webm": "WebM para download de Full HD (1080p)",
+ "timedmedia-derivative-desc-1080p.mp4": "Qualidade total do HD MP4 (1080 P)",
+ "timedmedia-subtitle-new-go": "Ir",
+ "timedmedia-file": "Arquivo"
+}
diff --git a/extensions/TimedMediaHandler/i18n/pt.json b/extensions/TimedMediaHandler/i18n/pt.json
new file mode 100644
index 00000000..379e2271
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/pt.json
@@ -0,0 +1,102 @@
+{
+ "@metadata": {
+ "authors": [
+ "Giro720",
+ "Hamilton Abreu",
+ "Luckas",
+ "Malafaya",
+ "Opraco",
+ "Vitorvicentevalente",
+ "Waldir",
+ "555",
+ "Tooguether",
+ "Macofe",
+ "FĆŗlvio"
+ ]
+ },
+ "timedmedia-desc": "Tratamento de Ɣudio, vƭdeo e legendagem, nos formatos WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Ɓudio Ogg $1, $2",
+ "timedmedia-ogg-short-video": "VĆ­deo Ogg $1, $2",
+ "timedmedia-ogg-short-general": "MultimƩdia Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Ć”udio Ogg $1, $2 de duraĆ§Ć£o, $3",
+ "timedmedia-ogg-long-video": "VĆ­deo Ogg $1, $2 de duraĆ§Ć£o, $4Ɨ$5 pixels, $3",
+ "timedmedia-ogg-long-multiplexed": "Ɓudio/vĆ­deo Ogg multifacetado, $1, $2 de duraĆ§Ć£o, $4Ɨ$5 pixels, $3 no todo",
+ "timedmedia-ogg-long-general": "MultimĆ©dia Ogg, $2 de duraĆ§Ć£o, $3",
+ "timedmedia-ogg-long-error": "Ficheiro ogg invƔlido: $1",
+ "timedmedia-ogg-long-no-streams": "Arquivo de mĆ­dia OGG. Aviso: Nenhum dos codecs utilizados neste arquivo sĆ£o reconhecidos.",
+ "timedmedia-webm-short-video": "VĆ­deo WebM $1, $2",
+ "timedmedia-webm-long-video": "Ɓudio/vĆ­deo WebM, $1, $2 de duraĆ§Ć£o, $4 Ɨ $5 pixels, $3 no todo",
+ "timedmedia-flac-short-audio": "Ficheiro de Ɣudio FLAC, $1",
+ "timedmedia-flac-long-audio": "Ficheiro de Ć”udio FLAC, duraĆ§Ć£o $1, $2",
+ "timedmedia-wav-short-audio": "Ficheiro de Ɣudio WAV, $1",
+ "timedmedia-wav-long-audio": "Ficheiro de Ć”udio WAV, duraĆ§Ć£o $1, $2",
+ "timedmedia-mp4-short-video": "VĆ­deo MP4 $1, $2",
+ "timedmedia-mp4-long-video": "Ɓudio/vĆ­deo MP$, $1, duraĆ§Ć£o $2, $4 Ɨ $5 pixels, $3",
+ "timedmedia-no-player-js": "Desculpe, mas ou o seu navegador estĆ” com o JavaScript desactivado ou nĆ£o tem nenhum dos leitores suportados.<br />\nPode fazer a <a href=\"$1\">descarga do vĆ­deo</a> ou o <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">de um leitor</a> para assistir ao vĆ­deo no seu navegador.",
+ "timedmedia-more": "Mais...",
+ "timedmedia-dismiss": "Fechar",
+ "timedmedia-download": "Fazer descarga do ficheiro",
+ "timedmedia-play-media": "Reproduzir conteĆŗdo",
+ "timedmedia-desc-link": "Sobre este ficheiro",
+ "timedmedia-oggThumb-version": "O oggHandler requer a versĆ£o $1 do oggThumb ou posterior.",
+ "timedmedia-oggThumb-failed": "O oggThumb nĆ£o conseguiu criar a miniatura.",
+ "timedmedia-status-header": "Estado da transcodificaĆ§Ć£o",
+ "timedmedia-update-status": "Actualizar o estado da transcodificaĆ§Ć£o",
+ "timedmedia-status": "Estado",
+ "timedmedia-status-unknown": "Estado desconhecido",
+ "timedmedia-transcodeinfo": "Formato",
+ "timedmedia-actions": "AcƧƵes",
+ "timedmedia-direct-link": "Descarregar",
+ "timedmedia-not-ready": "Ainda nĆ£o estĆ” pronto",
+ "timedmedia-completed-on": "ConcluĆ­da a $1",
+ "timedmedia-error-on": "Erro em $1",
+ "timedmedia-started-transcode": "Iniciou hĆ” $1. $2",
+ "timedmedia-percent-done": "O progresso Ć© cerca de $1%",
+ "timedmedia-in-job-queue": "Adicionado Ć  fila de tarefas hĆ” $1",
+ "timedmedia-unknown-target-size": "DimensĆ£o do destino desconhecida; $1 codificados",
+ "timedmedia-days": "{{PLURAL:$1|1 dia|$1 dias}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 hora|$1 horas}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minuto|$1 minutos}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 segundo|$1 segundos}}",
+ "timedmedia-reset": "Reiniciar transcodificaĆ§Ć£o",
+ "timedmedia-reset-confirm": "Reiniciar esta transcodificaĆ§Ć£o elimina qualquer ficheiro existente e volta a adicionar a transcodificaĆ§Ć£o Ć  fila de tarefas. A nova transcodificaĆ§Ć£o irĆ” demorar algum tempo. <br /><br />Tem a certeza de que pretende continuar?",
+ "timedmedia-reset-error": "Ocorreu um erro ao reiniciar a tarefa de transcodificaĆ§Ć£o",
+ "timedmedia-source-file": "Fonte $1",
+ "timedmedia-source-file-desc": "Ficheiro $1 original, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Ficheiro $1 original ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "VĆ­deo Ogg de baixa largura de banda (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "VĆ­deo Ogg para web streaming (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "VĆ­deo Ogg para web streaming (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "VĆ­deo Ogg de alta qualidade para download (720 P)",
+ "timedmedia-derivative-desc-360p.webm": "WebM para web streaming (360P)",
+ "timedmedia-derivative-desc-480p.webm": "WebM para web streaming (480P)",
+ "timedmedia-derivative-desc-720p.webm": "WebM de alta qualidade para download (720P)",
+ "timedmedia-derivative-desc-720p.mp4": "Qualidade HD MP4 (720P)",
+ "timedmedia-subtitle-new": "Criar nova traduĆ§Ć£o ou editar existente",
+ "timedmedia-subtitle-new-desc": "Seleccione o idioma e pressione o botĆ£o '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Enviar",
+ "timedmedia-subtitle-language": "Legendas em $1 ($2)",
+ "timedmedia-subtitle-no-video": "NĆ£o existe nenhum vĆ­deo associado Ć  actual pĆ”gina de legendas",
+ "timedmedia-subtitle-no-subtitles": "Neste momento nĆ£o existem legendas em $1 para este vĆ­deo. Pode [{{fullurl:{{FULLPAGENAME}}|action=edit}} editar a pĆ”gina] e adicionĆ”-las.",
+ "timedmedia-subtitle-remote": "A legenda para este ficheiro estĆ” hospedada em $1",
+ "timedmedia-subtitle-remote-link": "Pode [$1 ver a pĆ”gina de descriĆ§Ć£o] para este ficheiro em $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 vĆ­deo|$1 vĆ­deos}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 vĆ­deo ogg|$1 vĆ­deos ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 vĆ­deo WebM|$1 vĆ­deos WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transcodificaĆ§Ć£o|$1 transcodificaƧƵes}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 transcodificaĆ§Ć£o em andamento|$1 transcodificaƧƵes em andamento}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 transcodificaĆ§Ć£o em espera|$1 transcodificaƧƵes em espera}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 transcodificaĆ§Ć£o falhada|$1 transcodificaƧƵes falhadas}}",
+ "timedmedia-file": "Ficheiro",
+ "timedmedia-audios": "{{PLURAL:$1|$1 ficheiro de Ɣudio|$1 ficheiros de Ɣudio}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 ficheiro de Ɣudio Ogg|$1 ficheiros de Ɣudio Ogg}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 ficheiro de Ɣudio FLAC|$1 ficheiros de Ɣudio FLAC}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 ficheiro de Ɣudio WAV|$1 ficheiros de Ɣudio WAV}}",
+ "right-transcode-status": "Ver [[Special:TimedMediaHandler|informaĆ§Ć£o sobre a actividade actual de transcodificaĆ§Ć£o]]",
+ "action-transcode-status": "ver o estado actual de transcodificaĆ§Ć£o",
+ "orphanedtimedtext": "PĆ”ginas Legendagem Ć³rfĆ£s",
+ "orphanedtimedtext-summary": "Lista de pĆ”ginas [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] que nĆ£o tĆŖm um ficheiro correspondente.",
+ "orphanedtimedtext-unsupported": "Esta pĆ”gina especial sĆ³ Ć© suportada nas bases de dados MySQL.",
+ "orphanedtimedtext-notimedtext": "O domĆ­nio Legendagem nĆ£o estĆ” habilitado nesta wiki."
+}
diff --git a/extensions/TimedMediaHandler/i18n/qqq.json b/extensions/TimedMediaHandler/i18n/qqq.json
new file mode 100644
index 00000000..4fe17fe8
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/qqq.json
@@ -0,0 +1,172 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aotake",
+ "BrokenArrow",
+ "EugeneZelenko",
+ "Fryed-peach",
+ "Jon Harald SĆøby",
+ "Meno25",
+ "Minh Nguyen",
+ "Mormegil",
+ "Purodha",
+ "Raymond",
+ "Shirayuki",
+ "Siebrand",
+ "Umherirrender",
+ "ģ•„ė¼",
+ "Liuxinyu970226",
+ "Amire80",
+ "Robby"
+ ]
+ },
+ "extensionname-timedmedia": "{{optional}}",
+ "timedmedia-desc": "{{desc|name=Timed Media Handler|url=https://www.mediawiki.org/wiki/Extension:TimedMediaHandler}}",
+ "timedmedia-ogg-short-audio": "File details for Ogg sound (audio) files, short version.\nParameters:\n* $1 - stream type name. Any one of the following: Vorbis, Speex, FLAC\n* $2 - duration of the sound/audio (localized) - e.g. 1m34s\n{{Related|Timedmedia-ogg-short}}",
+ "timedmedia-ogg-short-video": "File details for Ogg video files, short version.\nParameters:\n* $1 - stream type name: Theora\n* $2 - duration of the video (localized) - e.g. 1m34s\n{{Related|Timedmedia-ogg-short}}",
+ "timedmedia-ogg-short-general": "File details for generic (non-audio, non-video) Ogg files, short version.\nParameters:\n* $1 - stream type name\n* $2 - duration of the media (localized) - e.g. 1m34s\n{{Related|Timedmedia-ogg-short}}",
+ "timedmedia-ogg-long-audio": "File details for Ogg sound (audio) files, long version.\n\nShown after the filename in the image description page.\n\nParameters:\n* $1 - stream type name. Any one of the following: Vorbis, Speex, FLAC\n* $2 - duration of the sound (localized) - e.g. 1m34s\n* $3 - bit-rate of the sound (localized) - e.g. 97kbps\n{{Related|Timedmedia-ogg-long}}",
+ "timedmedia-ogg-long-video": "File details for Ogg video files, long version.\n\nShown after the filename in the image description page.\n\nParameters:\n* $1 - stream type name: Theora\n* $2 - duration of the video (localized) - e.g. 1m34s\n* $3 - bit-rate of the video (localized) - e.g. 97kbps\n* $4 - width of the video (in pixels)\n* $5 - height of the video (in pixels)\n{{Related|Timedmedia-ogg-long}}",
+ "timedmedia-ogg-long-multiplexed": "{{doc-important|Start with a lowercase letter, unless the first word is \"Ogg\".}}\nFile details for Ogg multiplexed audio/video files, long version.\n\nShown after the filename in the image description page.\n\nParameters:\n* $1 - stream type names, slash-separated - e.g. Theora/Vorbis\n* $2 - duration (localized) - e.g. 1m34s\n* $3 - bit-rate (localized) - e.g. 97kbps\n* $4 - width of the video (in pixels)\n* $5 - height of the video (in pixels)\n{{Related|Timedmedia-ogg-long}}",
+ "timedmedia-ogg-long-general": "File details for Ogg generic (non-video, non-audio) files, long version.\n\nShown after the filename in the image description page.\n\nParameters:\n* $1 - (Unused)\n* $2 - duration (localized) - e.g. 1m34s\n* $3 - bit-rate (localized) - e.g. 97kbps\n{{Related|Timedmedia-ogg-long}}",
+ "timedmedia-ogg-long-error": "Used as error message. Parameters:\n* $1 - error message. e.g. File not found, invalid stream, etc.",
+ "timedmedia-ogg-long-no-streams": "Similar to {{msg-mw|timedmedia-ogg-long-error}}. Used as the long description for an ogg media file if there are no streams in the file using a recognized codec. This can be caused by an invalid ogg file, or by one using an obscure type of data (e.g. dirac video with no audio).",
+ "timedmedia-webm-short-video": "File details for WebM video files, short version.\nParameters:\n* $1 - stream type names (slash separated) - e.g. Vorbis/VP8\n* $2 - duration of the video (localized) - e.g. 1m34s\nSee also:\n* {{msg-mw|Timedmedia-webm-long-video}}",
+ "timedmedia-webm-long-video": "File details for WebM multiplexed audio/video files, long version.\n\nShown after the filename in the image description page.\n\nParameters:\n* $1 - stream type names (slash separated) - e.g. Vorbis/VP8\n* $2 - duration (localized) - e.g. 1m34s\n* $3 - bit-rate (localized) - e.g. 97kbps\n* $4 - width of the video (in pixels)\n* $5 - height of the video (in pixels)\nSee also:\n* {{msg-mw|Timedmedia-webm-short-video}}",
+ "timedmedia-flac-short-audio": "File details for FLAC audio files, short version.\nParameters:\n* $1 - duration of the audio (localized) - e.g. 1m34s\n\nPrimarily used on [[Special:Search]] results pages, i.e.\n https://commons.wikimedia.org/w/index.php?title=Special%3ASearch&profile=advanced&search=What%27s+a+love+dart&fulltext=Search&ns6=1&profile=advanced\n\nSee also:\n* {{msg-mw|Timedmedia-flac-long-audio}}\n* {{msg-mw|Timedmedia-ogg-short-audio}}",
+ "timedmedia-flac-long-audio": "File details for FLAC files, long version.\n\nShown after the filename in the image description page.\n\nParameters:\n* $1 - duration (localized) - e.g. 1m34s\n* $2 - bit-rate (localized) - e.g. 97kbps\nSee also:\n* {{msg-mw|Timedmedia-flac-short-audio}}",
+ "timedmedia-wav-short-audio": "File details for WAV audio files, short version.\nParameters:\n* $1 - duration of the audio (localized) - e.g. 1m34s\nSee also:\n* {{msg-mw|Timedmedia-wav-long-audio}}",
+ "timedmedia-wav-long-audio": "File details for WAV files, long version.\nShown after the filename in the image description page.\n\nParameters:\n* $1 - duration of the audio (localized) - e.g. 1m34s\n* $2 - bit-rate (localized) - e.g. 97kbps\nSee also:\n* {{msg-mw|Timedmedia-wav-short-audio}}",
+ "timedmedia-wav-pcm-required": "Message shown at upload if user tries to upload a WAV file using a codec that is not PCM",
+ "timedmedia-mp4-short-video": "File details for MP4 video files, short version.\nParameters:\n* $1 - stream type names (slash separated) - e.g. AAC/h.264\n* $2 - duration of the video (localized) - e.g. 1m34s\nSee also:\n* {{msg-mw|Timedmedia-mp4-long-video}}",
+ "timedmedia-mp4-long-video": "File details for MP4 multiplexed audio/video files, long version.\n\nShown after the filename in the image description page.\n\nParameters:\n* $1 - stream type names (slash separated) - e.g. AAC/h.264\n* $2 - duration (localized) - e.g. 1m34s\n* $3 - bit-rate (localized) - e.g. 97kbps\n* $4 - width of the video (in pixels)\n* $5 - height of the video (in pixels)\nSee also:\n* {{msg-mw|Timedmedia-mp4-short-video}}",
+ "timedmedia-no-player-js": "Used as fallback text displayed for browsers without js and without video tag support.\n\nParameters:\n* $1 - media source URL",
+ "timedmedia-more": "Unused at this time.\n{{Identical|More...}}",
+ "timedmedia-dismiss": "Unused at this time.\n{{Identical|Close}}",
+ "timedmedia-download": "Used as tooltip for the Download button.\n{{Identical|Download}}",
+ "timedmedia-play-media": "Used as tooltip for the link.",
+ "timedmedia-desc-link": "Unused at this time.\n{{Identical|About this file}}",
+ "timedmedia-oggThumb-version": "Used as error message when the specified option is invalid. Parameters:\n* $1 - version number \"0.9\" (hard-coded)",
+ "timedmedia-oggThumb-failed": "{{doc-important|Do not translate <code>oggThumb</code>.}}\nUsed as error message when executing oggThumb.",
+ "timedmedia-status-header": "Used as section heading.",
+ "timedmedia-update-status": "Used as text for the link which is used to purge.",
+ "timedmedia-status": "Used as column header.\n{{Identical|Status}}",
+ "timedmedia-status-unknown": "Used as status message on error.\n{{Identical|Unknown status}}",
+ "timedmedia-transcodebitrate": "A table column header for description of transcode bitrate",
+ "timedmedia-transcodeduration": "A table column header for description of transcode encoding time",
+ "timedmedia-transcodeinfo": "A table column header for description of Transcode derivative\n{{Identical|Format}}",
+ "timedmedia-actions": "Used as column header.\n{{Identical|Action}}",
+ "timedmedia-direct-link": "Used as column header.\n{{Identical|Download}}",
+ "timedmedia-not-ready": "State of a given transcode job being not yet complete or not yet ready",
+ "timedmedia-completed-on": "Completed transcode message. Parameters:\n* $1 - the timestamp (time and date) that the transcode was completed",
+ "timedmedia-error-on": "Parameters:\n* $1 - timestamp",
+ "timedmedia-started-transcode": "Status update for Transcodes. Parameters:\n* $1 - time passed since transcoded started (e.g. \"{{int:timedmedia-minutes|1}}{{int:comma-separator}}{{int:timedmedia-seconds|42}}\"), uses the following messages:\n** {{msg-mw|Timedmedia-days}}\n** {{msg-mw|Timedmedia-hours}}\n** {{msg-mw|Timedmedia-minutes}}\n** {{msg-mw|Timedmedia-seconds}}\n** {{msg-mw|Comma-separator}}\n* $2 - percentage of transcode complete",
+ "timedmedia-percent-done": "Commented out at this time.\n\nStatus update for Transcodes. Parameters:\n* $1 - percentage of the file transcoded so far\nSee also:\n* {{msg-mw|timedmedia-unknown-target-size}}",
+ "timedmedia-in-job-queue": "Shown on the file description page in the {{msg-mw|timedmedia-status-header}} section.\n\nParameters:\n* $1 - the time the media has been in the job queue (e.g. \"{{int:timedmedia-minutes|1}}{{int:comma-separator}}{{int:timedmedia-seconds|42}}\"), uses the following messages:\n** {{msg-mw|Timedmedia-days}}\n** {{msg-mw|Timedmedia-hours}}\n** {{msg-mw|Timedmedia-minutes}}\n** {{msg-mw|Timedmedia-seconds}}\n** {{msg-mw|Comma-separator}}",
+ "timedmedia-unknown-target-size": "Commented out at this time.\n\nStatus update for Transcodes. Parameters:\n* $1 - the number of bytes of the file transcoded so far (localized)\nSee also:\n* {{msg-mw|Timedmedia-percent-done}}",
+ "timedmedia-days": "Used as the duration, as <code>$1</code> in the following messages:\n* {{msg-mw|Timedmedia-in-job-queue}}\n* {{msg-mw|Timedmedia-started-transcode}}\nParameters:\n* $1 - number of days\n{{Related|Timedmedia-days}}\n{{Identical|Day}}",
+ "timedmedia-hours": "Used as the duration, as <code>$1</code> in the following messages:\n* {{msg-mw|Timedmedia-in-job-queue}}\n* {{msg-mw|Timedmedia-started-transcode}}\nParameters:\n* $1 - number of hours\n{{Related|Timedmedia-days}}\n{{Identical|Hour}}",
+ "timedmedia-minutes": "Used as the duration, as <code>$1</code> in the following messages:\n* {{msg-mw|Timedmedia-in-job-queue}}\n* {{msg-mw|Timedmedia-started-transcode}}\nParameters:\n* $1 - minutes\n{{Related|Timedmedia-days}}\n{{Identical|Minute}}",
+ "timedmedia-seconds": "Used as the duration, as <code>$1</code> in the following messages:\n* {{msg-mw|Timedmedia-in-job-queue}}\n* {{msg-mw|Timedmedia-started-transcode}}\nParameters:\n* $1 - number of seconds\n{{Related|Timedmedia-days}}\n{{Identical|Second}}",
+ "timedmedia-reset": "Used as action link text and as dialog title.\n\nThe contents of the dialog is {{msg-mw|Timedmedia-reset-confirm}}.",
+ "timedmedia-reset-confirm": "Used as confirmation message in the dialog which has the title {{msg-mw|Timedmedia-reset}}.",
+ "timedmedia-reset-error": "Used as generic error message.",
+ "timedmedia-ogg": "{{optional}}\nUsed as <code>$1</code> in the following messages:\n* {{msg-mw|Timedmedia-source-audio-file-desc}}\n* {{msg-mw|Timedmedia-source-file-desc}}\n* {{msg-mw|Timedmedia-source-file}}",
+ "timedmedia-webm": "{{optional}}\nUsed as <code>$1</code> in the following messages:\n* {{msg-mw|Timedmedia-source-audio-file-desc}}\n* {{msg-mw|Timedmedia-source-file-desc}}\n* {{msg-mw|Timedmedia-source-file}}",
+ "timedmedia-mp4": "{{Optional}}\nUsed as <code>$1</code> in the following messages:\n* {{msg-mw|Timedmedia-source-audio-file-desc}}\n* {{msg-mw|Timedmedia-source-file-desc}}\n* {{msg-mw|Timedmedia-source-file}}",
+ "timedmedia-wav": "{{Optional}}\nUsed as <code>$1</code> in the following messages:\n* {{msg-mw|Timedmedia-source-audio-file-desc}}\n* {{msg-mw|Timedmedia-source-file-desc}}\n* {{msg-mw|Timedmedia-source-file}}",
+ "timedmedia-flac": "{{Optional}}\n\nUsed as <code>$1</code> in the following messages:\n* {{msg-mw|Timedmedia-source-audio-file-desc}}\n* {{msg-mw|Timedmedia-source-file-desc}}\n* {{msg-mw|Timedmedia-source-file}}",
+ "timedmedia-source-file": "The source file. Parameters:\n* $1 - file type; any one of the following messages:\n** {{msg-mw|Timedmedia-ogg}}\n** {{msg-mw|Timedmedia-webm}}\n** {{msg-mw|Timedmedia-mp4}}\n** {{msg-mw|Timedmedia-flac}}\n** {{msg-mw|Timedmedia-wav}}\nSee also:\n* {{msg-mw|Timedmedia-source-audio-file-desc}}\n* {{msg-mw|Timedmedia-source-file-desc}}\n{{Identical|Source}}",
+ "timedmedia-source-file-desc": "Source file description. This is a file title in the primary source attributes of a timed media file. I can look like \"''Original Ogg file, 640 Ɨ 480 (10 Mbps)''\".\n\nParameters:\n* $1 - file type; any one of the following messages:\n** {{msg-mw|Timedmedia-ogg}}\n** {{msg-mw|Timedmedia-webm}}\n** {{msg-mw|Timedmedia-mp4}}\n** {{msg-mw|Timedmedia-flac}}\n** {{msg-mw|Timedmedia-wav}}\n* $2 - resolution width\n* $3 - resolution height\n* $4 - human readable bitrate\nSee also:\n* {{msg-mw|Timedmedia-source-audio-file-desc}} - for audio file",
+ "timedmedia-source-audio-file-desc": "Source file description. Parameters:\n* $1 - file type; any one of the following messages:\n** {{msg-mw|Timedmedia-ogg}}\n** {{msg-mw|Timedmedia-webm}}\n** {{msg-mw|Timedmedia-mp4}}\n** {{msg-mw|Timedmedia-flac}}\n** {{msg-mw|Timedmedia-wav}}\n* $2 - human readable bitrate\nSee also:\n* {{msg-mw|Timedmedia-source-file-desc}} - for video file",
+ "timedmedia-derivative-160p.ogv": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-160p.ogv": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-240p.ogv": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-240p.ogv": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-360p.ogv": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-360p.ogv": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-480p.ogv": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-480p.ogv": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-720p.ogv": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-720p.ogv": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-1080p.ogv": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-1080p.ogv": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-160p.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-160p.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-360p.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-360p.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-480p.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-480p.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-720p.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-720p.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-1080p.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-1080p.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-2160p.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-2160p.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-360p.vp9.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-360p.vp9.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-480p.vp9.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-480p.vp9.webm": "A type of media format encoding",
+ "timedmedia-derivative-720p.vp9.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-720p.vp9.webm": "A type of media format encoding",
+ "timedmedia-derivative-1080p.vp9.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-2160p.vp9.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-320p.mp4": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-320p.mp4": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-480p.mp4": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-480p.mp4": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-720p.mp4": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-720p.mp4": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-1080p.mp4": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-1080p.mp4": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-2160p.mp4": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-desc-2160p.mp4": "{{optional}} A type of media format encoding",
+ "timedmedia-derivative-ogg": "{{optional}} Short form of a media format.",
+ "timedmedia-derivative-desc-ogg": "{{optional}} Media format.",
+ "timedmedia-derivative-opus": "{{optional}} Short form of a media format.",
+ "timedmedia-derivative-desc-opus": "{{optional}} Media format.",
+ "timedmedia-derivative-mp3": "{{optional}} Short form of a media format.",
+ "timedmedia-derivative-desc-mp3": "{{optional}} Media format.",
+ "timedmedia-derivative-m4a": "{{optional}} Short form of a media format.",
+ "timedmedia-derivative-desc-m4a": "{{optional}} Media format.",
+ "timedmedia-subtitle-new": "Used as page title.",
+ "timedmedia-subtitle-new-desc": "Refers to {{msg-mw|Timedmedia-subtitle-new-go}}.",
+ "timedmedia-subtitle-new-go": "Used as label for the Submit button.\n\nPreceded by (and used in) the description {{msg-mw|Timedmedia-subtitle-new-desc}}.\n{{Identical|Go}}",
+ "timedmedia-subtitle-language": "Subtitle names. Parameters are:\n* $1 - subtitle language\n* $2 - subtitle key\n{{Identical|Subtitle}}",
+ "timedmedia-subtitle-no-video": "Message for a TimedText page without an associated video file",
+ "timedmedia-subtitle-no-subtitles": "Parameters:\n* $1 is a language name.",
+ "timedmedia-subtitle-remote": "Used as page title. Parameters:\n* $1 - the display name of the repository\nThe page body for this page title is:\n* {{msg-mw|timedmedia-subtitle-remote-link}}",
+ "timedmedia-subtitle-remote-link": "Used as page body. Parameters:\n* $1 - the description URL of the file\n* $2 - the display name of the repository\nThe page title for this message is:\n* {{msg-mw|timedmedia-subtitle-remote}}",
+ "timedmediahandler": "{{doc-special|TimedMediaHandler}}",
+ "timedmedia-videos": "Number of videos on [[Special:TimedMediaHandler]]. Parameters:\n* $1 - number of videos\n{{Related|Timedmedia-format-type}}\n{{Identical|Video}}",
+ "timedmedia-ogg-videos": "Number of Ogg videos on [[Special:TimedMediaHandler]]. Parameters:\n* $1 - number of videos\n{{Related|Timedmedia-format-type}}",
+ "timedmedia-webm-videos": "Number of WebM videos on [[Special:TimedMediaHandler]]. Parameters:\n* $1 - number of videos\n{{Related|Timedmedia-format-type}}",
+ "timedmedia-derivative-state-transcodes": "Number of transcodes. Parameters:\n* $1 - number of transcodes",
+ "timedmedia-derivative-state-active": "currently active transcoes\nParameters are:\n* $1 number of transcodes",
+ "timedmedia-derivative-state-queued": "queued transcode jobs\nParameters are:\n* $1 number of transcodes",
+ "timedmedia-derivative-state-failed": "failed transcode jobs\nParameters are:\n* $1 number of transcodes",
+ "timedmedia-file": "Used as table column header.\n{{Identical|File}}",
+ "timedmedia-audios": "Number of audio files on [[Special:TimedMediaHandler]]. Parameters:\n* $1 - number of audio files\n{{Related|Timedmedia-format-type}}",
+ "timedmedia-ogg-audios": "Number of ogg audio files, displayed on [[Special:TimedMediaHandler]]. Parameters:\n* $1 - the number of files\n{{Related|Timedmedia-format-type}}",
+ "timedmedia-flac-audios": "Number of FLAC audio files, displayed on [[Special:TimedMediaHandler]]. Parameters:\n* $1 - the number of files\n{{Related|Timedmedia-format-type}}",
+ "timedmedia-wav-audios": "Number of WAV audio files, displayed on [[Special:TimedMediaHandler]]. Parameters:\n* $1 - the number of files\n{{Related|Timedmedia-format-type}}",
+ "right-transcode-reset": "{{doc-right|transcode-reset}}",
+ "right-transcode-status": "{{doc-right|transcode-status}}",
+ "action-transcode-status": "{{doc-action|transcode-status}}",
+ "orphanedtimedtext": "{{doc-special|OrphanedTimedText}}",
+ "orphanedtimedtext-summary": "Summary of Special:OrphanedTimedText.",
+ "orphanedtimedtext-unsupported": "Shown if Special:OrphanedTimedText isn't supported for the current database back-end.",
+ "orphanedtimedtext-notimedtext": "Shown on Special:OrphanedTimedText if the TimedText namespace is disabled on that wiki (i.e. $wgEnableLocalTimedText is set to false). Note, do not use <nowiki>{{ns:TimedText}}</nowiki> in this message.",
+ "apihelp-query+transcodestatus-description": "{{doc-apihelp-description|query+transcodestatus}}",
+ "apihelp-query+transcodestatus-example-1": "{{doc-apihelp-example|query+transcodestatus}}",
+ "apihelp-query+videoinfo-description": "{{doc-apihelp-description|query+videoinfo}}",
+ "apihelp-query+videoinfo-param-prop": "{{doc-apihelp-param|query+videoinfo|prop}}",
+ "apihelp-query+videoinfo-example-1": "{{doc-apihelp-example|query+videoinfo}}",
+ "apihelp-transcodereset-description": "{{doc-apihelp-description|transcodereset}}",
+ "apihelp-transcodereset-param-title": "{{doc-apihelp-param|transcodereset|title}}",
+ "apihelp-transcodereset-param-transcodekey": "{{doc-apihelp-param|transcodereset|transcodekey}}",
+ "apihelp-transcodereset-example-1": "{{doc-apihelp-example|transcodereset}}",
+ "apihelp-transcodereset-example-2": "{{doc-apihelp-example|transcodereset}}"
+}
diff --git a/extensions/TimedMediaHandler/i18n/qu.json b/extensions/TimedMediaHandler/i18n/qu.json
new file mode 100644
index 00000000..4942568f
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/qu.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "AlimanRuna"
+ ]
+ },
+ "timedmedia-no-player-js": "Way way, wamp'unaykipiqa JavaScript nisqaman ama nisqam icha q'imisqa purichiq manam kanchu.<br />\n<a href=\"$1\">Widyuta chaqnamuyta</a> icha <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">purichiqta chaqnamuyta</a> atinki widyuta wamp'unaykipi purichinaykipaq.",
+ "timedmedia-more": "Astawan...",
+ "timedmedia-dismiss": "Wichq'ay",
+ "timedmedia-download": "WillaƱiqita chaqnamuy",
+ "timedmedia-desc-link": "Kay willaƱiqimanta",
+ "timedmedia-source-file": "$1 pukyu",
+ "timedmedia-source-audio-file-desc": "Qallariy $1 willaƱiqi ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ro.json b/extensions/TimedMediaHandler/i18n/ro.json
new file mode 100644
index 00000000..4162d861
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ro.json
@@ -0,0 +1,93 @@
+{
+ "@metadata": {
+ "authors": [
+ "Firilacroco",
+ "KlaudiuMihaila",
+ "Mihai",
+ "Minisarm",
+ "Stelistcristi",
+ "ImGelu"
+ ]
+ },
+ "timedmedia-desc": "Gestionar pentru fișiere audio, video și subtitrări sincronizate, cu suport pentru formatele WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "fișier audio ogg $1, $2",
+ "timedmedia-ogg-short-video": "fișier video ogg $1, $2",
+ "timedmedia-ogg-short-general": "fișier media ogg $1, $2",
+ "timedmedia-ogg-long-audio": "fișier audio ogg $1, lungime $2, $3",
+ "timedmedia-ogg-long-video": "fișier video ogg $1, lungime $2, $4Ɨ$5 pixeli, $3",
+ "timedmedia-ogg-long-multiplexed": "fișier multiplexat audio/video ogg, $1, lungime $2, $4Ɨ$5 pixeli, $3",
+ "timedmedia-ogg-long-general": "fișier media ogg, lungime $2, $3",
+ "timedmedia-ogg-long-error": "fișier ogg incorect: $1",
+ "timedmedia-webm-short-video": "fișier video WebM $1, $2",
+ "timedmedia-webm-long-video": "fișier audio/video WebM, $1, lungime $2, $4 Ɨ $5 pixeli, $3 per ansamblu",
+ "timedmedia-flac-short-audio": "fișier audio FLAC, $1",
+ "timedmedia-flac-long-audio": "fișier audio FLAC, lungime $1, $2 per ansmablu",
+ "timedmedia-mp4-short-video": "fișier video MP4 $1, $2",
+ "timedmedia-mp4-long-video": "fișier audio/video MP4, $1, lungime $2, $4 Ɨ $5 pixeli, $3 per ansamblu",
+ "timedmedia-no-player-js": "Ne pare rău, Ć®nsă navigatorul dumneavoastră fie are JavaScript dezactivat, fie nu conține niciun player suportat.<br />\nPuteți <a href=\"$1\">descărca clipul</a> sau puteți <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">descărca un player</a> pentru a-l reda direct Ć®n navigator.",
+ "timedmedia-more": "Mai multā€¦",
+ "timedmedia-dismiss": "Ǝnchide",
+ "timedmedia-download": "Descarcă fișierul",
+ "timedmedia-play-media": "Redă fișierul media",
+ "timedmedia-desc-link": "Despre acest fișier",
+ "timedmedia-oggThumb-version": "OggHandler necesită oggThumb, versiunea $1 sau mai recentă.",
+ "timedmedia-oggThumb-failed": "oggThumb nu a reușit să creeze miniatura.",
+ "timedmedia-status-header": "Starea codificării",
+ "timedmedia-update-status": "Actualizează starea codificării",
+ "timedmedia-status": "Stare",
+ "timedmedia-status-unknown": "Stare necunoscută",
+ "timedmedia-transcodebitrate": "Rată de bit",
+ "timedmedia-transcodeinfo": "Format",
+ "timedmedia-actions": "Acțiuni",
+ "timedmedia-direct-link": "Descarcă",
+ "timedmedia-not-ready": "Nu este gata",
+ "timedmedia-completed-on": "Finalizat $1",
+ "timedmedia-error-on": "Eroare la $1",
+ "timedmedia-started-transcode": "Pornită acum $1. $2",
+ "timedmedia-percent-done": "Aproximativ $1% finalizat",
+ "timedmedia-in-job-queue": "Adăugat la șirul de sarcini acum $1",
+ "timedmedia-unknown-target-size": "Dimensiune finală necunoscută, $1 codificați",
+ "timedmedia-days": "{{PLURAL:$1|o zi|$1 zile|$1 de zile}}",
+ "timedmedia-hours": "{{PLURAL:$1|o oră|$1 ore|$1 de ore}}",
+ "timedmedia-minutes": "{{PLURAL:$1|un minut|$1 minute|$1 de minute}}",
+ "timedmedia-seconds": "{{PLURAL:$1|o secundă|$1 secunde|$1 de secunde}}",
+ "timedmedia-reset": "Reinițializează codificarea",
+ "timedmedia-reset-confirm": "Reinițializarea acestei codificări va elimina orice fișier existent (dacă există) și va readăuga codificarea la șirul de sarcini. Va dura ceva timp pentru a recodifica. <br /><br />\nSunteți sigur că doriți să continuați?",
+ "timedmedia-reset-error": "Eroare la reinițializarea codificării.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Sursă $1",
+ "timedmedia-source-file-desc": "Fișier $1 original, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Fișier $1 original ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Videoclip Ogg cu lățime de bandă mică (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Videoclip Ogg pentru redare pe web (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Videoclip Ogg pentru redare pe web (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Videoclip Ogg descărcabil, de Ʈnaltă calitate (720P)",
+ "timedmedia-derivative-desc-160p.webm": "WebM pentru redare pe web (160P)",
+ "timedmedia-derivative-desc-360p.webm": "WebM pentru redare pe web (360P)",
+ "timedmedia-derivative-desc-480p.webm": "WebM pentru redare pe web (480P)",
+ "timedmedia-derivative-desc-720p.webm": "WebM descărcabil, de Ʈnaltă calitate (720P)",
+ "timedmedia-derivative-480p.vp9.webm": "VP9 480P",
+ "timedmedia-derivative-desc-320p.mp4": "MP4 prietenos cu dispozitivele (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "MP4 pentru redare pe web (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 de calitate HD (720P)",
+ "timedmedia-subtitle-new": "Creare traducere nouă sau modificare una existentă",
+ "timedmedia-subtitle-new-desc": "Alegeți limba și apăsați butonul '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Du-te",
+ "timedmedia-subtitle-language": "Subtitrare Ʈn $1 ($2)",
+ "timedmedia-subtitle-no-video": "Nu există niciun videoclip asociat cu pagina curentă de subtitrare",
+ "timedmedia-subtitle-no-subtitles": "Nu există Ć®n acest moment subtitrări Ć®n limba $1 pentru acest videoclip. Puteți [{{fullurl:{{FULLPAGENAME}}|action=edit}} modifica această pagină] pentru a le adăuga.",
+ "timedmedia-subtitle-remote": "Subtitrarea sincronizată a acestui fișier este găzduită la $1",
+ "timedmedia-subtitle-remote-link": "Puteți [$1 vizualiza pagina descriptivă] a acestui fișier la $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 videoclip|$1 videoclipuri|$1 de videoclipuri}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 videoclip Ogg|$1 videoclipuri Ogg|$1 de videoclipuri Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 videoclip WebM|$1 videoclipuri WebM|$1 de videoclipuri WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 codificare|$1 codificări|$1 de codificări}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 codificare Ʈn curs|$1 codificări Ʈn curs|$1 de codificări Ʈn curs}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 codificare Ć®n așteptare|$1 codificări Ć®n așteptare|$1 de codificări Ć®n așteptare}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 codificare eșuată|$1 codificări eșuate|$1 de codificări eșuate}}",
+ "timedmedia-file": "Fișier",
+ "right-transcode-reset": "Reinițializează videoclipuri nereușit codificate pentru ca acestea să fie readăugate la șirul de sarcini.",
+ "right-transcode-status": "Vizualizează [[Special:TimedMediaHandler|informații despre activitatea curentă de codificare]]",
+ "action-transcode-status": "vizualizați statutul actual al codificării"
+}
diff --git a/extensions/TimedMediaHandler/i18n/roa-tara.json b/extensions/TimedMediaHandler/i18n/roa-tara.json
new file mode 100644
index 00000000..a972d6b7
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/roa-tara.json
@@ -0,0 +1,91 @@
+{
+ "@metadata": {
+ "authors": [
+ "Joetaras"
+ ]
+ },
+ "timedmedia-desc": "Gestore pe le file audio, video e teste temporizzate, cu le formate supportate pe WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "File audie Ogg $1, $2",
+ "timedmedia-ogg-short-video": "File video Ogg $1, $2",
+ "timedmedia-ogg-short-general": "File media Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "File audie Ogg $1, lunghezze $2, $3",
+ "timedmedia-ogg-long-video": "File video Ogg $1, lunghezze $2, $4 x $5 pixel, $3",
+ "timedmedia-ogg-long-multiplexed": "File multiplexed audie e video Ogg $1, lunghezze $2, $4 x $5 pixel, $3 in totale",
+ "timedmedia-ogg-long-general": "File media Ogg, lunghezze $2, $3",
+ "timedmedia-ogg-long-error": "Ogg file invalide: $1",
+ "timedmedia-webm-short-video": "WebM $1 file video, $2",
+ "timedmedia-webm-long-video": "File WebM audio/video, $1, lunghezze $2, $4 Ɨ $5 pixel, $3 in totale",
+ "timedmedia-flac-short-audio": "File audio FLAC, $1",
+ "timedmedia-flac-long-audio": "File audio FLAC, lunghezze $1, in totale $2",
+ "timedmedia-wav-short-audio": "File audio WAV, $1",
+ "timedmedia-wav-long-audio": "File audio WAV, lunghezze $1, in totale $2",
+ "timedmedia-wav-pcm-required": "Tu puĆØ sulamende carecĆ  WAV de tipe PCM (Codece de Modulazione Pulsate).",
+ "timedmedia-mp4-short-video": "MP4 $1 file video, $2",
+ "timedmedia-mp4-long-video": "File MP4 audio/video, $1, lunghezze $2, $4 Ɨ $5 pixel, $3 in totale",
+ "timedmedia-no-player-js": "Ne dispiace, 'u browser tune tĆØne 'u JavaScript disabbilitate o non ge tĆØne 'n'esecutore supportate.<br />\nTu puĆØ <a href=\"$1\">scarecĆ  'u video</a> o <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">scarecĆ  'n'esecutore</a> pe 'ndrucĆ  'u video sus a 'u browser tune.",
+ "timedmedia-more": "De cchiĆ¹...",
+ "timedmedia-dismiss": "Chiude",
+ "timedmedia-download": "Scareche stu file",
+ "timedmedia-play-media": "Esegue 'u media",
+ "timedmedia-desc-link": "'Mbormaziune sus a stu file",
+ "timedmedia-oggThumb-version": "OggHandler vole 'a versine de oggThumb $1 o cchiĆ¹ ierte.",
+ "timedmedia-oggThumb-failed": "oggThumn ha fallite a ccrejĆ  le miniature.",
+ "timedmedia-status-header": "State d'a codifeche",
+ "timedmedia-update-status": "Aggiorne 'u state d'a codifeche",
+ "timedmedia-status": "State",
+ "timedmedia-status-unknown": "State scanusciute",
+ "timedmedia-transcodebitrate": "Bitrate",
+ "timedmedia-transcodeduration": "Tiembe de codifiche",
+ "timedmedia-transcodeinfo": "Formate",
+ "timedmedia-actions": "Aziune",
+ "timedmedia-direct-link": "Scareche",
+ "timedmedia-not-ready": "Non g'ĆØ pronde",
+ "timedmedia-completed-on": "Combletate $1",
+ "timedmedia-error-on": "Errore sus a $1",
+ "timedmedia-started-transcode": "Accumenzate $1 fĆ . $2",
+ "timedmedia-percent-done": "CchiĆ¹ o mene $1% fatte",
+ "timedmedia-in-job-queue": "Aggiunde a 'a FatƬe in code $1 fƠ",
+ "timedmedia-unknown-target-size": "Dimenzione d'a destinazione scanusciute, $1 codificate",
+ "timedmedia-days": "{{PLURAL:$1|1 sciurne|$1 sciurne}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 ore|$1 ore}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minute|$1 minute}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 seconde|$1 seconde}}",
+ "timedmedia-reset": "Azzere 'a transcodifeche",
+ "timedmedia-reset-confirm": "Stoche azzere sta transcodifiche ca adda luĆ  ogne file esistende (ce presende), e pĆ² aggiunge 'a transcodifiche jndr'Ć  code d'a fatƬe. CchiĆ¹ vote accumenze 'a transcodifiche. <br /><br />\nSƬ secure ca vuĆØ ccu vvĆØ nnande?",
+ "timedmedia-reset-error": "Errore mendre ste azzerave 'a fatƬe de transcodifiche.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 sorgende",
+ "timedmedia-source-file-desc": "File origgenale $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "File origgenale $1 ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Ogg video cu banda vasce (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Ogg video cu streaming web (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Ogg video cu streaming web (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Ogg video de qualitate ierte scarecabbele (720P)",
+ "timedmedia-derivative-desc-160p.webm": "Flusse web WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "Flusse web WebM (360P)",
+ "timedmedia-derivative-desc-480p.webm": "Flusse web WebM (480P)",
+ "timedmedia-derivative-desc-720p.webm": "WebM de qualitate ierte scarecabbele (720P)",
+ "timedmedia-derivative-desc-320p.mp4": "Dispositive-amiche MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "Streaming web MP4 (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "Qualitate HD MP4 (720P)",
+ "timedmedia-subtitle-new": "Ccreje 'na traduziona nove o ne cange une esistende",
+ "timedmedia-subtitle-new-desc": "Scacchie 'na lĆØnghe e cazze 'u buttone '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "VĆ©je",
+ "timedmedia-subtitle-language": "$1 ($2) sottotitele",
+ "timedmedia-subtitle-no-video": "Non ge stonne video associate cu 'u sottotitole d'a pĆ gene de mĆ²",
+ "timedmedia-subtitle-no-subtitles": "Non ge stonne sottotitole pe mĆ² jndr'Ć  $1 pe stu video, tu puĆØ [{{fullurl:{{FULLPAGENAME}}|action=edit}} cangiĆ  sta pĆ gene] o aggiungerle",
+ "timedmedia-subtitle-remote": "'U teste temborizzate pe stu file jĆØ ospitate sus a $1",
+ "timedmedia-subtitle-remote-link": "Tu puĆØ [$1 'ndrucĆ  'a pĆ gene de descrizione] pe stu file sus a $2",
+ "timedmediahandler": "Gestore TimedMedia",
+ "timedmedia-videos": "{{PLURAL:$1|$1 video}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Video Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 Video WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transcodifiche}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 transcodifiche in esecuzione}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 transcodifiche in code}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 transcodifiche fallite}}",
+ "timedmedia-file": "File",
+ "right-transcode-reset": "Azzeramende fallite o le video transcodificate onne state sckaffate cchiĆ¹ de 'na vote jndr'Ć  code d'a fatƬe.",
+ "right-transcode-status": "'Ndruche [[Special:TimedMediaHandler|le 'mbormaziune sus a l'attivitĆ  de transcodifiche de mĆ²]]",
+ "action-transcode-status": "'ndruche 'u state de mĆ² d'a transcodifeche"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ru.json b/extensions/TimedMediaHandler/i18n/ru.json
new file mode 100644
index 00000000..d4bf8e64
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ru.json
@@ -0,0 +1,111 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ahonc",
+ "Amire80",
+ "Eleferen",
+ "Kaganer",
+ "Kalan",
+ "Kv75",
+ "MaxSem",
+ "Okras",
+ "ŠŠ»ŠµŠŗсŠ°Š½Š“р Š”ŠøŠ³Š°Ń‡Ń‘Š²",
+ "NBS"
+ ]
+ },
+ "timedmedia-desc": "ŠžŠ±Ń€Š°Š±Š¾Ń‚чŠøŠŗ Š“Š»Ń Š°ŃƒŠ“ŠøŠ¾, Š²ŠøŠ“ŠµŠ¾ Šø суŠ±Ń‚ŠøтрŠ¾Š², с ŠæŠ¾Š“Š“ŠµŃ€Š¶ŠŗŠ¾Š¹ фŠ¾Ń€Š¼Š°Ń‚Š¾Š²: WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Š—Š²ŃƒŠŗŠ¾Š²Š¾Š¹ фŠ°Š¹Š» Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Š’ŠøŠ“ŠµŠ¾-фŠ°Š¹Š» Ogg $1, $2",
+ "timedmedia-ogg-short-general": "ŠœŠµŠ“ŠøŠ°Ń„Š°Š¹Š» Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Š—Š²ŃƒŠŗŠ¾Š²Š¾Š¹ фŠ°Š¹Š» Ogg $1, Š“Š»ŠøтŠµŠ»ŃŒŠ½Š¾ŃŃ‚ŃŒ $2, $3",
+ "timedmedia-ogg-long-video": "Š²ŠøŠ“ŠµŠ¾-фŠ°Š¹Š» Ogg $1, Š“Š»ŠøтŠµŠ»ŃŒŠ½Š¾ŃŃ‚ŃŒ $2, $4 Ɨ $5 {{PLURAL:$5|ŠæŠøŠŗсŠµŠ»ŃŒ|ŠæŠøŠŗсŠµŠ»Ń|ŠæŠøŠŗсŠµŠ»ŠµŠ¹}}, $3",
+ "timedmedia-ogg-long-multiplexed": "Š¼ŃƒŠ»ŃŒŃ‚ŠøŠæŠ»ŠµŠŗсŠ½Ń‹Š¹ Š°ŃƒŠ“ŠøŠ¾/Š²ŠøŠ“ŠµŠ¾Ń„Š°Š¹Š» Ogg, $1, Š“Š»ŠøтŠµŠ»ŃŒŠ½Š¾ŃŃ‚ŃŒ $2, $4 Ɨ $5 {{PLURAL:$5|ŠæŠøŠŗсŠµŠ»ŃŒ|ŠæŠøŠŗсŠµŠ»Ń|ŠæŠøŠŗсŠµŠ»ŠµŠ¹}}, $3 Š²ŃŠµŠ³Š¾",
+ "timedmedia-ogg-long-general": "Š¼ŠµŠ“ŠøŠ°Ń„Š°Š¹Š» Ogg, Š“Š»ŠøтŠµŠ»ŃŒŠ½Š¾ŃŃ‚ŃŒ $2, $3",
+ "timedmedia-ogg-long-error": "Š½ŠµŠæрŠ°Š²ŠøŠ»ŃŒŠ½Ń‹Š¹ Ogg-фŠ°Š¹Š»: $1",
+ "timedmedia-ogg-long-no-streams": "ŠœŃƒŠ»ŃŒŃ‚ŠøŠ¼ŠµŠ“ŠøŠ°-фŠ°Š¹Š» ogg. ŠŸŃ€ŠµŠ“уŠæрŠµŠ¶Š“ŠµŠ½ŠøŠµ: ŠŠø Š¾Š“ŠøŠ½ ŠøŠ· ŠŗŠ¾Š“ŠµŠŗŠ¾Š², ŠøсŠæŠ¾Š»ŃŒŠ·ŃƒŠµŠ¼Ń‹Ń… Š² этŠ¾Š¼ фŠ°Š¹Š»Šµ, Š½Šµ Š¾ŠæрŠµŠ“ŠµŠ»Ń‘Š½.",
+ "timedmedia-webm-short-video": "WebM $1 Š²ŠøŠ“ŠµŠ¾-фŠ°Š¹Š», $2",
+ "timedmedia-webm-long-video": "WebM Š°ŃƒŠ“ŠøŠ¾/Š²ŠøŠ“ŠµŠ¾ фŠ°Š¹Š», $1, ŠæрŠ¾Š“Š¾Š»Š¶ŠøтŠµŠ»ŃŒŠ½Š¾ŃŃ‚ŃŒ $2, $4 Ɨ $5 {{PLURAL:$5|ŠæŠøŠŗсŠµŠ»ŃŒ|ŠæŠøŠŗсŠµŠ»Ń|ŠæŠøŠŗсŠµŠ»ŠµŠ¹}}, Š²ŃŠµŠ³Š¾ $3",
+ "timedmedia-flac-short-audio": "ŠŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š» FLAC, $1",
+ "timedmedia-flac-long-audio": "ŠŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š» FLAC, Š“Š»ŠøŠ½Š° ā€” $1, Š±ŠøтрŠµŠ¹Ń‚ ā€” $2",
+ "timedmedia-wav-short-audio": "ŠŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š» WAV, $1",
+ "timedmedia-wav-long-audio": "ŠŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š» WAV, Š“Š»ŠøŠ½Š° ā€” $1, Š±ŠøтрŠµŠ¹Ń‚ ā€” $2",
+ "timedmedia-wav-pcm-required": "Š’Ń‹ Š¼Š¾Š¶ŠµŃ‚Šµ Š·Š°Š³Ń€ŃƒŠ·Šøть тŠ¾Š»ŃŒŠŗŠ¾ PCM (Pulse Code Modulation) WAV.",
+ "timedmedia-mp4-short-video": "MP4 $1 Š²ŠøŠ“ŠµŠ¾-фŠ°Š¹Š», $2",
+ "timedmedia-mp4-long-video": "ŠŃƒŠ“ŠøŠ¾/Š²ŠøŠ“ŠµŠ¾Ń„Š°Š¹Š» MP4 $1, Š“Š»ŠøŠ½Š° ā€” $2, $4 Ɨ $5 ŠæŠøŠŗсŠµŠ»ŠµŠ¹, Š±ŠøтрŠµŠ¹Ń‚ ā€” $3",
+ "timedmedia-no-player-js": "Šš сŠ¾Š¶Š°Š»ŠµŠ½Šøю, Š² Š²Š°ŃˆŠµŠ¼ Š±Ń€Š°ŃƒŠ·ŠµŃ€Šµ Š¾Ń‚ŠŗŠ»ŃŽŃ‡Ń‘Š½ JavaScript, ŠøŠ»Šø Š½Šµ ŠøŠ¼ŠµŠµŃ‚ся трŠµŠ±ŃƒŠµŠ¼Š¾Š³Š¾ ŠæрŠ¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»Ń.<br />\nŠ’Ń‹ Š¼Š¾Š¶ŠµŃ‚Šµ <a href=\"$1\">Š·Š°Š³Ń€ŃƒŠ·Šøть рŠ¾Š»ŠøŠŗ</a> ŠøŠ»Šø <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">Š·Š°Š³Ń€ŃƒŠ·Šøть ŠæрŠ¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»ŃŒ</a> Š“Š»Ń Š²Š¾ŃŠæрŠ¾ŠøŠ·Š²ŠµŠ“ŠµŠ½Šøя рŠ¾Š»ŠøŠŗŠ° Š² Š±Ń€Š°ŃƒŠ·ŠµŃ€Šµ.",
+ "timedmedia-more": "Š‘Š¾Š»ŃŒŃˆŠµā€¦",
+ "timedmedia-dismiss": "Š”Šŗрыть",
+ "timedmedia-download": "Š—Š°Š³Ń€ŃƒŠ·Šøть фŠ°Š¹Š»",
+ "timedmedia-play-media": "Š’Š¾ŃŠæрŠ¾ŠøŠ·Š²ŠµŃŃ‚Šø Š¼ŠµŠ“ŠøŠ°Ń„Š°Š¹Š»",
+ "timedmedia-desc-link": "Š˜Š½Ń„Š¾Ń€Š¼Š°Ń†Šøя Š¾Š± этŠ¾Š¼ фŠ°Š¹Š»Šµ",
+ "timedmedia-oggThumb-version": "OggHandler трŠµŠ±ŃƒŠµŃ‚ oggThumb Š²ŠµŃ€ŃŠøŠø $1 ŠøŠ»Šø Š±Š¾Š»ŠµŠµ ŠæŠ¾Š·Š“Š½ŠµŠ¹.",
+ "timedmedia-oggThumb-failed": "oggThumb Š½Šµ уŠ“Š°Š»Š¾ŃŃŒ сŠ¾Š·Š“Š°Ń‚ŃŒ Š¼ŠøŠ½ŠøŠ°Ń‚ŃŽŃ€Ńƒ.",
+ "timedmedia-status-header": "Š”Š¾ŃŃ‚Š¾ŃŠ½ŠøŠµ Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½Šøя",
+ "timedmedia-update-status": "ŠžŠ±Š½Š¾Š²Šøть стŠ°Ń‚ŃƒŃ Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½Šøя",
+ "timedmedia-status": "Š”Š¾ŃŃ‚Š¾ŃŠ½ŠøŠµ",
+ "timedmedia-status-unknown": "ŠŠµŠøŠ·Š²ŠµŃŃ‚Š½Š¾Šµ сŠ¾ŃŃ‚Š¾ŃŠ½ŠøŠµ",
+ "timedmedia-transcodeinfo": "Š¤Š¾Ń€Š¼Š°Ń‚",
+ "timedmedia-actions": "Š”ŠµŠ¹ŃŃ‚Š²Šøя",
+ "timedmedia-direct-link": "Š”ŠŗŠ°Ń‡Š°Ń‚ŃŒ",
+ "timedmedia-not-ready": "ŠŠµ Š³Š¾Ń‚Š¾Š²",
+ "timedmedia-completed-on": "Š—Š°Š²ŠµŃ€ŃˆŠµŠ½Š¾ $1",
+ "timedmedia-error-on": "ŠžŃˆŠøŠ±ŠŗŠ° $1",
+ "timedmedia-started-transcode": "Š—Š°ŠæущŠµŠ½Š¾ $1 Š½Š°Š·Š°Š“. $2",
+ "timedmedia-percent-done": "ŠŸŃ€ŠøŠ¼ŠµŃ€Š½Š¾ $1% Š²Ń‹ŠæŠ¾Š»Š½ŠµŠ½Š¾",
+ "timedmedia-in-job-queue": "Š”Š¾Š±Š°Š²Š»ŠµŠ½Š¾ Š² Š¾Ń‡ŠµŃ€ŠµŠ“ь Š·Š°Š“Š°Š½ŠøŠ¹ $1 Š½Š°Š·Š°Š“",
+ "timedmedia-unknown-target-size": "ŠŠµŠøŠ·Š²ŠµŃŃ‚Š½Ń‹Š¹ цŠµŠ»ŠµŠ²Š¾Š¹ рŠ°Š·Š¼ŠµŃ€, $1 ŠæрŠø ŠŗŠ¾Š“ŠøрŠ¾Š²ŠŗŠµ",
+ "timedmedia-days": "{{PLURAL:$1|$1 Š“ŠµŠ½ŃŒ|$1 Š“Š½Ń|$1 Š“Š½ŠµŠ¹}}",
+ "timedmedia-hours": "{{PLURAL:$1|$1 чŠ°Ń|$1 чŠ°ŃŠ°|$1 чŠ°ŃŠ¾Š²}}",
+ "timedmedia-minutes": "{{PLURAL:$1|$1 Š¼ŠøŠ½ŃƒŃ‚Š°|$1 Š¼ŠøŠ½ŃƒŃ‚Ń‹|$1 Š¼ŠøŠ½ŃƒŃ‚}}",
+ "timedmedia-seconds": "{{PLURAL:$1|$1 сŠµŠŗуŠ½Š“Š°|$1 сŠµŠŗуŠ½Š“ы|$1 сŠµŠŗуŠ½Š“}}",
+ "timedmedia-reset": "ŠŸŠµŃ€ŠµŠ·Š°ŠæусŠŗ Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½Šøя",
+ "timedmedia-reset-confirm": "ŠŸŠµŃ€ŠµŠ·Š°ŠæусŠŗ Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½Šøя уŠ“Š°Š»Šøт сущŠµŃŃ‚Š²ŃƒŃŽŃ‰ŠøŠ¹ фŠ°Š¹Š» (ŠµŃŠ»Šø Š¾Š½ сущŠµŃŃ‚Š²ŃƒŠµŃ‚), Šø Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½ŠøŠµ Š²Š½Š¾Š²ŃŒ Š±ŃƒŠ“ŠµŃ‚ Š“Š¾Š±Š°Š²Š»ŠµŠ½Š¾ Š² Š¾Ń‡ŠµŃ€ŠµŠ“ь Š·Š°Š“Š°Š½ŠøŠ¹. ŠŸŠ¾Š²Ń‚Š¾Ń€Š½Š¾Šµ Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½ŠøŠµ Š·Š°Š¹Š¼ŠµŃ‚ Š½ŠµŠŗŠ¾Ń‚Š¾Ń€Š¾Šµ Š²Ń€ŠµŠ¼Ń. <br /><br />\nŠ’Ń‹ уŠ²ŠµŃ€ŠµŠ½Ń‹, чтŠ¾ хŠ¾Ń‚ŠøтŠµ ŠæрŠ¾Š“Š¾Š»Š¶Šøть?",
+ "timedmedia-reset-error": "ŠžŃˆŠøŠ±ŠŗŠ° ŠæрŠø ŠæŠµŃ€ŠµŠ·Š°ŠæусŠŗŠµ Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½Šøя.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Š˜ŃŃ‚Š¾Ń‡Š½ŠøŠŗ $1",
+ "timedmedia-source-file-desc": "ŠžŃ€ŠøŠ³ŠøŠ½Š°Š» $1 фŠ°Š¹Š»Š°, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "ŠžŃ€ŠøŠ³ŠøŠ½Š°Š»ŃŒŠ½Ń‹Š¹ $1-фŠ°Š¹Š» ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Ogg-Š²ŠøŠ“ŠµŠ¾ Š½ŠøŠ·ŠŗŠ¾Š³Š¾ ŠŗŠ°Ń‡ŠµŃŃ‚Š²Š° (160p)",
+ "timedmedia-derivative-desc-360p.ogv": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Š¾Šµ Ogg-Š²ŠøŠ“ŠµŠ¾ (360p)",
+ "timedmedia-derivative-desc-480p.ogv": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Š¾Šµ Ogg-Š²ŠøŠ“ŠµŠ¾ (480p)",
+ "timedmedia-derivative-desc-720p.ogv": "Ogg-Š²ŠøŠ“ŠµŠ¾ Š²Ń‹ŃŠ¾ŠŗŠ¾Š³Š¾ ŠŗŠ°Ń‡ŠµŃŃ‚Š²Š° (720p)",
+ "timedmedia-derivative-desc-1080p.ogv": "Š”ŠŗŠ°Ń‡ŠøŠ²Š°ŠµŠ¼Š¾Šµ Ogg-Š²ŠøŠ“ŠµŠ¾ Š² фŠ¾Ń€Š¼Š°Ń‚Šµ Full HD (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Š¾Šµ WebM-Š²ŠøŠ“ŠµŠ¾ (160p)",
+ "timedmedia-derivative-desc-360p.webm": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Š¾Šµ WebM-Š²ŠøŠ“ŠµŠ¾ (360p)",
+ "timedmedia-derivative-desc-480p.webm": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Š¾Šµ WebM-Š²ŠøŠ“ŠµŠ¾ (480p)",
+ "timedmedia-derivative-desc-720p.webm": "WebM-Š²ŠøŠ“ŠµŠ¾ Š²Ń‹ŃŠ¾ŠŗŠ¾Š³Š¾ ŠŗŠ°Ń‡ŠµŃŃ‚Š²Š° (720p)",
+ "timedmedia-derivative-desc-1080p.webm": "Š”ŠŗŠ°Ń‡ŠøŠ²Š°ŠµŠ¼Š¾Šµ WebM-Š²ŠøŠ“ŠµŠ¾ Š² фŠ¾Ń€Š¼Š°Ń‚Šµ Full HD (1080P)",
+ "timedmedia-derivative-desc-320p.mp4": "ŠŠ“Š°ŠæтŠøрŠ¾Š²Š°Š½Š½Ń‹Š¹ Š“Š»Ń устрŠ¾Š¹ŃŃ‚Š²Š° MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Š¾Šµ MP4-Š²ŠøŠ“ŠµŠ¾ (480p)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 Š² HD-ŠŗŠ°Ń‡ŠµŃŃ‚Š²Šµ (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "MP4-Š²ŠøŠ“ŠµŠ¾ Š² фŠ¾Ń€Š¼Š°Ń‚Šµ Full HD (1080P)",
+ "timedmedia-subtitle-new": "Š”Š¾Š·Š“Š°Ń‚ŃŒ Š½Š¾Š²Ń‹Š¹ ŠæŠµŃ€ŠµŠ²Š¾Š“ ŠøŠ»Šø рŠµŠ“Š°ŠŗтŠøрŠ¾Š²Š°Ń‚ŃŒ сущŠµŃŃ‚Š²ŃƒŃŽŃ‰ŠøŠ¹",
+ "timedmedia-subtitle-new-desc": "Š’Ń‹Š±ŠµŃ€ŠøтŠµ яŠ·Ń‹Šŗ Šø Š½Š°Š¶Š¼ŠøтŠµ ŠŗŠ½Š¾ŠæŠŗу '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Š’Ń‹ŠæŠ¾Š»Š½Šøть",
+ "timedmedia-subtitle-language": "$1 ($2) суŠ±Ń‚Šøтры",
+ "timedmedia-subtitle-no-video": "ŠŠµŃ‚ Š²ŠøŠ“ŠµŠ¾, сŠ²ŃŠ·Š°Š½Š½Š¾Š³Š¾ с тŠµŠŗущŠµŠ¹ стрŠ°Š½ŠøцŠµŠ¹ суŠ±Ń‚ŠøтрŠ¾Š²",
+ "timedmedia-subtitle-no-subtitles": "Š’ Š½Š°ŃŃ‚Š¾ŃŃ‰ŠµŠµ Š²Ń€ŠµŠ¼Ń Š½ŠµŃ‚ суŠ±Ń‚ŠøтрŠ¾Š² Š½Š° $1 Š“Š»Ń этŠ¾Š³Š¾ Š²ŠøŠ“ŠµŠ¾, Š’Ń‹ Š¼Š¾Š¶ŠµŃ‚Šµ [{{fullurl:{{FULLPAGENAME}}|action=edit}} ŠøŠ·Š¼ŠµŠ½Šøть эту стрŠ°Š½Šøцу] Š“Š»Ń Šøх Š“Š¾Š±Š°Š²Š»ŠµŠ½Šøя",
+ "timedmedia-subtitle-remote": "Š”уŠ±Ń‚Šøтры Š“Š»Ń этŠ¾Š³Š¾ фŠ°Š¹Š»Š° рŠ°Š·Š¼ŠµŃ‰ŠµŠ½Ń‹ Š½Š° $1",
+ "timedmedia-subtitle-remote-link": "Š’Ń‹ Š¼Š¾Š¶ŠµŃ‚Šµ [$1 ŠæŠ¾ŃŠ¼Š¾Ń‚Ń€ŠµŃ‚ŃŒ стрŠ°Š½Šøцу Š¾ŠæŠøсŠ°Š½Šøя] этŠ¾Š³Š¾ фŠ°Š¹Š»Š° Š½Š° $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "$1 Š²ŠøŠ“ŠµŠ¾{{PLURAL:$1|фŠ°Š¹Š»|фŠ°Š¹Š»Š°|фŠ°Š¹Š»Š¾Š²}}",
+ "timedmedia-ogg-videos": "$1 Ogg Š²ŠøŠ“ŠµŠ¾{{PLURAL:$1|фŠ°Š¹Š»|фŠ°Š¹Š»Š°|фŠ°Š¹Š»Š¾Š²}}",
+ "timedmedia-webm-videos": "$1 WebM Š²ŠøŠ“ŠµŠ¾{{PLURAL:$1|фŠ°Š¹Š»|фŠ°Š¹Š»Š°|фŠ°Š¹Š»Š¾Š²}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½ŠøŠµ|$1 Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½Šøя|$1 Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½ŠøŠ¹}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 Š·Š°ŠæущŠµŠ½Š½Š¾Šµ Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½ŠøŠµ|$1 Š·Š°ŠæущŠµŠ½Š½Ń‹Ń… Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½Šøя|$1 Š·Š°ŠæущŠµŠ½Š½Ń‹Ń… Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½ŠøŠ¹}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 ŠæŠ¾ŃŃ‚Š°Š²Š»ŠµŠ½Š½Š¾Šµ Š² Š¾Ń‡ŠµŃ€ŠµŠ“ь Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½ŠøŠµ|$1 ŠæŠ¾ŃŃ‚Š°Š²Š»ŠµŠ½Š½Ń‹Ń… Š² Š¾Ń‡ŠµŃ€ŠµŠ“ь Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½Šøя|$1 ŠæŠ¾ŃŃ‚Š°Š²Š»ŠµŠ½Š½Ń‹Ń… Š² Š¾Ń‡ŠµŃ€ŠµŠ“ь Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½ŠøŠ¹}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 Š½ŠµŃƒŠ“Š°Š²ŃˆŠµŠµŃŃ Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½ŠøŠµ|$1 Š½ŠµŃƒŠ“Š°Š²ŃˆŠøхся Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½Šøя|$1 Š½ŠµŃƒŠ“Š°Š²ŃˆŠøхся Š“ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½ŠøŠ¹}}",
+ "timedmedia-file": "Š¤Š°Š¹Š»",
+ "timedmedia-audios": "{{PLURAL:$1|$1 Š°ŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š»|$1 Š°ŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š»Š°|$1 Š°ŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š»Š¾Š²ĢŸ}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Š°ŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š» Ogg|$1 Š°ŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š»Š° Ogg|$1 Š°ŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š»Š¾Š² Ogg}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 Š°ŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š» FLAC|$1 Š°ŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š»Š° FLAC|$1 Š°ŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š»Š¾Š² FLAC}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 Š°ŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š» WAV|$1 Š°ŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š»Š° WAV|$1 Š°ŃƒŠ“ŠøŠ¾Ń„Š°Š¹Š»Š¾Š² WAV}}",
+ "right-transcode-reset": "сŠ±Ń€Š¾Ń Š½ŠµŃƒŠ“Š°Š²ŃˆŠøхся ŠøŠ»Šø трŠ°Š½ŃŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½Š½Ń‹Ń… Š²ŠøŠ“ŠµŠ¾, чтŠ¾Š±Ń‹ Š¾Š½Šø Š²ŃŃ‚Š°Š»Šø Š² Š¾Ń‡ŠµŃ€ŠµŠ“ь Š·Š°Š“Š°Š½ŠøŠ¹ сŠ½Š¾Š²Š°",
+ "right-transcode-status": "ŠæрŠ¾ŃŠ¼Š¾Ń‚Ń€ [[Special:TimedMediaHandler|ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŠø Š¾ тŠµŠŗущŠµŠ¼ хŠ¾Š“Šµ ŠæŠµŃ€ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½Šøя]]",
+ "action-transcode-status": "ŠæрŠ¾ŃŠ¼Š¾Ń‚Ń€ тŠµŠŗущŠµŠ³Š¾ стŠ°Ń‚ŃƒŃŠ° ŠæŠµŃ€ŠµŠŗŠ¾Š“ŠøрŠ¾Š²Š°Š½Šøя",
+ "orphanedtimedtext": "ŠŸŠ¾Ń‚ŠµŃ€ŃŠ½Š½Ń‹Šµ стрŠ°Š½Šøцы TimedText",
+ "orphanedtimedtext-summary": "Š”ŠæŠøсŠ¾Šŗ стрŠ°Š½Šøц [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]], ŠŗŠ¾Ń‚Š¾Ń€Ń‹Šµ Š½Šµ ŠøŠ¼ŠµŃŽŃ‚ сŠ¾Š¾Ń‚Š²ŠµŃ‚стŠ²ŃƒŃŽŃ‰ŠµŠ³Š¾ фŠ°Š¹Š»Š°.",
+ "orphanedtimedtext-unsupported": "Š­Ń‚Š¾ сŠæŠµŃ†ŃŃ‚Ń€Š°Š½ŠøцŠ° ŠæŠ¾Š“Š“ŠµŃ€Š¶ŠøŠ²Š°ŠµŃ‚ся тŠ¾Š»ŃŒŠŗŠ¾ Š“Š»Ń Š±Š°Š· Š“Š°Š½Š½Ń‹Ń… MySQL.",
+ "orphanedtimedtext-notimedtext": "TimedText Š½Šµ Š²ŠŗŠ»ŃŽŃ‡ŠµŠ½ Š² этŠ¾Š¹ Š²ŠøŠŗŠø.",
+ "apihelp-transcodereset-param-title": "Š—Š°Š³Š¾Š»Š¾Š²Š¾Šŗ Š¼ŠµŠ“ŠøŠ°Ń„Š°Š¹Š»Š°."
+}
diff --git a/extensions/TimedMediaHandler/i18n/rue.json b/extensions/TimedMediaHandler/i18n/rue.json
new file mode 100644
index 00000000..66934a9c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/rue.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gazeb"
+ ]
+ },
+ "timedmedia-more": "Š’ŠµŃ†Šµ...",
+ "timedmedia-dismiss": "Š—Š°ŠæŠµŃ€Ń‚Šø",
+ "timedmedia-file": "Š¤Š°Š¹Š»"
+}
diff --git a/extensions/TimedMediaHandler/i18n/sa.json b/extensions/TimedMediaHandler/i18n/sa.json
new file mode 100644
index 00000000..f3634735
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/sa.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "Shubha",
+ "NehalDaveND"
+ ]
+ },
+ "timedmedia-more": "ą¤…ą¤§ą¤æą¤•ą¤®ą„.....",
+ "timedmedia-dismiss": "ą¤Ŗą¤æą¤¦ą¤§ą¤¾ą¤¤ą„",
+ "timedmedia-download": "ą¤øą¤žą„ą¤šą¤æą¤•ą¤¾ą¤Æą¤¾ą¤ƒ ą¤…ą¤µą¤¾ą¤°ą„‹ą¤Ŗą¤£ą¤®ą„",
+ "timedmedia-desc-link": "ą¤…ą¤øą„ą¤Æą¤¾ą¤ƒ ą¤øą¤žą„ą¤šą¤æą¤•ą¤¾ą¤Æą¤¾ą¤ƒ ą¤µą¤æą¤·ą¤Æą„‡",
+ "timedmedia-status": "ą¤øą„ą¤„ą¤æą¤¤ą¤æą¤ƒ",
+ "timedmedia-status-unknown": "ą¤…ą¤œą„ą¤žą¤¾ą¤¤ą¤øą„ą¤„ą¤æą¤¤ą¤æą¤ƒ",
+ "timedmedia-actions": "ą¤•ą„ą¤°ą¤æą¤Æą¤¾ą¤ƒ",
+ "timedmedia-source-file": "$1 ą¤øą„ą¤°ą„‹ą¤¤ą¤ƒ",
+ "timedmedia-source-audio-file-desc": "ą¤®ą„‚ą¤²ą¤®ą„ $1 ą¤øą¤žą„ą¤šą¤æą¤•ą¤¾ ($2)",
+ "timedmedia-subtitle-new-go": "ą¤—ą¤®ą„ą¤Æą¤¤ą¤¾ą¤®ą„",
+ "timedmedia-file": "ą¤øą¤žą„ą¤šą¤æą¤•ą¤¾"
+}
diff --git a/extensions/TimedMediaHandler/i18n/sah.json b/extensions/TimedMediaHandler/i18n/sah.json
new file mode 100644
index 00000000..0bee4097
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/sah.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "HalanTul"
+ ]
+ },
+ "timedmedia-desc": "ŠžŠ±Ń€Š°Š±Š¾Ń‚чŠøŠŗ фŠ°Š¹Š»Š¾Š² Ogg Theora Šø Vorbis с ŠøсŠæŠ¾Š»ŃŒŠ·Š¾Š²Š°Š½ŠøŠµŠ¼ JavaScript-ŠæрŠ¾ŠøŠ³Ń€Ń‹Š²Š°Ń‚ŠµŠ»Ń",
+ "timedmedia-ogg-short-audio": "Š—Š²ŃƒŠŗŠ¾Š²Š¾Š¹ фŠ°Š¹Š» Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Š’ŠøŠ“ŠµŠ¾-фŠ°Š¹Š» Ogg $1, $2",
+ "timedmedia-ogg-short-general": "ŠœŠµŠ“ŠøŠ°-фŠ°Š¹Š» Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Š·Š²ŃƒŠŗŠ¾Š²Š¾Š¹ фŠ°Š¹Š» Ogg $1, уŅ»ŃƒŠ½Š° $2, $3",
+ "timedmedia-ogg-long-video": "Š²ŠøŠ“ŠµŠ¾-фŠ°Š¹Š» Ogg $1, уŅ»ŃƒŠ½Š° $2, $4Ɨ$5 ŠæŠøŠøŠŗсэŠ»Š»ŃŃŃ…, $3",
+ "timedmedia-ogg-long-multiplexed": "Š¼ŃƒŠ»ŃŒŃ‚ŠøŠæŠ»ŠµŠŗсŠ½Ń‹Š¹ Š°ŃƒŠ“ŠøŠ¾/Š²ŠøŠ“ŠµŠ¾-фŠ°Š¹Š» Ogg, $1, уŅ»ŃƒŠ½Š° $2, $4Ɨ$5 ŠæŠøŠøŠŗсэŠ»Š»ŃŃŃ…, Š±Š°Ń€Ń‹Ń‚Š° $3",
+ "timedmedia-ogg-long-general": "Š¼ŠµŠ“ŠøŠ°-фŠ°Š¹Š» Ogg, уŅ»ŃƒŠ½Š° $2, $3",
+ "timedmedia-ogg-long-error": "сыыŅ»Š° Ogg-фŠ°Š¹Š»: $1",
+ "timedmedia-no-player-js": "Š„Š¾Š¼Š¾Š¹ŃƒŠ¾Ń… ŠøŅ»ŠøŠ½, Š±Ń€Š°ŃƒŠ·ŠµŃ€Š³Š°Ń€ JavaScript Š°Ń€Š°Š°Ń€Ń‹Š»Š»Š° сыŠ»Š“ьŠ°Ń€, эŠ±ŃŃ‚ŃŃ€ Š¾Š½Ńƒ ŅÆŠ»ŃŠ»ŃŃ‚ŃŃ€ тэрŠøŠ» суŠ¾Ń… эŠ±Šøт.<br />\nŠ­Š½ <a href=\"$1\">рŠ¾Š»ŠøŠ³Ń‹ хŠ°Ń‡Š°Š¹Š“Š°Š½Š°Š½ ыŠ»Š°Š½ ŠŗÓ©Ń€ŅÆÓ©Ń…Ń…ŅÆŠ½</a> Š±ŠøŠøтэр <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">Š¾Š¾Š½Š½ŃŒŠ¾Ń‚Š¾Ń€ тэрŠøŠ»Šø хŠ°Ń‡Š°Š¹Š“Š°Š½Š°Š½</a> Š±Ń€Š°ŃƒŠ·ŠµŃ€Š³Š°Ń€ ŠŗÓ©Ń€ŅÆÓ©Ń…Ń…ŅÆŠ½ сөŠæ.",
+ "timedmedia-more": "ÓØссө...",
+ "timedmedia-dismiss": "ŠšŠøстээ/сŠ°Šæ",
+ "timedmedia-download": "Š‘ŠøŠ»ŃŠ½Šø хŠ°Ń‡Š°Š¹Š“Š°Š°",
+ "timedmedia-desc-link": "Š‘Ńƒ Š±ŠøŠ»Ń туŅ»ŃƒŠ½Š°Š½",
+ "timedmedia-source-file": "Š«Š»Ń‹Š»Š»Ń‹Š±Ń‹Ń‚ сŠøрэ $1",
+ "timedmedia-source-audio-file-desc": "Š”ŃŒŠøŅ„Š½ŃŃŃ… $1-Š±ŠøŠ»Ń ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/scn.json b/extensions/TimedMediaHandler/i18n/scn.json
new file mode 100644
index 00000000..77993f87
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/scn.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Pippinu",
+ "Sarvaturi"
+ ]
+ },
+ "timedmedia-no-player-js": "Purtroppu lu tĆ² browser o havi lu JavaScript disattivatu o nun havi nuddu litturi suppurtatu.<br />\nTi poi <a href=\"$1\">scarricari lu spizzuni</a> o puru <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">scarricari nu litturi</a> p'arriprudĆ¹ciri lu spizzuni ntĆ“ tĆ² browser.",
+ "timedmedia-source-file": "Surgenti $1",
+ "timedmedia-source-audio-file-desc": "File $1 origginali ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/sco.json b/extensions/TimedMediaHandler/i18n/sco.json
new file mode 100644
index 00000000..a05c7efb
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/sco.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "John Reid",
+ "AmaryllisGardener"
+ ]
+ },
+ "timedmedia-ogg-long-no-streams": "Ogg media file. Warnishment: Nane o the codecs uised in this file ar recognized.",
+ "timedmedia-no-player-js": "Sorry, yer brouser either haes JavaScript disabled or daes nae hae ony supportit player.<br />\nYe can <a href=\"$1\">dounload the clip</a> or <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">dounload a player</a> tae play the clip in yer brouser.",
+ "timedmedia-source-file": "$1 soorce",
+ "timedmedia-source-audio-file-desc": "Oreeginal $1 file ($2)",
+ "timedmedia-audios": "{{PLURAL:$1|$1 audio file|$1 audio files}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ogg audio file|$1 Ogg audio files}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 FLAC audio file|$1 FLAC audio files}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 WAV audio file|$1 WAV audio files}}"
+}
diff --git a/extensions/TimedMediaHandler/i18n/sdh.json b/extensions/TimedMediaHandler/i18n/sdh.json
new file mode 100644
index 00000000..d4ff6455
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/sdh.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kurdbuddha"
+ ]
+ },
+ "timedmedia-file": "Ł¾Ū•Ś•ŚÆŪ•"
+}
diff --git a/extensions/TimedMediaHandler/i18n/sgs.json b/extensions/TimedMediaHandler/i18n/sgs.json
new file mode 100644
index 00000000..702050e7
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/sgs.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hugo.arg"
+ ]
+ },
+ "timedmedia-download": "Atsėsiōstė faila",
+ "timedmedia-source-file": "$1 kėlmie",
+ "timedmedia-source-audio-file-desc": "Pėrms $1 skvarmou ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/shn.json b/extensions/TimedMediaHandler/i18n/shn.json
new file mode 100644
index 00000000..5e27c963
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/shn.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Saimawnkham"
+ ]
+ },
+ "timedmedia-source-file": "į€„į€į€ŗį‚ˆį€„į‚ƒį‚‡ $1",
+ "timedmedia-source-audio-file-desc": "į¾į¢į‚†į‚‡į€„į€į€ŗį‚ˆį€į€­į€Æį¼į€ŗį€ø $1 į¾į¢į‚†į‚‡ ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/shy-latn.json b/extensions/TimedMediaHandler/i18n/shy-latn.json
new file mode 100644
index 00000000..ec64ab0c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/shy-latn.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Vikoula5"
+ ]
+ },
+ "timedmedia-days": "{{PLURAL:$1|1 ass|$1 ussan}}"
+}
diff --git a/extensions/TimedMediaHandler/i18n/si.json b/extensions/TimedMediaHandler/i18n/si.json
new file mode 100644
index 00000000..05795ef3
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/si.json
@@ -0,0 +1,85 @@
+{
+ "@metadata": {
+ "authors": [
+ "ą¶±ą¶±ą·Šą¶Æą·’ą¶øą·’ą¶­ą·”ą¶»ą·”",
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ",
+ "Susith Chandira Gts",
+ "ą·„ą¶»ą·’ą¶­"
+ ]
+ },
+ "timedmedia-desc": "Ogg Theora ą·ƒą·„ Vorbis ą¶œą·œą¶±ą·” ą·ƒą¶³ą·„ą· ą·„ą·ƒą·”ą¶»ą·”ą·€ą¶±ą¶ŗ, ą¶¢ą·ą·€ą·ą·ƒą·Šą¶šą·Šā€ą¶»ą·’ą¶“ą·Šą¶§ą·Š ą¶“ą·Šą¶½ą·šą¶ŗą¶»ą·Š ą·ƒą¶øą¶Ÿ",
+ "timedmedia-ogg-short-audio": "Ogg $1 ą·ą·Šā€ą¶»ą·€ą·Šā€ą¶ŗ ą¶œą·œą¶±ą·”ą·€, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 ą¶Æą·˜ą·ą·Šā€ą¶ŗ ą¶œą·œą¶±ą·”ą·€, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 ą¶øą·ą¶°ą·Šā€ą¶ŗ ą¶œą·œą¶±ą·”ą·€, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 ą·ą·Šā€ą¶»ą·€ą·Šā€ą¶ŗ ą¶œą·œą¶±ą·”ą·€, ą¶“ą·Šā€ą¶»ą·€ą¶»ą·Šą¶­ą¶±ą¶ŗ $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 ą¶Æą·˜ą·ą·Šā€ą¶ŗ ą¶œą·œą¶±ą·”ą·€, ą¶“ą·Šā€ą¶»ą·€ą¶»ą·Šą¶­ą¶±ą¶ŗ $2, $4Ɨ$5 ą¶“ą·’ą¶šą·Šą·ƒą¶½ą·Š, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg ą¶¶ą·„ą·”ą¶“ą¶®ą¶šą·ą¶»ą¶š ą·ą·Šā€ą¶»ą·€ą·Šā€ą¶ŗ/ą¶Æą·˜ą·ą·Šā€ą¶ŗ ą¶œą·œą¶±ą·”ą·€, $1, ą¶“ą·Šā€ą¶»ą·€ą¶»ą·Šą¶­ą¶±ą¶ŗ $2, $4Ɨ$5 ą¶“ą·’ą¶šą·Šą·ƒą¶½ą·Š, $3 ą·ƒą¶øą·ƒą·Šą¶­",
+ "timedmedia-ogg-long-general": "Ogg ą¶øą·ą¶°ą·Šā€ą¶ŗ ą¶œą·œą¶±ą·”ą·€, ą¶“ą·Šā€ą¶»ą·€ą¶»ą·Šą¶­ą¶±ą¶ŗ $2, $3",
+ "timedmedia-ogg-long-error": "ą¶…ą¶±ą·“ą¶­ą·’ą¶š ogg ą¶œą·œą¶±ą·”ą·€: $1",
+ "timedmedia-webm-short-video": "WebM $1 ą·€ą·’ą¶Æą·˜ą·ą·Šā€ą¶ŗ ą¶œą·œą¶±ą·”ą·€, $2",
+ "timedmedia-webm-long-video": "WebM ą·ą·Šā€ą¶»ą·€ą·Šā€ą¶ŗ/ą¶Æą·˜ą·ą·Šā€ą¶ŗ ą¶œą·œą¶±ą·”ą·€, $1, ą¶Æą·’ą¶œ $2, $4 Ɨ $5 ą¶“ą·’ą¶šą·Šą·ƒą¶½ą·Š, $3 ą·ƒą¶øą·ƒą·Šą¶®ą¶ŗ",
+ "timedmedia-mp4-short-video": "MP4 $1 ą¶Æą·˜ą·ą·Šā€ą¶ŗ ą¶œą·œą¶±ą·”ą·€, $2",
+ "timedmedia-mp4-long-video": "MP4 ą·ą·Šā€ą¶»ą·€ą·Šā€ą¶ŗ/ą¶Æą·˜ą·ą·Šā€ą¶ŗ ą¶œą·œą¶±ą·”ą·€, $1, ą¶Æą·’ą¶œ $2, $4 Ɨ $5 ą¶“ą·’ą¶šą·Šą·ƒą¶½ą·Š, $3 ą·ƒą¶øą·ƒą·Šą¶®ą¶ŗ",
+ "timedmedia-no-player-js": "ą·ƒą¶øą·ą·€ą¶±ą·Šą¶±, ą¶”ą¶¶ą·š ą¶œą·€ą·šą·‚ą¶šą¶ŗą·š ą¶¢ą·ą·€ą·ą·ƒą·Šą¶šą·Šā€ą¶»ą·’ą¶“ą·Šą¶§ą·Š ą¶…ą¶šą·Šā€ą¶»ą·“ą¶ŗ ą·€ą·“ ą¶‡ą¶­ ą¶±ą·ą¶­ą·„ą·œą¶­ą·Š ą¶šą·’ą·ƒą·’ą¶Æą·” ą¶…ą¶±ą·”ą¶œą·Šā€ą¶»ą·„ą¶ŗ ą¶Æą¶šą·Šą·€ą¶± ą¶“ą·Šą¶½ą·šą¶ŗą¶»ą¶ŗą¶šą·Š ą¶”ą¶¶ ą·ƒą¶­ą·”ą·€ ą¶±ą·ą¶­.<br />\ną¶”ą¶¶ą·š ą¶œą·€ą·šą·‚ą¶šą¶ŗą·™ą·„ą·’ ą·€ą·“ą¶©ą·’ą¶ŗą·ą·€ ą¶°ą·ą·€ą¶±ą¶ŗ ą¶šą·’ą¶»ą·“ą¶øą¶§ <a href=\"$1\">ą·€ą·“ą¶©ą·’ą¶ŗą·ą·€ ą¶¶ą·ą¶œą¶­ ą¶šą·’ą¶»ą·“ą¶ø</a> ą·„ą· <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ą¶“ą·Šą¶½ą·šą¶ŗą¶»ą¶ŗ ą¶¶ą·ą¶œą¶­ ą¶šą·’ą¶»ą·“ą¶ø</a> ą·ƒą·’ą¶Æą·” ą¶šą·… ą·„ą·ą¶šą·’ą¶ŗ.",
+ "timedmedia-more": "ą¶‰ą¶­ą·’ą¶»ą·’ą¶ŗā€¦",
+ "timedmedia-dismiss": "ą·€ą·ƒą¶±ą·Šą¶±",
+ "timedmedia-download": "ą¶œą·œą¶±ą·”ą·€ ą¶¶ą· ą¶œą¶±ą·Šą¶±",
+ "timedmedia-play-media": "ą¶øą·ą¶°ą·Šā€ą¶ŗ ą·€ą¶ŗą¶±ą·Šą¶±",
+ "timedmedia-desc-link": "ą¶øą·™ą¶ø ą¶œą·œą¶±ą·”ą·€ ą¶“ą·’ą·…ą·’ą¶¶ą¶³",
+ "timedmedia-oggThumb-version": "OggHandler ą·ƒą¶³ą·„ą· oggThumb $1 ą·ƒą¶‚ą·ƒą·Šą¶šą¶»ą¶«ą¶ŗ ą·„ą· ą¶…ą¶½ą·”ą¶­ą·Š ą¶‘ą¶šą¶šą·Š ą¶…ą·€ą·ą·ƒą·’ą¶ŗ.",
+ "timedmedia-oggThumb-failed": "ą·ƒą¶‚ą¶šą·Šą·‚ą·’ą¶“ą·Šą¶­ą¶ŗ ą¶­ą·ą¶±ą·”ą¶øą¶§ oggThumb ą¶…ą·ƒą¶øą¶­ą·Šą·€ą·’ą¶ŗ.",
+ "timedmedia-status-header": "Transcode ą¶­ą¶­ą·Šą·€ą¶ŗ",
+ "timedmedia-update-status": "transcode ą¶­ą¶­ą·Šą·€ą¶ŗ ą¶ŗą·ą·€ą¶­ą·Šą¶šą·ą¶½ą·“ą¶± ą¶šą¶»ą¶±ą·Šą¶±",
+ "timedmedia-status": "ą¶­ą¶­ą·Šą·€ą¶ŗ",
+ "timedmedia-status-unknown": "ą¶±ą·œą¶Æą¶±ą·Šą¶±ą· ą¶­ą¶­ą·Šą·€ą¶ŗ",
+ "timedmedia-transcodeinfo": "Transcode ą·€ą·Šā€ą¶ŗą·”ą¶­ą·Šą¶“ą¶±ą·Šą¶± ą·€ą·’ą·ƒą·Šą¶­ą¶»ą¶ŗ",
+ "timedmedia-actions": "ą¶šą·ą¶»ą·Šą¶ŗą¶ŗą¶±ą·Š",
+ "timedmedia-direct-link": "ą·€ą·Šā€ą¶ŗą·”ą¶­ą·Šą¶“ą¶±ą·Šą¶±ą¶ŗ ą¶¶ą·ą¶œą¶±ą·Šą¶±",
+ "timedmedia-not-ready": "ą·ƒą·”ą¶Æą·ą¶±ą¶øą·Š ą¶±ą·ą¶­",
+ "timedmedia-completed-on": "$1 transcode ą·ƒą¶øą·Šą¶“ą·–ą¶»ą·Šą¶« ą¶šą¶»ą¶± ą¶½ą¶Æą·“",
+ "timedmedia-error-on": "$1 ą·„ą·“ transcode ą¶Æą·ą·‚ą¶ŗą¶šą·Š.",
+ "timedmedia-started-transcode": "$1 ą¶“ą·™ą¶» Transcode ą¶†ą¶»ą¶øą·Šą¶· ą¶šą¶»ą¶± ą¶½ą¶Æą·“. $2",
+ "timedmedia-percent-done": "$1% ą¶“ą¶øą¶« ą¶‰ą·€ą¶»ą¶ŗą·’",
+ "timedmedia-in-job-queue": "$1 ą¶“ą·™ą¶» ą¶šą·˜ą¶­ą·Šā€ą¶ŗ ą¶“ą·™ą¶½ą¶§ ą¶‘ą¶šą·Š ą¶šą¶»ą¶± ą¶½ą¶Æą·“",
+ "timedmedia-unknown-target-size": "ą¶±ą·œą¶Æą¶±ą·Šą¶±ą· ą¶‰ą¶½ą¶šą·Šą¶šą¶œą¶­ ą¶“ą·Šā€ą¶»ą¶øą·ą¶«ą¶ŗ, $1 ą¶šą·šą¶­ą·ą¶‚ą¶šą¶±ą¶ŗ ą¶šą¶»ą¶± ą¶½ą¶Æą·“",
+ "timedmedia-days": "{{PLURAL:$1|ą¶Æą·€ą·ƒ|$1 ą¶Æą·€ą·ƒą·Š}}",
+ "timedmedia-hours": "{{PLURAL:$1|ą¶“ą·ą¶ŗ|$1 ą¶“ą·ą¶ŗ}}",
+ "timedmedia-minutes": "{{PLURAL:$1|ą¶øą·’ą¶±ą·’ą¶­ą·Šą¶­ą·”ą·€|$1 ą¶øą·’ą¶±ą·’ą¶­ą·Šą¶­ą·”}}",
+ "timedmedia-seconds": "{{PLURAL:$1|ą¶­ą¶­ą·Šą¶“ą¶»ą¶ŗ|$1 ą¶­ą¶­ą·Šą¶“ą¶»}}",
+ "timedmedia-reset": "transcode ą¶ŗą·…ą·’ ą·ƒą¶šą·ƒą¶±ą·Šą¶±",
+ "timedmedia-reset-error": "transcode ą¶šą·˜ą¶­ą·Šā€ą¶ŗ ą¶ŗą·…ą·’ ą·ƒą·ą¶šą·ƒą·“ą¶øą·š ą¶Æą·ą·‚ą¶ŗ.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 ą¶øą·–ą¶½ą·ą·ą·Šā€ą¶»ą¶ŗ",
+ "timedmedia-source-file-desc": "ą¶±ą·’ą¶ŗą¶ø $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "ą¶±ą·’ą¶ŗą¶ø $1 ą¶œą·œą¶±ą·”ą·€ ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "ą¶…ą·€ą¶ø ą¶šą¶½ą·ą¶“ ą¶“ą·…ą¶½ Ogg ą·€ą·’ą¶Æą·˜ą·ą·Šā€ą¶ŗ (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "ą¶¢ą·ą¶½ ą·ą·Šā€ą¶»ą·ą¶­ą¶øą¶ŗ Ogg ą·€ą·“ą¶©ą·’ą¶ŗą·ą·€ (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "ą¶¢ą·ą¶½ ą·ą·Šā€ą¶»ą·ą¶­ą¶øą¶ŗ Ogg ą·€ą·“ą¶©ą·’ą¶ŗą·ą·€ (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "ą¶‹ą·ƒą·ƒą·Š ą¶œą·”ą¶«ą¶­ą·Šą·€ą¶ŗą·š ą¶¶ą·ą¶œą¶­ą·„ą·ą¶šą·’ Ogg ą·€ą·“ą¶©ą·’ą¶ŗą·ą·€ (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "ą¶¶ą·ą¶œą¶­ ą¶šą·…ą·„ą·ą¶šą·’ Full HD Ogg ą·€ą·“ą¶©ą·’ą¶ŗą· ą¶“ą¶§ (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "ą¶¢ą·ą¶½ ą·ą·Šā€ą¶»ą·ą¶­ą¶øą¶ŗ WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "ą¶¢ą·ą¶½ ą·ą·Šā€ą¶»ą·ą¶­ą¶øą¶ŗ WebM (360P)",
+ "timedmedia-derivative-desc-480p.webm": "ą¶¢ą·ą¶½ ą·ą·Šā€ą¶»ą·ą¶­ą¶øą¶ŗ WebM (480P)",
+ "timedmedia-derivative-desc-720p.webm": "ą¶‹ą·ƒą·ƒą·Š ą¶œą·”ą¶«ą¶­ą·Šą·€ą¶ŗą·š ą¶¶ą·ą¶œą¶­ą·„ą·ą¶šą·’ WebM (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "ą¶¶ą·ą¶œą¶­ ą¶šą·…ą·„ą·ą¶šą·’ Full HD WebM (1080P)",
+ "timedmedia-derivative-desc-320p.mp4": "ą¶‹ą¶“ą·ą¶‚ą¶œ-ą·„ą·’ą¶­ą¶šą·ą¶øą·“ MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "ą¶¢ą·ą¶½ ą·ą·Šā€ą¶»ą·ą¶­ą¶øą¶ŗ MP4 (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "HD ą¶œą·”ą¶«ą¶­ą·Šą·€ą¶ŗą·š MP4 (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "Full HD ą¶­ą¶­ą·Šą·€ą¶ŗą·š MP4 (1080P)",
+ "timedmedia-subtitle-new": "ą¶±ą·€ ą¶“ą¶»ą·’ą·€ą¶»ą·Šą¶­ą¶±ą¶ŗą¶šą·Š ą¶­ą¶±ą¶±ą·Šą¶± ą·„ą· ą¶“ą·€ą¶­ą·Šą¶±ą· ą¶‘ą¶šą¶šą·Š ą·ƒą¶‚ą·ƒą·Šą¶šą¶»ą¶«ą¶ŗ ą¶šą¶»ą¶±ą·Šą¶±",
+ "timedmedia-subtitle-new-go": "ą¶ŗą¶±ą·Šą¶±",
+ "timedmedia-subtitle-language": "$1 ($2) ą¶‹ą¶“ą·ą·“ą¶»ą·Šą·‚",
+ "timedmedia-subtitle-no-video": "ą·€ą¶­ą·Šą¶øą¶±ą·Š ą¶‹ą¶“ą·ƒą·’ą¶»ą·”ą·ƒ ą¶“ą·’ą¶§ą·”ą·€ ą·ƒą¶øą¶Ÿ ą¶šą·’ą·ƒą·’ą¶Æą·” ą·€ą·“ą¶©ą·’ą¶ŗą·ą·€ą¶šą·Š ą·ƒą¶øą·Šą¶¶ą¶±ą·Šą¶° ą¶±ą·œą·€ą·š.",
+ "timedmedia-subtitle-remote": "ą¶øą·™ą¶ø ą¶œą·œą¶±ą·”ą·€ ą·ƒą¶³ą·„ą· ą¶šą·ą¶½ą·’ą¶­ ą¶“ą·™ą·… $1 ą·„ą·“ ą·ƒą¶­ą·Šą¶šą·ą¶» ą¶½ą¶¶ą· ą¶‡ą¶­",
+ "timedmedia-subtitle-remote-link": "ą¶”ą¶¶ą¶§ ą¶øą·™ą¶ø ą¶œą·œą¶±ą·”ą·€ ą·ƒą¶³ą·„ą· [$1 ą·€ą·’ą·ƒą·Šą¶­ą¶» ą¶“ą·’ą¶§ą·”ą·€] $2 ą·„ą·’ą¶Æą·“ ą¶¶ą¶½ą·ą¶œą¶­ ą·„ą·ą¶š",
+ "timedmediahandler": "ą¶šą·ą¶½ą·’ą¶­ą¶øą·ą¶°ą·Šā€ą¶ŗą·„ą·ƒą·”ą¶»ą·€ą¶±ą¶ŗ",
+ "timedmedia-videos": "{{PLURAL:$1|ą·€ą·“ą¶©ą·’ą¶ŗą·}} $1 ą¶šą·Š",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|Ogg ą·€ą·“ą¶©ą·’ą¶ŗą·}} $1 ą¶šą·Š",
+ "timedmedia-webm-videos": "{{PLURAL:$1|WebM ą·€ą·“ą¶©ą·’ą¶ŗą·}} $1 ą¶šą·Š",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transcode|$1 transcodes}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|ą¶°ą·ą·€ą¶±ą¶ŗ ą·€ą¶± transcode}} $1",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|ą¶“ą·™ą·…ą¶œą·ƒą·Šą·€ą· ą¶‡ą¶­ą·’ transcode}} $1",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|ą¶…ą·ƒą¶øą¶­ą·Š ą·€ą·– transcode}} $1",
+ "timedmedia-file": "ą¶œą·œą¶±ą·”ą·€",
+ "action-transcode-status": "ą·€ą¶­ą·Šą¶øą¶±ą·Š ą¶…ą¶±ą·” ą¶½ą·ą¶šą·“ą¶øą·Š ą¶­ą¶­ą·Šą·€ą¶ŗ ą¶±ą¶»ą¶¹ą¶±ą·Šą¶±"
+}
diff --git a/extensions/TimedMediaHandler/i18n/sk.json b/extensions/TimedMediaHandler/i18n/sk.json
new file mode 100644
index 00000000..0a1480c4
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/sk.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Helix84",
+ "TomĆ”Å”Polonec",
+ "Wizzard"
+ ]
+ },
+ "timedmedia-desc": "Obsluha sĆŗborov Ogg Theora a Vorbis s JavaScriptovĆ½m prehrĆ”vačom",
+ "timedmedia-ogg-short-audio": "ZvukovĆ½ sĆŗbor ogg $1, $2",
+ "timedmedia-ogg-short-video": "Video sĆŗbor ogg $1, $2",
+ "timedmedia-ogg-short-general": "MultimediĆ”lny sĆŗbor ogg $1, $2",
+ "timedmedia-ogg-long-audio": "ZvukovĆ½ sĆŗbor ogg $1, dÄŗžka $2, $3",
+ "timedmedia-ogg-long-video": "Video sĆŗbor ogg $1, dÄŗžka $2, $4Ɨ$5 pixelov, $3",
+ "timedmedia-ogg-long-multiplexed": "MultiplexovanĆ½ zvukovĆ½/video sĆŗbor ogg, $1, dÄŗžka $2, $4Ɨ$5 pixelov, $3 celkom",
+ "timedmedia-ogg-long-general": "MultimediĆ”lny sĆŗbor ogg, dÄŗžka $2, $3",
+ "timedmedia-ogg-long-error": "NeplatnĆ½ sĆŗbor ogg: $1",
+ "timedmedia-no-player-js": "Je nĆ”m ľĆŗto, ale vĆ”Å” prehliadač mĆ” buď vypnutĆ½ JavaScript, alebo nemĆ”te žiadny podporovanĆ½ prehrĆ”vač.<br />\nMĆ“Å¾ete si <a href=\"$1\">stiahnuÅ„ klip</a> alebo si <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">stiahnuÅ„ prehrĆ”vač</a>, ktorĆ½m si klip prehrajete v prehliadači.",
+ "timedmedia-more": "viac...",
+ "timedmedia-dismiss": "Zatvoriń",
+ "timedmedia-download": "StiahnuÅ„ sĆŗbor",
+ "timedmedia-desc-link": "O tomto sĆŗbore",
+ "timedmedia-source-file": "Zdroj $1",
+ "timedmedia-source-audio-file-desc": "PĆ“vodnĆ½ sĆŗbor $1 ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/sl.json b/extensions/TimedMediaHandler/i18n/sl.json
new file mode 100644
index 00000000..d298dd7a
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/sl.json
@@ -0,0 +1,96 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dbc334",
+ "Eleassar",
+ "Rzuwig"
+ ]
+ },
+ "timedmedia-desc": "Upravljavec zvoka, videa in časovnega besedila s podprtimi oblikami WebM, Ogg Theora, Vorbis in SubRip",
+ "timedmedia-ogg-short-audio": "avdiodatoteka Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Videodatoteka Ogg $1, $2",
+ "timedmedia-ogg-short-general": "Predstavnostna datoteka Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "avdiodatoteka Ogg $1, dolžine $2, $3",
+ "timedmedia-ogg-long-video": "videodatoteka ogg $1, dolžine $2, $4Ā Ć—Ā $5Ā pik, $3",
+ "timedmedia-ogg-long-multiplexed": "multipleksna avdio-/videodatoteka Ogg, $1, dolžine $2, $4 Ɨ $5 pik, skupaj $3",
+ "timedmedia-ogg-long-general": "predstavnostna datoteka Ogg, dolžine $2, $3",
+ "timedmedia-ogg-long-error": "Neveljavna datoteka Ogg: $1",
+ "timedmedia-webm-short-video": "Videodatoteka WebM $1, $2",
+ "timedmedia-webm-long-video": "Avdio-/videodatoteka WebM, $1, dolžine $2, $4 Ɨ $5 pik, skupaj $3",
+ "timedmedia-flac-short-audio": "Datoteka z zvokom FLAC, $1",
+ "timedmedia-flac-long-audio": "Datoteka z zvokom FLAC, dolžine $1, skupno $2",
+ "timedmedia-wav-short-audio": "Datoteka z zvokom WAV, $1",
+ "timedmedia-wav-long-audio": "Datoteka z zvokom WAV, dolžine $1, skupno $2",
+ "timedmedia-wav-pcm-required": "Naložite lahko samo PCM (Pulse Code Modulation) WAV.",
+ "timedmedia-mp4-short-video": "Videodatoteka MP4 $1, $2",
+ "timedmedia-mp4-long-video": "Avdio-/videodatoteka MP4, $1, dolžine $2, $4 Ɨ $5 pik, skupaj $3",
+ "timedmedia-no-player-js": "Oprostite, vaŔ brskalnik ima onemogočen JavaScript ali pa nima nobenega podprtega predvajalnika.<br />\nPosnetek lahko <a href=\"$1\">snamete</a> ali <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">prenesete predvajalnik</a> za predvajanje posnetka v svojem brskalniku.",
+ "timedmedia-more": "Več ...",
+ "timedmedia-dismiss": "Zapri",
+ "timedmedia-download": "Prenesi",
+ "timedmedia-play-media": "Predvajaj",
+ "timedmedia-desc-link": "O datoteki",
+ "timedmedia-oggThumb-version": "OggHandler potrebuje oggThumb različice $1 ali več.",
+ "timedmedia-oggThumb-failed": "OggThumbu ni uspelo ustvariti predogledne sličice.",
+ "timedmedia-status-header": "Stanje prekodiranja",
+ "timedmedia-update-status": "Posodobi stanje prekodiranja",
+ "timedmedia-status": "Stanje",
+ "timedmedia-status-unknown": "Neznano stanje",
+ "timedmedia-transcodeinfo": "Oblika",
+ "timedmedia-actions": "Dejanja",
+ "timedmedia-direct-link": "Prenos",
+ "timedmedia-not-ready": "Ni pripravljeno",
+ "timedmedia-completed-on": "Končano $1",
+ "timedmedia-error-on": "Napaka dne $1",
+ "timedmedia-started-transcode": "Začeto pred $1. $2",
+ "timedmedia-percent-done": "Končanih približno $1 %",
+ "timedmedia-in-job-queue": "Dodano v čakalno vrsto pred $1",
+ "timedmedia-unknown-target-size": "Neznana ciljna velikost, prekodirano $1",
+ "timedmedia-days": "$1 {{PLURAL:$1|dan|dneva|dnevi|dni}}",
+ "timedmedia-hours": "$1 {{PLURAL:$1|ura|uri|ure|ur}}",
+ "timedmedia-minutes": "$1 {{PLURAL:$1|minuta|minuti|minute|minut}}",
+ "timedmedia-seconds": "$1 {{PLURAL:$1|sekunda|sekundi|sekunde|sekund}}",
+ "timedmedia-reset": "Ponastavi prekodiranje",
+ "timedmedia-reset-confirm": "Ob ponastavitvi tega prekodiranja se bodo izbrisale vse obstoječe datoteke (če obstajajo), prekodiranje pa se bo ponovno dodalo v čakalno vrsto. Ponovno prekodiranje bo vzelo nekaj časa. <br /><br />Ste prepričani, da želite nadaljevati?",
+ "timedmedia-reset-error": "Napaka pri ponastavljanju prekodiranja.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "vir $1",
+ "timedmedia-source-file-desc": "Izvirna datoteka $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Izvirna datoteka $1 ($2)",
+ "timedmedia-derivative-160p.ogv": "Ogg 160P",
+ "timedmedia-derivative-desc-160p.ogv": "Video Ogg za majhno pasovno Ŕirino (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Spletni pretočni video Ogg (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Spletni pretočni video Ogg (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Visokokakovostni prenosni video Ogg (720P)",
+ "timedmedia-derivative-desc-160p.webm": "Spletni pretočni WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "WebM za pretakanje preko spleta (360P)",
+ "timedmedia-derivative-desc-480p.webm": "WebM za pretakanje preko spleta (480P)",
+ "timedmedia-derivative-desc-720p.webm": "Visokokakovostni WebM za prenos (720P)",
+ "timedmedia-derivative-desc-320p.mp4": "Napravam prijazni MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "Spletni pretočni WebM (160P)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 kakovosti HD (720P)",
+ "timedmedia-subtitle-new": "Ustvarite nov prevod ali uredite obstoječega",
+ "timedmedia-subtitle-new-desc": "Izberite jezik in pritisnite gumb '''{{int:Timedmedia-subtitle-new-go}}'''.",
+ "timedmedia-subtitle-new-go": "Pojdi",
+ "timedmedia-subtitle-language": "podnapisi v jeziku: $1 ($2)",
+ "timedmedia-subtitle-no-video": "S trenutno podnaslovno stranjo ni povezan noben videoposnetek",
+ "timedmedia-subtitle-no-subtitles": "V jeziku $1 trenutno ni nobenih podnapisov za ta video; stran lahko [{{fullurl:{{FULLPAGENAME}}|action=edit}} odprete za urejanje] in jih dodate.",
+ "timedmedia-subtitle-remote": "Časovno besedilo datoteke gostuje na $1",
+ "timedmedia-subtitle-remote-link": "[$1 Ogledate si lahko opisno stran] datoteke na $2",
+ "timedmediahandler": "Upravljavec časovne predstavnosti",
+ "timedmedia-videos": "{{PLURAL:$1|$ video|$ videa|$ videi|$ videov}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 video Ogg|$1 videa Ogg|$1 videi Ogg|$1 videov Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 video WebM|$1 videa WebM|$1 videi WebM|$1 videov WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|eno prekodiranje|dve prekodiranji|$1 prekodiranja|$1 prekodiranj}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|eno tekoče prekodiranje|dve tekoči prekodiranji|$1 prekodiranja|$1 prekodiranj}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|eno čakajoče prekodiranje|dve čakajoči prekodiranji|$1 čakajoča prekodiranja|$1 čakajočih prekodiranj}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|eno neuspelo prekodiranje|dve neuspeli prekodiranji|$1 neuspela prekodiranja|$1 neuspelih prekodiranj}}",
+ "timedmedia-file": "Datoteka:",
+ "timedmedia-audios": "$1 {{PLURAL:$1|zvočna datoteka|zvočni datoteki|zvočne datoteke|zvočnih datotek}}",
+ "timedmedia-ogg-audios": "$1 {{PLURAL:$1|zvočna datoteka|zvočni datoteki|zvočne datoteke|zvočnih datotek}} Ogg",
+ "timedmedia-flac-audios": "$1 {{PLURAL:$1|zvočna datoteka|zvočni datoteki|zvočne datoteke|zvočnih datotek}} FLAC",
+ "timedmedia-wav-audios": "$1 {{PLURAL:$1|zvočna datoteka|zvočni datoteki|zvočne datoteke|zvočnih datotek}} WAV",
+ "right-transcode-reset": "Ponastavitev neuspelih ali pretvorjenih videov, da so ponovno vstavljeni v čakalno vrsto opravil",
+ "right-transcode-status": "Ogled [[Special:TimedMediaHandler|informacij o trenutni dejavnosti pretvarjanja]]",
+ "action-transcode-status": "ogled trenutnega stanja pretvorbe"
+}
diff --git a/extensions/TimedMediaHandler/i18n/sq.json b/extensions/TimedMediaHandler/i18n/sq.json
new file mode 100644
index 00000000..bad879c1
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/sq.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dori",
+ "Liridon"
+ ]
+ },
+ "timedmedia-ogg-short-audio": "Skedƫ zanore Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Skedƫ pamore Ogg $1, $2",
+ "timedmedia-ogg-short-general": "Skedƫ mediatike Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Skedƫ zanore Ogg $1, kohƫzgjatja $2, $3",
+ "timedmedia-ogg-long-video": "SkedĆ« pamore Ogg $1, kohĆ«zgjatja $2, $4Ɨ$5 pixel, $3",
+ "timedmedia-no-player-js": "Na vjen keq, browser-i juaj ose ka tƫ Ƨaktivizuar JavaScript ose nuk ka mbƫshtetje pƫr ndonjƫ player.<br />\nJu mund tƫ <a href=\"$1\">shkarkoni klipin</a> ose <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">shkarkoni njƫ player</a> pƫr tƫ luajtur klipin nƫ shfletuesin tuaj.",
+ "timedmedia-more": "Mƫ shumƫ...",
+ "timedmedia-dismiss": "Mbylle",
+ "timedmedia-download": "Shkarko skedƫn",
+ "timedmedia-desc-link": "Rreth kƫsaj skede",
+ "timedmedia-source-file": "$1 burimi",
+ "timedmedia-source-audio-file-desc": "Skedari $1 orgjinal ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/sr-ec.json b/extensions/TimedMediaHandler/i18n/sr-ec.json
new file mode 100644
index 00000000..b6a3a4df
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/sr-ec.json
@@ -0,0 +1,55 @@
+{
+ "@metadata": {
+ "authors": [
+ "Milicevic01",
+ "Millosh",
+ "Rancher",
+ "Sasa Stefanovic",
+ "ŠœŠøхŠ°Ń˜Š»Š¾ ŠŠ½Ń’ŠµŠ»ŠŗŠ¾Š²Šøћ"
+ ]
+ },
+ "timedmedia-desc": "ŠžŠ±Ń€Š°Ń’ŠøŠ²Š°Ń‡ Š·Š° Š·Š²ŃƒŠŗ, Š²ŠøŠ“ŠµŠ¾ Šø усŠŗŠ»Š°Ń’ŠµŠ½Šø тŠµŠŗст, с ŠæŠ¾Š“ршŠŗŠ¾Š¼ Š·Š° фŠ¾Ń€Š¼Š°Ń‚Šµ WebM, Ogg Theora, Vorbis Šø SRT",
+ "timedmedia-ogg-short-audio": "Ogg $1 Š·Š²ŃƒŃ‡Š½Š° Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 Š²ŠøŠ“ŠµŠ¾-сŠ½ŠøŠ¼Š°Šŗ, $2.",
+ "timedmedia-ogg-short-general": "Ogg $1 Š¼ŠµŠ“ŠøјсŠŗŠ° Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°, $2.",
+ "timedmedia-ogg-long-audio": "Ogg $1 Š·Š²ŃƒŃ‡Š½Š° Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°, трŠ°Ń˜Š°ŃšŠµ $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 Š²ŠøŠ“ŠµŠ¾-сŠ½ŠøŠ¼Š°Šŗ, трŠ°Ń˜Š°ŃšŠµ $2, $4 Ɨ $5 ŠæŠøŠŗсŠµŠ»Š°, $3.",
+ "timedmedia-ogg-long-multiplexed": "ŠœŃƒŠ»Ń‚ŠøŠæŠ»ŠµŠŗсŠøрŠ°Š½Šø .ogg Š°ŃƒŠ“ŠøŠ¾/Š²ŠøŠ“ŠµŠ¾ сŠ½ŠøŠ¼Š°Šŗ, $1, трŠ°Ń˜Š°ŃšŠµ $2, $4 Ɨ $5 ŠæŠøŠŗсŠµŠ»Š°, $3.",
+ "timedmedia-ogg-long-general": "Ogg Š¼ŠµŠ“ŠøјсŠŗŠ° Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°, трŠ°Ń˜Š°ŃšŠµ $2, $3.",
+ "timedmedia-ogg-long-error": "ŠŠµŠøсŠæрŠ°Š²Š½Š° .ogg Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠ°: $1.",
+ "timedmedia-no-player-js": "Š–Š°Š¾ Š½Š°Š¼ јŠµ, Š°Š»Šø Š²Š°ŃˆŠµŠ¼ ŠæрŠµŠ³Š»ŠµŠ“Š°Ń‡Ńƒ јŠµ Š¾Š½ŠµŠ¼Š¾Š³ŃƒŃ›ŠµŠ½Š° јŠ°Š²Š°ŃŠŗрŠøŠæтŠ° ŠøŠ»Šø Š½ŠµŠ¼Š°Ń‚Šµ Š¾Š“Š³Š¾Š²Š°Ń€Š°Ń˜ŃƒŃ›Šø ŠæŠ»ŠµŃ˜ŠµŃ€.<br />\nŠœŠ¾Š¶ŠµŃ‚Šµ <a href=\"$1\">ŠæрŠµŃƒŠ·ŠµŃ‚Šø ŠŗŠ»ŠøŠæ</a> ŠøŠ»Šø <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ŠæрŠµŃƒŠ·ŠµŃ‚Šø ŠæŠ»ŠµŃ˜ŠµŃ€</a> Š“Š° рŠµŠæрŠ¾Š“уŠŗујŠµŃ‚Šµ ŠŗŠ»ŠøŠæ у Š²Š°ŃˆŠµŠ¼ ŠæрŠµŠ³Š»ŠµŠ“Š°Ń‡Ńƒ.",
+ "timedmedia-more": "Š’ŠøшŠµ...",
+ "timedmedia-dismiss": "Š—Š°Ń‚Š²Š¾Ń€Šø",
+ "timedmedia-download": "ŠŸŃ€ŠµŃƒŠ·Š¼Šø Š“Š°Ń‚Š¾Ń‚ŠµŠŗу",
+ "timedmedia-desc-link": "ŠŸŠ¾Š“Š°Ń†Šø Š¾ Š¾Š²Š¾Ń˜ Š“Š°Ń‚Š¾Ń‚ŠµŃ†Šø",
+ "timedmedia-days": "{{PLURAL:$1|1 Š“Š°Š½|$1 Š“Š°Š½Š°}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 сŠ°Ń‚|$1 сŠ°Ń‚Š°|$1 сŠ°Ń‚Šø}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 Š¼ŠøŠ½ŃƒŃ‚|$1 Š¼ŠøŠ½ŃƒŃ‚Š°}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 сŠµŠŗуŠ½Š“|$1 сŠµŠŗуŠ½Š“Šµ|$1 сŠµŠŗуŠ½Š“Šø}}",
+ "timedmedia-reset": "ŠŸŠ¾Š½ŠøштŠø ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµ",
+ "timedmedia-reset-confirm": "ŠŸŠ¾Š½ŠøштŠ°Š²Š°ŃšŠµ Š¾Š²Š¾Š³ ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠ° ћŠµ уŠŗŠ»Š¾Š½ŠøтŠø ŠæŠ¾ŃŃ‚Š¾Ń˜ŠµŃ›Ńƒ Š“Š°Ń‚Š¾Ń‚ŠµŠŗу (Š°ŠŗŠ¾ ŠæŠ¾ŃŃ‚Š¾Ń˜Šø) Šø Š²Ń€Š°Ń‚ŠøтŠø ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµ Š½Š° сŠæŠøсŠ°Šŗ Š·Š°Š“Š°Ń‚Š°ŠŗŠ°. ŠžŠ²Š° рŠ°Š“њŠ° Š¼Š¾Š¶Šµ Š“Š° ŠæŠ¾Ń‚Ń€Š°Ń˜Šµ. <br /><br />\nŠ–ŠµŠ»ŠøтŠµ Š»Šø Š“Š° Š½Š°ŃŃ‚Š°Š²ŠøтŠµ?",
+ "timedmedia-reset-error": "Š“Ń€ŠµŃˆŠŗŠ° ŠæрŠø ŠæŠ¾Š½ŠøштŠ°Š²Š°ŃšŃƒ Š·Š°Š“Š°Ń‚Š°ŠŗŠ° Š·Š° ŠæрŠµŠŗŠ¾Š“ŠøрŠ°ŃšŠµ.",
+ "timedmedia-ogg": "Ogg",
+ "timedmedia-webm": "WebM",
+ "timedmedia-flac": "FLAC",
+ "timedmedia-source-file": "Š˜Š·Š²Š¾Ń€Š½Šø $1",
+ "timedmedia-source-file-desc": "Š˜Š·Š²Š¾Ń€Š½Šø $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Š¢ŠøŠæ Š“Š°Ń‚Š¾Ń‚ŠµŠŗŠµ $1 ($2)",
+ "timedmedia-derivative-160p.ogv": "Ogg 160Šæ",
+ "timedmedia-derivative-desc-160p.ogv": "ŠŠøсŠŗŠ¾ŠæрŠ¾ŠæусŠ½Šø .ogg Š²ŠøŠ“ŠµŠ¾ (160Šæ)",
+ "timedmedia-derivative-360p.ogv": "Ogg 360Šæ",
+ "timedmedia-derivative-desc-360p.ogv": "Ogg Š²ŠøŠ“ŠµŠ¾ Š·Š° ŠµŠ¼ŠøтŠ¾Š²Š°ŃšŠµ (360Šæ)",
+ "timedmedia-derivative-480p.ogv": "Ogg 480Šæ",
+ "timedmedia-derivative-desc-480p.ogv": "Ogg Š²ŠøŠ“ŠµŠ¾ Š·Š° ŠµŠ¼ŠøтŠ¾Š²Š°ŃšŠµ (480Šæ)",
+ "timedmedia-derivative-720p.ogv": "Ogg 720Šæ",
+ "timedmedia-derivative-desc-720p.ogv": "Š’ŠøсŠ¾ŠŗŠ¾ŠŗŠ²Š°Š»ŠøтŠµŃ‚Š½Šø .ogg Š²ŠøŠ“ŠµŠ¾ Š·Š° ŠæрŠµŃƒŠ·ŠøŠ¼Š°ŃšŠµ (720Šæ)",
+ "timedmedia-derivative-360p.webm": "WebM 360Šæ",
+ "timedmedia-derivative-desc-360p.webm": "WebM Š·Š° ŠµŠ¼ŠøтŠ¾Š²Š°ŃšŠµ (360Šæ)",
+ "timedmedia-derivative-480p.webm": "WebM 480Šæ",
+ "timedmedia-derivative-desc-480p.webm": "WebM Š·Š° ŠµŠ¼ŠøтŠ¾Š²Š°ŃšŠµ (480Šæ)",
+ "timedmedia-derivative-720p.webm": "WebM 720Šæ",
+ "timedmedia-derivative-desc-720p.webm": "Š’ŠøсŠ¾ŠŗŠ¾ŠŗŠ²Š°Š»ŠøтŠµŃ‚Š½Šø WebM Š·Š° ŠæрŠµŃƒŠ·ŠøŠ¼Š°ŃšŠµ (720Šæ)",
+ "timedmedia-subtitle-language": "$1 ($2) тŠøтŠ»Š¾Š²Šø",
+ "timedmedia-subtitle-no-video": "ŠŠµŠ¼Š° Š²ŠøŠ“ŠµŠ¾-сŠ½ŠøŠ¼Š°ŠŗŠ° ŠæŠ¾Š²ŠµŠ·Š°Š½Šøх сŠ° тŠµŠŗућŠ¾Š¼ стрŠ°Š½ŠøцŠ¾Š¼ с тŠøтŠ»Š¾Š²ŠøŠ¼Š°",
+ "timedmedia-subtitle-no-subtitles": "Š¢Ń€ŠµŠ½ŃƒŃ‚Š½Š¾ Š½ŠµŠ¼Š° $1 тŠøтŠ»Š¾Š²Š° Š·Š° Š¾Š²Š°Ń˜ Š²ŠøŠ“ŠµŠ¾-сŠ½ŠøŠ¼Š°Šŗ. ŠœŠ¾Š¶ŠµŃ‚Šµ Š“Š° Šøх Š“Š¾Š“Š°Ń‚Šµ тŠ°ŠŗŠ¾ штŠ¾ ћŠµŃ‚Šµ [{{fullurl:{{FULLPAGENAME}}|action=edit}} урŠµŠ“ŠøтŠø стрŠ°Š½Šøцу]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/sr-el.json b/extensions/TimedMediaHandler/i18n/sr-el.json
new file mode 100644
index 00000000..936e1e92
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/sr-el.json
@@ -0,0 +1,53 @@
+{
+ "@metadata": {
+ "authors": [
+ "Michaello",
+ "Milicevic01",
+ "Rancher"
+ ]
+ },
+ "timedmedia-desc": "Obrađivač za zvuk, video i usklađeni tekst, s podrÅ”kom za formate WebM, Ogg Theora, Vorbis i SRT",
+ "timedmedia-ogg-short-audio": "Ogg $1 zvučna datoteka, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 video-snimak, $2.",
+ "timedmedia-ogg-short-general": "Ogg $1 medijska datoteka, $2.",
+ "timedmedia-ogg-long-audio": "Ogg $1 zvučna datoteka, dužina $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 video-snimak, trajanje $2, $4 Ɨ $5 piksela, $3.",
+ "timedmedia-ogg-long-multiplexed": "Multipleksirani .ogg audio/video snimak, $1, trajanje $2, $4 Ɨ $5 piksela, $3.",
+ "timedmedia-ogg-long-general": "Ogg medijska datoteka, dužina $2, $3.",
+ "timedmedia-ogg-long-error": "Neispravna .ogg datoteka: $1.",
+ "timedmedia-no-player-js": "Žao nam je, ali vaÅ”em pregledaču je onemogućena javaskripta ili nemate odgovarajući plejer.<br />\nMožete <a href=\"$1\">preuzeti klip</a> ili <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">preuzeti plejer</a> da reprodukujete klip u vaÅ”em pregledaču.",
+ "timedmedia-more": "ViŔe...",
+ "timedmedia-dismiss": "Zatvori",
+ "timedmedia-download": "Preuzmi datoteku",
+ "timedmedia-desc-link": "Podaci o ovoj datoteci",
+ "timedmedia-days": "{{PLURAL:$1|1 dan|$1 dana}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 sat|$1 sata|$1 sati}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minut|$1 minuta}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 sekund|$1 sekunde|$1 sekundi}}",
+ "timedmedia-reset": "PoniŔti prekodiranje",
+ "timedmedia-reset-confirm": "PoniÅ”tavanje ovog prekodiranja će ukloniti postojeću datoteku (ako postoji) i vratiti prekodiranje na spisak zadataka. Ova radnja može da potraje. <br /><br />\nŽelite li da nastavite?",
+ "timedmedia-reset-error": "GreŔka pri poniŔtavanju zadataka za prekodiranje.",
+ "timedmedia-ogg": "Ogg",
+ "timedmedia-webm": "WebM",
+ "timedmedia-source-file": "Izvorni $1",
+ "timedmedia-source-file-desc": "Izvorni $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Tip datoteke $1 ($2)",
+ "timedmedia-derivative-160p.ogv": "Ogg 160p",
+ "timedmedia-derivative-desc-160p.ogv": "Niskopropusni .ogg video (160p)",
+ "timedmedia-derivative-360p.ogv": "Ogg 360p",
+ "timedmedia-derivative-desc-360p.ogv": "Ogg video za emitovanje (360p)",
+ "timedmedia-derivative-480p.ogv": "Ogg 480p",
+ "timedmedia-derivative-desc-480p.ogv": "Ogg video za emitovanje (480p)",
+ "timedmedia-derivative-720p.ogv": "Ogg 720p",
+ "timedmedia-derivative-desc-720p.ogv": "Visokokvalitetni .ogg video za preuzimanje (720p)",
+ "timedmedia-derivative-360p.webm": "WebM 360p",
+ "timedmedia-derivative-desc-360p.webm": "WebM za emitovanje (360p)",
+ "timedmedia-derivative-480p.webm": "WebM 480p",
+ "timedmedia-derivative-desc-480p.webm": "WebM za emitovanje (480p)",
+ "timedmedia-derivative-720p.webm": "WebM 720p",
+ "timedmedia-derivative-desc-720p.webm": "Visokokvalitetni WebM za preuzimanje (720p)",
+ "timedmedia-subtitle-language": "$1 ($2) titlovi",
+ "timedmedia-subtitle-no-video": "Nema video-snimaka povezanih sa tekućom stranicom s titlovima",
+ "timedmedia-subtitle-no-subtitles": "Trenutno nema $1 titlova za ovaj video-snimak. Možete da ih dodate tako Å”to ćete [{{fullurl:{{FULLPAGENAME}}|action=edit}} urediti stranicu]",
+ "timedmedia-file": "Datoteka"
+}
diff --git a/extensions/TimedMediaHandler/i18n/stq.json b/extensions/TimedMediaHandler/i18n/stq.json
new file mode 100644
index 00000000..9657a896
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/stq.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "Pyt"
+ ]
+ },
+ "timedmedia-desc": "Stjuurengsprogramm foar Ogg Theora- un Vorbis-DoatƤie, inklusive n JavaScript-Ouspielsoftware",
+ "timedmedia-ogg-short-audio": "Ogg-$1-AudiodoatƤi, $2",
+ "timedmedia-ogg-short-video": "Ogg-$1-VideodoatƤi, $2",
+ "timedmedia-ogg-short-general": "Ogg-$1-MediadoatƤi, $2",
+ "timedmedia-ogg-long-audio": "Ogg-$1-AudiodoatƤi, Loangte: $2, $3",
+ "timedmedia-ogg-long-video": "Ogg-$1-VideodoatƤi, Loangte: $2, $4Ɨ$5 Pixel, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg-Audio-/Video-DoatƤi, $1, Loangte: $2, $4Ɨ$5 Pixel, $3",
+ "timedmedia-ogg-long-general": "Ogg-MediadoatƤi, Loangte: $2, $3",
+ "timedmedia-ogg-long-error": "Uungultige Ogg-DoatƤi: $1",
+ "timedmedia-more": "Optione ā€¦",
+ "timedmedia-dismiss": "Sluute",
+ "timedmedia-download": "DoatƤi spiekerje",
+ "timedmedia-desc-link": "Uur disse DoatƤi"
+}
diff --git a/extensions/TimedMediaHandler/i18n/su.json b/extensions/TimedMediaHandler/i18n/su.json
new file mode 100644
index 00000000..2fddd5c2
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/su.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kandar"
+ ]
+ },
+ "timedmedia-ogg-short-audio": "Koropak sora $1 ogg, $2",
+ "timedmedia-ogg-short-video": "Koropak vidƩo $1 ogg, $2",
+ "timedmedia-ogg-short-general": "Koropak mƩdia $1 ogg, $2",
+ "timedmedia-ogg-long-audio": "Koropak sora $1 ogg, lilana $2, $3",
+ "timedmedia-ogg-long-video": "Koropak vidĆ©o $1 ogg, lilana $2, $4Ɨ$5 piksel, $3",
+ "timedmedia-ogg-long-multiplexed": "Koropak sora/vidĆ©o ogg multiplĆ©ks, $1, lilana $2, $4Ɨ$5 piksel, $3 gembleng",
+ "timedmedia-ogg-long-general": "Koropak mƩdia ogg, lilana $2, $3",
+ "timedmedia-ogg-long-error": "Koropak ogg teu valid: $1",
+ "timedmedia-more": "Lianna...",
+ "timedmedia-dismiss": "Tutup",
+ "timedmedia-download": "Bedol",
+ "timedmedia-desc-link": "Ngeunaan ieu koropak"
+}
diff --git a/extensions/TimedMediaHandler/i18n/sv.json b/extensions/TimedMediaHandler/i18n/sv.json
new file mode 100644
index 00000000..dbba4c91
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/sv.json
@@ -0,0 +1,125 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ainali",
+ "Jon Harald SĆøby",
+ "Jopparn",
+ "Lejonel",
+ "Lokal Profil",
+ "Rotsee",
+ "Skalman",
+ "WikiPhoenix",
+ "Abbedabb"
+ ]
+ },
+ "timedmedia-desc": "Hanterare fƶr ljud-, video- och tidsbestƤmd text, med stƶd fƶr format WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Ogg $1 ljudfil, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 videofil, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 mediafil, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 ljudfil, lƤngd $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 videofil, lƤngd $2, $4Ɨ$5 pixel, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg multiplexad ljud/video-fil, $1, lƤngd $2, $4Ɨ$5 pixel, $3 totalt",
+ "timedmedia-ogg-long-general": "Ogg mediafil, lƤngd $2, $3",
+ "timedmedia-ogg-long-error": "Felaktig Ogg-fil: $1",
+ "timedmedia-ogg-long-no-streams": "Ogg-mediafil. Varning: Ingen av de omkodare som anvƤnds i denna fil kunde identifieras.",
+ "timedmedia-webm-short-video": "WebM $1 videofil, $2",
+ "timedmedia-webm-long-video": "WebM-fil fƶr ljud/video, $1, lƤngd $2, $4 Ɨ $5 pixlar, $3 totalt",
+ "timedmedia-flac-short-audio": "FLAC-ljudfil, $1",
+ "timedmedia-flac-long-audio": "FLAC-ljudfil, lƤngd $1, $2 totalt",
+ "timedmedia-wav-short-audio": "WAV-ljudfil, $1",
+ "timedmedia-wav-long-audio": "WAV-ljudfil, lƤngd $1, $2 total",
+ "timedmedia-wav-pcm-required": "Du kan enbart ladda upp PCM (Pulskodsmodulerad) WAV",
+ "timedmedia-mp4-short-video": "MP4 $1 videofil, $2",
+ "timedmedia-mp4-long-video": "MP4-fil fƶr ljud/video, $1, lƤngd $2, $4 Ɨ $5 pixlar, $3 totalt",
+ "timedmedia-no-player-js": "TyvƤrr, din webblƤsare har antingen JavaScript inaktiverat eller inte nƄgon spelare som stƶds.<br />\nDu kan <a href=\"$1\">ladda ner klippet</a> eller <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">hƤmta en spelare</a> fƶr att spela upp klippet i din webblƤsare.",
+ "timedmedia-more": "Mer...",
+ "timedmedia-dismiss": "StƤng",
+ "timedmedia-download": "Ladda ner filen",
+ "timedmedia-play-media": "Spela upp media",
+ "timedmedia-desc-link": "Om filen",
+ "timedmedia-oggThumb-version": "OggHandler krƤver oggThumb version $1 eller senare.",
+ "timedmedia-oggThumb-failed": "oggThumb misslyckades med att skapa miniatyrbilden.",
+ "timedmedia-status-header": "Transkodningsstatus",
+ "timedmedia-update-status": "Uppdatera transkodningsstatus",
+ "timedmedia-status": "Status",
+ "timedmedia-status-unknown": "OkƤnd status",
+ "timedmedia-transcodebitrate": "Bithastighet",
+ "timedmedia-transcodeduration": "Kodningstid",
+ "timedmedia-transcodeinfo": "Format",
+ "timedmedia-actions": "ƅtgƤrder",
+ "timedmedia-direct-link": "Ladda ned",
+ "timedmedia-not-ready": "Inte redo",
+ "timedmedia-completed-on": "Slutfƶrdes $1",
+ "timedmedia-error-on": "Fel $1",
+ "timedmedia-started-transcode": "Startade $1 sedan. $2",
+ "timedmedia-percent-done": "UngefƤr $1% klar",
+ "timedmedia-in-job-queue": "Lades till i jobbkƶn fƶr $1sedan",
+ "timedmedia-unknown-target-size": "OkƤnd mƄlstorlek, $1-kodad",
+ "timedmedia-days": "{{PLURAL:$1|1 dag|$1 dagar}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 timme|$1 timmar}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minut|$1 minuter}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 sekund|$1 sekunder}}",
+ "timedmedia-reset": "NollstƤll transkodningen",
+ "timedmedia-reset-confirm": "NollstƤllning av denna transkodning tar bort alla befintliga filer (om nƤrvarande), och lƤgger Ć„ter till transkodningen till jobbkƶn. Det kommer att ta tid att om-transkoda.<br /><br />\nƄr du sƤker pĆ„ att du vill fortsƤtta?",
+ "timedmedia-reset-error": "Fel i nollstƤllningen av transkod-jobbet.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 KƤlla",
+ "timedmedia-source-file-desc": "Ursprunglig $1-fil, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Ursprunglig $1-fil ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "LĆ„g bandbredd Ogg-video (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Webbstrƶmningsbar Ogg-video (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Webbstrƶmningsbar Ogg-video (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Hƶgkvalitets nedladdningsbar Ogg-video (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "Nedladdningsbar Ogg-video i full HD (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "Webbstrƶmningsbar WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "Webbstrƶmningsbar WebM (360P)",
+ "timedmedia-derivative-desc-480p.webm": "Webbstrƶmningsbar WebM (480P)",
+ "timedmedia-derivative-desc-720p.webm": "Hƶgkvalitets nedladdningsbar WebM (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "Nedladdningsbar WebM i full HD (1080P)",
+ "timedmedia-derivative-360p.vp9.webm": "VP9 360P",
+ "timedmedia-derivative-480p.vp9.webm": "VP9 480P",
+ "timedmedia-derivative-720p.vp9.webm": "VP9 720P",
+ "timedmedia-derivative-1080p.vp9.webm": "VP9 1080P",
+ "timedmedia-derivative-desc-320p.mp4": "EnhetsvƤnlig MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "Webbstrƶmningsbar MP4 (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "HD-kvalitet MP4 (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "MP4 med kvalitet i full HD (1080P)",
+ "timedmedia-subtitle-new": "Skapa ny ƶversƤttning eller redigera befintlig",
+ "timedmedia-subtitle-new-desc": "VƤlj sprƄk och tryck pƄ knappen '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "GĆ„",
+ "timedmedia-subtitle-language": "$1 ($2) undertexter",
+ "timedmedia-subtitle-no-video": "Det finns ingen video som Ƥr associerade med den aktuella undertextssidan",
+ "timedmedia-subtitle-no-subtitles": "Det finns fƶr nƤrvarande ingen textning pƄ $1 fƶr denna video, du kan [{{fullurl:{{FULLPAGENAME}}|action=edit}} redigera denna sida] fƶr att lƤgga till dem",
+ "timedmedia-subtitle-remote": "Undertexter (timed text) fƶr denna fil finns pƄ $1",
+ "timedmedia-subtitle-remote-link": "Du kan [$1 visa beskrivningssidan] fƶr denna fil pƄ $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 videoklipp|$1 videoklipp}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg-video|$1 Ogg-videor}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM-video|$1 WebM-videor}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transkodning|$1 transkodningar}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 aktiv transkodning|$1 aktiva transkodningar}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 kƶad transkodning|$1 kƶade transkodningar}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 misslyckad transkodning|$1 misslyckade transkodningar}}",
+ "timedmedia-file": "Fil",
+ "timedmedia-audios": "{{PLURAL:$1|$1 ljudfil|$1 ljudfiler}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ogg-ljudfil|$1 Ogg-ljudfiler}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 FLAC-ljudfil|$1 FLAC-ljudfiler}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 WAV-ljudfil|$1 WAV-ljudfiler}}",
+ "right-transcode-reset": "ƅterstƤll misslyckade eller transkodade videor sĆ„ att de Ć„ter infogas i jobbkƶn.",
+ "right-transcode-status": "Visa [[Special:TimedMediaHandler|information om den aktuella transkodningsaktivitetet]]",
+ "action-transcode-status": "visa den aktuella transkodningsstatusen",
+ "orphanedtimedtext": "FƶrƤldralƶsa TimedText-sidor",
+ "orphanedtimedtext-summary": "Lista ƶver [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] sidor som inte har en motsvarande fil.",
+ "orphanedtimedtext-unsupported": "Denna special-sida har bara stƶd pƄ MySQL-databaser.",
+ "orphanedtimedtext-notimedtext": "TimedText Ƥr inte aktiverat pƄ denna wiki.",
+ "apihelp-query+transcodestatus-description": "HƤmta transkodningsstatusen fƶr en viss filsida.",
+ "apihelp-query+transcodestatus-example-1": "HƤmta transkodningsstatusen fƶr [[:File:Clip.webm]]",
+ "apihelp-query+videoinfo-description": "Utƶkar imageinfo till att inkludera kƤllinformation fƶr video (derivat)",
+ "apihelp-query+videoinfo-param-prop": "Vilken videoinformation att hƤmta:\n;timestamp:LƤgger till tidsstƤmpeln fƶr den uppladdade versionen.\n;user:LƤgger till anvƤndaren som laddade upp videoversionen.\n;userid:LƤgger till anvƤndar-ID:et som laddade upp videoversionen.\n;comment:Kommentar fƶr versionen.\n;parsedcomment:Tolka kommentaren fƶr versionen.\n;canonicaltitle:LƤgger till den kanoniska titeln fƶr videofilen.\n;url:Ger URL:en till videon och beskrivningssidan.\n;size:LƤgger till storleken pƄ videon i bytes, dess hƶjd och vidd. Sidantal och varaktighet om applicerbart.\n;dimensions:Alias fƶr size.\n;sha1:LƤgger till SHA-1-hash fƶr videon.\n;mime:LƤgger till MIME-typ fƶr videon.\n;thumbmime:LƤgger till MIME-typ fƶr videons miniatyr (krƤver url och parametern $1urlwidth).\n;mediatype:LƤgger till mediatyp fƶr videon.\n;metadata:Listar Exif-metadata fƶr versionen av videon.\n;commonmetadata:Listar filformatgenerisk metadata fƶr versionen av videon.\n;extmetadata:Listar formaterad metadata kombinerad frƄn flera kƤllor. Resultaten Ƥr HTML-formaterade.\n;archivename:LƤgger till filnamn fƶr arkivversionen fƶr icke-senaste versioner.\n;bitdepth:LƤgger till bitdjup fƶr versionen.\n;uploadwarning:AnvƤnds av [[Special:Upload]]-sidan fƶr att fƄ information om en existerande fil. Ej avsedd fƶr bruk utanfƶr Mediawiki core.\n;derivatives:LƤgger till en lista fƶr de olika format- och kvalitetsversionerna fƶr en audio- eller videofil som Ƥr tillgƤngliga.",
+ "apihelp-query+videoinfo-example-1": "HƤmta information om [[:File:Folgers.ogv]]",
+ "apihelp-transcodereset-description": "AnvƤndare med \"transcode-reset\"-rƤttigheten kan ƄterstƤlla och kƶra om ett transkodningsjobb.",
+ "apihelp-transcodereset-param-title": "Mediefilens titel.",
+ "apihelp-transcodereset-param-transcodekey": "Den transkodningsnyckel du ƶnskar ƄterstƤlla. HƤmta frƄn [[Special:ApiHelp/query+transcodestatus|action=query&prop=transcodestatus]].",
+ "apihelp-transcodereset-example-1": "ƅterstƤll alla transkodningar fƶr [[:File:Clip.webm]]",
+ "apihelp-transcodereset-example-2": "ƅterstƤll \"360_560kbs.webm\"-transkodningsnyckeln fƶr [[:File:Clip.webm]]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/sw.json b/extensions/TimedMediaHandler/i18n/sw.json
new file mode 100644
index 00000000..51d86efc
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/sw.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Stephenwanjau"
+ ]
+ },
+ "timedmedia-download": "Pakua faili",
+ "timedmedia-desc-link": "Kuhusu faili hii",
+ "timedmedia-status": "Hali",
+ "timedmedia-actions": "Vitendo",
+ "timedmedia-not-ready": "Haiko tayari",
+ "timedmedia-subtitle-new-go": "Nenda",
+ "timedmedia-file": "Faili"
+}
diff --git a/extensions/TimedMediaHandler/i18n/szl.json b/extensions/TimedMediaHandler/i18n/szl.json
new file mode 100644
index 00000000..105eeaa9
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/szl.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Krol111"
+ ]
+ },
+ "timedmedia-source-file": "ZdrzÅÆdło ($1)",
+ "timedmedia-source-audio-file-desc": "Uoryginalny plik $1 ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ta.json b/extensions/TimedMediaHandler/i18n/ta.json
new file mode 100644
index 00000000..69410ef5
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ta.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "Balajijagadesh",
+ "Karthi.dr",
+ "Shanmugamp7",
+ "ą®®ą®¤ą®©ą®¾ą®¹ą®°ą®©ąÆ",
+ "Jayarathina"
+ ]
+ },
+ "timedmedia-ogg-long-general": "Ogg ą®Šą®Ÿą®• ą®•ąÆ‹ą®ŖąÆą®ŖąÆ, ą®ØąÆ€ą®³ą®®ąÆ $2 , $3",
+ "timedmedia-ogg-long-error": "ą®šąÆ†ą®²ąÆą®²ą®¾ą®¤ ogg ą®•ąÆ‹ą®ŖąÆą®ŖąÆ: $1",
+ "timedmedia-no-player-js": "ą®®ą®©ąÆą®©ą®æą®•ąÆą®•ą®µąÆą®®ąÆ, ą®‰ą®™ąÆą®•ą®³ąÆ ą®‰ą®²ą®¾ą®µą®æą®Æą®æą®²ąÆ ą®œą®¾ą®µą®¾ą®øąÆą®•ą®æą®°ą®æą®ŖąÆą®ŸąÆ ą®®ąÆą®Ÿą®•ąÆą®•ą®ŖąÆą®Ŗą®ŸąÆą®Ÿą®æą®°ąÆą®•ąÆą®•ą®æą®©ąÆą®±ą®¤ąÆ ą®…ą®²ąÆą®²ą®¤ąÆ ą®¤ą®•ąÆą®ØąÆą®¤ ą®‡ą®Æą®•ąÆą®•ą®æ ą®‡ą®²ąÆą®²ąÆˆ.<br />\ną®ØąÆ€ą®™ąÆą®•ą®³ąÆ <a href=\"$1\">ą®‡ą®•ąÆą®•ąÆ‹ą®ŖąÆą®Ŗą®æą®©ąÆˆ ą®¤ą®°ą®µą®æą®°ą®•ąÆą®•ą®®ąÆ ą®šąÆ†ą®ÆąÆą®Æą®²ą®¾ą®®ąÆ</a> ą®…ą®²ąÆą®²ą®¤ąÆ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ą®¤ą®•ąÆą®ØąÆą®¤ ą®‡ą®Æą®•ąÆą®•ą®æą®Æą®æą®©ąÆˆ ą®¤ą®°ą®µą®æą®°ą®•ąÆą®•ą®®ąÆ ą®šąÆ†ą®ÆąÆą®¤ąÆ</a> ą®‡ą®¤ą®©ąÆˆ ą®‰ą®™ąÆą®•ą®³ąÆ ą®‰ą®²ą®¾ą®µą®æą®Æą®æą®²ąÆ ą®“ą®ŸąÆą®Ÿą®²ą®¾ą®®ąÆ.",
+ "timedmedia-more": "ą®®ąÆ‡ą®²ąÆą®®ąÆ...",
+ "timedmedia-dismiss": "ą®®ąÆ‚ą®ŸąÆą®•",
+ "timedmedia-download": "ą®•ąÆ‹ą®ŖąÆą®ŖąÆˆ ą®Ŗą®¤ą®æą®µą®æą®±ą®•ąÆą®•ą®®ąÆ ą®šąÆ†ą®ÆąÆ",
+ "timedmedia-play-media": "ą®Šą®Ÿą®•ą®¤ąÆą®¤ąÆˆ ą®“ą®Ÿą®µą®æą®ŸąÆ",
+ "timedmedia-desc-link": "ą®‡ą®ØąÆą®¤ą®•ąÆ ą®•ąÆ‹ą®ŖąÆą®ŖąÆˆą®ŖąÆ ą®Ŗą®±ąÆą®±ą®æ",
+ "timedmedia-status": "ą®Øą®æą®²ąÆˆ",
+ "timedmedia-status-unknown": "ą®…ą®±ą®æą®Æą®ŖąÆą®Ŗą®Ÿą®¾ą®¤ ą®Øą®æą®²ąÆˆ",
+ "timedmedia-actions": "ą®šąÆ†ą®Æą®²ąÆą®•ą®³ąÆ",
+ "timedmedia-not-ready": "ą®¤ą®Æą®¾ą®°ą®¾ą®• ą®‡ą®²ąÆą®²ąÆˆ",
+ "timedmedia-percent-done": "ą®ą®±ą®¤ąÆą®¤ą®¾ą®“ $1% ą®®ąÆą®Ÿą®æą®ØąÆą®¤ą®¤ąÆ",
+ "timedmedia-mp4": "ą®Žą®®ąÆą®Ŗą®æ4",
+ "timedmedia-source-file": "$1 ą®®ąÆ‚ą®²ą®®ąÆ",
+ "timedmedia-source-file-desc": "ą®®ąÆ‚ą®² $1, $2 Ɨ $3 ($4)",
+ "timedmedia-subtitle-new": "ą®ŖąÆą®¤ą®æą®Æ ą®®ąÆŠą®“ą®æą®ŖąÆ†ą®Æą®°ąÆą®ŖąÆą®ŖąÆˆ ą®‰ą®°ąÆą®µą®¾ą®•ąÆą®•ą®µąÆą®®ąÆ ą®…ą®²ąÆą®²ą®¤ąÆ ą®‰ą®³ąÆą®³ą®¤ąÆˆą®¤ąÆ ą®¤ąÆŠą®•ąÆą®•ąÆą®•ą®µąÆą®®ąÆ",
+ "timedmedia-subtitle-new-go": "ą®šąÆ†ą®²ąÆ",
+ "timedmedia-subtitle-language": "$1 ($2) ą®¤ąÆą®£ąÆˆą®¤ąÆą®¤ą®²ąÆˆą®ŖąÆą®ŖąÆą®•ąÆą®•ą®³ąÆ",
+ "timedmedia-videos": "{{PLURAL:$1|$1 ą®•ą®¾ą®£ąÆŠą®³ą®æ|$1 ą®•ą®¾ą®£ąÆŠą®³ą®æą®•ą®³ąÆ}}",
+ "timedmedia-file": "ą®•ąÆ‹ą®ŖąÆą®ŖąÆ"
+}
diff --git a/extensions/TimedMediaHandler/i18n/tcy.json b/extensions/TimedMediaHandler/i18n/tcy.json
new file mode 100644
index 00000000..622447e7
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/tcy.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "VASANTH S.N."
+ ]
+ },
+ "timedmedia-source-file": "$1 ą²®ą³‚ą²²",
+ "timedmedia-source-audio-file-desc": "ą²®ą³‚ą²² $1 ą²•ą²”ą²¤ ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/te.json b/extensions/TimedMediaHandler/i18n/te.json
new file mode 100644
index 00000000..96cc2e73
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/te.json
@@ -0,0 +1,37 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kiranmayee",
+ "Veeven",
+ "ą°µą±ˆą°œą°¾ą°øą°¤ą±ą°Æ",
+ "ą°°ą°¹ą±ą°®ą°¾ą°Øą±ą°¦ą±ą°¦ą±€ą°Øą±"
+ ]
+ },
+ "timedmedia-ogg-short-audio": "Ogg $1 ą°¶ą±ą°°ą°¾ą°µą±ą°Æą°• ą°«ą±ˆą°²ą±, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 ą°µą±€ą°”ą°æą°Æą±‹ ą°«ą±ˆą°²ą±, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 ą°®ą±€ą°”ą°æą°Æą°¾ ą°«ą±ˆą°²ą±, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 ą°¶ą±ą°°ą°µą°£ ą°«ą±ˆą°²ą±, ą°Øą°æą°”ą°æą°µą°æ $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 ą°µą±€ą°”ą°æą°Æą±‹ ą°«ą±ˆą°²ą±, ą°Øą°æą°”ą°æą°µą°æ $2, $4Ɨ$5 ą°Ŗą°æą°•ą±ą°øą±†ą°³ą±ą°³ą±, $3",
+ "timedmedia-ogg-long-multiplexed": "ą°“ą°—ą± ą°®ą°²ą±ą°Ÿą°æą°Ŗą±ą°²ą±†ą°•ą±ą°øą±ą°”ą± ą°¶ą±ą°°ą°µą°£/ą°¦ą±ƒą°¶ą±ą°Æą°• ą°«ą±ˆą°²ą±, $1, ą°Øą°æą°”ą°æą°µą°æ $2, $4Ɨ$5 ą°Ŗą°æą°•ą±ą°øą±†ą°³ą±ą°³ą±, $3 ą°®ą±Šą°¤ą±ą°¤ą°‚",
+ "timedmedia-ogg-long-general": "Ogg ą°®ą±€ą°”ą°æą°Æą°¾ ą°«ą±ˆą°²ą±, ą°Øą°æą°”ą°æą°µą°æ $2, $3",
+ "timedmedia-ogg-long-error": "ą°¤ą°Ŗą±ą°Ŗą±ą°”ą± ogg ą°«ą±ˆą°²ą±: $1",
+ "timedmedia-no-player-js": "ą°•ą±ą°·ą°®ą°æą°‚ą°šą°¾ą°²ą°æ, ą°®ą±€ ą°µą°æą°¹ą°¾ą°°ą°æą°£ą°æą°²ą±‹ ą°œą°¾ą°µą°¾ą°øą±ą°•ą±ą°°ą°æą°Ŗą±ą°Ÿą± ą°…ą°šą±‡ą°¤ą°Øą°‚ą°—ą°¾ ą°‰ą°‚ą°¦ą°æ ą°²ą±‡ą°¦ą°¾ ą°®ą±€ ą°µą°æą°¹ą°¾ą°°ą°æą°£ą°æą°•ą°æ ą°¤ą°—ą°æą°Ø ą°¦ą±ƒą°¶ą±ą°Æą°šą°¾ą°²ą°•ą°‚ ą°…ą°‚ą°¦ą±ą°¬ą°¾ą°Ÿą±ą°²ą±‹ ą°²ą±‡ą°¦ą±.<br />\ną°®ą±€ą°°ą± <a href=\"$1\">ą°®ą±€ą°°ą± ą°µą±€ą°”ą°æą°Æą±‹ ą°•ą±ą°²ą°æą°Ŗą± ą°Øą°æ ą°¦ą°æą°‚ą°šą±ą°•ą±‹ą°µą°šą±ą°šą±</a> ą°²ą±‡ą°¦ą°¾ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">ą°¦ą±ƒą°¶ą±ą°Æą°šą°¾ą°²ą°•ą°¾ą°Øą±ą°Øą°æ</a> ą°¦ą°æą°‚ą°Ŗą±ą°•ą±Šą°Øą°æ ą°ˆ ą°µą±€ą°”ą°æą°Æą±‹ ą°•ą±ą°²ą°æą°Ŗą± ą°Øą± ą°®ą±€ ą°µą°æą°¹ą°¾ą°°ą°æą°£ą°æą°²ą±‹ ą°šą±‚ą°”ą°µą°šą±ą°šą±.",
+ "timedmedia-more": "ą°®ą°°ą°æą°Øą±ą°Øą°æ...",
+ "timedmedia-dismiss": "ą°®ą±‚ą°øą°æą°µą±‡ą°Æą°æ",
+ "timedmedia-download": "ą°«ą±ˆą°²ą±ą°Øą°æ ą°¦ą°æą°—ą±ą°®ą°¤ą°æ ą°šą±‡ą°øą±ą°•ą±‹ą°‚ą°”ą°æ",
+ "timedmedia-desc-link": "ą°ˆ ą°«ą±ˆą°²ą± ą°—ą±ą°°ą°æą°‚ą°šą°æ",
+ "timedmedia-status": "ą°øą±ą°„ą°æą°¤ą°æ",
+ "timedmedia-status-unknown": "ą°¤ą±†ą°²ą°æą°Æą°Øą°æ ą°øą±ą°„ą°æą°¤ą°æ",
+ "timedmedia-actions": "ą°šą°°ą±ą°Æą°²ą±",
+ "timedmedia-days": "{{PLURAL:$1|1 ą°°ą±‹ą°œą±|$1 ą°°ą±‹ą°œą±ą°²ą±}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 ą°—ą°‚ą°Ÿ|$1 ą°—ą°‚ą°Ÿą°²ą±}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 ą°Øą°æą°®ą°æą°·ą°‚|$1 ą°Øą°æą°®ą°æą°·ą°¾ą°²ą±}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 ą°•ą±ą°·ą°£ą°‚|$1 ą°•ą±ą°·ą°£ą°¾ą°²ą±}}",
+ "timedmedia-source-file": "$1 ą°®ą±‚ą°²ą°‚",
+ "timedmedia-source-file-desc": "ą°…ą°øą°²ą± $1 ą°¦ą°øą±ą°¤ą±ą°°ą°‚, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "ą°…ą°øą°²ą± $1 ą°¦ą°øą±ą°¤ą±ą°°ą°‚ ($2)",
+ "timedmedia-subtitle-new-go": "ą°µą±†ą°³ą±ą°³ą±",
+ "timedmedia-subtitle-language": "$1 ($2) ą°‰ą°Ŗą°¶ą±€ą°°ą±ą°·ą°æą°•ą°²ą±",
+ "timedmedia-videos": "{{PLURAL:$1|$1 ą°µą±€ą°”ą°æą°Æą±‹|$1 ą°µą±€ą°”ą°æą°Æą±‹ą°²ą±}}",
+ "timedmedia-file": "ą°¦ą°øą±ą°¤ą±ą°°ą°‚"
+}
diff --git a/extensions/TimedMediaHandler/i18n/tg-cyrl.json b/extensions/TimedMediaHandler/i18n/tg-cyrl.json
new file mode 100644
index 00000000..abfda498
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/tg-cyrl.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ibrahim"
+ ]
+ },
+ "timedmedia-desc": "Š‘Š° Š“Š°ŃŃ‚Š³ŠøрŠ°Š½Š“Š°Šµ Š±Š°Ń€Š¾Šø ŠæŠ°Ń€Š²Š°Š½Š“Š°Ņ³Š¾Šø Ogg Theora Š²Š° Vorbis, Š±Š¾ ŠæŠ°Ń…ŃˆŠŗуŠ½Š°Š½Š“Š°Šø JavaScript",
+ "timedmedia-ogg-short-audio": "Ogg $1 ŠæŠ°Ń€Š²Š°Š½Š“Š°Šø сŠ°Š²Ń‚Ó£, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 ŠæŠ°Ń€Š²Š°Š½Š“Š°Šø Š½Š°Š²Š¾Ń€Ó£, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 ŠæŠ°Ń€Š²Š°Š½Š“Š°Šø рŠ°ŃŠ¾Š½Š°, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 ŠæŠ°Ń€Š²Š°Š½Š“Š°Šø сŠ°Š²Ń‚Ó£, тÓÆŠ» $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 ŠæŠ°Ń€Š²Š°Š½Š“Š°Šø Š½Š°Š²Š¾Ń€Ó£, тÓÆŠ» $2, $4Ɨ$5 ŠæŠøŠŗсŠµŠ»Ņ³Š¾, $3",
+ "timedmedia-ogg-long-multiplexed": "ŠŸŠ°Ń€Š²Š°Š½Š“Š°Šø Ogg сŠ°Š²Ń‚Ó£/Š½Š°Š²Š¾Ń€Ó£ ŠæŠµŃ‡ŠøŠ“Š°, $1, тÓÆŠ» $2, $4Ɨ$5 ŠæŠøŠŗсŠµŠ»Ņ³Š¾, Š“Š°Ń€ Š¼Š°Ņ·Š¼ÓÆъ $3",
+ "timedmedia-ogg-long-general": "ŠŸŠ°Ń€Š²Š°Š½Š“Š°Šø рŠ°ŃŠ¾Š½Š°Šø Ogg, тÓÆŠ» $2, $3",
+ "timedmedia-ogg-long-error": "ŠŸŠ°Ń€Š²Š°Š½Š“Š°Šø Ņ“Š°Š¹Ń€ŠøŠ¼ŠøŅ·Š¾Š·Šø ogg: $1",
+ "timedmedia-more": "Š‘ŠµŃˆŃ‚Š°Ń€...",
+ "timedmedia-dismiss": "Š‘Š°ŃŃ‚Š°Š½",
+ "timedmedia-download": "Š‘Š¾Ń€Š³ŠøрŠøŠø ŠæŠ°Ń€Š²Š°Š½Š“Š°",
+ "timedmedia-desc-link": "Š”Š°Ń€ Š±Š¾Ń€Š°Šø ŠøŠ½ ŠæŠ°Ń€Š²Š°Š½Š“Š°"
+}
diff --git a/extensions/TimedMediaHandler/i18n/tg-latn.json b/extensions/TimedMediaHandler/i18n/tg-latn.json
new file mode 100644
index 00000000..b32a59aa
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/tg-latn.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "Liangent"
+ ]
+ },
+ "timedmedia-desc": "Ba dastgirandae baroi parvandahoi Ogg Theora va Vorbis, bo paxşkunandai JavaScript",
+ "timedmedia-ogg-short-audio": "Ogg $1 parvandai savtī, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 parvandai navorī, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 parvandai rasona, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 parvandai savtī, tūl $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 parvandai navorÄ«, tÅ«l $2, $4Ɨ$5 pikselho, $3",
+ "timedmedia-ogg-long-multiplexed": "Parvandai Ogg savtÄ«/navorÄ« pecida, $1, tÅ«l $2, $4Ɨ$5 pikselho, dar maƧmÅ«' $3",
+ "timedmedia-ogg-long-general": "Parvandai rasonai Ogg, tūl $2, $3",
+ "timedmedia-ogg-long-error": "Parvandai Ę£ajrimiƧozi ogg: $1",
+ "timedmedia-more": "Beştar...",
+ "timedmedia-dismiss": "Bastan",
+ "timedmedia-download": "Borgiriji parvanda",
+ "timedmedia-desc-link": "Dar borai in parvanda"
+}
diff --git a/extensions/TimedMediaHandler/i18n/tk.json b/extensions/TimedMediaHandler/i18n/tk.json
new file mode 100644
index 00000000..7b0d49a8
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/tk.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hanberke"
+ ]
+ },
+ "timedmedia-desc": "Ogg Theora we Vorbis faĆ½llary Ć¼Ć§in işleĆ½ji, JavaScript pleĆ½eri bilen bilelikde",
+ "timedmedia-ogg-short-audio": "Ogg $1 ses faĆ½ly, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 wideo faĆ½ly, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 media faĆ½ly, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 ses faĆ½ly, uzynlyk $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 wideo faĆ½ly, uzynlyk $2, $4Ɨ$5 piksel, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg multipleks audio/wideo faĆ½ly, $1, uzynlyk $2, $4Ɨ$5 piksel, $3 jemi",
+ "timedmedia-ogg-long-general": "Ogg media faĆ½ly, uzynlyk $2, $3",
+ "timedmedia-ogg-long-error": "NƤdogry ogg faĆ½ly: $1",
+ "timedmedia-more": "Has kƶp...",
+ "timedmedia-dismiss": "Ɲap",
+ "timedmedia-download": "FaĆ½l dĆ¼ÅŸĆ¼r",
+ "timedmedia-desc-link": "Bu faĆ½l hakda"
+}
diff --git a/extensions/TimedMediaHandler/i18n/tl.json b/extensions/TimedMediaHandler/i18n/tl.json
new file mode 100644
index 00000000..9aa38812
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/tl.json
@@ -0,0 +1,84 @@
+{
+ "@metadata": {
+ "authors": [
+ "AnakngAraw",
+ "Sky Harbor"
+ ]
+ },
+ "timedmedia-desc": "Tagahawak para sa audio, bidyo at inoorasang teksto, na may pagtangkilik ng anyo para sa WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "$1 na talaksang pangtunog ng Ogg, $2",
+ "timedmedia-ogg-short-video": "$1 talaksang pampalabas (''video'') ng Ogg, $2",
+ "timedmedia-ogg-short-general": "$1 talaksang pangmidya ng Ogg, $2",
+ "timedmedia-ogg-long-audio": "$1 talaksang pantunog ng Ogg, haba $2, $3",
+ "timedmedia-ogg-long-video": "$1 talaksan ng palabas ng Ogg, haba $2, $4Ɨ$5 mga piksel, $3",
+ "timedmedia-ogg-long-multiplexed": "magkasanib at nagsasabayang talaksang nadirinig o audio/palabas ng Ogg, $1, haba $2, $4Ɨ$5 mga piksel, $3 sa kalahatan",
+ "timedmedia-ogg-long-general": "Talaksang pangmidya ng ''Ogg'', haba $2, $3",
+ "timedmedia-ogg-long-error": "Hindi tanggap na talaksang ''ogg'': $1",
+ "timedmedia-webm-short-video": "$1 na talaksan ng bidyo ng WebM, $2",
+ "timedmedia-webm-long-video": "Talaksang pamparinig/bidyo ng WebM, $1, haba $2, $4 Ɨ $5 mga piksel, $3 lahat-lahat",
+ "timedmedia-no-player-js": "Paumahin, ang pantingin-tingin mo ay maaaring may hindi gumaganang JavaScript o walang anumang tinatangkilik na pampaandar.<br />\nMaaari kang <a href=\"$1\">magkargang pababa ng kaputol</a> o <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">magkargang pababa ng isang pampaandar</a> upang mapaandar ang kaputol sa loob ng iyong pantingin-tingin.",
+ "timedmedia-more": "Marami paā€¦",
+ "timedmedia-dismiss": "Isara",
+ "timedmedia-download": "Ikarga ang talaksan",
+ "timedmedia-play-media": "Paandarin ang midya",
+ "timedmedia-desc-link": "Tungkol sa talaksang ito",
+ "timedmedia-oggThumb-version": "Nangangailangan ang OggHandler ng bersyong $1 o mas luma ng oggThumb.",
+ "timedmedia-oggThumb-failed": "Nabigong lumikha ang oggThumb ng munting larawan.",
+ "timedmedia-status-header": "Katayuan ng transkodigo",
+ "timedmedia-update-status": "Isapanahon ang katayuan ng transkodigo",
+ "timedmedia-status": "Katayuan",
+ "timedmedia-status-unknown": "Hindi alam na katayuan",
+ "timedmedia-transcodeinfo": "Paglalarawan sa hinangong transkodigo",
+ "timedmedia-actions": "Mga kilos",
+ "timedmedia-direct-link": "Ikargang paibaba ang hinango",
+ "timedmedia-not-ready": "Hindi nakahanda",
+ "timedmedia-completed-on": "Nabuo ang transkodigo noong $1",
+ "timedmedia-error-on": "Kamalian sa transkodigo noong $1.",
+ "timedmedia-started-transcode": "Nagsimula ang transkodigo noong $1 na ang nakalilipas. $2",
+ "timedmedia-percent-done": "Halos $1% na ang natatapos",
+ "timedmedia-in-job-queue": "Idinagdag sa pila ng Gawain noong $1 na ang nakalilipas",
+ "timedmedia-unknown-target-size": "Hindi nalalaman na puntiryang sukat, $1 naisakodigo",
+ "timedmedia-days": "{{PLURAL:$1|araw|$1 mga araw}}",
+ "timedmedia-hours": "{{PLURAL:$1|horas|$1 mga oras}}",
+ "timedmedia-minutes": "{{PLURAL:$1|minuto|$1 mga minuto}}",
+ "timedmedia-seconds": "{{PLURAL:$1|segundo|$1 mga segundo}}",
+ "timedmedia-reset": "Itakdang muli ang transkodigo",
+ "timedmedia-reset-confirm": "Ang muling pagtatakda ng transkodigong ito ay magtatanggal ng anumang umiiral na talaksan (kung naroroon), at muling nitong idaragdag ang transkodigo sa pila ng trabaho. Gugugol ito ng ilang panahon upang muling maitranskodigo. <br /><br />\nNakatitiyak ka ba na nais mong magpatuloy?",
+ "timedmedia-reset-error": "Kamalian sa gawain ng muling pagtatakda ng transkodigo.",
+ "timedmedia-ogg": "Ogg",
+ "timedmedia-webm": "WebM",
+ "timedmedia-source-file": "$1 pinagkukunan",
+ "timedmedia-source-file-desc": "Orihinal na $1, $2 Ɨ $3 ( $4)",
+ "timedmedia-source-audio-file-desc": "Orihinal na talaksang $1 ($2)",
+ "timedmedia-derivative-160p.ogv": "Ogg 160P",
+ "timedmedia-derivative-desc-160p.ogv": "Mababang lapad ng paha ng bidyo ng Ogg (160P)",
+ "timedmedia-derivative-360p.ogv": "Ogg 360P",
+ "timedmedia-derivative-desc-360p.ogv": "Mapapaanod sa Web na bidyo ng Ogg (360P)",
+ "timedmedia-derivative-480p.ogv": "Ogg 480P",
+ "timedmedia-derivative-desc-480p.ogv": "Mapapaanod sa Web na bidyo ng Ogg (480P)",
+ "timedmedia-derivative-720p.ogv": "Ogg 720P",
+ "timedmedia-derivative-desc-720p.ogv": "Mataas na uri ng bidyo ng Ogg na maikakargang paibaba (720P)",
+ "timedmedia-derivative-160p.webm": "WebM 160P",
+ "timedmedia-derivative-desc-160p.webm": "Mapapaanod sa Web na WebM (160P)",
+ "timedmedia-derivative-360p.webm": "WebM 360P",
+ "timedmedia-derivative-desc-360p.webm": "Mapapaanod sa Web na WebM (360P)",
+ "timedmedia-derivative-480p.webm": "WebM 480P",
+ "timedmedia-derivative-desc-480p.webm": "Mapapaanod sa Web na WebM (480P)",
+ "timedmedia-derivative-720p.webm": "WebM 720P",
+ "timedmedia-derivative-desc-720p.webm": "Mataas na uri ng WebM na maikakargang paibaba (720P)",
+ "timedmedia-subtitle-new": "Lumikha ng bagong salinwika o baguhin ang umiiral na",
+ "timedmedia-subtitle-new-desc": "Palitan ang bahaging '''$1''' ng iyong [[:en:ISO 639|kodigo ng wika]] at pindutin ang pindutang '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Gawin",
+ "timedmedia-subtitle-language": "$1 ($2) kabahaging mga pamagat",
+ "timedmedia-subtitle-no-video": "Walang bidyo na may kaugnayan sa pangkasalukuyang pahina ng kabahaging pamagat",
+ "timedmedia-subtitle-no-subtitles": "Kasalukuyang walang mga kabahaging pamagat sa loob ng $1 para sa bidyong ito, maaari mong [{{fullurl:{{FULLPAGENAME}}|action=edit}} baguhin ang pahinang ito] upang maidagdag ang mga ito",
+ "timedmediahandler": "Inoorasang Panghawak ng Midya",
+ "timedmedia-videos": "{{PLURAL:$1|$1 bidyo|$1 mga bidyo}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 bidyo ng Ogg|$1 mga bidyo ng Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 bidyo ng WebM|$1 mga bidyo ng WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transkodigo|$1 mga transkodigo}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 tumatakbong transkodigo|$1 tumatakbong mga transkodigo}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 nakapilang transkodigo|$1 nakapilang mga transkodigo}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 nabigong transkodigo|$1 nabigong mga transkodigo}}",
+ "timedmedia-file": "Talaksan"
+}
diff --git a/extensions/TimedMediaHandler/i18n/tly.json b/extensions/TimedMediaHandler/i18n/tly.json
new file mode 100644
index 00000000..8123d4cc
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/tly.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Erdemaslancan"
+ ]
+ },
+ "timedmedia-subtitle-new-go": "Š”Š°Š²Š°Ń€Š“ŠµŃ˜"
+}
diff --git a/extensions/TimedMediaHandler/i18n/tr.json b/extensions/TimedMediaHandler/i18n/tr.json
new file mode 100644
index 00000000..e3e00c8f
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/tr.json
@@ -0,0 +1,80 @@
+{
+ "@metadata": {
+ "authors": [
+ "Erkan Yilmaz",
+ "Incelemeelemani",
+ "Joseph",
+ "Mach",
+ "Runningfridgesrule",
+ "Srhat",
+ "Sayginer",
+ "Stultiwikia",
+ "Mavrikant"
+ ]
+ },
+ "timedmedia-desc": "Ses işleyicisi, video ve zamanlanmış metin formatları iƧin WebM, Ogg Theora, Vorbis, srt desteği",
+ "timedmedia-ogg-short-audio": "Ogg $1 ses dosyası, $2",
+ "timedmedia-ogg-short-video": "Ogg $1 video dosyası, $2",
+ "timedmedia-ogg-short-general": "Ogg $1 medya dosyası, $2",
+ "timedmedia-ogg-long-audio": "Ogg $1 ses dosyası, sĆ¼re $2, $3",
+ "timedmedia-ogg-long-video": "Ogg $1 video dosyası, sĆ¼re $2, $4Ɨ$5 piksel, $3",
+ "timedmedia-ogg-long-multiplexed": "Ogg Ƨok dĆ¼zeyli ses/video dosyası, $1, sĆ¼re $2, $4Ɨ$5 piksel, $3 genelde",
+ "timedmedia-ogg-long-general": "Ogg medya dosyası, sĆ¼re $2, $3",
+ "timedmedia-ogg-long-error": "GeƧersiz ogg dosyası: $1",
+ "timedmedia-webm-short-video": "WebM $1 video dosyası, $2",
+ "timedmedia-webm-long-video": "WebM ses/video dosyası, $1, sĆ¼re $2, $4 Ɨ $5 piksel, $3 tĆ¼mĆ¼",
+ "timedmedia-flac-short-audio": "FLAC ses dosyası, $1",
+ "timedmedia-flac-long-audio": "FLAC ses dosyası, sĆ¼re $1, $2 tĆ¼mĆ¼",
+ "timedmedia-wav-short-audio": "WAV ses dosyası, $1",
+ "timedmedia-wav-long-audio": "WAV ses dosyası, sĆ¼re $1, $2 tĆ¼mĆ¼",
+ "timedmedia-wav-pcm-required": "Yalnızca PCM (Darbeli Kod ModĆ¼lasyonu) WAV yĆ¼kleyebilirsiniz.",
+ "timedmedia-mp4-short-video": "MP4 $1 video dosyası, $2",
+ "timedmedia-mp4-long-video": "MP4 ses/video dosyası, $1, sĆ¼re $2, $4 Ɨ $5 piksel, $3 tĆ¼mĆ¼",
+ "timedmedia-no-player-js": "ƜzgĆ¼nĆ¼z, tarayıcınızda JavaScript devredışı veya yĆ¼klĆ¼ bir oynatıcı yok.<br />\nÄ°sterseniz <a href=\"$1\">klibi indirebilir</a> veya tarayıcınız iƧin <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">oynatıcıyı buradan indirebilirsiniz</a>.",
+ "timedmedia-more": "Daha...",
+ "timedmedia-dismiss": "Kapat",
+ "timedmedia-download": "Dosya indir",
+ "timedmedia-play-media": "Medyayı oynat",
+ "timedmedia-desc-link": "Bu dosya hakkında",
+ "timedmedia-oggThumb-version": "OggHandler $1 veya daha yeni sĆ¼rĆ¼m oggThumb gerektirir.",
+ "timedmedia-oggThumb-failed": "oggThumb kĆ¼Ć§Ć¼k resim oluşturamadı.",
+ "timedmedia-status-header": "Transkodu durumu",
+ "timedmedia-update-status": "Transkodu durumunu gĆ¼ncelle",
+ "timedmedia-status": "Durum",
+ "timedmedia-status-unknown": "Bilinmeyen durum",
+ "timedmedia-transcodeinfo": "Format",
+ "timedmedia-actions": "İşlemler",
+ "timedmedia-direct-link": "TĆ¼revi indir",
+ "timedmedia-not-ready": "Hazır değil",
+ "timedmedia-completed-on": "Tamamlanan transkodu $1",
+ "timedmedia-error-on": "$1 Ć¼zerinde Ƨapraz kodlama hatası",
+ "timedmedia-started-transcode": "$1 ƶncesinde transkod başlangıcı. $2",
+ "timedmedia-percent-done": "Tamamlanan $1% hakkında",
+ "timedmedia-in-job-queue": "$1 ƶnce iş kuyruğuna eklendi",
+ "timedmedia-unknown-target-size": "$1 kodlamasında, bilinmeyen hedef boyutu",
+ "timedmedia-days": "{{PLURAL:$1|1 gĆ¼n|$1 gĆ¼n}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 saat|$1 saat}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 dakika|$1 dakika}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 saniye|$1 saniye}}",
+ "timedmedia-reset": "Transkodu sıfırla",
+ "timedmedia-reset-confirm": "Bu transkodu sıfırladığınız takdirde (eğer varsa), mevcut dosyalar kaldırılacak ve yeniden iş kuyruğuna alınacaktır. Bu yeniden kodlama biraz zaman alacaktır.<br /><br />\nDevam etmek istediğinize emin misiniz?",
+ "timedmedia-reset-error": "Transkodlama işinde sıfırlama hatası.",
+ "timedmedia-source-file": "$1 kaynağı",
+ "timedmedia-source-file-desc": "Orijinal $1 dosyası, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "Orijinal $1 dosyası ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Ogg videosu dĆ¼ÅŸĆ¼k bant genişliği (160P)",
+ "timedmedia-derivative-desc-1080p.ogv": "Full HD indirilebilir Ogg video (1080P)",
+ "timedmedia-derivative-desc-1080p.webm": "Full HD indirilebilir WebM (1080P)",
+ "timedmedia-derivative-desc-1080p.mp4": "Full HD kalitede MP4 (1080P)",
+ "timedmedia-subtitle-new-go": "Git",
+ "timedmedia-videos": "{{PLURAL:$1|$1 video|$1 video}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg videosu|$1 Ogg videosu}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM videosu|$1 WebM videosu}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transkod|$1 transkod}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 Ƨalışan transkod|$1 Ƨalışan transkod}}",
+ "timedmedia-file": "Dosya",
+ "timedmedia-audios": "{{PLURAL:$1|$1 ses dosyası|$1 ses dosyası}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Ogg ses dosyası|$1 Ogg ses dosyası}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 FLAC ses dosyası|$1 FLAC ses dosyası}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 WAV ses dosyası|$1 WAV ses dosyası}}"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ts.json b/extensions/TimedMediaHandler/i18n/ts.json
new file mode 100644
index 00000000..240bfe4c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ts.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Thuvack"
+ ]
+ },
+ "timedmedia-more": "Swinwanaā€¦",
+ "timedmedia-dismiss": "Pfala"
+}
diff --git a/extensions/TimedMediaHandler/i18n/tt-cyrl.json b/extensions/TimedMediaHandler/i18n/tt-cyrl.json
new file mode 100644
index 00000000..e9224c6c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/tt-cyrl.json
@@ -0,0 +1,17 @@
+{
+ "@metadata": {
+ "authors": [
+ "Š˜Š»ŃŒŠ½Š°Ń€",
+ "Derslek"
+ ]
+ },
+ "timedmedia-no-player-js": "ŠšŃ‹Š·Š³Š°Š½Ń‹Ń‡ŠŗŠ° ŠŗŠ°Ń€ŃˆŃ‹ сŠµŠ·Š½ŠµŅ£ Š±Ń€Š°ŃƒŠ·ŠµŃ€Š“Š° JavaScript сŅÆŠ½Š“ŠµŃ€ŠµŠ»Š³Ó™Š½, яŠøсә ŠŗŠøрәŠŗŠ»Šµ уŠ¹Š½Š°Ń‚Šŗыч юŠŗ.<br />\nŠ”ŠµŠ· <a href=\"$1\">рŠ¾Š»ŠøŠŗŠ½Ń‹</a> Š¹Ó©ŠŗŠ»Šø яŠøсә Š°Š½Ń‹ Š±Ń€Š°ŃƒŠ·ŠµŃ€Š“Š° уŠ¹Š½Š°Ń‚Ń‹Ń€ өчŠµŠ½<a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">уŠ¹Š½Š°Ń‚Šŗыч ŠŗушыŠ¼Ń‚Š°</a> Š¹Ó©ŠŗŠ»Šø Š°Š»Š°ŃŃ‹Š·.",
+ "timedmedia-more": "Š¢ŃƒŠ»Ń‹Ń€Š°Šŗ...",
+ "timedmedia-dismiss": "ŠÆŠ±Ńƒ",
+ "timedmedia-download": "Š¤Š°Š¹Š»Š½Ń‹ Š°Š»Ńƒ",
+ "timedmedia-desc-link": "Š¤Š°Š¹Š» турыŠ½Š“Š° Š¼Ó™Š³ŃŠŠ»ŅÆŠ¼Š°Ń‚",
+ "timedmedia-oggThumb-version": "OggHandler $1 юрŠ°Š¼Š°ŃŃ‹Š½Š½Š°Š½ Š“Š° юŠ³Š°Ń€Ń‹Ń€Š°Šŗ oggThumb тәэŠ¼ŠøŠ½Š°Ń‚Ń‹Š½ сŠ¾Ń€Ń‹Š¹.",
+ "timedmedia-oggThumb-failed": "oggThumb Š½ŠøŠ³ŠµŠ·ŠµŠ½Š“ә Š¼ŠøŠ½ŠøŠ°Ń‚ŃŽŃ€Š°Š½Ń‹ ясŠ°Šæ Š±ŃƒŠ»Š¼Š°Š“ы.",
+ "timedmedia-source-file": "$1-Š½Ń‡Šµ чыŠ³Š°Š½Š°Šŗ",
+ "timedmedia-source-audio-file-desc": "ŠžŃ€ŠøŠ³ŠøŠ½Š°Š»ŃŒ $1-фŠ°Š¹Š» ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/tzm.json b/extensions/TimedMediaHandler/i18n/tzm.json
new file mode 100644
index 00000000..cf77a584
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/tzm.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Tifinaghes"
+ ]
+ },
+ "timedmedia-mp4": "MP4"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ug-arab.json b/extensions/TimedMediaHandler/i18n/ug-arab.json
new file mode 100644
index 00000000..05e95334
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ug-arab.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sahran"
+ ]
+ },
+ "timedmedia-dismiss": "ŁŠŲ§Ł¾",
+ "timedmedia-status": "Ś¾Ų§Ł„Ū•ŲŖ",
+ "timedmedia-actions": "Ł…Ū•Ų“ŲŗŪ‡Ł„Ų§ŲŖ",
+ "timedmedia-not-ready": "ŲŖŪ•ŁŠŁŠŲ§Ų± Ų¦Ū•Ł…Ū•Ų³",
+ "timedmedia-subtitle-new-go": "ŁŠŪ†ŲŖŁƒŪ•Ł„",
+ "timedmedia-file": "Ś¾Ū†Ų¬Ų¬Ū•ŲŖ"
+}
diff --git a/extensions/TimedMediaHandler/i18n/uk.json b/extensions/TimedMediaHandler/i18n/uk.json
new file mode 100644
index 00000000..a70bd282
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/uk.json
@@ -0,0 +1,134 @@
+{
+ "@metadata": {
+ "authors": [
+ "AS",
+ "Ahonc",
+ "Andriykopanytsia",
+ "AtUkr",
+ "Base",
+ "NickK",
+ "Olvin",
+ "Prima klasy4na",
+ "Steve.rusyn",
+ "SteveR",
+ "Š¢ŠµŃŃ‚",
+ "ŠŃ‚Š°",
+ "Piramidion",
+ "Dars"
+ ]
+ },
+ "timedmedia-desc": "ŠžŠ±Ń€Š¾Š±Š»ŃŽŠ²Š°Ń‡ Š“Š»Ń Š°ŃƒŠ“іŠ¾, Š²Ń–Š“ŠµŠ¾ і суŠ±Ń‚ŠøтріŠ² Š· ŠæіŠ“трŠøŠ¼ŠŗŠ¾ŃŽ фŠ¾Ń€Š¼Š°Ń‚Ń–Š² WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "Š—Š²ŃƒŠŗŠ¾Š²ŠøŠ¹ фŠ°Š¹Š» Ogg $1, $2",
+ "timedmedia-ogg-short-video": "Š’Ń–Š“ŠµŠ¾-фŠ°Š¹Š» Ogg $1, $2",
+ "timedmedia-ogg-short-general": "Š¤Š°Š¹Š» Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "Š·Š²ŃƒŠŗŠ¾Š²ŠøŠ¹ фŠ°Š¹Š» Ogg $1, Š“Š¾Š²Š¶ŠøŠ½Š° $2, $3",
+ "timedmedia-ogg-long-video": "Š²Ń–Š“ŠµŠ¾-фŠ°Š¹Š» Ogg $1, Š“Š¾Š²Š¶ŠøŠ½Š° $2, $4Ɨ$5 ŠæіŠŗсŠµŠ»Ń–Š², $3",
+ "timedmedia-ogg-long-multiplexed": "Š¼ŃƒŠ»ŃŒŃ‚ŠøŠæŠ»ŠµŠŗсŠ½ŠøŠ¹ Š°ŃƒŠ“іŠ¾/Š²Ń–Š“ŠµŠ¾-фŠ°Š¹Š» ogg, $1, Š“Š¾Š²Š¶ŠøŠ½Š° $2, $4Ɨ$5 ŠæіŠŗсŠµŠ»Ń–Š², $3 усьŠ¾Š³Š¾",
+ "timedmedia-ogg-long-general": "Š¼ŠµŠ“іŠ°-фŠ°Š¹Š» Ogg, Š“Š¾Š²Š¶ŠøŠ½Š° $2, $3",
+ "timedmedia-ogg-long-error": "ŠŠµŠæрŠ°Š²ŠøŠ»ŃŒŠ½ŠøŠ¹ Ogg-фŠ°Š¹Š»: $1",
+ "timedmedia-ogg-long-no-streams": "ŠœŠµŠ“іŠ°Ń„Š°Š¹Š» Ogg. Š—Š°ŃŃ‚ŠµŃ€ŠµŠ¶ŠµŠ½Š½Ń: ŠŠµ рŠ¾Š·ŠæіŠ·Š½Š°Š½Š¾ Š¶Š¾Š“ŠµŠ½ Š· ŠŗŠ¾Š“ŠµŠŗіŠ², Š²ŠøŠŗŠ¾Ń€ŠøстŠ°Š½Šøх у цьŠ¾Š¼Ńƒ фŠ°Š¹Š»Ń–.",
+ "timedmedia-webm-short-video": "WebM $1 Š²Ń–Š“ŠµŠ¾-фŠ°Š¹Š», $2",
+ "timedmedia-webm-long-video": "WebM Š°ŃƒŠ“іŠ¾/Š²Ń–Š“ŠµŠ¾ фŠ°Š¹Š», $1, трŠøŠ²Š°Š»Ń–ŃŃ‚ŃŒ $2, $4 Ɨ $5 {{PLURAL:$5|ŠæіŠŗсŠµŠ»ŃŒ|ŠæіŠŗсŠµŠ»Ń–|ŠæіŠŗсŠµŠ»Ń–Š²}}, Š²ŃŃŒŠ¾Š³Š¾ $3",
+ "timedmedia-flac-short-audio": "FLAC Š°ŃƒŠ“іŠ¾-фŠ°Š¹Š»,$1",
+ "timedmedia-flac-long-audio": "FLAC Š°ŃƒŠ“іŠ¾-фŠ°Š¹Š», трŠøŠ²Š°Š»Ń–ŃŃ‚ŃŒ $1, $2 шŠ²ŠøŠ“Šŗість",
+ "timedmedia-wav-short-audio": "ŠŃƒŠ“іŠ¾-фŠ°Š¹Š» WAV, $1",
+ "timedmedia-wav-long-audio": "ŠŃƒŠ“іŠ¾-фŠ°Š¹Š» WAV, трŠøŠ²Š°Š»Ń–ŃŃ‚ŃŒ $1, $2 шŠ²ŠøŠ“Šŗість",
+ "timedmedia-wav-pcm-required": "Š’Šø Š¼Š¾Š¶ŠµŃ‚Šµ тіŠ»ŃŒŠŗŠø Š·Š°Š²Š°Š½Ń‚Š°Š¶ŠøтŠø PCM (іŠ¼ŠæуŠ»ŃŒŃŠ½Š¾-ŠŗŠ¾Š“Š¾Š²Š° Š¼Š¾Š“уŠ»ŃŃ†Ń–я) WAV.",
+ "timedmedia-mp4-short-video": "MP4 $1 Š²Ń–Š“ŠµŠ¾-фŠ°Š¹Š», $2",
+ "timedmedia-mp4-long-video": "MP4 Š°ŃƒŠ“іŠ¾/Š²Ń–Š“ŠµŠ¾ фŠ°Š¹Š», $1, трŠøŠ²Š°Š»Ń–ŃŃ‚ŃŒ $2, $4 Ɨ $5 {{PLURAL:$5|ŠæіŠŗсŠµŠ»ŃŒ|ŠæіŠŗсŠµŠ»Ń–|ŠæіŠŗсŠµŠ»Ń–Š²}}, Š²ŃŃŒŠ¾Š³Š¾ $3",
+ "timedmedia-no-player-js": "ŠŠ° Š¶Š°Š»ŃŒ, у Š’Š°ŃˆŠ¾Š¼Ńƒ Š±Ń€Š°ŃƒŠ·ŠµŃ€Ń– Š²ŠøŠ¼ŠŗŠ½ŠµŠ½Š¾ JavaScript і Š½Šµ ŠæіŠ“трŠøŠ¼ŃƒŃ”Ń‚ŃŒŃŃ Š¶Š¾Š“Š½Š¾Š³Š¾ ŠæрŠ¾Š³Ń€Š°Š²Š°Ń‡Š°.<br />\nŠ’Šø Š¼Š¾Š¶ŠµŃ‚Šµ <a href=\"$1\">Š·Š°Š²Š°Š½Ń‚Š°Š¶ŠøтŠø рŠ¾Š»ŠøŠŗ</a> Š°Š±Š¾ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">Š·Š°Š²Š°Š½Ń‚Š°Š¶ŠøтŠø ŠæрŠ¾Š³Ń€Š°Š²Š°Ń‡</a> Š“Š»Ń Š²Ń–Š“тŠ²Š¾Ń€ŠµŠ½Š½Ń– рŠ¾Š»ŠøŠŗу у Š±Ń€Š°ŃƒŠ·ŠµŃ€Ń–.",
+ "timedmedia-more": "Š‘Ń–Š»ŃŒŃˆŠµā€¦",
+ "timedmedia-dismiss": "Š—Š°ŠŗрŠøтŠø",
+ "timedmedia-download": "Š—Š°Š²Š°Š½Ń‚Š°Š¶ŠøтŠø фŠ°Š¹Š»",
+ "timedmedia-play-media": "Š’Ń–Š“тŠ²Š¾Ń€ŠøтŠø",
+ "timedmedia-desc-link": "Š†Š½Ń„Š¾Ń€Š¼Š°Ń†Ń–я ŠæрŠ¾ цŠµŠ¹ фŠ°Š¹Š»",
+ "timedmedia-oggThumb-version": "OggHandler Š²ŠøŠ¼Š°Š³Š°Ń” oggThumb Š²ŠµŃ€ŃŃ–Ń— $1 Š°Š±Š¾ Š±Ń–Š»ŃŒŃˆ ŠæіŠ·Š½ŃŒŠ¾Ń—.",
+ "timedmedia-oggThumb-failed": "oggThumb Š½Šµ Š²Š“Š°Š»Š¾ŃŃŒ стŠ²Š¾Ń€ŠøтŠø Š¼Ń–Š½Ń–Š°Ń‚ŃŽŃ€Ńƒ.",
+ "timedmedia-status-header": "Š”тŠ°Ń‚ŃƒŃ Š“ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń",
+ "timedmedia-update-status": "ŠžŠ½Š¾Š²ŠøтŠø стŠ°Ń‚ŃƒŃ Š“ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń",
+ "timedmedia-status": "Š”тŠ°Ń‚ŃƒŃ",
+ "timedmedia-status-unknown": "ŠŠµŠ²Ń–Š“Š¾Š¼ŠøŠ¹ стŠ°Ń‚ŃƒŃ",
+ "timedmedia-transcodebitrate": "Š‘Ń–Ń‚Ń€ŠµŠ¹Ń‚",
+ "timedmedia-transcodeduration": "Š§Š°Ń ŠŗŠ¾Š“уŠ²Š°Š½Š½Ń",
+ "timedmedia-transcodeinfo": "Š¤Š¾Ń€Š¼Š°Ń‚",
+ "timedmedia-actions": "Š”Ń–Ń—",
+ "timedmedia-direct-link": "Š—Š°Š²Š°Š½Ń‚Š°Š¶ŠøтŠø",
+ "timedmedia-not-ready": "ŠŠµ Š³Š¾Ń‚Š¾Š²Š¾",
+ "timedmedia-completed-on": "Š—Š°Š²ŠµŃ€ŃˆŠµŠ½Š¾ $1",
+ "timedmedia-error-on": "ŠŸŠ¾Š¼ŠøŠ»ŠŗŠ° Š½Š° $1.",
+ "timedmedia-started-transcode": "Š Š¾Š·ŠæŠ¾Ń‡Š°Ń‚Š¾ $1 Š½Š°Š·Š°Š“. $2",
+ "timedmedia-percent-done": "ŠŸŃ€ŠøŠ±Š»ŠøŠ·Š½Š¾ $1% Š³Š¾Ń‚Š¾Š²Š¾",
+ "timedmedia-in-job-queue": "Š”Š¾Š“Š°Š½Š¾ Š“Š¾ чŠµŃ€Š³Šø Š·Š°Š²Š“Š°Š½ŃŒ $1 Š½Š°Š·Š°Š“",
+ "timedmedia-unknown-target-size": "ŠŠµŠ²Ń–Š“Š¾Š¼ŠøŠ¹ ціŠ»ŃŒŠ¾Š²ŠøŠ¹ рŠ¾Š·Š¼Ń–Ń€, $1 ŠæрŠø ŠŗŠ¾Š“уŠ²Š°Š½Š½Ń–",
+ "timedmedia-days": "$1 {{PLURAL:$1|Š“ŠµŠ½ŃŒ|Š“Š½Ń–|Š“Š½Ń–Š²}}",
+ "timedmedia-hours": "$1 {{PLURAL:$1|Š³Š°Š“ŠøŠ½Ńƒ|Š³Š¾Š“ŠøŠ½Šø|Š³Š¾Š“ŠøŠ½}}",
+ "timedmedia-minutes": "$1 {{PLURAL:$1|хŠ²ŠøŠ»ŠøŠ½Ńƒ|хŠ²ŠøŠ»ŠøŠ½Šø|хŠ²ŠøŠ»ŠøŠ½}}",
+ "timedmedia-seconds": "$1 {{PLURAL:$1|сŠµŠŗуŠ½Š“у|сŠµŠŗуŠ½Š“Šø|сŠµŠŗуŠ½Š“}}",
+ "timedmedia-reset": "ŠŸŠµŃ€ŠµŠ·Š°ŠæусŠŗ Š“ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń",
+ "timedmedia-reset-confirm": "ŠŸŠµŃ€ŠµŠ·Š°ŠæусŠŗ Š“ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń Š²ŠøŠ“Š°Š»Šøть Š½Š°ŃŠ²Š½ŠøŠ¹ фŠ°Š¹Š» (яŠŗщŠ¾ Š²Ń–Š½ ісŠ½ŃƒŃ”), і Š“ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń Š·Š½Š¾Š² Š±ŃƒŠ“Šµ Š“Š¾Š“Š°Š½Š¾ Š² чŠµŃ€Š³Ńƒ Š·Š°Š²Š“Š°Š½ŃŒ. ŠŸŠ¾Š²Ń‚Š¾Ń€Š½Šµ Š“ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń Š·Š°Š¹Š¼Šµ яŠŗŠøŠ¹ŃŃŒ чŠ°Ń. <br /><br />\nŠ’Šø уŠæŠµŠ²Š½ŠµŠ½Ń–, щŠ¾ хŠ¾Ń‡ŠµŃ‚Šµ ŠæрŠ¾Š“Š¾Š²Š¶ŠøтŠø?",
+ "timedmedia-reset-error": "ŠŸŠ¾Š¼ŠøŠ»ŠŗŠ° ŠæрŠø ŠæŠµŃ€ŠµŠ·Š°ŠæусŠŗу Š“ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Š”Š¶ŠµŃ€ŠµŠ»Š¾ $1",
+ "timedmedia-source-file-desc": "ŠžŃ€ŠøŠ³Ń–Š½Š°Š»ŃŒŠ½ŠøŠ¹ $1 фŠ°Š¹Š», $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "ŠžŃ€ŠøŠ³Ń–Š½Š°Š»ŃŒŠ½ŠøŠ¹ $1 фŠ°Š¹Š» ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Ogg-Š²Ń–Š“ŠµŠ¾ Š½ŠøŠ·ŃŒŠŗŠ¾Ń— яŠŗŠ¾ŃŃ‚Ń– (160P)",
+ "timedmedia-derivative-desc-240p.ogv": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Šµ Ogg-Š²Ń–Š“ŠµŠ¾ (240P)",
+ "timedmedia-derivative-desc-360p.ogv": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Šµ Ogg-Š²Ń–Š“ŠµŠ¾ (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Šµ Ogg-Š²Ń–Š“ŠµŠ¾ (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Š’ŠøсŠ¾ŠŗŠ¾ŃŠŗісŠ½Šµ Ogg-Š²Ń–Š“ŠµŠ¾ (720P) Š“Š»Ń Š·Š°Š²Š°Š½Ń‚Š°Š¶ŠµŠ½Š½Ń",
+ "timedmedia-derivative-desc-1080p.ogv": "Š”ŠŗŠ°Ń‡ŃƒŠ²Š°Š½Šµ Ogg-Š²Ń–Š“ŠµŠ¾ у фŠ¾Ń€Š¼Š°Ń‚Ń– Full HD (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Šµ WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Šµ WebM (360P)",
+ "timedmedia-derivative-desc-480p.webm": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Šµ WebM (480P)",
+ "timedmedia-derivative-desc-720p.webm": "Š’ŠøсŠ¾ŠŗŠ¾ŃŠŗісŠ½Šµ WebM (720P) Š“Š»Ń Š·Š°Š²Š°Š½Ń‚Š°Š¶ŠµŠ½Š½Ń",
+ "timedmedia-derivative-desc-1080p.webm": "Š”ŠŗŠ°Ń‡ŃƒŠ²Š°Š½Šµ WebM-Š²Ń–Š“ŠµŠ¾ у фŠ¾Ń€Š¼Š°Ń‚Ń– Full HD (1080P)",
+ "timedmedia-derivative-desc-2160p.webm": "Š”ŠŗŠ°Ń‡ŃƒŠ²Š°Š½Šµ WebM-Š²Ń–Š“ŠµŠ¾ у фŠ¾Ń€Š¼Š°Ń‚Ń– Full 4K (2160P)",
+ "timedmedia-derivative-desc-360p.vp9.webm": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Šµ WebM VP9 (360P)",
+ "timedmedia-derivative-desc-480p.vp9.webm": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Šµ WebM VP9 (480P)",
+ "timedmedia-derivative-desc-720p.vp9.webm": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Šµ WebM VP9 у фŠ¾Ń€Š¼Š°Ń‚Ń– HD (720P)",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Šµ WebM VP9 у фŠ¾Ń€Š¼Š°Ń‚Ń– Full HD (1080P)",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "ŠŸŠ¾Ń‚Š¾ŠŗŠ¾Š²Šµ WebM-Š²Ń–Š“ŠµŠ¾ у фŠ¾Ń€Š¼Š°Ń‚Ń– Full 4K (2160P)",
+ "timedmedia-derivative-desc-320p.mp4": "Š”уŠ¼Ń–сŠ½ŠøŠ¹ Š· MP$ (320P) ŠæрŠøстріŠ¹",
+ "timedmedia-derivative-desc-480p.mp4": "Š’ŠµŠ±-ŠæŠ¾Ń‚Š¾ŠŗŠ¾Š²Šµ MP4 (480 Š )",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 яŠŗŠ¾ŃŃ‚Ń– HD (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "MP4-Š²Ń–Š“ŠµŠ¾ у фŠ¾Ń€Š¼Š°Ń‚Ń– Full HD (1080P)",
+ "timedmedia-derivative-desc-2160p.mp4": "MP4-Š²Ń–Š“ŠµŠ¾ у фŠ¾Ń€Š¼Š°Ń‚Ń– Full 4K (2160P)",
+ "timedmedia-subtitle-new": "Š”тŠ²Š¾Ń€ŠøтŠø Š½Š¾Š²ŠøŠ¹ ŠæŠµŃ€ŠµŠŗŠ»Š°Š“ Š°Š±Š¾ Š²Ń–Š“рŠµŠ“Š°Š³ŃƒŠ²Š°Ń‚Šø ісŠ½ŃƒŃŽŃ‡ŠøŠ¹",
+ "timedmedia-subtitle-new-desc": "Š’ŠøŠ±ŠµŃ€Ń–Ń‚ŃŒ Š¼Š¾Š²Ńƒ тŠ° Š½Š°Ń‚ŠøсŠ½Ń–Ń‚ŃŒ '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "ŠŸŠµŃ€ŠµŠ¹Ń‚Šø",
+ "timedmedia-subtitle-language": "$1 ($2) суŠ±Ń‚ŠøтрŠø",
+ "timedmedia-subtitle-no-video": "ŠŠµŠ¼Š°Ń” Š²Ń–Š“ŠµŠ¾, ŠæŠ¾Š²'яŠ·Š°Š½Š¾Š³Š¾ Š· ŠæŠ¾Ń‚Š¾Ń‡Š½Š¾ŃŽ стŠ¾Ń€Ń–Š½ŠŗŠ¾ŃŽ суŠ±Ń‚ŠøтріŠ²",
+ "timedmedia-subtitle-no-subtitles": "Š’ Š“Š°Š½ŠøŠ¹ чŠ°Ń Š½ŠµŠ¼Š°Ń” суŠ±Ń‚ŠøтріŠ² Š½Š° $1 Š“Š»Ń цьŠ¾Š³Š¾ Š²Ń–Š“ŠµŠ¾, Š’Šø Š¼Š¾Š¶ŠµŃ‚Šµ [{{fullurl:{{FULLPAGENAME}}|action=edit}} Š·Š¼Ń–Š½ŠøтŠø цю стŠ¾Ń€Ń–Š½Šŗу] Š“Š»Ń їх Š“Š¾Š“Š°Š²Š°Š½Š½Ń",
+ "timedmedia-subtitle-remote": "Š¢ŠµŠŗст Š“Š¾ цьŠ¾Š³Š¾ фŠ°Š¹Š»Ńƒ рŠ¾Š·Š¼Ń–щŠµŠ½ŠøŠ¹ Š½Š° $1",
+ "timedmedia-subtitle-remote-link": "Š’Šø Š¼Š¾Š¶ŠµŃ‚Šµ [$1 ŠæŠµŃ€ŠµŠ³Š»ŃŠ½ŃƒŃ‚Šø Š¾ŠæŠøс стŠ¾Ń€Ń–Š½ŠŗŠø] Š“Š»Ń цьŠ¾Š³Š¾ фŠ°Š¹Š»Ńƒ Š½Š° $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 Š²Ń–Š“ŠµŠ¾}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 Ogg Š²Ń–Š“ŠµŠ¾}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 WebM Š²Ń–Š“ŠµŠ¾}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|1=$1 ŠæŠµŃ€ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń|$1 ŠæŠµŃ€ŠµŠŗŠ¾Š“уŠ²Š°Š½ŃŒ}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|1=$1 ŠæрŠ°Ń†ŃŽŃŽŃ‡Ń– ŠæŠµŃ€ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń|$1 ŠæрŠ°Ń†ŃŽŃŽŃ‡Šøх ŠæŠµŃ€ŠµŠŗŠ¾Š“уŠ²Š°Š½ŃŒ}}",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|1=$1 ŠæŠµŃ€ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń Š² чŠµŃ€Š·Ń–|$1 ŠæŠµŃ€ŠµŠŗŠ¾Š“уŠ²Š°Š½ŃŒ Š² чŠµŃ€Š·Ń–}}",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|1=$1 Š½ŠµŠ²Š“Š°Š»Ń– ŠæŠµŃ€ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń|$1 Š½ŠµŠ²Š“Š°Š»Šøх ŠæŠµŃ€ŠµŠŗŠ¾Š“уŠ²Š°Š½ŃŒ}}",
+ "timedmedia-file": "Š¤Š°Š¹Š»",
+ "timedmedia-audios": "{{PLURAL:$1|$1 Š°ŃƒŠ“іŠ¾-фŠ°Š¹Š»|$1 Š°ŃƒŠ“іŠ¾-фŠ°Š¹Š»Ń–Š²ĢŸ|$1 Š°ŃƒŠ“іŠ¾-фŠ°Š¹Š»Šø}}",
+ "timedmedia-ogg-audios": "{{PLURAL:$1|$1 Š°ŃƒŠ“іŠ¾-фŠ°Š¹Š» Ogg|$1 Š°ŃƒŠ“іŠ¾-фŠ°Š¹Š»Ń–Š² Ogg|$1 Š°ŃƒŠ“іŠ¾-фŠ°Š¹Š»Šø Ogg}}",
+ "timedmedia-flac-audios": "{{PLURAL:$1|$1 Š°ŃƒŠ“іŠ¾-фŠ°Š¹Š» FLAC|$1 Š°ŃƒŠ“іŠ¾-фŠ°Š¹Š»Ń–Š² FLAC|$1 Š°ŃƒŠ“іŠ¾-фŠ°Š¹Š»Šø FLAC}}",
+ "timedmedia-wav-audios": "{{PLURAL:$1|$1 Š°ŃƒŠ“іŠ¾-фŠ°Š¹Š» WAV|$1 Š°ŃƒŠ“іŠ¾-фŠ°Š¹Š»Ń–Š² WAV|$1 Š°ŃƒŠ“іŠ¾-фŠ°Š¹Š»Šø WAV}}",
+ "right-transcode-reset": "сŠŗŠøŠ“Š°Š½Š½Ń Š½ŠµŠ²Š“Š°Š»Šøх Š°Š±Š¾ ŠæŠµŃ€ŠµŠŗŠ¾Š“Š¾Š²Š°Š½Šøх Š²Ń–Š“ŠµŠ¾ іŠ· ŠæŠ¾Š²Ń‚Š¾Ń€Š½ŠøŠ¼ Š·Š°Š½ŠµŃŠµŠ½Š½ŃŠ¼ їх Š² чŠµŃ€Š³Ńƒ Š·Š°Š²Š“Š°Š½ŃŒ",
+ "right-transcode-status": "ŠæŠµŃ€ŠµŠ³Š»ŃŠ“ [[Special:TimedMediaHandler|іŠ½Ń„Š¾Ń€Š¼Š°Ń†Ń–Ń— ŠæрŠ¾ ŠæŠ¾Ń‚Š¾Ń‡Š½Ńƒ Š“іяŠ»ŃŒŠ½Ń–ŃŃ‚ŃŒ Š· ŠæŠµŃ€ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń]]",
+ "action-transcode-status": "ŠŸŠµŃ€ŠµŠ³Š»ŃŠ“ ŠæŠ¾Ń‚Š¾Ń‡Š½Š¾Š³Š¾ стŠ°Š½Ńƒ ŠæŠµŃ€ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń",
+ "orphanedtimedtext": "Š”тŠ¾Ń€Ń–Š½ŠŗŠø-сŠøрŠ¾Ń‚Šø TimedText",
+ "orphanedtimedtext-summary": "Š”ŠæŠøсŠ¾Šŗ стŠ¾Ń€Ń–Š½Š¾Šŗ [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]], яŠŗі Š½Šµ Š¼Š°ŃŽŃ‚ŃŒ Š²Ń–Š“ŠæŠ¾Š²Ń–Š“Š½Š¾Š³Š¾ фŠ°Š¹Š»Ńƒ.",
+ "orphanedtimedtext-unsupported": "Š¦Ń сŠæŠµŃ†Ń–Š°Š»ŃŒŠ½Š° стŠ¾Ń€Ń–Š½ŠŗŠ° ŠæіŠ“трŠøŠ¼ŃƒŃ”Ń‚ŃŒŃŃ Š»ŠøшŠµ Š±Š°Š·Š°Š¼Šø Š“Š°Š½Šøх MySQL.",
+ "orphanedtimedtext-notimedtext": "TimedText Š½Šµ уŠ²Ń–Š¼ŠŗŠ½ŠµŠ½ŠøŠ¹ у ціŠ¹ Š²Ń–Šŗі.",
+ "apihelp-query+transcodestatus-description": "ŠžŃ‚Ń€ŠøŠ¼Š°Ń‚Šø трŠ°Š½ŃŠŗŠ¾Š“-стŠ°Ń‚ŃƒŃ Š“Š»Ń Š“Š°Š½Š¾Ń— стŠ¾Ń€Ń–Š½ŠŗŠø фŠ°Š¹Š»Ńƒ.",
+ "apihelp-query+transcodestatus-example-1": "ŠžŃ‚Ń€ŠøŠ¼Š°Ń‚Šø трŠ°Š½ŃŠŗŠ¾Š“-стŠ°Ń‚ŃƒŃ Š“Š»Ń [[:File:Clip.webm]]",
+ "apihelp-query+videoinfo-description": "Š Š¾Š·ŃˆŠøрює imageinfo і Š²ŠŗŠ»ŃŽŃ‡Š°Ń” іŠ½Ń„Š¾Ń€Š¼Š°Ń†Ń–ŃŽ Š“Š¶ŠµŃ€ŠµŠ»Š° Š²Ń–Š“ŠµŠ¾ (ŠæŠ¾Ń…Ń–Š“Š½Ń–)",
+ "apihelp-query+videoinfo-param-prop": "ŠÆŠŗу іŠ½Ń„Š¾Ń€Š¼Š°Ń†Ń–ŃŽ ŠæрŠ¾ Š²Ń–Š“ŠµŠ¾ Š¾Ń‚Ń€ŠøŠ¼ŃƒŠ²Š°Ń‚Šø:\n;timestamp:Š”Š¾Š“Š°Ń” чŠ°ŃŠ¾Š²Ńƒ Š¼Ń–Ń‚Šŗу Š·Š°Š²Š°Š½Ń‚Š°Š¶ŠµŠ½Š¾Ń— Š²ŠµŃ€ŃŃ–Ń—.\n;user:Š”Š¾Š“Š°Ń” ŠŗŠ¾Ń€ŠøстуŠ²Š°Ń‡Š°, яŠŗŠøŠ¹ Š·Š°Š²Š°Š½Ń‚Š°Š¶ŠøŠ² Š²ŠµŃ€ŃŃ–ŃŽ Š²Ń–Š“ŠµŠ¾.\n;userid:Š”Š¾Š“Š°Ń” ID ŠŗŠ¾Ń€ŠøстуŠ²Š°Ń‡Š°, яŠŗŠøŠ¹ Š·Š°Š²Š°Š½Ń‚Š°Š¶ŠøŠ² Š²ŠµŃ€ŃŃ–ŃŽ Š²Ń–Š“ŠµŠ¾.\n;comment:ŠšŠ¾Š¼ŠµŠ½Ń‚Š°Ń€ Š“Š¾ Š²ŠµŃ€ŃŃ–Ń—.\n;parsedcomment:ŠŸŠ°Ń€ŃŠøŠ½Š³ ŠŗŠ¾Š¼ŠµŠ½Ń‚Š°Ń€Ń Š“Š¾ Š²ŠµŃ€ŃŃ–Ń—.\n;canonicaltitle:Š”Š¾Š“Š°Ń” ŠŗŠ°Š½Š¾Š½Ń–чŠ½ŠøŠ¹ Š·Š°Š³Š¾Š»Š¾Š²Š¾Šŗ Š²Ń–Š“ŠµŠ¾Ń„Š°Š¹Š»Ńƒ.\n;url:Š”Š°Ń” URL Š½Š° Š²Ń–Š“ŠµŠ¾ тŠ° стŠ¾Ń€Ń–Š½Šŗу Š¾ŠæŠøсу.\n;size:Š”Š¾Š“Š°Ń” рŠ¾Š·Š¼Ń–Ń€Šø Š²Ń–Š“ŠµŠ¾ у Š±Š°Š¹Ń‚Š°Ń…, Š¹Š¾Š³Š¾ Š²ŠøсŠ¾Ń‚Ńƒ і шŠøрŠøŠ½Ńƒ. ŠŠ¾Š¼ŠµŃ€ стŠ¾Ń€Ń–Š½ŠŗŠø і трŠøŠ²Š°Š»Ń–ŃŃ‚ŃŒ Š“Š¾Š“Š°ŃŽŃ‚ŃŒŃŃ Š·Š° Š¼Š¾Š¶Š»ŠøŠ²Š¾ŃŃ‚Ń–.\n;dimensions:ŠŠ»Ń–Š°Ń рŠ¾Š·Š¼Ń–Ń€Ńƒ.\n;sha1:Š”Š¾Š“Š°Ń” Š³ŠµŃˆ SHA-1 Š²Ń–Š“ŠµŠ¾.\n;mime:Š”Š¾Š“Š°Ń” MIME-тŠøŠæ Š²Ń–Š“ŠµŠ¾.\n;thumbmime:Š”Š¾Š“Š°Ń” MIME-тŠøŠæ Š¼Ń–Š½Ń–Š°Ń‚ŃŽŃ€Šø Š²Ń–Š“ŠµŠ¾ (Š²ŠøŠ¼Š°Š³Š°Ń” url і ŠæŠ°Ń€Š°Š¼ŠµŃ‚Ń€ $1urlwidth).\n;mediatype:Š”Š¾Š“Š°Ń” Š¼ŠµŠ“іŠ°Ń‚ŠøŠæ Š²Ń–Š“ŠµŠ¾.\n;metadata:Š’ŠøŠ²Š¾Š“Šøть сŠæŠøсŠ¾Šŗ Exif-Š¼ŠµŃ‚Š°Š“Š°Š½Šøх Š²ŠµŃ€ŃŃ–Ń— Š²Ń–Š“ŠµŠ¾.\n;commonmetadata:Š’ŠøŠ²Š¾Š“Šøть сŠæŠøсŠ¾Šŗ Š¼ŠµŃ‚Š°Š“Š°Š½Šøх фŠ¾Ń€Š¼Š°Ń‚Ńƒ фŠ°Š¹Š»Ńƒ Š²ŠµŃ€ŃŃ–Ń— Š²Ń–Š“ŠµŠ¾.\n;extmetadata:Š’ŠøŠ²Š¾Š“Šøть сŠæŠøсŠ¾Šŗ фŠ¾Ń€Š¼Š°Ń‚Š¾Š²Š°Š½Šøх Š¼ŠµŃ‚Š°Š“Š°Š½Šøх, сŠŗŠ¾Š¼Š±Ń–Š½Š¾Š²Š°Š½Šøх Š· ŠŗіŠ»ŃŒŠŗŠ¾Ń… Š“Š¶ŠµŃ€ŠµŠ». Š ŠµŠ·ŃƒŠ»ŃŒŃ‚Š°Ń‚Šø Š²Ń–Š“фŠ¾Ń€Š¼Š°Ń‚Š¾Š²Š°Š½Ń– Š² HTML.\n;archivename:Š”Š¾Š“Š°Ń” Š½Š°Š·Š²Ńƒ фŠ°Š¹Š»Ńƒ Š°Ń€Ń…Ń–Š²Š¾Š²Š°Š½Š¾Ń— Š²ŠµŃ€ŃŃ–Ń— Š“Š»Ń Š½Šµ Š¾ŃŃ‚Š°Š½Š½Ń–Ń… Š²ŠµŃ€ŃŃ–Š¹.\n;bitdepth:Š”Š¾Š“Š°Ń” Š±Ń–Ń‚Š¾Š²Ńƒ Š³Š»ŠøŠ±ŠøŠ½Ńƒ Š²ŠµŃ€ŃŃ–Ń—.\n;uploadwarning:Š’ŠøŠŗŠ¾Ń€ŠøстŠ¾Š²ŃƒŃ”Ń‚ŃŒŃŃ стŠ¾Ń€Ń–Š½ŠŗŠ¾ŃŽ [[Special:Upload]] Š“Š»Ń Š¾Ń‚Ń€ŠøŠ¼Š°Š½Š½Ń іŠ½Ń„Š¾Ń€Š¼Š°Ń†Ń–Ń— ŠæрŠ¾ Š½Š°ŃŠ²Š½ŠøŠ¹ фŠ°Š¹Š». ŠŠµ ŠæрŠøŠ·Š½Š°Ń‡ŠµŠ½Š¾ Š“Š»Ń Š²ŠøŠŗŠ¾Ń€ŠøстŠ°Š½Š½Ń ŠæŠ¾Š·Š° яŠ“рŠ¾Š¼ MediaWiki.\n;derivatives:Š”Š¾Š“Š°Ń” Š¼Š°ŃŠøŠ² Š“Š¾ŃŃ‚ŃƒŠæŠ½Šøх Š²ŠµŃ€ŃŃ–Š¹ іŠ½ŃˆŠ¾Š³Š¾ фŠ¾Ń€Š¼Š°Ń‚Ńƒ і яŠŗŠ¾ŃŃ‚Ń– Š°ŃƒŠ“іŠ¾- чŠø Š²Ń–Š“ŠµŠ¾Ń„Š°Š¹Š»Ńƒ.",
+ "apihelp-query+videoinfo-example-1": "Š’ŠøтяŠ³ іŠ½Ń„Š¾Ń€Š¼Š°Ń†Ń–Ń— ŠæрŠ¾ [[:File:Folgers.ogv]]",
+ "apihelp-transcodereset-description": "ŠšŠ¾Ń€ŠøстуŠ²Š°Ń‡Ń– Š· ŠæрŠ°Š²Š¾Š¼ Ā«transcode-resetĀ» Š¼Š¾Š¶ŃƒŃ‚ŃŒ сŠŗŠøŠ½ŃƒŃ‚Šø і ŠæŠ¾Š²Ń‚Š¾Ń€ŠøтŠø Š·Š°Š“Š°Ń‡Ńƒ ŠæŠµŃ€ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń.",
+ "apihelp-transcodereset-param-title": "Š—Š°Š³Š¾Š»Š¾Š²Š¾Šŗ Š¼ŠµŠ“іŠ°Ń„Š°Š¹Š»Ńƒ.",
+ "apihelp-transcodereset-param-transcodekey": "ŠŸŠµŃ€ŠµŠŗŠ¾Š“уŠ²Š°Ń‚Šø ŠŗŠ»ŃŽŃ‡, яŠŗŠøŠ¹ Š’Šø хŠ¾Ń‡ŠµŃ‚Šµ сŠŗŠøŠ½ŃƒŃ‚Šø. Š’ŠøŠ±Ń–Ń€ŠŗŠ° Š· [[Special:ApiHelp/query+transcodestatus|action=query&prop=transcodestatus]].",
+ "apihelp-transcodereset-example-1": "Š”ŠŗŠøŠ½ŃƒŃ‚Šø усі ŠæŠµŃ€ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń Š“Š»Ń [[:File:Clip.webm]]",
+ "apihelp-transcodereset-example-2": "Š”ŠŗŠøŠ½ŃƒŃ‚Šø ŠŗŠ»ŃŽŃ‡ ŠæŠµŃ€ŠµŠŗŠ¾Š“уŠ²Š°Š½Š½Ń Ā«360_560kbs.webmĀ» Š“Š»Ń [[:File:Clip.webm]]"
+}
diff --git a/extensions/TimedMediaHandler/i18n/ur.json b/extensions/TimedMediaHandler/i18n/ur.json
new file mode 100644
index 00000000..7b58606a
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/ur.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ",
+ "Muhammad Shuaib",
+ "Ų¹Ų«Ł…Ų§Ł† Ų®Ų§Ł† Ų“Ų§Ū"
+ ]
+ },
+ "timedmedia-no-player-js": "Ł…Ų¹Ų°Ų±ŲŖŲŒ Ų¢Ł¾ Ś©Ū’ ŲØŲ±Ų§Ų¤Ų²Ų± Ł…ŪŒŚŗ Ų¬Ų§ŁˆŲ§Ų³Ś©Ų±Ł¾Ł¹ ŁŲ¹Ų§Ł„ Ł†ŪŪŒŚŗ ŪŒŲ§ Ś©ŁˆŲ¦ŪŒ Ł…Ų¹Ų§ŁˆŁ† Ł¾Ł„ŪŒŲ¦Ų± Ų“Ų§Ł…Ł„ Ł†ŪŪŒŚŗ ŪŪ’Ū”<br />\nŲ§Ų³ Ś©Ł„Ł¾ Ś©Łˆ Ų§Ł¾Ł†Ū’ ŲØŲ±Ų§Ų¤Ų²Ų± Ł…ŪŒŚŗ Ś†Ł„Ų§Ł†Ū’ Ś©Ū’ Ł„ŪŒŪ’ Ų¢Ł¾ <a href=\"$1\">Ś©Ł„Ł¾ Ś©Łˆ ŚˆŲ§Ų¤Ł†Ł„ŁˆŚˆ</a> Ś©Ų±Ł„ŪŒŚŗ ŪŒŲ§ </a> or <a href=\"//www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download\">Ł¾Ł„ŪŒŲ¦Ų± ŚˆŲ§Ų¤Ł†Ł„ŁˆŚˆ</a> Ś©Ų±Ł„ŪŒŚŗŪ”",
+ "timedmedia-more": "Ł…Ų²ŪŒŲÆ...",
+ "timedmedia-dismiss": "ŲØŁ†ŲÆ",
+ "timedmedia-download": "ŁŲ§Ų¦Ł„ ŚˆŲ§Ų¤Ł† Ł„ŁˆŚˆ ŲŒ Ų§ŲŖŲ§Ų±Ł†Ų§",
+ "timedmedia-play-media": "Ś©Ś¾ŪŒŁ„Ł†Ū’ Ś©Ū’ Ł…ŪŒŚˆŪŒŲ§",
+ "timedmedia-desc-link": "Ų§Ų³ ŁŲ§Ų¦Ł„ Ś©Ū’ ŲØŲ§Ų±Ū’ Ł…ŪŒŚŗ",
+ "timedmedia-status": "Ų­ŪŒŲ«ŪŒŲŖ",
+ "timedmedia-status-unknown": "Ł†Ų§Ł…Ų¹Ł„ŁˆŁ… Ł…Ł‚Ų§Ł…",
+ "timedmedia-actions": "Ų§Ų¹Ł…Ų§Ł„",
+ "timedmedia-source-file": "$1 Ł…Ų³ŁˆŲÆŪ",
+ "timedmedia-source-audio-file-desc": "Ų§ŲµŁ„ŪŒ $1 Ł…Ł„Ł ($2)",
+ "timedmedia-file": "ŁŲ§Ų¦Ł„"
+}
diff --git a/extensions/TimedMediaHandler/i18n/vec.json b/extensions/TimedMediaHandler/i18n/vec.json
new file mode 100644
index 00000000..c567687b
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/vec.json
@@ -0,0 +1,85 @@
+{
+ "@metadata": {
+ "authors": [
+ "Candalua",
+ "GatoSelvadego"
+ ]
+ },
+ "timedmedia-desc": "Gestor pa' i file audio, video e cĆ³ sototitołi; formati suportai: WebM, Ogg Theora, Vorbis, srt",
+ "timedmedia-ogg-short-audio": "File audio Ogg $1, $2",
+ "timedmedia-ogg-short-video": "File video Ogg $1, $2",
+ "timedmedia-ogg-short-general": "File multimedial Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "File audio Ogg $1, durata $2, $3",
+ "timedmedia-ogg-long-video": "File video Ogg $1, durata $2, dimensioni $4Ɨ$5 pixel, $3",
+ "timedmedia-ogg-long-multiplexed": "File audio/video multiplexed Ogg $1, durata $2, dimensioni $4Ɨ$5 pixel, conplessivamente $3",
+ "timedmedia-ogg-long-general": "File multimedial Ogg, durata $2, $3",
+ "timedmedia-ogg-long-error": "File ogg mƬa valido: $1",
+ "timedmedia-webm-short-video": "File video WebM $1, $2",
+ "timedmedia-webm-long-video": "File audio/video WebM $1, durata $2, dimension $4Ɨ$5 pixel, conplesivamente $3",
+ "timedmedia-mp4-short-video": "File video MP4 $1, $2",
+ "timedmedia-mp4-long-video": "File audio/video MP4 $1, durata $2, dimension $4Ɨ$5 pixel, conplesivamente $3",
+ "timedmedia-no-player-js": "El to browser el gĆ  JavaScript destacĆ , opure no'l gĆ  nissun riprodutor suportĆ .<br />\nTe pol <a href=\"$1\">descargar el file multimediale</a> o <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">un riprodutor</a> par farlo 'ndar sul to browser.",
+ "timedmedia-more": "Altro...",
+ "timedmedia-dismiss": "Sara",
+ "timedmedia-download": "Descarga el file",
+ "timedmedia-play-media": "Riproduxi el file multimediałe",
+ "timedmedia-desc-link": "Informazion su sto file",
+ "timedmedia-oggThumb-version": "Par OggHandler ghe vole oggThumb version $1 o sucessiva.",
+ "timedmedia-oggThumb-failed": "oggThumb no'l xe stĆ  bon de crear la miniadura.",
+ "timedmedia-status-header": "Stato transcodifega",
+ "timedmedia-update-status": "Axorna stato transcodifega",
+ "timedmedia-status": "Stato",
+ "timedmedia-status-unknown": "Stato sconosĆ¹o",
+ "timedmedia-transcodeinfo": "Descrision derivĆ  dal Transcodexe",
+ "timedmedia-actions": "Asion",
+ "timedmedia-direct-link": "Descarga derivĆ ",
+ "timedmedia-not-ready": "NĆ³ pronto",
+ "timedmedia-completed-on": "Transodifega conpletĆ  $1",
+ "timedmedia-error-on": "Eror inte ła transcodifega so $1.",
+ "timedmedia-started-transcode": "Transcodifega tacĆ  $1 fa. $2",
+ "timedmedia-percent-done": "$1% sirca conpletĆ ",
+ "timedmedia-in-job-queue": "XontĆ  a ła coa de laoro $1 fa",
+ "timedmedia-unknown-target-size": "Dimension de destinasion sconosĆ¹a, $1 codifegĆ ",
+ "timedmedia-days": "{{PLURAL:$1|1 xorno|$1 xorni}}",
+ "timedmedia-hours": "{{PLURAL:$1|1 ora|$1 ore}}",
+ "timedmedia-minutes": "{{PLURAL:$1|1 minuto|$1 minuti}}",
+ "timedmedia-seconds": "{{PLURAL:$1|1 secondo|$1 secondi}}",
+ "timedmedia-reset": "Rexeta transcodifega",
+ "timedmedia-reset-confirm": "Resetando sta transcodifica tuti i file esistenti (se presenti) i sarĆ  scancelĆ  e la transcodifica la sarĆ  de novo zontĆ  a la coa de laoro. Ghe vorĆ  un po' de tenpo par rifar la transcodifica. <br /><br />\nVuto 'ndar vanti?",
+ "timedmedia-reset-error": "Eror inte'l resetajo de ła transcodifega.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Fonte $1",
+ "timedmedia-source-file-desc": "File orixenałe $1, $2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "File originale $1 ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "Video Ogg a basa larghesa de banda (160P)",
+ "timedmedia-derivative-desc-360p.ogv": "Video Ogg trasmetibiłe in streaming via Web (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "Video Ogg trasmetibiłe in streaming via Web (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "Video Ogg descargabiłe in alta cuałitĆ  (720P)",
+ "timedmedia-derivative-desc-160p.webm": "WebM trasmetibiłe in streaming via Web (160P)",
+ "timedmedia-derivative-desc-360p.webm": "WebM trasmetibiłe in streaming via Web (360P)",
+ "timedmedia-derivative-desc-480p.webm": "WebM trasmetibiłe in streaming via Web (480P)",
+ "timedmedia-derivative-desc-720p.webm": "WebM descargabiłe in alta cuałitĆ  (720P)",
+ "timedmedia-derivative-desc-320p.mp4": "MP4 par dispoxitivi conpatibiłi (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "MP4 trasmetibiłe in streaming via Web (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 in cuałitĆ  HD (720P)",
+ "timedmedia-subtitle-new": "Crear na nova tradusion o canbiar una de chełe che ghe xe xĆ ",
+ "timedmedia-subtitle-new-desc": "Siegli la lengua e struca el boton '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "VĆ ",
+ "timedmedia-subtitle-language": "$1 ($2) sototitołi",
+ "timedmedia-subtitle-no-video": "NĆ³ ghe xe nisun video asociĆ  a l'atuałe pĆ jina de i sototitołi",
+ "timedmedia-subtitle-no-subtitles": "NĆ³ ghe xe al momento sototitołi in $1 par sto video, xe posibiłe [{{fullurl:{{FULLPAGENAME}}|action=edit}} canbiar sta pĆ jina] par xontarli",
+ "timedmedia-subtitle-remote": "I sototitołi par sto file i se cata so $1",
+ "timedmedia-subtitle-remote-link": "Te poi vardar ła [$1 pĆ jina de descrision] par sto file so $2",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "{{PLURAL:$1|$1 video}}",
+ "timedmedia-ogg-videos": "{{PLURAL:$1|$1 video Ogg}}",
+ "timedmedia-webm-videos": "{{PLURAL:$1|$1 video WebM}}",
+ "timedmedia-derivative-state-transcodes": "{{PLURAL:$1|$1 transcodifega|$1 transcodifeghe}}",
+ "timedmedia-derivative-state-active": "{{PLURAL:$1|$1 transcodifega|$1 transcodifeghe}} in execusion",
+ "timedmedia-derivative-state-queued": "{{PLURAL:$1|$1 transcodifega|$1 transcodifeghe}} in coa",
+ "timedmedia-derivative-state-failed": "{{PLURAL:$1|$1 transcodifega nĆ³ riusia|$1 transcodifeghe nĆ³ riusie}}",
+ "timedmedia-file": "File",
+ "right-transcode-reset": "Reinposta i video difetoxi o transcodifegai cusƬ che i posa esar incluxi de novo in coa de laoro.",
+ "right-transcode-status": "Vixuałixa [[Special:TimedMediaHandler|informasion so l'atuałe ativitĆ  de transcodifega]]",
+ "action-transcode-status": "mostrar l'atuałe stato de ła transcodifega"
+}
diff --git a/extensions/TimedMediaHandler/i18n/vep.json b/extensions/TimedMediaHandler/i18n/vep.json
new file mode 100644
index 00000000..9046204e
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/vep.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Š˜Š³Š¾Ń€ŃŒ Š‘Ń€Š¾Š“сŠŗŠøŠ¹"
+ ]
+ },
+ "timedmedia-more": "Enamba...",
+ "timedmedia-dismiss": "Peitta",
+ "timedmedia-download": "JĆ¼gutoitta fail",
+ "timedmedia-desc-link": "Informacii neciÅ” failas"
+}
diff --git a/extensions/TimedMediaHandler/i18n/vi.json b/extensions/TimedMediaHandler/i18n/vi.json
new file mode 100644
index 00000000..63187717
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/vi.json
@@ -0,0 +1,130 @@
+{
+ "@metadata": {
+ "authors": [
+ "Minh Nguyen",
+ "Vinhtantran",
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ",
+ "Trįŗ§n Nguyį»…n Minh Huy",
+ "Max20091"
+ ]
+ },
+ "timedmedia-desc": "Bį»™ trƬnh bĆ y cĆ”c tįŗ­p tin Ć¢m thanh, video, vĆ  phį»„ đį» hį»— trį»£ WebM, Ogg Theora, Vorbis, vĆ  srt",
+ "timedmedia-ogg-short-audio": "Tįŗ­p tin Ć¢m thanh Ogg $1, $2",
+ "timedmedia-ogg-short-video": "tįŗ­p tin video Ogg $1, $2",
+ "timedmedia-ogg-short-general": "tįŗ­p tin Ogg $1, $2",
+ "timedmedia-ogg-long-audio": "tįŗ­p tin Ć¢m thanh Ogg $1, dĆ i $2, $3",
+ "timedmedia-ogg-long-video": "tįŗ­p tin video Ogg $1, dĆ i $2, $4Ɨ$5 điį»ƒm įŗ£nh, $3",
+ "timedmedia-ogg-long-multiplexed": "tįŗ­p tin Ogg cĆ³ Ć¢m thanh vĆ  video ghĆ©p kĆŖnh, $1, dĆ i $2, $4Ɨ$5 điį»ƒm įŗ£nh, $3 tįŗ„t cįŗ£",
+ "timedmedia-ogg-long-general": "tįŗ­p tin phĘ°Ę”ng tiį»‡n Ogg, dĆ i $2, $3",
+ "timedmedia-ogg-long-error": "Tįŗ­p tin Ogg cĆ³ lį»—i: $1",
+ "timedmedia-ogg-long-no-streams": "Tįŗ­p tin phĘ°Ę”ng tiį»‡n Ogg. ChĆŗ Ć½: KhĆ“ng cĆ³ cĆ“ng nhįŗ­n codec nĆ o trong tįŗ­p tin nĆ y.",
+ "timedmedia-webm-short-video": "tįŗ­p tin video WebM $1, $2",
+ "timedmedia-webm-long-video": "tįŗ­p tin WebM cĆ³ Ć¢m thanh vĆ  video ghĆ©p kĆŖnh, $1, dĆ i $2, $4Ɨ$5 điį»ƒm įŗ£nh, $3 tįŗ„t cįŗ£",
+ "timedmedia-flac-short-audio": "tįŗ­p tin Ć¢m thanh FLAC, $1",
+ "timedmedia-flac-long-audio": "tįŗ­p tin Ć¢m thanh FLAC, dĆ i $1, $2 tįŗ„t cįŗ£",
+ "timedmedia-wav-short-audio": "tįŗ­p tin Ć¢m thanh WAV, $1",
+ "timedmedia-wav-long-audio": "tįŗ­p tin Ć¢m thanh WAV, dĆ i $1, $2 tįŗ„t cįŗ£",
+ "timedmedia-wav-pcm-required": "Bįŗ”n chį»‰ cĆ³ thį»ƒ tįŗ£i lĆŖn cĆ”c tįŗ­p tin WAV PCM (Pulse Code Modulation).",
+ "timedmedia-mp4-short-video": "tįŗ­p tin video MP4 $1, $2",
+ "timedmedia-mp4-long-video": "tįŗ­p tin Ć¢m thanh/video MP4, $1, dĆ i $2, $4Ɨ$5 điį»ƒm įŗ£nh, $3 tįŗ„t cįŗ£",
+ "timedmedia-no-player-js": "Rįŗ„t tiįŗæc, hoįŗ·c JavaScript bį»‹ tįŗÆt trong trƬnh duyį»‡t cį»§a bįŗ”n hoįŗ·c trƬnh duyį»‡t khĆ“ng cĆ³ trƬnh chĘ”i nĆ o đʰį»£c hį»— trį»£.<br />\nBįŗ”n cĆ³ thį»ƒ <a href=\"$1\">tįŗ£i vį» đoįŗ”n Ć¢m hoįŗ·c đoįŗ”n video</a> hay <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download?uselang=vi\">tįŗ£i vį» mį»™t trƬnh chĘ”i</a> đį»ƒ chĘ”i đoįŗ”n Ć¢m hoįŗ·c đoįŗ”n video trong trƬnh duyį»‡t.",
+ "timedmedia-more": "ThĆŖm nį»Æaā€¦",
+ "timedmedia-dismiss": "ÄĆ³ng",
+ "timedmedia-download": "Tįŗ£i tįŗ­p tin xuį»‘ng",
+ "timedmedia-play-media": "ChĘ”i phĘ°Ę”ng tiį»‡n",
+ "timedmedia-desc-link": "Chi tiįŗæt cį»§a tįŗ­p tin nĆ y",
+ "timedmedia-oggThumb-version": "OggHandler cįŗ§n oggThumb, phiĆŖn bįŗ£n $1 trį»Ÿ lĆŖn.",
+ "timedmedia-oggThumb-failed": "oggThumb bį»‹ thįŗ„t bįŗ”i trong viį»‡c tįŗ”o hƬnh thu nhį».",
+ "timedmedia-status-header": "Trįŗ”ng thĆ”i chuyį»ƒn mĆ£",
+ "timedmedia-update-status": "Cįŗ­p nhįŗ­t trįŗ”ng thĆ”i chuyį»ƒn mĆ£",
+ "timedmedia-status": "Trįŗ”ng thĆ”i",
+ "timedmedia-status-unknown": "Trįŗ”ng thĆ”i khĆ“ng rƵ",
+ "timedmedia-transcodebitrate": "Tį»‘c đį»™ bit",
+ "timedmedia-transcodeduration": "Thį»i gian mĆ£ hĆ³a",
+ "timedmedia-transcodeinfo": "Đį»‹nh dįŗ”ng",
+ "timedmedia-actions": "TĆ”c vį»„",
+ "timedmedia-direct-link": "Tįŗ£i vį»",
+ "timedmedia-not-ready": "ChĘ°a sįŗµn",
+ "timedmedia-completed-on": "HoĆ n tįŗ„t vĆ o $1",
+ "timedmedia-error-on": "Lį»—i vĆ o $1",
+ "timedmedia-started-transcode": "BįŗÆt đįŗ§u cĆ”ch Ä‘Ć¢y $1. $2",
+ "timedmedia-percent-done": "HoĆ n tįŗ„t khoįŗ£ng $1%",
+ "timedmedia-in-job-queue": "ÄĆ£ thĆŖm vĆ o hĆ ng đį»£i viį»‡c cĆ”ch Ä‘Ć¢y $1",
+ "timedmedia-unknown-target-size": "Tįŗ­p tin đƭch cĆ³ kĆ­ch thĘ°į»›c khĆ“ng rƵ, Ä‘Ć£ chuyį»ƒn mĆ£ $1",
+ "timedmedia-days": "$1 ngĆ y",
+ "timedmedia-hours": "$1 giį»",
+ "timedmedia-minutes": "$1 phĆŗt",
+ "timedmedia-seconds": "$1 giĆ¢y",
+ "timedmedia-reset": "Đįŗ·t lįŗ”i chuyį»ƒn mĆ£",
+ "timedmedia-reset-confirm": "Viį»‡c đįŗ·t lįŗ”i chuyį»ƒn mĆ£ sįŗ½ xĆ³a tįŗ­p tin nĆ o hiį»‡n cĆ³, nįŗæu cĆ³, vĆ  sįŗ½ lįŗ”i thĆŖm viį»‡c chuyį»ƒn mĆ£ vĆ o hĆ ng đį»£i viį»‡c. Viį»‡c chuyį»ƒn mĆ£ lįŗ”i sįŗ½ mįŗ„t mį»™t chĆŗt thƬ giį».<br /><br />\nBįŗ”n cĆ³ chįŗÆc chįŗÆn muį»‘n tiįŗæp tį»„c?",
+ "timedmedia-reset-error": "Lį»—i khi đįŗ·t lįŗ”i viį»‡c chuyį»ƒn mĆ£.",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "Tįŗ­p tin $1 gį»‘c",
+ "timedmedia-source-file-desc": "tįŗ­p tin $1 gį»‘c, $2Ɨ$3 ($4)",
+ "timedmedia-source-audio-file-desc": "Tįŗ­p tin $1 gį»‘c ($2)",
+ "timedmedia-derivative-160p.ogv": "Ogg 160p",
+ "timedmedia-derivative-desc-160p.ogv": "Video Ogg băng thĆ“ng thįŗ„p (160p)",
+ "timedmedia-derivative-desc-240p.ogv": "Video Ogg cĆ³ thį»ƒ truyį»n dĆ²ng trĆŖn Web (240p)",
+ "timedmedia-derivative-360p.ogv": "Ogg 360p",
+ "timedmedia-derivative-desc-360p.ogv": "Video Ogg cĆ³ thį»ƒ truyį»n dĆ²ng trĆŖn Web (360p)",
+ "timedmedia-derivative-480p.ogv": "Ogg 480p",
+ "timedmedia-derivative-desc-480p.ogv": "Video Ogg cĆ³ thį»ƒ truyį»n dĆ²ng trĆŖn Web (480p)",
+ "timedmedia-derivative-720p.ogv": "Ogg 720p",
+ "timedmedia-derivative-desc-720p.ogv": "Video Ogg chįŗ„t lĘ°į»£ng cao cĆ³ thį»ƒ tįŗ£i vį» (720p)",
+ "timedmedia-derivative-1080p.ogv": "Ogg 1080p",
+ "timedmedia-derivative-desc-1080p.ogv": "Video Ogg HD đįŗ§y đį»§ cĆ³ thį»ƒ tįŗ£i vį» (1080p)",
+ "timedmedia-derivative-160p.webm": "WebM 160p",
+ "timedmedia-derivative-desc-160p.webm": "WebM cĆ³ thį»ƒ truyį»n dĆ²ng trĆŖn Web (160p)",
+ "timedmedia-derivative-360p.webm": "WebM 360p",
+ "timedmedia-derivative-desc-360p.webm": "WebM cĆ³ thį»ƒ truyį»n dĆ²ng trĆŖn Web (360p)",
+ "timedmedia-derivative-480p.webm": "WebM 480p",
+ "timedmedia-derivative-desc-480p.webm": "WebM cĆ³ thį»ƒ truyį»n dĆ²ng trĆŖn Web (480p)",
+ "timedmedia-derivative-720p.webm": "WebM 720p",
+ "timedmedia-derivative-desc-720p.webm": "WebM chįŗ„t lĘ°į»£ng cao cĆ³ thį»ƒ tįŗ£i vį» (720p)",
+ "timedmedia-derivative-1080p.webm": "WebM 1080p",
+ "timedmedia-derivative-desc-1080p.webm": "WebM HD đįŗ§y đį»§ cĆ³ thį»ƒ tįŗ£i vį» (1080p)",
+ "timedmedia-derivative-desc-2160p.webm": "WebM 4K đįŗ§y đį»§ cĆ³ thį»ƒ tįŗ£i vį» (2160p)",
+ "timedmedia-derivative-desc-360p.vp9.webm": "WebM VP9 cĆ³ thį»ƒ truyį»n dĆ²ng trĆŖn Web (360p)",
+ "timedmedia-derivative-desc-480p.vp9.webm": "WebM VP9 cĆ³ thį»ƒ truyį»n dĆ²ng trĆŖn Web (480p)",
+ "timedmedia-derivative-desc-720p.vp9.webm": "WebM HD cĆ³ thį»ƒ truyį»n dĆ²ng trĆŖn Web (720p)",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "WebM VP9 HD đįŗ§y đį»§ cĆ³ thį»ƒ truyį»n dĆ²ng (1080p)",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "WebM VP9 4K đįŗ§y đį»§ cĆ³ thį»ƒ truyį»n dĆ²ng (2160p)",
+ "timedmedia-derivative-320p.mp4": "H.264 320p",
+ "timedmedia-derivative-desc-320p.mp4": "MP4 thĆ­ch hį»£p vį»›i thiįŗæt bį»‹ (320p)",
+ "timedmedia-derivative-480p.mp4": "H.264 480p",
+ "timedmedia-derivative-desc-480p.mp4": "MP4 cĆ³ thį»ƒ truyį»n dĆ²ng trĆŖn Web (480p)",
+ "timedmedia-derivative-720p.mp4": "H.264 720p",
+ "timedmedia-derivative-desc-720p.mp4": "MP4 chįŗ„t lĘ°į»£ng HD (720p)",
+ "timedmedia-derivative-1080p.mp4": "H.264 1080p",
+ "timedmedia-derivative-desc-1080p.mp4": "MP4 HD đįŗ§y đį»§ (1080p)",
+ "timedmedia-derivative-desc-2160p.mp4": "MP4 4K đįŗ§y đį»§ (2160p)",
+ "timedmedia-subtitle-new": "Tįŗ”o bįŗ£n dį»‹ch mį»›i hoįŗ·c sį»­a đį»•i bįŗ£n dį»‹ch Ä‘Ć£ tį»“n tįŗ”i",
+ "timedmedia-subtitle-new-desc": "Chį»n ngĆ“n ngį»Æ vĆ  bįŗ„m nĆŗt '''{{int:Timedmedia-subtitle-new-go}}'''",
+ "timedmedia-subtitle-new-go": "Tįŗ”o",
+ "timedmedia-subtitle-language": "Tiį»ƒu đį» $1 ($2)",
+ "timedmedia-subtitle-no-video": "KhĆ“ng cĆ³ video nĆ o į»©ng vį»›i trang tiį»ƒu đį» nĆ y",
+ "timedmedia-subtitle-no-subtitles": "Hiį»‡n khĆ“ng cĆ³ tiį»ƒu đį» nĆ o cho video nĆ y bįŗ±ng $1. Bįŗ”n cĆ³ thį»ƒ [{{fullurl:{{FULLPAGENAME}}|action=edit}} sį»­a đį»•i trang nĆ y] đį»ƒ thĆŖm tiį»ƒu đį».",
+ "timedmedia-subtitle-remote": "Văn bįŗ£n đį»“ng bį»™ cį»§a tįŗ­p tin nĆ y đʰį»£c cung cįŗ„p tį»« $1",
+ "timedmedia-subtitle-remote-link": "Bįŗ”n cĆ³ thį»ƒ [$1 xem trang miĆŖu tįŗ£] tįŗ­p tin nĆ y trĆŖn $2",
+ "timedmediahandler": "Bį»™ xį»­ lĆ½ phĘ°Ę”ng tiį»‡n đį»“ng bį»™",
+ "timedmedia-videos": "$1 video",
+ "timedmedia-ogg-videos": "$1 video Ogg",
+ "timedmedia-webm-videos": "$1 video WebM",
+ "timedmedia-derivative-state-transcodes": "$1 tįŗ­p tin chuyį»ƒn mĆ£",
+ "timedmedia-derivative-state-active": "$1 tįŗ­p tin đang chuyį»ƒn mĆ£",
+ "timedmedia-derivative-state-queued": "$1 tįŗ­p tin chuyį»ƒn mĆ£ trong hĆ ng đį»£i",
+ "timedmedia-derivative-state-failed": "$1 tįŗ­p tin chuyį»ƒn mĆ£ thįŗ„t bįŗ”i",
+ "timedmedia-file": "Tįŗ­p tin",
+ "timedmedia-audios": "$1 tįŗ­p tin Ć¢m thanh",
+ "timedmedia-ogg-audios": "$1 tįŗ­p tin Ć¢m thanh Ogg",
+ "timedmedia-flac-audios": "$1 tįŗ­p tin Ć¢m thanh FLAC",
+ "timedmedia-wav-audios": "$1 tįŗ­p tin Ć¢m thanh WAV",
+ "right-transcode-reset": "Đįŗ·t lįŗ”i cĆ”c video hį»ng hoįŗ·c Ä‘Ć£ chuyį»ƒn mĆ£ đį»ƒ chĆØn chĆŗng nĆ³ lįŗ”i vĆ o hĆ ng đį»£i viį»‡c.",
+ "right-transcode-status": "Xem [[Special:TimedMediaHandler|thĆ“ng tin vį» hoįŗ”t đį»™ng chuyį»ƒn mĆ£ đang xįŗ£y ra]]",
+ "action-transcode-status": "xem trįŗ”ng thĆ”i chuyį»ƒn mĆ£ hiį»‡n tįŗ”i",
+ "orphanedtimedtext": "CĆ”c trang TimedText mį»“ cĆ“i",
+ "orphanedtimedtext-summary": "Danh sĆ”ch trang [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] khĆ“ng cĆ³ tįŗ­p tin tĘ°Ę”ng į»©ng.",
+ "orphanedtimedtext-unsupported": "Trang đįŗ·c biį»‡t nĆ y chį»‰ đʰį»£c hį»— trį»£ trĆŖn cĘ” sį»Ÿ dį»Æ liį»‡u MySQL.",
+ "orphanedtimedtext-notimedtext": "TimedText khĆ“ng đʰį»£c kĆ­ch hoįŗ”t trĆŖn wiki nĆ y.",
+ "apihelp-transcodereset-param-title": "TĆŖn tįŗ­p tin phĘ°Ę”ng tiį»‡n."
+}
diff --git a/extensions/TimedMediaHandler/i18n/vo.json b/extensions/TimedMediaHandler/i18n/vo.json
new file mode 100644
index 00000000..b20db88e
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/vo.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Malafaya",
+ "Smeira"
+ ]
+ },
+ "timedmedia-more": "Pluikos...",
+ "timedmedia-dismiss": "FƤrmĆ¼kƶn",
+ "timedmedia-download": "DonĆ¼kƶn ragivi",
+ "timedmedia-desc-link": "TefĆ¼ ragiv at",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-audio-file-desc": "Ragiv: $1 rigik ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/vro.json b/extensions/TimedMediaHandler/i18n/vro.json
new file mode 100644
index 00000000..2222475c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/vro.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "VƵrok"
+ ]
+ },
+ "timedmedia-no-player-js": "Kah'os om suq vƵrgokaejan JavaScript keelet vai olƵ-Ƶi sul tarvilist nĆ¤Ć¼tƤmistarkvarra.<br />\nSaat <a href=\"$1\">lƵigu alla laatiq</a> vai <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">laatiq alla tarkvara</a>, minka lƵiku vƵrgokaejan nĆ¤Ć¼dƤdƤq.",
+ "timedmedia-source-file": "LƤteq $1",
+ "timedmedia-source-audio-file-desc": "AlguperƤne $1-fail ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/wa.json b/extensions/TimedMediaHandler/i18n/wa.json
new file mode 100644
index 00000000..81ee357d
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/wa.json
@@ -0,0 +1,4 @@
+{
+ "@metadata": [],
+ "timedmedia-dismiss": "ClƓre"
+}
diff --git a/extensions/TimedMediaHandler/i18n/war.json b/extensions/TimedMediaHandler/i18n/war.json
new file mode 100644
index 00000000..2b28e939
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/war.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "JinJian"
+ ]
+ },
+ "timedmedia-source-file": "$1 tinitikangan",
+ "timedmedia-source-audio-file-desc": "Orihinal $1 file ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/wuu.json b/extensions/TimedMediaHandler/i18n/wuu.json
new file mode 100644
index 00000000..f61881e2
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/wuu.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Poiuyt"
+ ]
+ },
+ "timedmedia-no-player-js": "åÆ¹å¼—čµ·ļ¼Œä½ äøŖęµč§ˆå™Øē¦ē”Ø仔JavaScriptęˆ–å‘’äøä»»ä½•ę”ÆꌁäøŖę’­ę”¾å™Ø怂<br />\nä½ åÆ仄<a href=\"$1\">äø‹č½½ē®‡åŖē‰‡ę®µ</a>ꈖ<a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">äø‹č½½äø€åŖę’­ę”¾å™Ø</a>å„½å‹’ęµč§ˆå™Øé‡Œę’­ę”¾ē‰‡ę®µć€‚",
+ "timedmedia-source-file": "$1åŽŸå§‹ę–‡ä»¶",
+ "timedmedia-source-audio-file-desc": "原始$1ꖇ件 ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/xmf.json b/extensions/TimedMediaHandler/i18n/xmf.json
new file mode 100644
index 00000000..208dab64
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/xmf.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Silovan"
+ ]
+ },
+ "timedmedia-no-player-js": "įƒ—įƒ„įƒ•įƒįƒœ įƒ‘įƒ įƒįƒ£įƒ–įƒ”įƒ įƒ” įƒ’įƒįƒ—įƒ˜įƒØįƒ˜įƒš įƒ įƒ” JavaScript įƒ•įƒįƒ įƒ“įƒ įƒ•įƒ įƒ įƒ” įƒįƒ®įƒ•įƒ˜įƒšįƒ£įƒ įƒ˜ įƒžįƒ įƒįƒ’įƒ įƒįƒ›įƒ.<br />\nįƒ—įƒ„įƒ•įƒ įƒØįƒ”įƒ’įƒ˜įƒšįƒ”įƒ‘įƒ£įƒœįƒ <a href=\"$1\">įƒ’įƒ”įƒ’įƒœįƒįƒ­įƒįƒ įƒįƒ— įƒ™įƒšįƒ˜įƒžįƒ˜</a> įƒ•įƒįƒ įƒ“įƒ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">įƒ’įƒ”įƒ’įƒœįƒįƒ­įƒįƒ įƒįƒ— įƒžįƒ įƒįƒ’įƒ įƒįƒ›įƒ</a> įƒ™įƒšįƒ˜įƒžįƒ˜įƒØ įƒ‘įƒ įƒįƒ£įƒ–įƒ”įƒ įƒ” įƒįƒ įƒ©įƒ„įƒ˜įƒšįƒ”įƒ—/įƒįƒ«įƒ˜įƒ įƒįƒ¤įƒįƒšįƒ.",
+ "timedmedia-source-file": "įƒ¬įƒ§įƒ£ $1",
+ "timedmedia-source-audio-file-desc": "įƒįƒ įƒ˜įƒ’įƒ˜įƒœįƒįƒšįƒ˜ $1 įƒ¤įƒįƒ˜įƒšįƒ˜ ($2)"
+}
diff --git a/extensions/TimedMediaHandler/i18n/yi.json b/extensions/TimedMediaHandler/i18n/yi.json
new file mode 100644
index 00000000..693e8639
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/yi.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "פוילישע×Ø",
+ "ą¶“ą·ƒą·’ą¶³ą·” ą¶šą·ą·€ą·’ą¶±ą·Šą¶Æ"
+ ]
+ },
+ "timedmedia-no-player-js": "אנטשולדיגט, אײַע×Ø ×‘×œ×¢×˜×¢×Ø×¢×Ø ××“×¢×Ø ×”××˜ JavaScript אומאקטיווי×Øט אדע×Ø ×”××˜ נישט קיין געשטיצטן שפילע×Ø.<br />\nאי×Ø ×§×¢× ×˜ <a href=\"$1\">א×Øאפלאדן דעם פילמקליפ</a> אדע×Ø <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">א×Øאפלאדן א שפילע×Ø</a> צו שפילן דעם קליפ אין אײַע×Ø ×‘×œ×¢×˜×¢×Ø×¢×Ø.",
+ "timedmedia-dismiss": "שליהן",
+ "timedmedia-download": "א×ØאÖøפלאÖøדן טעקע",
+ "timedmedia-status": "הטאַטוה",
+ "timedmedia-source-file": "$1 מקו×Ø",
+ "timedmedia-source-audio-file-desc": "א×Øיגינעלע $1 טעקע ($2)",
+ "timedmedia-file": "טעקע"
+}
diff --git a/extensions/TimedMediaHandler/i18n/yue.json b/extensions/TimedMediaHandler/i18n/yue.json
new file mode 100644
index 00000000..9cb1e97c
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/yue.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Yueman",
+ "CRCHF"
+ ]
+ },
+ "timedmedia-desc": "Ogg Theora 同 Vorbis ęŖ”ę”ˆå˜…č™•ē†å™Øļ¼ŒåŠ åŸ‹ JavaScript ę’­ę”¾å™Ø",
+ "timedmedia-ogg-short-audio": "Ogg $1 č²ęŖ”ļ¼Œ$2",
+ "timedmedia-ogg-short-video": "Ogg $1 ē•«ęŖ”ļ¼Œ$2",
+ "timedmedia-ogg-short-general": "Ogg $1 åŖ’ęŖ”ļ¼Œ$2",
+ "timedmedia-ogg-long-audio": "Ogg $1 č²ęŖ”ļ¼Œé•·åŗ¦$2ļ¼Œ$3",
+ "timedmedia-ogg-long-video": "Ogg $1 ē•«ęŖ”ļ¼Œé•·åŗ¦$2ļ¼Œ$4Ɨ$5像ē“ ļ¼Œ$3",
+ "timedmedia-ogg-long-multiplexed": "Ogg å¤šå·„č²ļ¼ē•«ęŖ”ļ¼Œ$1ļ¼Œé•·åŗ¦$2ļ¼Œ$4Ɨ$5像ē“ ļ¼Œēø½å…±$3",
+ "timedmedia-ogg-long-general": "Ogg åŖ’ęŖ”ļ¼Œé•·åŗ¦$2ļ¼Œ$3",
+ "timedmedia-ogg-long-error": "ē„”ę•ˆå˜…oggęŖ”: $1",
+ "timedmedia-no-player-js": "對唔住ļ¼Œä½ å€‹ē€č¦½å™Øē„”開到 JavaScript ꈖ者ē„”ę”Æę“å˜…ę’­ę”¾ēØ‹å¼ć€‚<br />\nä½ åÆ仄 <a href=\"$1\">äø‹č¼‰ę¢ē‰‡</a> ꈖ者 <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">äø‹č¼‰ę’­ę”¾ē؋式</a> ē­‰ä½ å€‹ē€č¦½å™Ø都åÆ仄꒭怂",
+ "timedmedia-more": "ę›“å¤š...",
+ "timedmedia-dismiss": "閂",
+ "timedmedia-download": "äø‹č¼‰ęŖ”ę”ˆ",
+ "timedmedia-desc-link": "é—œę–¼å‘¢å€‹ęŖ”ę”ˆ",
+ "timedmedia-source-file": "$1 來ęŗęŖ”",
+ "timedmedia-source-audio-file-desc": "åŽŸęœ¬ $1 ęŖ”ę”ˆ ļ¼ˆ$2ļ¼‰"
+}
diff --git a/extensions/TimedMediaHandler/i18n/zh-hans.json b/extensions/TimedMediaHandler/i18n/zh-hans.json
new file mode 100644
index 00000000..cd324e67
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/zh-hans.json
@@ -0,0 +1,137 @@
+{
+ "@metadata": {
+ "authors": [
+ "Byfserag",
+ "Gaoxuewei",
+ "Hzy980512",
+ "Liangent",
+ "Liuxinyu970226",
+ "Shizhao",
+ "Xiaomingyan",
+ "Yfdyh000",
+ "ä¹Œę‹‰č·Øę°Ŗ"
+ ]
+ },
+ "extensionname-timedmedia": "TimedMediaHandler",
+ "timedmedia-desc": "éŸ³é¢‘ć€č§†é¢‘å’Œå­—å¹•ēš„处ē†ē؋åŗļ¼Œę”ÆꌁWebMļ¼ŒOgg Theora态Vorbisļ¼Œsrtę ¼å¼",
+ "timedmedia-ogg-short-audio": "Ogg $1å£°éŸ³ę–‡ä»¶ļ¼Œ$2",
+ "timedmedia-ogg-short-video": "Ogg $1č§†é¢‘ę–‡ä»¶ļ¼Œ$2",
+ "timedmedia-ogg-short-general": "Ogg $1åŖ’ä½“ę–‡ä»¶ļ¼Œ$2",
+ "timedmedia-ogg-long-audio": "Ogg $1å£°éŸ³ę–‡ä»¶ļ¼Œé•æåŗ¦$2ļ¼Œ$3",
+ "timedmedia-ogg-long-video": "Ogg $1č§†é¢‘ę–‡ä»¶ļ¼Œé•æåŗ¦$2ļ¼Œ$4 Ɨ $5像ē“ ļ¼Œ$3",
+ "timedmedia-ogg-long-multiplexed": "Ogg多巄声音/č§†é¢‘ę–‡ä»¶ļ¼Œ$1ļ¼Œé•æåŗ¦$2ļ¼Œ$4 Ɨ $5像ē“ ļ¼Œå…±$3",
+ "timedmedia-ogg-long-general": "OggåŖ’ä½“ę–‡ä»¶ļ¼Œé•æåŗ¦$2ļ¼Œ$3",
+ "timedmedia-ogg-long-error": "ꗠꕈēš„oggꖇ件ļ¼š$1",
+ "timedmedia-ogg-long-no-streams": "OggåŖ’ä½“ę–‡ä»¶ć€‚č­¦å‘Šļ¼šę²”ęœ‰č®¤åÆē”ØäŗŽę­¤ę–‡ä»¶ēš„ē¼–č§£ē å™Ø怂",
+ "timedmedia-webm-short-video": "WebM $1č§†é¢‘ę–‡ä»¶ļ¼Œ$2",
+ "timedmedia-webm-long-video": "WebM音频/č§†é¢‘ę–‡ä»¶ļ¼Œ$1ļ¼Œé•æåŗ¦$2ļ¼Œ$4 Ɨ $5像ē“ ļ¼Œå…±$3",
+ "timedmedia-flac-short-audio": "FLACéŸ³é¢‘ę–‡ä»¶ļ¼Œ$1",
+ "timedmedia-flac-long-audio": "FLACéŸ³é¢‘ę–‡ä»¶ļ¼Œé•æåŗ¦$1ļ¼Œē ēŽ‡$2",
+ "timedmedia-wav-short-audio": "WAVéŸ³é¢‘ę–‡ä»¶ļ¼Œ$1",
+ "timedmedia-wav-long-audio": "WAVéŸ³é¢‘ę–‡ä»¶ļ¼Œę€»å…±é•æ$1ļ¼Œē ēŽ‡$2",
+ "timedmedia-wav-pcm-required": "ę‚ØåŖčƒ½äøŠä¼ č„‰å†²ē¼–ē č°ƒåˆ¶ļ¼ˆPCMļ¼‰WAV怂",
+ "timedmedia-mp4-short-video": "MP4 $1č§†é¢‘ę–‡ä»¶ļ¼Œ$2",
+ "timedmedia-mp4-long-video": "MP4音频/č§†é¢‘ę–‡ä»¶ļ¼Œ$1ļ¼Œé•æåŗ¦$2ļ¼Œ$4 Ɨ $5像ē“ ļ¼Œ$3 overall",
+ "timedmedia-no-player-js": "ꊱꭉļ¼Œę‚Øēš„ęµč§ˆå™Øē¦ē”Øäŗ†JavaScriptęˆ–ę²”ęœ‰ä»»ä½•åÆę”Æꌁēš„ę’­ę”¾å™Ø怂<br />\nę‚ØåÆ仄<a href=\"$1\">äø‹č½½čæ™äøŖē‰‡ę®µ</a>ꈖ<a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">äø‹č½½äø€äøŖę’­ę”¾å™Ø</a>仄åœØęµč§ˆå™Øäø­ę’­ę”¾ē‰‡ę®µć€‚",
+ "timedmedia-more": "ę›“å¤š...",
+ "timedmedia-dismiss": "关闭",
+ "timedmedia-download": "äø‹č½½ę–‡ä»¶",
+ "timedmedia-play-media": "ę’­ę”¾åŖ’体",
+ "timedmedia-desc-link": "关äŗŽčÆ„ę–‡ä»¶",
+ "timedmedia-oggThumb-version": "OggHandleréœ€č¦oggThumb $1ęˆ–č€…ä¹‹åŽēš„ē‰ˆęœ¬ć€‚",
+ "timedmedia-oggThumb-failed": "oggThumbęœŖčƒ½åˆ›å»ŗē¼©ē•„å›¾ć€‚",
+ "timedmedia-status-header": "č½¬ē ēŠ¶ę€",
+ "timedmedia-update-status": "ę›“ę–°č½¬ē ēŠ¶ę€",
+ "timedmedia-status": "ēŠ¶ę€",
+ "timedmedia-status-unknown": "ęœŖēŸ„ēŠ¶ę€",
+ "timedmedia-transcodebitrate": "ęƔē‰¹ēŽ‡",
+ "timedmedia-transcodeduration": "ē¼–ē ę—¶é—“",
+ "timedmedia-transcodeinfo": "ę ¼å¼",
+ "timedmedia-actions": "ę“ä½œ",
+ "timedmedia-direct-link": "äø‹č½½",
+ "timedmedia-not-ready": "ęœŖå°±ē»Ŗ",
+ "timedmedia-completed-on": "å·²å®Œęˆ$1",
+ "timedmedia-error-on": "äŗŽ$1错čÆÆ",
+ "timedmedia-started-transcode": "äŗŽ$1å‰å¼€å§‹ć€‚$2",
+ "timedmedia-percent-done": "大ēŗ¦$1%å·²å®Œęˆ",
+ "timedmedia-in-job-queue": "ę·»åŠ åˆ°å·„ä½œé˜Ÿåˆ—åœØ$1前",
+ "timedmedia-unknown-target-size": "ęœŖēŸ„ē›®ę ‡å¤§å°ļ¼Œ$1å·²ē¼–ē ",
+ "timedmedia-days": "$1天",
+ "timedmedia-hours": "{{PLURAL:$1|$1å°ę—¶}}",
+ "timedmedia-minutes": "$1分",
+ "timedmedia-seconds": "$1ē§’",
+ "timedmedia-reset": "重ē½®č½¬ē ",
+ "timedmedia-reset-confirm": "重ē½®č½¬ē å°†ä¼šå°½åÆčƒ½ē§»é™¤ę‰€ęœ‰ēŽ°ęœ‰ę–‡ä»¶ļ¼Œå¹¶å°†å…¶é‡ę–°åŠ å…„åˆ°č½¬ē å·„ä½œé˜Ÿåˆ—ć€‚čæ™å°†éœ€č¦äø€äŗ›ę—¶é—“ę„é‡ę–°č½¬ē ć€‚<br /><br />\nę‚Øē”®å®šč¦ē»§ē»­å—ļ¼Ÿ",
+ "timedmedia-reset-error": "重ē½®č½¬ē å·„ä½œę—¶å‘ē”Ÿé”™čÆÆ怂",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1åŽŸå§‹ę–‡ä»¶",
+ "timedmedia-source-file-desc": "原始$1ꖇ件ļ¼Œ$2 Ɨ $3ļ¼ˆ$4ļ¼‰",
+ "timedmedia-source-audio-file-desc": "原始$1ꖇ件 ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "低åø¦å®½Oggč§†é¢‘ļ¼ˆ160Pļ¼‰",
+ "timedmedia-derivative-desc-240p.ogv": "Web굁åŖ’体Oggč§†é¢‘ļ¼ˆ240Pļ¼‰",
+ "timedmedia-derivative-desc-360p.ogv": "Web굁åŖ’体Oggč§†é¢‘ļ¼ˆ360Pļ¼‰",
+ "timedmedia-derivative-desc-480p.ogv": "Web굁åŖ’体Oggč§†é¢‘ļ¼ˆ480Pļ¼‰",
+ "timedmedia-derivative-desc-720p.ogv": "高ęø…åÆäø‹č½½Oggč§†é¢‘ļ¼ˆ720Pļ¼‰",
+ "timedmedia-derivative-desc-1080p.ogv": "å…Ø高ęø…åÆäø‹č½½ Ogg č§†é¢‘ (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "Web굁åŖ’体WebMļ¼ˆ160Pļ¼‰",
+ "timedmedia-derivative-desc-360p.webm": "Web굁åŖ’体WebMļ¼ˆ360Pļ¼‰",
+ "timedmedia-derivative-desc-480p.webm": "Web굁åŖ’体WebMļ¼ˆ480Pļ¼‰",
+ "timedmedia-derivative-desc-720p.webm": "高ęø…åÆäø‹č½½WebMč§†é¢‘ļ¼ˆ720Pļ¼‰",
+ "timedmedia-derivative-desc-1080p.webm": "å…Ø高ęø…åÆäø‹č½½ WebM (1080P)",
+ "timedmedia-derivative-desc-2160p.webm": "å…Ø高ęø…åÆäø‹č½½ WebM (2160P)",
+ "timedmedia-derivative-360p.vp9.webm": "VP9 360P",
+ "timedmedia-derivative-desc-360p.vp9.webm": "Web굁åŖ’体WebM VP9ļ¼ˆ360Pļ¼‰",
+ "timedmedia-derivative-480p.vp9.webm": "VP9 480P",
+ "timedmedia-derivative-desc-480p.vp9.webm": "Web굁åŖ’体WebM VP9ļ¼ˆ480Pļ¼‰",
+ "timedmedia-derivative-720p.vp9.webm": "VP9 720P",
+ "timedmedia-derivative-desc-720p.vp9.webm": "高ęø…굁åŖ’体WebM VP9ļ¼ˆ720Pļ¼‰",
+ "timedmedia-derivative-1080p.vp9.webm": "VP9 1080P",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "å…Ø高ęø…굁åŖ’体WebM VP9ļ¼ˆ1080Pļ¼‰",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "å…Ø高ęø…굁åŖ’体WebM VP9ļ¼ˆ2160Pļ¼‰",
+ "timedmedia-derivative-desc-320p.mp4": "č®¾å¤‡å‹å„½MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "ē½‘锵굁åŖ’体MP4 (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "高ęø…MP4 (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "å…Ø高ęø…ē”»č“Ø MP4 (1080P)",
+ "timedmedia-derivative-desc-2160p.mp4": "å…Ø高ęø…ē”»č“Ø MP4 (2160P)",
+ "timedmedia-derivative-ogg": "Ogg Vorbis",
+ "timedmedia-derivative-desc-ogg": "Ogg Vorbis",
+ "timedmedia-derivative-desc-mp3": "MP3",
+ "timedmedia-subtitle-new": "创å»ŗꖰēæ»čÆ‘ęˆ–ē¼–č¾‘ēŽ°ęœ‰ēæ»čƑ",
+ "timedmedia-subtitle-new-desc": "选ꋩčÆ­č؀ē„¶åŽęŒ‰'''{{int:Timedmedia-subtitle-new-go}}'''ęŒ‰é’®",
+ "timedmedia-subtitle-new-go": "ꏐäŗ¤",
+ "timedmedia-subtitle-language": "$1ļ¼ˆ$2ļ¼‰å­—幕",
+ "timedmedia-subtitle-no-video": "å½“å‰å­—å¹•é”µé¢ę²”ęœ‰å…³č”ēš„č§†é¢‘",
+ "timedmedia-subtitle-no-subtitles": "å½“å‰ę²”ęœ‰čæ™äøŖč§†é¢‘ēš„$1字幕ļ¼Œę‚ØåÆ仄[{{fullurl:{{FULLPAGENAME}}|action=edit}} ē¼–č¾‘čæ™äøŖ锵面]ä»„ę·»åŠ ",
+ "timedmedia-subtitle-remote": "ęœ¬ę–‡ä»¶ēš„å­—å¹•ę–‡ä»¶ä½äŗŽ$1",
+ "timedmedia-subtitle-remote-link": "ä½ åÆ仄åœØ$2ęŸ„ēœ‹čÆ„ę–‡ä»¶ēš„[$1 čÆ“ę˜Žé”µé¢]",
+ "timedmediahandler": "å®šę—¶åŖ’体处ē†ē؋åŗ",
+ "timedmedia-videos": "$1äøŖč§†é¢‘",
+ "timedmedia-ogg-videos": "$1äøŖOggč§†é¢‘",
+ "timedmedia-webm-videos": "$1äøŖWebMč§†é¢‘",
+ "timedmedia-derivative-state-transcodes": "$1ę¬”č½¬ē ",
+ "timedmedia-derivative-state-active": "$1äøŖę­£åœØčæč”Œēš„č½¬ē ä»»åŠ”",
+ "timedmedia-derivative-state-queued": "$1äøŖ队列äø­ēš„č½¬ē ä»»åŠ”",
+ "timedmedia-derivative-state-failed": "$1ę¬”č½¬ē å¤±č“„",
+ "timedmedia-file": "ꖇ件",
+ "timedmedia-audios": "$1äøŖéŸ³é¢‘ę–‡ä»¶",
+ "timedmedia-ogg-audios": "$1äøŖOggéŸ³é¢‘ę–‡ä»¶",
+ "timedmedia-flac-audios": "$1äøŖFLACéŸ³é¢‘ę–‡ä»¶",
+ "timedmedia-wav-audios": "$1äøŖWAVéŸ³é¢‘ę–‡ä»¶",
+ "right-transcode-reset": "重ē½®å·²å¤±č“„ęˆ–å·²č½¬ē ēš„č§†é¢‘å°†å…¶å†ę¬”加兄到作äøšé˜Ÿåˆ—äø­ć€‚",
+ "right-transcode-status": "ęŸ„ēœ‹[[Special:TimedMediaHandler|å½“å‰č½¬ē ę“»åŠØēš„äæ”ęÆ]]",
+ "action-transcode-status": "ęŸ„ēœ‹å½“前ēš„č½¬ē ēŠ¶ę€",
+ "orphanedtimedtext": "å­¤ē«‹ēš„TimedText锵面",
+ "orphanedtimedtext-summary": "ę²”ęœ‰åƹåŗ”ꖇ件ēš„[[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]]锵面ēš„列č”Ø怂",
+ "orphanedtimedtext-unsupported": "ę­¤ē‰¹ę®Šé”µé¢åŖę”ÆꌁMySQLę•°ę®åŗ“怂",
+ "orphanedtimedtext-notimedtext": "TimedTextåœØę­¤wikięœŖåÆē”Ø怂",
+ "apihelp-query+transcodestatus-description": "čŽ·å–ęŒ‡å®šę–‡ä»¶é”µé¢ēš„č½¬ē ēŠ¶ę€ć€‚",
+ "apihelp-query+transcodestatus-example-1": "čŽ·å¾—[[:File:Clip.webm]]ēš„čƑē ēŠ¶ę€",
+ "apihelp-query+videoinfo-description": "ę‰©å±•å›¾åƒäæ”ęÆä»„åŒ…å«č§†é¢‘ęŗļ¼ˆå›¾åƒę„ęŗļ¼‰äæ”ęÆ",
+ "apihelp-query+videoinfo-param-prop": "č¦čŽ·å–ēš„č§†é¢‘äæ”ęÆļ¼š\n;timestamp:äøŗäøŠä¼ ē‰ˆęœ¬ę·»åŠ ę—¶é—“ęˆ³ć€‚\n;user:ę·»åŠ äøŠä¼ č§†é¢‘ē‰ˆęœ¬ēš„ē”Øęˆ·ć€‚\n;userid:ę·»åŠ äøŠä¼ č§†é¢‘ē‰ˆęœ¬ēš„ē”ØꈷID怂\n;comment:åƹē‰ˆęœ¬ēš„ę³Ø释怂\n;parsedcomment:č§£ęžåƹē‰ˆęœ¬ēš„ę³Ø释怂\n;canonicaltitle:ę·»åŠ č§†é¢‘ę–‡ä»¶ēš„č§„čŒƒę ‡é¢˜ć€‚\n;url:ęä¾›č‡³č§†é¢‘ēš„URL及其čÆ“ę˜Žé”µé¢ć€‚\n;size:ę·»åŠ č§†é¢‘å¤§å°ļ¼ˆå­—节ļ¼‰ć€é«˜åŗ¦å’Œå®½åŗ¦ć€‚å¦‚ęœ‰éœ€č¦ä¼šę·»åŠ é”µé¢č®”ę•°å’ŒęŒē»­ę—¶é—“怂\n;dimensions:å¤§å°åˆ«åć€‚\n;sha1:äøŗč§†é¢‘ę·»åŠ SHA-1哈åøŒå€¼ć€‚\n;mime:ę·»åŠ č§†é¢‘ēš„MIMEē±»åž‹ć€‚\n;thumbmime:ę·»åŠ č§†é¢‘ē¼©ē•„图ēš„MIMEē±»åž‹ļ¼ˆéœ€č¦urlå’Œå‚ę•°$1urlwidthļ¼‰ć€‚\n;mediatype:ę·»åŠ č§†é¢‘åŖ’体ē±»åž‹ć€‚\n;metadata:列äø¾č§†é¢‘ē‰ˆęœ¬ēš„EXIFå…ƒę•°ę®ć€‚\n;commonmetadata:列äø¾ē‰¹å®šę–‡ä»¶ę ¼å¼ēš„č§†é¢‘ē‰ˆęœ¬ēš„å…ƒę•°ę®ć€‚\n;extmetadata:列äø¾ę ¼å¼åŒ–å…ƒę•°ę®\n;archivename:äøŗ非꜀ꖰē‰ˆęœ¬ę·»åŠ å­˜ę”£ē‰ˆęœ¬ēš„ę–‡ä»¶åć€‚\n;bitdepth:ę·»åŠ ē‰ˆęœ¬ēš„ä½ę·±åŗ¦ć€‚\n;uploadwarning:č¢«[[Special:Upload]]锵面ä½æē”Øä»„čŽ·å–ęœ‰å…³ēŽ°ęœ‰ę–‡ä»¶ēš„äæ”ęÆ怂äøé€‚ē”ØäŗŽMediaWikię øåæƒä»„外代ē ć€‚\n;derivatives:ę·»åŠ äøåŒę ¼å¼ēš„阵列äøŽéŸ³é¢‘ęˆ–č§†é¢‘ę–‡ä»¶ēš„åÆē”Ø高č“Ø量ē‰ˆęœ¬ć€‚",
+ "apihelp-query+videoinfo-example-1": "ę£€ē“¢ęœ‰å…³[[:File:Folgers.ogv]]ēš„äæ”ęÆ",
+ "apihelp-transcodereset-description": "å…·ęœ‰ā€œtranscode-resetā€ęƒé™ēš„ē”ØꈷåÆ仄重ē½®å’Œé‡ę–°čæč”Œč½¬ē ä»»åŠ”怂",
+ "apihelp-transcodereset-param-title": "åŖ’ä½“ę–‡ä»¶ę ‡é¢˜ć€‚",
+ "apihelp-transcodereset-param-transcodekey": "ę‚ØåøŒęœ›é‡ē½®ēš„č½¬ē å…³é”®å­—怂从[[Special:ApiHelp/query+transcodestatus|action=query&prop=transcodestatus]]čŽ·å–ć€‚",
+ "apihelp-transcodereset-example-1": "重ē½®[[:File:Clip.webm]]ēš„ę‰€ęœ‰čƑē ",
+ "apihelp-transcodereset-example-2": "重ē½®[[:File:Clip.webm]]ēš„ā€œ360_560kbs.webmā€č½¬ē å…³é”®å­—"
+}
diff --git a/extensions/TimedMediaHandler/i18n/zh-hant.json b/extensions/TimedMediaHandler/i18n/zh-hant.json
new file mode 100644
index 00000000..c80a3438
--- /dev/null
+++ b/extensions/TimedMediaHandler/i18n/zh-hant.json
@@ -0,0 +1,119 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gaoxuewei",
+ "Justincheng12345",
+ "Liuxinyu970226",
+ "Mark85296341",
+ "Simon Shek",
+ "LNDDYL",
+ "Cwlin0416"
+ ]
+ },
+ "timedmedia-desc": "音čØŠć€å½±ē‰‡čˆ‡å­—å¹•č™•ē†ē؋式ļ¼Œę”Æę“ēš„ę ¼å¼åŒ…å« WebMļ¼ŒOgg Theora态Vorbisļ¼Œsrt",
+ "timedmedia-ogg-short-audio": "Ogg $1 č²éŸ³ęŖ”ę”ˆļ¼Œ$2",
+ "timedmedia-ogg-short-video": "Ogg $1 å½±ē‰‡ęŖ”ļ¼Œ$2",
+ "timedmedia-ogg-short-general": "Ogg $1 åŖ’é«”ęŖ”ę”ˆļ¼Œ$2",
+ "timedmedia-ogg-long-audio": "Ogg $1 č²éŸ³ęŖ”ę”ˆļ¼Œé•·åŗ¦ $2ļ¼Œ$3",
+ "timedmedia-ogg-long-video": "Ogg $1 å½±ē‰‡ęŖ”ę”ˆļ¼Œé•·åŗ¦ $2ļ¼Œ$4 Ɨ $5 像ē“ ļ¼Œ$3",
+ "timedmedia-ogg-long-multiplexed": "Ogg 多巄音č؊/å½±ē‰‡ęŖ”ę”ˆļ¼Œ$1ļ¼Œé•·åŗ¦ $2ļ¼Œ$4 Ɨ $5 ē•«ē“ ļ¼Œå…± $3",
+ "timedmedia-ogg-long-general": "Ogg åŖ’é«”ęŖ”ę”ˆļ¼Œé•·åŗ¦ $2ļ¼Œ$3",
+ "timedmedia-ogg-long-error": "ē„”ꕈēš„ Ogg ęŖ”ę”ˆļ¼š$1",
+ "timedmedia-ogg-long-no-streams": "Ogg åŖ’é«”ęŖ”ę”ˆć€‚ č­¦å‘Šļ¼šē„”ę³•č¾Ø識ꭤęŖ”ę”ˆäø­ä½æē”Øēš„ē·Øē¢¼ć€‚",
+ "timedmedia-webm-short-video": "WebM $1 å½±ē‰‡ęŖ”ļ¼Œ$2",
+ "timedmedia-webm-long-video": "WebM 音č؊/å½±ē‰‡ęŖ”ę”ˆļ¼Œ$1ļ¼Œé•·åŗ¦ $2ļ¼Œ$4 Ɨ $5 ē•«ē“ ļ¼Œå…± $3",
+ "timedmedia-flac-short-audio": "FLAC 音č؊ęŖ”ę”ˆļ¼Œ$1",
+ "timedmedia-flac-long-audio": "FLAC 音頻ęŖ”ę”ˆļ¼Œé•·åŗ¦ $1ļ¼Œå…± $2",
+ "timedmedia-wav-short-audio": "WAV 音č؊ęŖ”ę”ˆļ¼Œ$1",
+ "timedmedia-wav-long-audio": "WAV 音č؊ęŖ”ę”ˆļ¼Œé•·åŗ¦ $1ļ¼Œå…± $2",
+ "timedmedia-wav-pcm-required": "ę‚Ø僅åÆäøŠå‚³ PCM (Pulse Code Modulation) WAV怂",
+ "timedmedia-mp4-short-video": "MP4 $1 å½±ē‰‡ęŖ”ļ¼Œ$2",
+ "timedmedia-mp4-long-video": "MP4 音č؊/å½±ē‰‡ęŖ”ę”ˆļ¼Œ$1ļ¼Œé•·åŗ¦ $2ļ¼Œ$4 Ɨ $5 ē•«ē“ ļ¼Œå…± $3",
+ "timedmedia-no-player-js": "ꊱꭉļ¼Œę‚Øēš„ē€č¦½å™ØęœŖ開啟 JavaScript ęˆ–ę²’ęœ‰ę”Æę“ēš„ę’­ę”¾ēØ‹å¼ć€‚<br />\nę‚ØåÆ <a href=\"$1\">äø‹č¼‰č©²ē‰‡ę®µ</a> ꈖ <a href=\"https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download\">äø‹č¼‰ę’­ę”¾å™Ø</a> 仄åœØę‚Øēš„ē€č¦½å™Øäø­ę’­ę”¾ć€‚",
+ "timedmedia-more": "ę›“å¤š...",
+ "timedmedia-dismiss": "關閉",
+ "timedmedia-download": "äø‹č¼‰ęŖ”ę”ˆ",
+ "timedmedia-play-media": "ę’­ę”¾åŖ’é«”",
+ "timedmedia-desc-link": "é—œę–¼é€™å€‹ęŖ”ę”ˆ",
+ "timedmedia-oggThumb-version": "OggHandler éœ€č¦ä½æē”Ø oggThumb ē‰ˆęœ¬ $1 ęˆ–ę›“ę–°ēš„ē‰ˆęœ¬ć€‚",
+ "timedmedia-oggThumb-failed": "oggThumb å»ŗē«‹ēø®åœ–å¤±ę•—ć€‚",
+ "timedmedia-status-header": "č½‰ē¢¼ē‹€ę…‹",
+ "timedmedia-update-status": "ę›“ę–°č½‰ē¢¼ē‹€ę…‹",
+ "timedmedia-status": "ē‹€ę…‹",
+ "timedmedia-status-unknown": "äøę˜Žē‹€ę…‹",
+ "timedmedia-transcodebitrate": "位元ēŽ‡",
+ "timedmedia-transcodeduration": "ē·Øē¢¼ę™‚é–“",
+ "timedmedia-transcodeinfo": "ę ¼å¼",
+ "timedmedia-actions": "動作",
+ "timedmedia-direct-link": "äø‹č¼‰",
+ "timedmedia-not-ready": "尚ęœŖå°±ē·’",
+ "timedmedia-completed-on": "å·²å®Œęˆ $1",
+ "timedmedia-error-on": "ę–¼ $1 ē™¼ē”ŸéŒÆčŖ¤ć€‚",
+ "timedmedia-started-transcode": "å·²ę–¼ $1 å‰é–‹å§‹ć€‚$2",
+ "timedmedia-percent-done": "大ē“„å·²å®Œęˆ $1%",
+ "timedmedia-in-job-queue": "å·²ę–¼ $1 å‰ę–°å¢žč‡³å·„ä½œåŗåˆ—",
+ "timedmedia-unknown-target-size": "äøę˜Žē›®ęؙ大小ļ¼Œå·²ē·Øē¢¼ $1",
+ "timedmedia-days": "$1 天",
+ "timedmedia-hours": "$1 å°ę™‚",
+ "timedmedia-minutes": "$1 分",
+ "timedmedia-seconds": "$1 ē§’",
+ "timedmedia-reset": "重čØ­č½‰ē¢¼",
+ "timedmedia-reset-confirm": "重čØ­č½‰ē¢¼ęœƒē§»é™¤ę‰€ęœ‰å·²å­˜åœØēš„ęŖ”ę”ˆļ¼Œäø¦é‡ę–°å°‡ęŖ”ę”ˆåŠ å…„č½‰ē¢¼å·„作åŗåˆ—ć€‚é€™éœ€č¦čŠ±č²»äø€äŗ›ę™‚é–“ä¾†é‡ę–°č½‰ē¢¼ć€‚<br /><br />\nę‚Øē¢ŗå®šč¦ē¹¼ēŗŒå—Žļ¼Ÿ",
+ "timedmedia-reset-error": "重čØ­č½‰ē¢¼å·„ä½œę™‚ē™¼ē”ŸéŒÆčŖ¤ć€‚",
+ "timedmedia-mp4": "MP4",
+ "timedmedia-source-file": "$1 來ęŗęŖ”ę”ˆ",
+ "timedmedia-source-file-desc": "$1 原始ęŖ”ę”ˆļ¼Œ$2 Ɨ $3 ($4)",
+ "timedmedia-source-audio-file-desc": "原始 $1 ęŖ”ę”ˆ ($2)",
+ "timedmedia-derivative-desc-160p.ogv": "低頻åƬ Ogg å½±ē‰‡ (160P)",
+ "timedmedia-derivative-desc-240p.ogv": "ē¶²ē«™åÆäø²ęµ Ogg å½±ē‰‡ (240P)",
+ "timedmedia-derivative-desc-360p.ogv": "ē¶²ē«™åÆäø²ęµ Ogg å½±ē‰‡ (360P)",
+ "timedmedia-derivative-desc-480p.ogv": "ē¶²ē«™åÆäø²ęµ Ogg å½±ē‰‡ (480P)",
+ "timedmedia-derivative-desc-720p.ogv": "高ē•«č³ŖåÆäø‹č¼‰ Ogg å½±ē‰‡ (720P)",
+ "timedmedia-derivative-desc-1080p.ogv": "Full HD åÆäø‹č¼‰ Ogg 影像 (1080P)",
+ "timedmedia-derivative-desc-160p.webm": "ē¶²ē«™åÆäø²ęµ WebM (160P)",
+ "timedmedia-derivative-desc-360p.webm": "ē¶²ē«™åÆäø²ęµ WebM (360P)",
+ "timedmedia-derivative-desc-480p.webm": "ē¶²ē«™åÆäø²ęµ WebM (480P)",
+ "timedmedia-derivative-desc-720p.webm": "高ē•«č³ŖåÆäø‹č¼‰ WebM (720P)",
+ "timedmedia-derivative-desc-1080p.webm": "Full HD åÆäø‹č¼‰ WebM (1080P)",
+ "timedmedia-derivative-desc-2160p.webm": "Full HD åÆäø‹č¼‰ WebM (2160P)",
+ "timedmedia-derivative-desc-360p.vp9.webm": "ē¶²ē«™åÆäø²ęµ WebM VP9 (360P)",
+ "timedmedia-derivative-desc-480p.vp9.webm": "ē¶²ē«™åÆäø²ęµ WebM VP9 (480P)",
+ "timedmedia-derivative-desc-720p.vp9.webm": "HD ē¶²ē«™åÆäø²ęµ WebM VP9 (720P)",
+ "timedmedia-derivative-desc-1080p.vp9.webm": "Full HD ē¶²ē«™åÆäø²ęµ WebM VP9 (1080P)",
+ "timedmedia-derivative-desc-2160p.vp9.webm": "Full 4K ē¶²ē«™åÆäø²ęµ WebM VP9 (2160P)",
+ "timedmedia-derivative-desc-320p.mp4": "č”Œå‹•č£ē½®ę˜“ē”Ø MP4 (320P)",
+ "timedmedia-derivative-desc-480p.mp4": "ē¶²ē«™åÆäø²ęµ MP4 (480P)",
+ "timedmedia-derivative-desc-720p.mp4": "高ęø…品č³Ŗ MP4 (720P)",
+ "timedmedia-derivative-desc-1080p.mp4": "Full HD 品č³Ŗ MP4 (1080P)",
+ "timedmedia-derivative-desc-2160p.mp4": "Full 4K 品č³Ŗ MP4 (2160P)",
+ "timedmedia-subtitle-new": "å»ŗē«‹ę–°ēæ»č­Æꈖē·Øč¼Æē¾ęœ‰ēæ»č­Æ",
+ "timedmedia-subtitle-new-desc": "č«‹éø꓇čŖžč؀後點éø '''{{int:Timedmedia-subtitle-new-go}}''' ꌉ鈕",
+ "timedmedia-subtitle-new-go": "åŸ·č”Œ",
+ "timedmedia-subtitle-language": "$1 ($2) 字幕",
+ "timedmedia-subtitle-no-video": "ē›®å‰ę²’ęœ‰čˆ‡å­—å¹•é é¢ē›ø關ēš„å½±ē‰‡ć€‚",
+ "timedmedia-subtitle-no-subtitles": "ę­¤å½±ē‰‡ē›®å‰ę²’ęœ‰ $1 ēš„字幕ļ¼Œę‚ØåÆ [{{fullurl:{{FULLPAGENAME}}|action=edit}} ē·Øč¼Æę­¤é é¢] ä¾†å¢žåŠ å­—å¹•ć€‚",
+ "timedmedia-subtitle-remote": "ę­¤ęŖ”ę”ˆēš„å­—å¹•ä½ę–¼ $1",
+ "timedmedia-subtitle-remote-link": "ę‚ØåÆę–¼ $2 ęŖ¢č¦–ę­¤ęŖ”ę”ˆēš„ [$1 ꏏčæ°é é¢]",
+ "timedmediahandler": "TimedMediaHandler",
+ "timedmedia-videos": "$1 個影ē‰‡",
+ "timedmedia-ogg-videos": "$1 個 Ogg å½±ē‰‡",
+ "timedmedia-webm-videos": "$1 個 WebM å½±ē‰‡",
+ "timedmedia-derivative-state-transcodes": "$1 å€‹č½‰ē¢¼å·„作",
+ "timedmedia-derivative-state-active": "$1 å€‹ę­£åœØåŸ·č”Œēš„č½‰ē¢¼å·„作",
+ "timedmedia-derivative-state-queued": "$1 個åœØåŗåˆ—äø­ēš„č½‰ē¢¼å·„作",
+ "timedmedia-derivative-state-failed": "$1 ę¬”č½‰ē¢¼å¤±ę•—",
+ "timedmedia-file": "ęŖ”ę”ˆ",
+ "timedmedia-audios": "$1 個音č؊ęŖ”ę”ˆ",
+ "timedmedia-ogg-audios": "$1 個 Ogg 音č؊ęŖ”ę”ˆ",
+ "timedmedia-flac-audios": "$1 個 FLAC 音č؊ęŖ”ę”ˆ",
+ "timedmedia-wav-audios": "$1 個 WAV 音č؊ęŖ”ę”ˆ",
+ "right-transcode-reset": "重čØ­å·²å¤±ę•—ęˆ–å·²č¼šē¢¼ēš„å½±ē‰‡ļ¼Œå°‡å…¶é‡ę–°ęŽ’å…„åŗåˆ—äø­ć€‚",
+ "right-transcode-status": "ęŖ¢č¦– [[Special:TimedMediaHandler|ē›®å‰č½‰ē¢¼ę“»å‹•ēš„č³‡č؊]]",
+ "action-transcode-status": "ęŖ¢č¦–ē›®å‰č½‰ē¢¼ē‹€ę…‹",
+ "orphanedtimedtext": "å­¤ē«‹ēš„ TimedText 頁面",
+ "orphanedtimedtext-summary": "ęœŖ關čÆ任何ęŖ”ę”ˆēš„ [[{{#special:AllPages/TimedText:}}|{{ns:TimedText}}]] 頁面ęø…å–®ć€‚",
+ "orphanedtimedtext-unsupported": "ę­¤ē‰¹ę®Šé é¢åƒ…ę”Æę“ä½æē”Ø MySQL č³‡ę–™åŗ«ć€‚",
+ "orphanedtimedtext-notimedtext": "ę­¤ Wiki ęœŖ開啟 TimedText åŠŸčƒ½ć€‚",
+ "apihelp-query+transcodestatus-description": "å–å¾—ęŒ‡å®šęŖ”ę”ˆé é¢ēš„č½‰ē¢¼ē‹€ę…‹ć€‚",
+ "apihelp-query+transcodestatus-example-1": "取得 [[:File:Clip.webm]] ēš„č½‰ē¢¼ē‹€ę…‹"
+}
diff --git a/extensions/TimedMediaHandler/libs/getid3/getid3.lib.php b/extensions/TimedMediaHandler/libs/getid3/getid3.lib.php
new file mode 100644
index 00000000..16d5318a
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/getid3.lib.php
@@ -0,0 +1,1346 @@
+<?php
+/////////////////////////////////////////////////////////////////
+/// getID3() by James Heinrich <info@getid3.org> //
+// available at http://getid3.sourceforge.net //
+// or http://www.getid3.org //
+/////////////////////////////////////////////////////////////////
+// //
+// getid3.lib.php - part of getID3() //
+// See readme.txt for more details //
+// ///
+/////////////////////////////////////////////////////////////////
+
+
+class getid3_lib
+{
+
+ public static function PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8') {
+ $returnstring = '';
+ for ($i = 0; $i < strlen($string); $i++) {
+ if ($hex) {
+ $returnstring .= str_pad(dechex(ord($string{$i})), 2, '0', STR_PAD_LEFT);
+ } else {
+ $returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string{$i}) ? $string{$i} : '¤');
+ }
+ if ($spaces) {
+ $returnstring .= ' ';
+ }
+ }
+ if (!empty($htmlencoding)) {
+ if ($htmlencoding === true) {
+ $htmlencoding = 'UTF-8'; // prior to getID3 v1.9.0 the function's 4th parameter was boolean
+ }
+ $returnstring = htmlentities($returnstring, ENT_QUOTES, $htmlencoding);
+ }
+ return $returnstring;
+ }
+
+ public static function trunc($floatnumber) {
+ // truncates a floating-point number at the decimal point
+ // returns int (if possible, otherwise float)
+ if ($floatnumber >= 1) {
+ $truncatednumber = floor($floatnumber);
+ } elseif ($floatnumber <= -1) {
+ $truncatednumber = ceil($floatnumber);
+ } else {
+ $truncatednumber = 0;
+ }
+ if (self::intValueSupported($truncatednumber)) {
+ $truncatednumber = (int) $truncatednumber;
+ }
+ return $truncatednumber;
+ }
+
+
+ public static function safe_inc(&$variable, $increment=1) {
+ if (isset($variable)) {
+ $variable += $increment;
+ } else {
+ $variable = $increment;
+ }
+ return true;
+ }
+
+ public static function CastAsInt($floatnum) {
+ // convert to float if not already
+ $floatnum = (float) $floatnum;
+
+ // convert a float to type int, only if possible
+ if (self::trunc($floatnum) == $floatnum) {
+ // it's not floating point
+ if (self::intValueSupported($floatnum)) {
+ // it's within int range
+ $floatnum = (int) $floatnum;
+ }
+ }
+ return $floatnum;
+ }
+
+ public static function intValueSupported($num) {
+ // check if integers are 64-bit
+ static $hasINT64 = null;
+ if ($hasINT64 === null) { // 10x faster than is_null()
+ $hasINT64 = is_int(pow(2, 31)); // 32-bit int are limited to (2^31)-1
+ if (!$hasINT64 && !defined('PHP_INT_MIN')) {
+ define('PHP_INT_MIN', ~PHP_INT_MAX);
+ }
+ }
+ // if integers are 64-bit - no other check required
+ if ($hasINT64 || (($num <= PHP_INT_MAX) && ($num >= PHP_INT_MIN))) {
+ return true;
+ }
+ return false;
+ }
+
+ public static function DecimalizeFraction($fraction) {
+ list($numerator, $denominator) = explode('/', $fraction);
+ return $numerator / ($denominator ? $denominator : 1);
+ }
+
+
+ public static function DecimalBinary2Float($binarynumerator) {
+ $numerator = self::Bin2Dec($binarynumerator);
+ $denominator = self::Bin2Dec('1'.str_repeat('0', strlen($binarynumerator)));
+ return ($numerator / $denominator);
+ }
+
+
+ public static function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) {
+ // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
+ if (strpos($binarypointnumber, '.') === false) {
+ $binarypointnumber = '0.'.$binarypointnumber;
+ } elseif ($binarypointnumber{0} == '.') {
+ $binarypointnumber = '0'.$binarypointnumber;
+ }
+ $exponent = 0;
+ while (($binarypointnumber{0} != '1') || (substr($binarypointnumber, 1, 1) != '.')) {
+ if (substr($binarypointnumber, 1, 1) == '.') {
+ $exponent--;
+ $binarypointnumber = substr($binarypointnumber, 2, 1).'.'.substr($binarypointnumber, 3);
+ } else {
+ $pointpos = strpos($binarypointnumber, '.');
+ $exponent += ($pointpos - 1);
+ $binarypointnumber = str_replace('.', '', $binarypointnumber);
+ $binarypointnumber = $binarypointnumber{0}.'.'.substr($binarypointnumber, 1);
+ }
+ }
+ $binarypointnumber = str_pad(substr($binarypointnumber, 0, $maxbits + 2), $maxbits + 2, '0', STR_PAD_RIGHT);
+ return array('normalized'=>$binarypointnumber, 'exponent'=>(int) $exponent);
+ }
+
+
+ public static function Float2BinaryDecimal($floatvalue) {
+ // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
+ $maxbits = 128; // to how many bits of precision should the calculations be taken?
+ $intpart = self::trunc($floatvalue);
+ $floatpart = abs($floatvalue - $intpart);
+ $pointbitstring = '';
+ while (($floatpart != 0) && (strlen($pointbitstring) < $maxbits)) {
+ $floatpart *= 2;
+ $pointbitstring .= (string) self::trunc($floatpart);
+ $floatpart -= self::trunc($floatpart);
+ }
+ $binarypointnumber = decbin($intpart).'.'.$pointbitstring;
+ return $binarypointnumber;
+ }
+
+
+ public static function Float2String($floatvalue, $bits) {
+ // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
+ switch ($bits) {
+ case 32:
+ $exponentbits = 8;
+ $fractionbits = 23;
+ break;
+
+ case 64:
+ $exponentbits = 11;
+ $fractionbits = 52;
+ break;
+
+ default:
+ return false;
+ break;
+ }
+ if ($floatvalue >= 0) {
+ $signbit = '0';
+ } else {
+ $signbit = '1';
+ }
+ $normalizedbinary = self::NormalizeBinaryPoint(self::Float2BinaryDecimal($floatvalue), $fractionbits);
+ $biasedexponent = pow(2, $exponentbits - 1) - 1 + $normalizedbinary['exponent']; // (127 or 1023) +/- exponent
+ $exponentbitstring = str_pad(decbin($biasedexponent), $exponentbits, '0', STR_PAD_LEFT);
+ $fractionbitstring = str_pad(substr($normalizedbinary['normalized'], 2), $fractionbits, '0', STR_PAD_RIGHT);
+
+ return self::BigEndian2String(self::Bin2Dec($signbit.$exponentbitstring.$fractionbitstring), $bits % 8, false);
+ }
+
+
+ public static function LittleEndian2Float($byteword) {
+ return self::BigEndian2Float(strrev($byteword));
+ }
+
+
+ public static function BigEndian2Float($byteword) {
+ // ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
+ // http://www.psc.edu/general/software/packages/ieee/ieee.html
+ // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
+
+ $bitword = self::BigEndian2Bin($byteword);
+ if (!$bitword) {
+ return 0;
+ }
+ $signbit = $bitword{0};
+
+ switch (strlen($byteword) * 8) {
+ case 32:
+ $exponentbits = 8;
+ $fractionbits = 23;
+ break;
+
+ case 64:
+ $exponentbits = 11;
+ $fractionbits = 52;
+ break;
+
+ case 80:
+ // 80-bit Apple SANE format
+ // http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/
+ $exponentstring = substr($bitword, 1, 15);
+ $isnormalized = intval($bitword{16});
+ $fractionstring = substr($bitword, 17, 63);
+ $exponent = pow(2, self::Bin2Dec($exponentstring) - 16383);
+ $fraction = $isnormalized + self::DecimalBinary2Float($fractionstring);
+ $floatvalue = $exponent * $fraction;
+ if ($signbit == '1') {
+ $floatvalue *= -1;
+ }
+ return $floatvalue;
+ break;
+
+ default:
+ return false;
+ break;
+ }
+ $exponentstring = substr($bitword, 1, $exponentbits);
+ $fractionstring = substr($bitword, $exponentbits + 1, $fractionbits);
+ $exponent = self::Bin2Dec($exponentstring);
+ $fraction = self::Bin2Dec($fractionstring);
+
+ if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) {
+ // Not a Number
+ $floatvalue = false;
+ } elseif (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction == 0)) {
+ if ($signbit == '1') {
+ $floatvalue = '-infinity';
+ } else {
+ $floatvalue = '+infinity';
+ }
+ } elseif (($exponent == 0) && ($fraction == 0)) {
+ if ($signbit == '1') {
+ $floatvalue = -0;
+ } else {
+ $floatvalue = 0;
+ }
+ $floatvalue = ($signbit ? 0 : -0);
+ } elseif (($exponent == 0) && ($fraction != 0)) {
+ // These are 'unnormalized' values
+ $floatvalue = pow(2, (-1 * (pow(2, $exponentbits - 1) - 2))) * self::DecimalBinary2Float($fractionstring);
+ if ($signbit == '1') {
+ $floatvalue *= -1;
+ }
+ } elseif ($exponent != 0) {
+ $floatvalue = pow(2, ($exponent - (pow(2, $exponentbits - 1) - 1))) * (1 + self::DecimalBinary2Float($fractionstring));
+ if ($signbit == '1') {
+ $floatvalue *= -1;
+ }
+ }
+ return (float) $floatvalue;
+ }
+
+
+ public static function BigEndian2Int($byteword, $synchsafe=false, $signed=false) {
+ $intvalue = 0;
+ $bytewordlen = strlen($byteword);
+ if ($bytewordlen == 0) {
+ return false;
+ }
+ for ($i = 0; $i < $bytewordlen; $i++) {
+ if ($synchsafe) { // disregard MSB, effectively 7-bit bytes
+ //$intvalue = $intvalue | (ord($byteword{$i}) & 0x7F) << (($bytewordlen - 1 - $i) * 7); // faster, but runs into problems past 2^31 on 32-bit systems
+ $intvalue += (ord($byteword{$i}) & 0x7F) * pow(2, ($bytewordlen - 1 - $i) * 7);
+ } else {
+ $intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i));
+ }
+ }
+ if ($signed && !$synchsafe) {
+ // synchsafe ints are not allowed to be signed
+ if ($bytewordlen <= PHP_INT_SIZE) {
+ $signMaskBit = 0x80 << (8 * ($bytewordlen - 1));
+ if ($intvalue & $signMaskBit) {
+ $intvalue = 0 - ($intvalue & ($signMaskBit - 1));
+ }
+ } else {
+ throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits ('.strlen($byteword).') in self::BigEndian2Int()');
+ break;
+ }
+ }
+ return self::CastAsInt($intvalue);
+ }
+
+
+ public static function LittleEndian2Int($byteword, $signed=false) {
+ return self::BigEndian2Int(strrev($byteword), false, $signed);
+ }
+
+
+ public static function BigEndian2Bin($byteword) {
+ $binvalue = '';
+ $bytewordlen = strlen($byteword);
+ for ($i = 0; $i < $bytewordlen; $i++) {
+ $binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT);
+ }
+ return $binvalue;
+ }
+
+
+ public static function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) {
+ if ($number < 0) {
+ throw new Exception('ERROR: self::BigEndian2String() does not support negative numbers');
+ }
+ $maskbyte = (($synchsafe || $signed) ? 0x7F : 0xFF);
+ $intstring = '';
+ if ($signed) {
+ if ($minbytes > PHP_INT_SIZE) {
+ throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits in self::BigEndian2String()');
+ }
+ $number = $number & (0x80 << (8 * ($minbytes - 1)));
+ }
+ while ($number != 0) {
+ $quotient = ($number / ($maskbyte + 1));
+ $intstring = chr(ceil(($quotient - floor($quotient)) * $maskbyte)).$intstring;
+ $number = floor($quotient);
+ }
+ return str_pad($intstring, $minbytes, "\x00", STR_PAD_LEFT);
+ }
+
+
+ public static function Dec2Bin($number) {
+ while ($number >= 256) {
+ $bytes[] = (($number / 256) - (floor($number / 256))) * 256;
+ $number = floor($number / 256);
+ }
+ $bytes[] = $number;
+ $binstring = '';
+ for ($i = 0; $i < count($bytes); $i++) {
+ $binstring = (($i == count($bytes) - 1) ? decbin($bytes[$i]) : str_pad(decbin($bytes[$i]), 8, '0', STR_PAD_LEFT)).$binstring;
+ }
+ return $binstring;
+ }
+
+
+ public static function Bin2Dec($binstring, $signed=false) {
+ $signmult = 1;
+ if ($signed) {
+ if ($binstring{0} == '1') {
+ $signmult = -1;
+ }
+ $binstring = substr($binstring, 1);
+ }
+ $decvalue = 0;
+ for ($i = 0; $i < strlen($binstring); $i++) {
+ $decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i);
+ }
+ return self::CastAsInt($decvalue * $signmult);
+ }
+
+
+ public static function Bin2String($binstring) {
+ // return 'hi' for input of '0110100001101001'
+ $string = '';
+ $binstringreversed = strrev($binstring);
+ for ($i = 0; $i < strlen($binstringreversed); $i += 8) {
+ $string = chr(self::Bin2Dec(strrev(substr($binstringreversed, $i, 8)))).$string;
+ }
+ return $string;
+ }
+
+
+ public static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
+ $intstring = '';
+ while ($number > 0) {
+ if ($synchsafe) {
+ $intstring = $intstring.chr($number & 127);
+ $number >>= 7;
+ } else {
+ $intstring = $intstring.chr($number & 255);
+ $number >>= 8;
+ }
+ }
+ return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
+ }
+
+
+ public static function array_merge_clobber($array1, $array2) {
+ // written by kcŲhireability*com
+ // taken from http://www.php.net/manual/en/function.array-merge-recursive.php
+ if (!is_array($array1) || !is_array($array2)) {
+ return false;
+ }
+ $newarray = $array1;
+ foreach ($array2 as $key => $val) {
+ if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
+ $newarray[$key] = self::array_merge_clobber($newarray[$key], $val);
+ } else {
+ $newarray[$key] = $val;
+ }
+ }
+ return $newarray;
+ }
+
+
+ public static function array_merge_noclobber($array1, $array2) {
+ if (!is_array($array1) || !is_array($array2)) {
+ return false;
+ }
+ $newarray = $array1;
+ foreach ($array2 as $key => $val) {
+ if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
+ $newarray[$key] = self::array_merge_noclobber($newarray[$key], $val);
+ } elseif (!isset($newarray[$key])) {
+ $newarray[$key] = $val;
+ }
+ }
+ return $newarray;
+ }
+
+
+ public static function ksort_recursive(&$theArray) {
+ ksort($theArray);
+ foreach ($theArray as $key => $value) {
+ if (is_array($value)) {
+ self::ksort_recursive($theArray[$key]);
+ }
+ }
+ return true;
+ }
+
+ public static function fileextension($filename, $numextensions=1) {
+ if (strstr($filename, '.')) {
+ $reversedfilename = strrev($filename);
+ $offset = 0;
+ for ($i = 0; $i < $numextensions; $i++) {
+ $offset = strpos($reversedfilename, '.', $offset + 1);
+ if ($offset === false) {
+ return '';
+ }
+ }
+ return strrev(substr($reversedfilename, 0, $offset));
+ }
+ return '';
+ }
+
+
+ public static function PlaytimeString($seconds) {
+ $sign = (($seconds < 0) ? '-' : '');
+ $seconds = round(abs($seconds));
+ $H = (int) floor( $seconds / 3600);
+ $M = (int) floor(($seconds - (3600 * $H) ) / 60);
+ $S = (int) round( $seconds - (3600 * $H) - (60 * $M) );
+ return $sign.($H ? $H.':' : '').($H ? str_pad($M, 2, '0', STR_PAD_LEFT) : intval($M)).':'.str_pad($S, 2, 0, STR_PAD_LEFT);
+ }
+
+
+ public static function DateMac2Unix($macdate) {
+ // Macintosh timestamp: seconds since 00:00h January 1, 1904
+ // UNIX timestamp: seconds since 00:00h January 1, 1970
+ return self::CastAsInt($macdate - 2082844800);
+ }
+
+
+ public static function FixedPoint8_8($rawdata) {
+ return self::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (self::BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8));
+ }
+
+
+ public static function FixedPoint16_16($rawdata) {
+ return self::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (self::BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16));
+ }
+
+
+ public static function FixedPoint2_30($rawdata) {
+ $binarystring = self::BigEndian2Bin($rawdata);
+ return self::Bin2Dec(substr($binarystring, 0, 2)) + (float) (self::Bin2Dec(substr($binarystring, 2, 30)) / pow(2, 30));
+ }
+
+
+ public static function CreateDeepArray($ArrayPath, $Separator, $Value) {
+ // assigns $Value to a nested array path:
+ // $foo = self::CreateDeepArray('/path/to/my', '/', 'file.txt')
+ // is the same as:
+ // $foo = array('path'=>array('to'=>'array('my'=>array('file.txt'))));
+ // or
+ // $foo['path']['to']['my'] = 'file.txt';
+ $ArrayPath = ltrim($ArrayPath, $Separator);
+ if (($pos = strpos($ArrayPath, $Separator)) !== false) {
+ $ReturnedArray[substr($ArrayPath, 0, $pos)] = self::CreateDeepArray(substr($ArrayPath, $pos + 1), $Separator, $Value);
+ } else {
+ $ReturnedArray[$ArrayPath] = $Value;
+ }
+ return $ReturnedArray;
+ }
+
+ public static function array_max($arraydata, $returnkey=false) {
+ $maxvalue = false;
+ $maxkey = false;
+ foreach ($arraydata as $key => $value) {
+ if (!is_array($value)) {
+ if ($value > $maxvalue) {
+ $maxvalue = $value;
+ $maxkey = $key;
+ }
+ }
+ }
+ return ($returnkey ? $maxkey : $maxvalue);
+ }
+
+ public static function array_min($arraydata, $returnkey=false) {
+ $minvalue = false;
+ $minkey = false;
+ foreach ($arraydata as $key => $value) {
+ if (!is_array($value)) {
+ if ($value > $minvalue) {
+ $minvalue = $value;
+ $minkey = $key;
+ }
+ }
+ }
+ return ($returnkey ? $minkey : $minvalue);
+ }
+
+ public static function XML2array($XMLstring) {
+ if (function_exists('simplexml_load_string')
+ && function_exists('get_object_vars')
+ && function_exists('libxml_disable_entity_loader')
+ ) {
+ $loader = libxml_disable_entity_loader(true);
+ $XMLobject = simplexml_load_string($XMLstring);
+ $return = self::SimpleXMLelement2array($XMLobject);
+ libxml_disable_entity_loader($loader);
+ return $return;
+ }
+ return false;
+ }
+
+ public static function SimpleXMLelement2array($XMLobject) {
+ if (!is_object($XMLobject) && !is_array($XMLobject)) {
+ return $XMLobject;
+ }
+ $XMLarray = (is_object($XMLobject) ? get_object_vars($XMLobject) : $XMLobject);
+ foreach ($XMLarray as $key => $value) {
+ $XMLarray[$key] = self::SimpleXMLelement2array($value);
+ }
+ return $XMLarray;
+ }
+
+
+ // Allan Hansen <ahŲartemis*dk>
+ // self::md5_data() - returns md5sum for a file from startuing position to absolute end position
+ public static function hash_data($file, $offset, $end, $algorithm) {
+ static $tempdir = '';
+ if (!self::intValueSupported($end)) {
+ return false;
+ }
+ switch ($algorithm) {
+ case 'md5':
+ $hash_function = 'md5_file';
+ $unix_call = 'md5sum';
+ $windows_call = 'md5sum.exe';
+ $hash_length = 32;
+ break;
+
+ case 'sha1':
+ $hash_function = 'sha1_file';
+ $unix_call = 'sha1sum';
+ $windows_call = 'sha1sum.exe';
+ $hash_length = 40;
+ break;
+
+ default:
+ throw new Exception('Invalid algorithm ('.$algorithm.') in self::hash_data()');
+ break;
+ }
+ $size = $end - $offset;
+ while (true) {
+ if (GETID3_OS_ISWINDOWS) {
+
+ // It seems that sha1sum.exe for Windows only works on physical files, does not accept piped data
+ // Fall back to create-temp-file method:
+ if ($algorithm == 'sha1') {
+ break;
+ }
+
+ $RequiredFiles = array('cygwin1.dll', 'head.exe', 'tail.exe', $windows_call);
+ foreach ($RequiredFiles as $required_file) {
+ if (!is_readable(GETID3_HELPERAPPSDIR.$required_file)) {
+ // helper apps not available - fall back to old method
+ break 2;
+ }
+ }
+ $commandline = GETID3_HELPERAPPSDIR.'head.exe -c '.$end.' '.escapeshellarg(str_replace('/', DIRECTORY_SEPARATOR, $file)).' | ';
+ $commandline .= GETID3_HELPERAPPSDIR.'tail.exe -c '.$size.' | ';
+ $commandline .= GETID3_HELPERAPPSDIR.$windows_call;
+
+ } else {
+
+ $commandline = 'head -c'.$end.' '.escapeshellarg($file).' | ';
+ $commandline .= 'tail -c'.$size.' | ';
+ $commandline .= $unix_call;
+
+ }
+ if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
+ //throw new Exception('PHP running in Safe Mode - backtick operator not available, using slower non-system-call '.$algorithm.' algorithm');
+ break;
+ }
+ return substr(`$commandline`, 0, $hash_length);
+ }
+
+ if (empty($tempdir)) {
+ // yes this is ugly, feel free to suggest a better way
+ require_once(dirname(__FILE__).'/getid3.php');
+ $getid3_temp = new getID3();
+ $tempdir = $getid3_temp->tempdir;
+ unset($getid3_temp);
+ }
+ // try to create a temporary file in the system temp directory - invalid dirname should force to system temp dir
+ if (($data_filename = tempnam($tempdir, 'gI3')) === false) {
+ // can't find anywhere to create a temp file, just fail
+ return false;
+ }
+
+ // Init
+ $result = false;
+
+ // copy parts of file
+ try {
+ self::CopyFileParts($file, $data_filename, $offset, $end - $offset);
+ $result = $hash_function($data_filename);
+ } catch (Exception $e) {
+ throw new Exception('self::CopyFileParts() failed in getid_lib::hash_data(): '.$e->getMessage());
+ }
+ unlink($data_filename);
+ return $result;
+ }
+
+ public static function CopyFileParts($filename_source, $filename_dest, $offset, $length) {
+ if (!self::intValueSupported($offset + $length)) {
+ throw new Exception('cannot copy file portion, it extends beyond the '.round(PHP_INT_MAX / 1073741824).'GB limit');
+ }
+ if (is_readable($filename_source) && is_file($filename_source) && ($fp_src = fopen($filename_source, 'rb'))) {
+ if (($fp_dest = fopen($filename_dest, 'wb'))) {
+ if (fseek($fp_src, $offset, SEEK_SET) == 0) {
+ $byteslefttowrite = $length;
+ while (($byteslefttowrite > 0) && ($buffer = fread($fp_src, min($byteslefttowrite, getID3::FREAD_BUFFER_SIZE)))) {
+ $byteswritten = fwrite($fp_dest, $buffer, $byteslefttowrite);
+ $byteslefttowrite -= $byteswritten;
+ }
+ return true;
+ } else {
+ throw new Exception('failed to seek to offset '.$offset.' in '.$filename_source);
+ }
+ fclose($fp_dest);
+ } else {
+ throw new Exception('failed to create file for writing '.$filename_dest);
+ }
+ fclose($fp_src);
+ } else {
+ throw new Exception('failed to open file for reading '.$filename_source);
+ }
+ return false;
+ }
+
+ public static function iconv_fallback_int_utf8($charval) {
+ if ($charval < 128) {
+ // 0bbbbbbb
+ $newcharstring = chr($charval);
+ } elseif ($charval < 2048) {
+ // 110bbbbb 10bbbbbb
+ $newcharstring = chr(($charval >> 6) | 0xC0);
+ $newcharstring .= chr(($charval & 0x3F) | 0x80);
+ } elseif ($charval < 65536) {
+ // 1110bbbb 10bbbbbb 10bbbbbb
+ $newcharstring = chr(($charval >> 12) | 0xE0);
+ $newcharstring .= chr(($charval >> 6) | 0xC0);
+ $newcharstring .= chr(($charval & 0x3F) | 0x80);
+ } else {
+ // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
+ $newcharstring = chr(($charval >> 18) | 0xF0);
+ $newcharstring .= chr(($charval >> 12) | 0xC0);
+ $newcharstring .= chr(($charval >> 6) | 0xC0);
+ $newcharstring .= chr(($charval & 0x3F) | 0x80);
+ }
+ return $newcharstring;
+ }
+
+ // ISO-8859-1 => UTF-8
+ public static function iconv_fallback_iso88591_utf8($string, $bom=false) {
+ if (function_exists('utf8_encode')) {
+ return utf8_encode($string);
+ }
+ // utf8_encode() unavailable, use getID3()'s iconv_fallback() conversions (possibly PHP is compiled without XML support)
+ $newcharstring = '';
+ if ($bom) {
+ $newcharstring .= "\xEF\xBB\xBF";
+ }
+ for ($i = 0; $i < strlen($string); $i++) {
+ $charval = ord($string{$i});
+ $newcharstring .= self::iconv_fallback_int_utf8($charval);
+ }
+ return $newcharstring;
+ }
+
+ // ISO-8859-1 => UTF-16BE
+ public static function iconv_fallback_iso88591_utf16be($string, $bom=false) {
+ $newcharstring = '';
+ if ($bom) {
+ $newcharstring .= "\xFE\xFF";
+ }
+ for ($i = 0; $i < strlen($string); $i++) {
+ $newcharstring .= "\x00".$string{$i};
+ }
+ return $newcharstring;
+ }
+
+ // ISO-8859-1 => UTF-16LE
+ public static function iconv_fallback_iso88591_utf16le($string, $bom=false) {
+ $newcharstring = '';
+ if ($bom) {
+ $newcharstring .= "\xFF\xFE";
+ }
+ for ($i = 0; $i < strlen($string); $i++) {
+ $newcharstring .= $string{$i}."\x00";
+ }
+ return $newcharstring;
+ }
+
+ // ISO-8859-1 => UTF-16LE (BOM)
+ public static function iconv_fallback_iso88591_utf16($string) {
+ return self::iconv_fallback_iso88591_utf16le($string, true);
+ }
+
+ // UTF-8 => ISO-8859-1
+ public static function iconv_fallback_utf8_iso88591($string) {
+ if (function_exists('utf8_decode')) {
+ return utf8_decode($string);
+ }
+ // utf8_decode() unavailable, use getID3()'s iconv_fallback() conversions (possibly PHP is compiled without XML support)
+ $newcharstring = '';
+ $offset = 0;
+ $stringlength = strlen($string);
+ while ($offset < $stringlength) {
+ if ((ord($string{$offset}) | 0x07) == 0xF7) {
+ // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
+ $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
+ ((ord($string{($offset + 1)}) & 0x3F) << 12) &
+ ((ord($string{($offset + 2)}) & 0x3F) << 6) &
+ (ord($string{($offset + 3)}) & 0x3F);
+ $offset += 4;
+ } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
+ // 1110bbbb 10bbbbbb 10bbbbbb
+ $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
+ ((ord($string{($offset + 1)}) & 0x3F) << 6) &
+ (ord($string{($offset + 2)}) & 0x3F);
+ $offset += 3;
+ } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
+ // 110bbbbb 10bbbbbb
+ $charval = ((ord($string{($offset + 0)}) & 0x1F) << 6) &
+ (ord($string{($offset + 1)}) & 0x3F);
+ $offset += 2;
+ } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
+ // 0bbbbbbb
+ $charval = ord($string{$offset});
+ $offset += 1;
+ } else {
+ // error? throw some kind of warning here?
+ $charval = false;
+ $offset += 1;
+ }
+ if ($charval !== false) {
+ $newcharstring .= (($charval < 256) ? chr($charval) : '?');
+ }
+ }
+ return $newcharstring;
+ }
+
+ // UTF-8 => UTF-16BE
+ public static function iconv_fallback_utf8_utf16be($string, $bom=false) {
+ $newcharstring = '';
+ if ($bom) {
+ $newcharstring .= "\xFE\xFF";
+ }
+ $offset = 0;
+ $stringlength = strlen($string);
+ while ($offset < $stringlength) {
+ if ((ord($string{$offset}) | 0x07) == 0xF7) {
+ // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
+ $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
+ ((ord($string{($offset + 1)}) & 0x3F) << 12) &
+ ((ord($string{($offset + 2)}) & 0x3F) << 6) &
+ (ord($string{($offset + 3)}) & 0x3F);
+ $offset += 4;
+ } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
+ // 1110bbbb 10bbbbbb 10bbbbbb
+ $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
+ ((ord($string{($offset + 1)}) & 0x3F) << 6) &
+ (ord($string{($offset + 2)}) & 0x3F);
+ $offset += 3;
+ } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
+ // 110bbbbb 10bbbbbb
+ $charval = ((ord($string{($offset + 0)}) & 0x1F) << 6) &
+ (ord($string{($offset + 1)}) & 0x3F);
+ $offset += 2;
+ } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
+ // 0bbbbbbb
+ $charval = ord($string{$offset});
+ $offset += 1;
+ } else {
+ // error? throw some kind of warning here?
+ $charval = false;
+ $offset += 1;
+ }
+ if ($charval !== false) {
+ $newcharstring .= (($charval < 65536) ? self::BigEndian2String($charval, 2) : "\x00".'?');
+ }
+ }
+ return $newcharstring;
+ }
+
+ // UTF-8 => UTF-16LE
+ public static function iconv_fallback_utf8_utf16le($string, $bom=false) {
+ $newcharstring = '';
+ if ($bom) {
+ $newcharstring .= "\xFF\xFE";
+ }
+ $offset = 0;
+ $stringlength = strlen($string);
+ while ($offset < $stringlength) {
+ if ((ord($string{$offset}) | 0x07) == 0xF7) {
+ // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
+ $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
+ ((ord($string{($offset + 1)}) & 0x3F) << 12) &
+ ((ord($string{($offset + 2)}) & 0x3F) << 6) &
+ (ord($string{($offset + 3)}) & 0x3F);
+ $offset += 4;
+ } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
+ // 1110bbbb 10bbbbbb 10bbbbbb
+ $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
+ ((ord($string{($offset + 1)}) & 0x3F) << 6) &
+ (ord($string{($offset + 2)}) & 0x3F);
+ $offset += 3;
+ } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
+ // 110bbbbb 10bbbbbb
+ $charval = ((ord($string{($offset + 0)}) & 0x1F) << 6) &
+ (ord($string{($offset + 1)}) & 0x3F);
+ $offset += 2;
+ } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
+ // 0bbbbbbb
+ $charval = ord($string{$offset});
+ $offset += 1;
+ } else {
+ // error? maybe throw some warning here?
+ $charval = false;
+ $offset += 1;
+ }
+ if ($charval !== false) {
+ $newcharstring .= (($charval < 65536) ? self::LittleEndian2String($charval, 2) : '?'."\x00");
+ }
+ }
+ return $newcharstring;
+ }
+
+ // UTF-8 => UTF-16LE (BOM)
+ public static function iconv_fallback_utf8_utf16($string) {
+ return self::iconv_fallback_utf8_utf16le($string, true);
+ }
+
+ // UTF-16BE => UTF-8
+ public static function iconv_fallback_utf16be_utf8($string) {
+ if (substr($string, 0, 2) == "\xFE\xFF") {
+ // strip BOM
+ $string = substr($string, 2);
+ }
+ $newcharstring = '';
+ for ($i = 0; $i < strlen($string); $i += 2) {
+ $charval = self::BigEndian2Int(substr($string, $i, 2));
+ $newcharstring .= self::iconv_fallback_int_utf8($charval);
+ }
+ return $newcharstring;
+ }
+
+ // UTF-16LE => UTF-8
+ public static function iconv_fallback_utf16le_utf8($string) {
+ if (substr($string, 0, 2) == "\xFF\xFE") {
+ // strip BOM
+ $string = substr($string, 2);
+ }
+ $newcharstring = '';
+ for ($i = 0; $i < strlen($string); $i += 2) {
+ $charval = self::LittleEndian2Int(substr($string, $i, 2));
+ $newcharstring .= self::iconv_fallback_int_utf8($charval);
+ }
+ return $newcharstring;
+ }
+
+ // UTF-16BE => ISO-8859-1
+ public static function iconv_fallback_utf16be_iso88591($string) {
+ if (substr($string, 0, 2) == "\xFE\xFF") {
+ // strip BOM
+ $string = substr($string, 2);
+ }
+ $newcharstring = '';
+ for ($i = 0; $i < strlen($string); $i += 2) {
+ $charval = self::BigEndian2Int(substr($string, $i, 2));
+ $newcharstring .= (($charval < 256) ? chr($charval) : '?');
+ }
+ return $newcharstring;
+ }
+
+ // UTF-16LE => ISO-8859-1
+ public static function iconv_fallback_utf16le_iso88591($string) {
+ if (substr($string, 0, 2) == "\xFF\xFE") {
+ // strip BOM
+ $string = substr($string, 2);
+ }
+ $newcharstring = '';
+ for ($i = 0; $i < strlen($string); $i += 2) {
+ $charval = self::LittleEndian2Int(substr($string, $i, 2));
+ $newcharstring .= (($charval < 256) ? chr($charval) : '?');
+ }
+ return $newcharstring;
+ }
+
+ // UTF-16 (BOM) => ISO-8859-1
+ public static function iconv_fallback_utf16_iso88591($string) {
+ $bom = substr($string, 0, 2);
+ if ($bom == "\xFE\xFF") {
+ return self::iconv_fallback_utf16be_iso88591(substr($string, 2));
+ } elseif ($bom == "\xFF\xFE") {
+ return self::iconv_fallback_utf16le_iso88591(substr($string, 2));
+ }
+ return $string;
+ }
+
+ // UTF-16 (BOM) => UTF-8
+ public static function iconv_fallback_utf16_utf8($string) {
+ $bom = substr($string, 0, 2);
+ if ($bom == "\xFE\xFF") {
+ return self::iconv_fallback_utf16be_utf8(substr($string, 2));
+ } elseif ($bom == "\xFF\xFE") {
+ return self::iconv_fallback_utf16le_utf8(substr($string, 2));
+ }
+ return $string;
+ }
+
+ public static function iconv_fallback($in_charset, $out_charset, $string) {
+
+ if ($in_charset == $out_charset) {
+ return $string;
+ }
+
+ // iconv() availble
+ if (function_exists('iconv')) {
+ if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) {
+ switch ($out_charset) {
+ case 'ISO-8859-1':
+ $converted_string = rtrim($converted_string, "\x00");
+ break;
+ }
+ return $converted_string;
+ }
+
+ // iconv() may sometimes fail with "illegal character in input string" error message
+ // and return an empty string, but returning the unconverted string is more useful
+ return $string;
+ }
+
+
+ // iconv() not available
+ static $ConversionFunctionList = array();
+ if (empty($ConversionFunctionList)) {
+ $ConversionFunctionList['ISO-8859-1']['UTF-8'] = 'iconv_fallback_iso88591_utf8';
+ $ConversionFunctionList['ISO-8859-1']['UTF-16'] = 'iconv_fallback_iso88591_utf16';
+ $ConversionFunctionList['ISO-8859-1']['UTF-16BE'] = 'iconv_fallback_iso88591_utf16be';
+ $ConversionFunctionList['ISO-8859-1']['UTF-16LE'] = 'iconv_fallback_iso88591_utf16le';
+ $ConversionFunctionList['UTF-8']['ISO-8859-1'] = 'iconv_fallback_utf8_iso88591';
+ $ConversionFunctionList['UTF-8']['UTF-16'] = 'iconv_fallback_utf8_utf16';
+ $ConversionFunctionList['UTF-8']['UTF-16BE'] = 'iconv_fallback_utf8_utf16be';
+ $ConversionFunctionList['UTF-8']['UTF-16LE'] = 'iconv_fallback_utf8_utf16le';
+ $ConversionFunctionList['UTF-16']['ISO-8859-1'] = 'iconv_fallback_utf16_iso88591';
+ $ConversionFunctionList['UTF-16']['UTF-8'] = 'iconv_fallback_utf16_utf8';
+ $ConversionFunctionList['UTF-16LE']['ISO-8859-1'] = 'iconv_fallback_utf16le_iso88591';
+ $ConversionFunctionList['UTF-16LE']['UTF-8'] = 'iconv_fallback_utf16le_utf8';
+ $ConversionFunctionList['UTF-16BE']['ISO-8859-1'] = 'iconv_fallback_utf16be_iso88591';
+ $ConversionFunctionList['UTF-16BE']['UTF-8'] = 'iconv_fallback_utf16be_utf8';
+ }
+ if (isset($ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)])) {
+ $ConversionFunction = $ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)];
+ return self::$ConversionFunction($string);
+ }
+ throw new Exception('PHP does not have iconv() support - cannot convert from '.$in_charset.' to '.$out_charset);
+ }
+
+
+ public static function MultiByteCharString2HTML($string, $charset='ISO-8859-1') {
+ $string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string
+ $HTMLstring = '';
+
+ switch ($charset) {
+ case '1251':
+ case '1252':
+ case '866':
+ case '932':
+ case '936':
+ case '950':
+ case 'BIG5':
+ case 'BIG5-HKSCS':
+ case 'cp1251':
+ case 'cp1252':
+ case 'cp866':
+ case 'EUC-JP':
+ case 'EUCJP':
+ case 'GB2312':
+ case 'ibm866':
+ case 'ISO-8859-1':
+ case 'ISO-8859-15':
+ case 'ISO8859-1':
+ case 'ISO8859-15':
+ case 'KOI8-R':
+ case 'koi8-ru':
+ case 'koi8r':
+ case 'Shift_JIS':
+ case 'SJIS':
+ case 'win-1251':
+ case 'Windows-1251':
+ case 'Windows-1252':
+ $HTMLstring = htmlentities($string, ENT_COMPAT, $charset);
+ break;
+
+ case 'UTF-8':
+ $strlen = strlen($string);
+ for ($i = 0; $i < $strlen; $i++) {
+ $char_ord_val = ord($string{$i});
+ $charval = 0;
+ if ($char_ord_val < 0x80) {
+ $charval = $char_ord_val;
+ } elseif ((($char_ord_val & 0xF0) >> 4) == 0x0F && $i+3 < $strlen) {
+ $charval = (($char_ord_val & 0x07) << 18);
+ $charval += ((ord($string{++$i}) & 0x3F) << 12);
+ $charval += ((ord($string{++$i}) & 0x3F) << 6);
+ $charval += (ord($string{++$i}) & 0x3F);
+ } elseif ((($char_ord_val & 0xE0) >> 5) == 0x07 && $i+2 < $strlen) {
+ $charval = (($char_ord_val & 0x0F) << 12);
+ $charval += ((ord($string{++$i}) & 0x3F) << 6);
+ $charval += (ord($string{++$i}) & 0x3F);
+ } elseif ((($char_ord_val & 0xC0) >> 6) == 0x03 && $i+1 < $strlen) {
+ $charval = (($char_ord_val & 0x1F) << 6);
+ $charval += (ord($string{++$i}) & 0x3F);
+ }
+ if (($charval >= 32) && ($charval <= 127)) {
+ $HTMLstring .= htmlentities(chr($charval));
+ } else {
+ $HTMLstring .= '&#'.$charval.';';
+ }
+ }
+ break;
+
+ case 'UTF-16LE':
+ for ($i = 0; $i < strlen($string); $i += 2) {
+ $charval = self::LittleEndian2Int(substr($string, $i, 2));
+ if (($charval >= 32) && ($charval <= 127)) {
+ $HTMLstring .= chr($charval);
+ } else {
+ $HTMLstring .= '&#'.$charval.';';
+ }
+ }
+ break;
+
+ case 'UTF-16BE':
+ for ($i = 0; $i < strlen($string); $i += 2) {
+ $charval = self::BigEndian2Int(substr($string, $i, 2));
+ if (($charval >= 32) && ($charval <= 127)) {
+ $HTMLstring .= chr($charval);
+ } else {
+ $HTMLstring .= '&#'.$charval.';';
+ }
+ }
+ break;
+
+ default:
+ $HTMLstring = 'ERROR: Character set "'.$charset.'" not supported in MultiByteCharString2HTML()';
+ break;
+ }
+ return $HTMLstring;
+ }
+
+
+
+ public static function RGADnameLookup($namecode) {
+ static $RGADname = array();
+ if (empty($RGADname)) {
+ $RGADname[0] = 'not set';
+ $RGADname[1] = 'Track Gain Adjustment';
+ $RGADname[2] = 'Album Gain Adjustment';
+ }
+
+ return (isset($RGADname[$namecode]) ? $RGADname[$namecode] : '');
+ }
+
+
+ public static function RGADoriginatorLookup($originatorcode) {
+ static $RGADoriginator = array();
+ if (empty($RGADoriginator)) {
+ $RGADoriginator[0] = 'unspecified';
+ $RGADoriginator[1] = 'pre-set by artist/producer/mastering engineer';
+ $RGADoriginator[2] = 'set by user';
+ $RGADoriginator[3] = 'determined automatically';
+ }
+
+ return (isset($RGADoriginator[$originatorcode]) ? $RGADoriginator[$originatorcode] : '');
+ }
+
+
+ public static function RGADadjustmentLookup($rawadjustment, $signbit) {
+ $adjustment = $rawadjustment / 10;
+ if ($signbit == 1) {
+ $adjustment *= -1;
+ }
+ return (float) $adjustment;
+ }
+
+
+ public static function RGADgainString($namecode, $originatorcode, $replaygain) {
+ if ($replaygain < 0) {
+ $signbit = '1';
+ } else {
+ $signbit = '0';
+ }
+ $storedreplaygain = intval(round($replaygain * 10));
+ $gainstring = str_pad(decbin($namecode), 3, '0', STR_PAD_LEFT);
+ $gainstring .= str_pad(decbin($originatorcode), 3, '0', STR_PAD_LEFT);
+ $gainstring .= $signbit;
+ $gainstring .= str_pad(decbin($storedreplaygain), 9, '0', STR_PAD_LEFT);
+
+ return $gainstring;
+ }
+
+ public static function RGADamplitude2dB($amplitude) {
+ return 20 * log10($amplitude);
+ }
+
+
+ public static function GetDataImageSize($imgData, &$imageinfo=array()) {
+ static $tempdir = '';
+ if (empty($tempdir)) {
+ // yes this is ugly, feel free to suggest a better way
+ require_once(dirname(__FILE__).'/getid3.php');
+ $getid3_temp = new getID3();
+ $tempdir = $getid3_temp->tempdir;
+ unset($getid3_temp);
+ }
+ $GetDataImageSize = false;
+ if ($tempfilename = tempnam($tempdir, 'gI3')) {
+ if (is_writable($tempfilename) && is_file($tempfilename) && ($tmp = fopen($tempfilename, 'wb'))) {
+ fwrite($tmp, $imgData);
+ fclose($tmp);
+ $GetDataImageSize = @getimagesize($tempfilename, $imageinfo);
+ }
+ unlink($tempfilename);
+ }
+ return $GetDataImageSize;
+ }
+
+ public static function ImageExtFromMime($mime_type) {
+ // temporary way, works OK for now, but should be reworked in the future
+ return str_replace(array('image/', 'x-', 'jpeg'), array('', '', 'jpg'), $mime_type);
+ }
+
+ public static function ImageTypesLookup($imagetypeid) {
+ static $ImageTypesLookup = array();
+ if (empty($ImageTypesLookup)) {
+ $ImageTypesLookup[1] = 'gif';
+ $ImageTypesLookup[2] = 'jpeg';
+ $ImageTypesLookup[3] = 'png';
+ $ImageTypesLookup[4] = 'swf';
+ $ImageTypesLookup[5] = 'psd';
+ $ImageTypesLookup[6] = 'bmp';
+ $ImageTypesLookup[7] = 'tiff (little-endian)';
+ $ImageTypesLookup[8] = 'tiff (big-endian)';
+ $ImageTypesLookup[9] = 'jpc';
+ $ImageTypesLookup[10] = 'jp2';
+ $ImageTypesLookup[11] = 'jpx';
+ $ImageTypesLookup[12] = 'jb2';
+ $ImageTypesLookup[13] = 'swc';
+ $ImageTypesLookup[14] = 'iff';
+ }
+ return (isset($ImageTypesLookup[$imagetypeid]) ? $ImageTypesLookup[$imagetypeid] : '');
+ }
+
+ public static function CopyTagsToComments(&$ThisFileInfo) {
+
+ // Copy all entries from ['tags'] into common ['comments']
+ if (!empty($ThisFileInfo['tags'])) {
+ foreach ($ThisFileInfo['tags'] as $tagtype => $tagarray) {
+ foreach ($tagarray as $tagname => $tagdata) {
+ foreach ($tagdata as $key => $value) {
+ if (!empty($value)) {
+ if (empty($ThisFileInfo['comments'][$tagname])) {
+
+ // fall through and append value
+
+ } elseif ($tagtype == 'id3v1') {
+
+ $newvaluelength = strlen(trim($value));
+ foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) {
+ $oldvaluelength = strlen(trim($existingvalue));
+ if (($newvaluelength <= $oldvaluelength) && (substr($existingvalue, 0, $newvaluelength) == trim($value))) {
+ // new value is identical but shorter-than (or equal-length to) one already in comments - skip
+ break 2;
+ }
+ }
+
+ } elseif (!is_array($value)) {
+
+ $newvaluelength = strlen(trim($value));
+ foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) {
+ $oldvaluelength = strlen(trim($existingvalue));
+ if (($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) {
+ $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value);
+ break 2;
+ }
+ }
+
+ }
+ if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) {
+ $value = (is_string($value) ? trim($value) : $value);
+ $ThisFileInfo['comments'][$tagname][] = $value;
+ }
+ }
+ }
+ }
+ }
+
+ // Copy to ['comments_html']
+ foreach ($ThisFileInfo['comments'] as $field => $values) {
+ if ($field == 'picture') {
+ // pictures can take up a lot of space, and we don't need multiple copies of them
+ // let there be a single copy in [comments][picture], and not elsewhere
+ continue;
+ }
+ foreach ($values as $index => $value) {
+ if (is_array($value)) {
+ $ThisFileInfo['comments_html'][$field][$index] = $value;
+ } else {
+ $ThisFileInfo['comments_html'][$field][$index] = str_replace('&#0;', '', self::MultiByteCharString2HTML($value, $ThisFileInfo['encoding']));
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+
+ public static function EmbeddedLookup($key, $begin, $end, $file, $name) {
+
+ // Cached
+ static $cache;
+ if (isset($cache[$file][$name])) {
+ return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : '');
+ }
+
+ // Init
+ $keylength = strlen($key);
+ $line_count = $end - $begin - 7;
+
+ // Open php file
+ $fp = fopen($file, 'r');
+
+ // Discard $begin lines
+ for ($i = 0; $i < ($begin + 3); $i++) {
+ fgets($fp, 1024);
+ }
+
+ // Loop thru line
+ while (0 < $line_count--) {
+
+ // Read line
+ $line = ltrim(fgets($fp, 1024), "\t ");
+
+ // METHOD A: only cache the matching key - less memory but slower on next lookup of not-previously-looked-up key
+ //$keycheck = substr($line, 0, $keylength);
+ //if ($key == $keycheck) {
+ // $cache[$file][$name][$keycheck] = substr($line, $keylength + 1);
+ // break;
+ //}
+
+ // METHOD B: cache all keys in this lookup - more memory but faster on next lookup of not-previously-looked-up key
+ //$cache[$file][$name][substr($line, 0, $keylength)] = trim(substr($line, $keylength + 1));
+ $explodedLine = explode("\t", $line, 2);
+ $ThisKey = (isset($explodedLine[0]) ? $explodedLine[0] : '');
+ $ThisValue = (isset($explodedLine[1]) ? $explodedLine[1] : '');
+ $cache[$file][$name][$ThisKey] = trim($ThisValue);
+ }
+
+ // Close and return
+ fclose($fp);
+ return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : '');
+ }
+
+ public static function IncludeDependency($filename, $sourcefile, $DieOnFailure=false) {
+ global $GETID3_ERRORARRAY;
+
+ if (file_exists($filename)) {
+ if (include_once($filename)) {
+ return true;
+ } else {
+ $diemessage = basename($sourcefile).' depends on '.$filename.', which has errors';
+ }
+ } else {
+ $diemessage = basename($sourcefile).' depends on '.$filename.', which is missing';
+ }
+ if ($DieOnFailure) {
+ throw new Exception($diemessage);
+ } else {
+ $GETID3_ERRORARRAY[] = $diemessage;
+ }
+ return false;
+ }
+
+ public static function trimNullByte($string) {
+ return trim($string, "\x00");
+ }
+
+ public static function getFileSizeSyscall($path) {
+ $filesize = false;
+
+ if (GETID3_OS_ISWINDOWS) {
+ if (class_exists('COM')) { // From PHP 5.3.15 and 5.4.5, COM and DOTNET is no longer built into the php core.you have to add COM support in php.ini:
+ $filesystem = new COM('Scripting.FileSystemObject');
+ $file = $filesystem->GetFile($path);
+ $filesize = $file->Size();
+ unset($filesystem, $file);
+ } else {
+ $commandline = 'for %I in ('.escapeshellarg($path).') do @echo %~zI';
+ }
+ } else {
+ $commandline = 'ls -l '.escapeshellarg($path).' | awk \'{print $5}\'';
+ }
+ if (isset($commandline)) {
+ $output = trim(`$commandline`);
+ if (ctype_digit($output)) {
+ $filesize = (float) $output;
+ }
+ }
+ return $filesize;
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/libs/getid3/getid3.php b/extensions/TimedMediaHandler/libs/getid3/getid3.php
new file mode 100644
index 00000000..be0dd5f0
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/getid3.php
@@ -0,0 +1,1776 @@
+<?php
+/////////////////////////////////////////////////////////////////
+/// getID3() by James Heinrich <info@getid3.org> //
+// available at http://getid3.sourceforge.net //
+// or http://www.getid3.org //
+/////////////////////////////////////////////////////////////////
+// //
+// Please see readme.txt for more information //
+// ///
+/////////////////////////////////////////////////////////////////
+
+// define a constant rather than looking up every time it is needed
+if (!defined('GETID3_OS_ISWINDOWS')) {
+ define('GETID3_OS_ISWINDOWS', (stripos(PHP_OS, 'WIN') === 0));
+}
+// Get base path of getID3() - ONCE
+if (!defined('GETID3_INCLUDEPATH')) {
+ define('GETID3_INCLUDEPATH', dirname(__FILE__).DIRECTORY_SEPARATOR);
+}
+
+// attempt to define temp dir as something flexible but reliable
+$temp_dir = ini_get('upload_tmp_dir');
+if ($temp_dir && (!is_dir($temp_dir) || !is_readable($temp_dir))) {
+ $temp_dir = '';
+}
+if (!$temp_dir && function_exists('sys_get_temp_dir')) {
+ // PHP v5.2.1+
+ // sys_get_temp_dir() may give inaccessible temp dir, e.g. with open_basedir on virtual hosts
+ $temp_dir = sys_get_temp_dir();
+}
+$temp_dir = realpath($temp_dir);
+$open_basedir = ini_get('open_basedir');
+if ($open_basedir) {
+ // e.g. "/var/www/vhosts/getid3.org/httpdocs/:/tmp/"
+ $temp_dir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $temp_dir);
+ $open_basedir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $open_basedir);
+ if (substr($temp_dir, -1, 1) != DIRECTORY_SEPARATOR) {
+ $temp_dir .= DIRECTORY_SEPARATOR;
+ }
+ $found_valid_tempdir = false;
+ $open_basedirs = explode(PATH_SEPARATOR, $open_basedir);
+ foreach ($open_basedirs as $basedir) {
+ if (substr($basedir, -1, 1) != DIRECTORY_SEPARATOR) {
+ $basedir .= DIRECTORY_SEPARATOR;
+ }
+ if (preg_match('#^'.preg_quote($basedir).'#', $temp_dir)) {
+ $found_valid_tempdir = true;
+ break;
+ }
+ }
+ if (!$found_valid_tempdir) {
+ $temp_dir = '';
+ }
+ unset($open_basedirs, $found_valid_tempdir, $basedir);
+}
+if (!$temp_dir) {
+ $temp_dir = '*'; // invalid directory name should force tempnam() to use system default temp dir
+}
+// $temp_dir = '/something/else/'; // feel free to override temp dir here if it works better for your system
+define('GETID3_TEMP_DIR', $temp_dir);
+unset($open_basedir, $temp_dir);
+
+// End: Defines
+
+
+class getID3
+{
+ // public: Settings
+ public $encoding = 'UTF-8'; // CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE
+ public $encoding_id3v1 = 'ISO-8859-1'; // Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252'
+
+ // public: Optional tag checks - disable for speed.
+ public $option_tag_id3v1 = true; // Read and process ID3v1 tags
+ public $option_tag_id3v2 = true; // Read and process ID3v2 tags
+ public $option_tag_lyrics3 = true; // Read and process Lyrics3 tags
+ public $option_tag_apetag = true; // Read and process APE tags
+ public $option_tags_process = true; // Copy tags to root key 'tags' and encode to $this->encoding
+ public $option_tags_html = true; // Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities
+
+ // public: Optional tag/comment calucations
+ public $option_extra_info = true; // Calculate additional info such as bitrate, channelmode etc
+
+ // public: Optional handling of embedded attachments (e.g. images)
+ public $option_save_attachments = true; // defaults to true (ATTACHMENTS_INLINE) for backward compatibility
+
+ // public: Optional calculations
+ public $option_md5_data = false; // Get MD5 sum of data part - slow
+ public $option_md5_data_source = false; // Use MD5 of source file if availble - only FLAC and OptimFROG
+ public $option_sha1_data = false; // Get SHA1 sum of data part - slow
+ public $option_max_2gb_check = null; // Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on PHP_INT_MAX)
+
+ // public: Read buffer size in bytes
+ public $option_fread_buffer_size = 32768;
+
+ // Public variables
+ public $filename; // Filename of file being analysed.
+ public $fp; // Filepointer to file being analysed.
+ public $info; // Result array.
+ public $tempdir = GETID3_TEMP_DIR;
+
+ // Protected variables
+ protected $startup_error = '';
+ protected $startup_warning = '';
+ protected $memory_limit = 0;
+
+ const VERSION = '1.9.6-20130603';
+ const FREAD_BUFFER_SIZE = 32768;
+
+ const ATTACHMENTS_NONE = false;
+ const ATTACHMENTS_INLINE = true;
+
+ // public: constructor
+ public function __construct() {
+
+ // Check for PHP version
+ $required_php_version = '5.0.5';
+ if (version_compare(PHP_VERSION, $required_php_version, '<')) {
+ $this->startup_error .= 'getID3() requires PHP v'.$required_php_version.' or higher - you are running v'.PHP_VERSION;
+ return false;
+ }
+
+ // Check memory
+ $this->memory_limit = ini_get('memory_limit');
+ if (preg_match('#([0-9]+)M#i', $this->memory_limit, $matches)) {
+ // could be stored as "16M" rather than 16777216 for example
+ $this->memory_limit = $matches[1] * 1048576;
+ } elseif (preg_match('#([0-9]+)G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
+ // could be stored as "2G" rather than 2147483648 for example
+ $this->memory_limit = $matches[1] * 1073741824;
+ }
+ if ($this->memory_limit <= 0) {
+ // memory limits probably disabled
+ } elseif ($this->memory_limit <= 4194304) {
+ $this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini';
+ } elseif ($this->memory_limit <= 12582912) {
+ $this->startup_warning .= 'PHP has less than 12MB available memory and might run out if all modules are loaded. Increase memory_limit in php.ini';
+ }
+
+ // Check safe_mode off
+ if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
+ $this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.');
+ }
+
+ if (intval(ini_get('mbstring.func_overload')) > 0) {
+ $this->warning('WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", this may break things.');
+ }
+
+ // Check for magic_quotes_runtime
+ if (function_exists('get_magic_quotes_runtime')) {
+ if (get_magic_quotes_runtime()) {
+ return $this->startup_error('magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).');
+ }
+ }
+
+ // Check for magic_quotes_gpc
+ if (function_exists('magic_quotes_gpc')) {
+ if (get_magic_quotes_gpc()) {
+ return $this->startup_error('magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).');
+ }
+ }
+
+ // Load support library
+ if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) {
+ $this->startup_error .= 'getid3.lib.php is missing or corrupt';
+ }
+
+ if ($this->option_max_2gb_check === null) {
+ $this->option_max_2gb_check = (PHP_INT_MAX <= 2147483647);
+ }
+
+
+ // Needed for Windows only:
+ // Define locations of helper applications for Shorten, VorbisComment, MetaFLAC
+ // as well as other helper functions such as head, tail, md5sum, etc
+ // This path cannot contain spaces, but the below code will attempt to get the
+ // 8.3-equivalent path automatically
+ // IMPORTANT: This path must include the trailing slash
+ if (GETID3_OS_ISWINDOWS && !defined('GETID3_HELPERAPPSDIR')) {
+
+ $helperappsdir = GETID3_INCLUDEPATH.'..'.DIRECTORY_SEPARATOR.'helperapps'; // must not have any space in this path
+
+ if (!is_dir($helperappsdir)) {
+ $this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist';
+ } elseif (strpos(realpath($helperappsdir), ' ') !== false) {
+ $DirPieces = explode(DIRECTORY_SEPARATOR, realpath($helperappsdir));
+ $path_so_far = array();
+ foreach ($DirPieces as $key => $value) {
+ if (strpos($value, ' ') !== false) {
+ if (!empty($path_so_far)) {
+ $commandline = 'dir /x '.escapeshellarg(implode(DIRECTORY_SEPARATOR, $path_so_far));
+ $dir_listing = `$commandline`;
+ $lines = explode("\n", $dir_listing);
+ foreach ($lines as $line) {
+ $line = trim($line);
+ if (preg_match('#^([0-9/]{10}) +([0-9:]{4,5}( [AP]M)?) +(<DIR>|[0-9,]+) +([^ ]{0,11}) +(.+)$#', $line, $matches)) {
+ list($dummy, $date, $time, $ampm, $filesize, $shortname, $filename) = $matches;
+ if ((strtoupper($filesize) == '<DIR>') && (strtolower($filename) == strtolower($value))) {
+ $value = $shortname;
+ }
+ }
+ }
+ } else {
+ $this->startup_warning .= 'GETID3_HELPERAPPSDIR must not have any spaces in it - use 8dot3 naming convention if neccesary. You can run "dir /x" from the commandline to see the correct 8.3-style names.';
+ }
+ }
+ $path_so_far[] = $value;
+ }
+ $helperappsdir = implode(DIRECTORY_SEPARATOR, $path_so_far);
+ }
+ define('GETID3_HELPERAPPSDIR', $helperappsdir.DIRECTORY_SEPARATOR);
+ }
+
+ return true;
+ }
+
+ public function version() {
+ return self::VERSION;
+ }
+
+ public function fread_buffer_size() {
+ return $this->option_fread_buffer_size;
+ }
+
+
+ // public: setOption
+ public function setOption($optArray) {
+ if (!is_array($optArray) || empty($optArray)) {
+ return false;
+ }
+ foreach ($optArray as $opt => $val) {
+ if (isset($this->$opt) === false) {
+ continue;
+ }
+ $this->$opt = $val;
+ }
+ return true;
+ }
+
+
+ public function openfile($filename) {
+ try {
+ if (!empty($this->startup_error)) {
+ throw new getid3_exception($this->startup_error);
+ }
+ if (!empty($this->startup_warning)) {
+ $this->warning($this->startup_warning);
+ }
+
+ // init result array and set parameters
+ $this->filename = $filename;
+ $this->info = array();
+ $this->info['GETID3_VERSION'] = $this->version();
+ $this->info['php_memory_limit'] = $this->memory_limit;
+
+ // remote files not supported
+ if (preg_match('/^(ht|f)tp:\/\//', $filename)) {
+ throw new getid3_exception('Remote files are not supported - please copy the file locally first');
+ }
+
+ $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename);
+ $filename = preg_replace('#(.+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.DIRECTORY_SEPARATOR, $filename);
+
+ // open local file
+ if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
+ // great
+ } else {
+ throw new getid3_exception('Could not open "'.$filename.'" (does not exist, or is not a file)');
+ }
+
+ $this->info['filesize'] = filesize($filename);
+ // set redundant parameters - might be needed in some include file
+ $this->info['filename'] = basename($filename);
+ $this->info['filepath'] = str_replace('\\', '/', realpath(dirname($filename)));
+ $this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename'];
+
+
+ // option_max_2gb_check
+ if ($this->option_max_2gb_check) {
+ // PHP (32-bit all, and 64-bit Windows) doesn't support integers larger than 2^31 (~2GB)
+ // filesize() simply returns (filesize % (pow(2, 32)), no matter the actual filesize
+ // ftell() returns 0 if seeking to the end is beyond the range of unsigned integer
+ $fseek = fseek($this->fp, 0, SEEK_END);
+ if (($fseek < 0) || (($this->info['filesize'] != 0) && (ftell($this->fp) == 0)) ||
+ ($this->info['filesize'] < 0) ||
+ (ftell($this->fp) < 0)) {
+ $real_filesize = getid3_lib::getFileSizeSyscall($this->info['filenamepath']);
+
+ if ($real_filesize === false) {
+ unset($this->info['filesize']);
+ fclose($this->fp);
+ throw new getid3_exception('Unable to determine actual filesize. File is most likely larger than '.round(PHP_INT_MAX / 1073741824).'GB and is not supported by PHP.');
+ } elseif (getid3_lib::intValueSupported($real_filesize)) {
+ unset($this->info['filesize']);
+ fclose($this->fp);
+ throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize, 3).'GB, please report to info@getid3.org');
+ }
+ $this->info['filesize'] = $real_filesize;
+ $this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize, 3).'GB) and is not properly supported by PHP.');
+ }
+ }
+
+ // set more parameters
+ $this->info['avdataoffset'] = 0;
+ $this->info['avdataend'] = $this->info['filesize'];
+ $this->info['fileformat'] = ''; // filled in later
+ $this->info['audio']['dataformat'] = ''; // filled in later, unset if not used
+ $this->info['video']['dataformat'] = ''; // filled in later, unset if not used
+ $this->info['tags'] = array(); // filled in later, unset if not used
+ $this->info['error'] = array(); // filled in later, unset if not used
+ $this->info['warning'] = array(); // filled in later, unset if not used
+ $this->info['comments'] = array(); // filled in later, unset if not used
+ $this->info['encoding'] = $this->encoding; // required by id3v2 and iso modules - can be unset at the end if desired
+
+ return true;
+
+ } catch (Exception $e) {
+ $this->error($e->getMessage());
+ }
+ return false;
+ }
+
+ // public: analyze file
+ public function analyze($filename) {
+ try {
+ if (!$this->openfile($filename)) {
+ return $this->info;
+ }
+
+ // Handle tags
+ foreach (array('id3v2'=>'id3v2', 'id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) {
+ $option_tag = 'option_tag_'.$tag_name;
+ if ($this->$option_tag) {
+ $this->include_module('tag.'.$tag_name);
+ try {
+ $tag_class = 'getid3_'.$tag_name;
+ $tag = new $tag_class($this);
+ $tag->Analyze();
+ }
+ catch (getid3_exception $e) {
+ throw $e;
+ }
+ }
+ }
+ if (isset($this->info['id3v2']['tag_offset_start'])) {
+ $this->info['avdataoffset'] = max($this->info['avdataoffset'], $this->info['id3v2']['tag_offset_end']);
+ }
+ foreach (array('id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) {
+ if (isset($this->info[$tag_key]['tag_offset_start'])) {
+ $this->info['avdataend'] = min($this->info['avdataend'], $this->info[$tag_key]['tag_offset_start']);
+ }
+ }
+
+ // ID3v2 detection (NOT parsing), even if ($this->option_tag_id3v2 == false) done to make fileformat easier
+ if (!$this->option_tag_id3v2) {
+ fseek($this->fp, 0, SEEK_SET);
+ $header = fread($this->fp, 10);
+ if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) {
+ $this->info['id3v2']['header'] = true;
+ $this->info['id3v2']['majorversion'] = ord($header{3});
+ $this->info['id3v2']['minorversion'] = ord($header{4});
+ $this->info['avdataoffset'] += getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length
+ }
+ }
+
+ // read 32 kb file data
+ fseek($this->fp, $this->info['avdataoffset'], SEEK_SET);
+ $formattest = fread($this->fp, 32774);
+
+ // determine format
+ $determined_format = $this->GetFileFormat($formattest, $filename);
+
+ // unable to determine file format
+ if (!$determined_format) {
+ fclose($this->fp);
+ return $this->error('unable to determine file format');
+ }
+
+ // check for illegal ID3 tags
+ if (isset($determined_format['fail_id3']) && (in_array('id3v1', $this->info['tags']) || in_array('id3v2', $this->info['tags']))) {
+ if ($determined_format['fail_id3'] === 'ERROR') {
+ fclose($this->fp);
+ return $this->error('ID3 tags not allowed on this file type.');
+ } elseif ($determined_format['fail_id3'] === 'WARNING') {
+ $this->warning('ID3 tags not allowed on this file type.');
+ }
+ }
+
+ // check for illegal APE tags
+ if (isset($determined_format['fail_ape']) && in_array('ape', $this->info['tags'])) {
+ if ($determined_format['fail_ape'] === 'ERROR') {
+ fclose($this->fp);
+ return $this->error('APE tags not allowed on this file type.');
+ } elseif ($determined_format['fail_ape'] === 'WARNING') {
+ $this->warning('APE tags not allowed on this file type.');
+ }
+ }
+
+ // set mime type
+ $this->info['mime_type'] = $determined_format['mime_type'];
+
+ // supported format signature pattern detected, but module deleted
+ if (!file_exists(GETID3_INCLUDEPATH.$determined_format['include'])) {
+ fclose($this->fp);
+ return $this->error('Format not supported, module "'.$determined_format['include'].'" was removed.');
+ }
+
+ // module requires iconv support
+ // Check encoding/iconv support
+ if (!empty($determined_format['iconv_req']) && !function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) {
+ $errormessage = 'iconv() support is required for this module ('.$determined_format['include'].') for encodings other than ISO-8859-1, UTF-8, UTF-16LE, UTF16-BE, UTF-16. ';
+ if (GETID3_OS_ISWINDOWS) {
+ $errormessage .= 'PHP does not have iconv() support. Please enable php_iconv.dll in php.ini, and copy iconv.dll from c:/php/dlls to c:/windows/system32';
+ } else {
+ $errormessage .= 'PHP is not compiled with iconv() support. Please recompile with the --with-iconv switch';
+ }
+ return $this->error($errormessage);
+ }
+
+ // include module
+ include_once(GETID3_INCLUDEPATH.$determined_format['include']);
+
+ // instantiate module class
+ $class_name = 'getid3_'.$determined_format['module'];
+ if (!class_exists($class_name)) {
+ return $this->error('Format not supported, module "'.$determined_format['include'].'" is corrupt.');
+ }
+ $class = new $class_name($this);
+ $class->Analyze();
+ unset($class);
+
+ // close file
+ fclose($this->fp);
+
+ // process all tags - copy to 'tags' and convert charsets
+ if ($this->option_tags_process) {
+ $this->HandleAllTags();
+ }
+
+ // perform more calculations
+ if ($this->option_extra_info) {
+ $this->ChannelsBitratePlaytimeCalculations();
+ $this->CalculateCompressionRatioVideo();
+ $this->CalculateCompressionRatioAudio();
+ $this->CalculateReplayGain();
+ $this->ProcessAudioStreams();
+ }
+
+ // get the MD5 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags
+ if ($this->option_md5_data) {
+ // do not calc md5_data if md5_data_source is present - set by flac only - future MPC/SV8 too
+ if (!$this->option_md5_data_source || empty($this->info['md5_data_source'])) {
+ $this->getHashdata('md5');
+ }
+ }
+
+ // get the SHA1 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags
+ if ($this->option_sha1_data) {
+ $this->getHashdata('sha1');
+ }
+
+ // remove undesired keys
+ $this->CleanUp();
+
+ } catch (Exception $e) {
+ $this->error('Caught exception: '.$e->getMessage());
+ }
+
+ // return info array
+ return $this->info;
+ }
+
+
+ // private: error handling
+ public function error($message) {
+ $this->CleanUp();
+ if (!isset($this->info['error'])) {
+ $this->info['error'] = array();
+ }
+ $this->info['error'][] = $message;
+ return $this->info;
+ }
+
+
+ // private: warning handling
+ public function warning($message) {
+ $this->info['warning'][] = $message;
+ return true;
+ }
+
+
+ // private: CleanUp
+ private function CleanUp() {
+
+ // remove possible empty keys
+ $AVpossibleEmptyKeys = array('dataformat', 'bits_per_sample', 'encoder_options', 'streams', 'bitrate');
+ foreach ($AVpossibleEmptyKeys as $dummy => $key) {
+ if (empty($this->info['audio'][$key]) && isset($this->info['audio'][$key])) {
+ unset($this->info['audio'][$key]);
+ }
+ if (empty($this->info['video'][$key]) && isset($this->info['video'][$key])) {
+ unset($this->info['video'][$key]);
+ }
+ }
+
+ // remove empty root keys
+ if (!empty($this->info)) {
+ foreach ($this->info as $key => $value) {
+ if (empty($this->info[$key]) && ($this->info[$key] !== 0) && ($this->info[$key] !== '0')) {
+ unset($this->info[$key]);
+ }
+ }
+ }
+
+ // remove meaningless entries from unknown-format files
+ if (empty($this->info['fileformat'])) {
+ if (isset($this->info['avdataoffset'])) {
+ unset($this->info['avdataoffset']);
+ }
+ if (isset($this->info['avdataend'])) {
+ unset($this->info['avdataend']);
+ }
+ }
+
+ // remove possible duplicated identical entries
+ if (!empty($this->info['error'])) {
+ $this->info['error'] = array_values(array_unique($this->info['error']));
+ }
+ if (!empty($this->info['warning'])) {
+ $this->info['warning'] = array_values(array_unique($this->info['warning']));
+ }
+
+ // remove "global variable" type keys
+ unset($this->info['php_memory_limit']);
+
+ return true;
+ }
+
+
+ // return array containing information about all supported formats
+ public function GetFileFormatArray() {
+ static $format_info = array();
+ if (empty($format_info)) {
+ $format_info = array(
+
+ // Audio formats
+
+ // AC-3 - audio - Dolby AC-3 / Dolby Digital
+ 'ac3' => array(
+ 'pattern' => '^\x0B\x77',
+ 'group' => 'audio',
+ 'module' => 'ac3',
+ 'mime_type' => 'audio/ac3',
+ ),
+
+ // AAC - audio - Advanced Audio Coding (AAC) - ADIF format
+ 'adif' => array(
+ 'pattern' => '^ADIF',
+ 'group' => 'audio',
+ 'module' => 'aac',
+ 'mime_type' => 'application/octet-stream',
+ 'fail_ape' => 'WARNING',
+ ),
+
+/*
+ // AA - audio - Audible Audiobook
+ 'aa' => array(
+ 'pattern' => '^.{4}\x57\x90\x75\x36',
+ 'group' => 'audio',
+ 'module' => 'aa',
+ 'mime_type' => 'audio/audible',
+ ),
+*/
+ // AAC - audio - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3)
+ 'adts' => array(
+ 'pattern' => '^\xFF[\xF0-\xF1\xF8-\xF9]',
+ 'group' => 'audio',
+ 'module' => 'aac',
+ 'mime_type' => 'application/octet-stream',
+ 'fail_ape' => 'WARNING',
+ ),
+
+
+ // AU - audio - NeXT/Sun AUdio (AU)
+ 'au' => array(
+ 'pattern' => '^\.snd',
+ 'group' => 'audio',
+ 'module' => 'au',
+ 'mime_type' => 'audio/basic',
+ ),
+
+ // AVR - audio - Audio Visual Research
+ 'avr' => array(
+ 'pattern' => '^2BIT',
+ 'group' => 'audio',
+ 'module' => 'avr',
+ 'mime_type' => 'application/octet-stream',
+ ),
+
+ // BONK - audio - Bonk v0.9+
+ 'bonk' => array(
+ 'pattern' => '^\x00(BONK|INFO|META| ID3)',
+ 'group' => 'audio',
+ 'module' => 'bonk',
+ 'mime_type' => 'audio/xmms-bonk',
+ ),
+
+ // DSS - audio - Digital Speech Standard
+ 'dss' => array(
+ 'pattern' => '^[\x02-\x03]ds[s2]',
+ 'group' => 'audio',
+ 'module' => 'dss',
+ 'mime_type' => 'application/octet-stream',
+ ),
+
+ // DTS - audio - Dolby Theatre System
+ 'dts' => array(
+ 'pattern' => '^\x7F\xFE\x80\x01',
+ 'group' => 'audio',
+ 'module' => 'dts',
+ 'mime_type' => 'audio/dts',
+ ),
+
+ // FLAC - audio - Free Lossless Audio Codec
+ 'flac' => array(
+ 'pattern' => '^fLaC',
+ 'group' => 'audio',
+ 'module' => 'flac',
+ 'mime_type' => 'audio/x-flac',
+ ),
+
+ // LA - audio - Lossless Audio (LA)
+ 'la' => array(
+ 'pattern' => '^LA0[2-4]',
+ 'group' => 'audio',
+ 'module' => 'la',
+ 'mime_type' => 'application/octet-stream',
+ ),
+
+ // LPAC - audio - Lossless Predictive Audio Compression (LPAC)
+ 'lpac' => array(
+ 'pattern' => '^LPAC',
+ 'group' => 'audio',
+ 'module' => 'lpac',
+ 'mime_type' => 'application/octet-stream',
+ ),
+
+ // MIDI - audio - MIDI (Musical Instrument Digital Interface)
+ 'midi' => array(
+ 'pattern' => '^MThd',
+ 'group' => 'audio',
+ 'module' => 'midi',
+ 'mime_type' => 'audio/midi',
+ ),
+
+ // MAC - audio - Monkey's Audio Compressor
+ 'mac' => array(
+ 'pattern' => '^MAC ',
+ 'group' => 'audio',
+ 'module' => 'monkey',
+ 'mime_type' => 'application/octet-stream',
+ ),
+
+// has been known to produce false matches in random files (e.g. JPEGs), leave out until more precise matching available
+// // MOD - audio - MODule (assorted sub-formats)
+// 'mod' => array(
+// 'pattern' => '^.{1080}(M\\.K\\.|M!K!|FLT4|FLT8|[5-9]CHN|[1-3][0-9]CH)',
+// 'group' => 'audio',
+// 'module' => 'mod',
+// 'option' => 'mod',
+// 'mime_type' => 'audio/mod',
+// ),
+
+ // MOD - audio - MODule (Impulse Tracker)
+ 'it' => array(
+ 'pattern' => '^IMPM',
+ 'group' => 'audio',
+ 'module' => 'mod',
+ //'option' => 'it',
+ 'mime_type' => 'audio/it',
+ ),
+
+ // MOD - audio - MODule (eXtended Module, various sub-formats)
+ 'xm' => array(
+ 'pattern' => '^Extended Module',
+ 'group' => 'audio',
+ 'module' => 'mod',
+ //'option' => 'xm',
+ 'mime_type' => 'audio/xm',
+ ),
+
+ // MOD - audio - MODule (ScreamTracker)
+ 's3m' => array(
+ 'pattern' => '^.{44}SCRM',
+ 'group' => 'audio',
+ 'module' => 'mod',
+ //'option' => 's3m',
+ 'mime_type' => 'audio/s3m',
+ ),
+
+ // MPC - audio - Musepack / MPEGplus
+ 'mpc' => array(
+ 'pattern' => '^(MPCK|MP\+|[\x00\x01\x10\x11\x40\x41\x50\x51\x80\x81\x90\x91\xC0\xC1\xD0\xD1][\x20-37][\x00\x20\x40\x60\x80\xA0\xC0\xE0])',
+ 'group' => 'audio',
+ 'module' => 'mpc',
+ 'mime_type' => 'audio/x-musepack',
+ ),
+
+ // MP3 - audio - MPEG-audio Layer 3 (very similar to AAC-ADTS)
+ 'mp3' => array(
+ 'pattern' => '^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\x0B\x10-\x1B\x20-\x2B\x30-\x3B\x40-\x4B\x50-\x5B\x60-\x6B\x70-\x7B\x80-\x8B\x90-\x9B\xA0-\xAB\xB0-\xBB\xC0-\xCB\xD0-\xDB\xE0-\xEB\xF0-\xFB]',
+ 'group' => 'audio',
+ 'module' => 'mp3',
+ 'mime_type' => 'audio/mpeg',
+ ),
+
+ // OFR - audio - OptimFROG
+ 'ofr' => array(
+ 'pattern' => '^(\*RIFF|OFR)',
+ 'group' => 'audio',
+ 'module' => 'optimfrog',
+ 'mime_type' => 'application/octet-stream',
+ ),
+
+ // RKAU - audio - RKive AUdio compressor
+ 'rkau' => array(
+ 'pattern' => '^RKA',
+ 'group' => 'audio',
+ 'module' => 'rkau',
+ 'mime_type' => 'application/octet-stream',
+ ),
+
+ // SHN - audio - Shorten
+ 'shn' => array(
+ 'pattern' => '^ajkg',
+ 'group' => 'audio',
+ 'module' => 'shorten',
+ 'mime_type' => 'audio/xmms-shn',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+ // TTA - audio - TTA Lossless Audio Compressor (http://tta.corecodec.org)
+ 'tta' => array(
+ 'pattern' => '^TTA', // could also be '^TTA(\x01|\x02|\x03|2|1)'
+ 'group' => 'audio',
+ 'module' => 'tta',
+ 'mime_type' => 'application/octet-stream',
+ ),
+
+ // VOC - audio - Creative Voice (VOC)
+ 'voc' => array(
+ 'pattern' => '^Creative Voice File',
+ 'group' => 'audio',
+ 'module' => 'voc',
+ 'mime_type' => 'audio/voc',
+ ),
+
+ // VQF - audio - transform-domain weighted interleave Vector Quantization Format (VQF)
+ 'vqf' => array(
+ 'pattern' => '^TWIN',
+ 'group' => 'audio',
+ 'module' => 'vqf',
+ 'mime_type' => 'application/octet-stream',
+ ),
+
+ // WV - audio - WavPack (v4.0+)
+ 'wv' => array(
+ 'pattern' => '^wvpk',
+ 'group' => 'audio',
+ 'module' => 'wavpack',
+ 'mime_type' => 'application/octet-stream',
+ ),
+
+
+ // Audio-Video formats
+
+ // ASF - audio/video - Advanced Streaming Format, Windows Media Video, Windows Media Audio
+ 'asf' => array(
+ 'pattern' => '^\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C',
+ 'group' => 'audio-video',
+ 'module' => 'asf',
+ 'mime_type' => 'video/x-ms-asf',
+ 'iconv_req' => false,
+ ),
+
+ // BINK - audio/video - Bink / Smacker
+ 'bink' => array(
+ 'pattern' => '^(BIK|SMK)',
+ 'group' => 'audio-video',
+ 'module' => 'bink',
+ 'mime_type' => 'application/octet-stream',
+ ),
+
+ // FLV - audio/video - FLash Video
+ 'flv' => array(
+ 'pattern' => '^FLV\x01',
+ 'group' => 'audio-video',
+ 'module' => 'flv',
+ 'mime_type' => 'video/x-flv',
+ ),
+
+ // MKAV - audio/video - Mastroka
+ 'matroska' => array(
+ 'pattern' => '^\x1A\x45\xDF\xA3',
+ 'group' => 'audio-video',
+ 'module' => 'matroska',
+ 'mime_type' => 'video/x-matroska', // may also be audio/x-matroska
+ ),
+
+ // MPEG - audio/video - MPEG (Moving Pictures Experts Group)
+ 'mpeg' => array(
+ 'pattern' => '^\x00\x00\x01(\xBA|\xB3)',
+ 'group' => 'audio-video',
+ 'module' => 'mpeg',
+ 'mime_type' => 'video/mpeg',
+ ),
+
+ // NSV - audio/video - Nullsoft Streaming Video (NSV)
+ 'nsv' => array(
+ 'pattern' => '^NSV[sf]',
+ 'group' => 'audio-video',
+ 'module' => 'nsv',
+ 'mime_type' => 'application/octet-stream',
+ ),
+
+ // Ogg - audio/video - Ogg (Ogg-Vorbis, Ogg-FLAC, Speex, Ogg-Theora(*), Ogg-Tarkin(*))
+ 'ogg' => array(
+ 'pattern' => '^OggS',
+ 'group' => 'audio',
+ 'module' => 'ogg',
+ 'mime_type' => 'application/ogg',
+ 'fail_id3' => 'WARNING',
+ 'fail_ape' => 'WARNING',
+ ),
+
+ // QT - audio/video - Quicktime
+ 'quicktime' => array(
+ 'pattern' => '^.{4}(cmov|free|ftyp|mdat|moov|pnot|skip|wide)',
+ 'group' => 'audio-video',
+ 'module' => 'quicktime',
+ 'mime_type' => 'video/quicktime',
+ ),
+
+ // RIFF - audio/video - Resource Interchange File Format (RIFF) / WAV / AVI / CD-audio / SDSS = renamed variant used by SmartSound QuickTracks (www.smartsound.com) / FORM = Audio Interchange File Format (AIFF)
+ 'riff' => array(
+ 'pattern' => '^(RIFF|SDSS|FORM)',
+ 'group' => 'audio-video',
+ 'module' => 'riff',
+ 'mime_type' => 'audio/x-wave',
+ 'fail_ape' => 'WARNING',
+ ),
+
+ // Real - audio/video - RealAudio, RealVideo
+ 'real' => array(
+ 'pattern' => '^(\\.RMF|\\.ra)',
+ 'group' => 'audio-video',
+ 'module' => 'real',
+ 'mime_type' => 'audio/x-realaudio',
+ ),
+
+ // SWF - audio/video - ShockWave Flash
+ 'swf' => array(
+ 'pattern' => '^(F|C)WS',
+ 'group' => 'audio-video',
+ 'module' => 'swf',
+ 'mime_type' => 'application/x-shockwave-flash',
+ ),
+
+ // TS - audio/video - MPEG-2 Transport Stream
+ 'ts' => array(
+ 'pattern' => '^(\x47.{187}){10,}', // packets are 188 bytes long and start with 0x47 "G". Check for at least 10 packets matching this pattern
+ 'group' => 'audio-video',
+ 'module' => 'ts',
+ 'mime_type' => 'video/MP2T',
+ ),
+
+
+ // Still-Image formats
+
+ // BMP - still image - Bitmap (Windows, OS/2; uncompressed, RLE8, RLE4)
+ 'bmp' => array(
+ 'pattern' => '^BM',
+ 'group' => 'graphic',
+ 'module' => 'bmp',
+ 'mime_type' => 'image/bmp',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+ // GIF - still image - Graphics Interchange Format
+ 'gif' => array(
+ 'pattern' => '^GIF',
+ 'group' => 'graphic',
+ 'module' => 'gif',
+ 'mime_type' => 'image/gif',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+ // JPEG - still image - Joint Photographic Experts Group (JPEG)
+ 'jpg' => array(
+ 'pattern' => '^\xFF\xD8\xFF',
+ 'group' => 'graphic',
+ 'module' => 'jpg',
+ 'mime_type' => 'image/jpeg',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+ // PCD - still image - Kodak Photo CD
+ 'pcd' => array(
+ 'pattern' => '^.{2048}PCD_IPI\x00',
+ 'group' => 'graphic',
+ 'module' => 'pcd',
+ 'mime_type' => 'image/x-photo-cd',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+
+ // PNG - still image - Portable Network Graphics (PNG)
+ 'png' => array(
+ 'pattern' => '^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A',
+ 'group' => 'graphic',
+ 'module' => 'png',
+ 'mime_type' => 'image/png',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+
+ // SVG - still image - Scalable Vector Graphics (SVG)
+ 'svg' => array(
+ 'pattern' => '(<!DOCTYPE svg PUBLIC |xmlns="http:\/\/www\.w3\.org\/2000\/svg")',
+ 'group' => 'graphic',
+ 'module' => 'svg',
+ 'mime_type' => 'image/svg+xml',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+
+ // TIFF - still image - Tagged Information File Format (TIFF)
+ 'tiff' => array(
+ 'pattern' => '^(II\x2A\x00|MM\x00\x2A)',
+ 'group' => 'graphic',
+ 'module' => 'tiff',
+ 'mime_type' => 'image/tiff',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+
+ // EFAX - still image - eFax (TIFF derivative)
+ 'efax' => array(
+ 'pattern' => '^\xDC\xFE',
+ 'group' => 'graphic',
+ 'module' => 'efax',
+ 'mime_type' => 'image/efax',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+
+ // Data formats
+
+ // ISO - data - International Standards Organization (ISO) CD-ROM Image
+ 'iso' => array(
+ 'pattern' => '^.{32769}CD001',
+ 'group' => 'misc',
+ 'module' => 'iso',
+ 'mime_type' => 'application/octet-stream',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ 'iconv_req' => false,
+ ),
+
+ // RAR - data - RAR compressed data
+ 'rar' => array(
+ 'pattern' => '^Rar\!',
+ 'group' => 'archive',
+ 'module' => 'rar',
+ 'mime_type' => 'application/octet-stream',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+ // SZIP - audio/data - SZIP compressed data
+ 'szip' => array(
+ 'pattern' => '^SZ\x0A\x04',
+ 'group' => 'archive',
+ 'module' => 'szip',
+ 'mime_type' => 'application/octet-stream',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+ // TAR - data - TAR compressed data
+ 'tar' => array(
+ 'pattern' => '^.{100}[0-9\x20]{7}\x00[0-9\x20]{7}\x00[0-9\x20]{7}\x00[0-9\x20\x00]{12}[0-9\x20\x00]{12}',
+ 'group' => 'archive',
+ 'module' => 'tar',
+ 'mime_type' => 'application/x-tar',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+ // GZIP - data - GZIP compressed data
+ 'gz' => array(
+ 'pattern' => '^\x1F\x8B\x08',
+ 'group' => 'archive',
+ 'module' => 'gzip',
+ 'mime_type' => 'application/x-gzip',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+ // ZIP - data - ZIP compressed data
+ 'zip' => array(
+ 'pattern' => '^PK\x03\x04',
+ 'group' => 'archive',
+ 'module' => 'zip',
+ 'mime_type' => 'application/zip',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+
+ // Misc other formats
+
+ // PAR2 - data - Parity Volume Set Specification 2.0
+ 'par2' => array (
+ 'pattern' => '^PAR2\x00PKT',
+ 'group' => 'misc',
+ 'module' => 'par2',
+ 'mime_type' => 'application/octet-stream',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+ // PDF - data - Portable Document Format
+ 'pdf' => array(
+ 'pattern' => '^\x25PDF',
+ 'group' => 'misc',
+ 'module' => 'pdf',
+ 'mime_type' => 'application/pdf',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+ // MSOFFICE - data - ZIP compressed data
+ 'msoffice' => array(
+ 'pattern' => '^\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1', // D0CF11E == DOCFILE == Microsoft Office Document
+ 'group' => 'misc',
+ 'module' => 'msoffice',
+ 'mime_type' => 'application/octet-stream',
+ 'fail_id3' => 'ERROR',
+ 'fail_ape' => 'ERROR',
+ ),
+
+ // CUE - data - CUEsheet (index to single-file disc images)
+ 'cue' => array(
+ 'pattern' => '', // empty pattern means cannot be automatically detected, will fall through all other formats and match based on filename and very basic file contents
+ 'group' => 'misc',
+ 'module' => 'cue',
+ 'mime_type' => 'application/octet-stream',
+ ),
+
+ );
+ }
+
+ return $format_info;
+ }
+
+
+
+ public function GetFileFormat(&$filedata, $filename='') {
+ // this function will determine the format of a file based on usually
+ // the first 2-4 bytes of the file (8 bytes for PNG, 16 bytes for JPG,
+ // and in the case of ISO CD image, 6 bytes offset 32kb from the start
+ // of the file).
+
+ // Identify file format - loop through $format_info and detect with reg expr
+ foreach ($this->GetFileFormatArray() as $format_name => $info) {
+ // The /s switch on preg_match() forces preg_match() NOT to treat
+ // newline (0x0A) characters as special chars but do a binary match
+ if (!empty($info['pattern']) && preg_match('#'.$info['pattern'].'#s', $filedata)) {
+ $info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
+ return $info;
+ }
+ }
+
+
+ if (preg_match('#\.mp[123a]$#i', $filename)) {
+ // Too many mp3 encoders on the market put gabage in front of mpeg files
+ // use assume format on these if format detection failed
+ $GetFileFormatArray = $this->GetFileFormatArray();
+ $info = $GetFileFormatArray['mp3'];
+ $info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
+ return $info;
+ } elseif (preg_match('/\.cue$/i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) {
+ // there's not really a useful consistent "magic" at the beginning of .cue files to identify them
+ // so until I think of something better, just go by filename if all other format checks fail
+ // and verify there's at least one instance of "TRACK xx AUDIO" in the file
+ $GetFileFormatArray = $this->GetFileFormatArray();
+ $info = $GetFileFormatArray['cue'];
+ $info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
+ return $info;
+ }
+
+ return false;
+ }
+
+
+ // converts array to $encoding charset from $this->encoding
+ public function CharConvert(&$array, $encoding) {
+
+ // identical encoding - end here
+ if ($encoding == $this->encoding) {
+ return;
+ }
+
+ // loop thru array
+ foreach ($array as $key => $value) {
+
+ // go recursive
+ if (is_array($value)) {
+ $this->CharConvert($array[$key], $encoding);
+ }
+
+ // convert string
+ elseif (is_string($value)) {
+ $array[$key] = trim(getid3_lib::iconv_fallback($encoding, $this->encoding, $value));
+ }
+ }
+ }
+
+
+ public function HandleAllTags() {
+
+ // key name => array (tag name, character encoding)
+ static $tags;
+ if (empty($tags)) {
+ $tags = array(
+ 'asf' => array('asf' , 'UTF-16LE'),
+ 'midi' => array('midi' , 'ISO-8859-1'),
+ 'nsv' => array('nsv' , 'ISO-8859-1'),
+ 'ogg' => array('vorbiscomment' , 'UTF-8'),
+ 'png' => array('png' , 'UTF-8'),
+ 'tiff' => array('tiff' , 'ISO-8859-1'),
+ 'quicktime' => array('quicktime' , 'UTF-8'),
+ 'real' => array('real' , 'ISO-8859-1'),
+ 'vqf' => array('vqf' , 'ISO-8859-1'),
+ 'zip' => array('zip' , 'ISO-8859-1'),
+ 'riff' => array('riff' , 'ISO-8859-1'),
+ 'lyrics3' => array('lyrics3' , 'ISO-8859-1'),
+ 'id3v1' => array('id3v1' , $this->encoding_id3v1),
+ 'id3v2' => array('id3v2' , 'UTF-8'), // not according to the specs (every frame can have a different encoding), but getID3() force-converts all encodings to UTF-8
+ 'ape' => array('ape' , 'UTF-8'),
+ 'cue' => array('cue' , 'ISO-8859-1'),
+ 'matroska' => array('matroska' , 'UTF-8'),
+ 'flac' => array('vorbiscomment' , 'UTF-8'),
+ 'divxtag' => array('divx' , 'ISO-8859-1'),
+ );
+ }
+
+ // loop through comments array
+ foreach ($tags as $comment_name => $tagname_encoding_array) {
+ list($tag_name, $encoding) = $tagname_encoding_array;
+
+ // fill in default encoding type if not already present
+ if (isset($this->info[$comment_name]) && !isset($this->info[$comment_name]['encoding'])) {
+ $this->info[$comment_name]['encoding'] = $encoding;
+ }
+
+ // copy comments if key name set
+ if (!empty($this->info[$comment_name]['comments'])) {
+ foreach ($this->info[$comment_name]['comments'] as $tag_key => $valuearray) {
+ foreach ($valuearray as $key => $value) {
+ if (is_string($value)) {
+ $value = trim($value, " \r\n\t"); // do not trim nulls from $value!! Unicode characters will get mangled if trailing nulls are removed!
+ }
+ if ($value) {
+ $this->info['tags'][trim($tag_name)][trim($tag_key)][] = $value;
+ }
+ }
+ if ($tag_key == 'picture') {
+ unset($this->info[$comment_name]['comments'][$tag_key]);
+ }
+ }
+
+ if (!isset($this->info['tags'][$tag_name])) {
+ // comments are set but contain nothing but empty strings, so skip
+ continue;
+ }
+
+ if ($this->option_tags_html) {
+ foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
+ foreach ($valuearray as $key => $value) {
+ if (is_string($value)) {
+ //$this->info['tags_html'][$tag_name][$tag_key][$key] = getid3_lib::MultiByteCharString2HTML($value, $encoding);
+ $this->info['tags_html'][$tag_name][$tag_key][$key] = str_replace('&#0;', '', trim(getid3_lib::MultiByteCharString2HTML($value, $encoding)));
+ } else {
+ $this->info['tags_html'][$tag_name][$tag_key][$key] = $value;
+ }
+ }
+ }
+ }
+
+ $this->CharConvert($this->info['tags'][$tag_name], $encoding); // only copy gets converted!
+ }
+
+ }
+
+ // pictures can take up a lot of space, and we don't need multiple copies of them
+ // let there be a single copy in [comments][picture], and not elsewhere
+ if (!empty($this->info['tags'])) {
+ $unset_keys = array('tags', 'tags_html');
+ foreach ($this->info['tags'] as $tagtype => $tagarray) {
+ foreach ($tagarray as $tagname => $tagdata) {
+ if ($tagname == 'picture') {
+ foreach ($tagdata as $key => $tagarray) {
+ $this->info['comments']['picture'][] = $tagarray;
+ if (isset($tagarray['data']) && isset($tagarray['image_mime'])) {
+ if (isset($this->info['tags'][$tagtype][$tagname][$key])) {
+ unset($this->info['tags'][$tagtype][$tagname][$key]);
+ }
+ if (isset($this->info['tags_html'][$tagtype][$tagname][$key])) {
+ unset($this->info['tags_html'][$tagtype][$tagname][$key]);
+ }
+ }
+ }
+ }
+ }
+ foreach ($unset_keys as $unset_key) {
+ // remove possible empty keys from (e.g. [tags][id3v2][picture])
+ if (empty($this->info[$unset_key][$tagtype]['picture'])) {
+ unset($this->info[$unset_key][$tagtype]['picture']);
+ }
+ if (empty($this->info[$unset_key][$tagtype])) {
+ unset($this->info[$unset_key][$tagtype]);
+ }
+ if (empty($this->info[$unset_key])) {
+ unset($this->info[$unset_key]);
+ }
+ }
+ // remove duplicate copy of picture data from (e.g. [id3v2][comments][picture])
+ if (isset($this->info[$tagtype]['comments']['picture'])) {
+ unset($this->info[$tagtype]['comments']['picture']);
+ }
+ if (empty($this->info[$tagtype]['comments'])) {
+ unset($this->info[$tagtype]['comments']);
+ }
+ if (empty($this->info[$tagtype])) {
+ unset($this->info[$tagtype]);
+ }
+ }
+ }
+ return true;
+ }
+
+
+ public function getHashdata($algorithm) {
+ switch ($algorithm) {
+ case 'md5':
+ case 'sha1':
+ break;
+
+ default:
+ return $this->error('bad algorithm "'.$algorithm.'" in getHashdata()');
+ break;
+ }
+
+ if (!empty($this->info['fileformat']) && !empty($this->info['dataformat']) && ($this->info['fileformat'] == 'ogg') && ($this->info['audio']['dataformat'] == 'vorbis')) {
+
+ // We cannot get an identical md5_data value for Ogg files where the comments
+ // span more than 1 Ogg page (compared to the same audio data with smaller
+ // comments) using the normal getID3() method of MD5'ing the data between the
+ // end of the comments and the end of the file (minus any trailing tags),
+ // because the page sequence numbers of the pages that the audio data is on
+ // do not match. Under normal circumstances, where comments are smaller than
+ // the nominal 4-8kB page size, then this is not a problem, but if there are
+ // very large comments, the only way around it is to strip off the comment
+ // tags with vorbiscomment and MD5 that file.
+ // This procedure must be applied to ALL Ogg files, not just the ones with
+ // comments larger than 1 page, because the below method simply MD5's the
+ // whole file with the comments stripped, not just the portion after the
+ // comments block (which is the standard getID3() method.
+
+ // The above-mentioned problem of comments spanning multiple pages and changing
+ // page sequence numbers likely happens for OggSpeex and OggFLAC as well, but
+ // currently vorbiscomment only works on OggVorbis files.
+
+ if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
+
+ $this->warning('Failed making system call to vorbiscomment.exe - '.$algorithm.'_data is incorrect - error returned: PHP running in Safe Mode (backtick operator not available)');
+ $this->info[$algorithm.'_data'] = false;
+
+ } else {
+
+ // Prevent user from aborting script
+ $old_abort = ignore_user_abort(true);
+
+ // Create empty file
+ $empty = tempnam(GETID3_TEMP_DIR, 'getID3');
+ touch($empty);
+
+ // Use vorbiscomment to make temp file without comments
+ $temp = tempnam(GETID3_TEMP_DIR, 'getID3');
+ $file = $this->info['filenamepath'];
+
+ if (GETID3_OS_ISWINDOWS) {
+
+ if (file_exists(GETID3_HELPERAPPSDIR.'vorbiscomment.exe')) {
+
+ $commandline = '"'.GETID3_HELPERAPPSDIR.'vorbiscomment.exe" -w -c "'.$empty.'" "'.$file.'" "'.$temp.'"';
+ $VorbisCommentError = `$commandline`;
+
+ } else {
+
+ $VorbisCommentError = 'vorbiscomment.exe not found in '.GETID3_HELPERAPPSDIR;
+
+ }
+
+ } else {
+
+ $commandline = 'vorbiscomment -w -c "'.$empty.'" "'.$file.'" "'.$temp.'" 2>&1';
+ $commandline = 'vorbiscomment -w -c '.escapeshellarg($empty).' '.escapeshellarg($file).' '.escapeshellarg($temp).' 2>&1';
+ $VorbisCommentError = `$commandline`;
+
+ }
+
+ if (!empty($VorbisCommentError)) {
+
+ $this->info['warning'][] = 'Failed making system call to vorbiscomment(.exe) - '.$algorithm.'_data will be incorrect. If vorbiscomment is unavailable, please download from http://www.vorbis.com/download.psp and put in the getID3() directory. Error returned: '.$VorbisCommentError;
+ $this->info[$algorithm.'_data'] = false;
+
+ } else {
+
+ // Get hash of newly created file
+ switch ($algorithm) {
+ case 'md5':
+ $this->info[$algorithm.'_data'] = md5_file($temp);
+ break;
+
+ case 'sha1':
+ $this->info[$algorithm.'_data'] = sha1_file($temp);
+ break;
+ }
+ }
+
+ // Clean up
+ unlink($empty);
+ unlink($temp);
+
+ // Reset abort setting
+ ignore_user_abort($old_abort);
+
+ }
+
+ } else {
+
+ if (!empty($this->info['avdataoffset']) || (isset($this->info['avdataend']) && ($this->info['avdataend'] < $this->info['filesize']))) {
+
+ // get hash from part of file
+ $this->info[$algorithm.'_data'] = getid3_lib::hash_data($this->info['filenamepath'], $this->info['avdataoffset'], $this->info['avdataend'], $algorithm);
+
+ } else {
+
+ // get hash from whole file
+ switch ($algorithm) {
+ case 'md5':
+ $this->info[$algorithm.'_data'] = md5_file($this->info['filenamepath']);
+ break;
+
+ case 'sha1':
+ $this->info[$algorithm.'_data'] = sha1_file($this->info['filenamepath']);
+ break;
+ }
+ }
+
+ }
+ return true;
+ }
+
+
+ public function ChannelsBitratePlaytimeCalculations() {
+
+ // set channelmode on audio
+ if (!empty($this->info['audio']['channelmode']) || !isset($this->info['audio']['channels'])) {
+ // ignore
+ } elseif ($this->info['audio']['channels'] == 1) {
+ $this->info['audio']['channelmode'] = 'mono';
+ } elseif ($this->info['audio']['channels'] == 2) {
+ $this->info['audio']['channelmode'] = 'stereo';
+ }
+
+ // Calculate combined bitrate - audio + video
+ $CombinedBitrate = 0;
+ $CombinedBitrate += (isset($this->info['audio']['bitrate']) ? $this->info['audio']['bitrate'] : 0);
+ $CombinedBitrate += (isset($this->info['video']['bitrate']) ? $this->info['video']['bitrate'] : 0);
+ if (($CombinedBitrate > 0) && empty($this->info['bitrate'])) {
+ $this->info['bitrate'] = $CombinedBitrate;
+ }
+ //if ((isset($this->info['video']) && !isset($this->info['video']['bitrate'])) || (isset($this->info['audio']) && !isset($this->info['audio']['bitrate']))) {
+ // // for example, VBR MPEG video files cannot determine video bitrate:
+ // // should not set overall bitrate and playtime from audio bitrate only
+ // unset($this->info['bitrate']);
+ //}
+
+ // video bitrate undetermined, but calculable
+ if (isset($this->info['video']['dataformat']) && $this->info['video']['dataformat'] && (!isset($this->info['video']['bitrate']) || ($this->info['video']['bitrate'] == 0))) {
+ // if video bitrate not set
+ if (isset($this->info['audio']['bitrate']) && ($this->info['audio']['bitrate'] > 0) && ($this->info['audio']['bitrate'] == $this->info['bitrate'])) {
+ // AND if audio bitrate is set to same as overall bitrate
+ if (isset($this->info['playtime_seconds']) && ($this->info['playtime_seconds'] > 0)) {
+ // AND if playtime is set
+ if (isset($this->info['avdataend']) && isset($this->info['avdataoffset'])) {
+ // AND if AV data offset start/end is known
+ // THEN we can calculate the video bitrate
+ $this->info['bitrate'] = round((($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['playtime_seconds']);
+ $this->info['video']['bitrate'] = $this->info['bitrate'] - $this->info['audio']['bitrate'];
+ }
+ }
+ }
+ }
+
+ if ((!isset($this->info['playtime_seconds']) || ($this->info['playtime_seconds'] <= 0)) && !empty($this->info['bitrate'])) {
+ $this->info['playtime_seconds'] = (($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['bitrate'];
+ }
+
+ if (!isset($this->info['bitrate']) && !empty($this->info['playtime_seconds'])) {
+ $this->info['bitrate'] = (($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['playtime_seconds'];
+ }
+ if (isset($this->info['bitrate']) && empty($this->info['audio']['bitrate']) && empty($this->info['video']['bitrate'])) {
+ if (isset($this->info['audio']['dataformat']) && empty($this->info['video']['resolution_x'])) {
+ // audio only
+ $this->info['audio']['bitrate'] = $this->info['bitrate'];
+ } elseif (isset($this->info['video']['resolution_x']) && empty($this->info['audio']['dataformat'])) {
+ // video only
+ $this->info['video']['bitrate'] = $this->info['bitrate'];
+ }
+ }
+
+ // Set playtime string
+ if (!empty($this->info['playtime_seconds']) && empty($this->info['playtime_string'])) {
+ $this->info['playtime_string'] = getid3_lib::PlaytimeString($this->info['playtime_seconds']);
+ }
+ }
+
+
+ public function CalculateCompressionRatioVideo() {
+ if (empty($this->info['video'])) {
+ return false;
+ }
+ if (empty($this->info['video']['resolution_x']) || empty($this->info['video']['resolution_y'])) {
+ return false;
+ }
+ if (empty($this->info['video']['bits_per_sample'])) {
+ return false;
+ }
+
+ switch ($this->info['video']['dataformat']) {
+ case 'bmp':
+ case 'gif':
+ case 'jpeg':
+ case 'jpg':
+ case 'png':
+ case 'tiff':
+ $FrameRate = 1;
+ $PlaytimeSeconds = 1;
+ $BitrateCompressed = $this->info['filesize'] * 8;
+ break;
+
+ default:
+ if (!empty($this->info['video']['frame_rate'])) {
+ $FrameRate = $this->info['video']['frame_rate'];
+ } else {
+ return false;
+ }
+ if (!empty($this->info['playtime_seconds'])) {
+ $PlaytimeSeconds = $this->info['playtime_seconds'];
+ } else {
+ return false;
+ }
+ if (!empty($this->info['video']['bitrate'])) {
+ $BitrateCompressed = $this->info['video']['bitrate'];
+ } else {
+ return false;
+ }
+ break;
+ }
+ $BitrateUncompressed = $this->info['video']['resolution_x'] * $this->info['video']['resolution_y'] * $this->info['video']['bits_per_sample'] * $FrameRate;
+
+ $this->info['video']['compression_ratio'] = $BitrateCompressed / $BitrateUncompressed;
+ return true;
+ }
+
+
+ public function CalculateCompressionRatioAudio() {
+ if (empty($this->info['audio']['bitrate']) || empty($this->info['audio']['channels']) || empty($this->info['audio']['sample_rate']) || !is_numeric($this->info['audio']['sample_rate'])) {
+ return false;
+ }
+ $this->info['audio']['compression_ratio'] = $this->info['audio']['bitrate'] / ($this->info['audio']['channels'] * $this->info['audio']['sample_rate'] * (!empty($this->info['audio']['bits_per_sample']) ? $this->info['audio']['bits_per_sample'] : 16));
+
+ if (!empty($this->info['audio']['streams'])) {
+ foreach ($this->info['audio']['streams'] as $streamnumber => $streamdata) {
+ if (!empty($streamdata['bitrate']) && !empty($streamdata['channels']) && !empty($streamdata['sample_rate'])) {
+ $this->info['audio']['streams'][$streamnumber]['compression_ratio'] = $streamdata['bitrate'] / ($streamdata['channels'] * $streamdata['sample_rate'] * (!empty($streamdata['bits_per_sample']) ? $streamdata['bits_per_sample'] : 16));
+ }
+ }
+ }
+ return true;
+ }
+
+
+ public function CalculateReplayGain() {
+ if (isset($this->info['replay_gain'])) {
+ if (!isset($this->info['replay_gain']['reference_volume'])) {
+ $this->info['replay_gain']['reference_volume'] = (double) 89.0;
+ }
+ if (isset($this->info['replay_gain']['track']['adjustment'])) {
+ $this->info['replay_gain']['track']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['track']['adjustment'];
+ }
+ if (isset($this->info['replay_gain']['album']['adjustment'])) {
+ $this->info['replay_gain']['album']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['album']['adjustment'];
+ }
+
+ if (isset($this->info['replay_gain']['track']['peak'])) {
+ $this->info['replay_gain']['track']['max_noclip_gain'] = 0 - getid3_lib::RGADamplitude2dB($this->info['replay_gain']['track']['peak']);
+ }
+ if (isset($this->info['replay_gain']['album']['peak'])) {
+ $this->info['replay_gain']['album']['max_noclip_gain'] = 0 - getid3_lib::RGADamplitude2dB($this->info['replay_gain']['album']['peak']);
+ }
+ }
+ return true;
+ }
+
+ public function ProcessAudioStreams() {
+ if (!empty($this->info['audio']['bitrate']) || !empty($this->info['audio']['channels']) || !empty($this->info['audio']['sample_rate'])) {
+ if (!isset($this->info['audio']['streams'])) {
+ foreach ($this->info['audio'] as $key => $value) {
+ if ($key != 'streams') {
+ $this->info['audio']['streams'][0][$key] = $value;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ public function getid3_tempnam() {
+ return tempnam($this->tempdir, 'gI3');
+ }
+
+ public function include_module($name) {
+ //if (!file_exists($this->include_path.'module.'.$name.'.php')) {
+ if (!file_exists(GETID3_INCLUDEPATH.'module.'.$name.'.php')) {
+ throw new getid3_exception('Required module.'.$name.'.php is missing.');
+ }
+ include_once(GETID3_INCLUDEPATH.'module.'.$name.'.php');
+ return true;
+ }
+
+}
+
+
+abstract class getid3_handler
+{
+ protected $getid3; // pointer
+
+ protected $data_string_flag = false; // analyzing filepointer or string
+ protected $data_string = ''; // string to analyze
+ protected $data_string_position = 0; // seek position in string
+ protected $data_string_length = 0; // string length
+
+ private $dependency_to = null;
+
+
+ public function __construct(getID3 $getid3, $call_module=null) {
+ $this->getid3 = $getid3;
+
+ if ($call_module) {
+ $this->dependency_to = str_replace('getid3_', '', $call_module);
+ }
+ }
+
+
+ // Analyze from file pointer
+ abstract public function Analyze();
+
+
+ // Analyze from string instead
+ public function AnalyzeString($string) {
+ // Enter string mode
+ $this->setStringMode($string);
+
+ // Save info
+ $saved_avdataoffset = $this->getid3->info['avdataoffset'];
+ $saved_avdataend = $this->getid3->info['avdataend'];
+ $saved_filesize = (isset($this->getid3->info['filesize']) ? $this->getid3->info['filesize'] : null); // may be not set if called as dependency without openfile() call
+
+ // Reset some info
+ $this->getid3->info['avdataoffset'] = 0;
+ $this->getid3->info['avdataend'] = $this->getid3->info['filesize'] = $this->data_string_length;
+
+ // Analyze
+ $this->Analyze();
+
+ // Restore some info
+ $this->getid3->info['avdataoffset'] = $saved_avdataoffset;
+ $this->getid3->info['avdataend'] = $saved_avdataend;
+ $this->getid3->info['filesize'] = $saved_filesize;
+
+ // Exit string mode
+ $this->data_string_flag = false;
+ }
+
+ public function setStringMode($string) {
+ $this->data_string_flag = true;
+ $this->data_string = $string;
+ $this->data_string_length = strlen($string);
+ }
+
+ protected function ftell() {
+ if ($this->data_string_flag) {
+ return $this->data_string_position;
+ }
+ return ftell($this->getid3->fp);
+ }
+
+ protected function fread($bytes) {
+ if ($this->data_string_flag) {
+ $this->data_string_position += $bytes;
+ return substr($this->data_string, $this->data_string_position - $bytes, $bytes);
+ }
+ $pos = $this->ftell() + $bytes;
+ if (!getid3_lib::intValueSupported($pos)) {
+ throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 10);
+ }
+ return fread($this->getid3->fp, $bytes);
+ }
+
+ protected function fseek($bytes, $whence=SEEK_SET) {
+ if ($this->data_string_flag) {
+ switch ($whence) {
+ case SEEK_SET:
+ $this->data_string_position = $bytes;
+ break;
+
+ case SEEK_CUR:
+ $this->data_string_position += $bytes;
+ break;
+
+ case SEEK_END:
+ $this->data_string_position = $this->data_string_length + $bytes;
+ break;
+ }
+ return 0;
+ } else {
+ $pos = $bytes;
+ if ($whence == SEEK_CUR) {
+ $pos = $this->ftell() + $bytes;
+ } elseif ($whence == SEEK_END) {
+ $pos = $this->info['filesize'] + $bytes;
+ }
+ if (!getid3_lib::intValueSupported($pos)) {
+ throw new getid3_exception('cannot fseek('.$pos.') because beyond PHP filesystem limit', 10);
+ }
+ }
+ return fseek($this->getid3->fp, $bytes, $whence);
+ }
+
+ protected function feof() {
+ if ($this->data_string_flag) {
+ return $this->data_string_position >= $this->data_string_length;
+ }
+ return feof($this->getid3->fp);
+ }
+
+ final protected function isDependencyFor($module) {
+ return $this->dependency_to == $module;
+ }
+
+ protected function error($text)
+ {
+ $this->getid3->info['error'][] = $text;
+
+ return false;
+ }
+
+ protected function warning($text)
+ {
+ return $this->getid3->warning($text);
+ }
+
+ protected function notice($text)
+ {
+ // does nothing for now
+ }
+
+ public function saveAttachment($name, $offset, $length, $image_mime=null) {
+ try {
+
+ // do not extract at all
+ if ($this->getid3->option_save_attachments === getID3::ATTACHMENTS_NONE) {
+
+ $attachment = null; // do not set any
+
+ // extract to return array
+ } elseif ($this->getid3->option_save_attachments === getID3::ATTACHMENTS_INLINE) {
+
+ $this->fseek($offset);
+ $attachment = $this->fread($length); // get whole data in one pass, till it is anyway stored in memory
+ if ($attachment === false || strlen($attachment) != $length) {
+ throw new Exception('failed to read attachment data');
+ }
+
+ // assume directory path is given
+ } else {
+
+ // set up destination path
+ $dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR);
+ if (!is_dir($dir) || !is_writable($dir)) { // check supplied directory
+ throw new Exception('supplied path ('.$dir.') does not exist, or is not writable');
+ }
+ $dest = $dir.DIRECTORY_SEPARATOR.$name.($image_mime ? '.'.getid3_lib::ImageExtFromMime($image_mime) : '');
+
+ // create dest file
+ if (($fp_dest = fopen($dest, 'wb')) == false) {
+ throw new Exception('failed to create file '.$dest);
+ }
+
+ // copy data
+ $this->fseek($offset);
+ $buffersize = ($this->data_string_flag ? $length : $this->getid3->fread_buffer_size());
+ $bytesleft = $length;
+ while ($bytesleft > 0) {
+ if (($buffer = $this->fread(min($buffersize, $bytesleft))) === false || ($byteswritten = fwrite($fp_dest, $buffer)) === false || ($byteswritten === 0)) {
+ throw new Exception($buffer === false ? 'not enough data to read' : 'failed to write to destination file, may be not enough disk space');
+ }
+ $bytesleft -= $byteswritten;
+ }
+
+ fclose($fp_dest);
+ $attachment = $dest;
+
+ }
+
+ } catch (Exception $e) {
+
+ // close and remove dest file if created
+ if (isset($fp_dest) && is_resource($fp_dest)) {
+ fclose($fp_dest);
+ unlink($dest);
+ }
+
+ // do not set any is case of error
+ $attachment = null;
+ $this->warning('Failed to extract attachment '.$name.': '.$e->getMessage());
+
+ }
+
+ // seek to the end of attachment
+ $this->fseek($offset + $length);
+
+ return $attachment;
+ }
+
+}
+
+
+class getid3_exception extends Exception
+{
+ public $message;
+}
diff --git a/extensions/TimedMediaHandler/libs/getid3/license.txt b/extensions/TimedMediaHandler/libs/getid3/license.txt
new file mode 100644
index 00000000..f349faab
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/license.txt
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License. \ No newline at end of file
diff --git a/extensions/TimedMediaHandler/libs/getid3/module.audio-video.matroska.php b/extensions/TimedMediaHandler/libs/getid3/module.audio-video.matroska.php
new file mode 100644
index 00000000..3c1921fb
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/module.audio-video.matroska.php
@@ -0,0 +1,1771 @@
+<?php
+/////////////////////////////////////////////////////////////////
+/// getID3() by James Heinrich <info@getid3.org> //
+// available at http://getid3.sourceforge.net //
+// or http://www.getid3.org //
+/////////////////////////////////////////////////////////////////
+// See readme.txt for more details //
+/////////////////////////////////////////////////////////////////
+// //
+// module.audio-video.matriska.php //
+// module for analyzing Matroska containers //
+// dependencies: NONE //
+// ///
+/////////////////////////////////////////////////////////////////
+
+
+define('EBML_ID_CHAPTERS', 0x0043A770); // [10][43][A7][70] -- A system to define basic menus and partition data. For more detailed information, look at the Chapters Explanation.
+define('EBML_ID_SEEKHEAD', 0x014D9B74); // [11][4D][9B][74] -- Contains the position of other level 1 elements.
+define('EBML_ID_TAGS', 0x0254C367); // [12][54][C3][67] -- Element containing elements specific to Tracks/Chapters. A list of valid tags can be found <http://www.matroska.org/technical/specs/tagging/index.html>.
+define('EBML_ID_INFO', 0x0549A966); // [15][49][A9][66] -- Contains miscellaneous general information and statistics on the file.
+define('EBML_ID_TRACKS', 0x0654AE6B); // [16][54][AE][6B] -- A top-level block of information with many tracks described.
+define('EBML_ID_SEGMENT', 0x08538067); // [18][53][80][67] -- This element contains all other top-level (level 1) elements. Typically a Matroska file is composed of 1 segment.
+define('EBML_ID_ATTACHMENTS', 0x0941A469); // [19][41][A4][69] -- Contain attached files.
+define('EBML_ID_EBML', 0x0A45DFA3); // [1A][45][DF][A3] -- Set the EBML characteristics of the data to follow. Each EBML document has to start with this.
+define('EBML_ID_CUES', 0x0C53BB6B); // [1C][53][BB][6B] -- A top-level element to speed seeking access. All entries are local to the segment.
+define('EBML_ID_CLUSTER', 0x0F43B675); // [1F][43][B6][75] -- The lower level element containing the (monolithic) Block structure.
+define('EBML_ID_LANGUAGE', 0x02B59C); // [22][B5][9C] -- Specifies the language of the track in the Matroska languages form.
+define('EBML_ID_TRACKTIMECODESCALE', 0x03314F); // [23][31][4F] -- The scale to apply on this track to work at normal speed in relation with other tracks (mostly used to adjust video speed when the audio length differs).
+define('EBML_ID_DEFAULTDURATION', 0x03E383); // [23][E3][83] -- Number of nanoseconds (i.e. not scaled) per frame.
+define('EBML_ID_CODECNAME', 0x058688); // [25][86][88] -- A human-readable string specifying the codec.
+define('EBML_ID_CODECDOWNLOADURL', 0x06B240); // [26][B2][40] -- A URL to download about the codec used.
+define('EBML_ID_TIMECODESCALE', 0x0AD7B1); // [2A][D7][B1] -- Timecode scale in nanoseconds (1.000.000 means all timecodes in the segment are expressed in milliseconds).
+define('EBML_ID_COLOURSPACE', 0x0EB524); // [2E][B5][24] -- Same value as in AVI (32 bits).
+define('EBML_ID_GAMMAVALUE', 0x0FB523); // [2F][B5][23] -- Gamma Value.
+define('EBML_ID_CODECSETTINGS', 0x1A9697); // [3A][96][97] -- A string describing the encoding setting used.
+define('EBML_ID_CODECINFOURL', 0x1B4040); // [3B][40][40] -- A URL to find information about the codec used.
+define('EBML_ID_PREVFILENAME', 0x1C83AB); // [3C][83][AB] -- An escaped filename corresponding to the previous segment.
+define('EBML_ID_PREVUID', 0x1CB923); // [3C][B9][23] -- A unique ID to identify the previous chained segment (128 bits).
+define('EBML_ID_NEXTFILENAME', 0x1E83BB); // [3E][83][BB] -- An escaped filename corresponding to the next segment.
+define('EBML_ID_NEXTUID', 0x1EB923); // [3E][B9][23] -- A unique ID to identify the next chained segment (128 bits).
+define('EBML_ID_CONTENTCOMPALGO', 0x0254); // [42][54] -- The compression algorithm used. Algorithms that have been specified so far are:
+define('EBML_ID_CONTENTCOMPSETTINGS', 0x0255); // [42][55] -- Settings that might be needed by the decompressor. For Header Stripping (ContentCompAlgo=3), the bytes that were removed from the beggining of each frames of the track.
+define('EBML_ID_DOCTYPE', 0x0282); // [42][82] -- A string that describes the type of document that follows this EBML header ('matroska' in our case).
+define('EBML_ID_DOCTYPEREADVERSION', 0x0285); // [42][85] -- The minimum DocType version an interpreter has to support to read this file.
+define('EBML_ID_EBMLVERSION', 0x0286); // [42][86] -- The version of EBML parser used to create the file.
+define('EBML_ID_DOCTYPEVERSION', 0x0287); // [42][87] -- The version of DocType interpreter used to create the file.
+define('EBML_ID_EBMLMAXIDLENGTH', 0x02F2); // [42][F2] -- The maximum length of the IDs you'll find in this file (4 or less in Matroska).
+define('EBML_ID_EBMLMAXSIZELENGTH', 0x02F3); // [42][F3] -- The maximum length of the sizes you'll find in this file (8 or less in Matroska). This does not override the element size indicated at the beginning of an element. Elements that have an indicated size which is larger than what is allowed by EBMLMaxSizeLength shall be considered invalid.
+define('EBML_ID_EBMLREADVERSION', 0x02F7); // [42][F7] -- The minimum EBML version a parser has to support to read this file.
+define('EBML_ID_CHAPLANGUAGE', 0x037C); // [43][7C] -- The languages corresponding to the string, in the bibliographic ISO-639-2 form.
+define('EBML_ID_CHAPCOUNTRY', 0x037E); // [43][7E] -- The countries corresponding to the string, same 2 octets as in Internet domains.
+define('EBML_ID_SEGMENTFAMILY', 0x0444); // [44][44] -- A randomly generated unique ID that all segments related to each other must use (128 bits).
+define('EBML_ID_DATEUTC', 0x0461); // [44][61] -- Date of the origin of timecode (value 0), i.e. production date.
+define('EBML_ID_TAGLANGUAGE', 0x047A); // [44][7A] -- Specifies the language of the tag specified, in the Matroska languages form.
+define('EBML_ID_TAGDEFAULT', 0x0484); // [44][84] -- Indication to know if this is the default/original language to use for the given tag.
+define('EBML_ID_TAGBINARY', 0x0485); // [44][85] -- The values of the Tag if it is binary. Note that this cannot be used in the same SimpleTag as TagString.
+define('EBML_ID_TAGSTRING', 0x0487); // [44][87] -- The value of the Tag.
+define('EBML_ID_DURATION', 0x0489); // [44][89] -- Duration of the segment (based on TimecodeScale).
+define('EBML_ID_CHAPPROCESSPRIVATE', 0x050D); // [45][0D] -- Some optional data attached to the ChapProcessCodecID information. For ChapProcessCodecID = 1, it is the "DVD level" equivalent.
+define('EBML_ID_CHAPTERFLAGENABLED', 0x0598); // [45][98] -- Specify wether the chapter is enabled. It can be enabled/disabled by a Control Track. When disabled, the movie should skip all the content between the TimeStart and TimeEnd of this chapter.
+define('EBML_ID_TAGNAME', 0x05A3); // [45][A3] -- The name of the Tag that is going to be stored.
+define('EBML_ID_EDITIONENTRY', 0x05B9); // [45][B9] -- Contains all information about a segment edition.
+define('EBML_ID_EDITIONUID', 0x05BC); // [45][BC] -- A unique ID to identify the edition. It's useful for tagging an edition.
+define('EBML_ID_EDITIONFLAGHIDDEN', 0x05BD); // [45][BD] -- If an edition is hidden (1), it should not be available to the user interface (but still to Control Tracks).
+define('EBML_ID_EDITIONFLAGDEFAULT', 0x05DB); // [45][DB] -- If a flag is set (1) the edition should be used as the default one.
+define('EBML_ID_EDITIONFLAGORDERED', 0x05DD); // [45][DD] -- Specify if the chapters can be defined multiple times and the order to play them is enforced.
+define('EBML_ID_FILEDATA', 0x065C); // [46][5C] -- The data of the file.
+define('EBML_ID_FILEMIMETYPE', 0x0660); // [46][60] -- MIME type of the file.
+define('EBML_ID_FILENAME', 0x066E); // [46][6E] -- Filename of the attached file.
+define('EBML_ID_FILEREFERRAL', 0x0675); // [46][75] -- A binary value that a track/codec can refer to when the attachment is needed.
+define('EBML_ID_FILEDESCRIPTION', 0x067E); // [46][7E] -- A human-friendly name for the attached file.
+define('EBML_ID_FILEUID', 0x06AE); // [46][AE] -- Unique ID representing the file, as random as possible.
+define('EBML_ID_CONTENTENCALGO', 0x07E1); // [47][E1] -- The encryption algorithm used. The value '0' means that the contents have not been encrypted but only signed. Predefined values:
+define('EBML_ID_CONTENTENCKEYID', 0x07E2); // [47][E2] -- For public key algorithms this is the ID of the public key the the data was encrypted with.
+define('EBML_ID_CONTENTSIGNATURE', 0x07E3); // [47][E3] -- A cryptographic signature of the contents.
+define('EBML_ID_CONTENTSIGKEYID', 0x07E4); // [47][E4] -- This is the ID of the private key the data was signed with.
+define('EBML_ID_CONTENTSIGALGO', 0x07E5); // [47][E5] -- The algorithm used for the signature. A value of '0' means that the contents have not been signed but only encrypted. Predefined values:
+define('EBML_ID_CONTENTSIGHASHALGO', 0x07E6); // [47][E6] -- The hash algorithm used for the signature. A value of '0' means that the contents have not been signed but only encrypted. Predefined values:
+define('EBML_ID_MUXINGAPP', 0x0D80); // [4D][80] -- Muxing application or library ("libmatroska-0.4.3").
+define('EBML_ID_SEEK', 0x0DBB); // [4D][BB] -- Contains a single seek entry to an EBML element.
+define('EBML_ID_CONTENTENCODINGORDER', 0x1031); // [50][31] -- Tells when this modification was used during encoding/muxing starting with 0 and counting upwards. The decoder/demuxer has to start with the highest order number it finds and work its way down. This value has to be unique over all ContentEncodingOrder elements in the segment.
+define('EBML_ID_CONTENTENCODINGSCOPE', 0x1032); // [50][32] -- A bit field that describes which elements have been modified in this way. Values (big endian) can be OR'ed. Possible values:
+define('EBML_ID_CONTENTENCODINGTYPE', 0x1033); // [50][33] -- A value describing what kind of transformation has been done. Possible values:
+define('EBML_ID_CONTENTCOMPRESSION', 0x1034); // [50][34] -- Settings describing the compression used. Must be present if the value of ContentEncodingType is 0 and absent otherwise. Each block must be decompressable even if no previous block is available in order not to prevent seeking.
+define('EBML_ID_CONTENTENCRYPTION', 0x1035); // [50][35] -- Settings describing the encryption used. Must be present if the value of ContentEncodingType is 1 and absent otherwise.
+define('EBML_ID_CUEREFNUMBER', 0x135F); // [53][5F] -- Number of the referenced Block of Track X in the specified Cluster.
+define('EBML_ID_NAME', 0x136E); // [53][6E] -- A human-readable track name.
+define('EBML_ID_CUEBLOCKNUMBER', 0x1378); // [53][78] -- Number of the Block in the specified Cluster.
+define('EBML_ID_TRACKOFFSET', 0x137F); // [53][7F] -- A value to add to the Block's Timecode. This can be used to adjust the playback offset of a track.
+define('EBML_ID_SEEKID', 0x13AB); // [53][AB] -- The binary ID corresponding to the element name.
+define('EBML_ID_SEEKPOSITION', 0x13AC); // [53][AC] -- The position of the element in the segment in octets (0 = first level 1 element).
+define('EBML_ID_STEREOMODE', 0x13B8); // [53][B8] -- Stereo-3D video mode.
+define('EBML_ID_OLDSTEREOMODE', 0x13B9); // [53][B9] -- Bogus StereoMode value used in old versions of libmatroska. DO NOT USE. (0: mono, 1: right eye, 2: left eye, 3: both eyes).
+define('EBML_ID_PIXELCROPBOTTOM', 0x14AA); // [54][AA] -- The number of video pixels to remove at the bottom of the image (for HDTV content).
+define('EBML_ID_DISPLAYWIDTH', 0x14B0); // [54][B0] -- Width of the video frames to display.
+define('EBML_ID_DISPLAYUNIT', 0x14B2); // [54][B2] -- Type of the unit for DisplayWidth/Height (0: pixels, 1: centimeters, 2: inches).
+define('EBML_ID_ASPECTRATIOTYPE', 0x14B3); // [54][B3] -- Specify the possible modifications to the aspect ratio (0: free resizing, 1: keep aspect ratio, 2: fixed).
+define('EBML_ID_DISPLAYHEIGHT', 0x14BA); // [54][BA] -- Height of the video frames to display.
+define('EBML_ID_PIXELCROPTOP', 0x14BB); // [54][BB] -- The number of video pixels to remove at the top of the image.
+define('EBML_ID_PIXELCROPLEFT', 0x14CC); // [54][CC] -- The number of video pixels to remove on the left of the image.
+define('EBML_ID_PIXELCROPRIGHT', 0x14DD); // [54][DD] -- The number of video pixels to remove on the right of the image.
+define('EBML_ID_FLAGFORCED', 0x15AA); // [55][AA] -- Set if that track MUST be used during playback. There can be many forced track for a kind (audio, video or subs), the player should select the one which language matches the user preference or the default + forced track. Overlay MAY happen between a forced and non-forced track of the same kind.
+define('EBML_ID_MAXBLOCKADDITIONID', 0x15EE); // [55][EE] -- The maximum value of BlockAddID. A value 0 means there is no BlockAdditions for this track.
+define('EBML_ID_WRITINGAPP', 0x1741); // [57][41] -- Writing application ("mkvmerge-0.3.3").
+define('EBML_ID_CLUSTERSILENTTRACKS', 0x1854); // [58][54] -- The list of tracks that are not used in that part of the stream. It is useful when using overlay tracks on seeking. Then you should decide what track to use.
+define('EBML_ID_CLUSTERSILENTTRACKNUMBER', 0x18D7); // [58][D7] -- One of the track number that are not used from now on in the stream. It could change later if not specified as silent in a further Cluster.
+define('EBML_ID_ATTACHEDFILE', 0x21A7); // [61][A7] -- An attached file.
+define('EBML_ID_CONTENTENCODING', 0x2240); // [62][40] -- Settings for one content encoding like compression or encryption.
+define('EBML_ID_BITDEPTH', 0x2264); // [62][64] -- Bits per sample, mostly used for PCM.
+define('EBML_ID_CODECPRIVATE', 0x23A2); // [63][A2] -- Private data only known to the codec.
+define('EBML_ID_TARGETS', 0x23C0); // [63][C0] -- Contain all UIDs where the specified meta data apply. It is void to describe everything in the segment.
+define('EBML_ID_CHAPTERPHYSICALEQUIV', 0x23C3); // [63][C3] -- Specify the physical equivalent of this ChapterAtom like "DVD" (60) or "SIDE" (50), see complete list of values.
+define('EBML_ID_TAGCHAPTERUID', 0x23C4); // [63][C4] -- A unique ID to identify the Chapter(s) the tags belong to. If the value is 0 at this level, the tags apply to all chapters in the Segment.
+define('EBML_ID_TAGTRACKUID', 0x23C5); // [63][C5] -- A unique ID to identify the Track(s) the tags belong to. If the value is 0 at this level, the tags apply to all tracks in the Segment.
+define('EBML_ID_TAGATTACHMENTUID', 0x23C6); // [63][C6] -- A unique ID to identify the Attachment(s) the tags belong to. If the value is 0 at this level, the tags apply to all the attachments in the Segment.
+define('EBML_ID_TAGEDITIONUID', 0x23C9); // [63][C9] -- A unique ID to identify the EditionEntry(s) the tags belong to. If the value is 0 at this level, the tags apply to all editions in the Segment.
+define('EBML_ID_TARGETTYPE', 0x23CA); // [63][CA] -- An informational string that can be used to display the logical level of the target like "ALBUM", "TRACK", "MOVIE", "CHAPTER", etc (see TargetType).
+define('EBML_ID_TRACKTRANSLATE', 0x2624); // [66][24] -- The track identification for the given Chapter Codec.
+define('EBML_ID_TRACKTRANSLATETRACKID', 0x26A5); // [66][A5] -- The binary value used to represent this track in the chapter codec data. The format depends on the ChapProcessCodecID used.
+define('EBML_ID_TRACKTRANSLATECODEC', 0x26BF); // [66][BF] -- The chapter codec using this ID (0: Matroska Script, 1: DVD-menu).
+define('EBML_ID_TRACKTRANSLATEEDITIONUID', 0x26FC); // [66][FC] -- Specify an edition UID on which this translation applies. When not specified, it means for all editions found in the segment.
+define('EBML_ID_SIMPLETAG', 0x27C8); // [67][C8] -- Contains general information about the target.
+define('EBML_ID_TARGETTYPEVALUE', 0x28CA); // [68][CA] -- A number to indicate the logical level of the target (see TargetType).
+define('EBML_ID_CHAPPROCESSCOMMAND', 0x2911); // [69][11] -- Contains all the commands associated to the Atom.
+define('EBML_ID_CHAPPROCESSTIME', 0x2922); // [69][22] -- Defines when the process command should be handled (0: during the whole chapter, 1: before starting playback, 2: after playback of the chapter).
+define('EBML_ID_CHAPTERTRANSLATE', 0x2924); // [69][24] -- A tuple of corresponding ID used by chapter codecs to represent this segment.
+define('EBML_ID_CHAPPROCESSDATA', 0x2933); // [69][33] -- Contains the command information. The data should be interpreted depending on the ChapProcessCodecID value. For ChapProcessCodecID = 1, the data correspond to the binary DVD cell pre/post commands.
+define('EBML_ID_CHAPPROCESS', 0x2944); // [69][44] -- Contains all the commands associated to the Atom.
+define('EBML_ID_CHAPPROCESSCODECID', 0x2955); // [69][55] -- Contains the type of the codec used for the processing. A value of 0 means native Matroska processing (to be defined), a value of 1 means the DVD command set is used. More codec IDs can be added later.
+define('EBML_ID_CHAPTERTRANSLATEID', 0x29A5); // [69][A5] -- The binary value used to represent this segment in the chapter codec data. The format depends on the ChapProcessCodecID used.
+define('EBML_ID_CHAPTERTRANSLATECODEC', 0x29BF); // [69][BF] -- The chapter codec using this ID (0: Matroska Script, 1: DVD-menu).
+define('EBML_ID_CHAPTERTRANSLATEEDITIONUID', 0x29FC); // [69][FC] -- Specify an edition UID on which this correspondance applies. When not specified, it means for all editions found in the segment.
+define('EBML_ID_CONTENTENCODINGS', 0x2D80); // [6D][80] -- Settings for several content encoding mechanisms like compression or encryption.
+define('EBML_ID_MINCACHE', 0x2DE7); // [6D][E7] -- The minimum number of frames a player should be able to cache during playback. If set to 0, the reference pseudo-cache system is not used.
+define('EBML_ID_MAXCACHE', 0x2DF8); // [6D][F8] -- The maximum cache size required to store referenced frames in and the current frame. 0 means no cache is needed.
+define('EBML_ID_CHAPTERSEGMENTUID', 0x2E67); // [6E][67] -- A segment to play in place of this chapter. Edition ChapterSegmentEditionUID should be used for this segment, otherwise no edition is used.
+define('EBML_ID_CHAPTERSEGMENTEDITIONUID', 0x2EBC); // [6E][BC] -- The edition to play from the segment linked in ChapterSegmentUID.
+define('EBML_ID_TRACKOVERLAY', 0x2FAB); // [6F][AB] -- Specify that this track is an overlay track for the Track specified (in the u-integer). That means when this track has a gap (see SilentTracks) the overlay track should be used instead. The order of multiple TrackOverlay matters, the first one is the one that should be used. If not found it should be the second, etc.
+define('EBML_ID_TAG', 0x3373); // [73][73] -- Element containing elements specific to Tracks/Chapters.
+define('EBML_ID_SEGMENTFILENAME', 0x3384); // [73][84] -- A filename corresponding to this segment.
+define('EBML_ID_SEGMENTUID', 0x33A4); // [73][A4] -- A randomly generated unique ID to identify the current segment between many others (128 bits).
+define('EBML_ID_CHAPTERUID', 0x33C4); // [73][C4] -- A unique ID to identify the Chapter.
+define('EBML_ID_TRACKUID', 0x33C5); // [73][C5] -- A unique ID to identify the Track. This should be kept the same when making a direct stream copy of the Track to another file.
+define('EBML_ID_ATTACHMENTLINK', 0x3446); // [74][46] -- The UID of an attachment that is used by this codec.
+define('EBML_ID_CLUSTERBLOCKADDITIONS', 0x35A1); // [75][A1] -- Contain additional blocks to complete the main one. An EBML parser that has no knowledge of the Block structure could still see and use/skip these data.
+define('EBML_ID_CHANNELPOSITIONS', 0x347B); // [7D][7B] -- Table of horizontal angles for each successive channel, see appendix.
+define('EBML_ID_OUTPUTSAMPLINGFREQUENCY', 0x38B5); // [78][B5] -- Real output sampling frequency in Hz (used for SBR techniques).
+define('EBML_ID_TITLE', 0x3BA9); // [7B][A9] -- General name of the segment.
+define('EBML_ID_CHAPTERDISPLAY', 0x00); // [80] -- Contains all possible strings to use for the chapter display.
+define('EBML_ID_TRACKTYPE', 0x03); // [83] -- A set of track types coded on 8 bits (1: video, 2: audio, 3: complex, 0x10: logo, 0x11: subtitle, 0x12: buttons, 0x20: control).
+define('EBML_ID_CHAPSTRING', 0x05); // [85] -- Contains the string to use as the chapter atom.
+define('EBML_ID_CODECID', 0x06); // [86] -- An ID corresponding to the codec, see the codec page for more info.
+define('EBML_ID_FLAGDEFAULT', 0x08); // [88] -- Set if that track (audio, video or subs) SHOULD be used if no language found matches the user preference.
+define('EBML_ID_CHAPTERTRACKNUMBER', 0x09); // [89] -- UID of the Track to apply this chapter too. In the absense of a control track, choosing this chapter will select the listed Tracks and deselect unlisted tracks. Absense of this element indicates that the Chapter should be applied to any currently used Tracks.
+define('EBML_ID_CLUSTERSLICES', 0x0E); // [8E] -- Contains slices description.
+define('EBML_ID_CHAPTERTRACK', 0x0F); // [8F] -- List of tracks on which the chapter applies. If this element is not present, all tracks apply
+define('EBML_ID_CHAPTERTIMESTART', 0x11); // [91] -- Timecode of the start of Chapter (not scaled).
+define('EBML_ID_CHAPTERTIMEEND', 0x12); // [92] -- Timecode of the end of Chapter (timecode excluded, not scaled).
+define('EBML_ID_CUEREFTIME', 0x16); // [96] -- Timecode of the referenced Block.
+define('EBML_ID_CUEREFCLUSTER', 0x17); // [97] -- Position of the Cluster containing the referenced Block.
+define('EBML_ID_CHAPTERFLAGHIDDEN', 0x18); // [98] -- If a chapter is hidden (1), it should not be available to the user interface (but still to Control Tracks).
+define('EBML_ID_FLAGINTERLACED', 0x1A); // [9A] -- Set if the video is interlaced.
+define('EBML_ID_CLUSTERBLOCKDURATION', 0x1B); // [9B] -- The duration of the Block (based on TimecodeScale). This element is mandatory when DefaultDuration is set for the track. When not written and with no DefaultDuration, the value is assumed to be the difference between the timecode of this Block and the timecode of the next Block in "display" order (not coding order). This element can be useful at the end of a Track (as there is not other Block available), or when there is a break in a track like for subtitle tracks.
+define('EBML_ID_FLAGLACING', 0x1C); // [9C] -- Set if the track may contain blocks using lacing.
+define('EBML_ID_CHANNELS', 0x1F); // [9F] -- Numbers of channels in the track.
+define('EBML_ID_CLUSTERBLOCKGROUP', 0x20); // [A0] -- Basic container of information containing a single Block or BlockVirtual, and information specific to that Block/VirtualBlock.
+define('EBML_ID_CLUSTERBLOCK', 0x21); // [A1] -- Block containing the actual data to be rendered and a timecode relative to the Cluster Timecode.
+define('EBML_ID_CLUSTERBLOCKVIRTUAL', 0x22); // [A2] -- A Block with no data. It must be stored in the stream at the place the real Block should be in display order.
+define('EBML_ID_CLUSTERSIMPLEBLOCK', 0x23); // [A3] -- Similar to Block but without all the extra information, mostly used to reduced overhead when no extra feature is needed.
+define('EBML_ID_CLUSTERCODECSTATE', 0x24); // [A4] -- The new codec state to use. Data interpretation is private to the codec. This information should always be referenced by a seek entry.
+define('EBML_ID_CLUSTERBLOCKADDITIONAL', 0x25); // [A5] -- Interpreted by the codec as it wishes (using the BlockAddID).
+define('EBML_ID_CLUSTERBLOCKMORE', 0x26); // [A6] -- Contain the BlockAdditional and some parameters.
+define('EBML_ID_CLUSTERPOSITION', 0x27); // [A7] -- Position of the Cluster in the segment (0 in live broadcast streams). It might help to resynchronise offset on damaged streams.
+define('EBML_ID_CODECDECODEALL', 0x2A); // [AA] -- The codec can decode potentially damaged data.
+define('EBML_ID_CLUSTERPREVSIZE', 0x2B); // [AB] -- Size of the previous Cluster, in octets. Can be useful for backward playing.
+define('EBML_ID_TRACKENTRY', 0x2E); // [AE] -- Describes a track with all elements.
+define('EBML_ID_CLUSTERENCRYPTEDBLOCK', 0x2F); // [AF] -- Similar to SimpleBlock but the data inside the Block are Transformed (encrypt and/or signed).
+define('EBML_ID_PIXELWIDTH', 0x30); // [B0] -- Width of the encoded video frames in pixels.
+define('EBML_ID_CUETIME', 0x33); // [B3] -- Absolute timecode according to the segment time base.
+define('EBML_ID_SAMPLINGFREQUENCY', 0x35); // [B5] -- Sampling frequency in Hz.
+define('EBML_ID_CHAPTERATOM', 0x36); // [B6] -- Contains the atom information to use as the chapter atom (apply to all tracks).
+define('EBML_ID_CUETRACKPOSITIONS', 0x37); // [B7] -- Contain positions for different tracks corresponding to the timecode.
+define('EBML_ID_FLAGENABLED', 0x39); // [B9] -- Set if the track is used.
+define('EBML_ID_PIXELHEIGHT', 0x3A); // [BA] -- Height of the encoded video frames in pixels.
+define('EBML_ID_CUEPOINT', 0x3B); // [BB] -- Contains all information relative to a seek point in the segment.
+define('EBML_ID_CRC32', 0x3F); // [BF] -- The CRC is computed on all the data of the Master element it's in, regardless of its position. It's recommended to put the CRC value at the beggining of the Master element for easier reading. All level 1 elements should include a CRC-32.
+define('EBML_ID_CLUSTERBLOCKADDITIONID', 0x4B); // [CB] -- The ID of the BlockAdditional element (0 is the main Block).
+define('EBML_ID_CLUSTERLACENUMBER', 0x4C); // [CC] -- The reverse number of the frame in the lace (0 is the last frame, 1 is the next to last, etc). While there are a few files in the wild with this element, it is no longer in use and has been deprecated. Being able to interpret this element is not required for playback.
+define('EBML_ID_CLUSTERFRAMENUMBER', 0x4D); // [CD] -- The number of the frame to generate from this lace with this delay (allow you to generate many frames from the same Block/Frame).
+define('EBML_ID_CLUSTERDELAY', 0x4E); // [CE] -- The (scaled) delay to apply to the element.
+define('EBML_ID_CLUSTERDURATION', 0x4F); // [CF] -- The (scaled) duration to apply to the element.
+define('EBML_ID_TRACKNUMBER', 0x57); // [D7] -- The track number as used in the Block Header (using more than 127 tracks is not encouraged, though the design allows an unlimited number).
+define('EBML_ID_CUEREFERENCE', 0x5B); // [DB] -- The Clusters containing the required referenced Blocks.
+define('EBML_ID_VIDEO', 0x60); // [E0] -- Video settings.
+define('EBML_ID_AUDIO', 0x61); // [E1] -- Audio settings.
+define('EBML_ID_CLUSTERTIMESLICE', 0x68); // [E8] -- Contains extra time information about the data contained in the Block. While there are a few files in the wild with this element, it is no longer in use and has been deprecated. Being able to interpret this element is not required for playback.
+define('EBML_ID_CUECODECSTATE', 0x6A); // [EA] -- The position of the Codec State corresponding to this Cue element. 0 means that the data is taken from the initial Track Entry.
+define('EBML_ID_CUEREFCODECSTATE', 0x6B); // [EB] -- The position of the Codec State corresponding to this referenced element. 0 means that the data is taken from the initial Track Entry.
+define('EBML_ID_VOID', 0x6C); // [EC] -- Used to void damaged data, to avoid unexpected behaviors when using damaged data. The content is discarded. Also used to reserve space in a sub-element for later use.
+define('EBML_ID_CLUSTERTIMECODE', 0x67); // [E7] -- Absolute timecode of the cluster (based on TimecodeScale).
+define('EBML_ID_CLUSTERBLOCKADDID', 0x6E); // [EE] -- An ID to identify the BlockAdditional level.
+define('EBML_ID_CUECLUSTERPOSITION', 0x71); // [F1] -- The position of the Cluster containing the required Block.
+define('EBML_ID_CUETRACK', 0x77); // [F7] -- The track for which a position is given.
+define('EBML_ID_CLUSTERREFERENCEPRIORITY', 0x7A); // [FA] -- This frame is referenced and has the specified cache priority. In cache only a frame of the same or higher priority can replace this frame. A value of 0 means the frame is not referenced.
+define('EBML_ID_CLUSTERREFERENCEBLOCK', 0x7B); // [FB] -- Timecode of another frame used as a reference (ie: B or P frame). The timecode is relative to the block it's attached to.
+define('EBML_ID_CLUSTERREFERENCEVIRTUAL', 0x7D); // [FD] -- Relative position of the data that should be in position of the virtual block.
+
+
+/**
+* @tutorial http://www.matroska.org/technical/specs/index.html
+*
+* @todo Rewrite EBML parser to reduce it's size and honor default element values
+* @todo After rewrite implement stream size calculation, that will provide additional useful info and enable AAC/FLAC audio bitrate detection
+*/
+class getid3_matroska extends getid3_handler
+{
+ // public options
+ public static $hide_clusters = true; // if true, do not return information about CLUSTER chunks, since there's a lot of them and they're not usually useful [default: TRUE]
+ public static $parse_whole_file = false; // true to parse the whole file, not only header [default: FALSE]
+
+ // private parser settings/placeholders
+ private $EBMLbuffer = '';
+ private $EBMLbuffer_offset = 0;
+ private $EBMLbuffer_length = 0;
+ private $current_offset = 0;
+ private $unuseful_elements = array(EBML_ID_CRC32, EBML_ID_VOID);
+
+ public function Analyze()
+ {
+ $info = &$this->getid3->info;
+
+ // parse container
+ try {
+ $this->parseEBML($info);
+ } catch (Exception $e) {
+ $info['error'][] = 'EBML parser: '.$e->getMessage();
+ }
+
+ // calculate playtime
+ if (isset($info['matroska']['info']) && is_array($info['matroska']['info'])) {
+ foreach ($info['matroska']['info'] as $key => $infoarray) {
+ if (isset($infoarray['Duration'])) {
+ // TimecodeScale is how many nanoseconds each Duration unit is
+ $info['playtime_seconds'] = $infoarray['Duration'] * ((isset($infoarray['TimecodeScale']) ? $infoarray['TimecodeScale'] : 1000000) / 1000000000);
+ break;
+ }
+ }
+ }
+
+ // extract tags
+ if (isset($info['matroska']['tags']) && is_array($info['matroska']['tags'])) {
+ foreach ($info['matroska']['tags'] as $key => $infoarray) {
+ $this->ExtractCommentsSimpleTag($infoarray);
+ }
+ }
+
+ // process tracks
+ if (isset($info['matroska']['tracks']['tracks']) && is_array($info['matroska']['tracks']['tracks'])) {
+ foreach ($info['matroska']['tracks']['tracks'] as $key => $trackarray) {
+
+ $track_info = array();
+ $track_info['dataformat'] = self::CodecIDtoCommonName($trackarray['CodecID']);
+ $track_info['default'] = (isset($trackarray['FlagDefault']) ? $trackarray['FlagDefault'] : true);
+ if (isset($trackarray['Name'])) { $track_info['name'] = $trackarray['Name']; }
+
+ switch ($trackarray['TrackType']) {
+
+ case 1: // Video
+ $track_info['resolution_x'] = $trackarray['PixelWidth'];
+ $track_info['resolution_y'] = $trackarray['PixelHeight'];
+ $track_info['display_unit'] = self::displayUnit(isset($trackarray['DisplayUnit']) ? $trackarray['DisplayUnit'] : 0);
+ $track_info['display_x'] = (isset($trackarray['DisplayWidth']) ? $trackarray['DisplayWidth'] : $trackarray['PixelWidth']);
+ $track_info['display_y'] = (isset($trackarray['DisplayHeight']) ? $trackarray['DisplayHeight'] : $trackarray['PixelHeight']);
+
+ if (isset($trackarray['PixelCropBottom'])) { $track_info['crop_bottom'] = $trackarray['PixelCropBottom']; }
+ if (isset($trackarray['PixelCropTop'])) { $track_info['crop_top'] = $trackarray['PixelCropTop']; }
+ if (isset($trackarray['PixelCropLeft'])) { $track_info['crop_left'] = $trackarray['PixelCropLeft']; }
+ if (isset($trackarray['PixelCropRight'])) { $track_info['crop_right'] = $trackarray['PixelCropRight']; }
+ if (isset($trackarray['DefaultDuration'])) { $track_info['frame_rate'] = round(1000000000 / $trackarray['DefaultDuration'], 3); }
+ if (isset($trackarray['CodecName'])) { $track_info['codec'] = $trackarray['CodecName']; }
+
+ switch ($trackarray['CodecID']) {
+ case 'V_MS/VFW/FOURCC':
+ if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, false)) {
+ $this->warning('Unable to parse codec private data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio-video.riff.php"');
+ break;
+ }
+ $parsed = getid3_riff::ParseBITMAPINFOHEADER($trackarray['CodecPrivate']);
+ $track_info['codec'] = getid3_riff::fourccLookup($parsed['fourcc']);
+ $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed;
+ break;
+
+ /*case 'V_MPEG4/ISO/AVC':
+ $h264['profile'] = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 1, 1));
+ $h264['level'] = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 3, 1));
+ $rn = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 4, 1));
+ $h264['NALUlength'] = ($rn & 3) + 1;
+ $rn = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 5, 1));
+ $nsps = ($rn & 31);
+ $offset = 6;
+ for ($i = 0; $i < $nsps; $i ++) {
+ $length = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], $offset, 2));
+ $h264['SPS'][] = substr($trackarray['CodecPrivate'], $offset + 2, $length);
+ $offset += 2 + $length;
+ }
+ $npps = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], $offset, 1));
+ $offset += 1;
+ for ($i = 0; $i < $npps; $i ++) {
+ $length = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], $offset, 2));
+ $h264['PPS'][] = substr($trackarray['CodecPrivate'], $offset + 2, $length);
+ $offset += 2 + $length;
+ }
+ $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $h264;
+ break;*/
+ }
+
+ $info['video']['streams'][] = $track_info;
+ break;
+
+ case 2: // Audio
+ $track_info['sample_rate'] = (isset($trackarray['SamplingFrequency']) ? $trackarray['SamplingFrequency'] : 8000.0);
+ $track_info['channels'] = (isset($trackarray['Channels']) ? $trackarray['Channels'] : 1);
+ $track_info['language'] = (isset($trackarray['Language']) ? $trackarray['Language'] : 'eng');
+ if (isset($trackarray['BitDepth'])) { $track_info['bits_per_sample'] = $trackarray['BitDepth']; }
+ if (isset($trackarray['CodecName'])) { $track_info['codec'] = $trackarray['CodecName']; }
+
+ switch ($trackarray['CodecID']) {
+ case 'A_PCM/INT/LIT':
+ case 'A_PCM/INT/BIG':
+ $track_info['bitrate'] = $trackarray['SamplingFrequency'] * $trackarray['Channels'] * $trackarray['BitDepth'];
+ break;
+
+ case 'A_AC3':
+ case 'A_DTS':
+ case 'A_MPEG/L3':
+ case 'A_MPEG/L2':
+ case 'A_FLAC':
+ if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']).'.php', __FILE__, false)) {
+ $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio.'.$track_info['dataformat'].'.php"');
+ break;
+ }
+
+ if (!isset($info['matroska']['track_data_offsets'][$trackarray['TrackNumber']])) {
+ $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because $info[matroska][track_data_offsets]['.$trackarray['TrackNumber'].'] not set');
+ break;
+ }
+
+ // create temp instance
+ $getid3_temp = new getID3();
+ if ($track_info['dataformat'] != 'flac') {
+ $getid3_temp->openfile($this->getid3->filename);
+ }
+ $getid3_temp->info['avdataoffset'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'];
+ if ($track_info['dataformat'][0] == 'm' || $track_info['dataformat'] == 'flac') {
+ $getid3_temp->info['avdataend'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'] + $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['length'];
+ }
+
+ // analyze
+ $class = 'getid3_'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']);
+ $header_data_key = $track_info['dataformat'][0] == 'm' ? 'mpeg' : $track_info['dataformat'];
+ $getid3_audio = new $class($getid3_temp, __CLASS__);
+ if ($track_info['dataformat'] == 'flac') {
+ $getid3_audio->AnalyzeString($trackarray['CodecPrivate']);
+ }
+ else {
+ $getid3_audio->Analyze();
+ }
+ if (!empty($getid3_temp->info[$header_data_key])) {
+ $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info[$header_data_key];
+ if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
+ foreach ($getid3_temp->info['audio'] as $key => $value) {
+ $track_info[$key] = $value;
+ }
+ }
+ }
+ else {
+ $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because '.$class.'::Analyze() failed at offset '.$getid3_temp->info['avdataoffset']);
+ }
+
+ // copy errors and warnings
+ if (!empty($getid3_temp->info['error'])) {
+ foreach ($getid3_temp->info['error'] as $newerror) {
+ $this->warning($class.'() says: ['.$newerror.']');
+ }
+ }
+ if (!empty($getid3_temp->info['warning'])) {
+ foreach ($getid3_temp->info['warning'] as $newerror) {
+ if ($track_info['dataformat'] == 'mp3' && preg_match('/^Probable truncated file: expecting \d+ bytes of audio data, only found \d+ \(short by \d+ bytes\)$/', $newerror)) {
+ // LAME/Xing header is probably set, but audio data is chunked into Matroska file and near-impossible to verify if audio stream is complete, so ignore useless warning
+ continue;
+ }
+ $this->warning($class.'() says: ['.$newerror.']');
+ }
+ }
+ unset($getid3_temp, $getid3_audio);
+ break;
+
+ case 'A_AAC':
+ case 'A_AAC/MPEG2/LC':
+ case 'A_AAC/MPEG2/LC/SBR':
+ case 'A_AAC/MPEG4/LC':
+ case 'A_AAC/MPEG4/LC/SBR':
+ $this->warning($trackarray['CodecID'].' audio data contains no header, audio/video bitrates can\'t be calculated');
+ break;
+
+ case 'A_VORBIS':
+ if (!isset($trackarray['CodecPrivate'])) {
+ $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because CodecPrivate data not set');
+ break;
+ }
+ $vorbis_offset = strpos($trackarray['CodecPrivate'], 'vorbis', 1);
+ if ($vorbis_offset === false) {
+ $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because CodecPrivate data does not contain "vorbis" keyword');
+ break;
+ }
+ $vorbis_offset -= 1;
+
+ if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ogg.php', __FILE__, false)) {
+ $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio.ogg.php"');
+ break;
+ }
+
+ // create temp instance
+ $getid3_temp = new getID3();
+
+ // analyze
+ $getid3_ogg = new getid3_ogg($getid3_temp);
+ $oggpageinfo['page_seqno'] = 0;
+ $getid3_ogg->ParseVorbisPageHeader($trackarray['CodecPrivate'], $vorbis_offset, $oggpageinfo);
+ if (!empty($getid3_temp->info['ogg'])) {
+ $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ogg'];
+ if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
+ foreach ($getid3_temp->info['audio'] as $key => $value) {
+ $track_info[$key] = $value;
+ }
+ }
+ }
+
+ // copy errors and warnings
+ if (!empty($getid3_temp->info['error'])) {
+ foreach ($getid3_temp->info['error'] as $newerror) {
+ $this->warning('getid3_ogg() says: ['.$newerror.']');
+ }
+ }
+ if (!empty($getid3_temp->info['warning'])) {
+ foreach ($getid3_temp->info['warning'] as $newerror) {
+ $this->warning('getid3_ogg() says: ['.$newerror.']');
+ }
+ }
+
+ if (!empty($getid3_temp->info['ogg']['bitrate_nominal'])) {
+ $track_info['bitrate'] = $getid3_temp->info['ogg']['bitrate_nominal'];
+ }
+ unset($getid3_temp, $getid3_ogg, $oggpageinfo, $vorbis_offset);
+ break;
+
+ case 'A_MS/ACM':
+ if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, false)) {
+ $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio-video.riff.php"');
+ break;
+ }
+
+ $parsed = getid3_riff::parseWAVEFORMATex($trackarray['CodecPrivate']);
+ foreach ($parsed as $key => $value) {
+ if ($key != 'raw') {
+ $track_info[$key] = $value;
+ }
+ }
+ $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed;
+ break;
+
+ default:
+ $this->warning('Unhandled audio type "'.(isset($trackarray['CodecID']) ? $trackarray['CodecID'] : '').'"');
+ }
+
+ $info['audio']['streams'][] = $track_info;
+ break;
+ }
+ }
+
+ if (!empty($info['video']['streams'])) {
+ $info['video'] = self::getDefaultStreamInfo($info['video']['streams']);
+ }
+ if (!empty($info['audio']['streams'])) {
+ $info['audio'] = self::getDefaultStreamInfo($info['audio']['streams']);
+ }
+ }
+
+ // process attachments
+ if (isset($info['matroska']['attachments']) && $this->getid3->option_save_attachments !== getID3::ATTACHMENTS_NONE) {
+ foreach ($info['matroska']['attachments'] as $i => $entry) {
+ if (strpos($entry['FileMimeType'], 'image/') === 0 && !empty($entry['FileData'])) {
+ $info['matroska']['comments']['picture'][] = array('data' => $entry['FileData'], 'image_mime' => $entry['FileMimeType'], 'filename' => $entry['FileName']);
+ }
+ }
+ }
+
+ // determine mime type
+ if (!empty($info['video']['streams'])) {
+ $info['mime_type'] = ($info['matroska']['doctype'] == 'webm' ? 'video/webm' : 'video/x-matroska');
+ } elseif (!empty($info['audio']['streams'])) {
+ $info['mime_type'] = ($info['matroska']['doctype'] == 'webm' ? 'audio/webm' : 'audio/x-matroska');
+ } elseif (isset($info['mime_type'])) {
+ unset($info['mime_type']);
+ }
+
+ return true;
+ }
+
+ private function parseEBML(&$info) {
+ // http://www.matroska.org/technical/specs/index.html#EBMLBasics
+ $this->current_offset = $info['avdataoffset'];
+
+ while ($this->getEBMLelement($top_element, $info['avdataend'])) {
+ switch ($top_element['id']) {
+
+ case EBML_ID_EBML:
+ $info['fileformat'] = 'matroska';
+ $info['matroska']['header']['offset'] = $top_element['offset'];
+ $info['matroska']['header']['length'] = $top_element['length'];
+
+ while ($this->getEBMLelement($element_data, $top_element['end'], true)) {
+ switch ($element_data['id']) {
+
+ case EBML_ID_EBMLVERSION:
+ case EBML_ID_EBMLREADVERSION:
+ case EBML_ID_EBMLMAXIDLENGTH:
+ case EBML_ID_EBMLMAXSIZELENGTH:
+ case EBML_ID_DOCTYPEVERSION:
+ case EBML_ID_DOCTYPEREADVERSION:
+ $element_data['data'] = getid3_lib::BigEndian2Int($element_data['data']);
+ break;
+
+ case EBML_ID_DOCTYPE:
+ $element_data['data'] = getid3_lib::trimNullByte($element_data['data']);
+ $info['matroska']['doctype'] = $element_data['data'];
+ break;
+
+ case EBML_ID_CRC32: // not useful, ignore
+ $this->current_offset = $element_data['end'];
+ unset($element_data);
+ break;
+
+ default:
+ $this->unhandledElement('header', __LINE__, $element_data);
+ }
+ if (!empty($element_data)) {
+ unset($element_data['offset'], $element_data['end']);
+ $info['matroska']['header']['elements'][] = $element_data;
+ }
+ }
+ break;
+
+ case EBML_ID_SEGMENT:
+ $info['matroska']['segment'][0]['offset'] = $top_element['offset'];
+ $info['matroska']['segment'][0]['length'] = $top_element['length'];
+
+ while ($this->getEBMLelement($element_data, $top_element['end'])) {
+ if ($element_data['id'] != EBML_ID_CLUSTER || !self::$hide_clusters) { // collect clusters only if required
+ $info['matroska']['segments'][] = $element_data;
+ }
+ switch ($element_data['id']) {
+
+ case EBML_ID_SEEKHEAD: // Contains the position of other level 1 elements.
+
+ while ($this->getEBMLelement($seek_entry, $element_data['end'])) {
+ switch ($seek_entry['id']) {
+
+ case EBML_ID_SEEK: // Contains a single seek entry to an EBML element
+ while ($this->getEBMLelement($sub_seek_entry, $seek_entry['end'], true)) {
+
+ switch ($sub_seek_entry['id']) {
+
+ case EBML_ID_SEEKID:
+ $seek_entry['target_id'] = self::EBML2Int($sub_seek_entry['data']);
+ $seek_entry['target_name'] = self::EBMLidName($seek_entry['target_id']);
+ break;
+
+ case EBML_ID_SEEKPOSITION:
+ $seek_entry['target_offset'] = $element_data['offset'] + getid3_lib::BigEndian2Int($sub_seek_entry['data']);
+ break;
+
+ default:
+ $this->unhandledElement('seekhead.seek', __LINE__, $sub_seek_entry); }
+ }
+
+ if ($seek_entry['target_id'] != EBML_ID_CLUSTER || !self::$hide_clusters) { // collect clusters only if required
+ $info['matroska']['seek'][] = $seek_entry;
+ }
+ break;
+
+ default:
+ $this->unhandledElement('seekhead', __LINE__, $seek_entry);
+ }
+ }
+ break;
+
+ case EBML_ID_TRACKS: // A top-level block of information with many tracks described.
+ $info['matroska']['tracks'] = $element_data;
+
+ while ($this->getEBMLelement($track_entry, $element_data['end'])) {
+ switch ($track_entry['id']) {
+
+ case EBML_ID_TRACKENTRY: //subelements: Describes a track with all elements.
+
+ while ($this->getEBMLelement($subelement, $track_entry['end'], array(EBML_ID_VIDEO, EBML_ID_AUDIO, EBML_ID_CONTENTENCODINGS, EBML_ID_CODECPRIVATE))) {
+ switch ($subelement['id']) {
+
+ case EBML_ID_TRACKNUMBER:
+ case EBML_ID_TRACKUID:
+ case EBML_ID_TRACKTYPE:
+ case EBML_ID_MINCACHE:
+ case EBML_ID_MAXCACHE:
+ case EBML_ID_MAXBLOCKADDITIONID:
+ case EBML_ID_DEFAULTDURATION: // nanoseconds per frame
+ $track_entry[$subelement['id_name']] = getid3_lib::BigEndian2Int($subelement['data']);
+ break;
+
+ case EBML_ID_TRACKTIMECODESCALE:
+ $track_entry[$subelement['id_name']] = getid3_lib::BigEndian2Float($subelement['data']);
+ break;
+
+ case EBML_ID_CODECID:
+ case EBML_ID_LANGUAGE:
+ case EBML_ID_NAME:
+ case EBML_ID_CODECNAME:
+ $track_entry[$subelement['id_name']] = getid3_lib::trimNullByte($subelement['data']);
+ break;
+
+ case EBML_ID_CODECPRIVATE:
+ $track_entry[$subelement['id_name']] = $this->readEBMLelementData($subelement['length'], true);
+ break;
+
+ case EBML_ID_FLAGENABLED:
+ case EBML_ID_FLAGDEFAULT:
+ case EBML_ID_FLAGFORCED:
+ case EBML_ID_FLAGLACING:
+ case EBML_ID_CODECDECODEALL:
+ $track_entry[$subelement['id_name']] = (bool) getid3_lib::BigEndian2Int($subelement['data']);
+ break;
+
+ case EBML_ID_VIDEO:
+
+ while ($this->getEBMLelement($sub_subelement, $subelement['end'], true)) {
+ switch ($sub_subelement['id']) {
+
+ case EBML_ID_PIXELWIDTH:
+ case EBML_ID_PIXELHEIGHT:
+ case EBML_ID_PIXELCROPBOTTOM:
+ case EBML_ID_PIXELCROPTOP:
+ case EBML_ID_PIXELCROPLEFT:
+ case EBML_ID_PIXELCROPRIGHT:
+ case EBML_ID_DISPLAYWIDTH:
+ case EBML_ID_DISPLAYHEIGHT:
+ case EBML_ID_DISPLAYUNIT:
+ case EBML_ID_ASPECTRATIOTYPE:
+ case EBML_ID_STEREOMODE:
+ case EBML_ID_OLDSTEREOMODE:
+ $track_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_subelement['data']);
+ break;
+
+ case EBML_ID_FLAGINTERLACED:
+ $track_entry[$sub_subelement['id_name']] = (bool)getid3_lib::BigEndian2Int($sub_subelement['data']);
+ break;
+
+ case EBML_ID_GAMMAVALUE:
+ $track_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Float($sub_subelement['data']);
+ break;
+
+ case EBML_ID_COLOURSPACE:
+ $track_entry[$sub_subelement['id_name']] = getid3_lib::trimNullByte($sub_subelement['data']);
+ break;
+
+ default:
+ $this->unhandledElement('track.video', __LINE__, $sub_subelement);
+ }
+ }
+ break;
+
+ case EBML_ID_AUDIO:
+
+ while ($this->getEBMLelement($sub_subelement, $subelement['end'], true)) {
+ switch ($sub_subelement['id']) {
+
+ case EBML_ID_CHANNELS:
+ case EBML_ID_BITDEPTH:
+ $track_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_subelement['data']);
+ break;
+
+ case EBML_ID_SAMPLINGFREQUENCY:
+ case EBML_ID_OUTPUTSAMPLINGFREQUENCY:
+ $track_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Float($sub_subelement['data']);
+ break;
+
+ case EBML_ID_CHANNELPOSITIONS:
+ $track_entry[$sub_subelement['id_name']] = getid3_lib::trimNullByte($sub_subelement['data']);
+ break;
+
+ default:
+ $this->unhandledElement('track.audio', __LINE__, $sub_subelement);
+ }
+ }
+ break;
+
+ case EBML_ID_CONTENTENCODINGS:
+
+ while ($this->getEBMLelement($sub_subelement, $subelement['end'])) {
+ switch ($sub_subelement['id']) {
+
+ case EBML_ID_CONTENTENCODING:
+
+ while ($this->getEBMLelement($sub_sub_subelement, $sub_subelement['end'], array(EBML_ID_CONTENTCOMPRESSION, EBML_ID_CONTENTENCRYPTION))) {
+ switch ($sub_sub_subelement['id']) {
+
+ case EBML_ID_CONTENTENCODINGORDER:
+ case EBML_ID_CONTENTENCODINGSCOPE:
+ case EBML_ID_CONTENTENCODINGTYPE:
+ $track_entry[$sub_subelement['id_name']][$sub_sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_sub_subelement['data']);
+ break;
+
+ case EBML_ID_CONTENTCOMPRESSION:
+
+ while ($this->getEBMLelement($sub_sub_sub_subelement, $sub_sub_subelement['end'], true)) {
+ switch ($sub_sub_sub_subelement['id']) {
+
+ case EBML_ID_CONTENTCOMPALGO:
+ $track_entry[$sub_subelement['id_name']][$sub_sub_subelement['id_name']][$sub_sub_sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_sub_sub_subelement['data']);
+ break;
+
+ case EBML_ID_CONTENTCOMPSETTINGS:
+ $track_entry[$sub_subelement['id_name']][$sub_sub_subelement['id_name']][$sub_sub_sub_subelement['id_name']] = $sub_sub_sub_subelement['data'];
+ break;
+
+ default:
+ $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
+ }
+ }
+ break;
+
+ case EBML_ID_CONTENTENCRYPTION:
+
+ while ($this->getEBMLelement($sub_sub_sub_subelement, $sub_sub_subelement['end'], true)) {
+ switch ($sub_sub_sub_subelement['id']) {
+
+ case EBML_ID_CONTENTENCALGO:
+ case EBML_ID_CONTENTSIGALGO:
+ case EBML_ID_CONTENTSIGHASHALGO:
+ $track_entry[$sub_subelement['id_name']][$sub_sub_subelement['id_name']][$sub_sub_sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_sub_sub_subelement['data']);
+ break;
+
+ case EBML_ID_CONTENTENCKEYID:
+ case EBML_ID_CONTENTSIGNATURE:
+ case EBML_ID_CONTENTSIGKEYID:
+ $track_entry[$sub_subelement['id_name']][$sub_sub_subelement['id_name']][$sub_sub_sub_subelement['id_name']] = $sub_sub_sub_subelement['data'];
+ break;
+
+ default:
+ $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
+ }
+ }
+ break;
+
+ default:
+ $this->unhandledElement('track.contentencodings.contentencoding', __LINE__, $sub_sub_subelement);
+ }
+ }
+ break;
+
+ default:
+ $this->unhandledElement('track.contentencodings', __LINE__, $sub_subelement);
+ }
+ }
+ break;
+
+ default:
+ $this->unhandledElement('track', __LINE__, $subelement);
+ }
+ }
+
+ $info['matroska']['tracks']['tracks'][] = $track_entry;
+ break;
+
+ default:
+ $this->unhandledElement('tracks', __LINE__, $track_entry);
+ }
+ }
+ break;
+
+ case EBML_ID_INFO: // Contains miscellaneous general information and statistics on the file.
+ $info_entry = array();
+
+ while ($this->getEBMLelement($subelement, $element_data['end'], true)) {
+ switch ($subelement['id']) {
+
+ case EBML_ID_TIMECODESCALE:
+ $info_entry[$subelement['id_name']] = getid3_lib::BigEndian2Int($subelement['data']);
+ break;
+
+ case EBML_ID_DURATION:
+ $info_entry[$subelement['id_name']] = getid3_lib::BigEndian2Float($subelement['data']);
+ break;
+
+ case EBML_ID_DATEUTC:
+ $info_entry[$subelement['id_name']] = getid3_lib::BigEndian2Int($subelement['data']);
+ $info_entry[$subelement['id_name'].'_unix'] = self::EBMLdate2unix($info_entry[$subelement['id_name']]);
+ break;
+
+ case EBML_ID_SEGMENTUID:
+ case EBML_ID_PREVUID:
+ case EBML_ID_NEXTUID:
+ $info_entry[$subelement['id_name']] = getid3_lib::trimNullByte($subelement['data']);
+ break;
+
+ case EBML_ID_SEGMENTFAMILY:
+ $info_entry[$subelement['id_name']][] = getid3_lib::trimNullByte($subelement['data']);
+ break;
+
+ case EBML_ID_SEGMENTFILENAME:
+ case EBML_ID_PREVFILENAME:
+ case EBML_ID_NEXTFILENAME:
+ case EBML_ID_TITLE:
+ case EBML_ID_MUXINGAPP:
+ case EBML_ID_WRITINGAPP:
+ $info_entry[$subelement['id_name']] = getid3_lib::trimNullByte($subelement['data']);
+ $info['matroska']['comments'][strtolower($subelement['id_name'])][] = $info_entry[$subelement['id_name']];
+ break;
+
+ case EBML_ID_CHAPTERTRANSLATE:
+ $chaptertranslate_entry = array();
+
+ while ($this->getEBMLelement($sub_subelement, $subelement['end'], true)) {
+ switch ($sub_subelement['id']) {
+
+ case EBML_ID_CHAPTERTRANSLATEEDITIONUID:
+ $chaptertranslate_entry[$sub_subelement['id_name']][] = getid3_lib::BigEndian2Int($sub_subelement['data']);
+ break;
+
+ case EBML_ID_CHAPTERTRANSLATECODEC:
+ $chaptertranslate_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_subelement['data']);
+ break;
+
+ case EBML_ID_CHAPTERTRANSLATEID:
+ $chaptertranslate_entry[$sub_subelement['id_name']] = getid3_lib::trimNullByte($sub_subelement['data']);
+ break;
+
+ default:
+ $this->unhandledElement('info.chaptertranslate', __LINE__, $sub_subelement);
+ }
+ }
+ $info_entry[$subelement['id_name']] = $chaptertranslate_entry;
+ break;
+
+ default:
+ $this->unhandledElement('info', __LINE__, $subelement);
+ }
+ }
+ $info['matroska']['info'][] = $info_entry;
+ break;
+
+ case EBML_ID_CUES: // A top-level element to speed seeking access. All entries are local to the segment. Should be mandatory for non "live" streams.
+ if (self::$hide_clusters) { // do not parse cues if hide clusters is "ON" till they point to clusters anyway
+ $this->current_offset = $element_data['end'];
+ break;
+ }
+ $cues_entry = array();
+
+ while ($this->getEBMLelement($subelement, $element_data['end'])) {
+ switch ($subelement['id']) {
+
+ case EBML_ID_CUEPOINT:
+ $cuepoint_entry = array();
+
+ while ($this->getEBMLelement($sub_subelement, $subelement['end'], array(EBML_ID_CUETRACKPOSITIONS))) {
+ switch ($sub_subelement['id']) {
+
+ case EBML_ID_CUETRACKPOSITIONS:
+ $cuetrackpositions_entry = array();
+
+ while ($this->getEBMLelement($sub_sub_subelement, $sub_subelement['end'], true)) {
+ switch ($sub_sub_subelement['id']) {
+
+ case EBML_ID_CUETRACK:
+ case EBML_ID_CUECLUSTERPOSITION:
+ case EBML_ID_CUEBLOCKNUMBER:
+ case EBML_ID_CUECODECSTATE:
+ $cuetrackpositions_entry[$sub_sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_sub_subelement['data']);
+ break;
+
+ default:
+ $this->unhandledElement('cues.cuepoint.cuetrackpositions', __LINE__, $sub_sub_subelement);
+ }
+ }
+ $cuepoint_entry[$sub_subelement['id_name']][] = $cuetrackpositions_entry;
+ break;
+
+ case EBML_ID_CUETIME:
+ $cuepoint_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_subelement['data']);
+ break;
+
+ default:
+ $this->unhandledElement('cues.cuepoint', __LINE__, $sub_subelement);
+ }
+ }
+ $cues_entry[] = $cuepoint_entry;
+ break;
+
+ default:
+ $this->unhandledElement('cues', __LINE__, $subelement);
+ }
+ }
+ $info['matroska']['cues'] = $cues_entry;
+ break;
+
+ case EBML_ID_TAGS: // Element containing elements specific to Tracks/Chapters.
+ $tags_entry = array();
+
+ while ($this->getEBMLelement($subelement, $element_data['end'], false)) {
+ switch ($subelement['id']) {
+
+ case EBML_ID_TAG:
+ $tag_entry = array();
+
+ while ($this->getEBMLelement($sub_subelement, $subelement['end'], false)) {
+ switch ($sub_subelement['id']) {
+
+ case EBML_ID_TARGETS:
+ $targets_entry = array();
+
+ while ($this->getEBMLelement($sub_sub_subelement, $sub_subelement['end'], true)) {
+ switch ($sub_sub_subelement['id']) {
+
+ case EBML_ID_TARGETTYPEVALUE:
+ $targets_entry[$sub_sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_sub_subelement['data']);
+ $targets_entry[strtolower($sub_sub_subelement['id_name']).'_long'] = self::TargetTypeValue($targets_entry[$sub_sub_subelement['id_name']]);
+ break;
+
+ case EBML_ID_TARGETTYPE:
+ $targets_entry[$sub_sub_subelement['id_name']] = $sub_sub_subelement['data'];
+ break;
+
+ case EBML_ID_TAGTRACKUID:
+ case EBML_ID_TAGEDITIONUID:
+ case EBML_ID_TAGCHAPTERUID:
+ case EBML_ID_TAGATTACHMENTUID:
+ $targets_entry[$sub_sub_subelement['id_name']][] = getid3_lib::BigEndian2Int($sub_sub_subelement['data']);
+ break;
+
+ default:
+ $this->unhandledElement('tags.tag.targets', __LINE__, $sub_sub_subelement);
+ }
+ }
+ $tag_entry[$sub_subelement['id_name']] = $targets_entry;
+ break;
+
+ case EBML_ID_SIMPLETAG:
+ $tag_entry[$sub_subelement['id_name']][] = $this->HandleEMBLSimpleTag($sub_subelement['end']);
+ break;
+
+ default:
+ $this->unhandledElement('tags.tag', __LINE__, $sub_subelement);
+ }
+ }
+ $tags_entry[] = $tag_entry;
+ break;
+
+ default:
+ $this->unhandledElement('tags', __LINE__, $subelement);
+ }
+ }
+ $info['matroska']['tags'] = $tags_entry;
+ break;
+
+ case EBML_ID_ATTACHMENTS: // Contain attached files.
+
+ while ($this->getEBMLelement($subelement, $element_data['end'])) {
+ switch ($subelement['id']) {
+
+ case EBML_ID_ATTACHEDFILE:
+ $attachedfile_entry = array();
+
+ while ($this->getEBMLelement($sub_subelement, $subelement['end'], array(EBML_ID_FILEDATA))) {
+ switch ($sub_subelement['id']) {
+
+ case EBML_ID_FILEDESCRIPTION:
+ case EBML_ID_FILENAME:
+ case EBML_ID_FILEMIMETYPE:
+ $attachedfile_entry[$sub_subelement['id_name']] = $sub_subelement['data'];
+ break;
+
+ case EBML_ID_FILEDATA:
+ $attachedfile_entry['data_offset'] = $this->current_offset;
+ $attachedfile_entry['data_length'] = $sub_subelement['length'];
+
+ $attachedfile_entry[$sub_subelement['id_name']] = $this->saveAttachment(
+ $attachedfile_entry['FileName'],
+ $attachedfile_entry['data_offset'],
+ $attachedfile_entry['data_length']);
+
+ $this->current_offset = $sub_subelement['end'];
+ break;
+
+ case EBML_ID_FILEUID:
+ $attachedfile_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_subelement['data']);
+ break;
+
+ default:
+ $this->unhandledElement('attachments.attachedfile', __LINE__, $sub_subelement);
+ }
+ }
+ $info['matroska']['attachments'][] = $attachedfile_entry;
+ break;
+
+ default:
+ $this->unhandledElement('attachments', __LINE__, $subelement);
+ }
+ }
+ break;
+
+ case EBML_ID_CHAPTERS:
+
+ while ($this->getEBMLelement($subelement, $element_data['end'])) {
+ switch ($subelement['id']) {
+
+ case EBML_ID_EDITIONENTRY:
+ $editionentry_entry = array();
+
+ while ($this->getEBMLelement($sub_subelement, $subelement['end'], array(EBML_ID_CHAPTERATOM))) {
+ switch ($sub_subelement['id']) {
+
+ case EBML_ID_EDITIONUID:
+ $editionentry_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_subelement['data']);
+ break;
+
+ case EBML_ID_EDITIONFLAGHIDDEN:
+ case EBML_ID_EDITIONFLAGDEFAULT:
+ case EBML_ID_EDITIONFLAGORDERED:
+ $editionentry_entry[$sub_subelement['id_name']] = (bool)getid3_lib::BigEndian2Int($sub_subelement['data']);
+ break;
+
+ case EBML_ID_CHAPTERATOM:
+ $chapteratom_entry = array();
+
+ while ($this->getEBMLelement($sub_sub_subelement, $sub_subelement['end'], array(EBML_ID_CHAPTERTRACK, EBML_ID_CHAPTERDISPLAY))) {
+ switch ($sub_sub_subelement['id']) {
+
+ case EBML_ID_CHAPTERSEGMENTUID:
+ case EBML_ID_CHAPTERSEGMENTEDITIONUID:
+ $chapteratom_entry[$sub_sub_subelement['id_name']] = $sub_sub_subelement['data'];
+ break;
+
+ case EBML_ID_CHAPTERFLAGENABLED:
+ case EBML_ID_CHAPTERFLAGHIDDEN:
+ $chapteratom_entry[$sub_sub_subelement['id_name']] = (bool)getid3_lib::BigEndian2Int($sub_sub_subelement['data']);
+ break;
+
+ case EBML_ID_CHAPTERUID:
+ case EBML_ID_CHAPTERTIMESTART:
+ case EBML_ID_CHAPTERTIMEEND:
+ $chapteratom_entry[$sub_sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_sub_subelement['data']);
+ break;
+
+ case EBML_ID_CHAPTERTRACK:
+ $chaptertrack_entry = array();
+
+ while ($this->getEBMLelement($sub_sub_sub_subelement, $sub_sub_subelement['end'], true)) {
+ switch ($sub_sub_sub_subelement['id']) {
+
+ case EBML_ID_CHAPTERTRACKNUMBER:
+ $chaptertrack_entry[$sub_sub_sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_sub_sub_subelement['data']);
+ break;
+
+ default:
+ $this->unhandledElement('chapters.editionentry.chapteratom.chaptertrack', __LINE__, $sub_sub_sub_subelement);
+ }
+ }
+ $chapteratom_entry[$sub_sub_subelement['id_name']][] = $chaptertrack_entry;
+ break;
+
+ case EBML_ID_CHAPTERDISPLAY:
+ $chapterdisplay_entry = array();
+
+ while ($this->getEBMLelement($sub_sub_sub_subelement, $sub_sub_subelement['end'], true)) {
+ switch ($sub_sub_sub_subelement['id']) {
+
+ case EBML_ID_CHAPSTRING:
+ case EBML_ID_CHAPLANGUAGE:
+ case EBML_ID_CHAPCOUNTRY:
+ $chapterdisplay_entry[$sub_sub_sub_subelement['id_name']] = $sub_sub_sub_subelement['data'];
+ break;
+
+ default:
+ $this->unhandledElement('chapters.editionentry.chapteratom.chapterdisplay', __LINE__, $sub_sub_sub_subelement);
+ }
+ }
+ $chapteratom_entry[$sub_sub_subelement['id_name']][] = $chapterdisplay_entry;
+ break;
+
+ default:
+ $this->unhandledElement('chapters.editionentry.chapteratom', __LINE__, $sub_sub_subelement);
+ }
+ }
+ $editionentry_entry[$sub_subelement['id_name']][] = $chapteratom_entry;
+ break;
+
+ default:
+ $this->unhandledElement('chapters.editionentry', __LINE__, $sub_subelement);
+ }
+ }
+ $info['matroska']['chapters'][] = $editionentry_entry;
+ break;
+
+ default:
+ $this->unhandledElement('chapters', __LINE__, $subelement);
+ }
+ }
+ break;
+
+ case EBML_ID_CLUSTER: // The lower level element containing the (monolithic) Block structure.
+ $cluster_entry = array();
+
+ while ($this->getEBMLelement($subelement, $element_data['end'], array(EBML_ID_CLUSTERSILENTTRACKS, EBML_ID_CLUSTERBLOCKGROUP, EBML_ID_CLUSTERSIMPLEBLOCK))) {
+ switch ($subelement['id']) {
+
+ case EBML_ID_CLUSTERTIMECODE:
+ case EBML_ID_CLUSTERPOSITION:
+ case EBML_ID_CLUSTERPREVSIZE:
+ $cluster_entry[$subelement['id_name']] = getid3_lib::BigEndian2Int($subelement['data']);
+ break;
+
+ case EBML_ID_CLUSTERSILENTTRACKS:
+ $cluster_silent_tracks = array();
+
+ while ($this->getEBMLelement($sub_subelement, $subelement['end'], true)) {
+ switch ($sub_subelement['id']) {
+
+ case EBML_ID_CLUSTERSILENTTRACKNUMBER:
+ $cluster_silent_tracks[] = getid3_lib::BigEndian2Int($sub_subelement['data']);
+ break;
+
+ default:
+ $this->unhandledElement('cluster.silenttracks', __LINE__, $sub_subelement);
+ }
+ }
+ $cluster_entry[$subelement['id_name']][] = $cluster_silent_tracks;
+ break;
+
+ case EBML_ID_CLUSTERBLOCKGROUP:
+ $cluster_block_group = array('offset' => $this->current_offset);
+
+ while ($this->getEBMLelement($sub_subelement, $subelement['end'], array(EBML_ID_CLUSTERBLOCK))) {
+ switch ($sub_subelement['id']) {
+
+ case EBML_ID_CLUSTERBLOCK:
+ $cluster_block_group[$sub_subelement['id_name']] = $this->HandleEMBLClusterBlock($sub_subelement, EBML_ID_CLUSTERBLOCK, $info);
+ break;
+
+ case EBML_ID_CLUSTERREFERENCEPRIORITY: // unsigned-int
+ case EBML_ID_CLUSTERBLOCKDURATION: // unsigned-int
+ $cluster_block_group[$sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_subelement['data']);
+ break;
+
+ case EBML_ID_CLUSTERREFERENCEBLOCK: // signed-int
+ $cluster_block_group[$sub_subelement['id_name']][] = getid3_lib::BigEndian2Int($sub_subelement['data'], false, true);
+ break;
+
+ case EBML_ID_CLUSTERCODECSTATE:
+ $cluster_block_group[$sub_subelement['id_name']] = getid3_lib::trimNullByte($sub_subelement['data']);
+ break;
+
+ default:
+ $this->unhandledElement('clusters.blockgroup', __LINE__, $sub_subelement);
+ }
+ }
+ $cluster_entry[$subelement['id_name']][] = $cluster_block_group;
+ break;
+
+ case EBML_ID_CLUSTERSIMPLEBLOCK:
+ $cluster_entry[$subelement['id_name']][] = $this->HandleEMBLClusterBlock($subelement, EBML_ID_CLUSTERSIMPLEBLOCK, $info);
+ break;
+
+ default:
+ $this->unhandledElement('cluster', __LINE__, $subelement);
+ }
+ $this->current_offset = $subelement['end'];
+ }
+ if (!self::$hide_clusters) {
+ $info['matroska']['cluster'][] = $cluster_entry;
+ }
+
+ // check to see if all the data we need exists already, if so, break out of the loop
+ if (!self::$parse_whole_file) {
+ if (isset($info['matroska']['info']) && is_array($info['matroska']['info'])) {
+ if (isset($info['matroska']['tracks']['tracks']) && is_array($info['matroska']['tracks']['tracks'])) {
+ if (count($info['matroska']['track_data_offsets']) == count($info['matroska']['tracks']['tracks'])) {
+ return;
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ $this->unhandledElement('segment', __LINE__, $element_data);
+ }
+ }
+ break;
+
+ default:
+ $this->unhandledElement('root', __LINE__, $top_element);
+ }
+ }
+ }
+
+ private function EnsureBufferHasEnoughData($min_data=1024) {
+ if (($this->current_offset - $this->EBMLbuffer_offset) >= ($this->EBMLbuffer_length - $min_data)) {
+ $read_bytes = max($min_data, $this->getid3->fread_buffer_size());
+
+ try {
+ $this->fseek($this->current_offset);
+ $this->EBMLbuffer_offset = $this->current_offset;
+ $this->EBMLbuffer = $this->fread($read_bytes);
+ $this->EBMLbuffer_length = strlen($this->EBMLbuffer);
+ } catch (getid3_exception $e) {
+ $this->warning('EBML parser: '.$e->getMessage());
+ return false;
+ }
+
+ if ($this->EBMLbuffer_length == 0 && $this->feof()) {
+ return $this->error('EBML parser: ran out of file at offset '.$this->current_offset);
+ }
+ }
+ return true;
+ }
+
+ private function readEBMLint() {
+ $actual_offset = $this->current_offset - $this->EBMLbuffer_offset;
+
+ // get length of integer
+ $first_byte_int = ord($this->EBMLbuffer[$actual_offset]);
+ if (0x80 & $first_byte_int) {
+ $length = 1;
+ } elseif (0x40 & $first_byte_int) {
+ $length = 2;
+ } elseif (0x20 & $first_byte_int) {
+ $length = 3;
+ } elseif (0x10 & $first_byte_int) {
+ $length = 4;
+ } elseif (0x08 & $first_byte_int) {
+ $length = 5;
+ } elseif (0x04 & $first_byte_int) {
+ $length = 6;
+ } elseif (0x02 & $first_byte_int) {
+ $length = 7;
+ } elseif (0x01 & $first_byte_int) {
+ $length = 8;
+ } else {
+ throw new Exception('invalid EBML integer (leading 0x00) at '.$this->current_offset);
+ }
+
+ // read
+ $int_value = self::EBML2Int(substr($this->EBMLbuffer, $actual_offset, $length));
+ $this->current_offset += $length;
+
+ return $int_value;
+ }
+
+ private function readEBMLelementData($length, $check_buffer=false) {
+ if ($check_buffer && !$this->EnsureBufferHasEnoughData($length)) {
+ return false;
+ }
+ $data = substr($this->EBMLbuffer, $this->current_offset - $this->EBMLbuffer_offset, $length);
+ $this->current_offset += $length;
+ return $data;
+ }
+
+ private function getEBMLelement(&$element, $parent_end, $get_data=false) {
+ if ($this->current_offset >= $parent_end) {
+ return false;
+ }
+
+ if (!$this->EnsureBufferHasEnoughData()) {
+ $this->current_offset = PHP_INT_MAX; // do not exit parser right now, allow to finish current loop to gather maximum information
+ return false;
+ }
+
+ $element = array();
+
+ // set offset
+ $element['offset'] = $this->current_offset;
+
+ // get ID
+ $element['id'] = $this->readEBMLint();
+
+ // get name
+ $element['id_name'] = self::EBMLidName($element['id']);
+
+ // get length
+ $element['length'] = $this->readEBMLint();
+
+ // get end offset
+ $element['end'] = $this->current_offset + $element['length'];
+
+ // get raw data
+ $dont_parse = (in_array($element['id'], $this->unuseful_elements) || $element['id_name'] == dechex($element['id']));
+ if (($get_data === true || (is_array($get_data) && !in_array($element['id'], $get_data))) && !$dont_parse) {
+ $element['data'] = $this->readEBMLelementData($element['length'], $element);
+ }
+
+ return true;
+ }
+
+ private function unhandledElement($type, $line, $element) {
+ // warn only about unknown and missed elements, not about unuseful
+ if (!in_array($element['id'], $this->unuseful_elements)) {
+ $this->warning('Unhandled '.$type.' element ['.basename(__FILE__).':'.$line.'] ('.$element['id'].'::'.$element['id_name'].' ['.$element['length'].' bytes]) at '.$element['offset']);
+ }
+
+ // increase offset for unparsed elements
+ if (!isset($element['data'])) {
+ $this->current_offset = $element['end'];
+ }
+ }
+
+ private function ExtractCommentsSimpleTag($SimpleTagArray) {
+ if (!empty($SimpleTagArray['SimpleTag'])) {
+ foreach ($SimpleTagArray['SimpleTag'] as $SimpleTagKey => $SimpleTagData) {
+ if (!empty($SimpleTagData['TagName']) && !empty($SimpleTagData['TagString'])) {
+ $this->getid3->info['matroska']['comments'][strtolower($SimpleTagData['TagName'])][] = $SimpleTagData['TagString'];
+ }
+ if (!empty($SimpleTagData['SimpleTag'])) {
+ $this->ExtractCommentsSimpleTag($SimpleTagData);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private function HandleEMBLSimpleTag($parent_end) {
+ $simpletag_entry = array();
+
+ while ($this->getEBMLelement($element, $parent_end, array(EBML_ID_SIMPLETAG))) {
+ switch ($element['id']) {
+
+ case EBML_ID_TAGNAME:
+ case EBML_ID_TAGLANGUAGE:
+ case EBML_ID_TAGSTRING:
+ case EBML_ID_TAGBINARY:
+ $simpletag_entry[$element['id_name']] = $element['data'];
+ break;
+
+ case EBML_ID_SIMPLETAG:
+ $simpletag_entry[$element['id_name']][] = $this->HandleEMBLSimpleTag($element['end']);
+ break;
+
+ case EBML_ID_TAGDEFAULT:
+ $simpletag_entry[$element['id_name']] = (bool)getid3_lib::BigEndian2Int($element['data']);
+ break;
+
+ default:
+ $this->unhandledElement('tag.simpletag', __LINE__, $element);
+ }
+ }
+
+ return $simpletag_entry;
+ }
+
+ private function HandleEMBLClusterBlock($element, $block_type, &$info) {
+ // http://www.matroska.org/technical/specs/index.html#block_structure
+ // http://www.matroska.org/technical/specs/index.html#simpleblock_structure
+
+ $block_data = array();
+ $block_data['tracknumber'] = $this->readEBMLint();
+ $block_data['timecode'] = getid3_lib::BigEndian2Int($this->readEBMLelementData(2), false, true);
+ $block_data['flags_raw'] = getid3_lib::BigEndian2Int($this->readEBMLelementData(1));
+
+ if ($block_type == EBML_ID_CLUSTERSIMPLEBLOCK) {
+ $block_data['flags']['keyframe'] = (($block_data['flags_raw'] & 0x80) >> 7);
+ //$block_data['flags']['reserved1'] = (($block_data['flags_raw'] & 0x70) >> 4);
+ }
+ else {
+ //$block_data['flags']['reserved1'] = (($block_data['flags_raw'] & 0xF0) >> 4);
+ }
+ $block_data['flags']['invisible'] = (bool)(($block_data['flags_raw'] & 0x08) >> 3);
+ $block_data['flags']['lacing'] = (($block_data['flags_raw'] & 0x06) >> 1); // 00=no lacing; 01=Xiph lacing; 11=EBML lacing; 10=fixed-size lacing
+ if ($block_type == EBML_ID_CLUSTERSIMPLEBLOCK) {
+ $block_data['flags']['discardable'] = (($block_data['flags_raw'] & 0x01));
+ }
+ else {
+ //$block_data['flags']['reserved2'] = (($block_data['flags_raw'] & 0x01) >> 0);
+ }
+ $block_data['flags']['lacing_type'] = self::BlockLacingType($block_data['flags']['lacing']);
+
+ // Lace (when lacing bit is set)
+ if ($block_data['flags']['lacing'] > 0) {
+ $block_data['lace_frames'] = getid3_lib::BigEndian2Int($this->readEBMLelementData(1)) + 1; // Number of frames in the lace-1 (uint8)
+ if ($block_data['flags']['lacing'] != 0x02) {
+ for ($i = 1; $i < $block_data['lace_frames']; $i ++) { // Lace-coded size of each frame of the lace, except for the last one (multiple uint8). *This is not used with Fixed-size lacing as it is calculated automatically from (total size of lace) / (number of frames in lace).
+ if ($block_data['flags']['lacing'] == 0x03) { // EBML lacing
+ $block_data['lace_frames_size'][$i] = $this->readEBMLint(); // TODO: read size correctly, calc size for the last frame. For now offsets are deteminded OK with readEBMLint() and that's the most important thing.
+ }
+ else { // Xiph lacing
+ $block_data['lace_frames_size'][$i] = 0;
+ do {
+ $size = getid3_lib::BigEndian2Int($this->readEBMLelementData(1));
+ $block_data['lace_frames_size'][$i] += $size;
+ }
+ while ($size == 255);
+ }
+ }
+ if ($block_data['flags']['lacing'] == 0x01) { // calc size of the last frame only for Xiph lacing, till EBML sizes are now anyway determined incorrectly
+ $block_data['lace_frames_size'][] = $element['end'] - $this->current_offset - array_sum($block_data['lace_frames_size']);
+ }
+ }
+ }
+
+ if (!isset($info['matroska']['track_data_offsets'][$block_data['tracknumber']])) {
+ $info['matroska']['track_data_offsets'][$block_data['tracknumber']]['offset'] = $this->current_offset;
+ $info['matroska']['track_data_offsets'][$block_data['tracknumber']]['length'] = $element['end'] - $this->current_offset;
+ //$info['matroska']['track_data_offsets'][$block_data['tracknumber']]['total_length'] = 0;
+ }
+ //$info['matroska']['track_data_offsets'][$block_data['tracknumber']]['total_length'] += $info['matroska']['track_data_offsets'][$block_data['tracknumber']]['length'];
+ //$info['matroska']['track_data_offsets'][$block_data['tracknumber']]['duration'] = $block_data['timecode'] * ((isset($info['matroska']['info'][0]['TimecodeScale']) ? $info['matroska']['info'][0]['TimecodeScale'] : 1000000) / 1000000000);
+
+ // set offset manually
+ $this->current_offset = $element['end'];
+
+ return $block_data;
+ }
+
+ private static function EBML2Int($EBMLstring) {
+ // http://matroska.org/specs/
+
+ // Element ID coded with an UTF-8 like system:
+ // 1xxx xxxx - Class A IDs (2^7 -2 possible values) (base 0x8X)
+ // 01xx xxxx xxxx xxxx - Class B IDs (2^14-2 possible values) (base 0x4X 0xXX)
+ // 001x xxxx xxxx xxxx xxxx xxxx - Class C IDs (2^21-2 possible values) (base 0x2X 0xXX 0xXX)
+ // 0001 xxxx xxxx xxxx xxxx xxxx xxxx xxxx - Class D IDs (2^28-2 possible values) (base 0x1X 0xXX 0xXX 0xXX)
+ // Values with all x at 0 and 1 are reserved (hence the -2).
+
+ // Data size, in octets, is also coded with an UTF-8 like system :
+ // 1xxx xxxx - value 0 to 2^7-2
+ // 01xx xxxx xxxx xxxx - value 0 to 2^14-2
+ // 001x xxxx xxxx xxxx xxxx xxxx - value 0 to 2^21-2
+ // 0001 xxxx xxxx xxxx xxxx xxxx xxxx xxxx - value 0 to 2^28-2
+ // 0000 1xxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx - value 0 to 2^35-2
+ // 0000 01xx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx - value 0 to 2^42-2
+ // 0000 001x xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx - value 0 to 2^49-2
+ // 0000 0001 xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx - value 0 to 2^56-2
+
+ $first_byte_int = ord($EBMLstring[0]);
+ if (0x80 & $first_byte_int) {
+ $EBMLstring[0] = chr($first_byte_int & 0x7F);
+ } elseif (0x40 & $first_byte_int) {
+ $EBMLstring[0] = chr($first_byte_int & 0x3F);
+ } elseif (0x20 & $first_byte_int) {
+ $EBMLstring[0] = chr($first_byte_int & 0x1F);
+ } elseif (0x10 & $first_byte_int) {
+ $EBMLstring[0] = chr($first_byte_int & 0x0F);
+ } elseif (0x08 & $first_byte_int) {
+ $EBMLstring[0] = chr($first_byte_int & 0x07);
+ } elseif (0x04 & $first_byte_int) {
+ $EBMLstring[0] = chr($first_byte_int & 0x03);
+ } elseif (0x02 & $first_byte_int) {
+ $EBMLstring[0] = chr($first_byte_int & 0x01);
+ } elseif (0x01 & $first_byte_int) {
+ $EBMLstring[0] = chr($first_byte_int & 0x00);
+ }
+
+ return getid3_lib::BigEndian2Int($EBMLstring);
+ }
+
+ private static function EBMLdate2unix($EBMLdatestamp) {
+ // Date - signed 8 octets integer in nanoseconds with 0 indicating the precise beginning of the millennium (at 2001-01-01T00:00:00,000000000 UTC)
+ // 978307200 == mktime(0, 0, 0, 1, 1, 2001) == January 1, 2001 12:00:00am UTC
+ return round(($EBMLdatestamp / 1000000000) + 978307200);
+ }
+
+ public static function TargetTypeValue($target_type) {
+ // http://www.matroska.org/technical/specs/tagging/index.html
+ static $TargetTypeValue = array();
+ if (empty($TargetTypeValue)) {
+ $TargetTypeValue[10] = 'A: ~ V:shot'; // the lowest hierarchy found in music or movies
+ $TargetTypeValue[20] = 'A:subtrack/part/movement ~ V:scene'; // corresponds to parts of a track for audio (like a movement)
+ $TargetTypeValue[30] = 'A:track/song ~ V:chapter'; // the common parts of an album or a movie
+ $TargetTypeValue[40] = 'A:part/session ~ V:part/session'; // when an album or episode has different logical parts
+ $TargetTypeValue[50] = 'A:album/opera/concert ~ V:movie/episode/concert'; // the most common grouping level of music and video (equals to an episode for TV series)
+ $TargetTypeValue[60] = 'A:edition/issue/volume/opus ~ V:season/sequel/volume'; // a list of lower levels grouped together
+ $TargetTypeValue[70] = 'A:collection ~ V:collection'; // the high hierarchy consisting of many different lower items
+ }
+ return (isset($TargetTypeValue[$target_type]) ? $TargetTypeValue[$target_type] : $target_type);
+ }
+
+ public static function BlockLacingType($lacingtype) {
+ // http://matroska.org/technical/specs/index.html#block_structure
+ static $BlockLacingType = array();
+ if (empty($BlockLacingType)) {
+ $BlockLacingType[0x00] = 'no lacing';
+ $BlockLacingType[0x01] = 'Xiph lacing';
+ $BlockLacingType[0x02] = 'fixed-size lacing';
+ $BlockLacingType[0x03] = 'EBML lacing';
+ }
+ return (isset($BlockLacingType[$lacingtype]) ? $BlockLacingType[$lacingtype] : $lacingtype);
+ }
+
+ public static function CodecIDtoCommonName($codecid) {
+ // http://www.matroska.org/technical/specs/codecid/index.html
+ static $CodecIDlist = array();
+ if (empty($CodecIDlist)) {
+ $CodecIDlist['A_AAC'] = 'aac';
+ $CodecIDlist['A_AAC/MPEG2/LC'] = 'aac';
+ $CodecIDlist['A_AC3'] = 'ac3';
+ $CodecIDlist['A_DTS'] = 'dts';
+ $CodecIDlist['A_FLAC'] = 'flac';
+ $CodecIDlist['A_MPEG/L1'] = 'mp1';
+ $CodecIDlist['A_MPEG/L2'] = 'mp2';
+ $CodecIDlist['A_MPEG/L3'] = 'mp3';
+ $CodecIDlist['A_PCM/INT/LIT'] = 'pcm'; // PCM Integer Little Endian
+ $CodecIDlist['A_PCM/INT/BIG'] = 'pcm'; // PCM Integer Big Endian
+ $CodecIDlist['A_QUICKTIME/QDMC'] = 'quicktime'; // Quicktime: QDesign Music
+ $CodecIDlist['A_QUICKTIME/QDM2'] = 'quicktime'; // Quicktime: QDesign Music v2
+ $CodecIDlist['A_VORBIS'] = 'vorbis';
+ $CodecIDlist['V_MPEG1'] = 'mpeg';
+ $CodecIDlist['V_THEORA'] = 'theora';
+ $CodecIDlist['V_REAL/RV40'] = 'real';
+ $CodecIDlist['V_REAL/RV10'] = 'real';
+ $CodecIDlist['V_REAL/RV20'] = 'real';
+ $CodecIDlist['V_REAL/RV30'] = 'real';
+ $CodecIDlist['V_QUICKTIME'] = 'quicktime'; // Quicktime
+ $CodecIDlist['V_MPEG4/ISO/AP'] = 'mpeg4';
+ $CodecIDlist['V_MPEG4/ISO/ASP'] = 'mpeg4';
+ $CodecIDlist['V_MPEG4/ISO/AVC'] = 'h264';
+ $CodecIDlist['V_MPEG4/ISO/SP'] = 'mpeg4';
+ $CodecIDlist['V_VP8'] = 'vp8';
+ $CodecIDlist['V_MS/VFW/FOURCC'] = 'riff';
+ $CodecIDlist['A_MS/ACM'] = 'riff';
+ }
+ return (isset($CodecIDlist[$codecid]) ? $CodecIDlist[$codecid] : $codecid);
+ }
+
+ private static function EBMLidName($value) {
+ static $EBMLidList = array();
+ if (empty($EBMLidList)) {
+ $EBMLidList[EBML_ID_ASPECTRATIOTYPE] = 'AspectRatioType';
+ $EBMLidList[EBML_ID_ATTACHEDFILE] = 'AttachedFile';
+ $EBMLidList[EBML_ID_ATTACHMENTLINK] = 'AttachmentLink';
+ $EBMLidList[EBML_ID_ATTACHMENTS] = 'Attachments';
+ $EBMLidList[EBML_ID_AUDIO] = 'Audio';
+ $EBMLidList[EBML_ID_BITDEPTH] = 'BitDepth';
+ $EBMLidList[EBML_ID_CHANNELPOSITIONS] = 'ChannelPositions';
+ $EBMLidList[EBML_ID_CHANNELS] = 'Channels';
+ $EBMLidList[EBML_ID_CHAPCOUNTRY] = 'ChapCountry';
+ $EBMLidList[EBML_ID_CHAPLANGUAGE] = 'ChapLanguage';
+ $EBMLidList[EBML_ID_CHAPPROCESS] = 'ChapProcess';
+ $EBMLidList[EBML_ID_CHAPPROCESSCODECID] = 'ChapProcessCodecID';
+ $EBMLidList[EBML_ID_CHAPPROCESSCOMMAND] = 'ChapProcessCommand';
+ $EBMLidList[EBML_ID_CHAPPROCESSDATA] = 'ChapProcessData';
+ $EBMLidList[EBML_ID_CHAPPROCESSPRIVATE] = 'ChapProcessPrivate';
+ $EBMLidList[EBML_ID_CHAPPROCESSTIME] = 'ChapProcessTime';
+ $EBMLidList[EBML_ID_CHAPSTRING] = 'ChapString';
+ $EBMLidList[EBML_ID_CHAPTERATOM] = 'ChapterAtom';
+ $EBMLidList[EBML_ID_CHAPTERDISPLAY] = 'ChapterDisplay';
+ $EBMLidList[EBML_ID_CHAPTERFLAGENABLED] = 'ChapterFlagEnabled';
+ $EBMLidList[EBML_ID_CHAPTERFLAGHIDDEN] = 'ChapterFlagHidden';
+ $EBMLidList[EBML_ID_CHAPTERPHYSICALEQUIV] = 'ChapterPhysicalEquiv';
+ $EBMLidList[EBML_ID_CHAPTERS] = 'Chapters';
+ $EBMLidList[EBML_ID_CHAPTERSEGMENTEDITIONUID] = 'ChapterSegmentEditionUID';
+ $EBMLidList[EBML_ID_CHAPTERSEGMENTUID] = 'ChapterSegmentUID';
+ $EBMLidList[EBML_ID_CHAPTERTIMEEND] = 'ChapterTimeEnd';
+ $EBMLidList[EBML_ID_CHAPTERTIMESTART] = 'ChapterTimeStart';
+ $EBMLidList[EBML_ID_CHAPTERTRACK] = 'ChapterTrack';
+ $EBMLidList[EBML_ID_CHAPTERTRACKNUMBER] = 'ChapterTrackNumber';
+ $EBMLidList[EBML_ID_CHAPTERTRANSLATE] = 'ChapterTranslate';
+ $EBMLidList[EBML_ID_CHAPTERTRANSLATECODEC] = 'ChapterTranslateCodec';
+ $EBMLidList[EBML_ID_CHAPTERTRANSLATEEDITIONUID] = 'ChapterTranslateEditionUID';
+ $EBMLidList[EBML_ID_CHAPTERTRANSLATEID] = 'ChapterTranslateID';
+ $EBMLidList[EBML_ID_CHAPTERUID] = 'ChapterUID';
+ $EBMLidList[EBML_ID_CLUSTER] = 'Cluster';
+ $EBMLidList[EBML_ID_CLUSTERBLOCK] = 'ClusterBlock';
+ $EBMLidList[EBML_ID_CLUSTERBLOCKADDID] = 'ClusterBlockAddID';
+ $EBMLidList[EBML_ID_CLUSTERBLOCKADDITIONAL] = 'ClusterBlockAdditional';
+ $EBMLidList[EBML_ID_CLUSTERBLOCKADDITIONID] = 'ClusterBlockAdditionID';
+ $EBMLidList[EBML_ID_CLUSTERBLOCKADDITIONS] = 'ClusterBlockAdditions';
+ $EBMLidList[EBML_ID_CLUSTERBLOCKDURATION] = 'ClusterBlockDuration';
+ $EBMLidList[EBML_ID_CLUSTERBLOCKGROUP] = 'ClusterBlockGroup';
+ $EBMLidList[EBML_ID_CLUSTERBLOCKMORE] = 'ClusterBlockMore';
+ $EBMLidList[EBML_ID_CLUSTERBLOCKVIRTUAL] = 'ClusterBlockVirtual';
+ $EBMLidList[EBML_ID_CLUSTERCODECSTATE] = 'ClusterCodecState';
+ $EBMLidList[EBML_ID_CLUSTERDELAY] = 'ClusterDelay';
+ $EBMLidList[EBML_ID_CLUSTERDURATION] = 'ClusterDuration';
+ $EBMLidList[EBML_ID_CLUSTERENCRYPTEDBLOCK] = 'ClusterEncryptedBlock';
+ $EBMLidList[EBML_ID_CLUSTERFRAMENUMBER] = 'ClusterFrameNumber';
+ $EBMLidList[EBML_ID_CLUSTERLACENUMBER] = 'ClusterLaceNumber';
+ $EBMLidList[EBML_ID_CLUSTERPOSITION] = 'ClusterPosition';
+ $EBMLidList[EBML_ID_CLUSTERPREVSIZE] = 'ClusterPrevSize';
+ $EBMLidList[EBML_ID_CLUSTERREFERENCEBLOCK] = 'ClusterReferenceBlock';
+ $EBMLidList[EBML_ID_CLUSTERREFERENCEPRIORITY] = 'ClusterReferencePriority';
+ $EBMLidList[EBML_ID_CLUSTERREFERENCEVIRTUAL] = 'ClusterReferenceVirtual';
+ $EBMLidList[EBML_ID_CLUSTERSILENTTRACKNUMBER] = 'ClusterSilentTrackNumber';
+ $EBMLidList[EBML_ID_CLUSTERSILENTTRACKS] = 'ClusterSilentTracks';
+ $EBMLidList[EBML_ID_CLUSTERSIMPLEBLOCK] = 'ClusterSimpleBlock';
+ $EBMLidList[EBML_ID_CLUSTERTIMECODE] = 'ClusterTimecode';
+ $EBMLidList[EBML_ID_CLUSTERTIMESLICE] = 'ClusterTimeSlice';
+ $EBMLidList[EBML_ID_CODECDECODEALL] = 'CodecDecodeAll';
+ $EBMLidList[EBML_ID_CODECDOWNLOADURL] = 'CodecDownloadURL';
+ $EBMLidList[EBML_ID_CODECID] = 'CodecID';
+ $EBMLidList[EBML_ID_CODECINFOURL] = 'CodecInfoURL';
+ $EBMLidList[EBML_ID_CODECNAME] = 'CodecName';
+ $EBMLidList[EBML_ID_CODECPRIVATE] = 'CodecPrivate';
+ $EBMLidList[EBML_ID_CODECSETTINGS] = 'CodecSettings';
+ $EBMLidList[EBML_ID_COLOURSPACE] = 'ColourSpace';
+ $EBMLidList[EBML_ID_CONTENTCOMPALGO] = 'ContentCompAlgo';
+ $EBMLidList[EBML_ID_CONTENTCOMPRESSION] = 'ContentCompression';
+ $EBMLidList[EBML_ID_CONTENTCOMPSETTINGS] = 'ContentCompSettings';
+ $EBMLidList[EBML_ID_CONTENTENCALGO] = 'ContentEncAlgo';
+ $EBMLidList[EBML_ID_CONTENTENCKEYID] = 'ContentEncKeyID';
+ $EBMLidList[EBML_ID_CONTENTENCODING] = 'ContentEncoding';
+ $EBMLidList[EBML_ID_CONTENTENCODINGORDER] = 'ContentEncodingOrder';
+ $EBMLidList[EBML_ID_CONTENTENCODINGS] = 'ContentEncodings';
+ $EBMLidList[EBML_ID_CONTENTENCODINGSCOPE] = 'ContentEncodingScope';
+ $EBMLidList[EBML_ID_CONTENTENCODINGTYPE] = 'ContentEncodingType';
+ $EBMLidList[EBML_ID_CONTENTENCRYPTION] = 'ContentEncryption';
+ $EBMLidList[EBML_ID_CONTENTSIGALGO] = 'ContentSigAlgo';
+ $EBMLidList[EBML_ID_CONTENTSIGHASHALGO] = 'ContentSigHashAlgo';
+ $EBMLidList[EBML_ID_CONTENTSIGKEYID] = 'ContentSigKeyID';
+ $EBMLidList[EBML_ID_CONTENTSIGNATURE] = 'ContentSignature';
+ $EBMLidList[EBML_ID_CRC32] = 'CRC32';
+ $EBMLidList[EBML_ID_CUEBLOCKNUMBER] = 'CueBlockNumber';
+ $EBMLidList[EBML_ID_CUECLUSTERPOSITION] = 'CueClusterPosition';
+ $EBMLidList[EBML_ID_CUECODECSTATE] = 'CueCodecState';
+ $EBMLidList[EBML_ID_CUEPOINT] = 'CuePoint';
+ $EBMLidList[EBML_ID_CUEREFCLUSTER] = 'CueRefCluster';
+ $EBMLidList[EBML_ID_CUEREFCODECSTATE] = 'CueRefCodecState';
+ $EBMLidList[EBML_ID_CUEREFERENCE] = 'CueReference';
+ $EBMLidList[EBML_ID_CUEREFNUMBER] = 'CueRefNumber';
+ $EBMLidList[EBML_ID_CUEREFTIME] = 'CueRefTime';
+ $EBMLidList[EBML_ID_CUES] = 'Cues';
+ $EBMLidList[EBML_ID_CUETIME] = 'CueTime';
+ $EBMLidList[EBML_ID_CUETRACK] = 'CueTrack';
+ $EBMLidList[EBML_ID_CUETRACKPOSITIONS] = 'CueTrackPositions';
+ $EBMLidList[EBML_ID_DATEUTC] = 'DateUTC';
+ $EBMLidList[EBML_ID_DEFAULTDURATION] = 'DefaultDuration';
+ $EBMLidList[EBML_ID_DISPLAYHEIGHT] = 'DisplayHeight';
+ $EBMLidList[EBML_ID_DISPLAYUNIT] = 'DisplayUnit';
+ $EBMLidList[EBML_ID_DISPLAYWIDTH] = 'DisplayWidth';
+ $EBMLidList[EBML_ID_DOCTYPE] = 'DocType';
+ $EBMLidList[EBML_ID_DOCTYPEREADVERSION] = 'DocTypeReadVersion';
+ $EBMLidList[EBML_ID_DOCTYPEVERSION] = 'DocTypeVersion';
+ $EBMLidList[EBML_ID_DURATION] = 'Duration';
+ $EBMLidList[EBML_ID_EBML] = 'EBML';
+ $EBMLidList[EBML_ID_EBMLMAXIDLENGTH] = 'EBMLMaxIDLength';
+ $EBMLidList[EBML_ID_EBMLMAXSIZELENGTH] = 'EBMLMaxSizeLength';
+ $EBMLidList[EBML_ID_EBMLREADVERSION] = 'EBMLReadVersion';
+ $EBMLidList[EBML_ID_EBMLVERSION] = 'EBMLVersion';
+ $EBMLidList[EBML_ID_EDITIONENTRY] = 'EditionEntry';
+ $EBMLidList[EBML_ID_EDITIONFLAGDEFAULT] = 'EditionFlagDefault';
+ $EBMLidList[EBML_ID_EDITIONFLAGHIDDEN] = 'EditionFlagHidden';
+ $EBMLidList[EBML_ID_EDITIONFLAGORDERED] = 'EditionFlagOrdered';
+ $EBMLidList[EBML_ID_EDITIONUID] = 'EditionUID';
+ $EBMLidList[EBML_ID_FILEDATA] = 'FileData';
+ $EBMLidList[EBML_ID_FILEDESCRIPTION] = 'FileDescription';
+ $EBMLidList[EBML_ID_FILEMIMETYPE] = 'FileMimeType';
+ $EBMLidList[EBML_ID_FILENAME] = 'FileName';
+ $EBMLidList[EBML_ID_FILEREFERRAL] = 'FileReferral';
+ $EBMLidList[EBML_ID_FILEUID] = 'FileUID';
+ $EBMLidList[EBML_ID_FLAGDEFAULT] = 'FlagDefault';
+ $EBMLidList[EBML_ID_FLAGENABLED] = 'FlagEnabled';
+ $EBMLidList[EBML_ID_FLAGFORCED] = 'FlagForced';
+ $EBMLidList[EBML_ID_FLAGINTERLACED] = 'FlagInterlaced';
+ $EBMLidList[EBML_ID_FLAGLACING] = 'FlagLacing';
+ $EBMLidList[EBML_ID_GAMMAVALUE] = 'GammaValue';
+ $EBMLidList[EBML_ID_INFO] = 'Info';
+ $EBMLidList[EBML_ID_LANGUAGE] = 'Language';
+ $EBMLidList[EBML_ID_MAXBLOCKADDITIONID] = 'MaxBlockAdditionID';
+ $EBMLidList[EBML_ID_MAXCACHE] = 'MaxCache';
+ $EBMLidList[EBML_ID_MINCACHE] = 'MinCache';
+ $EBMLidList[EBML_ID_MUXINGAPP] = 'MuxingApp';
+ $EBMLidList[EBML_ID_NAME] = 'Name';
+ $EBMLidList[EBML_ID_NEXTFILENAME] = 'NextFilename';
+ $EBMLidList[EBML_ID_NEXTUID] = 'NextUID';
+ $EBMLidList[EBML_ID_OUTPUTSAMPLINGFREQUENCY] = 'OutputSamplingFrequency';
+ $EBMLidList[EBML_ID_PIXELCROPBOTTOM] = 'PixelCropBottom';
+ $EBMLidList[EBML_ID_PIXELCROPLEFT] = 'PixelCropLeft';
+ $EBMLidList[EBML_ID_PIXELCROPRIGHT] = 'PixelCropRight';
+ $EBMLidList[EBML_ID_PIXELCROPTOP] = 'PixelCropTop';
+ $EBMLidList[EBML_ID_PIXELHEIGHT] = 'PixelHeight';
+ $EBMLidList[EBML_ID_PIXELWIDTH] = 'PixelWidth';
+ $EBMLidList[EBML_ID_PREVFILENAME] = 'PrevFilename';
+ $EBMLidList[EBML_ID_PREVUID] = 'PrevUID';
+ $EBMLidList[EBML_ID_SAMPLINGFREQUENCY] = 'SamplingFrequency';
+ $EBMLidList[EBML_ID_SEEK] = 'Seek';
+ $EBMLidList[EBML_ID_SEEKHEAD] = 'SeekHead';
+ $EBMLidList[EBML_ID_SEEKID] = 'SeekID';
+ $EBMLidList[EBML_ID_SEEKPOSITION] = 'SeekPosition';
+ $EBMLidList[EBML_ID_SEGMENT] = 'Segment';
+ $EBMLidList[EBML_ID_SEGMENTFAMILY] = 'SegmentFamily';
+ $EBMLidList[EBML_ID_SEGMENTFILENAME] = 'SegmentFilename';
+ $EBMLidList[EBML_ID_SEGMENTUID] = 'SegmentUID';
+ $EBMLidList[EBML_ID_SIMPLETAG] = 'SimpleTag';
+ $EBMLidList[EBML_ID_CLUSTERSLICES] = 'ClusterSlices';
+ $EBMLidList[EBML_ID_STEREOMODE] = 'StereoMode';
+ $EBMLidList[EBML_ID_OLDSTEREOMODE] = 'OldStereoMode';
+ $EBMLidList[EBML_ID_TAG] = 'Tag';
+ $EBMLidList[EBML_ID_TAGATTACHMENTUID] = 'TagAttachmentUID';
+ $EBMLidList[EBML_ID_TAGBINARY] = 'TagBinary';
+ $EBMLidList[EBML_ID_TAGCHAPTERUID] = 'TagChapterUID';
+ $EBMLidList[EBML_ID_TAGDEFAULT] = 'TagDefault';
+ $EBMLidList[EBML_ID_TAGEDITIONUID] = 'TagEditionUID';
+ $EBMLidList[EBML_ID_TAGLANGUAGE] = 'TagLanguage';
+ $EBMLidList[EBML_ID_TAGNAME] = 'TagName';
+ $EBMLidList[EBML_ID_TAGTRACKUID] = 'TagTrackUID';
+ $EBMLidList[EBML_ID_TAGS] = 'Tags';
+ $EBMLidList[EBML_ID_TAGSTRING] = 'TagString';
+ $EBMLidList[EBML_ID_TARGETS] = 'Targets';
+ $EBMLidList[EBML_ID_TARGETTYPE] = 'TargetType';
+ $EBMLidList[EBML_ID_TARGETTYPEVALUE] = 'TargetTypeValue';
+ $EBMLidList[EBML_ID_TIMECODESCALE] = 'TimecodeScale';
+ $EBMLidList[EBML_ID_TITLE] = 'Title';
+ $EBMLidList[EBML_ID_TRACKENTRY] = 'TrackEntry';
+ $EBMLidList[EBML_ID_TRACKNUMBER] = 'TrackNumber';
+ $EBMLidList[EBML_ID_TRACKOFFSET] = 'TrackOffset';
+ $EBMLidList[EBML_ID_TRACKOVERLAY] = 'TrackOverlay';
+ $EBMLidList[EBML_ID_TRACKS] = 'Tracks';
+ $EBMLidList[EBML_ID_TRACKTIMECODESCALE] = 'TrackTimecodeScale';
+ $EBMLidList[EBML_ID_TRACKTRANSLATE] = 'TrackTranslate';
+ $EBMLidList[EBML_ID_TRACKTRANSLATECODEC] = 'TrackTranslateCodec';
+ $EBMLidList[EBML_ID_TRACKTRANSLATEEDITIONUID] = 'TrackTranslateEditionUID';
+ $EBMLidList[EBML_ID_TRACKTRANSLATETRACKID] = 'TrackTranslateTrackID';
+ $EBMLidList[EBML_ID_TRACKTYPE] = 'TrackType';
+ $EBMLidList[EBML_ID_TRACKUID] = 'TrackUID';
+ $EBMLidList[EBML_ID_VIDEO] = 'Video';
+ $EBMLidList[EBML_ID_VOID] = 'Void';
+ $EBMLidList[EBML_ID_WRITINGAPP] = 'WritingApp';
+ }
+
+ return (isset($EBMLidList[$value]) ? $EBMLidList[$value] : dechex($value));
+ }
+
+ public static function displayUnit($value) {
+ // http://www.matroska.org/technical/specs/index.html#DisplayUnit
+ static $units = array(
+ 0 => 'pixels',
+ 1 => 'centimeters',
+ 2 => 'inches',
+ 3 => 'Display Aspect Ratio');
+
+ return (isset($units[$value]) ? $units[$value] : 'unknown');
+ }
+
+ private static function getDefaultStreamInfo($streams)
+ {
+ foreach (array_reverse($streams) as $stream) {
+ if ($stream['default']) {
+ break;
+ }
+ }
+
+ $unset = array('default', 'name');
+ foreach ($unset as $u) {
+ if (isset($stream[$u])) {
+ unset($stream[$u]);
+ }
+ }
+
+ $info = $stream;
+ $info['streams'] = $streams;
+
+ return $info;
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/libs/getid3/module.audio-video.mpeg.php b/extensions/TimedMediaHandler/libs/getid3/module.audio-video.mpeg.php
new file mode 100644
index 00000000..999c5d9a
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/module.audio-video.mpeg.php
@@ -0,0 +1,296 @@
+<?php
+/////////////////////////////////////////////////////////////////
+/// getID3() by James Heinrich <info@getid3.org> //
+// available at http://getid3.sourceforge.net //
+// or http://www.getid3.org //
+/////////////////////////////////////////////////////////////////
+// See readme.txt for more details //
+/////////////////////////////////////////////////////////////////
+// //
+// module.audio-video.mpeg.php //
+// module for analyzing MPEG files //
+// dependencies: module.audio.mp3.php //
+// ///
+/////////////////////////////////////////////////////////////////
+
+getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
+
+define('GETID3_MPEG_VIDEO_PICTURE_START', "\x00\x00\x01\x00");
+define('GETID3_MPEG_VIDEO_USER_DATA_START', "\x00\x00\x01\xB2");
+define('GETID3_MPEG_VIDEO_SEQUENCE_HEADER', "\x00\x00\x01\xB3");
+define('GETID3_MPEG_VIDEO_SEQUENCE_ERROR', "\x00\x00\x01\xB4");
+define('GETID3_MPEG_VIDEO_EXTENSION_START', "\x00\x00\x01\xB5");
+define('GETID3_MPEG_VIDEO_SEQUENCE_END', "\x00\x00\x01\xB7");
+define('GETID3_MPEG_VIDEO_GROUP_START', "\x00\x00\x01\xB8");
+define('GETID3_MPEG_AUDIO_START', "\x00\x00\x01\xC0");
+
+
+class getid3_mpeg extends getid3_handler
+{
+
+ public function Analyze() {
+ $info = &$this->getid3->info;
+
+ if ($info['avdataend'] <= $info['avdataoffset']) {
+ $info['error'][] = '"avdataend" ('.$info['avdataend'].') is unexpectedly less-than-or-equal-to "avdataoffset" ('.$info['avdataoffset'].')';
+ return false;
+ }
+ $info['fileformat'] = 'mpeg';
+ fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
+ $MPEGstreamData = fread($this->getid3->fp, min(100000, $info['avdataend'] - $info['avdataoffset']));
+ $MPEGstreamDataLength = strlen($MPEGstreamData);
+
+ $foundVideo = true;
+ $VideoChunkOffset = 0;
+ while (substr($MPEGstreamData, $VideoChunkOffset++, 4) !== GETID3_MPEG_VIDEO_SEQUENCE_HEADER) {
+ if ($VideoChunkOffset >= $MPEGstreamDataLength) {
+ $foundVideo = false;
+ break;
+ }
+ }
+ if ($foundVideo) {
+
+ // Start code 32 bits
+ // horizontal frame size 12 bits
+ // vertical frame size 12 bits
+ // pixel aspect ratio 4 bits
+ // frame rate 4 bits
+ // bitrate 18 bits
+ // marker bit 1 bit
+ // VBV buffer size 10 bits
+ // constrained parameter flag 1 bit
+ // intra quant. matrix flag 1 bit
+ // intra quant. matrix values 512 bits (present if matrix flag == 1)
+ // non-intra quant. matrix flag 1 bit
+ // non-intra quant. matrix values 512 bits (present if matrix flag == 1)
+
+ $info['video']['dataformat'] = 'mpeg';
+
+ $VideoChunkOffset += (strlen(GETID3_MPEG_VIDEO_SEQUENCE_HEADER) - 1);
+
+ $FrameSizeDWORD = getid3_lib::BigEndian2Int(substr($MPEGstreamData, $VideoChunkOffset, 3));
+ $VideoChunkOffset += 3;
+
+ $AspectRatioFrameRateDWORD = getid3_lib::BigEndian2Int(substr($MPEGstreamData, $VideoChunkOffset, 1));
+ $VideoChunkOffset += 1;
+
+ $assortedinformation = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $VideoChunkOffset, 4));
+ $VideoChunkOffset += 4;
+
+ $info['mpeg']['video']['raw']['framesize_horizontal'] = ($FrameSizeDWORD & 0xFFF000) >> 12; // 12 bits for horizontal frame size
+ $info['mpeg']['video']['raw']['framesize_vertical'] = ($FrameSizeDWORD & 0x000FFF); // 12 bits for vertical frame size
+ $info['mpeg']['video']['raw']['pixel_aspect_ratio'] = ($AspectRatioFrameRateDWORD & 0xF0) >> 4;
+ $info['mpeg']['video']['raw']['frame_rate'] = ($AspectRatioFrameRateDWORD & 0x0F);
+
+ $info['mpeg']['video']['framesize_horizontal'] = $info['mpeg']['video']['raw']['framesize_horizontal'];
+ $info['mpeg']['video']['framesize_vertical'] = $info['mpeg']['video']['raw']['framesize_vertical'];
+
+ $info['mpeg']['video']['pixel_aspect_ratio'] = $this->MPEGvideoAspectRatioLookup($info['mpeg']['video']['raw']['pixel_aspect_ratio']);
+ $info['mpeg']['video']['pixel_aspect_ratio_text'] = $this->MPEGvideoAspectRatioTextLookup($info['mpeg']['video']['raw']['pixel_aspect_ratio']);
+ $info['mpeg']['video']['frame_rate'] = $this->MPEGvideoFramerateLookup($info['mpeg']['video']['raw']['frame_rate']);
+
+ $info['mpeg']['video']['raw']['bitrate'] = getid3_lib::Bin2Dec(substr($assortedinformation, 0, 18));
+ $info['mpeg']['video']['raw']['marker_bit'] = (bool) getid3_lib::Bin2Dec(substr($assortedinformation, 18, 1));
+ $info['mpeg']['video']['raw']['vbv_buffer_size'] = getid3_lib::Bin2Dec(substr($assortedinformation, 19, 10));
+ $info['mpeg']['video']['raw']['constrained_param_flag'] = (bool) getid3_lib::Bin2Dec(substr($assortedinformation, 29, 1));
+ $info['mpeg']['video']['raw']['intra_quant_flag'] = (bool) getid3_lib::Bin2Dec(substr($assortedinformation, 30, 1));
+ if ($info['mpeg']['video']['raw']['intra_quant_flag']) {
+
+ // read 512 bits
+ $info['mpeg']['video']['raw']['intra_quant'] = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $VideoChunkOffset, 64));
+ $VideoChunkOffset += 64;
+
+ $info['mpeg']['video']['raw']['non_intra_quant_flag'] = (bool) getid3_lib::Bin2Dec(substr($info['mpeg']['video']['raw']['intra_quant'], 511, 1));
+ $info['mpeg']['video']['raw']['intra_quant'] = getid3_lib::Bin2Dec(substr($assortedinformation, 31, 1)).substr(getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $VideoChunkOffset, 64)), 0, 511);
+
+ if ($info['mpeg']['video']['raw']['non_intra_quant_flag']) {
+ $info['mpeg']['video']['raw']['non_intra_quant'] = substr($MPEGstreamData, $VideoChunkOffset, 64);
+ $VideoChunkOffset += 64;
+ }
+
+ } else {
+
+ $info['mpeg']['video']['raw']['non_intra_quant_flag'] = (bool) getid3_lib::Bin2Dec(substr($assortedinformation, 31, 1));
+ if ($info['mpeg']['video']['raw']['non_intra_quant_flag']) {
+ $info['mpeg']['video']['raw']['non_intra_quant'] = substr($MPEGstreamData, $VideoChunkOffset, 64);
+ $VideoChunkOffset += 64;
+ }
+
+ }
+
+ if ($info['mpeg']['video']['raw']['bitrate'] == 0x3FFFF) { // 18 set bits
+
+ $info['warning'][] = 'This version of getID3() ['.$this->getid3->version().'] cannot determine average bitrate of VBR MPEG video files';
+ $info['mpeg']['video']['bitrate_mode'] = 'vbr';
+
+ } else {
+
+ $info['mpeg']['video']['bitrate'] = $info['mpeg']['video']['raw']['bitrate'] * 400;
+ $info['mpeg']['video']['bitrate_mode'] = 'cbr';
+ $info['video']['bitrate'] = $info['mpeg']['video']['bitrate'];
+
+ }
+
+ $info['video']['resolution_x'] = $info['mpeg']['video']['framesize_horizontal'];
+ $info['video']['resolution_y'] = $info['mpeg']['video']['framesize_vertical'];
+ $info['video']['frame_rate'] = $info['mpeg']['video']['frame_rate'];
+ $info['video']['bitrate_mode'] = $info['mpeg']['video']['bitrate_mode'];
+ $info['video']['pixel_aspect_ratio'] = $info['mpeg']['video']['pixel_aspect_ratio'];
+ $info['video']['lossless'] = false;
+ $info['video']['bits_per_sample'] = 24;
+
+ } else {
+
+ $info['error'][] = 'Could not find start of video block in the first 100,000 bytes (or before end of file) - this might not be an MPEG-video file?';
+
+ }
+
+ //0x000001B3 begins the sequence_header of every MPEG video stream.
+ //But in MPEG-2, this header must immediately be followed by an
+ //extension_start_code (0x000001B5) with a sequence_extension ID (1).
+ //(This extension contains all the additional MPEG-2 stuff.)
+ //MPEG-1 doesn't have this extension, so that's a sure way to tell the
+ //difference between MPEG-1 and MPEG-2 video streams.
+
+ if (substr($MPEGstreamData, $VideoChunkOffset, 4) == GETID3_MPEG_VIDEO_EXTENSION_START) {
+ $info['video']['codec'] = 'MPEG-2';
+ } else {
+ $info['video']['codec'] = 'MPEG-1';
+ }
+
+
+ $AudioChunkOffset = 0;
+ while (true) {
+ while (substr($MPEGstreamData, $AudioChunkOffset++, 4) !== GETID3_MPEG_AUDIO_START) {
+ if ($AudioChunkOffset >= $MPEGstreamDataLength) {
+ break 2;
+ }
+ }
+
+ $getid3_temp = new getID3();
+ $getid3_temp->openfile($this->getid3->filename);
+ $getid3_temp->info = $info;
+ $getid3_mp3 = new getid3_mp3($getid3_temp);
+ for ($i = 0; $i <= 7; $i++) {
+ // some files have the MPEG-audio header 8 bytes after the end of the $00 $00 $01 $C0 signature, some have it up to 13 bytes (or more?) after
+ // I have no idea why or what the difference is, so this is a stupid hack.
+ // If anybody has any better idea of what's going on, please let me know - info@getid3.org
+ fseek($getid3_temp->fp, ftell($this->getid3->fp), SEEK_SET);
+ $getid3_temp->info = $info; // only overwrite real data if valid header found
+ if ($getid3_mp3->decodeMPEGaudioHeader(($AudioChunkOffset + 3) + 8 + $i, $getid3_temp->info, false)) {
+ $info = $getid3_temp->info;
+ $info['audio']['bitrate_mode'] = 'cbr';
+ $info['audio']['lossless'] = false;
+ unset($getid3_temp, $getid3_mp3);
+ break 2;
+ }
+ }
+ unset($getid3_temp, $getid3_mp3);
+ }
+
+ // Temporary hack to account for interleaving overhead:
+ if (!empty($info['video']['bitrate']) && !empty($info['audio']['bitrate'])) {
+ $info['playtime_seconds'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / ($info['video']['bitrate'] + $info['audio']['bitrate']);
+
+ // Interleaved MPEG audio/video files have a certain amount of overhead that varies
+ // by both video and audio bitrates, and not in any sensible, linear/logarithmic patter
+ // Use interpolated lookup tables to approximately guess how much is overhead, because
+ // playtime is calculated as filesize / total-bitrate
+ $info['playtime_seconds'] *= $this->MPEGsystemNonOverheadPercentage($info['video']['bitrate'], $info['audio']['bitrate']);
+
+ //switch ($info['video']['bitrate']) {
+ // case('5000000'):
+ // $multiplier = 0.93292642112380355828048824319889;
+ // break;
+ // case('5500000'):
+ // $multiplier = 0.93582895375200989965359777343219;
+ // break;
+ // case('6000000'):
+ // $multiplier = 0.93796247714820932532911373859139;
+ // break;
+ // case('7000000'):
+ // $multiplier = 0.9413264083635103463010117778776;
+ // break;
+ // default:
+ // $multiplier = 1;
+ // break;
+ //}
+ //$info['playtime_seconds'] *= $multiplier;
+ //$info['warning'][] = 'Interleaved MPEG audio/video playtime may be inaccurate. With current hack should be within a few seconds of accurate. Report to info@getid3.org if off by more than 10 seconds.';
+ if ($info['video']['bitrate'] < 50000) {
+ $info['warning'][] = 'Interleaved MPEG audio/video playtime may be slightly inaccurate for video bitrates below 100kbps. Except in extreme low-bitrate situations, error should be less than 1%. Report to info@getid3.org if greater than this.';
+ }
+ }
+
+ return true;
+ }
+
+
+ public function MPEGsystemNonOverheadPercentage($VideoBitrate, $AudioBitrate) {
+ $OverheadPercentage = 0;
+
+ $AudioBitrate = max(min($AudioBitrate / 1000, 384), 32); // limit to range of 32kbps - 384kbps (should be only legal bitrates, but maybe VBR?)
+ $VideoBitrate = max(min($VideoBitrate / 1000, 10000), 10); // limit to range of 10kbps - 10Mbps (beyond that curves flatten anyways, no big loss)
+
+
+ //OMBB[audiobitrate] = array(video-10kbps, video-100kbps, video-1000kbps, video-10000kbps)
+ $OverheadMultiplierByBitrate[32] = array(0, 0.9676287944368530, 0.9802276264360310, 0.9844916183244460, 0.9852821845179940);
+ $OverheadMultiplierByBitrate[48] = array(0, 0.9779100089209830, 0.9787770035359320, 0.9846738664076130, 0.9852683013799960);
+ $OverheadMultiplierByBitrate[56] = array(0, 0.9731249855367600, 0.9776624308938040, 0.9832606361852130, 0.9843922606633340);
+ $OverheadMultiplierByBitrate[64] = array(0, 0.9755642683275760, 0.9795256705493390, 0.9836573009193170, 0.9851122539404470);
+ $OverheadMultiplierByBitrate[96] = array(0, 0.9788025247497290, 0.9798553314148700, 0.9822956869792560, 0.9834815119124690);
+ $OverheadMultiplierByBitrate[128] = array(0, 0.9816940050925480, 0.9821675936072120, 0.9829756927470870, 0.9839763420152050);
+ $OverheadMultiplierByBitrate[160] = array(0, 0.9825894094561180, 0.9820913399073960, 0.9823907143253970, 0.9832821783651570);
+ $OverheadMultiplierByBitrate[192] = array(0, 0.9832038474336260, 0.9825731694317960, 0.9821028622712400, 0.9828262076447620);
+ $OverheadMultiplierByBitrate[224] = array(0, 0.9836516298538770, 0.9824718601823890, 0.9818302180625380, 0.9823735101626480);
+ $OverheadMultiplierByBitrate[256] = array(0, 0.9845863022094920, 0.9837229411967540, 0.9824521662210830, 0.9828645172100790);
+ $OverheadMultiplierByBitrate[320] = array(0, 0.9849565280263180, 0.9837683142805110, 0.9822885275960400, 0.9824424382727190);
+ $OverheadMultiplierByBitrate[384] = array(0, 0.9856094774357600, 0.9844573394432720, 0.9825970399837330, 0.9824673808303890);
+
+ $BitrateToUseMin = 32;
+ $BitrateToUseMax = 32;
+ $previousBitrate = 32;
+ foreach ($OverheadMultiplierByBitrate as $key => $value) {
+ if ($AudioBitrate >= $previousBitrate) {
+ $BitrateToUseMin = $previousBitrate;
+ }
+ if ($AudioBitrate < $key) {
+ $BitrateToUseMax = $key;
+ break;
+ }
+ $previousBitrate = $key;
+ }
+ $FactorA = ($BitrateToUseMax - $AudioBitrate) / ($BitrateToUseMax - $BitrateToUseMin);
+
+ $VideoBitrateLog10 = log10($VideoBitrate);
+ $VideoFactorMin1 = $OverheadMultiplierByBitrate[$BitrateToUseMin][floor($VideoBitrateLog10)];
+ $VideoFactorMin2 = $OverheadMultiplierByBitrate[$BitrateToUseMax][floor($VideoBitrateLog10)];
+ $VideoFactorMax1 = $OverheadMultiplierByBitrate[$BitrateToUseMin][ceil($VideoBitrateLog10)];
+ $VideoFactorMax2 = $OverheadMultiplierByBitrate[$BitrateToUseMax][ceil($VideoBitrateLog10)];
+ $FactorV = $VideoBitrateLog10 - floor($VideoBitrateLog10);
+
+ $OverheadPercentage = $VideoFactorMin1 * $FactorA * $FactorV;
+ $OverheadPercentage += $VideoFactorMin2 * (1 - $FactorA) * $FactorV;
+ $OverheadPercentage += $VideoFactorMax1 * $FactorA * (1 - $FactorV);
+ $OverheadPercentage += $VideoFactorMax2 * (1 - $FactorA) * (1 - $FactorV);
+
+ return $OverheadPercentage;
+ }
+
+
+ public function MPEGvideoFramerateLookup($rawframerate) {
+ $MPEGvideoFramerateLookup = array(0, 23.976, 24, 25, 29.97, 30, 50, 59.94, 60);
+ return (isset($MPEGvideoFramerateLookup[$rawframerate]) ? (float) $MPEGvideoFramerateLookup[$rawframerate] : (float) 0);
+ }
+
+ public function MPEGvideoAspectRatioLookup($rawaspectratio) {
+ $MPEGvideoAspectRatioLookup = array(0, 1, 0.6735, 0.7031, 0.7615, 0.8055, 0.8437, 0.8935, 0.9157, 0.9815, 1.0255, 1.0695, 1.0950, 1.1575, 1.2015, 0);
+ return (isset($MPEGvideoAspectRatioLookup[$rawaspectratio]) ? (float) $MPEGvideoAspectRatioLookup[$rawaspectratio] : (float) 0);
+ }
+
+ public function MPEGvideoAspectRatioTextLookup($rawaspectratio) {
+ $MPEGvideoAspectRatioTextLookup = array('forbidden', 'square pixels', '0.6735', '16:9, 625 line, PAL', '0.7615', '0.8055', '16:9, 525 line, NTSC', '0.8935', '4:3, 625 line, PAL, CCIR601', '0.9815', '1.0255', '1.0695', '4:3, 525 line, NTSC, CCIR601', '1.1575', '1.2015', 'reserved');
+ return (isset($MPEGvideoAspectRatioTextLookup[$rawaspectratio]) ? $MPEGvideoAspectRatioTextLookup[$rawaspectratio] : '');
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/libs/getid3/module.audio-video.quicktime.php b/extensions/TimedMediaHandler/libs/getid3/module.audio-video.quicktime.php
new file mode 100644
index 00000000..e59d61cc
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/module.audio-video.quicktime.php
@@ -0,0 +1,2192 @@
+<?php
+/////////////////////////////////////////////////////////////////
+/// getID3() by James Heinrich <info@getid3.org> //
+// available at http://getid3.sourceforge.net //
+// or http://www.getid3.org //
+/////////////////////////////////////////////////////////////////
+// See readme.txt for more details //
+/////////////////////////////////////////////////////////////////
+// //
+// module.audio-video.quicktime.php //
+// module for analyzing Quicktime and MP3-in-MP4 files //
+// dependencies: module.audio.mp3.php //
+// ///
+/////////////////////////////////////////////////////////////////
+
+getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
+
+class getid3_quicktime extends getid3_handler
+{
+
+ public $ReturnAtomData = true;
+ public $ParseAllPossibleAtoms = false;
+
+ public function Analyze() {
+ $info = &$this->getid3->info;
+
+ $info['fileformat'] = 'quicktime';
+ $info['quicktime']['hinting'] = false;
+ $info['quicktime']['controller'] = 'standard'; // may be overridden if 'ctyp' atom is present
+
+ fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
+
+ $offset = 0;
+ $atomcounter = 0;
+
+ while ($offset < $info['avdataend']) {
+ if (!getid3_lib::intValueSupported($offset)) {
+ $info['error'][] = 'Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions';
+ break;
+ }
+ fseek($this->getid3->fp, $offset, SEEK_SET);
+ $AtomHeader = fread($this->getid3->fp, 8);
+
+ $atomsize = getid3_lib::BigEndian2Int(substr($AtomHeader, 0, 4));
+ $atomname = substr($AtomHeader, 4, 4);
+
+ // 64-bit MOV patch by jlegateŲktnc*com
+ if ($atomsize == 1) {
+ $atomsize = getid3_lib::BigEndian2Int(fread($this->getid3->fp, 8));
+ }
+
+ $info['quicktime'][$atomname]['name'] = $atomname;
+ $info['quicktime'][$atomname]['size'] = $atomsize;
+ $info['quicktime'][$atomname]['offset'] = $offset;
+
+ if (($offset + $atomsize) > $info['avdataend']) {
+ $info['error'][] = 'Atom at offset '.$offset.' claims to go beyond end-of-file (length: '.$atomsize.' bytes)';
+ return false;
+ }
+
+ if ($atomsize == 0) {
+ // Furthermore, for historical reasons the list of atoms is optionally
+ // terminated by a 32-bit integer set to 0. If you are writing a program
+ // to read user data atoms, you should allow for the terminating 0.
+ break;
+ }
+ switch ($atomname) {
+ case 'mdat': // Media DATa atom
+ // 'mdat' contains the actual data for the audio/video
+ if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) {
+
+ $info['avdataoffset'] = $info['quicktime'][$atomname]['offset'] + 8;
+ $OldAVDataEnd = $info['avdataend'];
+ $info['avdataend'] = $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size'];
+
+ $getid3_temp = new getID3();
+ $getid3_temp->openfile($this->getid3->filename);
+ $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
+ $getid3_temp->info['avdataend'] = $info['avdataend'];
+ $getid3_mp3 = new getid3_mp3($getid3_temp);
+ if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode(fread($this->getid3->fp, 4)))) {
+ $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
+ if (!empty($getid3_temp->info['warning'])) {
+ foreach ($getid3_temp->info['warning'] as $value) {
+ $info['warning'][] = $value;
+ }
+ }
+ if (!empty($getid3_temp->info['mpeg'])) {
+ $info['mpeg'] = $getid3_temp->info['mpeg'];
+ if (isset($info['mpeg']['audio'])) {
+ $info['audio']['dataformat'] = 'mp3';
+ $info['audio']['codec'] = (!empty($info['mpeg']['audio']['encoder']) ? $info['mpeg']['audio']['encoder'] : (!empty($info['mpeg']['audio']['codec']) ? $info['mpeg']['audio']['codec'] : (!empty($info['mpeg']['audio']['LAME']) ? 'LAME' :'mp3')));
+ $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
+ $info['audio']['channels'] = $info['mpeg']['audio']['channels'];
+ $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
+ $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
+ $info['bitrate'] = $info['audio']['bitrate'];
+ }
+ }
+ }
+ unset($getid3_mp3, $getid3_temp);
+ $info['avdataend'] = $OldAVDataEnd;
+ unset($OldAVDataEnd);
+
+ }
+ break;
+
+ case 'free': // FREE space atom
+ case 'skip': // SKIP atom
+ case 'wide': // 64-bit expansion placeholder atom
+ // 'free', 'skip' and 'wide' are just padding, contains no useful data at all
+ break;
+
+ default:
+ $atomHierarchy = array();
+ $info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, fread($this->getid3->fp, $atomsize), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms);
+ break;
+ }
+
+ $offset += $atomsize;
+ $atomcounter++;
+ }
+
+ if (!empty($info['avdataend_tmp'])) {
+ // this value is assigned to a temp value and then erased because
+ // otherwise any atoms beyond the 'mdat' atom would not get parsed
+ $info['avdataend'] = $info['avdataend_tmp'];
+ unset($info['avdataend_tmp']);
+ }
+
+ if (!isset($info['bitrate']) && isset($info['playtime_seconds'])) {
+ $info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
+ }
+ if (isset($info['bitrate']) && !isset($info['audio']['bitrate']) && !isset($info['quicktime']['video'])) {
+ $info['audio']['bitrate'] = $info['bitrate'];
+ }
+ if (!empty($info['playtime_seconds']) && !isset($info['video']['frame_rate']) && !empty($info['quicktime']['stts_framecount'])) {
+ foreach ($info['quicktime']['stts_framecount'] as $key => $samples_count) {
+ $samples_per_second = $samples_count / $info['playtime_seconds'];
+ if ($samples_per_second > 240) {
+ // has to be audio samples
+ } else {
+ $info['video']['frame_rate'] = $samples_per_second;
+ break;
+ }
+ }
+ }
+ if (($info['audio']['dataformat'] == 'mp4') && empty($info['video']['resolution_x'])) {
+ $info['fileformat'] = 'mp4';
+ $info['mime_type'] = 'audio/mp4';
+ unset($info['video']['dataformat']);
+ }
+
+ if (!$this->ReturnAtomData) {
+ unset($info['quicktime']['moov']);
+ }
+
+ if (empty($info['audio']['dataformat']) && !empty($info['quicktime']['audio'])) {
+ $info['audio']['dataformat'] = 'quicktime';
+ }
+ if (empty($info['video']['dataformat']) && !empty($info['quicktime']['video'])) {
+ $info['video']['dataformat'] = 'quicktime';
+ }
+
+ return true;
+ }
+
+ public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
+ // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
+
+ $info = &$this->getid3->info;
+
+ $atom_parent = array_pop($atomHierarchy);
+ array_push($atomHierarchy, $atomname);
+ $atom_structure['hierarchy'] = implode(' ', $atomHierarchy);
+ $atom_structure['name'] = $atomname;
+ $atom_structure['size'] = $atomsize;
+ $atom_structure['offset'] = $baseoffset;
+//echo getid3_lib::PrintHexBytes(substr($atom_data, 0, 8)).'<br>';
+//echo getid3_lib::PrintHexBytes(substr($atom_data, 0, 8), false).'<br><br>';
+ switch ($atomname) {
+ case 'moov': // MOVie container atom
+ case 'trak': // TRAcK container atom
+ case 'clip': // CLIPping container atom
+ case 'matt': // track MATTe container atom
+ case 'edts': // EDiTS container atom
+ case 'tref': // Track REFerence container atom
+ case 'mdia': // MeDIA container atom
+ case 'minf': // Media INFormation container atom
+ case 'dinf': // Data INFormation container atom
+ case 'udta': // User DaTA container atom
+ case 'cmov': // Compressed MOVie container atom
+ case 'rmra': // Reference Movie Record Atom
+ case 'rmda': // Reference Movie Descriptor Atom
+ case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR)
+ $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
+ break;
+
+ case 'ilst': // Item LiST container atom
+ $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
+
+ // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted
+ $allnumericnames = true;
+ foreach ($atom_structure['subatoms'] as $subatomarray) {
+ if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) {
+ $allnumericnames = false;
+ break;
+ }
+ }
+ if ($allnumericnames) {
+ $newData = array();
+ foreach ($atom_structure['subatoms'] as $subatomarray) {
+ foreach ($subatomarray['subatoms'] as $newData_subatomarray) {
+ unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']);
+ $newData[$subatomarray['name']] = $newData_subatomarray;
+ break;
+ }
+ }
+ $atom_structure['data'] = $newData;
+ unset($atom_structure['subatoms']);
+ }
+ break;
+
+ case "\x00\x00\x00\x01":
+ case "\x00\x00\x00\x02":
+ case "\x00\x00\x00\x03":
+ case "\x00\x00\x00\x04":
+ case "\x00\x00\x00\x05":
+ $atomname = getid3_lib::BigEndian2Int($atomname);
+ $atom_structure['name'] = $atomname;
+ $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
+ break;
+
+ case 'stbl': // Sample TaBLe container atom
+ $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
+ $isVideo = false;
+ $framerate = 0;
+ $framecount = 0;
+ foreach ($atom_structure['subatoms'] as $key => $value_array) {
+ if (isset($value_array['sample_description_table'])) {
+ foreach ($value_array['sample_description_table'] as $key2 => $value_array2) {
+ if (isset($value_array2['data_format'])) {
+ switch ($value_array2['data_format']) {
+ case 'avc1':
+ case 'mp4v':
+ // video data
+ $isVideo = true;
+ break;
+ case 'mp4a':
+ // audio data
+ break;
+ }
+ }
+ }
+ } elseif (isset($value_array['time_to_sample_table'])) {
+ foreach ($value_array['time_to_sample_table'] as $key2 => $value_array2) {
+ if (isset($value_array2['sample_count']) && isset($value_array2['sample_duration']) && ($value_array2['sample_duration'] > 0)) {
+ $framerate = round($info['quicktime']['time_scale'] / $value_array2['sample_duration'], 3);
+ $framecount = $value_array2['sample_count'];
+ }
+ }
+ }
+ }
+ if ($isVideo && $framerate) {
+ $info['quicktime']['video']['frame_rate'] = $framerate;
+ $info['video']['frame_rate'] = $info['quicktime']['video']['frame_rate'];
+ }
+ if ($isVideo && $framecount) {
+ $info['quicktime']['video']['frame_count'] = $framecount;
+ }
+ break;
+
+
+ case 'aART': // Album ARTist
+ case 'catg': // CaTeGory
+ case 'covr': // COVeR artwork
+ case 'cpil': // ComPILation
+ case 'cprt': // CoPyRighT
+ case 'desc': // DESCription
+ case 'disk': // DISK number
+ case 'egid': // Episode Global ID
+ case 'gnre': // GeNRE
+ case 'keyw': // KEYWord
+ case 'ldes':
+ case 'pcst': // PodCaST
+ case 'pgap': // GAPless Playback
+ case 'purd': // PURchase Date
+ case 'purl': // Podcast URL
+ case 'rati':
+ case 'rndu':
+ case 'rpdu':
+ case 'rtng': // RaTiNG
+ case 'stik':
+ case 'tmpo': // TeMPO (BPM)
+ case 'trkn': // TRacK Number
+ case 'tves': // TV EpiSode
+ case 'tvnn': // TV Network Name
+ case 'tvsh': // TV SHow Name
+ case 'tvsn': // TV SeasoN
+ case 'akID': // iTunes store account type
+ case 'apID':
+ case 'atID':
+ case 'cmID':
+ case 'cnID':
+ case 'geID':
+ case 'plID':
+ case 'sfID': // iTunes store country
+ case '©alb': // ALBum
+ case '©art': // ARTist
+ case '©ART':
+ case '©aut':
+ case '©cmt': // CoMmenT
+ case '©com': // COMposer
+ case '©cpy':
+ case '©day': // content created year
+ case '©dir':
+ case '©ed1':
+ case '©ed2':
+ case '©ed3':
+ case '©ed4':
+ case '©ed5':
+ case '©ed6':
+ case '©ed7':
+ case '©ed8':
+ case '©ed9':
+ case '©enc':
+ case '©fmt':
+ case '©gen': // GENre
+ case '©grp': // GRouPing
+ case '©hst':
+ case '©inf':
+ case '©lyr': // LYRics
+ case '©mak':
+ case '©mod':
+ case '©nam': // full NAMe
+ case '©ope':
+ case '©PRD':
+ case '©prd':
+ case '©prf':
+ case '©req':
+ case '©src':
+ case '©swr':
+ case '©too': // encoder
+ case '©trk': // TRacK
+ case '©url':
+ case '©wrn':
+ case '©wrt': // WRiTer
+ case '----': // itunes specific
+ if ($atom_parent == 'udta') {
+ // User data atom handler
+ $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
+ $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2));
+ $atom_structure['data'] = substr($atom_data, 4);
+
+ $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
+ if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
+ $info['comments']['language'][] = $atom_structure['language'];
+ }
+ } else {
+ // Apple item list box atom handler
+ $atomoffset = 0;
+ if (substr($atom_data, 2, 2) == "\x10\xB5") {
+ // not sure what it means, but observed on iPhone4 data.
+ // Each $atom_data has 2 bytes of datasize, plus 0x10B5, then data
+ while ($atomoffset < strlen($atom_data)) {
+ $boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 2));
+ $boxsmalltype = substr($atom_data, $atomoffset + 2, 2);
+ $boxsmalldata = substr($atom_data, $atomoffset + 4, $boxsmallsize);
+ switch ($boxsmalltype) {
+ case "\x10\xB5":
+ $atom_structure['data'] = $boxsmalldata;
+ break;
+ default:
+ $info['warning'][] = 'Unknown QuickTime smallbox type: "'.getid3_lib::PrintHexBytes($boxsmalltype).'" at offset '.$baseoffset;
+ $atom_structure['data'] = $atom_data;
+ break;
+ }
+ $atomoffset += (4 + $boxsmallsize);
+ }
+ } else {
+ while ($atomoffset < strlen($atom_data)) {
+ $boxsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 4));
+ $boxtype = substr($atom_data, $atomoffset + 4, 4);
+ $boxdata = substr($atom_data, $atomoffset + 8, $boxsize - 8);
+ if ($boxsize <= 1) {
+ $info['warning'][] = 'Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.$atomname.'" at offset: '.($atom_structure['offset'] + $atomoffset);
+ $atom_structure['data'] = null;
+ $atomoffset = strlen($atom_data);
+ break;
+ }
+ $atomoffset += $boxsize;
+
+ switch ($boxtype) {
+ case 'mean':
+ case 'name':
+ $atom_structure[$boxtype] = substr($boxdata, 4);
+ break;
+
+ case 'data':
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($boxdata, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata, 1, 3));
+ switch ($atom_structure['flags_raw']) {
+ case 0: // data flag
+ case 21: // tmpo/cpil flag
+ switch ($atomname) {
+ case 'cpil':
+ case 'pcst':
+ case 'pgap':
+ $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
+ break;
+
+ case 'tmpo':
+ $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2));
+ break;
+
+ case 'disk':
+ case 'trkn':
+ $num = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2));
+ $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2));
+ $atom_structure['data'] = empty($num) ? '' : $num;
+ $atom_structure['data'] .= empty($num_total) ? '' : '/'.$num_total;
+ break;
+
+ case 'gnre':
+ $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
+ $atom_structure['data'] = getid3_id3v1::LookupGenreName($GenreID - 1);
+ break;
+
+ case 'rtng':
+ $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
+ $atom_structure['data'] = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]);
+ break;
+
+ case 'stik':
+ $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
+ $atom_structure['data'] = $this->QuicktimeSTIKLookup($atom_structure[$atomname]);
+ break;
+
+ case 'sfID':
+ $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
+ $atom_structure['data'] = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]);
+ break;
+
+ case 'egid':
+ case 'purl':
+ $atom_structure['data'] = substr($boxdata, 8);
+ break;
+
+ default:
+ $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
+ }
+ break;
+
+ case 1: // text flag
+ case 13: // image flag
+ default:
+ $atom_structure['data'] = substr($boxdata, 8);
+ break;
+
+ }
+ break;
+
+ default:
+ $info['warning'][] = 'Unknown QuickTime box type: "'.getid3_lib::PrintHexBytes($boxtype).'" at offset '.$baseoffset;
+ $atom_structure['data'] = $atom_data;
+
+ }
+ }
+ }
+ }
+ $this->CopyToAppropriateCommentsSection($atomname, $atom_structure['data'], $atom_structure['name']);
+ break;
+
+
+ case 'play': // auto-PLAY atom
+ $atom_structure['autoplay'] = (bool) getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+
+ $info['quicktime']['autoplay'] = $atom_structure['autoplay'];
+ break;
+
+
+ case 'WLOC': // Window LOCation atom
+ $atom_structure['location_x'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
+ $atom_structure['location_y'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2));
+ break;
+
+
+ case 'LOOP': // LOOPing atom
+ case 'SelO': // play SELection Only atom
+ case 'AllF': // play ALL Frames atom
+ $atom_structure['data'] = getid3_lib::BigEndian2Int($atom_data);
+ break;
+
+
+ case 'name': //
+ case 'MCPS': // Media Cleaner PRo
+ case '@PRM': // adobe PReMiere version
+ case '@PRQ': // adobe PRemiere Quicktime version
+ $atom_structure['data'] = $atom_data;
+ break;
+
+
+ case 'cmvd': // Compressed MooV Data atom
+ // Code by ubergeekŲubergeek*tv based on information from
+ // http://developer.apple.com/quicktime/icefloe/dispatch012.html
+ $atom_structure['unCompressedSize'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
+
+ $CompressedFileData = substr($atom_data, 4);
+ if ($UncompressedHeader = @gzuncompress($CompressedFileData)) {
+ $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms);
+ } else {
+ $info['warning'][] = 'Error decompressing compressed MOV atom at offset '.$atom_structure['offset'];
+ }
+ break;
+
+
+ case 'dcom': // Data COMpression atom
+ $atom_structure['compression_id'] = $atom_data;
+ $atom_structure['compression_text'] = $this->QuicktimeDCOMLookup($atom_data);
+ break;
+
+
+ case 'rdrf': // Reference movie Data ReFerence atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
+ $atom_structure['flags']['internal_data'] = (bool) ($atom_structure['flags_raw'] & 0x000001);
+
+ $atom_structure['reference_type_name'] = substr($atom_data, 4, 4);
+ $atom_structure['reference_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
+ switch ($atom_structure['reference_type_name']) {
+ case 'url ':
+ $atom_structure['url'] = $this->NoNullString(substr($atom_data, 12));
+ break;
+
+ case 'alis':
+ $atom_structure['file_alias'] = substr($atom_data, 12);
+ break;
+
+ case 'rsrc':
+ $atom_structure['resource_alias'] = substr($atom_data, 12);
+ break;
+
+ default:
+ $atom_structure['data'] = substr($atom_data, 12);
+ break;
+ }
+ break;
+
+
+ case 'rmqu': // Reference Movie QUality atom
+ $atom_structure['movie_quality'] = getid3_lib::BigEndian2Int($atom_data);
+ break;
+
+
+ case 'rmcs': // Reference Movie Cpu Speed atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['cpu_speed_rating'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
+ break;
+
+
+ case 'rmvc': // Reference Movie Version Check atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['gestalt_selector'] = substr($atom_data, 4, 4);
+ $atom_structure['gestalt_value_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
+ $atom_structure['gestalt_value'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
+ $atom_structure['gestalt_check_type'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2));
+ break;
+
+
+ case 'rmcd': // Reference Movie Component check atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['component_type'] = substr($atom_data, 4, 4);
+ $atom_structure['component_subtype'] = substr($atom_data, 8, 4);
+ $atom_structure['component_manufacturer'] = substr($atom_data, 12, 4);
+ $atom_structure['component_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
+ $atom_structure['component_flags_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
+ $atom_structure['component_min_version'] = getid3_lib::BigEndian2Int(substr($atom_data, 24, 4));
+ break;
+
+
+ case 'rmdr': // Reference Movie Data Rate atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['data_rate'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+
+ $atom_structure['data_rate_bps'] = $atom_structure['data_rate'] * 10;
+ break;
+
+
+ case 'rmla': // Reference Movie Language Atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
+
+ $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
+ if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
+ $info['comments']['language'][] = $atom_structure['language'];
+ }
+ break;
+
+
+ case 'rmla': // Reference Movie Language Atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
+ break;
+
+
+ case 'ptv ': // Print To Video - defines a movie's full screen mode
+ // http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm
+ $atom_structure['display_size_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
+ $atom_structure['reserved_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); // hardcoded: 0x0000
+ $atom_structure['reserved_2'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x0000
+ $atom_structure['slide_show_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 1));
+ $atom_structure['play_on_open_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 7, 1));
+
+ $atom_structure['flags']['play_on_open'] = (bool) $atom_structure['play_on_open_flag'];
+ $atom_structure['flags']['slide_show'] = (bool) $atom_structure['slide_show_flag'];
+
+ $ptv_lookup[0] = 'normal';
+ $ptv_lookup[1] = 'double';
+ $ptv_lookup[2] = 'half';
+ $ptv_lookup[3] = 'full';
+ $ptv_lookup[4] = 'current';
+ if (isset($ptv_lookup[$atom_structure['display_size_raw']])) {
+ $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']];
+ } else {
+ $info['warning'][] = 'unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')';
+ }
+ break;
+
+
+ case 'stsd': // Sample Table Sample Description atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+ $stsdEntriesDataOffset = 8;
+ for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
+ $atom_structure['sample_description_table'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4));
+ $stsdEntriesDataOffset += 4;
+ $atom_structure['sample_description_table'][$i]['data_format'] = substr($atom_data, $stsdEntriesDataOffset, 4);
+ $stsdEntriesDataOffset += 4;
+ $atom_structure['sample_description_table'][$i]['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 6));
+ $stsdEntriesDataOffset += 6;
+ $atom_structure['sample_description_table'][$i]['reference_index'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 2));
+ $stsdEntriesDataOffset += 2;
+ $atom_structure['sample_description_table'][$i]['data'] = substr($atom_data, $stsdEntriesDataOffset, ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2));
+ $stsdEntriesDataOffset += ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2);
+
+ $atom_structure['sample_description_table'][$i]['encoder_version'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 0, 2));
+ $atom_structure['sample_description_table'][$i]['encoder_revision'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 2, 2));
+ $atom_structure['sample_description_table'][$i]['encoder_vendor'] = substr($atom_structure['sample_description_table'][$i]['data'], 4, 4);
+
+ switch ($atom_structure['sample_description_table'][$i]['encoder_vendor']) {
+
+ case "\x00\x00\x00\x00":
+ // audio tracks
+ $atom_structure['sample_description_table'][$i]['audio_channels'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 2));
+ $atom_structure['sample_description_table'][$i]['audio_bit_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 10, 2));
+ $atom_structure['sample_description_table'][$i]['audio_compression_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 2));
+ $atom_structure['sample_description_table'][$i]['audio_packet_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 14, 2));
+ $atom_structure['sample_description_table'][$i]['audio_sample_rate'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 16, 4));
+
+ // video tracks
+ // http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap3/qtff3.html
+ $atom_structure['sample_description_table'][$i]['temporal_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 4));
+ $atom_structure['sample_description_table'][$i]['spatial_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 4));
+ $atom_structure['sample_description_table'][$i]['width'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16, 2));
+ $atom_structure['sample_description_table'][$i]['height'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18, 2));
+ $atom_structure['sample_description_table'][$i]['resolution_x'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4));
+ $atom_structure['sample_description_table'][$i]['resolution_y'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 28, 4));
+ $atom_structure['sample_description_table'][$i]['data_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32, 4));
+ $atom_structure['sample_description_table'][$i]['frame_count'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 36, 2));
+ $atom_structure['sample_description_table'][$i]['compressor_name'] = substr($atom_structure['sample_description_table'][$i]['data'], 38, 4);
+ $atom_structure['sample_description_table'][$i]['pixel_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 42, 2));
+ $atom_structure['sample_description_table'][$i]['color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 44, 2));
+
+ switch ($atom_structure['sample_description_table'][$i]['data_format']) {
+ case '2vuY':
+ case 'avc1':
+ case 'cvid':
+ case 'dvc ':
+ case 'dvcp':
+ case 'gif ':
+ case 'h263':
+ case 'jpeg':
+ case 'kpcd':
+ case 'mjpa':
+ case 'mjpb':
+ case 'mp4v':
+ case 'png ':
+ case 'raw ':
+ case 'rle ':
+ case 'rpza':
+ case 'smc ':
+ case 'SVQ1':
+ case 'SVQ3':
+ case 'tiff':
+ case 'v210':
+ case 'v216':
+ case 'v308':
+ case 'v408':
+ case 'v410':
+ case 'yuv2':
+ $info['fileformat'] = 'mp4';
+ $info['video']['fourcc'] = $atom_structure['sample_description_table'][$i]['data_format'];
+// http://www.getid3.org/phpBB3/viewtopic.php?t=1550
+//if ((!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['width'])) && (empty($info['video']['resolution_x']) || empty($info['video']['resolution_y']) || (number_format($info['video']['resolution_x'], 6) != number_format(round($info['video']['resolution_x']), 6)) || (number_format($info['video']['resolution_y'], 6) != number_format(round($info['video']['resolution_y']), 6)))) { // ugly check for floating point numbers
+if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['height'])) {
+ // assume that values stored here are more important than values stored in [tkhd] atom
+ $info['video']['resolution_x'] = $atom_structure['sample_description_table'][$i]['width'];
+ $info['video']['resolution_y'] = $atom_structure['sample_description_table'][$i]['height'];
+ $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
+ $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
+}
+ break;
+
+ case 'qtvr':
+ $info['video']['dataformat'] = 'quicktimevr';
+ break;
+
+ case 'mp4a':
+ default:
+ $info['quicktime']['audio']['codec'] = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
+ $info['quicktime']['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate'];
+ $info['quicktime']['audio']['channels'] = $atom_structure['sample_description_table'][$i]['audio_channels'];
+ $info['quicktime']['audio']['bit_depth'] = $atom_structure['sample_description_table'][$i]['audio_bit_depth'];
+ $info['audio']['codec'] = $info['quicktime']['audio']['codec'];
+ $info['audio']['sample_rate'] = $info['quicktime']['audio']['sample_rate'];
+ $info['audio']['channels'] = $info['quicktime']['audio']['channels'];
+ $info['audio']['bits_per_sample'] = $info['quicktime']['audio']['bit_depth'];
+ switch ($atom_structure['sample_description_table'][$i]['data_format']) {
+ case 'raw ': // PCM
+ case 'alac': // Apple Lossless Audio Codec
+ $info['audio']['lossless'] = true;
+ break;
+ default:
+ $info['audio']['lossless'] = false;
+ break;
+ }
+ break;
+ }
+ break;
+
+ default:
+ switch ($atom_structure['sample_description_table'][$i]['data_format']) {
+ case 'mp4s':
+ $info['fileformat'] = 'mp4';
+ break;
+
+ default:
+ // video atom
+ $atom_structure['sample_description_table'][$i]['video_temporal_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 4));
+ $atom_structure['sample_description_table'][$i]['video_spatial_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 4));
+ $atom_structure['sample_description_table'][$i]['video_frame_width'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16, 2));
+ $atom_structure['sample_description_table'][$i]['video_frame_height'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18, 2));
+ $atom_structure['sample_description_table'][$i]['video_resolution_x'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 20, 4));
+ $atom_structure['sample_description_table'][$i]['video_resolution_y'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4));
+ $atom_structure['sample_description_table'][$i]['video_data_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 28, 4));
+ $atom_structure['sample_description_table'][$i]['video_frame_count'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32, 2));
+ $atom_structure['sample_description_table'][$i]['video_encoder_name_len'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 34, 1));
+ $atom_structure['sample_description_table'][$i]['video_encoder_name'] = substr($atom_structure['sample_description_table'][$i]['data'], 35, $atom_structure['sample_description_table'][$i]['video_encoder_name_len']);
+ $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 66, 2));
+ $atom_structure['sample_description_table'][$i]['video_color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 68, 2));
+
+ $atom_structure['sample_description_table'][$i]['video_pixel_color_type'] = (($atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color');
+ $atom_structure['sample_description_table'][$i]['video_pixel_color_name'] = $this->QuicktimeColorNameLookup($atom_structure['sample_description_table'][$i]['video_pixel_color_depth']);
+
+ if ($atom_structure['sample_description_table'][$i]['video_pixel_color_name'] != 'invalid') {
+ $info['quicktime']['video']['codec_fourcc'] = $atom_structure['sample_description_table'][$i]['data_format'];
+ $info['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
+ $info['quicktime']['video']['codec'] = (($atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']);
+ $info['quicktime']['video']['color_depth'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'];
+ $info['quicktime']['video']['color_depth_name'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_name'];
+
+ $info['video']['codec'] = $info['quicktime']['video']['codec'];
+ $info['video']['bits_per_sample'] = $info['quicktime']['video']['color_depth'];
+ }
+ $info['video']['lossless'] = false;
+ $info['video']['pixel_aspect_ratio'] = (float) 1;
+ break;
+ }
+ break;
+ }
+ switch (strtolower($atom_structure['sample_description_table'][$i]['data_format'])) {
+ case 'mp4a':
+ $info['audio']['dataformat'] = 'mp4';
+ $info['quicktime']['audio']['codec'] = 'mp4';
+ break;
+
+ case '3ivx':
+ case '3iv1':
+ case '3iv2':
+ $info['video']['dataformat'] = '3ivx';
+ break;
+
+ case 'xvid':
+ $info['video']['dataformat'] = 'xvid';
+ break;
+
+ case 'mp4v':
+ $info['video']['dataformat'] = 'mpeg4';
+ break;
+
+ case 'divx':
+ case 'div1':
+ case 'div2':
+ case 'div3':
+ case 'div4':
+ case 'div5':
+ case 'div6':
+ $info['video']['dataformat'] = 'divx';
+ break;
+
+ default:
+ // do nothing
+ break;
+ }
+ unset($atom_structure['sample_description_table'][$i]['data']);
+ }
+ break;
+
+
+ case 'stts': // Sample Table Time-to-Sample atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+ $sttsEntriesDataOffset = 8;
+ //$FrameRateCalculatorArray = array();
+ $frames_count = 0;
+ for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
+ $atom_structure['time_to_sample_table'][$i]['sample_count'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
+ $sttsEntriesDataOffset += 4;
+ $atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
+ $sttsEntriesDataOffset += 4;
+
+ $frames_count += $atom_structure['time_to_sample_table'][$i]['sample_count'];
+
+ // THIS SECTION REPLACED WITH CODE IN "stbl" ATOM
+ //if (!empty($info['quicktime']['time_scale']) && ($atom_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) {
+ // $stts_new_framerate = $info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'];
+ // if ($stts_new_framerate <= 60) {
+ // // some atoms have durations of "1" giving a very large framerate, which probably is not right
+ // $info['video']['frame_rate'] = max($info['video']['frame_rate'], $stts_new_framerate);
+ // }
+ //}
+ //
+ //$FrameRateCalculatorArray[($info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count'];
+ }
+ $info['quicktime']['stts_framecount'][] = $frames_count;
+ //$sttsFramesTotal = 0;
+ //$sttsSecondsTotal = 0;
+ //foreach ($FrameRateCalculatorArray as $frames_per_second => $frame_count) {
+ // if (($frames_per_second > 60) || ($frames_per_second < 1)) {
+ // // not video FPS information, probably audio information
+ // $sttsFramesTotal = 0;
+ // $sttsSecondsTotal = 0;
+ // break;
+ // }
+ // $sttsFramesTotal += $frame_count;
+ // $sttsSecondsTotal += $frame_count / $frames_per_second;
+ //}
+ //if (($sttsFramesTotal > 0) && ($sttsSecondsTotal > 0)) {
+ // if (($sttsFramesTotal / $sttsSecondsTotal) > $info['video']['frame_rate']) {
+ // $info['video']['frame_rate'] = $sttsFramesTotal / $sttsSecondsTotal;
+ // }
+ //}
+ break;
+
+
+ case 'stss': // Sample Table Sync Sample (key frames) atom
+ if ($ParseAllPossibleAtoms) {
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+ $stssEntriesDataOffset = 8;
+ for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
+ $atom_structure['time_to_sample_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stssEntriesDataOffset, 4));
+ $stssEntriesDataOffset += 4;
+ }
+ }
+ break;
+
+
+ case 'stsc': // Sample Table Sample-to-Chunk atom
+ if ($ParseAllPossibleAtoms) {
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+ $stscEntriesDataOffset = 8;
+ for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
+ $atom_structure['sample_to_chunk_table'][$i]['first_chunk'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
+ $stscEntriesDataOffset += 4;
+ $atom_structure['sample_to_chunk_table'][$i]['samples_per_chunk'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
+ $stscEntriesDataOffset += 4;
+ $atom_structure['sample_to_chunk_table'][$i]['sample_description'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
+ $stscEntriesDataOffset += 4;
+ }
+ }
+ break;
+
+
+ case 'stsz': // Sample Table SiZe atom
+ if ($ParseAllPossibleAtoms) {
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['sample_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+ $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
+ $stszEntriesDataOffset = 12;
+ if ($atom_structure['sample_size'] == 0) {
+ for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
+ $atom_structure['sample_size_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stszEntriesDataOffset, 4));
+ $stszEntriesDataOffset += 4;
+ }
+ }
+ }
+ break;
+
+
+ case 'stco': // Sample Table Chunk Offset atom
+ if ($ParseAllPossibleAtoms) {
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+ $stcoEntriesDataOffset = 8;
+ for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
+ $atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 4));
+ $stcoEntriesDataOffset += 4;
+ }
+ }
+ break;
+
+
+ case 'co64': // Chunk Offset 64-bit (version of "stco" that supports > 2GB files)
+ if ($ParseAllPossibleAtoms) {
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+ $stcoEntriesDataOffset = 8;
+ for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
+ $atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 8));
+ $stcoEntriesDataOffset += 8;
+ }
+ }
+ break;
+
+
+ case 'dref': // Data REFerence atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+ $drefDataOffset = 8;
+ for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
+ $atom_structure['data_references'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 4));
+ $drefDataOffset += 4;
+ $atom_structure['data_references'][$i]['type'] = substr($atom_data, $drefDataOffset, 4);
+ $drefDataOffset += 4;
+ $atom_structure['data_references'][$i]['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 1));
+ $drefDataOffset += 1;
+ $atom_structure['data_references'][$i]['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 3)); // hardcoded: 0x0000
+ $drefDataOffset += 3;
+ $atom_structure['data_references'][$i]['data'] = substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3));
+ $drefDataOffset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3);
+
+ $atom_structure['data_references'][$i]['flags']['self_reference'] = (bool) ($atom_structure['data_references'][$i]['flags_raw'] & 0x001);
+ }
+ break;
+
+
+ case 'gmin': // base Media INformation atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['graphics_mode'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
+ $atom_structure['opcolor_red'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2));
+ $atom_structure['opcolor_green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 2));
+ $atom_structure['opcolor_blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2));
+ $atom_structure['balance'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 2));
+ $atom_structure['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2));
+ break;
+
+
+ case 'smhd': // Sound Media information HeaDer atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['balance'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
+ $atom_structure['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2));
+ break;
+
+
+ case 'vmhd': // Video Media information HeaDer atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
+ $atom_structure['graphics_mode'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
+ $atom_structure['opcolor_red'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2));
+ $atom_structure['opcolor_green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 2));
+ $atom_structure['opcolor_blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2));
+
+ $atom_structure['flags']['no_lean_ahead'] = (bool) ($atom_structure['flags_raw'] & 0x001);
+ break;
+
+
+ case 'hdlr': // HanDLeR reference atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['component_type'] = substr($atom_data, 4, 4);
+ $atom_structure['component_subtype'] = substr($atom_data, 8, 4);
+ $atom_structure['component_manufacturer'] = substr($atom_data, 12, 4);
+ $atom_structure['component_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
+ $atom_structure['component_flags_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
+ $atom_structure['component_name'] = $this->Pascal2String(substr($atom_data, 24));
+
+ if (($atom_structure['component_subtype'] == 'STpn') && ($atom_structure['component_manufacturer'] == 'zzzz')) {
+ $info['video']['dataformat'] = 'quicktimevr';
+ }
+ break;
+
+
+ case 'mdhd': // MeDia HeaDer atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+ $atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
+ $atom_structure['time_scale'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
+ $atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
+ $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 2));
+ $atom_structure['quality'] = getid3_lib::BigEndian2Int(substr($atom_data, 22, 2));
+
+ if ($atom_structure['time_scale'] == 0) {
+ $info['error'][] = 'Corrupt Quicktime file: mdhd.time_scale == zero';
+ return false;
+ }
+ $info['quicktime']['time_scale'] = (isset($info['quicktime']['time_scale']) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
+
+ $atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
+ $atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
+ $atom_structure['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale'];
+ $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
+ if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
+ $info['comments']['language'][] = $atom_structure['language'];
+ }
+ break;
+
+
+ case 'pnot': // Preview atom
+ $atom_structure['modification_date'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // "standard Macintosh format"
+ $atom_structure['version_number'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x00
+ $atom_structure['atom_type'] = substr($atom_data, 6, 4); // usually: 'PICT'
+ $atom_structure['atom_index'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); // usually: 0x01
+
+ $atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']);
+ break;
+
+
+ case 'crgn': // Clipping ReGioN atom
+ $atom_structure['region_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); // The Region size, Region boundary box,
+ $atom_structure['boundary_box'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 8)); // and Clipping region data fields
+ $atom_structure['clipping_data'] = substr($atom_data, 10); // constitute a QuickDraw region.
+ break;
+
+
+ case 'load': // track LOAD settings atom
+ $atom_structure['preload_start_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
+ $atom_structure['preload_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+ $atom_structure['preload_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
+ $atom_structure['default_hints_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
+
+ $atom_structure['default_hints']['double_buffer'] = (bool) ($atom_structure['default_hints_raw'] & 0x0020);
+ $atom_structure['default_hints']['high_quality'] = (bool) ($atom_structure['default_hints_raw'] & 0x0100);
+ break;
+
+
+ case 'tmcd': // TiMe CoDe atom
+ case 'chap': // CHAPter list atom
+ case 'sync': // SYNChronization atom
+ case 'scpt': // tranSCriPT atom
+ case 'ssrc': // non-primary SouRCe atom
+ for ($i = 0; $i < (strlen($atom_data) % 4); $i++) {
+ $atom_structure['track_id'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $i * 4, 4));
+ }
+ break;
+
+
+ case 'elst': // Edit LiST atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+ for ($i = 0; $i < $atom_structure['number_entries']; $i++ ) {
+ $atom_structure['edit_list'][$i]['track_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 0, 4));
+ $atom_structure['edit_list'][$i]['media_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 4, 4));
+ $atom_structure['edit_list'][$i]['media_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 8 + ($i * 12) + 8, 4));
+ }
+ break;
+
+
+ case 'kmat': // compressed MATte atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
+ $atom_structure['matte_data_raw'] = substr($atom_data, 4);
+ break;
+
+
+ case 'ctab': // Color TABle atom
+ $atom_structure['color_table_seed'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // hardcoded: 0x00000000
+ $atom_structure['color_table_flags'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x8000
+ $atom_structure['color_table_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)) + 1;
+ for ($colortableentry = 0; $colortableentry < $atom_structure['color_table_size']; $colortableentry++) {
+ $atom_structure['color_table'][$colortableentry]['alpha'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 0, 2));
+ $atom_structure['color_table'][$colortableentry]['red'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 2, 2));
+ $atom_structure['color_table'][$colortableentry]['green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 4, 2));
+ $atom_structure['color_table'][$colortableentry]['blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 6, 2));
+ }
+ break;
+
+
+ case 'mvhd': // MoVie HeaDer atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
+ $atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+ $atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
+ $atom_structure['time_scale'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
+ $atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
+ $atom_structure['preferred_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 20, 4));
+ $atom_structure['preferred_volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 24, 2));
+ $atom_structure['reserved'] = substr($atom_data, 26, 10);
+ $atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 36, 4));
+ $atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
+ $atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 44, 4));
+ $atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 48, 4));
+ $atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
+ $atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 56, 4));
+ $atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 60, 4));
+ $atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
+ $atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 68, 4));
+ $atom_structure['preview_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 72, 4));
+ $atom_structure['preview_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 76, 4));
+ $atom_structure['poster_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 80, 4));
+ $atom_structure['selection_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 84, 4));
+ $atom_structure['selection_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 88, 4));
+ $atom_structure['current_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 92, 4));
+ $atom_structure['next_track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 96, 4));
+
+ if ($atom_structure['time_scale'] == 0) {
+ $info['error'][] = 'Corrupt Quicktime file: mvhd.time_scale == zero';
+ return false;
+ }
+ $atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
+ $atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
+ $info['quicktime']['time_scale'] = (isset($info['quicktime']['time_scale']) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
+ $info['quicktime']['display_scale'] = $atom_structure['matrix_a'];
+ $info['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale'];
+ break;
+
+
+ case 'tkhd': // TracK HeaDer atom
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
+ $atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+ $atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
+ $atom_structure['trackid'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
+ $atom_structure['reserved1'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
+ $atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
+ $atom_structure['reserved2'] = getid3_lib::BigEndian2Int(substr($atom_data, 24, 8));
+ $atom_structure['layer'] = getid3_lib::BigEndian2Int(substr($atom_data, 32, 2));
+ $atom_structure['alternate_group'] = getid3_lib::BigEndian2Int(substr($atom_data, 34, 2));
+ $atom_structure['volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 36, 2));
+ $atom_structure['reserved3'] = getid3_lib::BigEndian2Int(substr($atom_data, 38, 2));
+// http://developer.apple.com/library/mac/#documentation/QuickTime/RM/MovieBasics/MTEditing/K-Chapter/11MatrixFunctions.html
+// http://developer.apple.com/library/mac/#documentation/QuickTime/qtff/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-18737
+ $atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
+ $atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 44, 4));
+ $atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 48, 4));
+ $atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
+ $atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 56, 4));
+ $atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 60, 4));
+ $atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
+ $atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 68, 4));
+ $atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 72, 4));
+ $atom_structure['width'] = getid3_lib::FixedPoint16_16(substr($atom_data, 76, 4));
+ $atom_structure['height'] = getid3_lib::FixedPoint16_16(substr($atom_data, 80, 4));
+ $atom_structure['flags']['enabled'] = (bool) ($atom_structure['flags_raw'] & 0x0001);
+ $atom_structure['flags']['in_movie'] = (bool) ($atom_structure['flags_raw'] & 0x0002);
+ $atom_structure['flags']['in_preview'] = (bool) ($atom_structure['flags_raw'] & 0x0004);
+ $atom_structure['flags']['in_poster'] = (bool) ($atom_structure['flags_raw'] & 0x0008);
+ $atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
+ $atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
+
+ if ($atom_structure['flags']['enabled'] == 1) {
+ if (!isset($info['video']['resolution_x']) || !isset($info['video']['resolution_y'])) {
+ $info['video']['resolution_x'] = $atom_structure['width'];
+ $info['video']['resolution_y'] = $atom_structure['height'];
+ }
+ $info['video']['resolution_x'] = max($info['video']['resolution_x'], $atom_structure['width']);
+ $info['video']['resolution_y'] = max($info['video']['resolution_y'], $atom_structure['height']);
+ $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
+ $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
+ } else {
+ // see: http://www.getid3.org/phpBB3/viewtopic.php?t=1295
+ //if (isset($info['video']['resolution_x'])) { unset($info['video']['resolution_x']); }
+ //if (isset($info['video']['resolution_y'])) { unset($info['video']['resolution_y']); }
+ //if (isset($info['quicktime']['video'])) { unset($info['quicktime']['video']); }
+ }
+ break;
+
+
+ case 'iods': // Initial Object DeScriptor atom
+ // http://www.koders.com/c/fid1FAB3E762903DC482D8A246D4A4BF9F28E049594.aspx?s=windows.h
+ // http://libquicktime.sourcearchive.com/documentation/1.0.2plus-pdebian/iods_8c-source.html
+ $offset = 0;
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+ $offset += 1;
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 3));
+ $offset += 3;
+ $atom_structure['mp4_iod_tag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+ $offset += 1;
+ $atom_structure['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
+ //$offset already adjusted by quicktime_read_mp4_descr_length()
+ $atom_structure['object_descriptor_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2));
+ $offset += 2;
+ $atom_structure['od_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+ $offset += 1;
+ $atom_structure['scene_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+ $offset += 1;
+ $atom_structure['audio_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+ $offset += 1;
+ $atom_structure['video_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+ $offset += 1;
+ $atom_structure['graphics_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+ $offset += 1;
+
+ $atom_structure['num_iods_tracks'] = ($atom_structure['length'] - 7) / 6; // 6 bytes would only be right if all tracks use 1-byte length fields
+ for ($i = 0; $i < $atom_structure['num_iods_tracks']; $i++) {
+ $atom_structure['track'][$i]['ES_ID_IncTag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+ $offset += 1;
+ $atom_structure['track'][$i]['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
+ //$offset already adjusted by quicktime_read_mp4_descr_length()
+ $atom_structure['track'][$i]['track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4));
+ $offset += 4;
+ }
+
+ $atom_structure['audio_profile_name'] = $this->QuicktimeIODSaudioProfileName($atom_structure['audio_profile_id']);
+ $atom_structure['video_profile_name'] = $this->QuicktimeIODSvideoProfileName($atom_structure['video_profile_id']);
+ break;
+
+ case 'ftyp': // FileTYPe (?) atom (for MP4 it seems)
+ $atom_structure['signature'] = substr($atom_data, 0, 4);
+ $atom_structure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
+ $atom_structure['fourcc'] = substr($atom_data, 8, 4);
+ break;
+
+ case 'mdat': // Media DATa atom
+ case 'free': // FREE space atom
+ case 'skip': // SKIP atom
+ case 'wide': // 64-bit expansion placeholder atom
+ // 'mdat' data is too big to deal with, contains no useful metadata
+ // 'free', 'skip' and 'wide' are just padding, contains no useful data at all
+
+ // When writing QuickTime files, it is sometimes necessary to update an atom's size.
+ // It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom
+ // is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime
+ // puts an 8-byte placeholder atom before any atoms it may have to update the size of.
+ // In this way, if the atom needs to be converted from a 32-bit to a 64-bit atom, the
+ // placeholder atom can be overwritten to obtain the necessary 8 extra bytes.
+ // The placeholder atom has a type of kWideAtomPlaceholderType ( 'wide' ).
+ break;
+
+
+ case 'nsav': // NoSAVe atom
+ // http://developer.apple.com/technotes/tn/tn2038.html
+ $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
+ break;
+
+ case 'ctyp': // Controller TYPe atom (seen on QTVR)
+ // http://homepages.slingshot.co.nz/~helmboy/quicktime/formats/qtm-layout.txt
+ // some controller names are:
+ // 0x00 + 'std' for linear movie
+ // 'none' for no controls
+ $atom_structure['ctyp'] = substr($atom_data, 0, 4);
+ $info['quicktime']['controller'] = $atom_structure['ctyp'];
+ switch ($atom_structure['ctyp']) {
+ case 'qtvr':
+ $info['video']['dataformat'] = 'quicktimevr';
+ break;
+ }
+ break;
+
+ case 'pano': // PANOrama track (seen on QTVR)
+ $atom_structure['pano'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
+ break;
+
+ case 'hint': // HINT track
+ case 'hinf': //
+ case 'hinv': //
+ case 'hnti': //
+ $info['quicktime']['hinting'] = true;
+ break;
+
+ case 'imgt': // IMaGe Track reference (kQTVRImageTrackRefType) (seen on QTVR)
+ for ($i = 0; $i < ($atom_structure['size'] - 8); $i += 4) {
+ $atom_structure['imgt'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4));
+ }
+ break;
+
+
+ // Observed-but-not-handled atom types are just listed here to prevent warnings being generated
+ case 'FXTC': // Something to do with Adobe After Effects (?)
+ case 'PrmA':
+ case 'code':
+ case 'FIEL': // this is NOT "fiel" (Field Ordering) as describe here: http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html
+ case 'tapt': // TrackApertureModeDimensionsAID - http://developer.apple.com/documentation/QuickTime/Reference/QT7-1_Update_Reference/Constants/Constants.html
+ // tapt seems to be used to compute the video size [http://www.getid3.org/phpBB3/viewtopic.php?t=838]
+ // * http://lists.apple.com/archives/quicktime-api/2006/Aug/msg00014.html
+ // * http://handbrake.fr/irclogs/handbrake-dev/handbrake-dev20080128_pg2.html
+ case 'ctts':// STCompositionOffsetAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
+ case 'cslg':// STCompositionShiftLeastGreatestAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
+ case 'sdtp':// STSampleDependencyAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
+ case 'stps':// STPartialSyncSampleAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
+ //$atom_structure['data'] = $atom_data;
+ break;
+
+ case '©xyz': // GPS latitude+longitude+altitude
+ $atom_structure['data'] = $atom_data;
+ if (preg_match('#([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)?/$#i', $atom_data, $matches)) {
+ @list($all, $latitude, $longitude, $altitude) = $matches;
+ $info['quicktime']['comments']['gps_latitude'][] = floatval($latitude);
+ $info['quicktime']['comments']['gps_longitude'][] = floatval($longitude);
+ if (!empty($altitude)) {
+ $info['quicktime']['comments']['gps_altitude'][] = floatval($altitude);
+ }
+ } else {
+ $info['warning'][] = 'QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.';
+ }
+ break;
+
+ case 'NCDT':
+ // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
+ // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100
+ $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 4, $atomHierarchy, $ParseAllPossibleAtoms);
+ break;
+ case 'NCTH': // Nikon Camera THumbnail image
+ case 'NCVW': // Nikon Camera preVieW image
+ // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
+ if (preg_match('/^\xFF\xD8\xFF/', $atom_data)) {
+ $atom_structure['data'] = $atom_data;
+ $atom_structure['image_mime'] = 'image/jpeg';
+ $atom_structure['description'] = (($atomname == 'NCTH') ? 'Nikon Camera Thumbnail Image' : (($atomname == 'NCVW') ? 'Nikon Camera Preview Image' : 'Nikon preview image'));
+ $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']);
+ }
+ break;
+ case 'NCHD': // MakerNoteVersion
+ // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
+ $atom_structure['data'] = $atom_data;
+ break;
+ case 'NCTG': // NikonTags
+ // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
+ $atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data);
+ break;
+ case 'NCDB': // NikonTags
+ // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
+ $atom_structure['data'] = $atom_data;
+ break;
+
+ case "\x00\x00\x00\x00":
+ case 'meta': // METAdata atom
+ // some kind of metacontainer, may contain a big data dump such as:
+ // mdta keys  mdtacom.apple.quicktime.make (mdtacom.apple.quicktime.creationdate ,mdtacom.apple.quicktime.location.ISO6709 $mdtacom.apple.quicktime.software !mdtacom.apple.quicktime.model ilst   data DEApple 0  (data DE2011-05-11T17:54:04+0200 2  *data DE+52.4936+013.3897+040.247/   data DE4.3.1  data DEiPhone 4
+ // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt
+
+ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+ $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
+ $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
+ //$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
+ break;
+
+ case 'data': // metaDATA atom
+ // seems to be 2 bytes language code (ASCII), 2 bytes unknown (set to 0x10B5 in sample I have), remainder is useful data
+ $atom_structure['language'] = substr($atom_data, 4 + 0, 2);
+ $atom_structure['unknown'] = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2));
+ $atom_structure['data'] = substr($atom_data, 4 + 4);
+ break;
+
+ default:
+ $info['warning'][] = 'Unknown QuickTime atom type: "'.$atomname.'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset;
+ $atom_structure['data'] = $atom_data;
+ break;
+ }
+ array_pop($atomHierarchy);
+ return $atom_structure;
+ }
+
+ public function QuicktimeParseContainerAtom($atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
+//echo 'QuicktimeParseContainerAtom('.substr($atom_data, 4, 4).') @ '.$baseoffset.'<br><br>';
+ $atom_structure = false;
+ $subatomoffset = 0;
+ $subatomcounter = 0;
+ if ((strlen($atom_data) == 4) && (getid3_lib::BigEndian2Int($atom_data) == 0x00000000)) {
+ return false;
+ }
+ while ($subatomoffset < strlen($atom_data)) {
+ $subatomsize = getid3_lib::BigEndian2Int(substr($atom_data, $subatomoffset + 0, 4));
+ $subatomname = substr($atom_data, $subatomoffset + 4, 4);
+ $subatomdata = substr($atom_data, $subatomoffset + 8, $subatomsize - 8);
+ if ($subatomsize == 0) {
+ // Furthermore, for historical reasons the list of atoms is optionally
+ // terminated by a 32-bit integer set to 0. If you are writing a program
+ // to read user data atoms, you should allow for the terminating 0.
+ return $atom_structure;
+ }
+
+ $atom_structure[$subatomcounter] = $this->QuicktimeParseAtom($subatomname, $subatomsize, $subatomdata, $baseoffset + $subatomoffset, $atomHierarchy, $ParseAllPossibleAtoms);
+
+ $subatomoffset += $subatomsize;
+ $subatomcounter++;
+ }
+ return $atom_structure;
+ }
+
+
+ public function quicktime_read_mp4_descr_length($data, &$offset) {
+ // http://libquicktime.sourcearchive.com/documentation/2:1.0.2plus-pdebian-2build1/esds_8c-source.html
+ $num_bytes = 0;
+ $length = 0;
+ do {
+ $b = ord(substr($data, $offset++, 1));
+ $length = ($length << 7) | ($b & 0x7F);
+ } while (($b & 0x80) && ($num_bytes++ < 4));
+ return $length;
+ }
+
+
+ public function QuicktimeLanguageLookup($languageid) {
+ static $QuicktimeLanguageLookup = array();
+ if (empty($QuicktimeLanguageLookup)) {
+ $QuicktimeLanguageLookup[0] = 'English';
+ $QuicktimeLanguageLookup[1] = 'French';
+ $QuicktimeLanguageLookup[2] = 'German';
+ $QuicktimeLanguageLookup[3] = 'Italian';
+ $QuicktimeLanguageLookup[4] = 'Dutch';
+ $QuicktimeLanguageLookup[5] = 'Swedish';
+ $QuicktimeLanguageLookup[6] = 'Spanish';
+ $QuicktimeLanguageLookup[7] = 'Danish';
+ $QuicktimeLanguageLookup[8] = 'Portuguese';
+ $QuicktimeLanguageLookup[9] = 'Norwegian';
+ $QuicktimeLanguageLookup[10] = 'Hebrew';
+ $QuicktimeLanguageLookup[11] = 'Japanese';
+ $QuicktimeLanguageLookup[12] = 'Arabic';
+ $QuicktimeLanguageLookup[13] = 'Finnish';
+ $QuicktimeLanguageLookup[14] = 'Greek';
+ $QuicktimeLanguageLookup[15] = 'Icelandic';
+ $QuicktimeLanguageLookup[16] = 'Maltese';
+ $QuicktimeLanguageLookup[17] = 'Turkish';
+ $QuicktimeLanguageLookup[18] = 'Croatian';
+ $QuicktimeLanguageLookup[19] = 'Chinese (Traditional)';
+ $QuicktimeLanguageLookup[20] = 'Urdu';
+ $QuicktimeLanguageLookup[21] = 'Hindi';
+ $QuicktimeLanguageLookup[22] = 'Thai';
+ $QuicktimeLanguageLookup[23] = 'Korean';
+ $QuicktimeLanguageLookup[24] = 'Lithuanian';
+ $QuicktimeLanguageLookup[25] = 'Polish';
+ $QuicktimeLanguageLookup[26] = 'Hungarian';
+ $QuicktimeLanguageLookup[27] = 'Estonian';
+ $QuicktimeLanguageLookup[28] = 'Lettish';
+ $QuicktimeLanguageLookup[28] = 'Latvian';
+ $QuicktimeLanguageLookup[29] = 'Saamisk';
+ $QuicktimeLanguageLookup[29] = 'Lappish';
+ $QuicktimeLanguageLookup[30] = 'Faeroese';
+ $QuicktimeLanguageLookup[31] = 'Farsi';
+ $QuicktimeLanguageLookup[31] = 'Persian';
+ $QuicktimeLanguageLookup[32] = 'Russian';
+ $QuicktimeLanguageLookup[33] = 'Chinese (Simplified)';
+ $QuicktimeLanguageLookup[34] = 'Flemish';
+ $QuicktimeLanguageLookup[35] = 'Irish';
+ $QuicktimeLanguageLookup[36] = 'Albanian';
+ $QuicktimeLanguageLookup[37] = 'Romanian';
+ $QuicktimeLanguageLookup[38] = 'Czech';
+ $QuicktimeLanguageLookup[39] = 'Slovak';
+ $QuicktimeLanguageLookup[40] = 'Slovenian';
+ $QuicktimeLanguageLookup[41] = 'Yiddish';
+ $QuicktimeLanguageLookup[42] = 'Serbian';
+ $QuicktimeLanguageLookup[43] = 'Macedonian';
+ $QuicktimeLanguageLookup[44] = 'Bulgarian';
+ $QuicktimeLanguageLookup[45] = 'Ukrainian';
+ $QuicktimeLanguageLookup[46] = 'Byelorussian';
+ $QuicktimeLanguageLookup[47] = 'Uzbek';
+ $QuicktimeLanguageLookup[48] = 'Kazakh';
+ $QuicktimeLanguageLookup[49] = 'Azerbaijani';
+ $QuicktimeLanguageLookup[50] = 'AzerbaijanAr';
+ $QuicktimeLanguageLookup[51] = 'Armenian';
+ $QuicktimeLanguageLookup[52] = 'Georgian';
+ $QuicktimeLanguageLookup[53] = 'Moldavian';
+ $QuicktimeLanguageLookup[54] = 'Kirghiz';
+ $QuicktimeLanguageLookup[55] = 'Tajiki';
+ $QuicktimeLanguageLookup[56] = 'Turkmen';
+ $QuicktimeLanguageLookup[57] = 'Mongolian';
+ $QuicktimeLanguageLookup[58] = 'MongolianCyr';
+ $QuicktimeLanguageLookup[59] = 'Pashto';
+ $QuicktimeLanguageLookup[60] = 'Kurdish';
+ $QuicktimeLanguageLookup[61] = 'Kashmiri';
+ $QuicktimeLanguageLookup[62] = 'Sindhi';
+ $QuicktimeLanguageLookup[63] = 'Tibetan';
+ $QuicktimeLanguageLookup[64] = 'Nepali';
+ $QuicktimeLanguageLookup[65] = 'Sanskrit';
+ $QuicktimeLanguageLookup[66] = 'Marathi';
+ $QuicktimeLanguageLookup[67] = 'Bengali';
+ $QuicktimeLanguageLookup[68] = 'Assamese';
+ $QuicktimeLanguageLookup[69] = 'Gujarati';
+ $QuicktimeLanguageLookup[70] = 'Punjabi';
+ $QuicktimeLanguageLookup[71] = 'Oriya';
+ $QuicktimeLanguageLookup[72] = 'Malayalam';
+ $QuicktimeLanguageLookup[73] = 'Kannada';
+ $QuicktimeLanguageLookup[74] = 'Tamil';
+ $QuicktimeLanguageLookup[75] = 'Telugu';
+ $QuicktimeLanguageLookup[76] = 'Sinhalese';
+ $QuicktimeLanguageLookup[77] = 'Burmese';
+ $QuicktimeLanguageLookup[78] = 'Khmer';
+ $QuicktimeLanguageLookup[79] = 'Lao';
+ $QuicktimeLanguageLookup[80] = 'Vietnamese';
+ $QuicktimeLanguageLookup[81] = 'Indonesian';
+ $QuicktimeLanguageLookup[82] = 'Tagalog';
+ $QuicktimeLanguageLookup[83] = 'MalayRoman';
+ $QuicktimeLanguageLookup[84] = 'MalayArabic';
+ $QuicktimeLanguageLookup[85] = 'Amharic';
+ $QuicktimeLanguageLookup[86] = 'Tigrinya';
+ $QuicktimeLanguageLookup[87] = 'Galla';
+ $QuicktimeLanguageLookup[87] = 'Oromo';
+ $QuicktimeLanguageLookup[88] = 'Somali';
+ $QuicktimeLanguageLookup[89] = 'Swahili';
+ $QuicktimeLanguageLookup[90] = 'Ruanda';
+ $QuicktimeLanguageLookup[91] = 'Rundi';
+ $QuicktimeLanguageLookup[92] = 'Chewa';
+ $QuicktimeLanguageLookup[93] = 'Malagasy';
+ $QuicktimeLanguageLookup[94] = 'Esperanto';
+ $QuicktimeLanguageLookup[128] = 'Welsh';
+ $QuicktimeLanguageLookup[129] = 'Basque';
+ $QuicktimeLanguageLookup[130] = 'Catalan';
+ $QuicktimeLanguageLookup[131] = 'Latin';
+ $QuicktimeLanguageLookup[132] = 'Quechua';
+ $QuicktimeLanguageLookup[133] = 'Guarani';
+ $QuicktimeLanguageLookup[134] = 'Aymara';
+ $QuicktimeLanguageLookup[135] = 'Tatar';
+ $QuicktimeLanguageLookup[136] = 'Uighur';
+ $QuicktimeLanguageLookup[137] = 'Dzongkha';
+ $QuicktimeLanguageLookup[138] = 'JavaneseRom';
+ }
+ return (isset($QuicktimeLanguageLookup[$languageid]) ? $QuicktimeLanguageLookup[$languageid] : 'invalid');
+ }
+
+ public function QuicktimeVideoCodecLookup($codecid) {
+ static $QuicktimeVideoCodecLookup = array();
+ if (empty($QuicktimeVideoCodecLookup)) {
+ $QuicktimeVideoCodecLookup['.SGI'] = 'SGI';
+ $QuicktimeVideoCodecLookup['3IV1'] = '3ivx MPEG-4 v1';
+ $QuicktimeVideoCodecLookup['3IV2'] = '3ivx MPEG-4 v2';
+ $QuicktimeVideoCodecLookup['3IVX'] = '3ivx MPEG-4';
+ $QuicktimeVideoCodecLookup['8BPS'] = 'Planar RGB';
+ $QuicktimeVideoCodecLookup['avc1'] = 'H.264/MPEG-4 AVC';
+ $QuicktimeVideoCodecLookup['avr '] = 'AVR-JPEG';
+ $QuicktimeVideoCodecLookup['b16g'] = '16Gray';
+ $QuicktimeVideoCodecLookup['b32a'] = '32AlphaGray';
+ $QuicktimeVideoCodecLookup['b48r'] = '48RGB';
+ $QuicktimeVideoCodecLookup['b64a'] = '64ARGB';
+ $QuicktimeVideoCodecLookup['base'] = 'Base';
+ $QuicktimeVideoCodecLookup['clou'] = 'Cloud';
+ $QuicktimeVideoCodecLookup['cmyk'] = 'CMYK';
+ $QuicktimeVideoCodecLookup['cvid'] = 'Cinepak';
+ $QuicktimeVideoCodecLookup['dmb1'] = 'OpenDML JPEG';
+ $QuicktimeVideoCodecLookup['dvc '] = 'DVC-NTSC';
+ $QuicktimeVideoCodecLookup['dvcp'] = 'DVC-PAL';
+ $QuicktimeVideoCodecLookup['dvpn'] = 'DVCPro-NTSC';
+ $QuicktimeVideoCodecLookup['dvpp'] = 'DVCPro-PAL';
+ $QuicktimeVideoCodecLookup['fire'] = 'Fire';
+ $QuicktimeVideoCodecLookup['flic'] = 'FLC';
+ $QuicktimeVideoCodecLookup['gif '] = 'GIF';
+ $QuicktimeVideoCodecLookup['h261'] = 'H261';
+ $QuicktimeVideoCodecLookup['h263'] = 'H263';
+ $QuicktimeVideoCodecLookup['IV41'] = 'Indeo4';
+ $QuicktimeVideoCodecLookup['jpeg'] = 'JPEG';
+ $QuicktimeVideoCodecLookup['kpcd'] = 'PhotoCD';
+ $QuicktimeVideoCodecLookup['mjpa'] = 'Motion JPEG-A';
+ $QuicktimeVideoCodecLookup['mjpb'] = 'Motion JPEG-B';
+ $QuicktimeVideoCodecLookup['msvc'] = 'Microsoft Video1';
+ $QuicktimeVideoCodecLookup['myuv'] = 'MPEG YUV420';
+ $QuicktimeVideoCodecLookup['path'] = 'Vector';
+ $QuicktimeVideoCodecLookup['png '] = 'PNG';
+ $QuicktimeVideoCodecLookup['PNTG'] = 'MacPaint';
+ $QuicktimeVideoCodecLookup['qdgx'] = 'QuickDrawGX';
+ $QuicktimeVideoCodecLookup['qdrw'] = 'QuickDraw';
+ $QuicktimeVideoCodecLookup['raw '] = 'RAW';
+ $QuicktimeVideoCodecLookup['ripl'] = 'WaterRipple';
+ $QuicktimeVideoCodecLookup['rpza'] = 'Video';
+ $QuicktimeVideoCodecLookup['smc '] = 'Graphics';
+ $QuicktimeVideoCodecLookup['SVQ1'] = 'Sorenson Video 1';
+ $QuicktimeVideoCodecLookup['SVQ1'] = 'Sorenson Video 3';
+ $QuicktimeVideoCodecLookup['syv9'] = 'Sorenson YUV9';
+ $QuicktimeVideoCodecLookup['tga '] = 'Targa';
+ $QuicktimeVideoCodecLookup['tiff'] = 'TIFF';
+ $QuicktimeVideoCodecLookup['WRAW'] = 'Windows RAW';
+ $QuicktimeVideoCodecLookup['WRLE'] = 'BMP';
+ $QuicktimeVideoCodecLookup['y420'] = 'YUV420';
+ $QuicktimeVideoCodecLookup['yuv2'] = 'ComponentVideo';
+ $QuicktimeVideoCodecLookup['yuvs'] = 'ComponentVideoUnsigned';
+ $QuicktimeVideoCodecLookup['yuvu'] = 'ComponentVideoSigned';
+ }
+ return (isset($QuicktimeVideoCodecLookup[$codecid]) ? $QuicktimeVideoCodecLookup[$codecid] : '');
+ }
+
+ public function QuicktimeAudioCodecLookup($codecid) {
+ static $QuicktimeAudioCodecLookup = array();
+ if (empty($QuicktimeAudioCodecLookup)) {
+ $QuicktimeAudioCodecLookup['.mp3'] = 'Fraunhofer MPEG Layer-III alias';
+ $QuicktimeAudioCodecLookup['aac '] = 'ISO/IEC 14496-3 AAC';
+ $QuicktimeAudioCodecLookup['agsm'] = 'Apple GSM 10:1';
+ $QuicktimeAudioCodecLookup['alac'] = 'Apple Lossless Audio Codec';
+ $QuicktimeAudioCodecLookup['alaw'] = 'A-law 2:1';
+ $QuicktimeAudioCodecLookup['conv'] = 'Sample Format';
+ $QuicktimeAudioCodecLookup['dvca'] = 'DV';
+ $QuicktimeAudioCodecLookup['dvi '] = 'DV 4:1';
+ $QuicktimeAudioCodecLookup['eqal'] = 'Frequency Equalizer';
+ $QuicktimeAudioCodecLookup['fl32'] = '32-bit Floating Point';
+ $QuicktimeAudioCodecLookup['fl64'] = '64-bit Floating Point';
+ $QuicktimeAudioCodecLookup['ima4'] = 'Interactive Multimedia Association 4:1';
+ $QuicktimeAudioCodecLookup['in24'] = '24-bit Integer';
+ $QuicktimeAudioCodecLookup['in32'] = '32-bit Integer';
+ $QuicktimeAudioCodecLookup['lpc '] = 'LPC 23:1';
+ $QuicktimeAudioCodecLookup['MAC3'] = 'Macintosh Audio Compression/Expansion (MACE) 3:1';
+ $QuicktimeAudioCodecLookup['MAC6'] = 'Macintosh Audio Compression/Expansion (MACE) 6:1';
+ $QuicktimeAudioCodecLookup['mixb'] = '8-bit Mixer';
+ $QuicktimeAudioCodecLookup['mixw'] = '16-bit Mixer';
+ $QuicktimeAudioCodecLookup['mp4a'] = 'ISO/IEC 14496-3 AAC';
+ $QuicktimeAudioCodecLookup['MS'."\x00\x02"] = 'Microsoft ADPCM';
+ $QuicktimeAudioCodecLookup['MS'."\x00\x11"] = 'DV IMA';
+ $QuicktimeAudioCodecLookup['MS'."\x00\x55"] = 'Fraunhofer MPEG Layer III';
+ $QuicktimeAudioCodecLookup['NONE'] = 'No Encoding';
+ $QuicktimeAudioCodecLookup['Qclp'] = 'Qualcomm PureVoice';
+ $QuicktimeAudioCodecLookup['QDM2'] = 'QDesign Music 2';
+ $QuicktimeAudioCodecLookup['QDMC'] = 'QDesign Music 1';
+ $QuicktimeAudioCodecLookup['ratb'] = '8-bit Rate';
+ $QuicktimeAudioCodecLookup['ratw'] = '16-bit Rate';
+ $QuicktimeAudioCodecLookup['raw '] = 'raw PCM';
+ $QuicktimeAudioCodecLookup['sour'] = 'Sound Source';
+ $QuicktimeAudioCodecLookup['sowt'] = 'signed/two\'s complement (Little Endian)';
+ $QuicktimeAudioCodecLookup['str1'] = 'Iomega MPEG layer II';
+ $QuicktimeAudioCodecLookup['str2'] = 'Iomega MPEG *layer II';
+ $QuicktimeAudioCodecLookup['str3'] = 'Iomega MPEG **layer II';
+ $QuicktimeAudioCodecLookup['str4'] = 'Iomega MPEG ***layer II';
+ $QuicktimeAudioCodecLookup['twos'] = 'signed/two\'s complement (Big Endian)';
+ $QuicktimeAudioCodecLookup['ulaw'] = 'mu-law 2:1';
+ }
+ return (isset($QuicktimeAudioCodecLookup[$codecid]) ? $QuicktimeAudioCodecLookup[$codecid] : '');
+ }
+
+ public function QuicktimeDCOMLookup($compressionid) {
+ static $QuicktimeDCOMLookup = array();
+ if (empty($QuicktimeDCOMLookup)) {
+ $QuicktimeDCOMLookup['zlib'] = 'ZLib Deflate';
+ $QuicktimeDCOMLookup['adec'] = 'Apple Compression';
+ }
+ return (isset($QuicktimeDCOMLookup[$compressionid]) ? $QuicktimeDCOMLookup[$compressionid] : '');
+ }
+
+ public function QuicktimeColorNameLookup($colordepthid) {
+ static $QuicktimeColorNameLookup = array();
+ if (empty($QuicktimeColorNameLookup)) {
+ $QuicktimeColorNameLookup[1] = '2-color (monochrome)';
+ $QuicktimeColorNameLookup[2] = '4-color';
+ $QuicktimeColorNameLookup[4] = '16-color';
+ $QuicktimeColorNameLookup[8] = '256-color';
+ $QuicktimeColorNameLookup[16] = 'thousands (16-bit color)';
+ $QuicktimeColorNameLookup[24] = 'millions (24-bit color)';
+ $QuicktimeColorNameLookup[32] = 'millions+ (32-bit color)';
+ $QuicktimeColorNameLookup[33] = 'black & white';
+ $QuicktimeColorNameLookup[34] = '4-gray';
+ $QuicktimeColorNameLookup[36] = '16-gray';
+ $QuicktimeColorNameLookup[40] = '256-gray';
+ }
+ return (isset($QuicktimeColorNameLookup[$colordepthid]) ? $QuicktimeColorNameLookup[$colordepthid] : 'invalid');
+ }
+
+ public function QuicktimeSTIKLookup($stik) {
+ static $QuicktimeSTIKLookup = array();
+ if (empty($QuicktimeSTIKLookup)) {
+ $QuicktimeSTIKLookup[0] = 'Movie';
+ $QuicktimeSTIKLookup[1] = 'Normal';
+ $QuicktimeSTIKLookup[2] = 'Audiobook';
+ $QuicktimeSTIKLookup[5] = 'Whacked Bookmark';
+ $QuicktimeSTIKLookup[6] = 'Music Video';
+ $QuicktimeSTIKLookup[9] = 'Short Film';
+ $QuicktimeSTIKLookup[10] = 'TV Show';
+ $QuicktimeSTIKLookup[11] = 'Booklet';
+ $QuicktimeSTIKLookup[14] = 'Ringtone';
+ $QuicktimeSTIKLookup[21] = 'Podcast';
+ }
+ return (isset($QuicktimeSTIKLookup[$stik]) ? $QuicktimeSTIKLookup[$stik] : 'invalid');
+ }
+
+ public function QuicktimeIODSaudioProfileName($audio_profile_id) {
+ static $QuicktimeIODSaudioProfileNameLookup = array();
+ if (empty($QuicktimeIODSaudioProfileNameLookup)) {
+ $QuicktimeIODSaudioProfileNameLookup = array(
+ 0x00 => 'ISO Reserved (0x00)',
+ 0x01 => 'Main Audio Profile @ Level 1',
+ 0x02 => 'Main Audio Profile @ Level 2',
+ 0x03 => 'Main Audio Profile @ Level 3',
+ 0x04 => 'Main Audio Profile @ Level 4',
+ 0x05 => 'Scalable Audio Profile @ Level 1',
+ 0x06 => 'Scalable Audio Profile @ Level 2',
+ 0x07 => 'Scalable Audio Profile @ Level 3',
+ 0x08 => 'Scalable Audio Profile @ Level 4',
+ 0x09 => 'Speech Audio Profile @ Level 1',
+ 0x0A => 'Speech Audio Profile @ Level 2',
+ 0x0B => 'Synthetic Audio Profile @ Level 1',
+ 0x0C => 'Synthetic Audio Profile @ Level 2',
+ 0x0D => 'Synthetic Audio Profile @ Level 3',
+ 0x0E => 'High Quality Audio Profile @ Level 1',
+ 0x0F => 'High Quality Audio Profile @ Level 2',
+ 0x10 => 'High Quality Audio Profile @ Level 3',
+ 0x11 => 'High Quality Audio Profile @ Level 4',
+ 0x12 => 'High Quality Audio Profile @ Level 5',
+ 0x13 => 'High Quality Audio Profile @ Level 6',
+ 0x14 => 'High Quality Audio Profile @ Level 7',
+ 0x15 => 'High Quality Audio Profile @ Level 8',
+ 0x16 => 'Low Delay Audio Profile @ Level 1',
+ 0x17 => 'Low Delay Audio Profile @ Level 2',
+ 0x18 => 'Low Delay Audio Profile @ Level 3',
+ 0x19 => 'Low Delay Audio Profile @ Level 4',
+ 0x1A => 'Low Delay Audio Profile @ Level 5',
+ 0x1B => 'Low Delay Audio Profile @ Level 6',
+ 0x1C => 'Low Delay Audio Profile @ Level 7',
+ 0x1D => 'Low Delay Audio Profile @ Level 8',
+ 0x1E => 'Natural Audio Profile @ Level 1',
+ 0x1F => 'Natural Audio Profile @ Level 2',
+ 0x20 => 'Natural Audio Profile @ Level 3',
+ 0x21 => 'Natural Audio Profile @ Level 4',
+ 0x22 => 'Mobile Audio Internetworking Profile @ Level 1',
+ 0x23 => 'Mobile Audio Internetworking Profile @ Level 2',
+ 0x24 => 'Mobile Audio Internetworking Profile @ Level 3',
+ 0x25 => 'Mobile Audio Internetworking Profile @ Level 4',
+ 0x26 => 'Mobile Audio Internetworking Profile @ Level 5',
+ 0x27 => 'Mobile Audio Internetworking Profile @ Level 6',
+ 0x28 => 'AAC Profile @ Level 1',
+ 0x29 => 'AAC Profile @ Level 2',
+ 0x2A => 'AAC Profile @ Level 4',
+ 0x2B => 'AAC Profile @ Level 5',
+ 0x2C => 'High Efficiency AAC Profile @ Level 2',
+ 0x2D => 'High Efficiency AAC Profile @ Level 3',
+ 0x2E => 'High Efficiency AAC Profile @ Level 4',
+ 0x2F => 'High Efficiency AAC Profile @ Level 5',
+ 0xFE => 'Not part of MPEG-4 audio profiles',
+ 0xFF => 'No audio capability required',
+ );
+ }
+ return (isset($QuicktimeIODSaudioProfileNameLookup[$audio_profile_id]) ? $QuicktimeIODSaudioProfileNameLookup[$audio_profile_id] : 'ISO Reserved / User Private');
+ }
+
+
+ public function QuicktimeIODSvideoProfileName($video_profile_id) {
+ static $QuicktimeIODSvideoProfileNameLookup = array();
+ if (empty($QuicktimeIODSvideoProfileNameLookup)) {
+ $QuicktimeIODSvideoProfileNameLookup = array(
+ 0x00 => 'Reserved (0x00) Profile',
+ 0x01 => 'Simple Profile @ Level 1',
+ 0x02 => 'Simple Profile @ Level 2',
+ 0x03 => 'Simple Profile @ Level 3',
+ 0x08 => 'Simple Profile @ Level 0',
+ 0x10 => 'Simple Scalable Profile @ Level 0',
+ 0x11 => 'Simple Scalable Profile @ Level 1',
+ 0x12 => 'Simple Scalable Profile @ Level 2',
+ 0x15 => 'AVC/H264 Profile',
+ 0x21 => 'Core Profile @ Level 1',
+ 0x22 => 'Core Profile @ Level 2',
+ 0x32 => 'Main Profile @ Level 2',
+ 0x33 => 'Main Profile @ Level 3',
+ 0x34 => 'Main Profile @ Level 4',
+ 0x42 => 'N-bit Profile @ Level 2',
+ 0x51 => 'Scalable Texture Profile @ Level 1',
+ 0x61 => 'Simple Face Animation Profile @ Level 1',
+ 0x62 => 'Simple Face Animation Profile @ Level 2',
+ 0x63 => 'Simple FBA Profile @ Level 1',
+ 0x64 => 'Simple FBA Profile @ Level 2',
+ 0x71 => 'Basic Animated Texture Profile @ Level 1',
+ 0x72 => 'Basic Animated Texture Profile @ Level 2',
+ 0x81 => 'Hybrid Profile @ Level 1',
+ 0x82 => 'Hybrid Profile @ Level 2',
+ 0x91 => 'Advanced Real Time Simple Profile @ Level 1',
+ 0x92 => 'Advanced Real Time Simple Profile @ Level 2',
+ 0x93 => 'Advanced Real Time Simple Profile @ Level 3',
+ 0x94 => 'Advanced Real Time Simple Profile @ Level 4',
+ 0xA1 => 'Core Scalable Profile @ Level1',
+ 0xA2 => 'Core Scalable Profile @ Level2',
+ 0xA3 => 'Core Scalable Profile @ Level3',
+ 0xB1 => 'Advanced Coding Efficiency Profile @ Level 1',
+ 0xB2 => 'Advanced Coding Efficiency Profile @ Level 2',
+ 0xB3 => 'Advanced Coding Efficiency Profile @ Level 3',
+ 0xB4 => 'Advanced Coding Efficiency Profile @ Level 4',
+ 0xC1 => 'Advanced Core Profile @ Level 1',
+ 0xC2 => 'Advanced Core Profile @ Level 2',
+ 0xD1 => 'Advanced Scalable Texture @ Level1',
+ 0xD2 => 'Advanced Scalable Texture @ Level2',
+ 0xE1 => 'Simple Studio Profile @ Level 1',
+ 0xE2 => 'Simple Studio Profile @ Level 2',
+ 0xE3 => 'Simple Studio Profile @ Level 3',
+ 0xE4 => 'Simple Studio Profile @ Level 4',
+ 0xE5 => 'Core Studio Profile @ Level 1',
+ 0xE6 => 'Core Studio Profile @ Level 2',
+ 0xE7 => 'Core Studio Profile @ Level 3',
+ 0xE8 => 'Core Studio Profile @ Level 4',
+ 0xF0 => 'Advanced Simple Profile @ Level 0',
+ 0xF1 => 'Advanced Simple Profile @ Level 1',
+ 0xF2 => 'Advanced Simple Profile @ Level 2',
+ 0xF3 => 'Advanced Simple Profile @ Level 3',
+ 0xF4 => 'Advanced Simple Profile @ Level 4',
+ 0xF5 => 'Advanced Simple Profile @ Level 5',
+ 0xF7 => 'Advanced Simple Profile @ Level 3b',
+ 0xF8 => 'Fine Granularity Scalable Profile @ Level 0',
+ 0xF9 => 'Fine Granularity Scalable Profile @ Level 1',
+ 0xFA => 'Fine Granularity Scalable Profile @ Level 2',
+ 0xFB => 'Fine Granularity Scalable Profile @ Level 3',
+ 0xFC => 'Fine Granularity Scalable Profile @ Level 4',
+ 0xFD => 'Fine Granularity Scalable Profile @ Level 5',
+ 0xFE => 'Not part of MPEG-4 Visual profiles',
+ 0xFF => 'No visual capability required',
+ );
+ }
+ return (isset($QuicktimeIODSvideoProfileNameLookup[$video_profile_id]) ? $QuicktimeIODSvideoProfileNameLookup[$video_profile_id] : 'ISO Reserved Profile');
+ }
+
+
+ public function QuicktimeContentRatingLookup($rtng) {
+ static $QuicktimeContentRatingLookup = array();
+ if (empty($QuicktimeContentRatingLookup)) {
+ $QuicktimeContentRatingLookup[0] = 'None';
+ $QuicktimeContentRatingLookup[2] = 'Clean';
+ $QuicktimeContentRatingLookup[4] = 'Explicit';
+ }
+ return (isset($QuicktimeContentRatingLookup[$rtng]) ? $QuicktimeContentRatingLookup[$rtng] : 'invalid');
+ }
+
+ public function QuicktimeStoreAccountTypeLookup($akid) {
+ static $QuicktimeStoreAccountTypeLookup = array();
+ if (empty($QuicktimeStoreAccountTypeLookup)) {
+ $QuicktimeStoreAccountTypeLookup[0] = 'iTunes';
+ $QuicktimeStoreAccountTypeLookup[1] = 'AOL';
+ }
+ return (isset($QuicktimeStoreAccountTypeLookup[$akid]) ? $QuicktimeStoreAccountTypeLookup[$akid] : 'invalid');
+ }
+
+ public function QuicktimeStoreFrontCodeLookup($sfid) {
+ static $QuicktimeStoreFrontCodeLookup = array();
+ if (empty($QuicktimeStoreFrontCodeLookup)) {
+ $QuicktimeStoreFrontCodeLookup[143460] = 'Australia';
+ $QuicktimeStoreFrontCodeLookup[143445] = 'Austria';
+ $QuicktimeStoreFrontCodeLookup[143446] = 'Belgium';
+ $QuicktimeStoreFrontCodeLookup[143455] = 'Canada';
+ $QuicktimeStoreFrontCodeLookup[143458] = 'Denmark';
+ $QuicktimeStoreFrontCodeLookup[143447] = 'Finland';
+ $QuicktimeStoreFrontCodeLookup[143442] = 'France';
+ $QuicktimeStoreFrontCodeLookup[143443] = 'Germany';
+ $QuicktimeStoreFrontCodeLookup[143448] = 'Greece';
+ $QuicktimeStoreFrontCodeLookup[143449] = 'Ireland';
+ $QuicktimeStoreFrontCodeLookup[143450] = 'Italy';
+ $QuicktimeStoreFrontCodeLookup[143462] = 'Japan';
+ $QuicktimeStoreFrontCodeLookup[143451] = 'Luxembourg';
+ $QuicktimeStoreFrontCodeLookup[143452] = 'Netherlands';
+ $QuicktimeStoreFrontCodeLookup[143461] = 'New Zealand';
+ $QuicktimeStoreFrontCodeLookup[143457] = 'Norway';
+ $QuicktimeStoreFrontCodeLookup[143453] = 'Portugal';
+ $QuicktimeStoreFrontCodeLookup[143454] = 'Spain';
+ $QuicktimeStoreFrontCodeLookup[143456] = 'Sweden';
+ $QuicktimeStoreFrontCodeLookup[143459] = 'Switzerland';
+ $QuicktimeStoreFrontCodeLookup[143444] = 'United Kingdom';
+ $QuicktimeStoreFrontCodeLookup[143441] = 'United States';
+ }
+ return (isset($QuicktimeStoreFrontCodeLookup[$sfid]) ? $QuicktimeStoreFrontCodeLookup[$sfid] : 'invalid');
+ }
+
+ public function QuicktimeParseNikonNCTG($atom_data) {
+ // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
+ // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100
+ // Data is stored as records of:
+ // * 4 bytes record type
+ // * 2 bytes size of data field type:
+ // 0x0001 = flag (size field *= 1-byte)
+ // 0x0002 = char (size field *= 1-byte)
+ // 0x0003 = DWORD+ (size field *= 2-byte), values are stored CDAB
+ // 0x0004 = QWORD+ (size field *= 4-byte), values are stored EFGHABCD
+ // 0x0005 = float (size field *= 8-byte), values are stored aaaabbbb where value is aaaa/bbbb; possibly multiple sets of values appended together
+ // 0x0007 = bytes (size field *= 1-byte), values are stored as ??????
+ // 0x0008 = ????? (size field *= 2-byte), values are stored as ??????
+ // * 2 bytes data size field
+ // * ? bytes data (string data may be null-padded; datestamp fields are in the format "2011:05:25 20:24:15")
+ // all integers are stored BigEndian
+
+ $NCTGtagName = array(
+ 0x00000001 => 'Make',
+ 0x00000002 => 'Model',
+ 0x00000003 => 'Software',
+ 0x00000011 => 'CreateDate',
+ 0x00000012 => 'DateTimeOriginal',
+ 0x00000013 => 'FrameCount',
+ 0x00000016 => 'FrameRate',
+ 0x00000022 => 'FrameWidth',
+ 0x00000023 => 'FrameHeight',
+ 0x00000032 => 'AudioChannels',
+ 0x00000033 => 'AudioBitsPerSample',
+ 0x00000034 => 'AudioSampleRate',
+ 0x02000001 => 'MakerNoteVersion',
+ 0x02000005 => 'WhiteBalance',
+ 0x0200000b => 'WhiteBalanceFineTune',
+ 0x0200001e => 'ColorSpace',
+ 0x02000023 => 'PictureControlData',
+ 0x02000024 => 'WorldTime',
+ 0x02000032 => 'UnknownInfo',
+ 0x02000083 => 'LensType',
+ 0x02000084 => 'Lens',
+ );
+
+ $offset = 0;
+ $datalength = strlen($atom_data);
+ $parsed = array();
+ while ($offset < $datalength) {
+//echo getid3_lib::PrintHexBytes(substr($atom_data, $offset, 4)).'<br>';
+ $record_type = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4)); $offset += 4;
+ $data_size_type = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); $offset += 2;
+ $data_size = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); $offset += 2;
+ switch ($data_size_type) {
+ case 0x0001: // 0x0001 = flag (size field *= 1-byte)
+ $data = getid3_lib::BigEndian2Int(substr($atom_data, $offset, $data_size * 1));
+ $offset += ($data_size * 1);
+ break;
+ case 0x0002: // 0x0002 = char (size field *= 1-byte)
+ $data = substr($atom_data, $offset, $data_size * 1);
+ $offset += ($data_size * 1);
+ $data = rtrim($data, "\x00");
+ break;
+ case 0x0003: // 0x0003 = DWORD+ (size field *= 2-byte), values are stored CDAB
+ $data = '';
+ for ($i = $data_size - 1; $i >= 0; $i--) {
+ $data .= substr($atom_data, $offset + ($i * 2), 2);
+ }
+ $data = getid3_lib::BigEndian2Int($data);
+ $offset += ($data_size * 2);
+ break;
+ case 0x0004: // 0x0004 = QWORD+ (size field *= 4-byte), values are stored EFGHABCD
+ $data = '';
+ for ($i = $data_size - 1; $i >= 0; $i--) {
+ $data .= substr($atom_data, $offset + ($i * 4), 4);
+ }
+ $data = getid3_lib::BigEndian2Int($data);
+ $offset += ($data_size * 4);
+ break;
+ case 0x0005: // 0x0005 = float (size field *= 8-byte), values are stored aaaabbbb where value is aaaa/bbbb; possibly multiple sets of values appended together
+ $data = array();
+ for ($i = 0; $i < $data_size; $i++) {
+ $numerator = getid3_lib::BigEndian2Int(substr($atom_data, $offset + ($i * 8) + 0, 4));
+ $denomninator = getid3_lib::BigEndian2Int(substr($atom_data, $offset + ($i * 8) + 4, 4));
+ if ($denomninator == 0) {
+ $data[$i] = false;
+ } else {
+ $data[$i] = (double) $numerator / $denomninator;
+ }
+ }
+ $offset += (8 * $data_size);
+ if (count($data) == 1) {
+ $data = $data[0];
+ }
+ break;
+ case 0x0007: // 0x0007 = bytes (size field *= 1-byte), values are stored as ??????
+ $data = substr($atom_data, $offset, $data_size * 1);
+ $offset += ($data_size * 1);
+ break;
+ case 0x0008: // 0x0008 = ????? (size field *= 2-byte), values are stored as ??????
+ $data = substr($atom_data, $offset, $data_size * 2);
+ $offset += ($data_size * 2);
+ break;
+ default:
+echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br>';
+ break 2;
+ }
+
+ switch ($record_type) {
+ case 0x00000011: // CreateDate
+ case 0x00000012: // DateTimeOriginal
+ $data = strtotime($data);
+ break;
+ case 0x0200001e: // ColorSpace
+ switch ($data) {
+ case 1:
+ $data = 'sRGB';
+ break;
+ case 2:
+ $data = 'Adobe RGB';
+ break;
+ }
+ break;
+ case 0x02000023: // PictureControlData
+ $PictureControlAdjust = array(0=>'default', 1=>'quick', 2=>'full');
+ $FilterEffect = array(0x80=>'off', 0x81=>'yellow', 0x82=>'orange', 0x83=>'red', 0x84=>'green', 0xff=>'n/a');
+ $ToningEffect = array(0x80=>'b&w', 0x81=>'sepia', 0x82=>'cyanotype', 0x83=>'red', 0x84=>'yellow', 0x85=>'green', 0x86=>'blue-green', 0x87=>'blue', 0x88=>'purple-blue', 0x89=>'red-purple', 0xff=>'n/a');
+ $data = array(
+ 'PictureControlVersion' => substr($data, 0, 4),
+ 'PictureControlName' => rtrim(substr($data, 4, 20), "\x00"),
+ 'PictureControlBase' => rtrim(substr($data, 24, 20), "\x00"),
+ //'?' => substr($data, 44, 4),
+ 'PictureControlAdjust' => $PictureControlAdjust[ord(substr($data, 48, 1))],
+ 'PictureControlQuickAdjust' => ord(substr($data, 49, 1)),
+ 'Sharpness' => ord(substr($data, 50, 1)),
+ 'Contrast' => ord(substr($data, 51, 1)),
+ 'Brightness' => ord(substr($data, 52, 1)),
+ 'Saturation' => ord(substr($data, 53, 1)),
+ 'HueAdjustment' => ord(substr($data, 54, 1)),
+ 'FilterEffect' => $FilterEffect[ord(substr($data, 55, 1))],
+ 'ToningEffect' => $ToningEffect[ord(substr($data, 56, 1))],
+ 'ToningSaturation' => ord(substr($data, 57, 1)),
+ );
+ break;
+ case 0x02000024: // WorldTime
+ // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#WorldTime
+ // timezone is stored as offset from GMT in minutes
+ $timezone = getid3_lib::BigEndian2Int(substr($data, 0, 2));
+ if ($timezone & 0x8000) {
+ $timezone = 0 - (0x10000 - $timezone);
+ }
+ $timezone /= 60;
+
+ $dst = (bool) getid3_lib::BigEndian2Int(substr($data, 2, 1));
+ switch (getid3_lib::BigEndian2Int(substr($data, 3, 1))) {
+ case 2:
+ $datedisplayformat = 'D/M/Y'; break;
+ case 1:
+ $datedisplayformat = 'M/D/Y'; break;
+ case 0:
+ default:
+ $datedisplayformat = 'Y/M/D'; break;
+ }
+
+ $data = array('timezone'=>floatval($timezone), 'dst'=>$dst, 'display'=>$datedisplayformat);
+ break;
+ case 0x02000083: // LensType
+ $data = array(
+ //'_' => $data,
+ 'mf' => (bool) ($data & 0x01),
+ 'd' => (bool) ($data & 0x02),
+ 'g' => (bool) ($data & 0x04),
+ 'vr' => (bool) ($data & 0x08),
+ );
+ break;
+ }
+ $tag_name = (isset($NCTGtagName[$record_type]) ? $NCTGtagName[$record_type] : '0x'.str_pad(dechex($record_type), 8, '0', STR_PAD_LEFT));
+ $parsed[$tag_name] = $data;
+ }
+ return $parsed;
+ }
+
+
+ public function CopyToAppropriateCommentsSection($keyname, $data, $boxname='') {
+ static $handyatomtranslatorarray = array();
+ if (empty($handyatomtranslatorarray)) {
+ $handyatomtranslatorarray['©cpy'] = 'copyright';
+ $handyatomtranslatorarray['©day'] = 'creation_date'; // iTunes 4.0
+ $handyatomtranslatorarray['©dir'] = 'director';
+ $handyatomtranslatorarray['©ed1'] = 'edit1';
+ $handyatomtranslatorarray['©ed2'] = 'edit2';
+ $handyatomtranslatorarray['©ed3'] = 'edit3';
+ $handyatomtranslatorarray['©ed4'] = 'edit4';
+ $handyatomtranslatorarray['©ed5'] = 'edit5';
+ $handyatomtranslatorarray['©ed6'] = 'edit6';
+ $handyatomtranslatorarray['©ed7'] = 'edit7';
+ $handyatomtranslatorarray['©ed8'] = 'edit8';
+ $handyatomtranslatorarray['©ed9'] = 'edit9';
+ $handyatomtranslatorarray['©fmt'] = 'format';
+ $handyatomtranslatorarray['©inf'] = 'information';
+ $handyatomtranslatorarray['©prd'] = 'producer';
+ $handyatomtranslatorarray['©prf'] = 'performers';
+ $handyatomtranslatorarray['©req'] = 'system_requirements';
+ $handyatomtranslatorarray['©src'] = 'source_credit';
+ $handyatomtranslatorarray['©wrt'] = 'writer';
+
+ // http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
+ $handyatomtranslatorarray['©nam'] = 'title'; // iTunes 4.0
+ $handyatomtranslatorarray['©cmt'] = 'comment'; // iTunes 4.0
+ $handyatomtranslatorarray['©wrn'] = 'warning';
+ $handyatomtranslatorarray['©hst'] = 'host_computer';
+ $handyatomtranslatorarray['©mak'] = 'make';
+ $handyatomtranslatorarray['©mod'] = 'model';
+ $handyatomtranslatorarray['©PRD'] = 'product';
+ $handyatomtranslatorarray['©swr'] = 'software';
+ $handyatomtranslatorarray['©aut'] = 'author';
+ $handyatomtranslatorarray['©ART'] = 'artist';
+ $handyatomtranslatorarray['©trk'] = 'track';
+ $handyatomtranslatorarray['©alb'] = 'album'; // iTunes 4.0
+ $handyatomtranslatorarray['©com'] = 'comment';
+ $handyatomtranslatorarray['©gen'] = 'genre'; // iTunes 4.0
+ $handyatomtranslatorarray['©ope'] = 'composer';
+ $handyatomtranslatorarray['©url'] = 'url';
+ $handyatomtranslatorarray['©enc'] = 'encoder';
+
+ // http://atomicparsley.sourceforge.net/mpeg-4files.html
+ $handyatomtranslatorarray['©art'] = 'artist'; // iTunes 4.0
+ $handyatomtranslatorarray['aART'] = 'album_artist';
+ $handyatomtranslatorarray['trkn'] = 'track_number'; // iTunes 4.0
+ $handyatomtranslatorarray['disk'] = 'disc_number'; // iTunes 4.0
+ $handyatomtranslatorarray['gnre'] = 'genre'; // iTunes 4.0
+ $handyatomtranslatorarray['©too'] = 'encoder'; // iTunes 4.0
+ $handyatomtranslatorarray['tmpo'] = 'bpm'; // iTunes 4.0
+ $handyatomtranslatorarray['cprt'] = 'copyright'; // iTunes 4.0?
+ $handyatomtranslatorarray['cpil'] = 'compilation'; // iTunes 4.0
+ $handyatomtranslatorarray['covr'] = 'picture'; // iTunes 4.0
+ $handyatomtranslatorarray['rtng'] = 'rating'; // iTunes 4.0
+ $handyatomtranslatorarray['©grp'] = 'grouping'; // iTunes 4.2
+ $handyatomtranslatorarray['stik'] = 'stik'; // iTunes 4.9
+ $handyatomtranslatorarray['pcst'] = 'podcast'; // iTunes 4.9
+ $handyatomtranslatorarray['catg'] = 'category'; // iTunes 4.9
+ $handyatomtranslatorarray['keyw'] = 'keyword'; // iTunes 4.9
+ $handyatomtranslatorarray['purl'] = 'podcast_url'; // iTunes 4.9
+ $handyatomtranslatorarray['egid'] = 'episode_guid'; // iTunes 4.9
+ $handyatomtranslatorarray['desc'] = 'description'; // iTunes 5.0
+ $handyatomtranslatorarray['©lyr'] = 'lyrics'; // iTunes 5.0
+ $handyatomtranslatorarray['tvnn'] = 'tv_network_name'; // iTunes 6.0
+ $handyatomtranslatorarray['tvsh'] = 'tv_show_name'; // iTunes 6.0
+ $handyatomtranslatorarray['tvsn'] = 'tv_season'; // iTunes 6.0
+ $handyatomtranslatorarray['tves'] = 'tv_episode'; // iTunes 6.0
+ $handyatomtranslatorarray['purd'] = 'purchase_date'; // iTunes 6.0.2
+ $handyatomtranslatorarray['pgap'] = 'gapless_playback'; // iTunes 7.0
+
+ // http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt
+
+
+
+ // boxnames:
+ /*
+ $handyatomtranslatorarray['iTunSMPB'] = 'iTunSMPB';
+ $handyatomtranslatorarray['iTunNORM'] = 'iTunNORM';
+ $handyatomtranslatorarray['Encoding Params'] = 'Encoding Params';
+ $handyatomtranslatorarray['replaygain_track_gain'] = 'replaygain_track_gain';
+ $handyatomtranslatorarray['replaygain_track_peak'] = 'replaygain_track_peak';
+ $handyatomtranslatorarray['replaygain_track_minmax'] = 'replaygain_track_minmax';
+ $handyatomtranslatorarray['MusicIP PUID'] = 'MusicIP PUID';
+ $handyatomtranslatorarray['MusicBrainz Artist Id'] = 'MusicBrainz Artist Id';
+ $handyatomtranslatorarray['MusicBrainz Album Id'] = 'MusicBrainz Album Id';
+ $handyatomtranslatorarray['MusicBrainz Album Artist Id'] = 'MusicBrainz Album Artist Id';
+ $handyatomtranslatorarray['MusicBrainz Track Id'] = 'MusicBrainz Track Id';
+ $handyatomtranslatorarray['MusicBrainz Disc Id'] = 'MusicBrainz Disc Id';
+
+ // http://age.hobba.nl/audio/tag_frame_reference.html
+ $handyatomtranslatorarray['PLAY_COUNTER'] = 'play_counter'; // Foobar2000 - http://www.getid3.org/phpBB3/viewtopic.php?t=1355
+ $handyatomtranslatorarray['MEDIATYPE'] = 'mediatype'; // Foobar2000 - http://www.getid3.org/phpBB3/viewtopic.php?t=1355
+ */
+ }
+ $info = &$this->getid3->info;
+ $comment_key = '';
+ if ($boxname && ($boxname != $keyname)) {
+ $comment_key = (isset($handyatomtranslatorarray[$boxname]) ? $handyatomtranslatorarray[$boxname] : $boxname);
+ } elseif (isset($handyatomtranslatorarray[$keyname])) {
+ $comment_key = $handyatomtranslatorarray[$keyname];
+ }
+ if ($comment_key) {
+ if ($comment_key == 'picture') {
+ if (!is_array($data)) {
+ $image_mime = '';
+ if (preg_match('#^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A#', $data)) {
+ $image_mime = 'image/png';
+ } elseif (preg_match('#^\xFF\xD8\xFF#', $data)) {
+ $image_mime = 'image/jpeg';
+ } elseif (preg_match('#^GIF#', $data)) {
+ $image_mime = 'image/gif';
+ } elseif (preg_match('#^BM#', $data)) {
+ $image_mime = 'image/bmp';
+ }
+ $data = array('data'=>$data, 'image_mime'=>$image_mime);
+ }
+ }
+ $info['quicktime']['comments'][$comment_key][] = $data;
+ }
+ return true;
+ }
+
+ public function NoNullString($nullterminatedstring) {
+ // remove the single null terminator on null terminated strings
+ if (substr($nullterminatedstring, strlen($nullterminatedstring) - 1, 1) === "\x00") {
+ return substr($nullterminatedstring, 0, strlen($nullterminatedstring) - 1);
+ }
+ return $nullterminatedstring;
+ }
+
+ public function Pascal2String($pascalstring) {
+ // Pascal strings have 1 unsigned byte at the beginning saying how many chars (1-255) are in the string
+ return substr($pascalstring, 1);
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/libs/getid3/module.audio-video.riff.php b/extensions/TimedMediaHandler/libs/getid3/module.audio-video.riff.php
new file mode 100644
index 00000000..5ac5d1cd
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/module.audio-video.riff.php
@@ -0,0 +1,2435 @@
+<?php
+/////////////////////////////////////////////////////////////////
+/// getID3() by James Heinrich <info@getid3.org> //
+// available at http://getid3.sourceforge.net //
+// or http://www.getid3.org //
+/////////////////////////////////////////////////////////////////
+// See readme.txt for more details //
+/////////////////////////////////////////////////////////////////
+// //
+// module.audio-video.riff.php //
+// module for analyzing RIFF files //
+// multiple formats supported by this module: //
+// Wave, AVI, AIFF/AIFC, (MP3,AC3)/RIFF, Wavpack v3, 8SVX //
+// dependencies: module.audio.mp3.php //
+// module.audio.ac3.php //
+// module.audio.dts.php //
+// ///
+/////////////////////////////////////////////////////////////////
+
+/**
+* @todo Parse AC-3/DTS audio inside WAVE correctly
+* @todo Rewrite RIFF parser totally
+*/
+
+getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
+getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true);
+getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true);
+
+class getid3_riff extends getid3_handler
+{
+
+ public function Analyze() {
+ $info = &$this->getid3->info;
+
+ // initialize these values to an empty array, otherwise they default to NULL
+ // and you can't append array values to a NULL value
+ $info['riff'] = array('raw'=>array());
+
+ // Shortcuts
+ $thisfile_riff = &$info['riff'];
+ $thisfile_riff_raw = &$thisfile_riff['raw'];
+ $thisfile_audio = &$info['audio'];
+ $thisfile_video = &$info['video'];
+ $thisfile_audio_dataformat = &$thisfile_audio['dataformat'];
+ $thisfile_riff_audio = &$thisfile_riff['audio'];
+ $thisfile_riff_video = &$thisfile_riff['video'];
+
+ $Original['avdataoffset'] = $info['avdataoffset'];
+ $Original['avdataend'] = $info['avdataend'];
+
+ $this->fseek($info['avdataoffset']);
+ $RIFFheader = $this->fread(12);
+ $offset = $this->ftell();
+ $RIFFtype = substr($RIFFheader, 0, 4);
+ $RIFFsize = substr($RIFFheader, 4, 4);
+ $RIFFsubtype = substr($RIFFheader, 8, 4);
+
+ switch ($RIFFtype) {
+
+ case 'FORM': // AIFF, AIFC
+ $info['fileformat'] = 'aiff';
+ $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize);
+ $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4));
+ break;
+
+ case 'RIFF': // AVI, WAV, etc
+ case 'SDSS': // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com)
+ case 'RMP3': // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s
+ $info['fileformat'] = 'riff';
+ $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize);
+ if ($RIFFsubtype == 'RMP3') {
+ // RMP3 is identical to WAVE, just renamed. Used by [unknown program] when creating RIFF-MP3s
+ $RIFFsubtype = 'WAVE';
+ }
+ $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4));
+ if (($info['avdataend'] - $info['filesize']) == 1) {
+ // LiteWave appears to incorrectly *not* pad actual output file
+ // to nearest WORD boundary so may appear to be short by one
+ // byte, in which case - skip warning
+ $info['avdataend'] = $info['filesize'];
+ }
+
+ $nextRIFFoffset = $Original['avdataoffset'] + 8 + $thisfile_riff['header_size']; // 8 = "RIFF" + 32-bit offset
+ while ($nextRIFFoffset < min($info['filesize'], $info['avdataend'])) {
+ try {
+ $this->fseek($nextRIFFoffset);
+ } catch (getid3_exception $e) {
+ if ($e->getCode() == 10) {
+ //$this->warning('RIFF parser: '.$e->getMessage());
+ $this->error('AVI extends beyond '.round(PHP_INT_MAX / 1073741824).'GB and PHP filesystem functions cannot read that far, playtime may be wrong');
+ $this->warning('[avdataend] value may be incorrect, multiple AVIX chunks may be present');
+ break;
+ } else {
+ throw $e;
+ }
+ }
+ $nextRIFFheader = $this->fread(12);
+ if ($nextRIFFoffset == ($info['avdataend'] - 1)) {
+ if (substr($nextRIFFheader, 0, 1) == "\x00") {
+ // RIFF padded to WORD boundary, we're actually already at the end
+ break;
+ }
+ }
+ $nextRIFFheaderID = substr($nextRIFFheader, 0, 4);
+ $nextRIFFsize = $this->EitherEndian2Int(substr($nextRIFFheader, 4, 4));
+ $nextRIFFtype = substr($nextRIFFheader, 8, 4);
+ $chunkdata = array();
+ $chunkdata['offset'] = $nextRIFFoffset + 8;
+ $chunkdata['size'] = $nextRIFFsize;
+ $nextRIFFoffset = $chunkdata['offset'] + $chunkdata['size'];
+
+ switch ($nextRIFFheaderID) {
+
+ case 'RIFF':
+ $chunkdata['chunks'] = $this->ParseRIFF($chunkdata['offset'] + 4, $nextRIFFoffset);
+
+ if (!isset($thisfile_riff[$nextRIFFtype])) {
+ $thisfile_riff[$nextRIFFtype] = array();
+ }
+ $thisfile_riff[$nextRIFFtype][] = $chunkdata;
+ break;
+
+ case 'JUNK':
+ // ignore
+ $thisfile_riff[$nextRIFFheaderID][] = $chunkdata;
+ break;
+
+ case 'IDVX':
+ $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunkdata['size']));
+ break;
+
+ default:
+ if ($info['filesize'] == ($chunkdata['offset'] - 8 + 128)) {
+ $DIVXTAG = $nextRIFFheader.$this->fread(128 - 12);
+ if (substr($DIVXTAG, -7) == 'DIVXTAG') {
+ // DIVXTAG is supposed to be inside an IDVX chunk in a LIST chunk, but some bad encoders just slap it on the end of a file
+ $this->warning('Found wrongly-structured DIVXTAG at offset '.($this->ftell() - 128).', parsing anyway');
+ $info['divxtag']['comments'] = self::ParseDIVXTAG($DIVXTAG);
+ break 2;
+ }
+ }
+ $this->warning('Expecting "RIFF|JUNK|IDVX" at '.$nextRIFFoffset.', found "'.$nextRIFFheaderID.'" ('.getid3_lib::PrintHexBytes($nextRIFFheaderID).') - skipping rest of file');
+ break 2;
+
+ }
+
+ }
+ if ($RIFFsubtype == 'WAVE') {
+ $thisfile_riff_WAVE = &$thisfile_riff['WAVE'];
+ }
+ break;
+
+ default:
+ $this->error('Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "'.$RIFFsubtype.'" instead');
+ unset($info['fileformat']);
+ return false;
+ }
+
+ $streamindex = 0;
+ switch ($RIFFsubtype) {
+ case 'WAVE':
+ if (empty($thisfile_audio['bitrate_mode'])) {
+ $thisfile_audio['bitrate_mode'] = 'cbr';
+ }
+ if (empty($thisfile_audio_dataformat)) {
+ $thisfile_audio_dataformat = 'wav';
+ }
+
+ if (isset($thisfile_riff_WAVE['data'][0]['offset'])) {
+ $info['avdataoffset'] = $thisfile_riff_WAVE['data'][0]['offset'] + 8;
+ $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff_WAVE['data'][0]['size'];
+ }
+ if (isset($thisfile_riff_WAVE['fmt '][0]['data'])) {
+
+ $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']);
+ $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
+ if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || ($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) {
+ $info['error'][] = 'Corrupt RIFF file: bitrate_audio == zero';
+ return false;
+ }
+ $thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw'];
+ unset($thisfile_riff_audio[$streamindex]['raw']);
+ $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
+
+ $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
+ if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
+ $info['warning'][] = 'Audio codec = '.$thisfile_audio['codec'];
+ }
+ $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
+
+ if (empty($info['playtime_seconds'])) { // may already be set (e.g. DTS-WAV)
+ $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']);
+ }
+
+ $thisfile_audio['lossless'] = false;
+ if (isset($thisfile_riff_WAVE['data'][0]['offset']) && isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
+ switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
+
+ case 0x0001: // PCM
+ $thisfile_audio['lossless'] = true;
+ break;
+
+ case 0x2000: // AC-3
+ $thisfile_audio_dataformat = 'ac3';
+ break;
+
+ default:
+ // do nothing
+ break;
+
+ }
+ }
+ $thisfile_audio['streams'][$streamindex]['wformattag'] = $thisfile_audio['wformattag'];
+ $thisfile_audio['streams'][$streamindex]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
+ $thisfile_audio['streams'][$streamindex]['lossless'] = $thisfile_audio['lossless'];
+ $thisfile_audio['streams'][$streamindex]['dataformat'] = $thisfile_audio_dataformat;
+ }
+
+ if (isset($thisfile_riff_WAVE['rgad'][0]['data'])) {
+
+ // shortcuts
+ $rgadData = &$thisfile_riff_WAVE['rgad'][0]['data'];
+ $thisfile_riff_raw['rgad'] = array('track'=>array(), 'album'=>array());
+ $thisfile_riff_raw_rgad = &$thisfile_riff_raw['rgad'];
+ $thisfile_riff_raw_rgad_track = &$thisfile_riff_raw_rgad['track'];
+ $thisfile_riff_raw_rgad_album = &$thisfile_riff_raw_rgad['album'];
+
+ $thisfile_riff_raw_rgad['fPeakAmplitude'] = getid3_lib::LittleEndian2Float(substr($rgadData, 0, 4));
+ $thisfile_riff_raw_rgad['nRadioRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 4, 2));
+ $thisfile_riff_raw_rgad['nAudiophileRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 6, 2));
+
+ $nRadioRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT);
+ $nAudiophileRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT);
+ $thisfile_riff_raw_rgad_track['name'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3));
+ $thisfile_riff_raw_rgad_track['originator'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3));
+ $thisfile_riff_raw_rgad_track['signbit'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1));
+ $thisfile_riff_raw_rgad_track['adjustment'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9));
+ $thisfile_riff_raw_rgad_album['name'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3));
+ $thisfile_riff_raw_rgad_album['originator'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3));
+ $thisfile_riff_raw_rgad_album['signbit'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1));
+ $thisfile_riff_raw_rgad_album['adjustment'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9));
+
+ $thisfile_riff['rgad']['peakamplitude'] = $thisfile_riff_raw_rgad['fPeakAmplitude'];
+ if (($thisfile_riff_raw_rgad_track['name'] != 0) && ($thisfile_riff_raw_rgad_track['originator'] != 0)) {
+ $thisfile_riff['rgad']['track']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_track['name']);
+ $thisfile_riff['rgad']['track']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_track['originator']);
+ $thisfile_riff['rgad']['track']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_track['adjustment'], $thisfile_riff_raw_rgad_track['signbit']);
+ }
+ if (($thisfile_riff_raw_rgad_album['name'] != 0) && ($thisfile_riff_raw_rgad_album['originator'] != 0)) {
+ $thisfile_riff['rgad']['album']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_album['name']);
+ $thisfile_riff['rgad']['album']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_album['originator']);
+ $thisfile_riff['rgad']['album']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_album['adjustment'], $thisfile_riff_raw_rgad_album['signbit']);
+ }
+ }
+
+ if (isset($thisfile_riff_WAVE['fact'][0]['data'])) {
+ $thisfile_riff_raw['fact']['NumberOfSamples'] = $this->EitherEndian2Int(substr($thisfile_riff_WAVE['fact'][0]['data'], 0, 4));
+
+ // This should be a good way of calculating exact playtime,
+ // but some sample files have had incorrect number of samples,
+ // so cannot use this method
+
+ // if (!empty($thisfile_riff_raw['fmt ']['nSamplesPerSec'])) {
+ // $info['playtime_seconds'] = (float) $thisfile_riff_raw['fact']['NumberOfSamples'] / $thisfile_riff_raw['fmt ']['nSamplesPerSec'];
+ // }
+ }
+ if (!empty($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'])) {
+ $thisfile_audio['bitrate'] = getid3_lib::CastAsInt($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'] * 8);
+ }
+
+ if (isset($thisfile_riff_WAVE['bext'][0]['data'])) {
+ // shortcut
+ $thisfile_riff_WAVE_bext_0 = &$thisfile_riff_WAVE['bext'][0];
+
+ $thisfile_riff_WAVE_bext_0['title'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 0, 256));
+ $thisfile_riff_WAVE_bext_0['author'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 256, 32));
+ $thisfile_riff_WAVE_bext_0['reference'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 288, 32));
+ $thisfile_riff_WAVE_bext_0['origin_date'] = substr($thisfile_riff_WAVE_bext_0['data'], 320, 10);
+ $thisfile_riff_WAVE_bext_0['origin_time'] = substr($thisfile_riff_WAVE_bext_0['data'], 330, 8);
+ $thisfile_riff_WAVE_bext_0['time_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 338, 8));
+ $thisfile_riff_WAVE_bext_0['bwf_version'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 346, 1));
+ $thisfile_riff_WAVE_bext_0['reserved'] = substr($thisfile_riff_WAVE_bext_0['data'], 347, 254);
+ $thisfile_riff_WAVE_bext_0['coding_history'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_bext_0['data'], 601)));
+ if (preg_match('#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_date'], $matches_bext_date)) {
+ if (preg_match('#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_time'], $matches_bext_time)) {
+ list($dummy, $bext_timestamp['year'], $bext_timestamp['month'], $bext_timestamp['day']) = $matches_bext_date;
+ list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time;
+ $thisfile_riff_WAVE_bext_0['origin_date_unix'] = gmmktime($bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second'], $bext_timestamp['month'], $bext_timestamp['day'], $bext_timestamp['year']);
+ } else {
+ $info['warning'][] = 'RIFF.WAVE.BEXT.origin_time is invalid';
+ }
+ } else {
+ $info['warning'][] = 'RIFF.WAVE.BEXT.origin_date is invalid';
+ }
+ $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
+ $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title'];
+ }
+
+ if (isset($thisfile_riff_WAVE['MEXT'][0]['data'])) {
+ // shortcut
+ $thisfile_riff_WAVE_MEXT_0 = &$thisfile_riff_WAVE['MEXT'][0];
+
+ $thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 0, 2));
+ $thisfile_riff_WAVE_MEXT_0['flags']['homogenous'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0001);
+ if ($thisfile_riff_WAVE_MEXT_0['flags']['homogenous']) {
+ $thisfile_riff_WAVE_MEXT_0['flags']['padding'] = ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0002) ? false : true;
+ $thisfile_riff_WAVE_MEXT_0['flags']['22_or_44'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0004);
+ $thisfile_riff_WAVE_MEXT_0['flags']['free_format'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0008);
+
+ $thisfile_riff_WAVE_MEXT_0['nominal_frame_size'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 2, 2));
+ }
+ $thisfile_riff_WAVE_MEXT_0['anciliary_data_length'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 6, 2));
+ $thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 8, 2));
+ $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_left'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0001);
+ $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_free'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0002);
+ $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_right'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0004);
+ }
+
+ if (isset($thisfile_riff_WAVE['cart'][0]['data'])) {
+ // shortcut
+ $thisfile_riff_WAVE_cart_0 = &$thisfile_riff_WAVE['cart'][0];
+
+ $thisfile_riff_WAVE_cart_0['version'] = substr($thisfile_riff_WAVE_cart_0['data'], 0, 4);
+ $thisfile_riff_WAVE_cart_0['title'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 4, 64));
+ $thisfile_riff_WAVE_cart_0['artist'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 68, 64));
+ $thisfile_riff_WAVE_cart_0['cut_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 132, 64));
+ $thisfile_riff_WAVE_cart_0['client_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 196, 64));
+ $thisfile_riff_WAVE_cart_0['category'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 260, 64));
+ $thisfile_riff_WAVE_cart_0['classification'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 324, 64));
+ $thisfile_riff_WAVE_cart_0['out_cue'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 388, 64));
+ $thisfile_riff_WAVE_cart_0['start_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 452, 10));
+ $thisfile_riff_WAVE_cart_0['start_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 462, 8));
+ $thisfile_riff_WAVE_cart_0['end_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 470, 10));
+ $thisfile_riff_WAVE_cart_0['end_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 480, 8));
+ $thisfile_riff_WAVE_cart_0['producer_app_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 488, 64));
+ $thisfile_riff_WAVE_cart_0['producer_app_version'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 552, 64));
+ $thisfile_riff_WAVE_cart_0['user_defined_text'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 616, 64));
+ $thisfile_riff_WAVE_cart_0['zero_db_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 680, 4), true);
+ for ($i = 0; $i < 8; $i++) {
+ $thisfile_riff_WAVE_cart_0['post_time'][$i]['usage_fourcc'] = substr($thisfile_riff_WAVE_cart_0['data'], 684 + ($i * 8), 4);
+ $thisfile_riff_WAVE_cart_0['post_time'][$i]['timer_value'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 684 + ($i * 8) + 4, 4));
+ }
+ $thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024));
+ $thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
+
+ $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
+ $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title'];
+ }
+
+ if (isset($thisfile_riff_WAVE['SNDM'][0]['data'])) {
+ // SoundMiner metadata
+
+ // shortcuts
+ $thisfile_riff_WAVE_SNDM_0 = &$thisfile_riff_WAVE['SNDM'][0];
+ $thisfile_riff_WAVE_SNDM_0_data = &$thisfile_riff_WAVE_SNDM_0['data'];
+ $SNDM_startoffset = 0;
+ $SNDM_endoffset = $thisfile_riff_WAVE_SNDM_0['size'];
+
+ while ($SNDM_startoffset < $SNDM_endoffset) {
+ $SNDM_thisTagOffset = 0;
+ $SNDM_thisTagSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4));
+ $SNDM_thisTagOffset += 4;
+ $SNDM_thisTagKey = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4);
+ $SNDM_thisTagOffset += 4;
+ $SNDM_thisTagDataSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
+ $SNDM_thisTagOffset += 2;
+ $SNDM_thisTagDataFlags = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
+ $SNDM_thisTagOffset += 2;
+ $SNDM_thisTagDataText = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, $SNDM_thisTagDataSize);
+ $SNDM_thisTagOffset += $SNDM_thisTagDataSize;
+
+ if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) {
+ $info['warning'][] = 'RIFF.WAVE.SNDM.data contains tag not expected length (expected: '.$SNDM_thisTagSize.', found: '.(4 + 4 + 2 + 2 + $SNDM_thisTagDataSize).') at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
+ break;
+ } elseif ($SNDM_thisTagSize <= 0) {
+ $info['warning'][] = 'RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
+ break;
+ }
+ $SNDM_startoffset += $SNDM_thisTagSize;
+
+ $thisfile_riff_WAVE_SNDM_0['parsed_raw'][$SNDM_thisTagKey] = $SNDM_thisTagDataText;
+ if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) {
+ $thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText;
+ } else {
+ $info['warning'][] = 'RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
+ }
+ }
+
+ $tagmapping = array(
+ 'tracktitle'=>'title',
+ 'category' =>'genre',
+ 'cdtitle' =>'album',
+ 'tracktitle'=>'title',
+ );
+ foreach ($tagmapping as $fromkey => $tokey) {
+ if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
+ $thisfile_riff['comments'][$tokey][] = $thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey];
+ }
+ }
+ }
+
+ if (isset($thisfile_riff_WAVE['iXML'][0]['data'])) {
+ // requires functions simplexml_load_string and get_object_vars
+ if ($parsedXML = getid3_lib::XML2array($thisfile_riff_WAVE['iXML'][0]['data'])) {
+ $thisfile_riff_WAVE['iXML'][0]['parsed'] = $parsedXML;
+ if (isset($parsedXML['SPEED']['MASTER_SPEED'])) {
+ @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['MASTER_SPEED']);
+ $thisfile_riff_WAVE['iXML'][0]['master_speed'] = $numerator / ($denominator ? $denominator : 1000);
+ }
+ if (isset($parsedXML['SPEED']['TIMECODE_RATE'])) {
+ @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['TIMECODE_RATE']);
+ $thisfile_riff_WAVE['iXML'][0]['timecode_rate'] = $numerator / ($denominator ? $denominator : 1000);
+ }
+ if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) {
+ $samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0'));
+ $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE'];
+ $h = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] / 3600);
+ $m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600)) / 60);
+ $s = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60));
+ $f = ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate'];
+ $thisfile_riff_WAVE['iXML'][0]['timecode_string'] = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s, $f);
+ $thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d', $h, $m, $s, round($f));
+ }
+ unset($parsedXML);
+ }
+ }
+
+
+
+ if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) {
+ $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
+ $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']);
+ }
+
+ if (!empty($info['wavpack'])) {
+ $thisfile_audio_dataformat = 'wavpack';
+ $thisfile_audio['bitrate_mode'] = 'vbr';
+ $thisfile_audio['encoder'] = 'WavPack v'.$info['wavpack']['version'];
+
+ // Reset to the way it was - RIFF parsing will have messed this up
+ $info['avdataend'] = $Original['avdataend'];
+ $thisfile_audio['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
+
+ $this->fseek($info['avdataoffset'] - 44);
+ $RIFFdata = $this->fread(44);
+ $OrignalRIFFheaderSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 4, 4)) + 8;
+ $OrignalRIFFdataSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 40, 4)) + 44;
+
+ if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) {
+ $info['avdataend'] -= ($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
+ $this->fseek($info['avdataend']);
+ $RIFFdata .= $this->fread($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
+ }
+
+ // move the data chunk after all other chunks (if any)
+ // so that the RIFF parser doesn't see EOF when trying
+ // to skip over the data chunk
+ $RIFFdata = substr($RIFFdata, 0, 36).substr($RIFFdata, 44).substr($RIFFdata, 36, 8);
+ $getid3_riff = new getid3_riff($this->getid3);
+ $getid3_riff->ParseRIFFdata($RIFFdata);
+ unset($getid3_riff);
+ }
+
+ if (isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
+ switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
+ case 0x0001: // PCM
+ if (!empty($info['ac3'])) {
+ // Dolby Digital WAV files masquerade as PCM-WAV, but they're not
+ $thisfile_audio['wformattag'] = 0x2000;
+ $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']);
+ $thisfile_audio['lossless'] = false;
+ $thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
+ $thisfile_audio['sample_rate'] = $info['ac3']['sample_rate'];
+ }
+ if (!empty($info['dts'])) {
+ // Dolby DTS files masquerade as PCM-WAV, but they're not
+ $thisfile_audio['wformattag'] = 0x2001;
+ $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']);
+ $thisfile_audio['lossless'] = false;
+ $thisfile_audio['bitrate'] = $info['dts']['bitrate'];
+ $thisfile_audio['sample_rate'] = $info['dts']['sample_rate'];
+ }
+ break;
+ case 0x08AE: // ClearJump LiteWave
+ $thisfile_audio['bitrate_mode'] = 'vbr';
+ $thisfile_audio_dataformat = 'litewave';
+
+ //typedef struct tagSLwFormat {
+ // WORD m_wCompFormat; // low byte defines compression method, high byte is compression flags
+ // DWORD m_dwScale; // scale factor for lossy compression
+ // DWORD m_dwBlockSize; // number of samples in encoded blocks
+ // WORD m_wQuality; // alias for the scale factor
+ // WORD m_wMarkDistance; // distance between marks in bytes
+ // WORD m_wReserved;
+ //
+ // //following paramters are ignored if CF_FILESRC is not set
+ // DWORD m_dwOrgSize; // original file size in bytes
+ // WORD m_bFactExists; // indicates if 'fact' chunk exists in the original file
+ // DWORD m_dwRiffChunkSize; // riff chunk size in the original file
+ //
+ // PCMWAVEFORMAT m_OrgWf; // original wave format
+ // }SLwFormat, *PSLwFormat;
+
+ // shortcut
+ $thisfile_riff['litewave']['raw'] = array();
+ $riff_litewave = &$thisfile_riff['litewave'];
+ $riff_litewave_raw = &$riff_litewave['raw'];
+
+ $flags = array(
+ 'compression_method' => 1,
+ 'compression_flags' => 1,
+ 'm_dwScale' => 4,
+ 'm_dwBlockSize' => 4,
+ 'm_wQuality' => 2,
+ 'm_wMarkDistance' => 2,
+ 'm_wReserved' => 2,
+ 'm_dwOrgSize' => 4,
+ 'm_bFactExists' => 2,
+ 'm_dwRiffChunkSize' => 4,
+ );
+ $litewave_offset = 18;
+ foreach ($flags as $flag => $length) {
+ $riff_litewave_raw[$flag] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], $litewave_offset, $length));
+ $litewave_offset += $length;
+ }
+
+ //$riff_litewave['quality_factor'] = intval(round((2000 - $riff_litewave_raw['m_dwScale']) / 20));
+ $riff_litewave['quality_factor'] = $riff_litewave_raw['m_wQuality'];
+
+ $riff_litewave['flags']['raw_source'] = ($riff_litewave_raw['compression_flags'] & 0x01) ? false : true;
+ $riff_litewave['flags']['vbr_blocksize'] = ($riff_litewave_raw['compression_flags'] & 0x02) ? false : true;
+ $riff_litewave['flags']['seekpoints'] = (bool) ($riff_litewave_raw['compression_flags'] & 0x04);
+
+ $thisfile_audio['lossless'] = (($riff_litewave_raw['m_wQuality'] == 100) ? true : false);
+ $thisfile_audio['encoder_options'] = '-q'.$riff_litewave['quality_factor'];
+ break;
+
+ default:
+ break;
+ }
+ }
+ if ($info['avdataend'] > $info['filesize']) {
+ switch (!empty($thisfile_audio_dataformat) ? $thisfile_audio_dataformat : '') {
+ case 'wavpack': // WavPack
+ case 'lpac': // LPAC
+ case 'ofr': // OptimFROG
+ case 'ofs': // OptimFROG DualStream
+ // lossless compressed audio formats that keep original RIFF headers - skip warning
+ break;
+
+ case 'litewave':
+ if (($info['avdataend'] - $info['filesize']) == 1) {
+ // LiteWave appears to incorrectly *not* pad actual output file
+ // to nearest WORD boundary so may appear to be short by one
+ // byte, in which case - skip warning
+ } else {
+ // Short by more than one byte, throw warning
+ $info['warning'][] = 'Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
+ $info['avdataend'] = $info['filesize'];
+ }
+ break;
+
+ default:
+ if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2) == 0) && ((($info['filesize'] - $info['avdataoffset']) % 2) == 1)) {
+ // output file appears to be incorrectly *not* padded to nearest WORD boundary
+ // Output less severe warning
+ $info['warning'][] = 'File should probably be padded to nearest WORD boundary, but it is not (expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' therefore short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
+ $info['avdataend'] = $info['filesize'];
+ } else {
+ // Short by more than one byte, throw warning
+ $info['warning'][] = 'Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
+ $info['avdataend'] = $info['filesize'];
+ }
+ break;
+ }
+ }
+ if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) {
+ if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) {
+ $info['avdataend']--;
+ $info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
+ }
+ }
+ if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) {
+ unset($thisfile_audio['bits_per_sample']);
+ if (!empty($info['ac3']['bitrate']) && ($info['ac3']['bitrate'] != $thisfile_audio['bitrate'])) {
+ $thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
+ }
+ }
+ break;
+
+ case 'AVI ':
+ $thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
+ $thisfile_video['dataformat'] = 'avi';
+ $info['mime_type'] = 'video/avi';
+
+ if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
+ $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
+ if (isset($thisfile_riff['AVIX'])) {
+ $info['avdataend'] = $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['offset'] + $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['size'];
+ } else {
+ $info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size'];
+ }
+ if ($info['avdataend'] > $info['filesize']) {
+ $info['warning'][] = 'Probably truncated file - expecting '.($info['avdataend'] - $info['avdataoffset']).' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($info['avdataend'] - $info['filesize']).' bytes)';
+ $info['avdataend'] = $info['filesize'];
+ }
+ }
+
+ if (isset($thisfile_riff['AVI ']['hdrl']['strl']['indx'])) {
+ //$bIndexType = array(
+ // 0x00 => 'AVI_INDEX_OF_INDEXES',
+ // 0x01 => 'AVI_INDEX_OF_CHUNKS',
+ // 0x80 => 'AVI_INDEX_IS_DATA',
+ //);
+ //$bIndexSubtype = array(
+ // 0x01 => array(
+ // 0x01 => 'AVI_INDEX_2FIELD',
+ // ),
+ //);
+ foreach ($thisfile_riff['AVI ']['hdrl']['strl']['indx'] as $streamnumber => $steamdataarray) {
+ $ahsisd = &$thisfile_riff['AVI ']['hdrl']['strl']['indx'][$streamnumber]['data'];
+
+ $thisfile_riff_raw['indx'][$streamnumber]['wLongsPerEntry'] = $this->EitherEndian2Int(substr($ahsisd, 0, 2));
+ $thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType'] = $this->EitherEndian2Int(substr($ahsisd, 2, 1));
+ $thisfile_riff_raw['indx'][$streamnumber]['bIndexType'] = $this->EitherEndian2Int(substr($ahsisd, 3, 1));
+ $thisfile_riff_raw['indx'][$streamnumber]['nEntriesInUse'] = $this->EitherEndian2Int(substr($ahsisd, 4, 4));
+ $thisfile_riff_raw['indx'][$streamnumber]['dwChunkId'] = substr($ahsisd, 8, 4);
+ $thisfile_riff_raw['indx'][$streamnumber]['dwReserved'] = $this->EitherEndian2Int(substr($ahsisd, 12, 4));
+
+ //$thisfile_riff_raw['indx'][$streamnumber]['bIndexType_name'] = $bIndexType[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']];
+ //$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType_name'] = $bIndexSubtype[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']][$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType']];
+
+ unset($ahsisd);
+ }
+ }
+ if (isset($thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'])) {
+ $avihData = $thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'];
+
+ // shortcut
+ $thisfile_riff_raw['avih'] = array();
+ $thisfile_riff_raw_avih = &$thisfile_riff_raw['avih'];
+
+ $thisfile_riff_raw_avih['dwMicroSecPerFrame'] = $this->EitherEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L)
+ if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
+ $info['error'][] = 'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero';
+ return false;
+ }
+
+ $flags = array(
+ 'dwMaxBytesPerSec', // max. transfer rate
+ 'dwPaddingGranularity', // pad to multiples of this size; normally 2K.
+ 'dwFlags', // the ever-present flags
+ 'dwTotalFrames', // # frames in file
+ 'dwInitialFrames', //
+ 'dwStreams', //
+ 'dwSuggestedBufferSize', //
+ 'dwWidth', //
+ 'dwHeight', //
+ 'dwScale', //
+ 'dwRate', //
+ 'dwStart', //
+ 'dwLength', //
+ );
+ $avih_offset = 4;
+ foreach ($flags as $flag) {
+ $thisfile_riff_raw_avih[$flag] = $this->EitherEndian2Int(substr($avihData, $avih_offset, 4));
+ $avih_offset += 4;
+ }
+
+ $flags = array(
+ 'hasindex' => 0x00000010,
+ 'mustuseindex' => 0x00000020,
+ 'interleaved' => 0x00000100,
+ 'trustcktype' => 0x00000800,
+ 'capturedfile' => 0x00010000,
+ 'copyrighted' => 0x00020010,
+ );
+ foreach ($flags as $flag => $value) {
+ $thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
+ }
+
+ // shortcut
+ $thisfile_riff_video[$streamindex] = array();
+ $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
+
+ if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
+ $thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth'];
+ $thisfile_video['resolution_x'] = $thisfile_riff_video_current['frame_width'];
+ }
+ if ($thisfile_riff_raw_avih['dwHeight'] > 0) {
+ $thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight'];
+ $thisfile_video['resolution_y'] = $thisfile_riff_video_current['frame_height'];
+ }
+ if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) {
+ $thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames'];
+ $thisfile_video['total_frames'] = $thisfile_riff_video_current['total_frames'];
+ }
+
+ $thisfile_riff_video_current['frame_rate'] = round(1000000 / $thisfile_riff_raw_avih['dwMicroSecPerFrame'], 3);
+ $thisfile_video['frame_rate'] = $thisfile_riff_video_current['frame_rate'];
+ }
+ if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) {
+ if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) {
+ for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) {
+ if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) {
+ $strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'];
+ $strhfccType = substr($strhData, 0, 4);
+
+ if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) {
+ $strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'];
+
+ // shortcut
+ $thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw['strf'][$strhfccType][$streamindex];
+
+ switch ($strhfccType) {
+ case 'auds':
+ $thisfile_audio['bitrate_mode'] = 'cbr';
+ $thisfile_audio_dataformat = 'wav';
+ if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) {
+ $streamindex = count($thisfile_riff_audio);
+ }
+
+ $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($strfData);
+ $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
+
+ // shortcut
+ $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
+ $thisfile_audio_streams_currentstream = &$thisfile_audio['streams'][$streamindex];
+
+ if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) {
+ unset($thisfile_audio_streams_currentstream['bits_per_sample']);
+ }
+ $thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag'];
+ unset($thisfile_audio_streams_currentstream['raw']);
+
+ // shortcut
+ $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw'];
+
+ unset($thisfile_riff_audio[$streamindex]['raw']);
+ $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
+
+ $thisfile_audio['lossless'] = false;
+ switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) {
+ case 0x0001: // PCM
+ $thisfile_audio_dataformat = 'wav';
+ $thisfile_audio['lossless'] = true;
+ break;
+
+ case 0x0050: // MPEG Layer 2 or Layer 1
+ $thisfile_audio_dataformat = 'mp2'; // Assume Layer-2
+ break;
+
+ case 0x0055: // MPEG Layer 3
+ $thisfile_audio_dataformat = 'mp3';
+ break;
+
+ case 0x00FF: // AAC
+ $thisfile_audio_dataformat = 'aac';
+ break;
+
+ case 0x0161: // Windows Media v7 / v8 / v9
+ case 0x0162: // Windows Media Professional v9
+ case 0x0163: // Windows Media Lossess v9
+ $thisfile_audio_dataformat = 'wma';
+ break;
+
+ case 0x2000: // AC-3
+ $thisfile_audio_dataformat = 'ac3';
+ break;
+
+ case 0x2001: // DTS
+ $thisfile_audio_dataformat = 'dts';
+ break;
+
+ default:
+ $thisfile_audio_dataformat = 'wav';
+ break;
+ }
+ $thisfile_audio_streams_currentstream['dataformat'] = $thisfile_audio_dataformat;
+ $thisfile_audio_streams_currentstream['lossless'] = $thisfile_audio['lossless'];
+ $thisfile_audio_streams_currentstream['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
+ break;
+
+
+ case 'iavs':
+ case 'vids':
+ // shortcut
+ $thisfile_riff_raw['strh'][$i] = array();
+ $thisfile_riff_raw_strh_current = &$thisfile_riff_raw['strh'][$i];
+
+ $thisfile_riff_raw_strh_current['fccType'] = substr($strhData, 0, 4); // same as $strhfccType;
+ $thisfile_riff_raw_strh_current['fccHandler'] = substr($strhData, 4, 4);
+ $thisfile_riff_raw_strh_current['dwFlags'] = $this->EitherEndian2Int(substr($strhData, 8, 4)); // Contains AVITF_* flags
+ $thisfile_riff_raw_strh_current['wPriority'] = $this->EitherEndian2Int(substr($strhData, 12, 2));
+ $thisfile_riff_raw_strh_current['wLanguage'] = $this->EitherEndian2Int(substr($strhData, 14, 2));
+ $thisfile_riff_raw_strh_current['dwInitialFrames'] = $this->EitherEndian2Int(substr($strhData, 16, 4));
+ $thisfile_riff_raw_strh_current['dwScale'] = $this->EitherEndian2Int(substr($strhData, 20, 4));
+ $thisfile_riff_raw_strh_current['dwRate'] = $this->EitherEndian2Int(substr($strhData, 24, 4));
+ $thisfile_riff_raw_strh_current['dwStart'] = $this->EitherEndian2Int(substr($strhData, 28, 4));
+ $thisfile_riff_raw_strh_current['dwLength'] = $this->EitherEndian2Int(substr($strhData, 32, 4));
+ $thisfile_riff_raw_strh_current['dwSuggestedBufferSize'] = $this->EitherEndian2Int(substr($strhData, 36, 4));
+ $thisfile_riff_raw_strh_current['dwQuality'] = $this->EitherEndian2Int(substr($strhData, 40, 4));
+ $thisfile_riff_raw_strh_current['dwSampleSize'] = $this->EitherEndian2Int(substr($strhData, 44, 4));
+ $thisfile_riff_raw_strh_current['rcFrame'] = $this->EitherEndian2Int(substr($strhData, 48, 4));
+
+ $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strh_current['fccHandler']);
+ $thisfile_video['fourcc'] = $thisfile_riff_raw_strh_current['fccHandler'];
+ if (!$thisfile_riff_video_current['codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
+ $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']);
+ $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
+ }
+ $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
+ $thisfile_video['pixel_aspect_ratio'] = (float) 1;
+ switch ($thisfile_riff_raw_strh_current['fccHandler']) {
+ case 'HFYU': // Huffman Lossless Codec
+ case 'IRAW': // Intel YUV Uncompressed
+ case 'YUY2': // Uncompressed YUV 4:2:2
+ $thisfile_video['lossless'] = true;
+ break;
+
+ default:
+ $thisfile_video['lossless'] = false;
+ break;
+ }
+
+ switch ($strhfccType) {
+ case 'vids':
+ $thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($info['fileformat'] == 'riff'));
+ $thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount'];
+
+ if ($thisfile_riff_video_current['codec'] == 'DV') {
+ $thisfile_riff_video_current['dv_type'] = 2;
+ }
+ break;
+
+ case 'iavs':
+ $thisfile_riff_video_current['dv_type'] = 1;
+ break;
+ }
+ break;
+
+ default:
+ $info['warning'][] = 'Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"';
+ break;
+
+ }
+ }
+ }
+
+ if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
+
+ $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
+ if (self::fourccLookup($thisfile_video['fourcc'])) {
+ $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_video['fourcc']);
+ $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
+ }
+
+ switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) {
+ case 'HFYU': // Huffman Lossless Codec
+ case 'IRAW': // Intel YUV Uncompressed
+ case 'YUY2': // Uncompressed YUV 4:2:2
+ $thisfile_video['lossless'] = true;
+ //$thisfile_video['bits_per_sample'] = 24;
+ break;
+
+ default:
+ $thisfile_video['lossless'] = false;
+ //$thisfile_video['bits_per_sample'] = 24;
+ break;
+ }
+
+ }
+ }
+ }
+ }
+ break;
+
+ case 'CDDA':
+ $thisfile_audio['bitrate_mode'] = 'cbr';
+ $thisfile_audio_dataformat = 'cda';
+ $thisfile_audio['lossless'] = true;
+ unset($info['mime_type']);
+
+ $info['avdataoffset'] = 44;
+
+ if (isset($thisfile_riff['CDDA']['fmt '][0]['data'])) {
+ // shortcut
+ $thisfile_riff_CDDA_fmt_0 = &$thisfile_riff['CDDA']['fmt '][0];
+
+ $thisfile_riff_CDDA_fmt_0['unknown1'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 0, 2));
+ $thisfile_riff_CDDA_fmt_0['track_num'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 2, 2));
+ $thisfile_riff_CDDA_fmt_0['disc_id'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 4, 4));
+ $thisfile_riff_CDDA_fmt_0['start_offset_frame'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 8, 4));
+ $thisfile_riff_CDDA_fmt_0['playtime_frames'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 12, 4));
+ $thisfile_riff_CDDA_fmt_0['unknown6'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 16, 4));
+ $thisfile_riff_CDDA_fmt_0['unknown7'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 20, 4));
+
+ $thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75;
+ $thisfile_riff_CDDA_fmt_0['playtime_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75;
+ $info['comments']['track'] = $thisfile_riff_CDDA_fmt_0['track_num'];
+ $info['playtime_seconds'] = $thisfile_riff_CDDA_fmt_0['playtime_seconds'];
+
+ // hardcoded data for CD-audio
+ $thisfile_audio['sample_rate'] = 44100;
+ $thisfile_audio['channels'] = 2;
+ $thisfile_audio['bits_per_sample'] = 16;
+ $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $thisfile_audio['channels'] * $thisfile_audio['bits_per_sample'];
+ $thisfile_audio['bitrate_mode'] = 'cbr';
+ }
+ break;
+
+
+ case 'AIFF':
+ case 'AIFC':
+ $thisfile_audio['bitrate_mode'] = 'cbr';
+ $thisfile_audio_dataformat = 'aiff';
+ $thisfile_audio['lossless'] = true;
+ $info['mime_type'] = 'audio/x-aiff';
+
+ if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) {
+ $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'] + 8;
+ $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['SSND'][0]['size'];
+ if ($info['avdataend'] > $info['filesize']) {
+ if (($info['avdataend'] == ($info['filesize'] + 1)) && (($info['filesize'] % 2) == 1)) {
+ // structures rounded to 2-byte boundary, but dumb encoders
+ // forget to pad end of file to make this actually work
+ } else {
+ $info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found';
+ }
+ $info['avdataend'] = $info['filesize'];
+ }
+ }
+
+ if (isset($thisfile_riff[$RIFFsubtype]['COMM'][0]['data'])) {
+
+ // shortcut
+ $thisfile_riff_RIFFsubtype_COMM_0_data = &$thisfile_riff[$RIFFsubtype]['COMM'][0]['data'];
+
+ $thisfile_riff_audio['channels'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 0, 2), true);
+ $thisfile_riff_audio['total_samples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 2, 4), false);
+ $thisfile_riff_audio['bits_per_sample'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 6, 2), true);
+ $thisfile_riff_audio['sample_rate'] = (int) getid3_lib::BigEndian2Float(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 8, 10));
+
+ if ($thisfile_riff[$RIFFsubtype]['COMM'][0]['size'] > 18) {
+ $thisfile_riff_audio['codec_fourcc'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 18, 4);
+ $CodecNameSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 22, 1), false);
+ $thisfile_riff_audio['codec_name'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 23, $CodecNameSize);
+ switch ($thisfile_riff_audio['codec_name']) {
+ case 'NONE':
+ $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
+ $thisfile_audio['lossless'] = true;
+ break;
+
+ case '':
+ switch ($thisfile_riff_audio['codec_fourcc']) {
+ // http://developer.apple.com/qa/snd/snd07.html
+ case 'sowt':
+ $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM';
+ $thisfile_audio['lossless'] = true;
+ break;
+
+ case 'twos':
+ $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM';
+ $thisfile_audio['lossless'] = true;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ $thisfile_audio['codec'] = $thisfile_riff_audio['codec_name'];
+ $thisfile_audio['lossless'] = false;
+ break;
+ }
+ }
+
+ $thisfile_audio['channels'] = $thisfile_riff_audio['channels'];
+ if ($thisfile_riff_audio['bits_per_sample'] > 0) {
+ $thisfile_audio['bits_per_sample'] = $thisfile_riff_audio['bits_per_sample'];
+ }
+ $thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate'];
+ if ($thisfile_audio['sample_rate'] == 0) {
+ $info['error'][] = 'Corrupted AIFF file: sample_rate == zero';
+ return false;
+ }
+ $info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate'];
+ }
+
+ if (isset($thisfile_riff[$RIFFsubtype]['COMT'])) {
+ $offset = 0;
+ $CommentCount = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
+ $offset += 2;
+ for ($i = 0; $i < $CommentCount; $i++) {
+ $info['comments_raw'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 4), false);
+ $offset += 4;
+ $info['comments_raw'][$i]['marker_id'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), true);
+ $offset += 2;
+ $CommentLength = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
+ $offset += 2;
+ $info['comments_raw'][$i]['comment'] = substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, $CommentLength);
+ $offset += $CommentLength;
+
+ $info['comments_raw'][$i]['timestamp_unix'] = getid3_lib::DateMac2Unix($info['comments_raw'][$i]['timestamp']);
+ $thisfile_riff['comments']['comment'][] = $info['comments_raw'][$i]['comment'];
+ }
+ }
+
+ $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment');
+ foreach ($CommentsChunkNames as $key => $value) {
+ if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
+ $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
+ }
+ }
+/*
+ if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) {
+ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
+ $getid3_temp = new getID3();
+ $getid3_temp->openfile($this->getid3->filename);
+ $getid3_id3v2 = new getid3_id3v2($getid3_temp);
+ $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8;
+ if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
+ $info['id3v2'] = $getid3_temp->info['id3v2'];
+ }
+ unset($getid3_temp, $getid3_id3v2);
+ }
+*/
+ break;
+
+ case '8SVX':
+ $thisfile_audio['bitrate_mode'] = 'cbr';
+ $thisfile_audio_dataformat = '8svx';
+ $thisfile_audio['bits_per_sample'] = 8;
+ $thisfile_audio['channels'] = 1; // overridden below, if need be
+ $info['mime_type'] = 'audio/x-aiff';
+
+ if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
+ $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
+ $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'];
+ if ($info['avdataend'] > $info['filesize']) {
+ $info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found';
+ }
+ }
+
+ if (isset($thisfile_riff[$RIFFsubtype]['VHDR'][0]['offset'])) {
+ // shortcut
+ $thisfile_riff_RIFFsubtype_VHDR_0 = &$thisfile_riff[$RIFFsubtype]['VHDR'][0];
+
+ $thisfile_riff_RIFFsubtype_VHDR_0['oneShotHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 0, 4));
+ $thisfile_riff_RIFFsubtype_VHDR_0['repeatHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 4, 4));
+ $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerHiCycle'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 8, 4));
+ $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 12, 2));
+ $thisfile_riff_RIFFsubtype_VHDR_0['ctOctave'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 14, 1));
+ $thisfile_riff_RIFFsubtype_VHDR_0['sCompression'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 15, 1));
+ $thisfile_riff_RIFFsubtype_VHDR_0['Volume'] = getid3_lib::FixedPoint16_16(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 16, 4));
+
+ $thisfile_audio['sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'];
+
+ switch ($thisfile_riff_RIFFsubtype_VHDR_0['sCompression']) {
+ case 0:
+ $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
+ $thisfile_audio['lossless'] = true;
+ $ActualBitsPerSample = 8;
+ break;
+
+ case 1:
+ $thisfile_audio['codec'] = 'Fibonacci-delta encoding';
+ $thisfile_audio['lossless'] = false;
+ $ActualBitsPerSample = 4;
+ break;
+
+ default:
+ $info['warning'][] = 'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"';
+ break;
+ }
+ }
+
+ if (isset($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'])) {
+ $ChannelsIndex = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'], 0, 4));
+ switch ($ChannelsIndex) {
+ case 6: // Stereo
+ $thisfile_audio['channels'] = 2;
+ break;
+
+ case 2: // Left channel only
+ case 4: // Right channel only
+ $thisfile_audio['channels'] = 1;
+ break;
+
+ default:
+ $info['warning'][] = 'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"';
+ break;
+ }
+
+ }
+
+ $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment');
+ foreach ($CommentsChunkNames as $key => $value) {
+ if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
+ $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
+ }
+ }
+
+ $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $ActualBitsPerSample * $thisfile_audio['channels'];
+ if (!empty($thisfile_audio['bitrate'])) {
+ $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) / ($thisfile_audio['bitrate'] / 8);
+ }
+ break;
+
+
+ case 'CDXA':
+ $info['mime_type'] = 'video/mpeg';
+ if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) {
+ if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, false)) {
+ $getid3_temp = new getID3();
+ $getid3_temp->openfile($this->getid3->filename);
+ $getid3_mpeg = new getid3_mpeg($getid3_temp);
+ $getid3_mpeg->Analyze();
+ if (empty($getid3_temp->info['error'])) {
+ $info['audio'] = $getid3_temp->info['audio'];
+ $info['video'] = $getid3_temp->info['video'];
+ $info['mpeg'] = $getid3_temp->info['mpeg'];
+ $info['warning'] = $getid3_temp->info['warning'];
+ }
+ unset($getid3_temp, $getid3_mpeg);
+ }
+ }
+ break;
+
+
+ default:
+ $info['error'][] = 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "'.$RIFFsubtype.'" instead';
+ unset($info['fileformat']);
+ break;
+ }
+
+ switch ($RIFFsubtype) {
+ case 'WAVE':
+ case 'AIFF':
+ case 'AIFC':
+ $ID3v2_key_good = 'id3 ';
+ $ID3v2_keys_bad = array('ID3 ', 'tag ');
+ foreach ($ID3v2_keys_bad as $ID3v2_key_bad) {
+ if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) {
+ $thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad];
+ $info['warning'][] = 'mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"';
+ }
+ }
+
+ if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) {
+ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
+ $getid3_temp = new getID3();
+ $getid3_temp->openfile($this->getid3->filename);
+ $getid3_id3v2 = new getid3_id3v2($getid3_temp);
+ $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8;
+ if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
+ $info['id3v2'] = $getid3_temp->info['id3v2'];
+ }
+ unset($getid3_temp, $getid3_id3v2);
+ }
+ break;
+ }
+
+ if (isset($thisfile_riff_WAVE['DISP']) && is_array($thisfile_riff_WAVE['DISP'])) {
+ $thisfile_riff['comments']['title'][] = trim(substr($thisfile_riff_WAVE['DISP'][count($thisfile_riff_WAVE['DISP']) - 1]['data'], 4));
+ }
+ if (isset($thisfile_riff_WAVE['INFO']) && is_array($thisfile_riff_WAVE['INFO'])) {
+ self::parseComments($thisfile_riff_WAVE['INFO'], $thisfile_riff['comments']);
+ }
+ if (isset($thisfile_riff['AVI ']['INFO']) && is_array($thisfile_riff['AVI ']['INFO'])) {
+ self::parseComments($thisfile_riff['AVI ']['INFO'], $thisfile_riff['comments']);
+ }
+
+ if (empty($thisfile_audio['encoder']) && !empty($info['mpeg']['audio']['LAME']['short_version'])) {
+ $thisfile_audio['encoder'] = $info['mpeg']['audio']['LAME']['short_version'];
+ }
+
+ if (!isset($info['playtime_seconds'])) {
+ $info['playtime_seconds'] = 0;
+ }
+ if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
+ // needed for >2GB AVIs where 'avih' chunk only lists number of frames in that chunk, not entire movie
+ $info['playtime_seconds'] = $thisfile_riff_raw['strh'][0]['dwLength'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
+ } elseif (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
+ $info['playtime_seconds'] = $thisfile_riff_raw['avih']['dwTotalFrames'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
+ }
+
+ if ($info['playtime_seconds'] > 0) {
+ if (isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
+
+ if (!isset($info['bitrate'])) {
+ $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
+ }
+
+ } elseif (isset($thisfile_riff_audio) && !isset($thisfile_riff_video)) {
+
+ if (!isset($thisfile_audio['bitrate'])) {
+ $thisfile_audio['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
+ }
+
+ } elseif (!isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
+
+ if (!isset($thisfile_video['bitrate'])) {
+ $thisfile_video['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
+ }
+
+ }
+ }
+
+
+ if (isset($thisfile_riff_video) && isset($thisfile_audio['bitrate']) && ($thisfile_audio['bitrate'] > 0) && ($info['playtime_seconds'] > 0)) {
+
+ $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
+ $thisfile_audio['bitrate'] = 0;
+ $thisfile_video['bitrate'] = $info['bitrate'];
+ foreach ($thisfile_riff_audio as $channelnumber => $audioinfoarray) {
+ $thisfile_video['bitrate'] -= $audioinfoarray['bitrate'];
+ $thisfile_audio['bitrate'] += $audioinfoarray['bitrate'];
+ }
+ if ($thisfile_video['bitrate'] <= 0) {
+ unset($thisfile_video['bitrate']);
+ }
+ if ($thisfile_audio['bitrate'] <= 0) {
+ unset($thisfile_audio['bitrate']);
+ }
+ }
+
+ if (isset($info['mpeg']['audio'])) {
+ $thisfile_audio_dataformat = 'mp'.$info['mpeg']['audio']['layer'];
+ $thisfile_audio['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
+ $thisfile_audio['channels'] = $info['mpeg']['audio']['channels'];
+ $thisfile_audio['bitrate'] = $info['mpeg']['audio']['bitrate'];
+ $thisfile_audio['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
+ if (!empty($info['mpeg']['audio']['codec'])) {
+ $thisfile_audio['codec'] = $info['mpeg']['audio']['codec'].' '.$thisfile_audio['codec'];
+ }
+ if (!empty($thisfile_audio['streams'])) {
+ foreach ($thisfile_audio['streams'] as $streamnumber => $streamdata) {
+ if ($streamdata['dataformat'] == $thisfile_audio_dataformat) {
+ $thisfile_audio['streams'][$streamnumber]['sample_rate'] = $thisfile_audio['sample_rate'];
+ $thisfile_audio['streams'][$streamnumber]['channels'] = $thisfile_audio['channels'];
+ $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate'];
+ $thisfile_audio['streams'][$streamnumber]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
+ $thisfile_audio['streams'][$streamnumber]['codec'] = $thisfile_audio['codec'];
+ }
+ }
+ }
+ $getid3_mp3 = new getid3_mp3($this->getid3);
+ $thisfile_audio['encoder_options'] = $getid3_mp3->GuessEncoderOptions();
+ unset($getid3_mp3);
+ }
+
+
+ if (!empty($thisfile_riff_raw['fmt ']['wBitsPerSample']) && ($thisfile_riff_raw['fmt ']['wBitsPerSample'] > 0)) {
+ switch ($thisfile_audio_dataformat) {
+ case 'ac3':
+ // ignore bits_per_sample
+ break;
+
+ default:
+ $thisfile_audio['bits_per_sample'] = $thisfile_riff_raw['fmt ']['wBitsPerSample'];
+ break;
+ }
+ }
+
+
+ if (empty($thisfile_riff_raw)) {
+ unset($thisfile_riff['raw']);
+ }
+ if (empty($thisfile_riff_audio)) {
+ unset($thisfile_riff['audio']);
+ }
+ if (empty($thisfile_riff_video)) {
+ unset($thisfile_riff['video']);
+ }
+
+ return true;
+ }
+
+ public function ParseRIFF($startoffset, $maxoffset) {
+ $info = &$this->getid3->info;
+
+ $RIFFchunk = false;
+ $FoundAllChunksWeNeed = false;
+
+ try {
+ $this->fseek($startoffset);
+ $maxoffset = min($maxoffset, $info['avdataend']);
+ while ($this->ftell() < $maxoffset) {
+ $chunknamesize = $this->fread(8);
+ //$chunkname = substr($chunknamesize, 0, 4);
+ $chunkname = str_replace("\x00", '_', substr($chunknamesize, 0, 4)); // note: chunk names of 4 null bytes do appear to be legal (has been observed inside INFO and PRMI chunks, for example), but makes traversing array keys more difficult
+ $chunksize = $this->EitherEndian2Int(substr($chunknamesize, 4, 4));
+ //if (strlen(trim($chunkname, "\x00")) < 4) {
+ if (strlen($chunkname) < 4) {
+ $this->error('Expecting chunk name at offset '.($this->ftell() - 8).' but found nothing. Aborting RIFF parsing.');
+ break;
+ }
+ if (($chunksize == 0) && ($chunkname != 'JUNK')) {
+ $this->warning('Chunk ('.$chunkname.') size at offset '.($this->ftell() - 4).' is zero. Aborting RIFF parsing.');
+ break;
+ }
+ if (($chunksize % 2) != 0) {
+ // all structures are packed on word boundaries
+ $chunksize++;
+ }
+
+ switch ($chunkname) {
+ case 'LIST':
+ $listname = $this->fread(4);
+ if (preg_match('#^(movi|rec )$#i', $listname)) {
+ $RIFFchunk[$listname]['offset'] = $this->ftell() - 4;
+ $RIFFchunk[$listname]['size'] = $chunksize;
+
+ if (!$FoundAllChunksWeNeed) {
+ $WhereWeWere = $this->ftell();
+ $AudioChunkHeader = $this->fread(12);
+ $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2);
+ $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2);
+ $AudioChunkSize = getid3_lib::LittleEndian2Int(substr($AudioChunkHeader, 4, 4));
+
+ if ($AudioChunkStreamType == 'wb') {
+ $FirstFourBytes = substr($AudioChunkHeader, 8, 4);
+ if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', $FirstFourBytes)) {
+ // MP3
+ if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
+ $getid3_temp = new getID3();
+ $getid3_temp->openfile($this->getid3->filename);
+ $getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
+ $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
+ $getid3_mp3 = new getid3_mp3($getid3_temp);
+ $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
+ if (isset($getid3_temp->info['mpeg']['audio'])) {
+ $info['mpeg']['audio'] = $getid3_temp->info['mpeg']['audio'];
+ $info['audio'] = $getid3_temp->info['audio'];
+ $info['audio']['dataformat'] = 'mp'.$info['mpeg']['audio']['layer'];
+ $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
+ $info['audio']['channels'] = $info['mpeg']['audio']['channels'];
+ $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
+ $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
+ //$info['bitrate'] = $info['audio']['bitrate'];
+ }
+ unset($getid3_temp, $getid3_mp3);
+ }
+
+ } elseif (strpos($FirstFourBytes, getid3_ac3::syncword) === 0) {
+
+ // AC3
+ $getid3_temp = new getID3();
+ $getid3_temp->openfile($this->getid3->filename);
+ $getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
+ $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
+ $getid3_ac3 = new getid3_ac3($getid3_temp);
+ $getid3_ac3->Analyze();
+ if (empty($getid3_temp->info['error'])) {
+ $info['audio'] = $getid3_temp->info['audio'];
+ $info['ac3'] = $getid3_temp->info['ac3'];
+ if (!empty($getid3_temp->info['warning'])) {
+ foreach ($getid3_temp->info['warning'] as $key => $value) {
+ $info['warning'][] = $value;
+ }
+ }
+ }
+ unset($getid3_temp, $getid3_ac3);
+ }
+ }
+ $FoundAllChunksWeNeed = true;
+ $this->fseek($WhereWeWere);
+ }
+ $this->fseek($chunksize - 4, SEEK_CUR);
+
+ } else {
+
+ if (!isset($RIFFchunk[$listname])) {
+ $RIFFchunk[$listname] = array();
+ }
+ $LISTchunkParent = $listname;
+ $LISTchunkMaxOffset = $this->ftell() - 4 + $chunksize;
+ if ($parsedChunk = $this->ParseRIFF($this->ftell(), $LISTchunkMaxOffset)) {
+ $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk);
+ }
+
+ }
+ break;
+
+ default:
+ if (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname)) {
+ $this->fseek($chunksize, SEEK_CUR);
+ break;
+ }
+ $thisindex = 0;
+ if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) {
+ $thisindex = count($RIFFchunk[$chunkname]);
+ }
+ $RIFFchunk[$chunkname][$thisindex]['offset'] = $this->ftell() - 8;
+ $RIFFchunk[$chunkname][$thisindex]['size'] = $chunksize;
+ switch ($chunkname) {
+ case 'data':
+ $info['avdataoffset'] = $this->ftell();
+ $info['avdataend'] = $info['avdataoffset'] + $chunksize;
+
+ $testData = $this->fread(36);
+ if ($testData === '') {
+ break;
+ }
+ if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', substr($testData, 0, 4))) {
+
+ // Probably is MP3 data
+ if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) {
+ $getid3_temp = new getID3();
+ $getid3_temp->openfile($this->getid3->filename);
+ $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
+ $getid3_temp->info['avdataend'] = $info['avdataend'];
+ $getid3_mp3 = new getid3_mp3($getid3_temp);
+ $getid3_mp3->getOnlyMPEGaudioInfo($info['avdataoffset'], false);
+ if (empty($getid3_temp->info['error'])) {
+ $info['audio'] = $getid3_temp->info['audio'];
+ $info['mpeg'] = $getid3_temp->info['mpeg'];
+ }
+ unset($getid3_temp, $getid3_mp3);
+ }
+
+ } elseif (($isRegularAC3 = (substr($testData, 0, 2) == getid3_ac3::syncword)) || substr($testData, 8, 2) == strrev(getid3_ac3::syncword)) {
+
+ // This is probably AC-3 data
+ $getid3_temp = new getID3();
+ if ($isRegularAC3) {
+ $getid3_temp->openfile($this->getid3->filename);
+ $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
+ $getid3_temp->info['avdataend'] = $info['avdataend'];
+ }
+ $getid3_ac3 = new getid3_ac3($getid3_temp);
+ if ($isRegularAC3) {
+ $getid3_ac3->Analyze();
+ } else {
+ // Dolby Digital WAV
+ // AC-3 content, but not encoded in same format as normal AC-3 file
+ // For one thing, byte order is swapped
+ $ac3_data = '';
+ for ($i = 0; $i < 28; $i += 2) {
+ $ac3_data .= substr($testData, 8 + $i + 1, 1);
+ $ac3_data .= substr($testData, 8 + $i + 0, 1);
+ }
+ $getid3_ac3->AnalyzeString($ac3_data);
+ }
+
+ if (empty($getid3_temp->info['error'])) {
+ $info['audio'] = $getid3_temp->info['audio'];
+ $info['ac3'] = $getid3_temp->info['ac3'];
+ if (!empty($getid3_temp->info['warning'])) {
+ foreach ($getid3_temp->info['warning'] as $newerror) {
+ $this->warning('getid3_ac3() says: ['.$newerror.']');
+ }
+ }
+ }
+ unset($getid3_temp, $getid3_ac3);
+
+ } elseif (preg_match('/^('.implode('|', array_map('preg_quote', getid3_dts::$syncwords)).')/', $testData)) {
+
+ // This is probably DTS data
+ $getid3_temp = new getID3();
+ $getid3_temp->openfile($this->getid3->filename);
+ $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
+ $getid3_dts = new getid3_dts($getid3_temp);
+ $getid3_dts->Analyze();
+ if (empty($getid3_temp->info['error'])) {
+ $info['audio'] = $getid3_temp->info['audio'];
+ $info['dts'] = $getid3_temp->info['dts'];
+ $info['playtime_seconds'] = $getid3_temp->info['playtime_seconds']; // may not match RIFF calculations since DTS-WAV often used 14/16 bit-word packing
+ if (!empty($getid3_temp->info['warning'])) {
+ foreach ($getid3_temp->info['warning'] as $newerror) {
+ $this->warning('getid3_dts() says: ['.$newerror.']');
+ }
+ }
+ }
+
+ unset($getid3_temp, $getid3_dts);
+
+ } elseif (substr($testData, 0, 4) == 'wvpk') {
+
+ // This is WavPack data
+ $info['wavpack']['offset'] = $info['avdataoffset'];
+ $info['wavpack']['size'] = getid3_lib::LittleEndian2Int(substr($testData, 4, 4));
+ $this->parseWavPackHeader(substr($testData, 8, 28));
+
+ } else {
+ // This is some other kind of data (quite possibly just PCM)
+ // do nothing special, just skip it
+ }
+ $nextoffset = $info['avdataend'];
+ $this->fseek($nextoffset);
+ break;
+
+ case 'iXML':
+ case 'bext':
+ case 'cart':
+ case 'fmt ':
+ case 'strh':
+ case 'strf':
+ case 'indx':
+ case 'MEXT':
+ case 'DISP':
+ // always read data in
+ case 'JUNK':
+ // should be: never read data in
+ // but some programs write their version strings in a JUNK chunk (e.g. VirtualDub, AVIdemux, etc)
+ if ($chunksize < 1048576) {
+ if ($chunksize > 0) {
+ $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
+ if ($chunkname == 'JUNK') {
+ if (preg_match('#^([\\x20-\\x7F]+)#', $RIFFchunk[$chunkname][$thisindex]['data'], $matches)) {
+ // only keep text characters [chr(32)-chr(127)]
+ $info['riff']['comments']['junk'][] = trim($matches[1]);
+ }
+ // but if nothing there, ignore
+ // remove the key in either case
+ unset($RIFFchunk[$chunkname][$thisindex]['data']);
+ }
+ }
+ } else {
+ $this->warning('Chunk "'.$chunkname.'" at offset '.$this->ftell().' is unexpectedly larger than 1MB (claims to be '.number_format($chunksize).' bytes), skipping data');
+ $this->fseek($chunksize, SEEK_CUR);
+ }
+ break;
+
+ //case 'IDVX':
+ // $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize));
+ // break;
+
+ default:
+ if (!empty($LISTchunkParent) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
+ $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
+ $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
+ unset($RIFFchunk[$chunkname][$thisindex]['offset']);
+ unset($RIFFchunk[$chunkname][$thisindex]['size']);
+ if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) {
+ unset($RIFFchunk[$chunkname][$thisindex]);
+ }
+ if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) {
+ unset($RIFFchunk[$chunkname]);
+ }
+ $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = $this->fread($chunksize);
+ } elseif ($chunksize < 2048) {
+ // only read data in if smaller than 2kB
+ $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
+ } else {
+ $this->fseek($chunksize, SEEK_CUR);
+ }
+ break;
+ }
+ break;
+ }
+ }
+
+ } catch (getid3_exception $e) {
+ if ($e->getCode() == 10) {
+ $this->warning('RIFF parser: '.$e->getMessage());
+ } else {
+ throw $e;
+ }
+ }
+
+ return $RIFFchunk;
+ }
+
+ public function ParseRIFFdata(&$RIFFdata) {
+ $info = &$this->getid3->info;
+ if ($RIFFdata) {
+ $tempfile = tempnam(GETID3_TEMP_DIR, 'getID3');
+ $fp_temp = fopen($tempfile, 'wb');
+ $RIFFdataLength = strlen($RIFFdata);
+ $NewLengthString = getid3_lib::LittleEndian2String($RIFFdataLength, 4);
+ for ($i = 0; $i < 4; $i++) {
+ $RIFFdata[($i + 4)] = $NewLengthString[$i];
+ }
+ fwrite($fp_temp, $RIFFdata);
+ fclose($fp_temp);
+
+ $getid3_temp = new getID3();
+ $getid3_temp->openfile($tempfile);
+ $getid3_temp->info['filesize'] = $RIFFdataLength;
+ $getid3_temp->info['filenamepath'] = $info['filenamepath'];
+ $getid3_temp->info['tags'] = $info['tags'];
+ $getid3_temp->info['warning'] = $info['warning'];
+ $getid3_temp->info['error'] = $info['error'];
+ $getid3_temp->info['comments'] = $info['comments'];
+ $getid3_temp->info['audio'] = (isset($info['audio']) ? $info['audio'] : array());
+ $getid3_temp->info['video'] = (isset($info['video']) ? $info['video'] : array());
+ $getid3_riff = new getid3_riff($getid3_temp);
+ $getid3_riff->Analyze();
+
+ $info['riff'] = $getid3_temp->info['riff'];
+ $info['warning'] = $getid3_temp->info['warning'];
+ $info['error'] = $getid3_temp->info['error'];
+ $info['tags'] = $getid3_temp->info['tags'];
+ $info['comments'] = $getid3_temp->info['comments'];
+ unset($getid3_riff, $getid3_temp);
+ unlink($tempfile);
+ }
+ return false;
+ }
+
+ public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) {
+ $RIFFinfoKeyLookup = array(
+ 'IARL'=>'archivallocation',
+ 'IART'=>'artist',
+ 'ICDS'=>'costumedesigner',
+ 'ICMS'=>'commissionedby',
+ 'ICMT'=>'comment',
+ 'ICNT'=>'country',
+ 'ICOP'=>'copyright',
+ 'ICRD'=>'creationdate',
+ 'IDIM'=>'dimensions',
+ 'IDIT'=>'digitizationdate',
+ 'IDPI'=>'resolution',
+ 'IDST'=>'distributor',
+ 'IEDT'=>'editor',
+ 'IENG'=>'engineers',
+ 'IFRM'=>'accountofparts',
+ 'IGNR'=>'genre',
+ 'IKEY'=>'keywords',
+ 'ILGT'=>'lightness',
+ 'ILNG'=>'language',
+ 'IMED'=>'orignalmedium',
+ 'IMUS'=>'composer',
+ 'INAM'=>'title',
+ 'IPDS'=>'productiondesigner',
+ 'IPLT'=>'palette',
+ 'IPRD'=>'product',
+ 'IPRO'=>'producer',
+ 'IPRT'=>'part',
+ 'IRTD'=>'rating',
+ 'ISBJ'=>'subject',
+ 'ISFT'=>'software',
+ 'ISGN'=>'secondarygenre',
+ 'ISHP'=>'sharpness',
+ 'ISRC'=>'sourcesupplier',
+ 'ISRF'=>'digitizationsource',
+ 'ISTD'=>'productionstudio',
+ 'ISTR'=>'starring',
+ 'ITCH'=>'encoded_by',
+ 'IWEB'=>'url',
+ 'IWRI'=>'writer',
+ '____'=>'comment',
+ );
+ foreach ($RIFFinfoKeyLookup as $key => $value) {
+ if (isset($RIFFinfoArray[$key])) {
+ foreach ($RIFFinfoArray[$key] as $commentid => $commentdata) {
+ if (trim($commentdata['data']) != '') {
+ if (isset($CommentsTargetArray[$value])) {
+ $CommentsTargetArray[$value][] = trim($commentdata['data']);
+ } else {
+ $CommentsTargetArray[$value] = array(trim($commentdata['data']));
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ public static function parseWAVEFORMATex($WaveFormatExData) {
+ // shortcut
+ $WaveFormatEx['raw'] = array();
+ $WaveFormatEx_raw = &$WaveFormatEx['raw'];
+
+ $WaveFormatEx_raw['wFormatTag'] = substr($WaveFormatExData, 0, 2);
+ $WaveFormatEx_raw['nChannels'] = substr($WaveFormatExData, 2, 2);
+ $WaveFormatEx_raw['nSamplesPerSec'] = substr($WaveFormatExData, 4, 4);
+ $WaveFormatEx_raw['nAvgBytesPerSec'] = substr($WaveFormatExData, 8, 4);
+ $WaveFormatEx_raw['nBlockAlign'] = substr($WaveFormatExData, 12, 2);
+ $WaveFormatEx_raw['wBitsPerSample'] = substr($WaveFormatExData, 14, 2);
+ if (strlen($WaveFormatExData) > 16) {
+ $WaveFormatEx_raw['cbSize'] = substr($WaveFormatExData, 16, 2);
+ }
+ $WaveFormatEx_raw = array_map('getid3_lib::LittleEndian2Int', $WaveFormatEx_raw);
+
+ $WaveFormatEx['codec'] = self::wFormatTagLookup($WaveFormatEx_raw['wFormatTag']);
+ $WaveFormatEx['channels'] = $WaveFormatEx_raw['nChannels'];
+ $WaveFormatEx['sample_rate'] = $WaveFormatEx_raw['nSamplesPerSec'];
+ $WaveFormatEx['bitrate'] = $WaveFormatEx_raw['nAvgBytesPerSec'] * 8;
+ $WaveFormatEx['bits_per_sample'] = $WaveFormatEx_raw['wBitsPerSample'];
+
+ return $WaveFormatEx;
+ }
+
+ public function parseWavPackHeader($WavPackChunkData) {
+ // typedef struct {
+ // char ckID [4];
+ // long ckSize;
+ // short version;
+ // short bits; // added for version 2.00
+ // short flags, shift; // added for version 3.00
+ // long total_samples, crc, crc2;
+ // char extension [4], extra_bc, extras [3];
+ // } WavpackHeader;
+
+ // shortcut
+ $info = &$this->getid3->info;
+ $info['wavpack'] = array();
+ $thisfile_wavpack = &$info['wavpack'];
+
+ $thisfile_wavpack['version'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 0, 2));
+ if ($thisfile_wavpack['version'] >= 2) {
+ $thisfile_wavpack['bits'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 2, 2));
+ }
+ if ($thisfile_wavpack['version'] >= 3) {
+ $thisfile_wavpack['flags_raw'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 4, 2));
+ $thisfile_wavpack['shift'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 6, 2));
+ $thisfile_wavpack['total_samples'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 8, 4));
+ $thisfile_wavpack['crc1'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 12, 4));
+ $thisfile_wavpack['crc2'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 16, 4));
+ $thisfile_wavpack['extension'] = substr($WavPackChunkData, 20, 4);
+ $thisfile_wavpack['extra_bc'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 24, 1));
+ for ($i = 0; $i <= 2; $i++) {
+ $thisfile_wavpack['extras'][] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 25 + $i, 1));
+ }
+
+ // shortcut
+ $thisfile_wavpack['flags'] = array();
+ $thisfile_wavpack_flags = &$thisfile_wavpack['flags'];
+
+ $thisfile_wavpack_flags['mono'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000001);
+ $thisfile_wavpack_flags['fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000002);
+ $thisfile_wavpack_flags['raw_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000004);
+ $thisfile_wavpack_flags['calc_noise'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000008);
+ $thisfile_wavpack_flags['high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000010);
+ $thisfile_wavpack_flags['3_byte_samples'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000020);
+ $thisfile_wavpack_flags['over_20_bits'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000040);
+ $thisfile_wavpack_flags['use_wvc'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000080);
+ $thisfile_wavpack_flags['noiseshaping'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000100);
+ $thisfile_wavpack_flags['very_fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000200);
+ $thisfile_wavpack_flags['new_high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000400);
+ $thisfile_wavpack_flags['cancel_extreme'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000800);
+ $thisfile_wavpack_flags['cross_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x001000);
+ $thisfile_wavpack_flags['new_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x002000);
+ $thisfile_wavpack_flags['joint_stereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x004000);
+ $thisfile_wavpack_flags['extra_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x008000);
+ $thisfile_wavpack_flags['override_noiseshape'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x010000);
+ $thisfile_wavpack_flags['override_jointstereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x020000);
+ $thisfile_wavpack_flags['copy_source_filetime'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x040000);
+ $thisfile_wavpack_flags['create_exe'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x080000);
+ }
+
+ return true;
+ }
+
+ public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) {
+
+ $parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure
+ $parsed['biWidth'] = substr($BITMAPINFOHEADER, 4, 4); // width of the bitmap in pixels
+ $parsed['biHeight'] = substr($BITMAPINFOHEADER, 8, 4); // height of the bitmap in pixels. If biHeight is positive, the bitmap is a 'bottom-up' DIB and its origin is the lower left corner. If biHeight is negative, the bitmap is a 'top-down' DIB and its origin is the upper left corner
+ $parsed['biPlanes'] = substr($BITMAPINFOHEADER, 12, 2); // number of color planes on the target device. In most cases this value must be set to 1
+ $parsed['biBitCount'] = substr($BITMAPINFOHEADER, 14, 2); // Specifies the number of bits per pixels
+ $parsed['biSizeImage'] = substr($BITMAPINFOHEADER, 20, 4); // size of the bitmap data section of the image (the actual pixel data, excluding BITMAPINFOHEADER and RGBQUAD structures)
+ $parsed['biXPelsPerMeter'] = substr($BITMAPINFOHEADER, 24, 4); // horizontal resolution, in pixels per metre, of the target device
+ $parsed['biYPelsPerMeter'] = substr($BITMAPINFOHEADER, 28, 4); // vertical resolution, in pixels per metre, of the target device
+ $parsed['biClrUsed'] = substr($BITMAPINFOHEADER, 32, 4); // actual number of color indices in the color table used by the bitmap. If this value is zero, the bitmap uses the maximum number of colors corresponding to the value of the biBitCount member for the compression mode specified by biCompression
+ $parsed['biClrImportant'] = substr($BITMAPINFOHEADER, 36, 4); // number of color indices that are considered important for displaying the bitmap. If this value is zero, all colors are important
+ $parsed = array_map('getid3_lib::'.($littleEndian ? 'Little' : 'Big').'Endian2Int', $parsed);
+
+ $parsed['fourcc'] = substr($BITMAPINFOHEADER, 16, 4); // compression identifier
+
+ return $parsed;
+ }
+
+ public static function ParseDIVXTAG($DIVXTAG, $raw=false) {
+ // structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/
+ // source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip
+ // 'Byte Layout: '1111111111111111
+ // '32 for Movie - 1 '1111111111111111
+ // '28 for Author - 6 '6666666666666666
+ // '4 for year - 2 '6666666666662222
+ // '3 for genre - 3 '7777777777777777
+ // '48 for Comments - 7 '7777777777777777
+ // '1 for Rating - 4 '7777777777777777
+ // '5 for Future Additions - 0 '333400000DIVXTAG
+ // '128 bytes total
+
+ static $DIVXTAGgenre = array(
+ 0 => 'Action',
+ 1 => 'Action/Adventure',
+ 2 => 'Adventure',
+ 3 => 'Adult',
+ 4 => 'Anime',
+ 5 => 'Cartoon',
+ 6 => 'Claymation',
+ 7 => 'Comedy',
+ 8 => 'Commercial',
+ 9 => 'Documentary',
+ 10 => 'Drama',
+ 11 => 'Home Video',
+ 12 => 'Horror',
+ 13 => 'Infomercial',
+ 14 => 'Interactive',
+ 15 => 'Mystery',
+ 16 => 'Music Video',
+ 17 => 'Other',
+ 18 => 'Religion',
+ 19 => 'Sci Fi',
+ 20 => 'Thriller',
+ 21 => 'Western',
+ ),
+ $DIVXTAGrating = array(
+ 0 => 'Unrated',
+ 1 => 'G',
+ 2 => 'PG',
+ 3 => 'PG-13',
+ 4 => 'R',
+ 5 => 'NC-17',
+ );
+
+ $parsed['title'] = trim(substr($DIVXTAG, 0, 32));
+ $parsed['artist'] = trim(substr($DIVXTAG, 32, 28));
+ $parsed['year'] = intval(trim(substr($DIVXTAG, 60, 4)));
+ $parsed['comment'] = trim(substr($DIVXTAG, 64, 48));
+ $parsed['genre_id'] = intval(trim(substr($DIVXTAG, 112, 3)));
+ $parsed['rating_id'] = ord(substr($DIVXTAG, 115, 1));
+ //$parsed['padding'] = substr($DIVXTAG, 116, 5); // 5-byte null
+ //$parsed['magic'] = substr($DIVXTAG, 121, 7); // "DIVXTAG"
+
+ $parsed['genre'] = (isset($DIVXTAGgenre[$parsed['genre_id']]) ? $DIVXTAGgenre[$parsed['genre_id']] : $parsed['genre_id']);
+ $parsed['rating'] = (isset($DIVXTAGrating[$parsed['rating_id']]) ? $DIVXTAGrating[$parsed['rating_id']] : $parsed['rating_id']);
+
+ if (!$raw) {
+ unset($parsed['genre_id'], $parsed['rating_id']);
+ foreach ($parsed as $key => $value) {
+ if (!$value === '') {
+ unset($parsed['key']);
+ }
+ }
+ }
+
+ foreach ($parsed as $tag => $value) {
+ $parsed[$tag] = array($value);
+ }
+
+ return $parsed;
+ }
+
+ public static function waveSNDMtagLookup($tagshortname) {
+ $begin = __LINE__;
+
+ /** This is not a comment!
+
+ \A9kwd keywords
+ \A9BPM bpm
+ \A9trt tracktitle
+ \A9des description
+ \A9gen category
+ \A9fin featuredinstrument
+ \A9LID longid
+ \A9bex bwdescription
+ \A9pub publisher
+ \A9cdt cdtitle
+ \A9alb library
+ \A9com composer
+
+ */
+
+ return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm');
+ }
+
+ public static function wFormatTagLookup($wFormatTag) {
+
+ $begin = __LINE__;
+
+ /** This is not a comment!
+
+ 0x0000 Microsoft Unknown Wave Format
+ 0x0001 Pulse Code Modulation (PCM)
+ 0x0002 Microsoft ADPCM
+ 0x0003 IEEE Float
+ 0x0004 Compaq Computer VSELP
+ 0x0005 IBM CVSD
+ 0x0006 Microsoft A-Law
+ 0x0007 Microsoft mu-Law
+ 0x0008 Microsoft DTS
+ 0x0010 OKI ADPCM
+ 0x0011 Intel DVI/IMA ADPCM
+ 0x0012 Videologic MediaSpace ADPCM
+ 0x0013 Sierra Semiconductor ADPCM
+ 0x0014 Antex Electronics G.723 ADPCM
+ 0x0015 DSP Solutions DigiSTD
+ 0x0016 DSP Solutions DigiFIX
+ 0x0017 Dialogic OKI ADPCM
+ 0x0018 MediaVision ADPCM
+ 0x0019 Hewlett-Packard CU
+ 0x0020 Yamaha ADPCM
+ 0x0021 Speech Compression Sonarc
+ 0x0022 DSP Group TrueSpeech
+ 0x0023 Echo Speech EchoSC1
+ 0x0024 Audiofile AF36
+ 0x0025 Audio Processing Technology APTX
+ 0x0026 AudioFile AF10
+ 0x0027 Prosody 1612
+ 0x0028 LRC
+ 0x0030 Dolby AC2
+ 0x0031 Microsoft GSM 6.10
+ 0x0032 MSNAudio
+ 0x0033 Antex Electronics ADPCME
+ 0x0034 Control Resources VQLPC
+ 0x0035 DSP Solutions DigiREAL
+ 0x0036 DSP Solutions DigiADPCM
+ 0x0037 Control Resources CR10
+ 0x0038 Natural MicroSystems VBXADPCM
+ 0x0039 Crystal Semiconductor IMA ADPCM
+ 0x003A EchoSC3
+ 0x003B Rockwell ADPCM
+ 0x003C Rockwell Digit LK
+ 0x003D Xebec
+ 0x0040 Antex Electronics G.721 ADPCM
+ 0x0041 G.728 CELP
+ 0x0042 MSG723
+ 0x0050 MPEG Layer-2 or Layer-1
+ 0x0052 RT24
+ 0x0053 PAC
+ 0x0055 MPEG Layer-3
+ 0x0059 Lucent G.723
+ 0x0060 Cirrus
+ 0x0061 ESPCM
+ 0x0062 Voxware
+ 0x0063 Canopus Atrac
+ 0x0064 G.726 ADPCM
+ 0x0065 G.722 ADPCM
+ 0x0066 DSAT
+ 0x0067 DSAT Display
+ 0x0069 Voxware Byte Aligned
+ 0x0070 Voxware AC8
+ 0x0071 Voxware AC10
+ 0x0072 Voxware AC16
+ 0x0073 Voxware AC20
+ 0x0074 Voxware MetaVoice
+ 0x0075 Voxware MetaSound
+ 0x0076 Voxware RT29HW
+ 0x0077 Voxware VR12
+ 0x0078 Voxware VR18
+ 0x0079 Voxware TQ40
+ 0x0080 Softsound
+ 0x0081 Voxware TQ60
+ 0x0082 MSRT24
+ 0x0083 G.729A
+ 0x0084 MVI MV12
+ 0x0085 DF G.726
+ 0x0086 DF GSM610
+ 0x0088 ISIAudio
+ 0x0089 Onlive
+ 0x0091 SBC24
+ 0x0092 Dolby AC3 SPDIF
+ 0x0093 MediaSonic G.723
+ 0x0094 Aculab PLC Prosody 8kbps
+ 0x0097 ZyXEL ADPCM
+ 0x0098 Philips LPCBB
+ 0x0099 Packed
+ 0x00FF AAC
+ 0x0100 Rhetorex ADPCM
+ 0x0101 IBM mu-law
+ 0x0102 IBM A-law
+ 0x0103 IBM AVC Adaptive Differential Pulse Code Modulation (ADPCM)
+ 0x0111 Vivo G.723
+ 0x0112 Vivo Siren
+ 0x0123 Digital G.723
+ 0x0125 Sanyo LD ADPCM
+ 0x0130 Sipro Lab Telecom ACELP NET
+ 0x0131 Sipro Lab Telecom ACELP 4800
+ 0x0132 Sipro Lab Telecom ACELP 8V3
+ 0x0133 Sipro Lab Telecom G.729
+ 0x0134 Sipro Lab Telecom G.729A
+ 0x0135 Sipro Lab Telecom Kelvin
+ 0x0140 Windows Media Video V8
+ 0x0150 Qualcomm PureVoice
+ 0x0151 Qualcomm HalfRate
+ 0x0155 Ring Zero Systems TUB GSM
+ 0x0160 Microsoft Audio 1
+ 0x0161 Windows Media Audio V7 / V8 / V9
+ 0x0162 Windows Media Audio Professional V9
+ 0x0163 Windows Media Audio Lossless V9
+ 0x0200 Creative Labs ADPCM
+ 0x0202 Creative Labs Fastspeech8
+ 0x0203 Creative Labs Fastspeech10
+ 0x0210 UHER Informatic GmbH ADPCM
+ 0x0220 Quarterdeck
+ 0x0230 I-link Worldwide VC
+ 0x0240 Aureal RAW Sport
+ 0x0250 Interactive Products HSX
+ 0x0251 Interactive Products RPELP
+ 0x0260 Consistent Software CS2
+ 0x0270 Sony SCX
+ 0x0300 Fujitsu FM Towns Snd
+ 0x0400 BTV Digital
+ 0x0401 Intel Music Coder
+ 0x0450 QDesign Music
+ 0x0680 VME VMPCM
+ 0x0681 AT&T Labs TPC
+ 0x08AE ClearJump LiteWave
+ 0x1000 Olivetti GSM
+ 0x1001 Olivetti ADPCM
+ 0x1002 Olivetti CELP
+ 0x1003 Olivetti SBC
+ 0x1004 Olivetti OPR
+ 0x1100 Lernout & Hauspie Codec (0x1100)
+ 0x1101 Lernout & Hauspie CELP Codec (0x1101)
+ 0x1102 Lernout & Hauspie SBC Codec (0x1102)
+ 0x1103 Lernout & Hauspie SBC Codec (0x1103)
+ 0x1104 Lernout & Hauspie SBC Codec (0x1104)
+ 0x1400 Norris
+ 0x1401 AT&T ISIAudio
+ 0x1500 Soundspace Music Compression
+ 0x181C VoxWare RT24 Speech
+ 0x1FC4 NCT Soft ALF2CD (www.nctsoft.com)
+ 0x2000 Dolby AC3
+ 0x2001 Dolby DTS
+ 0x2002 WAVE_FORMAT_14_4
+ 0x2003 WAVE_FORMAT_28_8
+ 0x2004 WAVE_FORMAT_COOK
+ 0x2005 WAVE_FORMAT_DNET
+ 0x674F Ogg Vorbis 1
+ 0x6750 Ogg Vorbis 2
+ 0x6751 Ogg Vorbis 3
+ 0x676F Ogg Vorbis 1+
+ 0x6770 Ogg Vorbis 2+
+ 0x6771 Ogg Vorbis 3+
+ 0x7A21 GSM-AMR (CBR, no SID)
+ 0x7A22 GSM-AMR (VBR, including SID)
+ 0xFFFE WAVE_FORMAT_EXTENSIBLE
+ 0xFFFF WAVE_FORMAT_DEVELOPMENT
+
+ */
+
+ return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag');
+ }
+
+ public static function fourccLookup($fourcc) {
+
+ $begin = __LINE__;
+
+ /** This is not a comment!
+
+ swot http://developer.apple.com/qa/snd/snd07.html
+ ____ No Codec (____)
+ _BIT BI_BITFIELDS (Raw RGB)
+ _JPG JPEG compressed
+ _PNG PNG compressed W3C/ISO/IEC (RFC-2083)
+ _RAW Full Frames (Uncompressed)
+ _RGB Raw RGB Bitmap
+ _RL4 RLE 4bpp RGB
+ _RL8 RLE 8bpp RGB
+ 3IV1 3ivx MPEG-4 v1
+ 3IV2 3ivx MPEG-4 v2
+ 3IVX 3ivx MPEG-4
+ AASC Autodesk Animator
+ ABYR Kensington ?ABYR?
+ AEMI Array Microsystems VideoONE MPEG1-I Capture
+ AFLC Autodesk Animator FLC
+ AFLI Autodesk Animator FLI
+ AMPG Array Microsystems VideoONE MPEG
+ ANIM Intel RDX (ANIM)
+ AP41 AngelPotion Definitive
+ ASV1 Asus Video v1
+ ASV2 Asus Video v2
+ ASVX Asus Video 2.0 (audio)
+ AUR2 AuraVision Aura 2 Codec - YUV 4:2:2
+ AURA AuraVision Aura 1 Codec - YUV 4:1:1
+ AVDJ Independent JPEG Group\'s codec (AVDJ)
+ AVRN Independent JPEG Group\'s codec (AVRN)
+ AYUV 4:4:4 YUV (AYUV)
+ AZPR Quicktime Apple Video (AZPR)
+ BGR Raw RGB32
+ BLZ0 Blizzard DivX MPEG-4
+ BTVC Conexant Composite Video
+ BINK RAD Game Tools Bink Video
+ BT20 Conexant Prosumer Video
+ BTCV Conexant Composite Video Codec
+ BW10 Data Translation Broadway MPEG Capture
+ CC12 Intel YUV12
+ CDVC Canopus DV
+ CFCC Digital Processing Systems DPS Perception
+ CGDI Microsoft Office 97 Camcorder Video
+ CHAM Winnov Caviara Champagne
+ CJPG Creative WebCam JPEG
+ CLJR Cirrus Logic YUV 4:1:1
+ CMYK Common Data Format in Printing (Colorgraph)
+ CPLA Weitek 4:2:0 YUV Planar
+ CRAM Microsoft Video 1 (CRAM)
+ cvid Radius Cinepak
+ CVID Radius Cinepak
+ CWLT Microsoft Color WLT DIB
+ CYUV Creative Labs YUV
+ CYUY ATI YUV
+ D261 H.261
+ D263 H.263
+ DIB Device Independent Bitmap
+ DIV1 FFmpeg OpenDivX
+ DIV2 Microsoft MPEG-4 v1/v2
+ DIV3 DivX ;-) MPEG-4 v3.x Low-Motion
+ DIV4 DivX ;-) MPEG-4 v3.x Fast-Motion
+ DIV5 DivX MPEG-4 v5.x
+ DIV6 DivX ;-) (MS MPEG-4 v3.x)
+ DIVX DivX MPEG-4 v4 (OpenDivX / Project Mayo)
+ divx DivX MPEG-4
+ DMB1 Matrox Rainbow Runner hardware MJPEG
+ DMB2 Paradigm MJPEG
+ DSVD ?DSVD?
+ DUCK Duck TrueMotion 1.0
+ DPS0 DPS/Leitch Reality Motion JPEG
+ DPSC DPS/Leitch PAR Motion JPEG
+ DV25 Matrox DVCPRO codec
+ DV50 Matrox DVCPRO50 codec
+ DVC IEC 61834 and SMPTE 314M (DVC/DV Video)
+ DVCP IEC 61834 and SMPTE 314M (DVC/DV Video)
+ DVHD IEC Standard DV 1125 lines @ 30fps / 1250 lines @ 25fps
+ DVMA Darim Vision DVMPEG (dummy for MPEG compressor) (www.darvision.com)
+ DVSL IEC Standard DV compressed in SD (SDL)
+ DVAN ?DVAN?
+ DVE2 InSoft DVE-2 Videoconferencing
+ dvsd IEC 61834 and SMPTE 314M DVC/DV Video
+ DVSD IEC 61834 and SMPTE 314M DVC/DV Video
+ DVX1 Lucent DVX1000SP Video Decoder
+ DVX2 Lucent DVX2000S Video Decoder
+ DVX3 Lucent DVX3000S Video Decoder
+ DX50 DivX v5
+ DXT1 Microsoft DirectX Compressed Texture (DXT1)
+ DXT2 Microsoft DirectX Compressed Texture (DXT2)
+ DXT3 Microsoft DirectX Compressed Texture (DXT3)
+ DXT4 Microsoft DirectX Compressed Texture (DXT4)
+ DXT5 Microsoft DirectX Compressed Texture (DXT5)
+ DXTC Microsoft DirectX Compressed Texture (DXTC)
+ DXTn Microsoft DirectX Compressed Texture (DXTn)
+ EM2V Etymonix MPEG-2 I-frame (www.etymonix.com)
+ EKQ0 Elsa ?EKQ0?
+ ELK0 Elsa ?ELK0?
+ ESCP Eidos Escape
+ ETV1 eTreppid Video ETV1
+ ETV2 eTreppid Video ETV2
+ ETVC eTreppid Video ETVC
+ FLIC Autodesk FLI/FLC Animation
+ FLV1 Sorenson Spark
+ FLV4 On2 TrueMotion VP6
+ FRWT Darim Vision Forward Motion JPEG (www.darvision.com)
+ FRWU Darim Vision Forward Uncompressed (www.darvision.com)
+ FLJP D-Vision Field Encoded Motion JPEG
+ FPS1 FRAPS v1
+ FRWA SoftLab-Nsk Forward Motion JPEG w/ alpha channel
+ FRWD SoftLab-Nsk Forward Motion JPEG
+ FVF1 Iterated Systems Fractal Video Frame
+ GLZW Motion LZW (gabest@freemail.hu)
+ GPEG Motion JPEG (gabest@freemail.hu)
+ GWLT Microsoft Greyscale WLT DIB
+ H260 Intel ITU H.260 Videoconferencing
+ H261 Intel ITU H.261 Videoconferencing
+ H262 Intel ITU H.262 Videoconferencing
+ H263 Intel ITU H.263 Videoconferencing
+ H264 Intel ITU H.264 Videoconferencing
+ H265 Intel ITU H.265 Videoconferencing
+ H266 Intel ITU H.266 Videoconferencing
+ H267 Intel ITU H.267 Videoconferencing
+ H268 Intel ITU H.268 Videoconferencing
+ H269 Intel ITU H.269 Videoconferencing
+ HFYU Huffman Lossless Codec
+ HMCR Rendition Motion Compensation Format (HMCR)
+ HMRR Rendition Motion Compensation Format (HMRR)
+ I263 FFmpeg I263 decoder
+ IF09 Indeo YVU9 ("YVU9 with additional delta-frame info after the U plane")
+ IUYV Interlaced version of UYVY (www.leadtools.com)
+ IY41 Interlaced version of Y41P (www.leadtools.com)
+ IYU1 12 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard
+ IYU2 24 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard
+ IYUV Planar YUV format (8-bpp Y plane, followed by 8-bpp 2\D72 U and V planes)
+ i263 Intel ITU H.263 Videoconferencing (i263)
+ I420 Intel Indeo 4
+ IAN Intel Indeo 4 (RDX)
+ ICLB InSoft CellB Videoconferencing
+ IGOR Power DVD
+ IJPG Intergraph JPEG
+ ILVC Intel Layered Video
+ ILVR ITU-T H.263+
+ IPDV I-O Data Device Giga AVI DV Codec
+ IR21 Intel Indeo 2.1
+ IRAW Intel YUV Uncompressed
+ IV30 Intel Indeo 3.0
+ IV31 Intel Indeo 3.1
+ IV32 Ligos Indeo 3.2
+ IV33 Ligos Indeo 3.3
+ IV34 Ligos Indeo 3.4
+ IV35 Ligos Indeo 3.5
+ IV36 Ligos Indeo 3.6
+ IV37 Ligos Indeo 3.7
+ IV38 Ligos Indeo 3.8
+ IV39 Ligos Indeo 3.9
+ IV40 Ligos Indeo Interactive 4.0
+ IV41 Ligos Indeo Interactive 4.1
+ IV42 Ligos Indeo Interactive 4.2
+ IV43 Ligos Indeo Interactive 4.3
+ IV44 Ligos Indeo Interactive 4.4
+ IV45 Ligos Indeo Interactive 4.5
+ IV46 Ligos Indeo Interactive 4.6
+ IV47 Ligos Indeo Interactive 4.7
+ IV48 Ligos Indeo Interactive 4.8
+ IV49 Ligos Indeo Interactive 4.9
+ IV50 Ligos Indeo Interactive 5.0
+ JBYR Kensington ?JBYR?
+ JPEG Still Image JPEG DIB
+ JPGL Pegasus Lossless Motion JPEG
+ KMVC Team17 Software Karl Morton\'s Video Codec
+ LSVM Vianet Lighting Strike Vmail (Streaming) (www.vianet.com)
+ LEAD LEAD Video Codec
+ Ljpg LEAD MJPEG Codec
+ MDVD Alex MicroDVD Video (hacked MS MPEG-4) (www.tiasoft.de)
+ MJPA Morgan Motion JPEG (MJPA) (www.morgan-multimedia.com)
+ MJPB Morgan Motion JPEG (MJPB) (www.morgan-multimedia.com)
+ MMES Matrox MPEG-2 I-frame
+ MP2v Microsoft S-Mpeg 4 version 1 (MP2v)
+ MP42 Microsoft S-Mpeg 4 version 2 (MP42)
+ MP43 Microsoft S-Mpeg 4 version 3 (MP43)
+ MP4S Microsoft S-Mpeg 4 version 3 (MP4S)
+ MP4V FFmpeg MPEG-4
+ MPG1 FFmpeg MPEG 1/2
+ MPG2 FFmpeg MPEG 1/2
+ MPG3 FFmpeg DivX ;-) (MS MPEG-4 v3)
+ MPG4 Microsoft MPEG-4
+ MPGI Sigma Designs MPEG
+ MPNG PNG images decoder
+ MSS1 Microsoft Windows Screen Video
+ MSZH LCL (Lossless Codec Library) (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm)
+ M261 Microsoft H.261
+ M263 Microsoft H.263
+ M4S2 Microsoft Fully Compliant MPEG-4 v2 simple profile (M4S2)
+ m4s2 Microsoft Fully Compliant MPEG-4 v2 simple profile (m4s2)
+ MC12 ATI Motion Compensation Format (MC12)
+ MCAM ATI Motion Compensation Format (MCAM)
+ MJ2C Morgan Multimedia Motion JPEG2000
+ mJPG IBM Motion JPEG w/ Huffman Tables
+ MJPG Microsoft Motion JPEG DIB
+ MP42 Microsoft MPEG-4 (low-motion)
+ MP43 Microsoft MPEG-4 (fast-motion)
+ MP4S Microsoft MPEG-4 (MP4S)
+ mp4s Microsoft MPEG-4 (mp4s)
+ MPEG Chromatic Research MPEG-1 Video I-Frame
+ MPG4 Microsoft MPEG-4 Video High Speed Compressor
+ MPGI Sigma Designs MPEG
+ MRCA FAST Multimedia Martin Regen Codec
+ MRLE Microsoft Run Length Encoding
+ MSVC Microsoft Video 1
+ MTX1 Matrox ?MTX1?
+ MTX2 Matrox ?MTX2?
+ MTX3 Matrox ?MTX3?
+ MTX4 Matrox ?MTX4?
+ MTX5 Matrox ?MTX5?
+ MTX6 Matrox ?MTX6?
+ MTX7 Matrox ?MTX7?
+ MTX8 Matrox ?MTX8?
+ MTX9 Matrox ?MTX9?
+ MV12 Motion Pixels Codec (old)
+ MWV1 Aware Motion Wavelets
+ nAVI SMR Codec (hack of Microsoft MPEG-4) (IRC #shadowrealm)
+ NT00 NewTek LightWave HDTV YUV w/ Alpha (www.newtek.com)
+ NUV1 NuppelVideo
+ NTN1 Nogatech Video Compression 1
+ NVS0 nVidia GeForce Texture (NVS0)
+ NVS1 nVidia GeForce Texture (NVS1)
+ NVS2 nVidia GeForce Texture (NVS2)
+ NVS3 nVidia GeForce Texture (NVS3)
+ NVS4 nVidia GeForce Texture (NVS4)
+ NVS5 nVidia GeForce Texture (NVS5)
+ NVT0 nVidia GeForce Texture (NVT0)
+ NVT1 nVidia GeForce Texture (NVT1)
+ NVT2 nVidia GeForce Texture (NVT2)
+ NVT3 nVidia GeForce Texture (NVT3)
+ NVT4 nVidia GeForce Texture (NVT4)
+ NVT5 nVidia GeForce Texture (NVT5)
+ PIXL MiroXL, Pinnacle PCTV
+ PDVC I-O Data Device Digital Video Capture DV codec
+ PGVV Radius Video Vision
+ PHMO IBM Photomotion
+ PIM1 MPEG Realtime (Pinnacle Cards)
+ PIM2 Pegasus Imaging ?PIM2?
+ PIMJ Pegasus Imaging Lossless JPEG
+ PVEZ Horizons Technology PowerEZ
+ PVMM PacketVideo Corporation MPEG-4
+ PVW2 Pegasus Imaging Wavelet Compression
+ Q1.0 Q-Team\'s QPEG 1.0 (www.q-team.de)
+ Q1.1 Q-Team\'s QPEG 1.1 (www.q-team.de)
+ QPEG Q-Team QPEG 1.0
+ qpeq Q-Team QPEG 1.1
+ RGB Raw BGR32
+ RGBA Raw RGB w/ Alpha
+ RMP4 REALmagic MPEG-4 (unauthorized XVID copy) (www.sigmadesigns.com)
+ ROQV Id RoQ File Video Decoder
+ RPZA Quicktime Apple Video (RPZA)
+ RUD0 Rududu video codec (http://rududu.ifrance.com/rududu/)
+ RV10 RealVideo 1.0 (aka RealVideo 5.0)
+ RV13 RealVideo 1.0 (RV13)
+ RV20 RealVideo G2
+ RV30 RealVideo 8
+ RV40 RealVideo 9
+ RGBT Raw RGB w/ Transparency
+ RLE Microsoft Run Length Encoder
+ RLE4 Run Length Encoded (4bpp, 16-color)
+ RLE8 Run Length Encoded (8bpp, 256-color)
+ RT21 Intel Indeo RealTime Video 2.1
+ rv20 RealVideo G2
+ rv30 RealVideo 8
+ RVX Intel RDX (RVX )
+ SMC Apple Graphics (SMC )
+ SP54 Logitech Sunplus Sp54 Codec for Mustek GSmart Mini 2
+ SPIG Radius Spigot
+ SVQ3 Sorenson Video 3 (Apple Quicktime 5)
+ s422 Tekram VideoCap C210 YUV 4:2:2
+ SDCC Sun Communication Digital Camera Codec
+ SFMC CrystalNet Surface Fitting Method
+ SMSC Radius SMSC
+ SMSD Radius SMSD
+ smsv WorldConnect Wavelet Video
+ SPIG Radius Spigot
+ SPLC Splash Studios ACM Audio Codec (www.splashstudios.net)
+ SQZ2 Microsoft VXTreme Video Codec V2
+ STVA ST Microelectronics CMOS Imager Data (Bayer)
+ STVB ST Microelectronics CMOS Imager Data (Nudged Bayer)
+ STVC ST Microelectronics CMOS Imager Data (Bunched)
+ STVX ST Microelectronics CMOS Imager Data (Extended CODEC Data Format)
+ STVY ST Microelectronics CMOS Imager Data (Extended CODEC Data Format with Correction Data)
+ SV10 Sorenson Video R1
+ SVQ1 Sorenson Video
+ T420 Toshiba YUV 4:2:0
+ TM2A Duck TrueMotion Archiver 2.0 (www.duck.com)
+ TVJP Pinnacle/Truevision Targa 2000 board (TVJP)
+ TVMJ Pinnacle/Truevision Targa 2000 board (TVMJ)
+ TY0N Tecomac Low-Bit Rate Codec (www.tecomac.com)
+ TY2C Trident Decompression Driver
+ TLMS TeraLogic Motion Intraframe Codec (TLMS)
+ TLST TeraLogic Motion Intraframe Codec (TLST)
+ TM20 Duck TrueMotion 2.0
+ TM2X Duck TrueMotion 2X
+ TMIC TeraLogic Motion Intraframe Codec (TMIC)
+ TMOT Horizons Technology TrueMotion S
+ tmot Horizons TrueMotion Video Compression
+ TR20 Duck TrueMotion RealTime 2.0
+ TSCC TechSmith Screen Capture Codec
+ TV10 Tecomac Low-Bit Rate Codec
+ TY2N Trident ?TY2N?
+ U263 UB Video H.263/H.263+/H.263++ Decoder
+ UMP4 UB Video MPEG 4 (www.ubvideo.com)
+ UYNV Nvidia UYVY packed 4:2:2
+ UYVP Evans & Sutherland YCbCr 4:2:2 extended precision
+ UCOD eMajix.com ClearVideo
+ ULTI IBM Ultimotion
+ UYVY UYVY packed 4:2:2
+ V261 Lucent VX2000S
+ VIFP VFAPI Reader Codec (www.yks.ne.jp/~hori/)
+ VIV1 FFmpeg H263+ decoder
+ VIV2 Vivo H.263
+ VQC2 Vector-quantised codec 2 (research) http://eprints.ecs.soton.ac.uk/archive/00001310/01/VTC97-js.pdf)
+ VTLP Alaris VideoGramPiX
+ VYU9 ATI YUV (VYU9)
+ VYUY ATI YUV (VYUY)
+ V261 Lucent VX2000S
+ V422 Vitec Multimedia 24-bit YUV 4:2:2 Format
+ V655 Vitec Multimedia 16-bit YUV 4:2:2 Format
+ VCR1 ATI Video Codec 1
+ VCR2 ATI Video Codec 2
+ VCR3 ATI VCR 3.0
+ VCR4 ATI VCR 4.0
+ VCR5 ATI VCR 5.0
+ VCR6 ATI VCR 6.0
+ VCR7 ATI VCR 7.0
+ VCR8 ATI VCR 8.0
+ VCR9 ATI VCR 9.0
+ VDCT Vitec Multimedia Video Maker Pro DIB
+ VDOM VDOnet VDOWave
+ VDOW VDOnet VDOLive (H.263)
+ VDTZ Darim Vison VideoTizer YUV
+ VGPX Alaris VideoGramPiX
+ VIDS Vitec Multimedia YUV 4:2:2 CCIR 601 for V422
+ VIVO Vivo H.263 v2.00
+ vivo Vivo H.263
+ VIXL Miro/Pinnacle Video XL
+ VLV1 VideoLogic/PURE Digital Videologic Capture
+ VP30 On2 VP3.0
+ VP31 On2 VP3.1
+ VP6F On2 TrueMotion VP6
+ VX1K Lucent VX1000S Video Codec
+ VX2K Lucent VX2000S Video Codec
+ VXSP Lucent VX1000SP Video Codec
+ WBVC Winbond W9960
+ WHAM Microsoft Video 1 (WHAM)
+ WINX Winnov Software Compression
+ WJPG AverMedia Winbond JPEG
+ WMV1 Windows Media Video V7
+ WMV2 Windows Media Video V8
+ WMV3 Windows Media Video V9
+ WNV1 Winnov Hardware Compression
+ XYZP Extended PAL format XYZ palette (www.riff.org)
+ x263 Xirlink H.263
+ XLV0 NetXL Video Decoder
+ XMPG Xing MPEG (I-Frame only)
+ XVID XviD MPEG-4 (www.xvid.org)
+ XXAN ?XXAN?
+ YU92 Intel YUV (YU92)
+ YUNV Nvidia Uncompressed YUV 4:2:2
+ YUVP Extended PAL format YUV palette (www.riff.org)
+ Y211 YUV 2:1:1 Packed
+ Y411 YUV 4:1:1 Packed
+ Y41B Weitek YUV 4:1:1 Planar
+ Y41P Brooktree PC1 YUV 4:1:1 Packed
+ Y41T Brooktree PC1 YUV 4:1:1 with transparency
+ Y42B Weitek YUV 4:2:2 Planar
+ Y42T Brooktree UYUV 4:2:2 with transparency
+ Y422 ADS Technologies Copy of UYVY used in Pyro WebCam firewire camera
+ Y800 Simple, single Y plane for monochrome images
+ Y8 Grayscale video
+ YC12 Intel YUV 12 codec
+ YUV8 Winnov Caviar YUV8
+ YUV9 Intel YUV9
+ YUY2 Uncompressed YUV 4:2:2
+ YUYV Canopus YUV
+ YV12 YVU12 Planar
+ YVU9 Intel YVU9 Planar (8-bpp Y plane, followed by 8-bpp 4x4 U and V planes)
+ YVYU YVYU 4:2:2 Packed
+ ZLIB Lossless Codec Library zlib compression (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm)
+ ZPEG Metheus Video Zipper
+
+ */
+
+ return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc');
+ }
+
+ private function EitherEndian2Int($byteword, $signed=false) {
+ if ($this->getid3->info['fileformat'] == 'riff') {
+ return getid3_lib::LittleEndian2Int($byteword, $signed);
+ }
+ return getid3_lib::BigEndian2Int($byteword, false, $signed);
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/libs/getid3/module.audio.ac3.php b/extensions/TimedMediaHandler/libs/getid3/module.audio.ac3.php
new file mode 100644
index 00000000..9834feb5
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/module.audio.ac3.php
@@ -0,0 +1,473 @@
+<?php
+/////////////////////////////////////////////////////////////////
+/// getID3() by James Heinrich <info@getid3.org> //
+// available at http://getid3.sourceforge.net //
+// or http://www.getid3.org //
+/////////////////////////////////////////////////////////////////
+// See readme.txt for more details //
+/////////////////////////////////////////////////////////////////
+// //
+// module.audio.ac3.php //
+// module for analyzing AC-3 (aka Dolby Digital) audio files //
+// dependencies: NONE //
+// ///
+/////////////////////////////////////////////////////////////////
+
+
+class getid3_ac3 extends getid3_handler
+{
+ private $AC3header = array();
+ private $BSIoffset = 0;
+
+ const syncword = "\x0B\x77";
+
+ public function Analyze() {
+ $info = &$this->getid3->info;
+
+ ///AH
+ $info['ac3']['raw']['bsi'] = array();
+ $thisfile_ac3 = &$info['ac3'];
+ $thisfile_ac3_raw = &$thisfile_ac3['raw'];
+ $thisfile_ac3_raw_bsi = &$thisfile_ac3_raw['bsi'];
+
+
+ // http://www.atsc.org/standards/a_52a.pdf
+
+ $info['fileformat'] = 'ac3';
+
+ // An AC-3 serial coded audio bit stream is made up of a sequence of synchronization frames
+ // Each synchronization frame contains 6 coded audio blocks (AB), each of which represent 256
+ // new audio samples per channel. A synchronization information (SI) header at the beginning
+ // of each frame contains information needed to acquire and maintain synchronization. A
+ // bit stream information (BSI) header follows SI, and contains parameters describing the coded
+ // audio service. The coded audio blocks may be followed by an auxiliary data (Aux) field. At the
+ // end of each frame is an error check field that includes a CRC word for error detection. An
+ // additional CRC word is located in the SI header, the use of which, by a decoder, is optional.
+ //
+ // syncinfo() | bsi() | AB0 | AB1 | AB2 | AB3 | AB4 | AB5 | Aux | CRC
+
+ // syncinfo() {
+ // syncword 16
+ // crc1 16
+ // fscod 2
+ // frmsizecod 6
+ // } /* end of syncinfo */
+
+ $this->fseek($info['avdataoffset']);
+ $this->AC3header['syncinfo'] = $this->fread(5);
+
+ if (strpos($this->AC3header['syncinfo'], self::syncword) === 0) {
+ $thisfile_ac3_raw['synchinfo']['synchword'] = self::syncword;
+ $offset = 2;
+ } else {
+ if (!$this->isDependencyFor('matroska')) {
+ unset($info['fileformat'], $info['ac3']);
+ return $this->error('Expecting "'.getid3_lib::PrintHexBytes(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($this->AC3header['syncinfo'], 0, 2)).'"');
+ }
+ $offset = 0;
+ $this->fseek(-2, SEEK_CUR);
+ }
+
+ $info['audio']['dataformat'] = 'ac3';
+ $info['audio']['bitrate_mode'] = 'cbr';
+ $info['audio']['lossless'] = false;
+
+ $thisfile_ac3_raw['synchinfo']['crc1'] = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], $offset, 2));
+ $ac3_synchinfo_fscod_frmsizecod = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], ($offset + 2), 1));
+ $thisfile_ac3_raw['synchinfo']['fscod'] = ($ac3_synchinfo_fscod_frmsizecod & 0xC0) >> 6;
+ $thisfile_ac3_raw['synchinfo']['frmsizecod'] = ($ac3_synchinfo_fscod_frmsizecod & 0x3F);
+
+ $thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw['synchinfo']['fscod']);
+ if ($thisfile_ac3_raw['synchinfo']['fscod'] <= 3) {
+ $info['audio']['sample_rate'] = $thisfile_ac3['sample_rate'];
+ }
+
+ $thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw['synchinfo']['frmsizecod'], $thisfile_ac3_raw['synchinfo']['fscod']);
+ $thisfile_ac3['bitrate'] = self::bitrateLookup($thisfile_ac3_raw['synchinfo']['frmsizecod']);
+ $info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
+
+ $this->AC3header['bsi'] = getid3_lib::BigEndian2Bin($this->fread(15));
+ $ac3_bsi_offset = 0;
+
+ $thisfile_ac3_raw_bsi['bsid'] = $this->readHeaderBSI(5);
+ if ($thisfile_ac3_raw_bsi['bsid'] > 8) {
+ // Decoders which can decode version 8 will thus be able to decode version numbers less than 8.
+ // If this standard is extended by the addition of additional elements or features, a value of bsid greater than 8 will be used.
+ // Decoders built to this version of the standard will not be able to decode versions with bsid greater than 8.
+ $this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 8');
+ unset($info['ac3']);
+ return false;
+ }
+
+ $thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
+ $thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
+
+ $thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
+ $ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
+ foreach($ac3_coding_mode as $key => $value) {
+ $thisfile_ac3[$key] = $value;
+ }
+ switch ($thisfile_ac3_raw_bsi['acmod']) {
+ case 0:
+ case 1:
+ $info['audio']['channelmode'] = 'mono';
+ break;
+ case 3:
+ case 4:
+ $info['audio']['channelmode'] = 'stereo';
+ break;
+ default:
+ $info['audio']['channelmode'] = 'surround';
+ break;
+ }
+ $info['audio']['channels'] = $thisfile_ac3['num_channels'];
+
+ if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) {
+ // If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream.
+ $thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2);
+ $thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']);
+ }
+
+ if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) {
+ // If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream.
+ $thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2);
+ $thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']);
+ }
+
+ if ($thisfile_ac3_raw_bsi['acmod'] == 0x02) {
+ // When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround.
+ $thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
+ $thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']);
+ }
+
+ $thisfile_ac3_raw_bsi['lfeon'] = (bool) $this->readHeaderBSI(1);
+ $thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['lfeon'];
+ if ($thisfile_ac3_raw_bsi['lfeon']) {
+ //$info['audio']['channels']++;
+ $info['audio']['channels'] .= '.1';
+ }
+
+ $thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['lfeon']);
+
+ // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
+ // The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
+ $thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5);
+ $thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';
+
+ $thisfile_ac3_raw_bsi['compre_flag'] = (bool) $this->readHeaderBSI(1);
+ if ($thisfile_ac3_raw_bsi['compre_flag']) {
+ $thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8);
+ $thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']);
+ }
+
+ $thisfile_ac3_raw_bsi['langcode_flag'] = (bool) $this->readHeaderBSI(1);
+ if ($thisfile_ac3_raw_bsi['langcode_flag']) {
+ $thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8);
+ }
+
+ $thisfile_ac3_raw_bsi['audprodie'] = (bool) $this->readHeaderBSI(1);
+ if ($thisfile_ac3_raw_bsi['audprodie']) {
+ $thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5);
+ $thisfile_ac3_raw_bsi['roomtyp'] = $this->readHeaderBSI(2);
+
+ $thisfile_ac3['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB';
+ $thisfile_ac3['room_type'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']);
+ }
+
+ if ($thisfile_ac3_raw_bsi['acmod'] == 0x00) {
+ // If acmod is 0, then two completely independent program channels (dual mono)
+ // are encoded into the bit stream, and are referenced as Ch1, Ch2. In this case,
+ // a number of additional items are present in BSI or audblk to fully describe Ch2.
+
+ // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
+ // The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
+ $thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5);
+ $thisfile_ac3['dialogue_normalization2'] = '-'.$thisfile_ac3_raw_bsi['dialnorm2'].'dB';
+
+ $thisfile_ac3_raw_bsi['compre_flag2'] = (bool) $this->readHeaderBSI(1);
+ if ($thisfile_ac3_raw_bsi['compre_flag2']) {
+ $thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8);
+ $thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']);
+ }
+
+ $thisfile_ac3_raw_bsi['langcode_flag2'] = (bool) $this->readHeaderBSI(1);
+ if ($thisfile_ac3_raw_bsi['langcode_flag2']) {
+ $thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8);
+ }
+
+ $thisfile_ac3_raw_bsi['audprodie2'] = (bool) $this->readHeaderBSI(1);
+ if ($thisfile_ac3_raw_bsi['audprodie2']) {
+ $thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5);
+ $thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2);
+
+ $thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB';
+ $thisfile_ac3['room_type2'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']);
+ }
+
+ }
+
+ $thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1);
+
+ $thisfile_ac3_raw_bsi['original'] = (bool) $this->readHeaderBSI(1);
+
+ $thisfile_ac3_raw_bsi['timecode1_flag'] = (bool) $this->readHeaderBSI(1);
+ if ($thisfile_ac3_raw_bsi['timecode1_flag']) {
+ $thisfile_ac3_raw_bsi['timecode1'] = $this->readHeaderBSI(14);
+ }
+
+ $thisfile_ac3_raw_bsi['timecode2_flag'] = (bool) $this->readHeaderBSI(1);
+ if ($thisfile_ac3_raw_bsi['timecode2_flag']) {
+ $thisfile_ac3_raw_bsi['timecode2'] = $this->readHeaderBSI(14);
+ }
+
+ $thisfile_ac3_raw_bsi['addbsi_flag'] = (bool) $this->readHeaderBSI(1);
+ if ($thisfile_ac3_raw_bsi['addbsi_flag']) {
+ $thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6);
+
+ $this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length']));
+
+ $thisfile_ac3_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8);
+ $this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8;
+ }
+
+ return true;
+ }
+
+ private function readHeaderBSI($length) {
+ $data = substr($this->AC3header['bsi'], $this->BSIoffset, $length);
+ $this->BSIoffset += $length;
+
+ return bindec($data);
+ }
+
+ public static function sampleRateCodeLookup($fscod) {
+ static $sampleRateCodeLookup = array(
+ 0 => 48000,
+ 1 => 44100,
+ 2 => 32000,
+ 3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
+ );
+ return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false);
+ }
+
+ public static function serviceTypeLookup($bsmod, $acmod) {
+ static $serviceTypeLookup = array();
+ if (empty($serviceTypeLookup)) {
+ for ($i = 0; $i <= 7; $i++) {
+ $serviceTypeLookup[0][$i] = 'main audio service: complete main (CM)';
+ $serviceTypeLookup[1][$i] = 'main audio service: music and effects (ME)';
+ $serviceTypeLookup[2][$i] = 'associated service: visually impaired (VI)';
+ $serviceTypeLookup[3][$i] = 'associated service: hearing impaired (HI)';
+ $serviceTypeLookup[4][$i] = 'associated service: dialogue (D)';
+ $serviceTypeLookup[5][$i] = 'associated service: commentary (C)';
+ $serviceTypeLookup[6][$i] = 'associated service: emergency (E)';
+ }
+
+ $serviceTypeLookup[7][1] = 'associated service: voice over (VO)';
+ for ($i = 2; $i <= 7; $i++) {
+ $serviceTypeLookup[7][$i] = 'main audio service: karaoke';
+ }
+ }
+ return (isset($serviceTypeLookup[$bsmod][$acmod]) ? $serviceTypeLookup[$bsmod][$acmod] : false);
+ }
+
+ public static function audioCodingModeLookup($acmod) {
+ // array(channel configuration, # channels (not incl LFE), channel order)
+ static $audioCodingModeLookup = array (
+ 0 => array('channel_config'=>'1+1', 'num_channels'=>2, 'channel_order'=>'Ch1,Ch2'),
+ 1 => array('channel_config'=>'1/0', 'num_channels'=>1, 'channel_order'=>'C'),
+ 2 => array('channel_config'=>'2/0', 'num_channels'=>2, 'channel_order'=>'L,R'),
+ 3 => array('channel_config'=>'3/0', 'num_channels'=>3, 'channel_order'=>'L,C,R'),
+ 4 => array('channel_config'=>'2/1', 'num_channels'=>3, 'channel_order'=>'L,R,S'),
+ 5 => array('channel_config'=>'3/1', 'num_channels'=>4, 'channel_order'=>'L,C,R,S'),
+ 6 => array('channel_config'=>'2/2', 'num_channels'=>4, 'channel_order'=>'L,R,SL,SR'),
+ 7 => array('channel_config'=>'3/2', 'num_channels'=>5, 'channel_order'=>'L,C,R,SL,SR'),
+ );
+ return (isset($audioCodingModeLookup[$acmod]) ? $audioCodingModeLookup[$acmod] : false);
+ }
+
+ public static function centerMixLevelLookup($cmixlev) {
+ static $centerMixLevelLookup;
+ if (empty($centerMixLevelLookup)) {
+ $centerMixLevelLookup = array(
+ 0 => pow(2, -3.0 / 6), // 0.707 (-3.0 dB)
+ 1 => pow(2, -4.5 / 6), // 0.595 (-4.5 dB)
+ 2 => pow(2, -6.0 / 6), // 0.500 (-6.0 dB)
+ 3 => 'reserved'
+ );
+ }
+ return (isset($centerMixLevelLookup[$cmixlev]) ? $centerMixLevelLookup[$cmixlev] : false);
+ }
+
+ public static function surroundMixLevelLookup($surmixlev) {
+ static $surroundMixLevelLookup;
+ if (empty($surroundMixLevelLookup)) {
+ $surroundMixLevelLookup = array(
+ 0 => pow(2, -3.0 / 6),
+ 1 => pow(2, -6.0 / 6),
+ 2 => 0,
+ 3 => 'reserved'
+ );
+ }
+ return (isset($surroundMixLevelLookup[$surmixlev]) ? $surroundMixLevelLookup[$surmixlev] : false);
+ }
+
+ public static function dolbySurroundModeLookup($dsurmod) {
+ static $dolbySurroundModeLookup = array(
+ 0 => 'not indicated',
+ 1 => 'Not Dolby Surround encoded',
+ 2 => 'Dolby Surround encoded',
+ 3 => 'reserved'
+ );
+ return (isset($dolbySurroundModeLookup[$dsurmod]) ? $dolbySurroundModeLookup[$dsurmod] : false);
+ }
+
+ public static function channelsEnabledLookup($acmod, $lfeon) {
+ $lookup = array(
+ 'ch1'=>(bool) ($acmod == 0),
+ 'ch2'=>(bool) ($acmod == 0),
+ 'left'=>(bool) ($acmod > 1),
+ 'right'=>(bool) ($acmod > 1),
+ 'center'=>(bool) ($acmod & 0x01),
+ 'surround_mono'=>false,
+ 'surround_left'=>false,
+ 'surround_right'=>false,
+ 'lfe'=>$lfeon);
+ switch ($acmod) {
+ case 4:
+ case 5:
+ $lookup['surround_mono'] = true;
+ break;
+ case 6:
+ case 7:
+ $lookup['surround_left'] = true;
+ $lookup['surround_right'] = true;
+ break;
+ }
+ return $lookup;
+ }
+
+ public static function heavyCompression($compre) {
+ // The first four bits indicate gain changes in 6.02dB increments which can be
+ // implemented with an arithmetic shift operation. The following four bits
+ // indicate linear gain changes, and require a 5-bit multiply.
+ // We will represent the two 4-bit fields of compr as follows:
+ // X0 X1 X2 X3 . Y4 Y5 Y6 Y7
+ // The meaning of the X values is most simply described by considering X to represent a 4-bit
+ // signed integer with values from -8 to +7. The gain indicated by X is then (X + 1) * 6.02 dB. The
+ // following table shows this in detail.
+
+ // Meaning of 4 msb of compr
+ // 7 +48.16 dB
+ // 6 +42.14 dB
+ // 5 +36.12 dB
+ // 4 +30.10 dB
+ // 3 +24.08 dB
+ // 2 +18.06 dB
+ // 1 +12.04 dB
+ // 0 +6.02 dB
+ // -1 0 dB
+ // -2 -6.02 dB
+ // -3 -12.04 dB
+ // -4 -18.06 dB
+ // -5 -24.08 dB
+ // -6 -30.10 dB
+ // -7 -36.12 dB
+ // -8 -42.14 dB
+
+ $fourbit = str_pad(decbin(($compre & 0xF0) >> 4), 4, '0', STR_PAD_LEFT);
+ if ($fourbit{0} == '1') {
+ $log_gain = -8 + bindec(substr($fourbit, 1));
+ } else {
+ $log_gain = bindec(substr($fourbit, 1));
+ }
+ $log_gain = ($log_gain + 1) * getid3_lib::RGADamplitude2dB(2);
+
+ // The value of Y is a linear representation of a gain change of up to -6 dB. Y is considered to
+ // be an unsigned fractional integer, with a leading value of 1, or: 0.1 Y4 Y5 Y6 Y7 (base 2). Y can
+ // represent values between 0.111112 (or 31/32) and 0.100002 (or 1/2). Thus, Y can represent gain
+ // changes from -0.28 dB to -6.02 dB.
+
+ $lin_gain = (16 + ($compre & 0x0F)) / 32;
+
+ // The combination of X and Y values allows compr to indicate gain changes from
+ // 48.16 - 0.28 = +47.89 dB, to
+ // -42.14 - 6.02 = -48.16 dB.
+
+ return $log_gain - $lin_gain;
+ }
+
+ public static function roomTypeLookup($roomtyp) {
+ static $roomTypeLookup = array(
+ 0 => 'not indicated',
+ 1 => 'large room, X curve monitor',
+ 2 => 'small room, flat monitor',
+ 3 => 'reserved'
+ );
+ return (isset($roomTypeLookup[$roomtyp]) ? $roomTypeLookup[$roomtyp] : false);
+ }
+
+ public static function frameSizeLookup($frmsizecod, $fscod) {
+ $padding = (bool) ($frmsizecod % 2);
+ $framesizeid = floor($frmsizecod / 2);
+
+ static $frameSizeLookup = array();
+ if (empty($frameSizeLookup)) {
+ $frameSizeLookup = array (
+ 0 => array(128, 138, 192),
+ 1 => array(40, 160, 174, 240),
+ 2 => array(48, 192, 208, 288),
+ 3 => array(56, 224, 242, 336),
+ 4 => array(64, 256, 278, 384),
+ 5 => array(80, 320, 348, 480),
+ 6 => array(96, 384, 416, 576),
+ 7 => array(112, 448, 486, 672),
+ 8 => array(128, 512, 556, 768),
+ 9 => array(160, 640, 696, 960),
+ 10 => array(192, 768, 834, 1152),
+ 11 => array(224, 896, 974, 1344),
+ 12 => array(256, 1024, 1114, 1536),
+ 13 => array(320, 1280, 1392, 1920),
+ 14 => array(384, 1536, 1670, 2304),
+ 15 => array(448, 1792, 1950, 2688),
+ 16 => array(512, 2048, 2228, 3072),
+ 17 => array(576, 2304, 2506, 3456),
+ 18 => array(640, 2560, 2786, 3840)
+ );
+ }
+ if (($fscod == 1) && $padding) {
+ // frame lengths are padded by 1 word (16 bits) at 44100
+ $frameSizeLookup[$frmsizecod] += 2;
+ }
+ return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] : false);
+ }
+
+ public static function bitrateLookup($frmsizecod) {
+ $framesizeid = floor($frmsizecod / 2);
+
+ static $bitrateLookup = array(
+ 0 => 32000,
+ 1 => 40000,
+ 2 => 48000,
+ 3 => 56000,
+ 4 => 64000,
+ 5 => 80000,
+ 6 => 96000,
+ 7 => 112000,
+ 8 => 128000,
+ 9 => 160000,
+ 10 => 192000,
+ 11 => 224000,
+ 12 => 256000,
+ 13 => 320000,
+ 14 => 384000,
+ 15 => 448000,
+ 16 => 512000,
+ 17 => 576000,
+ 18 => 640000
+ );
+ return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false);
+ }
+
+
+}
diff --git a/extensions/TimedMediaHandler/libs/getid3/module.audio.dts.php b/extensions/TimedMediaHandler/libs/getid3/module.audio.dts.php
new file mode 100644
index 00000000..1c6b36f9
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/module.audio.dts.php
@@ -0,0 +1,291 @@
+<?php
+/////////////////////////////////////////////////////////////////
+/// getID3() by James Heinrich <info@getid3.org> //
+// available at http://getid3.sourceforge.net //
+// or http://www.getid3.org //
+/////////////////////////////////////////////////////////////////
+// See readme.txt for more details //
+/////////////////////////////////////////////////////////////////
+// //
+// module.audio.dts.php //
+// module for analyzing DTS Audio files //
+// dependencies: NONE //
+// //
+/////////////////////////////////////////////////////////////////
+
+
+/**
+* @tutorial http://wiki.multimedia.cx/index.php?title=DTS
+*/
+
+class getid3_dts extends getid3_handler
+{
+ /**
+ * Default DTS syncword used in native .cpt or .dts formats
+ */
+ const syncword = "\x7F\xFE\x80\x01";
+
+ private $readBinDataOffset = 0;
+
+ /**
+ * Possible syncwords indicating bitstream encoding
+ */
+ public static $syncwords = array(
+ 0 => "\x7F\xFE\x80\x01", // raw big-endian
+ 1 => "\xFE\x7F\x01\x80", // raw little-endian
+ 2 => "\x1F\xFF\xE8\x00", // 14-bit big-endian
+ 3 => "\xFF\x1F\x00\xE8"); // 14-bit little-endian
+
+ public function Analyze() {
+ $info = &$this->getid3->info;
+ $info['fileformat'] = 'dts';
+
+ $this->fseek($info['avdataoffset']);
+ $DTSheader = $this->fread(20); // we only need 2 words magic + 6 words frame header, but these words may be normal 16-bit words OR 14-bit words with 2 highest bits set to zero, so 8 words can be either 8*16/8 = 16 bytes OR 8*16*(16/14)/8 = 18.3 bytes
+
+ // check syncword
+ $sync = substr($DTSheader, 0, 4);
+ if (($encoding = array_search($sync, self::$syncwords)) !== false) {
+
+ $info['dts']['raw']['magic'] = $sync;
+ $this->readBinDataOffset = 32;
+
+ } elseif ($this->isDependencyFor('matroska')) {
+
+ // Matroska contains DTS without syncword encoded as raw big-endian format
+ $encoding = 0;
+ $this->readBinDataOffset = 0;
+
+ } else {
+
+ unset($info['fileformat']);
+ return $this->error('Expecting "'.implode('| ', array_map('getid3_lib::PrintHexBytes', self::$syncwords)).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($sync).'"');
+
+ }
+
+ // decode header
+ $fhBS = '';
+ for ($word_offset = 0; $word_offset <= strlen($DTSheader); $word_offset += 2) {
+ switch ($encoding) {
+ case 0: // raw big-endian
+ $fhBS .= getid3_lib::BigEndian2Bin( substr($DTSheader, $word_offset, 2) );
+ break;
+ case 1: // raw little-endian
+ $fhBS .= getid3_lib::BigEndian2Bin(strrev(substr($DTSheader, $word_offset, 2)));
+ break;
+ case 2: // 14-bit big-endian
+ $fhBS .= substr(getid3_lib::BigEndian2Bin( substr($DTSheader, $word_offset, 2) ), 2, 14);
+ break;
+ case 3: // 14-bit little-endian
+ $fhBS .= substr(getid3_lib::BigEndian2Bin(strrev(substr($DTSheader, $word_offset, 2))), 2, 14);
+ break;
+ }
+ }
+
+ $info['dts']['raw']['frame_type'] = $this->readBinData($fhBS, 1);
+ $info['dts']['raw']['deficit_samples'] = $this->readBinData($fhBS, 5);
+ $info['dts']['flags']['crc_present'] = (bool) $this->readBinData($fhBS, 1);
+ $info['dts']['raw']['pcm_sample_blocks'] = $this->readBinData($fhBS, 7);
+ $info['dts']['raw']['frame_byte_size'] = $this->readBinData($fhBS, 14);
+ $info['dts']['raw']['channel_arrangement'] = $this->readBinData($fhBS, 6);
+ $info['dts']['raw']['sample_frequency'] = $this->readBinData($fhBS, 4);
+ $info['dts']['raw']['bitrate'] = $this->readBinData($fhBS, 5);
+ $info['dts']['flags']['embedded_downmix'] = (bool) $this->readBinData($fhBS, 1);
+ $info['dts']['flags']['dynamicrange'] = (bool) $this->readBinData($fhBS, 1);
+ $info['dts']['flags']['timestamp'] = (bool) $this->readBinData($fhBS, 1);
+ $info['dts']['flags']['auxdata'] = (bool) $this->readBinData($fhBS, 1);
+ $info['dts']['flags']['hdcd'] = (bool) $this->readBinData($fhBS, 1);
+ $info['dts']['raw']['extension_audio'] = $this->readBinData($fhBS, 3);
+ $info['dts']['flags']['extended_coding'] = (bool) $this->readBinData($fhBS, 1);
+ $info['dts']['flags']['audio_sync_insertion'] = (bool) $this->readBinData($fhBS, 1);
+ $info['dts']['raw']['lfe_effects'] = $this->readBinData($fhBS, 2);
+ $info['dts']['flags']['predictor_history'] = (bool) $this->readBinData($fhBS, 1);
+ if ($info['dts']['flags']['crc_present']) {
+ $info['dts']['raw']['crc16'] = $this->readBinData($fhBS, 16);
+ }
+ $info['dts']['flags']['mri_perfect_reconst'] = (bool) $this->readBinData($fhBS, 1);
+ $info['dts']['raw']['encoder_soft_version'] = $this->readBinData($fhBS, 4);
+ $info['dts']['raw']['copy_history'] = $this->readBinData($fhBS, 2);
+ $info['dts']['raw']['bits_per_sample'] = $this->readBinData($fhBS, 2);
+ $info['dts']['flags']['surround_es'] = (bool) $this->readBinData($fhBS, 1);
+ $info['dts']['flags']['front_sum_diff'] = (bool) $this->readBinData($fhBS, 1);
+ $info['dts']['flags']['surround_sum_diff'] = (bool) $this->readBinData($fhBS, 1);
+ $info['dts']['raw']['dialog_normalization'] = $this->readBinData($fhBS, 4);
+
+
+ $info['dts']['bitrate'] = self::bitrateLookup($info['dts']['raw']['bitrate']);
+ $info['dts']['bits_per_sample'] = self::bitPerSampleLookup($info['dts']['raw']['bits_per_sample']);
+ $info['dts']['sample_rate'] = self::sampleRateLookup($info['dts']['raw']['sample_frequency']);
+ $info['dts']['dialog_normalization'] = self::dialogNormalization($info['dts']['raw']['dialog_normalization'], $info['dts']['raw']['encoder_soft_version']);
+ $info['dts']['flags']['lossless'] = (($info['dts']['raw']['bitrate'] == 31) ? true : false);
+ $info['dts']['bitrate_mode'] = (($info['dts']['raw']['bitrate'] == 30) ? 'vbr' : 'cbr');
+ $info['dts']['channels'] = self::numChannelsLookup($info['dts']['raw']['channel_arrangement']);
+ $info['dts']['channel_arrangement'] = self::channelArrangementLookup($info['dts']['raw']['channel_arrangement']);
+
+ $info['audio']['dataformat'] = 'dts';
+ $info['audio']['lossless'] = $info['dts']['flags']['lossless'];
+ $info['audio']['bitrate_mode'] = $info['dts']['bitrate_mode'];
+ $info['audio']['bits_per_sample'] = $info['dts']['bits_per_sample'];
+ $info['audio']['sample_rate'] = $info['dts']['sample_rate'];
+ $info['audio']['channels'] = $info['dts']['channels'];
+ $info['audio']['bitrate'] = $info['dts']['bitrate'];
+ if (isset($info['avdataend']) && !empty($info['dts']['bitrate']) && is_numeric($info['dts']['bitrate'])) {
+ $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) / ($info['dts']['bitrate'] / 8);
+ if (($encoding == 2) || ($encoding == 3)) {
+ // 14-bit data packed into 16-bit words, so the playtime is wrong because only (14/16) of the bytes in the data portion of the file are used at the specified bitrate
+ $info['playtime_seconds'] *= (14 / 16);
+ }
+ }
+ return true;
+ }
+
+ private function readBinData($bin, $length) {
+ $data = substr($bin, $this->readBinDataOffset, $length);
+ $this->readBinDataOffset += $length;
+
+ return bindec($data);
+ }
+
+ public static function bitrateLookup($index) {
+ static $lookup = array(
+ 0 => 32000,
+ 1 => 56000,
+ 2 => 64000,
+ 3 => 96000,
+ 4 => 112000,
+ 5 => 128000,
+ 6 => 192000,
+ 7 => 224000,
+ 8 => 256000,
+ 9 => 320000,
+ 10 => 384000,
+ 11 => 448000,
+ 12 => 512000,
+ 13 => 576000,
+ 14 => 640000,
+ 15 => 768000,
+ 16 => 960000,
+ 17 => 1024000,
+ 18 => 1152000,
+ 19 => 1280000,
+ 20 => 1344000,
+ 21 => 1408000,
+ 22 => 1411200,
+ 23 => 1472000,
+ 24 => 1536000,
+ 25 => 1920000,
+ 26 => 2048000,
+ 27 => 3072000,
+ 28 => 3840000,
+ 29 => 'open',
+ 30 => 'variable',
+ 31 => 'lossless',
+ );
+ return (isset($lookup[$index]) ? $lookup[$index] : false);
+ }
+
+ public static function sampleRateLookup($index) {
+ static $lookup = array(
+ 0 => 'invalid',
+ 1 => 8000,
+ 2 => 16000,
+ 3 => 32000,
+ 4 => 'invalid',
+ 5 => 'invalid',
+ 6 => 11025,
+ 7 => 22050,
+ 8 => 44100,
+ 9 => 'invalid',
+ 10 => 'invalid',
+ 11 => 12000,
+ 12 => 24000,
+ 13 => 48000,
+ 14 => 'invalid',
+ 15 => 'invalid',
+ );
+ return (isset($lookup[$index]) ? $lookup[$index] : false);
+ }
+
+ public static function bitPerSampleLookup($index) {
+ static $lookup = array(
+ 0 => 16,
+ 1 => 20,
+ 2 => 24,
+ 3 => 24,
+ );
+ return (isset($lookup[$index]) ? $lookup[$index] : false);
+ }
+
+ public static function numChannelsLookup($index) {
+ switch ($index) {
+ case 0:
+ return 1;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ return 2;
+ break;
+ case 5:
+ case 6:
+ return 3;
+ break;
+ case 7:
+ case 8:
+ return 4;
+ break;
+ case 9:
+ return 5;
+ break;
+ case 10:
+ case 11:
+ case 12:
+ return 6;
+ break;
+ case 13:
+ return 7;
+ break;
+ case 14:
+ case 15:
+ return 8;
+ break;
+ }
+ return false;
+ }
+
+ public static function channelArrangementLookup($index) {
+ static $lookup = array(
+ 0 => 'A',
+ 1 => 'A + B (dual mono)',
+ 2 => 'L + R (stereo)',
+ 3 => '(L+R) + (L-R) (sum-difference)',
+ 4 => 'LT + RT (left and right total)',
+ 5 => 'C + L + R',
+ 6 => 'L + R + S',
+ 7 => 'C + L + R + S',
+ 8 => 'L + R + SL + SR',
+ 9 => 'C + L + R + SL + SR',
+ 10 => 'CL + CR + L + R + SL + SR',
+ 11 => 'C + L + R+ LR + RR + OV',
+ 12 => 'CF + CR + LF + RF + LR + RR',
+ 13 => 'CL + C + CR + L + R + SL + SR',
+ 14 => 'CL + CR + L + R + SL1 + SL2 + SR1 + SR2',
+ 15 => 'CL + C+ CR + L + R + SL + S + SR',
+ );
+ return (isset($lookup[$index]) ? $lookup[$index] : 'user-defined');
+ }
+
+ public static function dialogNormalization($index, $version) {
+ switch ($version) {
+ case 7:
+ return 0 - $index;
+ break;
+ case 6:
+ return 0 - 16 - $index;
+ break;
+ }
+ return false;
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/libs/getid3/module.audio.flac.php b/extensions/TimedMediaHandler/libs/getid3/module.audio.flac.php
new file mode 100644
index 00000000..6b9598c7
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/module.audio.flac.php
@@ -0,0 +1,442 @@
+<?php
+/////////////////////////////////////////////////////////////////
+/// getID3() by James Heinrich <info@getid3.org> //
+// available at http://getid3.sourceforge.net //
+// or http://www.getid3.org //
+/////////////////////////////////////////////////////////////////
+// See readme.txt for more details //
+/////////////////////////////////////////////////////////////////
+// //
+// module.audio.flac.php //
+// module for analyzing FLAC and OggFLAC audio files //
+// dependencies: module.audio.ogg.php //
+// ///
+/////////////////////////////////////////////////////////////////
+
+
+getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ogg.php', __FILE__, true);
+
+/**
+* @tutorial http://flac.sourceforge.net/format.html
+*/
+class getid3_flac extends getid3_handler
+{
+ const syncword = 'fLaC';
+
+ public function Analyze() {
+ $info = &$this->getid3->info;
+
+ $this->fseek($info['avdataoffset']);
+ $StreamMarker = $this->fread(4);
+ if ($StreamMarker != self::syncword) {
+ return $this->error('Expecting "'.getid3_lib::PrintHexBytes(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($StreamMarker).'"');
+ }
+ $info['fileformat'] = 'flac';
+ $info['audio']['dataformat'] = 'flac';
+ $info['audio']['bitrate_mode'] = 'vbr';
+ $info['audio']['lossless'] = true;
+
+ // parse flac container
+ return $this->parseMETAdata();
+ }
+
+ public function parseMETAdata() {
+ $info = &$this->getid3->info;
+ do {
+ $BlockOffset = $this->ftell();
+ $BlockHeader = $this->fread(4);
+ $LBFBT = getid3_lib::BigEndian2Int(substr($BlockHeader, 0, 1));
+ $LastBlockFlag = (bool) ($LBFBT & 0x80);
+ $BlockType = ($LBFBT & 0x7F);
+ $BlockLength = getid3_lib::BigEndian2Int(substr($BlockHeader, 1, 3));
+ $BlockTypeText = self::metaBlockTypeLookup($BlockType);
+
+ if (($BlockOffset + 4 + $BlockLength) > $info['avdataend']) {
+ $this->error('METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockTypeText.') at offset '.$BlockOffset.' extends beyond end of file');
+ break;
+ }
+ if ($BlockLength < 1) {
+ $this->error('METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockLength.') at offset '.$BlockOffset.' is invalid');
+ break;
+ }
+
+ $info['flac'][$BlockTypeText]['raw'] = array();
+ $BlockTypeText_raw = &$info['flac'][$BlockTypeText]['raw'];
+
+ $BlockTypeText_raw['offset'] = $BlockOffset;
+ $BlockTypeText_raw['last_meta_block'] = $LastBlockFlag;
+ $BlockTypeText_raw['block_type'] = $BlockType;
+ $BlockTypeText_raw['block_type_text'] = $BlockTypeText;
+ $BlockTypeText_raw['block_length'] = $BlockLength;
+ if ($BlockTypeText_raw['block_type'] != 0x06) { // do not read attachment data automatically
+ $BlockTypeText_raw['block_data'] = $this->fread($BlockLength);
+ }
+
+ switch ($BlockTypeText) {
+ case 'STREAMINFO': // 0x00
+ if (!$this->parseSTREAMINFO($BlockTypeText_raw['block_data'])) {
+ return false;
+ }
+ break;
+
+ case 'PADDING': // 0x01
+ unset($info['flac']['PADDING']); // ignore
+ break;
+
+ case 'APPLICATION': // 0x02
+ if (!$this->parseAPPLICATION($BlockTypeText_raw['block_data'])) {
+ return false;
+ }
+ break;
+
+ case 'SEEKTABLE': // 0x03
+ if (!$this->parseSEEKTABLE($BlockTypeText_raw['block_data'])) {
+ return false;
+ }
+ break;
+
+ case 'VORBIS_COMMENT': // 0x04
+ if (!$this->parseVORBIS_COMMENT($BlockTypeText_raw['block_data'])) {
+ return false;
+ }
+ break;
+
+ case 'CUESHEET': // 0x05
+ if (!$this->parseCUESHEET($BlockTypeText_raw['block_data'])) {
+ return false;
+ }
+ break;
+
+ case 'PICTURE': // 0x06
+ if (!$this->parsePICTURE()) {
+ return false;
+ }
+ break;
+
+ default:
+ $this->warning('Unhandled METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockType.') at offset '.$BlockOffset);
+ }
+
+ unset($info['flac'][$BlockTypeText]['raw']);
+ $info['avdataoffset'] = $this->ftell();
+ }
+ while ($LastBlockFlag === false);
+
+ // handle tags
+ if (!empty($info['flac']['VORBIS_COMMENT']['comments'])) {
+ $info['flac']['comments'] = $info['flac']['VORBIS_COMMENT']['comments'];
+ }
+ if (!empty($info['flac']['VORBIS_COMMENT']['vendor'])) {
+ $info['audio']['encoder'] = str_replace('reference ', '', $info['flac']['VORBIS_COMMENT']['vendor']);
+ }
+
+ // copy attachments to 'comments' array if nesesary
+ if (isset($info['flac']['PICTURE']) && ($this->getid3->option_save_attachments !== getID3::ATTACHMENTS_NONE)) {
+ foreach ($info['flac']['PICTURE'] as $entry) {
+ if (!empty($entry['data'])) {
+ $info['flac']['comments']['picture'][] = array('image_mime'=>$entry['image_mime'], 'data'=>$entry['data']);
+ }
+ }
+ }
+
+ if (isset($info['flac']['STREAMINFO'])) {
+ if (!$this->isDependencyFor('matroska')) {
+ $info['flac']['compressed_audio_bytes'] = $info['avdataend'] - $info['avdataoffset'];
+ }
+ $info['flac']['uncompressed_audio_bytes'] = $info['flac']['STREAMINFO']['samples_stream'] * $info['flac']['STREAMINFO']['channels'] * ($info['flac']['STREAMINFO']['bits_per_sample'] / 8);
+ if ($info['flac']['uncompressed_audio_bytes'] == 0) {
+ return $this->error('Corrupt FLAC file: uncompressed_audio_bytes == zero');
+ }
+ if (!empty($info['flac']['compressed_audio_bytes'])) {
+ $info['flac']['compression_ratio'] = $info['flac']['compressed_audio_bytes'] / $info['flac']['uncompressed_audio_bytes'];
+ }
+ }
+
+ // set md5_data_source - built into flac 0.5+
+ if (isset($info['flac']['STREAMINFO']['audio_signature'])) {
+
+ if ($info['flac']['STREAMINFO']['audio_signature'] === str_repeat("\x00", 16)) {
+ $this->warning('FLAC STREAMINFO.audio_signature is null (known issue with libOggFLAC)');
+ }
+ else {
+ $info['md5_data_source'] = '';
+ $md5 = $info['flac']['STREAMINFO']['audio_signature'];
+ for ($i = 0; $i < strlen($md5); $i++) {
+ $info['md5_data_source'] .= str_pad(dechex(ord($md5[$i])), 2, '00', STR_PAD_LEFT);
+ }
+ if (!preg_match('/^[0-9a-f]{32}$/', $info['md5_data_source'])) {
+ unset($info['md5_data_source']);
+ }
+ }
+ }
+
+ if (isset($info['flac']['STREAMINFO']['bits_per_sample'])) {
+ $info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample'];
+ if ($info['audio']['bits_per_sample'] == 8) {
+ // special case
+ // must invert sign bit on all data bytes before MD5'ing to match FLAC's calculated value
+ // MD5sum calculates on unsigned bytes, but FLAC calculated MD5 on 8-bit audio data as signed
+ $this->warning('FLAC calculates MD5 data strangely on 8-bit audio, so the stored md5_data_source value will not match the decoded WAV file');
+ }
+ }
+
+ return true;
+ }
+
+ private function parseSTREAMINFO($BlockData) {
+ $info = &$this->getid3->info;
+
+ $info['flac']['STREAMINFO'] = array();
+ $streaminfo = &$info['flac']['STREAMINFO'];
+
+ $streaminfo['min_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 0, 2));
+ $streaminfo['max_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 2, 2));
+ $streaminfo['min_frame_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 4, 3));
+ $streaminfo['max_frame_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 7, 3));
+
+ $SRCSBSS = getid3_lib::BigEndian2Bin(substr($BlockData, 10, 8));
+ $streaminfo['sample_rate'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 0, 20));
+ $streaminfo['channels'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 20, 3)) + 1;
+ $streaminfo['bits_per_sample'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 23, 5)) + 1;
+ $streaminfo['samples_stream'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 28, 36));
+
+ $streaminfo['audio_signature'] = substr($BlockData, 18, 16);
+
+ if (!empty($streaminfo['sample_rate'])) {
+
+ $info['audio']['bitrate_mode'] = 'vbr';
+ $info['audio']['sample_rate'] = $streaminfo['sample_rate'];
+ $info['audio']['channels'] = $streaminfo['channels'];
+ $info['audio']['bits_per_sample'] = $streaminfo['bits_per_sample'];
+ $info['playtime_seconds'] = $streaminfo['samples_stream'] / $streaminfo['sample_rate'];
+ if ($info['playtime_seconds'] > 0) {
+ if (!$this->isDependencyFor('matroska')) {
+ $info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
+ }
+ else {
+ $this->warning('Cannot determine audio bitrate because total stream size is unknown');
+ }
+ }
+
+ } else {
+ return $this->error('Corrupt METAdata block: STREAMINFO');
+ }
+
+ return true;
+ }
+
+ private function parseAPPLICATION($BlockData) {
+ $info = &$this->getid3->info;
+
+ $ApplicationID = getid3_lib::BigEndian2Int(substr($BlockData, 0, 4));
+ $info['flac']['APPLICATION'][$ApplicationID]['name'] = self::applicationIDLookup($ApplicationID);
+ $info['flac']['APPLICATION'][$ApplicationID]['data'] = substr($BlockData, 4);
+
+ return true;
+ }
+
+ private function parseSEEKTABLE($BlockData) {
+ $info = &$this->getid3->info;
+
+ $offset = 0;
+ $BlockLength = strlen($BlockData);
+ $placeholderpattern = str_repeat("\xFF", 8);
+ while ($offset < $BlockLength) {
+ $SampleNumberString = substr($BlockData, $offset, 8);
+ $offset += 8;
+ if ($SampleNumberString == $placeholderpattern) {
+
+ // placeholder point
+ getid3_lib::safe_inc($info['flac']['SEEKTABLE']['placeholders'], 1);
+ $offset += 10;
+
+ } else {
+
+ $SampleNumber = getid3_lib::BigEndian2Int($SampleNumberString);
+ $info['flac']['SEEKTABLE'][$SampleNumber]['offset'] = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 8));
+ $offset += 8;
+ $info['flac']['SEEKTABLE'][$SampleNumber]['samples'] = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 2));
+ $offset += 2;
+
+ }
+ }
+
+ return true;
+ }
+
+ private function parseVORBIS_COMMENT($BlockData) {
+ $info = &$this->getid3->info;
+
+ $getid3_ogg = new getid3_ogg($this->getid3);
+ if ($this->isDependencyFor('matroska')) {
+ $getid3_ogg->setStringMode($this->data_string);
+ }
+ $getid3_ogg->ParseVorbisComments();
+ if (isset($info['ogg'])) {
+ unset($info['ogg']['comments_raw']);
+ $info['flac']['VORBIS_COMMENT'] = $info['ogg'];
+ unset($info['ogg']);
+ }
+
+ unset($getid3_ogg);
+
+ return true;
+ }
+
+ private function parseCUESHEET($BlockData) {
+ $info = &$this->getid3->info;
+ $offset = 0;
+ $info['flac']['CUESHEET']['media_catalog_number'] = trim(substr($BlockData, $offset, 128), "\0");
+ $offset += 128;
+ $info['flac']['CUESHEET']['lead_in_samples'] = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 8));
+ $offset += 8;
+ $info['flac']['CUESHEET']['flags']['is_cd'] = (bool) (getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1)) & 0x80);
+ $offset += 1;
+
+ $offset += 258; // reserved
+
+ $info['flac']['CUESHEET']['number_tracks'] = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1));
+ $offset += 1;
+
+ for ($track = 0; $track < $info['flac']['CUESHEET']['number_tracks']; $track++) {
+ $TrackSampleOffset = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 8));
+ $offset += 8;
+ $TrackNumber = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1));
+ $offset += 1;
+
+ $info['flac']['CUESHEET']['tracks'][$TrackNumber]['sample_offset'] = $TrackSampleOffset;
+
+ $info['flac']['CUESHEET']['tracks'][$TrackNumber]['isrc'] = substr($BlockData, $offset, 12);
+ $offset += 12;
+
+ $TrackFlagsRaw = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1));
+ $offset += 1;
+ $info['flac']['CUESHEET']['tracks'][$TrackNumber]['flags']['is_audio'] = (bool) ($TrackFlagsRaw & 0x80);
+ $info['flac']['CUESHEET']['tracks'][$TrackNumber]['flags']['pre_emphasis'] = (bool) ($TrackFlagsRaw & 0x40);
+
+ $offset += 13; // reserved
+
+ $info['flac']['CUESHEET']['tracks'][$TrackNumber]['index_points'] = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1));
+ $offset += 1;
+
+ for ($index = 0; $index < $info['flac']['CUESHEET']['tracks'][$TrackNumber]['index_points']; $index++) {
+ $IndexSampleOffset = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 8));
+ $offset += 8;
+ $IndexNumber = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1));
+ $offset += 1;
+
+ $offset += 3; // reserved
+
+ $info['flac']['CUESHEET']['tracks'][$TrackNumber]['indexes'][$IndexNumber] = $IndexSampleOffset;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Parse METADATA_BLOCK_PICTURE flac structure and extract attachment
+ * External usage: audio.ogg
+ */
+ public function parsePICTURE() {
+ $info = &$this->getid3->info;
+
+ $picture['typeid'] = getid3_lib::BigEndian2Int($this->fread(4));
+ $picture['type'] = self::pictureTypeLookup($picture['typeid']);
+ $picture['image_mime'] = $this->fread(getid3_lib::BigEndian2Int($this->fread(4)));
+ $descr_length = getid3_lib::BigEndian2Int($this->fread(4));
+ if ($descr_length) {
+ $picture['description'] = $this->fread($descr_length);
+ }
+ $picture['width'] = getid3_lib::BigEndian2Int($this->fread(4));
+ $picture['height'] = getid3_lib::BigEndian2Int($this->fread(4));
+ $picture['color_depth'] = getid3_lib::BigEndian2Int($this->fread(4));
+ $picture['colors_indexed'] = getid3_lib::BigEndian2Int($this->fread(4));
+ $data_length = getid3_lib::BigEndian2Int($this->fread(4));
+
+ if ($picture['image_mime'] == '-->') {
+ $picture['data'] = $this->fread($data_length);
+ } else {
+ $picture['data'] = $this->saveAttachment(
+ str_replace('/', '_', $picture['type']).'_'.$this->ftell(),
+ $this->ftell(),
+ $data_length,
+ $picture['image_mime']);
+ }
+
+ $info['flac']['PICTURE'][] = $picture;
+
+ return true;
+ }
+
+ public static function metaBlockTypeLookup($blocktype) {
+ static $lookup = array(
+ 0 => 'STREAMINFO',
+ 1 => 'PADDING',
+ 2 => 'APPLICATION',
+ 3 => 'SEEKTABLE',
+ 4 => 'VORBIS_COMMENT',
+ 5 => 'CUESHEET',
+ 6 => 'PICTURE',
+ );
+ return (isset($lookup[$blocktype]) ? $lookup[$blocktype] : 'reserved');
+ }
+
+ public static function applicationIDLookup($applicationid) {
+ // http://flac.sourceforge.net/id.html
+ static $lookup = array(
+ 0x41544348 => 'FlacFile', // "ATCH"
+ 0x42534F4C => 'beSolo', // "BSOL"
+ 0x42554753 => 'Bugs Player', // "BUGS"
+ 0x43756573 => 'GoldWave cue points (specification)', // "Cues"
+ 0x46696361 => 'CUE Splitter', // "Fica"
+ 0x46746F6C => 'flac-tools', // "Ftol"
+ 0x4D4F5442 => 'MOTB MetaCzar', // "MOTB"
+ 0x4D505345 => 'MP3 Stream Editor', // "MPSE"
+ 0x4D754D4C => 'MusicML: Music Metadata Language', // "MuML"
+ 0x52494646 => 'Sound Devices RIFF chunk storage', // "RIFF"
+ 0x5346464C => 'Sound Font FLAC', // "SFFL"
+ 0x534F4E59 => 'Sony Creative Software', // "SONY"
+ 0x5351455A => 'flacsqueeze', // "SQEZ"
+ 0x54745776 => 'TwistedWave', // "TtWv"
+ 0x55495453 => 'UITS Embedding tools', // "UITS"
+ 0x61696666 => 'FLAC AIFF chunk storage', // "aiff"
+ 0x696D6167 => 'flac-image application for storing arbitrary files in APPLICATION metadata blocks', // "imag"
+ 0x7065656D => 'Parseable Embedded Extensible Metadata (specification)', // "peem"
+ 0x71667374 => 'QFLAC Studio', // "qfst"
+ 0x72696666 => 'FLAC RIFF chunk storage', // "riff"
+ 0x74756E65 => 'TagTuner', // "tune"
+ 0x78626174 => 'XBAT', // "xbat"
+ 0x786D6364 => 'xmcd', // "xmcd"
+ );
+ return (isset($lookup[$applicationid]) ? $lookup[$applicationid] : 'reserved');
+ }
+
+ public static function pictureTypeLookup($type_id) {
+ static $lookup = array (
+ 0 => 'Other',
+ 1 => '32x32 pixels \'file icon\' (PNG only)',
+ 2 => 'Other file icon',
+ 3 => 'Cover (front)',
+ 4 => 'Cover (back)',
+ 5 => 'Leaflet page',
+ 6 => 'Media (e.g. label side of CD)',
+ 7 => 'Lead artist/lead performer/soloist',
+ 8 => 'Artist/performer',
+ 9 => 'Conductor',
+ 10 => 'Band/Orchestra',
+ 11 => 'Composer',
+ 12 => 'Lyricist/text writer',
+ 13 => 'Recording Location',
+ 14 => 'During recording',
+ 15 => 'During performance',
+ 16 => 'Movie/video screen capture',
+ 17 => 'A bright coloured fish',
+ 18 => 'Illustration',
+ 19 => 'Band/artist logotype',
+ 20 => 'Publisher/Studio logotype',
+ );
+ return (isset($lookup[$type_id]) ? $lookup[$type_id] : 'reserved');
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/libs/getid3/module.audio.mp3.php b/extensions/TimedMediaHandler/libs/getid3/module.audio.mp3.php
new file mode 100644
index 00000000..e6ffea94
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/module.audio.mp3.php
@@ -0,0 +1,2009 @@
+<?php
+/////////////////////////////////////////////////////////////////
+/// getID3() by James Heinrich <info@getid3.org> //
+// available at http://getid3.sourceforge.net //
+// or http://www.getid3.org //
+/////////////////////////////////////////////////////////////////
+// See readme.txt for more details //
+/////////////////////////////////////////////////////////////////
+// //
+// module.audio.mp3.php //
+// module for analyzing MP3 files //
+// dependencies: NONE //
+// ///
+/////////////////////////////////////////////////////////////////
+
+
+// number of frames to scan to determine if MPEG-audio sequence is valid
+// Lower this number to 5-20 for faster scanning
+// Increase this number to 50+ for most accurate detection of valid VBR/CBR
+// mpeg-audio streams
+define('GETID3_MP3_VALID_CHECK_FRAMES', 35);
+
+
+class getid3_mp3 extends getid3_handler
+{
+
+ public $allow_bruteforce = false; // forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow, unrecommended, but may provide data from otherwise-unusuable files
+
+ public function Analyze() {
+ $info = &$this->getid3->info;
+
+ $initialOffset = $info['avdataoffset'];
+
+ if (!$this->getOnlyMPEGaudioInfo($info['avdataoffset'])) {
+ if ($this->allow_bruteforce) {
+ $info['error'][] = 'Rescanning file in BruteForce mode';
+ $this->getOnlyMPEGaudioInfoBruteForce($this->getid3->fp, $info);
+ }
+ }
+
+
+ if (isset($info['mpeg']['audio']['bitrate_mode'])) {
+ $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
+ }
+
+ if (((isset($info['id3v2']['headerlength']) && ($info['avdataoffset'] > $info['id3v2']['headerlength'])) || (!isset($info['id3v2']) && ($info['avdataoffset'] > 0) && ($info['avdataoffset'] != $initialOffset)))) {
+
+ $synchoffsetwarning = 'Unknown data before synch ';
+ if (isset($info['id3v2']['headerlength'])) {
+ $synchoffsetwarning .= '(ID3v2 header ends at '.$info['id3v2']['headerlength'].', then '.($info['avdataoffset'] - $info['id3v2']['headerlength']).' bytes garbage, ';
+ } elseif ($initialOffset > 0) {
+ $synchoffsetwarning .= '(should be at '.$initialOffset.', ';
+ } else {
+ $synchoffsetwarning .= '(should be at beginning of file, ';
+ }
+ $synchoffsetwarning .= 'synch detected at '.$info['avdataoffset'].')';
+ if (isset($info['audio']['bitrate_mode']) && ($info['audio']['bitrate_mode'] == 'cbr')) {
+
+ if (!empty($info['id3v2']['headerlength']) && (($info['avdataoffset'] - $info['id3v2']['headerlength']) == $info['mpeg']['audio']['framelength'])) {
+
+ $synchoffsetwarning .= '. This is a known problem with some versions of LAME (3.90-3.92) DLL in CBR mode.';
+ $info['audio']['codec'] = 'LAME';
+ $CurrentDataLAMEversionString = 'LAME3.';
+
+ } elseif (empty($info['id3v2']['headerlength']) && ($info['avdataoffset'] == $info['mpeg']['audio']['framelength'])) {
+
+ $synchoffsetwarning .= '. This is a known problem with some versions of LAME (3.90 - 3.92) DLL in CBR mode.';
+ $info['audio']['codec'] = 'LAME';
+ $CurrentDataLAMEversionString = 'LAME3.';
+
+ }
+
+ }
+ $info['warning'][] = $synchoffsetwarning;
+
+ }
+
+ if (isset($info['mpeg']['audio']['LAME'])) {
+ $info['audio']['codec'] = 'LAME';
+ if (!empty($info['mpeg']['audio']['LAME']['long_version'])) {
+ $info['audio']['encoder'] = rtrim($info['mpeg']['audio']['LAME']['long_version'], "\x00");
+ } elseif (!empty($info['mpeg']['audio']['LAME']['short_version'])) {
+ $info['audio']['encoder'] = rtrim($info['mpeg']['audio']['LAME']['short_version'], "\x00");
+ }
+ }
+
+ $CurrentDataLAMEversionString = (!empty($CurrentDataLAMEversionString) ? $CurrentDataLAMEversionString : (isset($info['audio']['encoder']) ? $info['audio']['encoder'] : ''));
+ if (!empty($CurrentDataLAMEversionString) && (substr($CurrentDataLAMEversionString, 0, 6) == 'LAME3.') && !preg_match('[0-9\)]', substr($CurrentDataLAMEversionString, -1))) {
+ // a version number of LAME that does not end with a number like "LAME3.92"
+ // or with a closing parenthesis like "LAME3.88 (alpha)"
+ // or a version of LAME with the LAMEtag-not-filled-in-DLL-mode bug (3.90-3.92)
+
+ // not sure what the actual last frame length will be, but will be less than or equal to 1441
+ $PossiblyLongerLAMEversion_FrameLength = 1441;
+
+ // Not sure what version of LAME this is - look in padding of last frame for longer version string
+ $PossibleLAMEversionStringOffset = $info['avdataend'] - $PossiblyLongerLAMEversion_FrameLength;
+ fseek($this->getid3->fp, $PossibleLAMEversionStringOffset);
+ $PossiblyLongerLAMEversion_Data = fread($this->getid3->fp, $PossiblyLongerLAMEversion_FrameLength);
+ switch (substr($CurrentDataLAMEversionString, -1)) {
+ case 'a':
+ case 'b':
+ // "LAME3.94a" will have a longer version string of "LAME3.94 (alpha)" for example
+ // need to trim off "a" to match longer string
+ $CurrentDataLAMEversionString = substr($CurrentDataLAMEversionString, 0, -1);
+ break;
+ }
+ if (($PossiblyLongerLAMEversion_String = strstr($PossiblyLongerLAMEversion_Data, $CurrentDataLAMEversionString)) !== false) {
+ if (substr($PossiblyLongerLAMEversion_String, 0, strlen($CurrentDataLAMEversionString)) == $CurrentDataLAMEversionString) {
+ $PossiblyLongerLAMEversion_NewString = substr($PossiblyLongerLAMEversion_String, 0, strspn($PossiblyLongerLAMEversion_String, 'LAME0123456789., (abcdefghijklmnopqrstuvwxyzJFSOND)')); //"LAME3.90.3" "LAME3.87 (beta 1, Sep 27 2000)" "LAME3.88 (beta)"
+ if (empty($info['audio']['encoder']) || (strlen($PossiblyLongerLAMEversion_NewString) > strlen($info['audio']['encoder']))) {
+ $info['audio']['encoder'] = $PossiblyLongerLAMEversion_NewString;
+ }
+ }
+ }
+ }
+ if (!empty($info['audio']['encoder'])) {
+ $info['audio']['encoder'] = rtrim($info['audio']['encoder'], "\x00 ");
+ }
+
+ switch (isset($info['mpeg']['audio']['layer']) ? $info['mpeg']['audio']['layer'] : '') {
+ case 1:
+ case 2:
+ $info['audio']['dataformat'] = 'mp'.$info['mpeg']['audio']['layer'];
+ break;
+ }
+ if (isset($info['fileformat']) && ($info['fileformat'] == 'mp3')) {
+ switch ($info['audio']['dataformat']) {
+ case 'mp1':
+ case 'mp2':
+ case 'mp3':
+ $info['fileformat'] = $info['audio']['dataformat'];
+ break;
+
+ default:
+ $info['warning'][] = 'Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"';
+ break;
+ }
+ }
+
+ if (empty($info['fileformat'])) {
+ unset($info['fileformat']);
+ unset($info['audio']['bitrate_mode']);
+ unset($info['avdataoffset']);
+ unset($info['avdataend']);
+ return false;
+ }
+
+ $info['mime_type'] = 'audio/mpeg';
+ $info['audio']['lossless'] = false;
+
+ // Calculate playtime
+ if (!isset($info['playtime_seconds']) && isset($info['audio']['bitrate']) && ($info['audio']['bitrate'] > 0)) {
+ $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) * 8 / $info['audio']['bitrate'];
+ }
+
+ $info['audio']['encoder_options'] = $this->GuessEncoderOptions();
+
+ return true;
+ }
+
+
+ public function GuessEncoderOptions() {
+ // shortcuts
+ $info = &$this->getid3->info;
+ if (!empty($info['mpeg']['audio'])) {
+ $thisfile_mpeg_audio = &$info['mpeg']['audio'];
+ if (!empty($thisfile_mpeg_audio['LAME'])) {
+ $thisfile_mpeg_audio_lame = &$thisfile_mpeg_audio['LAME'];
+ }
+ }
+
+ $encoder_options = '';
+ static $NamedPresetBitrates = array(16, 24, 40, 56, 112, 128, 160, 192, 256);
+
+ if (isset($thisfile_mpeg_audio['VBR_method']) && ($thisfile_mpeg_audio['VBR_method'] == 'Fraunhofer') && !empty($thisfile_mpeg_audio['VBR_quality'])) {
+
+ $encoder_options = 'VBR q'.$thisfile_mpeg_audio['VBR_quality'];
+
+ } elseif (!empty($thisfile_mpeg_audio_lame['preset_used']) && (!in_array($thisfile_mpeg_audio_lame['preset_used_id'], $NamedPresetBitrates))) {
+
+ $encoder_options = $thisfile_mpeg_audio_lame['preset_used'];
+
+ } elseif (!empty($thisfile_mpeg_audio_lame['vbr_quality'])) {
+
+ static $KnownEncoderValues = array();
+ if (empty($KnownEncoderValues)) {
+
+ //$KnownEncoderValues[abrbitrate_minbitrate][vbr_quality][raw_vbr_method][raw_noise_shaping][raw_stereo_mode][ath_type][lowpass_frequency] = 'preset name';
+ $KnownEncoderValues[0xFF][58][1][1][3][2][20500] = '--alt-preset insane'; // 3.90, 3.90.1, 3.92
+ $KnownEncoderValues[0xFF][58][1][1][3][2][20600] = '--alt-preset insane'; // 3.90.2, 3.90.3, 3.91
+ $KnownEncoderValues[0xFF][57][1][1][3][4][20500] = '--alt-preset insane'; // 3.94, 3.95
+ $KnownEncoderValues['**'][78][3][2][3][2][19500] = '--alt-preset extreme'; // 3.90, 3.90.1, 3.92
+ $KnownEncoderValues['**'][78][3][2][3][2][19600] = '--alt-preset extreme'; // 3.90.2, 3.91
+ $KnownEncoderValues['**'][78][3][1][3][2][19600] = '--alt-preset extreme'; // 3.90.3
+ $KnownEncoderValues['**'][78][4][2][3][2][19500] = '--alt-preset fast extreme'; // 3.90, 3.90.1, 3.92
+ $KnownEncoderValues['**'][78][4][2][3][2][19600] = '--alt-preset fast extreme'; // 3.90.2, 3.90.3, 3.91
+ $KnownEncoderValues['**'][78][3][2][3][4][19000] = '--alt-preset standard'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
+ $KnownEncoderValues['**'][78][3][1][3][4][19000] = '--alt-preset standard'; // 3.90.3
+ $KnownEncoderValues['**'][78][4][2][3][4][19000] = '--alt-preset fast standard'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
+ $KnownEncoderValues['**'][78][4][1][3][4][19000] = '--alt-preset fast standard'; // 3.90.3
+ $KnownEncoderValues['**'][88][4][1][3][3][19500] = '--r3mix'; // 3.90, 3.90.1, 3.92
+ $KnownEncoderValues['**'][88][4][1][3][3][19600] = '--r3mix'; // 3.90.2, 3.90.3, 3.91
+ $KnownEncoderValues['**'][67][4][1][3][4][18000] = '--r3mix'; // 3.94, 3.95
+ $KnownEncoderValues['**'][68][3][2][3][4][18000] = '--alt-preset medium'; // 3.90.3
+ $KnownEncoderValues['**'][68][4][2][3][4][18000] = '--alt-preset fast medium'; // 3.90.3
+
+ $KnownEncoderValues[0xFF][99][1][1][1][2][0] = '--preset studio'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
+ $KnownEncoderValues[0xFF][58][2][1][3][2][20600] = '--preset studio'; // 3.90.3, 3.93.1
+ $KnownEncoderValues[0xFF][58][2][1][3][2][20500] = '--preset studio'; // 3.93
+ $KnownEncoderValues[0xFF][57][2][1][3][4][20500] = '--preset studio'; // 3.94, 3.95
+ $KnownEncoderValues[0xC0][88][1][1][1][2][0] = '--preset cd'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
+ $KnownEncoderValues[0xC0][58][2][2][3][2][19600] = '--preset cd'; // 3.90.3, 3.93.1
+ $KnownEncoderValues[0xC0][58][2][2][3][2][19500] = '--preset cd'; // 3.93
+ $KnownEncoderValues[0xC0][57][2][1][3][4][19500] = '--preset cd'; // 3.94, 3.95
+ $KnownEncoderValues[0xA0][78][1][1][3][2][18000] = '--preset hifi'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
+ $KnownEncoderValues[0xA0][58][2][2][3][2][18000] = '--preset hifi'; // 3.90.3, 3.93, 3.93.1
+ $KnownEncoderValues[0xA0][57][2][1][3][4][18000] = '--preset hifi'; // 3.94, 3.95
+ $KnownEncoderValues[0x80][67][1][1][3][2][18000] = '--preset tape'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
+ $KnownEncoderValues[0x80][67][1][1][3][2][15000] = '--preset radio'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
+ $KnownEncoderValues[0x70][67][1][1][3][2][15000] = '--preset fm'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
+ $KnownEncoderValues[0x70][58][2][2][3][2][16000] = '--preset tape/radio/fm'; // 3.90.3, 3.93, 3.93.1
+ $KnownEncoderValues[0x70][57][2][1][3][4][16000] = '--preset tape/radio/fm'; // 3.94, 3.95
+ $KnownEncoderValues[0x38][58][2][2][0][2][10000] = '--preset voice'; // 3.90.3, 3.93, 3.93.1
+ $KnownEncoderValues[0x38][57][2][1][0][4][15000] = '--preset voice'; // 3.94, 3.95
+ $KnownEncoderValues[0x38][57][2][1][0][4][16000] = '--preset voice'; // 3.94a14
+ $KnownEncoderValues[0x28][65][1][1][0][2][7500] = '--preset mw-us'; // 3.90, 3.90.1, 3.92
+ $KnownEncoderValues[0x28][65][1][1][0][2][7600] = '--preset mw-us'; // 3.90.2, 3.91
+ $KnownEncoderValues[0x28][58][2][2][0][2][7000] = '--preset mw-us'; // 3.90.3, 3.93, 3.93.1
+ $KnownEncoderValues[0x28][57][2][1][0][4][10500] = '--preset mw-us'; // 3.94, 3.95
+ $KnownEncoderValues[0x28][57][2][1][0][4][11200] = '--preset mw-us'; // 3.94a14
+ $KnownEncoderValues[0x28][57][2][1][0][4][8800] = '--preset mw-us'; // 3.94a15
+ $KnownEncoderValues[0x18][58][2][2][0][2][4000] = '--preset phon+/lw/mw-eu/sw'; // 3.90.3, 3.93.1
+ $KnownEncoderValues[0x18][58][2][2][0][2][3900] = '--preset phon+/lw/mw-eu/sw'; // 3.93
+ $KnownEncoderValues[0x18][57][2][1][0][4][5900] = '--preset phon+/lw/mw-eu/sw'; // 3.94, 3.95
+ $KnownEncoderValues[0x18][57][2][1][0][4][6200] = '--preset phon+/lw/mw-eu/sw'; // 3.94a14
+ $KnownEncoderValues[0x18][57][2][1][0][4][3200] = '--preset phon+/lw/mw-eu/sw'; // 3.94a15
+ $KnownEncoderValues[0x10][58][2][2][0][2][3800] = '--preset phone'; // 3.90.3, 3.93.1
+ $KnownEncoderValues[0x10][58][2][2][0][2][3700] = '--preset phone'; // 3.93
+ $KnownEncoderValues[0x10][57][2][1][0][4][5600] = '--preset phone'; // 3.94, 3.95
+ }
+
+ if (isset($KnownEncoderValues[$thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']])) {
+
+ $encoder_options = $KnownEncoderValues[$thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']];
+
+ } elseif (isset($KnownEncoderValues['**'][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']])) {
+
+ $encoder_options = $KnownEncoderValues['**'][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']];
+
+ } elseif ($info['audio']['bitrate_mode'] == 'vbr') {
+
+ // http://gabriel.mp3-tech.org/mp3infotag.html
+ // int Quality = (100 - 10 * gfp->VBR_q - gfp->quality)h
+
+
+ $LAME_V_value = 10 - ceil($thisfile_mpeg_audio_lame['vbr_quality'] / 10);
+ $LAME_q_value = 100 - $thisfile_mpeg_audio_lame['vbr_quality'] - ($LAME_V_value * 10);
+ $encoder_options = '-V'.$LAME_V_value.' -q'.$LAME_q_value;
+
+ } elseif ($info['audio']['bitrate_mode'] == 'cbr') {
+
+ $encoder_options = strtoupper($info['audio']['bitrate_mode']).ceil($info['audio']['bitrate'] / 1000);
+
+ } else {
+
+ $encoder_options = strtoupper($info['audio']['bitrate_mode']);
+
+ }
+
+ } elseif (!empty($thisfile_mpeg_audio_lame['bitrate_abr'])) {
+
+ $encoder_options = 'ABR'.$thisfile_mpeg_audio_lame['bitrate_abr'];
+
+ } elseif (!empty($info['audio']['bitrate'])) {
+
+ if ($info['audio']['bitrate_mode'] == 'cbr') {
+ $encoder_options = strtoupper($info['audio']['bitrate_mode']).ceil($info['audio']['bitrate'] / 1000);
+ } else {
+ $encoder_options = strtoupper($info['audio']['bitrate_mode']);
+ }
+
+ }
+ if (!empty($thisfile_mpeg_audio_lame['bitrate_min'])) {
+ $encoder_options .= ' -b'.$thisfile_mpeg_audio_lame['bitrate_min'];
+ }
+
+ if (!empty($thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev']) || !empty($thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'])) {
+ $encoder_options .= ' --nogap';
+ }
+
+ if (!empty($thisfile_mpeg_audio_lame['lowpass_frequency'])) {
+ $ExplodedOptions = explode(' ', $encoder_options, 4);
+ if ($ExplodedOptions[0] == '--r3mix') {
+ $ExplodedOptions[1] = 'r3mix';
+ }
+ switch ($ExplodedOptions[0]) {
+ case '--preset':
+ case '--alt-preset':
+ case '--r3mix':
+ if ($ExplodedOptions[1] == 'fast') {
+ $ExplodedOptions[1] .= ' '.$ExplodedOptions[2];
+ }
+ switch ($ExplodedOptions[1]) {
+ case 'portable':
+ case 'medium':
+ case 'standard':
+ case 'extreme':
+ case 'insane':
+ case 'fast portable':
+ case 'fast medium':
+ case 'fast standard':
+ case 'fast extreme':
+ case 'fast insane':
+ case 'r3mix':
+ static $ExpectedLowpass = array(
+ 'insane|20500' => 20500,
+ 'insane|20600' => 20600, // 3.90.2, 3.90.3, 3.91
+ 'medium|18000' => 18000,
+ 'fast medium|18000' => 18000,
+ 'extreme|19500' => 19500, // 3.90, 3.90.1, 3.92, 3.95
+ 'extreme|19600' => 19600, // 3.90.2, 3.90.3, 3.91, 3.93.1
+ 'fast extreme|19500' => 19500, // 3.90, 3.90.1, 3.92, 3.95
+ 'fast extreme|19600' => 19600, // 3.90.2, 3.90.3, 3.91, 3.93.1
+ 'standard|19000' => 19000,
+ 'fast standard|19000' => 19000,
+ 'r3mix|19500' => 19500, // 3.90, 3.90.1, 3.92
+ 'r3mix|19600' => 19600, // 3.90.2, 3.90.3, 3.91
+ 'r3mix|18000' => 18000, // 3.94, 3.95
+ );
+ if (!isset($ExpectedLowpass[$ExplodedOptions[1].'|'.$thisfile_mpeg_audio_lame['lowpass_frequency']]) && ($thisfile_mpeg_audio_lame['lowpass_frequency'] < 22050) && (round($thisfile_mpeg_audio_lame['lowpass_frequency'] / 1000) < round($thisfile_mpeg_audio['sample_rate'] / 2000))) {
+ $encoder_options .= ' --lowpass '.$thisfile_mpeg_audio_lame['lowpass_frequency'];
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+ }
+ }
+
+ if (isset($thisfile_mpeg_audio_lame['raw']['source_sample_freq'])) {
+ if (($thisfile_mpeg_audio['sample_rate'] == 44100) && ($thisfile_mpeg_audio_lame['raw']['source_sample_freq'] != 1)) {
+ $encoder_options .= ' --resample 44100';
+ } elseif (($thisfile_mpeg_audio['sample_rate'] == 48000) && ($thisfile_mpeg_audio_lame['raw']['source_sample_freq'] != 2)) {
+ $encoder_options .= ' --resample 48000';
+ } elseif ($thisfile_mpeg_audio['sample_rate'] < 44100) {
+ switch ($thisfile_mpeg_audio_lame['raw']['source_sample_freq']) {
+ case 0: // <= 32000
+ // may or may not be same as source frequency - ignore
+ break;
+ case 1: // 44100
+ case 2: // 48000
+ case 3: // 48000+
+ $ExplodedOptions = explode(' ', $encoder_options, 4);
+ switch ($ExplodedOptions[0]) {
+ case '--preset':
+ case '--alt-preset':
+ switch ($ExplodedOptions[1]) {
+ case 'fast':
+ case 'portable':
+ case 'medium':
+ case 'standard':
+ case 'extreme':
+ case 'insane':
+ $encoder_options .= ' --resample '.$thisfile_mpeg_audio['sample_rate'];
+ break;
+
+ default:
+ static $ExpectedResampledRate = array(
+ 'phon+/lw/mw-eu/sw|16000' => 16000,
+ 'mw-us|24000' => 24000, // 3.95
+ 'mw-us|32000' => 32000, // 3.93
+ 'mw-us|16000' => 16000, // 3.92
+ 'phone|16000' => 16000,
+ 'phone|11025' => 11025, // 3.94a15
+ 'radio|32000' => 32000, // 3.94a15
+ 'fm/radio|32000' => 32000, // 3.92
+ 'fm|32000' => 32000, // 3.90
+ 'voice|32000' => 32000);
+ if (!isset($ExpectedResampledRate[$ExplodedOptions[1].'|'.$thisfile_mpeg_audio['sample_rate']])) {
+ $encoder_options .= ' --resample '.$thisfile_mpeg_audio['sample_rate'];
+ }
+ break;
+ }
+ break;
+
+ case '--r3mix':
+ default:
+ $encoder_options .= ' --resample '.$thisfile_mpeg_audio['sample_rate'];
+ break;
+ }
+ break;
+ }
+ }
+ }
+ if (empty($encoder_options) && !empty($info['audio']['bitrate']) && !empty($info['audio']['bitrate_mode'])) {
+ //$encoder_options = strtoupper($info['audio']['bitrate_mode']).ceil($info['audio']['bitrate'] / 1000);
+ $encoder_options = strtoupper($info['audio']['bitrate_mode']);
+ }
+
+ return $encoder_options;
+ }
+
+
+ public function decodeMPEGaudioHeader($offset, &$info, $recursivesearch=true, $ScanAsCBR=false, $FastMPEGheaderScan=false) {
+ static $MPEGaudioVersionLookup;
+ static $MPEGaudioLayerLookup;
+ static $MPEGaudioBitrateLookup;
+ static $MPEGaudioFrequencyLookup;
+ static $MPEGaudioChannelModeLookup;
+ static $MPEGaudioModeExtensionLookup;
+ static $MPEGaudioEmphasisLookup;
+ if (empty($MPEGaudioVersionLookup)) {
+ $MPEGaudioVersionLookup = self::MPEGaudioVersionArray();
+ $MPEGaudioLayerLookup = self::MPEGaudioLayerArray();
+ $MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray();
+ $MPEGaudioFrequencyLookup = self::MPEGaudioFrequencyArray();
+ $MPEGaudioChannelModeLookup = self::MPEGaudioChannelModeArray();
+ $MPEGaudioModeExtensionLookup = self::MPEGaudioModeExtensionArray();
+ $MPEGaudioEmphasisLookup = self::MPEGaudioEmphasisArray();
+ }
+
+ if (fseek($this->getid3->fp, $offset, SEEK_SET) != 0) {
+ $info['error'][] = 'decodeMPEGaudioHeader() failed to seek to next offset at '.$offset;
+ return false;
+ }
+ //$headerstring = fread($this->getid3->fp, 1441); // worst-case max length = 32kHz @ 320kbps layer 3 = 1441 bytes/frame
+ $headerstring = fread($this->getid3->fp, 226); // LAME header at offset 36 + 190 bytes of Xing/LAME data
+
+ // MP3 audio frame structure:
+ // $aa $aa $aa $aa [$bb $bb] $cc...
+ // where $aa..$aa is the four-byte mpeg-audio header (below)
+ // $bb $bb is the optional 2-byte CRC
+ // and $cc... is the audio data
+
+ $head4 = substr($headerstring, 0, 4);
+
+ static $MPEGaudioHeaderDecodeCache = array();
+ if (isset($MPEGaudioHeaderDecodeCache[$head4])) {
+ $MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4];
+ } else {
+ $MPEGheaderRawArray = self::MPEGaudioHeaderDecode($head4);
+ $MPEGaudioHeaderDecodeCache[$head4] = $MPEGheaderRawArray;
+ }
+
+ static $MPEGaudioHeaderValidCache = array();
+ if (!isset($MPEGaudioHeaderValidCache[$head4])) { // Not in cache
+ //$MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true); // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1)
+ $MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false);
+ }
+
+ // shortcut
+ if (!isset($info['mpeg']['audio'])) {
+ $info['mpeg']['audio'] = array();
+ }
+ $thisfile_mpeg_audio = &$info['mpeg']['audio'];
+
+
+ if ($MPEGaudioHeaderValidCache[$head4]) {
+ $thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray;
+ } else {
+ $info['error'][] = 'Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset;
+ return false;
+ }
+
+ if (!$FastMPEGheaderScan) {
+ $thisfile_mpeg_audio['version'] = $MPEGaudioVersionLookup[$thisfile_mpeg_audio['raw']['version']];
+ $thisfile_mpeg_audio['layer'] = $MPEGaudioLayerLookup[$thisfile_mpeg_audio['raw']['layer']];
+
+ $thisfile_mpeg_audio['channelmode'] = $MPEGaudioChannelModeLookup[$thisfile_mpeg_audio['raw']['channelmode']];
+ $thisfile_mpeg_audio['channels'] = (($thisfile_mpeg_audio['channelmode'] == 'mono') ? 1 : 2);
+ $thisfile_mpeg_audio['sample_rate'] = $MPEGaudioFrequencyLookup[$thisfile_mpeg_audio['version']][$thisfile_mpeg_audio['raw']['sample_rate']];
+ $thisfile_mpeg_audio['protection'] = !$thisfile_mpeg_audio['raw']['protection'];
+ $thisfile_mpeg_audio['private'] = (bool) $thisfile_mpeg_audio['raw']['private'];
+ $thisfile_mpeg_audio['modeextension'] = $MPEGaudioModeExtensionLookup[$thisfile_mpeg_audio['layer']][$thisfile_mpeg_audio['raw']['modeextension']];
+ $thisfile_mpeg_audio['copyright'] = (bool) $thisfile_mpeg_audio['raw']['copyright'];
+ $thisfile_mpeg_audio['original'] = (bool) $thisfile_mpeg_audio['raw']['original'];
+ $thisfile_mpeg_audio['emphasis'] = $MPEGaudioEmphasisLookup[$thisfile_mpeg_audio['raw']['emphasis']];
+
+ $info['audio']['channels'] = $thisfile_mpeg_audio['channels'];
+ $info['audio']['sample_rate'] = $thisfile_mpeg_audio['sample_rate'];
+
+ if ($thisfile_mpeg_audio['protection']) {
+ $thisfile_mpeg_audio['crc'] = getid3_lib::BigEndian2Int(substr($headerstring, 4, 2));
+ }
+ }
+
+ if ($thisfile_mpeg_audio['raw']['bitrate'] == 15) {
+ // http://www.hydrogenaudio.org/?act=ST&f=16&t=9682&st=0
+ $info['warning'][] = 'Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1';
+ $thisfile_mpeg_audio['raw']['bitrate'] = 0;
+ }
+ $thisfile_mpeg_audio['padding'] = (bool) $thisfile_mpeg_audio['raw']['padding'];
+ $thisfile_mpeg_audio['bitrate'] = $MPEGaudioBitrateLookup[$thisfile_mpeg_audio['version']][$thisfile_mpeg_audio['layer']][$thisfile_mpeg_audio['raw']['bitrate']];
+
+ if (($thisfile_mpeg_audio['bitrate'] == 'free') && ($offset == $info['avdataoffset'])) {
+ // only skip multiple frame check if free-format bitstream found at beginning of file
+ // otherwise is quite possibly simply corrupted data
+ $recursivesearch = false;
+ }
+
+ // For Layer 2 there are some combinations of bitrate and mode which are not allowed.
+ if (!$FastMPEGheaderScan && ($thisfile_mpeg_audio['layer'] == '2')) {
+
+ $info['audio']['dataformat'] = 'mp2';
+ switch ($thisfile_mpeg_audio['channelmode']) {
+
+ case 'mono':
+ if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] <= 192000)) {
+ // these are ok
+ } else {
+ $info['error'][] = $thisfile_mpeg_audio['bitrate'].'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.';
+ return false;
+ }
+ break;
+
+ case 'stereo':
+ case 'joint stereo':
+ case 'dual channel':
+ if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] == 64000) || ($thisfile_mpeg_audio['bitrate'] >= 96000)) {
+ // these are ok
+ } else {
+ $info['error'][] = intval(round($thisfile_mpeg_audio['bitrate'] / 1000)).'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.';
+ return false;
+ }
+ break;
+
+ }
+
+ }
+
+
+ if ($info['audio']['sample_rate'] > 0) {
+ $thisfile_mpeg_audio['framelength'] = self::MPEGaudioFrameLength($thisfile_mpeg_audio['bitrate'], $thisfile_mpeg_audio['version'], $thisfile_mpeg_audio['layer'], (int) $thisfile_mpeg_audio['padding'], $info['audio']['sample_rate']);
+ }
+
+ $nextframetestoffset = $offset + 1;
+ if ($thisfile_mpeg_audio['bitrate'] != 'free') {
+
+ $info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate'];
+
+ if (isset($thisfile_mpeg_audio['framelength'])) {
+ $nextframetestoffset = $offset + $thisfile_mpeg_audio['framelength'];
+ } else {
+ $info['error'][] = 'Frame at offset('.$offset.') is has an invalid frame length.';
+ return false;
+ }
+
+ }
+
+ $ExpectedNumberOfAudioBytes = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Variable-bitrate headers
+
+ if (substr($headerstring, 4 + 32, 4) == 'VBRI') {
+ // Fraunhofer VBR header is hardcoded 'VBRI' at offset 0x24 (36)
+ // specs taken from http://minnie.tuhs.org/pipermail/mp3encoder/2001-January/001800.html
+
+ $thisfile_mpeg_audio['bitrate_mode'] = 'vbr';
+ $thisfile_mpeg_audio['VBR_method'] = 'Fraunhofer';
+ $info['audio']['codec'] = 'Fraunhofer';
+
+ $SideInfoData = substr($headerstring, 4 + 2, 32);
+
+ $FraunhoferVBROffset = 36;
+
+ $thisfile_mpeg_audio['VBR_encoder_version'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 4, 2)); // VbriVersion
+ $thisfile_mpeg_audio['VBR_encoder_delay'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 6, 2)); // VbriDelay
+ $thisfile_mpeg_audio['VBR_quality'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 8, 2)); // VbriQuality
+ $thisfile_mpeg_audio['VBR_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 10, 4)); // VbriStreamBytes
+ $thisfile_mpeg_audio['VBR_frames'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 14, 4)); // VbriStreamFrames
+ $thisfile_mpeg_audio['VBR_seek_offsets'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 18, 2)); // VbriTableSize
+ $thisfile_mpeg_audio['VBR_seek_scale'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 20, 2)); // VbriTableScale
+ $thisfile_mpeg_audio['VBR_entry_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 22, 2)); // VbriEntryBytes
+ $thisfile_mpeg_audio['VBR_entry_frames'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 24, 2)); // VbriEntryFrames
+
+ $ExpectedNumberOfAudioBytes = $thisfile_mpeg_audio['VBR_bytes'];
+
+ $previousbyteoffset = $offset;
+ for ($i = 0; $i < $thisfile_mpeg_audio['VBR_seek_offsets']; $i++) {
+ $Fraunhofer_OffsetN = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset, $thisfile_mpeg_audio['VBR_entry_bytes']));
+ $FraunhoferVBROffset += $thisfile_mpeg_audio['VBR_entry_bytes'];
+ $thisfile_mpeg_audio['VBR_offsets_relative'][$i] = ($Fraunhofer_OffsetN * $thisfile_mpeg_audio['VBR_seek_scale']);
+ $thisfile_mpeg_audio['VBR_offsets_absolute'][$i] = ($Fraunhofer_OffsetN * $thisfile_mpeg_audio['VBR_seek_scale']) + $previousbyteoffset;
+ $previousbyteoffset += $Fraunhofer_OffsetN;
+ }
+
+
+ } else {
+
+ // Xing VBR header is hardcoded 'Xing' at a offset 0x0D (13), 0x15 (21) or 0x24 (36)
+ // depending on MPEG layer and number of channels
+
+ $VBRidOffset = self::XingVBRidOffset($thisfile_mpeg_audio['version'], $thisfile_mpeg_audio['channelmode']);
+ $SideInfoData = substr($headerstring, 4 + 2, $VBRidOffset - 4);
+
+ if ((substr($headerstring, $VBRidOffset, strlen('Xing')) == 'Xing') || (substr($headerstring, $VBRidOffset, strlen('Info')) == 'Info')) {
+ // 'Xing' is traditional Xing VBR frame
+ // 'Info' is LAME-encoded CBR (This was done to avoid CBR files to be recognized as traditional Xing VBR files by some decoders.)
+ // 'Info' *can* legally be used to specify a VBR file as well, however.
+
+ // http://www.multiweb.cz/twoinches/MP3inside.htm
+ //00..03 = "Xing" or "Info"
+ //04..07 = Flags:
+ // 0x01 Frames Flag set if value for number of frames in file is stored
+ // 0x02 Bytes Flag set if value for filesize in bytes is stored
+ // 0x04 TOC Flag set if values for TOC are stored
+ // 0x08 VBR Scale Flag set if values for VBR scale is stored
+ //08..11 Frames: Number of frames in file (including the first Xing/Info one)
+ //12..15 Bytes: File length in Bytes
+ //16..115 TOC (Table of Contents):
+ // Contains of 100 indexes (one Byte length) for easier lookup in file. Approximately solves problem with moving inside file.
+ // Each Byte has a value according this formula:
+ // (TOC[i] / 256) * fileLenInBytes
+ // So if song lasts eg. 240 sec. and you want to jump to 60. sec. (and file is 5 000 000 Bytes length) you can use:
+ // TOC[(60/240)*100] = TOC[25]
+ // and corresponding Byte in file is then approximately at:
+ // (TOC[25]/256) * 5000000
+ //116..119 VBR Scale
+
+
+ // should be safe to leave this at 'vbr' and let it be overriden to 'cbr' if a CBR preset/mode is used by LAME
+// if (substr($headerstring, $VBRidOffset, strlen('Info')) == 'Xing') {
+ $thisfile_mpeg_audio['bitrate_mode'] = 'vbr';
+ $thisfile_mpeg_audio['VBR_method'] = 'Xing';
+// } else {
+// $ScanAsCBR = true;
+// $thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
+// }
+
+ $thisfile_mpeg_audio['xing_flags_raw'] = getid3_lib::BigEndian2Int(substr($headerstring, $VBRidOffset + 4, 4));
+
+ $thisfile_mpeg_audio['xing_flags']['frames'] = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000001);
+ $thisfile_mpeg_audio['xing_flags']['bytes'] = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000002);
+ $thisfile_mpeg_audio['xing_flags']['toc'] = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000004);
+ $thisfile_mpeg_audio['xing_flags']['vbr_scale'] = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000008);
+
+ if ($thisfile_mpeg_audio['xing_flags']['frames']) {
+ $thisfile_mpeg_audio['VBR_frames'] = getid3_lib::BigEndian2Int(substr($headerstring, $VBRidOffset + 8, 4));
+ //$thisfile_mpeg_audio['VBR_frames']--; // don't count header Xing/Info frame
+ }
+ if ($thisfile_mpeg_audio['xing_flags']['bytes']) {
+ $thisfile_mpeg_audio['VBR_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $VBRidOffset + 12, 4));
+ }
+
+ //if (($thisfile_mpeg_audio['bitrate'] == 'free') && !empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
+ if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
+
+ $framelengthfloat = $thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames'];
+
+ if ($thisfile_mpeg_audio['layer'] == '1') {
+ // BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
+ //$info['audio']['bitrate'] = ((($framelengthfloat / 4) - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 12;
+ $info['audio']['bitrate'] = ($framelengthfloat / 4) * $thisfile_mpeg_audio['sample_rate'] * (2 / $info['audio']['channels']) / 12;
+ } else {
+ // Bitrate = ((FrameLengthInBytes - Padding) * SampleRate) / 144
+ //$info['audio']['bitrate'] = (($framelengthfloat - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 144;
+ $info['audio']['bitrate'] = $framelengthfloat * $thisfile_mpeg_audio['sample_rate'] * (2 / $info['audio']['channels']) / 144;
+ }
+ $thisfile_mpeg_audio['framelength'] = floor($framelengthfloat);
+ }
+
+ if ($thisfile_mpeg_audio['xing_flags']['toc']) {
+ $LAMEtocData = substr($headerstring, $VBRidOffset + 16, 100);
+ for ($i = 0; $i < 100; $i++) {
+ $thisfile_mpeg_audio['toc'][$i] = ord($LAMEtocData{$i});
+ }
+ }
+ if ($thisfile_mpeg_audio['xing_flags']['vbr_scale']) {
+ $thisfile_mpeg_audio['VBR_scale'] = getid3_lib::BigEndian2Int(substr($headerstring, $VBRidOffset + 116, 4));
+ }
+
+
+ // http://gabriel.mp3-tech.org/mp3infotag.html
+ if (substr($headerstring, $VBRidOffset + 120, 4) == 'LAME') {
+
+ // shortcut
+ $thisfile_mpeg_audio['LAME'] = array();
+ $thisfile_mpeg_audio_lame = &$thisfile_mpeg_audio['LAME'];
+
+
+ $thisfile_mpeg_audio_lame['long_version'] = substr($headerstring, $VBRidOffset + 120, 20);
+ $thisfile_mpeg_audio_lame['short_version'] = substr($thisfile_mpeg_audio_lame['long_version'], 0, 9);
+
+ if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.90') {
+
+ // extra 11 chars are not part of version string when LAMEtag present
+ unset($thisfile_mpeg_audio_lame['long_version']);
+
+ // It the LAME tag was only introduced in LAME v3.90
+ // http://www.hydrogenaudio.org/?act=ST&f=15&t=9933
+
+ // Offsets of various bytes in http://gabriel.mp3-tech.org/mp3infotag.html
+ // are assuming a 'Xing' identifier offset of 0x24, which is the case for
+ // MPEG-1 non-mono, but not for other combinations
+ $LAMEtagOffsetContant = $VBRidOffset - 0x24;
+
+ // shortcuts
+ $thisfile_mpeg_audio_lame['RGAD'] = array('track'=>array(), 'album'=>array());
+ $thisfile_mpeg_audio_lame_RGAD = &$thisfile_mpeg_audio_lame['RGAD'];
+ $thisfile_mpeg_audio_lame_RGAD_track = &$thisfile_mpeg_audio_lame_RGAD['track'];
+ $thisfile_mpeg_audio_lame_RGAD_album = &$thisfile_mpeg_audio_lame_RGAD['album'];
+ $thisfile_mpeg_audio_lame['raw'] = array();
+ $thisfile_mpeg_audio_lame_raw = &$thisfile_mpeg_audio_lame['raw'];
+
+ // byte $9B VBR Quality
+ // This field is there to indicate a quality level, although the scale was not precised in the original Xing specifications.
+ // Actually overwrites original Xing bytes
+ unset($thisfile_mpeg_audio['VBR_scale']);
+ $thisfile_mpeg_audio_lame['vbr_quality'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0x9B, 1));
+
+ // bytes $9C-$A4 Encoder short VersionString
+ $thisfile_mpeg_audio_lame['short_version'] = substr($headerstring, $LAMEtagOffsetContant + 0x9C, 9);
+
+ // byte $A5 Info Tag revision + VBR method
+ $LAMEtagRevisionVBRmethod = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA5, 1));
+
+ $thisfile_mpeg_audio_lame['tag_revision'] = ($LAMEtagRevisionVBRmethod & 0xF0) >> 4;
+ $thisfile_mpeg_audio_lame_raw['vbr_method'] = $LAMEtagRevisionVBRmethod & 0x0F;
+ $thisfile_mpeg_audio_lame['vbr_method'] = self::LAMEvbrMethodLookup($thisfile_mpeg_audio_lame_raw['vbr_method']);
+ $thisfile_mpeg_audio['bitrate_mode'] = substr($thisfile_mpeg_audio_lame['vbr_method'], 0, 3); // usually either 'cbr' or 'vbr', but truncates 'vbr-old / vbr-rh' to 'vbr'
+
+ // byte $A6 Lowpass filter value
+ $thisfile_mpeg_audio_lame['lowpass_frequency'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA6, 1)) * 100;
+
+ // bytes $A7-$AE Replay Gain
+ // http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html
+ // bytes $A7-$AA : 32 bit floating point "Peak signal amplitude"
+ if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.94b') {
+ // LAME 3.94a16 and later - 9.23 fixed point
+ // ie 0x0059E2EE / (2^23) = 5890798 / 8388608 = 0.7022378444671630859375
+ $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = (float) ((getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4))) / 8388608);
+ } else {
+ // LAME 3.94a15 and earlier - 32-bit floating point
+ // Actually 3.94a16 will fall in here too and be WRONG, but is hard to detect 3.94a16 vs 3.94a15
+ $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = getid3_lib::LittleEndian2Float(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4));
+ }
+ if ($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] == 0) {
+ unset($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']);
+ } else {
+ $thisfile_mpeg_audio_lame_RGAD['peak_db'] = getid3_lib::RGADamplitude2dB($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']);
+ }
+
+ $thisfile_mpeg_audio_lame_raw['RGAD_track'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAB, 2));
+ $thisfile_mpeg_audio_lame_raw['RGAD_album'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAD, 2));
+
+
+ if ($thisfile_mpeg_audio_lame_raw['RGAD_track'] != 0) {
+
+ $thisfile_mpeg_audio_lame_RGAD_track['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0xE000) >> 13;
+ $thisfile_mpeg_audio_lame_RGAD_track['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x1C00) >> 10;
+ $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x0200) >> 9;
+ $thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x01FF;
+ $thisfile_mpeg_audio_lame_RGAD_track['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['name']);
+ $thisfile_mpeg_audio_lame_RGAD_track['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['originator']);
+ $thisfile_mpeg_audio_lame_RGAD_track['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit']);
+
+ if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) {
+ $info['replay_gain']['track']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'];
+ }
+ $info['replay_gain']['track']['originator'] = $thisfile_mpeg_audio_lame_RGAD_track['originator'];
+ $info['replay_gain']['track']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_track['gain_db'];
+ } else {
+ unset($thisfile_mpeg_audio_lame_RGAD['track']);
+ }
+ if ($thisfile_mpeg_audio_lame_raw['RGAD_album'] != 0) {
+
+ $thisfile_mpeg_audio_lame_RGAD_album['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0xE000) >> 13;
+ $thisfile_mpeg_audio_lame_RGAD_album['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x1C00) >> 10;
+ $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x0200) >> 9;
+ $thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x01FF;
+ $thisfile_mpeg_audio_lame_RGAD_album['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['name']);
+ $thisfile_mpeg_audio_lame_RGAD_album['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['originator']);
+ $thisfile_mpeg_audio_lame_RGAD_album['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit']);
+
+ if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) {
+ $info['replay_gain']['album']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'];
+ }
+ $info['replay_gain']['album']['originator'] = $thisfile_mpeg_audio_lame_RGAD_album['originator'];
+ $info['replay_gain']['album']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_album['gain_db'];
+ } else {
+ unset($thisfile_mpeg_audio_lame_RGAD['album']);
+ }
+ if (empty($thisfile_mpeg_audio_lame_RGAD)) {
+ unset($thisfile_mpeg_audio_lame['RGAD']);
+ }
+
+
+ // byte $AF Encoding flags + ATH Type
+ $EncodingFlagsATHtype = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAF, 1));
+ $thisfile_mpeg_audio_lame['encoding_flags']['nspsytune'] = (bool) ($EncodingFlagsATHtype & 0x10);
+ $thisfile_mpeg_audio_lame['encoding_flags']['nssafejoint'] = (bool) ($EncodingFlagsATHtype & 0x20);
+ $thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'] = (bool) ($EncodingFlagsATHtype & 0x40);
+ $thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev'] = (bool) ($EncodingFlagsATHtype & 0x80);
+ $thisfile_mpeg_audio_lame['ath_type'] = $EncodingFlagsATHtype & 0x0F;
+
+ // byte $B0 if ABR {specified bitrate} else {minimal bitrate}
+ $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB0, 1));
+ if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 2) { // Average BitRate (ABR)
+ $thisfile_mpeg_audio_lame['bitrate_abr'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'];
+ } elseif ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { // Constant BitRate (CBR)
+ // ignore
+ } elseif ($thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] > 0) { // Variable BitRate (VBR) - minimum bitrate
+ $thisfile_mpeg_audio_lame['bitrate_min'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'];
+ }
+
+ // bytes $B1-$B3 Encoder delays
+ $EncoderDelays = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB1, 3));
+ $thisfile_mpeg_audio_lame['encoder_delay'] = ($EncoderDelays & 0xFFF000) >> 12;
+ $thisfile_mpeg_audio_lame['end_padding'] = $EncoderDelays & 0x000FFF;
+
+ // byte $B4 Misc
+ $MiscByte = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB4, 1));
+ $thisfile_mpeg_audio_lame_raw['noise_shaping'] = ($MiscByte & 0x03);
+ $thisfile_mpeg_audio_lame_raw['stereo_mode'] = ($MiscByte & 0x1C) >> 2;
+ $thisfile_mpeg_audio_lame_raw['not_optimal_quality'] = ($MiscByte & 0x20) >> 5;
+ $thisfile_mpeg_audio_lame_raw['source_sample_freq'] = ($MiscByte & 0xC0) >> 6;
+ $thisfile_mpeg_audio_lame['noise_shaping'] = $thisfile_mpeg_audio_lame_raw['noise_shaping'];
+ $thisfile_mpeg_audio_lame['stereo_mode'] = self::LAMEmiscStereoModeLookup($thisfile_mpeg_audio_lame_raw['stereo_mode']);
+ $thisfile_mpeg_audio_lame['not_optimal_quality'] = (bool) $thisfile_mpeg_audio_lame_raw['not_optimal_quality'];
+ $thisfile_mpeg_audio_lame['source_sample_freq'] = self::LAMEmiscSourceSampleFrequencyLookup($thisfile_mpeg_audio_lame_raw['source_sample_freq']);
+
+ // byte $B5 MP3 Gain
+ $thisfile_mpeg_audio_lame_raw['mp3_gain'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB5, 1), false, true);
+ $thisfile_mpeg_audio_lame['mp3_gain_db'] = (getid3_lib::RGADamplitude2dB(2) / 4) * $thisfile_mpeg_audio_lame_raw['mp3_gain'];
+ $thisfile_mpeg_audio_lame['mp3_gain_factor'] = pow(2, ($thisfile_mpeg_audio_lame['mp3_gain_db'] / 6));
+
+ // bytes $B6-$B7 Preset and surround info
+ $PresetSurroundBytes = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB6, 2));
+ // Reserved = ($PresetSurroundBytes & 0xC000);
+ $thisfile_mpeg_audio_lame_raw['surround_info'] = ($PresetSurroundBytes & 0x3800);
+ $thisfile_mpeg_audio_lame['surround_info'] = self::LAMEsurroundInfoLookup($thisfile_mpeg_audio_lame_raw['surround_info']);
+ $thisfile_mpeg_audio_lame['preset_used_id'] = ($PresetSurroundBytes & 0x07FF);
+ $thisfile_mpeg_audio_lame['preset_used'] = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame);
+ if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) {
+ $info['warning'][] = 'Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org';
+ }
+ if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) {
+ // this may change if 3.90.4 ever comes out
+ $thisfile_mpeg_audio_lame['short_version'] = 'LAME3.90.3';
+ }
+
+ // bytes $B8-$BB MusicLength
+ $thisfile_mpeg_audio_lame['audio_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB8, 4));
+ $ExpectedNumberOfAudioBytes = (($thisfile_mpeg_audio_lame['audio_bytes'] > 0) ? $thisfile_mpeg_audio_lame['audio_bytes'] : $thisfile_mpeg_audio['VBR_bytes']);
+
+ // bytes $BC-$BD MusicCRC
+ $thisfile_mpeg_audio_lame['music_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBC, 2));
+
+ // bytes $BE-$BF CRC-16 of Info Tag
+ $thisfile_mpeg_audio_lame['lame_tag_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBE, 2));
+
+
+ // LAME CBR
+ if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) {
+
+ $thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
+ $thisfile_mpeg_audio['bitrate'] = self::ClosestStandardMP3Bitrate($thisfile_mpeg_audio['bitrate']);
+ $info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate'];
+ //if (empty($thisfile_mpeg_audio['bitrate']) || (!empty($thisfile_mpeg_audio_lame['bitrate_min']) && ($thisfile_mpeg_audio_lame['bitrate_min'] != 255))) {
+ // $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio_lame['bitrate_min'];
+ //}
+
+ }
+
+ }
+ }
+
+ } else {
+
+ // not Fraunhofer or Xing VBR methods, most likely CBR (but could be VBR with no header)
+ $thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
+ if ($recursivesearch) {
+ $thisfile_mpeg_audio['bitrate_mode'] = 'vbr';
+ if ($this->RecursiveFrameScanning($offset, $nextframetestoffset, true)) {
+ $recursivesearch = false;
+ $thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
+ }
+ if ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') {
+ $info['warning'][] = 'VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.';
+ }
+ }
+
+ }
+
+ }
+
+ if (($ExpectedNumberOfAudioBytes > 0) && ($ExpectedNumberOfAudioBytes != ($info['avdataend'] - $info['avdataoffset']))) {
+ if ($ExpectedNumberOfAudioBytes > ($info['avdataend'] - $info['avdataoffset'])) {
+ if (isset($info['fileformat']) && ($info['fileformat'] == 'riff')) {
+ // ignore, audio data is broken into chunks so will always be data "missing"
+ } elseif (($ExpectedNumberOfAudioBytes - ($info['avdataend'] - $info['avdataoffset'])) == 1) {
+ $info['warning'][] = 'Last byte of data truncated (this is a known bug in Meracl ID3 Tag Writer before v1.3.5)';
+ } else {
+ $info['warning'][] = 'Probable truncated file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, only found '.($info['avdataend'] - $info['avdataoffset']).' (short by '.($ExpectedNumberOfAudioBytes - ($info['avdataend'] - $info['avdataoffset'])).' bytes)';
+ }
+ } else {
+ if ((($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes) == 1) {
+ // $prenullbytefileoffset = ftell($this->getid3->fp);
+ // fseek($this->getid3->fp, $info['avdataend'], SEEK_SET);
+ // $PossibleNullByte = fread($this->getid3->fp, 1);
+ // fseek($this->getid3->fp, $prenullbytefileoffset, SEEK_SET);
+ // if ($PossibleNullByte === "\x00") {
+ $info['avdataend']--;
+ // $info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
+ // } else {
+ // $info['warning'][] = 'Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)';
+ // }
+ } else {
+ $info['warning'][] = 'Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)';
+ }
+ }
+ }
+
+ if (($thisfile_mpeg_audio['bitrate'] == 'free') && empty($info['audio']['bitrate'])) {
+ if (($offset == $info['avdataoffset']) && empty($thisfile_mpeg_audio['VBR_frames'])) {
+ $framebytelength = $this->FreeFormatFrameLength($offset, true);
+ if ($framebytelength > 0) {
+ $thisfile_mpeg_audio['framelength'] = $framebytelength;
+ if ($thisfile_mpeg_audio['layer'] == '1') {
+ // BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
+ $info['audio']['bitrate'] = ((($framebytelength / 4) - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 12;
+ } else {
+ // Bitrate = ((FrameLengthInBytes - Padding) * SampleRate) / 144
+ $info['audio']['bitrate'] = (($framebytelength - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 144;
+ }
+ } else {
+ $info['error'][] = 'Error calculating frame length of free-format MP3 without Xing/LAME header';
+ }
+ }
+ }
+
+ if (isset($thisfile_mpeg_audio['VBR_frames']) ? $thisfile_mpeg_audio['VBR_frames'] : '') {
+ switch ($thisfile_mpeg_audio['bitrate_mode']) {
+ case 'vbr':
+ case 'abr':
+ $bytes_per_frame = 1152;
+ if (($thisfile_mpeg_audio['version'] == '1') && ($thisfile_mpeg_audio['layer'] == 1)) {
+ $bytes_per_frame = 384;
+ } elseif ((($thisfile_mpeg_audio['version'] == '2') || ($thisfile_mpeg_audio['version'] == '2.5')) && ($thisfile_mpeg_audio['layer'] == 3)) {
+ $bytes_per_frame = 576;
+ }
+ $thisfile_mpeg_audio['VBR_bitrate'] = (isset($thisfile_mpeg_audio['VBR_bytes']) ? (($thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($info['audio']['sample_rate'] / $bytes_per_frame) : 0);
+ if ($thisfile_mpeg_audio['VBR_bitrate'] > 0) {
+ $info['audio']['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate'];
+ $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; // to avoid confusion
+ }
+ break;
+ }
+ }
+
+ // End variable-bitrate headers
+ ////////////////////////////////////////////////////////////////////////////////////
+
+ if ($recursivesearch) {
+
+ if (!$this->RecursiveFrameScanning($offset, $nextframetestoffset, $ScanAsCBR)) {
+ return false;
+ }
+
+ }
+
+
+ //if (false) {
+ // // experimental side info parsing section - not returning anything useful yet
+ //
+ // $SideInfoBitstream = getid3_lib::BigEndian2Bin($SideInfoData);
+ // $SideInfoOffset = 0;
+ //
+ // if ($thisfile_mpeg_audio['version'] == '1') {
+ // if ($thisfile_mpeg_audio['channelmode'] == 'mono') {
+ // // MPEG-1 (mono)
+ // $thisfile_mpeg_audio['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 9);
+ // $SideInfoOffset += 9;
+ // $SideInfoOffset += 5;
+ // } else {
+ // // MPEG-1 (stereo, joint-stereo, dual-channel)
+ // $thisfile_mpeg_audio['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 9);
+ // $SideInfoOffset += 9;
+ // $SideInfoOffset += 3;
+ // }
+ // } else { // 2 or 2.5
+ // if ($thisfile_mpeg_audio['channelmode'] == 'mono') {
+ // // MPEG-2, MPEG-2.5 (mono)
+ // $thisfile_mpeg_audio['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 8);
+ // $SideInfoOffset += 8;
+ // $SideInfoOffset += 1;
+ // } else {
+ // // MPEG-2, MPEG-2.5 (stereo, joint-stereo, dual-channel)
+ // $thisfile_mpeg_audio['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 8);
+ // $SideInfoOffset += 8;
+ // $SideInfoOffset += 2;
+ // }
+ // }
+ //
+ // if ($thisfile_mpeg_audio['version'] == '1') {
+ // for ($channel = 0; $channel < $info['audio']['channels']; $channel++) {
+ // for ($scfsi_band = 0; $scfsi_band < 4; $scfsi_band++) {
+ // $thisfile_mpeg_audio['scfsi'][$channel][$scfsi_band] = substr($SideInfoBitstream, $SideInfoOffset, 1);
+ // $SideInfoOffset += 2;
+ // }
+ // }
+ // }
+ // for ($granule = 0; $granule < (($thisfile_mpeg_audio['version'] == '1') ? 2 : 1); $granule++) {
+ // for ($channel = 0; $channel < $info['audio']['channels']; $channel++) {
+ // $thisfile_mpeg_audio['part2_3_length'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 12);
+ // $SideInfoOffset += 12;
+ // $thisfile_mpeg_audio['big_values'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 9);
+ // $SideInfoOffset += 9;
+ // $thisfile_mpeg_audio['global_gain'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 8);
+ // $SideInfoOffset += 8;
+ // if ($thisfile_mpeg_audio['version'] == '1') {
+ // $thisfile_mpeg_audio['scalefac_compress'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 4);
+ // $SideInfoOffset += 4;
+ // } else {
+ // $thisfile_mpeg_audio['scalefac_compress'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 9);
+ // $SideInfoOffset += 9;
+ // }
+ // $thisfile_mpeg_audio['window_switching_flag'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
+ // $SideInfoOffset += 1;
+ //
+ // if ($thisfile_mpeg_audio['window_switching_flag'][$granule][$channel] == '1') {
+ //
+ // $thisfile_mpeg_audio['block_type'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 2);
+ // $SideInfoOffset += 2;
+ // $thisfile_mpeg_audio['mixed_block_flag'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
+ // $SideInfoOffset += 1;
+ //
+ // for ($region = 0; $region < 2; $region++) {
+ // $thisfile_mpeg_audio['table_select'][$granule][$channel][$region] = substr($SideInfoBitstream, $SideInfoOffset, 5);
+ // $SideInfoOffset += 5;
+ // }
+ // $thisfile_mpeg_audio['table_select'][$granule][$channel][2] = 0;
+ //
+ // for ($window = 0; $window < 3; $window++) {
+ // $thisfile_mpeg_audio['subblock_gain'][$granule][$channel][$window] = substr($SideInfoBitstream, $SideInfoOffset, 3);
+ // $SideInfoOffset += 3;
+ // }
+ //
+ // } else {
+ //
+ // for ($region = 0; $region < 3; $region++) {
+ // $thisfile_mpeg_audio['table_select'][$granule][$channel][$region] = substr($SideInfoBitstream, $SideInfoOffset, 5);
+ // $SideInfoOffset += 5;
+ // }
+ //
+ // $thisfile_mpeg_audio['region0_count'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 4);
+ // $SideInfoOffset += 4;
+ // $thisfile_mpeg_audio['region1_count'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 3);
+ // $SideInfoOffset += 3;
+ // $thisfile_mpeg_audio['block_type'][$granule][$channel] = 0;
+ // }
+ //
+ // if ($thisfile_mpeg_audio['version'] == '1') {
+ // $thisfile_mpeg_audio['preflag'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
+ // $SideInfoOffset += 1;
+ // }
+ // $thisfile_mpeg_audio['scalefac_scale'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
+ // $SideInfoOffset += 1;
+ // $thisfile_mpeg_audio['count1table_select'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
+ // $SideInfoOffset += 1;
+ // }
+ // }
+ //}
+
+ return true;
+ }
+
+ public function RecursiveFrameScanning(&$offset, &$nextframetestoffset, $ScanAsCBR) {
+ $info = &$this->getid3->info;
+ $firstframetestarray = array('error'=>'', 'warning'=>'', 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
+ $this->decodeMPEGaudioHeader($offset, $firstframetestarray, false);
+
+ for ($i = 0; $i < GETID3_MP3_VALID_CHECK_FRAMES; $i++) {
+ // check next GETID3_MP3_VALID_CHECK_FRAMES frames for validity, to make sure we haven't run across a false synch
+ if (($nextframetestoffset + 4) >= $info['avdataend']) {
+ // end of file
+ return true;
+ }
+
+ $nextframetestarray = array('error'=>'', 'warning'=>'', 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
+ if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) {
+ if ($ScanAsCBR) {
+ // force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header
+ if (!isset($nextframetestarray['mpeg']['audio']['bitrate']) || !isset($firstframetestarray['mpeg']['audio']['bitrate']) || ($nextframetestarray['mpeg']['audio']['bitrate'] != $firstframetestarray['mpeg']['audio']['bitrate'])) {
+ return false;
+ }
+ }
+
+
+ // next frame is OK, get ready to check the one after that
+ if (isset($nextframetestarray['mpeg']['audio']['framelength']) && ($nextframetestarray['mpeg']['audio']['framelength'] > 0)) {
+ $nextframetestoffset += $nextframetestarray['mpeg']['audio']['framelength'];
+ } else {
+ $info['error'][] = 'Frame at offset ('.$offset.') is has an invalid frame length.';
+ return false;
+ }
+
+ } elseif (!empty($firstframetestarray['mpeg']['audio']['framelength']) && (($nextframetestoffset + $firstframetestarray['mpeg']['audio']['framelength']) > $info['avdataend'])) {
+
+ // it's not the end of the file, but there's not enough data left for another frame, so assume it's garbage/padding and return OK
+ return true;
+
+ } else {
+
+ // next frame is not valid, note the error and fail, so scanning can contiue for a valid frame sequence
+ $info['warning'][] = 'Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.';
+
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public function FreeFormatFrameLength($offset, $deepscan=false) {
+ $info = &$this->getid3->info;
+
+ fseek($this->getid3->fp, $offset, SEEK_SET);
+ $MPEGaudioData = fread($this->getid3->fp, 32768);
+
+ $SyncPattern1 = substr($MPEGaudioData, 0, 4);
+ // may be different pattern due to padding
+ $SyncPattern2 = $SyncPattern1{0}.$SyncPattern1{1}.chr(ord($SyncPattern1{2}) | 0x02).$SyncPattern1{3};
+ if ($SyncPattern2 === $SyncPattern1) {
+ $SyncPattern2 = $SyncPattern1{0}.$SyncPattern1{1}.chr(ord($SyncPattern1{2}) & 0xFD).$SyncPattern1{3};
+ }
+
+ $framelength = false;
+ $framelength1 = strpos($MPEGaudioData, $SyncPattern1, 4);
+ $framelength2 = strpos($MPEGaudioData, $SyncPattern2, 4);
+ if ($framelength1 > 4) {
+ $framelength = $framelength1;
+ }
+ if (($framelength2 > 4) && ($framelength2 < $framelength1)) {
+ $framelength = $framelength2;
+ }
+ if (!$framelength) {
+
+ // LAME 3.88 has a different value for modeextension on the first frame vs the rest
+ $framelength1 = strpos($MPEGaudioData, substr($SyncPattern1, 0, 3), 4);
+ $framelength2 = strpos($MPEGaudioData, substr($SyncPattern2, 0, 3), 4);
+
+ if ($framelength1 > 4) {
+ $framelength = $framelength1;
+ }
+ if (($framelength2 > 4) && ($framelength2 < $framelength1)) {
+ $framelength = $framelength2;
+ }
+ if (!$framelength) {
+ $info['error'][] = 'Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($SyncPattern1).' or '.getid3_lib::PrintHexBytes($SyncPattern2).') after offset '.$offset;
+ return false;
+ } else {
+ $info['warning'][] = 'ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)';
+ $info['audio']['codec'] = 'LAME';
+ $info['audio']['encoder'] = 'LAME3.88';
+ $SyncPattern1 = substr($SyncPattern1, 0, 3);
+ $SyncPattern2 = substr($SyncPattern2, 0, 3);
+ }
+ }
+
+ if ($deepscan) {
+
+ $ActualFrameLengthValues = array();
+ $nextoffset = $offset + $framelength;
+ while ($nextoffset < ($info['avdataend'] - 6)) {
+ fseek($this->getid3->fp, $nextoffset - 1, SEEK_SET);
+ $NextSyncPattern = fread($this->getid3->fp, 6);
+ if ((substr($NextSyncPattern, 1, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 1, strlen($SyncPattern2)) == $SyncPattern2)) {
+ // good - found where expected
+ $ActualFrameLengthValues[] = $framelength;
+ } elseif ((substr($NextSyncPattern, 0, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 0, strlen($SyncPattern2)) == $SyncPattern2)) {
+ // ok - found one byte earlier than expected (last frame wasn't padded, first frame was)
+ $ActualFrameLengthValues[] = ($framelength - 1);
+ $nextoffset--;
+ } elseif ((substr($NextSyncPattern, 2, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 2, strlen($SyncPattern2)) == $SyncPattern2)) {
+ // ok - found one byte later than expected (last frame was padded, first frame wasn't)
+ $ActualFrameLengthValues[] = ($framelength + 1);
+ $nextoffset++;
+ } else {
+ $info['error'][] = 'Did not find expected free-format sync pattern at offset '.$nextoffset;
+ return false;
+ }
+ $nextoffset += $framelength;
+ }
+ if (count($ActualFrameLengthValues) > 0) {
+ $framelength = intval(round(array_sum($ActualFrameLengthValues) / count($ActualFrameLengthValues)));
+ }
+ }
+ return $framelength;
+ }
+
+ public function getOnlyMPEGaudioInfoBruteForce() {
+ $MPEGaudioHeaderDecodeCache = array();
+ $MPEGaudioHeaderValidCache = array();
+ $MPEGaudioHeaderLengthCache = array();
+ $MPEGaudioVersionLookup = self::MPEGaudioVersionArray();
+ $MPEGaudioLayerLookup = self::MPEGaudioLayerArray();
+ $MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray();
+ $MPEGaudioFrequencyLookup = self::MPEGaudioFrequencyArray();
+ $MPEGaudioChannelModeLookup = self::MPEGaudioChannelModeArray();
+ $MPEGaudioModeExtensionLookup = self::MPEGaudioModeExtensionArray();
+ $MPEGaudioEmphasisLookup = self::MPEGaudioEmphasisArray();
+ $LongMPEGversionLookup = array();
+ $LongMPEGlayerLookup = array();
+ $LongMPEGbitrateLookup = array();
+ $LongMPEGpaddingLookup = array();
+ $LongMPEGfrequencyLookup = array();
+ $Distribution['bitrate'] = array();
+ $Distribution['frequency'] = array();
+ $Distribution['layer'] = array();
+ $Distribution['version'] = array();
+ $Distribution['padding'] = array();
+
+ $info = &$this->getid3->info;
+ fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
+
+ $max_frames_scan = 5000;
+ $frames_scanned = 0;
+
+ $previousvalidframe = $info['avdataoffset'];
+ while (ftell($this->getid3->fp) < $info['avdataend']) {
+ set_time_limit(30);
+ $head4 = fread($this->getid3->fp, 4);
+ if (strlen($head4) < 4) {
+ break;
+ }
+ if ($head4{0} != "\xFF") {
+ for ($i = 1; $i < 4; $i++) {
+ if ($head4{$i} == "\xFF") {
+ fseek($this->getid3->fp, $i - 4, SEEK_CUR);
+ continue 2;
+ }
+ }
+ continue;
+ }
+ if (!isset($MPEGaudioHeaderDecodeCache[$head4])) {
+ $MPEGaudioHeaderDecodeCache[$head4] = self::MPEGaudioHeaderDecode($head4);
+ }
+ if (!isset($MPEGaudioHeaderValidCache[$head4])) {
+ $MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGaudioHeaderDecodeCache[$head4], false, false);
+ }
+ if ($MPEGaudioHeaderValidCache[$head4]) {
+
+ if (!isset($MPEGaudioHeaderLengthCache[$head4])) {
+ $LongMPEGversionLookup[$head4] = $MPEGaudioVersionLookup[$MPEGaudioHeaderDecodeCache[$head4]['version']];
+ $LongMPEGlayerLookup[$head4] = $MPEGaudioLayerLookup[$MPEGaudioHeaderDecodeCache[$head4]['layer']];
+ $LongMPEGbitrateLookup[$head4] = $MPEGaudioBitrateLookup[$LongMPEGversionLookup[$head4]][$LongMPEGlayerLookup[$head4]][$MPEGaudioHeaderDecodeCache[$head4]['bitrate']];
+ $LongMPEGpaddingLookup[$head4] = (bool) $MPEGaudioHeaderDecodeCache[$head4]['padding'];
+ $LongMPEGfrequencyLookup[$head4] = $MPEGaudioFrequencyLookup[$LongMPEGversionLookup[$head4]][$MPEGaudioHeaderDecodeCache[$head4]['sample_rate']];
+ $MPEGaudioHeaderLengthCache[$head4] = self::MPEGaudioFrameLength(
+ $LongMPEGbitrateLookup[$head4],
+ $LongMPEGversionLookup[$head4],
+ $LongMPEGlayerLookup[$head4],
+ $LongMPEGpaddingLookup[$head4],
+ $LongMPEGfrequencyLookup[$head4]);
+ }
+ if ($MPEGaudioHeaderLengthCache[$head4] > 4) {
+ $WhereWeWere = ftell($this->getid3->fp);
+ fseek($this->getid3->fp, $MPEGaudioHeaderLengthCache[$head4] - 4, SEEK_CUR);
+ $next4 = fread($this->getid3->fp, 4);
+ if ($next4{0} == "\xFF") {
+ if (!isset($MPEGaudioHeaderDecodeCache[$next4])) {
+ $MPEGaudioHeaderDecodeCache[$next4] = self::MPEGaudioHeaderDecode($next4);
+ }
+ if (!isset($MPEGaudioHeaderValidCache[$next4])) {
+ $MPEGaudioHeaderValidCache[$next4] = self::MPEGaudioHeaderValid($MPEGaudioHeaderDecodeCache[$next4], false, false);
+ }
+ if ($MPEGaudioHeaderValidCache[$next4]) {
+ fseek($this->getid3->fp, -4, SEEK_CUR);
+
+ getid3_lib::safe_inc($Distribution['bitrate'][$LongMPEGbitrateLookup[$head4]]);
+ getid3_lib::safe_inc($Distribution['layer'][$LongMPEGlayerLookup[$head4]]);
+ getid3_lib::safe_inc($Distribution['version'][$LongMPEGversionLookup[$head4]]);
+ getid3_lib::safe_inc($Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])]);
+ getid3_lib::safe_inc($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]);
+ if ($max_frames_scan && (++$frames_scanned >= $max_frames_scan)) {
+ $pct_data_scanned = (ftell($this->getid3->fp) - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']);
+ $info['warning'][] = 'too many MPEG audio frames to scan, only scanned first '.$max_frames_scan.' frames ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.';
+ foreach ($Distribution as $key1 => $value1) {
+ foreach ($value1 as $key2 => $value2) {
+ $Distribution[$key1][$key2] = round($value2 / $pct_data_scanned);
+ }
+ }
+ break;
+ }
+ continue;
+ }
+ }
+ unset($next4);
+ fseek($this->getid3->fp, $WhereWeWere - 3, SEEK_SET);
+ }
+
+ }
+ }
+ foreach ($Distribution as $key => $value) {
+ ksort($Distribution[$key], SORT_NUMERIC);
+ }
+ ksort($Distribution['version'], SORT_STRING);
+ $info['mpeg']['audio']['bitrate_distribution'] = $Distribution['bitrate'];
+ $info['mpeg']['audio']['frequency_distribution'] = $Distribution['frequency'];
+ $info['mpeg']['audio']['layer_distribution'] = $Distribution['layer'];
+ $info['mpeg']['audio']['version_distribution'] = $Distribution['version'];
+ $info['mpeg']['audio']['padding_distribution'] = $Distribution['padding'];
+ if (count($Distribution['version']) > 1) {
+ $info['error'][] = 'Corrupt file - more than one MPEG version detected';
+ }
+ if (count($Distribution['layer']) > 1) {
+ $info['error'][] = 'Corrupt file - more than one MPEG layer detected';
+ }
+ if (count($Distribution['frequency']) > 1) {
+ $info['error'][] = 'Corrupt file - more than one MPEG sample rate detected';
+ }
+
+
+ $bittotal = 0;
+ foreach ($Distribution['bitrate'] as $bitratevalue => $bitratecount) {
+ if ($bitratevalue != 'free') {
+ $bittotal += ($bitratevalue * $bitratecount);
+ }
+ }
+ $info['mpeg']['audio']['frame_count'] = array_sum($Distribution['bitrate']);
+ if ($info['mpeg']['audio']['frame_count'] == 0) {
+ $info['error'][] = 'no MPEG audio frames found';
+ return false;
+ }
+ $info['mpeg']['audio']['bitrate'] = ($bittotal / $info['mpeg']['audio']['frame_count']);
+ $info['mpeg']['audio']['bitrate_mode'] = ((count($Distribution['bitrate']) > 0) ? 'vbr' : 'cbr');
+ $info['mpeg']['audio']['sample_rate'] = getid3_lib::array_max($Distribution['frequency'], true);
+
+ $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
+ $info['audio']['bitrate_mode'] = $info['mpeg']['audio']['bitrate_mode'];
+ $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
+ $info['audio']['dataformat'] = 'mp'.getid3_lib::array_max($Distribution['layer'], true);
+ $info['fileformat'] = $info['audio']['dataformat'];
+
+ return true;
+ }
+
+
+ public function getOnlyMPEGaudioInfo($avdataoffset, $BitrateHistogram=false) {
+ // looks for synch, decodes MPEG audio header
+
+ $info = &$this->getid3->info;
+
+ static $MPEGaudioVersionLookup;
+ static $MPEGaudioLayerLookup;
+ static $MPEGaudioBitrateLookup;
+ if (empty($MPEGaudioVersionLookup)) {
+ $MPEGaudioVersionLookup = self::MPEGaudioVersionArray();
+ $MPEGaudioLayerLookup = self::MPEGaudioLayerArray();
+ $MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray();
+
+ }
+
+ fseek($this->getid3->fp, $avdataoffset, SEEK_SET);
+ $sync_seek_buffer_size = min(128 * 1024, $info['avdataend'] - $avdataoffset);
+ if ($sync_seek_buffer_size <= 0) {
+ $info['error'][] = 'Invalid $sync_seek_buffer_size at offset '.$avdataoffset;
+ return false;
+ }
+ $header = fread($this->getid3->fp, $sync_seek_buffer_size);
+ $sync_seek_buffer_size = strlen($header);
+ $SynchSeekOffset = 0;
+ while ($SynchSeekOffset < $sync_seek_buffer_size) {
+ if ((($avdataoffset + $SynchSeekOffset) < $info['avdataend']) && !feof($this->getid3->fp)) {
+
+ if ($SynchSeekOffset > $sync_seek_buffer_size) {
+ // if a synch's not found within the first 128k bytes, then give up
+ $info['error'][] = 'Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB';
+ if (isset($info['audio']['bitrate'])) {
+ unset($info['audio']['bitrate']);
+ }
+ if (isset($info['mpeg']['audio'])) {
+ unset($info['mpeg']['audio']);
+ }
+ if (empty($info['mpeg'])) {
+ unset($info['mpeg']);
+ }
+ return false;
+
+ } elseif (feof($this->getid3->fp)) {
+
+ $info['error'][] = 'Could not find valid MPEG audio synch before end of file';
+ if (isset($info['audio']['bitrate'])) {
+ unset($info['audio']['bitrate']);
+ }
+ if (isset($info['mpeg']['audio'])) {
+ unset($info['mpeg']['audio']);
+ }
+ if (isset($info['mpeg']) && (!is_array($info['mpeg']) || (count($info['mpeg']) == 0))) {
+ unset($info['mpeg']);
+ }
+ return false;
+ }
+ }
+
+ if (($SynchSeekOffset + 1) >= strlen($header)) {
+ $info['error'][] = 'Could not find valid MPEG synch before end of file';
+ return false;
+ }
+
+ if (($header{$SynchSeekOffset} == "\xFF") && ($header{($SynchSeekOffset + 1)} > "\xE0")) { // synch detected
+ if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) {
+ $FirstFrameThisfileInfo = $info;
+ $FirstFrameAVDataOffset = $avdataoffset + $SynchSeekOffset;
+ if (!$this->decodeMPEGaudioHeader($FirstFrameAVDataOffset, $FirstFrameThisfileInfo, false)) {
+ // if this is the first valid MPEG-audio frame, save it in case it's a VBR header frame and there's
+ // garbage between this frame and a valid sequence of MPEG-audio frames, to be restored below
+ unset($FirstFrameThisfileInfo);
+ }
+ }
+
+ $dummy = $info; // only overwrite real data if valid header found
+ if ($this->decodeMPEGaudioHeader($avdataoffset + $SynchSeekOffset, $dummy, true)) {
+ $info = $dummy;
+ $info['avdataoffset'] = $avdataoffset + $SynchSeekOffset;
+ switch (isset($info['fileformat']) ? $info['fileformat'] : '') {
+ case '':
+ case 'id3':
+ case 'ape':
+ case 'mp3':
+ $info['fileformat'] = 'mp3';
+ $info['audio']['dataformat'] = 'mp3';
+ break;
+ }
+ if (isset($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode']) && ($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr')) {
+ if (!(abs($info['audio']['bitrate'] - $FirstFrameThisfileInfo['audio']['bitrate']) <= 1)) {
+ // If there is garbage data between a valid VBR header frame and a sequence
+ // of valid MPEG-audio frames the VBR data is no longer discarded.
+ $info = $FirstFrameThisfileInfo;
+ $info['avdataoffset'] = $FirstFrameAVDataOffset;
+ $info['fileformat'] = 'mp3';
+ $info['audio']['dataformat'] = 'mp3';
+ $dummy = $info;
+ unset($dummy['mpeg']['audio']);
+ $GarbageOffsetStart = $FirstFrameAVDataOffset + $FirstFrameThisfileInfo['mpeg']['audio']['framelength'];
+ $GarbageOffsetEnd = $avdataoffset + $SynchSeekOffset;
+ if ($this->decodeMPEGaudioHeader($GarbageOffsetEnd, $dummy, true, true)) {
+ $info = $dummy;
+ $info['avdataoffset'] = $GarbageOffsetEnd;
+ $info['warning'][] = 'apparently-valid VBR header not used because could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd;
+ } else {
+ $info['warning'][] = 'using data from VBR header even though could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')';
+ }
+ }
+ }
+ if (isset($info['mpeg']['audio']['bitrate_mode']) && ($info['mpeg']['audio']['bitrate_mode'] == 'vbr') && !isset($info['mpeg']['audio']['VBR_method'])) {
+ // VBR file with no VBR header
+ $BitrateHistogram = true;
+ }
+
+ if ($BitrateHistogram) {
+
+ $info['mpeg']['audio']['stereo_distribution'] = array('stereo'=>0, 'joint stereo'=>0, 'dual channel'=>0, 'mono'=>0);
+ $info['mpeg']['audio']['version_distribution'] = array('1'=>0, '2'=>0, '2.5'=>0);
+
+ if ($info['mpeg']['audio']['version'] == '1') {
+ if ($info['mpeg']['audio']['layer'] == 3) {
+ $info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 40000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 320000=>0);
+ } elseif ($info['mpeg']['audio']['layer'] == 2) {
+ $info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 320000=>0, 384000=>0);
+ } elseif ($info['mpeg']['audio']['layer'] == 1) {
+ $info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 64000=>0, 96000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 288000=>0, 320000=>0, 352000=>0, 384000=>0, 416000=>0, 448000=>0);
+ }
+ } elseif ($info['mpeg']['audio']['layer'] == 1) {
+ $info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 144000=>0, 160000=>0, 176000=>0, 192000=>0, 224000=>0, 256000=>0);
+ } else {
+ $info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 8000=>0, 16000=>0, 24000=>0, 32000=>0, 40000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 144000=>0, 160000=>0);
+ }
+
+ $dummy = array('error'=>$info['error'], 'warning'=>$info['warning'], 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
+ $synchstartoffset = $info['avdataoffset'];
+ fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
+
+ // you can play with these numbers:
+ $max_frames_scan = 50000;
+ $max_scan_segments = 10;
+
+ // don't play with these numbers:
+ $FastMode = false;
+ $SynchErrorsFound = 0;
+ $frames_scanned = 0;
+ $this_scan_segment = 0;
+ $frames_scan_per_segment = ceil($max_frames_scan / $max_scan_segments);
+ $pct_data_scanned = 0;
+ for ($current_segment = 0; $current_segment < $max_scan_segments; $current_segment++) {
+ $frames_scanned_this_segment = 0;
+ if (ftell($this->getid3->fp) >= $info['avdataend']) {
+ break;
+ }
+ $scan_start_offset[$current_segment] = max(ftell($this->getid3->fp), $info['avdataoffset'] + round($current_segment * (($info['avdataend'] - $info['avdataoffset']) / $max_scan_segments)));
+ if ($current_segment > 0) {
+ fseek($this->getid3->fp, $scan_start_offset[$current_segment], SEEK_SET);
+ $buffer_4k = fread($this->getid3->fp, 4096);
+ for ($j = 0; $j < (strlen($buffer_4k) - 4); $j++) {
+ if (($buffer_4k{$j} == "\xFF") && ($buffer_4k{($j + 1)} > "\xE0")) { // synch detected
+ if ($this->decodeMPEGaudioHeader($scan_start_offset[$current_segment] + $j, $dummy, false, false, $FastMode)) {
+ $calculated_next_offset = $scan_start_offset[$current_segment] + $j + $dummy['mpeg']['audio']['framelength'];
+ if ($this->decodeMPEGaudioHeader($calculated_next_offset, $dummy, false, false, $FastMode)) {
+ $scan_start_offset[$current_segment] += $j;
+ break;
+ }
+ }
+ }
+ }
+ }
+ $synchstartoffset = $scan_start_offset[$current_segment];
+ while ($this->decodeMPEGaudioHeader($synchstartoffset, $dummy, false, false, $FastMode)) {
+ $FastMode = true;
+ $thisframebitrate = $MPEGaudioBitrateLookup[$MPEGaudioVersionLookup[$dummy['mpeg']['audio']['raw']['version']]][$MPEGaudioLayerLookup[$dummy['mpeg']['audio']['raw']['layer']]][$dummy['mpeg']['audio']['raw']['bitrate']];
+
+ if (empty($dummy['mpeg']['audio']['framelength'])) {
+ $SynchErrorsFound++;
+ $synchstartoffset++;
+ } else {
+ getid3_lib::safe_inc($info['mpeg']['audio']['bitrate_distribution'][$thisframebitrate]);
+ getid3_lib::safe_inc($info['mpeg']['audio']['stereo_distribution'][$dummy['mpeg']['audio']['channelmode']]);
+ getid3_lib::safe_inc($info['mpeg']['audio']['version_distribution'][$dummy['mpeg']['audio']['version']]);
+ $synchstartoffset += $dummy['mpeg']['audio']['framelength'];
+ }
+ $frames_scanned++;
+ if ($frames_scan_per_segment && (++$frames_scanned_this_segment >= $frames_scan_per_segment)) {
+ $this_pct_scanned = (ftell($this->getid3->fp) - $scan_start_offset[$current_segment]) / ($info['avdataend'] - $info['avdataoffset']);
+ if (($current_segment == 0) && (($this_pct_scanned * $max_scan_segments) >= 1)) {
+ // file likely contains < $max_frames_scan, just scan as one segment
+ $max_scan_segments = 1;
+ $frames_scan_per_segment = $max_frames_scan;
+ } else {
+ $pct_data_scanned += $this_pct_scanned;
+ break;
+ }
+ }
+ }
+ }
+ if ($pct_data_scanned > 0) {
+ $info['warning'][] = 'too many MPEG audio frames to scan, only scanned '.$frames_scanned.' frames in '.$max_scan_segments.' segments ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.';
+ foreach ($info['mpeg']['audio'] as $key1 => $value1) {
+ if (!preg_match('#_distribution$#i', $key1)) {
+ continue;
+ }
+ foreach ($value1 as $key2 => $value2) {
+ $info['mpeg']['audio'][$key1][$key2] = round($value2 / $pct_data_scanned);
+ }
+ }
+ }
+
+ if ($SynchErrorsFound > 0) {
+ $info['warning'][] = 'Found '.$SynchErrorsFound.' synch errors in histogram analysis';
+ //return false;
+ }
+
+ $bittotal = 0;
+ $framecounter = 0;
+ foreach ($info['mpeg']['audio']['bitrate_distribution'] as $bitratevalue => $bitratecount) {
+ $framecounter += $bitratecount;
+ if ($bitratevalue != 'free') {
+ $bittotal += ($bitratevalue * $bitratecount);
+ }
+ }
+ if ($framecounter == 0) {
+ $info['error'][] = 'Corrupt MP3 file: framecounter == zero';
+ return false;
+ }
+ $info['mpeg']['audio']['frame_count'] = getid3_lib::CastAsInt($framecounter);
+ $info['mpeg']['audio']['bitrate'] = ($bittotal / $framecounter);
+
+ $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
+
+
+ // Definitively set VBR vs CBR, even if the Xing/LAME/VBRI header says differently
+ $distinct_bitrates = 0;
+ foreach ($info['mpeg']['audio']['bitrate_distribution'] as $bitrate_value => $bitrate_count) {
+ if ($bitrate_count > 0) {
+ $distinct_bitrates++;
+ }
+ }
+ if ($distinct_bitrates > 1) {
+ $info['mpeg']['audio']['bitrate_mode'] = 'vbr';
+ } else {
+ $info['mpeg']['audio']['bitrate_mode'] = 'cbr';
+ }
+ $info['audio']['bitrate_mode'] = $info['mpeg']['audio']['bitrate_mode'];
+
+ }
+
+ break; // exit while()
+ }
+ }
+
+ $SynchSeekOffset++;
+ if (($avdataoffset + $SynchSeekOffset) >= $info['avdataend']) {
+ // end of file/data
+
+ if (empty($info['mpeg']['audio'])) {
+
+ $info['error'][] = 'could not find valid MPEG synch before end of file';
+ if (isset($info['audio']['bitrate'])) {
+ unset($info['audio']['bitrate']);
+ }
+ if (isset($info['mpeg']['audio'])) {
+ unset($info['mpeg']['audio']);
+ }
+ if (isset($info['mpeg']) && (!is_array($info['mpeg']) || empty($info['mpeg']))) {
+ unset($info['mpeg']);
+ }
+ return false;
+
+ }
+ break;
+ }
+
+ }
+ $info['audio']['channels'] = $info['mpeg']['audio']['channels'];
+ $info['audio']['channelmode'] = $info['mpeg']['audio']['channelmode'];
+ $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
+ return true;
+ }
+
+
+ public static function MPEGaudioVersionArray() {
+ static $MPEGaudioVersion = array('2.5', false, '2', '1');
+ return $MPEGaudioVersion;
+ }
+
+ public static function MPEGaudioLayerArray() {
+ static $MPEGaudioLayer = array(false, 3, 2, 1);
+ return $MPEGaudioLayer;
+ }
+
+ public static function MPEGaudioBitrateArray() {
+ static $MPEGaudioBitrate;
+ if (empty($MPEGaudioBitrate)) {
+ $MPEGaudioBitrate = array (
+ '1' => array (1 => array('free', 32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000),
+ 2 => array('free', 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000),
+ 3 => array('free', 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000)
+ ),
+
+ '2' => array (1 => array('free', 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000, 224000, 256000),
+ 2 => array('free', 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000),
+ )
+ );
+ $MPEGaudioBitrate['2'][3] = $MPEGaudioBitrate['2'][2];
+ $MPEGaudioBitrate['2.5'] = $MPEGaudioBitrate['2'];
+ }
+ return $MPEGaudioBitrate;
+ }
+
+ public static function MPEGaudioFrequencyArray() {
+ static $MPEGaudioFrequency;
+ if (empty($MPEGaudioFrequency)) {
+ $MPEGaudioFrequency = array (
+ '1' => array(44100, 48000, 32000),
+ '2' => array(22050, 24000, 16000),
+ '2.5' => array(11025, 12000, 8000)
+ );
+ }
+ return $MPEGaudioFrequency;
+ }
+
+ public static function MPEGaudioChannelModeArray() {
+ static $MPEGaudioChannelMode = array('stereo', 'joint stereo', 'dual channel', 'mono');
+ return $MPEGaudioChannelMode;
+ }
+
+ public static function MPEGaudioModeExtensionArray() {
+ static $MPEGaudioModeExtension;
+ if (empty($MPEGaudioModeExtension)) {
+ $MPEGaudioModeExtension = array (
+ 1 => array('4-31', '8-31', '12-31', '16-31'),
+ 2 => array('4-31', '8-31', '12-31', '16-31'),
+ 3 => array('', 'IS', 'MS', 'IS+MS')
+ );
+ }
+ return $MPEGaudioModeExtension;
+ }
+
+ public static function MPEGaudioEmphasisArray() {
+ static $MPEGaudioEmphasis = array('none', '50/15ms', false, 'CCIT J.17');
+ return $MPEGaudioEmphasis;
+ }
+
+ public static function MPEGaudioHeaderBytesValid($head4, $allowBitrate15=false) {
+ return self::MPEGaudioHeaderValid(self::MPEGaudioHeaderDecode($head4), false, $allowBitrate15);
+ }
+
+ public static function MPEGaudioHeaderValid($rawarray, $echoerrors=false, $allowBitrate15=false) {
+ if (($rawarray['synch'] & 0x0FFE) != 0x0FFE) {
+ return false;
+ }
+
+ static $MPEGaudioVersionLookup;
+ static $MPEGaudioLayerLookup;
+ static $MPEGaudioBitrateLookup;
+ static $MPEGaudioFrequencyLookup;
+ static $MPEGaudioChannelModeLookup;
+ static $MPEGaudioModeExtensionLookup;
+ static $MPEGaudioEmphasisLookup;
+ if (empty($MPEGaudioVersionLookup)) {
+ $MPEGaudioVersionLookup = self::MPEGaudioVersionArray();
+ $MPEGaudioLayerLookup = self::MPEGaudioLayerArray();
+ $MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray();
+ $MPEGaudioFrequencyLookup = self::MPEGaudioFrequencyArray();
+ $MPEGaudioChannelModeLookup = self::MPEGaudioChannelModeArray();
+ $MPEGaudioModeExtensionLookup = self::MPEGaudioModeExtensionArray();
+ $MPEGaudioEmphasisLookup = self::MPEGaudioEmphasisArray();
+ }
+
+ if (isset($MPEGaudioVersionLookup[$rawarray['version']])) {
+ $decodedVersion = $MPEGaudioVersionLookup[$rawarray['version']];
+ } else {
+ echo ($echoerrors ? "\n".'invalid Version ('.$rawarray['version'].')' : '');
+ return false;
+ }
+ if (isset($MPEGaudioLayerLookup[$rawarray['layer']])) {
+ $decodedLayer = $MPEGaudioLayerLookup[$rawarray['layer']];
+ } else {
+ echo ($echoerrors ? "\n".'invalid Layer ('.$rawarray['layer'].')' : '');
+ return false;
+ }
+ if (!isset($MPEGaudioBitrateLookup[$decodedVersion][$decodedLayer][$rawarray['bitrate']])) {
+ echo ($echoerrors ? "\n".'invalid Bitrate ('.$rawarray['bitrate'].')' : '');
+ if ($rawarray['bitrate'] == 15) {
+ // known issue in LAME 3.90 - 3.93.1 where free-format has bitrate ID of 15 instead of 0
+ // let it go through here otherwise file will not be identified
+ if (!$allowBitrate15) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ if (!isset($MPEGaudioFrequencyLookup[$decodedVersion][$rawarray['sample_rate']])) {
+ echo ($echoerrors ? "\n".'invalid Frequency ('.$rawarray['sample_rate'].')' : '');
+ return false;
+ }
+ if (!isset($MPEGaudioChannelModeLookup[$rawarray['channelmode']])) {
+ echo ($echoerrors ? "\n".'invalid ChannelMode ('.$rawarray['channelmode'].')' : '');
+ return false;
+ }
+ if (!isset($MPEGaudioModeExtensionLookup[$decodedLayer][$rawarray['modeextension']])) {
+ echo ($echoerrors ? "\n".'invalid Mode Extension ('.$rawarray['modeextension'].')' : '');
+ return false;
+ }
+ if (!isset($MPEGaudioEmphasisLookup[$rawarray['emphasis']])) {
+ echo ($echoerrors ? "\n".'invalid Emphasis ('.$rawarray['emphasis'].')' : '');
+ return false;
+ }
+ // These are just either set or not set, you can't mess that up :)
+ // $rawarray['protection'];
+ // $rawarray['padding'];
+ // $rawarray['private'];
+ // $rawarray['copyright'];
+ // $rawarray['original'];
+
+ return true;
+ }
+
+ public static function MPEGaudioHeaderDecode($Header4Bytes) {
+ // AAAA AAAA AAAB BCCD EEEE FFGH IIJJ KLMM
+ // A - Frame sync (all bits set)
+ // B - MPEG Audio version ID
+ // C - Layer description
+ // D - Protection bit
+ // E - Bitrate index
+ // F - Sampling rate frequency index
+ // G - Padding bit
+ // H - Private bit
+ // I - Channel Mode
+ // J - Mode extension (Only if Joint stereo)
+ // K - Copyright
+ // L - Original
+ // M - Emphasis
+
+ if (strlen($Header4Bytes) != 4) {
+ return false;
+ }
+
+ $MPEGrawHeader['synch'] = (getid3_lib::BigEndian2Int(substr($Header4Bytes, 0, 2)) & 0xFFE0) >> 4;
+ $MPEGrawHeader['version'] = (ord($Header4Bytes{1}) & 0x18) >> 3; // BB
+ $MPEGrawHeader['layer'] = (ord($Header4Bytes{1}) & 0x06) >> 1; // CC
+ $MPEGrawHeader['protection'] = (ord($Header4Bytes{1}) & 0x01); // D
+ $MPEGrawHeader['bitrate'] = (ord($Header4Bytes{2}) & 0xF0) >> 4; // EEEE
+ $MPEGrawHeader['sample_rate'] = (ord($Header4Bytes{2}) & 0x0C) >> 2; // FF
+ $MPEGrawHeader['padding'] = (ord($Header4Bytes{2}) & 0x02) >> 1; // G
+ $MPEGrawHeader['private'] = (ord($Header4Bytes{2}) & 0x01); // H
+ $MPEGrawHeader['channelmode'] = (ord($Header4Bytes{3}) & 0xC0) >> 6; // II
+ $MPEGrawHeader['modeextension'] = (ord($Header4Bytes{3}) & 0x30) >> 4; // JJ
+ $MPEGrawHeader['copyright'] = (ord($Header4Bytes{3}) & 0x08) >> 3; // K
+ $MPEGrawHeader['original'] = (ord($Header4Bytes{3}) & 0x04) >> 2; // L
+ $MPEGrawHeader['emphasis'] = (ord($Header4Bytes{3}) & 0x03); // MM
+
+ return $MPEGrawHeader;
+ }
+
+ public static function MPEGaudioFrameLength(&$bitrate, &$version, &$layer, $padding, &$samplerate) {
+ static $AudioFrameLengthCache = array();
+
+ if (!isset($AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate])) {
+ $AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate] = false;
+ if ($bitrate != 'free') {
+
+ if ($version == '1') {
+
+ if ($layer == '1') {
+
+ // For Layer I slot is 32 bits long
+ $FrameLengthCoefficient = 48;
+ $SlotLength = 4;
+
+ } else { // Layer 2 / 3
+
+ // for Layer 2 and Layer 3 slot is 8 bits long.
+ $FrameLengthCoefficient = 144;
+ $SlotLength = 1;
+
+ }
+
+ } else { // MPEG-2 / MPEG-2.5
+
+ if ($layer == '1') {
+
+ // For Layer I slot is 32 bits long
+ $FrameLengthCoefficient = 24;
+ $SlotLength = 4;
+
+ } elseif ($layer == '2') {
+
+ // for Layer 2 and Layer 3 slot is 8 bits long.
+ $FrameLengthCoefficient = 144;
+ $SlotLength = 1;
+
+ } else { // layer 3
+
+ // for Layer 2 and Layer 3 slot is 8 bits long.
+ $FrameLengthCoefficient = 72;
+ $SlotLength = 1;
+
+ }
+
+ }
+
+ // FrameLengthInBytes = ((Coefficient * BitRate) / SampleRate) + Padding
+ if ($samplerate > 0) {
+ $NewFramelength = ($FrameLengthCoefficient * $bitrate) / $samplerate;
+ $NewFramelength = floor($NewFramelength / $SlotLength) * $SlotLength; // round to next-lower multiple of SlotLength (1 byte for Layer 2/3, 4 bytes for Layer I)
+ if ($padding) {
+ $NewFramelength += $SlotLength;
+ }
+ $AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate] = (int) $NewFramelength;
+ }
+ }
+ }
+ return $AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate];
+ }
+
+ public static function ClosestStandardMP3Bitrate($bit_rate) {
+ static $standard_bit_rates = array (320000, 256000, 224000, 192000, 160000, 128000, 112000, 96000, 80000, 64000, 56000, 48000, 40000, 32000, 24000, 16000, 8000);
+ static $bit_rate_table = array (0=>'-');
+ $round_bit_rate = intval(round($bit_rate, -3));
+ if (!isset($bit_rate_table[$round_bit_rate])) {
+ if ($round_bit_rate > max($standard_bit_rates)) {
+ $bit_rate_table[$round_bit_rate] = round($bit_rate, 2 - strlen($bit_rate));
+ } else {
+ $bit_rate_table[$round_bit_rate] = max($standard_bit_rates);
+ foreach ($standard_bit_rates as $standard_bit_rate) {
+ if ($round_bit_rate >= $standard_bit_rate + (($bit_rate_table[$round_bit_rate] - $standard_bit_rate) / 2)) {
+ break;
+ }
+ $bit_rate_table[$round_bit_rate] = $standard_bit_rate;
+ }
+ }
+ }
+ return $bit_rate_table[$round_bit_rate];
+ }
+
+ public static function XingVBRidOffset($version, $channelmode) {
+ static $XingVBRidOffsetCache = array();
+ if (empty($XingVBRidOffset)) {
+ $XingVBRidOffset = array (
+ '1' => array ('mono' => 0x15, // 4 + 17 = 21
+ 'stereo' => 0x24, // 4 + 32 = 36
+ 'joint stereo' => 0x24,
+ 'dual channel' => 0x24
+ ),
+
+ '2' => array ('mono' => 0x0D, // 4 + 9 = 13
+ 'stereo' => 0x15, // 4 + 17 = 21
+ 'joint stereo' => 0x15,
+ 'dual channel' => 0x15
+ ),
+
+ '2.5' => array ('mono' => 0x15,
+ 'stereo' => 0x15,
+ 'joint stereo' => 0x15,
+ 'dual channel' => 0x15
+ )
+ );
+ }
+ return $XingVBRidOffset[$version][$channelmode];
+ }
+
+ public static function LAMEvbrMethodLookup($VBRmethodID) {
+ static $LAMEvbrMethodLookup = array(
+ 0x00 => 'unknown',
+ 0x01 => 'cbr',
+ 0x02 => 'abr',
+ 0x03 => 'vbr-old / vbr-rh',
+ 0x04 => 'vbr-new / vbr-mtrh',
+ 0x05 => 'vbr-mt',
+ 0x06 => 'vbr (full vbr method 4)',
+ 0x08 => 'cbr (constant bitrate 2 pass)',
+ 0x09 => 'abr (2 pass)',
+ 0x0F => 'reserved'
+ );
+ return (isset($LAMEvbrMethodLookup[$VBRmethodID]) ? $LAMEvbrMethodLookup[$VBRmethodID] : '');
+ }
+
+ public static function LAMEmiscStereoModeLookup($StereoModeID) {
+ static $LAMEmiscStereoModeLookup = array(
+ 0 => 'mono',
+ 1 => 'stereo',
+ 2 => 'dual mono',
+ 3 => 'joint stereo',
+ 4 => 'forced stereo',
+ 5 => 'auto',
+ 6 => 'intensity stereo',
+ 7 => 'other'
+ );
+ return (isset($LAMEmiscStereoModeLookup[$StereoModeID]) ? $LAMEmiscStereoModeLookup[$StereoModeID] : '');
+ }
+
+ public static function LAMEmiscSourceSampleFrequencyLookup($SourceSampleFrequencyID) {
+ static $LAMEmiscSourceSampleFrequencyLookup = array(
+ 0 => '<= 32 kHz',
+ 1 => '44.1 kHz',
+ 2 => '48 kHz',
+ 3 => '> 48kHz'
+ );
+ return (isset($LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID]) ? $LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID] : '');
+ }
+
+ public static function LAMEsurroundInfoLookup($SurroundInfoID) {
+ static $LAMEsurroundInfoLookup = array(
+ 0 => 'no surround info',
+ 1 => 'DPL encoding',
+ 2 => 'DPL2 encoding',
+ 3 => 'Ambisonic encoding'
+ );
+ return (isset($LAMEsurroundInfoLookup[$SurroundInfoID]) ? $LAMEsurroundInfoLookup[$SurroundInfoID] : 'reserved');
+ }
+
+ public static function LAMEpresetUsedLookup($LAMEtag) {
+
+ if ($LAMEtag['preset_used_id'] == 0) {
+ // no preset used (LAME >=3.93)
+ // no preset recorded (LAME <3.93)
+ return '';
+ }
+ $LAMEpresetUsedLookup = array();
+
+ ///// THIS PART CANNOT BE STATIC .
+ for ($i = 8; $i <= 320; $i++) {
+ switch ($LAMEtag['vbr_method']) {
+ case 'cbr':
+ $LAMEpresetUsedLookup[$i] = '--alt-preset '.$LAMEtag['vbr_method'].' '.$i;
+ break;
+ case 'abr':
+ default: // other VBR modes shouldn't be here(?)
+ $LAMEpresetUsedLookup[$i] = '--alt-preset '.$i;
+ break;
+ }
+ }
+
+ // named old-style presets (studio, phone, voice, etc) are handled in GuessEncoderOptions()
+
+ // named alt-presets
+ $LAMEpresetUsedLookup[1000] = '--r3mix';
+ $LAMEpresetUsedLookup[1001] = '--alt-preset standard';
+ $LAMEpresetUsedLookup[1002] = '--alt-preset extreme';
+ $LAMEpresetUsedLookup[1003] = '--alt-preset insane';
+ $LAMEpresetUsedLookup[1004] = '--alt-preset fast standard';
+ $LAMEpresetUsedLookup[1005] = '--alt-preset fast extreme';
+ $LAMEpresetUsedLookup[1006] = '--alt-preset medium';
+ $LAMEpresetUsedLookup[1007] = '--alt-preset fast medium';
+
+ // LAME 3.94 additions/changes
+ $LAMEpresetUsedLookup[1010] = '--preset portable'; // 3.94a15 Oct 21 2003
+ $LAMEpresetUsedLookup[1015] = '--preset radio'; // 3.94a15 Oct 21 2003
+
+ $LAMEpresetUsedLookup[320] = '--preset insane'; // 3.94a15 Nov 12 2003
+ $LAMEpresetUsedLookup[410] = '-V9';
+ $LAMEpresetUsedLookup[420] = '-V8';
+ $LAMEpresetUsedLookup[440] = '-V6';
+ $LAMEpresetUsedLookup[430] = '--preset radio'; // 3.94a15 Nov 12 2003
+ $LAMEpresetUsedLookup[450] = '--preset '.(($LAMEtag['raw']['vbr_method'] == 4) ? 'fast ' : '').'portable'; // 3.94a15 Nov 12 2003
+ $LAMEpresetUsedLookup[460] = '--preset '.(($LAMEtag['raw']['vbr_method'] == 4) ? 'fast ' : '').'medium'; // 3.94a15 Nov 12 2003
+ $LAMEpresetUsedLookup[470] = '--r3mix'; // 3.94b1 Dec 18 2003
+ $LAMEpresetUsedLookup[480] = '--preset '.(($LAMEtag['raw']['vbr_method'] == 4) ? 'fast ' : '').'standard'; // 3.94a15 Nov 12 2003
+ $LAMEpresetUsedLookup[490] = '-V1';
+ $LAMEpresetUsedLookup[500] = '--preset '.(($LAMEtag['raw']['vbr_method'] == 4) ? 'fast ' : '').'extreme'; // 3.94a15 Nov 12 2003
+
+ return (isset($LAMEpresetUsedLookup[$LAMEtag['preset_used_id']]) ? $LAMEpresetUsedLookup[$LAMEtag['preset_used_id']] : 'new/unknown preset: '.$LAMEtag['preset_used_id'].' - report to info@getid3.org');
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/libs/getid3/module.audio.ogg.php b/extensions/TimedMediaHandler/libs/getid3/module.audio.ogg.php
new file mode 100644
index 00000000..a2a35aad
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/module.audio.ogg.php
@@ -0,0 +1,671 @@
+<?php
+/////////////////////////////////////////////////////////////////
+/// getID3() by James Heinrich <info@getid3.org> //
+// available at http://getid3.sourceforge.net //
+// or http://www.getid3.org //
+/////////////////////////////////////////////////////////////////
+// See readme.txt for more details //
+/////////////////////////////////////////////////////////////////
+// //
+// module.audio.ogg.php //
+// module for analyzing Ogg Vorbis, OggFLAC and Speex files //
+// dependencies: module.audio.flac.php //
+// ///
+/////////////////////////////////////////////////////////////////
+
+getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.flac.php', __FILE__, true);
+
+class getid3_ogg extends getid3_handler
+{
+ // http://xiph.org/vorbis/doc/Vorbis_I_spec.html
+ public function Analyze() {
+ $info = &$this->getid3->info;
+
+ $info['fileformat'] = 'ogg';
+
+ // Warn about illegal tags - only vorbiscomments are allowed
+ if (isset($info['id3v2'])) {
+ $info['warning'][] = 'Illegal ID3v2 tag present.';
+ }
+ if (isset($info['id3v1'])) {
+ $info['warning'][] = 'Illegal ID3v1 tag present.';
+ }
+ if (isset($info['ape'])) {
+ $info['warning'][] = 'Illegal APE tag present.';
+ }
+
+
+ // Page 1 - Stream Header
+
+ $this->fseek($info['avdataoffset']);
+
+ $oggpageinfo = $this->ParseOggPageHeader();
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
+
+ if ($this->ftell() >= $this->getid3->fread_buffer_size()) {
+ $info['error'][] = 'Could not find start of Ogg page in the first '.$this->getid3->fread_buffer_size().' bytes (this might not be an Ogg-Vorbis file?)';
+ unset($info['fileformat']);
+ unset($info['ogg']);
+ return false;
+ }
+
+ $filedata = $this->fread($oggpageinfo['page_length']);
+ $filedataoffset = 0;
+
+ if (substr($filedata, 0, 4) == 'fLaC') {
+
+ $info['audio']['dataformat'] = 'flac';
+ $info['audio']['bitrate_mode'] = 'vbr';
+ $info['audio']['lossless'] = true;
+
+ } elseif (substr($filedata, 1, 6) == 'vorbis') {
+
+ $this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo);
+
+ } elseif (substr($filedata, 0, 8) == 'Speex ') {
+
+ // http://www.speex.org/manual/node10.html
+
+ $info['audio']['dataformat'] = 'speex';
+ $info['mime_type'] = 'audio/speex';
+ $info['audio']['bitrate_mode'] = 'abr';
+ $info['audio']['lossless'] = false;
+
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_string'] = substr($filedata, $filedataoffset, 8); // hard-coded to 'Speex '
+ $filedataoffset += 8;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version'] = substr($filedata, $filedataoffset, 20);
+ $filedataoffset += 20;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version_id'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['header_size'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode_bitstream_version'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['nb_channels'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['bitrate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['framesize'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['vbr'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['frames_per_packet'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['extra_headers'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['reserved1'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['reserved2'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+
+ $info['speex']['speex_version'] = trim($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version']);
+ $info['speex']['sample_rate'] = $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['rate'];
+ $info['speex']['channels'] = $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['nb_channels'];
+ $info['speex']['vbr'] = (bool) $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['vbr'];
+ $info['speex']['band_type'] = $this->SpeexBandModeLookup($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode']);
+
+ $info['audio']['sample_rate'] = $info['speex']['sample_rate'];
+ $info['audio']['channels'] = $info['speex']['channels'];
+ if ($info['speex']['vbr']) {
+ $info['audio']['bitrate_mode'] = 'vbr';
+ }
+
+
+ } elseif (substr($filedata, 0, 8) == "fishead\x00") {
+
+ // Ogg Skeleton version 3.0 Format Specification
+ // http://xiph.org/ogg/doc/skeleton.html
+ $filedataoffset += 8;
+ $info['ogg']['skeleton']['fishead']['raw']['version_major'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
+ $filedataoffset += 2;
+ $info['ogg']['skeleton']['fishead']['raw']['version_minor'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
+ $filedataoffset += 2;
+ $info['ogg']['skeleton']['fishead']['raw']['presentationtime_numerator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
+ $filedataoffset += 8;
+ $info['ogg']['skeleton']['fishead']['raw']['presentationtime_denominator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
+ $filedataoffset += 8;
+ $info['ogg']['skeleton']['fishead']['raw']['basetime_numerator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
+ $filedataoffset += 8;
+ $info['ogg']['skeleton']['fishead']['raw']['basetime_denominator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
+ $filedataoffset += 8;
+ $info['ogg']['skeleton']['fishead']['raw']['utc'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 20));
+ $filedataoffset += 20;
+
+ $info['ogg']['skeleton']['fishead']['version'] = $info['ogg']['skeleton']['fishead']['raw']['version_major'].'.'.$info['ogg']['skeleton']['fishead']['raw']['version_minor'];
+ $info['ogg']['skeleton']['fishead']['presentationtime'] = $info['ogg']['skeleton']['fishead']['raw']['presentationtime_numerator'] / $info['ogg']['skeleton']['fishead']['raw']['presentationtime_denominator'];
+ $info['ogg']['skeleton']['fishead']['basetime'] = $info['ogg']['skeleton']['fishead']['raw']['basetime_numerator'] / $info['ogg']['skeleton']['fishead']['raw']['basetime_denominator'];
+ $info['ogg']['skeleton']['fishead']['utc'] = $info['ogg']['skeleton']['fishead']['raw']['utc'];
+
+
+ $counter = 0;
+ do {
+ $oggpageinfo = $this->ParseOggPageHeader();
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno'].'.'.$counter++] = $oggpageinfo;
+ $filedata = $this->fread($oggpageinfo['page_length']);
+ $this->fseek($oggpageinfo['page_end_offset']);
+
+ if (substr($filedata, 0, 8) == "fisbone\x00") {
+
+ $filedataoffset = 8;
+ $info['ogg']['skeleton']['fisbone']['raw']['message_header_offset'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['skeleton']['fisbone']['raw']['serial_number'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['skeleton']['fisbone']['raw']['number_header_packets'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['skeleton']['fisbone']['raw']['granulerate_numerator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
+ $filedataoffset += 8;
+ $info['ogg']['skeleton']['fisbone']['raw']['granulerate_denominator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
+ $filedataoffset += 8;
+ $info['ogg']['skeleton']['fisbone']['raw']['basegranule'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
+ $filedataoffset += 8;
+ $info['ogg']['skeleton']['fisbone']['raw']['preroll'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['skeleton']['fisbone']['raw']['granuleshift'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
+ $filedataoffset += 1;
+ $info['ogg']['skeleton']['fisbone']['raw']['padding'] = substr($filedata, $filedataoffset, 3);
+ $filedataoffset += 3;
+
+ } elseif (substr($filedata, 1, 6) == 'theora') {
+
+ $info['video']['dataformat'] = 'theora';
+ $info['error'][] = 'Ogg Theora not correctly handled in this version of getID3 ['.$this->getid3->version().']';
+ //break;
+
+ } elseif (substr($filedata, 1, 6) == 'vorbis') {
+
+ $this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo);
+
+ } else {
+ $info['error'][] = 'unexpected';
+ //break;
+ }
+ //} while ($oggpageinfo['page_seqno'] == 0);
+ } while (($oggpageinfo['page_seqno'] == 0) && (substr($filedata, 0, 8) != "fisbone\x00"));
+
+ $this->fseek($oggpageinfo['page_start_offset']);
+
+ $info['error'][] = 'Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']';
+ //return false;
+
+ } else {
+
+ $info['error'][] = 'Expecting either "Speex " or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"';
+ unset($info['ogg']);
+ unset($info['mime_type']);
+ return false;
+
+ }
+
+ // Page 2 - Comment Header
+ $oggpageinfo = $this->ParseOggPageHeader();
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
+
+ switch ($info['audio']['dataformat']) {
+ case 'vorbis':
+ $filedata = $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['packet_type'] = getid3_lib::LittleEndian2Int(substr($filedata, 0, 1));
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, 1, 6); // hard-coded to 'vorbis'
+
+ $this->ParseVorbisComments();
+ break;
+
+ case 'flac':
+ $flac = new getid3_flac($this->getid3);
+ if (!$flac->parseMETAdata()) {
+ $info['error'][] = 'Failed to parse FLAC headers';
+ return false;
+ }
+ unset($flac);
+ break;
+
+ case 'speex':
+ $this->fseek($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length'], SEEK_CUR);
+ $this->ParseVorbisComments();
+ break;
+ }
+
+
+ // Last Page - Number of Samples
+ if (!getid3_lib::intValueSupported($info['avdataend'])) {
+
+ $info['warning'][] = 'Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)';
+
+ } else {
+
+ $this->fseek(max($info['avdataend'] - $this->getid3->fread_buffer_size(), 0));
+ $LastChunkOfOgg = strrev($this->fread($this->getid3->fread_buffer_size()));
+ if ($LastOggSpostion = strpos($LastChunkOfOgg, 'SggO')) {
+ $this->fseek($info['avdataend'] - ($LastOggSpostion + strlen('SggO')));
+ $info['avdataend'] = $this->ftell();
+ $info['ogg']['pageheader']['eos'] = $this->ParseOggPageHeader();
+ $info['ogg']['samples'] = $info['ogg']['pageheader']['eos']['pcm_abs_position'];
+ if ($info['ogg']['samples'] == 0) {
+ $info['error'][] = 'Corrupt Ogg file: eos.number of samples == zero';
+ return false;
+ }
+ if (!empty($info['audio']['sample_rate'])) {
+ $info['ogg']['bitrate_average'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / ($info['ogg']['samples'] / $info['audio']['sample_rate']);
+ }
+ }
+
+ }
+
+ if (!empty($info['ogg']['bitrate_average'])) {
+ $info['audio']['bitrate'] = $info['ogg']['bitrate_average'];
+ } elseif (!empty($info['ogg']['bitrate_nominal'])) {
+ $info['audio']['bitrate'] = $info['ogg']['bitrate_nominal'];
+ } elseif (!empty($info['ogg']['bitrate_min']) && !empty($info['ogg']['bitrate_max'])) {
+ $info['audio']['bitrate'] = ($info['ogg']['bitrate_min'] + $info['ogg']['bitrate_max']) / 2;
+ }
+ if (isset($info['audio']['bitrate']) && !isset($info['playtime_seconds'])) {
+ if ($info['audio']['bitrate'] == 0) {
+ $info['error'][] = 'Corrupt Ogg file: bitrate_audio == zero';
+ return false;
+ }
+ $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $info['audio']['bitrate']);
+ }
+
+ if (isset($info['ogg']['vendor'])) {
+ $info['audio']['encoder'] = preg_replace('/^Encoded with /', '', $info['ogg']['vendor']);
+
+ // Vorbis only
+ if ($info['audio']['dataformat'] == 'vorbis') {
+
+ // Vorbis 1.0 starts with Xiph.Org
+ if (preg_match('/^Xiph.Org/', $info['audio']['encoder'])) {
+
+ if ($info['audio']['bitrate_mode'] == 'abr') {
+
+ // Set -b 128 on abr files
+ $info['audio']['encoder_options'] = '-b '.round($info['ogg']['bitrate_nominal'] / 1000);
+
+ } elseif (($info['audio']['bitrate_mode'] == 'vbr') && ($info['audio']['channels'] == 2) && ($info['audio']['sample_rate'] >= 44100) && ($info['audio']['sample_rate'] <= 48000)) {
+ // Set -q N on vbr files
+ $info['audio']['encoder_options'] = '-q '.$this->get_quality_from_nominal_bitrate($info['ogg']['bitrate_nominal']);
+
+ }
+ }
+
+ if (empty($info['audio']['encoder_options']) && !empty($info['ogg']['bitrate_nominal'])) {
+ $info['audio']['encoder_options'] = 'Nominal bitrate: '.intval(round($info['ogg']['bitrate_nominal'] / 1000)).'kbps';
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public function ParseVorbisPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) {
+ $info = &$this->getid3->info;
+ $info['audio']['dataformat'] = 'vorbis';
+ $info['audio']['lossless'] = false;
+
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['packet_type'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
+ $filedataoffset += 1;
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, $filedataoffset, 6); // hard-coded to 'vorbis'
+ $filedataoffset += 6;
+ $info['ogg']['bitstreamversion'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['numberofchannels'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
+ $filedataoffset += 1;
+ $info['audio']['channels'] = $info['ogg']['numberofchannels'];
+ $info['ogg']['samplerate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ if ($info['ogg']['samplerate'] == 0) {
+ $info['error'][] = 'Corrupt Ogg file: sample rate == zero';
+ return false;
+ }
+ $info['audio']['sample_rate'] = $info['ogg']['samplerate'];
+ $info['ogg']['samples'] = 0; // filled in later
+ $info['ogg']['bitrate_average'] = 0; // filled in later
+ $info['ogg']['bitrate_max'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['bitrate_nominal'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['bitrate_min'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $info['ogg']['blocksize_small'] = pow(2, getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)) & 0x0F);
+ $info['ogg']['blocksize_large'] = pow(2, (getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)) & 0xF0) >> 4);
+ $info['ogg']['stop_bit'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)); // must be 1, marks end of packet
+
+ $info['audio']['bitrate_mode'] = 'vbr'; // overridden if actually abr
+ if ($info['ogg']['bitrate_max'] == 0xFFFFFFFF) {
+ unset($info['ogg']['bitrate_max']);
+ $info['audio']['bitrate_mode'] = 'abr';
+ }
+ if ($info['ogg']['bitrate_nominal'] == 0xFFFFFFFF) {
+ unset($info['ogg']['bitrate_nominal']);
+ }
+ if ($info['ogg']['bitrate_min'] == 0xFFFFFFFF) {
+ unset($info['ogg']['bitrate_min']);
+ $info['audio']['bitrate_mode'] = 'abr';
+ }
+ return true;
+ }
+
+ public function ParseOggPageHeader() {
+ // http://xiph.org/ogg/vorbis/doc/framing.html
+ $oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file
+
+ $filedata = $this->fread($this->getid3->fread_buffer_size());
+ $filedataoffset = 0;
+ while ((substr($filedata, $filedataoffset++, 4) != 'OggS')) {
+ if (($this->ftell() - $oggheader['page_start_offset']) >= $this->getid3->fread_buffer_size()) {
+ // should be found before here
+ return false;
+ }
+ if ((($filedataoffset + 28) > strlen($filedata)) || (strlen($filedata) < 28)) {
+ if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) === false)) {
+ // get some more data, unless eof, in which case fail
+ return false;
+ }
+ }
+ }
+ $filedataoffset += strlen('OggS') - 1; // page, delimited by 'OggS'
+
+ $oggheader['stream_structver'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
+ $filedataoffset += 1;
+ $oggheader['flags_raw'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
+ $filedataoffset += 1;
+ $oggheader['flags']['fresh'] = (bool) ($oggheader['flags_raw'] & 0x01); // fresh packet
+ $oggheader['flags']['bos'] = (bool) ($oggheader['flags_raw'] & 0x02); // first page of logical bitstream (bos)
+ $oggheader['flags']['eos'] = (bool) ($oggheader['flags_raw'] & 0x04); // last page of logical bitstream (eos)
+
+ $oggheader['pcm_abs_position'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
+ $filedataoffset += 8;
+ $oggheader['stream_serialno'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $oggheader['page_seqno'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $oggheader['page_checksum'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
+ $filedataoffset += 4;
+ $oggheader['page_segments'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
+ $filedataoffset += 1;
+ $oggheader['page_length'] = 0;
+ for ($i = 0; $i < $oggheader['page_segments']; $i++) {
+ $oggheader['segment_table'][$i] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
+ $filedataoffset += 1;
+ $oggheader['page_length'] += $oggheader['segment_table'][$i];
+ }
+ $oggheader['header_end_offset'] = $oggheader['page_start_offset'] + $filedataoffset;
+ $oggheader['page_end_offset'] = $oggheader['header_end_offset'] + $oggheader['page_length'];
+ $this->fseek($oggheader['header_end_offset']);
+
+ return $oggheader;
+ }
+
+ // http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810005
+ public function ParseVorbisComments() {
+ $info = &$this->getid3->info;
+
+ $OriginalOffset = $this->ftell();
+ $commentdataoffset = 0;
+ $VorbisCommentPage = 1;
+
+ switch ($info['audio']['dataformat']) {
+ case 'vorbis':
+ case 'speex':
+ $CommentStartOffset = $info['ogg']['pageheader'][$VorbisCommentPage]['page_start_offset']; // Second Ogg page, after header block
+ $this->fseek($CommentStartOffset);
+ $commentdataoffset = 27 + $info['ogg']['pageheader'][$VorbisCommentPage]['page_segments'];
+ $commentdata = $this->fread(self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1) + $commentdataoffset);
+
+ if ($info['audio']['dataformat'] == 'vorbis') {
+ $commentdataoffset += (strlen('vorbis') + 1);
+ }
+ break;
+
+ case 'flac':
+ $CommentStartOffset = $info['flac']['VORBIS_COMMENT']['raw']['offset'] + 4;
+ $this->fseek($CommentStartOffset);
+ $commentdata = $this->fread($info['flac']['VORBIS_COMMENT']['raw']['block_length']);
+ break;
+
+ default:
+ return false;
+ }
+
+ $VendorSize = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
+ $commentdataoffset += 4;
+
+ $info['ogg']['vendor'] = substr($commentdata, $commentdataoffset, $VendorSize);
+ $commentdataoffset += $VendorSize;
+
+ $CommentsCount = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
+ $commentdataoffset += 4;
+ $info['avdataoffset'] = $CommentStartOffset + $commentdataoffset;
+
+ $basicfields = array('TITLE', 'ARTIST', 'ALBUM', 'TRACKNUMBER', 'GENRE', 'DATE', 'DESCRIPTION', 'COMMENT');
+ $ThisFileInfo_ogg_comments_raw = &$info['ogg']['comments_raw'];
+ for ($i = 0; $i < $CommentsCount; $i++) {
+
+ $ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] = $CommentStartOffset + $commentdataoffset;
+
+ if ($this->ftell() < ($ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] + 4)) {
+ if ($oggpageinfo = $this->ParseOggPageHeader()) {
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
+
+ $VorbisCommentPage++;
+
+ // First, save what we haven't read yet
+ $AsYetUnusedData = substr($commentdata, $commentdataoffset);
+
+ // Then take that data off the end
+ $commentdata = substr($commentdata, 0, $commentdataoffset);
+
+ // Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct
+ $commentdata .= str_repeat("\x00", 27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);
+ $commentdataoffset += (27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);
+
+ // Finally, stick the unused data back on the end
+ $commentdata .= $AsYetUnusedData;
+
+ //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
+ $commentdata .= $this->fread($this->OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1));
+ }
+
+ }
+ $ThisFileInfo_ogg_comments_raw[$i]['size'] = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
+
+ // replace avdataoffset with position just after the last vorbiscomment
+ $info['avdataoffset'] = $ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] + $ThisFileInfo_ogg_comments_raw[$i]['size'] + 4;
+
+ $commentdataoffset += 4;
+ while ((strlen($commentdata) - $commentdataoffset) < $ThisFileInfo_ogg_comments_raw[$i]['size']) {
+ if (($ThisFileInfo_ogg_comments_raw[$i]['size'] > $info['avdataend']) || ($ThisFileInfo_ogg_comments_raw[$i]['size'] < 0)) {
+ $info['warning'][] = 'Invalid Ogg comment size (comment #'.$i.', claims to be '.number_format($ThisFileInfo_ogg_comments_raw[$i]['size']).' bytes) - aborting reading comments';
+ break 2;
+ }
+
+ $VorbisCommentPage++;
+
+ $oggpageinfo = $this->ParseOggPageHeader();
+ $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
+
+ // First, save what we haven't read yet
+ $AsYetUnusedData = substr($commentdata, $commentdataoffset);
+
+ // Then take that data off the end
+ $commentdata = substr($commentdata, 0, $commentdataoffset);
+
+ // Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct
+ $commentdata .= str_repeat("\x00", 27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);
+ $commentdataoffset += (27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);
+
+ // Finally, stick the unused data back on the end
+ $commentdata .= $AsYetUnusedData;
+
+ //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
+ if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) {
+ $info['warning'][] = 'undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell();
+ break;
+ }
+ $readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1);
+ if ($readlength <= 0) {
+ $info['warning'][] = 'invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell();
+ break;
+ }
+ $commentdata .= $this->fread($readlength);
+
+ //$filebaseoffset += $oggpageinfo['header_end_offset'] - $oggpageinfo['page_start_offset'];
+ }
+ $ThisFileInfo_ogg_comments_raw[$i]['offset'] = $commentdataoffset;
+ $commentstring = substr($commentdata, $commentdataoffset, $ThisFileInfo_ogg_comments_raw[$i]['size']);
+ $commentdataoffset += $ThisFileInfo_ogg_comments_raw[$i]['size'];
+
+ if (!$commentstring) {
+
+ // no comment?
+ $info['warning'][] = 'Blank Ogg comment ['.$i.']';
+
+ } elseif (strstr($commentstring, '=')) {
+
+ $commentexploded = explode('=', $commentstring, 2);
+ $ThisFileInfo_ogg_comments_raw[$i]['key'] = strtoupper($commentexploded[0]);
+ $ThisFileInfo_ogg_comments_raw[$i]['value'] = (isset($commentexploded[1]) ? $commentexploded[1] : '');
+
+ if ($ThisFileInfo_ogg_comments_raw[$i]['key'] == 'METADATA_BLOCK_PICTURE') {
+
+ // http://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE
+ // The unencoded format is that of the FLAC picture block. The fields are stored in big endian order as in FLAC, picture data is stored according to the relevant standard.
+ // http://flac.sourceforge.net/format.html#metadata_block_picture
+ $flac = new getid3_flac($this->getid3);
+ $flac->setStringMode(base64_decode($ThisFileInfo_ogg_comments_raw[$i]['value']));
+ $flac->parsePICTURE();
+ $info['ogg']['comments']['picture'][] = $flac->getid3->info['flac']['PICTURE'][0];
+ unset($flac);
+
+ } elseif ($ThisFileInfo_ogg_comments_raw[$i]['key'] == 'COVERART') {
+
+ $data = base64_decode($ThisFileInfo_ogg_comments_raw[$i]['value']);
+ $this->notice('Found deprecated COVERART tag, it should be replaced in honor of METADATA_BLOCK_PICTURE structure');
+ /** @todo use 'coverartmime' where available */
+ $imageinfo = getid3_lib::GetDataImageSize($data);
+ if ($imageinfo === false || !isset($imageinfo['mime'])) {
+ $this->warning('COVERART vorbiscomment tag contains invalid image');
+ continue;
+ }
+
+ $ogg = new self($this->getid3);
+ $ogg->setStringMode($data);
+ $info['ogg']['comments']['picture'][] = array(
+ 'image_mime' => $imageinfo['mime'],
+ 'data' => $ogg->saveAttachment('coverart', 0, strlen($data), $imageinfo['mime']),
+ );
+ unset($ogg);
+
+ } else {
+
+ $info['ogg']['comments'][strtolower($ThisFileInfo_ogg_comments_raw[$i]['key'])][] = $ThisFileInfo_ogg_comments_raw[$i]['value'];
+
+ }
+
+ } else {
+
+ $info['warning'][] = '[known problem with CDex >= v1.40, < v1.50b7] Invalid Ogg comment name/value pair ['.$i.']: '.$commentstring;
+
+ }
+ unset($ThisFileInfo_ogg_comments_raw[$i]);
+ }
+ unset($ThisFileInfo_ogg_comments_raw);
+
+
+ // Replay Gain Adjustment
+ // http://privatewww.essex.ac.uk/~djmrob/replaygain/
+ if (isset($info['ogg']['comments']) && is_array($info['ogg']['comments'])) {
+ foreach ($info['ogg']['comments'] as $index => $commentvalue) {
+ switch ($index) {
+ case 'rg_audiophile':
+ case 'replaygain_album_gain':
+ $info['replay_gain']['album']['adjustment'] = (double) $commentvalue[0];
+ unset($info['ogg']['comments'][$index]);
+ break;
+
+ case 'rg_radio':
+ case 'replaygain_track_gain':
+ $info['replay_gain']['track']['adjustment'] = (double) $commentvalue[0];
+ unset($info['ogg']['comments'][$index]);
+ break;
+
+ case 'replaygain_album_peak':
+ $info['replay_gain']['album']['peak'] = (double) $commentvalue[0];
+ unset($info['ogg']['comments'][$index]);
+ break;
+
+ case 'rg_peak':
+ case 'replaygain_track_peak':
+ $info['replay_gain']['track']['peak'] = (double) $commentvalue[0];
+ unset($info['ogg']['comments'][$index]);
+ break;
+
+ case 'replaygain_reference_loudness':
+ $info['replay_gain']['reference_volume'] = (double) $commentvalue[0];
+ unset($info['ogg']['comments'][$index]);
+ break;
+
+ default:
+ // do nothing
+ break;
+ }
+ }
+ }
+
+ $this->fseek($OriginalOffset);
+
+ return true;
+ }
+
+ public static function SpeexBandModeLookup($mode) {
+ static $SpeexBandModeLookup = array();
+ if (empty($SpeexBandModeLookup)) {
+ $SpeexBandModeLookup[0] = 'narrow';
+ $SpeexBandModeLookup[1] = 'wide';
+ $SpeexBandModeLookup[2] = 'ultra-wide';
+ }
+ return (isset($SpeexBandModeLookup[$mode]) ? $SpeexBandModeLookup[$mode] : null);
+ }
+
+
+ public static function OggPageSegmentLength($OggInfoArray, $SegmentNumber=1) {
+ for ($i = 0; $i < $SegmentNumber; $i++) {
+ $segmentlength = 0;
+ foreach ($OggInfoArray['segment_table'] as $key => $value) {
+ $segmentlength += $value;
+ if ($value < 255) {
+ break;
+ }
+ }
+ }
+ return $segmentlength;
+ }
+
+
+ public static function get_quality_from_nominal_bitrate($nominal_bitrate) {
+
+ // decrease precision
+ $nominal_bitrate = $nominal_bitrate / 1000;
+
+ if ($nominal_bitrate < 128) {
+ // q-1 to q4
+ $qval = ($nominal_bitrate - 64) / 16;
+ } elseif ($nominal_bitrate < 256) {
+ // q4 to q8
+ $qval = $nominal_bitrate / 32;
+ } elseif ($nominal_bitrate < 320) {
+ // q8 to q9
+ $qval = ($nominal_bitrate + 256) / 64;
+ } else {
+ // q9 to q10
+ $qval = ($nominal_bitrate + 1300) / 180;
+ }
+ //return $qval; // 5.031324
+ //return intval($qval); // 5
+ return round($qval, 1); // 5 or 4.9
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/libs/getid3/module.tag.id3v1.php b/extensions/TimedMediaHandler/libs/getid3/module.tag.id3v1.php
new file mode 100644
index 00000000..fd9069e0
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/module.tag.id3v1.php
@@ -0,0 +1,359 @@
+<?php
+/////////////////////////////////////////////////////////////////
+/// getID3() by James Heinrich <info@getid3.org> //
+// available at http://getid3.sourceforge.net //
+// or http://www.getid3.org //
+/////////////////////////////////////////////////////////////////
+// See readme.txt for more details //
+/////////////////////////////////////////////////////////////////
+// //
+// module.tag.id3v1.php //
+// module for analyzing ID3v1 tags //
+// dependencies: NONE //
+// ///
+/////////////////////////////////////////////////////////////////
+
+
+class getid3_id3v1 extends getid3_handler
+{
+
+ public function Analyze() {
+ $info = &$this->getid3->info;
+
+ if (!getid3_lib::intValueSupported($info['filesize'])) {
+ $info['warning'][] = 'Unable to check for ID3v1 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
+ return false;
+ }
+
+ fseek($this->getid3->fp, -256, SEEK_END);
+ $preid3v1 = fread($this->getid3->fp, 128);
+ $id3v1tag = fread($this->getid3->fp, 128);
+
+ if (substr($id3v1tag, 0, 3) == 'TAG') {
+
+ $info['avdataend'] = $info['filesize'] - 128;
+
+ $ParsedID3v1['title'] = $this->cutfield(substr($id3v1tag, 3, 30));
+ $ParsedID3v1['artist'] = $this->cutfield(substr($id3v1tag, 33, 30));
+ $ParsedID3v1['album'] = $this->cutfield(substr($id3v1tag, 63, 30));
+ $ParsedID3v1['year'] = $this->cutfield(substr($id3v1tag, 93, 4));
+ $ParsedID3v1['comment'] = substr($id3v1tag, 97, 30); // can't remove nulls yet, track detection depends on them
+ $ParsedID3v1['genreid'] = ord(substr($id3v1tag, 127, 1));
+
+ // If second-last byte of comment field is null and last byte of comment field is non-null
+ // then this is ID3v1.1 and the comment field is 28 bytes long and the 30th byte is the track number
+ if (($id3v1tag{125} === "\x00") && ($id3v1tag{126} !== "\x00")) {
+ $ParsedID3v1['track'] = ord(substr($ParsedID3v1['comment'], 29, 1));
+ $ParsedID3v1['comment'] = substr($ParsedID3v1['comment'], 0, 28);
+ }
+ $ParsedID3v1['comment'] = $this->cutfield($ParsedID3v1['comment']);
+
+ $ParsedID3v1['genre'] = $this->LookupGenreName($ParsedID3v1['genreid']);
+ if (!empty($ParsedID3v1['genre'])) {
+ unset($ParsedID3v1['genreid']);
+ }
+ if (isset($ParsedID3v1['genre']) && (empty($ParsedID3v1['genre']) || ($ParsedID3v1['genre'] == 'Unknown'))) {
+ unset($ParsedID3v1['genre']);
+ }
+
+ foreach ($ParsedID3v1 as $key => $value) {
+ $ParsedID3v1['comments'][$key][0] = $value;
+ }
+
+ // ID3v1 data is supposed to be padded with NULL characters, but some taggers pad with spaces
+ $GoodFormatID3v1tag = $this->GenerateID3v1Tag(
+ $ParsedID3v1['title'],
+ $ParsedID3v1['artist'],
+ $ParsedID3v1['album'],
+ $ParsedID3v1['year'],
+ (isset($ParsedID3v1['genre']) ? $this->LookupGenreID($ParsedID3v1['genre']) : false),
+ $ParsedID3v1['comment'],
+ (!empty($ParsedID3v1['track']) ? $ParsedID3v1['track'] : ''));
+ $ParsedID3v1['padding_valid'] = true;
+ if ($id3v1tag !== $GoodFormatID3v1tag) {
+ $ParsedID3v1['padding_valid'] = false;
+ $info['warning'][] = 'Some ID3v1 fields do not use NULL characters for padding';
+ }
+
+ $ParsedID3v1['tag_offset_end'] = $info['filesize'];
+ $ParsedID3v1['tag_offset_start'] = $ParsedID3v1['tag_offset_end'] - 128;
+
+ $info['id3v1'] = $ParsedID3v1;
+ }
+
+ if (substr($preid3v1, 0, 3) == 'TAG') {
+ // The way iTunes handles tags is, well, brain-damaged.
+ // It completely ignores v1 if ID3v2 is present.
+ // This goes as far as adding a new v1 tag *even if there already is one*
+
+ // A suspected double-ID3v1 tag has been detected, but it could be that
+ // the "TAG" identifier is a legitimate part of an APE or Lyrics3 tag
+ if (substr($preid3v1, 96, 8) == 'APETAGEX') {
+ // an APE tag footer was found before the last ID3v1, assume false "TAG" synch
+ } elseif (substr($preid3v1, 119, 6) == 'LYRICS') {
+ // a Lyrics3 tag footer was found before the last ID3v1, assume false "TAG" synch
+ } else {
+ // APE and Lyrics3 footers not found - assume double ID3v1
+ $info['warning'][] = 'Duplicate ID3v1 tag detected - this has been known to happen with iTunes';
+ $info['avdataend'] -= 128;
+ }
+ }
+
+ return true;
+ }
+
+ public static function cutfield($str) {
+ return trim(substr($str, 0, strcspn($str, "\x00")));
+ }
+
+ public static function ArrayOfGenres($allowSCMPXextended=false) {
+ static $GenreLookup = array(
+ 0 => 'Blues',
+ 1 => 'Classic Rock',
+ 2 => 'Country',
+ 3 => 'Dance',
+ 4 => 'Disco',
+ 5 => 'Funk',
+ 6 => 'Grunge',
+ 7 => 'Hip-Hop',
+ 8 => 'Jazz',
+ 9 => 'Metal',
+ 10 => 'New Age',
+ 11 => 'Oldies',
+ 12 => 'Other',
+ 13 => 'Pop',
+ 14 => 'R&B',
+ 15 => 'Rap',
+ 16 => 'Reggae',
+ 17 => 'Rock',
+ 18 => 'Techno',
+ 19 => 'Industrial',
+ 20 => 'Alternative',
+ 21 => 'Ska',
+ 22 => 'Death Metal',
+ 23 => 'Pranks',
+ 24 => 'Soundtrack',
+ 25 => 'Euro-Techno',
+ 26 => 'Ambient',
+ 27 => 'Trip-Hop',
+ 28 => 'Vocal',
+ 29 => 'Jazz+Funk',
+ 30 => 'Fusion',
+ 31 => 'Trance',
+ 32 => 'Classical',
+ 33 => 'Instrumental',
+ 34 => 'Acid',
+ 35 => 'House',
+ 36 => 'Game',
+ 37 => 'Sound Clip',
+ 38 => 'Gospel',
+ 39 => 'Noise',
+ 40 => 'Alt. Rock',
+ 41 => 'Bass',
+ 42 => 'Soul',
+ 43 => 'Punk',
+ 44 => 'Space',
+ 45 => 'Meditative',
+ 46 => 'Instrumental Pop',
+ 47 => 'Instrumental Rock',
+ 48 => 'Ethnic',
+ 49 => 'Gothic',
+ 50 => 'Darkwave',
+ 51 => 'Techno-Industrial',
+ 52 => 'Electronic',
+ 53 => 'Pop-Folk',
+ 54 => 'Eurodance',
+ 55 => 'Dream',
+ 56 => 'Southern Rock',
+ 57 => 'Comedy',
+ 58 => 'Cult',
+ 59 => 'Gangsta Rap',
+ 60 => 'Top 40',
+ 61 => 'Christian Rap',
+ 62 => 'Pop/Funk',
+ 63 => 'Jungle',
+ 64 => 'Native American',
+ 65 => 'Cabaret',
+ 66 => 'New Wave',
+ 67 => 'Psychedelic',
+ 68 => 'Rave',
+ 69 => 'Showtunes',
+ 70 => 'Trailer',
+ 71 => 'Lo-Fi',
+ 72 => 'Tribal',
+ 73 => 'Acid Punk',
+ 74 => 'Acid Jazz',
+ 75 => 'Polka',
+ 76 => 'Retro',
+ 77 => 'Musical',
+ 78 => 'Rock & Roll',
+ 79 => 'Hard Rock',
+ 80 => 'Folk',
+ 81 => 'Folk/Rock',
+ 82 => 'National Folk',
+ 83 => 'Swing',
+ 84 => 'Fast-Fusion',
+ 85 => 'Bebob',
+ 86 => 'Latin',
+ 87 => 'Revival',
+ 88 => 'Celtic',
+ 89 => 'Bluegrass',
+ 90 => 'Avantgarde',
+ 91 => 'Gothic Rock',
+ 92 => 'Progressive Rock',
+ 93 => 'Psychedelic Rock',
+ 94 => 'Symphonic Rock',
+ 95 => 'Slow Rock',
+ 96 => 'Big Band',
+ 97 => 'Chorus',
+ 98 => 'Easy Listening',
+ 99 => 'Acoustic',
+ 100 => 'Humour',
+ 101 => 'Speech',
+ 102 => 'Chanson',
+ 103 => 'Opera',
+ 104 => 'Chamber Music',
+ 105 => 'Sonata',
+ 106 => 'Symphony',
+ 107 => 'Booty Bass',
+ 108 => 'Primus',
+ 109 => 'Porn Groove',
+ 110 => 'Satire',
+ 111 => 'Slow Jam',
+ 112 => 'Club',
+ 113 => 'Tango',
+ 114 => 'Samba',
+ 115 => 'Folklore',
+ 116 => 'Ballad',
+ 117 => 'Power Ballad',
+ 118 => 'Rhythmic Soul',
+ 119 => 'Freestyle',
+ 120 => 'Duet',
+ 121 => 'Punk Rock',
+ 122 => 'Drum Solo',
+ 123 => 'A Cappella',
+ 124 => 'Euro-House',
+ 125 => 'Dance Hall',
+ 126 => 'Goa',
+ 127 => 'Drum & Bass',
+ 128 => 'Club-House',
+ 129 => 'Hardcore',
+ 130 => 'Terror',
+ 131 => 'Indie',
+ 132 => 'BritPop',
+ 133 => 'Negerpunk',
+ 134 => 'Polsk Punk',
+ 135 => 'Beat',
+ 136 => 'Christian Gangsta Rap',
+ 137 => 'Heavy Metal',
+ 138 => 'Black Metal',
+ 139 => 'Crossover',
+ 140 => 'Contemporary Christian',
+ 141 => 'Christian Rock',
+ 142 => 'Merengue',
+ 143 => 'Salsa',
+ 144 => 'Thrash Metal',
+ 145 => 'Anime',
+ 146 => 'JPop',
+ 147 => 'Synthpop',
+
+ 255 => 'Unknown',
+
+ 'CR' => 'Cover',
+ 'RX' => 'Remix'
+ );
+
+ static $GenreLookupSCMPX = array();
+ if ($allowSCMPXextended && empty($GenreLookupSCMPX)) {
+ $GenreLookupSCMPX = $GenreLookup;
+ // http://www.geocities.co.jp/SiliconValley-Oakland/3664/alittle.html#GenreExtended
+ // Extended ID3v1 genres invented by SCMPX
+ // Note that 255 "Japanese Anime" conflicts with standard "Unknown"
+ $GenreLookupSCMPX[240] = 'Sacred';
+ $GenreLookupSCMPX[241] = 'Northern Europe';
+ $GenreLookupSCMPX[242] = 'Irish & Scottish';
+ $GenreLookupSCMPX[243] = 'Scotland';
+ $GenreLookupSCMPX[244] = 'Ethnic Europe';
+ $GenreLookupSCMPX[245] = 'Enka';
+ $GenreLookupSCMPX[246] = 'Children\'s Song';
+ $GenreLookupSCMPX[247] = 'Japanese Sky';
+ $GenreLookupSCMPX[248] = 'Japanese Heavy Rock';
+ $GenreLookupSCMPX[249] = 'Japanese Doom Rock';
+ $GenreLookupSCMPX[250] = 'Japanese J-POP';
+ $GenreLookupSCMPX[251] = 'Japanese Seiyu';
+ $GenreLookupSCMPX[252] = 'Japanese Ambient Techno';
+ $GenreLookupSCMPX[253] = 'Japanese Moemoe';
+ $GenreLookupSCMPX[254] = 'Japanese Tokusatsu';
+ //$GenreLookupSCMPX[255] = 'Japanese Anime';
+ }
+
+ return ($allowSCMPXextended ? $GenreLookupSCMPX : $GenreLookup);
+ }
+
+ public static function LookupGenreName($genreid, $allowSCMPXextended=true) {
+ switch ($genreid) {
+ case 'RX':
+ case 'CR':
+ break;
+ default:
+ if (!is_numeric($genreid)) {
+ return false;
+ }
+ $genreid = intval($genreid); // to handle 3 or '3' or '03'
+ break;
+ }
+ $GenreLookup = self::ArrayOfGenres($allowSCMPXextended);
+ return (isset($GenreLookup[$genreid]) ? $GenreLookup[$genreid] : false);
+ }
+
+ public static function LookupGenreID($genre, $allowSCMPXextended=false) {
+ $GenreLookup = self::ArrayOfGenres($allowSCMPXextended);
+ $LowerCaseNoSpaceSearchTerm = strtolower(str_replace(' ', '', $genre));
+ foreach ($GenreLookup as $key => $value) {
+ if (strtolower(str_replace(' ', '', $value)) == $LowerCaseNoSpaceSearchTerm) {
+ return $key;
+ }
+ }
+ return false;
+ }
+
+ public static function StandardiseID3v1GenreName($OriginalGenre) {
+ if (($GenreID = self::LookupGenreID($OriginalGenre)) !== false) {
+ return self::LookupGenreName($GenreID);
+ }
+ return $OriginalGenre;
+ }
+
+ public static function GenerateID3v1Tag($title, $artist, $album, $year, $genreid, $comment, $track='') {
+ $ID3v1Tag = 'TAG';
+ $ID3v1Tag .= str_pad(trim(substr($title, 0, 30)), 30, "\x00", STR_PAD_RIGHT);
+ $ID3v1Tag .= str_pad(trim(substr($artist, 0, 30)), 30, "\x00", STR_PAD_RIGHT);
+ $ID3v1Tag .= str_pad(trim(substr($album, 0, 30)), 30, "\x00", STR_PAD_RIGHT);
+ $ID3v1Tag .= str_pad(trim(substr($year, 0, 4)), 4, "\x00", STR_PAD_LEFT);
+ if (!empty($track) && ($track > 0) && ($track <= 255)) {
+ $ID3v1Tag .= str_pad(trim(substr($comment, 0, 28)), 28, "\x00", STR_PAD_RIGHT);
+ $ID3v1Tag .= "\x00";
+ if (gettype($track) == 'string') {
+ $track = (int) $track;
+ }
+ $ID3v1Tag .= chr($track);
+ } else {
+ $ID3v1Tag .= str_pad(trim(substr($comment, 0, 30)), 30, "\x00", STR_PAD_RIGHT);
+ }
+ if (($genreid < 0) || ($genreid > 147)) {
+ $genreid = 255; // 'unknown' genre
+ }
+ switch (gettype($genreid)) {
+ case 'string':
+ case 'integer':
+ $ID3v1Tag .= chr(intval($genreid));
+ break;
+ default:
+ $ID3v1Tag .= chr(255); // 'unknown' genre
+ break;
+ }
+
+ return $ID3v1Tag;
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/libs/getid3/module.tag.id3v2.php b/extensions/TimedMediaHandler/libs/getid3/module.tag.id3v2.php
new file mode 100644
index 00000000..b08f9f9a
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/module.tag.id3v2.php
@@ -0,0 +1,3414 @@
+<?php
+/////////////////////////////////////////////////////////////////
+/// getID3() by James Heinrich <info@getid3.org> //
+// available at http://getid3.sourceforge.net //
+// or http://www.getid3.org //
+/////////////////////////////////////////////////////////////////
+// See readme.txt for more details //
+/////////////////////////////////////////////////////////////////
+/// //
+// module.tag.id3v2.php //
+// module for analyzing ID3v2 tags //
+// dependencies: module.tag.id3v1.php //
+// ///
+/////////////////////////////////////////////////////////////////
+
+getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v1.php', __FILE__, true);
+
+class getid3_id3v2 extends getid3_handler
+{
+ public $StartingOffset = 0;
+
+ public function Analyze() {
+ $info = &$this->getid3->info;
+
+ // Overall tag structure:
+ // +-----------------------------+
+ // | Header (10 bytes) |
+ // +-----------------------------+
+ // | Extended Header |
+ // | (variable length, OPTIONAL) |
+ // +-----------------------------+
+ // | Frames (variable length) |
+ // +-----------------------------+
+ // | Padding |
+ // | (variable length, OPTIONAL) |
+ // +-----------------------------+
+ // | Footer (10 bytes, OPTIONAL) |
+ // +-----------------------------+
+
+ // Header
+ // ID3v2/file identifier "ID3"
+ // ID3v2 version $04 00
+ // ID3v2 flags (%ab000000 in v2.2, %abc00000 in v2.3, %abcd0000 in v2.4.x)
+ // ID3v2 size 4 * %0xxxxxxx
+
+
+ // shortcuts
+ $info['id3v2']['header'] = true;
+ $thisfile_id3v2 = &$info['id3v2'];
+ $thisfile_id3v2['flags'] = array();
+ $thisfile_id3v2_flags = &$thisfile_id3v2['flags'];
+
+
+ fseek($this->getid3->fp, $this->StartingOffset, SEEK_SET);
+ $header = fread($this->getid3->fp, 10);
+ if (substr($header, 0, 3) == 'ID3' && strlen($header) == 10) {
+
+ $thisfile_id3v2['majorversion'] = ord($header{3});
+ $thisfile_id3v2['minorversion'] = ord($header{4});
+
+ // shortcut
+ $id3v2_majorversion = &$thisfile_id3v2['majorversion'];
+
+ } else {
+
+ unset($info['id3v2']);
+ return false;
+
+ }
+
+ if ($id3v2_majorversion > 4) { // this script probably won't correctly parse ID3v2.5.x and above (if it ever exists)
+
+ $info['error'][] = 'this script only parses up to ID3v2.4.x - this tag is ID3v2.'.$id3v2_majorversion.'.'.$thisfile_id3v2['minorversion'];
+ return false;
+
+ }
+
+ $id3_flags = ord($header{5});
+ switch ($id3v2_majorversion) {
+ case 2:
+ // %ab000000 in v2.2
+ $thisfile_id3v2_flags['unsynch'] = (bool) ($id3_flags & 0x80); // a - Unsynchronisation
+ $thisfile_id3v2_flags['compression'] = (bool) ($id3_flags & 0x40); // b - Compression
+ break;
+
+ case 3:
+ // %abc00000 in v2.3
+ $thisfile_id3v2_flags['unsynch'] = (bool) ($id3_flags & 0x80); // a - Unsynchronisation
+ $thisfile_id3v2_flags['exthead'] = (bool) ($id3_flags & 0x40); // b - Extended header
+ $thisfile_id3v2_flags['experim'] = (bool) ($id3_flags & 0x20); // c - Experimental indicator
+ break;
+
+ case 4:
+ // %abcd0000 in v2.4
+ $thisfile_id3v2_flags['unsynch'] = (bool) ($id3_flags & 0x80); // a - Unsynchronisation
+ $thisfile_id3v2_flags['exthead'] = (bool) ($id3_flags & 0x40); // b - Extended header
+ $thisfile_id3v2_flags['experim'] = (bool) ($id3_flags & 0x20); // c - Experimental indicator
+ $thisfile_id3v2_flags['isfooter'] = (bool) ($id3_flags & 0x10); // d - Footer present
+ break;
+ }
+
+ $thisfile_id3v2['headerlength'] = getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length
+
+ $thisfile_id3v2['tag_offset_start'] = $this->StartingOffset;
+ $thisfile_id3v2['tag_offset_end'] = $thisfile_id3v2['tag_offset_start'] + $thisfile_id3v2['headerlength'];
+
+
+
+ // create 'encoding' key - used by getid3::HandleAllTags()
+ // in ID3v2 every field can have it's own encoding type
+ // so force everything to UTF-8 so it can be handled consistantly
+ $thisfile_id3v2['encoding'] = 'UTF-8';
+
+
+ // Frames
+
+ // All ID3v2 frames consists of one frame header followed by one or more
+ // fields containing the actual information. The header is always 10
+ // bytes and laid out as follows:
+ //
+ // Frame ID $xx xx xx xx (four characters)
+ // Size 4 * %0xxxxxxx
+ // Flags $xx xx
+
+ $sizeofframes = $thisfile_id3v2['headerlength'] - 10; // not including 10-byte initial header
+ if (!empty($thisfile_id3v2['exthead']['length'])) {
+ $sizeofframes -= ($thisfile_id3v2['exthead']['length'] + 4);
+ }
+ if (!empty($thisfile_id3v2_flags['isfooter'])) {
+ $sizeofframes -= 10; // footer takes last 10 bytes of ID3v2 header, after frame data, before audio
+ }
+ if ($sizeofframes > 0) {
+
+ $framedata = fread($this->getid3->fp, $sizeofframes); // read all frames from file into $framedata variable
+
+ // if entire frame data is unsynched, de-unsynch it now (ID3v2.3.x)
+ if (!empty($thisfile_id3v2_flags['unsynch']) && ($id3v2_majorversion <= 3)) {
+ $framedata = $this->DeUnsynchronise($framedata);
+ }
+ // [in ID3v2.4.0] Unsynchronisation [S:6.1] is done on frame level, instead
+ // of on tag level, making it easier to skip frames, increasing the streamability
+ // of the tag. The unsynchronisation flag in the header [S:3.1] indicates that
+ // there exists an unsynchronised frame, while the new unsynchronisation flag in
+ // the frame header [S:4.1.2] indicates unsynchronisation.
+
+
+ //$framedataoffset = 10 + ($thisfile_id3v2['exthead']['length'] ? $thisfile_id3v2['exthead']['length'] + 4 : 0); // how many bytes into the stream - start from after the 10-byte header (and extended header length+4, if present)
+ $framedataoffset = 10; // how many bytes into the stream - start from after the 10-byte header
+
+
+ // Extended Header
+ if (!empty($thisfile_id3v2_flags['exthead'])) {
+ $extended_header_offset = 0;
+
+ if ($id3v2_majorversion == 3) {
+
+ // v2.3 definition:
+ //Extended header size $xx xx xx xx // 32-bit integer
+ //Extended Flags $xx xx
+ // %x0000000 %00000000 // v2.3
+ // x - CRC data present
+ //Size of padding $xx xx xx xx
+
+ $thisfile_id3v2['exthead']['length'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 4), 0);
+ $extended_header_offset += 4;
+
+ $thisfile_id3v2['exthead']['flag_bytes'] = 2;
+ $thisfile_id3v2['exthead']['flag_raw'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, $thisfile_id3v2['exthead']['flag_bytes']));
+ $extended_header_offset += $thisfile_id3v2['exthead']['flag_bytes'];
+
+ $thisfile_id3v2['exthead']['flags']['crc'] = (bool) ($thisfile_id3v2['exthead']['flag_raw'] & 0x8000);
+
+ $thisfile_id3v2['exthead']['padding_size'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 4));
+ $extended_header_offset += 4;
+
+ if ($thisfile_id3v2['exthead']['flags']['crc']) {
+ $thisfile_id3v2['exthead']['flag_data']['crc'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 4));
+ $extended_header_offset += 4;
+ }
+ $extended_header_offset += $thisfile_id3v2['exthead']['padding_size'];
+
+ } elseif ($id3v2_majorversion == 4) {
+
+ // v2.4 definition:
+ //Extended header size 4 * %0xxxxxxx // 28-bit synchsafe integer
+ //Number of flag bytes $01
+ //Extended Flags $xx
+ // %0bcd0000 // v2.4
+ // b - Tag is an update
+ // Flag data length $00
+ // c - CRC data present
+ // Flag data length $05
+ // Total frame CRC 5 * %0xxxxxxx
+ // d - Tag restrictions
+ // Flag data length $01
+
+ $thisfile_id3v2['exthead']['length'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 4), true);
+ $extended_header_offset += 4;
+
+ $thisfile_id3v2['exthead']['flag_bytes'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 1)); // should always be 1
+ $extended_header_offset += 1;
+
+ $thisfile_id3v2['exthead']['flag_raw'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, $thisfile_id3v2['exthead']['flag_bytes']));
+ $extended_header_offset += $thisfile_id3v2['exthead']['flag_bytes'];
+
+ $thisfile_id3v2['exthead']['flags']['update'] = (bool) ($thisfile_id3v2['exthead']['flag_raw'] & 0x40);
+ $thisfile_id3v2['exthead']['flags']['crc'] = (bool) ($thisfile_id3v2['exthead']['flag_raw'] & 0x20);
+ $thisfile_id3v2['exthead']['flags']['restrictions'] = (bool) ($thisfile_id3v2['exthead']['flag_raw'] & 0x10);
+
+ if ($thisfile_id3v2['exthead']['flags']['update']) {
+ $ext_header_chunk_length = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 1)); // should be 0
+ $extended_header_offset += 1;
+ }
+
+ if ($thisfile_id3v2['exthead']['flags']['crc']) {
+ $ext_header_chunk_length = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 1)); // should be 5
+ $extended_header_offset += 1;
+ $thisfile_id3v2['exthead']['flag_data']['crc'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, $ext_header_chunk_length), true, false);
+ $extended_header_offset += $ext_header_chunk_length;
+ }
+
+ if ($thisfile_id3v2['exthead']['flags']['restrictions']) {
+ $ext_header_chunk_length = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 1)); // should be 1
+ $extended_header_offset += 1;
+
+ // %ppqrrstt
+ $restrictions_raw = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 1));
+ $extended_header_offset += 1;
+ $thisfile_id3v2['exthead']['flags']['restrictions']['tagsize'] = ($restrictions_raw & 0xC0) >> 6; // p - Tag size restrictions
+ $thisfile_id3v2['exthead']['flags']['restrictions']['textenc'] = ($restrictions_raw & 0x20) >> 5; // q - Text encoding restrictions
+ $thisfile_id3v2['exthead']['flags']['restrictions']['textsize'] = ($restrictions_raw & 0x18) >> 3; // r - Text fields size restrictions
+ $thisfile_id3v2['exthead']['flags']['restrictions']['imgenc'] = ($restrictions_raw & 0x04) >> 2; // s - Image encoding restrictions
+ $thisfile_id3v2['exthead']['flags']['restrictions']['imgsize'] = ($restrictions_raw & 0x03) >> 0; // t - Image size restrictions
+
+ $thisfile_id3v2['exthead']['flags']['restrictions_text']['tagsize'] = $this->LookupExtendedHeaderRestrictionsTagSizeLimits($thisfile_id3v2['exthead']['flags']['restrictions']['tagsize']);
+ $thisfile_id3v2['exthead']['flags']['restrictions_text']['textenc'] = $this->LookupExtendedHeaderRestrictionsTextEncodings($thisfile_id3v2['exthead']['flags']['restrictions']['textenc']);
+ $thisfile_id3v2['exthead']['flags']['restrictions_text']['textsize'] = $this->LookupExtendedHeaderRestrictionsTextFieldSize($thisfile_id3v2['exthead']['flags']['restrictions']['textsize']);
+ $thisfile_id3v2['exthead']['flags']['restrictions_text']['imgenc'] = $this->LookupExtendedHeaderRestrictionsImageEncoding($thisfile_id3v2['exthead']['flags']['restrictions']['imgenc']);
+ $thisfile_id3v2['exthead']['flags']['restrictions_text']['imgsize'] = $this->LookupExtendedHeaderRestrictionsImageSizeSize($thisfile_id3v2['exthead']['flags']['restrictions']['imgsize']);
+ }
+
+ if ($thisfile_id3v2['exthead']['length'] != $extended_header_offset) {
+ $info['warning'][] = 'ID3v2.4 extended header length mismatch (expecting '.intval($thisfile_id3v2['exthead']['length']).', found '.intval($extended_header_offset).')';
+ }
+ }
+
+ $framedataoffset += $extended_header_offset;
+ $framedata = substr($framedata, $extended_header_offset);
+ } // end extended header
+
+
+ while (isset($framedata) && (strlen($framedata) > 0)) { // cycle through until no more frame data is left to parse
+ if (strlen($framedata) <= $this->ID3v2HeaderLength($id3v2_majorversion)) {
+ // insufficient room left in ID3v2 header for actual data - must be padding
+ $thisfile_id3v2['padding']['start'] = $framedataoffset;
+ $thisfile_id3v2['padding']['length'] = strlen($framedata);
+ $thisfile_id3v2['padding']['valid'] = true;
+ for ($i = 0; $i < $thisfile_id3v2['padding']['length']; $i++) {
+ if ($framedata{$i} != "\x00") {
+ $thisfile_id3v2['padding']['valid'] = false;
+ $thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;
+ $info['warning'][] = 'Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)';
+ break;
+ }
+ }
+ break; // skip rest of ID3v2 header
+ }
+ if ($id3v2_majorversion == 2) {
+ // Frame ID $xx xx xx (three characters)
+ // Size $xx xx xx (24-bit integer)
+ // Flags $xx xx
+
+ $frame_header = substr($framedata, 0, 6); // take next 6 bytes for header
+ $framedata = substr($framedata, 6); // and leave the rest in $framedata
+ $frame_name = substr($frame_header, 0, 3);
+ $frame_size = getid3_lib::BigEndian2Int(substr($frame_header, 3, 3), 0);
+ $frame_flags = 0; // not used for anything in ID3v2.2, just set to avoid E_NOTICEs
+
+ } elseif ($id3v2_majorversion > 2) {
+
+ // Frame ID $xx xx xx xx (four characters)
+ // Size $xx xx xx xx (32-bit integer in v2.3, 28-bit synchsafe in v2.4+)
+ // Flags $xx xx
+
+ $frame_header = substr($framedata, 0, 10); // take next 10 bytes for header
+ $framedata = substr($framedata, 10); // and leave the rest in $framedata
+
+ $frame_name = substr($frame_header, 0, 4);
+ if ($id3v2_majorversion == 3) {
+ $frame_size = getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 0); // 32-bit integer
+ } else { // ID3v2.4+
+ $frame_size = getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 1); // 32-bit synchsafe integer (28-bit value)
+ }
+
+ if ($frame_size < (strlen($framedata) + 4)) {
+ $nextFrameID = substr($framedata, $frame_size, 4);
+ if ($this->IsValidID3v2FrameName($nextFrameID, $id3v2_majorversion)) {
+ // next frame is OK
+ } elseif (($frame_name == "\x00".'MP3') || ($frame_name == "\x00\x00".'MP') || ($frame_name == ' MP3') || ($frame_name == 'MP3e')) {
+ // MP3ext known broken frames - "ok" for the purposes of this test
+ } elseif (($id3v2_majorversion == 4) && ($this->IsValidID3v2FrameName(substr($framedata, getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 0), 4), 3))) {
+ $info['warning'][] = 'ID3v2 tag written as ID3v2.4, but with non-synchsafe integers (ID3v2.3 style). Older versions of (Helium2; iTunes) are known culprits of this. Tag has been parsed as ID3v2.3';
+ $id3v2_majorversion = 3;
+ $frame_size = getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 0); // 32-bit integer
+ }
+ }
+
+
+ $frame_flags = getid3_lib::BigEndian2Int(substr($frame_header, 8, 2));
+ }
+
+ if ((($id3v2_majorversion == 2) && ($frame_name == "\x00\x00\x00")) || ($frame_name == "\x00\x00\x00\x00")) {
+ // padding encountered
+
+ $thisfile_id3v2['padding']['start'] = $framedataoffset;
+ $thisfile_id3v2['padding']['length'] = strlen($frame_header) + strlen($framedata);
+ $thisfile_id3v2['padding']['valid'] = true;
+
+ $len = strlen($framedata);
+ for ($i = 0; $i < $len; $i++) {
+ if ($framedata{$i} != "\x00") {
+ $thisfile_id3v2['padding']['valid'] = false;
+ $thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;
+ $info['warning'][] = 'Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)';
+ break;
+ }
+ }
+ break; // skip rest of ID3v2 header
+ }
+
+ if ($frame_name == 'COM ') {
+ $info['warning'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))). [Note: this particular error has been known to happen with tags edited by iTunes (versions "X v2.0.3", "v3.0.1" are known-guilty, probably others too)]';
+ $frame_name = 'COMM';
+ }
+ if (($frame_size <= strlen($framedata)) && ($this->IsValidID3v2FrameName($frame_name, $id3v2_majorversion))) {
+
+ unset($parsedFrame);
+ $parsedFrame['frame_name'] = $frame_name;
+ $parsedFrame['frame_flags_raw'] = $frame_flags;
+ $parsedFrame['data'] = substr($framedata, 0, $frame_size);
+ $parsedFrame['datalength'] = getid3_lib::CastAsInt($frame_size);
+ $parsedFrame['dataoffset'] = $framedataoffset;
+
+ $this->ParseID3v2Frame($parsedFrame);
+ $thisfile_id3v2[$frame_name][] = $parsedFrame;
+
+ $framedata = substr($framedata, $frame_size);
+
+ } else { // invalid frame length or FrameID
+
+ if ($frame_size <= strlen($framedata)) {
+
+ if ($this->IsValidID3v2FrameName(substr($framedata, $frame_size, 4), $id3v2_majorversion)) {
+
+ // next frame is valid, just skip the current frame
+ $framedata = substr($framedata, $frame_size);
+ $info['warning'][] = 'Next ID3v2 frame is valid, skipping current frame.';
+
+ } else {
+
+ // next frame is invalid too, abort processing
+ //unset($framedata);
+ $framedata = null;
+ $info['error'][] = 'Next ID3v2 frame is also invalid, aborting processing.';
+
+ }
+
+ } elseif ($frame_size == strlen($framedata)) {
+
+ // this is the last frame, just skip
+ $info['warning'][] = 'This was the last ID3v2 frame.';
+
+ } else {
+
+ // next frame is invalid too, abort processing
+ //unset($framedata);
+ $framedata = null;
+ $info['warning'][] = 'Invalid ID3v2 frame size, aborting.';
+
+ }
+ if (!$this->IsValidID3v2FrameName($frame_name, $id3v2_majorversion)) {
+
+ switch ($frame_name) {
+ case "\x00\x00".'MP':
+ case "\x00".'MP3':
+ case ' MP3':
+ case 'MP3e':
+ case "\x00".'MP':
+ case ' MP':
+ case 'MP3':
+ $info['warning'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))). [Note: this particular error has been known to happen with tags edited by "MP3ext (www.mutschler.de/mp3ext/)"]';
+ break;
+
+ default:
+ $info['warning'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))).';
+ break;
+ }
+
+ } elseif (!isset($framedata) || ($frame_size > strlen($framedata))) {
+
+ $info['error'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: $frame_size ('.$frame_size.') > strlen($framedata) ('.(isset($framedata) ? strlen($framedata) : 'null').')).';
+
+ } else {
+
+ $info['error'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag).';
+
+ }
+
+ }
+ $framedataoffset += ($frame_size + $this->ID3v2HeaderLength($id3v2_majorversion));
+
+ }
+
+ }
+
+
+ // Footer
+
+ // The footer is a copy of the header, but with a different identifier.
+ // ID3v2 identifier "3DI"
+ // ID3v2 version $04 00
+ // ID3v2 flags %abcd0000
+ // ID3v2 size 4 * %0xxxxxxx
+
+ if (isset($thisfile_id3v2_flags['isfooter']) && $thisfile_id3v2_flags['isfooter']) {
+ $footer = fread($this->getid3->fp, 10);
+ if (substr($footer, 0, 3) == '3DI') {
+ $thisfile_id3v2['footer'] = true;
+ $thisfile_id3v2['majorversion_footer'] = ord($footer{3});
+ $thisfile_id3v2['minorversion_footer'] = ord($footer{4});
+ }
+ if ($thisfile_id3v2['majorversion_footer'] <= 4) {
+ $id3_flags = ord(substr($footer{5}));
+ $thisfile_id3v2_flags['unsynch_footer'] = (bool) ($id3_flags & 0x80);
+ $thisfile_id3v2_flags['extfoot_footer'] = (bool) ($id3_flags & 0x40);
+ $thisfile_id3v2_flags['experim_footer'] = (bool) ($id3_flags & 0x20);
+ $thisfile_id3v2_flags['isfooter_footer'] = (bool) ($id3_flags & 0x10);
+
+ $thisfile_id3v2['footerlength'] = getid3_lib::BigEndian2Int(substr($footer, 6, 4), 1);
+ }
+ } // end footer
+
+ if (isset($thisfile_id3v2['comments']['genre'])) {
+ foreach ($thisfile_id3v2['comments']['genre'] as $key => $value) {
+ unset($thisfile_id3v2['comments']['genre'][$key]);
+ $thisfile_id3v2['comments'] = getid3_lib::array_merge_noclobber($thisfile_id3v2['comments'], array('genre'=>$this->ParseID3v2GenreString($value)));
+ }
+ }
+
+ if (isset($thisfile_id3v2['comments']['track'])) {
+ foreach ($thisfile_id3v2['comments']['track'] as $key => $value) {
+ if (strstr($value, '/')) {
+ list($thisfile_id3v2['comments']['tracknum'][$key], $thisfile_id3v2['comments']['totaltracks'][$key]) = explode('/', $thisfile_id3v2['comments']['track'][$key]);
+ }
+ }
+ }
+
+ if (!isset($thisfile_id3v2['comments']['year']) && !empty($thisfile_id3v2['comments']['recording_time'][0]) && preg_match('#^([0-9]{4})#', trim($thisfile_id3v2['comments']['recording_time'][0]), $matches)) {
+ $thisfile_id3v2['comments']['year'] = array($matches[1]);
+ }
+
+
+ if (!empty($thisfile_id3v2['TXXX'])) {
+ // MediaMonkey does this, maybe others: write a blank RGAD frame, but put replay-gain adjustment values in TXXX frames
+ foreach ($thisfile_id3v2['TXXX'] as $txxx_array) {
+ switch ($txxx_array['description']) {
+ case 'replaygain_track_gain':
+ if (empty($info['replay_gain']['track']['adjustment']) && !empty($txxx_array['data'])) {
+ $info['replay_gain']['track']['adjustment'] = floatval(trim(str_replace('dB', '', $txxx_array['data'])));
+ }
+ break;
+ case 'replaygain_track_peak':
+ if (empty($info['replay_gain']['track']['peak']) && !empty($txxx_array['data'])) {
+ $info['replay_gain']['track']['peak'] = floatval($txxx_array['data']);
+ }
+ break;
+ case 'replaygain_album_gain':
+ if (empty($info['replay_gain']['album']['adjustment']) && !empty($txxx_array['data'])) {
+ $info['replay_gain']['album']['adjustment'] = floatval(trim(str_replace('dB', '', $txxx_array['data'])));
+ }
+ break;
+ }
+ }
+ }
+
+
+ // Set avdataoffset
+ $info['avdataoffset'] = $thisfile_id3v2['headerlength'];
+ if (isset($thisfile_id3v2['footer'])) {
+ $info['avdataoffset'] += 10;
+ }
+
+ return true;
+ }
+
+
+ public function ParseID3v2GenreString($genrestring) {
+ // Parse genres into arrays of genreName and genreID
+ // ID3v2.2.x, ID3v2.3.x: '(21)' or '(4)Eurodisco' or '(51)(39)' or '(55)((I think...)'
+ // ID3v2.4.x: '21' $00 'Eurodisco' $00
+ $clean_genres = array();
+ if (strpos($genrestring, "\x00") === false) {
+ $genrestring = preg_replace('#\(([0-9]{1,3})\)#', '$1'."\x00", $genrestring);
+ }
+ $genre_elements = explode("\x00", $genrestring);
+ foreach ($genre_elements as $element) {
+ $element = trim($element);
+ if ($element) {
+ if (preg_match('#^[0-9]{1,3}#', $element)) {
+ $clean_genres[] = getid3_id3v1::LookupGenreName($element);
+ } else {
+ $clean_genres[] = str_replace('((', '(', $element);
+ }
+ }
+ }
+ return $clean_genres;
+ }
+
+
+ public function ParseID3v2Frame(&$parsedFrame) {
+
+ // shortcuts
+ $info = &$this->getid3->info;
+ $id3v2_majorversion = $info['id3v2']['majorversion'];
+
+ $parsedFrame['framenamelong'] = $this->FrameNameLongLookup($parsedFrame['frame_name']);
+ if (empty($parsedFrame['framenamelong'])) {
+ unset($parsedFrame['framenamelong']);
+ }
+ $parsedFrame['framenameshort'] = $this->FrameNameShortLookup($parsedFrame['frame_name']);
+ if (empty($parsedFrame['framenameshort'])) {
+ unset($parsedFrame['framenameshort']);
+ }
+
+ if ($id3v2_majorversion >= 3) { // frame flags are not part of the ID3v2.2 standard
+ if ($id3v2_majorversion == 3) {
+ // Frame Header Flags
+ // %abc00000 %ijk00000
+ $parsedFrame['flags']['TagAlterPreservation'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x8000); // a - Tag alter preservation
+ $parsedFrame['flags']['FileAlterPreservation'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x4000); // b - File alter preservation
+ $parsedFrame['flags']['ReadOnly'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x2000); // c - Read only
+ $parsedFrame['flags']['compression'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0080); // i - Compression
+ $parsedFrame['flags']['Encryption'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0040); // j - Encryption
+ $parsedFrame['flags']['GroupingIdentity'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0020); // k - Grouping identity
+
+ } elseif ($id3v2_majorversion == 4) {
+ // Frame Header Flags
+ // %0abc0000 %0h00kmnp
+ $parsedFrame['flags']['TagAlterPreservation'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x4000); // a - Tag alter preservation
+ $parsedFrame['flags']['FileAlterPreservation'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x2000); // b - File alter preservation
+ $parsedFrame['flags']['ReadOnly'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x1000); // c - Read only
+ $parsedFrame['flags']['GroupingIdentity'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0040); // h - Grouping identity
+ $parsedFrame['flags']['compression'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0008); // k - Compression
+ $parsedFrame['flags']['Encryption'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0004); // m - Encryption
+ $parsedFrame['flags']['Unsynchronisation'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0002); // n - Unsynchronisation
+ $parsedFrame['flags']['DataLengthIndicator'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0001); // p - Data length indicator
+
+ // Frame-level de-unsynchronisation - ID3v2.4
+ if ($parsedFrame['flags']['Unsynchronisation']) {
+ $parsedFrame['data'] = $this->DeUnsynchronise($parsedFrame['data']);
+ }
+
+ if ($parsedFrame['flags']['DataLengthIndicator']) {
+ $parsedFrame['data_length_indicator'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 0, 4), 1);
+ $parsedFrame['data'] = substr($parsedFrame['data'], 4);
+ }
+ }
+
+ // Frame-level de-compression
+ if ($parsedFrame['flags']['compression']) {
+ $parsedFrame['decompressed_size'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 0, 4));
+ if (!function_exists('gzuncompress')) {
+ $info['warning'][] = 'gzuncompress() support required to decompress ID3v2 frame "'.$parsedFrame['frame_name'].'"';
+ } else {
+ if ($decompresseddata = @gzuncompress(substr($parsedFrame['data'], 4))) {
+ //if ($decompresseddata = @gzuncompress($parsedFrame['data'])) {
+ $parsedFrame['data'] = $decompresseddata;
+ unset($decompresseddata);
+ } else {
+ $info['warning'][] = 'gzuncompress() failed on compressed contents of ID3v2 frame "'.$parsedFrame['frame_name'].'"';
+ }
+ }
+ }
+ }
+
+ if (!empty($parsedFrame['flags']['DataLengthIndicator'])) {
+ if ($parsedFrame['data_length_indicator'] != strlen($parsedFrame['data'])) {
+ $info['warning'][] = 'ID3v2 frame "'.$parsedFrame['frame_name'].'" should be '.$parsedFrame['data_length_indicator'].' bytes long according to DataLengthIndicator, but found '.strlen($parsedFrame['data']).' bytes of data';
+ }
+ }
+
+ if (isset($parsedFrame['datalength']) && ($parsedFrame['datalength'] == 0)) {
+
+ $warning = 'Frame "'.$parsedFrame['frame_name'].'" at offset '.$parsedFrame['dataoffset'].' has no data portion';
+ switch ($parsedFrame['frame_name']) {
+ case 'WCOM':
+ $warning .= ' (this is known to happen with files tagged by RioPort)';
+ break;
+
+ default:
+ break;
+ }
+ $info['warning'][] = $warning;
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'UFID')) || // 4.1 UFID Unique file identifier
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'UFI'))) { // 4.1 UFI Unique file identifier
+ // There may be more than one 'UFID' frame in a tag,
+ // but only one with the same 'Owner identifier'.
+ // <Header for 'Unique file identifier', ID: 'UFID'>
+ // Owner identifier <text string> $00
+ // Identifier <up to 64 bytes binary data>
+ $exploded = explode("\x00", $parsedFrame['data'], 2);
+ $parsedFrame['ownerid'] = (isset($exploded[0]) ? $exploded[0] : '');
+ $parsedFrame['data'] = (isset($exploded[1]) ? $exploded[1] : '');
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'TXXX')) || // 4.2.2 TXXX User defined text information frame
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'TXX'))) { // 4.2.2 TXX User defined text information frame
+ // There may be more than one 'TXXX' frame in each tag,
+ // but only one with the same description.
+ // <Header for 'User defined text information frame', ID: 'TXXX'>
+ // Text encoding $xx
+ // Description <text string according to encoding> $00 (00)
+ // Value <text string according to encoding>
+
+ $frame_offset = 0;
+ $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+
+ if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
+ $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
+ }
+ $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
+ if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
+ $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
+ }
+ $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_description) === 0) {
+ $frame_description = '';
+ }
+ $parsedFrame['encodingid'] = $frame_textencoding;
+ $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
+
+ $parsedFrame['description'] = $frame_description;
+ $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)));
+ if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
+ $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = trim(getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']));
+ }
+ //unset($parsedFrame['data']); do not unset, may be needed elsewhere, e.g. for replaygain
+
+
+ } elseif ($parsedFrame['frame_name']{0} == 'T') { // 4.2. T??[?] Text information frame
+ // There may only be one text information frame of its kind in an tag.
+ // <Header for 'Text information frame', ID: 'T000' - 'TZZZ',
+ // excluding 'TXXX' described in 4.2.6.>
+ // Text encoding $xx
+ // Information <text string(s) according to encoding>
+
+ $frame_offset = 0;
+ $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
+ $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
+ }
+
+ $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
+
+ $parsedFrame['encodingid'] = $frame_textencoding;
+ $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
+
+ if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
+ // ID3v2.3 specs say that TPE1 (and others) can contain multiple artist values separated with /
+ // This of course breaks when an artist name contains slash character, e.g. "AC/DC"
+ // MP3tag (maybe others) implement alternative system where multiple artists are null-separated, which makes more sense
+ // getID3 will split null-separated artists into multiple artists and leave slash-separated ones to the user
+ switch ($parsedFrame['encoding']) {
+ case 'UTF-16':
+ case 'UTF-16BE':
+ case 'UTF-16LE':
+ $wordsize = 2;
+ break;
+ case 'ISO-8859-1':
+ case 'UTF-8':
+ default:
+ $wordsize = 1;
+ break;
+ }
+ $Txxx_elements = array();
+ $Txxx_elements_start_offset = 0;
+ for ($i = 0; $i < strlen($parsedFrame['data']); $i += $wordsize) {
+ if (substr($parsedFrame['data'], $i, $wordsize) == str_repeat("\x00", $wordsize)) {
+ $Txxx_elements[] = substr($parsedFrame['data'], $Txxx_elements_start_offset, $i - $Txxx_elements_start_offset);
+ $Txxx_elements_start_offset = $i + $wordsize;
+ }
+ }
+ $Txxx_elements[] = substr($parsedFrame['data'], $Txxx_elements_start_offset, $i - $Txxx_elements_start_offset);
+ foreach ($Txxx_elements as $Txxx_element) {
+ $string = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $Txxx_element);
+ if (!empty($string)) {
+ $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = $string;
+ }
+ }
+ unset($string, $wordsize, $i, $Txxx_elements, $Txxx_element, $Txxx_elements_start_offset);
+ }
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'WXXX')) || // 4.3.2 WXXX User defined URL link frame
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'WXX'))) { // 4.3.2 WXX User defined URL link frame
+ // There may be more than one 'WXXX' frame in each tag,
+ // but only one with the same description
+ // <Header for 'User defined URL link frame', ID: 'WXXX'>
+ // Text encoding $xx
+ // Description <text string according to encoding> $00 (00)
+ // URL <text string>
+
+ $frame_offset = 0;
+ $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
+ $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
+ }
+ $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
+ if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
+ $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
+ }
+ $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+
+ if (ord($frame_description) === 0) {
+ $frame_description = '';
+ }
+ $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)));
+
+ $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding));
+ if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
+ $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
+ }
+ if ($frame_terminatorpos) {
+ // there are null bytes after the data - this is not according to spec
+ // only use data up to first null byte
+ $frame_urldata = (string) substr($parsedFrame['data'], 0, $frame_terminatorpos);
+ } else {
+ // no null bytes following data, just use all data
+ $frame_urldata = (string) $parsedFrame['data'];
+ }
+
+ $parsedFrame['encodingid'] = $frame_textencoding;
+ $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
+
+ $parsedFrame['url'] = $frame_urldata;
+ $parsedFrame['description'] = $frame_description;
+ if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
+ $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['url']);
+ }
+ unset($parsedFrame['data']);
+
+
+ } elseif ($parsedFrame['frame_name']{0} == 'W') { // 4.3. W??? URL link frames
+ // There may only be one URL link frame of its kind in a tag,
+ // except when stated otherwise in the frame description
+ // <Header for 'URL link frame', ID: 'W000' - 'WZZZ', excluding 'WXXX'
+ // described in 4.3.2.>
+ // URL <text string>
+
+ $parsedFrame['url'] = trim($parsedFrame['data']);
+ if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
+ $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = $parsedFrame['url'];
+ }
+ unset($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion == 3) && ($parsedFrame['frame_name'] == 'IPLS')) || // 4.4 IPLS Involved people list (ID3v2.3 only)
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'IPL'))) { // 4.4 IPL Involved people list (ID3v2.2 only)
+ // http://id3.org/id3v2.3.0#sec4.4
+ // There may only be one 'IPL' frame in each tag
+ // <Header for 'User defined URL link frame', ID: 'IPL'>
+ // Text encoding $xx
+ // People list strings <textstrings>
+
+ $frame_offset = 0;
+ $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
+ $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
+ }
+ $parsedFrame['encodingid'] = $frame_textencoding;
+ $parsedFrame['encoding'] = $this->TextEncodingNameLookup($parsedFrame['encodingid']);
+ $parsedFrame['data_raw'] = (string) substr($parsedFrame['data'], $frame_offset);
+
+ // http://www.getid3.org/phpBB3/viewtopic.php?t=1369
+ // "this tag typically contains null terminated strings, which are associated in pairs"
+ // "there are users that use the tag incorrectly"
+ $IPLS_parts = array();
+ if (strpos($parsedFrame['data_raw'], "\x00") !== false) {
+ $IPLS_parts_unsorted = array();
+ if (((strlen($parsedFrame['data_raw']) % 2) == 0) && ((substr($parsedFrame['data_raw'], 0, 2) == "\xFF\xFE") || (substr($parsedFrame['data_raw'], 0, 2) == "\xFE\xFF"))) {
+ // UTF-16, be careful looking for null bytes since most 2-byte characters may contain one; you need to find twin null bytes, and on even padding
+ $thisILPS = '';
+ for ($i = 0; $i < strlen($parsedFrame['data_raw']); $i += 2) {
+ $twobytes = substr($parsedFrame['data_raw'], $i, 2);
+ if ($twobytes === "\x00\x00") {
+ $IPLS_parts_unsorted[] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $thisILPS);
+ $thisILPS = '';
+ } else {
+ $thisILPS .= $twobytes;
+ }
+ }
+ if (strlen($thisILPS) > 2) { // 2-byte BOM
+ $IPLS_parts_unsorted[] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $thisILPS);
+ }
+ } else {
+ // ISO-8859-1 or UTF-8 or other single-byte-null character set
+ $IPLS_parts_unsorted = explode("\x00", $parsedFrame['data_raw']);
+ }
+ if (count($IPLS_parts_unsorted) == 1) {
+ // just a list of names, e.g. "Dino Baptiste, Jimmy Copley, John Gordon, Bernie Marsden, Sharon Watson"
+ foreach ($IPLS_parts_unsorted as $key => $value) {
+ $IPLS_parts_sorted = preg_split('#[;,\\r\\n\\t]#', $value);
+ $position = '';
+ foreach ($IPLS_parts_sorted as $person) {
+ $IPLS_parts[] = array('position'=>$position, 'person'=>$person);
+ }
+ }
+ } elseif ((count($IPLS_parts_unsorted) % 2) == 0) {
+ $position = '';
+ $person = '';
+ foreach ($IPLS_parts_unsorted as $key => $value) {
+ if (($key % 2) == 0) {
+ $position = $value;
+ } else {
+ $person = $value;
+ $IPLS_parts[] = array('position'=>$position, 'person'=>$person);
+ $position = '';
+ $person = '';
+ }
+ }
+ } else {
+ foreach ($IPLS_parts_unsorted as $key => $value) {
+ $IPLS_parts[] = array($value);
+ }
+ }
+
+ } else {
+ $IPLS_parts = preg_split('#[;,\\r\\n\\t]#', $parsedFrame['data_raw']);
+ }
+ $parsedFrame['data'] = $IPLS_parts;
+
+ if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
+ $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = $parsedFrame['data'];
+ }
+
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'MCDI')) || // 4.4 MCDI Music CD identifier
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'MCI'))) { // 4.5 MCI Music CD identifier
+ // There may only be one 'MCDI' frame in each tag
+ // <Header for 'Music CD identifier', ID: 'MCDI'>
+ // CD TOC <binary data>
+
+ if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
+ $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = $parsedFrame['data'];
+ }
+
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'ETCO')) || // 4.5 ETCO Event timing codes
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'ETC'))) { // 4.6 ETC Event timing codes
+ // There may only be one 'ETCO' frame in each tag
+ // <Header for 'Event timing codes', ID: 'ETCO'>
+ // Time stamp format $xx
+ // Where time stamp format is:
+ // $01 (32-bit value) MPEG frames from beginning of file
+ // $02 (32-bit value) milliseconds from beginning of file
+ // Followed by a list of key events in the following format:
+ // Type of event $xx
+ // Time stamp $xx (xx ...)
+ // The 'Time stamp' is set to zero if directly at the beginning of the sound
+ // or after the previous event. All events MUST be sorted in chronological order.
+
+ $frame_offset = 0;
+ $parsedFrame['timestampformat'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+
+ while ($frame_offset < strlen($parsedFrame['data'])) {
+ $parsedFrame['typeid'] = substr($parsedFrame['data'], $frame_offset++, 1);
+ $parsedFrame['type'] = $this->ETCOEventLookup($parsedFrame['typeid']);
+ $parsedFrame['timestamp'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4));
+ $frame_offset += 4;
+ }
+ unset($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'MLLT')) || // 4.6 MLLT MPEG location lookup table
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'MLL'))) { // 4.7 MLL MPEG location lookup table
+ // There may only be one 'MLLT' frame in each tag
+ // <Header for 'Location lookup table', ID: 'MLLT'>
+ // MPEG frames between reference $xx xx
+ // Bytes between reference $xx xx xx
+ // Milliseconds between reference $xx xx xx
+ // Bits for bytes deviation $xx
+ // Bits for milliseconds dev. $xx
+ // Then for every reference the following data is included;
+ // Deviation in bytes %xxx....
+ // Deviation in milliseconds %xxx....
+
+ $frame_offset = 0;
+ $parsedFrame['framesbetweenreferences'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 0, 2));
+ $parsedFrame['bytesbetweenreferences'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 2, 3));
+ $parsedFrame['msbetweenreferences'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 5, 3));
+ $parsedFrame['bitsforbytesdeviation'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 8, 1));
+ $parsedFrame['bitsformsdeviation'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 9, 1));
+ $parsedFrame['data'] = substr($parsedFrame['data'], 10);
+ while ($frame_offset < strlen($parsedFrame['data'])) {
+ $deviationbitstream .= getid3_lib::BigEndian2Bin(substr($parsedFrame['data'], $frame_offset++, 1));
+ }
+ $reference_counter = 0;
+ while (strlen($deviationbitstream) > 0) {
+ $parsedFrame[$reference_counter]['bytedeviation'] = bindec(substr($deviationbitstream, 0, $parsedFrame['bitsforbytesdeviation']));
+ $parsedFrame[$reference_counter]['msdeviation'] = bindec(substr($deviationbitstream, $parsedFrame['bitsforbytesdeviation'], $parsedFrame['bitsformsdeviation']));
+ $deviationbitstream = substr($deviationbitstream, $parsedFrame['bitsforbytesdeviation'] + $parsedFrame['bitsformsdeviation']);
+ $reference_counter++;
+ }
+ unset($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'SYTC')) || // 4.7 SYTC Synchronised tempo codes
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'STC'))) { // 4.8 STC Synchronised tempo codes
+ // There may only be one 'SYTC' frame in each tag
+ // <Header for 'Synchronised tempo codes', ID: 'SYTC'>
+ // Time stamp format $xx
+ // Tempo data <binary data>
+ // Where time stamp format is:
+ // $01 (32-bit value) MPEG frames from beginning of file
+ // $02 (32-bit value) milliseconds from beginning of file
+
+ $frame_offset = 0;
+ $parsedFrame['timestampformat'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $timestamp_counter = 0;
+ while ($frame_offset < strlen($parsedFrame['data'])) {
+ $parsedFrame[$timestamp_counter]['tempo'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ if ($parsedFrame[$timestamp_counter]['tempo'] == 255) {
+ $parsedFrame[$timestamp_counter]['tempo'] += ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ }
+ $parsedFrame[$timestamp_counter]['timestamp'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4));
+ $frame_offset += 4;
+ $timestamp_counter++;
+ }
+ unset($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'USLT')) || // 4.8 USLT Unsynchronised lyric/text transcription
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'ULT'))) { // 4.9 ULT Unsynchronised lyric/text transcription
+ // There may be more than one 'Unsynchronised lyrics/text transcription' frame
+ // in each tag, but only one with the same language and content descriptor.
+ // <Header for 'Unsynchronised lyrics/text transcription', ID: 'USLT'>
+ // Text encoding $xx
+ // Language $xx xx xx
+ // Content descriptor <text string according to encoding> $00 (00)
+ // Lyrics/text <full text string according to encoding>
+
+ $frame_offset = 0;
+ $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
+ $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
+ }
+ $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
+ $frame_offset += 3;
+ $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
+ if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
+ $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
+ }
+ $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_description) === 0) {
+ $frame_description = '';
+ }
+ $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)));
+
+ $parsedFrame['encodingid'] = $frame_textencoding;
+ $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
+
+ $parsedFrame['data'] = $parsedFrame['data'];
+ $parsedFrame['language'] = $frame_language;
+ $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
+ $parsedFrame['description'] = $frame_description;
+ if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
+ $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']);
+ }
+ unset($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'SYLT')) || // 4.9 SYLT Synchronised lyric/text
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'SLT'))) { // 4.10 SLT Synchronised lyric/text
+ // There may be more than one 'SYLT' frame in each tag,
+ // but only one with the same language and content descriptor.
+ // <Header for 'Synchronised lyrics/text', ID: 'SYLT'>
+ // Text encoding $xx
+ // Language $xx xx xx
+ // Time stamp format $xx
+ // $01 (32-bit value) MPEG frames from beginning of file
+ // $02 (32-bit value) milliseconds from beginning of file
+ // Content type $xx
+ // Content descriptor <text string according to encoding> $00 (00)
+ // Terminated text to be synced (typically a syllable)
+ // Sync identifier (terminator to above string) $00 (00)
+ // Time stamp $xx (xx ...)
+
+ $frame_offset = 0;
+ $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
+ $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
+ }
+ $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
+ $frame_offset += 3;
+ $parsedFrame['timestampformat'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['contenttypeid'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['contenttype'] = $this->SYTLContentTypeLookup($parsedFrame['contenttypeid']);
+ $parsedFrame['encodingid'] = $frame_textencoding;
+ $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
+
+ $parsedFrame['language'] = $frame_language;
+ $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
+
+ $timestampindex = 0;
+ $frame_remainingdata = substr($parsedFrame['data'], $frame_offset);
+ while (strlen($frame_remainingdata)) {
+ $frame_offset = 0;
+ $frame_terminatorpos = strpos($frame_remainingdata, $this->TextEncodingTerminatorLookup($frame_textencoding));
+ if ($frame_terminatorpos === false) {
+ $frame_remainingdata = '';
+ } else {
+ if (ord(substr($frame_remainingdata, $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
+ $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
+ }
+ $parsedFrame['lyrics'][$timestampindex]['data'] = substr($frame_remainingdata, $frame_offset, $frame_terminatorpos - $frame_offset);
+
+ $frame_remainingdata = substr($frame_remainingdata, $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)));
+ if (($timestampindex == 0) && (ord($frame_remainingdata{0}) != 0)) {
+ // timestamp probably omitted for first data item
+ } else {
+ $parsedFrame['lyrics'][$timestampindex]['timestamp'] = getid3_lib::BigEndian2Int(substr($frame_remainingdata, 0, 4));
+ $frame_remainingdata = substr($frame_remainingdata, 4);
+ }
+ $timestampindex++;
+ }
+ }
+ unset($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'COMM')) || // 4.10 COMM Comments
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'COM'))) { // 4.11 COM Comments
+ // There may be more than one comment frame in each tag,
+ // but only one with the same language and content descriptor.
+ // <Header for 'Comment', ID: 'COMM'>
+ // Text encoding $xx
+ // Language $xx xx xx
+ // Short content descrip. <text string according to encoding> $00 (00)
+ // The actual text <full text string according to encoding>
+
+ if (strlen($parsedFrame['data']) < 5) {
+
+ $info['warning'][] = 'Invalid data (too short) for "'.$parsedFrame['frame_name'].'" frame at offset '.$parsedFrame['dataoffset'];
+
+ } else {
+
+ $frame_offset = 0;
+ $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
+ $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
+ }
+ $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
+ $frame_offset += 3;
+ $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
+ if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
+ $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
+ }
+ $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_description) === 0) {
+ $frame_description = '';
+ }
+ $frame_text = (string) substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)));
+
+ $parsedFrame['encodingid'] = $frame_textencoding;
+ $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
+
+ $parsedFrame['language'] = $frame_language;
+ $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
+ $parsedFrame['description'] = $frame_description;
+ $parsedFrame['data'] = $frame_text;
+ if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
+ $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']);
+ }
+
+ }
+
+ } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'RVA2')) { // 4.11 RVA2 Relative volume adjustment (2) (ID3v2.4+ only)
+ // There may be more than one 'RVA2' frame in each tag,
+ // but only one with the same identification string
+ // <Header for 'Relative volume adjustment (2)', ID: 'RVA2'>
+ // Identification <text string> $00
+ // The 'identification' string is used to identify the situation and/or
+ // device where this adjustment should apply. The following is then
+ // repeated for every channel:
+ // Type of channel $xx
+ // Volume adjustment $xx xx
+ // Bits representing peak $xx
+ // Peak volume $xx (xx ...)
+
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00");
+ $frame_idstring = substr($parsedFrame['data'], 0, $frame_terminatorpos);
+ if (ord($frame_idstring) === 0) {
+ $frame_idstring = '';
+ }
+ $frame_remainingdata = substr($parsedFrame['data'], $frame_terminatorpos + strlen("\x00"));
+ $parsedFrame['description'] = $frame_idstring;
+ $RVA2channelcounter = 0;
+ while (strlen($frame_remainingdata) >= 5) {
+ $frame_offset = 0;
+ $frame_channeltypeid = ord(substr($frame_remainingdata, $frame_offset++, 1));
+ $parsedFrame[$RVA2channelcounter]['channeltypeid'] = $frame_channeltypeid;
+ $parsedFrame[$RVA2channelcounter]['channeltype'] = $this->RVA2ChannelTypeLookup($frame_channeltypeid);
+ $parsedFrame[$RVA2channelcounter]['volumeadjust'] = getid3_lib::BigEndian2Int(substr($frame_remainingdata, $frame_offset, 2), false, true); // 16-bit signed
+ $frame_offset += 2;
+ $parsedFrame[$RVA2channelcounter]['bitspeakvolume'] = ord(substr($frame_remainingdata, $frame_offset++, 1));
+ if (($parsedFrame[$RVA2channelcounter]['bitspeakvolume'] < 1) || ($parsedFrame[$RVA2channelcounter]['bitspeakvolume'] > 4)) {
+ $info['warning'][] = 'ID3v2::RVA2 frame['.$RVA2channelcounter.'] contains invalid '.$parsedFrame[$RVA2channelcounter]['bitspeakvolume'].'-byte bits-representing-peak value';
+ break;
+ }
+ $frame_bytespeakvolume = ceil($parsedFrame[$RVA2channelcounter]['bitspeakvolume'] / 8);
+ $parsedFrame[$RVA2channelcounter]['peakvolume'] = getid3_lib::BigEndian2Int(substr($frame_remainingdata, $frame_offset, $frame_bytespeakvolume));
+ $frame_remainingdata = substr($frame_remainingdata, $frame_offset + $frame_bytespeakvolume);
+ $RVA2channelcounter++;
+ }
+ unset($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion == 3) && ($parsedFrame['frame_name'] == 'RVAD')) || // 4.12 RVAD Relative volume adjustment (ID3v2.3 only)
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'RVA'))) { // 4.12 RVA Relative volume adjustment (ID3v2.2 only)
+ // There may only be one 'RVA' frame in each tag
+ // <Header for 'Relative volume adjustment', ID: 'RVA'>
+ // ID3v2.2 => Increment/decrement %000000ba
+ // ID3v2.3 => Increment/decrement %00fedcba
+ // Bits used for volume descr. $xx
+ // Relative volume change, right $xx xx (xx ...) // a
+ // Relative volume change, left $xx xx (xx ...) // b
+ // Peak volume right $xx xx (xx ...)
+ // Peak volume left $xx xx (xx ...)
+ // ID3v2.3 only, optional (not present in ID3v2.2):
+ // Relative volume change, right back $xx xx (xx ...) // c
+ // Relative volume change, left back $xx xx (xx ...) // d
+ // Peak volume right back $xx xx (xx ...)
+ // Peak volume left back $xx xx (xx ...)
+ // ID3v2.3 only, optional (not present in ID3v2.2):
+ // Relative volume change, center $xx xx (xx ...) // e
+ // Peak volume center $xx xx (xx ...)
+ // ID3v2.3 only, optional (not present in ID3v2.2):
+ // Relative volume change, bass $xx xx (xx ...) // f
+ // Peak volume bass $xx xx (xx ...)
+
+ $frame_offset = 0;
+ $frame_incrdecrflags = getid3_lib::BigEndian2Bin(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['incdec']['right'] = (bool) substr($frame_incrdecrflags, 6, 1);
+ $parsedFrame['incdec']['left'] = (bool) substr($frame_incrdecrflags, 7, 1);
+ $parsedFrame['bitsvolume'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $frame_bytesvolume = ceil($parsedFrame['bitsvolume'] / 8);
+ $parsedFrame['volumechange']['right'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume));
+ if ($parsedFrame['incdec']['right'] === false) {
+ $parsedFrame['volumechange']['right'] *= -1;
+ }
+ $frame_offset += $frame_bytesvolume;
+ $parsedFrame['volumechange']['left'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume));
+ if ($parsedFrame['incdec']['left'] === false) {
+ $parsedFrame['volumechange']['left'] *= -1;
+ }
+ $frame_offset += $frame_bytesvolume;
+ $parsedFrame['peakvolume']['right'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume));
+ $frame_offset += $frame_bytesvolume;
+ $parsedFrame['peakvolume']['left'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume));
+ $frame_offset += $frame_bytesvolume;
+ if ($id3v2_majorversion == 3) {
+ $parsedFrame['data'] = substr($parsedFrame['data'], $frame_offset);
+ if (strlen($parsedFrame['data']) > 0) {
+ $parsedFrame['incdec']['rightrear'] = (bool) substr($frame_incrdecrflags, 4, 1);
+ $parsedFrame['incdec']['leftrear'] = (bool) substr($frame_incrdecrflags, 5, 1);
+ $parsedFrame['volumechange']['rightrear'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume));
+ if ($parsedFrame['incdec']['rightrear'] === false) {
+ $parsedFrame['volumechange']['rightrear'] *= -1;
+ }
+ $frame_offset += $frame_bytesvolume;
+ $parsedFrame['volumechange']['leftrear'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume));
+ if ($parsedFrame['incdec']['leftrear'] === false) {
+ $parsedFrame['volumechange']['leftrear'] *= -1;
+ }
+ $frame_offset += $frame_bytesvolume;
+ $parsedFrame['peakvolume']['rightrear'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume));
+ $frame_offset += $frame_bytesvolume;
+ $parsedFrame['peakvolume']['leftrear'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume));
+ $frame_offset += $frame_bytesvolume;
+ }
+ $parsedFrame['data'] = substr($parsedFrame['data'], $frame_offset);
+ if (strlen($parsedFrame['data']) > 0) {
+ $parsedFrame['incdec']['center'] = (bool) substr($frame_incrdecrflags, 3, 1);
+ $parsedFrame['volumechange']['center'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume));
+ if ($parsedFrame['incdec']['center'] === false) {
+ $parsedFrame['volumechange']['center'] *= -1;
+ }
+ $frame_offset += $frame_bytesvolume;
+ $parsedFrame['peakvolume']['center'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume));
+ $frame_offset += $frame_bytesvolume;
+ }
+ $parsedFrame['data'] = substr($parsedFrame['data'], $frame_offset);
+ if (strlen($parsedFrame['data']) > 0) {
+ $parsedFrame['incdec']['bass'] = (bool) substr($frame_incrdecrflags, 2, 1);
+ $parsedFrame['volumechange']['bass'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume));
+ if ($parsedFrame['incdec']['bass'] === false) {
+ $parsedFrame['volumechange']['bass'] *= -1;
+ }
+ $frame_offset += $frame_bytesvolume;
+ $parsedFrame['peakvolume']['bass'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume));
+ $frame_offset += $frame_bytesvolume;
+ }
+ }
+ unset($parsedFrame['data']);
+
+
+ } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'EQU2')) { // 4.12 EQU2 Equalisation (2) (ID3v2.4+ only)
+ // There may be more than one 'EQU2' frame in each tag,
+ // but only one with the same identification string
+ // <Header of 'Equalisation (2)', ID: 'EQU2'>
+ // Interpolation method $xx
+ // $00 Band
+ // $01 Linear
+ // Identification <text string> $00
+ // The following is then repeated for every adjustment point
+ // Frequency $xx xx
+ // Volume adjustment $xx xx
+
+ $frame_offset = 0;
+ $frame_interpolationmethod = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_idstring = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_idstring) === 0) {
+ $frame_idstring = '';
+ }
+ $parsedFrame['description'] = $frame_idstring;
+ $frame_remainingdata = substr($parsedFrame['data'], $frame_terminatorpos + strlen("\x00"));
+ while (strlen($frame_remainingdata)) {
+ $frame_frequency = getid3_lib::BigEndian2Int(substr($frame_remainingdata, 0, 2)) / 2;
+ $parsedFrame['data'][$frame_frequency] = getid3_lib::BigEndian2Int(substr($frame_remainingdata, 2, 2), false, true);
+ $frame_remainingdata = substr($frame_remainingdata, 4);
+ }
+ $parsedFrame['interpolationmethod'] = $frame_interpolationmethod;
+ unset($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion == 3) && ($parsedFrame['frame_name'] == 'EQUA')) || // 4.12 EQUA Equalisation (ID3v2.3 only)
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'EQU'))) { // 4.13 EQU Equalisation (ID3v2.2 only)
+ // There may only be one 'EQUA' frame in each tag
+ // <Header for 'Relative volume adjustment', ID: 'EQU'>
+ // Adjustment bits $xx
+ // This is followed by 2 bytes + ('adjustment bits' rounded up to the
+ // nearest byte) for every equalisation band in the following format,
+ // giving a frequency range of 0 - 32767Hz:
+ // Increment/decrement %x (MSB of the Frequency)
+ // Frequency (lower 15 bits)
+ // Adjustment $xx (xx ...)
+
+ $frame_offset = 0;
+ $parsedFrame['adjustmentbits'] = substr($parsedFrame['data'], $frame_offset++, 1);
+ $frame_adjustmentbytes = ceil($parsedFrame['adjustmentbits'] / 8);
+
+ $frame_remainingdata = (string) substr($parsedFrame['data'], $frame_offset);
+ while (strlen($frame_remainingdata) > 0) {
+ $frame_frequencystr = getid3_lib::BigEndian2Bin(substr($frame_remainingdata, 0, 2));
+ $frame_incdec = (bool) substr($frame_frequencystr, 0, 1);
+ $frame_frequency = bindec(substr($frame_frequencystr, 1, 15));
+ $parsedFrame[$frame_frequency]['incdec'] = $frame_incdec;
+ $parsedFrame[$frame_frequency]['adjustment'] = getid3_lib::BigEndian2Int(substr($frame_remainingdata, 2, $frame_adjustmentbytes));
+ if ($parsedFrame[$frame_frequency]['incdec'] === false) {
+ $parsedFrame[$frame_frequency]['adjustment'] *= -1;
+ }
+ $frame_remainingdata = substr($frame_remainingdata, 2 + $frame_adjustmentbytes);
+ }
+ unset($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'RVRB')) || // 4.13 RVRB Reverb
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'REV'))) { // 4.14 REV Reverb
+ // There may only be one 'RVRB' frame in each tag.
+ // <Header for 'Reverb', ID: 'RVRB'>
+ // Reverb left (ms) $xx xx
+ // Reverb right (ms) $xx xx
+ // Reverb bounces, left $xx
+ // Reverb bounces, right $xx
+ // Reverb feedback, left to left $xx
+ // Reverb feedback, left to right $xx
+ // Reverb feedback, right to right $xx
+ // Reverb feedback, right to left $xx
+ // Premix left to right $xx
+ // Premix right to left $xx
+
+ $frame_offset = 0;
+ $parsedFrame['left'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2));
+ $frame_offset += 2;
+ $parsedFrame['right'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2));
+ $frame_offset += 2;
+ $parsedFrame['bouncesL'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['bouncesR'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['feedbackLL'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['feedbackLR'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['feedbackRR'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['feedbackRL'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['premixLR'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['premixRL'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ unset($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'APIC')) || // 4.14 APIC Attached picture
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'PIC'))) { // 4.15 PIC Attached picture
+ // There may be several pictures attached to one file,
+ // each in their individual 'APIC' frame, but only one
+ // with the same content descriptor
+ // <Header for 'Attached picture', ID: 'APIC'>
+ // Text encoding $xx
+ // ID3v2.3+ => MIME type <text string> $00
+ // ID3v2.2 => Image format $xx xx xx
+ // Picture type $xx
+ // Description <text string according to encoding> $00 (00)
+ // Picture data <binary data>
+
+ $frame_offset = 0;
+ $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
+ $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
+ }
+
+ if ($id3v2_majorversion == 2 && strlen($parsedFrame['data']) > $frame_offset) {
+ $frame_imagetype = substr($parsedFrame['data'], $frame_offset, 3);
+ if (strtolower($frame_imagetype) == 'ima') {
+ // complete hack for mp3Rage (www.chaoticsoftware.com) that puts ID3v2.3-formatted
+ // MIME type instead of 3-char ID3v2.2-format image type (thanks xbhoffƘpacbell*net)
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_mimetype = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_mimetype) === 0) {
+ $frame_mimetype = '';
+ }
+ $frame_imagetype = strtoupper(str_replace('image/', '', strtolower($frame_mimetype)));
+ if ($frame_imagetype == 'JPEG') {
+ $frame_imagetype = 'JPG';
+ }
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+ } else {
+ $frame_offset += 3;
+ }
+ }
+ if ($id3v2_majorversion > 2 && strlen($parsedFrame['data']) > $frame_offset) {
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_mimetype = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_mimetype) === 0) {
+ $frame_mimetype = '';
+ }
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+ }
+
+ $frame_picturetype = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+
+ if ($frame_offset >= $parsedFrame['datalength']) {
+ $info['warning'][] = 'data portion of APIC frame is missing at offset '.($parsedFrame['dataoffset'] + 8 + $frame_offset);
+ } else {
+ $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
+ if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
+ $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
+ }
+ $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_description) === 0) {
+ $frame_description = '';
+ }
+ $parsedFrame['encodingid'] = $frame_textencoding;
+ $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
+
+ if ($id3v2_majorversion == 2) {
+ $parsedFrame['imagetype'] = $frame_imagetype;
+ } else {
+ $parsedFrame['mime'] = $frame_mimetype;
+ }
+ $parsedFrame['picturetypeid'] = $frame_picturetype;
+ $parsedFrame['picturetype'] = $this->APICPictureTypeLookup($frame_picturetype);
+ $parsedFrame['description'] = $frame_description;
+ $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)));
+ $parsedFrame['datalength'] = strlen($parsedFrame['data']);
+
+ $parsedFrame['image_mime'] = '';
+ $imageinfo = array();
+ $imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo);
+ if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
+ $parsedFrame['image_mime'] = 'image/'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]);
+ if ($imagechunkcheck[0]) {
+ $parsedFrame['image_width'] = $imagechunkcheck[0];
+ }
+ if ($imagechunkcheck[1]) {
+ $parsedFrame['image_height'] = $imagechunkcheck[1];
+ }
+ }
+
+ do {
+ if ($this->getid3->option_save_attachments === false) {
+ // skip entirely
+ unset($parsedFrame['data']);
+ break;
+ }
+ if ($this->getid3->option_save_attachments === true) {
+ // great
+/*
+ } elseif (is_int($this->getid3->option_save_attachments)) {
+ if ($this->getid3->option_save_attachments < $parsedFrame['data_length']) {
+ // too big, skip
+ $info['warning'][] = 'attachment at '.$frame_offset.' is too large to process inline ('.number_format($parsedFrame['data_length']).' bytes)';
+ unset($parsedFrame['data']);
+ break;
+ }
+*/
+ } elseif (is_string($this->getid3->option_save_attachments)) {
+ $dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR);
+ if (!is_dir($dir) || !is_writable($dir)) {
+ // cannot write, skip
+ $info['warning'][] = 'attachment at '.$frame_offset.' cannot be saved to "'.$dir.'" (not writable)';
+ unset($parsedFrame['data']);
+ break;
+ }
+ }
+ // if we get this far, must be OK
+ if (is_string($this->getid3->option_save_attachments)) {
+ $destination_filename = $dir.DIRECTORY_SEPARATOR.md5($info['filenamepath']).'_'.$frame_offset;
+ if (!file_exists($destination_filename) || is_writable($destination_filename)) {
+ file_put_contents($destination_filename, $parsedFrame['data']);
+ } else {
+ $info['warning'][] = 'attachment at '.$frame_offset.' cannot be saved to "'.$destination_filename.'" (not writable)';
+ }
+ $parsedFrame['data_filename'] = $destination_filename;
+ unset($parsedFrame['data']);
+ } else {
+ if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
+ if (!isset($info['id3v2']['comments']['picture'])) {
+ $info['id3v2']['comments']['picture'] = array();
+ }
+ $info['id3v2']['comments']['picture'][] = array('data'=>$parsedFrame['data'], 'image_mime'=>$parsedFrame['image_mime']);
+ }
+ }
+ } while (false);
+ }
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'GEOB')) || // 4.15 GEOB General encapsulated object
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'GEO'))) { // 4.16 GEO General encapsulated object
+ // There may be more than one 'GEOB' frame in each tag,
+ // but only one with the same content descriptor
+ // <Header for 'General encapsulated object', ID: 'GEOB'>
+ // Text encoding $xx
+ // MIME type <text string> $00
+ // Filename <text string according to encoding> $00 (00)
+ // Content description <text string according to encoding> $00 (00)
+ // Encapsulated object <binary data>
+
+ $frame_offset = 0;
+ $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
+ $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
+ }
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_mimetype = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_mimetype) === 0) {
+ $frame_mimetype = '';
+ }
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+
+ $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
+ if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
+ $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
+ }
+ $frame_filename = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_filename) === 0) {
+ $frame_filename = '';
+ }
+ $frame_offset = $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding));
+
+ $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
+ if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
+ $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
+ }
+ $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_description) === 0) {
+ $frame_description = '';
+ }
+ $frame_offset = $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding));
+
+ $parsedFrame['objectdata'] = (string) substr($parsedFrame['data'], $frame_offset);
+ $parsedFrame['encodingid'] = $frame_textencoding;
+ $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
+
+ $parsedFrame['mime'] = $frame_mimetype;
+ $parsedFrame['filename'] = $frame_filename;
+ $parsedFrame['description'] = $frame_description;
+ unset($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'PCNT')) || // 4.16 PCNT Play counter
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'CNT'))) { // 4.17 CNT Play counter
+ // There may only be one 'PCNT' frame in each tag.
+ // When the counter reaches all one's, one byte is inserted in
+ // front of the counter thus making the counter eight bits bigger
+ // <Header for 'Play counter', ID: 'PCNT'>
+ // Counter $xx xx xx xx (xx ...)
+
+ $parsedFrame['data'] = getid3_lib::BigEndian2Int($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'POPM')) || // 4.17 POPM Popularimeter
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'POP'))) { // 4.18 POP Popularimeter
+ // There may be more than one 'POPM' frame in each tag,
+ // but only one with the same email address
+ // <Header for 'Popularimeter', ID: 'POPM'>
+ // Email to user <text string> $00
+ // Rating $xx
+ // Counter $xx xx xx xx (xx ...)
+
+ $frame_offset = 0;
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_emailaddress = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_emailaddress) === 0) {
+ $frame_emailaddress = '';
+ }
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+ $frame_rating = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['counter'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset));
+ $parsedFrame['email'] = $frame_emailaddress;
+ $parsedFrame['rating'] = $frame_rating;
+ unset($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'RBUF')) || // 4.18 RBUF Recommended buffer size
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'BUF'))) { // 4.19 BUF Recommended buffer size
+ // There may only be one 'RBUF' frame in each tag
+ // <Header for 'Recommended buffer size', ID: 'RBUF'>
+ // Buffer size $xx xx xx
+ // Embedded info flag %0000000x
+ // Offset to next tag $xx xx xx xx
+
+ $frame_offset = 0;
+ $parsedFrame['buffersize'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 3));
+ $frame_offset += 3;
+
+ $frame_embeddedinfoflags = getid3_lib::BigEndian2Bin(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['flags']['embededinfo'] = (bool) substr($frame_embeddedinfoflags, 7, 1);
+ $parsedFrame['nexttagoffset'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4));
+ unset($parsedFrame['data']);
+
+
+ } elseif (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'CRM')) { // 4.20 Encrypted meta frame (ID3v2.2 only)
+ // There may be more than one 'CRM' frame in a tag,
+ // but only one with the same 'owner identifier'
+ // <Header for 'Encrypted meta frame', ID: 'CRM'>
+ // Owner identifier <textstring> $00 (00)
+ // Content/explanation <textstring> $00 (00)
+ // Encrypted datablock <binary data>
+
+ $frame_offset = 0;
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_ownerid = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_description) === 0) {
+ $frame_description = '';
+ }
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+
+ $parsedFrame['ownerid'] = $frame_ownerid;
+ $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
+ $parsedFrame['description'] = $frame_description;
+ unset($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'AENC')) || // 4.19 AENC Audio encryption
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'CRA'))) { // 4.21 CRA Audio encryption
+ // There may be more than one 'AENC' frames in a tag,
+ // but only one with the same 'Owner identifier'
+ // <Header for 'Audio encryption', ID: 'AENC'>
+ // Owner identifier <text string> $00
+ // Preview start $xx xx
+ // Preview length $xx xx
+ // Encryption info <binary data>
+
+ $frame_offset = 0;
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_ownerid = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_ownerid) === 0) {
+ $frame_ownerid == '';
+ }
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+ $parsedFrame['ownerid'] = $frame_ownerid;
+ $parsedFrame['previewstart'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2));
+ $frame_offset += 2;
+ $parsedFrame['previewlength'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2));
+ $frame_offset += 2;
+ $parsedFrame['encryptioninfo'] = (string) substr($parsedFrame['data'], $frame_offset);
+ unset($parsedFrame['data']);
+
+
+ } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'LINK')) || // 4.20 LINK Linked information
+ (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'LNK'))) { // 4.22 LNK Linked information
+ // There may be more than one 'LINK' frame in a tag,
+ // but only one with the same contents
+ // <Header for 'Linked information', ID: 'LINK'>
+ // ID3v2.3+ => Frame identifier $xx xx xx xx
+ // ID3v2.2 => Frame identifier $xx xx xx
+ // URL <text string> $00
+ // ID and additional data <text string(s)>
+
+ $frame_offset = 0;
+ if ($id3v2_majorversion == 2) {
+ $parsedFrame['frameid'] = substr($parsedFrame['data'], $frame_offset, 3);
+ $frame_offset += 3;
+ } else {
+ $parsedFrame['frameid'] = substr($parsedFrame['data'], $frame_offset, 4);
+ $frame_offset += 4;
+ }
+
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_url = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_url) === 0) {
+ $frame_url = '';
+ }
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+ $parsedFrame['url'] = $frame_url;
+
+ $parsedFrame['additionaldata'] = (string) substr($parsedFrame['data'], $frame_offset);
+ if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
+ $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = utf8_encode($parsedFrame['url']);
+ }
+ unset($parsedFrame['data']);
+
+
+ } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'POSS')) { // 4.21 POSS Position synchronisation frame (ID3v2.3+ only)
+ // There may only be one 'POSS' frame in each tag
+ // <Head for 'Position synchronisation', ID: 'POSS'>
+ // Time stamp format $xx
+ // Position $xx (xx ...)
+
+ $frame_offset = 0;
+ $parsedFrame['timestampformat'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['position'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset));
+ unset($parsedFrame['data']);
+
+
+ } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'USER')) { // 4.22 USER Terms of use (ID3v2.3+ only)
+ // There may be more than one 'Terms of use' frame in a tag,
+ // but only one with the same 'Language'
+ // <Header for 'Terms of use frame', ID: 'USER'>
+ // Text encoding $xx
+ // Language $xx xx xx
+ // The actual text <text string according to encoding>
+
+ $frame_offset = 0;
+ $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
+ $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
+ }
+ $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
+ $frame_offset += 3;
+ $parsedFrame['language'] = $frame_language;
+ $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
+ $parsedFrame['encodingid'] = $frame_textencoding;
+ $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
+
+ $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
+ if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
+ $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']);
+ }
+ unset($parsedFrame['data']);
+
+
+ } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'OWNE')) { // 4.23 OWNE Ownership frame (ID3v2.3+ only)
+ // There may only be one 'OWNE' frame in a tag
+ // <Header for 'Ownership frame', ID: 'OWNE'>
+ // Text encoding $xx
+ // Price paid <text string> $00
+ // Date of purch. <text string>
+ // Seller <text string according to encoding>
+
+ $frame_offset = 0;
+ $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
+ $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
+ }
+ $parsedFrame['encodingid'] = $frame_textencoding;
+ $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
+
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_pricepaid = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+
+ $parsedFrame['pricepaid']['currencyid'] = substr($frame_pricepaid, 0, 3);
+ $parsedFrame['pricepaid']['currency'] = $this->LookupCurrencyUnits($parsedFrame['pricepaid']['currencyid']);
+ $parsedFrame['pricepaid']['value'] = substr($frame_pricepaid, 3);
+
+ $parsedFrame['purchasedate'] = substr($parsedFrame['data'], $frame_offset, 8);
+ if (!$this->IsValidDateStampString($parsedFrame['purchasedate'])) {
+ $parsedFrame['purchasedateunix'] = mktime (0, 0, 0, substr($parsedFrame['purchasedate'], 4, 2), substr($parsedFrame['purchasedate'], 6, 2), substr($parsedFrame['purchasedate'], 0, 4));
+ }
+ $frame_offset += 8;
+
+ $parsedFrame['seller'] = (string) substr($parsedFrame['data'], $frame_offset);
+ unset($parsedFrame['data']);
+
+
+ } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'COMR')) { // 4.24 COMR Commercial frame (ID3v2.3+ only)
+ // There may be more than one 'commercial frame' in a tag,
+ // but no two may be identical
+ // <Header for 'Commercial frame', ID: 'COMR'>
+ // Text encoding $xx
+ // Price string <text string> $00
+ // Valid until <text string>
+ // Contact URL <text string> $00
+ // Received as $xx
+ // Name of seller <text string according to encoding> $00 (00)
+ // Description <text string according to encoding> $00 (00)
+ // Picture MIME type <string> $00
+ // Seller logo <binary data>
+
+ $frame_offset = 0;
+ $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
+ $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
+ }
+
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_pricestring = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+ $frame_rawpricearray = explode('/', $frame_pricestring);
+ foreach ($frame_rawpricearray as $key => $val) {
+ $frame_currencyid = substr($val, 0, 3);
+ $parsedFrame['price'][$frame_currencyid]['currency'] = $this->LookupCurrencyUnits($frame_currencyid);
+ $parsedFrame['price'][$frame_currencyid]['value'] = substr($val, 3);
+ }
+
+ $frame_datestring = substr($parsedFrame['data'], $frame_offset, 8);
+ $frame_offset += 8;
+
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_contacturl = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+
+ $frame_receivedasid = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+
+ $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
+ if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
+ $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
+ }
+ $frame_sellername = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_sellername) === 0) {
+ $frame_sellername = '';
+ }
+ $frame_offset = $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding));
+
+ $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
+ if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
+ $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
+ }
+ $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_description) === 0) {
+ $frame_description = '';
+ }
+ $frame_offset = $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding));
+
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_mimetype = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+
+ $frame_sellerlogo = substr($parsedFrame['data'], $frame_offset);
+
+ $parsedFrame['encodingid'] = $frame_textencoding;
+ $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
+
+ $parsedFrame['pricevaliduntil'] = $frame_datestring;
+ $parsedFrame['contacturl'] = $frame_contacturl;
+ $parsedFrame['receivedasid'] = $frame_receivedasid;
+ $parsedFrame['receivedas'] = $this->COMRReceivedAsLookup($frame_receivedasid);
+ $parsedFrame['sellername'] = $frame_sellername;
+ $parsedFrame['description'] = $frame_description;
+ $parsedFrame['mime'] = $frame_mimetype;
+ $parsedFrame['logo'] = $frame_sellerlogo;
+ unset($parsedFrame['data']);
+
+
+ } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'ENCR')) { // 4.25 ENCR Encryption method registration (ID3v2.3+ only)
+ // There may be several 'ENCR' frames in a tag,
+ // but only one containing the same symbol
+ // and only one containing the same owner identifier
+ // <Header for 'Encryption method registration', ID: 'ENCR'>
+ // Owner identifier <text string> $00
+ // Method symbol $xx
+ // Encryption data <binary data>
+
+ $frame_offset = 0;
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_ownerid = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_ownerid) === 0) {
+ $frame_ownerid = '';
+ }
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+
+ $parsedFrame['ownerid'] = $frame_ownerid;
+ $parsedFrame['methodsymbol'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
+
+
+ } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'GRID')) { // 4.26 GRID Group identification registration (ID3v2.3+ only)
+
+ // There may be several 'GRID' frames in a tag,
+ // but only one containing the same symbol
+ // and only one containing the same owner identifier
+ // <Header for 'Group ID registration', ID: 'GRID'>
+ // Owner identifier <text string> $00
+ // Group symbol $xx
+ // Group dependent data <binary data>
+
+ $frame_offset = 0;
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_ownerid = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_ownerid) === 0) {
+ $frame_ownerid = '';
+ }
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+
+ $parsedFrame['ownerid'] = $frame_ownerid;
+ $parsedFrame['groupsymbol'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
+
+
+ } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'PRIV')) { // 4.27 PRIV Private frame (ID3v2.3+ only)
+ // The tag may contain more than one 'PRIV' frame
+ // but only with different contents
+ // <Header for 'Private frame', ID: 'PRIV'>
+ // Owner identifier <text string> $00
+ // The private data <binary data>
+
+ $frame_offset = 0;
+ $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
+ $frame_ownerid = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+ if (ord($frame_ownerid) === 0) {
+ $frame_ownerid = '';
+ }
+ $frame_offset = $frame_terminatorpos + strlen("\x00");
+
+ $parsedFrame['ownerid'] = $frame_ownerid;
+ $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
+
+
+ } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'SIGN')) { // 4.28 SIGN Signature frame (ID3v2.4+ only)
+ // There may be more than one 'signature frame' in a tag,
+ // but no two may be identical
+ // <Header for 'Signature frame', ID: 'SIGN'>
+ // Group symbol $xx
+ // Signature <binary data>
+
+ $frame_offset = 0;
+ $parsedFrame['groupsymbol'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
+
+
+ } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'SEEK')) { // 4.29 SEEK Seek frame (ID3v2.4+ only)
+ // There may only be one 'seek frame' in a tag
+ // <Header for 'Seek frame', ID: 'SEEK'>
+ // Minimum offset to next tag $xx xx xx xx
+
+ $frame_offset = 0;
+ $parsedFrame['data'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4));
+
+
+ } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'ASPI')) { // 4.30 ASPI Audio seek point index (ID3v2.4+ only)
+ // There may only be one 'audio seek point index' frame in a tag
+ // <Header for 'Seek Point Index', ID: 'ASPI'>
+ // Indexed data start (S) $xx xx xx xx
+ // Indexed data length (L) $xx xx xx xx
+ // Number of index points (N) $xx xx
+ // Bits per index point (b) $xx
+ // Then for every index point the following data is included:
+ // Fraction at index (Fi) $xx (xx)
+
+ $frame_offset = 0;
+ $parsedFrame['datastart'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4));
+ $frame_offset += 4;
+ $parsedFrame['indexeddatalength'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4));
+ $frame_offset += 4;
+ $parsedFrame['indexpoints'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2));
+ $frame_offset += 2;
+ $parsedFrame['bitsperpoint'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
+ $frame_bytesperpoint = ceil($parsedFrame['bitsperpoint'] / 8);
+ for ($i = 0; $i < $frame_indexpoints; $i++) {
+ $parsedFrame['indexes'][$i] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesperpoint));
+ $frame_offset += $frame_bytesperpoint;
+ }
+ unset($parsedFrame['data']);
+
+ } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'RGAD')) { // Replay Gain Adjustment
+ // http://privatewww.essex.ac.uk/~djmrob/replaygain/file_format_id3v2.html
+ // There may only be one 'RGAD' frame in a tag
+ // <Header for 'Replay Gain Adjustment', ID: 'RGAD'>
+ // Peak Amplitude $xx $xx $xx $xx
+ // Radio Replay Gain Adjustment %aaabbbcd %dddddddd
+ // Audiophile Replay Gain Adjustment %aaabbbcd %dddddddd
+ // a - name code
+ // b - originator code
+ // c - sign bit
+ // d - replay gain adjustment
+
+ $frame_offset = 0;
+ $parsedFrame['peakamplitude'] = getid3_lib::BigEndian2Float(substr($parsedFrame['data'], $frame_offset, 4));
+ $frame_offset += 4;
+ $rg_track_adjustment = getid3_lib::Dec2Bin(substr($parsedFrame['data'], $frame_offset, 2));
+ $frame_offset += 2;
+ $rg_album_adjustment = getid3_lib::Dec2Bin(substr($parsedFrame['data'], $frame_offset, 2));
+ $frame_offset += 2;
+ $parsedFrame['raw']['track']['name'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 0, 3));
+ $parsedFrame['raw']['track']['originator'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 3, 3));
+ $parsedFrame['raw']['track']['signbit'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 6, 1));
+ $parsedFrame['raw']['track']['adjustment'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 7, 9));
+ $parsedFrame['raw']['album']['name'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 0, 3));
+ $parsedFrame['raw']['album']['originator'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 3, 3));
+ $parsedFrame['raw']['album']['signbit'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 6, 1));
+ $parsedFrame['raw']['album']['adjustment'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 7, 9));
+ $parsedFrame['track']['name'] = getid3_lib::RGADnameLookup($parsedFrame['raw']['track']['name']);
+ $parsedFrame['track']['originator'] = getid3_lib::RGADoriginatorLookup($parsedFrame['raw']['track']['originator']);
+ $parsedFrame['track']['adjustment'] = getid3_lib::RGADadjustmentLookup($parsedFrame['raw']['track']['adjustment'], $parsedFrame['raw']['track']['signbit']);
+ $parsedFrame['album']['name'] = getid3_lib::RGADnameLookup($parsedFrame['raw']['album']['name']);
+ $parsedFrame['album']['originator'] = getid3_lib::RGADoriginatorLookup($parsedFrame['raw']['album']['originator']);
+ $parsedFrame['album']['adjustment'] = getid3_lib::RGADadjustmentLookup($parsedFrame['raw']['album']['adjustment'], $parsedFrame['raw']['album']['signbit']);
+
+ $info['replay_gain']['track']['peak'] = $parsedFrame['peakamplitude'];
+ $info['replay_gain']['track']['originator'] = $parsedFrame['track']['originator'];
+ $info['replay_gain']['track']['adjustment'] = $parsedFrame['track']['adjustment'];
+ $info['replay_gain']['album']['originator'] = $parsedFrame['album']['originator'];
+ $info['replay_gain']['album']['adjustment'] = $parsedFrame['album']['adjustment'];
+
+ unset($parsedFrame['data']);
+
+ }
+
+ return true;
+ }
+
+
+ public function DeUnsynchronise($data) {
+ return str_replace("\xFF\x00", "\xFF", $data);
+ }
+
+ public function LookupExtendedHeaderRestrictionsTagSizeLimits($index) {
+ static $LookupExtendedHeaderRestrictionsTagSizeLimits = array(
+ 0x00 => 'No more than 128 frames and 1 MB total tag size',
+ 0x01 => 'No more than 64 frames and 128 KB total tag size',
+ 0x02 => 'No more than 32 frames and 40 KB total tag size',
+ 0x03 => 'No more than 32 frames and 4 KB total tag size',
+ );
+ return (isset($LookupExtendedHeaderRestrictionsTagSizeLimits[$index]) ? $LookupExtendedHeaderRestrictionsTagSizeLimits[$index] : '');
+ }
+
+ public function LookupExtendedHeaderRestrictionsTextEncodings($index) {
+ static $LookupExtendedHeaderRestrictionsTextEncodings = array(
+ 0x00 => 'No restrictions',
+ 0x01 => 'Strings are only encoded with ISO-8859-1 or UTF-8',
+ );
+ return (isset($LookupExtendedHeaderRestrictionsTextEncodings[$index]) ? $LookupExtendedHeaderRestrictionsTextEncodings[$index] : '');
+ }
+
+ public function LookupExtendedHeaderRestrictionsTextFieldSize($index) {
+ static $LookupExtendedHeaderRestrictionsTextFieldSize = array(
+ 0x00 => 'No restrictions',
+ 0x01 => 'No string is longer than 1024 characters',
+ 0x02 => 'No string is longer than 128 characters',
+ 0x03 => 'No string is longer than 30 characters',
+ );
+ return (isset($LookupExtendedHeaderRestrictionsTextFieldSize[$index]) ? $LookupExtendedHeaderRestrictionsTextFieldSize[$index] : '');
+ }
+
+ public function LookupExtendedHeaderRestrictionsImageEncoding($index) {
+ static $LookupExtendedHeaderRestrictionsImageEncoding = array(
+ 0x00 => 'No restrictions',
+ 0x01 => 'Images are encoded only with PNG or JPEG',
+ );
+ return (isset($LookupExtendedHeaderRestrictionsImageEncoding[$index]) ? $LookupExtendedHeaderRestrictionsImageEncoding[$index] : '');
+ }
+
+ public function LookupExtendedHeaderRestrictionsImageSizeSize($index) {
+ static $LookupExtendedHeaderRestrictionsImageSizeSize = array(
+ 0x00 => 'No restrictions',
+ 0x01 => 'All images are 256x256 pixels or smaller',
+ 0x02 => 'All images are 64x64 pixels or smaller',
+ 0x03 => 'All images are exactly 64x64 pixels, unless required otherwise',
+ );
+ return (isset($LookupExtendedHeaderRestrictionsImageSizeSize[$index]) ? $LookupExtendedHeaderRestrictionsImageSizeSize[$index] : '');
+ }
+
+ public function LookupCurrencyUnits($currencyid) {
+
+ $begin = __LINE__;
+
+ /** This is not a comment!
+
+
+ AED Dirhams
+ AFA Afghanis
+ ALL Leke
+ AMD Drams
+ ANG Guilders
+ AOA Kwanza
+ ARS Pesos
+ ATS Schillings
+ AUD Dollars
+ AWG Guilders
+ AZM Manats
+ BAM Convertible Marka
+ BBD Dollars
+ BDT Taka
+ BEF Francs
+ BGL Leva
+ BHD Dinars
+ BIF Francs
+ BMD Dollars
+ BND Dollars
+ BOB Bolivianos
+ BRL Brazil Real
+ BSD Dollars
+ BTN Ngultrum
+ BWP Pulas
+ BYR Rubles
+ BZD Dollars
+ CAD Dollars
+ CDF Congolese Francs
+ CHF Francs
+ CLP Pesos
+ CNY Yuan Renminbi
+ COP Pesos
+ CRC Colones
+ CUP Pesos
+ CVE Escudos
+ CYP Pounds
+ CZK Koruny
+ DEM Deutsche Marks
+ DJF Francs
+ DKK Kroner
+ DOP Pesos
+ DZD Algeria Dinars
+ EEK Krooni
+ EGP Pounds
+ ERN Nakfa
+ ESP Pesetas
+ ETB Birr
+ EUR Euro
+ FIM Markkaa
+ FJD Dollars
+ FKP Pounds
+ FRF Francs
+ GBP Pounds
+ GEL Lari
+ GGP Pounds
+ GHC Cedis
+ GIP Pounds
+ GMD Dalasi
+ GNF Francs
+ GRD Drachmae
+ GTQ Quetzales
+ GYD Dollars
+ HKD Dollars
+ HNL Lempiras
+ HRK Kuna
+ HTG Gourdes
+ HUF Forints
+ IDR Rupiahs
+ IEP Pounds
+ ILS New Shekels
+ IMP Pounds
+ INR Rupees
+ IQD Dinars
+ IRR Rials
+ ISK Kronur
+ ITL Lire
+ JEP Pounds
+ JMD Dollars
+ JOD Dinars
+ JPY Yen
+ KES Shillings
+ KGS Soms
+ KHR Riels
+ KMF Francs
+ KPW Won
+ KWD Dinars
+ KYD Dollars
+ KZT Tenge
+ LAK Kips
+ LBP Pounds
+ LKR Rupees
+ LRD Dollars
+ LSL Maloti
+ LTL Litai
+ LUF Francs
+ LVL Lati
+ LYD Dinars
+ MAD Dirhams
+ MDL Lei
+ MGF Malagasy Francs
+ MKD Denars
+ MMK Kyats
+ MNT Tugriks
+ MOP Patacas
+ MRO Ouguiyas
+ MTL Liri
+ MUR Rupees
+ MVR Rufiyaa
+ MWK Kwachas
+ MXN Pesos
+ MYR Ringgits
+ MZM Meticais
+ NAD Dollars
+ NGN Nairas
+ NIO Gold Cordobas
+ NLG Guilders
+ NOK Krone
+ NPR Nepal Rupees
+ NZD Dollars
+ OMR Rials
+ PAB Balboa
+ PEN Nuevos Soles
+ PGK Kina
+ PHP Pesos
+ PKR Rupees
+ PLN Zlotych
+ PTE Escudos
+ PYG Guarani
+ QAR Rials
+ ROL Lei
+ RUR Rubles
+ RWF Rwanda Francs
+ SAR Riyals
+ SBD Dollars
+ SCR Rupees
+ SDD Dinars
+ SEK Kronor
+ SGD Dollars
+ SHP Pounds
+ SIT Tolars
+ SKK Koruny
+ SLL Leones
+ SOS Shillings
+ SPL Luigini
+ SRG Guilders
+ STD Dobras
+ SVC Colones
+ SYP Pounds
+ SZL Emalangeni
+ THB Baht
+ TJR Rubles
+ TMM Manats
+ TND Dinars
+ TOP Pa'anga
+ TRL Liras
+ TTD Dollars
+ TVD Tuvalu Dollars
+ TWD New Dollars
+ TZS Shillings
+ UAH Hryvnia
+ UGX Shillings
+ USD Dollars
+ UYU Pesos
+ UZS Sums
+ VAL Lire
+ VEB Bolivares
+ VND Dong
+ VUV Vatu
+ WST Tala
+ XAF Francs
+ XAG Ounces
+ XAU Ounces
+ XCD Dollars
+ XDR Special Drawing Rights
+ XPD Ounces
+ XPF Francs
+ XPT Ounces
+ YER Rials
+ YUM New Dinars
+ ZAR Rand
+ ZMK Kwacha
+ ZWD Zimbabwe Dollars
+
+ */
+
+ return getid3_lib::EmbeddedLookup($currencyid, $begin, __LINE__, __FILE__, 'id3v2-currency-units');
+ }
+
+
+ public function LookupCurrencyCountry($currencyid) {
+
+ $begin = __LINE__;
+
+ /** This is not a comment!
+
+ AED United Arab Emirates
+ AFA Afghanistan
+ ALL Albania
+ AMD Armenia
+ ANG Netherlands Antilles
+ AOA Angola
+ ARS Argentina
+ ATS Austria
+ AUD Australia
+ AWG Aruba
+ AZM Azerbaijan
+ BAM Bosnia and Herzegovina
+ BBD Barbados
+ BDT Bangladesh
+ BEF Belgium
+ BGL Bulgaria
+ BHD Bahrain
+ BIF Burundi
+ BMD Bermuda
+ BND Brunei Darussalam
+ BOB Bolivia
+ BRL Brazil
+ BSD Bahamas
+ BTN Bhutan
+ BWP Botswana
+ BYR Belarus
+ BZD Belize
+ CAD Canada
+ CDF Congo/Kinshasa
+ CHF Switzerland
+ CLP Chile
+ CNY China
+ COP Colombia
+ CRC Costa Rica
+ CUP Cuba
+ CVE Cape Verde
+ CYP Cyprus
+ CZK Czech Republic
+ DEM Germany
+ DJF Djibouti
+ DKK Denmark
+ DOP Dominican Republic
+ DZD Algeria
+ EEK Estonia
+ EGP Egypt
+ ERN Eritrea
+ ESP Spain
+ ETB Ethiopia
+ EUR Euro Member Countries
+ FIM Finland
+ FJD Fiji
+ FKP Falkland Islands (Malvinas)
+ FRF France
+ GBP United Kingdom
+ GEL Georgia
+ GGP Guernsey
+ GHC Ghana
+ GIP Gibraltar
+ GMD Gambia
+ GNF Guinea
+ GRD Greece
+ GTQ Guatemala
+ GYD Guyana
+ HKD Hong Kong
+ HNL Honduras
+ HRK Croatia
+ HTG Haiti
+ HUF Hungary
+ IDR Indonesia
+ IEP Ireland (Eire)
+ ILS Israel
+ IMP Isle of Man
+ INR India
+ IQD Iraq
+ IRR Iran
+ ISK Iceland
+ ITL Italy
+ JEP Jersey
+ JMD Jamaica
+ JOD Jordan
+ JPY Japan
+ KES Kenya
+ KGS Kyrgyzstan
+ KHR Cambodia
+ KMF Comoros
+ KPW Korea
+ KWD Kuwait
+ KYD Cayman Islands
+ KZT Kazakstan
+ LAK Laos
+ LBP Lebanon
+ LKR Sri Lanka
+ LRD Liberia
+ LSL Lesotho
+ LTL Lithuania
+ LUF Luxembourg
+ LVL Latvia
+ LYD Libya
+ MAD Morocco
+ MDL Moldova
+ MGF Madagascar
+ MKD Macedonia
+ MMK Myanmar (Burma)
+ MNT Mongolia
+ MOP Macau
+ MRO Mauritania
+ MTL Malta
+ MUR Mauritius
+ MVR Maldives (Maldive Islands)
+ MWK Malawi
+ MXN Mexico
+ MYR Malaysia
+ MZM Mozambique
+ NAD Namibia
+ NGN Nigeria
+ NIO Nicaragua
+ NLG Netherlands (Holland)
+ NOK Norway
+ NPR Nepal
+ NZD New Zealand
+ OMR Oman
+ PAB Panama
+ PEN Peru
+ PGK Papua New Guinea
+ PHP Philippines
+ PKR Pakistan
+ PLN Poland
+ PTE Portugal
+ PYG Paraguay
+ QAR Qatar
+ ROL Romania
+ RUR Russia
+ RWF Rwanda
+ SAR Saudi Arabia
+ SBD Solomon Islands
+ SCR Seychelles
+ SDD Sudan
+ SEK Sweden
+ SGD Singapore
+ SHP Saint Helena
+ SIT Slovenia
+ SKK Slovakia
+ SLL Sierra Leone
+ SOS Somalia
+ SPL Seborga
+ SRG Suriname
+ STD SĆ£o Tome and Principe
+ SVC El Salvador
+ SYP Syria
+ SZL Swaziland
+ THB Thailand
+ TJR Tajikistan
+ TMM Turkmenistan
+ TND Tunisia
+ TOP Tonga
+ TRL Turkey
+ TTD Trinidad and Tobago
+ TVD Tuvalu
+ TWD Taiwan
+ TZS Tanzania
+ UAH Ukraine
+ UGX Uganda
+ USD United States of America
+ UYU Uruguay
+ UZS Uzbekistan
+ VAL Vatican City
+ VEB Venezuela
+ VND Viet Nam
+ VUV Vanuatu
+ WST Samoa
+ XAF CommunautĆ© FinanciĆØre Africaine
+ XAG Silver
+ XAU Gold
+ XCD East Caribbean
+ XDR International Monetary Fund
+ XPD Palladium
+ XPF Comptoirs FranƧais du Pacifique
+ XPT Platinum
+ YER Yemen
+ YUM Yugoslavia
+ ZAR South Africa
+ ZMK Zambia
+ ZWD Zimbabwe
+
+ */
+
+ return getid3_lib::EmbeddedLookup($currencyid, $begin, __LINE__, __FILE__, 'id3v2-currency-country');
+ }
+
+
+
+ public static function LanguageLookup($languagecode, $casesensitive=false) {
+
+ if (!$casesensitive) {
+ $languagecode = strtolower($languagecode);
+ }
+
+ // http://www.id3.org/id3v2.4.0-structure.txt
+ // [4. ID3v2 frame overview]
+ // The three byte language field, present in several frames, is used to
+ // describe the language of the frame's content, according to ISO-639-2
+ // [ISO-639-2]. The language should be represented in lower case. If the
+ // language is not known the string "XXX" should be used.
+
+
+ // ISO 639-2 - http://www.id3.org/iso639-2.html
+
+ $begin = __LINE__;
+
+ /** This is not a comment!
+
+ XXX unknown
+ xxx unknown
+ aar Afar
+ abk Abkhazian
+ ace Achinese
+ ach Acoli
+ ada Adangme
+ afa Afro-Asiatic (Other)
+ afh Afrihili
+ afr Afrikaans
+ aka Akan
+ akk Akkadian
+ alb Albanian
+ ale Aleut
+ alg Algonquian Languages
+ amh Amharic
+ ang English, Old (ca. 450-1100)
+ apa Apache Languages
+ ara Arabic
+ arc Aramaic
+ arm Armenian
+ arn Araucanian
+ arp Arapaho
+ art Artificial (Other)
+ arw Arawak
+ asm Assamese
+ ath Athapascan Languages
+ ava Avaric
+ ave Avestan
+ awa Awadhi
+ aym Aymara
+ aze Azerbaijani
+ bad Banda
+ bai Bamileke Languages
+ bak Bashkir
+ bal Baluchi
+ bam Bambara
+ ban Balinese
+ baq Basque
+ bas Basa
+ bat Baltic (Other)
+ bej Beja
+ bel Byelorussian
+ bem Bemba
+ ben Bengali
+ ber Berber (Other)
+ bho Bhojpuri
+ bih Bihari
+ bik Bikol
+ bin Bini
+ bis Bislama
+ bla Siksika
+ bnt Bantu (Other)
+ bod Tibetan
+ bra Braj
+ bre Breton
+ bua Buriat
+ bug Buginese
+ bul Bulgarian
+ bur Burmese
+ cad Caddo
+ cai Central American Indian (Other)
+ car Carib
+ cat Catalan
+ cau Caucasian (Other)
+ ceb Cebuano
+ cel Celtic (Other)
+ ces Czech
+ cha Chamorro
+ chb Chibcha
+ che Chechen
+ chg Chagatai
+ chi Chinese
+ chm Mari
+ chn Chinook jargon
+ cho Choctaw
+ chr Cherokee
+ chu Church Slavic
+ chv Chuvash
+ chy Cheyenne
+ cop Coptic
+ cor Cornish
+ cos Corsican
+ cpe Creoles and Pidgins, English-based (Other)
+ cpf Creoles and Pidgins, French-based (Other)
+ cpp Creoles and Pidgins, Portuguese-based (Other)
+ cre Cree
+ crp Creoles and Pidgins (Other)
+ cus Cushitic (Other)
+ cym Welsh
+ cze Czech
+ dak Dakota
+ dan Danish
+ del Delaware
+ deu German
+ din Dinka
+ div Divehi
+ doi Dogri
+ dra Dravidian (Other)
+ dua Duala
+ dum Dutch, Middle (ca. 1050-1350)
+ dut Dutch
+ dyu Dyula
+ dzo Dzongkha
+ efi Efik
+ egy Egyptian (Ancient)
+ eka Ekajuk
+ ell Greek, Modern (1453-)
+ elx Elamite
+ eng English
+ enm English, Middle (ca. 1100-1500)
+ epo Esperanto
+ esk Eskimo (Other)
+ esl Spanish
+ est Estonian
+ eus Basque
+ ewe Ewe
+ ewo Ewondo
+ fan Fang
+ fao Faroese
+ fas Persian
+ fat Fanti
+ fij Fijian
+ fin Finnish
+ fiu Finno-Ugrian (Other)
+ fon Fon
+ fra French
+ fre French
+ frm French, Middle (ca. 1400-1600)
+ fro French, Old (842- ca. 1400)
+ fry Frisian
+ ful Fulah
+ gaa Ga
+ gae Gaelic (Scots)
+ gai Irish
+ gay Gayo
+ gdh Gaelic (Scots)
+ gem Germanic (Other)
+ geo Georgian
+ ger German
+ gez Geez
+ gil Gilbertese
+ glg Gallegan
+ gmh German, Middle High (ca. 1050-1500)
+ goh German, Old High (ca. 750-1050)
+ gon Gondi
+ got Gothic
+ grb Grebo
+ grc Greek, Ancient (to 1453)
+ gre Greek, Modern (1453-)
+ grn Guarani
+ guj Gujarati
+ hai Haida
+ hau Hausa
+ haw Hawaiian
+ heb Hebrew
+ her Herero
+ hil Hiligaynon
+ him Himachali
+ hin Hindi
+ hmo Hiri Motu
+ hun Hungarian
+ hup Hupa
+ hye Armenian
+ iba Iban
+ ibo Igbo
+ ice Icelandic
+ ijo Ijo
+ iku Inuktitut
+ ilo Iloko
+ ina Interlingua (International Auxiliary language Association)
+ inc Indic (Other)
+ ind Indonesian
+ ine Indo-European (Other)
+ ine Interlingue
+ ipk Inupiak
+ ira Iranian (Other)
+ iri Irish
+ iro Iroquoian uages
+ isl Icelandic
+ ita Italian
+ jav Javanese
+ jaw Javanese
+ jpn Japanese
+ jpr Judeo-Persian
+ jrb Judeo-Arabic
+ kaa Kara-Kalpak
+ kab Kabyle
+ kac Kachin
+ kal Greenlandic
+ kam Kamba
+ kan Kannada
+ kar Karen
+ kas Kashmiri
+ kat Georgian
+ kau Kanuri
+ kaw Kawi
+ kaz Kazakh
+ kha Khasi
+ khi Khoisan (Other)
+ khm Khmer
+ kho Khotanese
+ kik Kikuyu
+ kin Kinyarwanda
+ kir Kirghiz
+ kok Konkani
+ kom Komi
+ kon Kongo
+ kor Korean
+ kpe Kpelle
+ kro Kru
+ kru Kurukh
+ kua Kuanyama
+ kum Kumyk
+ kur Kurdish
+ kus Kusaie
+ kut Kutenai
+ lad Ladino
+ lah Lahnda
+ lam Lamba
+ lao Lao
+ lat Latin
+ lav Latvian
+ lez Lezghian
+ lin Lingala
+ lit Lithuanian
+ lol Mongo
+ loz Lozi
+ ltz Letzeburgesch
+ lub Luba-Katanga
+ lug Ganda
+ lui Luiseno
+ lun Lunda
+ luo Luo (Kenya and Tanzania)
+ mac Macedonian
+ mad Madurese
+ mag Magahi
+ mah Marshall
+ mai Maithili
+ mak Macedonian
+ mak Makasar
+ mal Malayalam
+ man Mandingo
+ mao Maori
+ map Austronesian (Other)
+ mar Marathi
+ mas Masai
+ max Manx
+ may Malay
+ men Mende
+ mga Irish, Middle (900 - 1200)
+ mic Micmac
+ min Minangkabau
+ mis Miscellaneous (Other)
+ mkh Mon-Kmer (Other)
+ mlg Malagasy
+ mlt Maltese
+ mni Manipuri
+ mno Manobo Languages
+ moh Mohawk
+ mol Moldavian
+ mon Mongolian
+ mos Mossi
+ mri Maori
+ msa Malay
+ mul Multiple Languages
+ mun Munda Languages
+ mus Creek
+ mwr Marwari
+ mya Burmese
+ myn Mayan Languages
+ nah Aztec
+ nai North American Indian (Other)
+ nau Nauru
+ nav Navajo
+ nbl Ndebele, South
+ nde Ndebele, North
+ ndo Ndongo
+ nep Nepali
+ new Newari
+ nic Niger-Kordofanian (Other)
+ niu Niuean
+ nla Dutch
+ nno Norwegian (Nynorsk)
+ non Norse, Old
+ nor Norwegian
+ nso Sotho, Northern
+ nub Nubian Languages
+ nya Nyanja
+ nym Nyamwezi
+ nyn Nyankole
+ nyo Nyoro
+ nzi Nzima
+ oci Langue d'Oc (post 1500)
+ oji Ojibwa
+ ori Oriya
+ orm Oromo
+ osa Osage
+ oss Ossetic
+ ota Turkish, Ottoman (1500 - 1928)
+ oto Otomian Languages
+ paa Papuan-Australian (Other)
+ pag Pangasinan
+ pal Pahlavi
+ pam Pampanga
+ pan Panjabi
+ pap Papiamento
+ pau Palauan
+ peo Persian, Old (ca 600 - 400 B.C.)
+ per Persian
+ phn Phoenician
+ pli Pali
+ pol Polish
+ pon Ponape
+ por Portuguese
+ pra Prakrit uages
+ pro Provencal, Old (to 1500)
+ pus Pushto
+ que Quechua
+ raj Rajasthani
+ rar Rarotongan
+ roa Romance (Other)
+ roh Rhaeto-Romance
+ rom Romany
+ ron Romanian
+ rum Romanian
+ run Rundi
+ rus Russian
+ sad Sandawe
+ sag Sango
+ sah Yakut
+ sai South American Indian (Other)
+ sal Salishan Languages
+ sam Samaritan Aramaic
+ san Sanskrit
+ sco Scots
+ scr Serbo-Croatian
+ sel Selkup
+ sem Semitic (Other)
+ sga Irish, Old (to 900)
+ shn Shan
+ sid Sidamo
+ sin Singhalese
+ sio Siouan Languages
+ sit Sino-Tibetan (Other)
+ sla Slavic (Other)
+ slk Slovak
+ slo Slovak
+ slv Slovenian
+ smi Sami Languages
+ smo Samoan
+ sna Shona
+ snd Sindhi
+ sog Sogdian
+ som Somali
+ son Songhai
+ sot Sotho, Southern
+ spa Spanish
+ sqi Albanian
+ srd Sardinian
+ srr Serer
+ ssa Nilo-Saharan (Other)
+ ssw Siswant
+ ssw Swazi
+ suk Sukuma
+ sun Sudanese
+ sus Susu
+ sux Sumerian
+ sve Swedish
+ swa Swahili
+ swe Swedish
+ syr Syriac
+ tah Tahitian
+ tam Tamil
+ tat Tatar
+ tel Telugu
+ tem Timne
+ ter Tereno
+ tgk Tajik
+ tgl Tagalog
+ tha Thai
+ tib Tibetan
+ tig Tigre
+ tir Tigrinya
+ tiv Tivi
+ tli Tlingit
+ tmh Tamashek
+ tog Tonga (Nyasa)
+ ton Tonga (Tonga Islands)
+ tru Truk
+ tsi Tsimshian
+ tsn Tswana
+ tso Tsonga
+ tuk Turkmen
+ tum Tumbuka
+ tur Turkish
+ tut Altaic (Other)
+ twi Twi
+ tyv Tuvinian
+ uga Ugaritic
+ uig Uighur
+ ukr Ukrainian
+ umb Umbundu
+ und Undetermined
+ urd Urdu
+ uzb Uzbek
+ vai Vai
+ ven Venda
+ vie Vietnamese
+ vol VolapĆ¼k
+ vot Votic
+ wak Wakashan Languages
+ wal Walamo
+ war Waray
+ was Washo
+ wel Welsh
+ wen Sorbian Languages
+ wol Wolof
+ xho Xhosa
+ yao Yao
+ yap Yap
+ yid Yiddish
+ yor Yoruba
+ zap Zapotec
+ zen Zenaga
+ zha Zhuang
+ zho Chinese
+ zul Zulu
+ zun Zuni
+
+ */
+
+ return getid3_lib::EmbeddedLookup($languagecode, $begin, __LINE__, __FILE__, 'id3v2-languagecode');
+ }
+
+
+ public static function ETCOEventLookup($index) {
+ if (($index >= 0x17) && ($index <= 0xDF)) {
+ return 'reserved for future use';
+ }
+ if (($index >= 0xE0) && ($index <= 0xEF)) {
+ return 'not predefined synch 0-F';
+ }
+ if (($index >= 0xF0) && ($index <= 0xFC)) {
+ return 'reserved for future use';
+ }
+
+ static $EventLookup = array(
+ 0x00 => 'padding (has no meaning)',
+ 0x01 => 'end of initial silence',
+ 0x02 => 'intro start',
+ 0x03 => 'main part start',
+ 0x04 => 'outro start',
+ 0x05 => 'outro end',
+ 0x06 => 'verse start',
+ 0x07 => 'refrain start',
+ 0x08 => 'interlude start',
+ 0x09 => 'theme start',
+ 0x0A => 'variation start',
+ 0x0B => 'key change',
+ 0x0C => 'time change',
+ 0x0D => 'momentary unwanted noise (Snap, Crackle & Pop)',
+ 0x0E => 'sustained noise',
+ 0x0F => 'sustained noise end',
+ 0x10 => 'intro end',
+ 0x11 => 'main part end',
+ 0x12 => 'verse end',
+ 0x13 => 'refrain end',
+ 0x14 => 'theme end',
+ 0x15 => 'profanity',
+ 0x16 => 'profanity end',
+ 0xFD => 'audio end (start of silence)',
+ 0xFE => 'audio file ends',
+ 0xFF => 'one more byte of events follows'
+ );
+
+ return (isset($EventLookup[$index]) ? $EventLookup[$index] : '');
+ }
+
+ public static function SYTLContentTypeLookup($index) {
+ static $SYTLContentTypeLookup = array(
+ 0x00 => 'other',
+ 0x01 => 'lyrics',
+ 0x02 => 'text transcription',
+ 0x03 => 'movement/part name', // (e.g. 'Adagio')
+ 0x04 => 'events', // (e.g. 'Don Quijote enters the stage')
+ 0x05 => 'chord', // (e.g. 'Bb F Fsus')
+ 0x06 => 'trivia/\'pop up\' information',
+ 0x07 => 'URLs to webpages',
+ 0x08 => 'URLs to images'
+ );
+
+ return (isset($SYTLContentTypeLookup[$index]) ? $SYTLContentTypeLookup[$index] : '');
+ }
+
+ public static function APICPictureTypeLookup($index, $returnarray=false) {
+ static $APICPictureTypeLookup = array(
+ 0x00 => 'Other',
+ 0x01 => '32x32 pixels \'file icon\' (PNG only)',
+ 0x02 => 'Other file icon',
+ 0x03 => 'Cover (front)',
+ 0x04 => 'Cover (back)',
+ 0x05 => 'Leaflet page',
+ 0x06 => 'Media (e.g. label side of CD)',
+ 0x07 => 'Lead artist/lead performer/soloist',
+ 0x08 => 'Artist/performer',
+ 0x09 => 'Conductor',
+ 0x0A => 'Band/Orchestra',
+ 0x0B => 'Composer',
+ 0x0C => 'Lyricist/text writer',
+ 0x0D => 'Recording Location',
+ 0x0E => 'During recording',
+ 0x0F => 'During performance',
+ 0x10 => 'Movie/video screen capture',
+ 0x11 => 'A bright coloured fish',
+ 0x12 => 'Illustration',
+ 0x13 => 'Band/artist logotype',
+ 0x14 => 'Publisher/Studio logotype'
+ );
+ if ($returnarray) {
+ return $APICPictureTypeLookup;
+ }
+ return (isset($APICPictureTypeLookup[$index]) ? $APICPictureTypeLookup[$index] : '');
+ }
+
+ public static function COMRReceivedAsLookup($index) {
+ static $COMRReceivedAsLookup = array(
+ 0x00 => 'Other',
+ 0x01 => 'Standard CD album with other songs',
+ 0x02 => 'Compressed audio on CD',
+ 0x03 => 'File over the Internet',
+ 0x04 => 'Stream over the Internet',
+ 0x05 => 'As note sheets',
+ 0x06 => 'As note sheets in a book with other sheets',
+ 0x07 => 'Music on other media',
+ 0x08 => 'Non-musical merchandise'
+ );
+
+ return (isset($COMRReceivedAsLookup[$index]) ? $COMRReceivedAsLookup[$index] : '');
+ }
+
+ public static function RVA2ChannelTypeLookup($index) {
+ static $RVA2ChannelTypeLookup = array(
+ 0x00 => 'Other',
+ 0x01 => 'Master volume',
+ 0x02 => 'Front right',
+ 0x03 => 'Front left',
+ 0x04 => 'Back right',
+ 0x05 => 'Back left',
+ 0x06 => 'Front centre',
+ 0x07 => 'Back centre',
+ 0x08 => 'Subwoofer'
+ );
+
+ return (isset($RVA2ChannelTypeLookup[$index]) ? $RVA2ChannelTypeLookup[$index] : '');
+ }
+
+ public static function FrameNameLongLookup($framename) {
+
+ $begin = __LINE__;
+
+ /** This is not a comment!
+
+ AENC Audio encryption
+ APIC Attached picture
+ ASPI Audio seek point index
+ BUF Recommended buffer size
+ CNT Play counter
+ COM Comments
+ COMM Comments
+ COMR Commercial frame
+ CRA Audio encryption
+ CRM Encrypted meta frame
+ ENCR Encryption method registration
+ EQU Equalisation
+ EQU2 Equalisation (2)
+ EQUA Equalisation
+ ETC Event timing codes
+ ETCO Event timing codes
+ GEO General encapsulated object
+ GEOB General encapsulated object
+ GRID Group identification registration
+ IPL Involved people list
+ IPLS Involved people list
+ LINK Linked information
+ LNK Linked information
+ MCDI Music CD identifier
+ MCI Music CD Identifier
+ MLL MPEG location lookup table
+ MLLT MPEG location lookup table
+ OWNE Ownership frame
+ PCNT Play counter
+ PIC Attached picture
+ POP Popularimeter
+ POPM Popularimeter
+ POSS Position synchronisation frame
+ PRIV Private frame
+ RBUF Recommended buffer size
+ REV Reverb
+ RVA Relative volume adjustment
+ RVA2 Relative volume adjustment (2)
+ RVAD Relative volume adjustment
+ RVRB Reverb
+ SEEK Seek frame
+ SIGN Signature frame
+ SLT Synchronised lyric/text
+ STC Synced tempo codes
+ SYLT Synchronised lyric/text
+ SYTC Synchronised tempo codes
+ TAL Album/Movie/Show title
+ TALB Album/Movie/Show title
+ TBP BPM (Beats Per Minute)
+ TBPM BPM (beats per minute)
+ TCM Composer
+ TCMP Part of a compilation
+ TCO Content type
+ TCOM Composer
+ TCON Content type
+ TCOP Copyright message
+ TCP Part of a compilation
+ TCR Copyright message
+ TDA Date
+ TDAT Date
+ TDEN Encoding time
+ TDLY Playlist delay
+ TDOR Original release time
+ TDRC Recording time
+ TDRL Release time
+ TDTG Tagging time
+ TDY Playlist delay
+ TEN Encoded by
+ TENC Encoded by
+ TEXT Lyricist/Text writer
+ TFLT File type
+ TFT File type
+ TIM Time
+ TIME Time
+ TIPL Involved people list
+ TIT1 Content group description
+ TIT2 Title/songname/content description
+ TIT3 Subtitle/Description refinement
+ TKE Initial key
+ TKEY Initial key
+ TLA Language(s)
+ TLAN Language(s)
+ TLE Length
+ TLEN Length
+ TMCL Musician credits list
+ TMED Media type
+ TMOO Mood
+ TMT Media type
+ TOA Original artist(s)/performer(s)
+ TOAL Original album/movie/show title
+ TOF Original filename
+ TOFN Original filename
+ TOL Original Lyricist(s)/text writer(s)
+ TOLY Original lyricist(s)/text writer(s)
+ TOPE Original artist(s)/performer(s)
+ TOR Original release year
+ TORY Original release year
+ TOT Original album/Movie/Show title
+ TOWN File owner/licensee
+ TP1 Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group
+ TP2 Band/Orchestra/Accompaniment
+ TP3 Conductor/Performer refinement
+ TP4 Interpreted, remixed, or otherwise modified by
+ TPA Part of a set
+ TPB Publisher
+ TPE1 Lead performer(s)/Soloist(s)
+ TPE2 Band/orchestra/accompaniment
+ TPE3 Conductor/performer refinement
+ TPE4 Interpreted, remixed, or otherwise modified by
+ TPOS Part of a set
+ TPRO Produced notice
+ TPUB Publisher
+ TRC ISRC (International Standard Recording Code)
+ TRCK Track number/Position in set
+ TRD Recording dates
+ TRDA Recording dates
+ TRK Track number/Position in set
+ TRSN Internet radio station name
+ TRSO Internet radio station owner
+ TS2 Album-Artist sort order
+ TSA Album sort order
+ TSC Composer sort order
+ TSI Size
+ TSIZ Size
+ TSO2 Album-Artist sort order
+ TSOA Album sort order
+ TSOC Composer sort order
+ TSOP Performer sort order
+ TSOT Title sort order
+ TSP Performer sort order
+ TSRC ISRC (international standard recording code)
+ TSS Software/hardware and settings used for encoding
+ TSSE Software/Hardware and settings used for encoding
+ TSST Set subtitle
+ TST Title sort order
+ TT1 Content group description
+ TT2 Title/Songname/Content description
+ TT3 Subtitle/Description refinement
+ TXT Lyricist/text writer
+ TXX User defined text information frame
+ TXXX User defined text information frame
+ TYE Year
+ TYER Year
+ UFI Unique file identifier
+ UFID Unique file identifier
+ ULT Unsychronised lyric/text transcription
+ USER Terms of use
+ USLT Unsynchronised lyric/text transcription
+ WAF Official audio file webpage
+ WAR Official artist/performer webpage
+ WAS Official audio source webpage
+ WCM Commercial information
+ WCOM Commercial information
+ WCOP Copyright/Legal information
+ WCP Copyright/Legal information
+ WOAF Official audio file webpage
+ WOAR Official artist/performer webpage
+ WOAS Official audio source webpage
+ WORS Official Internet radio station homepage
+ WPAY Payment
+ WPB Publishers official webpage
+ WPUB Publishers official webpage
+ WXX User defined URL link frame
+ WXXX User defined URL link frame
+ TFEA Featured Artist
+ TSTU Recording Studio
+ rgad Replay Gain Adjustment
+
+ */
+
+ return getid3_lib::EmbeddedLookup($framename, $begin, __LINE__, __FILE__, 'id3v2-framename_long');
+
+ // Last three:
+ // from Helium2 [www.helium2.com]
+ // from http://privatewww.essex.ac.uk/~djmrob/replaygain/file_format_id3v2.html
+ }
+
+
+ public static function FrameNameShortLookup($framename) {
+
+ $begin = __LINE__;
+
+ /** This is not a comment!
+
+ AENC audio_encryption
+ APIC attached_picture
+ ASPI audio_seek_point_index
+ BUF recommended_buffer_size
+ CNT play_counter
+ COM comment
+ COMM comment
+ COMR commercial_frame
+ CRA audio_encryption
+ CRM encrypted_meta_frame
+ ENCR encryption_method_registration
+ EQU equalisation
+ EQU2 equalisation
+ EQUA equalisation
+ ETC event_timing_codes
+ ETCO event_timing_codes
+ GEO general_encapsulated_object
+ GEOB general_encapsulated_object
+ GRID group_identification_registration
+ IPL involved_people_list
+ IPLS involved_people_list
+ LINK linked_information
+ LNK linked_information
+ MCDI music_cd_identifier
+ MCI music_cd_identifier
+ MLL mpeg_location_lookup_table
+ MLLT mpeg_location_lookup_table
+ OWNE ownership_frame
+ PCNT play_counter
+ PIC attached_picture
+ POP popularimeter
+ POPM popularimeter
+ POSS position_synchronisation_frame
+ PRIV private_frame
+ RBUF recommended_buffer_size
+ REV reverb
+ RVA relative_volume_adjustment
+ RVA2 relative_volume_adjustment
+ RVAD relative_volume_adjustment
+ RVRB reverb
+ SEEK seek_frame
+ SIGN signature_frame
+ SLT synchronised_lyric
+ STC synced_tempo_codes
+ SYLT synchronised_lyric
+ SYTC synchronised_tempo_codes
+ TAL album
+ TALB album
+ TBP bpm
+ TBPM bpm
+ TCM composer
+ TCMP part_of_a_compilation
+ TCO genre
+ TCOM composer
+ TCON genre
+ TCOP copyright_message
+ TCP part_of_a_compilation
+ TCR copyright_message
+ TDA date
+ TDAT date
+ TDEN encoding_time
+ TDLY playlist_delay
+ TDOR original_release_time
+ TDRC recording_time
+ TDRL release_time
+ TDTG tagging_time
+ TDY playlist_delay
+ TEN encoded_by
+ TENC encoded_by
+ TEXT lyricist
+ TFLT file_type
+ TFT file_type
+ TIM time
+ TIME time
+ TIPL involved_people_list
+ TIT1 content_group_description
+ TIT2 title
+ TIT3 subtitle
+ TKE initial_key
+ TKEY initial_key
+ TLA language
+ TLAN language
+ TLE length
+ TLEN length
+ TMCL musician_credits_list
+ TMED media_type
+ TMOO mood
+ TMT media_type
+ TOA original_artist
+ TOAL original_album
+ TOF original_filename
+ TOFN original_filename
+ TOL original_lyricist
+ TOLY original_lyricist
+ TOPE original_artist
+ TOR original_year
+ TORY original_year
+ TOT original_album
+ TOWN file_owner
+ TP1 artist
+ TP2 band
+ TP3 conductor
+ TP4 remixer
+ TPA part_of_a_set
+ TPB publisher
+ TPE1 artist
+ TPE2 band
+ TPE3 conductor
+ TPE4 remixer
+ TPOS part_of_a_set
+ TPRO produced_notice
+ TPUB publisher
+ TRC isrc
+ TRCK track_number
+ TRD recording_dates
+ TRDA recording_dates
+ TRK track_number
+ TRSN internet_radio_station_name
+ TRSO internet_radio_station_owner
+ TS2 album_artist_sort_order
+ TSA album_sort_order
+ TSC composer_sort_order
+ TSI size
+ TSIZ size
+ TSO2 album_artist_sort_order
+ TSOA album_sort_order
+ TSOC composer_sort_order
+ TSOP performer_sort_order
+ TSOT title_sort_order
+ TSP performer_sort_order
+ TSRC isrc
+ TSS encoder_settings
+ TSSE encoder_settings
+ TSST set_subtitle
+ TST title_sort_order
+ TT1 content_group_description
+ TT2 title
+ TT3 subtitle
+ TXT lyricist
+ TXX text
+ TXXX text
+ TYE year
+ TYER year
+ UFI unique_file_identifier
+ UFID unique_file_identifier
+ ULT unsychronised_lyric
+ USER terms_of_use
+ USLT unsynchronised_lyric
+ WAF url_file
+ WAR url_artist
+ WAS url_source
+ WCM commercial_information
+ WCOM commercial_information
+ WCOP copyright
+ WCP copyright
+ WOAF url_file
+ WOAR url_artist
+ WOAS url_source
+ WORS url_station
+ WPAY url_payment
+ WPB url_publisher
+ WPUB url_publisher
+ WXX url_user
+ WXXX url_user
+ TFEA featured_artist
+ TSTU recording_studio
+ rgad replay_gain_adjustment
+
+ */
+
+ return getid3_lib::EmbeddedLookup($framename, $begin, __LINE__, __FILE__, 'id3v2-framename_short');
+ }
+
+ public static function TextEncodingTerminatorLookup($encoding) {
+ // http://www.id3.org/id3v2.4.0-structure.txt
+ // Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings:
+ static $TextEncodingTerminatorLookup = array(
+ 0 => "\x00", // $00 ISO-8859-1. Terminated with $00.
+ 1 => "\x00\x00", // $01 UTF-16 encoded Unicode with BOM. All strings in the same frame SHALL have the same byteorder. Terminated with $00 00.
+ 2 => "\x00\x00", // $02 UTF-16BE encoded Unicode without BOM. Terminated with $00 00.
+ 3 => "\x00", // $03 UTF-8 encoded Unicode. Terminated with $00.
+ 255 => "\x00\x00"
+ );
+ return (isset($TextEncodingTerminatorLookup[$encoding]) ? $TextEncodingTerminatorLookup[$encoding] : '');
+ }
+
+ public static function TextEncodingNameLookup($encoding) {
+ // http://www.id3.org/id3v2.4.0-structure.txt
+ // Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings:
+ static $TextEncodingNameLookup = array(
+ 0 => 'ISO-8859-1', // $00 ISO-8859-1. Terminated with $00.
+ 1 => 'UTF-16', // $01 UTF-16 encoded Unicode with BOM. All strings in the same frame SHALL have the same byteorder. Terminated with $00 00.
+ 2 => 'UTF-16BE', // $02 UTF-16BE encoded Unicode without BOM. Terminated with $00 00.
+ 3 => 'UTF-8', // $03 UTF-8 encoded Unicode. Terminated with $00.
+ 255 => 'UTF-16BE'
+ );
+ return (isset($TextEncodingNameLookup[$encoding]) ? $TextEncodingNameLookup[$encoding] : 'ISO-8859-1');
+ }
+
+ public static function IsValidID3v2FrameName($framename, $id3v2majorversion) {
+ switch ($id3v2majorversion) {
+ case 2:
+ return preg_match('#[A-Z][A-Z0-9]{2}#', $framename);
+ break;
+
+ case 3:
+ case 4:
+ return preg_match('#[A-Z][A-Z0-9]{3}#', $framename);
+ break;
+ }
+ return false;
+ }
+
+ public static function IsANumber($numberstring, $allowdecimal=false, $allownegative=false) {
+ for ($i = 0; $i < strlen($numberstring); $i++) {
+ if ((chr($numberstring{$i}) < chr('0')) || (chr($numberstring{$i}) > chr('9'))) {
+ if (($numberstring{$i} == '.') && $allowdecimal) {
+ // allowed
+ } elseif (($numberstring{$i} == '-') && $allownegative && ($i == 0)) {
+ // allowed
+ } else {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public static function IsValidDateStampString($datestamp) {
+ if (strlen($datestamp) != 8) {
+ return false;
+ }
+ if (!self::IsANumber($datestamp, false)) {
+ return false;
+ }
+ $year = substr($datestamp, 0, 4);
+ $month = substr($datestamp, 4, 2);
+ $day = substr($datestamp, 6, 2);
+ if (($year == 0) || ($month == 0) || ($day == 0)) {
+ return false;
+ }
+ if ($month > 12) {
+ return false;
+ }
+ if ($day > 31) {
+ return false;
+ }
+ if (($day > 30) && (($month == 4) || ($month == 6) || ($month == 9) || ($month == 11))) {
+ return false;
+ }
+ if (($day > 29) && ($month == 2)) {
+ return false;
+ }
+ return true;
+ }
+
+ public static function ID3v2HeaderLength($majorversion) {
+ return (($majorversion == 2) ? 6 : 10);
+ }
+
+}
+
diff --git a/extensions/TimedMediaHandler/libs/getid3/readme.txt b/extensions/TimedMediaHandler/libs/getid3/readme.txt
new file mode 100644
index 00000000..ebd004eb
--- /dev/null
+++ b/extensions/TimedMediaHandler/libs/getid3/readme.txt
@@ -0,0 +1,591 @@
+/////////////////////////////////////////////////////////////////
+/// getID3() by James Heinrich <info@getid3.org> //
+// available at http://getid3.sourceforge.net //
+// or http://www.getid3.org //
+/////////////////////////////////////////////////////////////////
+// //
+// changelog.txt - part of getID3() //
+// See readme.txt for more details //
+// ///
+/////////////////////////////////////////////////////////////////
+
+ This code is released under the GNU GPL:
+ http://www.gnu.org/copyleft/gpl.html
+
+ +---------------------------------------------+
+ | If you do use this code somewhere, send me |
+ | an email and tell me how/where you used it. |
+ | |
+ | If you want to donate, there is a link on |
+ | http://www.getid3.org for PayPal donations. |
+ +---------------------------------------------+
+
+
+
+Quick Start
+===========================================================================
+
+Q: How can I check that getID3() works on my server/files?
+A: Unzip getID3() to a directory, then access /demos/demo.browse.php
+
+
+
+Support
+===========================================================================
+
+Q: I have a question, or I found a bug. What do I do?
+A: The preferred method of support requests and/or bug reports is the
+ forum at http://support.getid3.org/
+
+
+
+Sourceforge Notification
+===========================================================================
+
+It's highly recommended that you sign up for notification from
+Sourceforge for when new versions are released. Please visit:
+http://sourceforge.net/project/showfiles.php?group_id=55859
+and click the little "monitor package" icon/link. If you're
+previously signed up for the mailing list, be aware that it has
+been discontinued, only the automated Sourceforge notification
+will be used from now on.
+
+
+
+What does getID3() do?
+===========================================================================
+
+Reads & parses (to varying degrees):
+ ā‚¬ tags:
+ * APE (v1 and v2)
+ * ID3v1 (& ID3v1.1)
+ * ID3v2 (v2.4, v2.3, v2.2)
+ * Lyrics3 (v1 & v2)
+
+ ā‚¬ audio-lossy:
+ * MP3/MP2/MP1
+ * MPC / Musepack
+ * Ogg (Vorbis, OggFLAC, Speex)
+ * AC3
+ * DTS
+ * RealAudio
+ * Speex
+ * DSS
+ * VQF
+
+ ā‚¬ audio-lossless:
+ * AIFF
+ * AU
+ * Bonk
+ * CD-audio (*.cda)
+ * FLAC
+ * LA (Lossless Audio)
+ * LiteWave
+ * LPAC
+ * MIDI
+ * Monkey's Audio
+ * OptimFROG
+ * RKAU
+ * Shorten
+ * TTA
+ * VOC
+ * WAV (RIFF)
+ * WavPack
+
+ ā‚¬ audio-video:
+ * ASF: ASF, Windows Media Audio (WMA), Windows Media Video (WMV)
+ * AVI (RIFF)
+ * Flash
+ * Matroska (MKV)
+ * MPEG-1 / MPEG-2
+ * NSV (Nullsoft Streaming Video)
+ * Quicktime
+ * RealVideo
+
+ ā‚¬ still image:
+ * BMP
+ * GIF
+ * JPEG
+ * PNG
+ * TIFF
+ * SWF (Flash)
+ * PhotoCD
+
+ ā‚¬ data:
+ * ISO-9660 CD-ROM image (directory structure)
+ * SZIP (limited support)
+ * ZIP (directory structure)
+ * TAR
+ * CUE
+
+
+Writes:
+ * ID3v1 (& ID3v1.1)
+ * ID3v2 (v2.3 & v2.4)
+ * VorbisComment on OggVorbis
+ * VorbisComment on FLAC (not OggFLAC)
+ * APE v2
+ * Lyrics3 (delete only)
+
+
+
+Requirements
+===========================================================================
+
+* PHP 4.2.0 (or higher) for getID3() 1.7.x (and earlier)
+* PHP 5.3.0 (or higher) for getID3() 1.8.x (and up)
+* PHP 5.0.0 (or higher) for getID3() 2.0.x (and up)
+* at least 4MB memory for PHP. 8MB is highly recommended.
+ 12MB is required with all modules loaded.
+
+
+
+Usage
+===========================================================================
+
+See /demos/demo.basic.php for a very basic use of getID3() with no
+fancy output, just scanning one file.
+
+See structure.txt for the returned data structure.
+
+*> For an example of a complete directory-browsing, <*
+*> file-scanning implementation of getID3(), please run <*
+*> /demos/demo.browse.php <*
+
+See /demos/demo.mysql.php for a sample recursive scanning code that
+scans every file in a given directory, and all sub-directories, stores
+the results in a database and allows various analysis / maintenance
+operations
+
+To analyze remote files over HTTP or FTP you need to copy the file
+locally first before running getID3(). Your code would look something
+like this:
+
+// Copy remote file locally to scan with getID3()
+$remotefilename = 'http://www.example.com/filename.mp3';
+if ($fp_remote = fopen($remotefilename, 'rb')) {
+ $localtempfilename = tempnam('/tmp', 'getID3');
+ if ($fp_local = fopen($localtempfilename, 'wb')) {
+ while ($buffer = fread($fp_remote, 8192)) {
+ fwrite($fp_local, $buffer);
+ }
+ fclose($fp_local);
+
+ // Initialize getID3 engine
+ $getID3 = new getID3;
+
+ $ThisFileInfo = $getID3->analyze($filename);
+
+ // Delete temporary file
+ unlink($localtempfilename);
+ }
+ fclose($fp_remote);
+}
+
+
+See /demos/demo.write.php for how to write tags.
+
+
+
+What does the returned data structure look like?
+===========================================================================
+
+See structure.txt
+
+It is recommended that you look at the output of
+/demos/demo.browse.php scanning the file(s) you're interested in to
+confirm what data is actually returned for any particular filetype in
+general, and your files in particular, as the actual data returned
+may vary considerably depending on what information is available in
+the file itself.
+
+
+
+Notes
+===========================================================================
+
+getID3() 1.x:
+If the format parser encounters a critical problem, it will return
+something in $fileinfo['error'], describing the encountered error. If
+a less critical error or notice is generated it will appear in
+$fileinfo['warning']. Both keys may contain more than one warning or
+error. If something is returned in ['error'] then the file was not
+correctly parsed and returned data may or may not be correct and/or
+complete. If something is returned in ['warning'] (and not ['error'])
+then the data that is returned is OK - usually getID3() is reporting
+errors in the file that have been worked around due to known bugs in
+other programs. Some warnings may indicate that the data that is
+returned is OK but that some data could not be extracted due to
+errors in the file.
+
+getID3() 2.x:
+See above except errors are thrown (so you will only get one error).
+
+
+
+Disclaimer
+===========================================================================
+
+getID3() has been tested on many systems, on many types of files,
+under many operating systems, and is generally believe to be stable
+and safe. That being said, there is still the chance there is an
+undiscovered and/or unfixed bug that may potentially corrupt your
+file, especially within the writing functions. By using getID3() you
+agree that it's not my fault if any of your files are corrupted.
+In fact, I'm not liable for anything :)
+
+
+
+License
+===========================================================================
+
+GNU General Public License - see license.txt
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to:
+Free Software Foundation, Inc.
+59 Temple Place - Suite 330
+Boston, MA 02111-1307, USA.
+
+FAQ:
+Q: Can I use getID3() in my program? Do I need a commercial license?
+A: You're generally free to use getID3 however you see fit. The only
+ case in which you would require a commercial license is if you're
+ selling your closed-source program that integrates getID3. If you
+ sell your program including a copy of getID3, that's fine as long
+ as you include a copy of the sourcecode when you sell it. Or you
+ can distribute your code without getID3 and say "download it from
+ getid3.sourceforge.net"
+
+
+
+Why is it called "getID3()" if it does so much more than just that?
+===========================================================================
+
+v0.1 did in fact just do that. I don't have a copy of code that old, but I
+could essentially write it today with a one-line function:
+ function getID3($filename) { return unpack('a3TAG/a30title/a30artist/a30album/a4year/a28comment/c1track/c1genreid', substr(file_get_contents($filename), -128)); }
+
+
+Future Plans
+===========================================================================
+http://www.getid3.org/phpBB3/viewforum.php?f=7
+
+* Better support for MP4 container format
+* Scan for appended ID3v2 tag at end of file per ID3v2.4 specs (Section 5.0)
+* Support for JPEG-2000 (http://www.morgan-multimedia.com/jpeg2000_overview.htm)
+* Support for MOD (mod/stm/s3m/it/xm/mtm/ult/669)
+* Support for ACE (thanks Vince)
+* Support for Ogg other than Vorbis, Speex and OggFlac (ie. Ogg+Xvid)
+* Ability to create Xing/LAME VBR header for VBR MP3s that are missing VBR header
+* Ability to "clean" ID3v2 padding (replace invalid padding with valid padding)
+* Warn if MP3s change version mid-stream (in full-scan mode)
+* check for corrupt/broken mid-file MP3 streams in histogram scan
+* Support for lossless-compression formats
+ (http://www.firstpr.com.au/audiocomp/lossless/#Links)
+ (http://compression.ca/act-sound.html)
+ (http://web.inter.nl.net/users/hvdh/lossless/lossless.htm)
+* Support for RIFF-INFO chunks
+ * http://lotto.st-andrews.ac.uk/~njh/tag_interchange.html
+ (thanks Nick Humfrey <njhƘsurgeradio*co*uk>)
+ * http://abcavi.narod.ru/sof/abcavi/infotags.htm
+ (thanks Kibi)
+* Better support for Bink video
+* http://www.hr/josip/DSP/AudioFile2.html
+* http://www.pcisys.net/~melanson/codecs/
+* Detect mp3PRO
+* Support for PSD
+* Support for JPC
+* Support for JP2
+* Support for JPX
+* Support for JB2
+* Support for IFF
+* Support for ICO
+* Support for ANI
+* Support for EXE (comments, author, etc) (thanks p*quaedackersƘplanet*nl)
+* Support for DVD-IFO (region, subtitles, aspect ratio, etc)
+ (thanks p*quaedackersƘplanet*nl)
+* More complete support for SWF - parsing encapsulated MP3 and/or JPEG content
+ (thanks n8n8Ƙyahoo*com)
+* Support for a2b
+* Optional scan-through-frames for AVI verification
+ (thanks rockcohenƘmassive-interactive*nl)
+* Support for TTF (thanks infoƘbutterflyx*com)
+* Support for DSS (http://www.getid3.org/phpBB3/viewtopic.php?t=171)
+* Support for SMAF (http://smaf-yamaha.com/what/demo.html)
+ http://www.getid3.org/phpBB3/viewtopic.php?t=182
+* Support for AMR (http://www.getid3.org/phpBB3/viewtopic.php?t=195)
+* Support for 3gpp (http://www.getid3.org/phpBB3/viewtopic.php?t=195)
+* Support for ID4 (http://www.wackysoft.cjb.net grizlyY2KƘhotmail*com)
+* Parse XML data returned in Ogg comments
+* Parse XML data from Quicktime SMIL metafiles (klausrathƘmac*com)
+* ID3v2 genre string creator function
+* More complete parsing of JPG
+* Support for all old-style ASF packets
+* ASF/WMA/WMV tag writing
+* Parse declared T??? ID3v2 text information frames, where appropriate
+ (thanks Christian Fritz for the idea)
+* Recognize encoder:
+ http://www.guerillasoft.com/EncSpot2/index.html
+ http://ff123.net/identify.html
+ http://www.hydrogenaudio.org/?act=ST&f=16&t=9414
+ http://www.hydrogenaudio.org/?showtopic=11785
+* Support for other OS/2 bitmap structures: Bitmap Array('BA'),
+ Color Icon('CI'), Color Pointer('CP'), Icon('IC'), Pointer ('PT')
+ http://netghost.narod.ru/gff/graphics/summary/os2bmp.htm
+* Support for WavPack RAW mode
+* ASF/WMA/WMV data packet parsing
+* ID3v2FrameFlagsLookupTagAlter()
+* ID3v2FrameFlagsLookupFileAlter()
+* obey ID3v2 tag alter/preserve/discard rules
+* http://www.geocities.com/SiliconValley/Sector/9654/Softdoc/Illyrium/Aolyr.htm
+* proper checking for LINK/LNK frame validity in ID3v2 writing
+* proper checking for ASPI-TLEN frame validity in ID3v2 writing
+* proper checking for COMR frame validity in ID3v2 writing
+* http://www.geocities.co.jp/SiliconValley-Oakland/3664/index.html
+* decode GEOB ID3v2 structure as encoded by RealJukebox,
+ decode NCON ID3v2 structure as encoded by MusicMatch
+ (probably won't happen - the formats are proprietary)
+
+
+
+Known Bugs/Issues in getID3() that may be fixed eventually
+===========================================================================
+http://www.getid3.org/phpBB3/viewtopic.php?t=25
+
+* Cannot determine bitrate for MPEG video with VBR video data
+ (need documentation)
+* Interlace/progressive cannot be determined for MPEG video
+ (need documentation)
+* MIDI playtime is sometimes inaccurate
+* AAC-RAW mode files cannot be identified
+* WavPack-RAW mode files cannot be identified
+* mp4 files report lots of "Unknown QuickTime atom type"
+ (need documentation)
+* Encrypted ASF/WMA/WMV files warn about "unhandled GUID
+ ASF_Content_Encryption_Object"
+* Bitrate split between audio and video cannot be calculated for
+ NSV, only the total bitrate. (need documentation)
+* All Ogg formats (Vorbis, OggFLAC, Speex) are affected by the
+ problem of large VorbisComments spanning multiple Ogg pages, but
+ but only OggVorbis files can be processed with vorbiscomment.
+* The version of "head" supplied with Mac OS 10.2.8 (maybe other
+ versions too) does only understands a single option (-n) and
+ therefore fails. getID3 ignores this and returns wrong md5_data.
+
+
+
+Known Bugs/Issues in getID3() that cannot be fixed
+--------------------------------------------------
+http://www.getid3.org/phpBB3/viewtopic.php?t=25
+
+* 32-bit PHP installations only:
+ Files larger than 2GB cannot always be parsed fully by getID3()
+ due to limitations in the 32-bit PHP filesystem functions.
+ NOTE: Since v1.7.8b3 there is partial support for larger-than-
+ 2GB files, most of which will parse OK, as long as no critical
+ data is located beyond the 2GB offset.
+ Known will-work:
+ * all file formats on 64-bit PHP
+ * ZIP (format doesn't support files >2GB)
+ * FLAC (current encoders don't support files >2GB)
+ Known will-not-work:
+ * ID3v1 tags (always located at end-of-file)
+ * Lyrics3 tags (always located at end-of-file)
+ * APE tags (always located at end-of-file)
+ Maybe-will-work:
+ * Quicktime (will work if needed metadata is before 2GB offset,
+ that is if the file has been hinted/optimized for streaming)
+ * RIFF.WAV (should work fine, but gives warnings about not being
+ able to parse all chunks)
+ * RIFF.AVI (playtime will probably be wrong, is only based on
+ "movi" chunk that fits in the first 2GB, should issue error
+ to show that playtime is incorrect. Other data should be mostly
+ correct, assuming that data is constant throughout the file)
+
+
+
+Known Bugs/Issues in other programs
+-----------------------------------
+http://www.getid3.org/phpBB3/viewtopic.php?t=25
+
+* Windows Media Player (up to v11) and iTunes (up to v10+) do
+ not correctly handle ID3v2.3 tags with UTF-16BE+BOM
+ encoding (they assume the data is UTF-16LE+BOM and either
+ crash (WMP) or output Asian character set (iTunes)
+* Winamp (up to v2.80 at least) does not support ID3v2.4 tags,
+ only ID3v2.3
+ see: http://forums.winamp.com/showthread.php?postid=387524
+* Some versions of Helium2 (www.helium2.com) do not write
+ ID3v2.4-compliant Frame Sizes, even though the tag is marked
+ as ID3v2.4) (detected by getID3())
+* MP3ext V3.3.17 places a non-compliant padding string at the end
+ of the ID3v2 header. This is supposedly fixed in v3.4b21 but
+ only if you manually add a registry key. This fix is not yet
+ confirmed. (detected by getID3())
+* CDex v1.40 (fixed by v1.50b7) writes non-compliant Ogg comment
+ strings, supposed to be in the format "NAME=value" but actually
+ written just "value" (detected by getID3())
+* Oggenc 0.9-rc3 flags the encoded file as ABR whether it's
+ actually ABR or VBR.
+* iTunes (versions "X v2.0.3", "v3.0.1" are known-guilty, probably
+ other versions are too) writes ID3v2.3 comment tags using a
+ frame name 'COM ' which is not valid for ID3v2.3+ (it's an
+ ID3v2.2-style frame name) (detected by getID3())
+* MP2enc does not encode mono CBR MP2 files properly (half speed
+ sound and double playtime)
+* MP2enc does not encode mono VBR MP2 files properly (actually
+ encoded as stereo)
+* tooLAME does not encode mono VBR MP2 files properly (actually
+ encoded as stereo)
+* AACenc encodes files in VBR mode (actually ABR) even if CBR is
+ specified
+* AAC/ADIF - bitrate_mode = cbr for vbr files
+* LAME 3.90-3.92 prepends one frame of null data (space for the
+ LAME/VBR header, but it never gets written) when encoding in CBR
+ mode with the DLL
+* Ahead Nero encodes TwinVQF with a DSIZ value (which is supposed
+ to be the filesize in bytes) of "0" for TwinVQF v1.0 and "1" for
+ TwinVQF v2.0 (detected by getID3())
+* Ahead Nero encodes TwinVQF files 1 second shorter than they
+ should be
+* AAC-ADTS files are always actually encoded VBR, even if CBR mode
+ is specified (the CBR-mode switches on the encoder enable ABR
+ mode, not CBR as such, but it's not possible to tell the
+ difference between such ABR files and true VBR)
+* STREAMINFO.audio_signature in OggFLAC is always null. "The reason
+ it's like that is because there is no seeking support in
+ libOggFLAC yet, so it has no way to go back and write the
+ computed sum after encoding. Seeking support in Ogg FLAC is the
+ #1 item for the next release." - Josh Coalson (FLAC developer)
+ NOTE: getID3() will calculate md5_data in a method similar to
+ other file formats, but that value cannot be compared to the
+ md5_data value from FLAC data in a FLAC file format.
+* STREAMINFO.audio_signature is not calculated in FLAC v0.3.0 &
+ v0.4.0 - getID3() will calculate md5_data in a method similar to
+ other file formats, but that value cannot be compared to the
+ md5_data value from FLAC v0.5.0+
+* RioPort (various versions including 2.0 and 3.11) tags ID3v2 with
+ a WCOM frame that has no data portion
+* Earlier versions of Coolplayer adds illegal ID3 tags to Ogg Vorbis
+ files, thus making them corrupt.
+* Meracl ID3 Tag Writer v1.3.4 (and older) incorrectly truncates the
+ last byte of data from an MP3 file when appending a new ID3v1 tag.
+ (detected by getID3())
+* Lossless-Audio files encoded with and without the -noseek switch
+ do actually differ internally and therefore cannot match md5_data
+* iTunes has been known to append a new ID3v1 tag on the end of an
+ existing ID3v1 tag when ID3v2 tag is also present
+ (detected by getID3())
+* MediaMonkey may write a blank RGAD ID3v2 frame but put actual
+ replay gain adjustments in a series of user-defined TXXX frames
+ (detected and handled by getID3() since v1.9.2)
+
+
+
+
+Reference material:
+===========================================================================
+
+[www.id3.org material now mirrored at http://id3lib.sourceforge.net/id3/]
+* http://www.id3.org/id3v2.4.0-structure.txt
+* http://www.id3.org/id3v2.4.0-frames.txt
+* http://www.id3.org/id3v2.4.0-changes.txt
+* http://www.id3.org/id3v2.3.0.txt
+* http://www.id3.org/id3v2-00.txt
+* http://www.id3.org/mp3frame.html
+* http://minnie.tuhs.org/pipermail/mp3encoder/2001-January/001800.html <mathewhendry@hotmail.com>
+* http://www.dv.co.yu/mpgscript/mpeghdr.htm
+* http://www.mp3-tech.org/programmer/frame_header.html
+* http://users.belgacom.net/gc247244/extra/tag.html
+* http://gabriel.mp3-tech.org/mp3infotag.html
+* http://www.id3.org/iso4217.html
+* http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-1.TXT
+* http://www.xiph.org/ogg/vorbis/doc/framing.html
+* http://www.xiph.org/ogg/vorbis/doc/v-comment.html
+* http://leknor.com/code/php/class.ogg.php.txt
+* http://www.id3.org/iso639-2.html
+* http://www.id3.org/lyrics3.html
+* http://www.id3.org/lyrics3200.html
+* http://www.psc.edu/general/software/packages/ieee/ieee.html
+* http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
+* http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
+* http://www.jmcgowan.com/avi.html
+* http://www.wotsit.org/
+* http://www.herdsoft.com/ti/davincie/davp3xo2.htm
+* http://www.mathdogs.com/vorbis-illuminated/bitstream-appendix.html
+* "Standard MIDI File Format" by Dustin Caldwell (from www.wotsit.org)
+* http://midistudio.com/Help/GMSpecs_Patches.htm
+* http://www.xiph.org/archives/vorbis/200109/0459.html
+* http://www.replaygain.org/
+* http://www.lossless-audio.com/
+* http://download.microsoft.com/download/winmediatech40/Doc/1.0/WIN98MeXP/EN-US/ASF_Specification_v.1.0.exe
+* http://mediaxw.sourceforge.net/files/doc/Active%20Streaming%20Format%20(ASF)%201.0%20Specification.pdf
+* http://www.uni-jena.de/~pfk/mpp/sv8/ (archived at http://www.hydrogenaudio.org/musepack/klemm/www.personal.uni-jena.de/~pfk/mpp/sv8/)
+* http://jfaul.de/atl/
+* http://www.uni-jena.de/~pfk/mpp/ (archived at http://www.hydrogenaudio.org/musepack/klemm/www.personal.uni-jena.de/~pfk/mpp/)
+* http://www.libpng.org/pub/png/spec/png-1.2-pdg.html
+* http://www.real.com/devzone/library/creating/rmsdk/doc/rmff.htm
+* http://www.fastgraph.com/help/bmp_os2_header_format.html
+* http://netghost.narod.ru/gff/graphics/summary/os2bmp.htm
+* http://flac.sourceforge.net/format.html
+* http://www.research.att.com/projects/mpegaudio/mpeg2.html
+* http://www.audiocoding.com/wiki/index.php?page=AAC
+* http://libmpeg.org/mpeg4/doc/w2203tfs.pdf
+* http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
+* http://developer.apple.com/techpubs/quicktime/qtdevdocs/RM/frameset.htm
+* http://www.nullsoft.com/nsv/
+* http://www.wotsit.org/download.asp?f=iso9660
+* http://sandbox.mc.edu/~bennet/cs110/tc/tctod.html
+* http://www.cdroller.com/htm/readdata.html
+* http://www.speex.org/manual/node10.html
+* http://www.harmony-central.com/Computer/Programming/aiff-file-format.doc
+* http://www.faqs.org/rfcs/rfc2361.html
+* http://ghido.shelter.ro/
+* http://www.ebu.ch/tech_t3285.pdf
+* http://www.sr.se/utveckling/tu/bwf
+* http://ftp.aessc.org/pub/aes46-2002.pdf
+* http://cartchunk.org:8080/
+* http://www.broadcastpapers.com/radio/cartchunk01.htm
+* http://www.hr/josip/DSP/AudioFile2.html
+* http://home.attbi.com/~chris.bagwell/AudioFormats-11.html
+* http://www.pure-mac.com/extkey.html
+* http://cesnet.dl.sourceforge.net/sourceforge/bonkenc/bonk-binary-format-0.9.txt
+* http://www.headbands.com/gspot/
+* http://www.openswf.org/spec/SWFfileformat.html
+* http://j-faul.virtualave.net/
+* http://www.btinternet.com/~AnthonyJ/Atari/programming/avr_format.html
+* http://cui.unige.ch/OSG/info/AudioFormats/ap11.html
+* http://sswf.sourceforge.net/SWFalexref.html
+* http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt
+* http://www-lehre.informatik.uni-osnabrueck.de/~fbstark/diplom/docs/swf/Flash_Uncovered.htm
+* http://developer.apple.com/quicktime/icefloe/dispatch012.html
+* http://www.csdn.net/Dev/Format/graphics/PCD.htm
+* http://tta.iszf.irk.ru/
+* http://www.atsc.org/standards/a_52a.pdf
+* http://www.alanwood.net/unicode/
+* http://www.freelists.org/archives/matroska-devel/07-2003/msg00010.html
+* http://www.its.msstate.edu/net/real/reports/config/tags.stats
+* http://homepages.slingshot.co.nz/~helmboy/quicktime/formats/qtm-layout.txt
+* http://brennan.young.net/Comp/LiveStage/things.html
+* http://www.multiweb.cz/twoinches/MP3inside.htm
+* http://www.geocities.co.jp/SiliconValley-Oakland/3664/alittle.html#GenreExtended
+* http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/
+* http://www.unicode.org/unicode/faq/utf_bom.html
+* http://tta.corecodec.org/?menu=format
+* http://www.scvi.net/nsvformat.htm
+* http://pda.etsi.org/pda/queryform.asp
+* http://cpansearch.perl.org/src/RGIBSON/Audio-DSS-0.02/lib/Audio/DSS.pm
+* http://trac.musepack.net/trac/wiki/SV8Specification
+* http://wyday.com/cuesharp/specification.php
+* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html \ No newline at end of file
diff --git a/extensions/TimedMediaHandler/maintenance/cleanupTranscodes.php b/extensions/TimedMediaHandler/maintenance/cleanupTranscodes.php
new file mode 100644
index 00000000..01c7b004
--- /dev/null
+++ b/extensions/TimedMediaHandler/maintenance/cleanupTranscodes.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * cleanup transcodes no longer defined in $wgEnabledTranscodeSet
+ *
+ */
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = dirname( __FILE__ ) . '/../../..';
+}
+require_once( "$IP/maintenance/Maintenance.php" );
+
+class CleanupTranscodes extends Maintenance {
+
+ public function __construct() {
+ parent::__construct();
+ $this->addOption( "key", "remove all transcodes for given key", false, true );
+ $this->addOption( "all", "remove all transcodes", false, false );
+ $this->mDescription = "cleanup transcodes left over after changing encoding profiles.";
+ }
+ public function execute() {
+ global $wgEnabledTranscodeSet;
+
+ if ( $this->hasOption( "all" ) ) {
+ $where = array();
+ } elseif ( $this->hasOption( "key" ) ) {
+ $where = array( 'transcode_key' => $this->getOption( 'key' ) );
+ } else {
+ $where = 'transcode_key NOT IN ("'. implode('", "', $wgEnabledTranscodeSet ).'")';
+ }
+ $this->output( "Cleanup transcodes:\n" );
+ $dbr = wfGetDB( DB_SLAVE );
+ $res = $dbr->select( 'transcode', '*', $where, __METHOD__ );
+ foreach ( $res as $row ) {
+ $this->output(
+ 'remove: '. $row->transcode_image_name . ' ' . $row->transcode_key . "\n"
+ );
+ $title = Title::newFromText( $row->transcode_image_name, NS_FILE );
+ $file = wfLocalFile( $title );
+ WebVideoTranscode::removeTranscodes( $file, $row->transcode_key );
+ }
+ $this->output( "Finished!\n" );
+ }
+}
+
+$maintClass = 'CleanupTranscodes'; // Tells it to run the class
+require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/extensions/TimedMediaHandler/maintenance/moveTranscoded.php b/extensions/TimedMediaHandler/maintenance/moveTranscoded.php
new file mode 100644
index 00000000..1ff6717c
--- /dev/null
+++ b/extensions/TimedMediaHandler/maintenance/moveTranscoded.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * move transcoded files from thumb to transcoded container
+ *
+ */
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = dirname( __FILE__ ) . '/../../..';
+}
+require_once( "$IP/maintenance/Maintenance.php" );
+
+class MoveTranscoded extends Maintenance {
+
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "move transcoded files from thumb to transcoded container.";
+ }
+ public function execute() {
+ global $wgEnabledTranscodeSet;
+
+ $this->output( "Move transcoded files:\n" );
+ $dbr = wfGetDB( DB_SLAVE );
+ $res = $dbr->select( 'transcode', '*', array(), __METHOD__ );
+ foreach ( $res as $row ) {
+ $title = Title::newFromText( $row->transcode_image_name, NS_FILE );
+ $file = wfLocalFile( $title );
+ if ( !$file ) {
+ continue;
+ }
+ $oldPath = $file->getThumbPath( $file->getName() . '.' . $row->transcode_key );
+
+ $newPath = WebVideoTranscode::getDerivativeFilePath( $file, $row->transcode_key );
+ if ($oldPath != $newPath) {
+ if( $file->repo->fileExists( $oldPath ) ){
+ if( $file->repo->fileExists( $newPath ) ){
+ $res = $file->repo->quickPurge( $oldPath );
+ if( !$res ){
+ wfDebug( "Could not delete file $oldPath\n" );
+ } else {
+ $this->output( "deleted $oldPath, exists in transcoded container\n" );
+ }
+ } else {
+ $this->output( " $oldPath => $newPath\n" );
+ $file->repo->quickImport( $oldPath, $newPath );
+ $file->repo->quickPurge( $oldPath );
+ }
+ }
+ }
+
+ }
+ $this->output( "Finished!\n" );
+ }
+}
+
+$maintClass = 'MoveTranscoded'; // Tells it to run the class
+require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/extensions/TimedMediaHandler/maintenance/resetTranscodes.php b/extensions/TimedMediaHandler/maintenance/resetTranscodes.php
new file mode 100644
index 00000000..ca3493ed
--- /dev/null
+++ b/extensions/TimedMediaHandler/maintenance/resetTranscodes.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * reset stalled transcodes
+ *
+ */
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = dirname( __FILE__ ) . '/../../..';
+}
+require_once( "$IP/maintenance/Maintenance.php" );
+
+class ResetTranscodes extends Maintenance {
+
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Reset stalled transcodes, that are no longer in the job queue.";
+ }
+ public function execute() {
+ global $wgEnabledTranscodeSet;
+ $where = array(
+ "transcode_time_startwork" => NULL,
+ "transcode_time_error" => NULL
+ );
+ $dbr = wfGetDB( DB_SLAVE );
+ $res = $dbr->select( 'transcode', '*', $where, __METHOD__ );
+ foreach ( $res as $row ) {
+ $title = Title::newFromText( $row->transcode_image_name, NS_FILE );
+ // re-insert WebVideoTranscodeJob,
+ // will only be added if not in queue
+ // due to deduplication
+ $job = new WebVideoTranscodeJob( $title, array(
+ 'transcodeMode' => 'derivative',
+ 'transcodeKey' => $row->transcode_key,
+ ) );
+ $job->insert();
+ }
+ }
+}
+
+$maintClass = 'ResetTranscodes'; // Tells it to run the class
+require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/extensions/TimedMediaHandler/maintenance/retryTranscodes.php b/extensions/TimedMediaHandler/maintenance/retryTranscodes.php
new file mode 100644
index 00000000..be1ab9ee
--- /dev/null
+++ b/extensions/TimedMediaHandler/maintenance/retryTranscodes.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Retry transcodes for a given key or error.
+ * This script can be used after updating/fixing
+ * the encoding pipeline to rerun transcodes
+ * that are known to work now.
+ *
+ */
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = dirname( __FILE__ ) . '/../../..';
+}
+require_once( "$IP/maintenance/Maintenance.php" );
+
+class RetryTranscodes extends Maintenance {
+
+ public function __construct() {
+ parent::__construct();
+ $this->addOption( "key", "retry all failed transcodes for given key", false, true );
+ $this->addOption( "error", "retry all failed transcodes matching error substring", false, true);
+ $this->mDescription = "retry transcodes for given key or error";
+ }
+ public function execute() {
+ if ( !$this->hasOption( "error" ) && !$this->hasOption( "key" ) ) {
+ $this->output("You have to provide --key and/or --error\n");
+ return;
+ }
+ $dbw = wfGetDB( DB_MASTER );
+ $cond = array();
+ $cond[] = 'transcode_time_error IS NOT NULL';
+ if ( $this->hasOption( "key" ) ) {
+ $cond['transcode_key'] = $this->getOption( 'key' );
+ }
+ if ( $this->hasOption( "error" ) ) {
+ $cond[] = "transcode_error " . $dbw->buildLike( $dbw->anyString(),
+ $this->getOption( 'error' ), $dbw->anyString() );
+ }
+ do {
+ $res = $dbw->select( 'transcode', 'transcode_id',
+ $cond, __METHOD__, array( 'LIMIT' => 100 ) );
+ $ids = array();
+ foreach ( $res as $row ) {
+ $ids[] = $row->transcode_id;
+ }
+ if ( $ids ) {
+ $dbw->delete( 'transcode',
+ array( 'transcode_id' => $ids ), __METHOD__ );
+ wfWaitForSlaves();
+ }
+ } while ($ids);
+ }
+}
+
+$maintClass = 'RetryTranscodes'; // Tells it to run the class
+require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/extensions/TimedMediaHandler/mwEmbedLoader.php b/extensions/TimedMediaHandler/mwEmbedLoader.php
new file mode 100644
index 00000000..ae03a3dd
--- /dev/null
+++ b/extensions/TimedMediaHandler/mwEmbedLoader.php
@@ -0,0 +1,24 @@
+<?php
+// This is a stub entry point to load.php This is need to support valid paths for the stand alone
+// mwEmbed module html test files.
+
+// This is useful for running stand alone test of mwEmbed components in the TimedMediaHandler
+// extension. ( ie MwEmbedModules/EmbedPlayer/tests/*.html files )
+
+$_GET['modules'] = 'startup';
+$_GET['only'] = 'scripts';
+
+// NOTE this won't work so well with symbolic links
+$loaderPath = dirname(__FILE__) . '/../../load.php';
+if( is_file( $loaderPath ) ){
+ chdir( dirname( $loaderPath ) );
+ include_once( $loaderPath );
+} else {
+ print "if( console && typeof console.log == 'function' ){ console.log('Error can't find load.php for stand alone tests' ) }";
+}
+// Bootstrap some js code to make the "loader" work in stand alone tests:
+// Note this has to be wrapped in a document.write to run after other document.writes
+$pageStartupScript = ResourceLoader::makeInlineScript(
+ Xml::encodeJsCall( 'mw.loader.go', array() )
+);
+echo Xml::encodeJsCall( 'document.write', array( $pageStartupScript ) );
diff --git a/extensions/TimedMediaHandler/package.json b/extensions/TimedMediaHandler/package.json
new file mode 100644
index 00000000..30067c35
--- /dev/null
+++ b/extensions/TimedMediaHandler/package.json
@@ -0,0 +1,14 @@
+{
+ "private": true,
+ "scripts": {
+ "test": "grunt test"
+ },
+ "devDependencies": {
+ "grunt": "0.4.5",
+ "grunt-cli": "0.1.13",
+ "grunt-contrib-jshint": "0.11.3",
+ "grunt-banana-checker": "0.2.2",
+ "grunt-jscs": "1.8.0",
+ "grunt-jsonlint": "1.0.4"
+ }
+}
diff --git a/extensions/TimedMediaHandler/resources/PopUpThumbVideo.css b/extensions/TimedMediaHandler/resources/PopUpThumbVideo.css
new file mode 100644
index 00000000..3ba0572a
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/PopUpThumbVideo.css
@@ -0,0 +1,29 @@
+.PopUpMediaTransform a .play-btn-large{
+ position : absolute;
+ top: 50%;
+ left : 50%;
+ width: 70px;
+ height: 53px;
+ margin-left: -35px;
+ margin-top: -25px;
+ /* @embed */
+ background-image:url('player_big_play_button.png');
+}
+.PopUpMediaTransform a .play-btn-large :hover{
+ /* @embed */
+ background-image:url('player_big_play_button_hover.png');
+}
+.PopUpMediaTransform {
+ position : relative;
+ display: inline-block;
+}
+/* Should hopefully be only visible to screen readers */
+.mw-tmh-playtext {
+ display: block;
+ height: 0;
+ overflow: hidden;
+}
+
+li.gallerybox div.thumb div.PopUpMediaTransform {
+ margin: 0 auto;
+}
diff --git a/extensions/TimedMediaHandler/resources/download_sprite.png b/extensions/TimedMediaHandler/resources/download_sprite.png
new file mode 100644
index 00000000..541d4a99
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/download_sprite.png
Binary files differ
diff --git a/extensions/TimedMediaHandler/resources/embedPlayerIframe.css b/extensions/TimedMediaHandler/resources/embedPlayerIframe.css
new file mode 100644
index 00000000..eb6e9003
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/embedPlayerIframe.css
@@ -0,0 +1,7 @@
+body {
+ margin-left: 0px;
+ margin-top: 0px;
+ margin-right: 0px;
+ margin-bottom: 0px;
+ overflow: hidden;
+}
diff --git a/extensions/TimedMediaHandler/resources/ext.tmh.OgvJsSupport.js b/extensions/TimedMediaHandler/resources/ext.tmh.OgvJsSupport.js
new file mode 100644
index 00000000..af3fd9f5
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/ext.tmh.OgvJsSupport.js
@@ -0,0 +1,67 @@
+( function( $, mw ) {
+
+ var support = mw.OgvJsSupport = {
+ /**
+ * Ensure that the OGVPlayer class is loaded before continuing.
+ *
+ * @return jQuery.Deferred
+ */
+ loadOgvJs: function() {
+ return $.Deferred( function( deferred ) {
+ if ( typeof OGVPlayer === 'undefined' ) {
+ mw.loader.using( 'ext.tmh.OgvJs', function() {
+ OGVLoader.base = support.basePath();
+ deferred.resolve();
+ } );
+ } else {
+ deferred.resolve();
+ }
+ });
+ },
+
+ /**
+ * Get the base path of ogv.js and friends.
+ *
+ * @return string
+ */
+ basePath: function() {
+ var ext = mw.config.get( 'wgExtensionAssetsPath' ),
+ binPlayers = ext + '/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers';
+ return binPlayers + '/ogv.js';
+ },
+
+ /**
+ * Return a stub audio context
+ *
+ * This is used for iOS Safari to enable Web Audio by triggering an empty
+ * audio output channel during a user input event handler. Without that,
+ * audio is left disabled and won't work when we start things up after an
+ * asynchronous code load.
+ *
+ * @return AudioContext
+ */
+ initAudioContext: function() {
+ var AudioContext = window.AudioContext || window.webkitAudioContext;
+ if ( AudioContext ) {
+ var context = new AudioContext(),
+ node;
+ if ( context.createScriptProcessor ) {
+ node = context.createScriptProcessor( 1024, 0, 2 );
+ } else if ( context.createJavaScriptNode ) {
+ node = context.createJavaScriptNode( 1024, 0, 2 );
+ } else {
+ throw new Error( 'Bad version of web audio API?' );
+ }
+
+ // Don't actually run any audio, just start & stop the node
+ node.connect( context.destination );
+ node.disconnect();
+
+ return context;
+ } else {
+ return null;
+ }
+ }
+ };
+
+} )( jQuery, mediaWiki );
diff --git a/extensions/TimedMediaHandler/resources/ext.tmh.TimedTextSelector.js b/extensions/TimedMediaHandler/resources/ext.tmh.TimedTextSelector.js
new file mode 100644
index 00000000..b53bb6f8
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/ext.tmh.TimedTextSelector.js
@@ -0,0 +1,8 @@
+( function ( $, mw ) {
+ $( function () {
+ $( '#timedmedia-tt-go' ).click( function () {
+ window.location = mw.config.get( 'wgScript' ) + '?title=' + mw.util.wikiUrlencode( mw.config.get( 'wgPageName' ) ) + '.' + $( '#timedmedia-tt-input' ).val() + '.srt&action=edit';
+ } );
+ } );
+
+} )( jQuery, mediaWiki );
diff --git a/extensions/TimedMediaHandler/resources/ext.tmh.transcodetable.js b/extensions/TimedMediaHandler/resources/ext.tmh.transcodetable.js
new file mode 100644
index 00000000..a8c8f98d
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/ext.tmh.transcodetable.js
@@ -0,0 +1,90 @@
+/**
+* Javascript to support transcode table on image page
+*/
+( function ( mw, $ ) {
+ $( document ).ready( function () {
+ var errorPopup, $errorLink;
+
+ errorPopup = function () {
+ // pop up dialog
+ mw.addDialog( {
+ 'width': '640',
+ 'height': '480',
+ 'title': $(this).attr( 'title' ),
+ 'content': $('<textarea />')
+ .css( {
+ 'width':'99%',
+ 'height':'99%'
+ } )
+ .text( $(this).attr('data-error') )
+ } )
+ .css( 'overflow', 'hidden' );
+ return false;
+ };
+
+ // Old version. Need to keep for a little while in case of cached pages.
+ $( '.mw-filepage-transcodestatus .errorlink' ).click( errorPopup );
+ // New version.
+ $errorLink = $( '.mw-filepage-transcodestatus .mw-tmh-pseudo-error-link' );
+ $errorLink.wrapInner( function () {
+ var $this = $( this );
+ return $( '<a />' ).attr( {
+ href: '#',
+ title: $this.text(),
+ 'data-error': $this.attr( 'data-error' )
+ } ).click( errorPopup );
+ } );
+
+ // Reset transcode action:
+ $( '.mw-filepage-transcodereset a' ).click( function () {
+ var tKey = $( this ).attr( 'data-transcodekey' ),
+ buttons = {};
+
+ buttons[ mw.msg( 'mwe-ok' ) ] = function () {
+ var api,
+ _thisDialog = this,
+ cancelBtn = {};
+
+ // Only show cancel button while loading:
+ cancelBtn[ mw.msg( 'mwe-cancel' ) ] = function () {
+ $(this).dialog( 'close' );
+ };
+ $( _thisDialog ).dialog( 'option', 'buttons', cancelBtn );
+
+ $( this ).loadingSpinner();
+
+ api = new mw.Api();
+ api.postWithEditToken( {
+ 'action' : 'transcodereset',
+ 'transcodekey' : tKey,
+ 'title' : mw.config.get('wgPageName')
+ } ).done( function () {
+ // Refresh the page
+ location.reload();
+ } ).fail( function ( code, data ) {
+ if( data.error && data.error.info ){
+ $( _thisDialog ).text( data.error.info );
+ } else {
+ $( _thisDialog ).text( mw.msg( 'timedmedia-reset-error' ) );
+ }
+ var okBtn = {};
+ okBtn[ mw.msg('mwe-ok') ] = function() { $(this).dialog( 'close' ); };
+ $( _thisDialog ).dialog( 'option', 'buttons', okBtn );
+ } );
+ };
+ buttons[ mw.msg( 'mwe-cancel' ) ] = function () {
+ $( this ).dialog( 'close' );
+ };
+ // pop up dialog
+ mw.addDialog( {
+ 'width': '400',
+ 'height': '200',
+ 'title': mw.msg( 'timedmedia-reset' ),
+ 'content': mw.msg( 'timedmedia-reset-confirm' ),
+ 'buttons': buttons
+ } )
+ .css( 'overflow', 'hidden' );
+ return false;
+ });
+ });
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/resources/mw.MediaWikiPlayer.loader.js b/extensions/TimedMediaHandler/resources/mw.MediaWikiPlayer.loader.js
new file mode 100644
index 00000000..6167418b
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/mw.MediaWikiPlayer.loader.js
@@ -0,0 +1,8 @@
+( function ( mw, $ ) {
+ // Add MediaWikiSupportPlayer dependency on players with a mediaWiki title
+ $( mw ).bind( 'EmbedPlayerUpdateDependencies', function ( event, embedPlayer, dependencySet ) {
+ if ( $( embedPlayer ).attr( 'data-mwtitle' ) ) {
+ $.merge( dependencySet, ['mw.MediaWikiPlayerSupport'] );
+ }
+ } );
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/resources/mw.MediaWikiPlayerSupport.js b/extensions/TimedMediaHandler/resources/mw.MediaWikiPlayerSupport.js
new file mode 100644
index 00000000..16ce367c
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/mw.MediaWikiPlayerSupport.js
@@ -0,0 +1,380 @@
+( function ( mw, $ ) {
+ /**
+ * Merge in the default video attributes supported by embedPlayer:
+ */
+ mw.mergeConfig( 'EmbedPlayer.Attributes', {
+ // A apiTitleKey for looking up subtitles, credits and related videos
+ 'data-mwtitle': null,
+
+ // The apiProvider where to lookup the title key
+ 'data-mwprovider': null
+ } );
+
+ // Add mediaWiki player support to target embedPlayer
+ $( mw ).bind( 'EmbedPlayerNewPlayer', function ( event, embedPlayer ) {
+ mw.addMediaWikiPlayerSupport( embedPlayer );
+ });
+
+ /**
+ * Closure function wraps mediaWiki embedPlayer bindings
+ */
+ mw.addMediaWikiPlayerSupport = function ( embedPlayer ) {
+ var apiTitleKey, apiProvider, $creditsCache = false;
+ // Set some local variables:
+ if ( !embedPlayer['data-mwtitle'] ) {
+ return false;
+ } else {
+ apiTitleKey = embedPlayer['data-mwtitle'];
+ // legacy support ( set as attribute )
+ embedPlayer.apiTitleKey = apiTitleKey;
+ }
+ // Set local apiProvider via config if not defined
+ apiProvider = embedPlayer['data-mwprovider'];
+ if ( !apiProvider ) {
+ apiProvider = mw.config.get( 'EmbedPlayer.ApiProvider' );
+ }
+
+ /**
+ * Loads mediaWiki sources for a given embedPlayer
+ * @param {function} callback Function called once player sources have been added
+ */
+ function loadPlayerSources( callback ) {
+ // Setup the request
+ var request = {
+ 'prop': 'imageinfo',
+ // In case the user added File: or Image: to the apiKey:
+ 'titles': 'File:' + decodeURIComponent( apiTitleKey ).replace( /^(File:|Image:)/, '' ),
+ 'iiprop': 'url|size|dimensions|metadata',
+ 'iiurlwidth': embedPlayer.getWidth(),
+ 'redirects': true // automatically resolve redirects
+ };
+
+ // Run the request:
+ mw.getJSON( mw.getApiProviderURL( apiProvider ), request, function ( data ) {
+ var i, page, imageinfo;
+ if ( data.query.pages ) {
+ for ( i in data.query.pages ) {
+ if ( i === '-1' ) {
+ callback( false );
+ return ;
+ }
+ page = data.query.pages[i];
+ }
+ } else {
+ callback( false );
+ return ;
+ }
+ // Make sure we have imageinfo:
+ if ( !page.imageinfo || !page.imageinfo[0] ) {
+ callback( false );
+ return ;
+ }
+ imageinfo = page.imageinfo[0];
+
+ // TODO these should call public methods rather than update internals:
+
+ // Update the poster
+ embedPlayer.poster = imageinfo.thumburl;
+
+ // Add the media src
+ embedPlayer.mediaElement.tryAddSource(
+ $( '<source />' )
+ .attr( 'src', imageinfo.url )
+ .get( 0 )
+ );
+
+ // Set the duration
+ if ( imageinfo.metadata[2].name === 'length' ) {
+ embedPlayer.duration = imageinfo.metadata[2].value;
+ }
+
+ // Set the width height
+ // Make sure we have an accurate aspect ratio
+ if ( imageinfo.height !== 0 && imageinfo.width !== 0 ) {
+ embedPlayer.height = Math.floor( embedPlayer.width * ( imageinfo.height / imageinfo.width ) );
+ }
+
+ // Update the css for the player interface
+ $( embedPlayer ).css( 'height', embedPlayer.height );
+
+ callback();
+ });
+ }
+
+ /**
+ * Build a clip credit from the resource wikiText page
+ *
+ * TODO parse the resource page template
+ *
+ * @param {String} resourceHTML Resource wiki text page contents
+ */
+ function doCreditLine( resourceHTML, articleUrl ) {
+ var authUrl, $page, $author, $authorText, $links, $date, $authorLink,
+ imgSize = {},
+ // Get the title string ( again a "Title" like js object could help out here. )
+ titleStr = embedPlayer.apiTitleKey.replace( /_/g, ' ' ),
+ // Setup the initial credits line:
+ $creditLine = $( '<div />' );
+
+ // Add the title:
+ $creditLine.append(
+ $( '<span>' ).html(
+ mw.msg( 'mwe-embedplayer-credit-title',
+ // get the link
+ $( '<div>' ).append(
+ $( '<a/>' ).attr( {
+ 'href': articleUrl,
+ 'title': titleStr
+ } )
+ .text( titleStr )
+ )[0].innerHTML
+ )
+ )
+ );
+
+ // Parse some data from the page info template if possible:
+ $page = $( resourceHTML );
+
+ // Look for author:
+ $author = $page.find( '#fileinfotpl_aut' );
+ if ( $author.length ) {
+ // Get the real author sibling of fileinfotpl_aut
+ $authorText = $author.next();
+ // Remove white space:
+ $authorText.find( 'br' ).remove();
+
+ // Update link to be absolute per page url context:
+ $links = $authorText.find( 'a' );
+ if ( $links.length ) {
+ $links.each( function ( i, authorLink ) {
+ $authorLink = $( authorLink );
+ authUrl = $authorLink.attr( 'href' );
+ authUrl = mw.absoluteUrl( authUrl, articleUrl );
+ $authorLink.attr( 'href', authUrl );
+ });
+ }
+ $creditLine.append( $( '<br />' ),
+ mw.msg( 'mwe-embedplayer-credit-author', $authorText.html() )
+ );
+ }
+
+ // Look for date:
+ $date = $page.find( '#fileinfotpl_date' );
+ if ( $date.length ) {
+ // Get the real date sibling of fileinfotpl_date
+ $date = $date.next();
+
+ // remove white space:
+ $date.find( 'br' ).remove();
+ $creditLine.append( $( '<br />' ),
+ mw.msg( 'mwe-embedplayer-credit-date', $date.html() )
+ );
+ }
+
+ // Build out the image and credit line
+ if ( embedPlayer.isAudio() ) {
+ imgSize.height = imgSize.width = ( embedPlayer.controlBuilder.getOverlayWidth() < 250 ) ? 45 : 80;
+ } else {
+ imgSize.width = ( embedPlayer.controlBuilder.getOverlayWidth() < 250 ) ? 45 : 120;
+ imgSize.height = Math.floor( imgSize.width * ( embedPlayer.getHeight() / embedPlayer.getWidth() ) );
+ }
+ return $( '<div/>' ).addClass( 'creditline' )
+ .append(
+ $( '<a/>' ).attr( {
+ 'href': articleUrl,
+ 'title': titleStr
+ } ).html(
+ $( '<img/>' ).attr( {
+ 'border': 0,
+ 'src': embedPlayer.poster
+ } ).css( imgSize )
+ )
+ )
+ .append(
+ $creditLine
+ );
+ }
+
+ /**
+ * Issues a request to populate the credits box
+ */
+ function showCredits( $target, callback ) {
+ var apiUrl, fileTitle, request;
+ if ( $creditsCache ) {
+ $target.html( $creditsCache );
+ callback( true );
+ return;
+ }
+ // Setup shortcuts:
+ apiUrl = mw.getApiProviderURL( apiProvider );
+ fileTitle = 'File:' + decodeURIComponent( apiTitleKey ).replace( /^File:|^Image:/, '');
+
+ // Get the image page ( cache for 1 hour )
+ request = {
+ 'action': 'parse',
+ 'page': fileTitle,
+ 'smaxage': 3600,
+ 'maxage': 3600
+ };
+ mw.getJSON( apiUrl, request, function ( data ) {
+ var descUrl = apiUrl.replace( 'api.php', 'index.php');
+ descUrl += '?title=' + encodeURIComponent( fileTitle );
+ if ( data && data.parse && data.parse.text && data.parse.text['*'] ) {
+ // TODO improve provider 'concept' to support page title link
+ $creditsCache = doCreditLine( data.parse.text['*'], descUrl );
+ } else {
+ $creditsCache = doCreditLine( false, descUrl );
+ }
+ $target.html( $creditsCache );
+ callback( true );
+ } );
+ }
+ /**
+ * Adds embedPlayer Bindings
+ */
+
+ // Show credits when requested
+ $( embedPlayer ).bindQueueCallback( 'showCredits', function ( $target, callback ) {
+ if ( $target.data( 'playerId') !== embedPlayer.id ) {
+ // bad event trigger
+ return ;
+ }
+ // Only request the credits once:
+ showCredits( $target, callback );
+ });
+
+ // Show credits on clip complete:
+ $( embedPlayer ).bind( 'onEndedDone', function ( event, id ) {
+ if ( embedPlayer.id !== id ) {
+ // possible event trigger error. ( skip )
+ return ;
+ }
+ // dont show credits for audio elements,
+ // seek to begining instead
+ if ( embedPlayer.isAudio() ) {
+ embedPlayer.setCurrentTime( 0 );
+ return ;
+ }
+ var cb = embedPlayer.controlBuilder;
+ cb.checkMenuOverlay();
+ cb.showMenuOverlay();
+ cb.showMenuItem( 'credits' );
+ });
+
+ $( embedPlayer ).bind( 'showInlineDownloadLink', function () {
+ // Add recommend HTML5 player if we have non-native playback:
+ if ( embedPlayer.controlBuilder.checkNativeWarning( ) ) {
+ embedPlayer.controlBuilder.addWarningBinding(
+ 'EmbedPlayer.ShowNativeWarning',
+ mw.msg( 'mwe-embedplayer-for_best_experience',
+ $( '<div>' ).append(
+ $( '<a />' ).attr({
+ 'href': 'http://www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download',
+ 'target': '_new'
+ })
+ )[0].innerHTML
+ ),
+ true
+ );
+ }
+ });
+
+ $( embedPlayer ).bind( 'TimedText_BuildCCMenu', function ( event, $menu, id ) {
+ var _this,
+ pageTitle,
+ addTextPage,
+ $li;
+ if ( id !== embedPlayer.id ) {
+ _this = $( '#' + id )[0].timedText;
+ embedPlayer = _this.embedPlayer;
+ }
+ // Put in the "Make Transcript" link if config enabled and we have an api key
+ if ( embedPlayer.apiTitleKey ) {
+ // check if not already there:
+ if ( $menu.find( '.add-timed-text' ).length ) {
+ // add text link already present
+ return ;
+ }
+
+ pageTitle = 'TimedText:' +
+ decodeURIComponent( embedPlayer.apiTitleKey ).replace( /^File:|^Image:/, '' );
+ addTextPage = mw.getApiProviderURL( apiProvider )
+ .replace( 'api.php', 'index.php') +
+ '?title=' + encodeURIComponent( pageTitle );
+
+ $li = $.getLineItem( mw.msg( 'mwe-timedtext-upload-timed-text'), 'script', function () {
+ window.location = addTextPage;
+ });
+
+ $li.addClass( 'add-timed-text')
+ .find( 'a' )
+ .attr( {
+ 'href': addTextPage,
+ 'target': '_new'
+ } );
+ $menu.append(
+ $li
+ );
+ }
+ });
+
+ $( embedPlayer ).bindQueueCallback( 'checkPlayerSourcesEvent', function ( callback ) {
+ // Only load source if none are available:
+ if ( embedPlayer.mediaElement.sources.length === 0 ) {
+ loadPlayerSources( callback );
+ } else {
+ // No source to load, issue callback directly
+ callback();
+ }
+ } );
+ $( mw ).bindQueueCallback( 'TimedText_LoadTextSource', function ( source, callback ) {
+ if ( !source.mwtitle || !source.mwprovider ) {
+ callback();
+ return ;
+ }
+ // Load via api
+ var apiUrl = mw.getApiProviderURL( source.mwprovider ),
+ // Get the image page ( cache for 1 hour )
+ request = {
+ 'action': 'parse',
+ 'page': source.mwtitle,
+ 'smaxage': 3600,
+ 'maxage': 3600
+ };
+ mw.getJSON( apiUrl, request, function ( data ) {
+ if ( data && data.parse && data.parse.text && data.parse.text['*'] ) {
+ source.loaded = true;
+ source.mimeType = 'text/mw-srt';
+ source.captions = source.getCaptions( data.parse.text['*'] );
+ callback();
+ } else {
+ mw.log( 'Error: MediaWiki api error in getting timed text:', data );
+ callback();
+ }
+ });
+ });
+
+ $( embedPlayer ).bind( 'getShareIframeSrc', function ( event, callback, id ) {
+ if ( id !== embedPlayer.id ) {
+ embedPlayer = $( '#' + id )[0];
+ }
+ var iframeUrl = false;
+ // Do a special check for wikimediacommons provider as a known shared reop
+ if ( embedPlayer['data-mwprovider'] === 'wikimediacommons' ) {
+ iframeUrl = '//commons.wikimedia.org/wiki/File:' + decodeURIComponent( embedPlayer.apiTitleKey ).replace( /^(File:|Image:)/, '' );
+ } else {
+ // use the local wiki:
+ if ( mw.config.get( 'wgServer' ) && mw.config.get( 'wgArticlePath' ) ) {
+ iframeUrl = mw.config.get( 'wgServer' ) +
+ mw.config.get( 'wgArticlePath' ).replace( /\$1/, 'File:' +
+ decodeURIComponent( embedPlayer.apiTitleKey ).replace( /^(File:|Image:)/, '' ) );
+ }
+ }
+ if ( iframeUrl ) {
+ iframeUrl += '?embedplayer=yes';
+ }
+ callback( iframeUrl );
+ });
+ };
+
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/resources/mw.PopUpThumbVideo.js b/extensions/TimedMediaHandler/resources/mw.PopUpThumbVideo.js
new file mode 100644
index 00000000..c0aa30df
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/mw.PopUpThumbVideo.js
@@ -0,0 +1,44 @@
+/**
+* Simple script to add pop-up video dialog link support for video thumbnails
+*/
+( function ( mw, $ ) {
+ $( document ).ready( function () {
+ $('.PopUpMediaTransform a').each( function () {
+ var link, title,
+ parent = $( this ).parent();
+ if ( parent.attr( 'videopayload' ) ) {
+ $( this ).click( function ( /*event*/ ) {
+ var thisref = this;
+
+ mw.loader.using( 'mw.MwEmbedSupport', function () {
+ var $videoContainer = $( $( thisref ).parent().attr( 'videopayload' ) );
+ mw.addDialog({
+ 'width': 'auto',
+ 'height': 'auto',
+ 'title': mw.html.escape( $videoContainer.find( 'video, audio' ).attr( 'data-mwtitle' ) ),
+ 'content': $videoContainer,
+ 'close': function(){
+ // On close destroy the dialog rather than just hiding it,
+ // so it doesn't eat up resources or keep playing.
+ $( this ).remove();
+ return true;
+ },
+ 'open': function() {
+ $( this ).find( 'video, audio' ).embedPlayer();
+ }
+ })
+ .css( 'overflow', 'hidden' );
+ } );
+ // don't follow file link
+ return false;
+ } );
+ } else if ( parent.attr( 'data-videopayload' ) ) {
+ link = $( this ).attr( 'href' );
+ title = mw.Title.newFromImg( { src: link } );
+ if ( title && title.getPrefixedDb() !== mw.config.get( 'wgPageName' ) ) {
+ $( this ).attr( 'href', title.getUrl() );
+ }
+ } /* else fall back to linking directly to media file */
+ } );
+ } );
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/resources/mw.TMHGalleryHook.js b/extensions/TimedMediaHandler/resources/mw.TMHGalleryHook.js
new file mode 100644
index 00000000..fd23690e
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/mw.TMHGalleryHook.js
@@ -0,0 +1,46 @@
+/**
+* Simple script to add pop-up video dialog link support for video thumbnails
+*/
+( function ( mw ) {
+ // Hook to allow dynamically resizing videos in image galleries
+ mw.hook( 'mediawiki.page.gallery.resize' ).add( function ( info ) {
+ var $mwPlayerContainer,
+ $popUp,
+ $tmhVideo,
+ $mwContainer = info.$imageDiv.find( '.mediaContainer' );
+ if ( info.resolved ) {
+ // Everything is already done here.
+ return;
+ }
+
+ $mwContainer = info.$imageDiv.find( '.mediaContainer' );
+ if ( $mwContainer.length ) {
+ // Add some padding, so caption doesn't overlap video controls if
+ // we are overlaying the caption on top of the image.
+ if ( !info.$outerDiv.parent().hasClass( 'mw-gallery-packed' ) ) {
+ info.$outerDiv.find( 'div.gallerytext' ).css( 'padding-bottom', '20px' );
+ }
+
+ info.$imageDiv.width( info.imgWidth );
+ $mwContainer.width( info.imgWidth );
+ $mwPlayerContainer = $mwContainer.children( '.mwPlayerContainer' );
+ if ( $mwPlayerContainer.length ) {
+ // Case 1: HTML5 player already loaded
+ $mwPlayerContainer.width( info.imgWidth ).height( info.imgHeight );
+ $mwPlayerContainer.find( 'img.playerPoster' ).width( info.imgWidth ).height( info.imgHeight );
+ } else {
+ // Case 2: Raw video element
+ $tmhVideo = info.$imageDiv.find( 'video' );
+ $tmhVideo.width( info.imgWidth ).height( info.imgHeight );
+ }
+ info.resolved = true;
+ return;
+ }
+
+ $popUp = info.$imageDiv.find( '.PopUpMediaTransform' );
+ if ( $popUp.length ) {
+ info.$imageDiv.width( info.imgWidth );
+ $popUp.add( $popUp.find( 'img' ) ).width( info.imgWidth ).height( info.imgHeight );
+ }
+ } );
+} )( mediaWiki );
diff --git a/extensions/TimedMediaHandler/resources/player_big_play_button.png b/extensions/TimedMediaHandler/resources/player_big_play_button.png
new file mode 100644
index 00000000..041fea9c
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/player_big_play_button.png
Binary files differ
diff --git a/extensions/TimedMediaHandler/resources/player_big_play_button_hover.png b/extensions/TimedMediaHandler/resources/player_big_play_button_hover.png
new file mode 100644
index 00000000..3517563e
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/player_big_play_button_hover.png
Binary files differ
diff --git a/extensions/TimedMediaHandler/resources/transcodeTable.css b/extensions/TimedMediaHandler/resources/transcodeTable.css
new file mode 100644
index 00000000..795ce134
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/transcodeTable.css
@@ -0,0 +1,14 @@
+.mw-filepage-transcodestatus .download-btn {
+ background-image: url('download_sprite.png');
+ width: 49px;
+ height: 36px;
+ background-repeat:no-repeat;
+ background-position: -50px;
+}
+.mw-filepage-transcodestatus .download-btn:hover {
+ background-position: 0 0;
+}
+.mw-filepage-transcodestatus .download-btn span {
+ /* Text hidden by the above image */
+ display: none;
+}
diff --git a/extensions/TimedMediaHandler/tests/phpunit/ApiTestCaseVideoUpload.php b/extensions/TimedMediaHandler/tests/phpunit/ApiTestCaseVideoUpload.php
new file mode 100644
index 00000000..9dd4cb52
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/ApiTestCaseVideoUpload.php
@@ -0,0 +1,130 @@
+<?php
+/**
+ * Abstract test class to support Video Tests with video uploads
+ * @author dale
+ */
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+ exit;
+}
+
+// Include core class ApiTestCaseUpload ( not part of base autoLoader )
+global $IP;
+require_once( "$IP/tests/phpunit/includes/api/ApiTestCaseUpload.php" );
+
+abstract class ApiTestCaseVideoUpload extends ApiTestCaseUpload {
+ /**
+ * @return Array set of test files with associated metadata
+ */
+ static function mediaFilesProvider(){
+ return array(
+ array(
+ // Double wrap the file array to match phpunit data provider conventions
+ array(
+ 'mime' => 'application/ogg',
+ 'filePath' => dirname( __FILE__ ) . '/media/test5seconds.electricsheep.300x400.ogv',
+ "size" => 301477,
+ "width" => 400,
+ "height" => 300,
+ "mediatype" => "VIDEO",
+ "bandwidth" => 452216,
+ "framerate" => 30
+ )
+ ),
+ array(
+ array(
+ 'mime' => 'video/webm',
+ 'filePath' => dirname( __FILE__ ) . '/media/shuttle10seconds.1080x608.webm',
+ "size" => 699018,
+ "width" => 1080,
+ "height" => 608,
+ "mediatype" => "VIDEO",
+ "bandwidth" => 522142,
+ "framerate" => 29.97
+ )
+ )
+ );
+ }
+ /**
+ * Fixture -- run after every test
+ * Clean up temporary files etc.
+ *
+ */
+ protected function tearDown() {
+ parent::tearDown();
+
+ $testMediaFiles = $this->mediaFilesProvider();
+ foreach( $testMediaFiles as $file ){
+ $file = $file[0];
+ // Clean up and delete all files
+ $this->deleteFileByFilename( $file['filePath'] );
+ }
+ }
+
+ /**
+ * Do login
+ */
+ protected function doLogin( $user = 'sysop' ) {
+ $user = self::$users['uploader'];
+
+ $params = array(
+ 'action' => 'login',
+ 'lgname' => $user->username,
+ 'lgpassword' => $user->password
+ );
+ list( $result, , $session ) = $this->doApiRequest( $params );
+ $token = $result['login']['token'];
+
+ $params = array(
+ 'action' => 'login',
+ 'lgtoken' => $token,
+ 'lgname' => $user->username,
+ 'lgpassword' => $user->password
+ );
+ list( $result, , $session ) = $this->doApiRequest( $params, $session );
+ return $session;
+ }
+
+ /**
+ * uploads a file:
+ */
+ public function uploadFile( $file ){
+ global $wgUser;
+ // get a session object
+ $session = $this->doLogin();
+ // Update the global user:
+ $wgUser = self::$users['uploader']->getUser();
+
+ // Upload the media file:
+ $fileName = basename( $file['filePath'] );
+
+ // remove if already in thd db:
+ $this->deleteFileByFileName( $fileName );
+ $this->deleteFileByContent( $file['filePath'] );
+
+ if ( !$this->fakeUploadFile( 'file', $fileName, $file['mime'], $file['filePath'] ) ) {
+ $this->markTestIncomplete( "Couldn't upload file!\n" );
+ }
+
+ $params = array(
+ 'action' => 'upload',
+ 'filename' => $fileName,
+ 'file' => 'dummy content',
+ 'comment' => 'dummy comment',
+ 'text' => "This is the page text for $fileName",
+ // This uploadFile function supports video tests not a test upload warnings
+ 'ignorewarnings' => true
+ );
+
+ try{
+ list( $result, , ) = $this->doApiRequestWithToken( $params, $session );
+ } catch( Exception $e ) {
+ // Could not upload mark test that called uploadFile as incomplete
+ $this->markTestIncomplete( $e->getMessage() );
+ }
+
+ return $result;
+
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/tests/phpunit/README b/extensions/TimedMediaHandler/tests/phpunit/README
new file mode 100644
index 00000000..dd9eba39
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/README
@@ -0,0 +1,11 @@
+
+Some TimedMediaHandler testing notes:
+
+ We have a base class ApiTestCaseVideoUpload that establishes the uploads. Actual uploading
+ is tested in the core uploading support so we focus these tests on timed media handler functionality
+
+ We sometimes combine a few tests because fixtures don't play well with dataProvider
+ since the mediawiki test framework nukes the db every time you run the next test in
+ a given dataProvider data set.
+
+
diff --git a/extensions/TimedMediaHandler/tests/phpunit/TestApiUploadVideo.php b/extensions/TimedMediaHandler/tests/phpunit/TestApiUploadVideo.php
new file mode 100644
index 00000000..ebc38ddf
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/TestApiUploadVideo.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * TestApiUploadVideo test case.
+ *
+ * NOTE: This build heavily on ApiUploadTest ( would need to refactor ApiUploadTest for this to work better )
+ *
+ * @ingroup timedmedia
+ * @since 0.2
+ * @author Michael Dale
+ */
+
+/**
+ * @group Database
+ * @group Destructive
+ * @group medium
+ */
+class TestApiUploadVideo extends ApiTestCaseVideoUpload {
+
+ /**
+ * @dataProvider mediaFilesProvider
+ */
+ public function testUploadVideoFiles( $file ){
+
+ $result = $this->uploadFile( $file );
+
+ // Run asserts
+ $this->assertTrue( isset( $result['upload'] ) );
+ $this->assertEquals( 'Success', $result['upload']['result'] );
+ $this->assertEquals( filesize( $file['filePath'] ), ( int )$result['upload']['imageinfo']['size'] );
+ $this->assertEquals( $file['mime'], $result['upload']['imageinfo']['mime'] );
+
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/tests/phpunit/TestOggHandler.php b/extensions/TimedMediaHandler/tests/phpunit/TestOggHandler.php
new file mode 100644
index 00000000..3c058974
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/TestOggHandler.php
@@ -0,0 +1,67 @@
+<?php
+class TestOggHandler extends MediaWikiMediaTestCase {
+
+ /** @var OggHandlerTMH */
+ private $handler;
+
+ function getFilePath() {
+ return __DIR__ . '/media';
+ }
+
+ function setUp() {
+ parent::setUp();
+ $this->handler = new OggHandlerTMH;
+ }
+
+ /**
+ * @dataProvider providerGetCommonMetaArray
+ * @param $filename String name of file
+ * @param $expected Array
+ */
+ function testGetCommonMetaArray( $filename, $expected ) {
+ $testFile = $this->dataFile( $filename, 'application/ogg' );
+ $this->assertEquals( $expected, $this->handler->getCommonMetaArray( $testFile ) );
+ }
+
+ function providerGetCommonMetaArray() {
+ return array(
+ array( 'test5seconds.electricsheep.300x400.ogv',
+ array(
+ 'Software' => array( 'Lavf53.21.1' ),
+ 'ObjectName' => array( 'Electric Sheep' ),
+ 'UserComment' => array( 'šŸ‘' )
+ )
+ ),
+ array( 'doubleTag.oga',
+ array(
+ 'Artist' => array( 'Brian', 'Bawolff' ),
+ 'Software' => array( 'Lavf55.10.2' )
+ )
+ ),
+ array( 'broken-file.ogg',
+ array()
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider providerGetWebType
+ * @param $filename String name of file
+ * @param $expected String Mime type (including codecs)
+ */
+ function testGetWebType( $filename, $expected ) {
+ $testFile = $this->dataFile( $filename, 'application/ogg' );
+ $this->assertEquals( $expected, $this->handler->getWebType( $testFile ) );
+ }
+
+ function providerGetWebType() {
+ return array(
+ array( 'test5seconds.electricsheep.300x400.ogv', 'video/ogg; codecs="theora"' ),
+ array( 'doubleTag.oga', 'audio/ogg; codecs="vorbis"' ),
+ // XXX: This behaviour is somewhat questionable. It perhaps should be
+ // application/ogg in this case.
+ array( 'broken-file.ogg', 'audio/ogg' ),
+ );
+ }
+
+}
diff --git a/extensions/TimedMediaHandler/tests/phpunit/TestTimeParsing.php b/extensions/TimedMediaHandler/tests/phpunit/TestTimeParsing.php
new file mode 100644
index 00000000..b4ec6ba9
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/TestTimeParsing.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * TestTimeParsing test .
+ *
+ * @ingroup timedmedia
+ * @since 0.2
+ * @author Michael Dale
+ */
+
+
+class TestTimeParsing extends PHPUnit_Framework_TestCase {
+ /**
+ * Test time string to np2
+ */
+ function testSeconds2NptFormat() {
+ // Some time conversions:
+ $this->assertEquals( TimedMediaHandler::seconds2npt( 100 ), '0:1:40' );
+ $this->assertEquals( TimedMediaHandler::seconds2npt( 0 ), '0:0:0' );
+ $this->assertEquals( TimedMediaHandler::seconds2npt( 3601 ), '1:0:1' );
+
+ // Test failures:
+ $this->assertEquals( TimedMediaHandler::seconds2npt( 'foo' ), false );
+ $this->assertEquals( TimedMediaHandler::seconds2npt( -1 ), false );
+ }
+
+ /**
+ * Test time parsing to seconds
+ */
+ function testParseTimeString() {
+ // Some time conversions:
+ $this->assertEquals( TimedMediaHandler::parseTimeString( 100 ), 100 );
+ $this->assertEquals( TimedMediaHandler::parseTimeString( '1:0:0' ), 3600 );
+ $this->assertEquals( TimedMediaHandler::parseTimeString( -1 ), 0 );
+ // Test longer than duration check ( should return time -1 )
+ $this->assertEquals( TimedMediaHandler::parseTimeString( 10, 9 ), 8 );
+
+ // Test failures:
+ $this->assertEquals( TimedMediaHandler::parseTimeString( '1:1:1:1' ), false );
+ $this->assertEquals( TimedMediaHandler::parseTimeString( 'abc' ), false );
+
+ }
+} \ No newline at end of file
diff --git a/extensions/TimedMediaHandler/tests/phpunit/TestTimedMediaHandler.php b/extensions/TimedMediaHandler/tests/phpunit/TestTimedMediaHandler.php
new file mode 100644
index 00000000..2ca350a0
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/TestTimedMediaHandler.php
@@ -0,0 +1,47 @@
+<?php
+class TestTimedMediaHandler extends MediaWikiTestCase {
+
+ /** @var TimedMediaHandler */
+ private $handler;
+
+ function setUp() {
+ $this->handler = new TimedMediaHandler;
+ parent::setUp();
+ }
+
+ /**
+ * @dataProvider providerParseParamString
+ * @param $str String a thumbnail parameter string
+ * @param $expected Array Expected thumbnailing parameters
+ */
+ function testParseParamString( $str, $expected ) {
+ $result = $this->handler->parseParamString( $str );
+ $this->assertEquals( $result, $expected );
+ }
+
+ function providerParseParamString() {
+ return array(
+ array(
+ 'mid',
+ array(),
+ ),
+ array(
+ '220px-',
+ array( 'width' => 220 ),
+ ),
+ array(
+ 'seek=30',
+ array( 'thumbtime' => 30.0 ),
+ ),
+ array(
+ 'seek=15.72',
+ array( 'thumbtime' => 15.72 ),
+ ),
+ array(
+ '180px-seek=15',
+ array( 'thumbtime' => 15, 'width' => 180 ),
+ ),
+ );
+
+ }
+}
diff --git a/extensions/TimedMediaHandler/tests/phpunit/TestTimedMediaTransformOutput.php b/extensions/TimedMediaHandler/tests/phpunit/TestTimedMediaTransformOutput.php
new file mode 100644
index 00000000..9bcc89fb
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/TestTimedMediaTransformOutput.php
@@ -0,0 +1,142 @@
+<?php
+class TestTimedMediaTransformOutput extends MediaWikiMediaTestCase {
+
+ private $sortMethod;
+ private $thumbObj;
+
+ function getFilePath() {
+ return __DIR__ . '/media';
+ }
+
+ protected function setUp() {
+ parent::setUp();
+
+ // Disable video thumbnail generation. Not needed for this test.
+ $reflection = new ReflectionClass( $this->repo );
+ $reflectionProperty = $reflection->getProperty( 'transformVia404' );
+ $reflectionProperty->setAccessible( true );
+ $reflectionProperty->setValue( $this->repo, true );
+
+ $this->setMWGlobals( 'wgMinimumVideoPlayerSize', '400' );
+ }
+
+ /**
+ * @param $width int The requested width of the thumbnail
+ * @param $minVideoSize int The min width a non-pop up video is acceptable
+ * @param $expectPopup boolean Do we expect a pop up video
+ *
+ * @dataProvider providerIsPopUp
+ */
+ function testIsPopUp( $width, $minVideoSize, $expectPopup ) {
+ $this->setMwGlobals( 'wgMinimumVideoPlayerSize', $minVideoSize );
+
+ // Note this file has a width of 400px and a height of 300px
+ $file = $this->dataFile( 'test5seconds.electricsheep.300x400.ogv', 'application/ogg' );
+ $thumbnail = $file->transform( array( 'width' => $width ) );
+ $this->assertTrue( $thumbnail && !$thumbnail->isError() );
+
+ $reflection = new ReflectionClass( $thumbnail );
+ $reflMethod = $reflection->getMethod( 'useImagePopUp' );
+ $reflMethod->setAccessible( true );
+
+ $actual = $reflMethod->invoke( $thumbnail );
+ $this->assertEquals( $actual, $expectPopup );
+
+ }
+
+ function providerIsPopUp() {
+ return array(
+ array( 400, 800, false ),
+ array( 300, 800, true ),
+ array( 300, 200, false ),
+ array( 300, 300, false )
+ );
+ }
+
+ /**
+ * @param $thumbWidth int Requested width
+ * @param $sources array
+ * @param $sortedSources array
+ * @dataProvider providerSortMediaByBandwidth
+ */
+ function testSortMediaByBandwidth( $thumbWidth, $sources, $sortedSources ) {
+ $params = array(
+ 'width' => $thumbWidth,
+ 'height' => $thumbWidth * 9 / 16,
+ 'isVideo' => true,
+ 'fillwindow' => false,
+ 'file' => new FakeDimensionFile( array( 1820, 1024 ) )
+ );
+ $this->thumbObj = new TimedMediaTransformOutput( $params );
+
+ $reflection = new ReflectionClass( $this->thumbObj );
+ $this->sortMethod = $reflection->getMethod( 'sortMediaByBandwidth' );
+ $this->sortMethod->setAccessible( true );
+
+ usort( $sources, array( $this, 'callSortMethodHelper' ) );
+ $this->assertEquals( $sortedSources, $sources );
+ }
+
+ public function callSortMethodHelper( $a, $b ) {
+ return $this->sortMethod->invoke( $this->thumbObj, $a, $b );
+ }
+
+
+ function providerSortMediaByBandwidth() {
+ return array(
+ array(
+ 600,
+ array(
+ array( 'width' => 1000, 'bandwidth' => 2000 ),
+ array( 'width' => 1000, 'bandwidth' => 7000 ),
+ array( 'width' => 1000, 'bandwidth' => 1000 ),
+ ),
+ array(
+ array( 'width' => 1000, 'bandwidth' => 1000 ),
+ array( 'width' => 1000, 'bandwidth' => 2000 ),
+ array( 'width' => 1000, 'bandwidth' => 7000 ),
+ ),
+ ),
+ array(
+ 600,
+ array(
+ array( 'width' => 200, 'bandwidth' => 2000 ),
+ array( 'width' => 1000, 'bandwidth' => 7000 ),
+ array( 'width' => 200, 'bandwidth' => 1000 ),
+ ),
+ array(
+ array( 'width' => 1000, 'bandwidth' => 7000 ),
+ array( 'width' => 200, 'bandwidth' => 1000 ),
+ array( 'width' => 200, 'bandwidth' => 2000 ),
+ ),
+ ),
+ array(
+ /* Pop up viewer in this case */
+ 100,
+ array(
+ array( 'width' => 700, 'bandwidth' => 2000 ),
+ array( 'width' => 1000, 'bandwidth' => 7000 ),
+ array( 'width' => 700, 'bandwidth' => 1000 ),
+ ),
+ array(
+ array( 'width' => 1000, 'bandwidth' => 7000 ),
+ array( 'width' => 700, 'bandwidth' => 1000 ),
+ array( 'width' => 700, 'bandwidth' => 2000 ),
+ ),
+ ),
+ array(
+ 600,
+ array(
+ array( 'width' => 700, 'bandwidth' => 2000 ),
+ array( 'width' => 800, 'bandwidth' => 7000 ),
+ array( 'width' => 1000, 'bandwidth' => 1000 ),
+ ),
+ array(
+ array( 'width' => 1000, 'bandwidth' => 1000 ),
+ array( 'width' => 700, 'bandwidth' => 2000 ),
+ array( 'width' => 800, 'bandwidth' => 7000 ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/extensions/TimedMediaHandler/tests/phpunit/TestVideoThumbnail.php b/extensions/TimedMediaHandler/tests/phpunit/TestVideoThumbnail.php
new file mode 100644
index 00000000..b3c9ef87
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/TestVideoThumbnail.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * @ingroup timedmedia
+ * @author dale
+ * @group medium
+ */
+class TestVideoThumbnail extends ApiTestCaseVideoUpload {
+
+ /**
+ * Once video files are uploaded test thumbnail generating
+ *
+ * @dataProvider mediaFilesProvider
+ * Broken as per bug 61877
+ * @group Broken
+ */
+ function testApiThumbnails( $file ){
+ // Upload the file to the mediaWiki system
+ $result = $this->uploadFile( $file);
+
+ // Do a API request and check for valid thumbnails:
+ $fileName = basename( $file['filePath'] );
+ $params = array(
+ 'action' => 'query',
+ 'titles' => 'File:' . $fileName,
+ 'prop' => 'imageinfo',
+ 'iiprop' => "url|size|thumbmime",
+ );
+
+ // Do a request for a small ( 200px ) thumbnail
+ list($result,,) = $this->doApiRequest(
+ array_merge( $params, array(
+ 'iiurlwidth' => '200'
+ )
+ )
+ );
+
+ // Check The thumbnail output:
+ $this->assertTrue( isset( $result['query'] ) );
+
+ $page = current( $result['query']['pages'] );
+ $this->assertTrue( isset( $page['imageinfo'] ) );
+
+ $imageInfo = current( $page['imageinfo'] );
+
+ // Make sure we got a 200 wide pixel image:
+ $this->assertEquals( 200, ( int )$imageInfo['thumbwidth'] );
+
+ // Thumbnails should be image/jpeg:
+ $this->assertEquals( 'image/jpeg', $imageInfo['thumbmime'] );
+
+ // Make sure the thumbnail url is valid and the correct size ( assuming php has getimagesize function)
+ if( function_exists( 'getimagesize' ) ){
+ list($width ,,,) = getimagesize ( $imageInfo[ 'thumburl'] );
+ $this->assertEquals( 200, $width );
+ }
+
+ /**
+ * We combine tests because fixtures don't play well with dataProvider
+ * see README for more info
+ */
+
+ // Test a larger thumbnail with 1 second time offset
+ list( $result,, ) = $this->doApiRequest(
+ array_merge( $params, array(
+ 'iiurlwidth' => '600',
+ 'iiurlparam' => '1'
+ )
+ )
+ );
+ $page = current( $result['query']['pages'] );
+ $imageInfo = current( $page['imageinfo'] );
+ // Thumb should max out at source size ( no upscale )
+ $targetWidth = ( ( int )$file['width'] < 600 ) ? ( int )$file['width'] : 600;
+ $this->assertEquals( $targetWidth, ( int )$imageInfo['thumbwidth'] );
+ if( function_exists( 'getimagesize' ) ){
+ list( $srcImageWidth ,,,) = getimagesize ( $imageInfo[ 'thumburl'] );
+ $this->assertEquals( $targetWidth, $srcImageWidth );
+ }
+ }
+}
diff --git a/extensions/TimedMediaHandler/tests/phpunit/TestVideoTranscode.php b/extensions/TimedMediaHandler/tests/phpunit/TestVideoTranscode.php
new file mode 100644
index 00000000..af0e6f1f
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/TestVideoTranscode.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * @ingroup timedmedia
+ * @author michael dale
+ * @group medium
+ */
+class TestVideoTranscode extends ApiTestCaseVideoUpload {
+
+ /**
+ * Once video files are uploaded test transcoding
+ *
+ * Test if a transcode job is added for a file once requested
+ *
+ * @dataProvider mediaFilesProvider
+ * Broken as per bug 61878
+ * @group Broken
+ */
+ function testTranscodeJobs( $file ){
+ // Upload the file to the mediaWiki system
+ $result = $this->uploadFile( $file );
+
+ // Check for derivatives ( should trigger adding jobs )
+ $fileName = basename( $file['filePath'] );
+ $params = array(
+ 'action' => 'query',
+ 'titles' => 'File:' . $fileName,
+ 'prop' => 'videoinfo',
+ 'viprop' => "derivatives",
+ );
+ list($result,,) = $this->doApiRequest( $params );
+
+ // Get the $derivatives:
+ $derivatives = $this->getDerivativesFromResult( $result );
+ // Only the "source" asset will be present at first:
+ $source = current( $derivatives );
+
+ // Check that the source matches the api bandwidth property:
+ $this->assertEquals( $file['bandwidth'], $source['bandwidth'] );
+
+ // Check if the transcode jobs were added:
+ // get results: query jobs table
+ $db = wfGetDB( DB_MASTER );
+ $res = $db->select( 'transcode', '*', array(
+ 'transcode_image_name' => ucfirst( $fileName )
+ ) );
+ // Make sure we target at least one ogg and one webm:
+ $hasOgg = $hasWebM = false;
+ $targetEncodes = array();
+ foreach( $res as $row ){
+ $codec = WebVideoTranscode::$derivativeSettings[ $row->transcode_key ]['videoCodec'];
+ if( $codec == 'theora' ){
+ $hasOgg = true;
+ }
+ if( $codec == 'vp8' ){
+ $hasWebM = true;
+ }
+ $targetEncodes[ $row->transcode_key ] = $row;
+ };
+ // Make sure we have ogg and webm:
+ $this->assertTrue( $hasOgg && $hasWebM );
+
+ // Now run the transcode job queue
+ $this->runTranscodeJobs();
+
+ $res = $db->select( 'transcode', '*', array(
+ 'transcode_image_name' => ucfirst( $fileName )
+ ) );
+
+ // Now check if the derivatives were created:
+ list($result,,) = $this->doApiRequest( $params );
+ $derivatives = $this->getDerivativesFromResult( $result );
+
+ // Check that every requested encode was encoded:
+ foreach( $targetEncodes as $transcodeKey => $row ){
+ $targetEncodeFound = false;
+ foreach( $derivatives as $derv ){
+ // The transcode key is always the last part of the file name:
+ if( substr( $derv['src'], -1 * strlen( $transcodeKey ) ) == $transcodeKey ){
+ $targetEncodeFound = true;
+ }
+ }
+ // Test that target encode was found:
+ $this->assertTrue( $targetEncodeFound );
+ }
+
+ }
+
+ // Run Transcode job
+ function runTranscodeJobs(){
+ $dbw = wfGetDB( DB_MASTER );
+ $type = 'webVideoTranscode';
+ // Set the condition to only run the webVideoTranscode
+ $conds = array( "job_cmd" => $type );
+
+ while ( $dbw->selectField( 'job', 'job_id', $conds, 'runJobs.php' ) ) {
+ for ( ; ; ) {
+ $job = Job::pop_type( $type );
+ if ( !$job )
+ break;
+
+ wfWaitForSlaves( 5 );
+ $t = microtime( true );
+ $offset = $job->id;
+ $status = $job->run();
+ $t = microtime( true ) - $t;
+ $timeMs = intval( $t * 1000 );
+ }
+ }
+ }
+
+ function getDerivativesFromResult( $result ){
+ // Only the source should be listed initially:
+ $this->assertTrue( isset( $result['query']['pages'] ) );
+ $page = current( $result['query']['pages'] );
+
+ $videoInfo = current( $page['videoinfo'] );
+ $this->assertTrue( isset( $videoInfo['derivatives'] ) );
+
+ return $videoInfo['derivatives'];
+ }
+}
diff --git a/extensions/TimedMediaHandler/tests/phpunit/TestWebMHandler.php b/extensions/TimedMediaHandler/tests/phpunit/TestWebMHandler.php
new file mode 100644
index 00000000..2d73f46d
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/TestWebMHandler.php
@@ -0,0 +1,52 @@
+<?php
+class TestOggHandler extends MediaWikiMediaTestCase {
+
+ /** @var OggHandlerTMH */
+ private $handler;
+
+ function getFilePath() {
+ return __DIR__ . '/media';
+ }
+
+ function setUp() {
+ parent::setUp();
+ $this->handler = new WebMHandler;
+ }
+
+ /**
+ * @dataProvider providerGetStreamTypes
+ * @param $filename String name of file
+ * @param $expected array List of codecs in file
+ */
+ function testGetStreamTypes( $filename, $expected ) {
+ $testFile = $this->dataFile( $filename, 'video/webm' );
+ $this->assertEquals( $expected, $this->handler->getStreamTypes( $testFile ) );
+ }
+
+ function providerGetStreamTypes() {
+ return array(
+ array( 'shuttle10seconds.1080x608.webm', array( 'VP8' ) ),
+ array( 'VP9-tractor.webm', array( 'VP9' ) ),
+ array( 'bear-vp9-opus.webm', array( 'Opus', 'VP9' ) )
+ );
+ }
+
+
+ /**
+ * @dataProvider providerGetWebType
+ * @param $filename String name of file
+ * @param $expected String Mime type
+ */
+ function testGetWebType( $filename, $expected ) {
+ $testFile = $this->dataFile( $filename, 'video/webm' );
+ $this->assertEquals( $expected, $this->handler->getWebType( $testFile ) );
+ }
+
+ function providerGetWebType() {
+ return array(
+ array( 'shuttle10seconds.1080x608.webm', 'video/webm; codecs="vp8"' ),
+ array( 'VP9-tractor.webm', 'video/webm; codecs="vp9"' ),
+ array( 'bear-vp9-opus.webm', 'video/webm; codecs="opus, vp9"' )
+ );
+ }
+}
diff --git a/extensions/TimedMediaHandler/tests/phpunit/media/README b/extensions/TimedMediaHandler/tests/phpunit/media/README
new file mode 100644
index 00000000..b21871ea
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/media/README
@@ -0,0 +1,38 @@
+doubleTag.oga and broken-file.ogg were created by Brian Wolff and is released into the public domain
+
+VP9-tractor.webm is from http://base-n.de/webm/VP9%20Sample.html and was encoded from a public domain
+file located at http://media.xiph.org/video/derf/y4m/
+
+bear-vp9-opus.webm comes from the chromnium project at the url
+http://code.metager.de/source/raw/chromium/media/test/data/bear-vp9-opus.webm
+which has the following copyright notice:
+
+1 // Copyright 2014 The Chromium Authors. All rights reserved.
+2 //
+3 // Redistribution and use in source and binary forms, with or without
+4 // modification, are permitted provided that the following conditions are
+5 // met:
+6 //
+7 // * Redistributions of source code must retain the above copyright
+8 // notice, this list of conditions and the following disclaimer.
+9 // * Redistributions in binary form must reproduce the above
+10 // copyright notice, this list of conditions and the following disclaimer
+11 // in the documentation and/or other materials provided with the
+12 // distribution.
+13 // * Neither the name of Google Inc. nor the names of its
+14 // contributors may be used to endorse or promote products derived from
+15 // this software without specific prior written permission.
+16 //
+17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
diff --git a/extensions/TimedMediaHandler/tests/phpunit/media/VP9-tractor.webm b/extensions/TimedMediaHandler/tests/phpunit/media/VP9-tractor.webm
new file mode 100644
index 00000000..bbe96f5d
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/media/VP9-tractor.webm
Binary files differ
diff --git a/extensions/TimedMediaHandler/tests/phpunit/media/bear-vp9-opus.webm b/extensions/TimedMediaHandler/tests/phpunit/media/bear-vp9-opus.webm
new file mode 100644
index 00000000..80355cfa
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/media/bear-vp9-opus.webm
Binary files differ
diff --git a/extensions/TimedMediaHandler/tests/phpunit/media/broken-file.ogg b/extensions/TimedMediaHandler/tests/phpunit/media/broken-file.ogg
new file mode 100644
index 00000000..c9fc4fd5
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/media/broken-file.ogg
Binary files differ
diff --git a/extensions/TimedMediaHandler/tests/phpunit/media/doubleTag.oga b/extensions/TimedMediaHandler/tests/phpunit/media/doubleTag.oga
new file mode 100644
index 00000000..f7fac168
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/media/doubleTag.oga
Binary files differ
diff --git a/extensions/TimedMediaHandler/tests/phpunit/media/shuttle10seconds.1080x608.webm b/extensions/TimedMediaHandler/tests/phpunit/media/shuttle10seconds.1080x608.webm
new file mode 100644
index 00000000..a7b865b1
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/media/shuttle10seconds.1080x608.webm
Binary files differ
diff --git a/extensions/TimedMediaHandler/tests/phpunit/media/test5seconds.electricsheep.300x400.ogv b/extensions/TimedMediaHandler/tests/phpunit/media/test5seconds.electricsheep.300x400.ogv
new file mode 100644
index 00000000..a73ec5bf
--- /dev/null
+++ b/extensions/TimedMediaHandler/tests/phpunit/media/test5seconds.electricsheep.300x400.ogv
Binary files differ
diff --git a/extensions/TimedMediaHandler/version b/extensions/TimedMediaHandler/version
new file mode 100644
index 00000000..20e3a345
--- /dev/null
+++ b/extensions/TimedMediaHandler/version
@@ -0,0 +1,5 @@
+TimedMediaHandler: 7cab54e2e482d51df69e4b9c880182b23cabf0bc
+
+2016-01-27T22:15:53
+
+7cab54e
diff --git a/robots.txt b/robots.txt
new file mode 100644
index 00000000..42018bd9
--- /dev/null
+++ b/robots.txt
@@ -0,0 +1,8 @@
+# No me indexes el historial loco
+User-Agent: *
+Disallow: /index.php
+
+# Dejar que Internet Archive indexe las pƔginas en bruto
+User-Agent: ia_archiver
+Allow: /*&action=raw
+
diff --git a/skins/ArchLinux/ArchLinuxTemplate.php b/skins/ArchLinux/ArchLinuxTemplate.php
index 52c23aec..3e10befc 100644
--- a/skins/ArchLinux/ArchLinuxTemplate.php
+++ b/skins/ArchLinux/ArchLinuxTemplate.php
@@ -46,26 +46,17 @@ class ArchLinuxTemplate extends BaseTemplate {
?>
<div id="archnavbar"><!-- Arch Linux global navigation bar -->
- <div id="archnavbarlogo">
- <p><a id="logo" href="<?php if (isset($wgArchHome)) { echo $wgArchHome; } ?>"></a></p>
- </div>
- <div id="archnavbarmenu">
- <ul id="archnavbarlist">
- <?php
- if (isset($wgArchNavBar)) {
- foreach ($wgArchNavBar as $name => $url) {
- if ((isset($wgArchNavBarSelected) && $this->data['title'] == $name && in_array($name, $wgArchNavBarSelected))
- || (!(isset($wgArchNavBarSelected) && in_array($this->data['title'], $wgArchNavBarSelected)) && isset($wgArchNavBarSelectedDefault) && $name == $wgArchNavBarSelectedDefault)) {
- $anbClass = ' class="anb-selected"';
- } else {
- $anbClass = '';
- }
- echo '<li id="anb-'.strtolower($name).'"'.$anbClass.'><a href="'.$url.'">'.$name.'</a></li>';
- }
- }
- ?>
- </ul>
- </div>
+ <div id="archnavbarlogo"><h1><a href="https://www.parabola.nu/">Parabola GNU/Linux-libre</a></h1></div>
+ <div id="archnavbarmenu">
+ <ul id="archnavbarlist">
+ <li id="anb-home"><a href="https://www.parabola.nu/" title="Parabola news, packages, projects and more">Home</a></li>
+ <li id="anb-packages"><a href="https://www.parabola.nu/packages/" title="Package Database">Packages</a></li>
+ <li id="anb-wiki" class="anb-selected"><a href="https://wiki.parabola.nu/" title="Community documentation">Wiki</a></li>
+ <li id="anb-bugs"><a href="https://labs.parabola.nu" title="Issue Tracker">Bugs</a></li>
+ <li id="anb-projects"><a href="https://projects.parabola.nu/" title="Our Code">Projects</a></li>
+ <li id="anb-download"><a href="https://wiki.parabola.nu/Get_Parabola" title="Get Parabola">Download</a></li>
+ </ul>
+ </div>
</div><!-- #archnavbar -->
<div id="globalWrapper">
diff --git a/skins/ArchLinux/archlogo.png b/skins/ArchLinux/archlogo.png
index 42b79e27..8726397a 100644
--- a/skins/ArchLinux/archlogo.png
+++ b/skins/ArchLinux/archlogo.png
Binary files differ
diff --git a/skins/ArchLinux/archnavbar.css b/skins/ArchLinux/archnavbar.css
index 1e769857..574d8b2b 100644
--- a/skins/ArchLinux/archnavbar.css
+++ b/skins/ArchLinux/archnavbar.css
@@ -5,15 +5,15 @@
*/
/* container for the entire bar */
-#archnavbar { height: 40px !important; padding: 10px 15px !important; background: #333 !important; border-bottom: 5px #08c solid !important; }
-#archnavbarlogo { float: left !important; margin: 0 !important; padding: 0 !important; height: 40px !important; width: 190px !important; background: url('archlogo.png') no-repeat !important; }
+#archnavbar { height: 40px !important; padding: 10px 15px !important; background: #000 !important; border-bottom: 5px #787DAB solid !important; }
+#archnavbarlogo { float: left !important; margin: -5px 0 0 0 !important; padding: 0 !important; height: 50px !important; width: 324px !important; background: url('archlogo.png') no-repeat !important; }
/* move the heading/paragraph text offscreen */
#archnavbarlogo p { margin: 0 !important; padding: 0 !important; text-indent: -9999px !important; }
-#archnavbarlogo h1 { margin: 0 !important; padding: 0 !important; text-indent: -9999px !important; }
+#archnavbarlogo h1 { margin: 0 !important; padding: 0 !important; text-indent: -9999px !important; border-bottom: 0px !important; }
/* make the link the same size as the logo */
-#archnavbarlogo a { display: block !important; height: 40px !important; width: 190px !important; }
+#archnavbarlogo a { display: block !important; height: 50px !important; width: 324px !important; }
/* display the list inline, float it to the right and style it */
#archnavbar ul { display: inline !important; float: right !important; list-style: none !important; margin: 0 !important; padding: 0 !important; }
@@ -22,4 +22,3 @@
/* style the links */
#archnavbar ul#archnavbarlist li a { color: #999; font-weight: bold !important; text-decoration: none !important; }
#archnavbar ul li a:hover { color: white !important; text-decoration: underline !important; }
-
diff --git a/skins/ArchLinux/favicon.ico b/skins/ArchLinux/favicon.ico
index 8ef6f130..c67bbd61 100644
--- a/skins/ArchLinux/favicon.ico
+++ b/skins/ArchLinux/favicon.ico
Binary files differ
diff --git a/skins/ArchLinux/skin.json b/skins/ArchLinux/skin.json
index 0729e1cf..e45a8341 100644
--- a/skins/ArchLinux/skin.json
+++ b/skins/ArchLinux/skin.json
@@ -1,8 +1,8 @@
{
"name": "ArchLinux",
"author": [ "Pierre Schmitz" ],
- "url": "https://www.archlinux.org",
- "description": "MediaWiki skin based on MonoBook",
+ "url": "https://www.parabola.nu",
+ "description": "MediaWiki skin based on MonoBook, customized for Parabola",
"license-name": "GPL-2.0+",
"type": "skin",
"ValidSkinNames": {