webpack-test.js 1.1 MB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284232852328623287232882328923290232912329223293232942329523296232972329823299233002330123302233032330423305233062330723308233092331023311233122331323314233152331623317233182331923320233212332223323233242332523326233272332823329233302333123332233332333423335233362333723338233392334023341233422334323344233452334623347233482334923350233512335223353233542335523356233572335823359233602336123362233632336423365233662336723368233692337023371233722337323374233752337623377233782337923380233812338223383233842338523386233872338823389233902339123392233932339423395233962339723398233992340023401234022340323404234052340623407234082340923410234112341223413234142341523416234172341823419234202342123422234232342423425234262342723428234292343023431234322343323434234352343623437234382343923440234412344223443234442344523446234472344823449234502345123452234532345423455234562345723458234592346023461234622346323464234652346623467234682346923470234712347223473234742347523476234772347823479234802348123482234832348423485234862348723488234892349023491234922349323494234952349623497234982349923500235012350223503235042350523506235072350823509235102351123512235132351423515235162351723518235192352023521235222352323524235252352623527235282352923530235312353223533235342353523536235372353823539235402354123542235432354423545235462354723548235492355023551235522355323554235552355623557235582355923560235612356223563235642356523566235672356823569235702357123572235732357423575235762357723578235792358023581235822358323584235852358623587235882358923590235912359223593235942359523596235972359823599236002360123602236032360423605236062360723608236092361023611236122361323614236152361623617236182361923620236212362223623236242362523626236272362823629236302363123632236332363423635236362363723638236392364023641236422364323644236452364623647236482364923650236512365223653236542365523656236572365823659236602366123662236632366423665236662366723668236692367023671236722367323674236752367623677236782367923680236812368223683236842368523686236872368823689236902369123692236932369423695236962369723698236992370023701237022370323704237052370623707237082370923710237112371223713237142371523716237172371823719237202372123722237232372423725237262372723728237292373023731237322373323734237352373623737237382373923740237412374223743237442374523746237472374823749237502375123752237532375423755237562375723758237592376023761237622376323764237652376623767237682376923770237712377223773237742377523776237772377823779237802378123782237832378423785237862378723788237892379023791237922379323794237952379623797237982379923800238012380223803238042380523806238072380823809238102381123812238132381423815238162381723818238192382023821238222382323824238252382623827238282382923830238312383223833238342383523836238372383823839238402384123842238432384423845238462384723848238492385023851238522385323854238552385623857238582385923860238612386223863238642386523866238672386823869238702387123872238732387423875238762387723878238792388023881238822388323884238852388623887238882388923890238912389223893238942389523896238972389823899239002390123902239032390423905239062390723908239092391023911239122391323914239152391623917239182391923920239212392223923239242392523926239272392823929239302393123932239332393423935239362393723938239392394023941239422394323944239452394623947239482394923950239512395223953239542395523956239572395823959239602396123962239632396423965239662396723968239692397023971239722397323974239752397623977239782397923980239812398223983239842398523986239872398823989239902399123992239932399423995239962399723998239992400024001240022400324004240052400624007240082400924010240112401224013240142401524016240172401824019240202402124022240232402424025240262402724028240292403024031240322403324034240352403624037240382403924040240412404224043240442404524046240472404824049240502405124052240532405424055240562405724058240592406024061240622406324064240652406624067240682406924070240712407224073240742407524076240772407824079240802408124082240832408424085240862408724088240892409024091240922409324094240952409624097240982409924100241012410224103241042410524106241072410824109241102411124112241132411424115241162411724118241192412024121241222412324124241252412624127241282412924130241312413224133241342413524136241372413824139241402414124142241432414424145241462414724148241492415024151241522415324154241552415624157241582415924160241612416224163241642416524166241672416824169241702417124172241732417424175241762417724178241792418024181241822418324184241852418624187241882418924190241912419224193241942419524196241972419824199242002420124202242032420424205242062420724208242092421024211242122421324214242152421624217242182421924220242212422224223242242422524226242272422824229242302423124232242332423424235242362423724238242392424024241242422424324244242452424624247242482424924250242512425224253242542425524256242572425824259242602426124262242632426424265242662426724268242692427024271242722427324274242752427624277242782427924280242812428224283242842428524286242872428824289242902429124292242932429424295242962429724298242992430024301243022430324304243052430624307243082430924310243112431224313243142431524316243172431824319243202432124322243232432424325243262432724328243292433024331243322433324334243352433624337243382433924340243412434224343243442434524346243472434824349243502435124352243532435424355243562435724358243592436024361243622436324364243652436624367243682436924370243712437224373243742437524376243772437824379243802438124382243832438424385243862438724388243892439024391243922439324394243952439624397243982439924400244012440224403244042440524406244072440824409244102441124412244132441424415244162441724418244192442024421244222442324424244252442624427244282442924430244312443224433244342443524436244372443824439244402444124442244432444424445244462444724448244492445024451244522445324454244552445624457244582445924460244612446224463244642446524466244672446824469244702447124472244732447424475244762447724478244792448024481244822448324484244852448624487244882448924490244912449224493244942449524496244972449824499245002450124502245032450424505245062450724508245092451024511245122451324514245152451624517245182451924520245212452224523245242452524526245272452824529245302453124532245332453424535245362453724538245392454024541245422454324544245452454624547245482454924550245512455224553245542455524556245572455824559245602456124562245632456424565245662456724568245692457024571245722457324574245752457624577245782457924580245812458224583245842458524586245872458824589245902459124592245932459424595245962459724598245992460024601246022460324604246052460624607246082460924610246112461224613246142461524616246172461824619246202462124622246232462424625246262462724628246292463024631246322463324634246352463624637246382463924640246412464224643246442464524646246472464824649246502465124652246532465424655246562465724658246592466024661246622466324664246652466624667246682466924670246712467224673246742467524676246772467824679246802468124682246832468424685246862468724688246892469024691246922469324694246952469624697246982469924700247012470224703247042470524706247072470824709247102471124712247132471424715247162471724718247192472024721247222472324724247252472624727247282472924730247312473224733247342473524736247372473824739247402474124742247432474424745247462474724748247492475024751247522475324754247552475624757247582475924760247612476224763247642476524766247672476824769247702477124772247732477424775247762477724778247792478024781247822478324784247852478624787247882478924790247912479224793247942479524796247972479824799248002480124802248032480424805248062480724808248092481024811248122481324814248152481624817248182481924820248212482224823248242482524826248272482824829248302483124832248332483424835248362483724838248392484024841248422484324844248452484624847248482484924850248512485224853248542485524856248572485824859248602486124862248632486424865248662486724868248692487024871248722487324874248752487624877248782487924880248812488224883248842488524886248872488824889248902489124892248932489424895248962489724898248992490024901249022490324904249052490624907249082490924910249112491224913249142491524916249172491824919249202492124922249232492424925249262492724928249292493024931249322493324934249352493624937249382493924940249412494224943249442494524946249472494824949249502495124952249532495424955249562495724958249592496024961249622496324964249652496624967249682496924970249712497224973249742497524976249772497824979249802498124982249832498424985249862498724988249892499024991249922499324994249952499624997249982499925000250012500225003250042500525006250072500825009250102501125012250132501425015250162501725018250192502025021250222502325024250252502625027250282502925030250312503225033250342503525036250372503825039250402504125042250432504425045250462504725048250492505025051250522505325054250552505625057250582505925060250612506225063250642506525066250672506825069250702507125072250732507425075250762507725078250792508025081250822508325084250852508625087250882508925090250912509225093250942509525096250972509825099251002510125102251032510425105251062510725108251092511025111251122511325114251152511625117251182511925120251212512225123251242512525126251272512825129251302513125132251332513425135251362513725138251392514025141251422514325144251452514625147251482514925150251512515225153251542515525156251572515825159251602516125162251632516425165251662516725168251692517025171251722517325174251752517625177251782517925180251812518225183251842518525186251872518825189251902519125192251932519425195251962519725198251992520025201252022520325204252052520625207252082520925210252112521225213252142521525216252172521825219252202522125222252232522425225252262522725228252292523025231252322523325234252352523625237252382523925240252412524225243252442524525246252472524825249252502525125252252532525425255252562525725258252592526025261252622526325264252652526625267252682526925270252712527225273252742527525276252772527825279252802528125282252832528425285252862528725288252892529025291252922529325294252952529625297252982529925300253012530225303253042530525306253072530825309253102531125312253132531425315253162531725318253192532025321253222532325324253252532625327253282532925330253312533225333253342533525336253372533825339253402534125342253432534425345253462534725348253492535025351253522535325354253552535625357253582535925360253612536225363253642536525366253672536825369253702537125372253732537425375253762537725378253792538025381253822538325384253852538625387253882538925390253912539225393253942539525396253972539825399254002540125402254032540425405254062540725408254092541025411254122541325414254152541625417254182541925420254212542225423254242542525426254272542825429254302543125432254332543425435254362543725438254392544025441254422544325444254452544625447254482544925450254512545225453254542545525456254572545825459254602546125462254632546425465254662546725468254692547025471254722547325474254752547625477254782547925480254812548225483254842548525486254872548825489254902549125492254932549425495254962549725498254992550025501255022550325504255052550625507255082550925510255112551225513255142551525516255172551825519255202552125522255232552425525255262552725528255292553025531255322553325534255352553625537255382553925540255412554225543255442554525546255472554825549255502555125552255532555425555255562555725558255592556025561255622556325564255652556625567255682556925570255712557225573255742557525576255772557825579255802558125582255832558425585255862558725588255892559025591255922559325594255952559625597255982559925600256012560225603256042560525606256072560825609256102561125612256132561425615256162561725618256192562025621256222562325624256252562625627256282562925630256312563225633256342563525636256372563825639256402564125642256432564425645256462564725648256492565025651256522565325654256552565625657256582565925660256612566225663256642566525666256672566825669256702567125672256732567425675256762567725678256792568025681256822568325684256852568625687256882568925690256912569225693256942569525696256972569825699257002570125702257032570425705257062570725708257092571025711257122571325714257152571625717257182571925720257212572225723257242572525726257272572825729257302573125732257332573425735257362573725738257392574025741257422574325744257452574625747257482574925750257512575225753257542575525756257572575825759257602576125762257632576425765257662576725768257692577025771257722577325774257752577625777257782577925780257812578225783257842578525786257872578825789257902579125792257932579425795257962579725798257992580025801258022580325804258052580625807258082580925810258112581225813258142581525816258172581825819258202582125822258232582425825258262582725828258292583025831258322583325834258352583625837258382583925840258412584225843258442584525846258472584825849258502585125852258532585425855258562585725858258592586025861258622586325864258652586625867258682586925870258712587225873258742587525876258772587825879258802588125882258832588425885258862588725888258892589025891258922589325894258952589625897258982589925900259012590225903259042590525906259072590825909259102591125912259132591425915259162591725918259192592025921259222592325924259252592625927259282592925930259312593225933259342593525936259372593825939259402594125942259432594425945259462594725948259492595025951259522595325954259552595625957259582595925960259612596225963259642596525966259672596825969259702597125972259732597425975259762597725978259792598025981259822598325984259852598625987259882598925990259912599225993259942599525996259972599825999260002600126002260032600426005260062600726008260092601026011260122601326014260152601626017260182601926020260212602226023260242602526026260272602826029260302603126032260332603426035260362603726038260392604026041260422604326044260452604626047260482604926050260512605226053260542605526056260572605826059260602606126062260632606426065260662606726068260692607026071260722607326074260752607626077260782607926080260812608226083260842608526086260872608826089260902609126092260932609426095260962609726098260992610026101261022610326104261052610626107261082610926110261112611226113261142611526116261172611826119261202612126122261232612426125261262612726128261292613026131261322613326134261352613626137261382613926140261412614226143261442614526146261472614826149261502615126152261532615426155261562615726158261592616026161261622616326164261652616626167261682616926170261712617226173261742617526176261772617826179261802618126182261832618426185261862618726188261892619026191261922619326194261952619626197261982619926200262012620226203262042620526206262072620826209262102621126212262132621426215262162621726218262192622026221262222622326224262252622626227262282622926230262312623226233262342623526236262372623826239262402624126242262432624426245262462624726248262492625026251262522625326254262552625626257262582625926260262612626226263262642626526266262672626826269262702627126272262732627426275262762627726278262792628026281262822628326284262852628626287262882628926290262912629226293262942629526296262972629826299263002630126302263032630426305263062630726308263092631026311263122631326314263152631626317263182631926320263212632226323263242632526326263272632826329263302633126332263332633426335263362633726338263392634026341263422634326344263452634626347263482634926350263512635226353263542635526356263572635826359263602636126362263632636426365263662636726368263692637026371263722637326374263752637626377263782637926380263812638226383263842638526386263872638826389263902639126392263932639426395263962639726398263992640026401264022640326404264052640626407264082640926410264112641226413264142641526416264172641826419264202642126422264232642426425264262642726428264292643026431264322643326434264352643626437264382643926440264412644226443264442644526446264472644826449264502645126452264532645426455264562645726458264592646026461264622646326464264652646626467264682646926470264712647226473264742647526476264772647826479264802648126482264832648426485264862648726488264892649026491264922649326494264952649626497264982649926500265012650226503265042650526506265072650826509265102651126512265132651426515265162651726518265192652026521265222652326524265252652626527265282652926530265312653226533265342653526536265372653826539265402654126542265432654426545265462654726548265492655026551265522655326554265552655626557265582655926560265612656226563265642656526566265672656826569265702657126572265732657426575265762657726578265792658026581265822658326584265852658626587265882658926590265912659226593265942659526596265972659826599266002660126602266032660426605266062660726608266092661026611266122661326614266152661626617266182661926620266212662226623266242662526626266272662826629266302663126632266332663426635266362663726638266392664026641266422664326644266452664626647266482664926650266512665226653266542665526656266572665826659266602666126662266632666426665266662666726668266692667026671266722667326674266752667626677266782667926680266812668226683266842668526686266872668826689266902669126692266932669426695266962669726698266992670026701267022670326704267052670626707267082670926710267112671226713267142671526716267172671826719267202672126722267232672426725267262672726728267292673026731267322673326734267352673626737267382673926740267412674226743267442674526746267472674826749267502675126752267532675426755267562675726758267592676026761267622676326764267652676626767267682676926770267712677226773267742677526776267772677826779267802678126782267832678426785267862678726788267892679026791267922679326794267952679626797267982679926800268012680226803268042680526806268072680826809268102681126812268132681426815268162681726818268192682026821268222682326824268252682626827268282682926830268312683226833268342683526836268372683826839268402684126842268432684426845268462684726848268492685026851268522685326854268552685626857268582685926860268612686226863268642686526866268672686826869268702687126872268732687426875268762687726878268792688026881268822688326884268852688626887268882688926890268912689226893268942689526896268972689826899269002690126902269032690426905269062690726908269092691026911269122691326914269152691626917269182691926920269212692226923269242692526926269272692826929269302693126932269332693426935269362693726938269392694026941269422694326944269452694626947269482694926950269512695226953269542695526956269572695826959269602696126962269632696426965269662696726968269692697026971269722697326974269752697626977269782697926980269812698226983269842698526986269872698826989269902699126992269932699426995269962699726998269992700027001270022700327004270052700627007270082700927010270112701227013270142701527016270172701827019270202702127022270232702427025270262702727028270292703027031270322703327034270352703627037270382703927040270412704227043270442704527046270472704827049270502705127052270532705427055270562705727058270592706027061270622706327064270652706627067270682706927070270712707227073270742707527076270772707827079270802708127082270832708427085270862708727088270892709027091270922709327094270952709627097270982709927100271012710227103271042710527106271072710827109271102711127112271132711427115271162711727118271192712027121271222712327124271252712627127271282712927130271312713227133271342713527136271372713827139271402714127142271432714427145271462714727148271492715027151271522715327154271552715627157271582715927160271612716227163271642716527166271672716827169271702717127172271732717427175271762717727178271792718027181271822718327184271852718627187271882718927190271912719227193271942719527196271972719827199272002720127202272032720427205272062720727208272092721027211272122721327214272152721627217272182721927220272212722227223272242722527226272272722827229272302723127232272332723427235272362723727238272392724027241272422724327244272452724627247272482724927250272512725227253272542725527256272572725827259272602726127262272632726427265272662726727268272692727027271272722727327274272752727627277272782727927280272812728227283272842728527286272872728827289272902729127292272932729427295272962729727298272992730027301273022730327304273052730627307273082730927310273112731227313273142731527316273172731827319273202732127322273232732427325273262732727328273292733027331273322733327334273352733627337273382733927340273412734227343273442734527346273472734827349273502735127352273532735427355273562735727358273592736027361273622736327364273652736627367273682736927370273712737227373273742737527376273772737827379273802738127382273832738427385273862738727388273892739027391273922739327394273952739627397273982739927400274012740227403274042740527406274072740827409274102741127412274132741427415274162741727418274192742027421274222742327424274252742627427274282742927430274312743227433274342743527436274372743827439274402744127442274432744427445274462744727448274492745027451274522745327454274552745627457274582745927460274612746227463274642746527466274672746827469274702747127472274732747427475274762747727478274792748027481274822748327484274852748627487274882748927490274912749227493274942749527496274972749827499275002750127502275032750427505275062750727508275092751027511275122751327514275152751627517275182751927520275212752227523275242752527526275272752827529275302753127532275332753427535275362753727538275392754027541275422754327544275452754627547275482754927550275512755227553275542755527556275572755827559275602756127562275632756427565275662756727568275692757027571275722757327574275752757627577275782757927580275812758227583275842758527586275872758827589275902759127592275932759427595275962759727598275992760027601276022760327604276052760627607276082760927610276112761227613276142761527616276172761827619276202762127622276232762427625276262762727628276292763027631276322763327634276352763627637276382763927640276412764227643276442764527646276472764827649276502765127652276532765427655276562765727658276592766027661276622766327664276652766627667276682766927670276712767227673276742767527676276772767827679276802768127682276832768427685276862768727688276892769027691276922769327694276952769627697276982769927700277012770227703277042770527706277072770827709277102771127712277132771427715277162771727718277192772027721277222772327724277252772627727277282772927730277312773227733277342773527736277372773827739277402774127742277432774427745277462774727748277492775027751277522775327754277552775627757277582775927760277612776227763277642776527766277672776827769277702777127772277732777427775277762777727778277792778027781277822778327784277852778627787277882778927790277912779227793277942779527796277972779827799278002780127802278032780427805278062780727808278092781027811278122781327814278152781627817278182781927820278212782227823278242782527826278272782827829278302783127832278332783427835278362783727838278392784027841278422784327844278452784627847278482784927850278512785227853278542785527856278572785827859278602786127862278632786427865278662786727868278692787027871278722787327874278752787627877278782787927880278812788227883278842788527886278872788827889278902789127892278932789427895278962789727898278992790027901279022790327904279052790627907279082790927910279112791227913279142791527916279172791827919279202792127922279232792427925279262792727928279292793027931279322793327934279352793627937279382793927940279412794227943279442794527946279472794827949279502795127952279532795427955279562795727958279592796027961279622796327964279652796627967279682796927970279712797227973279742797527976279772797827979279802798127982279832798427985279862798727988279892799027991279922799327994279952799627997279982799928000280012800228003280042800528006280072800828009280102801128012280132801428015280162801728018280192802028021280222802328024280252802628027280282802928030280312803228033280342803528036280372803828039280402804128042280432804428045280462804728048280492805028051280522805328054280552805628057280582805928060280612806228063280642806528066280672806828069280702807128072280732807428075280762807728078280792808028081280822808328084280852808628087280882808928090280912809228093280942809528096280972809828099281002810128102281032810428105281062810728108281092811028111281122811328114281152811628117281182811928120281212812228123281242812528126281272812828129281302813128132281332813428135281362813728138281392814028141281422814328144281452814628147281482814928150281512815228153281542815528156281572815828159281602816128162281632816428165281662816728168281692817028171281722817328174281752817628177281782817928180281812818228183281842818528186281872818828189281902819128192281932819428195281962819728198281992820028201282022820328204282052820628207282082820928210282112821228213282142821528216282172821828219282202822128222282232822428225282262822728228282292823028231282322823328234282352823628237282382823928240282412824228243282442824528246282472824828249282502825128252282532825428255282562825728258282592826028261282622826328264282652826628267282682826928270282712827228273282742827528276282772827828279282802828128282282832828428285282862828728288282892829028291282922829328294282952829628297282982829928300283012830228303283042830528306283072830828309283102831128312283132831428315283162831728318283192832028321283222832328324283252832628327283282832928330283312833228333283342833528336283372833828339283402834128342283432834428345283462834728348283492835028351283522835328354283552835628357283582835928360283612836228363283642836528366283672836828369283702837128372283732837428375283762837728378283792838028381283822838328384283852838628387283882838928390283912839228393283942839528396283972839828399284002840128402284032840428405284062840728408284092841028411284122841328414284152841628417284182841928420284212842228423284242842528426284272842828429284302843128432284332843428435284362843728438284392844028441284422844328444284452844628447284482844928450284512845228453284542845528456284572845828459284602846128462284632846428465284662846728468284692847028471284722847328474284752847628477284782847928480284812848228483284842848528486284872848828489284902849128492284932849428495284962849728498284992850028501285022850328504285052850628507285082850928510285112851228513285142851528516285172851828519285202852128522285232852428525285262852728528285292853028531285322853328534285352853628537285382853928540285412854228543285442854528546285472854828549285502855128552285532855428555285562855728558285592856028561285622856328564285652856628567285682856928570285712857228573285742857528576285772857828579285802858128582285832858428585285862858728588285892859028591285922859328594285952859628597285982859928600286012860228603286042860528606286072860828609286102861128612286132861428615286162861728618286192862028621286222862328624286252862628627286282862928630286312863228633286342863528636286372863828639286402864128642286432864428645286462864728648286492865028651286522865328654286552865628657286582865928660286612866228663286642866528666286672866828669286702867128672286732867428675286762867728678286792868028681286822868328684286852868628687286882868928690286912869228693286942869528696286972869828699287002870128702287032870428705287062870728708287092871028711287122871328714287152871628717287182871928720287212872228723287242872528726287272872828729287302873128732287332873428735287362873728738287392874028741287422874328744287452874628747287482874928750287512875228753287542875528756287572875828759287602876128762287632876428765287662876728768287692877028771287722877328774287752877628777287782877928780287812878228783287842878528786287872878828789287902879128792287932879428795287962879728798287992880028801288022880328804288052880628807288082880928810288112881228813288142881528816288172881828819288202882128822288232882428825288262882728828288292883028831288322883328834288352883628837288382883928840288412884228843288442884528846288472884828849288502885128852288532885428855288562885728858288592886028861288622886328864288652886628867288682886928870288712887228873288742887528876288772887828879288802888128882288832888428885288862888728888288892889028891288922889328894288952889628897288982889928900289012890228903289042890528906289072890828909289102891128912289132891428915289162891728918289192892028921289222892328924289252892628927289282892928930289312893228933289342893528936289372893828939289402894128942289432894428945289462894728948289492895028951289522895328954289552895628957289582895928960289612896228963289642896528966289672896828969289702897128972289732897428975289762897728978289792898028981289822898328984289852898628987289882898928990289912899228993289942899528996289972899828999290002900129002290032900429005290062900729008290092901029011290122901329014290152901629017290182901929020290212902229023290242902529026290272902829029290302903129032290332903429035290362903729038290392904029041290422904329044290452904629047290482904929050290512905229053290542905529056290572905829059290602906129062290632906429065290662906729068290692907029071290722907329074290752907629077290782907929080290812908229083290842908529086290872908829089290902909129092290932909429095290962909729098290992910029101291022910329104291052910629107291082910929110291112911229113291142911529116291172911829119291202912129122291232912429125291262912729128291292913029131291322913329134291352913629137291382913929140291412914229143291442914529146291472914829149291502915129152291532915429155291562915729158291592916029161291622916329164291652916629167291682916929170291712917229173291742917529176291772917829179291802918129182291832918429185291862918729188291892919029191291922919329194291952919629197291982919929200292012920229203292042920529206292072920829209292102921129212292132921429215292162921729218292192922029221292222922329224292252922629227292282922929230292312923229233292342923529236292372923829239292402924129242292432924429245292462924729248292492925029251292522925329254292552925629257292582925929260292612926229263292642926529266292672926829269292702927129272292732927429275292762927729278292792928029281292822928329284292852928629287292882928929290292912929229293292942929529296292972929829299293002930129302293032930429305293062930729308293092931029311293122931329314293152931629317293182931929320293212932229323293242932529326293272932829329293302933129332293332933429335293362933729338293392934029341293422934329344293452934629347293482934929350293512935229353293542935529356293572935829359293602936129362293632936429365293662936729368293692937029371293722937329374293752937629377293782937929380293812938229383293842938529386293872938829389293902939129392293932939429395293962939729398293992940029401294022940329404294052940629407294082940929410294112941229413294142941529416294172941829419294202942129422294232942429425294262942729428294292943029431294322943329434294352943629437294382943929440294412944229443294442944529446294472944829449294502945129452294532945429455294562945729458294592946029461294622946329464294652946629467294682946929470294712947229473294742947529476294772947829479294802948129482294832948429485294862948729488294892949029491294922949329494294952949629497294982949929500295012950229503295042950529506295072950829509295102951129512295132951429515295162951729518295192952029521295222952329524295252952629527295282952929530295312953229533295342953529536295372953829539295402954129542295432954429545295462954729548295492955029551295522955329554295552955629557295582955929560295612956229563295642956529566295672956829569295702957129572295732957429575295762957729578295792958029581295822958329584295852958629587295882958929590295912959229593295942959529596295972959829599296002960129602296032960429605296062960729608296092961029611296122961329614296152961629617296182961929620296212962229623296242962529626296272962829629296302963129632296332963429635296362963729638296392964029641296422964329644296452964629647296482964929650296512965229653296542965529656296572965829659296602966129662296632966429665296662966729668296692967029671296722967329674296752967629677296782967929680296812968229683296842968529686296872968829689296902969129692296932969429695296962969729698296992970029701297022970329704297052970629707297082970929710297112971229713297142971529716297172971829719297202972129722297232972429725297262972729728297292973029731297322973329734297352973629737297382973929740297412974229743297442974529746297472974829749297502975129752297532975429755297562975729758297592976029761297622976329764297652976629767297682976929770297712977229773297742977529776297772977829779297802978129782297832978429785297862978729788297892979029791297922979329794297952979629797297982979929800298012980229803298042980529806298072980829809298102981129812298132981429815298162981729818298192982029821298222982329824298252982629827298282982929830298312983229833298342983529836298372983829839298402984129842298432984429845298462984729848298492985029851298522985329854298552985629857298582985929860298612986229863298642986529866298672986829869298702987129872298732987429875298762987729878298792988029881298822988329884298852988629887298882988929890298912989229893298942989529896298972989829899299002990129902299032990429905299062990729908299092991029911299122991329914299152991629917299182991929920299212992229923299242992529926299272992829929299302993129932299332993429935299362993729938299392994029941299422994329944299452994629947299482994929950299512995229953299542995529956299572995829959299602996129962299632996429965299662996729968299692997029971299722997329974299752997629977299782997929980299812998229983299842998529986299872998829989299902999129992299932999429995299962999729998299993000030001300023000330004300053000630007300083000930010300113001230013300143001530016300173001830019300203002130022300233002430025300263002730028300293003030031300323003330034300353003630037300383003930040300413004230043300443004530046300473004830049300503005130052300533005430055300563005730058300593006030061300623006330064300653006630067300683006930070300713007230073300743007530076300773007830079300803008130082300833008430085300863008730088300893009030091300923009330094300953009630097300983009930100301013010230103301043010530106301073010830109301103011130112301133011430115301163011730118301193012030121301223012330124301253012630127301283012930130301313013230133301343013530136301373013830139301403014130142301433014430145301463014730148301493015030151301523015330154301553015630157301583015930160301613016230163301643016530166301673016830169301703017130172301733017430175301763017730178301793018030181301823018330184301853018630187301883018930190301913019230193301943019530196301973019830199302003020130202302033020430205302063020730208302093021030211302123021330214302153021630217302183021930220302213022230223302243022530226302273022830229302303023130232302333023430235302363023730238302393024030241302423024330244302453024630247302483024930250302513025230253302543025530256302573025830259302603026130262302633026430265302663026730268302693027030271302723027330274302753027630277302783027930280302813028230283302843028530286302873028830289302903029130292302933029430295302963029730298302993030030301303023030330304303053030630307303083030930310303113031230313303143031530316303173031830319303203032130322303233032430325303263032730328303293033030331303323033330334303353033630337303383033930340303413034230343303443034530346303473034830349303503035130352303533035430355303563035730358303593036030361303623036330364303653036630367303683036930370303713037230373303743037530376303773037830379303803038130382303833038430385303863038730388303893039030391303923039330394303953039630397303983039930400304013040230403304043040530406304073040830409304103041130412304133041430415304163041730418304193042030421304223042330424304253042630427304283042930430304313043230433304343043530436304373043830439304403044130442304433044430445304463044730448304493045030451304523045330454304553045630457304583045930460304613046230463304643046530466304673046830469304703047130472304733047430475304763047730478304793048030481304823048330484304853048630487304883048930490304913049230493304943049530496304973049830499305003050130502305033050430505305063050730508305093051030511305123051330514305153051630517305183051930520305213052230523305243052530526305273052830529305303053130532305333053430535305363053730538305393054030541305423054330544305453054630547305483054930550305513055230553305543055530556305573055830559305603056130562305633056430565305663056730568305693057030571305723057330574305753057630577305783057930580305813058230583305843058530586305873058830589305903059130592305933059430595305963059730598305993060030601306023060330604306053060630607306083060930610306113061230613306143061530616306173061830619306203062130622306233062430625306263062730628306293063030631306323063330634306353063630637306383063930640306413064230643306443064530646306473064830649306503065130652306533065430655306563065730658306593066030661306623066330664306653066630667306683066930670306713067230673306743067530676306773067830679306803068130682306833068430685306863068730688306893069030691306923069330694306953069630697306983069930700307013070230703307043070530706307073070830709307103071130712307133071430715307163071730718307193072030721307223072330724307253072630727307283072930730307313073230733307343073530736307373073830739307403074130742307433074430745307463074730748307493075030751307523075330754307553075630757307583075930760307613076230763307643076530766307673076830769307703077130772307733077430775307763077730778307793078030781307823078330784307853078630787307883078930790307913079230793307943079530796307973079830799308003080130802308033080430805308063080730808308093081030811308123081330814308153081630817308183081930820308213082230823308243082530826308273082830829308303083130832308333083430835308363083730838308393084030841308423084330844308453084630847308483084930850308513085230853308543085530856308573085830859308603086130862308633086430865308663086730868308693087030871308723087330874308753087630877308783087930880308813088230883308843088530886308873088830889308903089130892308933089430895308963089730898308993090030901309023090330904309053090630907309083090930910309113091230913309143091530916309173091830919309203092130922309233092430925309263092730928309293093030931309323093330934309353093630937309383093930940309413094230943309443094530946309473094830949309503095130952309533095430955309563095730958309593096030961309623096330964309653096630967309683096930970309713097230973309743097530976309773097830979309803098130982309833098430985309863098730988309893099030991309923099330994309953099630997309983099931000310013100231003310043100531006310073100831009310103101131012310133101431015310163101731018310193102031021310223102331024310253102631027310283102931030310313103231033310343103531036310373103831039310403104131042310433104431045310463104731048310493105031051310523105331054310553105631057310583105931060310613106231063310643106531066310673106831069310703107131072310733107431075310763107731078310793108031081310823108331084310853108631087310883108931090310913109231093310943109531096310973109831099311003110131102311033110431105311063110731108311093111031111311123111331114311153111631117311183111931120311213112231123311243112531126311273112831129311303113131132311333113431135311363113731138311393114031141311423114331144311453114631147311483114931150311513115231153311543115531156311573115831159311603116131162311633116431165311663116731168311693117031171311723117331174311753117631177311783117931180311813118231183311843118531186311873118831189311903119131192311933119431195311963119731198311993120031201312023120331204312053120631207312083120931210312113121231213312143121531216312173121831219312203122131222312233122431225312263122731228312293123031231312323123331234312353123631237312383123931240312413124231243312443124531246312473124831249312503125131252312533125431255312563125731258312593126031261312623126331264312653126631267312683126931270312713127231273312743127531276312773127831279312803128131282312833128431285312863128731288312893129031291312923129331294312953129631297312983129931300313013130231303313043130531306313073130831309313103131131312313133131431315313163131731318313193132031321313223132331324313253132631327313283132931330313313133231333313343133531336313373133831339313403134131342313433134431345313463134731348313493135031351313523135331354313553135631357313583135931360313613136231363313643136531366313673136831369313703137131372313733137431375313763137731378313793138031381313823138331384313853138631387313883138931390313913139231393313943139531396313973139831399314003140131402314033140431405314063140731408314093141031411314123141331414314153141631417314183141931420314213142231423314243142531426314273142831429314303143131432314333143431435314363143731438314393144031441314423144331444314453144631447314483144931450314513145231453314543145531456314573145831459314603146131462314633146431465314663146731468314693147031471314723147331474314753147631477314783147931480314813148231483314843148531486314873148831489314903149131492314933149431495314963149731498314993150031501315023150331504315053150631507315083150931510315113151231513315143151531516315173151831519315203152131522315233152431525315263152731528315293153031531315323153331534315353153631537315383153931540315413154231543315443154531546315473154831549315503155131552315533155431555315563155731558315593156031561315623156331564315653156631567315683156931570315713157231573315743157531576315773157831579315803158131582315833158431585315863158731588315893159031591315923159331594315953159631597315983159931600316013160231603316043160531606316073160831609316103161131612316133161431615316163161731618316193162031621316223162331624316253162631627316283162931630316313163231633316343163531636316373163831639316403164131642316433164431645316463164731648316493165031651316523165331654316553165631657316583165931660316613166231663316643166531666316673166831669316703167131672316733167431675316763167731678316793168031681316823168331684316853168631687316883168931690316913169231693316943169531696316973169831699317003170131702317033170431705317063170731708317093171031711317123171331714317153171631717317183171931720317213172231723317243172531726317273172831729317303173131732317333173431735317363173731738317393174031741317423174331744317453174631747317483174931750317513175231753317543175531756317573175831759317603176131762317633176431765317663176731768317693177031771317723177331774317753177631777317783177931780317813178231783317843178531786317873178831789317903179131792317933179431795317963179731798317993180031801318023180331804318053180631807318083180931810318113181231813318143181531816318173181831819318203182131822318233182431825318263182731828318293183031831318323183331834318353183631837318383183931840318413184231843318443184531846318473184831849318503185131852318533185431855318563185731858318593186031861318623186331864318653186631867318683186931870318713187231873318743187531876318773187831879318803188131882318833188431885318863188731888318893189031891318923189331894318953189631897318983189931900319013190231903319043190531906319073190831909319103191131912319133191431915319163191731918319193192031921319223192331924319253192631927319283192931930319313193231933319343193531936319373193831939319403194131942319433194431945319463194731948319493195031951319523195331954319553195631957319583195931960319613196231963319643196531966319673196831969319703197131972319733197431975319763197731978319793198031981319823198331984319853198631987319883198931990319913199231993319943199531996319973199831999320003200132002320033200432005320063200732008320093201032011320123201332014320153201632017320183201932020320213202232023320243202532026320273202832029320303203132032320333203432035320363203732038320393204032041320423204332044320453204632047320483204932050320513205232053320543205532056320573205832059320603206132062320633206432065320663206732068320693207032071320723207332074320753207632077320783207932080320813208232083320843208532086320873208832089320903209132092320933209432095320963209732098320993210032101321023210332104321053210632107321083210932110321113211232113321143211532116321173211832119321203212132122321233212432125321263212732128321293213032131321323213332134321353213632137321383213932140321413214232143321443214532146321473214832149321503215132152321533215432155321563215732158321593216032161321623216332164321653216632167321683216932170321713217232173321743217532176321773217832179321803218132182321833218432185321863218732188321893219032191321923219332194321953219632197321983219932200322013220232203322043220532206322073220832209322103221132212322133221432215322163221732218322193222032221322223222332224322253222632227322283222932230322313223232233322343223532236322373223832239322403224132242322433224432245322463224732248322493225032251322523225332254322553225632257322583225932260322613226232263322643226532266322673226832269322703227132272322733227432275322763227732278322793228032281322823228332284322853228632287322883228932290322913229232293322943229532296322973229832299323003230132302323033230432305323063230732308323093231032311323123231332314323153231632317323183231932320323213232232323323243232532326323273232832329323303233132332323333233432335323363233732338323393234032341323423234332344323453234632347323483234932350323513235232353323543235532356323573235832359323603236132362323633236432365323663236732368323693237032371323723237332374323753237632377323783237932380323813238232383323843238532386323873238832389323903239132392323933239432395323963239732398323993240032401324023240332404324053240632407324083240932410324113241232413324143241532416324173241832419324203242132422324233242432425324263242732428324293243032431324323243332434324353243632437324383243932440324413244232443324443244532446324473244832449324503245132452324533245432455324563245732458324593246032461324623246332464324653246632467324683246932470324713247232473324743247532476324773247832479324803248132482324833248432485324863248732488324893249032491324923249332494324953249632497324983249932500325013250232503325043250532506325073250832509325103251132512325133251432515325163251732518325193252032521325223252332524325253252632527325283252932530325313253232533325343253532536325373253832539325403254132542325433254432545325463254732548325493255032551325523255332554325553255632557325583255932560325613256232563325643256532566325673256832569325703257132572325733257432575325763257732578325793258032581325823258332584325853258632587325883258932590325913259232593325943259532596325973259832599326003260132602326033260432605326063260732608326093261032611326123261332614326153261632617326183261932620326213262232623326243262532626326273262832629326303263132632326333263432635326363263732638326393264032641326423264332644326453264632647326483264932650326513265232653326543265532656326573265832659326603266132662326633266432665326663266732668326693267032671326723267332674326753267632677326783267932680326813268232683326843268532686326873268832689326903269132692326933269432695326963269732698326993270032701327023270332704327053270632707327083270932710327113271232713327143271532716327173271832719327203272132722327233272432725327263272732728327293273032731327323273332734327353273632737327383273932740327413274232743327443274532746327473274832749327503275132752327533275432755327563275732758327593276032761327623276332764327653276632767327683276932770327713277232773327743277532776327773277832779327803278132782327833278432785327863278732788327893279032791327923279332794327953279632797327983279932800328013280232803328043280532806328073280832809328103281132812328133281432815328163281732818328193282032821328223282332824328253282632827328283282932830328313283232833328343283532836328373283832839328403284132842328433284432845328463284732848328493285032851328523285332854328553285632857328583285932860328613286232863328643286532866328673286832869328703287132872328733287432875328763287732878328793288032881328823288332884328853288632887328883288932890328913289232893328943289532896328973289832899329003290132902329033290432905329063290732908329093291032911329123291332914329153291632917329183291932920329213292232923329243292532926329273292832929329303293132932329333293432935329363293732938329393294032941329423294332944329453294632947329483294932950329513295232953329543295532956329573295832959329603296132962329633296432965329663296732968329693297032971329723297332974329753297632977329783297932980329813298232983329843298532986329873298832989329903299132992329933299432995329963299732998329993300033001330023300333004330053300633007330083300933010330113301233013330143301533016330173301833019330203302133022330233302433025330263302733028330293303033031330323303333034330353303633037330383303933040330413304233043330443304533046330473304833049330503305133052330533305433055330563305733058330593306033061330623306333064330653306633067330683306933070330713307233073330743307533076330773307833079330803308133082330833308433085330863308733088330893309033091330923309333094330953309633097330983309933100331013310233103331043310533106331073310833109331103311133112331133311433115331163311733118331193312033121331223312333124331253312633127331283312933130331313313233133331343313533136331373313833139331403314133142331433314433145331463314733148331493315033151331523315333154331553315633157331583315933160331613316233163331643316533166331673316833169331703317133172331733317433175331763317733178331793318033181331823318333184331853318633187331883318933190331913319233193331943319533196331973319833199332003320133202332033320433205332063320733208332093321033211332123321333214332153321633217332183321933220332213322233223332243322533226332273322833229332303323133232332333323433235332363323733238332393324033241332423324333244332453324633247332483324933250332513325233253332543325533256332573325833259332603326133262332633326433265332663326733268332693327033271332723327333274332753327633277332783327933280332813328233283332843328533286332873328833289332903329133292332933329433295332963329733298332993330033301333023330333304333053330633307333083330933310333113331233313333143331533316333173331833319333203332133322333233332433325333263332733328333293333033331333323333333334333353333633337333383333933340333413334233343333443334533346333473334833349333503335133352333533335433355333563335733358333593336033361333623336333364333653336633367333683336933370333713337233373333743337533376333773337833379333803338133382333833338433385333863338733388333893339033391333923339333394333953339633397333983339933400334013340233403334043340533406334073340833409334103341133412334133341433415334163341733418334193342033421334223342333424334253342633427334283342933430334313343233433334343343533436334373343833439334403344133442334433344433445334463344733448334493345033451334523345333454334553345633457334583345933460334613346233463334643346533466334673346833469334703347133472334733347433475334763347733478334793348033481334823348333484334853348633487334883348933490334913349233493334943349533496334973349833499335003350133502335033350433505335063350733508335093351033511335123351333514335153351633517335183351933520335213352233523335243352533526335273352833529335303353133532335333353433535335363353733538335393354033541335423354333544335453354633547335483354933550335513355233553335543355533556335573355833559335603356133562335633356433565335663356733568335693357033571335723357333574335753357633577335783357933580335813358233583335843358533586335873358833589335903359133592335933359433595335963359733598335993360033601336023360333604336053360633607336083360933610336113361233613336143361533616336173361833619336203362133622336233362433625336263362733628336293363033631336323363333634336353363633637336383363933640336413364233643336443364533646336473364833649336503365133652336533365433655336563365733658336593366033661336623366333664336653366633667336683366933670336713367233673336743367533676336773367833679336803368133682336833368433685336863368733688336893369033691336923369333694336953369633697336983369933700337013370233703337043370533706337073370833709337103371133712337133371433715337163371733718337193372033721337223372333724337253372633727337283372933730337313373233733337343373533736337373373833739337403374133742337433374433745337463374733748337493375033751337523375333754337553375633757337583375933760337613376233763337643376533766337673376833769337703377133772337733377433775337763377733778337793378033781337823378333784337853378633787337883378933790337913379233793337943379533796337973379833799338003380133802338033380433805338063380733808338093381033811338123381333814338153381633817338183381933820338213382233823338243382533826338273382833829338303383133832338333383433835338363383733838338393384033841338423384333844338453384633847338483384933850338513385233853338543385533856338573385833859338603386133862338633386433865338663386733868338693387033871338723387333874338753387633877338783387933880338813388233883338843388533886338873388833889338903389133892338933389433895338963389733898338993390033901339023390333904339053390633907339083390933910339113391233913339143391533916339173391833919339203392133922339233392433925339263392733928339293393033931339323393333934339353393633937339383393933940339413394233943339443394533946339473394833949339503395133952339533395433955339563395733958339593396033961339623396333964339653396633967339683396933970339713397233973339743397533976339773397833979339803398133982339833398433985339863398733988339893399033991339923399333994339953399633997339983399934000340013400234003340043400534006340073400834009340103401134012340133401434015340163401734018340193402034021340223402334024340253402634027340283402934030340313403234033340343403534036340373403834039340403404134042340433404434045340463404734048340493405034051340523405334054340553405634057340583405934060340613406234063340643406534066340673406834069340703407134072340733407434075340763407734078340793408034081340823408334084340853408634087340883408934090340913409234093340943409534096340973409834099341003410134102341033410434105341063410734108341093411034111341123411334114341153411634117341183411934120341213412234123341243412534126341273412834129341303413134132341333413434135341363413734138341393414034141341423414334144341453414634147341483414934150341513415234153341543415534156341573415834159341603416134162341633416434165341663416734168341693417034171341723417334174341753417634177341783417934180341813418234183341843418534186341873418834189341903419134192341933419434195341963419734198341993420034201342023420334204342053420634207342083420934210342113421234213342143421534216342173421834219342203422134222342233422434225342263422734228342293423034231342323423334234342353423634237342383423934240342413424234243342443424534246342473424834249342503425134252342533425434255342563425734258342593426034261342623426334264342653426634267342683426934270342713427234273342743427534276342773427834279342803428134282342833428434285342863428734288342893429034291342923429334294342953429634297342983429934300343013430234303343043430534306343073430834309343103431134312343133431434315343163431734318343193432034321343223432334324343253432634327343283432934330343313433234333343343433534336343373433834339343403434134342343433434434345343463434734348343493435034351343523435334354343553435634357343583435934360343613436234363343643436534366343673436834369343703437134372343733437434375343763437734378343793438034381343823438334384343853438634387343883438934390343913439234393343943439534396343973439834399344003440134402344033440434405344063440734408344093441034411344123441334414344153441634417344183441934420344213442234423344243442534426344273442834429344303443134432344333443434435344363443734438344393444034441344423444334444344453444634447344483444934450344513445234453344543445534456344573445834459344603446134462344633446434465344663446734468344693447034471344723447334474344753447634477344783447934480344813448234483344843448534486344873448834489344903449134492344933449434495344963449734498344993450034501345023450334504345053450634507345083450934510345113451234513345143451534516345173451834519345203452134522345233452434525345263452734528345293453034531345323453334534345353453634537345383453934540345413454234543345443454534546345473454834549345503455134552345533455434555345563455734558345593456034561345623456334564345653456634567345683456934570345713457234573345743457534576345773457834579345803458134582345833458434585345863458734588345893459034591345923459334594345953459634597345983459934600346013460234603346043460534606346073460834609346103461134612346133461434615346163461734618346193462034621346223462334624346253462634627346283462934630346313463234633346343463534636346373463834639346403464134642346433464434645346463464734648346493465034651346523465334654346553465634657346583465934660346613466234663346643466534666346673466834669346703467134672346733467434675346763467734678346793468034681346823468334684346853468634687346883468934690346913469234693346943469534696346973469834699347003470134702347033470434705347063470734708347093471034711347123471334714347153471634717347183471934720347213472234723347243472534726347273472834729347303473134732347333473434735347363473734738347393474034741347423474334744347453474634747347483474934750347513475234753347543475534756347573475834759347603476134762347633476434765347663476734768347693477034771347723477334774347753477634777347783477934780347813478234783347843478534786347873478834789347903479134792347933479434795347963479734798347993480034801348023480334804348053480634807348083480934810348113481234813348143481534816348173481834819348203482134822348233482434825348263482734828348293483034831348323483334834348353483634837348383483934840348413484234843348443484534846348473484834849348503485134852348533485434855348563485734858348593486034861348623486334864348653486634867348683486934870348713487234873348743487534876348773487834879348803488134882348833488434885348863488734888348893489034891348923489334894348953489634897348983489934900349013490234903349043490534906349073490834909349103491134912349133491434915349163491734918349193492034921349223492334924349253492634927349283492934930349313493234933349343493534936349373493834939349403494134942349433494434945349463494734948349493495034951349523495334954349553495634957349583495934960349613496234963349643496534966349673496834969349703497134972349733497434975349763497734978349793498034981349823498334984349853498634987349883498934990349913499234993349943499534996349973499834999350003500135002350033500435005350063500735008350093501035011350123501335014350153501635017350183501935020350213502235023350243502535026350273502835029350303503135032350333503435035350363503735038350393504035041350423504335044350453504635047350483504935050350513505235053350543505535056350573505835059350603506135062350633506435065350663506735068350693507035071350723507335074350753507635077350783507935080350813508235083350843508535086350873508835089350903509135092350933509435095350963509735098350993510035101351023510335104351053510635107351083510935110351113511235113351143511535116351173511835119351203512135122351233512435125351263512735128351293513035131351323513335134351353513635137351383513935140351413514235143351443514535146351473514835149351503515135152351533515435155351563515735158351593516035161351623516335164351653516635167351683516935170351713517235173351743517535176351773517835179351803518135182351833518435185351863518735188351893519035191351923519335194351953519635197351983519935200352013520235203352043520535206352073520835209352103521135212352133521435215352163521735218352193522035221352223522335224352253522635227352283522935230352313523235233352343523535236352373523835239352403524135242352433524435245352463524735248352493525035251352523525335254352553525635257352583525935260352613526235263352643526535266352673526835269352703527135272352733527435275352763527735278352793528035281352823528335284352853528635287352883528935290352913529235293352943529535296352973529835299353003530135302353033530435305353063530735308353093531035311353123531335314353153531635317353183531935320353213532235323353243532535326353273532835329353303533135332353333533435335353363533735338353393534035341353423534335344353453534635347353483534935350353513535235353353543535535356353573535835359353603536135362353633536435365353663536735368353693537035371353723537335374353753537635377353783537935380353813538235383353843538535386353873538835389353903539135392353933539435395353963539735398353993540035401354023540335404354053540635407354083540935410354113541235413354143541535416354173541835419354203542135422354233542435425354263542735428354293543035431354323543335434354353543635437354383543935440354413544235443354443544535446354473544835449354503545135452354533545435455354563545735458354593546035461354623546335464354653546635467354683546935470354713547235473354743547535476354773547835479354803548135482354833548435485354863548735488354893549035491354923549335494354953549635497354983549935500355013550235503355043550535506355073550835509355103551135512355133551435515355163551735518355193552035521355223552335524355253552635527355283552935530355313553235533355343553535536355373553835539355403554135542355433554435545355463554735548355493555035551355523555335554355553555635557355583555935560355613556235563355643556535566355673556835569355703557135572355733557435575355763557735578355793558035581355823558335584355853558635587355883558935590355913559235593355943559535596355973559835599356003560135602356033560435605356063560735608356093561035611356123561335614356153561635617356183561935620356213562235623356243562535626356273562835629356303563135632356333563435635356363563735638356393564035641356423564335644356453564635647356483564935650356513565235653356543565535656356573565835659356603566135662356633566435665356663566735668356693567035671356723567335674356753567635677356783567935680356813568235683356843568535686356873568835689356903569135692356933569435695356963569735698356993570035701357023570335704357053570635707357083570935710357113571235713357143571535716357173571835719357203572135722357233572435725357263572735728357293573035731357323573335734357353573635737357383573935740357413574235743357443574535746357473574835749357503575135752357533575435755357563575735758357593576035761357623576335764357653576635767357683576935770357713577235773357743577535776357773577835779357803578135782357833578435785357863578735788357893579035791357923579335794357953579635797357983579935800358013580235803358043580535806358073580835809358103581135812358133581435815358163581735818358193582035821358223582335824358253582635827358283582935830358313583235833358343583535836358373583835839358403584135842358433584435845358463584735848358493585035851358523585335854358553585635857358583585935860358613586235863358643586535866358673586835869358703587135872358733587435875358763587735878358793588035881358823588335884358853588635887358883588935890358913589235893358943589535896358973589835899359003590135902359033590435905359063590735908359093591035911359123591335914359153591635917359183591935920359213592235923359243592535926359273592835929359303593135932359333593435935359363593735938359393594035941359423594335944359453594635947359483594935950359513595235953359543595535956359573595835959359603596135962359633596435965359663596735968359693597035971359723597335974359753597635977359783597935980359813598235983359843598535986359873598835989359903599135992359933599435995359963599735998359993600036001360023600336004360053600636007360083600936010360113601236013360143601536016360173601836019360203602136022360233602436025360263602736028360293603036031360323603336034360353603636037360383603936040360413604236043360443604536046360473604836049360503605136052360533605436055360563605736058360593606036061360623606336064360653606636067360683606936070360713607236073360743607536076360773607836079360803608136082360833608436085360863608736088360893609036091360923609336094360953609636097360983609936100361013610236103361043610536106361073610836109361103611136112361133611436115361163611736118361193612036121361223612336124361253612636127361283612936130361313613236133361343613536136361373613836139361403614136142361433614436145361463614736148361493615036151361523615336154361553615636157361583615936160361613616236163361643616536166361673616836169361703617136172361733617436175361763617736178361793618036181361823618336184361853618636187361883618936190361913619236193361943619536196361973619836199362003620136202362033620436205362063620736208362093621036211362123621336214362153621636217362183621936220362213622236223362243622536226362273622836229362303623136232362333623436235362363623736238362393624036241362423624336244362453624636247362483624936250362513625236253362543625536256362573625836259362603626136262362633626436265362663626736268362693627036271362723627336274362753627636277362783627936280362813628236283362843628536286362873628836289362903629136292362933629436295362963629736298362993630036301363023630336304363053630636307363083630936310363113631236313363143631536316363173631836319363203632136322363233632436325363263632736328363293633036331363323633336334363353633636337363383633936340363413634236343363443634536346363473634836349363503635136352363533635436355363563635736358363593636036361363623636336364363653636636367363683636936370363713637236373363743637536376363773637836379363803638136382363833638436385363863638736388363893639036391363923639336394363953639636397363983639936400364013640236403364043640536406364073640836409364103641136412364133641436415364163641736418364193642036421364223642336424364253642636427364283642936430364313643236433364343643536436364373643836439364403644136442364433644436445364463644736448364493645036451364523645336454364553645636457364583645936460364613646236463364643646536466364673646836469364703647136472364733647436475364763647736478364793648036481364823648336484364853648636487364883648936490364913649236493364943649536496364973649836499365003650136502365033650436505365063650736508365093651036511365123651336514365153651636517365183651936520365213652236523365243652536526365273652836529365303653136532365333653436535365363653736538365393654036541365423654336544365453654636547365483654936550365513655236553365543655536556365573655836559365603656136562365633656436565365663656736568365693657036571365723657336574365753657636577365783657936580365813658236583365843658536586365873658836589365903659136592365933659436595365963659736598365993660036601366023660336604366053660636607366083660936610366113661236613366143661536616366173661836619366203662136622366233662436625366263662736628366293663036631366323663336634366353663636637366383663936640366413664236643366443664536646366473664836649366503665136652366533665436655366563665736658366593666036661366623666336664366653666636667366683666936670366713667236673366743667536676366773667836679366803668136682366833668436685366863668736688366893669036691366923669336694366953669636697366983669936700367013670236703367043670536706367073670836709367103671136712367133671436715367163671736718367193672036721367223672336724367253672636727367283672936730367313673236733367343673536736367373673836739367403674136742367433674436745367463674736748367493675036751367523675336754367553675636757367583675936760367613676236763367643676536766367673676836769367703677136772367733677436775367763677736778367793678036781367823678336784367853678636787367883678936790367913679236793367943679536796367973679836799
  1. /******/ (function(modules) { // webpackBootstrap
  2. /******/ // The module cache
  3. /******/ var installedModules = {};
  4. /******/ // The require function
  5. /******/ function __webpack_require__(moduleId) {
  6. /******/ // Check if module is in cache
  7. /******/ if(installedModules[moduleId])
  8. /******/ return installedModules[moduleId].exports;
  9. /******/ // Create a new module (and put it into the cache)
  10. /******/ var module = installedModules[moduleId] = {
  11. /******/ exports: {},
  12. /******/ id: moduleId,
  13. /******/ loaded: false
  14. /******/ };
  15. /******/ // Execute the module function
  16. /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  17. /******/ // Flag the module as loaded
  18. /******/ module.loaded = true;
  19. /******/ // Return the exports of the module
  20. /******/ return module.exports;
  21. /******/ }
  22. /******/ // expose the modules object (__webpack_modules__)
  23. /******/ __webpack_require__.m = modules;
  24. /******/ // expose the module cache
  25. /******/ __webpack_require__.c = installedModules;
  26. /******/ // __webpack_public_path__
  27. /******/ __webpack_require__.p = "";
  28. /******/ // Load entry module and return exports
  29. /******/ return __webpack_require__(0);
  30. /******/ })
  31. /************************************************************************/
  32. /******/ ([
  33. /* 0 */
  34. /***/ (function(module, exports, __webpack_require__) {
  35. /* eslint-disable no-var */
  36. /* eslint-env qunit */
  37. var mediaSources = __webpack_require__(1);
  38. var q = window.QUnit;
  39. q.module('Webpack Require');
  40. q.test('mediaSources should be requirable and bundled via webpack', function(assert) {
  41. assert.ok(mediaSources, 'videojs-contrib-media-sources is required properly');
  42. });
  43. /***/ }),
  44. /* 1 */
  45. /***/ (function(module, exports, __webpack_require__) {
  46. /**
  47. * @file videojs-contrib-media-sources.js
  48. */
  49. 'use strict';
  50. Object.defineProperty(exports, '__esModule', {
  51. value: true
  52. });
  53. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  54. var _globalWindow = __webpack_require__(2);
  55. var _globalWindow2 = _interopRequireDefault(_globalWindow);
  56. var _flashMediaSource = __webpack_require__(3);
  57. var _flashMediaSource2 = _interopRequireDefault(_flashMediaSource);
  58. var _htmlMediaSource = __webpack_require__(137);
  59. var _htmlMediaSource2 = _interopRequireDefault(_htmlMediaSource);
  60. var _videoJs = __webpack_require__(6);
  61. var _videoJs2 = _interopRequireDefault(_videoJs);
  62. var urlCount = 0;
  63. // ------------
  64. // Media Source
  65. // ------------
  66. var defaults = {
  67. // how to determine the MediaSource implementation to use. There
  68. // are three available modes:
  69. // - auto: use native MediaSources where available and Flash
  70. // everywhere else
  71. // - html5: always use native MediaSources
  72. // - flash: always use the Flash MediaSource polyfill
  73. mode: 'auto'
  74. };
  75. // store references to the media sources so they can be connected
  76. // to a video element (a swf object)
  77. // TODO: can we store this somewhere local to this module?
  78. _videoJs2['default'].mediaSources = {};
  79. /**
  80. * Provide a method for a swf object to notify JS that a
  81. * media source is now open.
  82. *
  83. * @param {String} msObjectURL string referencing the MSE Object URL
  84. * @param {String} swfId the swf id
  85. */
  86. var open = function open(msObjectURL, swfId) {
  87. var mediaSource = _videoJs2['default'].mediaSources[msObjectURL];
  88. if (mediaSource) {
  89. mediaSource.trigger({ type: 'sourceopen', swfId: swfId });
  90. } else {
  91. throw new Error('Media Source not found (Video.js)');
  92. }
  93. };
  94. /**
  95. * Check to see if the native MediaSource object exists and supports
  96. * an MP4 container with both H.264 video and AAC-LC audio.
  97. *
  98. * @return {Boolean} if native media sources are supported
  99. */
  100. var supportsNativeMediaSources = function supportsNativeMediaSources() {
  101. return !!_globalWindow2['default'].MediaSource && !!_globalWindow2['default'].MediaSource.isTypeSupported && _globalWindow2['default'].MediaSource.isTypeSupported('video/mp4;codecs="avc1.4d400d,mp4a.40.2"');
  102. };
  103. /**
  104. * An emulation of the MediaSource API so that we can support
  105. * native and non-native functionality such as flash and
  106. * video/mp2t videos. returns an instance of HtmlMediaSource or
  107. * FlashMediaSource depending on what is supported and what options
  108. * are passed in.
  109. *
  110. * @link https://developer.mozilla.org/en-US/docs/Web/API/MediaSource/MediaSource
  111. * @param {Object} options options to use during setup.
  112. */
  113. var MediaSource = function MediaSource(options) {
  114. var settings = _videoJs2['default'].mergeOptions(defaults, options);
  115. this.MediaSource = {
  116. open: open,
  117. supportsNativeMediaSources: supportsNativeMediaSources
  118. };
  119. // determine whether HTML MediaSources should be used
  120. if (settings.mode === 'html5' || settings.mode === 'auto' && supportsNativeMediaSources()) {
  121. return new _htmlMediaSource2['default']();
  122. } else if (_videoJs2['default'].getTech('Flash')) {
  123. return new _flashMediaSource2['default']();
  124. }
  125. throw new Error('Cannot use Flash or Html5 to create a MediaSource for this video');
  126. };
  127. exports.MediaSource = MediaSource;
  128. MediaSource.open = open;
  129. MediaSource.supportsNativeMediaSources = supportsNativeMediaSources;
  130. /**
  131. * A wrapper around the native URL for our MSE object
  132. * implementation, this object is exposed under videojs.URL
  133. *
  134. * @link https://developer.mozilla.org/en-US/docs/Web/API/URL/URL
  135. */
  136. var URL = {
  137. /**
  138. * A wrapper around the native createObjectURL for our objects.
  139. * This function maps a native or emulated mediaSource to a blob
  140. * url so that it can be loaded into video.js
  141. *
  142. * @link https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
  143. * @param {MediaSource} object the object to create a blob url to
  144. */
  145. createObjectURL: function createObjectURL(object) {
  146. var objectUrlPrefix = 'blob:vjs-media-source/';
  147. var url = undefined;
  148. // use the native MediaSource to generate an object URL
  149. if (object instanceof _htmlMediaSource2['default']) {
  150. url = _globalWindow2['default'].URL.createObjectURL(object.nativeMediaSource_);
  151. object.url_ = url;
  152. return url;
  153. }
  154. // if the object isn't an emulated MediaSource, delegate to the
  155. // native implementation
  156. if (!(object instanceof _flashMediaSource2['default'])) {
  157. url = _globalWindow2['default'].URL.createObjectURL(object);
  158. object.url_ = url;
  159. return url;
  160. }
  161. // build a URL that can be used to map back to the emulated
  162. // MediaSource
  163. url = objectUrlPrefix + urlCount;
  164. urlCount++;
  165. // setup the mapping back to object
  166. _videoJs2['default'].mediaSources[url] = object;
  167. return url;
  168. }
  169. };
  170. exports.URL = URL;
  171. _videoJs2['default'].MediaSource = MediaSource;
  172. _videoJs2['default'].URL = URL;
  173. /***/ }),
  174. /* 2 */
  175. /***/ (function(module, exports) {
  176. /* WEBPACK VAR INJECTION */(function(global) {var win;
  177. if (typeof window !== "undefined") {
  178. win = window;
  179. } else if (typeof global !== "undefined") {
  180. win = global;
  181. } else if (typeof self !== "undefined"){
  182. win = self;
  183. } else {
  184. win = {};
  185. }
  186. module.exports = win;
  187. /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  188. /***/ }),
  189. /* 3 */
  190. /***/ (function(module, exports, __webpack_require__) {
  191. /**
  192. * @file flash-media-source.js
  193. */
  194. 'use strict';
  195. Object.defineProperty(exports, '__esModule', {
  196. value: true
  197. });
  198. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  199. var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
  200. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  201. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
  202. function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  203. var _globalDocument = __webpack_require__(4);
  204. var _globalDocument2 = _interopRequireDefault(_globalDocument);
  205. var _videoJs = __webpack_require__(6);
  206. var _videoJs2 = _interopRequireDefault(_videoJs);
  207. var _flashSourceBuffer = __webpack_require__(114);
  208. var _flashSourceBuffer2 = _interopRequireDefault(_flashSourceBuffer);
  209. var _flashConstants = __webpack_require__(135);
  210. var _flashConstants2 = _interopRequireDefault(_flashConstants);
  211. var _codecUtils = __webpack_require__(136);
  212. /**
  213. * A flash implmentation of HTML MediaSources and a polyfill
  214. * for browsers that don't support native or HTML MediaSources..
  215. *
  216. * @link https://developer.mozilla.org/en-US/docs/Web/API/MediaSource
  217. * @class FlashMediaSource
  218. * @extends videojs.EventTarget
  219. */
  220. var FlashMediaSource = (function (_videojs$EventTarget) {
  221. _inherits(FlashMediaSource, _videojs$EventTarget);
  222. function FlashMediaSource() {
  223. var _this = this;
  224. _classCallCheck(this, FlashMediaSource);
  225. _get(Object.getPrototypeOf(FlashMediaSource.prototype), 'constructor', this).call(this);
  226. this.sourceBuffers = [];
  227. this.readyState = 'closed';
  228. this.on(['sourceopen', 'webkitsourceopen'], function (event) {
  229. // find the swf where we will push media data
  230. _this.swfObj = _globalDocument2['default'].getElementById(event.swfId);
  231. _this.player_ = (0, _videoJs2['default'])(_this.swfObj.parentNode);
  232. _this.tech_ = _this.swfObj.tech;
  233. _this.readyState = 'open';
  234. _this.tech_.on('seeking', function () {
  235. var i = _this.sourceBuffers.length;
  236. while (i--) {
  237. _this.sourceBuffers[i].abort();
  238. }
  239. });
  240. // trigger load events
  241. if (_this.swfObj) {
  242. _this.swfObj.vjs_load();
  243. }
  244. });
  245. }
  246. /**
  247. * Set or return the presentation duration.
  248. *
  249. * @param {Double} value the duration of the media in seconds
  250. * @param {Double} the current presentation duration
  251. * @link http://www.w3.org/TR/media-source/#widl-MediaSource-duration
  252. */
  253. /**
  254. * We have this function so that the html and flash interfaces
  255. * are the same.
  256. *
  257. * @private
  258. */
  259. _createClass(FlashMediaSource, [{
  260. key: 'addSeekableRange_',
  261. value: function addSeekableRange_() {}
  262. // intentional no-op
  263. /**
  264. * Create a new flash source buffer and add it to our flash media source.
  265. *
  266. * @link https://developer.mozilla.org/en-US/docs/Web/API/MediaSource/addSourceBuffer
  267. * @param {String} type the content-type of the source
  268. * @return {Object} the flash source buffer
  269. */
  270. }, {
  271. key: 'addSourceBuffer',
  272. value: function addSourceBuffer(type) {
  273. var parsedType = (0, _codecUtils.parseContentType)(type);
  274. var sourceBuffer = undefined;
  275. // if this is an FLV type, we'll push data to flash
  276. if (parsedType.type === 'video/mp2t' || parsedType.type === 'audio/mp2t') {
  277. // Flash source buffers
  278. sourceBuffer = new _flashSourceBuffer2['default'](this);
  279. } else {
  280. throw new Error('NotSupportedError (Video.js)');
  281. }
  282. this.sourceBuffers.push(sourceBuffer);
  283. return sourceBuffer;
  284. }
  285. /**
  286. * Signals the end of the stream.
  287. *
  288. * @link https://w3c.github.io/media-source/#widl-MediaSource-endOfStream-void-EndOfStreamError-error
  289. * @param {String=} error Signals that a playback error
  290. * has occurred. If specified, it must be either "network" or
  291. * "decode".
  292. */
  293. }, {
  294. key: 'endOfStream',
  295. value: function endOfStream(error) {
  296. if (error === 'network') {
  297. // MEDIA_ERR_NETWORK
  298. this.tech_.error(2);
  299. } else if (error === 'decode') {
  300. // MEDIA_ERR_DECODE
  301. this.tech_.error(3);
  302. }
  303. if (this.readyState !== 'ended') {
  304. this.readyState = 'ended';
  305. this.swfObj.vjs_endOfStream();
  306. }
  307. }
  308. }]);
  309. return FlashMediaSource;
  310. })(_videoJs2['default'].EventTarget);
  311. exports['default'] = FlashMediaSource;
  312. try {
  313. Object.defineProperty(FlashMediaSource.prototype, 'duration', {
  314. /**
  315. * Return the presentation duration.
  316. *
  317. * @return {Double} the duration of the media in seconds
  318. * @link http://www.w3.org/TR/media-source/#widl-MediaSource-duration
  319. */
  320. get: function get() {
  321. if (!this.swfObj) {
  322. return NaN;
  323. }
  324. // get the current duration from the SWF
  325. return this.swfObj.vjs_getProperty('duration');
  326. },
  327. /**
  328. * Set the presentation duration.
  329. *
  330. * @param {Double} value the duration of the media in seconds
  331. * @return {Double} the duration of the media in seconds
  332. * @link http://www.w3.org/TR/media-source/#widl-MediaSource-duration
  333. */
  334. set: function set(value) {
  335. var i = undefined;
  336. var oldDuration = this.swfObj.vjs_getProperty('duration');
  337. this.swfObj.vjs_setProperty('duration', value);
  338. if (value < oldDuration) {
  339. // In MSE, this triggers the range removal algorithm which causes
  340. // an update to occur
  341. for (i = 0; i < this.sourceBuffers.length; i++) {
  342. this.sourceBuffers[i].remove(value, oldDuration);
  343. }
  344. }
  345. return value;
  346. }
  347. });
  348. } catch (e) {
  349. // IE8 throws if defineProperty is called on a non-DOM node. We
  350. // don't support IE8 but we shouldn't throw an error if loaded
  351. // there.
  352. FlashMediaSource.prototype.duration = NaN;
  353. }
  354. for (var property in _flashConstants2['default']) {
  355. FlashMediaSource[property] = _flashConstants2['default'][property];
  356. }
  357. module.exports = exports['default'];
  358. /***/ }),
  359. /* 4 */
  360. /***/ (function(module, exports, __webpack_require__) {
  361. /* WEBPACK VAR INJECTION */(function(global) {var topLevel = typeof global !== 'undefined' ? global :
  362. typeof window !== 'undefined' ? window : {}
  363. var minDoc = __webpack_require__(5);
  364. var doccy;
  365. if (typeof document !== 'undefined') {
  366. doccy = document;
  367. } else {
  368. doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
  369. if (!doccy) {
  370. doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
  371. }
  372. }
  373. module.exports = doccy;
  374. /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  375. /***/ }),
  376. /* 5 */
  377. /***/ (function(module, exports) {
  378. /* (ignored) */
  379. /***/ }),
  380. /* 6 */
  381. /***/ (function(module, exports, __webpack_require__) {
  382. var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;'use strict';
  383. exports.__esModule = true;
  384. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /**
  385. * @file video.js
  386. * @module videojs
  387. */
  388. /* global define */
  389. // Include the built-in techs
  390. var _window = __webpack_require__(7);
  391. var _window2 = _interopRequireDefault(_window);
  392. var _document = __webpack_require__(8);
  393. var _document2 = _interopRequireDefault(_document);
  394. var _browser = __webpack_require__(10);
  395. var browser = _interopRequireWildcard(_browser);
  396. var _dom = __webpack_require__(11);
  397. var Dom = _interopRequireWildcard(_dom);
  398. var _setup = __webpack_require__(16);
  399. var setup = _interopRequireWildcard(_setup);
  400. var _stylesheet = __webpack_require__(18);
  401. var stylesheet = _interopRequireWildcard(_stylesheet);
  402. var _component = __webpack_require__(19);
  403. var _component2 = _interopRequireDefault(_component);
  404. var _eventTarget = __webpack_require__(23);
  405. var _eventTarget2 = _interopRequireDefault(_eventTarget);
  406. var _events = __webpack_require__(17);
  407. var Events = _interopRequireWildcard(_events);
  408. var _player = __webpack_require__(24);
  409. var _player2 = _interopRequireDefault(_player);
  410. var _plugins = __webpack_require__(110);
  411. var _plugins2 = _interopRequireDefault(_plugins);
  412. var _mergeOptions2 = __webpack_require__(22);
  413. var _mergeOptions3 = _interopRequireDefault(_mergeOptions2);
  414. var _fn = __webpack_require__(20);
  415. var Fn = _interopRequireWildcard(_fn);
  416. var _textTrack = __webpack_require__(34);
  417. var _textTrack2 = _interopRequireDefault(_textTrack);
  418. var _audioTrack = __webpack_require__(111);
  419. var _audioTrack2 = _interopRequireDefault(_audioTrack);
  420. var _videoTrack = __webpack_require__(112);
  421. var _videoTrack2 = _interopRequireDefault(_videoTrack);
  422. var _timeRanges = __webpack_require__(25);
  423. var _formatTime = __webpack_require__(67);
  424. var _formatTime2 = _interopRequireDefault(_formatTime);
  425. var _log = __webpack_require__(13);
  426. var _log2 = _interopRequireDefault(_log);
  427. var _url = __webpack_require__(38);
  428. var Url = _interopRequireWildcard(_url);
  429. var _obj = __webpack_require__(14);
  430. var _computedStyle = __webpack_require__(75);
  431. var _computedStyle2 = _interopRequireDefault(_computedStyle);
  432. var _extend = __webpack_require__(113);
  433. var _extend2 = _interopRequireDefault(_extend);
  434. var _xhr = __webpack_require__(39);
  435. var _xhr2 = _interopRequireDefault(_xhr);
  436. var _tech = __webpack_require__(32);
  437. var _tech2 = _interopRequireDefault(_tech);
  438. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  439. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  440. // HTML5 Element Shim for IE8
  441. if (typeof HTMLVideoElement === 'undefined' && Dom.isReal()) {
  442. _document2['default'].createElement('video');
  443. _document2['default'].createElement('audio');
  444. _document2['default'].createElement('track');
  445. }
  446. /**
  447. * Doubles as the main function for users to create a player instance and also
  448. * the main library object.
  449. * The `videojs` function can be used to initialize or retrieve a player.
  450. *
  451. * @param {string|Element} id
  452. * Video element or video element ID
  453. *
  454. * @param {Object} [options]
  455. * Optional options object for config/settings
  456. *
  457. * @param {Component~ReadyCallback} [ready]
  458. * Optional ready callback
  459. *
  460. * @return {Player}
  461. * A player instance
  462. *
  463. * @mixes videojs
  464. */
  465. function videojs(id, options, ready) {
  466. var tag = void 0;
  467. // Allow for element or ID to be passed in
  468. // String ID
  469. if (typeof id === 'string') {
  470. // Adjust for jQuery ID syntax
  471. if (id.indexOf('#') === 0) {
  472. id = id.slice(1);
  473. }
  474. // If a player instance has already been created for this ID return it.
  475. if (videojs.getPlayers()[id]) {
  476. // If options or ready funtion are passed, warn
  477. if (options) {
  478. _log2['default'].warn('Player "' + id + '" is already initialised. Options will not be applied.');
  479. }
  480. if (ready) {
  481. videojs.getPlayers()[id].ready(ready);
  482. }
  483. return videojs.getPlayers()[id];
  484. }
  485. // Otherwise get element for ID
  486. tag = Dom.getEl(id);
  487. // ID is a media element
  488. } else {
  489. tag = id;
  490. }
  491. // Check for a useable element
  492. // re: nodeName, could be a box div also
  493. if (!tag || !tag.nodeName) {
  494. throw new TypeError('The element or ID supplied is not valid. (videojs)');
  495. }
  496. // Element may have a player attr referring to an already created player instance.
  497. // If so return that otherwise set up a new player below
  498. if (tag.player || _player2['default'].players[tag.playerId]) {
  499. return tag.player || _player2['default'].players[tag.playerId];
  500. }
  501. options = options || {};
  502. videojs.hooks('beforesetup').forEach(function (hookFunction) {
  503. var opts = hookFunction(tag, (0, _mergeOptions3['default'])(options));
  504. if (!(0, _obj.isObject)(opts) || Array.isArray(opts)) {
  505. _log2['default'].error('please return an object in beforesetup hooks');
  506. return;
  507. }
  508. options = (0, _mergeOptions3['default'])(options, opts);
  509. });
  510. var PlayerComponent = _component2['default'].getComponent('Player');
  511. // If not, set up a new player
  512. var player = new PlayerComponent(tag, options, ready);
  513. videojs.hooks('setup').forEach(function (hookFunction) {
  514. return hookFunction(player);
  515. });
  516. return player;
  517. }
  518. /**
  519. * An Object that contains lifecycle hooks as keys which point to an array
  520. * of functions that are run when a lifecycle is triggered
  521. */
  522. videojs.hooks_ = {};
  523. /**
  524. * Get a list of hooks for a specific lifecycle
  525. *
  526. * @param {string} type
  527. * the lifecyle to get hooks from
  528. *
  529. * @param {Function} [fn]
  530. * Optionally add a hook to the lifecycle that your are getting.
  531. *
  532. * @return {Array}
  533. * an array of hooks, or an empty array if there are none.
  534. */
  535. videojs.hooks = function (type, fn) {
  536. videojs.hooks_[type] = videojs.hooks_[type] || [];
  537. if (fn) {
  538. videojs.hooks_[type] = videojs.hooks_[type].concat(fn);
  539. }
  540. return videojs.hooks_[type];
  541. };
  542. /**
  543. * Add a function hook to a specific videojs lifecycle.
  544. *
  545. * @param {string} type
  546. * the lifecycle to hook the function to.
  547. *
  548. * @param {Function|Function[]}
  549. * The function or array of functions to attach.
  550. */
  551. videojs.hook = function (type, fn) {
  552. videojs.hooks(type, fn);
  553. };
  554. /**
  555. * Remove a hook from a specific videojs lifecycle.
  556. *
  557. * @param {string} type
  558. * the lifecycle that the function hooked to
  559. *
  560. * @param {Function} fn
  561. * The hooked function to remove
  562. *
  563. * @return {boolean}
  564. * The function that was removed or undef
  565. */
  566. videojs.removeHook = function (type, fn) {
  567. var index = videojs.hooks(type).indexOf(fn);
  568. if (index <= -1) {
  569. return false;
  570. }
  571. videojs.hooks_[type] = videojs.hooks_[type].slice();
  572. videojs.hooks_[type].splice(index, 1);
  573. return true;
  574. };
  575. // Add default styles
  576. if (_window2['default'].VIDEOJS_NO_DYNAMIC_STYLE !== true && Dom.isReal()) {
  577. var style = Dom.$('.vjs-styles-defaults');
  578. if (!style) {
  579. style = stylesheet.createStyleElement('vjs-styles-defaults');
  580. var head = Dom.$('head');
  581. if (head) {
  582. head.insertBefore(style, head.firstChild);
  583. }
  584. stylesheet.setTextContent(style, '\n .video-js {\n width: 300px;\n height: 150px;\n }\n\n .vjs-fluid {\n padding-top: 56.25%\n }\n ');
  585. }
  586. }
  587. // Run Auto-load players
  588. // You have to wait at least once in case this script is loaded after your
  589. // video in the DOM (weird behavior only with minified version)
  590. setup.autoSetupTimeout(1, videojs);
  591. /**
  592. * Current software version. Follows semver.
  593. *
  594. * @type {string}
  595. */
  596. videojs.VERSION = '5.20.3';
  597. /**
  598. * The global options object. These are the settings that take effect
  599. * if no overrides are specified when the player is created.
  600. *
  601. * @type {Object}
  602. */
  603. videojs.options = _player2['default'].prototype.options_;
  604. /**
  605. * Get an object with the currently created players, keyed by player ID
  606. *
  607. * @return {Object}
  608. * The created players
  609. */
  610. videojs.getPlayers = function () {
  611. return _player2['default'].players;
  612. };
  613. /**
  614. * Expose players object.
  615. *
  616. * @memberOf videojs
  617. * @property {Object} players
  618. */
  619. videojs.players = _player2['default'].players;
  620. /**
  621. * Get a component class object by name
  622. *
  623. * @borrows Component.getComponent as videojs.getComponent
  624. */
  625. videojs.getComponent = _component2['default'].getComponent;
  626. /**
  627. * Register a component so it can referred to by name. Used when adding to other
  628. * components, either through addChild `component.addChild('myComponent')` or through
  629. * default children options `{ children: ['myComponent'] }`.
  630. *
  631. * > NOTE: You could also just initialize the component before adding.
  632. * `component.addChild(new MyComponent());`
  633. *
  634. * @param {string} name
  635. * The class name of the component
  636. *
  637. * @param {Component} comp
  638. * The component class
  639. *
  640. * @return {Component}
  641. * The newly registered component
  642. */
  643. videojs.registerComponent = function (name, comp) {
  644. if (_tech2['default'].isTech(comp)) {
  645. _log2['default'].warn('The ' + name + ' tech was registered as a component. It should instead be registered using videojs.registerTech(name, tech)');
  646. }
  647. _component2['default'].registerComponent.call(_component2['default'], name, comp);
  648. };
  649. /**
  650. * Get a Tech class object by name
  651. *
  652. * @borrows Tech.getTech as videojs.getTech
  653. */
  654. videojs.getTech = _tech2['default'].getTech;
  655. /**
  656. * Register a Tech so it can referred to by name.
  657. * This is used in the tech order for the player.
  658. *
  659. * @borrows Tech.registerTech as videojs.registerTech
  660. */
  661. videojs.registerTech = _tech2['default'].registerTech;
  662. /**
  663. * A suite of browser and device tests from {@link browser}.
  664. *
  665. * @type {Object}
  666. * @private
  667. */
  668. videojs.browser = browser;
  669. /**
  670. * Whether or not the browser supports touch events. Included for backward
  671. * compatibility with 4.x, but deprecated. Use `videojs.browser.TOUCH_ENABLED`
  672. * instead going forward.
  673. *
  674. * @deprecated since version 5.0
  675. * @type {boolean}
  676. */
  677. videojs.TOUCH_ENABLED = browser.TOUCH_ENABLED;
  678. /**
  679. * Subclass an existing class
  680. * Mimics ES6 subclassing with the `extend` keyword
  681. *
  682. * @borrows extend:extendFn as videojs.extend
  683. */
  684. videojs.extend = _extend2['default'];
  685. /**
  686. * Merge two options objects recursively
  687. * Performs a deep merge like lodash.merge but **only merges plain objects**
  688. * (not arrays, elements, anything else)
  689. * Other values will be copied directly from the second object.
  690. *
  691. * @borrows merge-options:mergeOptions as videojs.mergeOptions
  692. */
  693. videojs.mergeOptions = _mergeOptions3['default'];
  694. /**
  695. * Change the context (this) of a function
  696. *
  697. * > NOTE: as of v5.0 we require an ES5 shim, so you should use the native
  698. * `function() {}.bind(newContext);` instead of this.
  699. *
  700. * @borrows fn:bind as videojs.bind
  701. */
  702. videojs.bind = Fn.bind;
  703. /**
  704. * Create a Video.js player plugin.
  705. * Plugins are only initialized when options for the plugin are included
  706. * in the player options, or the plugin function on the player instance is
  707. * called.
  708. *
  709. * @borrows plugin:plugin as videojs.plugin
  710. */
  711. videojs.plugin = _plugins2['default'];
  712. /**
  713. * Adding languages so that they're available to all players.
  714. * Example: `videojs.addLanguage('es', { 'Hello': 'Hola' });`
  715. *
  716. * @param {string} code
  717. * The language code or dictionary property
  718. *
  719. * @param {Object} data
  720. * The data values to be translated
  721. *
  722. * @return {Object}
  723. * The resulting language dictionary object
  724. */
  725. videojs.addLanguage = function (code, data) {
  726. var _mergeOptions;
  727. code = ('' + code).toLowerCase();
  728. videojs.options.languages = (0, _mergeOptions3['default'])(videojs.options.languages, (_mergeOptions = {}, _mergeOptions[code] = data, _mergeOptions));
  729. return videojs.options.languages[code];
  730. };
  731. /**
  732. * Log messages
  733. *
  734. * @borrows log:log as videojs.log
  735. */
  736. videojs.log = _log2['default'];
  737. /**
  738. * Creates an emulated TimeRange object.
  739. *
  740. * @borrows time-ranges:createTimeRanges as videojs.createTimeRange
  741. */
  742. /**
  743. * @borrows time-ranges:createTimeRanges as videojs.createTimeRanges
  744. */
  745. videojs.createTimeRange = videojs.createTimeRanges = _timeRanges.createTimeRanges;
  746. /**
  747. * Format seconds as a time string, H:MM:SS or M:SS
  748. * Supplying a guide (in seconds) will force a number of leading zeros
  749. * to cover the length of the guide
  750. *
  751. * @borrows format-time:formatTime as videojs.formatTime
  752. */
  753. videojs.formatTime = _formatTime2['default'];
  754. /**
  755. * Resolve and parse the elements of a URL
  756. *
  757. * @borrows url:parseUrl as videojs.parseUrl
  758. */
  759. videojs.parseUrl = Url.parseUrl;
  760. /**
  761. * Returns whether the url passed is a cross domain request or not.
  762. *
  763. * @borrows url:isCrossOrigin as videojs.isCrossOrigin
  764. */
  765. videojs.isCrossOrigin = Url.isCrossOrigin;
  766. /**
  767. * Event target class.
  768. *
  769. * @borrows EventTarget as videojs.EventTarget
  770. */
  771. videojs.EventTarget = _eventTarget2['default'];
  772. /**
  773. * Add an event listener to element
  774. * It stores the handler function in a separate cache object
  775. * and adds a generic handler to the element's event,
  776. * along with a unique id (guid) to the element.
  777. *
  778. * @borrows events:on as videojs.on
  779. */
  780. videojs.on = Events.on;
  781. /**
  782. * Trigger a listener only once for an event
  783. *
  784. * @borrows events:one as videojs.one
  785. */
  786. videojs.one = Events.one;
  787. /**
  788. * Removes event listeners from an element
  789. *
  790. * @borrows events:off as videojs.off
  791. */
  792. videojs.off = Events.off;
  793. /**
  794. * Trigger an event for an element
  795. *
  796. * @borrows events:trigger as videojs.trigger
  797. */
  798. videojs.trigger = Events.trigger;
  799. /**
  800. * A cross-browser XMLHttpRequest wrapper. Here's a simple example:
  801. *
  802. * @param {Object} options
  803. * settings for the request.
  804. *
  805. * @return {XMLHttpRequest|XDomainRequest}
  806. * The request object.
  807. *
  808. * @see https://github.com/Raynos/xhr
  809. */
  810. videojs.xhr = _xhr2['default'];
  811. /**
  812. * TextTrack class
  813. *
  814. * @borrows TextTrack as videojs.TextTrack
  815. */
  816. videojs.TextTrack = _textTrack2['default'];
  817. /**
  818. * export the AudioTrack class so that source handlers can create
  819. * AudioTracks and then add them to the players AudioTrackList
  820. *
  821. * @borrows AudioTrack as videojs.AudioTrack
  822. */
  823. videojs.AudioTrack = _audioTrack2['default'];
  824. /**
  825. * export the VideoTrack class so that source handlers can create
  826. * VideoTracks and then add them to the players VideoTrackList
  827. *
  828. * @borrows VideoTrack as videojs.VideoTrack
  829. */
  830. videojs.VideoTrack = _videoTrack2['default'];
  831. /**
  832. * Determines, via duck typing, whether or not a value is a DOM element.
  833. *
  834. * @borrows dom:isEl as videojs.isEl
  835. */
  836. videojs.isEl = Dom.isEl;
  837. /**
  838. * Determines, via duck typing, whether or not a value is a text node.
  839. *
  840. * @borrows dom:isTextNode as videojs.isTextNode
  841. */
  842. videojs.isTextNode = Dom.isTextNode;
  843. /**
  844. * Creates an element and applies properties.
  845. *
  846. * @borrows dom:createEl as videojs.createEl
  847. */
  848. videojs.createEl = Dom.createEl;
  849. /**
  850. * Check if an element has a CSS class
  851. *
  852. * @borrows dom:hasElClass as videojs.hasClass
  853. */
  854. videojs.hasClass = Dom.hasElClass;
  855. /**
  856. * Add a CSS class name to an element
  857. *
  858. * @borrows dom:addElClass as videojs.addClass
  859. */
  860. videojs.addClass = Dom.addElClass;
  861. /**
  862. * Remove a CSS class name from an element
  863. *
  864. * @borrows dom:removeElClass as videojs.removeClass
  865. */
  866. videojs.removeClass = Dom.removeElClass;
  867. /**
  868. * Adds or removes a CSS class name on an element depending on an optional
  869. * condition or the presence/absence of the class name.
  870. *
  871. * @borrows dom:toggleElClass as videojs.toggleClass
  872. */
  873. videojs.toggleClass = Dom.toggleElClass;
  874. /**
  875. * Apply attributes to an HTML element.
  876. *
  877. * @borrows dom:setElAttributes as videojs.setAttribute
  878. */
  879. videojs.setAttributes = Dom.setElAttributes;
  880. /**
  881. * Get an element's attribute values, as defined on the HTML tag
  882. * Attributes are not the same as properties. They're defined on the tag
  883. * or with setAttribute (which shouldn't be used with HTML)
  884. * This will return true or false for boolean attributes.
  885. *
  886. * @borrows dom:getElAttributes as videojs.getAttributes
  887. */
  888. videojs.getAttributes = Dom.getElAttributes;
  889. /**
  890. * Empties the contents of an element.
  891. *
  892. * @borrows dom:emptyEl as videojs.emptyEl
  893. */
  894. videojs.emptyEl = Dom.emptyEl;
  895. /**
  896. * Normalizes and appends content to an element.
  897. *
  898. * The content for an element can be passed in multiple types and
  899. * combinations, whose behavior is as follows:
  900. *
  901. * - String
  902. * Normalized into a text node.
  903. *
  904. * - Element, TextNode
  905. * Passed through.
  906. *
  907. * - Array
  908. * A one-dimensional array of strings, elements, nodes, or functions (which
  909. * return single strings, elements, or nodes).
  910. *
  911. * - Function
  912. * If the sole argument, is expected to produce a string, element,
  913. * node, or array.
  914. *
  915. * @borrows dom:appendContents as videojs.appendContet
  916. */
  917. videojs.appendContent = Dom.appendContent;
  918. /**
  919. * Normalizes and inserts content into an element; this is identical to
  920. * `appendContent()`, except it empties the element first.
  921. *
  922. * The content for an element can be passed in multiple types and
  923. * combinations, whose behavior is as follows:
  924. *
  925. * - String
  926. * Normalized into a text node.
  927. *
  928. * - Element, TextNode
  929. * Passed through.
  930. *
  931. * - Array
  932. * A one-dimensional array of strings, elements, nodes, or functions (which
  933. * return single strings, elements, or nodes).
  934. *
  935. * - Function
  936. * If the sole argument, is expected to produce a string, element,
  937. * node, or array.
  938. *
  939. * @borrows dom:insertContent as videojs.insertContent
  940. */
  941. videojs.insertContent = Dom.insertContent;
  942. /**
  943. * A safe getComputedStyle with an IE8 fallback.
  944. *
  945. * This is because in Firefox, if the player is loaded in an iframe with `display:none`,
  946. * then `getComputedStyle` returns `null`, so, we do a null-check to make sure
  947. * that the player doesn't break in these cases.
  948. * See https://bugzilla.mozilla.org/show_bug.cgi?id=548397 for more details.
  949. *
  950. * @borrows computed-style:computedStyle as videojs.computedStyle
  951. */
  952. videojs.computedStyle = _computedStyle2['default'];
  953. /*
  954. * Custom Universal Module Definition (UMD)
  955. *
  956. * Video.js will never be a non-browser lib so we can simplify UMD a bunch and
  957. * still support requirejs and browserify. This also needs to be closure
  958. * compiler compatible, so string keys are used.
  959. */
  960. if (true) {
  961. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function () {
  962. return videojs;
  963. }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  964. // checking that module is an object too because of umdjs/umd#35
  965. } else if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object' && (typeof module === 'undefined' ? 'undefined' : _typeof(module)) === 'object') {
  966. module.exports = videojs;
  967. }
  968. exports['default'] = videojs;
  969. /***/ }),
  970. /* 7 */
  971. /***/ (function(module, exports) {
  972. /* WEBPACK VAR INJECTION */(function(global) {if (typeof window !== "undefined") {
  973. module.exports = window;
  974. } else if (typeof global !== "undefined") {
  975. module.exports = global;
  976. } else if (typeof self !== "undefined"){
  977. module.exports = self;
  978. } else {
  979. module.exports = {};
  980. }
  981. /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  982. /***/ }),
  983. /* 8 */
  984. /***/ (function(module, exports, __webpack_require__) {
  985. /* WEBPACK VAR INJECTION */(function(global) {var topLevel = typeof global !== 'undefined' ? global :
  986. typeof window !== 'undefined' ? window : {}
  987. var minDoc = __webpack_require__(9);
  988. if (typeof document !== 'undefined') {
  989. module.exports = document;
  990. } else {
  991. var doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
  992. if (!doccy) {
  993. doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
  994. }
  995. module.exports = doccy;
  996. }
  997. /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  998. /***/ }),
  999. /* 9 */
  1000. /***/ (function(module, exports) {
  1001. /* (ignored) */
  1002. /***/ }),
  1003. /* 10 */
  1004. /***/ (function(module, exports, __webpack_require__) {
  1005. 'use strict';
  1006. exports.__esModule = true;
  1007. exports.BACKGROUND_SIZE_SUPPORTED = exports.TOUCH_ENABLED = exports.IS_ANY_SAFARI = exports.IS_SAFARI = exports.IE_VERSION = exports.IS_IE8 = exports.CHROME_VERSION = exports.IS_CHROME = exports.IS_EDGE = exports.IS_FIREFOX = exports.IS_NATIVE_ANDROID = exports.IS_OLD_ANDROID = exports.ANDROID_VERSION = exports.IS_ANDROID = exports.IOS_VERSION = exports.IS_IOS = exports.IS_IPOD = exports.IS_IPHONE = exports.IS_IPAD = undefined;
  1008. var _dom = __webpack_require__(11);
  1009. var Dom = _interopRequireWildcard(_dom);
  1010. var _window = __webpack_require__(7);
  1011. var _window2 = _interopRequireDefault(_window);
  1012. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  1013. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  1014. /**
  1015. * @file browser.js
  1016. * @module browser
  1017. */
  1018. var USER_AGENT = _window2['default'].navigator && _window2['default'].navigator.userAgent || '';
  1019. var webkitVersionMap = /AppleWebKit\/([\d.]+)/i.exec(USER_AGENT);
  1020. var appleWebkitVersion = webkitVersionMap ? parseFloat(webkitVersionMap.pop()) : null;
  1021. /*
  1022. * Device is an iPhone
  1023. *
  1024. * @type {Boolean}
  1025. * @constant
  1026. * @private
  1027. */
  1028. var IS_IPAD = exports.IS_IPAD = /iPad/i.test(USER_AGENT);
  1029. // The Facebook app's UIWebView identifies as both an iPhone and iPad, so
  1030. // to identify iPhones, we need to exclude iPads.
  1031. // http://artsy.github.io/blog/2012/10/18/the-perils-of-ios-user-agent-sniffing/
  1032. var IS_IPHONE = exports.IS_IPHONE = /iPhone/i.test(USER_AGENT) && !IS_IPAD;
  1033. var IS_IPOD = exports.IS_IPOD = /iPod/i.test(USER_AGENT);
  1034. var IS_IOS = exports.IS_IOS = IS_IPHONE || IS_IPAD || IS_IPOD;
  1035. var IOS_VERSION = exports.IOS_VERSION = function () {
  1036. var match = USER_AGENT.match(/OS (\d+)_/i);
  1037. if (match && match[1]) {
  1038. return match[1];
  1039. }
  1040. return null;
  1041. }();
  1042. var IS_ANDROID = exports.IS_ANDROID = /Android/i.test(USER_AGENT);
  1043. var ANDROID_VERSION = exports.ANDROID_VERSION = function () {
  1044. // This matches Android Major.Minor.Patch versions
  1045. // ANDROID_VERSION is Major.Minor as a Number, if Minor isn't available, then only Major is returned
  1046. var match = USER_AGENT.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i);
  1047. if (!match) {
  1048. return null;
  1049. }
  1050. var major = match[1] && parseFloat(match[1]);
  1051. var minor = match[2] && parseFloat(match[2]);
  1052. if (major && minor) {
  1053. return parseFloat(match[1] + '.' + match[2]);
  1054. } else if (major) {
  1055. return major;
  1056. }
  1057. return null;
  1058. }();
  1059. // Old Android is defined as Version older than 2.3, and requiring a webkit version of the android browser
  1060. var IS_OLD_ANDROID = exports.IS_OLD_ANDROID = IS_ANDROID && /webkit/i.test(USER_AGENT) && ANDROID_VERSION < 2.3;
  1061. var IS_NATIVE_ANDROID = exports.IS_NATIVE_ANDROID = IS_ANDROID && ANDROID_VERSION < 5 && appleWebkitVersion < 537;
  1062. var IS_FIREFOX = exports.IS_FIREFOX = /Firefox/i.test(USER_AGENT);
  1063. var IS_EDGE = exports.IS_EDGE = /Edge/i.test(USER_AGENT);
  1064. var IS_CHROME = exports.IS_CHROME = !IS_EDGE && /Chrome/i.test(USER_AGENT);
  1065. var CHROME_VERSION = exports.CHROME_VERSION = function () {
  1066. var match = USER_AGENT.match(/Chrome\/(\d+)/);
  1067. if (match && match[1]) {
  1068. return parseFloat(match[1]);
  1069. }
  1070. return null;
  1071. }();
  1072. var IS_IE8 = exports.IS_IE8 = /MSIE\s8\.0/.test(USER_AGENT);
  1073. var IE_VERSION = exports.IE_VERSION = function () {
  1074. var result = /MSIE\s(\d+)\.\d/.exec(USER_AGENT);
  1075. var version = result && parseFloat(result[1]);
  1076. if (!version && /Trident\/7.0/i.test(USER_AGENT) && /rv:11.0/.test(USER_AGENT)) {
  1077. // IE 11 has a different user agent string than other IE versions
  1078. version = 11.0;
  1079. }
  1080. return version;
  1081. }();
  1082. var IS_SAFARI = exports.IS_SAFARI = /Safari/i.test(USER_AGENT) && !IS_CHROME && !IS_ANDROID && !IS_EDGE;
  1083. var IS_ANY_SAFARI = exports.IS_ANY_SAFARI = IS_SAFARI || IS_IOS;
  1084. var TOUCH_ENABLED = exports.TOUCH_ENABLED = Dom.isReal() && ('ontouchstart' in _window2['default'] || _window2['default'].DocumentTouch && _window2['default'].document instanceof _window2['default'].DocumentTouch);
  1085. var BACKGROUND_SIZE_SUPPORTED = exports.BACKGROUND_SIZE_SUPPORTED = Dom.isReal() && 'backgroundSize' in _window2['default'].document.createElement('video').style;
  1086. /***/ }),
  1087. /* 11 */
  1088. /***/ (function(module, exports, __webpack_require__) {
  1089. 'use strict';
  1090. exports.__esModule = true;
  1091. exports.$$ = exports.$ = undefined;
  1092. var _templateObject = _taggedTemplateLiteralLoose(['Setting attributes in the second argument of createEl()\n has been deprecated. Use the third argument instead.\n createEl(type, properties, attributes). Attempting to set ', ' to ', '.'], ['Setting attributes in the second argument of createEl()\n has been deprecated. Use the third argument instead.\n createEl(type, properties, attributes). Attempting to set ', ' to ', '.']);
  1093. exports.isReal = isReal;
  1094. exports.isEl = isEl;
  1095. exports.getEl = getEl;
  1096. exports.createEl = createEl;
  1097. exports.textContent = textContent;
  1098. exports.insertElFirst = insertElFirst;
  1099. exports.getElData = getElData;
  1100. exports.hasElData = hasElData;
  1101. exports.removeElData = removeElData;
  1102. exports.hasElClass = hasElClass;
  1103. exports.addElClass = addElClass;
  1104. exports.removeElClass = removeElClass;
  1105. exports.toggleElClass = toggleElClass;
  1106. exports.setElAttributes = setElAttributes;
  1107. exports.getElAttributes = getElAttributes;
  1108. exports.getAttribute = getAttribute;
  1109. exports.setAttribute = setAttribute;
  1110. exports.removeAttribute = removeAttribute;
  1111. exports.blockTextSelection = blockTextSelection;
  1112. exports.unblockTextSelection = unblockTextSelection;
  1113. exports.findElPosition = findElPosition;
  1114. exports.getPointerPosition = getPointerPosition;
  1115. exports.isTextNode = isTextNode;
  1116. exports.emptyEl = emptyEl;
  1117. exports.normalizeContent = normalizeContent;
  1118. exports.appendContent = appendContent;
  1119. exports.insertContent = insertContent;
  1120. var _document = __webpack_require__(8);
  1121. var _document2 = _interopRequireDefault(_document);
  1122. var _window = __webpack_require__(7);
  1123. var _window2 = _interopRequireDefault(_window);
  1124. var _guid = __webpack_require__(12);
  1125. var Guid = _interopRequireWildcard(_guid);
  1126. var _log = __webpack_require__(13);
  1127. var _log2 = _interopRequireDefault(_log);
  1128. var _tsml = __webpack_require__(15);
  1129. var _tsml2 = _interopRequireDefault(_tsml);
  1130. var _obj = __webpack_require__(14);
  1131. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  1132. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  1133. function _taggedTemplateLiteralLoose(strings, raw) { strings.raw = raw; return strings; } /**
  1134. * @file dom.js
  1135. * @module dom
  1136. */
  1137. /**
  1138. * Detect if a value is a string with any non-whitespace characters.
  1139. *
  1140. * @param {string} str
  1141. * The string to check
  1142. *
  1143. * @return {boolean}
  1144. * - True if the string is non-blank
  1145. * - False otherwise
  1146. *
  1147. */
  1148. function isNonBlankString(str) {
  1149. return typeof str === 'string' && /\S/.test(str);
  1150. }
  1151. /**
  1152. * Throws an error if the passed string has whitespace. This is used by
  1153. * class methods to be relatively consistent with the classList API.
  1154. *
  1155. * @param {string} str
  1156. * The string to check for whitespace.
  1157. *
  1158. * @throws {Error}
  1159. * Throws an error if there is whitespace in the string.
  1160. *
  1161. */
  1162. function throwIfWhitespace(str) {
  1163. if (/\s/.test(str)) {
  1164. throw new Error('class has illegal whitespace characters');
  1165. }
  1166. }
  1167. /**
  1168. * Produce a regular expression for matching a className within an elements className.
  1169. *
  1170. * @param {string} className
  1171. * The className to generate the RegExp for.
  1172. *
  1173. * @return {RegExp}
  1174. * The RegExp that will check for a specific `className` in an elements
  1175. * className.
  1176. */
  1177. function classRegExp(className) {
  1178. return new RegExp('(^|\\s)' + className + '($|\\s)');
  1179. }
  1180. /**
  1181. * Whether the current DOM interface appears to be real.
  1182. *
  1183. * @return {Boolean}
  1184. */
  1185. function isReal() {
  1186. return (
  1187. // Both document and window will never be undefined thanks to `global`.
  1188. _document2['default'] === _window2['default'].document &&
  1189. // In IE < 9, DOM methods return "object" as their type, so all we can
  1190. // confidently check is that it exists.
  1191. typeof _document2['default'].createElement !== 'undefined'
  1192. );
  1193. }
  1194. /**
  1195. * Determines, via duck typing, whether or not a value is a DOM element.
  1196. *
  1197. * @param {Mixed} value
  1198. * The thing to check
  1199. *
  1200. * @return {boolean}
  1201. * - True if it is a DOM element
  1202. * - False otherwise
  1203. */
  1204. function isEl(value) {
  1205. return (0, _obj.isObject)(value) && value.nodeType === 1;
  1206. }
  1207. /**
  1208. * Creates functions to query the DOM using a given method.
  1209. *
  1210. * @param {string} method
  1211. * The method to create the query with.
  1212. *
  1213. * @return {Function}
  1214. * The query method
  1215. */
  1216. function createQuerier(method) {
  1217. return function (selector, context) {
  1218. if (!isNonBlankString(selector)) {
  1219. return _document2['default'][method](null);
  1220. }
  1221. if (isNonBlankString(context)) {
  1222. context = _document2['default'].querySelector(context);
  1223. }
  1224. var ctx = isEl(context) ? context : _document2['default'];
  1225. return ctx[method] && ctx[method](selector);
  1226. };
  1227. }
  1228. /**
  1229. * Shorthand for document.getElementById()
  1230. * Also allows for CSS (jQuery) ID syntax. But nothing other than IDs.
  1231. *
  1232. * @param {string} id
  1233. * The id of the element to get
  1234. *
  1235. * @return {Element|null}
  1236. * Element with supplied ID or null if there wasn't one.
  1237. */
  1238. function getEl(id) {
  1239. if (id.indexOf('#') === 0) {
  1240. id = id.slice(1);
  1241. }
  1242. return _document2['default'].getElementById(id);
  1243. }
  1244. /**
  1245. * Creates an element and applies properties.
  1246. *
  1247. * @param {string} [tagName='div']
  1248. * Name of tag to be created.
  1249. *
  1250. * @param {Object} [properties={}]
  1251. * Element properties to be applied.
  1252. *
  1253. * @param {Object} [attributes={}]
  1254. * Element attributes to be applied.
  1255. *
  1256. * @param {String|Element|TextNode|Array|Function} [content]
  1257. * Contents for the element (see: {@link dom:normalizeContent})
  1258. *
  1259. * @return {Element}
  1260. * The element that was created.
  1261. */
  1262. function createEl() {
  1263. var tagName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'div';
  1264. var properties = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  1265. var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  1266. var content = arguments[3];
  1267. var el = _document2['default'].createElement(tagName);
  1268. Object.getOwnPropertyNames(properties).forEach(function (propName) {
  1269. var val = properties[propName];
  1270. // See #2176
  1271. // We originally were accepting both properties and attributes in the
  1272. // same object, but that doesn't work so well.
  1273. if (propName.indexOf('aria-') !== -1 || propName === 'role' || propName === 'type') {
  1274. _log2['default'].warn((0, _tsml2['default'])(_templateObject, propName, val));
  1275. el.setAttribute(propName, val);
  1276. // Handle textContent since it's not supported everywhere and we have a
  1277. // method for it.
  1278. } else if (propName === 'textContent') {
  1279. textContent(el, val);
  1280. } else {
  1281. el[propName] = val;
  1282. }
  1283. });
  1284. Object.getOwnPropertyNames(attributes).forEach(function (attrName) {
  1285. el.setAttribute(attrName, attributes[attrName]);
  1286. });
  1287. if (content) {
  1288. appendContent(el, content);
  1289. }
  1290. return el;
  1291. }
  1292. /**
  1293. * Injects text into an element, replacing any existing contents entirely.
  1294. *
  1295. * @param {Element} el
  1296. * The element to add text content into
  1297. *
  1298. * @param {string} text
  1299. * The text content to add.
  1300. *
  1301. * @return {Element}
  1302. * The element with added text content.
  1303. */
  1304. function textContent(el, text) {
  1305. if (typeof el.textContent === 'undefined') {
  1306. el.innerText = text;
  1307. } else {
  1308. el.textContent = text;
  1309. }
  1310. return el;
  1311. }
  1312. /**
  1313. * Insert an element as the first child node of another
  1314. *
  1315. * @param {Element} child
  1316. * Element to insert
  1317. *
  1318. * @param {Element} parent
  1319. * Element to insert child into
  1320. *
  1321. */
  1322. function insertElFirst(child, parent) {
  1323. if (parent.firstChild) {
  1324. parent.insertBefore(child, parent.firstChild);
  1325. } else {
  1326. parent.appendChild(child);
  1327. }
  1328. }
  1329. /**
  1330. * Element Data Store. Allows for binding data to an element without putting it directly on the element.
  1331. * Ex. Event listeners are stored here.
  1332. * (also from jsninja.com, slightly modified and updated for closure compiler)
  1333. *
  1334. * @type {Object}
  1335. * @private
  1336. */
  1337. var elData = {};
  1338. /*
  1339. * Unique attribute name to store an element's guid in
  1340. *
  1341. * @type {string}
  1342. * @constant
  1343. * @private
  1344. */
  1345. var elIdAttr = 'vdata' + new Date().getTime();
  1346. /**
  1347. * Returns the cache object where data for an element is stored
  1348. *
  1349. * @param {Element} el
  1350. * Element to store data for.
  1351. *
  1352. * @return {Object}
  1353. * The cache object for that el that was passed in.
  1354. */
  1355. function getElData(el) {
  1356. var id = el[elIdAttr];
  1357. if (!id) {
  1358. id = el[elIdAttr] = Guid.newGUID();
  1359. }
  1360. if (!elData[id]) {
  1361. elData[id] = {};
  1362. }
  1363. return elData[id];
  1364. }
  1365. /**
  1366. * Returns whether or not an element has cached data
  1367. *
  1368. * @param {Element} el
  1369. * Check if this element has cached data.
  1370. *
  1371. * @return {boolean}
  1372. * - True if the DOM element has cached data.
  1373. * - False otherwise.
  1374. */
  1375. function hasElData(el) {
  1376. var id = el[elIdAttr];
  1377. if (!id) {
  1378. return false;
  1379. }
  1380. return !!Object.getOwnPropertyNames(elData[id]).length;
  1381. }
  1382. /**
  1383. * Delete data for the element from the cache and the guid attr from getElementById
  1384. *
  1385. * @param {Element} el
  1386. * Remove cached data for this element.
  1387. */
  1388. function removeElData(el) {
  1389. var id = el[elIdAttr];
  1390. if (!id) {
  1391. return;
  1392. }
  1393. // Remove all stored data
  1394. delete elData[id];
  1395. // Remove the elIdAttr property from the DOM node
  1396. try {
  1397. delete el[elIdAttr];
  1398. } catch (e) {
  1399. if (el.removeAttribute) {
  1400. el.removeAttribute(elIdAttr);
  1401. } else {
  1402. // IE doesn't appear to support removeAttribute on the document element
  1403. el[elIdAttr] = null;
  1404. }
  1405. }
  1406. }
  1407. /**
  1408. * Check if an element has a CSS class
  1409. *
  1410. * @param {Element} element
  1411. * Element to check
  1412. *
  1413. * @param {string} classToCheck
  1414. * Class name to check for
  1415. *
  1416. * @return {boolean}
  1417. * - True if the element had the class
  1418. * - False otherwise.
  1419. *
  1420. * @throws {Error}
  1421. * Throws an error if `classToCheck` has white space.
  1422. */
  1423. function hasElClass(element, classToCheck) {
  1424. throwIfWhitespace(classToCheck);
  1425. if (element.classList) {
  1426. return element.classList.contains(classToCheck);
  1427. }
  1428. return classRegExp(classToCheck).test(element.className);
  1429. }
  1430. /**
  1431. * Add a CSS class name to an element
  1432. *
  1433. * @param {Element} element
  1434. * Element to add class name to.
  1435. *
  1436. * @param {string} classToAdd
  1437. * Class name to add.
  1438. *
  1439. * @return {Element}
  1440. * The dom element with the added class name.
  1441. */
  1442. function addElClass(element, classToAdd) {
  1443. if (element.classList) {
  1444. element.classList.add(classToAdd);
  1445. // Don't need to `throwIfWhitespace` here because `hasElClass` will do it
  1446. // in the case of classList not being supported.
  1447. } else if (!hasElClass(element, classToAdd)) {
  1448. element.className = (element.className + ' ' + classToAdd).trim();
  1449. }
  1450. return element;
  1451. }
  1452. /**
  1453. * Remove a CSS class name from an element
  1454. *
  1455. * @param {Element} element
  1456. * Element to remove a class name from.
  1457. *
  1458. * @param {string} classToRemove
  1459. * Class name to remove
  1460. *
  1461. * @return {Element}
  1462. * The dom element with class name removed.
  1463. */
  1464. function removeElClass(element, classToRemove) {
  1465. if (element.classList) {
  1466. element.classList.remove(classToRemove);
  1467. } else {
  1468. throwIfWhitespace(classToRemove);
  1469. element.className = element.className.split(/\s+/).filter(function (c) {
  1470. return c !== classToRemove;
  1471. }).join(' ');
  1472. }
  1473. return element;
  1474. }
  1475. /**
  1476. * The callback definition for toggleElClass.
  1477. *
  1478. * @callback Dom~PredicateCallback
  1479. * @param {Element} element
  1480. * The DOM element of the Component.
  1481. *
  1482. * @param {string} classToToggle
  1483. * The `className` that wants to be toggled
  1484. *
  1485. * @return {boolean|undefined}
  1486. * - If true the `classToToggle` will get added to `element`.
  1487. * - If false the `classToToggle` will get removed from `element`.
  1488. * - If undefined this callback will be ignored
  1489. */
  1490. /**
  1491. * Adds or removes a CSS class name on an element depending on an optional
  1492. * condition or the presence/absence of the class name.
  1493. *
  1494. * @param {Element} element
  1495. * The element to toggle a class name on.
  1496. *
  1497. * @param {string} classToToggle
  1498. * The class that should be toggled
  1499. *
  1500. * @param {boolean|PredicateCallback} [predicate]
  1501. * See the return value for {@link Dom~PredicateCallback}
  1502. *
  1503. * @return {Element}
  1504. * The element with a class that has been toggled.
  1505. */
  1506. function toggleElClass(element, classToToggle, predicate) {
  1507. // This CANNOT use `classList` internally because IE does not support the
  1508. // second parameter to the `classList.toggle()` method! Which is fine because
  1509. // `classList` will be used by the add/remove functions.
  1510. var has = hasElClass(element, classToToggle);
  1511. if (typeof predicate === 'function') {
  1512. predicate = predicate(element, classToToggle);
  1513. }
  1514. if (typeof predicate !== 'boolean') {
  1515. predicate = !has;
  1516. }
  1517. // If the necessary class operation matches the current state of the
  1518. // element, no action is required.
  1519. if (predicate === has) {
  1520. return;
  1521. }
  1522. if (predicate) {
  1523. addElClass(element, classToToggle);
  1524. } else {
  1525. removeElClass(element, classToToggle);
  1526. }
  1527. return element;
  1528. }
  1529. /**
  1530. * Apply attributes to an HTML element.
  1531. *
  1532. * @param {Element} el
  1533. * Element to add attributes to.
  1534. *
  1535. * @param {Object} [attributes]
  1536. * Attributes to be applied.
  1537. */
  1538. function setElAttributes(el, attributes) {
  1539. Object.getOwnPropertyNames(attributes).forEach(function (attrName) {
  1540. var attrValue = attributes[attrName];
  1541. if (attrValue === null || typeof attrValue === 'undefined' || attrValue === false) {
  1542. el.removeAttribute(attrName);
  1543. } else {
  1544. el.setAttribute(attrName, attrValue === true ? '' : attrValue);
  1545. }
  1546. });
  1547. }
  1548. /**
  1549. * Get an element's attribute values, as defined on the HTML tag
  1550. * Attributes are not the same as properties. They're defined on the tag
  1551. * or with setAttribute (which shouldn't be used with HTML)
  1552. * This will return true or false for boolean attributes.
  1553. *
  1554. * @param {Element} tag
  1555. * Element from which to get tag attributes.
  1556. *
  1557. * @return {Object}
  1558. * All attributes of the element.
  1559. */
  1560. function getElAttributes(tag) {
  1561. var obj = {};
  1562. // known boolean attributes
  1563. // we can check for matching boolean properties, but older browsers
  1564. // won't know about HTML5 boolean attributes that we still read from
  1565. var knownBooleans = ',' + 'autoplay,controls,loop,muted,default' + ',';
  1566. if (tag && tag.attributes && tag.attributes.length > 0) {
  1567. var attrs = tag.attributes;
  1568. for (var i = attrs.length - 1; i >= 0; i--) {
  1569. var attrName = attrs[i].name;
  1570. var attrVal = attrs[i].value;
  1571. // check for known booleans
  1572. // the matching element property will return a value for typeof
  1573. if (typeof tag[attrName] === 'boolean' || knownBooleans.indexOf(',' + attrName + ',') !== -1) {
  1574. // the value of an included boolean attribute is typically an empty
  1575. // string ('') which would equal false if we just check for a false value.
  1576. // we also don't want support bad code like autoplay='false'
  1577. attrVal = attrVal !== null ? true : false;
  1578. }
  1579. obj[attrName] = attrVal;
  1580. }
  1581. }
  1582. return obj;
  1583. }
  1584. /**
  1585. * Get the value of an element's attribute
  1586. *
  1587. * @param {Element} el
  1588. * A DOM element
  1589. *
  1590. * @param {string} attribute
  1591. * Attribute to get the value of
  1592. *
  1593. * @return {string}
  1594. * value of the attribute
  1595. */
  1596. function getAttribute(el, attribute) {
  1597. return el.getAttribute(attribute);
  1598. }
  1599. /**
  1600. * Set the value of an element's attribute
  1601. *
  1602. * @param {Element} el
  1603. * A DOM element
  1604. *
  1605. * @param {string} attribute
  1606. * Attribute to set
  1607. *
  1608. * @param {string} value
  1609. * Value to set the attribute to
  1610. */
  1611. function setAttribute(el, attribute, value) {
  1612. el.setAttribute(attribute, value);
  1613. }
  1614. /**
  1615. * Remove an element's attribute
  1616. *
  1617. * @param {Element} el
  1618. * A DOM element
  1619. *
  1620. * @param {string} attribute
  1621. * Attribute to remove
  1622. */
  1623. function removeAttribute(el, attribute) {
  1624. el.removeAttribute(attribute);
  1625. }
  1626. /**
  1627. * Attempt to block the ability to select text while dragging controls
  1628. */
  1629. function blockTextSelection() {
  1630. _document2['default'].body.focus();
  1631. _document2['default'].onselectstart = function () {
  1632. return false;
  1633. };
  1634. }
  1635. /**
  1636. * Turn off text selection blocking
  1637. */
  1638. function unblockTextSelection() {
  1639. _document2['default'].onselectstart = function () {
  1640. return true;
  1641. };
  1642. }
  1643. /**
  1644. * The postion of a DOM element on the page.
  1645. *
  1646. * @typedef {Object} Dom~Position
  1647. *
  1648. * @property {number} left
  1649. * Pixels to the left
  1650. *
  1651. * @property {number} top
  1652. * Pixels on top
  1653. */
  1654. /**
  1655. * Offset Left.
  1656. * getBoundingClientRect technique from
  1657. * John Resig
  1658. *
  1659. * @see http://ejohn.org/blog/getboundingclientrect-is-awesome/
  1660. *
  1661. * @param {Element} el
  1662. * Element from which to get offset
  1663. *
  1664. * @return {Dom~Position}
  1665. * The position of the element that was passed in.
  1666. */
  1667. function findElPosition(el) {
  1668. var box = void 0;
  1669. if (el.getBoundingClientRect && el.parentNode) {
  1670. box = el.getBoundingClientRect();
  1671. }
  1672. if (!box) {
  1673. return {
  1674. left: 0,
  1675. top: 0
  1676. };
  1677. }
  1678. var docEl = _document2['default'].documentElement;
  1679. var body = _document2['default'].body;
  1680. var clientLeft = docEl.clientLeft || body.clientLeft || 0;
  1681. var scrollLeft = _window2['default'].pageXOffset || body.scrollLeft;
  1682. var left = box.left + scrollLeft - clientLeft;
  1683. var clientTop = docEl.clientTop || body.clientTop || 0;
  1684. var scrollTop = _window2['default'].pageYOffset || body.scrollTop;
  1685. var top = box.top + scrollTop - clientTop;
  1686. // Android sometimes returns slightly off decimal values, so need to round
  1687. return {
  1688. left: Math.round(left),
  1689. top: Math.round(top)
  1690. };
  1691. }
  1692. /**
  1693. * x and y coordinates for a dom element or mouse pointer
  1694. *
  1695. * @typedef {Object} Dom~Coordinates
  1696. *
  1697. * @property {number} x
  1698. * x coordinate in pixels
  1699. *
  1700. * @property {number} y
  1701. * y coordinate in pixels
  1702. */
  1703. /**
  1704. * Get pointer position in element
  1705. * Returns an object with x and y coordinates.
  1706. * The base on the coordinates are the bottom left of the element.
  1707. *
  1708. * @param {Element} el
  1709. * Element on which to get the pointer position on
  1710. *
  1711. * @param {EventTarget~Event} event
  1712. * Event object
  1713. *
  1714. * @return {Dom~Coordinates}
  1715. * A Coordinates object corresponding to the mouse position.
  1716. *
  1717. */
  1718. function getPointerPosition(el, event) {
  1719. var position = {};
  1720. var box = findElPosition(el);
  1721. var boxW = el.offsetWidth;
  1722. var boxH = el.offsetHeight;
  1723. var boxY = box.top;
  1724. var boxX = box.left;
  1725. var pageY = event.pageY;
  1726. var pageX = event.pageX;
  1727. if (event.changedTouches) {
  1728. pageX = event.changedTouches[0].pageX;
  1729. pageY = event.changedTouches[0].pageY;
  1730. }
  1731. position.y = Math.max(0, Math.min(1, (boxY - pageY + boxH) / boxH));
  1732. position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW));
  1733. return position;
  1734. }
  1735. /**
  1736. * Determines, via duck typing, whether or not a value is a text node.
  1737. *
  1738. * @param {Mixed} value
  1739. * Check if this value is a text node.
  1740. *
  1741. * @return {boolean}
  1742. * - True if it is a text node
  1743. * - False otherwise
  1744. */
  1745. function isTextNode(value) {
  1746. return (0, _obj.isObject)(value) && value.nodeType === 3;
  1747. }
  1748. /**
  1749. * Empties the contents of an element.
  1750. *
  1751. * @param {Element} el
  1752. * The element to empty children from
  1753. *
  1754. * @return {Element}
  1755. * The element with no children
  1756. */
  1757. function emptyEl(el) {
  1758. while (el.firstChild) {
  1759. el.removeChild(el.firstChild);
  1760. }
  1761. return el;
  1762. }
  1763. /**
  1764. * Normalizes content for eventual insertion into the DOM.
  1765. *
  1766. * This allows a wide range of content definition methods, but protects
  1767. * from falling into the trap of simply writing to `innerHTML`, which is
  1768. * an XSS concern.
  1769. *
  1770. * The content for an element can be passed in multiple types and
  1771. * combinations, whose behavior is as follows:
  1772. *
  1773. * @param {String|Element|TextNode|Array|Function} content
  1774. * - String: Normalized into a text node.
  1775. * - Element/TextNode: Passed through.
  1776. * - Array: A one-dimensional array of strings, elements, nodes, or functions
  1777. * (which return single strings, elements, or nodes).
  1778. * - Function: If the sole argument, is expected to produce a string, element,
  1779. * node, or array as defined above.
  1780. *
  1781. * @return {Array}
  1782. * All of the content that was passed in normalized.
  1783. */
  1784. function normalizeContent(content) {
  1785. // First, invoke content if it is a function. If it produces an array,
  1786. // that needs to happen before normalization.
  1787. if (typeof content === 'function') {
  1788. content = content();
  1789. }
  1790. // Next up, normalize to an array, so one or many items can be normalized,
  1791. // filtered, and returned.
  1792. return (Array.isArray(content) ? content : [content]).map(function (value) {
  1793. // First, invoke value if it is a function to produce a new value,
  1794. // which will be subsequently normalized to a Node of some kind.
  1795. if (typeof value === 'function') {
  1796. value = value();
  1797. }
  1798. if (isEl(value) || isTextNode(value)) {
  1799. return value;
  1800. }
  1801. if (typeof value === 'string' && /\S/.test(value)) {
  1802. return _document2['default'].createTextNode(value);
  1803. }
  1804. }).filter(function (value) {
  1805. return value;
  1806. });
  1807. }
  1808. /**
  1809. * Normalizes and appends content to an element.
  1810. *
  1811. * @param {Element} el
  1812. * Element to append normalized content to.
  1813. *
  1814. *
  1815. * @param {String|Element|TextNode|Array|Function} content
  1816. * See the `content` argument of {@link dom:normalizeContent}
  1817. *
  1818. * @return {Element}
  1819. * The element with appended normalized content.
  1820. */
  1821. function appendContent(el, content) {
  1822. normalizeContent(content).forEach(function (node) {
  1823. return el.appendChild(node);
  1824. });
  1825. return el;
  1826. }
  1827. /**
  1828. * Normalizes and inserts content into an element; this is identical to
  1829. * `appendContent()`, except it empties the element first.
  1830. *
  1831. * @param {Element} el
  1832. * Element to insert normalized content into.
  1833. *
  1834. * @param {String|Element|TextNode|Array|Function} content
  1835. * See the `content` argument of {@link dom:normalizeContent}
  1836. *
  1837. * @return {Element}
  1838. * The element with inserted normalized content.
  1839. *
  1840. */
  1841. function insertContent(el, content) {
  1842. return appendContent(emptyEl(el), content);
  1843. }
  1844. /**
  1845. * Finds a single DOM element matching `selector` within the optional
  1846. * `context` of another DOM element (defaulting to `document`).
  1847. *
  1848. * @param {string} selector
  1849. * A valid CSS selector, which will be passed to `querySelector`.
  1850. *
  1851. * @param {Element|String} [context=document]
  1852. * A DOM element within which to query. Can also be a selector
  1853. * string in which case the first matching element will be used
  1854. * as context. If missing (or no element matches selector), falls
  1855. * back to `document`.
  1856. *
  1857. * @return {Element|null}
  1858. * The element that was found or null.
  1859. */
  1860. var $ = exports.$ = createQuerier('querySelector');
  1861. /**
  1862. * Finds a all DOM elements matching `selector` within the optional
  1863. * `context` of another DOM element (defaulting to `document`).
  1864. *
  1865. * @param {string} selector
  1866. * A valid CSS selector, which will be passed to `querySelectorAll`.
  1867. *
  1868. * @param {Element|String} [context=document]
  1869. * A DOM element within which to query. Can also be a selector
  1870. * string in which case the first matching element will be used
  1871. * as context. If missing (or no element matches selector), falls
  1872. * back to `document`.
  1873. *
  1874. * @return {NodeList}
  1875. * A element list of elements that were found. Will be empty if none were found.
  1876. *
  1877. */
  1878. var $$ = exports.$$ = createQuerier('querySelectorAll');
  1879. /***/ }),
  1880. /* 12 */
  1881. /***/ (function(module, exports) {
  1882. "use strict";
  1883. exports.__esModule = true;
  1884. exports.newGUID = newGUID;
  1885. /**
  1886. * @file guid.js
  1887. * @module guid
  1888. */
  1889. /**
  1890. * Unique ID for an element or function
  1891. * @type {Number}
  1892. */
  1893. var _guid = 1;
  1894. /**
  1895. * Get a unique auto-incrementing ID by number that has not been returned before.
  1896. *
  1897. * @return {number}
  1898. * A new unique ID.
  1899. */
  1900. function newGUID() {
  1901. return _guid++;
  1902. }
  1903. /***/ }),
  1904. /* 13 */
  1905. /***/ (function(module, exports, __webpack_require__) {
  1906. 'use strict';
  1907. exports.__esModule = true;
  1908. exports.logByType = undefined;
  1909. var _window = __webpack_require__(7);
  1910. var _window2 = _interopRequireDefault(_window);
  1911. var _browser = __webpack_require__(10);
  1912. var _obj = __webpack_require__(14);
  1913. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  1914. var log = void 0;
  1915. /**
  1916. * Log messages to the console and history based on the type of message
  1917. *
  1918. * @param {string} type
  1919. * The name of the console method to use.
  1920. *
  1921. * @param {Array} args
  1922. * The arguments to be passed to the matching console method.
  1923. *
  1924. * @param {boolean} [stringify]
  1925. * By default, only old IEs should get console argument stringification,
  1926. * but this is exposed as a parameter to facilitate testing.
  1927. */
  1928. /**
  1929. * @file log.js
  1930. * @module log
  1931. */
  1932. var logByType = exports.logByType = function logByType(type, args) {
  1933. var stringify = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : !!_browser.IE_VERSION && _browser.IE_VERSION < 11;
  1934. if (type !== 'log') {
  1935. // add the type to the front of the message when it's not "log"
  1936. args.unshift(type.toUpperCase() + ':');
  1937. }
  1938. // add to history
  1939. log.history.push(args);
  1940. // add console prefix after adding to history
  1941. args.unshift('VIDEOJS:');
  1942. // If there's no console then don't try to output messages, but they will
  1943. // still be stored in `log.history`.
  1944. //
  1945. // Was setting these once outside of this function, but containing them
  1946. // in the function makes it easier to test cases where console doesn't exist
  1947. // when the module is executed.
  1948. var fn = _window2['default'].console && _window2['default'].console[type];
  1949. // Bail out if there's no console.
  1950. if (!fn) {
  1951. return;
  1952. }
  1953. // IEs previous to 11 log objects uselessly as "[object Object]"; so, JSONify
  1954. // objects and arrays for those less-capable browsers.
  1955. if (stringify) {
  1956. args = args.map(function (a) {
  1957. if ((0, _obj.isObject)(a) || Array.isArray(a)) {
  1958. try {
  1959. return JSON.stringify(a);
  1960. } catch (x) {
  1961. return String(a);
  1962. }
  1963. }
  1964. // Cast to string before joining, so we get null and undefined explicitly
  1965. // included in output (as we would in a modern console).
  1966. return String(a);
  1967. }).join(' ');
  1968. }
  1969. // Old IE versions do not allow .apply() for console methods (they are
  1970. // reported as objects rather than functions).
  1971. if (!fn.apply) {
  1972. fn(args);
  1973. } else {
  1974. fn[Array.isArray(args) ? 'apply' : 'call'](_window2['default'].console, args);
  1975. }
  1976. };
  1977. /**
  1978. * Log plain debug messages
  1979. *
  1980. * @param {Mixed[]} args
  1981. * One or more messages or objects that should be logged.
  1982. */
  1983. log = function log() {
  1984. for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
  1985. args[_key] = arguments[_key];
  1986. }
  1987. logByType('log', args);
  1988. };
  1989. /**
  1990. * Keep a history of log messages
  1991. *
  1992. * @type {Array}
  1993. */
  1994. log.history = [];
  1995. /**
  1996. * Log error messages
  1997. *
  1998. * @param {Mixed[]} args
  1999. * One or more messages or objects that should be logged as an error
  2000. */
  2001. log.error = function () {
  2002. for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
  2003. args[_key2] = arguments[_key2];
  2004. }
  2005. return logByType('error', args);
  2006. };
  2007. /**
  2008. * Log warning messages
  2009. *
  2010. * @param {Mixed[]} args
  2011. * One or more messages or objects that should be logged as a warning.
  2012. */
  2013. log.warn = function () {
  2014. for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
  2015. args[_key3] = arguments[_key3];
  2016. }
  2017. return logByType('warn', args);
  2018. };
  2019. exports['default'] = log;
  2020. /***/ }),
  2021. /* 14 */
  2022. /***/ (function(module, exports) {
  2023. 'use strict';
  2024. exports.__esModule = true;
  2025. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  2026. exports.each = each;
  2027. exports.reduce = reduce;
  2028. exports.assign = assign;
  2029. exports.isObject = isObject;
  2030. exports.isPlain = isPlain;
  2031. /**
  2032. * @file obj.js
  2033. * @module obj
  2034. */
  2035. /**
  2036. * @callback obj:EachCallback
  2037. *
  2038. * @param {Mixed} value
  2039. * The current key for the object that is being iterated over.
  2040. *
  2041. * @param {string} key
  2042. * The current key-value for object that is being iterated over
  2043. */
  2044. /**
  2045. * @callback obj:ReduceCallback
  2046. *
  2047. * @param {Mixed} accum
  2048. * The value that is accumulating over the reduce loop.
  2049. *
  2050. * @param {Mixed} value
  2051. * The current key for the object that is being iterated over.
  2052. *
  2053. * @param {string} key
  2054. * The current key-value for object that is being iterated over
  2055. *
  2056. * @return {Mixed}
  2057. * The new accumulated value.
  2058. */
  2059. var toString = Object.prototype.toString;
  2060. /**
  2061. * Get the keys of an Object
  2062. *
  2063. * @param {Object}
  2064. * The Object to get the keys from
  2065. *
  2066. * @return {string[]}
  2067. * An array of the keys from the object. Returns an empty array if the
  2068. * object passed in was invalid or had no keys.
  2069. *
  2070. * @private
  2071. */
  2072. var keys = function keys(object) {
  2073. return isObject(object) ? Object.keys(object) : [];
  2074. };
  2075. /**
  2076. * Array-like iteration for objects.
  2077. *
  2078. * @param {Object} object
  2079. * The object to iterate over
  2080. *
  2081. * @param {obj:EachCallback} fn
  2082. * The callback function which is called for each key in the object.
  2083. */
  2084. function each(object, fn) {
  2085. keys(object).forEach(function (key) {
  2086. return fn(object[key], key);
  2087. });
  2088. }
  2089. /**
  2090. * Array-like reduce for objects.
  2091. *
  2092. * @param {Object} object
  2093. * The Object that you want to reduce.
  2094. *
  2095. * @param {Function} fn
  2096. * A callback function which is called for each key in the object. It
  2097. * receives the accumulated value and the per-iteration value and key
  2098. * as arguments.
  2099. *
  2100. * @param {Mixed} [initial = 0]
  2101. * Starting value
  2102. *
  2103. * @return {Mixed}
  2104. * The final accumulated value.
  2105. */
  2106. function reduce(object, fn) {
  2107. var initial = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
  2108. return keys(object).reduce(function (accum, key) {
  2109. return fn(accum, object[key], key);
  2110. }, initial);
  2111. }
  2112. /**
  2113. * Object.assign-style object shallow merge/extend.
  2114. *
  2115. * @param {Object} target
  2116. * @param {Object} ...sources
  2117. * @return {Object}
  2118. */
  2119. function assign(target) {
  2120. for (var _len = arguments.length, sources = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  2121. sources[_key - 1] = arguments[_key];
  2122. }
  2123. if (Object.assign) {
  2124. return Object.assign.apply(Object, [target].concat(sources));
  2125. }
  2126. sources.forEach(function (source) {
  2127. if (!source) {
  2128. return;
  2129. }
  2130. each(source, function (value, key) {
  2131. target[key] = value;
  2132. });
  2133. });
  2134. return target;
  2135. }
  2136. /**
  2137. * Returns whether a value is an object of any kind - including DOM nodes,
  2138. * arrays, regular expressions, etc. Not functions, though.
  2139. *
  2140. * This avoids the gotcha where using `typeof` on a `null` value
  2141. * results in `'object'`.
  2142. *
  2143. * @param {Object} value
  2144. * @return {Boolean}
  2145. */
  2146. function isObject(value) {
  2147. return !!value && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object';
  2148. }
  2149. /**
  2150. * Returns whether an object appears to be a "plain" object - that is, a
  2151. * direct instance of `Object`.
  2152. *
  2153. * @param {Object} value
  2154. * @return {Boolean}
  2155. */
  2156. function isPlain(value) {
  2157. return isObject(value) && toString.call(value) === '[object Object]' && value.constructor === Object;
  2158. }
  2159. /***/ }),
  2160. /* 15 */
  2161. /***/ (function(module, exports) {
  2162. function clean (s) {
  2163. return s.replace(/\n\r?\s*/g, '')
  2164. }
  2165. module.exports = function tsml (sa) {
  2166. var s = ''
  2167. , i = 0
  2168. for (; i < arguments.length; i++)
  2169. s += clean(sa[i]) + (arguments[i + 1] || '')
  2170. return s
  2171. }
  2172. /***/ }),
  2173. /* 16 */
  2174. /***/ (function(module, exports, __webpack_require__) {
  2175. 'use strict';
  2176. exports.__esModule = true;
  2177. exports.hasLoaded = exports.autoSetupTimeout = exports.autoSetup = undefined;
  2178. var _dom = __webpack_require__(11);
  2179. var Dom = _interopRequireWildcard(_dom);
  2180. var _events = __webpack_require__(17);
  2181. var Events = _interopRequireWildcard(_events);
  2182. var _document = __webpack_require__(8);
  2183. var _document2 = _interopRequireDefault(_document);
  2184. var _window = __webpack_require__(7);
  2185. var _window2 = _interopRequireDefault(_window);
  2186. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  2187. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  2188. /**
  2189. * @file setup.js - Functions for setting up a player without
  2190. * user interaction based on the data-setup `attribute` of the video tag.
  2191. *
  2192. * @module setup
  2193. */
  2194. var _windowLoaded = false;
  2195. var videojs = void 0;
  2196. /**
  2197. * Set up any tags that have a data-setup `attribute` when the player is started.
  2198. */
  2199. var autoSetup = function autoSetup() {
  2200. // Protect against breakage in non-browser environments.
  2201. if (!Dom.isReal()) {
  2202. return;
  2203. }
  2204. // One day, when we stop supporting IE8, go back to this, but in the meantime...*hack hack hack*
  2205. // var vids = Array.prototype.slice.call(document.getElementsByTagName('video'));
  2206. // var audios = Array.prototype.slice.call(document.getElementsByTagName('audio'));
  2207. // var mediaEls = vids.concat(audios);
  2208. // Because IE8 doesn't support calling slice on a node list, we need to loop
  2209. // through each list of elements to build up a new, combined list of elements.
  2210. var vids = _document2['default'].getElementsByTagName('video');
  2211. var audios = _document2['default'].getElementsByTagName('audio');
  2212. var mediaEls = [];
  2213. if (vids && vids.length > 0) {
  2214. for (var i = 0, e = vids.length; i < e; i++) {
  2215. mediaEls.push(vids[i]);
  2216. }
  2217. }
  2218. if (audios && audios.length > 0) {
  2219. for (var _i = 0, _e = audios.length; _i < _e; _i++) {
  2220. mediaEls.push(audios[_i]);
  2221. }
  2222. }
  2223. // Check if any media elements exist
  2224. if (mediaEls && mediaEls.length > 0) {
  2225. for (var _i2 = 0, _e2 = mediaEls.length; _i2 < _e2; _i2++) {
  2226. var mediaEl = mediaEls[_i2];
  2227. // Check if element exists, has getAttribute func.
  2228. // IE seems to consider typeof el.getAttribute == 'object' instead of
  2229. // 'function' like expected, at least when loading the player immediately.
  2230. if (mediaEl && mediaEl.getAttribute) {
  2231. // Make sure this player hasn't already been set up.
  2232. if (mediaEl.player === undefined) {
  2233. var options = mediaEl.getAttribute('data-setup');
  2234. // Check if data-setup attr exists.
  2235. // We only auto-setup if they've added the data-setup attr.
  2236. if (options !== null) {
  2237. // Create new video.js instance.
  2238. videojs(mediaEl);
  2239. }
  2240. }
  2241. // If getAttribute isn't defined, we need to wait for the DOM.
  2242. } else {
  2243. autoSetupTimeout(1);
  2244. break;
  2245. }
  2246. }
  2247. // No videos were found, so keep looping unless page is finished loading.
  2248. } else if (!_windowLoaded) {
  2249. autoSetupTimeout(1);
  2250. }
  2251. };
  2252. /**
  2253. * Wait until the page is loaded before running autoSetup. This will be called in
  2254. * autoSetup if `hasLoaded` returns false.
  2255. *
  2256. * @param {number} wait
  2257. * How long to wait in ms
  2258. *
  2259. * @param {videojs} [vjs]
  2260. * The videojs library function
  2261. */
  2262. function autoSetupTimeout(wait, vjs) {
  2263. if (vjs) {
  2264. videojs = vjs;
  2265. }
  2266. _window2['default'].setTimeout(autoSetup, wait);
  2267. }
  2268. if (Dom.isReal() && _document2['default'].readyState === 'complete') {
  2269. _windowLoaded = true;
  2270. } else {
  2271. /**
  2272. * Listen for the load event on window, and set _windowLoaded to true.
  2273. *
  2274. * @listens load
  2275. */
  2276. Events.one(_window2['default'], 'load', function () {
  2277. _windowLoaded = true;
  2278. });
  2279. }
  2280. /**
  2281. * check if the document has been loaded
  2282. */
  2283. var hasLoaded = function hasLoaded() {
  2284. return _windowLoaded;
  2285. };
  2286. exports.autoSetup = autoSetup;
  2287. exports.autoSetupTimeout = autoSetupTimeout;
  2288. exports.hasLoaded = hasLoaded;
  2289. /***/ }),
  2290. /* 17 */
  2291. /***/ (function(module, exports, __webpack_require__) {
  2292. 'use strict';
  2293. exports.__esModule = true;
  2294. exports.fixEvent = fixEvent;
  2295. exports.on = on;
  2296. exports.off = off;
  2297. exports.trigger = trigger;
  2298. exports.one = one;
  2299. var _dom = __webpack_require__(11);
  2300. var Dom = _interopRequireWildcard(_dom);
  2301. var _guid = __webpack_require__(12);
  2302. var Guid = _interopRequireWildcard(_guid);
  2303. var _log = __webpack_require__(13);
  2304. var _log2 = _interopRequireDefault(_log);
  2305. var _window = __webpack_require__(7);
  2306. var _window2 = _interopRequireDefault(_window);
  2307. var _document = __webpack_require__(8);
  2308. var _document2 = _interopRequireDefault(_document);
  2309. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  2310. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  2311. /**
  2312. * Clean up the listener cache and dispatchers
  2313. *
  2314. * @param {Element|Object} elem
  2315. * Element to clean up
  2316. *
  2317. * @param {string} type
  2318. * Type of event to clean up
  2319. */
  2320. function _cleanUpEvents(elem, type) {
  2321. var data = Dom.getElData(elem);
  2322. // Remove the events of a particular type if there are none left
  2323. if (data.handlers[type].length === 0) {
  2324. delete data.handlers[type];
  2325. // data.handlers[type] = null;
  2326. // Setting to null was causing an error with data.handlers
  2327. // Remove the meta-handler from the element
  2328. if (elem.removeEventListener) {
  2329. elem.removeEventListener(type, data.dispatcher, false);
  2330. } else if (elem.detachEvent) {
  2331. elem.detachEvent('on' + type, data.dispatcher);
  2332. }
  2333. }
  2334. // Remove the events object if there are no types left
  2335. if (Object.getOwnPropertyNames(data.handlers).length <= 0) {
  2336. delete data.handlers;
  2337. delete data.dispatcher;
  2338. delete data.disabled;
  2339. }
  2340. // Finally remove the element data if there is no data left
  2341. if (Object.getOwnPropertyNames(data).length === 0) {
  2342. Dom.removeElData(elem);
  2343. }
  2344. }
  2345. /**
  2346. * Loops through an array of event types and calls the requested method for each type.
  2347. *
  2348. * @param {Function} fn
  2349. * The event method we want to use.
  2350. *
  2351. * @param {Element|Object} elem
  2352. * Element or object to bind listeners to
  2353. *
  2354. * @param {string} type
  2355. * Type of event to bind to.
  2356. *
  2357. * @param {EventTarget~EventListener} callback
  2358. * Event listener.
  2359. */
  2360. /**
  2361. * @file events.js. An Event System (John Resig - Secrets of a JS Ninja http://jsninja.com/)
  2362. * (Original book version wasn't completely usable, so fixed some things and made Closure Compiler compatible)
  2363. * This should work very similarly to jQuery's events, however it's based off the book version which isn't as
  2364. * robust as jquery's, so there's probably some differences.
  2365. *
  2366. * @module events
  2367. */
  2368. function _handleMultipleEvents(fn, elem, types, callback) {
  2369. types.forEach(function (type) {
  2370. // Call the event method for each one of the types
  2371. fn(elem, type, callback);
  2372. });
  2373. }
  2374. /**
  2375. * Fix a native event to have standard property values
  2376. *
  2377. * @param {Object} event
  2378. * Event object to fix.
  2379. *
  2380. * @return {Object}
  2381. * Fixed event object.
  2382. */
  2383. function fixEvent(event) {
  2384. function returnTrue() {
  2385. return true;
  2386. }
  2387. function returnFalse() {
  2388. return false;
  2389. }
  2390. // Test if fixing up is needed
  2391. // Used to check if !event.stopPropagation instead of isPropagationStopped
  2392. // But native events return true for stopPropagation, but don't have
  2393. // other expected methods like isPropagationStopped. Seems to be a problem
  2394. // with the Javascript Ninja code. So we're just overriding all events now.
  2395. if (!event || !event.isPropagationStopped) {
  2396. var old = event || _window2['default'].event;
  2397. event = {};
  2398. // Clone the old object so that we can modify the values event = {};
  2399. // IE8 Doesn't like when you mess with native event properties
  2400. // Firefox returns false for event.hasOwnProperty('type') and other props
  2401. // which makes copying more difficult.
  2402. // TODO: Probably best to create a whitelist of event props
  2403. for (var key in old) {
  2404. // Safari 6.0.3 warns you if you try to copy deprecated layerX/Y
  2405. // Chrome warns you if you try to copy deprecated keyboardEvent.keyLocation
  2406. // and webkitMovementX/Y
  2407. if (key !== 'layerX' && key !== 'layerY' && key !== 'keyLocation' && key !== 'webkitMovementX' && key !== 'webkitMovementY') {
  2408. // Chrome 32+ warns if you try to copy deprecated returnValue, but
  2409. // we still want to if preventDefault isn't supported (IE8).
  2410. if (!(key === 'returnValue' && old.preventDefault)) {
  2411. event[key] = old[key];
  2412. }
  2413. }
  2414. }
  2415. // The event occurred on this element
  2416. if (!event.target) {
  2417. event.target = event.srcElement || _document2['default'];
  2418. }
  2419. // Handle which other element the event is related to
  2420. if (!event.relatedTarget) {
  2421. event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
  2422. }
  2423. // Stop the default browser action
  2424. event.preventDefault = function () {
  2425. if (old.preventDefault) {
  2426. old.preventDefault();
  2427. }
  2428. event.returnValue = false;
  2429. old.returnValue = false;
  2430. event.defaultPrevented = true;
  2431. };
  2432. event.defaultPrevented = false;
  2433. // Stop the event from bubbling
  2434. event.stopPropagation = function () {
  2435. if (old.stopPropagation) {
  2436. old.stopPropagation();
  2437. }
  2438. event.cancelBubble = true;
  2439. old.cancelBubble = true;
  2440. event.isPropagationStopped = returnTrue;
  2441. };
  2442. event.isPropagationStopped = returnFalse;
  2443. // Stop the event from bubbling and executing other handlers
  2444. event.stopImmediatePropagation = function () {
  2445. if (old.stopImmediatePropagation) {
  2446. old.stopImmediatePropagation();
  2447. }
  2448. event.isImmediatePropagationStopped = returnTrue;
  2449. event.stopPropagation();
  2450. };
  2451. event.isImmediatePropagationStopped = returnFalse;
  2452. // Handle mouse position
  2453. if (event.clientX !== null && event.clientX !== undefined) {
  2454. var doc = _document2['default'].documentElement;
  2455. var body = _document2['default'].body;
  2456. event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
  2457. event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
  2458. }
  2459. // Handle key presses
  2460. event.which = event.charCode || event.keyCode;
  2461. // Fix button for mouse clicks:
  2462. // 0 == left; 1 == middle; 2 == right
  2463. if (event.button !== null && event.button !== undefined) {
  2464. // The following is disabled because it does not pass videojs-standard
  2465. // and... yikes.
  2466. /* eslint-disable */
  2467. event.button = event.button & 1 ? 0 : event.button & 4 ? 1 : event.button & 2 ? 2 : 0;
  2468. /* eslint-enable */
  2469. }
  2470. }
  2471. // Returns fixed-up instance
  2472. return event;
  2473. }
  2474. /**
  2475. * Whether passive event listeners are supported
  2476. */
  2477. var _supportsPassive = false;
  2478. (function () {
  2479. try {
  2480. var opts = Object.defineProperty({}, 'passive', {
  2481. get: function get() {
  2482. _supportsPassive = true;
  2483. }
  2484. });
  2485. _window2['default'].addEventListener('test', null, opts);
  2486. } catch (e) {
  2487. // disregard
  2488. }
  2489. })();
  2490. /**
  2491. * Touch events Chrome expects to be passive
  2492. */
  2493. var passiveEvents = ['touchstart', 'touchmove'];
  2494. /**
  2495. * Add an event listener to element
  2496. * It stores the handler function in a separate cache object
  2497. * and adds a generic handler to the element's event,
  2498. * along with a unique id (guid) to the element.
  2499. *
  2500. * @param {Element|Object} elem
  2501. * Element or object to bind listeners to
  2502. *
  2503. * @param {string|string[]} type
  2504. * Type of event to bind to.
  2505. *
  2506. * @param {EventTarget~EventListener} fn
  2507. * Event listener.
  2508. */
  2509. function on(elem, type, fn) {
  2510. if (Array.isArray(type)) {
  2511. return _handleMultipleEvents(on, elem, type, fn);
  2512. }
  2513. var data = Dom.getElData(elem);
  2514. // We need a place to store all our handler data
  2515. if (!data.handlers) {
  2516. data.handlers = {};
  2517. }
  2518. if (!data.handlers[type]) {
  2519. data.handlers[type] = [];
  2520. }
  2521. if (!fn.guid) {
  2522. fn.guid = Guid.newGUID();
  2523. }
  2524. data.handlers[type].push(fn);
  2525. if (!data.dispatcher) {
  2526. data.disabled = false;
  2527. data.dispatcher = function (event, hash) {
  2528. if (data.disabled) {
  2529. return;
  2530. }
  2531. event = fixEvent(event);
  2532. var handlers = data.handlers[event.type];
  2533. if (handlers) {
  2534. // Copy handlers so if handlers are added/removed during the process it doesn't throw everything off.
  2535. var handlersCopy = handlers.slice(0);
  2536. for (var m = 0, n = handlersCopy.length; m < n; m++) {
  2537. if (event.isImmediatePropagationStopped()) {
  2538. break;
  2539. } else {
  2540. try {
  2541. handlersCopy[m].call(elem, event, hash);
  2542. } catch (e) {
  2543. _log2['default'].error(e);
  2544. }
  2545. }
  2546. }
  2547. }
  2548. };
  2549. }
  2550. if (data.handlers[type].length === 1) {
  2551. if (elem.addEventListener) {
  2552. var options = false;
  2553. if (_supportsPassive && passiveEvents.indexOf(type) > -1) {
  2554. options = { passive: true };
  2555. }
  2556. elem.addEventListener(type, data.dispatcher, options);
  2557. } else if (elem.attachEvent) {
  2558. elem.attachEvent('on' + type, data.dispatcher);
  2559. }
  2560. }
  2561. }
  2562. /**
  2563. * Removes event listeners from an element
  2564. *
  2565. * @param {Element|Object} elem
  2566. * Object to remove listeners from.
  2567. *
  2568. * @param {string|string[]} [type]
  2569. * Type of listener to remove. Don't include to remove all events from element.
  2570. *
  2571. * @param {EventTarget~EventListener} [fn]
  2572. * Specific listener to remove. Don't include to remove listeners for an event
  2573. * type.
  2574. */
  2575. function off(elem, type, fn) {
  2576. // Don't want to add a cache object through getElData if not needed
  2577. if (!Dom.hasElData(elem)) {
  2578. return;
  2579. }
  2580. var data = Dom.getElData(elem);
  2581. // If no events exist, nothing to unbind
  2582. if (!data.handlers) {
  2583. return;
  2584. }
  2585. if (Array.isArray(type)) {
  2586. return _handleMultipleEvents(off, elem, type, fn);
  2587. }
  2588. // Utility function
  2589. var removeType = function removeType(t) {
  2590. data.handlers[t] = [];
  2591. _cleanUpEvents(elem, t);
  2592. };
  2593. // Are we removing all bound events?
  2594. if (!type) {
  2595. for (var t in data.handlers) {
  2596. removeType(t);
  2597. }
  2598. return;
  2599. }
  2600. var handlers = data.handlers[type];
  2601. // If no handlers exist, nothing to unbind
  2602. if (!handlers) {
  2603. return;
  2604. }
  2605. // If no listener was provided, remove all listeners for type
  2606. if (!fn) {
  2607. removeType(type);
  2608. return;
  2609. }
  2610. // We're only removing a single handler
  2611. if (fn.guid) {
  2612. for (var n = 0; n < handlers.length; n++) {
  2613. if (handlers[n].guid === fn.guid) {
  2614. handlers.splice(n--, 1);
  2615. }
  2616. }
  2617. }
  2618. _cleanUpEvents(elem, type);
  2619. }
  2620. /**
  2621. * Trigger an event for an element
  2622. *
  2623. * @param {Element|Object} elem
  2624. * Element to trigger an event on
  2625. *
  2626. * @param {EventTarget~Event|string} event
  2627. * A string (the type) or an event object with a type attribute
  2628. *
  2629. * @param {Object} [hash]
  2630. * data hash to pass along with the event
  2631. *
  2632. * @return {boolean|undefined}
  2633. * - Returns the opposite of `defaultPrevented` if default was prevented
  2634. * - Otherwise returns undefined
  2635. */
  2636. function trigger(elem, event, hash) {
  2637. // Fetches element data and a reference to the parent (for bubbling).
  2638. // Don't want to add a data object to cache for every parent,
  2639. // so checking hasElData first.
  2640. var elemData = Dom.hasElData(elem) ? Dom.getElData(elem) : {};
  2641. var parent = elem.parentNode || elem.ownerDocument;
  2642. // type = event.type || event,
  2643. // handler;
  2644. // If an event name was passed as a string, creates an event out of it
  2645. if (typeof event === 'string') {
  2646. event = { type: event, target: elem };
  2647. }
  2648. // Normalizes the event properties.
  2649. event = fixEvent(event);
  2650. // If the passed element has a dispatcher, executes the established handlers.
  2651. if (elemData.dispatcher) {
  2652. elemData.dispatcher.call(elem, event, hash);
  2653. }
  2654. // Unless explicitly stopped or the event does not bubble (e.g. media events)
  2655. // recursively calls this function to bubble the event up the DOM.
  2656. if (parent && !event.isPropagationStopped() && event.bubbles === true) {
  2657. trigger.call(null, parent, event, hash);
  2658. // If at the top of the DOM, triggers the default action unless disabled.
  2659. } else if (!parent && !event.defaultPrevented) {
  2660. var targetData = Dom.getElData(event.target);
  2661. // Checks if the target has a default action for this event.
  2662. if (event.target[event.type]) {
  2663. // Temporarily disables event dispatching on the target as we have already executed the handler.
  2664. targetData.disabled = true;
  2665. // Executes the default action.
  2666. if (typeof event.target[event.type] === 'function') {
  2667. event.target[event.type]();
  2668. }
  2669. // Re-enables event dispatching.
  2670. targetData.disabled = false;
  2671. }
  2672. }
  2673. // Inform the triggerer if the default was prevented by returning false
  2674. return !event.defaultPrevented;
  2675. }
  2676. /**
  2677. * Trigger a listener only once for an event
  2678. *
  2679. * @param {Element|Object} elem
  2680. * Element or object to bind to.
  2681. *
  2682. * @param {string|string[]} type
  2683. * Name/type of event
  2684. *
  2685. * @param {Event~EventListener} fn
  2686. * Event Listener function
  2687. */
  2688. function one(elem, type, fn) {
  2689. if (Array.isArray(type)) {
  2690. return _handleMultipleEvents(one, elem, type, fn);
  2691. }
  2692. var func = function func() {
  2693. off(elem, type, func);
  2694. fn.apply(this, arguments);
  2695. };
  2696. // copy the guid to the new function so it can removed using the original function's ID
  2697. func.guid = fn.guid = fn.guid || Guid.newGUID();
  2698. on(elem, type, func);
  2699. }
  2700. /***/ }),
  2701. /* 18 */
  2702. /***/ (function(module, exports, __webpack_require__) {
  2703. 'use strict';
  2704. exports.__esModule = true;
  2705. exports.setTextContent = exports.createStyleElement = undefined;
  2706. var _document = __webpack_require__(8);
  2707. var _document2 = _interopRequireDefault(_document);
  2708. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  2709. /**
  2710. * Create a DOM syle element given a className for it.
  2711. *
  2712. * @param {string} className
  2713. * The className to add to the created style element.
  2714. *
  2715. * @return {Element}
  2716. * The element that was created.
  2717. */
  2718. var createStyleElement = exports.createStyleElement = function createStyleElement(className) {
  2719. var style = _document2['default'].createElement('style');
  2720. style.className = className;
  2721. return style;
  2722. };
  2723. /**
  2724. * Add text to a DOM element.
  2725. *
  2726. * @param {Element} el
  2727. * The Element to add text content to.
  2728. *
  2729. * @param {string} content
  2730. * The text to add to the element.
  2731. */
  2732. /**
  2733. * @file stylesheet.js
  2734. * @module stylesheet
  2735. */
  2736. var setTextContent = exports.setTextContent = function setTextContent(el, content) {
  2737. if (el.styleSheet) {
  2738. el.styleSheet.cssText = content;
  2739. } else {
  2740. el.textContent = content;
  2741. }
  2742. };
  2743. /***/ }),
  2744. /* 19 */
  2745. /***/ (function(module, exports, __webpack_require__) {
  2746. 'use strict';
  2747. exports.__esModule = true;
  2748. var _window = __webpack_require__(7);
  2749. var _window2 = _interopRequireDefault(_window);
  2750. var _dom = __webpack_require__(11);
  2751. var Dom = _interopRequireWildcard(_dom);
  2752. var _fn = __webpack_require__(20);
  2753. var Fn = _interopRequireWildcard(_fn);
  2754. var _guid = __webpack_require__(12);
  2755. var Guid = _interopRequireWildcard(_guid);
  2756. var _events = __webpack_require__(17);
  2757. var Events = _interopRequireWildcard(_events);
  2758. var _log = __webpack_require__(13);
  2759. var _log2 = _interopRequireDefault(_log);
  2760. var _toTitleCase = __webpack_require__(21);
  2761. var _toTitleCase2 = _interopRequireDefault(_toTitleCase);
  2762. var _mergeOptions = __webpack_require__(22);
  2763. var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
  2764. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  2765. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  2766. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
  2767. * Player Component - Base class for all UI objects
  2768. *
  2769. * @file component.js
  2770. */
  2771. /**
  2772. * Base class for all UI Components.
  2773. * Components are UI objects which represent both a javascript object and an element
  2774. * in the DOM. They can be children of other components, and can have
  2775. * children themselves.
  2776. *
  2777. * Components can also use methods from {@link EventTarget}
  2778. */
  2779. var Component = function () {
  2780. /**
  2781. * A callback that is called when a component is ready. Does not have any
  2782. * paramters and any callback value will be ignored.
  2783. *
  2784. * @callback Component~ReadyCallback
  2785. * @this Component
  2786. */
  2787. /**
  2788. * Creates an instance of this class.
  2789. *
  2790. * @param {Player} player
  2791. * The `Player` that this class should be attached to.
  2792. *
  2793. * @param {Object} [options]
  2794. * The key/value store of player options.
  2795. #
  2796. * @param {Object[]} [options.children]
  2797. * An array of children objects to intialize this component with. Children objects have
  2798. * a name property that will be used if more than one component of the same type needs to be
  2799. * added.
  2800. *
  2801. * @param {Component~ReadyCallback} [ready]
  2802. * Function that gets called when the `Component` is ready.
  2803. */
  2804. function Component(player, options, ready) {
  2805. _classCallCheck(this, Component);
  2806. // The component might be the player itself and we can't pass `this` to super
  2807. if (!player && this.play) {
  2808. this.player_ = player = this; // eslint-disable-line
  2809. } else {
  2810. this.player_ = player;
  2811. }
  2812. // Make a copy of prototype.options_ to protect against overriding defaults
  2813. this.options_ = (0, _mergeOptions2['default'])({}, this.options_);
  2814. // Updated options with supplied options
  2815. options = this.options_ = (0, _mergeOptions2['default'])(this.options_, options);
  2816. // Get ID from options or options element if one is supplied
  2817. this.id_ = options.id || options.el && options.el.id;
  2818. // If there was no ID from the options, generate one
  2819. if (!this.id_) {
  2820. // Don't require the player ID function in the case of mock players
  2821. var id = player && player.id && player.id() || 'no_player';
  2822. this.id_ = id + '_component_' + Guid.newGUID();
  2823. }
  2824. this.name_ = options.name || null;
  2825. // Create element if one wasn't provided in options
  2826. if (options.el) {
  2827. this.el_ = options.el;
  2828. } else if (options.createEl !== false) {
  2829. this.el_ = this.createEl();
  2830. }
  2831. this.children_ = [];
  2832. this.childIndex_ = {};
  2833. this.childNameIndex_ = {};
  2834. // Add any child components in options
  2835. if (options.initChildren !== false) {
  2836. this.initChildren();
  2837. }
  2838. this.ready(ready);
  2839. // Don't want to trigger ready here or it will before init is actually
  2840. // finished for all children that run this constructor
  2841. if (options.reportTouchActivity !== false) {
  2842. this.enableTouchActivity();
  2843. }
  2844. }
  2845. /**
  2846. * Dispose of the `Component` and all child components.
  2847. *
  2848. * @fires Component#dispose
  2849. */
  2850. Component.prototype.dispose = function dispose() {
  2851. /**
  2852. * Triggered when a `Component` is disposed.
  2853. *
  2854. * @event Component#dispose
  2855. * @type {EventTarget~Event}
  2856. *
  2857. * @property {boolean} [bubbles=false]
  2858. * set to false so that the close event does not
  2859. * bubble up
  2860. */
  2861. this.trigger({ type: 'dispose', bubbles: false });
  2862. // Dispose all children.
  2863. if (this.children_) {
  2864. for (var i = this.children_.length - 1; i >= 0; i--) {
  2865. if (this.children_[i].dispose) {
  2866. this.children_[i].dispose();
  2867. }
  2868. }
  2869. }
  2870. // Delete child references
  2871. this.children_ = null;
  2872. this.childIndex_ = null;
  2873. this.childNameIndex_ = null;
  2874. // Remove all event listeners.
  2875. this.off();
  2876. // Remove element from DOM
  2877. if (this.el_.parentNode) {
  2878. this.el_.parentNode.removeChild(this.el_);
  2879. }
  2880. Dom.removeElData(this.el_);
  2881. this.el_ = null;
  2882. };
  2883. /**
  2884. * Return the {@link Player} that the `Component` has attached to.
  2885. *
  2886. * @return {Player}
  2887. * The player that this `Component` has attached to.
  2888. */
  2889. Component.prototype.player = function player() {
  2890. return this.player_;
  2891. };
  2892. /**
  2893. * Deep merge of options objects with new options.
  2894. * > Note: When both `obj` and `options` contain properties whose values are objects.
  2895. * The two properties get merged using {@link module:mergeOptions}
  2896. *
  2897. * @param {Object} obj
  2898. * The object that contains new options.
  2899. *
  2900. * @return {Object}
  2901. * A new object of `this.options_` and `obj` merged together.
  2902. *
  2903. * @deprecated since version 5
  2904. */
  2905. Component.prototype.options = function options(obj) {
  2906. _log2['default'].warn('this.options() has been deprecated and will be moved to the constructor in 6.0');
  2907. if (!obj) {
  2908. return this.options_;
  2909. }
  2910. this.options_ = (0, _mergeOptions2['default'])(this.options_, obj);
  2911. return this.options_;
  2912. };
  2913. /**
  2914. * Get the `Component`s DOM element
  2915. *
  2916. * @return {Element}
  2917. * The DOM element for this `Component`.
  2918. */
  2919. Component.prototype.el = function el() {
  2920. return this.el_;
  2921. };
  2922. /**
  2923. * Create the `Component`s DOM element.
  2924. *
  2925. * @param {string} [tagName]
  2926. * Element's DOM node type. e.g. 'div'
  2927. *
  2928. * @param {Object} [properties]
  2929. * An object of properties that should be set.
  2930. *
  2931. * @param {Object} [attributes]
  2932. * An object of attributes that should be set.
  2933. *
  2934. * @return {Element}
  2935. * The element that gets created.
  2936. */
  2937. Component.prototype.createEl = function createEl(tagName, properties, attributes) {
  2938. return Dom.createEl(tagName, properties, attributes);
  2939. };
  2940. /**
  2941. * Localize a string given the string in english.
  2942. *
  2943. * @param {string} string
  2944. * The string to localize.
  2945. *
  2946. * @return {string}
  2947. * The localized string or if no localization exists the english string.
  2948. */
  2949. Component.prototype.localize = function localize(string) {
  2950. var code = this.player_.language && this.player_.language();
  2951. var languages = this.player_.languages && this.player_.languages();
  2952. if (!code || !languages) {
  2953. return string;
  2954. }
  2955. var language = languages[code];
  2956. if (language && language[string]) {
  2957. return language[string];
  2958. }
  2959. var primaryCode = code.split('-')[0];
  2960. var primaryLang = languages[primaryCode];
  2961. if (primaryLang && primaryLang[string]) {
  2962. return primaryLang[string];
  2963. }
  2964. return string;
  2965. };
  2966. /**
  2967. * Return the `Component`s DOM element. This is where children get inserted.
  2968. * This will usually be the the same as the element returned in {@link Component#el}.
  2969. *
  2970. * @return {Element}
  2971. * The content element for this `Component`.
  2972. */
  2973. Component.prototype.contentEl = function contentEl() {
  2974. return this.contentEl_ || this.el_;
  2975. };
  2976. /**
  2977. * Get this `Component`s ID
  2978. *
  2979. * @return {string}
  2980. * The id of this `Component`
  2981. */
  2982. Component.prototype.id = function id() {
  2983. return this.id_;
  2984. };
  2985. /**
  2986. * Get the `Component`s name. The name gets used to reference the `Component`
  2987. * and is set during registration.
  2988. *
  2989. * @return {string}
  2990. * The name of this `Component`.
  2991. */
  2992. Component.prototype.name = function name() {
  2993. return this.name_;
  2994. };
  2995. /**
  2996. * Get an array of all child components
  2997. *
  2998. * @return {Array}
  2999. * The children
  3000. */
  3001. Component.prototype.children = function children() {
  3002. return this.children_;
  3003. };
  3004. /**
  3005. * Returns the child `Component` with the given `id`.
  3006. *
  3007. * @param {string} id
  3008. * The id of the child `Component` to get.
  3009. *
  3010. * @return {Component|undefined}
  3011. * The child `Component` with the given `id` or undefined.
  3012. */
  3013. Component.prototype.getChildById = function getChildById(id) {
  3014. return this.childIndex_[id];
  3015. };
  3016. /**
  3017. * Returns the child `Component` with the given `name`.
  3018. *
  3019. * @param {string} name
  3020. * The name of the child `Component` to get.
  3021. *
  3022. * @return {Component|undefined}
  3023. * The child `Component` with the given `name` or undefined.
  3024. */
  3025. Component.prototype.getChild = function getChild(name) {
  3026. if (!name) {
  3027. return;
  3028. }
  3029. name = (0, _toTitleCase2['default'])(name);
  3030. return this.childNameIndex_[name];
  3031. };
  3032. /**
  3033. * Add a child `Component` inside the current `Component`.
  3034. *
  3035. *
  3036. * @param {string|Component} child
  3037. * The name or instance of a child to add.
  3038. *
  3039. * @param {Object} [options={}]
  3040. * The key/value store of options that will get passed to children of
  3041. * the child.
  3042. *
  3043. * @param {number} [index=this.children_.length]
  3044. * The index to attempt to add a child into.
  3045. *
  3046. * @return {Component}
  3047. * The `Component` that gets added as a child. When using a string the
  3048. * `Component` will get created by this process.
  3049. */
  3050. Component.prototype.addChild = function addChild(child) {
  3051. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  3052. var index = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.children_.length;
  3053. var component = void 0;
  3054. var componentName = void 0;
  3055. // If child is a string, create component with options
  3056. if (typeof child === 'string') {
  3057. componentName = (0, _toTitleCase2['default'])(child);
  3058. // Options can also be specified as a boolean,
  3059. // so convert to an empty object if false.
  3060. if (!options) {
  3061. options = {};
  3062. }
  3063. // Same as above, but true is deprecated so show a warning.
  3064. if (options === true) {
  3065. _log2['default'].warn('Initializing a child component with `true` is deprecated.' + 'Children should be defined in an array when possible, ' + 'but if necessary use an object instead of `true`.');
  3066. options = {};
  3067. }
  3068. var componentClassName = options.componentClass || componentName;
  3069. // Set name through options
  3070. options.name = componentName;
  3071. // Create a new object & element for this controls set
  3072. // If there's no .player_, this is a player
  3073. var ComponentClass = Component.getComponent(componentClassName);
  3074. if (!ComponentClass) {
  3075. throw new Error('Component ' + componentClassName + ' does not exist');
  3076. }
  3077. // data stored directly on the videojs object may be
  3078. // misidentified as a component to retain
  3079. // backwards-compatibility with 4.x. check to make sure the
  3080. // component class can be instantiated.
  3081. if (typeof ComponentClass !== 'function') {
  3082. return null;
  3083. }
  3084. component = new ComponentClass(this.player_ || this, options);
  3085. // child is a component instance
  3086. } else {
  3087. component = child;
  3088. }
  3089. this.children_.splice(index, 0, component);
  3090. if (typeof component.id === 'function') {
  3091. this.childIndex_[component.id()] = component;
  3092. }
  3093. // If a name wasn't used to create the component, check if we can use the
  3094. // name function of the component
  3095. componentName = componentName || component.name && (0, _toTitleCase2['default'])(component.name());
  3096. if (componentName) {
  3097. this.childNameIndex_[componentName] = component;
  3098. }
  3099. // Add the UI object's element to the container div (box)
  3100. // Having an element is not required
  3101. if (typeof component.el === 'function' && component.el()) {
  3102. var childNodes = this.contentEl().children;
  3103. var refNode = childNodes[index] || null;
  3104. this.contentEl().insertBefore(component.el(), refNode);
  3105. }
  3106. // Return so it can stored on parent object if desired.
  3107. return component;
  3108. };
  3109. /**
  3110. * Remove a child `Component` from this `Component`s list of children. Also removes
  3111. * the child `Component`s element from this `Component`s element.
  3112. *
  3113. * @param {Component} component
  3114. * The child `Component` to remove.
  3115. */
  3116. Component.prototype.removeChild = function removeChild(component) {
  3117. if (typeof component === 'string') {
  3118. component = this.getChild(component);
  3119. }
  3120. if (!component || !this.children_) {
  3121. return;
  3122. }
  3123. var childFound = false;
  3124. for (var i = this.children_.length - 1; i >= 0; i--) {
  3125. if (this.children_[i] === component) {
  3126. childFound = true;
  3127. this.children_.splice(i, 1);
  3128. break;
  3129. }
  3130. }
  3131. if (!childFound) {
  3132. return;
  3133. }
  3134. this.childIndex_[component.id()] = null;
  3135. this.childNameIndex_[component.name()] = null;
  3136. var compEl = component.el();
  3137. if (compEl && compEl.parentNode === this.contentEl()) {
  3138. this.contentEl().removeChild(component.el());
  3139. }
  3140. };
  3141. /**
  3142. * Add and initialize default child `Component`s based upon options.
  3143. */
  3144. Component.prototype.initChildren = function initChildren() {
  3145. var _this = this;
  3146. var children = this.options_.children;
  3147. if (children) {
  3148. // `this` is `parent`
  3149. var parentOptions = this.options_;
  3150. var handleAdd = function handleAdd(child) {
  3151. var name = child.name;
  3152. var opts = child.opts;
  3153. // Allow options for children to be set at the parent options
  3154. // e.g. videojs(id, { controlBar: false });
  3155. // instead of videojs(id, { children: { controlBar: false });
  3156. if (parentOptions[name] !== undefined) {
  3157. opts = parentOptions[name];
  3158. }
  3159. // Allow for disabling default components
  3160. // e.g. options['children']['posterImage'] = false
  3161. if (opts === false) {
  3162. return;
  3163. }
  3164. // Allow options to be passed as a simple boolean if no configuration
  3165. // is necessary.
  3166. if (opts === true) {
  3167. opts = {};
  3168. }
  3169. // We also want to pass the original player options
  3170. // to each component as well so they don't need to
  3171. // reach back into the player for options later.
  3172. opts.playerOptions = _this.options_.playerOptions;
  3173. // Create and add the child component.
  3174. // Add a direct reference to the child by name on the parent instance.
  3175. // If two of the same component are used, different names should be supplied
  3176. // for each
  3177. var newChild = _this.addChild(name, opts);
  3178. if (newChild) {
  3179. _this[name] = newChild;
  3180. }
  3181. };
  3182. // Allow for an array of children details to passed in the options
  3183. var workingChildren = void 0;
  3184. var Tech = Component.getComponent('Tech');
  3185. if (Array.isArray(children)) {
  3186. workingChildren = children;
  3187. } else {
  3188. workingChildren = Object.keys(children);
  3189. }
  3190. workingChildren
  3191. // children that are in this.options_ but also in workingChildren would
  3192. // give us extra children we do not want. So, we want to filter them out.
  3193. .concat(Object.keys(this.options_).filter(function (child) {
  3194. return !workingChildren.some(function (wchild) {
  3195. if (typeof wchild === 'string') {
  3196. return child === wchild;
  3197. }
  3198. return child === wchild.name;
  3199. });
  3200. })).map(function (child) {
  3201. var name = void 0;
  3202. var opts = void 0;
  3203. if (typeof child === 'string') {
  3204. name = child;
  3205. opts = children[name] || _this.options_[name] || {};
  3206. } else {
  3207. name = child.name;
  3208. opts = child;
  3209. }
  3210. return { name: name, opts: opts };
  3211. }).filter(function (child) {
  3212. // we have to make sure that child.name isn't in the techOrder since
  3213. // techs are registerd as Components but can't aren't compatible
  3214. // See https://github.com/videojs/video.js/issues/2772
  3215. var c = Component.getComponent(child.opts.componentClass || (0, _toTitleCase2['default'])(child.name));
  3216. return c && !Tech.isTech(c);
  3217. }).forEach(handleAdd);
  3218. }
  3219. };
  3220. /**
  3221. * Builds the default DOM class name. Should be overriden by sub-components.
  3222. *
  3223. * @return {string}
  3224. * The DOM class name for this object.
  3225. *
  3226. * @abstract
  3227. */
  3228. Component.prototype.buildCSSClass = function buildCSSClass() {
  3229. // Child classes can include a function that does:
  3230. // return 'CLASS NAME' + this._super();
  3231. return '';
  3232. };
  3233. /**
  3234. * Add an `event listener` to this `Component`s element.
  3235. *
  3236. * The benefit of using this over the following:
  3237. * - `VjsEvents.on(otherElement, 'eventName', myFunc)`
  3238. * - `otherComponent.on('eventName', myFunc)`
  3239. *
  3240. * 1. Is that the listeners will get cleaned up when either component gets disposed.
  3241. * 1. It will also bind `myComponent` as the context of `myFunc`.
  3242. * > NOTE: If you remove the element from the DOM that has used `on` you need to
  3243. * clean up references using: `myComponent.trigger(el, 'dispose')`
  3244. * This will also allow the browser to garbage collect it. In special
  3245. * cases such as with `window` and `document`, which are both permanent,
  3246. * this is not necessary.
  3247. *
  3248. * @param {string|Component|string[]} [first]
  3249. * The event name, and array of event names, or another `Component`.
  3250. *
  3251. * @param {EventTarget~EventListener|string|string[]} [second]
  3252. * The listener function, an event name, or an Array of events names.
  3253. *
  3254. * @param {EventTarget~EventListener} [third]
  3255. * The event handler if `first` is a `Component` and `second` is an event name
  3256. * or an Array of event names.
  3257. *
  3258. * @return {Component}
  3259. * Returns itself; method can be chained.
  3260. *
  3261. * @listens Component#dispose
  3262. */
  3263. Component.prototype.on = function on(first, second, third) {
  3264. var _this2 = this;
  3265. if (typeof first === 'string' || Array.isArray(first)) {
  3266. Events.on(this.el_, first, Fn.bind(this, second));
  3267. // Targeting another component or element
  3268. } else {
  3269. var target = first;
  3270. var type = second;
  3271. var fn = Fn.bind(this, third);
  3272. // When this component is disposed, remove the listener from the other component
  3273. var removeOnDispose = function removeOnDispose() {
  3274. return _this2.off(target, type, fn);
  3275. };
  3276. // Use the same function ID so we can remove it later it using the ID
  3277. // of the original listener
  3278. removeOnDispose.guid = fn.guid;
  3279. this.on('dispose', removeOnDispose);
  3280. // If the other component is disposed first we need to clean the reference
  3281. // to the other component in this component's removeOnDispose listener
  3282. // Otherwise we create a memory leak.
  3283. var cleanRemover = function cleanRemover() {
  3284. return _this2.off('dispose', removeOnDispose);
  3285. };
  3286. // Add the same function ID so we can easily remove it later
  3287. cleanRemover.guid = fn.guid;
  3288. // Check if this is a DOM node
  3289. if (first.nodeName) {
  3290. // Add the listener to the other element
  3291. Events.on(target, type, fn);
  3292. Events.on(target, 'dispose', cleanRemover);
  3293. // Should be a component
  3294. // Not using `instanceof Component` because it makes mock players difficult
  3295. } else if (typeof first.on === 'function') {
  3296. // Add the listener to the other component
  3297. target.on(type, fn);
  3298. target.on('dispose', cleanRemover);
  3299. }
  3300. }
  3301. return this;
  3302. };
  3303. /**
  3304. * Remove an event listener from this `Component`s element. If the second argument is
  3305. * exluded all listeners for the type passed in as the first argument will be removed.
  3306. *
  3307. * @param {string|Component|string[]} [first]
  3308. * The event name, and array of event names, or another `Component`.
  3309. *
  3310. * @param {EventTarget~EventListener|string|string[]} [second]
  3311. * The listener function, an event name, or an Array of events names.
  3312. *
  3313. * @param {EventTarget~EventListener} [third]
  3314. * The event handler if `first` is a `Component` and `second` is an event name
  3315. * or an Array of event names.
  3316. *
  3317. * @return {Component}
  3318. * Returns itself; method can be chained.
  3319. */
  3320. Component.prototype.off = function off(first, second, third) {
  3321. if (!first || typeof first === 'string' || Array.isArray(first)) {
  3322. Events.off(this.el_, first, second);
  3323. } else {
  3324. var target = first;
  3325. var type = second;
  3326. // Ensure there's at least a guid, even if the function hasn't been used
  3327. var fn = Fn.bind(this, third);
  3328. // Remove the dispose listener on this component,
  3329. // which was given the same guid as the event listener
  3330. this.off('dispose', fn);
  3331. if (first.nodeName) {
  3332. // Remove the listener
  3333. Events.off(target, type, fn);
  3334. // Remove the listener for cleaning the dispose listener
  3335. Events.off(target, 'dispose', fn);
  3336. } else {
  3337. target.off(type, fn);
  3338. target.off('dispose', fn);
  3339. }
  3340. }
  3341. return this;
  3342. };
  3343. /**
  3344. * Add an event listener that gets triggered only once and then gets removed.
  3345. *
  3346. * @param {string|Component|string[]} [first]
  3347. * The event name, and array of event names, or another `Component`.
  3348. *
  3349. * @param {EventTarget~EventListener|string|string[]} [second]
  3350. * The listener function, an event name, or an Array of events names.
  3351. *
  3352. * @param {EventTarget~EventListener} [third]
  3353. * The event handler if `first` is a `Component` and `second` is an event name
  3354. * or an Array of event names.
  3355. *
  3356. * @return {Component}
  3357. * Returns itself; method can be chained.
  3358. */
  3359. Component.prototype.one = function one(first, second, third) {
  3360. var _this3 = this,
  3361. _arguments = arguments;
  3362. if (typeof first === 'string' || Array.isArray(first)) {
  3363. Events.one(this.el_, first, Fn.bind(this, second));
  3364. } else {
  3365. var target = first;
  3366. var type = second;
  3367. var fn = Fn.bind(this, third);
  3368. var newFunc = function newFunc() {
  3369. _this3.off(target, type, newFunc);
  3370. fn.apply(null, _arguments);
  3371. };
  3372. // Keep the same function ID so we can remove it later
  3373. newFunc.guid = fn.guid;
  3374. this.on(target, type, newFunc);
  3375. }
  3376. return this;
  3377. };
  3378. /**
  3379. * Trigger an event on an element.
  3380. *
  3381. * @param {EventTarget~Event|Object|string} event
  3382. * The event name, and Event, or an event-like object with a type attribute
  3383. * set to the event name.
  3384. *
  3385. * @param {Object} [hash]
  3386. * Data hash to pass along with the event
  3387. *
  3388. * @return {Component}
  3389. * Returns itself; method can be chained.
  3390. */
  3391. Component.prototype.trigger = function trigger(event, hash) {
  3392. Events.trigger(this.el_, event, hash);
  3393. return this;
  3394. };
  3395. /**
  3396. * Bind a listener to the component's ready state. If the ready event has already
  3397. * happened it will trigger the function immediately.
  3398. *
  3399. * @param {Component~ReadyCallback} fn
  3400. * A function to call when ready is triggered.
  3401. *
  3402. * @param {boolean} [sync=false]
  3403. * Execute the listener synchronously if `Component` is ready.
  3404. *
  3405. * @return {Component}
  3406. * Returns itself; method can be chained.
  3407. */
  3408. Component.prototype.ready = function ready(fn) {
  3409. var sync = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  3410. if (fn) {
  3411. if (this.isReady_) {
  3412. if (sync) {
  3413. fn.call(this);
  3414. } else {
  3415. // Call the function asynchronously by default for consistency
  3416. this.setTimeout(fn, 1);
  3417. }
  3418. } else {
  3419. this.readyQueue_ = this.readyQueue_ || [];
  3420. this.readyQueue_.push(fn);
  3421. }
  3422. }
  3423. return this;
  3424. };
  3425. /**
  3426. * Trigger all the ready listeners for this `Component`.
  3427. *
  3428. * @fires Component#ready
  3429. */
  3430. Component.prototype.triggerReady = function triggerReady() {
  3431. this.isReady_ = true;
  3432. // Ensure ready is triggerd asynchronously
  3433. this.setTimeout(function () {
  3434. var readyQueue = this.readyQueue_;
  3435. // Reset Ready Queue
  3436. this.readyQueue_ = [];
  3437. if (readyQueue && readyQueue.length > 0) {
  3438. readyQueue.forEach(function (fn) {
  3439. fn.call(this);
  3440. }, this);
  3441. }
  3442. // Allow for using event listeners also
  3443. /**
  3444. * Triggered when a `Component` is ready.
  3445. *
  3446. * @event Component#ready
  3447. * @type {EventTarget~Event}
  3448. */
  3449. this.trigger('ready');
  3450. }, 1);
  3451. };
  3452. /**
  3453. * Find a single DOM element matching a `selector`. This can be within the `Component`s
  3454. * `contentEl()` or another custom context.
  3455. *
  3456. * @param {string} selector
  3457. * A valid CSS selector, which will be passed to `querySelector`.
  3458. *
  3459. * @param {Element|string} [context=this.contentEl()]
  3460. * A DOM element within which to query. Can also be a selector string in
  3461. * which case the first matching element will get used as context. If
  3462. * missing `this.contentEl()` gets used. If `this.contentEl()` returns
  3463. * nothing it falls back to `document`.
  3464. *
  3465. * @return {Element|null}
  3466. * the dom element that was found, or null
  3467. *
  3468. * @see [Information on CSS Selectors](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_Started/Selectors)
  3469. */
  3470. Component.prototype.$ = function $(selector, context) {
  3471. return Dom.$(selector, context || this.contentEl());
  3472. };
  3473. /**
  3474. * Finds all DOM element matching a `selector`. This can be within the `Component`s
  3475. * `contentEl()` or another custom context.
  3476. *
  3477. * @param {string} selector
  3478. * A valid CSS selector, which will be passed to `querySelectorAll`.
  3479. *
  3480. * @param {Element|string} [context=this.contentEl()]
  3481. * A DOM element within which to query. Can also be a selector string in
  3482. * which case the first matching element will get used as context. If
  3483. * missing `this.contentEl()` gets used. If `this.contentEl()` returns
  3484. * nothing it falls back to `document`.
  3485. *
  3486. * @return {NodeList}
  3487. * a list of dom elements that were found
  3488. *
  3489. * @see [Information on CSS Selectors](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_Started/Selectors)
  3490. */
  3491. Component.prototype.$$ = function $$(selector, context) {
  3492. return Dom.$$(selector, context || this.contentEl());
  3493. };
  3494. /**
  3495. * Check if a component's element has a CSS class name.
  3496. *
  3497. * @param {string} classToCheck
  3498. * CSS class name to check.
  3499. *
  3500. * @return {boolean}
  3501. * - True if the `Component` has the class.
  3502. * - False if the `Component` does not have the class`
  3503. */
  3504. Component.prototype.hasClass = function hasClass(classToCheck) {
  3505. return Dom.hasElClass(this.el_, classToCheck);
  3506. };
  3507. /**
  3508. * Add a CSS class name to the `Component`s element.
  3509. *
  3510. * @param {string} classToAdd
  3511. * CSS class name to add
  3512. *
  3513. * @return {Component}
  3514. * Returns itself; method can be chained.
  3515. */
  3516. Component.prototype.addClass = function addClass(classToAdd) {
  3517. Dom.addElClass(this.el_, classToAdd);
  3518. return this;
  3519. };
  3520. /**
  3521. * Remove a CSS class name from the `Component`s element.
  3522. *
  3523. * @param {string} classToRemove
  3524. * CSS class name to remove
  3525. *
  3526. * @return {Component}
  3527. * Returns itself; method can be chained.
  3528. */
  3529. Component.prototype.removeClass = function removeClass(classToRemove) {
  3530. Dom.removeElClass(this.el_, classToRemove);
  3531. return this;
  3532. };
  3533. /**
  3534. * Add or remove a CSS class name from the component's element.
  3535. * - `classToToggle` gets added when {@link Component#hasClass} would return false.
  3536. * - `classToToggle` gets removed when {@link Component#hasClass} would return true.
  3537. *
  3538. * @param {string} classToToggle
  3539. * The class to add or remove based on (@link Component#hasClass}
  3540. *
  3541. * @param {boolean|Dom~predicate} [predicate]
  3542. * An {@link Dom~predicate} function or a boolean
  3543. *
  3544. * @return {Component}
  3545. * Returns itself; method can be chained.
  3546. */
  3547. Component.prototype.toggleClass = function toggleClass(classToToggle, predicate) {
  3548. Dom.toggleElClass(this.el_, classToToggle, predicate);
  3549. return this;
  3550. };
  3551. /**
  3552. * Show the `Component`s element if it is hidden by removing the
  3553. * 'vjs-hidden' class name from it.
  3554. *
  3555. * @return {Component}
  3556. * Returns itself; method can be chained.
  3557. */
  3558. Component.prototype.show = function show() {
  3559. this.removeClass('vjs-hidden');
  3560. return this;
  3561. };
  3562. /**
  3563. * Hide the `Component`s element if it is currently showing by adding the
  3564. * 'vjs-hidden` class name to it.
  3565. *
  3566. * @return {Component}
  3567. * Returns itself; method can be chained.
  3568. */
  3569. Component.prototype.hide = function hide() {
  3570. this.addClass('vjs-hidden');
  3571. return this;
  3572. };
  3573. /**
  3574. * Lock a `Component`s element in its visible state by adding the 'vjs-lock-showing'
  3575. * class name to it. Used during fadeIn/fadeOut.
  3576. *
  3577. * @return {Component}
  3578. * Returns itself; method can be chained.
  3579. *
  3580. * @private
  3581. */
  3582. Component.prototype.lockShowing = function lockShowing() {
  3583. this.addClass('vjs-lock-showing');
  3584. return this;
  3585. };
  3586. /**
  3587. * Unlock a `Component`s element from its visible state by removing the 'vjs-lock-showing'
  3588. * class name from it. Used during fadeIn/fadeOut.
  3589. *
  3590. * @return {Component}
  3591. * Returns itself; method can be chained.
  3592. *
  3593. * @private
  3594. */
  3595. Component.prototype.unlockShowing = function unlockShowing() {
  3596. this.removeClass('vjs-lock-showing');
  3597. return this;
  3598. };
  3599. /**
  3600. * Get the value of an attribute on the `Component`s element.
  3601. *
  3602. * @param {string} attribute
  3603. * Name of the attribute to get the value from.
  3604. *
  3605. * @return {string|null}
  3606. * - The value of the attribute that was asked for.
  3607. * - Can be an empty string on some browsers if the attribute does not exist
  3608. * or has no value
  3609. * - Most browsers will return null if the attibute does not exist or has
  3610. * no value.
  3611. *
  3612. * @see [DOM API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute}
  3613. */
  3614. Component.prototype.getAttribute = function getAttribute(attribute) {
  3615. return Dom.getAttribute(this.el_, attribute);
  3616. };
  3617. /**
  3618. * Set the value of an attribute on the `Component`'s element
  3619. *
  3620. * @param {string} attribute
  3621. * Name of the attribute to set.
  3622. *
  3623. * @param {string} value
  3624. * Value to set the attribute to.
  3625. *
  3626. * @return {Component}
  3627. * Returns itself; method can be chained.
  3628. *
  3629. * @see [DOM API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute}
  3630. */
  3631. Component.prototype.setAttribute = function setAttribute(attribute, value) {
  3632. Dom.setAttribute(this.el_, attribute, value);
  3633. return this;
  3634. };
  3635. /**
  3636. * Remove an attribute from the `Component`s element.
  3637. *
  3638. * @param {string} attribute
  3639. * Name of the attribute to remove.
  3640. *
  3641. * @return {Component}
  3642. * Returns itself; method can be chained.
  3643. *
  3644. * @see [DOM API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute}
  3645. */
  3646. Component.prototype.removeAttribute = function removeAttribute(attribute) {
  3647. Dom.removeAttribute(this.el_, attribute);
  3648. return this;
  3649. };
  3650. /**
  3651. * Get or set the width of the component based upon the CSS styles.
  3652. * See {@link Component#dimension} for more detailed information.
  3653. *
  3654. * @param {number|string} [num]
  3655. * The width that you want to set postfixed with '%', 'px' or nothing.
  3656. *
  3657. * @param {boolean} [skipListeners]
  3658. * Skip the resize event trigger
  3659. *
  3660. * @return {Component|number|string}
  3661. * - The width when getting, zero if there is no width. Can be a string
  3662. * postpixed with '%' or 'px'.
  3663. * - Returns itself when setting; method can be chained.
  3664. */
  3665. Component.prototype.width = function width(num, skipListeners) {
  3666. return this.dimension('width', num, skipListeners);
  3667. };
  3668. /**
  3669. * Get or set the height of the component based upon the CSS styles.
  3670. * See {@link Component#dimension} for more detailed information.
  3671. *
  3672. * @param {number|string} [num]
  3673. * The height that you want to set postfixed with '%', 'px' or nothing.
  3674. *
  3675. * @param {boolean} [skipListeners]
  3676. * Skip the resize event trigger
  3677. *
  3678. * @return {Component|number|string}
  3679. * - The width when getting, zero if there is no width. Can be a string
  3680. * postpixed with '%' or 'px'.
  3681. * - Returns itself when setting; method can be chained.
  3682. */
  3683. Component.prototype.height = function height(num, skipListeners) {
  3684. return this.dimension('height', num, skipListeners);
  3685. };
  3686. /**
  3687. * Set both the width and height of the `Component` element at the same time.
  3688. *
  3689. * @param {number|string} width
  3690. * Width to set the `Component`s element to.
  3691. *
  3692. * @param {number|string} height
  3693. * Height to set the `Component`s element to.
  3694. *
  3695. * @return {Component}
  3696. * Returns itself; method can be chained.
  3697. */
  3698. Component.prototype.dimensions = function dimensions(width, height) {
  3699. // Skip resize listeners on width for optimization
  3700. return this.width(width, true).height(height);
  3701. };
  3702. /**
  3703. * Get or set width or height of the `Component` element. This is the shared code
  3704. * for the {@link Component#width} and {@link Component#height}.
  3705. *
  3706. * Things to know:
  3707. * - If the width or height in an number this will return the number postfixed with 'px'.
  3708. * - If the width/height is a percent this will return the percent postfixed with '%'
  3709. * - Hidden elements have a width of 0 with `window.getComputedStyle`. This function
  3710. * defaults to the `Component`s `style.width` and falls back to `window.getComputedStyle`.
  3711. * See [this]{@link http://www.foliotek.com/devblog/getting-the-width-of-a-hidden-element-with-jquery-using-width/}
  3712. * for more information
  3713. * - If you want the computed style of the component, use {@link Component#currentWidth}
  3714. * and {@link {Component#currentHeight}
  3715. *
  3716. * @fires Component#resize
  3717. *
  3718. * @param {string} widthOrHeight
  3719. 8 'width' or 'height'
  3720. *
  3721. * @param {number|string} [num]
  3722. 8 New dimension
  3723. *
  3724. * @param {boolean} [skipListeners]
  3725. * Skip resize event trigger
  3726. *
  3727. * @return {Component}
  3728. * - the dimension when getting or 0 if unset
  3729. * - Returns itself when setting; method can be chained.
  3730. */
  3731. Component.prototype.dimension = function dimension(widthOrHeight, num, skipListeners) {
  3732. if (num !== undefined) {
  3733. // Set to zero if null or literally NaN (NaN !== NaN)
  3734. if (num === null || num !== num) {
  3735. num = 0;
  3736. }
  3737. // Check if using css width/height (% or px) and adjust
  3738. if (('' + num).indexOf('%') !== -1 || ('' + num).indexOf('px') !== -1) {
  3739. this.el_.style[widthOrHeight] = num;
  3740. } else if (num === 'auto') {
  3741. this.el_.style[widthOrHeight] = '';
  3742. } else {
  3743. this.el_.style[widthOrHeight] = num + 'px';
  3744. }
  3745. // skipListeners allows us to avoid triggering the resize event when setting both width and height
  3746. if (!skipListeners) {
  3747. /**
  3748. * Triggered when a component is resized.
  3749. *
  3750. * @event Component#resize
  3751. * @type {EventTarget~Event}
  3752. */
  3753. this.trigger('resize');
  3754. }
  3755. // Return component
  3756. return this;
  3757. }
  3758. // Not setting a value, so getting it
  3759. // Make sure element exists
  3760. if (!this.el_) {
  3761. return 0;
  3762. }
  3763. // Get dimension value from style
  3764. var val = this.el_.style[widthOrHeight];
  3765. var pxIndex = val.indexOf('px');
  3766. if (pxIndex !== -1) {
  3767. // Return the pixel value with no 'px'
  3768. return parseInt(val.slice(0, pxIndex), 10);
  3769. }
  3770. // No px so using % or no style was set, so falling back to offsetWidth/height
  3771. // If component has display:none, offset will return 0
  3772. // TODO: handle display:none and no dimension style using px
  3773. return parseInt(this.el_['offset' + (0, _toTitleCase2['default'])(widthOrHeight)], 10);
  3774. };
  3775. /**
  3776. * Get the width or the height of the `Component` elements computed style. Uses
  3777. * `window.getComputedStyle`.
  3778. *
  3779. * @param {string} widthOrHeight
  3780. * A string containing 'width' or 'height'. Whichever one you want to get.
  3781. *
  3782. * @return {number}
  3783. * The dimension that gets asked for or 0 if nothing was set
  3784. * for that dimension.
  3785. */
  3786. Component.prototype.currentDimension = function currentDimension(widthOrHeight) {
  3787. var computedWidthOrHeight = 0;
  3788. if (widthOrHeight !== 'width' && widthOrHeight !== 'height') {
  3789. throw new Error('currentDimension only accepts width or height value');
  3790. }
  3791. if (typeof _window2['default'].getComputedStyle === 'function') {
  3792. var computedStyle = _window2['default'].getComputedStyle(this.el_);
  3793. computedWidthOrHeight = computedStyle.getPropertyValue(widthOrHeight) || computedStyle[widthOrHeight];
  3794. }
  3795. // remove 'px' from variable and parse as integer
  3796. computedWidthOrHeight = parseFloat(computedWidthOrHeight);
  3797. // if the computed value is still 0, it's possible that the browser is lying
  3798. // and we want to check the offset values.
  3799. // This code also runs on IE8 and wherever getComputedStyle doesn't exist.
  3800. if (computedWidthOrHeight === 0) {
  3801. var rule = 'offset' + (0, _toTitleCase2['default'])(widthOrHeight);
  3802. computedWidthOrHeight = this.el_[rule];
  3803. }
  3804. return computedWidthOrHeight;
  3805. };
  3806. /**
  3807. * An object that contains width and height values of the `Component`s
  3808. * computed style. Uses `window.getComputedStyle`.
  3809. *
  3810. * @typedef {Object} Component~DimensionObject
  3811. *
  3812. * @property {number} width
  3813. * The width of the `Component`s computed style.
  3814. *
  3815. * @property {number} height
  3816. * The height of the `Component`s computed style.
  3817. */
  3818. /**
  3819. * Get an object that contains width and height values of the `Component`s
  3820. * computed style.
  3821. *
  3822. * @return {Component~DimensionObject}
  3823. * The dimensions of the components element
  3824. */
  3825. Component.prototype.currentDimensions = function currentDimensions() {
  3826. return {
  3827. width: this.currentDimension('width'),
  3828. height: this.currentDimension('height')
  3829. };
  3830. };
  3831. /**
  3832. * Get the width of the `Component`s computed style. Uses `window.getComputedStyle`.
  3833. *
  3834. * @return {number} width
  3835. * The width of the `Component`s computed style.
  3836. */
  3837. Component.prototype.currentWidth = function currentWidth() {
  3838. return this.currentDimension('width');
  3839. };
  3840. /**
  3841. * Get the height of the `Component`s computed style. Uses `window.getComputedStyle`.
  3842. *
  3843. * @return {number} height
  3844. * The height of the `Component`s computed style.
  3845. */
  3846. Component.prototype.currentHeight = function currentHeight() {
  3847. return this.currentDimension('height');
  3848. };
  3849. /**
  3850. * Set the focus to this component
  3851. */
  3852. Component.prototype.focus = function focus() {
  3853. this.el_.focus();
  3854. };
  3855. /**
  3856. * Remove the focus from this component
  3857. */
  3858. Component.prototype.blur = function blur() {
  3859. this.el_.blur();
  3860. };
  3861. /**
  3862. * Emit a 'tap' events when touch event support gets detected. This gets used to
  3863. * support toggling the controls through a tap on the video. They get enabled
  3864. * because every sub-component would have extra overhead otherwise.
  3865. *
  3866. * @private
  3867. * @fires Component#tap
  3868. * @listens Component#touchstart
  3869. * @listens Component#touchmove
  3870. * @listens Component#touchleave
  3871. * @listens Component#touchcancel
  3872. * @listens Component#touchend
  3873. */
  3874. Component.prototype.emitTapEvents = function emitTapEvents() {
  3875. // Track the start time so we can determine how long the touch lasted
  3876. var touchStart = 0;
  3877. var firstTouch = null;
  3878. // Maximum movement allowed during a touch event to still be considered a tap
  3879. // Other popular libs use anywhere from 2 (hammer.js) to 15,
  3880. // so 10 seems like a nice, round number.
  3881. var tapMovementThreshold = 10;
  3882. // The maximum length a touch can be while still being considered a tap
  3883. var touchTimeThreshold = 200;
  3884. var couldBeTap = void 0;
  3885. this.on('touchstart', function (event) {
  3886. // If more than one finger, don't consider treating this as a click
  3887. if (event.touches.length === 1) {
  3888. // Copy pageX/pageY from the object
  3889. firstTouch = {
  3890. pageX: event.touches[0].pageX,
  3891. pageY: event.touches[0].pageY
  3892. };
  3893. // Record start time so we can detect a tap vs. "touch and hold"
  3894. touchStart = new Date().getTime();
  3895. // Reset couldBeTap tracking
  3896. couldBeTap = true;
  3897. }
  3898. });
  3899. this.on('touchmove', function (event) {
  3900. // If more than one finger, don't consider treating this as a click
  3901. if (event.touches.length > 1) {
  3902. couldBeTap = false;
  3903. } else if (firstTouch) {
  3904. // Some devices will throw touchmoves for all but the slightest of taps.
  3905. // So, if we moved only a small distance, this could still be a tap
  3906. var xdiff = event.touches[0].pageX - firstTouch.pageX;
  3907. var ydiff = event.touches[0].pageY - firstTouch.pageY;
  3908. var touchDistance = Math.sqrt(xdiff * xdiff + ydiff * ydiff);
  3909. if (touchDistance > tapMovementThreshold) {
  3910. couldBeTap = false;
  3911. }
  3912. }
  3913. });
  3914. var noTap = function noTap() {
  3915. couldBeTap = false;
  3916. };
  3917. // TODO: Listen to the original target. http://youtu.be/DujfpXOKUp8?t=13m8s
  3918. this.on('touchleave', noTap);
  3919. this.on('touchcancel', noTap);
  3920. // When the touch ends, measure how long it took and trigger the appropriate
  3921. // event
  3922. this.on('touchend', function (event) {
  3923. firstTouch = null;
  3924. // Proceed only if the touchmove/leave/cancel event didn't happen
  3925. if (couldBeTap === true) {
  3926. // Measure how long the touch lasted
  3927. var touchTime = new Date().getTime() - touchStart;
  3928. // Make sure the touch was less than the threshold to be considered a tap
  3929. if (touchTime < touchTimeThreshold) {
  3930. // Don't let browser turn this into a click
  3931. event.preventDefault();
  3932. /**
  3933. * Triggered when a `Component` is tapped.
  3934. *
  3935. * @event Component#tap
  3936. * @type {EventTarget~Event}
  3937. */
  3938. this.trigger('tap');
  3939. // It may be good to copy the touchend event object and change the
  3940. // type to tap, if the other event properties aren't exact after
  3941. // Events.fixEvent runs (e.g. event.target)
  3942. }
  3943. }
  3944. });
  3945. };
  3946. /**
  3947. * This function reports user activity whenever touch events happen. This can get
  3948. * turned off by any sub-components that wants touch events to act another way.
  3949. *
  3950. * Report user touch activity when touch events occur. User activity gets used to
  3951. * determine when controls should show/hide. It is simple when it comes to mouse
  3952. * events, because any mouse event should show the controls. So we capture mouse
  3953. * events that bubble up to the player and report activity when that happens.
  3954. * With touch events it isn't as easy as `touchstart` and `touchend` toggle player
  3955. * controls. So touch events can't help us at the player level either.
  3956. *
  3957. * User activity gets checked asynchronously. So what could happen is a tap event
  3958. * on the video turns the controls off. Then the `touchend` event bubbles up to
  3959. * the player. Which, if it reported user activity, would turn the controls right
  3960. * back on. We also don't want to completely block touch events from bubbling up.
  3961. * Furthermore a `touchmove` event and anything other than a tap, should not turn
  3962. * controls back on.
  3963. *
  3964. * @listens Component#touchstart
  3965. * @listens Component#touchmove
  3966. * @listens Component#touchend
  3967. * @listens Component#touchcancel
  3968. */
  3969. Component.prototype.enableTouchActivity = function enableTouchActivity() {
  3970. // Don't continue if the root player doesn't support reporting user activity
  3971. if (!this.player() || !this.player().reportUserActivity) {
  3972. return;
  3973. }
  3974. // listener for reporting that the user is active
  3975. var report = Fn.bind(this.player(), this.player().reportUserActivity);
  3976. var touchHolding = void 0;
  3977. this.on('touchstart', function () {
  3978. report();
  3979. // For as long as the they are touching the device or have their mouse down,
  3980. // we consider them active even if they're not moving their finger or mouse.
  3981. // So we want to continue to update that they are active
  3982. this.clearInterval(touchHolding);
  3983. // report at the same interval as activityCheck
  3984. touchHolding = this.setInterval(report, 250);
  3985. });
  3986. var touchEnd = function touchEnd(event) {
  3987. report();
  3988. // stop the interval that maintains activity if the touch is holding
  3989. this.clearInterval(touchHolding);
  3990. };
  3991. this.on('touchmove', report);
  3992. this.on('touchend', touchEnd);
  3993. this.on('touchcancel', touchEnd);
  3994. };
  3995. /**
  3996. * A callback that has no parameters and is bound into `Component`s context.
  3997. *
  3998. * @callback Component~GenericCallback
  3999. * @this Component
  4000. */
  4001. /**
  4002. * Creates a function that runs after an `x` millisecond timeout. This function is a
  4003. * wrapper around `window.setTimeout`. There are a few reasons to use this one
  4004. * instead though:
  4005. * 1. It gets cleared via {@link Component#clearTimeout} when
  4006. * {@link Component#dispose} gets called.
  4007. * 2. The function callback will gets turned into a {@link Component~GenericCallback}
  4008. *
  4009. * > Note: You can use `window.clearTimeout` on the id returned by this function. This
  4010. * will cause its dispose listener not to get cleaned up! Please use
  4011. * {@link Component#clearTimeout} or {@link Component#dispose}.
  4012. *
  4013. * @param {Component~GenericCallback} fn
  4014. * The function that will be run after `timeout`.
  4015. *
  4016. * @param {number} timeout
  4017. * Timeout in milliseconds to delay before executing the specified function.
  4018. *
  4019. * @return {number}
  4020. * Returns a timeout ID that gets used to identify the timeout. It can also
  4021. * get used in {@link Component#clearTimeout} to clear the timeout that
  4022. * was set.
  4023. *
  4024. * @listens Component#dispose
  4025. * @see [Similar to]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout}
  4026. */
  4027. Component.prototype.setTimeout = function setTimeout(fn, timeout) {
  4028. fn = Fn.bind(this, fn);
  4029. var timeoutId = _window2['default'].setTimeout(fn, timeout);
  4030. var disposeFn = function disposeFn() {
  4031. this.clearTimeout(timeoutId);
  4032. };
  4033. disposeFn.guid = 'vjs-timeout-' + timeoutId;
  4034. this.on('dispose', disposeFn);
  4035. return timeoutId;
  4036. };
  4037. /**
  4038. * Clears a timeout that gets created via `window.setTimeout` or
  4039. * {@link Component#setTimeout}. If you set a timeout via {@link Component#setTimeout}
  4040. * use this function instead of `window.clearTimout`. If you don't your dispose
  4041. * listener will not get cleaned up until {@link Component#dispose}!
  4042. *
  4043. * @param {number} timeoutId
  4044. * The id of the timeout to clear. The return value of
  4045. * {@link Component#setTimeout} or `window.setTimeout`.
  4046. *
  4047. * @return {number}
  4048. * Returns the timeout id that was cleared.
  4049. *
  4050. * @see [Similar to]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/clearTimeout}
  4051. */
  4052. Component.prototype.clearTimeout = function clearTimeout(timeoutId) {
  4053. _window2['default'].clearTimeout(timeoutId);
  4054. var disposeFn = function disposeFn() {};
  4055. disposeFn.guid = 'vjs-timeout-' + timeoutId;
  4056. this.off('dispose', disposeFn);
  4057. return timeoutId;
  4058. };
  4059. /**
  4060. * Creates a function that gets run every `x` milliseconds. This function is a wrapper
  4061. * around `window.setInterval`. There are a few reasons to use this one instead though.
  4062. * 1. It gets cleared via {@link Component#clearInterval} when
  4063. * {@link Component#dispose} gets called.
  4064. * 2. The function callback will be a {@link Component~GenericCallback}
  4065. *
  4066. * @param {Component~GenericCallback} fn
  4067. * The function to run every `x` seconds.
  4068. *
  4069. * @param {number} interval
  4070. * Execute the specified function every `x` milliseconds.
  4071. *
  4072. * @return {number}
  4073. * Returns an id that can be used to identify the interval. It can also be be used in
  4074. * {@link Component#clearInterval} to clear the interval.
  4075. *
  4076. * @listens Component#dispose
  4077. * @see [Similar to]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval}
  4078. */
  4079. Component.prototype.setInterval = function setInterval(fn, interval) {
  4080. fn = Fn.bind(this, fn);
  4081. var intervalId = _window2['default'].setInterval(fn, interval);
  4082. var disposeFn = function disposeFn() {
  4083. this.clearInterval(intervalId);
  4084. };
  4085. disposeFn.guid = 'vjs-interval-' + intervalId;
  4086. this.on('dispose', disposeFn);
  4087. return intervalId;
  4088. };
  4089. /**
  4090. * Clears an interval that gets created via `window.setInterval` or
  4091. * {@link Component#setInterval}. If you set an inteval via {@link Component#setInterval}
  4092. * use this function instead of `window.clearInterval`. If you don't your dispose
  4093. * listener will not get cleaned up until {@link Component#dispose}!
  4094. *
  4095. * @param {number} intervalId
  4096. * The id of the interval to clear. The return value of
  4097. * {@link Component#setInterval} or `window.setInterval`.
  4098. *
  4099. * @return {number}
  4100. * Returns the interval id that was cleared.
  4101. *
  4102. * @see [Similar to]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/clearInterval}
  4103. */
  4104. Component.prototype.clearInterval = function clearInterval(intervalId) {
  4105. _window2['default'].clearInterval(intervalId);
  4106. var disposeFn = function disposeFn() {};
  4107. disposeFn.guid = 'vjs-interval-' + intervalId;
  4108. this.off('dispose', disposeFn);
  4109. return intervalId;
  4110. };
  4111. /**
  4112. * Register a `Component` with `videojs` given the name and the component.
  4113. *
  4114. * > NOTE: {@link Tech}s should not be registered as a `Component`. {@link Tech}s
  4115. * should be registered using {@link Tech.registerTech} or
  4116. * {@link videojs:videojs.registerTech}.
  4117. *
  4118. * > NOTE: This function can also be seen on videojs as
  4119. * {@link videojs:videojs.registerComponent}.
  4120. *
  4121. * @param {string} name
  4122. * The name of the `Component` to register.
  4123. *
  4124. * @param {Component} comp
  4125. * The `Component` class to register.
  4126. *
  4127. * @return {Component}
  4128. * The `Component` that was registered.
  4129. */
  4130. Component.registerComponent = function registerComponent(name, comp) {
  4131. if (!name) {
  4132. return;
  4133. }
  4134. name = (0, _toTitleCase2['default'])(name);
  4135. if (!Component.components_) {
  4136. Component.components_ = {};
  4137. }
  4138. if (name === 'Player' && Component.components_[name]) {
  4139. var Player = Component.components_[name];
  4140. // If we have players that were disposed, then their name will still be
  4141. // in Players.players. So, we must loop through and verify that the value
  4142. // for each item is not null. This allows registration of the Player component
  4143. // after all players have been disposed or before any were created.
  4144. if (Player.players && Object.keys(Player.players).length > 0 && Object.keys(Player.players).map(function (playerName) {
  4145. return Player.players[playerName];
  4146. }).every(Boolean)) {
  4147. throw new Error('Can not register Player component after player has been created');
  4148. }
  4149. }
  4150. Component.components_[name] = comp;
  4151. return comp;
  4152. };
  4153. /**
  4154. * Get a `Component` based on the name it was registered with.
  4155. *
  4156. * @param {string} name
  4157. * The Name of the component to get.
  4158. *
  4159. * @return {Component}
  4160. * The `Component` that got registered under the given name.
  4161. *
  4162. * @deprecated In `videojs` 6 this will not return `Component`s that were not
  4163. * registered using {@link Component.registerComponent}. Currently we
  4164. * check the global `videojs` object for a `Component` name and
  4165. * return that if it exists.
  4166. */
  4167. Component.getComponent = function getComponent(name) {
  4168. if (!name) {
  4169. return;
  4170. }
  4171. name = (0, _toTitleCase2['default'])(name);
  4172. if (Component.components_ && Component.components_[name]) {
  4173. return Component.components_[name];
  4174. }
  4175. if (_window2['default'] && _window2['default'].videojs && _window2['default'].videojs[name]) {
  4176. _log2['default'].warn('The ' + name + ' component was added to the videojs object when it should be registered using videojs.registerComponent(name, component)');
  4177. return _window2['default'].videojs[name];
  4178. }
  4179. };
  4180. /**
  4181. * Sets up the constructor using the supplied init method or uses the init of the
  4182. * parent object.
  4183. *
  4184. * @param {Object} [props={}]
  4185. * An object of properties.
  4186. *
  4187. * @return {Object}
  4188. * the extended object.
  4189. *
  4190. * @deprecated since version 5
  4191. */
  4192. Component.extend = function extend(props) {
  4193. props = props || {};
  4194. _log2['default'].warn('Component.extend({}) has been deprecated, ' + ' use videojs.extend(Component, {}) instead');
  4195. // Set up the constructor using the supplied init method
  4196. // or using the init of the parent object
  4197. // Make sure to check the unobfuscated version for external libs
  4198. var init = props.init || props.init || this.prototype.init || this.prototype.init || function () {};
  4199. // In Resig's simple class inheritance (previously used) the constructor
  4200. // is a function that calls `this.init.apply(arguments)`
  4201. // However that would prevent us from using `ParentObject.call(this);`
  4202. // in a Child constructor because the `this` in `this.init`
  4203. // would still refer to the Child and cause an infinite loop.
  4204. // We would instead have to do
  4205. // `ParentObject.prototype.init.apply(this, arguments);`
  4206. // Bleh. We're not creating a _super() function, so it's good to keep
  4207. // the parent constructor reference simple.
  4208. var subObj = function subObj() {
  4209. init.apply(this, arguments);
  4210. };
  4211. // Inherit from this object's prototype
  4212. subObj.prototype = Object.create(this.prototype);
  4213. // Reset the constructor property for subObj otherwise
  4214. // instances of subObj would have the constructor of the parent Object
  4215. subObj.prototype.constructor = subObj;
  4216. // Make the class extendable
  4217. subObj.extend = Component.extend;
  4218. // Extend subObj's prototype with functions and other properties from props
  4219. for (var name in props) {
  4220. if (props.hasOwnProperty(name)) {
  4221. subObj.prototype[name] = props[name];
  4222. }
  4223. }
  4224. return subObj;
  4225. };
  4226. return Component;
  4227. }();
  4228. Component.registerComponent('Component', Component);
  4229. exports['default'] = Component;
  4230. /***/ }),
  4231. /* 20 */
  4232. /***/ (function(module, exports, __webpack_require__) {
  4233. 'use strict';
  4234. exports.__esModule = true;
  4235. exports.throttle = exports.bind = undefined;
  4236. var _guid = __webpack_require__(12);
  4237. /**
  4238. * Bind (a.k.a proxy or Context). A simple method for changing the context of a function
  4239. * It also stores a unique id on the function so it can be easily removed from events.
  4240. *
  4241. * @param {Mixed} context
  4242. * The object to bind as scope.
  4243. *
  4244. * @param {Function} fn
  4245. * The function to be bound to a scope.
  4246. *
  4247. * @param {number} [uid]
  4248. * An optional unique ID for the function to be set
  4249. *
  4250. * @return {Function}
  4251. * The new function that will be bound into the context given
  4252. */
  4253. var bind = exports.bind = function bind(context, fn, uid) {
  4254. // Make sure the function has a unique ID
  4255. if (!fn.guid) {
  4256. fn.guid = (0, _guid.newGUID)();
  4257. }
  4258. // Create the new function that changes the context
  4259. var bound = function bound() {
  4260. return fn.apply(context, arguments);
  4261. };
  4262. // Allow for the ability to individualize this function
  4263. // Needed in the case where multiple objects might share the same prototype
  4264. // IF both items add an event listener with the same function, then you try to remove just one
  4265. // it will remove both because they both have the same guid.
  4266. // when using this, you need to use the bind method when you remove the listener as well.
  4267. // currently used in text tracks
  4268. bound.guid = uid ? uid + '_' + fn.guid : fn.guid;
  4269. return bound;
  4270. };
  4271. /**
  4272. * Wraps the given function, `fn`, with a new function that only invokes `fn`
  4273. * at most once per every `wait` milliseconds.
  4274. *
  4275. * @param {Function} fn
  4276. * The function to be throttled.
  4277. *
  4278. * @param {Number} wait
  4279. * The number of milliseconds by which to throttle.
  4280. *
  4281. * @return {Function}
  4282. */
  4283. /**
  4284. * @file fn.js
  4285. * @module fn
  4286. */
  4287. var throttle = exports.throttle = function throttle(fn, wait) {
  4288. var last = Date.now();
  4289. var throttled = function throttled() {
  4290. var now = Date.now();
  4291. if (now - last >= wait) {
  4292. fn.apply(undefined, arguments);
  4293. last = now;
  4294. }
  4295. };
  4296. return throttled;
  4297. };
  4298. /***/ }),
  4299. /* 21 */
  4300. /***/ (function(module, exports) {
  4301. 'use strict';
  4302. exports.__esModule = true;
  4303. /**
  4304. * @file to-title-case.js
  4305. * @module to-title-case
  4306. */
  4307. /**
  4308. * Uppercase the first letter of a string.
  4309. *
  4310. * @param {string} string
  4311. * String to be uppercased
  4312. *
  4313. * @return {string}
  4314. * The string with an uppercased first letter
  4315. */
  4316. function toTitleCase(string) {
  4317. if (typeof string !== 'string') {
  4318. return string;
  4319. }
  4320. return string.charAt(0).toUpperCase() + string.slice(1);
  4321. }
  4322. exports['default'] = toTitleCase;
  4323. /***/ }),
  4324. /* 22 */
  4325. /***/ (function(module, exports, __webpack_require__) {
  4326. 'use strict';
  4327. exports.__esModule = true;
  4328. exports['default'] = mergeOptions;
  4329. var _obj = __webpack_require__(14);
  4330. /**
  4331. * Deep-merge one or more options objects, recursively merging **only** plain
  4332. * object properties.
  4333. *
  4334. * @param {Object[]} sources
  4335. * One or more objects to merge into a new object.
  4336. *
  4337. * @returns {Object}
  4338. * A new object that is the merged result of all sources.
  4339. */
  4340. function mergeOptions() {
  4341. var result = {};
  4342. for (var _len = arguments.length, sources = Array(_len), _key = 0; _key < _len; _key++) {
  4343. sources[_key] = arguments[_key];
  4344. }
  4345. sources.forEach(function (source) {
  4346. if (!source) {
  4347. return;
  4348. }
  4349. (0, _obj.each)(source, function (value, key) {
  4350. if (!(0, _obj.isPlain)(value)) {
  4351. result[key] = value;
  4352. return;
  4353. }
  4354. if (!(0, _obj.isPlain)(result[key])) {
  4355. result[key] = {};
  4356. }
  4357. result[key] = mergeOptions(result[key], value);
  4358. });
  4359. });
  4360. return result;
  4361. } /**
  4362. * @file merge-options.js
  4363. * @module merge-options
  4364. */
  4365. /***/ }),
  4366. /* 23 */
  4367. /***/ (function(module, exports, __webpack_require__) {
  4368. 'use strict';
  4369. exports.__esModule = true;
  4370. var _events = __webpack_require__(17);
  4371. var Events = _interopRequireWildcard(_events);
  4372. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  4373. /**
  4374. * `EventTarget` is a class that can have the same API as the DOM `EventTarget`. It
  4375. * adds shorthand functions that wrap around lengthy functions. For example:
  4376. * the `on` function is a wrapper around `addEventListener`.
  4377. *
  4378. * @see [EventTarget Spec]{@link https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget}
  4379. * @class EventTarget
  4380. */
  4381. var EventTarget = function EventTarget() {};
  4382. /**
  4383. * A Custom DOM event.
  4384. *
  4385. * @typedef {Object} EventTarget~Event
  4386. * @see [Properties]{@link https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent}
  4387. */
  4388. /**
  4389. * All event listeners should follow the following format.
  4390. *
  4391. * @callback EventTarget~EventListener
  4392. * @this {EventTarget}
  4393. *
  4394. * @param {EventTarget~Event} event
  4395. * the event that triggered this function
  4396. *
  4397. * @param {Object} [hash]
  4398. * hash of data sent during the event
  4399. */
  4400. /**
  4401. * An object containing event names as keys and booleans as values.
  4402. *
  4403. * > NOTE: If an event name is set to a true value here {@link EventTarget#trigger}
  4404. * will have extra functionality. See that function for more information.
  4405. *
  4406. * @property EventTarget.prototype.allowedEvents_
  4407. * @private
  4408. */
  4409. /**
  4410. * @file src/js/event-target.js
  4411. */
  4412. EventTarget.prototype.allowedEvents_ = {};
  4413. /**
  4414. * Adds an `event listener` to an instance of an `EventTarget`. An `event listener` is a
  4415. * function that will get called when an event with a certain name gets triggered.
  4416. *
  4417. * @param {string|string[]} type
  4418. * An event name or an array of event names.
  4419. *
  4420. * @param {EventTarget~EventListener} fn
  4421. * The function to call with `EventTarget`s
  4422. */
  4423. EventTarget.prototype.on = function (type, fn) {
  4424. // Remove the addEventListener alias before calling Events.on
  4425. // so we don't get into an infinite type loop
  4426. var ael = this.addEventListener;
  4427. this.addEventListener = function () {};
  4428. Events.on(this, type, fn);
  4429. this.addEventListener = ael;
  4430. };
  4431. /**
  4432. * An alias of {@link EventTarget#on}. Allows `EventTarget` to mimic
  4433. * the standard DOM API.
  4434. *
  4435. * @function
  4436. * @see {@link EventTarget#on}
  4437. */
  4438. EventTarget.prototype.addEventListener = EventTarget.prototype.on;
  4439. /**
  4440. * Removes an `event listener` for a specific event from an instance of `EventTarget`.
  4441. * This makes it so that the `event listener` will no longer get called when the
  4442. * named event happens.
  4443. *
  4444. * @param {string|string[]} type
  4445. * An event name or an array of event names.
  4446. *
  4447. * @param {EventTarget~EventListener} fn
  4448. * The function to remove.
  4449. */
  4450. EventTarget.prototype.off = function (type, fn) {
  4451. Events.off(this, type, fn);
  4452. };
  4453. /**
  4454. * An alias of {@link EventTarget#off}. Allows `EventTarget` to mimic
  4455. * the standard DOM API.
  4456. *
  4457. * @function
  4458. * @see {@link EventTarget#off}
  4459. */
  4460. EventTarget.prototype.removeEventListener = EventTarget.prototype.off;
  4461. /**
  4462. * This function will add an `event listener` that gets triggered only once. After the
  4463. * first trigger it will get removed. This is like adding an `event listener`
  4464. * with {@link EventTarget#on} that calls {@link EventTarget#off} on itself.
  4465. *
  4466. * @param {string|string[]} type
  4467. * An event name or an array of event names.
  4468. *
  4469. * @param {EventTarget~EventListener} fn
  4470. * The function to be called once for each event name.
  4471. */
  4472. EventTarget.prototype.one = function (type, fn) {
  4473. // Remove the addEventListener alialing Events.on
  4474. // so we don't get into an infinite type loop
  4475. var ael = this.addEventListener;
  4476. this.addEventListener = function () {};
  4477. Events.one(this, type, fn);
  4478. this.addEventListener = ael;
  4479. };
  4480. /**
  4481. * This function causes an event to happen. This will then cause any `event listeners`
  4482. * that are waiting for that event, to get called. If there are no `event listeners`
  4483. * for an event then nothing will happen.
  4484. *
  4485. * If the name of the `Event` that is being triggered is in `EventTarget.allowedEvents_`.
  4486. * Trigger will also call the `on` + `uppercaseEventName` function.
  4487. *
  4488. * Example:
  4489. * 'click' is in `EventTarget.allowedEvents_`, so, trigger will attempt to call
  4490. * `onClick` if it exists.
  4491. *
  4492. * @param {string|EventTarget~Event|Object} event
  4493. * The name of the event, an `Event`, or an object with a key of type set to
  4494. * an event name.
  4495. */
  4496. EventTarget.prototype.trigger = function (event) {
  4497. var type = event.type || event;
  4498. if (typeof event === 'string') {
  4499. event = { type: type };
  4500. }
  4501. event = Events.fixEvent(event);
  4502. if (this.allowedEvents_[type] && this['on' + type]) {
  4503. this['on' + type](event);
  4504. }
  4505. Events.trigger(this, event);
  4506. };
  4507. /**
  4508. * An alias of {@link EventTarget#trigger}. Allows `EventTarget` to mimic
  4509. * the standard DOM API.
  4510. *
  4511. * @function
  4512. * @see {@link EventTarget#trigger}
  4513. */
  4514. EventTarget.prototype.dispatchEvent = EventTarget.prototype.trigger;
  4515. exports['default'] = EventTarget;
  4516. /***/ }),
  4517. /* 24 */
  4518. /***/ (function(module, exports, __webpack_require__) {
  4519. 'use strict';
  4520. exports.__esModule = true;
  4521. var _component = __webpack_require__(19);
  4522. var _component2 = _interopRequireDefault(_component);
  4523. var _document = __webpack_require__(8);
  4524. var _document2 = _interopRequireDefault(_document);
  4525. var _window = __webpack_require__(7);
  4526. var _window2 = _interopRequireDefault(_window);
  4527. var _events = __webpack_require__(17);
  4528. var Events = _interopRequireWildcard(_events);
  4529. var _dom = __webpack_require__(11);
  4530. var Dom = _interopRequireWildcard(_dom);
  4531. var _fn = __webpack_require__(20);
  4532. var Fn = _interopRequireWildcard(_fn);
  4533. var _guid = __webpack_require__(12);
  4534. var Guid = _interopRequireWildcard(_guid);
  4535. var _browser = __webpack_require__(10);
  4536. var browser = _interopRequireWildcard(_browser);
  4537. var _log = __webpack_require__(13);
  4538. var _log2 = _interopRequireDefault(_log);
  4539. var _toTitleCase = __webpack_require__(21);
  4540. var _toTitleCase2 = _interopRequireDefault(_toTitleCase);
  4541. var _timeRanges = __webpack_require__(25);
  4542. var _buffer = __webpack_require__(26);
  4543. var _stylesheet = __webpack_require__(18);
  4544. var stylesheet = _interopRequireWildcard(_stylesheet);
  4545. var _fullscreenApi = __webpack_require__(27);
  4546. var _fullscreenApi2 = _interopRequireDefault(_fullscreenApi);
  4547. var _mediaError = __webpack_require__(28);
  4548. var _mediaError2 = _interopRequireDefault(_mediaError);
  4549. var _tuple = __webpack_require__(29);
  4550. var _tuple2 = _interopRequireDefault(_tuple);
  4551. var _obj = __webpack_require__(14);
  4552. var _mergeOptions = __webpack_require__(22);
  4553. var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
  4554. var _textTrackListConverter = __webpack_require__(30);
  4555. var _textTrackListConverter2 = _interopRequireDefault(_textTrackListConverter);
  4556. var _modalDialog = __webpack_require__(31);
  4557. var _modalDialog2 = _interopRequireDefault(_modalDialog);
  4558. var _tech = __webpack_require__(32);
  4559. var _tech2 = _interopRequireDefault(_tech);
  4560. var _audioTrackList = __webpack_require__(49);
  4561. var _audioTrackList2 = _interopRequireDefault(_audioTrackList);
  4562. var _videoTrackList = __webpack_require__(48);
  4563. var _videoTrackList2 = _interopRequireDefault(_videoTrackList);
  4564. __webpack_require__(54);
  4565. __webpack_require__(55);
  4566. __webpack_require__(57);
  4567. __webpack_require__(59);
  4568. __webpack_require__(60);
  4569. __webpack_require__(61);
  4570. __webpack_require__(63);
  4571. __webpack_require__(64);
  4572. __webpack_require__(107);
  4573. __webpack_require__(108);
  4574. __webpack_require__(109);
  4575. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  4576. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  4577. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  4578. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  4579. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  4580. * @file player.js
  4581. */
  4582. // Subclasses Component
  4583. // The following imports are used only to ensure that the corresponding modules
  4584. // are always included in the video.js package. Importing the modules will
  4585. // execute them and they will register themselves with video.js.
  4586. // Import Html5 tech, at least for disposing the original video tag.
  4587. // The following tech events are simply re-triggered
  4588. // on the player when they happen
  4589. var TECH_EVENTS_RETRIGGER = [
  4590. /**
  4591. * Fired while the user agent is downloading media data.
  4592. *
  4593. * @event Player#progress
  4594. * @type {EventTarget~Event}
  4595. */
  4596. /**
  4597. * Retrigger the `progress` event that was triggered by the {@link Tech}.
  4598. *
  4599. * @private
  4600. * @method Player#handleTechProgress_
  4601. * @fires Player#progress
  4602. * @listens Tech#progress
  4603. */
  4604. 'progress',
  4605. /**
  4606. * Fires when the loading of an audio/video is aborted.
  4607. *
  4608. * @event Player#abort
  4609. * @type {EventTarget~Event}
  4610. */
  4611. /**
  4612. * Retrigger the `abort` event that was triggered by the {@link Tech}.
  4613. *
  4614. * @private
  4615. * @method Player#handleTechAbort_
  4616. * @fires Player#abort
  4617. * @listens Tech#abort
  4618. */
  4619. 'abort',
  4620. /**
  4621. * Fires when the browser is intentionally not getting media data.
  4622. *
  4623. * @event Player#suspend
  4624. * @type {EventTarget~Event}
  4625. */
  4626. /**
  4627. * Retrigger the `suspend` event that was triggered by the {@link Tech}.
  4628. *
  4629. * @private
  4630. * @method Player#handleTechSuspend_
  4631. * @fires Player#suspend
  4632. * @listens Tech#suspend
  4633. */
  4634. 'suspend',
  4635. /**
  4636. * Fires when the current playlist is empty.
  4637. *
  4638. * @event Player#emptied
  4639. * @type {EventTarget~Event}
  4640. */
  4641. /**
  4642. * Retrigger the `emptied` event that was triggered by the {@link Tech}.
  4643. *
  4644. * @private
  4645. * @method Player#handleTechEmptied_
  4646. * @fires Player#emptied
  4647. * @listens Tech#emptied
  4648. */
  4649. 'emptied',
  4650. /**
  4651. * Fires when the browser is trying to get media data, but data is not available.
  4652. *
  4653. * @event Player#stalled
  4654. * @type {EventTarget~Event}
  4655. */
  4656. /**
  4657. * Retrigger the `stalled` event that was triggered by the {@link Tech}.
  4658. *
  4659. * @private
  4660. * @method Player#handleTechStalled_
  4661. * @fires Player#stalled
  4662. * @listens Tech#stalled
  4663. */
  4664. 'stalled',
  4665. /**
  4666. * Fires when the browser has loaded meta data for the audio/video.
  4667. *
  4668. * @event Player#loadedmetadata
  4669. * @type {EventTarget~Event}
  4670. */
  4671. /**
  4672. * Retrigger the `stalled` event that was triggered by the {@link Tech}.
  4673. *
  4674. * @private
  4675. * @method Player#handleTechLoadedmetadata_
  4676. * @fires Player#loadedmetadata
  4677. * @listens Tech#loadedmetadata
  4678. */
  4679. 'loadedmetadata',
  4680. /**
  4681. * Fires when the browser has loaded the current frame of the audio/video.
  4682. *
  4683. * @event player#loadeddata
  4684. * @type {event}
  4685. */
  4686. /**
  4687. * Retrigger the `loadeddata` event that was triggered by the {@link Tech}.
  4688. *
  4689. * @private
  4690. * @method Player#handleTechLoaddeddata_
  4691. * @fires Player#loadeddata
  4692. * @listens Tech#loadeddata
  4693. */
  4694. 'loadeddata',
  4695. /**
  4696. * Fires when the current playback position has changed.
  4697. *
  4698. * @event player#timeupdate
  4699. * @type {event}
  4700. */
  4701. /**
  4702. * Retrigger the `timeupdate` event that was triggered by the {@link Tech}.
  4703. *
  4704. * @private
  4705. * @method Player#handleTechTimeUpdate_
  4706. * @fires Player#timeupdate
  4707. * @listens Tech#timeupdate
  4708. */
  4709. 'timeupdate',
  4710. /**
  4711. * Fires when the playing speed of the audio/video is changed
  4712. *
  4713. * @event player#ratechange
  4714. * @type {event}
  4715. */
  4716. /**
  4717. * Retrigger the `ratechange` event that was triggered by the {@link Tech}.
  4718. *
  4719. * @private
  4720. * @method Player#handleTechRatechange_
  4721. * @fires Player#ratechange
  4722. * @listens Tech#ratechange
  4723. */
  4724. 'ratechange',
  4725. /**
  4726. * Fires when the volume has been changed
  4727. *
  4728. * @event player#volumechange
  4729. * @type {event}
  4730. */
  4731. /**
  4732. * Retrigger the `volumechange` event that was triggered by the {@link Tech}.
  4733. *
  4734. * @private
  4735. * @method Player#handleTechVolumechange_
  4736. * @fires Player#volumechange
  4737. * @listens Tech#volumechange
  4738. */
  4739. 'volumechange',
  4740. /**
  4741. * Fires when the text track has been changed
  4742. *
  4743. * @event player#texttrackchange
  4744. * @type {event}
  4745. */
  4746. /**
  4747. * Retrigger the `texttrackchange` event that was triggered by the {@link Tech}.
  4748. *
  4749. * @private
  4750. * @method Player#handleTechTexttrackchange_
  4751. * @fires Player#texttrackchange
  4752. * @listens Tech#texttrackchange
  4753. */
  4754. 'texttrackchange'];
  4755. /**
  4756. * An instance of the `Player` class is created when any of the Video.js setup methods
  4757. * are used to initialize a video.
  4758. *
  4759. * After an instance has been created it can be accessed globally in two ways:
  4760. * 1. By calling `videojs('example_video_1');`
  4761. * 2. By using it directly via `videojs.players.example_video_1;`
  4762. *
  4763. * @extends Component
  4764. */
  4765. var Player = function (_Component) {
  4766. _inherits(Player, _Component);
  4767. /**
  4768. * Create an instance of this class.
  4769. *
  4770. * @param {Element} tag
  4771. * The original video DOM element used for configuring options.
  4772. *
  4773. * @param {Object} [options]
  4774. * Object of option names and values.
  4775. *
  4776. * @param {Component~ReadyCallback} [ready]
  4777. * Ready callback function.
  4778. */
  4779. function Player(tag, options, ready) {
  4780. _classCallCheck(this, Player);
  4781. // Make sure tag ID exists
  4782. tag.id = tag.id || 'vjs_video_' + Guid.newGUID();
  4783. // Set Options
  4784. // The options argument overrides options set in the video tag
  4785. // which overrides globally set options.
  4786. // This latter part coincides with the load order
  4787. // (tag must exist before Player)
  4788. options = (0, _obj.assign)(Player.getTagSettings(tag), options);
  4789. // Delay the initialization of children because we need to set up
  4790. // player properties first, and can't use `this` before `super()`
  4791. options.initChildren = false;
  4792. // Same with creating the element
  4793. options.createEl = false;
  4794. // we don't want the player to report touch activity on itself
  4795. // see enableTouchActivity in Component
  4796. options.reportTouchActivity = false;
  4797. // If language is not set, get the closest lang attribute
  4798. if (!options.language) {
  4799. if (typeof tag.closest === 'function') {
  4800. var closest = tag.closest('[lang]');
  4801. if (closest) {
  4802. options.language = closest.getAttribute('lang');
  4803. }
  4804. } else {
  4805. var element = tag;
  4806. while (element && element.nodeType === 1) {
  4807. if (Dom.getElAttributes(element).hasOwnProperty('lang')) {
  4808. options.language = element.getAttribute('lang');
  4809. break;
  4810. }
  4811. element = element.parentNode;
  4812. }
  4813. }
  4814. }
  4815. // Run base component initializing with new options
  4816. // if the global option object was accidentally blown away by
  4817. // someone, bail early with an informative error
  4818. var _this = _possibleConstructorReturn(this, _Component.call(this, null, options, ready));
  4819. if (!_this.options_ || !_this.options_.techOrder || !_this.options_.techOrder.length) {
  4820. throw new Error('No techOrder specified. Did you overwrite ' + 'videojs.options instead of just changing the ' + 'properties you want to override?');
  4821. }
  4822. // Store the original tag used to set options
  4823. _this.tag = tag;
  4824. // Store the tag attributes used to restore html5 element
  4825. _this.tagAttributes = tag && Dom.getElAttributes(tag);
  4826. // Update current language
  4827. _this.language(_this.options_.language);
  4828. // Update Supported Languages
  4829. if (options.languages) {
  4830. // Normalise player option languages to lowercase
  4831. var languagesToLower = {};
  4832. Object.getOwnPropertyNames(options.languages).forEach(function (name) {
  4833. languagesToLower[name.toLowerCase()] = options.languages[name];
  4834. });
  4835. _this.languages_ = languagesToLower;
  4836. } else {
  4837. _this.languages_ = Player.prototype.options_.languages;
  4838. }
  4839. // Cache for video property values.
  4840. _this.cache_ = {};
  4841. // Set poster
  4842. _this.poster_ = options.poster || '';
  4843. // Set controls
  4844. _this.controls_ = !!options.controls;
  4845. // Original tag settings stored in options
  4846. // now remove immediately so native controls don't flash.
  4847. // May be turned back on by HTML5 tech if nativeControlsForTouch is true
  4848. tag.controls = false;
  4849. /*
  4850. * Store the internal state of scrubbing
  4851. *
  4852. * @private
  4853. * @return {Boolean} True if the user is scrubbing
  4854. */
  4855. _this.scrubbing_ = false;
  4856. _this.el_ = _this.createEl();
  4857. // We also want to pass the original player options to each component and plugin
  4858. // as well so they don't need to reach back into the player for options later.
  4859. // We also need to do another copy of this.options_ so we don't end up with
  4860. // an infinite loop.
  4861. var playerOptionsCopy = (0, _mergeOptions2['default'])(_this.options_);
  4862. // Load plugins
  4863. if (options.plugins) {
  4864. var plugins = options.plugins;
  4865. Object.getOwnPropertyNames(plugins).forEach(function (name) {
  4866. if (typeof this[name] === 'function') {
  4867. this[name](plugins[name]);
  4868. } else {
  4869. _log2['default'].error('Unable to find plugin:', name);
  4870. }
  4871. }, _this);
  4872. }
  4873. _this.options_.playerOptions = playerOptionsCopy;
  4874. _this.initChildren();
  4875. // Set isAudio based on whether or not an audio tag was used
  4876. _this.isAudio(tag.nodeName.toLowerCase() === 'audio');
  4877. // Update controls className. Can't do this when the controls are initially
  4878. // set because the element doesn't exist yet.
  4879. if (_this.controls()) {
  4880. _this.addClass('vjs-controls-enabled');
  4881. } else {
  4882. _this.addClass('vjs-controls-disabled');
  4883. }
  4884. // Set ARIA label and region role depending on player type
  4885. _this.el_.setAttribute('role', 'region');
  4886. if (_this.isAudio()) {
  4887. _this.el_.setAttribute('aria-label', 'audio player');
  4888. } else {
  4889. _this.el_.setAttribute('aria-label', 'video player');
  4890. }
  4891. if (_this.isAudio()) {
  4892. _this.addClass('vjs-audio');
  4893. }
  4894. if (_this.flexNotSupported_()) {
  4895. _this.addClass('vjs-no-flex');
  4896. }
  4897. // TODO: Make this smarter. Toggle user state between touching/mousing
  4898. // using events, since devices can have both touch and mouse events.
  4899. // if (browser.TOUCH_ENABLED) {
  4900. // this.addClass('vjs-touch-enabled');
  4901. // }
  4902. // iOS Safari has broken hover handling
  4903. if (!browser.IS_IOS) {
  4904. _this.addClass('vjs-workinghover');
  4905. }
  4906. // Make player easily findable by ID
  4907. Player.players[_this.id_] = _this;
  4908. // Add a major version class to aid css in plugins
  4909. var majorVersion = '5.20.3'.split('.')[0];
  4910. _this.addClass('vjs-v' + majorVersion);
  4911. // When the player is first initialized, trigger activity so components
  4912. // like the control bar show themselves if needed
  4913. _this.userActive(true);
  4914. _this.reportUserActivity();
  4915. _this.listenForUserActivity_();
  4916. _this.on('fullscreenchange', _this.handleFullscreenChange_);
  4917. _this.on('stageclick', _this.handleStageClick_);
  4918. return _this;
  4919. }
  4920. /**
  4921. * Destroys the video player and does any necessary cleanup.
  4922. *
  4923. * This is especially helpful if you are dynamically adding and removing videos
  4924. * to/from the DOM.
  4925. *
  4926. * @fires Player#dispose
  4927. */
  4928. Player.prototype.dispose = function dispose() {
  4929. /**
  4930. * Called when the player is being disposed of.
  4931. *
  4932. * @event Player#dispose
  4933. * @type {EventTarget~Event}
  4934. */
  4935. this.trigger('dispose');
  4936. // prevent dispose from being called twice
  4937. this.off('dispose');
  4938. if (this.styleEl_ && this.styleEl_.parentNode) {
  4939. this.styleEl_.parentNode.removeChild(this.styleEl_);
  4940. }
  4941. // Kill reference to this player
  4942. Player.players[this.id_] = null;
  4943. if (this.tag && this.tag.player) {
  4944. this.tag.player = null;
  4945. }
  4946. if (this.el_ && this.el_.player) {
  4947. this.el_.player = null;
  4948. }
  4949. if (this.tech_) {
  4950. this.tech_.dispose();
  4951. }
  4952. _Component.prototype.dispose.call(this);
  4953. };
  4954. /**
  4955. * Create the `Player`'s DOM element.
  4956. *
  4957. * @return {Element}
  4958. * The DOM element that gets created.
  4959. */
  4960. Player.prototype.createEl = function createEl() {
  4961. var tag = this.tag;
  4962. var el = void 0;
  4963. var playerElIngest = this.playerElIngest_ = tag.parentNode && tag.parentNode.hasAttribute && tag.parentNode.hasAttribute('data-vjs-player');
  4964. if (playerElIngest) {
  4965. el = this.el_ = tag.parentNode;
  4966. } else {
  4967. el = this.el_ = _Component.prototype.createEl.call(this, 'div');
  4968. }
  4969. // set tabindex to -1 so we could focus on the player element
  4970. tag.setAttribute('tabindex', '-1');
  4971. // Remove width/height attrs from tag so CSS can make it 100% width/height
  4972. tag.removeAttribute('width');
  4973. tag.removeAttribute('height');
  4974. // Copy over all the attributes from the tag, including ID and class
  4975. // ID will now reference player box, not the video tag
  4976. var attrs = Dom.getElAttributes(tag);
  4977. Object.getOwnPropertyNames(attrs).forEach(function (attr) {
  4978. // workaround so we don't totally break IE7
  4979. // http://stackoverflow.com/questions/3653444/css-styles-not-applied-on-dynamic-elements-in-internet-explorer-7
  4980. if (attr === 'class') {
  4981. el.className += ' ' + attrs[attr];
  4982. } else {
  4983. el.setAttribute(attr, attrs[attr]);
  4984. }
  4985. });
  4986. // Update tag id/class for use as HTML5 playback tech
  4987. // Might think we should do this after embedding in container so .vjs-tech class
  4988. // doesn't flash 100% width/height, but class only applies with .video-js parent
  4989. tag.playerId = tag.id;
  4990. tag.id += '_html5_api';
  4991. tag.className = 'vjs-tech';
  4992. // Make player findable on elements
  4993. tag.player = el.player = this;
  4994. // Default state of video is paused
  4995. this.addClass('vjs-paused');
  4996. // Add a style element in the player that we'll use to set the width/height
  4997. // of the player in a way that's still overrideable by CSS, just like the
  4998. // video element
  4999. if (_window2['default'].VIDEOJS_NO_DYNAMIC_STYLE !== true) {
  5000. this.styleEl_ = stylesheet.createStyleElement('vjs-styles-dimensions');
  5001. var defaultsStyleEl = Dom.$('.vjs-styles-defaults');
  5002. var head = Dom.$('head');
  5003. head.insertBefore(this.styleEl_, defaultsStyleEl ? defaultsStyleEl.nextSibling : head.firstChild);
  5004. }
  5005. // Pass in the width/height/aspectRatio options which will update the style el
  5006. this.width(this.options_.width);
  5007. this.height(this.options_.height);
  5008. this.fluid(this.options_.fluid);
  5009. this.aspectRatio(this.options_.aspectRatio);
  5010. // Hide any links within the video/audio tag, because IE doesn't hide them completely.
  5011. var links = tag.getElementsByTagName('a');
  5012. for (var i = 0; i < links.length; i++) {
  5013. var linkEl = links.item(i);
  5014. Dom.addElClass(linkEl, 'vjs-hidden');
  5015. linkEl.setAttribute('hidden', 'hidden');
  5016. }
  5017. // insertElFirst seems to cause the networkState to flicker from 3 to 2, so
  5018. // keep track of the original for later so we can know if the source originally failed
  5019. tag.initNetworkState_ = tag.networkState;
  5020. // Wrap video tag in div (el/box) container
  5021. if (tag.parentNode && !playerElIngest) {
  5022. tag.parentNode.insertBefore(el, tag);
  5023. }
  5024. // insert the tag as the first child of the player element
  5025. // then manually add it to the children array so that this.addChild
  5026. // will work properly for other components
  5027. //
  5028. // Breaks iPhone, fixed in HTML5 setup.
  5029. Dom.insertElFirst(tag, el);
  5030. this.children_.unshift(tag);
  5031. this.el_ = el;
  5032. return el;
  5033. };
  5034. /**
  5035. * A getter/setter for the `Player`'s width.
  5036. *
  5037. * @param {number} [value]
  5038. * The value to set the `Player's width to.
  5039. *
  5040. * @return {number}
  5041. * The current width of the `Player`.
  5042. */
  5043. Player.prototype.width = function width(value) {
  5044. return this.dimension('width', value);
  5045. };
  5046. /**
  5047. * A getter/setter for the `Player`'s height.
  5048. *
  5049. * @param {number} [value]
  5050. * The value to set the `Player's heigth to.
  5051. *
  5052. * @return {number}
  5053. * The current heigth of the `Player`.
  5054. */
  5055. Player.prototype.height = function height(value) {
  5056. return this.dimension('height', value);
  5057. };
  5058. /**
  5059. * A getter/setter for the `Player`'s width & height.
  5060. *
  5061. * @param {string} dimension
  5062. * This string can be:
  5063. * - 'width'
  5064. * - 'height'
  5065. *
  5066. * @param {number} [value]
  5067. * Value for dimension specified in the first argument.
  5068. *
  5069. * @return {Player|number}
  5070. * - Returns itself when setting; method can be chained.
  5071. * - The dimension arguments value when getting (width/height).
  5072. */
  5073. Player.prototype.dimension = function dimension(_dimension, value) {
  5074. var privDimension = _dimension + '_';
  5075. if (value === undefined) {
  5076. return this[privDimension] || 0;
  5077. }
  5078. if (value === '') {
  5079. // If an empty string is given, reset the dimension to be automatic
  5080. this[privDimension] = undefined;
  5081. } else {
  5082. var parsedVal = parseFloat(value);
  5083. if (isNaN(parsedVal)) {
  5084. _log2['default'].error('Improper value "' + value + '" supplied for for ' + _dimension);
  5085. return this;
  5086. }
  5087. this[privDimension] = parsedVal;
  5088. }
  5089. this.updateStyleEl_();
  5090. return this;
  5091. };
  5092. /**
  5093. * A getter/setter/toggler for the vjs-fluid `className` on the `Player`.
  5094. *
  5095. * @param {boolean} [bool]
  5096. * - A value of true adds the class.
  5097. * - A value of false removes the class.
  5098. * - No value will toggle the fluid class.
  5099. *
  5100. * @return {boolean|undefined}
  5101. * - The value of fluid when getting.
  5102. * - `undefined` when setting.
  5103. */
  5104. Player.prototype.fluid = function fluid(bool) {
  5105. if (bool === undefined) {
  5106. return !!this.fluid_;
  5107. }
  5108. this.fluid_ = !!bool;
  5109. if (bool) {
  5110. this.addClass('vjs-fluid');
  5111. } else {
  5112. this.removeClass('vjs-fluid');
  5113. }
  5114. this.updateStyleEl_();
  5115. };
  5116. /**
  5117. * Get/Set the aspect ratio
  5118. *
  5119. * @param {string} [ratio]
  5120. * Aspect ratio for player
  5121. *
  5122. * @return {string|undefined}
  5123. * returns the current aspect ratio when getting
  5124. */
  5125. /**
  5126. * A getter/setter for the `Player`'s aspect ratio.
  5127. *
  5128. * @param {string} [ratio]
  5129. * The value to set the `Player's aspect ratio to.
  5130. *
  5131. * @return {string|undefined}
  5132. * - The current aspect ratio of the `Player` when getting.
  5133. * - undefined when setting
  5134. */
  5135. Player.prototype.aspectRatio = function aspectRatio(ratio) {
  5136. if (ratio === undefined) {
  5137. return this.aspectRatio_;
  5138. }
  5139. // Check for width:height format
  5140. if (!/^\d+\:\d+$/.test(ratio)) {
  5141. throw new Error('Improper value supplied for aspect ratio. The format should be width:height, for example 16:9.');
  5142. }
  5143. this.aspectRatio_ = ratio;
  5144. // We're assuming if you set an aspect ratio you want fluid mode,
  5145. // because in fixed mode you could calculate width and height yourself.
  5146. this.fluid(true);
  5147. this.updateStyleEl_();
  5148. };
  5149. /**
  5150. * Update styles of the `Player` element (height, width and aspect ratio).
  5151. *
  5152. * @private
  5153. * @listens Tech#loadedmetadata
  5154. */
  5155. Player.prototype.updateStyleEl_ = function updateStyleEl_() {
  5156. if (_window2['default'].VIDEOJS_NO_DYNAMIC_STYLE === true) {
  5157. var _width = typeof this.width_ === 'number' ? this.width_ : this.options_.width;
  5158. var _height = typeof this.height_ === 'number' ? this.height_ : this.options_.height;
  5159. var techEl = this.tech_ && this.tech_.el();
  5160. if (techEl) {
  5161. if (_width >= 0) {
  5162. techEl.width = _width;
  5163. }
  5164. if (_height >= 0) {
  5165. techEl.height = _height;
  5166. }
  5167. }
  5168. return;
  5169. }
  5170. var width = void 0;
  5171. var height = void 0;
  5172. var aspectRatio = void 0;
  5173. var idClass = void 0;
  5174. // The aspect ratio is either used directly or to calculate width and height.
  5175. if (this.aspectRatio_ !== undefined && this.aspectRatio_ !== 'auto') {
  5176. // Use any aspectRatio that's been specifically set
  5177. aspectRatio = this.aspectRatio_;
  5178. } else if (this.videoWidth() > 0) {
  5179. // Otherwise try to get the aspect ratio from the video metadata
  5180. aspectRatio = this.videoWidth() + ':' + this.videoHeight();
  5181. } else {
  5182. // Or use a default. The video element's is 2:1, but 16:9 is more common.
  5183. aspectRatio = '16:9';
  5184. }
  5185. // Get the ratio as a decimal we can use to calculate dimensions
  5186. var ratioParts = aspectRatio.split(':');
  5187. var ratioMultiplier = ratioParts[1] / ratioParts[0];
  5188. if (this.width_ !== undefined) {
  5189. // Use any width that's been specifically set
  5190. width = this.width_;
  5191. } else if (this.height_ !== undefined) {
  5192. // Or calulate the width from the aspect ratio if a height has been set
  5193. width = this.height_ / ratioMultiplier;
  5194. } else {
  5195. // Or use the video's metadata, or use the video el's default of 300
  5196. width = this.videoWidth() || 300;
  5197. }
  5198. if (this.height_ !== undefined) {
  5199. // Use any height that's been specifically set
  5200. height = this.height_;
  5201. } else {
  5202. // Otherwise calculate the height from the ratio and the width
  5203. height = width * ratioMultiplier;
  5204. }
  5205. // Ensure the CSS class is valid by starting with an alpha character
  5206. if (/^[^a-zA-Z]/.test(this.id())) {
  5207. idClass = 'dimensions-' + this.id();
  5208. } else {
  5209. idClass = this.id() + '-dimensions';
  5210. }
  5211. // Ensure the right class is still on the player for the style element
  5212. this.addClass(idClass);
  5213. stylesheet.setTextContent(this.styleEl_, '\n .' + idClass + ' {\n width: ' + width + 'px;\n height: ' + height + 'px;\n }\n\n .' + idClass + '.vjs-fluid {\n padding-top: ' + ratioMultiplier * 100 + '%;\n }\n ');
  5214. };
  5215. /**
  5216. * Load/Create an instance of playback {@link Tech} including element
  5217. * and API methods. Then append the `Tech` element in `Player` as a child.
  5218. *
  5219. * @param {string} techName
  5220. * name of the playback technology
  5221. *
  5222. * @param {string} source
  5223. * video source
  5224. *
  5225. * @private
  5226. */
  5227. Player.prototype.loadTech_ = function loadTech_(techName, source) {
  5228. var _this2 = this;
  5229. // Pause and remove current playback technology
  5230. if (this.tech_) {
  5231. this.unloadTech_();
  5232. }
  5233. // get rid of the HTML5 video tag as soon as we are using another tech
  5234. if (techName !== 'Html5' && this.tag) {
  5235. _tech2['default'].getTech('Html5').disposeMediaElement(this.tag);
  5236. this.tag.player = null;
  5237. this.tag = null;
  5238. }
  5239. this.techName_ = techName;
  5240. // Turn off API access because we're loading a new tech that might load asynchronously
  5241. this.isReady_ = false;
  5242. // Grab tech-specific options from player options and add source and parent element to use.
  5243. var techOptions = (0, _obj.assign)({
  5244. source: source,
  5245. 'nativeControlsForTouch': this.options_.nativeControlsForTouch,
  5246. 'playerId': this.id(),
  5247. 'techId': this.id() + '_' + techName + '_api',
  5248. 'videoTracks': this.videoTracks_,
  5249. 'textTracks': this.textTracks_,
  5250. 'audioTracks': this.audioTracks_,
  5251. 'autoplay': this.options_.autoplay,
  5252. 'playsinline': this.options_.playsinline,
  5253. 'preload': this.options_.preload,
  5254. 'loop': this.options_.loop,
  5255. 'muted': this.options_.muted,
  5256. 'poster': this.poster(),
  5257. 'language': this.language(),
  5258. 'playerElIngest': this.playerElIngest_ || false,
  5259. 'vtt.js': this.options_['vtt.js']
  5260. }, this.options_[techName.toLowerCase()]);
  5261. if (this.tag) {
  5262. techOptions.tag = this.tag;
  5263. }
  5264. if (source) {
  5265. this.currentType_ = source.type;
  5266. if (source.src === this.cache_.src && this.cache_.currentTime > 0) {
  5267. techOptions.startTime = this.cache_.currentTime;
  5268. }
  5269. this.cache_.sources = null;
  5270. this.cache_.source = source;
  5271. this.cache_.src = source.src;
  5272. }
  5273. // Initialize tech instance
  5274. var TechComponent = _tech2['default'].getTech(techName);
  5275. // Support old behavior of techs being registered as components.
  5276. // Remove once that deprecated behavior is removed.
  5277. if (!TechComponent) {
  5278. TechComponent = _component2['default'].getComponent(techName);
  5279. }
  5280. this.tech_ = new TechComponent(techOptions);
  5281. // player.triggerReady is always async, so don't need this to be async
  5282. this.tech_.ready(Fn.bind(this, this.handleTechReady_), true);
  5283. _textTrackListConverter2['default'].jsonToTextTracks(this.textTracksJson_ || [], this.tech_);
  5284. // Listen to all HTML5-defined events and trigger them on the player
  5285. TECH_EVENTS_RETRIGGER.forEach(function (event) {
  5286. _this2.on(_this2.tech_, event, _this2['handleTech' + (0, _toTitleCase2['default'])(event) + '_']);
  5287. });
  5288. this.on(this.tech_, 'loadstart', this.handleTechLoadStart_);
  5289. this.on(this.tech_, 'waiting', this.handleTechWaiting_);
  5290. this.on(this.tech_, 'canplay', this.handleTechCanPlay_);
  5291. this.on(this.tech_, 'canplaythrough', this.handleTechCanPlayThrough_);
  5292. this.on(this.tech_, 'playing', this.handleTechPlaying_);
  5293. this.on(this.tech_, 'ended', this.handleTechEnded_);
  5294. this.on(this.tech_, 'seeking', this.handleTechSeeking_);
  5295. this.on(this.tech_, 'seeked', this.handleTechSeeked_);
  5296. this.on(this.tech_, 'play', this.handleTechPlay_);
  5297. this.on(this.tech_, 'firstplay', this.handleTechFirstPlay_);
  5298. this.on(this.tech_, 'pause', this.handleTechPause_);
  5299. this.on(this.tech_, 'durationchange', this.handleTechDurationChange_);
  5300. this.on(this.tech_, 'fullscreenchange', this.handleTechFullscreenChange_);
  5301. this.on(this.tech_, 'error', this.handleTechError_);
  5302. this.on(this.tech_, 'loadedmetadata', this.updateStyleEl_);
  5303. this.on(this.tech_, 'posterchange', this.handleTechPosterChange_);
  5304. this.on(this.tech_, 'textdata', this.handleTechTextData_);
  5305. this.usingNativeControls(this.techGet_('controls'));
  5306. if (this.controls() && !this.usingNativeControls()) {
  5307. this.addTechControlsListeners_();
  5308. }
  5309. // Add the tech element in the DOM if it was not already there
  5310. // Make sure to not insert the original video element if using Html5
  5311. if (this.tech_.el().parentNode !== this.el() && (techName !== 'Html5' || !this.tag)) {
  5312. Dom.insertElFirst(this.tech_.el(), this.el());
  5313. }
  5314. // Get rid of the original video tag reference after the first tech is loaded
  5315. if (this.tag) {
  5316. this.tag.player = null;
  5317. this.tag = null;
  5318. }
  5319. };
  5320. /**
  5321. * Unload and dispose of the current playback {@link Tech}.
  5322. *
  5323. * @private
  5324. */
  5325. Player.prototype.unloadTech_ = function unloadTech_() {
  5326. // Save the current text tracks so that we can reuse the same text tracks with the next tech
  5327. this.videoTracks_ = this.videoTracks();
  5328. this.textTracks_ = this.textTracks();
  5329. this.audioTracks_ = this.audioTracks();
  5330. this.textTracksJson_ = _textTrackListConverter2['default'].textTracksToJson(this.tech_);
  5331. this.isReady_ = false;
  5332. this.tech_.dispose();
  5333. this.tech_ = false;
  5334. };
  5335. /**
  5336. * Return a reference to the current {@link Tech}, but only if given an object with the
  5337. * `IWillNotUseThisInPlugins` property having a true value. This is try and prevent misuse
  5338. * of techs by plugins.
  5339. *
  5340. * @param {Object} safety
  5341. * An object that must contain `{IWillNotUseThisInPlugins: true}`
  5342. *
  5343. * @param {boolean} safety.IWillNotUseThisInPlugins
  5344. * Must be set to true or else this function will throw an error.
  5345. *
  5346. * @return {Tech}
  5347. * The Tech
  5348. */
  5349. Player.prototype.tech = function tech(safety) {
  5350. if (safety && safety.IWillNotUseThisInPlugins) {
  5351. return this.tech_;
  5352. }
  5353. var errorText = '\n Please make sure that you are not using this inside of a plugin.\n To disable this alert and error, please pass in an object with\n `IWillNotUseThisInPlugins` to the `tech` method. See\n https://github.com/videojs/video.js/issues/2617 for more info.\n ';
  5354. _window2['default'].alert(errorText);
  5355. throw new Error(errorText);
  5356. };
  5357. /**
  5358. * Set up click and touch listeners for the playback element
  5359. *
  5360. * - On desktops: a click on the video itself will toggle playback
  5361. * - On mobile devices: a click on the video toggles controls
  5362. * which is done by toggling the user state between active and
  5363. * inactive
  5364. * - A tap can signal that a user has become active or has become inactive
  5365. * e.g. a quick tap on an iPhone movie should reveal the controls. Another
  5366. * quick tap should hide them again (signaling the user is in an inactive
  5367. * viewing state)
  5368. * - In addition to this, we still want the user to be considered inactive after
  5369. * a few seconds of inactivity.
  5370. *
  5371. * > Note: the only part of iOS interaction we can't mimic with this setup
  5372. * is a touch and hold on the video element counting as activity in order to
  5373. * keep the controls showing, but that shouldn't be an issue. A touch and hold
  5374. * on any controls will still keep the user active
  5375. *
  5376. * @private
  5377. */
  5378. Player.prototype.addTechControlsListeners_ = function addTechControlsListeners_() {
  5379. // Make sure to remove all the previous listeners in case we are called multiple times.
  5380. this.removeTechControlsListeners_();
  5381. // Some browsers (Chrome & IE) don't trigger a click on a flash swf, but do
  5382. // trigger mousedown/up.
  5383. // http://stackoverflow.com/questions/1444562/javascript-onclick-event-over-flash-object
  5384. // Any touch events are set to block the mousedown event from happening
  5385. this.on(this.tech_, 'mousedown', this.handleTechClick_);
  5386. // If the controls were hidden we don't want that to change without a tap event
  5387. // so we'll check if the controls were already showing before reporting user
  5388. // activity
  5389. this.on(this.tech_, 'touchstart', this.handleTechTouchStart_);
  5390. this.on(this.tech_, 'touchmove', this.handleTechTouchMove_);
  5391. this.on(this.tech_, 'touchend', this.handleTechTouchEnd_);
  5392. // The tap listener needs to come after the touchend listener because the tap
  5393. // listener cancels out any reportedUserActivity when setting userActive(false)
  5394. this.on(this.tech_, 'tap', this.handleTechTap_);
  5395. };
  5396. /**
  5397. * Remove the listeners used for click and tap controls. This is needed for
  5398. * toggling to controls disabled, where a tap/touch should do nothing.
  5399. *
  5400. * @private
  5401. */
  5402. Player.prototype.removeTechControlsListeners_ = function removeTechControlsListeners_() {
  5403. // We don't want to just use `this.off()` because there might be other needed
  5404. // listeners added by techs that extend this.
  5405. this.off(this.tech_, 'tap', this.handleTechTap_);
  5406. this.off(this.tech_, 'touchstart', this.handleTechTouchStart_);
  5407. this.off(this.tech_, 'touchmove', this.handleTechTouchMove_);
  5408. this.off(this.tech_, 'touchend', this.handleTechTouchEnd_);
  5409. this.off(this.tech_, 'mousedown', this.handleTechClick_);
  5410. };
  5411. /**
  5412. * Player waits for the tech to be ready
  5413. *
  5414. * @private
  5415. */
  5416. Player.prototype.handleTechReady_ = function handleTechReady_() {
  5417. this.triggerReady();
  5418. // Keep the same volume as before
  5419. if (this.cache_.volume) {
  5420. this.techCall_('setVolume', this.cache_.volume);
  5421. }
  5422. // Look if the tech found a higher resolution poster while loading
  5423. this.handleTechPosterChange_();
  5424. // Update the duration if available
  5425. this.handleTechDurationChange_();
  5426. // Chrome and Safari both have issues with autoplay.
  5427. // In Safari (5.1.1), when we move the video element into the container div, autoplay doesn't work.
  5428. // In Chrome (15), if you have autoplay + a poster + no controls, the video gets hidden (but audio plays)
  5429. // This fixes both issues. Need to wait for API, so it updates displays correctly
  5430. if ((this.src() || this.currentSrc()) && this.tag && this.options_.autoplay && this.paused()) {
  5431. try {
  5432. // Chrome Fix. Fixed in Chrome v16.
  5433. delete this.tag.poster;
  5434. } catch (e) {
  5435. (0, _log2['default'])('deleting tag.poster throws in some browsers', e);
  5436. }
  5437. this.play();
  5438. }
  5439. };
  5440. /**
  5441. * Retrigger the `loadstart` event that was triggered by the {@link Tech}. This
  5442. * function will also trigger {@link Player#firstplay} if it is the first loadstart
  5443. * for a video.
  5444. *
  5445. * @fires Player#loadstart
  5446. * @fires Player#firstplay
  5447. * @listens Tech#loadstart
  5448. * @private
  5449. */
  5450. Player.prototype.handleTechLoadStart_ = function handleTechLoadStart_() {
  5451. // TODO: Update to use `emptied` event instead. See #1277.
  5452. this.removeClass('vjs-ended');
  5453. this.removeClass('vjs-seeking');
  5454. // reset the error state
  5455. this.error(null);
  5456. // If it's already playing we want to trigger a firstplay event now.
  5457. // The firstplay event relies on both the play and loadstart events
  5458. // which can happen in any order for a new source
  5459. if (!this.paused()) {
  5460. /**
  5461. * Fired when the user agent begins looking for media data
  5462. *
  5463. * @event Player#loadstart
  5464. * @type {EventTarget~Event}
  5465. */
  5466. this.trigger('loadstart');
  5467. this.trigger('firstplay');
  5468. } else {
  5469. // reset the hasStarted state
  5470. this.hasStarted(false);
  5471. this.trigger('loadstart');
  5472. }
  5473. };
  5474. /**
  5475. * Add/remove the vjs-has-started class
  5476. *
  5477. * @fires Player#firstplay
  5478. *
  5479. * @param {boolean} hasStarted
  5480. * - true: adds the class
  5481. * - false: remove the class
  5482. *
  5483. * @return {boolean}
  5484. * the boolean value of hasStarted
  5485. */
  5486. Player.prototype.hasStarted = function hasStarted(_hasStarted) {
  5487. if (_hasStarted !== undefined) {
  5488. // only update if this is a new value
  5489. if (this.hasStarted_ !== _hasStarted) {
  5490. this.hasStarted_ = _hasStarted;
  5491. if (_hasStarted) {
  5492. this.addClass('vjs-has-started');
  5493. // trigger the firstplay event if this newly has played
  5494. this.trigger('firstplay');
  5495. } else {
  5496. this.removeClass('vjs-has-started');
  5497. }
  5498. }
  5499. return this;
  5500. }
  5501. return !!this.hasStarted_;
  5502. };
  5503. /**
  5504. * Fired whenever the media begins or resumes playback
  5505. *
  5506. * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-play}
  5507. * @fires Player#play
  5508. * @listens Tech#play
  5509. * @private
  5510. */
  5511. Player.prototype.handleTechPlay_ = function handleTechPlay_() {
  5512. this.removeClass('vjs-ended');
  5513. this.removeClass('vjs-paused');
  5514. this.addClass('vjs-playing');
  5515. // hide the poster when the user hits play
  5516. this.hasStarted(true);
  5517. /**
  5518. * Triggered whenever an {@link Tech#play} event happens. Indicates that
  5519. * playback has started or resumed.
  5520. *
  5521. * @event Player#play
  5522. * @type {EventTarget~Event}
  5523. */
  5524. this.trigger('play');
  5525. };
  5526. /**
  5527. * Retrigger the `waiting` event that was triggered by the {@link Tech}.
  5528. *
  5529. * @fires Player#waiting
  5530. * @listens Tech#waiting
  5531. * @private
  5532. */
  5533. Player.prototype.handleTechWaiting_ = function handleTechWaiting_() {
  5534. var _this3 = this;
  5535. this.addClass('vjs-waiting');
  5536. /**
  5537. * A readyState change on the DOM element has caused playback to stop.
  5538. *
  5539. * @event Player#waiting
  5540. * @type {EventTarget~Event}
  5541. */
  5542. this.trigger('waiting');
  5543. this.one('timeupdate', function () {
  5544. return _this3.removeClass('vjs-waiting');
  5545. });
  5546. };
  5547. /**
  5548. * Retrigger the `canplay` event that was triggered by the {@link Tech}.
  5549. * > Note: This is not consistent between browsers. See #1351
  5550. *
  5551. * @fires Player#canplay
  5552. * @listens Tech#canplay
  5553. * @private
  5554. */
  5555. Player.prototype.handleTechCanPlay_ = function handleTechCanPlay_() {
  5556. this.removeClass('vjs-waiting');
  5557. /**
  5558. * The media has a readyState of HAVE_FUTURE_DATA or greater.
  5559. *
  5560. * @event Player#canplay
  5561. * @type {EventTarget~Event}
  5562. */
  5563. this.trigger('canplay');
  5564. };
  5565. /**
  5566. * Retrigger the `canplaythrough` event that was triggered by the {@link Tech}.
  5567. *
  5568. * @fires Player#canplaythrough
  5569. * @listens Tech#canplaythrough
  5570. * @private
  5571. */
  5572. Player.prototype.handleTechCanPlayThrough_ = function handleTechCanPlayThrough_() {
  5573. this.removeClass('vjs-waiting');
  5574. /**
  5575. * The media has a readyState of HAVE_ENOUGH_DATA or greater. This means that the
  5576. * entire media file can be played without buffering.
  5577. *
  5578. * @event Player#canplaythrough
  5579. * @type {EventTarget~Event}
  5580. */
  5581. this.trigger('canplaythrough');
  5582. };
  5583. /**
  5584. * Retrigger the `playing` event that was triggered by the {@link Tech}.
  5585. *
  5586. * @fires Player#playing
  5587. * @listens Tech#playing
  5588. * @private
  5589. */
  5590. Player.prototype.handleTechPlaying_ = function handleTechPlaying_() {
  5591. this.removeClass('vjs-waiting');
  5592. /**
  5593. * The media is no longer blocked from playback, and has started playing.
  5594. *
  5595. * @event Player#playing
  5596. * @type {EventTarget~Event}
  5597. */
  5598. this.trigger('playing');
  5599. };
  5600. /**
  5601. * Retrigger the `seeking` event that was triggered by the {@link Tech}.
  5602. *
  5603. * @fires Player#seeking
  5604. * @listens Tech#seeking
  5605. * @private
  5606. */
  5607. Player.prototype.handleTechSeeking_ = function handleTechSeeking_() {
  5608. this.addClass('vjs-seeking');
  5609. /**
  5610. * Fired whenever the player is jumping to a new time
  5611. *
  5612. * @event Player#seeking
  5613. * @type {EventTarget~Event}
  5614. */
  5615. this.trigger('seeking');
  5616. };
  5617. /**
  5618. * Retrigger the `seeked` event that was triggered by the {@link Tech}.
  5619. *
  5620. * @fires Player#seeked
  5621. * @listens Tech#seeked
  5622. * @private
  5623. */
  5624. Player.prototype.handleTechSeeked_ = function handleTechSeeked_() {
  5625. this.removeClass('vjs-seeking');
  5626. /**
  5627. * Fired when the player has finished jumping to a new time
  5628. *
  5629. * @event Player#seeked
  5630. * @type {EventTarget~Event}
  5631. */
  5632. this.trigger('seeked');
  5633. };
  5634. /**
  5635. * Retrigger the `firstplay` event that was triggered by the {@link Tech}.
  5636. *
  5637. * @fires Player#firstplay
  5638. * @listens Tech#firstplay
  5639. * @deprecated As of 6.0 passing the `starttime` option to the player will be deprecated
  5640. * @private
  5641. */
  5642. Player.prototype.handleTechFirstPlay_ = function handleTechFirstPlay_() {
  5643. // If the first starttime attribute is specified
  5644. // then we will start at the given offset in seconds
  5645. if (this.options_.starttime) {
  5646. _log2['default'].warn('Passing the `starttime` option to the player will be deprecated in 6.0');
  5647. this.currentTime(this.options_.starttime);
  5648. }
  5649. this.addClass('vjs-has-started');
  5650. /**
  5651. * Fired the first time a video is played. Not part of the HLS spec, and this is
  5652. * probably not the best implementation yet, so use sparingly. If you don't have a
  5653. * reason to prevent playback, use `myPlayer.one('play');` instead.
  5654. *
  5655. * @event Player#firstplay
  5656. * @type {EventTarget~Event}
  5657. */
  5658. this.trigger('firstplay');
  5659. };
  5660. /**
  5661. * Retrigger the `pause` event that was triggered by the {@link Tech}.
  5662. *
  5663. * @fires Player#pause
  5664. * @listens Tech#pause
  5665. * @private
  5666. */
  5667. Player.prototype.handleTechPause_ = function handleTechPause_() {
  5668. this.removeClass('vjs-playing');
  5669. this.addClass('vjs-paused');
  5670. /**
  5671. * Fired whenever the media has been paused
  5672. *
  5673. * @event Player#pause
  5674. * @type {EventTarget~Event}
  5675. */
  5676. this.trigger('pause');
  5677. };
  5678. /**
  5679. * Retrigger the `ended` event that was triggered by the {@link Tech}.
  5680. *
  5681. * @fires Player#ended
  5682. * @listens Tech#ended
  5683. * @private
  5684. */
  5685. Player.prototype.handleTechEnded_ = function handleTechEnded_() {
  5686. this.addClass('vjs-ended');
  5687. if (this.options_.loop) {
  5688. this.currentTime(0);
  5689. this.play();
  5690. } else if (!this.paused()) {
  5691. this.pause();
  5692. }
  5693. /**
  5694. * Fired when the end of the media resource is reached (currentTime == duration)
  5695. *
  5696. * @event Player#ended
  5697. * @type {EventTarget~Event}
  5698. */
  5699. this.trigger('ended');
  5700. };
  5701. /**
  5702. * Fired when the duration of the media resource is first known or changed
  5703. *
  5704. * @listens Tech#durationchange
  5705. * @private
  5706. */
  5707. Player.prototype.handleTechDurationChange_ = function handleTechDurationChange_() {
  5708. this.duration(this.techGet_('duration'));
  5709. };
  5710. /**
  5711. * Handle a click on the media element to play/pause
  5712. *
  5713. * @param {EventTarget~Event} event
  5714. * the event that caused this function to trigger
  5715. *
  5716. * @listens Tech#mousedown
  5717. * @private
  5718. */
  5719. Player.prototype.handleTechClick_ = function handleTechClick_(event) {
  5720. // We're using mousedown to detect clicks thanks to Flash, but mousedown
  5721. // will also be triggered with right-clicks, so we need to prevent that
  5722. if (event.button !== 0) {
  5723. return;
  5724. }
  5725. // When controls are disabled a click should not toggle playback because
  5726. // the click is considered a control
  5727. if (this.controls()) {
  5728. if (this.paused()) {
  5729. this.play();
  5730. } else {
  5731. this.pause();
  5732. }
  5733. }
  5734. };
  5735. /**
  5736. * Handle a tap on the media element. It will toggle the user
  5737. * activity state, which hides and shows the controls.
  5738. *
  5739. * @listens Tech#tap
  5740. * @private
  5741. */
  5742. Player.prototype.handleTechTap_ = function handleTechTap_() {
  5743. this.userActive(!this.userActive());
  5744. };
  5745. /**
  5746. * Handle touch to start
  5747. *
  5748. * @listens Tech#touchstart
  5749. * @private
  5750. */
  5751. Player.prototype.handleTechTouchStart_ = function handleTechTouchStart_() {
  5752. this.userWasActive = this.userActive();
  5753. };
  5754. /**
  5755. * Handle touch to move
  5756. *
  5757. * @listens Tech#touchmove
  5758. * @private
  5759. */
  5760. Player.prototype.handleTechTouchMove_ = function handleTechTouchMove_() {
  5761. if (this.userWasActive) {
  5762. this.reportUserActivity();
  5763. }
  5764. };
  5765. /**
  5766. * Handle touch to end
  5767. *
  5768. * @param {EventTarget~Event} event
  5769. * the touchend event that triggered
  5770. * this function
  5771. *
  5772. * @listens Tech#touchend
  5773. * @private
  5774. */
  5775. Player.prototype.handleTechTouchEnd_ = function handleTechTouchEnd_(event) {
  5776. // Stop the mouse events from also happening
  5777. event.preventDefault();
  5778. };
  5779. /**
  5780. * Fired when the player switches in or out of fullscreen mode
  5781. *
  5782. * @private
  5783. * @listens Player#fullscreenchange
  5784. */
  5785. Player.prototype.handleFullscreenChange_ = function handleFullscreenChange_() {
  5786. if (this.isFullscreen()) {
  5787. this.addClass('vjs-fullscreen');
  5788. } else {
  5789. this.removeClass('vjs-fullscreen');
  5790. }
  5791. };
  5792. /**
  5793. * native click events on the SWF aren't triggered on IE11, Win8.1RT
  5794. * use stageclick events triggered from inside the SWF instead
  5795. *
  5796. * @private
  5797. * @listens stageclick
  5798. */
  5799. Player.prototype.handleStageClick_ = function handleStageClick_() {
  5800. this.reportUserActivity();
  5801. };
  5802. /**
  5803. * Handle Tech Fullscreen Change
  5804. *
  5805. * @param {EventTarget~Event} event
  5806. * the fullscreenchange event that triggered this function
  5807. *
  5808. * @param {Object} data
  5809. * the data that was sent with the event
  5810. *
  5811. * @private
  5812. * @listens Tech#fullscreenchange
  5813. * @fires Player#fullscreenchange
  5814. */
  5815. Player.prototype.handleTechFullscreenChange_ = function handleTechFullscreenChange_(event, data) {
  5816. if (data) {
  5817. this.isFullscreen(data.isFullscreen);
  5818. }
  5819. /**
  5820. * Fired when going in and out of fullscreen.
  5821. *
  5822. * @event Player#fullscreenchange
  5823. * @type {EventTarget~Event}
  5824. */
  5825. this.trigger('fullscreenchange');
  5826. };
  5827. /**
  5828. * Fires when an error occurred during the loading of an audio/video.
  5829. *
  5830. * @private
  5831. * @listens Tech#error
  5832. */
  5833. Player.prototype.handleTechError_ = function handleTechError_() {
  5834. var error = this.tech_.error();
  5835. this.error(error);
  5836. };
  5837. /**
  5838. * Retrigger the `textdata` event that was triggered by the {@link Tech}.
  5839. *
  5840. * @fires Player#textdata
  5841. * @listens Tech#textdata
  5842. * @private
  5843. */
  5844. Player.prototype.handleTechTextData_ = function handleTechTextData_() {
  5845. var data = null;
  5846. if (arguments.length > 1) {
  5847. data = arguments[1];
  5848. }
  5849. /**
  5850. * Fires when we get a textdata event from tech
  5851. *
  5852. * @event Player#textdata
  5853. * @type {EventTarget~Event}
  5854. */
  5855. this.trigger('textdata', data);
  5856. };
  5857. /**
  5858. * Get object for cached values.
  5859. *
  5860. * @return {Object}
  5861. * get the current object cache
  5862. */
  5863. Player.prototype.getCache = function getCache() {
  5864. return this.cache_;
  5865. };
  5866. /**
  5867. * Pass values to the playback tech
  5868. *
  5869. * @param {string} [method]
  5870. * the method to call
  5871. *
  5872. * @param {Object} arg
  5873. * the argument to pass
  5874. *
  5875. * @private
  5876. */
  5877. Player.prototype.techCall_ = function techCall_(method, arg) {
  5878. // If it's not ready yet, call method when it is
  5879. if (this.tech_ && !this.tech_.isReady_) {
  5880. this.tech_.ready(function () {
  5881. this[method](arg);
  5882. }, true);
  5883. // Otherwise call method now
  5884. } else {
  5885. try {
  5886. if (this.tech_) {
  5887. this.tech_[method](arg);
  5888. }
  5889. } catch (e) {
  5890. (0, _log2['default'])(e);
  5891. throw e;
  5892. }
  5893. }
  5894. };
  5895. /**
  5896. * Get calls can't wait for the tech, and sometimes don't need to.
  5897. *
  5898. * @param {string} method
  5899. * Tech method
  5900. *
  5901. * @return {Function|undefined}
  5902. * the method or undefined
  5903. *
  5904. * @private
  5905. */
  5906. Player.prototype.techGet_ = function techGet_(method) {
  5907. if (this.tech_ && this.tech_.isReady_) {
  5908. // Flash likes to die and reload when you hide or reposition it.
  5909. // In these cases the object methods go away and we get errors.
  5910. // When that happens we'll catch the errors and inform tech that it's not ready any more.
  5911. try {
  5912. return this.tech_[method]();
  5913. } catch (e) {
  5914. // When building additional tech libs, an expected method may not be defined yet
  5915. if (this.tech_[method] === undefined) {
  5916. (0, _log2['default'])('Video.js: ' + method + ' method not defined for ' + this.techName_ + ' playback technology.', e);
  5917. // When a method isn't available on the object it throws a TypeError
  5918. } else if (e.name === 'TypeError') {
  5919. (0, _log2['default'])('Video.js: ' + method + ' unavailable on ' + this.techName_ + ' playback technology element.', e);
  5920. this.tech_.isReady_ = false;
  5921. } else {
  5922. (0, _log2['default'])(e);
  5923. }
  5924. throw e;
  5925. }
  5926. }
  5927. return;
  5928. };
  5929. /**
  5930. * start media playback
  5931. *
  5932. * @return {Player}
  5933. * A reference to the player object this function was called on
  5934. */
  5935. Player.prototype.play = function play() {
  5936. // Only calls the tech's play if we already have a src loaded
  5937. if (this.src() || this.currentSrc()) {
  5938. this.techCall_('play');
  5939. } else {
  5940. this.tech_.one('loadstart', function () {
  5941. this.play();
  5942. });
  5943. }
  5944. return this;
  5945. };
  5946. /**
  5947. * Pause the video playback
  5948. *
  5949. * @return {Player}
  5950. * A reference to the player object this function was called on
  5951. */
  5952. Player.prototype.pause = function pause() {
  5953. this.techCall_('pause');
  5954. return this;
  5955. };
  5956. /**
  5957. * Check if the player is paused or has yet to play
  5958. *
  5959. * @return {boolean}
  5960. * - false: if the media is currently playing
  5961. * - true: if media is not currently playing
  5962. */
  5963. Player.prototype.paused = function paused() {
  5964. // The initial state of paused should be true (in Safari it's actually false)
  5965. return this.techGet_('paused') === false ? false : true;
  5966. };
  5967. /**
  5968. * Returns whether or not the user is "scrubbing". Scrubbing is
  5969. * when the user has clicked the progress bar handle and is
  5970. * dragging it along the progress bar.
  5971. *
  5972. * @param {boolean} [isScrubbing]
  5973. * wether the user is or is not scrubbing
  5974. *
  5975. * @return {boolean|Player}
  5976. * A instance of the player that called this function when setting,
  5977. * and the value of scrubbing when getting
  5978. */
  5979. Player.prototype.scrubbing = function scrubbing(isScrubbing) {
  5980. if (isScrubbing !== undefined) {
  5981. this.scrubbing_ = !!isScrubbing;
  5982. if (isScrubbing) {
  5983. this.addClass('vjs-scrubbing');
  5984. } else {
  5985. this.removeClass('vjs-scrubbing');
  5986. }
  5987. return this;
  5988. }
  5989. return this.scrubbing_;
  5990. };
  5991. /**
  5992. * Get or set the current time (in seconds)
  5993. *
  5994. * @param {number|string} [seconds]
  5995. * The time to seek to in seconds
  5996. *
  5997. * @return {Player|number}
  5998. * - the current time in seconds when getting
  5999. * - a reference to the current player object when setting
  6000. */
  6001. Player.prototype.currentTime = function currentTime(seconds) {
  6002. if (seconds !== undefined) {
  6003. this.techCall_('setCurrentTime', seconds);
  6004. return this;
  6005. }
  6006. // cache last currentTime and return. default to 0 seconds
  6007. //
  6008. // Caching the currentTime is meant to prevent a massive amount of reads on the tech's
  6009. // currentTime when scrubbing, but may not provide much performance benefit afterall.
  6010. // Should be tested. Also something has to read the actual current time or the cache will
  6011. // never get updated.
  6012. this.cache_.currentTime = this.techGet_('currentTime') || 0;
  6013. return this.cache_.currentTime;
  6014. };
  6015. /**
  6016. * Normally gets the length in time of the video in seconds;
  6017. * in all but the rarest use cases an argument will NOT be passed to the method
  6018. *
  6019. * > **NOTE**: The video must have started loading before the duration can be
  6020. * known, and in the case of Flash, may not be known until the video starts
  6021. * playing.
  6022. *
  6023. * @fires Player#durationchange
  6024. *
  6025. * @param {number} [seconds]
  6026. * The duration of the video to set in seconds
  6027. *
  6028. * @return {number|Player}
  6029. * - The duration of the video in seconds when getting
  6030. * - A reference to the player that called this function
  6031. * when setting
  6032. */
  6033. Player.prototype.duration = function duration(seconds) {
  6034. if (seconds === undefined) {
  6035. // return NaN if the duration is not known
  6036. return this.cache_.duration !== undefined ? this.cache_.duration : NaN;
  6037. }
  6038. seconds = parseFloat(seconds);
  6039. // Standardize on Inifity for signaling video is live
  6040. if (seconds < 0) {
  6041. seconds = Infinity;
  6042. }
  6043. if (seconds !== this.cache_.duration) {
  6044. // Cache the last set value for optimized scrubbing (esp. Flash)
  6045. this.cache_.duration = seconds;
  6046. if (seconds === Infinity) {
  6047. this.addClass('vjs-live');
  6048. } else {
  6049. this.removeClass('vjs-live');
  6050. }
  6051. /**
  6052. * @event Player#durationchange
  6053. * @type {EventTarget~Event}
  6054. */
  6055. this.trigger('durationchange');
  6056. }
  6057. return this;
  6058. };
  6059. /**
  6060. * Calculates how much time is left in the video. Not part
  6061. * of the native video API.
  6062. *
  6063. * @return {number}
  6064. * The time remaining in seconds
  6065. */
  6066. Player.prototype.remainingTime = function remainingTime() {
  6067. return this.duration() - this.currentTime();
  6068. };
  6069. //
  6070. // Kind of like an array of portions of the video that have been downloaded.
  6071. /**
  6072. * Get a TimeRange object with an array of the times of the video
  6073. * that have been downloaded. If you just want the percent of the
  6074. * video that's been downloaded, use bufferedPercent.
  6075. *
  6076. * @see [Buffered Spec]{@link http://dev.w3.org/html5/spec/video.html#dom-media-buffered}
  6077. *
  6078. * @return {TimeRange}
  6079. * A mock TimeRange object (following HTML spec)
  6080. */
  6081. Player.prototype.buffered = function buffered() {
  6082. var buffered = this.techGet_('buffered');
  6083. if (!buffered || !buffered.length) {
  6084. buffered = (0, _timeRanges.createTimeRange)(0, 0);
  6085. }
  6086. return buffered;
  6087. };
  6088. /**
  6089. * Get the percent (as a decimal) of the video that's been downloaded.
  6090. * This method is not a part of the native HTML video API.
  6091. *
  6092. * @return {number}
  6093. * A decimal between 0 and 1 representing the percent
  6094. * that is bufferred 0 being 0% and 1 being 100%
  6095. */
  6096. Player.prototype.bufferedPercent = function bufferedPercent() {
  6097. return (0, _buffer.bufferedPercent)(this.buffered(), this.duration());
  6098. };
  6099. /**
  6100. * Get the ending time of the last buffered time range
  6101. * This is used in the progress bar to encapsulate all time ranges.
  6102. *
  6103. * @return {number}
  6104. * The end of the last buffered time range
  6105. */
  6106. Player.prototype.bufferedEnd = function bufferedEnd() {
  6107. var buffered = this.buffered();
  6108. var duration = this.duration();
  6109. var end = buffered.end(buffered.length - 1);
  6110. if (end > duration) {
  6111. end = duration;
  6112. }
  6113. return end;
  6114. };
  6115. /**
  6116. * Get or set the current volume of the media
  6117. *
  6118. * @param {number} [percentAsDecimal]
  6119. * The new volume as a decimal percent:
  6120. * - 0 is muted/0%/off
  6121. * - 1.0 is 100%/full
  6122. * - 0.5 is half volume or 50%
  6123. *
  6124. * @return {Player|number}
  6125. * a reference to the calling player when setting and the
  6126. * current volume as a percent when getting
  6127. */
  6128. Player.prototype.volume = function volume(percentAsDecimal) {
  6129. var vol = void 0;
  6130. if (percentAsDecimal !== undefined) {
  6131. // Force value to between 0 and 1
  6132. vol = Math.max(0, Math.min(1, parseFloat(percentAsDecimal)));
  6133. this.cache_.volume = vol;
  6134. this.techCall_('setVolume', vol);
  6135. return this;
  6136. }
  6137. // Default to 1 when returning current volume.
  6138. vol = parseFloat(this.techGet_('volume'));
  6139. return isNaN(vol) ? 1 : vol;
  6140. };
  6141. /**
  6142. * Get the current muted state, or turn mute on or off
  6143. *
  6144. * @param {boolean} [muted]
  6145. * - true to mute
  6146. * - false to unmute
  6147. *
  6148. * @return {boolean|Player}
  6149. * - true if mute is on and getting
  6150. * - false if mute is off and getting
  6151. * - A reference to the current player when setting
  6152. */
  6153. Player.prototype.muted = function muted(_muted) {
  6154. if (_muted !== undefined) {
  6155. this.techCall_('setMuted', _muted);
  6156. return this;
  6157. }
  6158. return this.techGet_('muted') || false;
  6159. };
  6160. /**
  6161. * Check if current tech can support native fullscreen
  6162. * (e.g. with built in controls like iOS, so not our flash swf)
  6163. *
  6164. * @return {boolean}
  6165. * if native fullscreen is supported
  6166. */
  6167. Player.prototype.supportsFullScreen = function supportsFullScreen() {
  6168. return this.techGet_('supportsFullScreen') || false;
  6169. };
  6170. /**
  6171. * Check if the player is in fullscreen mode or tell the player that it
  6172. * is or is not in fullscreen mode.
  6173. *
  6174. * > NOTE: As of the latest HTML5 spec, isFullscreen is no longer an official
  6175. * property and instead document.fullscreenElement is used. But isFullscreen is
  6176. * still a valuable property for internal player workings.
  6177. *
  6178. * @param {boolean} [isFS]
  6179. * Set the players current fullscreen state
  6180. *
  6181. * @return {boolean|Player}
  6182. * - true if fullscreen is on and getting
  6183. * - false if fullscreen is off and getting
  6184. * - A reference to the current player when setting
  6185. */
  6186. Player.prototype.isFullscreen = function isFullscreen(isFS) {
  6187. if (isFS !== undefined) {
  6188. this.isFullscreen_ = !!isFS;
  6189. return this;
  6190. }
  6191. return !!this.isFullscreen_;
  6192. };
  6193. /**
  6194. * Increase the size of the video to full screen
  6195. * In some browsers, full screen is not supported natively, so it enters
  6196. * "full window mode", where the video fills the browser window.
  6197. * In browsers and devices that support native full screen, sometimes the
  6198. * browser's default controls will be shown, and not the Video.js custom skin.
  6199. * This includes most mobile devices (iOS, Android) and older versions of
  6200. * Safari.
  6201. *
  6202. * @fires Player#fullscreenchange
  6203. * @return {Player}
  6204. * A reference to the current player
  6205. */
  6206. Player.prototype.requestFullscreen = function requestFullscreen() {
  6207. var fsApi = _fullscreenApi2['default'];
  6208. this.isFullscreen(true);
  6209. if (fsApi.requestFullscreen) {
  6210. // the browser supports going fullscreen at the element level so we can
  6211. // take the controls fullscreen as well as the video
  6212. // Trigger fullscreenchange event after change
  6213. // We have to specifically add this each time, and remove
  6214. // when canceling fullscreen. Otherwise if there's multiple
  6215. // players on a page, they would all be reacting to the same fullscreen
  6216. // events
  6217. Events.on(_document2['default'], fsApi.fullscreenchange, Fn.bind(this, function documentFullscreenChange(e) {
  6218. this.isFullscreen(_document2['default'][fsApi.fullscreenElement]);
  6219. // If cancelling fullscreen, remove event listener.
  6220. if (this.isFullscreen() === false) {
  6221. Events.off(_document2['default'], fsApi.fullscreenchange, documentFullscreenChange);
  6222. }
  6223. /**
  6224. * @event Player#fullscreenchange
  6225. * @type {EventTarget~Event}
  6226. */
  6227. this.trigger('fullscreenchange');
  6228. }));
  6229. this.el_[fsApi.requestFullscreen]();
  6230. } else if (this.tech_.supportsFullScreen()) {
  6231. // we can't take the video.js controls fullscreen but we can go fullscreen
  6232. // with native controls
  6233. this.techCall_('enterFullScreen');
  6234. } else {
  6235. // fullscreen isn't supported so we'll just stretch the video element to
  6236. // fill the viewport
  6237. this.enterFullWindow();
  6238. /**
  6239. * @event Player#fullscreenchange
  6240. * @type {EventTarget~Event}
  6241. */
  6242. this.trigger('fullscreenchange');
  6243. }
  6244. return this;
  6245. };
  6246. /**
  6247. * Return the video to its normal size after having been in full screen mode
  6248. *
  6249. * @fires Player#fullscreenchange
  6250. *
  6251. * @return {Player}
  6252. * A reference to the current player
  6253. */
  6254. Player.prototype.exitFullscreen = function exitFullscreen() {
  6255. var fsApi = _fullscreenApi2['default'];
  6256. this.isFullscreen(false);
  6257. // Check for browser element fullscreen support
  6258. if (fsApi.requestFullscreen) {
  6259. _document2['default'][fsApi.exitFullscreen]();
  6260. } else if (this.tech_.supportsFullScreen()) {
  6261. this.techCall_('exitFullScreen');
  6262. } else {
  6263. this.exitFullWindow();
  6264. /**
  6265. * @event Player#fullscreenchange
  6266. * @type {EventTarget~Event}
  6267. */
  6268. this.trigger('fullscreenchange');
  6269. }
  6270. return this;
  6271. };
  6272. /**
  6273. * When fullscreen isn't supported we can stretch the
  6274. * video container to as wide as the browser will let us.
  6275. *
  6276. * @fires Player#enterFullWindow
  6277. */
  6278. Player.prototype.enterFullWindow = function enterFullWindow() {
  6279. this.isFullWindow = true;
  6280. // Storing original doc overflow value to return to when fullscreen is off
  6281. this.docOrigOverflow = _document2['default'].documentElement.style.overflow;
  6282. // Add listener for esc key to exit fullscreen
  6283. Events.on(_document2['default'], 'keydown', Fn.bind(this, this.fullWindowOnEscKey));
  6284. // Hide any scroll bars
  6285. _document2['default'].documentElement.style.overflow = 'hidden';
  6286. // Apply fullscreen styles
  6287. Dom.addElClass(_document2['default'].body, 'vjs-full-window');
  6288. /**
  6289. * @event Player#enterFullWindow
  6290. * @type {EventTarget~Event}
  6291. */
  6292. this.trigger('enterFullWindow');
  6293. };
  6294. /**
  6295. * Check for call to either exit full window or
  6296. * full screen on ESC key
  6297. *
  6298. * @param {string} event
  6299. * Event to check for key press
  6300. */
  6301. Player.prototype.fullWindowOnEscKey = function fullWindowOnEscKey(event) {
  6302. if (event.keyCode === 27) {
  6303. if (this.isFullscreen() === true) {
  6304. this.exitFullscreen();
  6305. } else {
  6306. this.exitFullWindow();
  6307. }
  6308. }
  6309. };
  6310. /**
  6311. * Exit full window
  6312. *
  6313. * @fires Player#exitFullWindow
  6314. */
  6315. Player.prototype.exitFullWindow = function exitFullWindow() {
  6316. this.isFullWindow = false;
  6317. Events.off(_document2['default'], 'keydown', this.fullWindowOnEscKey);
  6318. // Unhide scroll bars.
  6319. _document2['default'].documentElement.style.overflow = this.docOrigOverflow;
  6320. // Remove fullscreen styles
  6321. Dom.removeElClass(_document2['default'].body, 'vjs-full-window');
  6322. // Resize the box, controller, and poster to original sizes
  6323. // this.positionAll();
  6324. /**
  6325. * @event Player#exitFullWindow
  6326. * @type {EventTarget~Event}
  6327. */
  6328. this.trigger('exitFullWindow');
  6329. };
  6330. /**
  6331. * Check whether the player can play a given mimetype
  6332. *
  6333. * @see https://www.w3.org/TR/2011/WD-html5-20110113/video.html#dom-navigator-canplaytype
  6334. *
  6335. * @param {string} type
  6336. * The mimetype to check
  6337. *
  6338. * @return {string}
  6339. * 'probably', 'maybe', or '' (empty string)
  6340. */
  6341. Player.prototype.canPlayType = function canPlayType(type) {
  6342. var can = void 0;
  6343. // Loop through each playback technology in the options order
  6344. for (var i = 0, j = this.options_.techOrder; i < j.length; i++) {
  6345. var techName = (0, _toTitleCase2['default'])(j[i]);
  6346. var tech = _tech2['default'].getTech(techName);
  6347. // Support old behavior of techs being registered as components.
  6348. // Remove once that deprecated behavior is removed.
  6349. if (!tech) {
  6350. tech = _component2['default'].getComponent(techName);
  6351. }
  6352. // Check if the current tech is defined before continuing
  6353. if (!tech) {
  6354. _log2['default'].error('The "' + techName + '" tech is undefined. Skipped browser support check for that tech.');
  6355. continue;
  6356. }
  6357. // Check if the browser supports this technology
  6358. if (tech.isSupported()) {
  6359. can = tech.canPlayType(type);
  6360. if (can) {
  6361. return can;
  6362. }
  6363. }
  6364. }
  6365. return '';
  6366. };
  6367. /**
  6368. * Select source based on tech-order or source-order
  6369. * Uses source-order selection if `options.sourceOrder` is truthy. Otherwise,
  6370. * defaults to tech-order selection
  6371. *
  6372. * @param {Array} sources
  6373. * The sources for a media asset
  6374. *
  6375. * @return {Object|boolean}
  6376. * Object of source and tech order or false
  6377. */
  6378. Player.prototype.selectSource = function selectSource(sources) {
  6379. var _this4 = this;
  6380. // Get only the techs specified in `techOrder` that exist and are supported by the
  6381. // current platform
  6382. var techs = this.options_.techOrder.map(_toTitleCase2['default']).map(function (techName) {
  6383. // `Component.getComponent(...)` is for support of old behavior of techs
  6384. // being registered as components.
  6385. // Remove once that deprecated behavior is removed.
  6386. return [techName, _tech2['default'].getTech(techName) || _component2['default'].getComponent(techName)];
  6387. }).filter(function (_ref) {
  6388. var techName = _ref[0],
  6389. tech = _ref[1];
  6390. // Check if the current tech is defined before continuing
  6391. if (tech) {
  6392. // Check if the browser supports this technology
  6393. return tech.isSupported();
  6394. }
  6395. _log2['default'].error('The "' + techName + '" tech is undefined. Skipped browser support check for that tech.');
  6396. return false;
  6397. });
  6398. // Iterate over each `innerArray` element once per `outerArray` element and execute
  6399. // `tester` with both. If `tester` returns a non-falsy value, exit early and return
  6400. // that value.
  6401. var findFirstPassingTechSourcePair = function findFirstPassingTechSourcePair(outerArray, innerArray, tester) {
  6402. var found = void 0;
  6403. outerArray.some(function (outerChoice) {
  6404. return innerArray.some(function (innerChoice) {
  6405. found = tester(outerChoice, innerChoice);
  6406. if (found) {
  6407. return true;
  6408. }
  6409. });
  6410. });
  6411. return found;
  6412. };
  6413. var foundSourceAndTech = void 0;
  6414. var flip = function flip(fn) {
  6415. return function (a, b) {
  6416. return fn(b, a);
  6417. };
  6418. };
  6419. var finder = function finder(_ref2, source) {
  6420. var techName = _ref2[0],
  6421. tech = _ref2[1];
  6422. if (tech.canPlaySource(source, _this4.options_[techName.toLowerCase()])) {
  6423. return { source: source, tech: techName };
  6424. }
  6425. };
  6426. // Depending on the truthiness of `options.sourceOrder`, we swap the order of techs and sources
  6427. // to select from them based on their priority.
  6428. if (this.options_.sourceOrder) {
  6429. // Source-first ordering
  6430. foundSourceAndTech = findFirstPassingTechSourcePair(sources, techs, flip(finder));
  6431. } else {
  6432. // Tech-first ordering
  6433. foundSourceAndTech = findFirstPassingTechSourcePair(techs, sources, finder);
  6434. }
  6435. return foundSourceAndTech || false;
  6436. };
  6437. /**
  6438. * The source function updates the video source
  6439. * There are three types of variables you can pass as the argument.
  6440. * **URL string**: A URL to the the video file. Use this method if you are sure
  6441. * the current playback technology (HTML5/Flash) can support the source you
  6442. * provide. Currently only MP4 files can be used in both HTML5 and Flash.
  6443. *
  6444. * @param {Tech~SourceObject|Tech~SourceObject[]} [source]
  6445. * One SourceObject or an array of SourceObjects
  6446. *
  6447. * @return {string|Player}
  6448. * - The current video source when getting
  6449. * - The player when setting
  6450. */
  6451. Player.prototype.src = function src(source) {
  6452. if (source === undefined) {
  6453. return this.techGet_('src');
  6454. }
  6455. var currentTech = _tech2['default'].getTech(this.techName_);
  6456. // Support old behavior of techs being registered as components.
  6457. // Remove once that deprecated behavior is removed.
  6458. if (!currentTech) {
  6459. currentTech = _component2['default'].getComponent(this.techName_);
  6460. }
  6461. // case: Array of source objects to choose from and pick the best to play
  6462. if (Array.isArray(source)) {
  6463. this.sourceList_(source);
  6464. // case: URL String (http://myvideo...)
  6465. } else if (typeof source === 'string') {
  6466. // create a source object from the string
  6467. this.src({ src: source });
  6468. // case: Source object { src: '', type: '' ... }
  6469. } else if (source instanceof Object) {
  6470. // check if the source has a type and the loaded tech cannot play the source
  6471. // if there's no type we'll just try the current tech
  6472. if (source.type && !currentTech.canPlaySource(source, this.options_[this.techName_.toLowerCase()])) {
  6473. // create a source list with the current source and send through
  6474. // the tech loop to check for a compatible technology
  6475. this.sourceList_([source]);
  6476. } else {
  6477. this.cache_.sources = null;
  6478. this.cache_.source = source;
  6479. this.cache_.src = source.src;
  6480. this.currentType_ = source.type || '';
  6481. // wait until the tech is ready to set the source
  6482. this.ready(function () {
  6483. // The setSource tech method was added with source handlers
  6484. // so older techs won't support it
  6485. // We need to check the direct prototype for the case where subclasses
  6486. // of the tech do not support source handlers
  6487. if (currentTech.prototype.hasOwnProperty('setSource')) {
  6488. this.techCall_('setSource', source);
  6489. } else {
  6490. this.techCall_('src', source.src);
  6491. }
  6492. if (this.options_.preload === 'auto') {
  6493. this.load();
  6494. }
  6495. if (this.options_.autoplay) {
  6496. this.play();
  6497. }
  6498. // Set the source synchronously if possible (#2326)
  6499. }, true);
  6500. }
  6501. }
  6502. return this;
  6503. };
  6504. /**
  6505. * Handle an array of source objects
  6506. *
  6507. * @param {Tech~SourceObject[]} sources
  6508. * Array of source objects
  6509. *
  6510. * @private
  6511. */
  6512. Player.prototype.sourceList_ = function sourceList_(sources) {
  6513. var sourceTech = this.selectSource(sources);
  6514. if (sourceTech) {
  6515. if (sourceTech.tech === this.techName_) {
  6516. // if this technology is already loaded, set the source
  6517. this.src(sourceTech.source);
  6518. } else {
  6519. // load this technology with the chosen source
  6520. this.loadTech_(sourceTech.tech, sourceTech.source);
  6521. }
  6522. this.cache_.sources = sources;
  6523. } else {
  6524. // We need to wrap this in a timeout to give folks a chance to add error event handlers
  6525. this.setTimeout(function () {
  6526. this.error({ code: 4, message: this.localize(this.options_.notSupportedMessage) });
  6527. }, 0);
  6528. // we could not find an appropriate tech, but let's still notify the delegate that this is it
  6529. // this needs a better comment about why this is needed
  6530. this.triggerReady();
  6531. }
  6532. };
  6533. /**
  6534. * Begin loading the src data.
  6535. *
  6536. * @return {Player}
  6537. * A reference to the player
  6538. */
  6539. Player.prototype.load = function load() {
  6540. this.techCall_('load');
  6541. return this;
  6542. };
  6543. /**
  6544. * Reset the player. Loads the first tech in the techOrder,
  6545. * and calls `reset` on the tech`.
  6546. *
  6547. * @return {Player}
  6548. * A reference to the player
  6549. */
  6550. Player.prototype.reset = function reset() {
  6551. this.loadTech_((0, _toTitleCase2['default'])(this.options_.techOrder[0]), null);
  6552. this.techCall_('reset');
  6553. return this;
  6554. };
  6555. /**
  6556. * Returns all of the current source objects.
  6557. *
  6558. * @return {Tech~SourceObject[]}
  6559. * The current source objects
  6560. */
  6561. Player.prototype.currentSources = function currentSources() {
  6562. var source = this.currentSource();
  6563. var sources = [];
  6564. // assume `{}` or `{ src }`
  6565. if (Object.keys(source).length !== 0) {
  6566. sources.push(source);
  6567. }
  6568. return this.cache_.sources || sources;
  6569. };
  6570. /**
  6571. * Returns the current source object.
  6572. *
  6573. * @return {Tech~SourceObject}
  6574. * The current source object
  6575. */
  6576. Player.prototype.currentSource = function currentSource() {
  6577. var source = {};
  6578. var src = this.currentSrc();
  6579. if (src) {
  6580. source.src = src;
  6581. }
  6582. return this.cache_.source || source;
  6583. };
  6584. /**
  6585. * Returns the fully qualified URL of the current source value e.g. http://mysite.com/video.mp4
  6586. * Can be used in conjuction with `currentType` to assist in rebuilding the current source object.
  6587. *
  6588. * @return {string}
  6589. * The current source
  6590. */
  6591. Player.prototype.currentSrc = function currentSrc() {
  6592. return this.techGet_('currentSrc') || this.cache_.src || '';
  6593. };
  6594. /**
  6595. * Get the current source type e.g. video/mp4
  6596. * This can allow you rebuild the current source object so that you could load the same
  6597. * source and tech later
  6598. *
  6599. * @return {string}
  6600. * The source MIME type
  6601. */
  6602. Player.prototype.currentType = function currentType() {
  6603. return this.currentType_ || '';
  6604. };
  6605. /**
  6606. * Get or set the preload attribute
  6607. *
  6608. * @param {boolean} [value]
  6609. * - true means that we should preload
  6610. * - false maens that we should not preload
  6611. *
  6612. * @return {string|Player}
  6613. * - the preload attribute value when getting
  6614. * - the player when setting
  6615. */
  6616. Player.prototype.preload = function preload(value) {
  6617. if (value !== undefined) {
  6618. this.techCall_('setPreload', value);
  6619. this.options_.preload = value;
  6620. return this;
  6621. }
  6622. return this.techGet_('preload');
  6623. };
  6624. /**
  6625. * Get or set the autoplay attribute.
  6626. *
  6627. * @param {boolean} [value]
  6628. * - true means that we should autoplay
  6629. * - false maens that we should not autoplay
  6630. *
  6631. * @return {string|Player}
  6632. * - the current value of autoplay
  6633. * - the player when setting
  6634. */
  6635. Player.prototype.autoplay = function autoplay(value) {
  6636. if (value !== undefined) {
  6637. this.techCall_('setAutoplay', value);
  6638. this.options_.autoplay = value;
  6639. return this;
  6640. }
  6641. return this.techGet_('autoplay', value);
  6642. };
  6643. /**
  6644. * Set or unset the playsinline attribute.
  6645. * Playsinline tells the browser that non-fullscreen playback is preferred.
  6646. *
  6647. * @param {boolean} [value]
  6648. * - true means that we should try to play inline by default
  6649. * - false means that we should use the browser's default playback mode,
  6650. * which in most cases is inline. iOS Safari is a notable exception
  6651. * and plays fullscreen by default.
  6652. *
  6653. * @return {string|Player}
  6654. * - the current value of playsinline
  6655. * - the player when setting
  6656. *
  6657. * @see [Spec]{@link https://html.spec.whatwg.org/#attr-video-playsinline}
  6658. */
  6659. Player.prototype.playsinline = function playsinline(value) {
  6660. if (value !== undefined) {
  6661. this.techCall_('setPlaysinline', value);
  6662. this.options_.playsinline = value;
  6663. return this;
  6664. }
  6665. return this.techGet_('playsinline');
  6666. };
  6667. /**
  6668. * Get or set the loop attribute on the video element.
  6669. *
  6670. * @param {boolean} [value]
  6671. * - true means that we should loop the video
  6672. * - false means that we should not loop the video
  6673. *
  6674. * @return {string|Player}
  6675. * - the current value of loop when getting
  6676. * - the player when setting
  6677. */
  6678. Player.prototype.loop = function loop(value) {
  6679. if (value !== undefined) {
  6680. this.techCall_('setLoop', value);
  6681. this.options_.loop = value;
  6682. return this;
  6683. }
  6684. return this.techGet_('loop');
  6685. };
  6686. /**
  6687. * Get or set the poster image source url
  6688. *
  6689. * @fires Player#posterchange
  6690. *
  6691. * @param {string} [src]
  6692. * Poster image source URL
  6693. *
  6694. * @return {string|Player}
  6695. * - the current value of poster when getting
  6696. * - the player when setting
  6697. */
  6698. Player.prototype.poster = function poster(src) {
  6699. if (src === undefined) {
  6700. return this.poster_;
  6701. }
  6702. // The correct way to remove a poster is to set as an empty string
  6703. // other falsey values will throw errors
  6704. if (!src) {
  6705. src = '';
  6706. }
  6707. // update the internal poster variable
  6708. this.poster_ = src;
  6709. // update the tech's poster
  6710. this.techCall_('setPoster', src);
  6711. // alert components that the poster has been set
  6712. /**
  6713. * This event fires when the poster image is changed on the player.
  6714. *
  6715. * @event Player#posterchange
  6716. * @type {EventTarget~Event}
  6717. */
  6718. this.trigger('posterchange');
  6719. return this;
  6720. };
  6721. /**
  6722. * Some techs (e.g. YouTube) can provide a poster source in an
  6723. * asynchronous way. We want the poster component to use this
  6724. * poster source so that it covers up the tech's controls.
  6725. * (YouTube's play button). However we only want to use this
  6726. * soruce if the player user hasn't set a poster through
  6727. * the normal APIs.
  6728. *
  6729. * @fires Player#posterchange
  6730. * @listens Tech#posterchange
  6731. * @private
  6732. */
  6733. Player.prototype.handleTechPosterChange_ = function handleTechPosterChange_() {
  6734. if (!this.poster_ && this.tech_ && this.tech_.poster) {
  6735. this.poster_ = this.tech_.poster() || '';
  6736. // Let components know the poster has changed
  6737. this.trigger('posterchange');
  6738. }
  6739. };
  6740. /**
  6741. * Get or set whether or not the controls are showing.
  6742. *
  6743. * @fires Player#controlsenabled
  6744. *
  6745. * @param {boolean} [bool]
  6746. * - true to turn controls on
  6747. * - false to turn controls off
  6748. *
  6749. * @return {boolean|Player}
  6750. * - the current value of controls when getting
  6751. * - the player when setting
  6752. */
  6753. Player.prototype.controls = function controls(bool) {
  6754. if (bool !== undefined) {
  6755. bool = !!bool;
  6756. // Don't trigger a change event unless it actually changed
  6757. if (this.controls_ !== bool) {
  6758. this.controls_ = bool;
  6759. if (this.usingNativeControls()) {
  6760. this.techCall_('setControls', bool);
  6761. }
  6762. if (bool) {
  6763. this.removeClass('vjs-controls-disabled');
  6764. this.addClass('vjs-controls-enabled');
  6765. /**
  6766. * @event Player#controlsenabled
  6767. * @type {EventTarget~Event}
  6768. */
  6769. this.trigger('controlsenabled');
  6770. if (!this.usingNativeControls()) {
  6771. this.addTechControlsListeners_();
  6772. }
  6773. } else {
  6774. this.removeClass('vjs-controls-enabled');
  6775. this.addClass('vjs-controls-disabled');
  6776. /**
  6777. * @event Player#controlsdisabled
  6778. * @type {EventTarget~Event}
  6779. */
  6780. this.trigger('controlsdisabled');
  6781. if (!this.usingNativeControls()) {
  6782. this.removeTechControlsListeners_();
  6783. }
  6784. }
  6785. }
  6786. return this;
  6787. }
  6788. return !!this.controls_;
  6789. };
  6790. /**
  6791. * Toggle native controls on/off. Native controls are the controls built into
  6792. * devices (e.g. default iPhone controls), Flash, or other techs
  6793. * (e.g. Vimeo Controls)
  6794. * **This should only be set by the current tech, because only the tech knows
  6795. * if it can support native controls**
  6796. *
  6797. * @fires Player#usingnativecontrols
  6798. * @fires Player#usingcustomcontrols
  6799. *
  6800. * @param {boolean} [bool]
  6801. * - true to turn native controls on
  6802. * - false to turn native controls off
  6803. *
  6804. * @return {boolean|Player}
  6805. * - the current value of native controls when getting
  6806. * - the player when setting
  6807. */
  6808. Player.prototype.usingNativeControls = function usingNativeControls(bool) {
  6809. if (bool !== undefined) {
  6810. bool = !!bool;
  6811. // Don't trigger a change event unless it actually changed
  6812. if (this.usingNativeControls_ !== bool) {
  6813. this.usingNativeControls_ = bool;
  6814. if (bool) {
  6815. this.addClass('vjs-using-native-controls');
  6816. /**
  6817. * player is using the native device controls
  6818. *
  6819. * @event Player#usingnativecontrols
  6820. * @type {EventTarget~Event}
  6821. */
  6822. this.trigger('usingnativecontrols');
  6823. } else {
  6824. this.removeClass('vjs-using-native-controls');
  6825. /**
  6826. * player is using the custom HTML controls
  6827. *
  6828. * @event Player#usingcustomcontrols
  6829. * @type {EventTarget~Event}
  6830. */
  6831. this.trigger('usingcustomcontrols');
  6832. }
  6833. }
  6834. return this;
  6835. }
  6836. return !!this.usingNativeControls_;
  6837. };
  6838. /**
  6839. * Set or get the current MediaError
  6840. *
  6841. * @fires Player#error
  6842. *
  6843. * @param {MediaError|string|number} [err]
  6844. * A MediaError or a string/number to be turned
  6845. * into a MediaError
  6846. *
  6847. * @return {MediaError|null|Player}
  6848. * - The current MediaError when getting (or null)
  6849. * - The player when setting
  6850. */
  6851. Player.prototype.error = function error(err) {
  6852. if (err === undefined) {
  6853. return this.error_ || null;
  6854. }
  6855. // restoring to default
  6856. if (err === null) {
  6857. this.error_ = err;
  6858. this.removeClass('vjs-error');
  6859. if (this.errorDisplay) {
  6860. this.errorDisplay.close();
  6861. }
  6862. return this;
  6863. }
  6864. this.error_ = new _mediaError2['default'](err);
  6865. // add the vjs-error classname to the player
  6866. this.addClass('vjs-error');
  6867. // log the name of the error type and any message
  6868. // ie8 just logs "[object object]" if you just log the error object
  6869. _log2['default'].error('(CODE:' + this.error_.code + ' ' + _mediaError2['default'].errorTypes[this.error_.code] + ')', this.error_.message, this.error_);
  6870. /**
  6871. * @event Player#error
  6872. * @type {EventTarget~Event}
  6873. */
  6874. this.trigger('error');
  6875. return this;
  6876. };
  6877. /**
  6878. * Report user activity
  6879. *
  6880. * @param {Object} event
  6881. * Event object
  6882. */
  6883. Player.prototype.reportUserActivity = function reportUserActivity(event) {
  6884. this.userActivity_ = true;
  6885. };
  6886. /**
  6887. * Get/set if user is active
  6888. *
  6889. * @fires Player#useractive
  6890. * @fires Player#userinactive
  6891. *
  6892. * @param {boolean} [bool]
  6893. * - true if the user is active
  6894. * - false if the user is inactive
  6895. * @return {boolean|Player}
  6896. * - the current value of userActive when getting
  6897. * - the player when setting
  6898. */
  6899. Player.prototype.userActive = function userActive(bool) {
  6900. if (bool !== undefined) {
  6901. bool = !!bool;
  6902. if (bool !== this.userActive_) {
  6903. this.userActive_ = bool;
  6904. if (bool) {
  6905. // If the user was inactive and is now active we want to reset the
  6906. // inactivity timer
  6907. this.userActivity_ = true;
  6908. this.removeClass('vjs-user-inactive');
  6909. this.addClass('vjs-user-active');
  6910. /**
  6911. * @event Player#useractive
  6912. * @type {EventTarget~Event}
  6913. */
  6914. this.trigger('useractive');
  6915. } else {
  6916. // We're switching the state to inactive manually, so erase any other
  6917. // activity
  6918. this.userActivity_ = false;
  6919. // Chrome/Safari/IE have bugs where when you change the cursor it can
  6920. // trigger a mousemove event. This causes an issue when you're hiding
  6921. // the cursor when the user is inactive, and a mousemove signals user
  6922. // activity. Making it impossible to go into inactive mode. Specifically
  6923. // this happens in fullscreen when we really need to hide the cursor.
  6924. //
  6925. // When this gets resolved in ALL browsers it can be removed
  6926. // https://code.google.com/p/chromium/issues/detail?id=103041
  6927. if (this.tech_) {
  6928. this.tech_.one('mousemove', function (e) {
  6929. e.stopPropagation();
  6930. e.preventDefault();
  6931. });
  6932. }
  6933. this.removeClass('vjs-user-active');
  6934. this.addClass('vjs-user-inactive');
  6935. /**
  6936. * @event Player#userinactive
  6937. * @type {EventTarget~Event}
  6938. */
  6939. this.trigger('userinactive');
  6940. }
  6941. }
  6942. return this;
  6943. }
  6944. return this.userActive_;
  6945. };
  6946. /**
  6947. * Listen for user activity based on timeout value
  6948. *
  6949. * @private
  6950. */
  6951. Player.prototype.listenForUserActivity_ = function listenForUserActivity_() {
  6952. var mouseInProgress = void 0;
  6953. var lastMoveX = void 0;
  6954. var lastMoveY = void 0;
  6955. var handleActivity = Fn.bind(this, this.reportUserActivity);
  6956. var handleMouseMove = function handleMouseMove(e) {
  6957. // #1068 - Prevent mousemove spamming
  6958. // Chrome Bug: https://code.google.com/p/chromium/issues/detail?id=366970
  6959. if (e.screenX !== lastMoveX || e.screenY !== lastMoveY) {
  6960. lastMoveX = e.screenX;
  6961. lastMoveY = e.screenY;
  6962. handleActivity();
  6963. }
  6964. };
  6965. var handleMouseDown = function handleMouseDown() {
  6966. handleActivity();
  6967. // For as long as the they are touching the device or have their mouse down,
  6968. // we consider them active even if they're not moving their finger or mouse.
  6969. // So we want to continue to update that they are active
  6970. this.clearInterval(mouseInProgress);
  6971. // Setting userActivity=true now and setting the interval to the same time
  6972. // as the activityCheck interval (250) should ensure we never miss the
  6973. // next activityCheck
  6974. mouseInProgress = this.setInterval(handleActivity, 250);
  6975. };
  6976. var handleMouseUp = function handleMouseUp(event) {
  6977. handleActivity();
  6978. // Stop the interval that maintains activity if the mouse/touch is down
  6979. this.clearInterval(mouseInProgress);
  6980. };
  6981. // Any mouse movement will be considered user activity
  6982. this.on('mousedown', handleMouseDown);
  6983. this.on('mousemove', handleMouseMove);
  6984. this.on('mouseup', handleMouseUp);
  6985. // Listen for keyboard navigation
  6986. // Shouldn't need to use inProgress interval because of key repeat
  6987. this.on('keydown', handleActivity);
  6988. this.on('keyup', handleActivity);
  6989. // Run an interval every 250 milliseconds instead of stuffing everything into
  6990. // the mousemove/touchmove function itself, to prevent performance degradation.
  6991. // `this.reportUserActivity` simply sets this.userActivity_ to true, which
  6992. // then gets picked up by this loop
  6993. // http://ejohn.org/blog/learning-from-twitter/
  6994. var inactivityTimeout = void 0;
  6995. this.setInterval(function () {
  6996. // Check to see if mouse/touch activity has happened
  6997. if (this.userActivity_) {
  6998. // Reset the activity tracker
  6999. this.userActivity_ = false;
  7000. // If the user state was inactive, set the state to active
  7001. this.userActive(true);
  7002. // Clear any existing inactivity timeout to start the timer over
  7003. this.clearTimeout(inactivityTimeout);
  7004. var timeout = this.options_.inactivityTimeout;
  7005. if (timeout > 0) {
  7006. // In <timeout> milliseconds, if no more activity has occurred the
  7007. // user will be considered inactive
  7008. inactivityTimeout = this.setTimeout(function () {
  7009. // Protect against the case where the inactivityTimeout can trigger just
  7010. // before the next user activity is picked up by the activity check loop
  7011. // causing a flicker
  7012. if (!this.userActivity_) {
  7013. this.userActive(false);
  7014. }
  7015. }, timeout);
  7016. }
  7017. }
  7018. }, 250);
  7019. };
  7020. /**
  7021. * Gets or sets the current playback rate. A playback rate of
  7022. * 1.0 represents normal speed and 0.5 would indicate half-speed
  7023. * playback, for instance.
  7024. *
  7025. * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-playbackrate
  7026. *
  7027. * @param {number} [rate]
  7028. * New playback rate to set.
  7029. *
  7030. * @return {number|Player}
  7031. * - The current playback rate when getting or 1.0
  7032. * - the player when setting
  7033. */
  7034. Player.prototype.playbackRate = function playbackRate(rate) {
  7035. if (rate !== undefined) {
  7036. this.techCall_('setPlaybackRate', rate);
  7037. return this;
  7038. }
  7039. if (this.tech_ && this.tech_.featuresPlaybackRate) {
  7040. return this.techGet_('playbackRate');
  7041. }
  7042. return 1.0;
  7043. };
  7044. /**
  7045. * Gets or sets the audio flag
  7046. *
  7047. * @param {boolean} bool
  7048. * - true signals that this is an audio player
  7049. * - false signals that this is not an audio player
  7050. *
  7051. * @return {Player|boolean}
  7052. * - the current value of isAudio when getting
  7053. * - the player if setting
  7054. */
  7055. Player.prototype.isAudio = function isAudio(bool) {
  7056. if (bool !== undefined) {
  7057. this.isAudio_ = !!bool;
  7058. return this;
  7059. }
  7060. return !!this.isAudio_;
  7061. };
  7062. /**
  7063. * Get the {@link VideoTrackList}
  7064. *
  7065. * @see https://html.spec.whatwg.org/multipage/embedded-content.html#videotracklist
  7066. *
  7067. * @return {VideoTrackList}
  7068. * the current video track list
  7069. */
  7070. Player.prototype.videoTracks = function videoTracks() {
  7071. // if we have not yet loadTech_, we create videoTracks_
  7072. // these will be passed to the tech during loading
  7073. if (!this.tech_) {
  7074. this.videoTracks_ = this.videoTracks_ || new _videoTrackList2['default']();
  7075. return this.videoTracks_;
  7076. }
  7077. return this.tech_.videoTracks();
  7078. };
  7079. /**
  7080. * Get the {@link AudioTrackList}
  7081. *
  7082. * @see https://html.spec.whatwg.org/multipage/embedded-content.html#audiotracklist
  7083. *
  7084. * @return {AudioTrackList}
  7085. * the current audio track list
  7086. */
  7087. Player.prototype.audioTracks = function audioTracks() {
  7088. // if we have not yet loadTech_, we create videoTracks_
  7089. // these will be passed to the tech during loading
  7090. if (!this.tech_) {
  7091. this.audioTracks_ = this.audioTracks_ || new _audioTrackList2['default']();
  7092. return this.audioTracks_;
  7093. }
  7094. return this.tech_.audioTracks();
  7095. };
  7096. /**
  7097. * Get the {@link TextTrackList}
  7098. *
  7099. * Text tracks are tracks of timed text events.
  7100. * - Captions: text displayed over the video
  7101. * for the hearing impaired
  7102. * - Subtitles: text displayed over the video for
  7103. * those who don't understand language in the video
  7104. * - Chapters: text displayed in a menu allowing the user to jump
  7105. * to particular points (chapters) in the video
  7106. * - Descriptions: (not yet implemented) audio descriptions that are read back to
  7107. * the user by a screen reading device
  7108. *
  7109. * @see http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-texttracks
  7110. *
  7111. * @return {TextTrackList|undefined}
  7112. * The current TextTrackList or undefined if
  7113. * or undefined if we don't have a tech
  7114. */
  7115. Player.prototype.textTracks = function textTracks() {
  7116. // cannot use techGet_ directly because it checks to see whether the tech is ready.
  7117. // Flash is unlikely to be ready in time but textTracks should still work.
  7118. if (this.tech_) {
  7119. return this.tech_.textTracks();
  7120. }
  7121. };
  7122. /**
  7123. * Get the "remote" {@link TextTrackList}. Remote Text Tracks
  7124. * are tracks that were added to the HTML video element and can
  7125. * be removed, whereas normal texttracks cannot be removed.
  7126. *
  7127. *
  7128. * @return {TextTrackList|undefined}
  7129. * The current remote text track list or undefined
  7130. * if we don't have a tech
  7131. */
  7132. Player.prototype.remoteTextTracks = function remoteTextTracks() {
  7133. if (this.tech_) {
  7134. return this.tech_.remoteTextTracks();
  7135. }
  7136. };
  7137. /**
  7138. * Get the "remote" {@link HTMLTrackElementList}.
  7139. * This gives the user all of the DOM elements that match up
  7140. * with the remote {@link TextTrackList}.
  7141. *
  7142. * @return {HTMLTrackElementList}
  7143. * The current remote text track list elements
  7144. * or undefined if we don't have a tech
  7145. */
  7146. Player.prototype.remoteTextTrackEls = function remoteTextTrackEls() {
  7147. if (this.tech_) {
  7148. return this.tech_.remoteTextTrackEls();
  7149. }
  7150. };
  7151. /**
  7152. * A helper method for adding a {@link TextTrack} to our
  7153. * {@link TextTrackList}.
  7154. *
  7155. * In addition to the W3C settings we allow adding additional info through options.
  7156. *
  7157. * @see http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-addtexttrack
  7158. *
  7159. * @param {string} [kind]
  7160. * the kind of TextTrack you are adding
  7161. *
  7162. * @param {string} [label]
  7163. * the label to give the TextTrack label
  7164. *
  7165. * @param {string} [language]
  7166. * the language to set on the TextTrack
  7167. *
  7168. * @return {TextTrack|undefined}
  7169. * the TextTrack that was added or undefined
  7170. * if there is no tech
  7171. */
  7172. Player.prototype.addTextTrack = function addTextTrack(kind, label, language) {
  7173. if (this.tech_) {
  7174. return this.tech_.addTextTrack(kind, label, language);
  7175. }
  7176. };
  7177. /**
  7178. * Create a remote {@link TextTrack} and an {@link HTMLTrackElement}. It will
  7179. * automatically removed from the video element whenever the source changes, unless
  7180. * manualCleanup is set to false.
  7181. *
  7182. * @param {Object} options
  7183. * Options to pass to {@link HTMLTrackElement} during creation. See
  7184. * {@link HTMLTrackElement} for object properties that you should use.
  7185. *
  7186. * @param {boolean} [manualCleanup=true] if set to false, the TextTrack will be
  7187. *
  7188. * @return {HTMLTrackElement}
  7189. * the HTMLTrackElement that was created and added
  7190. * to the HTMLTrackElementList and the remote
  7191. * TextTrackList
  7192. *
  7193. * @deprecated The default value of the "manualCleanup" parameter will default
  7194. * to "false" in upcoming versions of Video.js
  7195. */
  7196. Player.prototype.addRemoteTextTrack = function addRemoteTextTrack(options, manualCleanup) {
  7197. if (this.tech_) {
  7198. return this.tech_.addRemoteTextTrack(options, manualCleanup);
  7199. }
  7200. };
  7201. /**
  7202. * Remove a remote {@link TextTrack} from the respective
  7203. * {@link TextTrackList} and {@link HTMLTrackElementList}.
  7204. *
  7205. * @param {Object} track
  7206. * Remote {@link TextTrack} to remove
  7207. *
  7208. * @return {undefined}
  7209. * does not return anything
  7210. */
  7211. Player.prototype.removeRemoteTextTrack = function removeRemoteTextTrack() {
  7212. var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
  7213. _ref3$track = _ref3.track,
  7214. track = _ref3$track === undefined ? arguments[0] : _ref3$track;
  7215. // destructure the input into an object with a track argument, defaulting to arguments[0]
  7216. // default the whole argument to an empty object if nothing was passed in
  7217. if (this.tech_) {
  7218. return this.tech_.removeRemoteTextTrack(track);
  7219. }
  7220. };
  7221. /**
  7222. * Gets available media playback quality metrics as specified by the W3C's Media
  7223. * Playback Quality API.
  7224. *
  7225. * @see [Spec]{@link https://wicg.github.io/media-playback-quality}
  7226. *
  7227. * @return {Object|undefined}
  7228. * An object with supported media playback quality metrics or undefined if there
  7229. * is no tech or the tech does not support it.
  7230. */
  7231. Player.prototype.getVideoPlaybackQuality = function getVideoPlaybackQuality() {
  7232. return this.techGet_('getVideoPlaybackQuality');
  7233. };
  7234. /**
  7235. * Get video width
  7236. *
  7237. * @return {number}
  7238. * current video width
  7239. */
  7240. Player.prototype.videoWidth = function videoWidth() {
  7241. return this.tech_ && this.tech_.videoWidth && this.tech_.videoWidth() || 0;
  7242. };
  7243. /**
  7244. * Get video height
  7245. *
  7246. * @return {number}
  7247. * current video height
  7248. */
  7249. Player.prototype.videoHeight = function videoHeight() {
  7250. return this.tech_ && this.tech_.videoHeight && this.tech_.videoHeight() || 0;
  7251. };
  7252. // Methods to add support for
  7253. // initialTime: function() { return this.techCall_('initialTime'); },
  7254. // startOffsetTime: function() { return this.techCall_('startOffsetTime'); },
  7255. // played: function() { return this.techCall_('played'); },
  7256. // defaultPlaybackRate: function() { return this.techCall_('defaultPlaybackRate'); },
  7257. // defaultMuted: function() { return this.techCall_('defaultMuted'); }
  7258. /**
  7259. * The player's language code
  7260. * NOTE: The language should be set in the player options if you want the
  7261. * the controls to be built with a specific language. Changing the lanugage
  7262. * later will not update controls text.
  7263. *
  7264. * @param {string} [code]
  7265. * the language code to set the player to
  7266. *
  7267. * @return {string|Player}
  7268. * - The current language code when getting
  7269. * - A reference to the player when setting
  7270. */
  7271. Player.prototype.language = function language(code) {
  7272. if (code === undefined) {
  7273. return this.language_;
  7274. }
  7275. this.language_ = String(code).toLowerCase();
  7276. return this;
  7277. };
  7278. /**
  7279. * Get the player's language dictionary
  7280. * Merge every time, because a newly added plugin might call videojs.addLanguage() at any time
  7281. * Languages specified directly in the player options have precedence
  7282. *
  7283. * @return {Array}
  7284. * An array of of supported languages
  7285. */
  7286. Player.prototype.languages = function languages() {
  7287. return (0, _mergeOptions2['default'])(Player.prototype.options_.languages, this.languages_);
  7288. };
  7289. /**
  7290. * returns a JavaScript object reperesenting the current track
  7291. * information. **DOES not return it as JSON**
  7292. *
  7293. * @return {Object}
  7294. * Object representing the current of track info
  7295. */
  7296. Player.prototype.toJSON = function toJSON() {
  7297. var options = (0, _mergeOptions2['default'])(this.options_);
  7298. var tracks = options.tracks;
  7299. options.tracks = [];
  7300. for (var i = 0; i < tracks.length; i++) {
  7301. var track = tracks[i];
  7302. // deep merge tracks and null out player so no circular references
  7303. track = (0, _mergeOptions2['default'])(track);
  7304. track.player = undefined;
  7305. options.tracks[i] = track;
  7306. }
  7307. return options;
  7308. };
  7309. /**
  7310. * Creates a simple modal dialog (an instance of the {@link ModalDialog}
  7311. * component) that immediately overlays the player with arbitrary
  7312. * content and removes itself when closed.
  7313. *
  7314. * @param {string|Function|Element|Array|null} content
  7315. * Same as {@link ModalDialog#content}'s param of the same name.
  7316. * The most straight-forward usage is to provide a string or DOM
  7317. * element.
  7318. *
  7319. * @param {Object} [options]
  7320. * Extra options which will be passed on to the {@link ModalDialog}.
  7321. *
  7322. * @return {ModalDialog}
  7323. * the {@link ModalDialog} that was created
  7324. */
  7325. Player.prototype.createModal = function createModal(content, options) {
  7326. var _this5 = this;
  7327. options = options || {};
  7328. options.content = content || '';
  7329. var modal = new _modalDialog2['default'](this, options);
  7330. this.addChild(modal);
  7331. modal.on('dispose', function () {
  7332. _this5.removeChild(modal);
  7333. });
  7334. return modal.open();
  7335. };
  7336. /**
  7337. * Gets tag settings
  7338. *
  7339. * @param {Element} tag
  7340. * The player tag
  7341. *
  7342. * @return {Object}
  7343. * An object containing all of the settings
  7344. * for a player tag
  7345. */
  7346. Player.getTagSettings = function getTagSettings(tag) {
  7347. var baseOptions = {
  7348. sources: [],
  7349. tracks: []
  7350. };
  7351. var tagOptions = Dom.getElAttributes(tag);
  7352. var dataSetup = tagOptions['data-setup'];
  7353. if (Dom.hasElClass(tag, 'vjs-fluid')) {
  7354. tagOptions.fluid = true;
  7355. }
  7356. // Check if data-setup attr exists.
  7357. if (dataSetup !== null) {
  7358. // Parse options JSON
  7359. // If empty string, make it a parsable json object.
  7360. var _safeParseTuple = (0, _tuple2['default'])(dataSetup || '{}'),
  7361. err = _safeParseTuple[0],
  7362. data = _safeParseTuple[1];
  7363. if (err) {
  7364. _log2['default'].error(err);
  7365. }
  7366. (0, _obj.assign)(tagOptions, data);
  7367. }
  7368. (0, _obj.assign)(baseOptions, tagOptions);
  7369. // Get tag children settings
  7370. if (tag.hasChildNodes()) {
  7371. var children = tag.childNodes;
  7372. for (var i = 0, j = children.length; i < j; i++) {
  7373. var child = children[i];
  7374. // Change case needed: http://ejohn.org/blog/nodename-case-sensitivity/
  7375. var childName = child.nodeName.toLowerCase();
  7376. if (childName === 'source') {
  7377. baseOptions.sources.push(Dom.getElAttributes(child));
  7378. } else if (childName === 'track') {
  7379. baseOptions.tracks.push(Dom.getElAttributes(child));
  7380. }
  7381. }
  7382. }
  7383. return baseOptions;
  7384. };
  7385. /**
  7386. * Determine wether or not flexbox is supported
  7387. *
  7388. * @return {boolean}
  7389. * - true if flexbox is supported
  7390. * - false if flexbox is not supported
  7391. */
  7392. Player.prototype.flexNotSupported_ = function flexNotSupported_() {
  7393. var elem = _document2['default'].createElement('i');
  7394. // Note: We don't actually use flexBasis (or flexOrder), but it's one of the more
  7395. // common flex features that we can rely on when checking for flex support.
  7396. return !('flexBasis' in elem.style || 'webkitFlexBasis' in elem.style || 'mozFlexBasis' in elem.style || 'msFlexBasis' in elem.style ||
  7397. // IE10-specific (2012 flex spec)
  7398. 'msFlexOrder' in elem.style);
  7399. };
  7400. return Player;
  7401. }(_component2['default']);
  7402. /**
  7403. * Global player list
  7404. *
  7405. * @type {Object}
  7406. */
  7407. Player.players = {};
  7408. var navigator = _window2['default'].navigator;
  7409. /*
  7410. * Player instance options, surfaced using options
  7411. * options = Player.prototype.options_
  7412. * Make changes in options, not here.
  7413. *
  7414. * @type {Object}
  7415. * @private
  7416. */
  7417. Player.prototype.options_ = {
  7418. // Default order of fallback technology
  7419. techOrder: ['html5', 'flash'],
  7420. // techOrder: ['flash','html5'],
  7421. html5: {},
  7422. flash: {},
  7423. // defaultVolume: 0.85,
  7424. defaultVolume: 0.00,
  7425. // default inactivity timeout
  7426. inactivityTimeout: 2000,
  7427. // default playback rates
  7428. playbackRates: [],
  7429. // Add playback rate selection by adding rates
  7430. // 'playbackRates': [0.5, 1, 1.5, 2],
  7431. // Included control sets
  7432. children: ['mediaLoader', 'posterImage', 'textTrackDisplay', 'loadingSpinner', 'bigPlayButton', 'controlBar', 'errorDisplay', 'textTrackSettings'],
  7433. language: navigator && (navigator.languages && navigator.languages[0] || navigator.userLanguage || navigator.language) || 'en',
  7434. // locales and their language translations
  7435. languages: {},
  7436. // Default message to show when a video cannot be played.
  7437. notSupportedMessage: 'No compatible source was found for this media.'
  7438. };
  7439. [
  7440. /**
  7441. * Returns whether or not the player is in the "ended" state.
  7442. *
  7443. * @return {Boolean} True if the player is in the ended state, false if not.
  7444. * @method Player#ended
  7445. */
  7446. 'ended',
  7447. /**
  7448. * Returns whether or not the player is in the "seeking" state.
  7449. *
  7450. * @return {Boolean} True if the player is in the seeking state, false if not.
  7451. * @method Player#seeking
  7452. */
  7453. 'seeking',
  7454. /**
  7455. * Returns the TimeRanges of the media that are currently available
  7456. * for seeking to.
  7457. *
  7458. * @return {TimeRanges} the seekable intervals of the media timeline
  7459. * @method Player#seekable
  7460. */
  7461. 'seekable',
  7462. /**
  7463. * Returns the current state of network activity for the element, from
  7464. * the codes in the list below.
  7465. * - NETWORK_EMPTY (numeric value 0)
  7466. * The element has not yet been initialised. All attributes are in
  7467. * their initial states.
  7468. * - NETWORK_IDLE (numeric value 1)
  7469. * The element's resource selection algorithm is active and has
  7470. * selected a resource, but it is not actually using the network at
  7471. * this time.
  7472. * - NETWORK_LOADING (numeric value 2)
  7473. * The user agent is actively trying to download data.
  7474. * - NETWORK_NO_SOURCE (numeric value 3)
  7475. * The element's resource selection algorithm is active, but it has
  7476. * not yet found a resource to use.
  7477. *
  7478. * @see https://html.spec.whatwg.org/multipage/embedded-content.html#network-states
  7479. * @return {number} the current network activity state
  7480. * @method Player#networkState
  7481. */
  7482. 'networkState',
  7483. /**
  7484. * Returns a value that expresses the current state of the element
  7485. * with respect to rendering the current playback position, from the
  7486. * codes in the list below.
  7487. * - HAVE_NOTHING (numeric value 0)
  7488. * No information regarding the media resource is available.
  7489. * - HAVE_METADATA (numeric value 1)
  7490. * Enough of the resource has been obtained that the duration of the
  7491. * resource is available.
  7492. * - HAVE_CURRENT_DATA (numeric value 2)
  7493. * Data for the immediate current playback position is available.
  7494. * - HAVE_FUTURE_DATA (numeric value 3)
  7495. * Data for the immediate current playback position is available, as
  7496. * well as enough data for the user agent to advance the current
  7497. * playback position in the direction of playback.
  7498. * - HAVE_ENOUGH_DATA (numeric value 4)
  7499. * The user agent estimates that enough data is available for
  7500. * playback to proceed uninterrupted.
  7501. *
  7502. * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-readystate
  7503. * @return {number} the current playback rendering state
  7504. * @method Player#readyState
  7505. */
  7506. 'readyState'].forEach(function (fn) {
  7507. Player.prototype[fn] = function () {
  7508. return this.techGet_(fn);
  7509. };
  7510. });
  7511. TECH_EVENTS_RETRIGGER.forEach(function (event) {
  7512. Player.prototype['handleTech' + (0, _toTitleCase2['default'])(event) + '_'] = function () {
  7513. return this.trigger(event);
  7514. };
  7515. });
  7516. /**
  7517. * Fired when the player has initial duration and dimension information
  7518. *
  7519. * @event Player#loadedmetadata
  7520. * @type {EventTarget~Event}
  7521. */
  7522. /**
  7523. * Fired when the player has downloaded data at the current playback position
  7524. *
  7525. * @event Player#loadeddata
  7526. * @type {EventTarget~Event}
  7527. */
  7528. /**
  7529. * Fired when the current playback position has changed *
  7530. * During playback this is fired every 15-250 milliseconds, depending on the
  7531. * playback technology in use.
  7532. *
  7533. * @event Player#timeupdate
  7534. * @type {EventTarget~Event}
  7535. */
  7536. /**
  7537. * Fired when the volume changes
  7538. *
  7539. * @event Player#volumechange
  7540. * @type {EventTarget~Event}
  7541. */
  7542. _component2['default'].registerComponent('Player', Player);
  7543. exports['default'] = Player;
  7544. /***/ }),
  7545. /* 25 */
  7546. /***/ (function(module, exports, __webpack_require__) {
  7547. 'use strict';
  7548. exports.__esModule = true;
  7549. exports.createTimeRange = undefined;
  7550. exports.createTimeRanges = createTimeRanges;
  7551. var _log = __webpack_require__(13);
  7552. var _log2 = _interopRequireDefault(_log);
  7553. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  7554. /**
  7555. * Returns the time for the specified index at the start or end
  7556. * of a TimeRange object.
  7557. *
  7558. * @function time-ranges:indexFunction
  7559. *
  7560. * @param {number} [index=0]
  7561. * The range number to return the time for.
  7562. *
  7563. * @return {number}
  7564. * The time that offset at the specified index.
  7565. *
  7566. * @depricated index must be set to a value, in the future this will throw an error.
  7567. */
  7568. /**
  7569. * An object that contains ranges of time for various reasons.
  7570. *
  7571. * @typedef {Object} TimeRange
  7572. *
  7573. * @property {number} length
  7574. * The number of time ranges represented by this Object
  7575. *
  7576. * @property {time-ranges:indexFunction} start
  7577. * Returns the time offset at which a specified time range begins.
  7578. *
  7579. * @property {time-ranges:indexFunction} end
  7580. * Returns the time offset at which a specified time range begins.
  7581. *
  7582. * @see https://developer.mozilla.org/en-US/docs/Web/API/TimeRanges
  7583. */
  7584. /**
  7585. * Check if any of the time ranges are over the maximum index.
  7586. *
  7587. * @param {string} fnName
  7588. * The function name to use for logging
  7589. *
  7590. * @param {number} index
  7591. * The index to check
  7592. *
  7593. * @param {number} maxIndex
  7594. * The maximum possible index
  7595. *
  7596. * @throws {Error} if the timeRanges provided are over the maxIndex
  7597. */
  7598. function rangeCheck(fnName, index, maxIndex) {
  7599. if (index < 0 || index > maxIndex) {
  7600. throw new Error('Failed to execute \'' + fnName + '\' on \'TimeRanges\': The index provided (' + index + ') is greater than or equal to the maximum bound (' + maxIndex + ').');
  7601. }
  7602. }
  7603. /**
  7604. * Check if any of the time ranges are over the maximum index.
  7605. *
  7606. * @param {string} fnName
  7607. * The function name to use for logging
  7608. *
  7609. * @param {string} valueIndex
  7610. * The proprety that should be used to get the time. should be 'start' or 'end'
  7611. *
  7612. * @param {Array} ranges
  7613. * An array of time ranges
  7614. *
  7615. * @param {Array} [rangeIndex=0]
  7616. * The index to start the search at
  7617. *
  7618. * @return {number}
  7619. * The time that offset at the specified index.
  7620. *
  7621. *
  7622. * @depricated rangeIndex must be set to a value, in the future this will throw an error.
  7623. * @throws {Error} if rangeIndex is more than the length of ranges
  7624. */
  7625. /**
  7626. * @file time-ranges.js
  7627. * @module time-ranges
  7628. */
  7629. function getRange(fnName, valueIndex, ranges, rangeIndex) {
  7630. if (rangeIndex === undefined) {
  7631. _log2['default'].warn('DEPRECATED: Function \'' + fnName + '\' on \'TimeRanges\' called without an index argument.');
  7632. rangeIndex = 0;
  7633. }
  7634. rangeCheck(fnName, rangeIndex, ranges.length - 1);
  7635. return ranges[rangeIndex][valueIndex];
  7636. }
  7637. /**
  7638. * Create a time range object givent ranges of time.
  7639. *
  7640. * @param {Array} [ranges]
  7641. * An array of time ranges.
  7642. */
  7643. function createTimeRangesObj(ranges) {
  7644. if (ranges === undefined || ranges.length === 0) {
  7645. return {
  7646. length: 0,
  7647. start: function start() {
  7648. throw new Error('This TimeRanges object is empty');
  7649. },
  7650. end: function end() {
  7651. throw new Error('This TimeRanges object is empty');
  7652. }
  7653. };
  7654. }
  7655. return {
  7656. length: ranges.length,
  7657. start: getRange.bind(null, 'start', 0, ranges),
  7658. end: getRange.bind(null, 'end', 1, ranges)
  7659. };
  7660. }
  7661. /**
  7662. * Should create a fake `TimeRange` object which mimics an HTML5 time range instance.
  7663. *
  7664. * @param {number|Array} start
  7665. * The start of a single range or an array of ranges
  7666. *
  7667. * @param {number} end
  7668. * The end of a single range.
  7669. *
  7670. * @private
  7671. */
  7672. function createTimeRanges(start, end) {
  7673. if (Array.isArray(start)) {
  7674. return createTimeRangesObj(start);
  7675. } else if (start === undefined || end === undefined) {
  7676. return createTimeRangesObj();
  7677. }
  7678. return createTimeRangesObj([[start, end]]);
  7679. }
  7680. exports.createTimeRange = createTimeRanges;
  7681. /***/ }),
  7682. /* 26 */
  7683. /***/ (function(module, exports, __webpack_require__) {
  7684. 'use strict';
  7685. exports.__esModule = true;
  7686. exports.bufferedPercent = bufferedPercent;
  7687. var _timeRanges = __webpack_require__(25);
  7688. /**
  7689. * Compute the percentage of the media that has been buffered.
  7690. *
  7691. * @param {TimeRange} buffered
  7692. * The current `TimeRange` object representing buffered time ranges
  7693. *
  7694. * @param {number} duration
  7695. * Total duration of the media
  7696. *
  7697. * @return {number}
  7698. * Percent buffered of the total duration in decimal form.
  7699. */
  7700. function bufferedPercent(buffered, duration) {
  7701. var bufferedDuration = 0;
  7702. var start = void 0;
  7703. var end = void 0;
  7704. if (!duration) {
  7705. return 0;
  7706. }
  7707. if (!buffered || !buffered.length) {
  7708. buffered = (0, _timeRanges.createTimeRange)(0, 0);
  7709. }
  7710. for (var i = 0; i < buffered.length; i++) {
  7711. start = buffered.start(i);
  7712. end = buffered.end(i);
  7713. // buffered end can be bigger than duration by a very small fraction
  7714. if (end > duration) {
  7715. end = duration;
  7716. }
  7717. bufferedDuration += end - start;
  7718. }
  7719. return bufferedDuration / duration;
  7720. } /**
  7721. * @file buffer.js
  7722. * @module buffer
  7723. */
  7724. /***/ }),
  7725. /* 27 */
  7726. /***/ (function(module, exports, __webpack_require__) {
  7727. 'use strict';
  7728. exports.__esModule = true;
  7729. var _document = __webpack_require__(8);
  7730. var _document2 = _interopRequireDefault(_document);
  7731. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  7732. /**
  7733. * Store the browser-specific methods for the fullscreen API.
  7734. *
  7735. * @type {Object}
  7736. * @see [Specification]{@link https://fullscreen.spec.whatwg.org}
  7737. * @see [Map Approach From Screenfull.js]{@link https://github.com/sindresorhus/screenfull.js}
  7738. */
  7739. var FullscreenApi = {};
  7740. // browser API methods
  7741. /**
  7742. * @file fullscreen-api.js
  7743. * @module fullscreen-api
  7744. * @private
  7745. */
  7746. var apiMap = [['requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror'],
  7747. // WebKit
  7748. ['webkitRequestFullscreen', 'webkitExitFullscreen', 'webkitFullscreenElement', 'webkitFullscreenEnabled', 'webkitfullscreenchange', 'webkitfullscreenerror'],
  7749. // Old WebKit (Safari 5.1)
  7750. ['webkitRequestFullScreen', 'webkitCancelFullScreen', 'webkitCurrentFullScreenElement', 'webkitCancelFullScreen', 'webkitfullscreenchange', 'webkitfullscreenerror'],
  7751. // Mozilla
  7752. ['mozRequestFullScreen', 'mozCancelFullScreen', 'mozFullScreenElement', 'mozFullScreenEnabled', 'mozfullscreenchange', 'mozfullscreenerror'],
  7753. // Microsoft
  7754. ['msRequestFullscreen', 'msExitFullscreen', 'msFullscreenElement', 'msFullscreenEnabled', 'MSFullscreenChange', 'MSFullscreenError']];
  7755. var specApi = apiMap[0];
  7756. var browserApi = void 0;
  7757. // determine the supported set of functions
  7758. for (var i = 0; i < apiMap.length; i++) {
  7759. // check for exitFullscreen function
  7760. if (apiMap[i][1] in _document2['default']) {
  7761. browserApi = apiMap[i];
  7762. break;
  7763. }
  7764. }
  7765. // map the browser API names to the spec API names
  7766. if (browserApi) {
  7767. for (var _i = 0; _i < browserApi.length; _i++) {
  7768. FullscreenApi[specApi[_i]] = browserApi[_i];
  7769. }
  7770. }
  7771. exports['default'] = FullscreenApi;
  7772. /***/ }),
  7773. /* 28 */
  7774. /***/ (function(module, exports, __webpack_require__) {
  7775. 'use strict';
  7776. exports.__esModule = true;
  7777. var _obj = __webpack_require__(14);
  7778. /**
  7779. * A Custom `MediaError` class which mimics the standard HTML5 `MediaError` class.
  7780. *
  7781. * @param {number|string|Object|MediaError} value
  7782. * This can be of multiple types:
  7783. * - number: should be a standard error code
  7784. * - string: an error message (the code will be 0)
  7785. * - Object: arbitrary properties
  7786. * - `MediaError` (native): used to populate a video.js `MediaError` object
  7787. * - `MediaError` (video.js): will return itself if it's already a
  7788. * video.js `MediaError` object.
  7789. *
  7790. * @see [MediaError Spec]{@link https://dev.w3.org/html5/spec-author-view/video.html#mediaerror}
  7791. * @see [Encrypted MediaError Spec]{@link https://www.w3.org/TR/2013/WD-encrypted-media-20130510/#error-codes}
  7792. *
  7793. * @class MediaError
  7794. */
  7795. function MediaError(value) {
  7796. // Allow redundant calls to this constructor to avoid having `instanceof`
  7797. // checks peppered around the code.
  7798. if (value instanceof MediaError) {
  7799. return value;
  7800. }
  7801. if (typeof value === 'number') {
  7802. this.code = value;
  7803. } else if (typeof value === 'string') {
  7804. // default code is zero, so this is a custom error
  7805. this.message = value;
  7806. } else if ((0, _obj.isObject)(value)) {
  7807. // We assign the `code` property manually because native `MediaError` objects
  7808. // do not expose it as an own/enumerable property of the object.
  7809. if (typeof value.code === 'number') {
  7810. this.code = value.code;
  7811. }
  7812. (0, _obj.assign)(this, value);
  7813. }
  7814. if (!this.message) {
  7815. this.message = MediaError.defaultMessages[this.code] || '';
  7816. }
  7817. }
  7818. /**
  7819. * The error code that refers two one of the defined `MediaError` types
  7820. *
  7821. * @type {Number}
  7822. */
  7823. /**
  7824. * @file media-error.js
  7825. */
  7826. MediaError.prototype.code = 0;
  7827. /**
  7828. * An optional message that to show with the error. Message is not part of the HTML5
  7829. * video spec but allows for more informative custom errors.
  7830. *
  7831. * @type {String}
  7832. */
  7833. MediaError.prototype.message = '';
  7834. /**
  7835. * An optional status code that can be set by plugins to allow even more detail about
  7836. * the error. For example a plugin might provide a specific HTTP status code and an
  7837. * error message for that code. Then when the plugin gets that error this class will
  7838. * know how to display an error message for it. This allows a custom message to show
  7839. * up on the `Player` error overlay.
  7840. *
  7841. * @type {Array}
  7842. */
  7843. MediaError.prototype.status = null;
  7844. /**
  7845. * Errors indexed by the W3C standard. The order **CANNOT CHANGE**! See the
  7846. * specification listed under {@link MediaError} for more information.
  7847. *
  7848. * @enum {array}
  7849. * @readonly
  7850. * @property {string} 0 - MEDIA_ERR_CUSTOM
  7851. * @property {string} 1 - MEDIA_ERR_CUSTOM
  7852. * @property {string} 2 - MEDIA_ERR_ABORTED
  7853. * @property {string} 3 - MEDIA_ERR_NETWORK
  7854. * @property {string} 4 - MEDIA_ERR_SRC_NOT_SUPPORTED
  7855. * @property {string} 5 - MEDIA_ERR_ENCRYPTED
  7856. */
  7857. MediaError.errorTypes = ['MEDIA_ERR_CUSTOM', 'MEDIA_ERR_ABORTED', 'MEDIA_ERR_NETWORK', 'MEDIA_ERR_DECODE', 'MEDIA_ERR_SRC_NOT_SUPPORTED', 'MEDIA_ERR_ENCRYPTED'];
  7858. /**
  7859. * The default `MediaError` messages based on the {@link MediaError.errorTypes}.
  7860. *
  7861. * @type {Array}
  7862. * @constant
  7863. */
  7864. MediaError.defaultMessages = {
  7865. 1: 'You aborted the media playback',
  7866. 2: 'A network error caused the media download to fail part-way.',
  7867. 3: 'The media playback was aborted due to a corruption problem or because the media used features your browser did not support.',
  7868. 4: 'The media could not be loaded, either because the server or network failed or because the format is not supported.',
  7869. 5: 'The media is encrypted and we do not have the keys to decrypt it.'
  7870. };
  7871. // Add types as properties on MediaError
  7872. // e.g. MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
  7873. for (var errNum = 0; errNum < MediaError.errorTypes.length; errNum++) {
  7874. MediaError[MediaError.errorTypes[errNum]] = errNum;
  7875. // values should be accessible on both the class and instance
  7876. MediaError.prototype[MediaError.errorTypes[errNum]] = errNum;
  7877. }
  7878. // jsdocs for instance/static members added above
  7879. // instance methods use `#` and static methods use `.`
  7880. /**
  7881. * W3C error code for any custom error.
  7882. *
  7883. * @member MediaError#MEDIA_ERR_CUSTOM
  7884. * @constant {number}
  7885. * @default 0
  7886. */
  7887. /**
  7888. * W3C error code for any custom error.
  7889. *
  7890. * @member MediaError.MEDIA_ERR_CUSTOM
  7891. * @constant {number}
  7892. * @default 0
  7893. */
  7894. /**
  7895. * W3C error code for media error aborted.
  7896. *
  7897. * @member MediaError#MEDIA_ERR_ABORTED
  7898. * @constant {number}
  7899. * @default 1
  7900. */
  7901. /**
  7902. * W3C error code for media error aborted.
  7903. *
  7904. * @member MediaError.MEDIA_ERR_ABORTED
  7905. * @constant {number}
  7906. * @default 1
  7907. */
  7908. /**
  7909. * W3C error code for any network error.
  7910. *
  7911. * @member MediaError#MEDIA_ERR_NETWORK
  7912. * @constant {number}
  7913. * @default 2
  7914. */
  7915. /**
  7916. * W3C error code for any network error.
  7917. *
  7918. * @member MediaError.MEDIA_ERR_NETWORK
  7919. * @constant {number}
  7920. * @default 2
  7921. */
  7922. /**
  7923. * W3C error code for any decoding error.
  7924. *
  7925. * @member MediaError#MEDIA_ERR_DECODE
  7926. * @constant {number}
  7927. * @default 3
  7928. */
  7929. /**
  7930. * W3C error code for any decoding error.
  7931. *
  7932. * @member MediaError.MEDIA_ERR_DECODE
  7933. * @constant {number}
  7934. * @default 3
  7935. */
  7936. /**
  7937. * W3C error code for any time that a source is not supported.
  7938. *
  7939. * @member MediaError#MEDIA_ERR_SRC_NOT_SUPPORTED
  7940. * @constant {number}
  7941. * @default 4
  7942. */
  7943. /**
  7944. * W3C error code for any time that a source is not supported.
  7945. *
  7946. * @member MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED
  7947. * @constant {number}
  7948. * @default 4
  7949. */
  7950. /**
  7951. * W3C error code for any time that a source is encrypted.
  7952. *
  7953. * @member MediaError#MEDIA_ERR_ENCRYPTED
  7954. * @constant {number}
  7955. * @default 5
  7956. */
  7957. /**
  7958. * W3C error code for any time that a source is encrypted.
  7959. *
  7960. * @member MediaError.MEDIA_ERR_ENCRYPTED
  7961. * @constant {number}
  7962. * @default 5
  7963. */
  7964. exports['default'] = MediaError;
  7965. /***/ }),
  7966. /* 29 */
  7967. /***/ (function(module, exports) {
  7968. module.exports = SafeParseTuple
  7969. function SafeParseTuple(obj, reviver) {
  7970. var json
  7971. var error = null
  7972. try {
  7973. json = JSON.parse(obj, reviver)
  7974. } catch (err) {
  7975. error = err
  7976. }
  7977. return [error, json]
  7978. }
  7979. /***/ }),
  7980. /* 30 */
  7981. /***/ (function(module, exports) {
  7982. 'use strict';
  7983. exports.__esModule = true;
  7984. /**
  7985. * @file text-track-list-converter.js Utilities for capturing text track state and
  7986. * re-creating tracks based on a capture.
  7987. *
  7988. * @module text-track-list-converter
  7989. */
  7990. /**
  7991. * Examine a single {@link TextTrack} and return a JSON-compatible javascript object that
  7992. * represents the {@link TextTrack}'s state.
  7993. *
  7994. * @param {TextTrack} track
  7995. * The text track to query.
  7996. *
  7997. * @return {Object}
  7998. * A serializable javascript representation of the TextTrack.
  7999. * @private
  8000. */
  8001. var trackToJson_ = function trackToJson_(track) {
  8002. var ret = ['kind', 'label', 'language', 'id', 'inBandMetadataTrackDispatchType', 'mode', 'src'].reduce(function (acc, prop, i) {
  8003. if (track[prop]) {
  8004. acc[prop] = track[prop];
  8005. }
  8006. return acc;
  8007. }, {
  8008. cues: track.cues && Array.prototype.map.call(track.cues, function (cue) {
  8009. return {
  8010. startTime: cue.startTime,
  8011. endTime: cue.endTime,
  8012. text: cue.text,
  8013. id: cue.id
  8014. };
  8015. })
  8016. });
  8017. return ret;
  8018. };
  8019. /**
  8020. * Examine a {@link Tech} and return a JSON-compatible javascript array that represents the
  8021. * state of all {@link TextTrack}s currently configured. The return array is compatible with
  8022. * {@link text-track-list-converter:jsonToTextTracks}.
  8023. *
  8024. * @param {Tech} tech
  8025. * The tech object to query
  8026. *
  8027. * @return {Array}
  8028. * A serializable javascript representation of the {@link Tech}s
  8029. * {@link TextTrackList}.
  8030. */
  8031. var textTracksToJson = function textTracksToJson(tech) {
  8032. var trackEls = tech.$$('track');
  8033. var trackObjs = Array.prototype.map.call(trackEls, function (t) {
  8034. return t.track;
  8035. });
  8036. var tracks = Array.prototype.map.call(trackEls, function (trackEl) {
  8037. var json = trackToJson_(trackEl.track);
  8038. if (trackEl.src) {
  8039. json.src = trackEl.src;
  8040. }
  8041. return json;
  8042. });
  8043. return tracks.concat(Array.prototype.filter.call(tech.textTracks(), function (track) {
  8044. return trackObjs.indexOf(track) === -1;
  8045. }).map(trackToJson_));
  8046. };
  8047. /**
  8048. * Create a set of remote {@link TextTrack}s on a {@link Tech} based on an array of javascript
  8049. * object {@link TextTrack} representations.
  8050. *
  8051. * @param {Array} json
  8052. * An array of `TextTrack` representation objects, like those that would be
  8053. * produced by `textTracksToJson`.
  8054. *
  8055. * @param {Tech} tech
  8056. * The `Tech` to create the `TextTrack`s on.
  8057. */
  8058. var jsonToTextTracks = function jsonToTextTracks(json, tech) {
  8059. json.forEach(function (track) {
  8060. var addedTrack = tech.addRemoteTextTrack(track).track;
  8061. if (!track.src && track.cues) {
  8062. track.cues.forEach(function (cue) {
  8063. return addedTrack.addCue(cue);
  8064. });
  8065. }
  8066. });
  8067. return tech.textTracks();
  8068. };
  8069. exports['default'] = { textTracksToJson: textTracksToJson, jsonToTextTracks: jsonToTextTracks, trackToJson_: trackToJson_ };
  8070. /***/ }),
  8071. /* 31 */
  8072. /***/ (function(module, exports, __webpack_require__) {
  8073. 'use strict';
  8074. exports.__esModule = true;
  8075. var _dom = __webpack_require__(11);
  8076. var Dom = _interopRequireWildcard(_dom);
  8077. var _fn = __webpack_require__(20);
  8078. var Fn = _interopRequireWildcard(_fn);
  8079. var _component = __webpack_require__(19);
  8080. var _component2 = _interopRequireDefault(_component);
  8081. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  8082. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  8083. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  8084. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  8085. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  8086. * @file modal-dialog.js
  8087. */
  8088. var MODAL_CLASS_NAME = 'vjs-modal-dialog';
  8089. var ESC = 27;
  8090. /**
  8091. * The `ModalDialog` displays over the video and its controls, which blocks
  8092. * interaction with the player until it is closed.
  8093. *
  8094. * Modal dialogs include a "Close" button and will close when that button
  8095. * is activated - or when ESC is pressed anywhere.
  8096. *
  8097. * @extends Component
  8098. */
  8099. var ModalDialog = function (_Component) {
  8100. _inherits(ModalDialog, _Component);
  8101. /**
  8102. * Create an instance of this class.
  8103. *
  8104. * @param {Player} player
  8105. * The `Player` that this class should be attached to.
  8106. *
  8107. * @param {Object} [options]
  8108. * The key/value store of player options.
  8109. *
  8110. * @param {Mixed} [options.content=undefined]
  8111. * Provide customized content for this modal.
  8112. *
  8113. * @param {string} [options.description]
  8114. * A text description for the modal, primarily for accessibility.
  8115. *
  8116. * @param {boolean} [options.fillAlways=false]
  8117. * Normally, modals are automatically filled only the first time
  8118. * they open. This tells the modal to refresh its content
  8119. * every time it opens.
  8120. *
  8121. * @param {string} [options.label]
  8122. * A text label for the modal, primarily for accessibility.
  8123. *
  8124. * @param {boolean} [options.temporary=true]
  8125. * If `true`, the modal can only be opened once; it will be
  8126. * disposed as soon as it's closed.
  8127. *
  8128. * @param {boolean} [options.uncloseable=false]
  8129. * If `true`, the user will not be able to close the modal
  8130. * through the UI in the normal ways. Programmatic closing is
  8131. * still possible.
  8132. */
  8133. function ModalDialog(player, options) {
  8134. _classCallCheck(this, ModalDialog);
  8135. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
  8136. _this.opened_ = _this.hasBeenOpened_ = _this.hasBeenFilled_ = false;
  8137. _this.closeable(!_this.options_.uncloseable);
  8138. _this.content(_this.options_.content);
  8139. // Make sure the contentEl is defined AFTER any children are initialized
  8140. // because we only want the contents of the modal in the contentEl
  8141. // (not the UI elements like the close button).
  8142. _this.contentEl_ = Dom.createEl('div', {
  8143. className: MODAL_CLASS_NAME + '-content'
  8144. }, {
  8145. role: 'document'
  8146. });
  8147. _this.descEl_ = Dom.createEl('p', {
  8148. className: MODAL_CLASS_NAME + '-description vjs-offscreen',
  8149. id: _this.el().getAttribute('aria-describedby')
  8150. });
  8151. Dom.textContent(_this.descEl_, _this.description());
  8152. _this.el_.appendChild(_this.descEl_);
  8153. _this.el_.appendChild(_this.contentEl_);
  8154. return _this;
  8155. }
  8156. /**
  8157. * Create the `ModalDialog`'s DOM element
  8158. *
  8159. * @return {Element}
  8160. * The DOM element that gets created.
  8161. */
  8162. ModalDialog.prototype.createEl = function createEl() {
  8163. return _Component.prototype.createEl.call(this, 'div', {
  8164. className: this.buildCSSClass(),
  8165. tabIndex: -1
  8166. }, {
  8167. 'aria-describedby': this.id() + '_description',
  8168. 'aria-hidden': 'true',
  8169. 'aria-label': this.label(),
  8170. 'role': 'dialog'
  8171. });
  8172. };
  8173. /**
  8174. * Builds the default DOM `className`.
  8175. *
  8176. * @return {string}
  8177. * The DOM `className` for this object.
  8178. */
  8179. ModalDialog.prototype.buildCSSClass = function buildCSSClass() {
  8180. return MODAL_CLASS_NAME + ' vjs-hidden ' + _Component.prototype.buildCSSClass.call(this);
  8181. };
  8182. /**
  8183. * Handles `keydown` events on the document, looking for ESC, which closes
  8184. * the modal.
  8185. *
  8186. * @param {EventTarget~Event} e
  8187. * The keypress that triggered this event.
  8188. *
  8189. * @listens keydown
  8190. */
  8191. ModalDialog.prototype.handleKeyPress = function handleKeyPress(e) {
  8192. if (e.which === ESC && this.closeable()) {
  8193. this.close();
  8194. }
  8195. };
  8196. /**
  8197. * Returns the label string for this modal. Primarily used for accessibility.
  8198. *
  8199. * @return {string}
  8200. * the localized or raw label of this modal.
  8201. */
  8202. ModalDialog.prototype.label = function label() {
  8203. return this.options_.label || this.localize('Modal Window');
  8204. };
  8205. /**
  8206. * Returns the description string for this modal. Primarily used for
  8207. * accessibility.
  8208. *
  8209. * @return {string}
  8210. * The localized or raw description of this modal.
  8211. */
  8212. ModalDialog.prototype.description = function description() {
  8213. var desc = this.options_.description || this.localize('This is a modal window.');
  8214. // Append a universal closeability message if the modal is closeable.
  8215. if (this.closeable()) {
  8216. desc += ' ' + this.localize('This modal can be closed by pressing the Escape key or activating the close button.');
  8217. }
  8218. return desc;
  8219. };
  8220. /**
  8221. * Opens the modal.
  8222. *
  8223. * @fires ModalDialog#beforemodalopen
  8224. * @fires ModalDialog#modalopen
  8225. *
  8226. * @return {ModalDialog}
  8227. * Returns itself; method can be chained.
  8228. */
  8229. ModalDialog.prototype.open = function open() {
  8230. if (!this.opened_) {
  8231. var player = this.player();
  8232. /**
  8233. * Fired just before a `ModalDialog` is opened.
  8234. *
  8235. * @event ModalDialog#beforemodalopen
  8236. * @type {EventTarget~Event}
  8237. */
  8238. this.trigger('beforemodalopen');
  8239. this.opened_ = true;
  8240. // Fill content if the modal has never opened before and
  8241. // never been filled.
  8242. if (this.options_.fillAlways || !this.hasBeenOpened_ && !this.hasBeenFilled_) {
  8243. this.fill();
  8244. }
  8245. // If the player was playing, pause it and take note of its previously
  8246. // playing state.
  8247. this.wasPlaying_ = !player.paused();
  8248. if (this.options_.pauseOnOpen && this.wasPlaying_) {
  8249. player.pause();
  8250. }
  8251. if (this.closeable()) {
  8252. this.on(this.el_.ownerDocument, 'keydown', Fn.bind(this, this.handleKeyPress));
  8253. }
  8254. player.controls(false);
  8255. this.show();
  8256. this.el().setAttribute('aria-hidden', 'false');
  8257. /**
  8258. * Fired just after a `ModalDialog` is opened.
  8259. *
  8260. * @event ModalDialog#modalopen
  8261. * @type {EventTarget~Event}
  8262. */
  8263. this.trigger('modalopen');
  8264. this.hasBeenOpened_ = true;
  8265. }
  8266. return this;
  8267. };
  8268. /**
  8269. * If the `ModalDialog` is currently open or closed.
  8270. *
  8271. * @param {boolean} [value]
  8272. * If given, it will open (`true`) or close (`false`) the modal.
  8273. *
  8274. * @return {boolean}
  8275. * the current open state of the modaldialog
  8276. */
  8277. ModalDialog.prototype.opened = function opened(value) {
  8278. if (typeof value === 'boolean') {
  8279. this[value ? 'open' : 'close']();
  8280. }
  8281. return this.opened_;
  8282. };
  8283. /**
  8284. * Closes the modal, does nothing if the `ModalDialog` is
  8285. * not open.
  8286. *
  8287. * @fires ModalDialog#beforemodalclose
  8288. * @fires ModalDialog#modalclose
  8289. *
  8290. * @return {ModalDialog}
  8291. * Returns itself; method can be chained.
  8292. */
  8293. ModalDialog.prototype.close = function close() {
  8294. if (this.opened_) {
  8295. var player = this.player();
  8296. /**
  8297. * Fired just before a `ModalDialog` is closed.
  8298. *
  8299. * @event ModalDialog#beforemodalclose
  8300. * @type {EventTarget~Event}
  8301. */
  8302. this.trigger('beforemodalclose');
  8303. this.opened_ = false;
  8304. if (this.wasPlaying_ && this.options_.pauseOnOpen) {
  8305. player.play();
  8306. }
  8307. if (this.closeable()) {
  8308. this.off(this.el_.ownerDocument, 'keydown', Fn.bind(this, this.handleKeyPress));
  8309. }
  8310. player.controls(true);
  8311. this.hide();
  8312. this.el().setAttribute('aria-hidden', 'true');
  8313. /**
  8314. * Fired just after a `ModalDialog` is closed.
  8315. *
  8316. * @event ModalDialog#modalclose
  8317. * @type {EventTarget~Event}
  8318. */
  8319. this.trigger('modalclose');
  8320. if (this.options_.temporary) {
  8321. this.dispose();
  8322. }
  8323. }
  8324. return this;
  8325. };
  8326. /**
  8327. * Check to see if the `ModalDialog` is closeable via the UI.
  8328. *
  8329. * @param {boolean} [value]
  8330. * If given as a boolean, it will set the `closeable` option.
  8331. *
  8332. * @return {boolean}
  8333. * Returns the final value of the closable option.
  8334. */
  8335. ModalDialog.prototype.closeable = function closeable(value) {
  8336. if (typeof value === 'boolean') {
  8337. var closeable = this.closeable_ = !!value;
  8338. var close = this.getChild('closeButton');
  8339. // If this is being made closeable and has no close button, add one.
  8340. if (closeable && !close) {
  8341. // The close button should be a child of the modal - not its
  8342. // content element, so temporarily change the content element.
  8343. var temp = this.contentEl_;
  8344. this.contentEl_ = this.el_;
  8345. close = this.addChild('closeButton', { controlText: 'Close Modal Dialog' });
  8346. this.contentEl_ = temp;
  8347. this.on(close, 'close', this.close);
  8348. }
  8349. // If this is being made uncloseable and has a close button, remove it.
  8350. if (!closeable && close) {
  8351. this.off(close, 'close', this.close);
  8352. this.removeChild(close);
  8353. close.dispose();
  8354. }
  8355. }
  8356. return this.closeable_;
  8357. };
  8358. /**
  8359. * Fill the modal's content element with the modal's "content" option.
  8360. * The content element will be emptied before this change takes place.
  8361. *
  8362. * @return {ModalDialog}
  8363. * Returns itself; method can be chained.
  8364. */
  8365. ModalDialog.prototype.fill = function fill() {
  8366. return this.fillWith(this.content());
  8367. };
  8368. /**
  8369. * Fill the modal's content element with arbitrary content.
  8370. * The content element will be emptied before this change takes place.
  8371. *
  8372. * @fires ModalDialog#beforemodalfill
  8373. * @fires ModalDialog#modalfill
  8374. *
  8375. * @param {Mixed} [content]
  8376. * The same rules apply to this as apply to the `content` option.
  8377. *
  8378. * @return {ModalDialog}
  8379. * Returns itself; method can be chained.
  8380. */
  8381. ModalDialog.prototype.fillWith = function fillWith(content) {
  8382. var contentEl = this.contentEl();
  8383. var parentEl = contentEl.parentNode;
  8384. var nextSiblingEl = contentEl.nextSibling;
  8385. /**
  8386. * Fired just before a `ModalDialog` is filled with content.
  8387. *
  8388. * @event ModalDialog#beforemodalfill
  8389. * @type {EventTarget~Event}
  8390. */
  8391. this.trigger('beforemodalfill');
  8392. this.hasBeenFilled_ = true;
  8393. // Detach the content element from the DOM before performing
  8394. // manipulation to avoid modifying the live DOM multiple times.
  8395. parentEl.removeChild(contentEl);
  8396. this.empty();
  8397. Dom.insertContent(contentEl, content);
  8398. /**
  8399. * Fired just after a `ModalDialog` is filled with content.
  8400. *
  8401. * @event ModalDialog#modalfill
  8402. * @type {EventTarget~Event}
  8403. */
  8404. this.trigger('modalfill');
  8405. // Re-inject the re-filled content element.
  8406. if (nextSiblingEl) {
  8407. parentEl.insertBefore(contentEl, nextSiblingEl);
  8408. } else {
  8409. parentEl.appendChild(contentEl);
  8410. }
  8411. return this;
  8412. };
  8413. /**
  8414. * Empties the content element. This happens anytime the modal is filled.
  8415. *
  8416. * @fires ModalDialog#beforemodalempty
  8417. * @fires ModalDialog#modalempty
  8418. *
  8419. * @return {ModalDialog}
  8420. * Returns itself; method can be chained.
  8421. */
  8422. ModalDialog.prototype.empty = function empty() {
  8423. /**
  8424. * Fired just before a `ModalDialog` is emptied.
  8425. *
  8426. * @event ModalDialog#beforemodalempty
  8427. * @type {EventTarget~Event}
  8428. */
  8429. this.trigger('beforemodalempty');
  8430. Dom.emptyEl(this.contentEl());
  8431. /**
  8432. * Fired just after a `ModalDialog` is emptied.
  8433. *
  8434. * @event ModalDialog#modalempty
  8435. * @type {EventTarget~Event}
  8436. */
  8437. this.trigger('modalempty');
  8438. return this;
  8439. };
  8440. /**
  8441. * Gets or sets the modal content, which gets normalized before being
  8442. * rendered into the DOM.
  8443. *
  8444. * This does not update the DOM or fill the modal, but it is called during
  8445. * that process.
  8446. *
  8447. * @param {Mixed} [value]
  8448. * If defined, sets the internal content value to be used on the
  8449. * next call(s) to `fill`. This value is normalized before being
  8450. * inserted. To "clear" the internal content value, pass `null`.
  8451. *
  8452. * @return {Mixed}
  8453. * The current content of the modal dialog
  8454. */
  8455. ModalDialog.prototype.content = function content(value) {
  8456. if (typeof value !== 'undefined') {
  8457. this.content_ = value;
  8458. }
  8459. return this.content_;
  8460. };
  8461. return ModalDialog;
  8462. }(_component2['default']);
  8463. /**
  8464. * Default options for `ModalDialog` default options.
  8465. *
  8466. * @type {Object}
  8467. * @private
  8468. */
  8469. ModalDialog.prototype.options_ = {
  8470. pauseOnOpen: true,
  8471. temporary: true
  8472. };
  8473. _component2['default'].registerComponent('ModalDialog', ModalDialog);
  8474. exports['default'] = ModalDialog;
  8475. /***/ }),
  8476. /* 32 */
  8477. /***/ (function(module, exports, __webpack_require__) {
  8478. 'use strict';
  8479. exports.__esModule = true;
  8480. var _component = __webpack_require__(19);
  8481. var _component2 = _interopRequireDefault(_component);
  8482. var _htmlTrackElement = __webpack_require__(33);
  8483. var _htmlTrackElement2 = _interopRequireDefault(_htmlTrackElement);
  8484. var _htmlTrackElementList = __webpack_require__(45);
  8485. var _htmlTrackElementList2 = _interopRequireDefault(_htmlTrackElementList);
  8486. var _mergeOptions = __webpack_require__(22);
  8487. var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
  8488. var _textTrack = __webpack_require__(34);
  8489. var _textTrack2 = _interopRequireDefault(_textTrack);
  8490. var _textTrackList = __webpack_require__(46);
  8491. var _textTrackList2 = _interopRequireDefault(_textTrackList);
  8492. var _videoTrackList = __webpack_require__(48);
  8493. var _videoTrackList2 = _interopRequireDefault(_videoTrackList);
  8494. var _audioTrackList = __webpack_require__(49);
  8495. var _audioTrackList2 = _interopRequireDefault(_audioTrackList);
  8496. var _fn = __webpack_require__(20);
  8497. var Fn = _interopRequireWildcard(_fn);
  8498. var _log = __webpack_require__(13);
  8499. var _log2 = _interopRequireDefault(_log);
  8500. var _timeRanges = __webpack_require__(25);
  8501. var _buffer = __webpack_require__(26);
  8502. var _mediaError = __webpack_require__(28);
  8503. var _mediaError2 = _interopRequireDefault(_mediaError);
  8504. var _window = __webpack_require__(7);
  8505. var _window2 = _interopRequireDefault(_window);
  8506. var _document = __webpack_require__(8);
  8507. var _document2 = _interopRequireDefault(_document);
  8508. var _obj = __webpack_require__(14);
  8509. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  8510. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  8511. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  8512. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  8513. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  8514. * @file tech.js
  8515. */
  8516. /**
  8517. * An Object containing a structure like: `{src: 'url', type: 'mimetype'}` or string
  8518. * that just contains the src url alone.
  8519. * * `var SourceObject = {src: 'http://ex.com/video.mp4', type: 'video/mp4'};`
  8520. * `var SourceString = 'http://example.com/some-video.mp4';`
  8521. *
  8522. * @typedef {Object|string} Tech~SourceObject
  8523. *
  8524. * @property {string} src
  8525. * The url to the source
  8526. *
  8527. * @property {string} type
  8528. * The mime type of the source
  8529. */
  8530. /**
  8531. * A function used by {@link Tech} to create a new {@link TextTrack}.
  8532. *
  8533. * @param {Tech} self
  8534. * An instance of the Tech class.
  8535. *
  8536. * @param {string} kind
  8537. * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata)
  8538. *
  8539. * @param {string} [label]
  8540. * Label to identify the text track
  8541. *
  8542. * @param {string} [language]
  8543. * Two letter language abbreviation
  8544. *
  8545. * @param {Object} [options={}]
  8546. * An object with additional text track options
  8547. *
  8548. * @return {TextTrack}
  8549. * The text track that was created.
  8550. */
  8551. function createTrackHelper(self, kind, label, language) {
  8552. var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
  8553. var tracks = self.textTracks();
  8554. options.kind = kind;
  8555. if (label) {
  8556. options.label = label;
  8557. }
  8558. if (language) {
  8559. options.language = language;
  8560. }
  8561. options.tech = self;
  8562. var track = new _textTrack2['default'](options);
  8563. tracks.addTrack_(track);
  8564. return track;
  8565. }
  8566. /**
  8567. * This is the base class for media playback technology controllers, such as
  8568. * {@link Flash} and {@link HTML5}
  8569. *
  8570. * @extends Component
  8571. */
  8572. var Tech = function (_Component) {
  8573. _inherits(Tech, _Component);
  8574. /**
  8575. * Create an instance of this Tech.
  8576. *
  8577. * @param {Object} [options]
  8578. * The key/value store of player options.
  8579. *
  8580. * @param {Component~ReadyCallback} ready
  8581. * Callback function to call when the `HTML5` Tech is ready.
  8582. */
  8583. function Tech() {
  8584. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  8585. var ready = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {};
  8586. _classCallCheck(this, Tech);
  8587. // we don't want the tech to report user activity automatically.
  8588. // This is done manually in addControlsListeners
  8589. options.reportTouchActivity = false;
  8590. // keep track of whether the current source has played at all to
  8591. // implement a very limited played()
  8592. var _this = _possibleConstructorReturn(this, _Component.call(this, null, options, ready));
  8593. _this.hasStarted_ = false;
  8594. _this.on('playing', function () {
  8595. this.hasStarted_ = true;
  8596. });
  8597. _this.on('loadstart', function () {
  8598. this.hasStarted_ = false;
  8599. });
  8600. _this.textTracks_ = options.textTracks;
  8601. _this.videoTracks_ = options.videoTracks;
  8602. _this.audioTracks_ = options.audioTracks;
  8603. // Manually track progress in cases where the browser/flash player doesn't report it.
  8604. if (!_this.featuresProgressEvents) {
  8605. _this.manualProgressOn();
  8606. }
  8607. // Manually track timeupdates in cases where the browser/flash player doesn't report it.
  8608. if (!_this.featuresTimeupdateEvents) {
  8609. _this.manualTimeUpdatesOn();
  8610. }
  8611. ['Text', 'Audio', 'Video'].forEach(function (track) {
  8612. if (options['native' + track + 'Tracks'] === false) {
  8613. _this['featuresNative' + track + 'Tracks'] = false;
  8614. }
  8615. });
  8616. if (options.nativeCaptions === false) {
  8617. _this.featuresNativeTextTracks = false;
  8618. }
  8619. if (!_this.featuresNativeTextTracks) {
  8620. _this.emulateTextTracks();
  8621. }
  8622. _this.autoRemoteTextTracks_ = new _textTrackList2['default']();
  8623. _this.initTextTrackListeners();
  8624. _this.initTrackListeners();
  8625. // Turn on component tap events only if not using native controls
  8626. if (!options.nativeControlsForTouch) {
  8627. _this.emitTapEvents();
  8628. }
  8629. if (_this.constructor) {
  8630. _this.name_ = _this.constructor.name || 'Unknown Tech';
  8631. }
  8632. return _this;
  8633. }
  8634. /* Fallbacks for unsupported event types
  8635. ================================================================================ */
  8636. /**
  8637. * Polyfill the `progress` event for browsers that don't support it natively.
  8638. *
  8639. * @see {@link Tech#trackProgress}
  8640. */
  8641. Tech.prototype.manualProgressOn = function manualProgressOn() {
  8642. this.on('durationchange', this.onDurationChange);
  8643. this.manualProgress = true;
  8644. // Trigger progress watching when a source begins loading
  8645. this.one('ready', this.trackProgress);
  8646. };
  8647. /**
  8648. * Turn off the polyfill for `progress` events that was created in
  8649. * {@link Tech#manualProgressOn}
  8650. */
  8651. Tech.prototype.manualProgressOff = function manualProgressOff() {
  8652. this.manualProgress = false;
  8653. this.stopTrackingProgress();
  8654. this.off('durationchange', this.onDurationChange);
  8655. };
  8656. /**
  8657. * This is used to trigger a `progress` event when the buffered percent changes. It
  8658. * sets an interval function that will be called every 500 milliseconds to check if the
  8659. * buffer end percent has changed.
  8660. *
  8661. * > This function is called by {@link Tech#manualProgressOn}
  8662. *
  8663. * @param {EventTarget~Event} event
  8664. * The `ready` event that caused this to run.
  8665. *
  8666. * @listens Tech#ready
  8667. * @fires Tech#progress
  8668. */
  8669. Tech.prototype.trackProgress = function trackProgress(event) {
  8670. this.stopTrackingProgress();
  8671. this.progressInterval = this.setInterval(Fn.bind(this, function () {
  8672. // Don't trigger unless buffered amount is greater than last time
  8673. var numBufferedPercent = this.bufferedPercent();
  8674. if (this.bufferedPercent_ !== numBufferedPercent) {
  8675. /**
  8676. * See {@link Player#progress}
  8677. *
  8678. * @event Tech#progress
  8679. * @type {EventTarget~Event}
  8680. */
  8681. this.trigger('progress');
  8682. }
  8683. this.bufferedPercent_ = numBufferedPercent;
  8684. if (numBufferedPercent === 1) {
  8685. this.stopTrackingProgress();
  8686. }
  8687. }), 500);
  8688. };
  8689. /**
  8690. * Update our internal duration on a `durationchange` event by calling
  8691. * {@link Tech#duration}.
  8692. *
  8693. * @param {EventTarget~Event} event
  8694. * The `durationchange` event that caused this to run.
  8695. *
  8696. * @listens Tech#durationchange
  8697. */
  8698. Tech.prototype.onDurationChange = function onDurationChange(event) {
  8699. this.duration_ = this.duration();
  8700. };
  8701. /**
  8702. * Get and create a `TimeRange` object for buffering.
  8703. *
  8704. * @return {TimeRange}
  8705. * The time range object that was created.
  8706. */
  8707. Tech.prototype.buffered = function buffered() {
  8708. return (0, _timeRanges.createTimeRange)(0, 0);
  8709. };
  8710. /**
  8711. * Get the percentage of the current video that is currently buffered.
  8712. *
  8713. * @return {number}
  8714. * A number from 0 to 1 that represents the decimal percentage of the
  8715. * video that is buffered.
  8716. *
  8717. */
  8718. Tech.prototype.bufferedPercent = function bufferedPercent() {
  8719. return (0, _buffer.bufferedPercent)(this.buffered(), this.duration_);
  8720. };
  8721. /**
  8722. * Turn off the polyfill for `progress` events that was created in
  8723. * {@link Tech#manualProgressOn}
  8724. * Stop manually tracking progress events by clearing the interval that was set in
  8725. * {@link Tech#trackProgress}.
  8726. */
  8727. Tech.prototype.stopTrackingProgress = function stopTrackingProgress() {
  8728. this.clearInterval(this.progressInterval);
  8729. };
  8730. /**
  8731. * Polyfill the `timeupdate` event for browsers that don't support it.
  8732. *
  8733. * @see {@link Tech#trackCurrentTime}
  8734. */
  8735. Tech.prototype.manualTimeUpdatesOn = function manualTimeUpdatesOn() {
  8736. this.manualTimeUpdates = true;
  8737. this.on('play', this.trackCurrentTime);
  8738. this.on('pause', this.stopTrackingCurrentTime);
  8739. };
  8740. /**
  8741. * Turn off the polyfill for `timeupdate` events that was created in
  8742. * {@link Tech#manualTimeUpdatesOn}
  8743. */
  8744. Tech.prototype.manualTimeUpdatesOff = function manualTimeUpdatesOff() {
  8745. this.manualTimeUpdates = false;
  8746. this.stopTrackingCurrentTime();
  8747. this.off('play', this.trackCurrentTime);
  8748. this.off('pause', this.stopTrackingCurrentTime);
  8749. };
  8750. /**
  8751. * Sets up an interval function to track current time and trigger `timeupdate` every
  8752. * 250 milliseconds.
  8753. *
  8754. * @listens Tech#play
  8755. * @triggers Tech#timeupdate
  8756. */
  8757. Tech.prototype.trackCurrentTime = function trackCurrentTime() {
  8758. if (this.currentTimeInterval) {
  8759. this.stopTrackingCurrentTime();
  8760. }
  8761. this.currentTimeInterval = this.setInterval(function () {
  8762. /**
  8763. * Triggered at an interval of 250ms to indicated that time is passing in the video.
  8764. *
  8765. * @event Tech#timeupdate
  8766. * @type {EventTarget~Event}
  8767. */
  8768. this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true });
  8769. // 42 = 24 fps // 250 is what Webkit uses // FF uses 15
  8770. }, 250);
  8771. };
  8772. /**
  8773. * Stop the interval function created in {@link Tech#trackCurrentTime} so that the
  8774. * `timeupdate` event is no longer triggered.
  8775. *
  8776. * @listens {Tech#pause}
  8777. */
  8778. Tech.prototype.stopTrackingCurrentTime = function stopTrackingCurrentTime() {
  8779. this.clearInterval(this.currentTimeInterval);
  8780. // #1002 - if the video ends right before the next timeupdate would happen,
  8781. // the progress bar won't make it all the way to the end
  8782. this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true });
  8783. };
  8784. /**
  8785. * Turn off all event polyfills, clear the `Tech`s {@link AudioTrackList},
  8786. * {@link VideoTrackList}, and {@link TextTrackList}, and dispose of this Tech.
  8787. *
  8788. * @fires Component#dispose
  8789. */
  8790. Tech.prototype.dispose = function dispose() {
  8791. // clear out all tracks because we can't reuse them between techs
  8792. this.clearTracks(['audio', 'video', 'text']);
  8793. // Turn off any manual progress or timeupdate tracking
  8794. if (this.manualProgress) {
  8795. this.manualProgressOff();
  8796. }
  8797. if (this.manualTimeUpdates) {
  8798. this.manualTimeUpdatesOff();
  8799. }
  8800. _Component.prototype.dispose.call(this);
  8801. };
  8802. /**
  8803. * Clear out a single `TrackList` or an array of `TrackLists` given their names.
  8804. *
  8805. * > Note: Techs without source handlers should call this between sources for `video`
  8806. * & `audio` tracks. You don't want to use them between tracks!
  8807. *
  8808. * @param {string[]|string} types
  8809. * TrackList names to clear, valid names are `video`, `audio`, and
  8810. * `text`.
  8811. */
  8812. Tech.prototype.clearTracks = function clearTracks(types) {
  8813. var _this2 = this;
  8814. types = [].concat(types);
  8815. // clear out all tracks because we can't reuse them between techs
  8816. types.forEach(function (type) {
  8817. var list = _this2[type + 'Tracks']() || [];
  8818. var i = list.length;
  8819. while (i--) {
  8820. var track = list[i];
  8821. if (type === 'text') {
  8822. _this2.removeRemoteTextTrack(track);
  8823. }
  8824. list.removeTrack_(track);
  8825. }
  8826. });
  8827. };
  8828. /**
  8829. * Remove any TextTracks added via addRemoteTextTrack that are
  8830. * flagged for automatic garbage collection
  8831. */
  8832. Tech.prototype.cleanupAutoTextTracks = function cleanupAutoTextTracks() {
  8833. var list = this.autoRemoteTextTracks_ || [];
  8834. var i = list.length;
  8835. while (i--) {
  8836. var track = list[i];
  8837. this.removeRemoteTextTrack(track);
  8838. }
  8839. };
  8840. /**
  8841. * Reset the tech, which will removes all sources and reset the internal readyState.
  8842. *
  8843. * @abstract
  8844. */
  8845. Tech.prototype.reset = function reset() {};
  8846. /**
  8847. * Get or set an error on the Tech.
  8848. *
  8849. * @param {MediaError} [err]
  8850. * Error to set on the Tech
  8851. *
  8852. * @return {MediaError|null}
  8853. * The current error object on the tech, or null if there isn't one.
  8854. */
  8855. Tech.prototype.error = function error(err) {
  8856. if (err !== undefined) {
  8857. this.error_ = new _mediaError2['default'](err);
  8858. this.trigger('error');
  8859. }
  8860. return this.error_;
  8861. };
  8862. /**
  8863. * Returns the `TimeRange`s that have been played through for the current source.
  8864. *
  8865. * > NOTE: This implementation is incomplete. It does not track the played `TimeRange`.
  8866. * It only checks wether the source has played at all or not.
  8867. *
  8868. * @return {TimeRange}
  8869. * - A single time range if this video has played
  8870. * - An empty set of ranges if not.
  8871. */
  8872. Tech.prototype.played = function played() {
  8873. if (this.hasStarted_) {
  8874. return (0, _timeRanges.createTimeRange)(0, 0);
  8875. }
  8876. return (0, _timeRanges.createTimeRange)();
  8877. };
  8878. /**
  8879. * Causes a manual time update to occur if {@link Tech#manualTimeUpdatesOn} was
  8880. * previously called.
  8881. *
  8882. * @fires Tech#timeupdate
  8883. */
  8884. Tech.prototype.setCurrentTime = function setCurrentTime() {
  8885. // improve the accuracy of manual timeupdates
  8886. if (this.manualTimeUpdates) {
  8887. /**
  8888. * A manual `timeupdate` event.
  8889. *
  8890. * @event Tech#timeupdate
  8891. * @type {EventTarget~Event}
  8892. */
  8893. this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true });
  8894. }
  8895. };
  8896. /**
  8897. * Turn on listeners for {@link TextTrackList} events. This adds
  8898. * {@link EventTarget~EventListeners} for `texttrackchange`, `addtrack` and
  8899. * `removetrack`.
  8900. *
  8901. * @fires Tech#texttrackchange
  8902. */
  8903. Tech.prototype.initTextTrackListeners = function initTextTrackListeners() {
  8904. var textTrackListChanges = Fn.bind(this, function () {
  8905. /**
  8906. * Triggered when tracks are added or removed on the Tech {@link TextTrackList}
  8907. *
  8908. * @event Tech#texttrackchange
  8909. * @type {EventTarget~Event}
  8910. */
  8911. this.trigger('texttrackchange');
  8912. });
  8913. var tracks = this.textTracks();
  8914. if (!tracks) {
  8915. return;
  8916. }
  8917. tracks.addEventListener('removetrack', textTrackListChanges);
  8918. tracks.addEventListener('addtrack', textTrackListChanges);
  8919. this.on('dispose', Fn.bind(this, function () {
  8920. tracks.removeEventListener('removetrack', textTrackListChanges);
  8921. tracks.removeEventListener('addtrack', textTrackListChanges);
  8922. }));
  8923. };
  8924. /**
  8925. * Turn on listeners for {@link VideoTrackList} and {@link {AudioTrackList} events.
  8926. * This adds {@link EventTarget~EventListeners} for `addtrack`, and `removetrack`.
  8927. *
  8928. * @fires Tech#audiotrackchange
  8929. * @fires Tech#videotrackchange
  8930. */
  8931. Tech.prototype.initTrackListeners = function initTrackListeners() {
  8932. var _this3 = this;
  8933. var trackTypes = ['video', 'audio'];
  8934. trackTypes.forEach(function (type) {
  8935. /**
  8936. * Triggered when tracks are added or removed on the Tech {@link AudioTrackList}
  8937. *
  8938. * @event Tech#audiotrackchange
  8939. * @type {EventTarget~Event}
  8940. */
  8941. /**
  8942. * Triggered when tracks are added or removed on the Tech {@link VideoTrackList}
  8943. *
  8944. * @event Tech#videotrackchange
  8945. * @type {EventTarget~Event}
  8946. */
  8947. var trackListChanges = function trackListChanges() {
  8948. _this3.trigger(type + 'trackchange');
  8949. };
  8950. var tracks = _this3[type + 'Tracks']();
  8951. tracks.addEventListener('removetrack', trackListChanges);
  8952. tracks.addEventListener('addtrack', trackListChanges);
  8953. _this3.on('dispose', function () {
  8954. tracks.removeEventListener('removetrack', trackListChanges);
  8955. tracks.removeEventListener('addtrack', trackListChanges);
  8956. });
  8957. });
  8958. };
  8959. /**
  8960. * Emulate TextTracks using vtt.js if necessary
  8961. *
  8962. * @fires Tech#vttjsloaded
  8963. * @fires Tech#vttjserror
  8964. */
  8965. Tech.prototype.addWebVttScript_ = function addWebVttScript_() {
  8966. var _this4 = this;
  8967. if (_window2['default'].WebVTT) {
  8968. return;
  8969. }
  8970. // Initially, Tech.el_ is a child of a dummy-div wait until the Component system
  8971. // signals that the Tech is ready at which point Tech.el_ is part of the DOM
  8972. // before inserting the WebVTT script
  8973. if (_document2['default'].body.contains(this.el())) {
  8974. var vtt = __webpack_require__(50);
  8975. // load via require if available and vtt.js script location was not passed in
  8976. // as an option. novtt builds will turn the above require call into an empty object
  8977. // which will cause this if check to always fail.
  8978. if (!this.options_['vtt.js'] && (0, _obj.isPlain)(vtt) && Object.keys(vtt).length > 0) {
  8979. this.trigger('vttjsloaded');
  8980. return;
  8981. }
  8982. // load vtt.js via the script location option or the cdn of no location was
  8983. // passed in
  8984. var script = _document2['default'].createElement('script');
  8985. script.src = this.options_['vtt.js'] || 'https://vjs.zencdn.net/vttjs/0.12.4/vtt.min.js';
  8986. script.onload = function () {
  8987. /**
  8988. * Fired when vtt.js is loaded.
  8989. *
  8990. * @event Tech#vttjsloaded
  8991. * @type {EventTarget~Event}
  8992. */
  8993. _this4.trigger('vttjsloaded');
  8994. };
  8995. script.onerror = function () {
  8996. /**
  8997. * Fired when vtt.js was not loaded due to an error
  8998. *
  8999. * @event Tech#vttjsloaded
  9000. * @type {EventTarget~Event}
  9001. */
  9002. _this4.trigger('vttjserror');
  9003. };
  9004. this.on('dispose', function () {
  9005. script.onload = null;
  9006. script.onerror = null;
  9007. });
  9008. // but have not loaded yet and we set it to true before the inject so that
  9009. // we don't overwrite the injected window.WebVTT if it loads right away
  9010. _window2['default'].WebVTT = true;
  9011. this.el().parentNode.appendChild(script);
  9012. } else {
  9013. this.ready(this.addWebVttScript_);
  9014. }
  9015. };
  9016. /**
  9017. * Emulate texttracks
  9018. *
  9019. * @method emulateTextTracks
  9020. */
  9021. Tech.prototype.emulateTextTracks = function emulateTextTracks() {
  9022. var _this5 = this;
  9023. var tracks = this.textTracks();
  9024. if (!tracks) {
  9025. return;
  9026. }
  9027. var remoteTracks = this.remoteTextTracks();
  9028. var handleAddTrack = function handleAddTrack(e) {
  9029. return tracks.addTrack_(e.track);
  9030. };
  9031. var handleRemoveTrack = function handleRemoveTrack(e) {
  9032. return tracks.removeTrack_(e.track);
  9033. };
  9034. remoteTracks.on('addtrack', handleAddTrack);
  9035. remoteTracks.on('removetrack', handleRemoveTrack);
  9036. this.addWebVttScript_();
  9037. var updateDisplay = function updateDisplay() {
  9038. return _this5.trigger('texttrackchange');
  9039. };
  9040. var textTracksChanges = function textTracksChanges() {
  9041. updateDisplay();
  9042. for (var i = 0; i < tracks.length; i++) {
  9043. var track = tracks[i];
  9044. track.removeEventListener('cuechange', updateDisplay);
  9045. if (track.mode === 'showing') {
  9046. track.addEventListener('cuechange', updateDisplay);
  9047. }
  9048. }
  9049. };
  9050. textTracksChanges();
  9051. tracks.addEventListener('change', textTracksChanges);
  9052. tracks.addEventListener('addtrack', textTracksChanges);
  9053. tracks.addEventListener('removetrack', textTracksChanges);
  9054. this.on('dispose', function () {
  9055. remoteTracks.off('addtrack', handleAddTrack);
  9056. remoteTracks.off('removetrack', handleRemoveTrack);
  9057. tracks.removeEventListener('change', textTracksChanges);
  9058. tracks.removeEventListener('addtrack', textTracksChanges);
  9059. tracks.removeEventListener('removetrack', textTracksChanges);
  9060. for (var i = 0; i < tracks.length; i++) {
  9061. var track = tracks[i];
  9062. track.removeEventListener('cuechange', updateDisplay);
  9063. }
  9064. });
  9065. };
  9066. /**
  9067. * Get the `Tech`s {@link VideoTrackList}.
  9068. *
  9069. * @return {VideoTrackList}
  9070. * The video track list that the Tech is currently using.
  9071. */
  9072. Tech.prototype.videoTracks = function videoTracks() {
  9073. this.videoTracks_ = this.videoTracks_ || new _videoTrackList2['default']();
  9074. return this.videoTracks_;
  9075. };
  9076. /**
  9077. * Get the `Tech`s {@link AudioTrackList}.
  9078. *
  9079. * @return {AudioTrackList}
  9080. * The audio track list that the Tech is currently using.
  9081. */
  9082. Tech.prototype.audioTracks = function audioTracks() {
  9083. this.audioTracks_ = this.audioTracks_ || new _audioTrackList2['default']();
  9084. return this.audioTracks_;
  9085. };
  9086. /**
  9087. * Get the `Tech`s {@link TextTrackList}.
  9088. *
  9089. * @return {TextTrackList}
  9090. * The text track list that the Tech is currently using.
  9091. */
  9092. Tech.prototype.textTracks = function textTracks() {
  9093. this.textTracks_ = this.textTracks_ || new _textTrackList2['default']();
  9094. return this.textTracks_;
  9095. };
  9096. /**
  9097. * Get the `Tech`s remote {@link TextTrackList}, which is created from elements
  9098. * that were added to the DOM.
  9099. *
  9100. * @return {TextTrackList}
  9101. * The remote text track list that the Tech is currently using.
  9102. */
  9103. Tech.prototype.remoteTextTracks = function remoteTextTracks() {
  9104. this.remoteTextTracks_ = this.remoteTextTracks_ || new _textTrackList2['default']();
  9105. return this.remoteTextTracks_;
  9106. };
  9107. /**
  9108. * Get The `Tech`s {HTMLTrackElementList}, which are the elements in the DOM that are
  9109. * being used as TextTracks.
  9110. *
  9111. * @return {HTMLTrackElementList}
  9112. * The current HTML track elements that exist for the tech.
  9113. */
  9114. Tech.prototype.remoteTextTrackEls = function remoteTextTrackEls() {
  9115. this.remoteTextTrackEls_ = this.remoteTextTrackEls_ || new _htmlTrackElementList2['default']();
  9116. return this.remoteTextTrackEls_;
  9117. };
  9118. /**
  9119. * Create and returns a remote {@link TextTrack} object.
  9120. *
  9121. * @param {string} kind
  9122. * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata)
  9123. *
  9124. * @param {string} [label]
  9125. * Label to identify the text track
  9126. *
  9127. * @param {string} [language]
  9128. * Two letter language abbreviation
  9129. *
  9130. * @return {TextTrack}
  9131. * The TextTrack that gets created.
  9132. */
  9133. Tech.prototype.addTextTrack = function addTextTrack(kind, label, language) {
  9134. if (!kind) {
  9135. throw new Error('TextTrack kind is required but was not provided');
  9136. }
  9137. return createTrackHelper(this, kind, label, language);
  9138. };
  9139. /**
  9140. * Create an emulated TextTrack for use by addRemoteTextTrack
  9141. *
  9142. * This is intended to be overridden by classes that inherit from
  9143. * Tech in order to create native or custom TextTracks.
  9144. *
  9145. * @param {Object} options
  9146. * The object should contain the options to initialize the TextTrack with.
  9147. *
  9148. * @param {string} [options.kind]
  9149. * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata).
  9150. *
  9151. * @param {string} [options.label].
  9152. * Label to identify the text track
  9153. *
  9154. * @param {string} [options.language]
  9155. * Two letter language abbreviation.
  9156. *
  9157. * @return {HTMLTrackElement}
  9158. * The track element that gets created.
  9159. */
  9160. Tech.prototype.createRemoteTextTrack = function createRemoteTextTrack(options) {
  9161. var track = (0, _mergeOptions2['default'])(options, {
  9162. tech: this
  9163. });
  9164. return new _htmlTrackElement2['default'](track);
  9165. };
  9166. /**
  9167. * Creates a remote text track object and returns an html track element.
  9168. *
  9169. * > Note: This can be an emulated {@link HTMLTrackElement} or a native one.
  9170. *
  9171. * @param {Object} options
  9172. * See {@link Tech#createRemoteTextTrack} for more detailed properties.
  9173. *
  9174. * @param {boolean} [manualCleanup=true]
  9175. * - When false: the TextTrack will be automatically removed from the video
  9176. * element whenever the source changes
  9177. * - When True: The TextTrack will have to be cleaned up manually
  9178. *
  9179. * @return {HTMLTrackElement}
  9180. * An Html Track Element.
  9181. *
  9182. * @deprecated The default functionality for this function will be equivalent
  9183. * to "manualCleanup=false" in the future. The manualCleanup parameter will
  9184. * also be removed.
  9185. */
  9186. Tech.prototype.addRemoteTextTrack = function addRemoteTextTrack() {
  9187. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  9188. var manualCleanup = arguments[1];
  9189. var htmlTrackElement = this.createRemoteTextTrack(options);
  9190. if (manualCleanup !== true && manualCleanup !== false) {
  9191. // deprecation warning
  9192. _log2['default'].warn('Calling addRemoteTextTrack without explicitly setting the "manualCleanup" parameter to `true` is deprecated and default to `false` in future version of video.js');
  9193. manualCleanup = true;
  9194. }
  9195. // store HTMLTrackElement and TextTrack to remote list
  9196. this.remoteTextTrackEls().addTrackElement_(htmlTrackElement);
  9197. this.remoteTextTracks().addTrack_(htmlTrackElement.track);
  9198. if (manualCleanup !== true) {
  9199. // create the TextTrackList if it doesn't exist
  9200. this.autoRemoteTextTracks_.addTrack_(htmlTrackElement.track);
  9201. }
  9202. return htmlTrackElement;
  9203. };
  9204. /**
  9205. * Remove a remote text track from the remote `TextTrackList`.
  9206. *
  9207. * @param {TextTrack} track
  9208. * `TextTrack` to remove from the `TextTrackList`
  9209. */
  9210. Tech.prototype.removeRemoteTextTrack = function removeRemoteTextTrack(track) {
  9211. var trackElement = this.remoteTextTrackEls().getTrackElementByTrack_(track);
  9212. // remove HTMLTrackElement and TextTrack from remote list
  9213. this.remoteTextTrackEls().removeTrackElement_(trackElement);
  9214. this.remoteTextTracks().removeTrack_(track);
  9215. this.autoRemoteTextTracks_.removeTrack_(track);
  9216. };
  9217. /**
  9218. * Gets available media playback quality metrics as specified by the W3C's Media
  9219. * Playback Quality API.
  9220. *
  9221. * @see [Spec]{@link https://wicg.github.io/media-playback-quality}
  9222. *
  9223. * @return {Object}
  9224. * An object with supported media playback quality metrics
  9225. *
  9226. * @abstract
  9227. */
  9228. Tech.prototype.getVideoPlaybackQuality = function getVideoPlaybackQuality() {
  9229. return {};
  9230. };
  9231. /**
  9232. * A method to set a poster from a `Tech`.
  9233. *
  9234. * @abstract
  9235. */
  9236. Tech.prototype.setPoster = function setPoster() {};
  9237. /**
  9238. * A method to check for the presence of the 'playsinine' <video> attribute.
  9239. *
  9240. * @abstract
  9241. */
  9242. Tech.prototype.playsinline = function playsinline() {};
  9243. /**
  9244. * A method to set or unset the 'playsinine' <video> attribute.
  9245. *
  9246. * @abstract
  9247. */
  9248. Tech.prototype.setPlaysinline = function setPlaysinline() {};
  9249. /*
  9250. * Check if the tech can support the given mime-type.
  9251. *
  9252. * The base tech does not support any type, but source handlers might
  9253. * overwrite this.
  9254. *
  9255. * @param {string} type
  9256. * The mimetype to check for support
  9257. *
  9258. * @return {string}
  9259. * 'probably', 'maybe', or empty string
  9260. *
  9261. * @see [Spec]{@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canPlayType}
  9262. *
  9263. * @abstract
  9264. */
  9265. Tech.prototype.canPlayType = function canPlayType() {
  9266. return '';
  9267. };
  9268. /*
  9269. * Return whether the argument is a Tech or not.
  9270. * Can be passed either a Class like `Html5` or a instance like `player.tech_`
  9271. *
  9272. * @param {Object} component
  9273. * The item to check
  9274. *
  9275. * @return {boolean}
  9276. * Whether it is a tech or not
  9277. * - True if it is a tech
  9278. * - False if it is not
  9279. */
  9280. Tech.isTech = function isTech(component) {
  9281. return component.prototype instanceof Tech || component instanceof Tech || component === Tech;
  9282. };
  9283. /**
  9284. * Registers a `Tech` into a shared list for videojs.
  9285. *
  9286. * @param {string} name
  9287. * Name of the `Tech` to register.
  9288. *
  9289. * @param {Object} tech
  9290. * The `Tech` class to register.
  9291. */
  9292. Tech.registerTech = function registerTech(name, tech) {
  9293. if (!Tech.techs_) {
  9294. Tech.techs_ = {};
  9295. }
  9296. if (!Tech.isTech(tech)) {
  9297. throw new Error('Tech ' + name + ' must be a Tech');
  9298. }
  9299. Tech.techs_[name] = tech;
  9300. return tech;
  9301. };
  9302. /**
  9303. * Get a `Tech` from the shared list by name.
  9304. *
  9305. * @param {string} name
  9306. * Name of the component to get
  9307. *
  9308. * @return {Tech|undefined}
  9309. * The `Tech` or undefined if there was no tech with the name requsted.
  9310. */
  9311. Tech.getTech = function getTech(name) {
  9312. if (Tech.techs_ && Tech.techs_[name]) {
  9313. return Tech.techs_[name];
  9314. }
  9315. if (_window2['default'] && _window2['default'].videojs && _window2['default'].videojs[name]) {
  9316. _log2['default'].warn('The ' + name + ' tech was added to the videojs object when it should be registered using videojs.registerTech(name, tech)');
  9317. return _window2['default'].videojs[name];
  9318. }
  9319. };
  9320. return Tech;
  9321. }(_component2['default']);
  9322. /**
  9323. * List of associated text tracks.
  9324. *
  9325. * @type {TextTrackList}
  9326. * @private
  9327. */
  9328. Tech.prototype.textTracks_; // eslint-disable-line
  9329. /**
  9330. * List of associated audio tracks.
  9331. *
  9332. * @type {AudioTrackList}
  9333. * @private
  9334. */
  9335. Tech.prototype.audioTracks_; // eslint-disable-line
  9336. /**
  9337. * List of associated video tracks.
  9338. *
  9339. * @type {VideoTrackList}
  9340. * @private
  9341. */
  9342. Tech.prototype.videoTracks_; // eslint-disable-line
  9343. /**
  9344. * Boolean indicating wether the `Tech` supports volume control.
  9345. *
  9346. * @type {boolean}
  9347. * @default
  9348. */
  9349. Tech.prototype.featuresVolumeControl = true;
  9350. /**
  9351. * Boolean indicating wether the `Tech` support fullscreen resize control.
  9352. * Resizing plugins using request fullscreen reloads the plugin
  9353. *
  9354. * @type {boolean}
  9355. * @default
  9356. */
  9357. Tech.prototype.featuresFullscreenResize = false;
  9358. /**
  9359. * Boolean indicating wether the `Tech` supports changing the speed at which the video
  9360. * plays. Examples:
  9361. * - Set player to play 2x (twice) as fast
  9362. * - Set player to play 0.5x (half) as fast
  9363. *
  9364. * @type {boolean}
  9365. * @default
  9366. */
  9367. Tech.prototype.featuresPlaybackRate = false;
  9368. /**
  9369. * Boolean indicating wether the `Tech` supports the `progress` event. This is currently
  9370. * not triggered by video-js-swf. This will be used to determine if
  9371. * {@link Tech#manualProgressOn} should be called.
  9372. *
  9373. * @type {boolean}
  9374. * @default
  9375. */
  9376. Tech.prototype.featuresProgressEvents = false;
  9377. /**
  9378. * Boolean indicating wether the `Tech` supports the `timeupdate` event. This is currently
  9379. * not triggered by video-js-swf. This will be used to determine if
  9380. * {@link Tech#manualTimeUpdates} should be called.
  9381. *
  9382. * @type {boolean}
  9383. * @default
  9384. */
  9385. Tech.prototype.featuresTimeupdateEvents = false;
  9386. /**
  9387. * Boolean indicating wether the `Tech` supports the native `TextTrack`s.
  9388. * This will help us integrate with native `TextTrack`s if the browser supports them.
  9389. *
  9390. * @type {boolean}
  9391. * @default
  9392. */
  9393. Tech.prototype.featuresNativeTextTracks = false;
  9394. /**
  9395. * A functional mixin for techs that want to use the Source Handler pattern.
  9396. * Source handlers are scripts for handling specific formats.
  9397. * The source handler pattern is used for adaptive formats (HLS, DASH) that
  9398. * manually load video data and feed it into a Source Buffer (Media Source Extensions)
  9399. * Example: `Tech.withSourceHandlers.call(MyTech);`
  9400. *
  9401. * @param {Tech} _Tech
  9402. * The tech to add source handler functions to.
  9403. *
  9404. * @mixes Tech~SourceHandlerAdditions
  9405. */
  9406. Tech.withSourceHandlers = function (_Tech) {
  9407. /**
  9408. * Register a source handler
  9409. *
  9410. * @param {Function} handler
  9411. * The source handler class
  9412. *
  9413. * @param {number} [index]
  9414. * Register it at the following index
  9415. */
  9416. _Tech.registerSourceHandler = function (handler, index) {
  9417. var handlers = _Tech.sourceHandlers;
  9418. if (!handlers) {
  9419. handlers = _Tech.sourceHandlers = [];
  9420. }
  9421. if (index === undefined) {
  9422. // add to the end of the list
  9423. index = handlers.length;
  9424. }
  9425. handlers.splice(index, 0, handler);
  9426. };
  9427. /**
  9428. * Check if the tech can support the given type. Also checks the
  9429. * Techs sourceHandlers.
  9430. *
  9431. * @param {string} type
  9432. * The mimetype to check.
  9433. *
  9434. * @return {string}
  9435. * 'probably', 'maybe', or '' (empty string)
  9436. */
  9437. _Tech.canPlayType = function (type) {
  9438. var handlers = _Tech.sourceHandlers || [];
  9439. var can = void 0;
  9440. for (var i = 0; i < handlers.length; i++) {
  9441. can = handlers[i].canPlayType(type);
  9442. if (can) {
  9443. return can;
  9444. }
  9445. }
  9446. return '';
  9447. };
  9448. /**
  9449. * Returns the first source handler that supports the source.
  9450. *
  9451. * TODO: Answer question: should 'probably' be prioritized over 'maybe'
  9452. *
  9453. * @param {Tech~SourceObject} source
  9454. * The source object
  9455. *
  9456. * @param {Object} options
  9457. * The options passed to the tech
  9458. *
  9459. * @return {SourceHandler|null}
  9460. * The first source handler that supports the source or null if
  9461. * no SourceHandler supports the source
  9462. */
  9463. _Tech.selectSourceHandler = function (source, options) {
  9464. var handlers = _Tech.sourceHandlers || [];
  9465. var can = void 0;
  9466. for (var i = 0; i < handlers.length; i++) {
  9467. can = handlers[i].canHandleSource(source, options);
  9468. if (can) {
  9469. return handlers[i];
  9470. }
  9471. }
  9472. return null;
  9473. };
  9474. /**
  9475. * Check if the tech can support the given source.
  9476. *
  9477. * @param {Tech~SourceObject} srcObj
  9478. * The source object
  9479. *
  9480. * @param {Object} options
  9481. * The options passed to the tech
  9482. *
  9483. * @return {string}
  9484. * 'probably', 'maybe', or '' (empty string)
  9485. */
  9486. _Tech.canPlaySource = function (srcObj, options) {
  9487. var sh = _Tech.selectSourceHandler(srcObj, options);
  9488. if (sh) {
  9489. return sh.canHandleSource(srcObj, options);
  9490. }
  9491. return '';
  9492. };
  9493. /**
  9494. * When using a source handler, prefer its implementation of
  9495. * any function normally provided by the tech.
  9496. */
  9497. var deferrable = ['seekable', 'duration'];
  9498. /**
  9499. * A wrapper around {@link Tech#seekable} that will call a `SourceHandler`s seekable
  9500. * function if it exists, with a fallback to the Techs seekable function.
  9501. *
  9502. * @method _Tech.seekable
  9503. */
  9504. /**
  9505. * A wrapper around {@link Tech#duration} that will call a `SourceHandler`s duration
  9506. * function if it exists, otherwise it will fallback to the techs duration function.
  9507. *
  9508. * @method _Tech.duration
  9509. */
  9510. deferrable.forEach(function (fnName) {
  9511. var originalFn = this[fnName];
  9512. if (typeof originalFn !== 'function') {
  9513. return;
  9514. }
  9515. this[fnName] = function () {
  9516. if (this.sourceHandler_ && this.sourceHandler_[fnName]) {
  9517. return this.sourceHandler_[fnName].apply(this.sourceHandler_, arguments);
  9518. }
  9519. return originalFn.apply(this, arguments);
  9520. };
  9521. }, _Tech.prototype);
  9522. /**
  9523. * Create a function for setting the source using a source object
  9524. * and source handlers.
  9525. * Should never be called unless a source handler was found.
  9526. *
  9527. * @param {Tech~SourceObject} source
  9528. * A source object with src and type keys
  9529. *
  9530. * @return {Tech}
  9531. * Returns itself; this method is chainable
  9532. */
  9533. _Tech.prototype.setSource = function (source) {
  9534. var sh = _Tech.selectSourceHandler(source, this.options_);
  9535. if (!sh) {
  9536. // Fall back to a native source hander when unsupported sources are
  9537. // deliberately set
  9538. if (_Tech.nativeSourceHandler) {
  9539. sh = _Tech.nativeSourceHandler;
  9540. } else {
  9541. _log2['default'].error('No source hander found for the current source.');
  9542. }
  9543. }
  9544. // Dispose any existing source handler
  9545. this.disposeSourceHandler();
  9546. this.off('dispose', this.disposeSourceHandler);
  9547. if (sh !== _Tech.nativeSourceHandler) {
  9548. this.currentSource_ = source;
  9549. // Catch if someone replaced the src without calling setSource.
  9550. // If they do, set currentSource_ to null and dispose our source handler.
  9551. this.off(this.el_, 'loadstart', _Tech.prototype.firstLoadStartListener_);
  9552. this.off(this.el_, 'loadstart', _Tech.prototype.successiveLoadStartListener_);
  9553. this.one(this.el_, 'loadstart', _Tech.prototype.firstLoadStartListener_);
  9554. }
  9555. this.sourceHandler_ = sh.handleSource(source, this, this.options_);
  9556. this.on('dispose', this.disposeSourceHandler);
  9557. return this;
  9558. };
  9559. /**
  9560. * Called once for the first loadstart of a video.
  9561. *
  9562. * @listens Tech#loadstart
  9563. */
  9564. _Tech.prototype.firstLoadStartListener_ = function () {
  9565. this.one(this.el_, 'loadstart', _Tech.prototype.successiveLoadStartListener_);
  9566. };
  9567. // On successive loadstarts when setSource has not been called again
  9568. /**
  9569. * Called after the first loadstart for a video occurs.
  9570. *
  9571. * @listens Tech#loadstart
  9572. */
  9573. _Tech.prototype.successiveLoadStartListener_ = function () {
  9574. this.disposeSourceHandler();
  9575. this.one(this.el_, 'loadstart', _Tech.prototype.successiveLoadStartListener_);
  9576. };
  9577. /**
  9578. * Clean up any existing SourceHandlers and listeners when the Tech is disposed.
  9579. *
  9580. * @listens Tech#dispose
  9581. */
  9582. _Tech.prototype.disposeSourceHandler = function () {
  9583. // if we have a source and get another one
  9584. // then we are loading something new
  9585. // than clear all of our current tracks
  9586. if (this.currentSource_) {
  9587. this.clearTracks(['audio', 'video']);
  9588. this.currentSource_ = null;
  9589. }
  9590. // always clean up auto-text tracks
  9591. this.cleanupAutoTextTracks();
  9592. if (this.sourceHandler_) {
  9593. this.off(this.el_, 'loadstart', _Tech.prototype.firstLoadStartListener_);
  9594. this.off(this.el_, 'loadstart', _Tech.prototype.successiveLoadStartListener_);
  9595. if (this.sourceHandler_.dispose) {
  9596. this.sourceHandler_.dispose();
  9597. }
  9598. this.sourceHandler_ = null;
  9599. }
  9600. };
  9601. };
  9602. _component2['default'].registerComponent('Tech', Tech);
  9603. // Old name for Tech
  9604. // @deprecated
  9605. _component2['default'].registerComponent('MediaTechController', Tech);
  9606. Tech.registerTech('Tech', Tech);
  9607. exports['default'] = Tech;
  9608. /***/ }),
  9609. /* 33 */
  9610. /***/ (function(module, exports, __webpack_require__) {
  9611. 'use strict';
  9612. exports.__esModule = true;
  9613. var _browser = __webpack_require__(10);
  9614. var browser = _interopRequireWildcard(_browser);
  9615. var _document = __webpack_require__(8);
  9616. var _document2 = _interopRequireDefault(_document);
  9617. var _eventTarget = __webpack_require__(23);
  9618. var _eventTarget2 = _interopRequireDefault(_eventTarget);
  9619. var _textTrack = __webpack_require__(34);
  9620. var _textTrack2 = _interopRequireDefault(_textTrack);
  9621. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  9622. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  9623. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  9624. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  9625. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  9626. * @file html-track-element.js
  9627. */
  9628. /**
  9629. * @typedef {HTMLTrackElement~ReadyState}
  9630. * @enum {number}
  9631. */
  9632. var NONE = 0;
  9633. var LOADING = 1;
  9634. var LOADED = 2;
  9635. var ERROR = 3;
  9636. /**
  9637. * A single track represented in the DOM.
  9638. *
  9639. * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#htmltrackelement}
  9640. * @extends EventTarget
  9641. */
  9642. var HTMLTrackElement = function (_EventTarget) {
  9643. _inherits(HTMLTrackElement, _EventTarget);
  9644. /**
  9645. * Create an instance of this class.
  9646. *
  9647. * @param {Object} options={}
  9648. * Object of option names and values
  9649. *
  9650. * @param {Tech} options.tech
  9651. * A reference to the tech that owns this HTMLTrackElement.
  9652. *
  9653. * @param {TextTrack~Kind} [options.kind='subtitles']
  9654. * A valid text track kind.
  9655. *
  9656. * @param {TextTrack~Mode} [options.mode='disabled']
  9657. * A valid text track mode.
  9658. *
  9659. * @param {string} [options.id='vjs_track_' + Guid.newGUID()]
  9660. * A unique id for this TextTrack.
  9661. *
  9662. * @param {string} [options.label='']
  9663. * The menu label for this track.
  9664. *
  9665. * @param {string} [options.language='']
  9666. * A valid two character language code.
  9667. *
  9668. * @param {string} [options.srclang='']
  9669. * A valid two character language code. An alternative, but deprioritized
  9670. * vesion of `options.language`
  9671. *
  9672. * @param {string} [options.src]
  9673. * A url to TextTrack cues.
  9674. *
  9675. * @param {boolean} [options.default]
  9676. * If this track should default to on or off.
  9677. */
  9678. function HTMLTrackElement() {
  9679. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  9680. _classCallCheck(this, HTMLTrackElement);
  9681. var _this = _possibleConstructorReturn(this, _EventTarget.call(this));
  9682. var readyState = void 0;
  9683. var trackElement = _this; // eslint-disable-line
  9684. if (browser.IS_IE8) {
  9685. trackElement = _document2['default'].createElement('custom');
  9686. for (var prop in HTMLTrackElement.prototype) {
  9687. if (prop !== 'constructor') {
  9688. trackElement[prop] = HTMLTrackElement.prototype[prop];
  9689. }
  9690. }
  9691. }
  9692. var track = new _textTrack2['default'](options);
  9693. trackElement.kind = track.kind;
  9694. trackElement.src = track.src;
  9695. trackElement.srclang = track.language;
  9696. trackElement.label = track.label;
  9697. trackElement['default'] = track['default'];
  9698. /**
  9699. * @member {HTMLTrackElement~ReadyState} readyState
  9700. * The current ready state of the track element.
  9701. */
  9702. Object.defineProperty(trackElement, 'readyState', {
  9703. get: function get() {
  9704. return readyState;
  9705. }
  9706. });
  9707. /**
  9708. * @member {TextTrack} track
  9709. * The underlying TextTrack object.
  9710. */
  9711. Object.defineProperty(trackElement, 'track', {
  9712. get: function get() {
  9713. return track;
  9714. }
  9715. });
  9716. readyState = NONE;
  9717. /**
  9718. * @listens TextTrack#loadeddata
  9719. * @fires HTMLTrackElement#load
  9720. */
  9721. track.addEventListener('loadeddata', function () {
  9722. readyState = LOADED;
  9723. trackElement.trigger({
  9724. type: 'load',
  9725. target: trackElement
  9726. });
  9727. });
  9728. if (browser.IS_IE8) {
  9729. var _ret;
  9730. return _ret = trackElement, _possibleConstructorReturn(_this, _ret);
  9731. }
  9732. return _this;
  9733. }
  9734. return HTMLTrackElement;
  9735. }(_eventTarget2['default']);
  9736. HTMLTrackElement.prototype.allowedEvents_ = {
  9737. load: 'load'
  9738. };
  9739. HTMLTrackElement.NONE = NONE;
  9740. HTMLTrackElement.LOADING = LOADING;
  9741. HTMLTrackElement.LOADED = LOADED;
  9742. HTMLTrackElement.ERROR = ERROR;
  9743. exports['default'] = HTMLTrackElement;
  9744. /***/ }),
  9745. /* 34 */
  9746. /***/ (function(module, exports, __webpack_require__) {
  9747. 'use strict';
  9748. exports.__esModule = true;
  9749. var _textTrackCueList = __webpack_require__(35);
  9750. var _textTrackCueList2 = _interopRequireDefault(_textTrackCueList);
  9751. var _fn = __webpack_require__(20);
  9752. var Fn = _interopRequireWildcard(_fn);
  9753. var _trackEnums = __webpack_require__(36);
  9754. var _log = __webpack_require__(13);
  9755. var _log2 = _interopRequireDefault(_log);
  9756. var _window = __webpack_require__(7);
  9757. var _window2 = _interopRequireDefault(_window);
  9758. var _track = __webpack_require__(37);
  9759. var _track2 = _interopRequireDefault(_track);
  9760. var _url = __webpack_require__(38);
  9761. var _xhr = __webpack_require__(39);
  9762. var _xhr2 = _interopRequireDefault(_xhr);
  9763. var _mergeOptions = __webpack_require__(22);
  9764. var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
  9765. var _browser = __webpack_require__(10);
  9766. var browser = _interopRequireWildcard(_browser);
  9767. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  9768. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  9769. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  9770. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  9771. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  9772. * @file text-track.js
  9773. */
  9774. /**
  9775. * Takes a webvtt file contents and parses it into cues
  9776. *
  9777. * @param {string} srcContent
  9778. * webVTT file contents
  9779. *
  9780. * @param {TextTrack} track
  9781. * TextTrack to add cues to. Cues come from the srcContent.
  9782. *
  9783. * @private
  9784. */
  9785. var parseCues = function parseCues(srcContent, track) {
  9786. var parser = new _window2['default'].WebVTT.Parser(_window2['default'], _window2['default'].vttjs, _window2['default'].WebVTT.StringDecoder());
  9787. var errors = [];
  9788. parser.oncue = function (cue) {
  9789. track.addCue(cue);
  9790. };
  9791. parser.onparsingerror = function (error) {
  9792. errors.push(error);
  9793. };
  9794. parser.onflush = function () {
  9795. track.trigger({
  9796. type: 'loadeddata',
  9797. target: track
  9798. });
  9799. };
  9800. parser.parse(srcContent);
  9801. if (errors.length > 0) {
  9802. if (_window2['default'].console && _window2['default'].console.groupCollapsed) {
  9803. _window2['default'].console.groupCollapsed('Text Track parsing errors for ' + track.src);
  9804. }
  9805. errors.forEach(function (error) {
  9806. return _log2['default'].error(error);
  9807. });
  9808. if (_window2['default'].console && _window2['default'].console.groupEnd) {
  9809. _window2['default'].console.groupEnd();
  9810. }
  9811. }
  9812. parser.flush();
  9813. };
  9814. /**
  9815. * Load a `TextTrack` from a specifed url.
  9816. *
  9817. * @param {string} src
  9818. * Url to load track from.
  9819. *
  9820. * @param {TextTrack} track
  9821. * Track to add cues to. Comes from the content at the end of `url`.
  9822. *
  9823. * @private
  9824. */
  9825. var loadTrack = function loadTrack(src, track) {
  9826. var opts = {
  9827. uri: src
  9828. };
  9829. var crossOrigin = (0, _url.isCrossOrigin)(src);
  9830. if (crossOrigin) {
  9831. opts.cors = crossOrigin;
  9832. }
  9833. (0, _xhr2['default'])(opts, Fn.bind(this, function (err, response, responseBody) {
  9834. if (err) {
  9835. return _log2['default'].error(err, response);
  9836. }
  9837. track.loaded_ = true;
  9838. // Make sure that vttjs has loaded, otherwise, wait till it finished loading
  9839. // NOTE: this is only used for the alt/video.novtt.js build
  9840. if (typeof _window2['default'].WebVTT !== 'function') {
  9841. if (track.tech_) {
  9842. var loadHandler = function loadHandler() {
  9843. return parseCues(responseBody, track);
  9844. };
  9845. track.tech_.on('vttjsloaded', loadHandler);
  9846. track.tech_.on('vttjserror', function () {
  9847. _log2['default'].error('vttjs failed to load, stopping trying to process ' + track.src);
  9848. track.tech_.off('vttjsloaded', loadHandler);
  9849. });
  9850. }
  9851. } else {
  9852. parseCues(responseBody, track);
  9853. }
  9854. }));
  9855. };
  9856. /**
  9857. * A representation of a single `TextTrack`.
  9858. *
  9859. * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttrack}
  9860. * @extends Track
  9861. */
  9862. var TextTrack = function (_Track) {
  9863. _inherits(TextTrack, _Track);
  9864. /**
  9865. * Create an instance of this class.
  9866. *
  9867. * @param {Object} options={}
  9868. * Object of option names and values
  9869. *
  9870. * @param {Tech} options.tech
  9871. * A reference to the tech that owns this TextTrack.
  9872. *
  9873. * @param {TextTrack~Kind} [options.kind='subtitles']
  9874. * A valid text track kind.
  9875. *
  9876. * @param {TextTrack~Mode} [options.mode='disabled']
  9877. * A valid text track mode.
  9878. *
  9879. * @param {string} [options.id='vjs_track_' + Guid.newGUID()]
  9880. * A unique id for this TextTrack.
  9881. *
  9882. * @param {string} [options.label='']
  9883. * The menu label for this track.
  9884. *
  9885. * @param {string} [options.language='']
  9886. * A valid two character language code.
  9887. *
  9888. * @param {string} [options.srclang='']
  9889. * A valid two character language code. An alternative, but deprioritized
  9890. * vesion of `options.language`
  9891. *
  9892. * @param {string} [options.src]
  9893. * A url to TextTrack cues.
  9894. *
  9895. * @param {boolean} [options.default]
  9896. * If this track should default to on or off.
  9897. */
  9898. function TextTrack() {
  9899. var _this, _ret;
  9900. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  9901. _classCallCheck(this, TextTrack);
  9902. if (!options.tech) {
  9903. throw new Error('A tech was not provided.');
  9904. }
  9905. var settings = (0, _mergeOptions2['default'])(options, {
  9906. kind: _trackEnums.TextTrackKind[options.kind] || 'subtitles',
  9907. language: options.language || options.srclang || ''
  9908. });
  9909. var mode = _trackEnums.TextTrackMode[settings.mode] || 'disabled';
  9910. var default_ = settings['default'];
  9911. if (settings.kind === 'metadata' || settings.kind === 'chapters') {
  9912. mode = 'hidden';
  9913. }
  9914. // on IE8 this will be a document element
  9915. // for every other browser this will be a normal object
  9916. var tt = (_this = _possibleConstructorReturn(this, _Track.call(this, settings)), _this);
  9917. tt.tech_ = settings.tech;
  9918. if (browser.IS_IE8) {
  9919. for (var prop in TextTrack.prototype) {
  9920. if (prop !== 'constructor') {
  9921. tt[prop] = TextTrack.prototype[prop];
  9922. }
  9923. }
  9924. }
  9925. tt.cues_ = [];
  9926. tt.activeCues_ = [];
  9927. var cues = new _textTrackCueList2['default'](tt.cues_);
  9928. var activeCues = new _textTrackCueList2['default'](tt.activeCues_);
  9929. var changed = false;
  9930. var timeupdateHandler = Fn.bind(tt, function () {
  9931. // Accessing this.activeCues for the side-effects of updating itself
  9932. // due to it's nature as a getter function. Do not remove or cues will
  9933. // stop updating!
  9934. /* eslint-disable no-unused-expressions */
  9935. this.activeCues;
  9936. /* eslint-enable no-unused-expressions */
  9937. if (changed) {
  9938. this.trigger('cuechange');
  9939. changed = false;
  9940. }
  9941. });
  9942. if (mode !== 'disabled') {
  9943. tt.tech_.ready(function () {
  9944. tt.tech_.on('timeupdate', timeupdateHandler);
  9945. }, true);
  9946. }
  9947. /**
  9948. * @member {boolean} default
  9949. * If this track was set to be on or off by default. Cannot be changed after
  9950. * creation.
  9951. *
  9952. * @readonly
  9953. */
  9954. Object.defineProperty(tt, 'default', {
  9955. get: function get() {
  9956. return default_;
  9957. },
  9958. set: function set() {}
  9959. });
  9960. /**
  9961. * @member {string} mode
  9962. * Set the mode of this TextTrack to a valid {@link TextTrack~Mode}. Will
  9963. * not be set if setting to an invalid mode.
  9964. *
  9965. * @fires TextTrack#modechange
  9966. */
  9967. Object.defineProperty(tt, 'mode', {
  9968. get: function get() {
  9969. return mode;
  9970. },
  9971. set: function set(newMode) {
  9972. var _this2 = this;
  9973. if (!_trackEnums.TextTrackMode[newMode]) {
  9974. return;
  9975. }
  9976. mode = newMode;
  9977. if (mode === 'showing') {
  9978. this.tech_.ready(function () {
  9979. _this2.tech_.on('timeupdate', timeupdateHandler);
  9980. }, true);
  9981. }
  9982. /**
  9983. * An event that fires when mode changes on this track. This allows
  9984. * the TextTrackList that holds this track to act accordingly.
  9985. *
  9986. * > Note: This is not part of the spec!
  9987. *
  9988. * @event TextTrack#modechange
  9989. * @type {EventTarget~Event}
  9990. */
  9991. this.trigger('modechange');
  9992. }
  9993. });
  9994. /**
  9995. * @member {TextTrackCueList} cues
  9996. * The text track cue list for this TextTrack.
  9997. */
  9998. Object.defineProperty(tt, 'cues', {
  9999. get: function get() {
  10000. if (!this.loaded_) {
  10001. return null;
  10002. }
  10003. return cues;
  10004. },
  10005. set: function set() {}
  10006. });
  10007. /**
  10008. * @member {TextTrackCueList} activeCues
  10009. * The list text track cues that are currently active for this TextTrack.
  10010. */
  10011. Object.defineProperty(tt, 'activeCues', {
  10012. get: function get() {
  10013. if (!this.loaded_) {
  10014. return null;
  10015. }
  10016. // nothing to do
  10017. if (this.cues.length === 0) {
  10018. return activeCues;
  10019. }
  10020. var ct = this.tech_.currentTime();
  10021. var active = [];
  10022. for (var i = 0, l = this.cues.length; i < l; i++) {
  10023. var cue = this.cues[i];
  10024. if (cue.startTime <= ct && cue.endTime >= ct) {
  10025. active.push(cue);
  10026. } else if (cue.startTime === cue.endTime && cue.startTime <= ct && cue.startTime + 0.5 >= ct) {
  10027. active.push(cue);
  10028. }
  10029. }
  10030. changed = false;
  10031. if (active.length !== this.activeCues_.length) {
  10032. changed = true;
  10033. } else {
  10034. for (var _i = 0; _i < active.length; _i++) {
  10035. if (this.activeCues_.indexOf(active[_i]) === -1) {
  10036. changed = true;
  10037. }
  10038. }
  10039. }
  10040. this.activeCues_ = active;
  10041. activeCues.setCues_(this.activeCues_);
  10042. return activeCues;
  10043. },
  10044. set: function set() {}
  10045. });
  10046. if (settings.src) {
  10047. tt.src = settings.src;
  10048. loadTrack(settings.src, tt);
  10049. } else {
  10050. tt.loaded_ = true;
  10051. }
  10052. return _ret = tt, _possibleConstructorReturn(_this, _ret);
  10053. }
  10054. /**
  10055. * Add a cue to the internal list of cues.
  10056. *
  10057. * @param {TextTrack~Cue} cue
  10058. * The cue to add to our internal list
  10059. */
  10060. TextTrack.prototype.addCue = function addCue(originalCue) {
  10061. var cue = originalCue;
  10062. if (_window2['default'].vttjs && !(originalCue instanceof _window2['default'].vttjs.VTTCue)) {
  10063. cue = new _window2['default'].vttjs.VTTCue(originalCue.startTime, originalCue.endTime, originalCue.text);
  10064. for (var prop in originalCue) {
  10065. if (!(prop in cue)) {
  10066. cue[prop] = originalCue[prop];
  10067. }
  10068. }
  10069. // make sure that `id` is copied over
  10070. cue.id = originalCue.id;
  10071. cue.originalCue_ = originalCue;
  10072. }
  10073. var tracks = this.tech_.textTracks();
  10074. if (tracks) {
  10075. for (var i = 0; i < tracks.length; i++) {
  10076. if (tracks[i] !== this) {
  10077. tracks[i].removeCue(cue);
  10078. }
  10079. }
  10080. }
  10081. this.cues_.push(cue);
  10082. this.cues.setCues_(this.cues_);
  10083. };
  10084. /**
  10085. * Remove a cue from our internal list
  10086. *
  10087. * @param {TextTrack~Cue} removeCue
  10088. * The cue to remove from our internal list
  10089. */
  10090. TextTrack.prototype.removeCue = function removeCue(_removeCue) {
  10091. var i = this.cues_.length;
  10092. while (i--) {
  10093. var cue = this.cues_[i];
  10094. if (cue === _removeCue || cue.originalCue_ && cue.originalCue_ === _removeCue) {
  10095. this.cues_.splice(i, 1);
  10096. this.cues.setCues_(this.cues_);
  10097. break;
  10098. }
  10099. }
  10100. };
  10101. return TextTrack;
  10102. }(_track2['default']);
  10103. /**
  10104. * cuechange - One or more cues in the track have become active or stopped being active.
  10105. */
  10106. TextTrack.prototype.allowedEvents_ = {
  10107. cuechange: 'cuechange'
  10108. };
  10109. exports['default'] = TextTrack;
  10110. /***/ }),
  10111. /* 35 */
  10112. /***/ (function(module, exports, __webpack_require__) {
  10113. 'use strict';
  10114. exports.__esModule = true;
  10115. var _browser = __webpack_require__(10);
  10116. var browser = _interopRequireWildcard(_browser);
  10117. var _document = __webpack_require__(8);
  10118. var _document2 = _interopRequireDefault(_document);
  10119. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  10120. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  10121. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
  10122. * @file text-track-cue-list.js
  10123. */
  10124. /**
  10125. * @typedef {Object} TextTrackCue
  10126. *
  10127. * @property {string} id
  10128. * The unique id for this text track cue
  10129. *
  10130. * @property {number} startTime
  10131. * The start time for this text track cue
  10132. *
  10133. * @property {number} endTime
  10134. * The end time for this text track cue
  10135. *
  10136. * @property {boolean} pauseOnExit
  10137. * Pause when the end time is reached if true.
  10138. *
  10139. * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackcue}
  10140. */
  10141. /**
  10142. * A List of TextTrackCues.
  10143. *
  10144. * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackcuelist}
  10145. */
  10146. var TextTrackCueList = function () {
  10147. /**
  10148. * Create an instance of this class..
  10149. *
  10150. * @param {Array} cues
  10151. * A list of cues to be initialized with
  10152. */
  10153. function TextTrackCueList(cues) {
  10154. _classCallCheck(this, TextTrackCueList);
  10155. var list = this; // eslint-disable-line
  10156. if (browser.IS_IE8) {
  10157. list = _document2['default'].createElement('custom');
  10158. for (var prop in TextTrackCueList.prototype) {
  10159. if (prop !== 'constructor') {
  10160. list[prop] = TextTrackCueList.prototype[prop];
  10161. }
  10162. }
  10163. }
  10164. TextTrackCueList.prototype.setCues_.call(list, cues);
  10165. /**
  10166. * @member {number} length
  10167. * The current number of `TextTrackCue`s in the TextTrackCueList.
  10168. */
  10169. Object.defineProperty(list, 'length', {
  10170. get: function get() {
  10171. return this.length_;
  10172. }
  10173. });
  10174. if (browser.IS_IE8) {
  10175. return list;
  10176. }
  10177. }
  10178. /**
  10179. * A setter for cues in this list. Creates getters
  10180. * an an index for the cues.
  10181. *
  10182. * @param {Array} cues
  10183. * An array of cues to set
  10184. *
  10185. * @private
  10186. */
  10187. TextTrackCueList.prototype.setCues_ = function setCues_(cues) {
  10188. var oldLength = this.length || 0;
  10189. var i = 0;
  10190. var l = cues.length;
  10191. this.cues_ = cues;
  10192. this.length_ = cues.length;
  10193. var defineProp = function defineProp(index) {
  10194. if (!('' + index in this)) {
  10195. Object.defineProperty(this, '' + index, {
  10196. get: function get() {
  10197. return this.cues_[index];
  10198. }
  10199. });
  10200. }
  10201. };
  10202. if (oldLength < l) {
  10203. i = oldLength;
  10204. for (; i < l; i++) {
  10205. defineProp.call(this, i);
  10206. }
  10207. }
  10208. };
  10209. /**
  10210. * Get a `TextTrackCue` that is currently in the `TextTrackCueList` by id.
  10211. *
  10212. * @param {string} id
  10213. * The id of the cue that should be searched for.
  10214. *
  10215. * @return {TextTrackCue|null}
  10216. * A single cue or null if none was found.
  10217. */
  10218. TextTrackCueList.prototype.getCueById = function getCueById(id) {
  10219. var result = null;
  10220. for (var i = 0, l = this.length; i < l; i++) {
  10221. var cue = this[i];
  10222. if (cue.id === id) {
  10223. result = cue;
  10224. break;
  10225. }
  10226. }
  10227. return result;
  10228. };
  10229. return TextTrackCueList;
  10230. }();
  10231. exports['default'] = TextTrackCueList;
  10232. /***/ }),
  10233. /* 36 */
  10234. /***/ (function(module, exports) {
  10235. 'use strict';
  10236. exports.__esModule = true;
  10237. /**
  10238. * @file track-kinds.js
  10239. */
  10240. /**
  10241. * All possible `VideoTrackKind`s
  10242. *
  10243. * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-videotrack-kind
  10244. * @typedef VideoTrack~Kind
  10245. * @enum
  10246. */
  10247. var VideoTrackKind = exports.VideoTrackKind = {
  10248. alternative: 'alternative',
  10249. captions: 'captions',
  10250. main: 'main',
  10251. sign: 'sign',
  10252. subtitles: 'subtitles',
  10253. commentary: 'commentary'
  10254. };
  10255. /**
  10256. * All possible `AudioTrackKind`s
  10257. *
  10258. * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-audiotrack-kind
  10259. * @typedef AudioTrack~Kind
  10260. * @enum
  10261. */
  10262. var AudioTrackKind = exports.AudioTrackKind = {
  10263. 'alternative': 'alternative',
  10264. 'descriptions': 'descriptions',
  10265. 'main': 'main',
  10266. 'main-desc': 'main-desc',
  10267. 'translation': 'translation',
  10268. 'commentary': 'commentary'
  10269. };
  10270. /**
  10271. * All possible `TextTrackKind`s
  10272. *
  10273. * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-texttrack-kind
  10274. * @typedef TextTrack~Kind
  10275. * @enum
  10276. */
  10277. var TextTrackKind = exports.TextTrackKind = {
  10278. subtitles: 'subtitles',
  10279. captions: 'captions',
  10280. descriptions: 'descriptions',
  10281. chapters: 'chapters',
  10282. metadata: 'metadata'
  10283. };
  10284. /**
  10285. * All possible `TextTrackMode`s
  10286. *
  10287. * @see https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackmode
  10288. * @typedef TextTrack~Mode
  10289. * @enum
  10290. */
  10291. var TextTrackMode = exports.TextTrackMode = {
  10292. disabled: 'disabled',
  10293. hidden: 'hidden',
  10294. showing: 'showing'
  10295. };
  10296. /***/ }),
  10297. /* 37 */
  10298. /***/ (function(module, exports, __webpack_require__) {
  10299. 'use strict';
  10300. exports.__esModule = true;
  10301. var _browser = __webpack_require__(10);
  10302. var browser = _interopRequireWildcard(_browser);
  10303. var _document = __webpack_require__(8);
  10304. var _document2 = _interopRequireDefault(_document);
  10305. var _guid = __webpack_require__(12);
  10306. var Guid = _interopRequireWildcard(_guid);
  10307. var _eventTarget = __webpack_require__(23);
  10308. var _eventTarget2 = _interopRequireDefault(_eventTarget);
  10309. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  10310. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  10311. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  10312. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  10313. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  10314. * @file track.js
  10315. */
  10316. /**
  10317. * A Track class that contains all of the common functionality for {@link AudioTrack},
  10318. * {@link VideoTrack}, and {@link TextTrack}.
  10319. *
  10320. * > Note: This class should not be used directly
  10321. *
  10322. * @see {@link https://html.spec.whatwg.org/multipage/embedded-content.html}
  10323. * @extends EventTarget
  10324. * @abstract
  10325. */
  10326. var Track = function (_EventTarget) {
  10327. _inherits(Track, _EventTarget);
  10328. /**
  10329. * Create an instance of this class.
  10330. *
  10331. * @param {Object} [options={}]
  10332. * Object of option names and values
  10333. *
  10334. * @param {string} [options.kind='']
  10335. * A valid kind for the track type you are creating.
  10336. *
  10337. * @param {string} [options.id='vjs_track_' + Guid.newGUID()]
  10338. * A unique id for this AudioTrack.
  10339. *
  10340. * @param {string} [options.label='']
  10341. * The menu label for this track.
  10342. *
  10343. * @param {string} [options.language='']
  10344. * A valid two character language code.
  10345. *
  10346. * @abstract
  10347. */
  10348. function Track() {
  10349. var _ret;
  10350. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  10351. _classCallCheck(this, Track);
  10352. var _this = _possibleConstructorReturn(this, _EventTarget.call(this));
  10353. var track = _this; // eslint-disable-line
  10354. if (browser.IS_IE8) {
  10355. track = _document2['default'].createElement('custom');
  10356. for (var prop in Track.prototype) {
  10357. if (prop !== 'constructor') {
  10358. track[prop] = Track.prototype[prop];
  10359. }
  10360. }
  10361. }
  10362. var trackProps = {
  10363. id: options.id || 'vjs_track_' + Guid.newGUID(),
  10364. kind: options.kind || '',
  10365. label: options.label || '',
  10366. language: options.language || ''
  10367. };
  10368. /**
  10369. * @member {string} id
  10370. * The id of this track. Cannot be changed after creation.
  10371. *
  10372. * @readonly
  10373. */
  10374. /**
  10375. * @member {string} kind
  10376. * The kind of track that this is. Cannot be changed after creation.
  10377. *
  10378. * @readonly
  10379. */
  10380. /**
  10381. * @member {string} label
  10382. * The label of this track. Cannot be changed after creation.
  10383. *
  10384. * @readonly
  10385. */
  10386. /**
  10387. * @member {string} language
  10388. * The two letter language code for this track. Cannot be changed after
  10389. * creation.
  10390. *
  10391. * @readonly
  10392. */
  10393. var _loop = function _loop(key) {
  10394. Object.defineProperty(track, key, {
  10395. get: function get() {
  10396. return trackProps[key];
  10397. },
  10398. set: function set() {}
  10399. });
  10400. };
  10401. for (var key in trackProps) {
  10402. _loop(key);
  10403. }
  10404. return _ret = track, _possibleConstructorReturn(_this, _ret);
  10405. }
  10406. return Track;
  10407. }(_eventTarget2['default']);
  10408. exports['default'] = Track;
  10409. /***/ }),
  10410. /* 38 */
  10411. /***/ (function(module, exports, __webpack_require__) {
  10412. 'use strict';
  10413. exports.__esModule = true;
  10414. exports.isCrossOrigin = exports.getFileExtension = exports.getAbsoluteURL = exports.parseUrl = undefined;
  10415. var _document = __webpack_require__(8);
  10416. var _document2 = _interopRequireDefault(_document);
  10417. var _window = __webpack_require__(7);
  10418. var _window2 = _interopRequireDefault(_window);
  10419. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  10420. /**
  10421. * @typedef {Object} url:URLObject
  10422. *
  10423. * @property {string} protocol
  10424. * The protocol of the url that was parsed.
  10425. *
  10426. * @property {string} hostname
  10427. * The hostname of the url that was parsed.
  10428. *
  10429. * @property {string} port
  10430. * The port of the url that was parsed.
  10431. *
  10432. * @property {string} pathname
  10433. * The pathname of the url that was parsed.
  10434. *
  10435. * @property {string} search
  10436. * The search query of the url that was parsed.
  10437. *
  10438. * @property {string} hash
  10439. * The hash of the url that was parsed.
  10440. *
  10441. * @property {string} host
  10442. * The host of the url that was parsed.
  10443. */
  10444. /**
  10445. * Resolve and parse the elements of a URL.
  10446. *
  10447. * @param {String} url
  10448. * The url to parse
  10449. *
  10450. * @return {url:URLObject}
  10451. * An object of url details
  10452. */
  10453. /**
  10454. * @file url.js
  10455. * @module url
  10456. */
  10457. var parseUrl = exports.parseUrl = function parseUrl(url) {
  10458. var props = ['protocol', 'hostname', 'port', 'pathname', 'search', 'hash', 'host'];
  10459. // add the url to an anchor and let the browser parse the URL
  10460. var a = _document2['default'].createElement('a');
  10461. a.href = url;
  10462. // IE8 (and 9?) Fix
  10463. // ie8 doesn't parse the URL correctly until the anchor is actually
  10464. // added to the body, and an innerHTML is needed to trigger the parsing
  10465. var addToBody = a.host === '' && a.protocol !== 'file:';
  10466. var div = void 0;
  10467. if (addToBody) {
  10468. div = _document2['default'].createElement('div');
  10469. div.innerHTML = '<a href="' + url + '"></a>';
  10470. a = div.firstChild;
  10471. // prevent the div from affecting layout
  10472. div.setAttribute('style', 'display:none; position:absolute;');
  10473. _document2['default'].body.appendChild(div);
  10474. }
  10475. // Copy the specific URL properties to a new object
  10476. // This is also needed for IE8 because the anchor loses its
  10477. // properties when it's removed from the dom
  10478. var details = {};
  10479. for (var i = 0; i < props.length; i++) {
  10480. details[props[i]] = a[props[i]];
  10481. }
  10482. // IE9 adds the port to the host property unlike everyone else. If
  10483. // a port identifier is added for standard ports, strip it.
  10484. if (details.protocol === 'http:') {
  10485. details.host = details.host.replace(/:80$/, '');
  10486. }
  10487. if (details.protocol === 'https:') {
  10488. details.host = details.host.replace(/:443$/, '');
  10489. }
  10490. if (addToBody) {
  10491. _document2['default'].body.removeChild(div);
  10492. }
  10493. return details;
  10494. };
  10495. /**
  10496. * Get absolute version of relative URL. Used to tell flash correct URL.
  10497. *
  10498. *
  10499. * @param {string} url
  10500. * URL to make absolute
  10501. *
  10502. * @return {string}
  10503. * Absolute URL
  10504. *
  10505. * @see http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue
  10506. */
  10507. var getAbsoluteURL = exports.getAbsoluteURL = function getAbsoluteURL(url) {
  10508. // Check if absolute URL
  10509. if (!url.match(/^https?:\/\//)) {
  10510. // Convert to absolute URL. Flash hosted off-site needs an absolute URL.
  10511. var div = _document2['default'].createElement('div');
  10512. div.innerHTML = '<a href="' + url + '">x</a>';
  10513. url = div.firstChild.href;
  10514. }
  10515. return url;
  10516. };
  10517. /**
  10518. * Returns the extension of the passed file name. It will return an empty string
  10519. * if passed an invalid path.
  10520. *
  10521. * @param {string} path
  10522. * The fileName path like '/path/to/file.mp4'
  10523. *
  10524. * @returns {string}
  10525. * The extension in lower case or an empty string if no
  10526. * extension could be found.
  10527. */
  10528. var getFileExtension = exports.getFileExtension = function getFileExtension(path) {
  10529. if (typeof path === 'string') {
  10530. var splitPathRe = /^(\/?)([\s\S]*?)((?:\.{1,2}|[^\/]+?)(\.([^\.\/\?]+)))(?:[\/]*|[\?].*)$/i;
  10531. var pathParts = splitPathRe.exec(path);
  10532. if (pathParts) {
  10533. return pathParts.pop().toLowerCase();
  10534. }
  10535. }
  10536. return '';
  10537. };
  10538. /**
  10539. * Returns whether the url passed is a cross domain request or not.
  10540. *
  10541. * @param {string} url
  10542. * The url to check.
  10543. *
  10544. * @return {boolean}
  10545. * Whether it is a cross domain request or not.
  10546. */
  10547. var isCrossOrigin = exports.isCrossOrigin = function isCrossOrigin(url) {
  10548. var winLoc = _window2['default'].location;
  10549. var urlInfo = parseUrl(url);
  10550. // IE8 protocol relative urls will return ':' for protocol
  10551. var srcProtocol = urlInfo.protocol === ':' ? winLoc.protocol : urlInfo.protocol;
  10552. // Check if url is for another domain/origin
  10553. // IE8 doesn't know location.origin, so we won't rely on it here
  10554. var crossOrigin = srcProtocol + urlInfo.host !== winLoc.protocol + winLoc.host;
  10555. return crossOrigin;
  10556. };
  10557. /***/ }),
  10558. /* 39 */
  10559. /***/ (function(module, exports, __webpack_require__) {
  10560. "use strict";
  10561. var window = __webpack_require__(2)
  10562. var isFunction = __webpack_require__(40)
  10563. var parseHeaders = __webpack_require__(41)
  10564. var xtend = __webpack_require__(44)
  10565. module.exports = createXHR
  10566. createXHR.XMLHttpRequest = window.XMLHttpRequest || noop
  10567. createXHR.XDomainRequest = "withCredentials" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window.XDomainRequest
  10568. forEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) {
  10569. createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) {
  10570. options = initParams(uri, options, callback)
  10571. options.method = method.toUpperCase()
  10572. return _createXHR(options)
  10573. }
  10574. })
  10575. function forEachArray(array, iterator) {
  10576. for (var i = 0; i < array.length; i++) {
  10577. iterator(array[i])
  10578. }
  10579. }
  10580. function isEmpty(obj){
  10581. for(var i in obj){
  10582. if(obj.hasOwnProperty(i)) return false
  10583. }
  10584. return true
  10585. }
  10586. function initParams(uri, options, callback) {
  10587. var params = uri
  10588. if (isFunction(options)) {
  10589. callback = options
  10590. if (typeof uri === "string") {
  10591. params = {uri:uri}
  10592. }
  10593. } else {
  10594. params = xtend(options, {uri: uri})
  10595. }
  10596. params.callback = callback
  10597. return params
  10598. }
  10599. function createXHR(uri, options, callback) {
  10600. options = initParams(uri, options, callback)
  10601. return _createXHR(options)
  10602. }
  10603. function _createXHR(options) {
  10604. if(typeof options.callback === "undefined"){
  10605. throw new Error("callback argument missing")
  10606. }
  10607. var called = false
  10608. var callback = function cbOnce(err, response, body){
  10609. if(!called){
  10610. called = true
  10611. options.callback(err, response, body)
  10612. }
  10613. }
  10614. function readystatechange() {
  10615. if (xhr.readyState === 4) {
  10616. loadFunc()
  10617. }
  10618. }
  10619. function getBody() {
  10620. // Chrome with requestType=blob throws errors arround when even testing access to responseText
  10621. var body = undefined
  10622. if (xhr.response) {
  10623. body = xhr.response
  10624. } else {
  10625. body = xhr.responseText || getXml(xhr)
  10626. }
  10627. if (isJson) {
  10628. try {
  10629. body = JSON.parse(body)
  10630. } catch (e) {}
  10631. }
  10632. return body
  10633. }
  10634. var failureResponse = {
  10635. body: undefined,
  10636. headers: {},
  10637. statusCode: 0,
  10638. method: method,
  10639. url: uri,
  10640. rawRequest: xhr
  10641. }
  10642. function errorFunc(evt) {
  10643. clearTimeout(timeoutTimer)
  10644. if(!(evt instanceof Error)){
  10645. evt = new Error("" + (evt || "Unknown XMLHttpRequest Error") )
  10646. }
  10647. evt.statusCode = 0
  10648. return callback(evt, failureResponse)
  10649. }
  10650. // will load the data & process the response in a special response object
  10651. function loadFunc() {
  10652. if (aborted) return
  10653. var status
  10654. clearTimeout(timeoutTimer)
  10655. if(options.useXDR && xhr.status===undefined) {
  10656. //IE8 CORS GET successful response doesn't have a status field, but body is fine
  10657. status = 200
  10658. } else {
  10659. status = (xhr.status === 1223 ? 204 : xhr.status)
  10660. }
  10661. var response = failureResponse
  10662. var err = null
  10663. if (status !== 0){
  10664. response = {
  10665. body: getBody(),
  10666. statusCode: status,
  10667. method: method,
  10668. headers: {},
  10669. url: uri,
  10670. rawRequest: xhr
  10671. }
  10672. if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE
  10673. response.headers = parseHeaders(xhr.getAllResponseHeaders())
  10674. }
  10675. } else {
  10676. err = new Error("Internal XMLHttpRequest Error")
  10677. }
  10678. return callback(err, response, response.body)
  10679. }
  10680. var xhr = options.xhr || null
  10681. if (!xhr) {
  10682. if (options.cors || options.useXDR) {
  10683. xhr = new createXHR.XDomainRequest()
  10684. }else{
  10685. xhr = new createXHR.XMLHttpRequest()
  10686. }
  10687. }
  10688. var key
  10689. var aborted
  10690. var uri = xhr.url = options.uri || options.url
  10691. var method = xhr.method = options.method || "GET"
  10692. var body = options.body || options.data || null
  10693. var headers = xhr.headers = options.headers || {}
  10694. var sync = !!options.sync
  10695. var isJson = false
  10696. var timeoutTimer
  10697. if ("json" in options) {
  10698. isJson = true
  10699. headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json") //Don't override existing accept header declared by user
  10700. if (method !== "GET" && method !== "HEAD") {
  10701. headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json") //Don't override existing accept header declared by user
  10702. body = JSON.stringify(options.json)
  10703. }
  10704. }
  10705. xhr.onreadystatechange = readystatechange
  10706. xhr.onload = loadFunc
  10707. xhr.onerror = errorFunc
  10708. // IE9 must have onprogress be set to a unique function.
  10709. xhr.onprogress = function () {
  10710. // IE must die
  10711. }
  10712. xhr.ontimeout = errorFunc
  10713. xhr.open(method, uri, !sync, options.username, options.password)
  10714. //has to be after open
  10715. if(!sync) {
  10716. xhr.withCredentials = !!options.withCredentials
  10717. }
  10718. // Cannot set timeout with sync request
  10719. // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly
  10720. // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent
  10721. if (!sync && options.timeout > 0 ) {
  10722. timeoutTimer = setTimeout(function(){
  10723. aborted=true//IE9 may still call readystatechange
  10724. xhr.abort("timeout")
  10725. var e = new Error("XMLHttpRequest timeout")
  10726. e.code = "ETIMEDOUT"
  10727. errorFunc(e)
  10728. }, options.timeout )
  10729. }
  10730. if (xhr.setRequestHeader) {
  10731. for(key in headers){
  10732. if(headers.hasOwnProperty(key)){
  10733. xhr.setRequestHeader(key, headers[key])
  10734. }
  10735. }
  10736. } else if (options.headers && !isEmpty(options.headers)) {
  10737. throw new Error("Headers cannot be set on an XDomainRequest object")
  10738. }
  10739. if ("responseType" in options) {
  10740. xhr.responseType = options.responseType
  10741. }
  10742. if ("beforeSend" in options &&
  10743. typeof options.beforeSend === "function"
  10744. ) {
  10745. options.beforeSend(xhr)
  10746. }
  10747. xhr.send(body)
  10748. return xhr
  10749. }
  10750. function getXml(xhr) {
  10751. if (xhr.responseType === "document") {
  10752. return xhr.responseXML
  10753. }
  10754. var firefoxBugTakenEffect = xhr.status === 204 && xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror"
  10755. if (xhr.responseType === "" && !firefoxBugTakenEffect) {
  10756. return xhr.responseXML
  10757. }
  10758. return null
  10759. }
  10760. function noop() {}
  10761. /***/ }),
  10762. /* 40 */
  10763. /***/ (function(module, exports) {
  10764. module.exports = isFunction
  10765. var toString = Object.prototype.toString
  10766. function isFunction (fn) {
  10767. var string = toString.call(fn)
  10768. return string === '[object Function]' ||
  10769. (typeof fn === 'function' && string !== '[object RegExp]') ||
  10770. (typeof window !== 'undefined' &&
  10771. // IE8 and below
  10772. (fn === window.setTimeout ||
  10773. fn === window.alert ||
  10774. fn === window.confirm ||
  10775. fn === window.prompt))
  10776. };
  10777. /***/ }),
  10778. /* 41 */
  10779. /***/ (function(module, exports, __webpack_require__) {
  10780. var trim = __webpack_require__(42)
  10781. , forEach = __webpack_require__(43)
  10782. , isArray = function(arg) {
  10783. return Object.prototype.toString.call(arg) === '[object Array]';
  10784. }
  10785. module.exports = function (headers) {
  10786. if (!headers)
  10787. return {}
  10788. var result = {}
  10789. forEach(
  10790. trim(headers).split('\n')
  10791. , function (row) {
  10792. var index = row.indexOf(':')
  10793. , key = trim(row.slice(0, index)).toLowerCase()
  10794. , value = trim(row.slice(index + 1))
  10795. if (typeof(result[key]) === 'undefined') {
  10796. result[key] = value
  10797. } else if (isArray(result[key])) {
  10798. result[key].push(value)
  10799. } else {
  10800. result[key] = [ result[key], value ]
  10801. }
  10802. }
  10803. )
  10804. return result
  10805. }
  10806. /***/ }),
  10807. /* 42 */
  10808. /***/ (function(module, exports) {
  10809. exports = module.exports = trim;
  10810. function trim(str){
  10811. return str.replace(/^\s*|\s*$/g, '');
  10812. }
  10813. exports.left = function(str){
  10814. return str.replace(/^\s*/, '');
  10815. };
  10816. exports.right = function(str){
  10817. return str.replace(/\s*$/, '');
  10818. };
  10819. /***/ }),
  10820. /* 43 */
  10821. /***/ (function(module, exports, __webpack_require__) {
  10822. var isFunction = __webpack_require__(40)
  10823. module.exports = forEach
  10824. var toString = Object.prototype.toString
  10825. var hasOwnProperty = Object.prototype.hasOwnProperty
  10826. function forEach(list, iterator, context) {
  10827. if (!isFunction(iterator)) {
  10828. throw new TypeError('iterator must be a function')
  10829. }
  10830. if (arguments.length < 3) {
  10831. context = this
  10832. }
  10833. if (toString.call(list) === '[object Array]')
  10834. forEachArray(list, iterator, context)
  10835. else if (typeof list === 'string')
  10836. forEachString(list, iterator, context)
  10837. else
  10838. forEachObject(list, iterator, context)
  10839. }
  10840. function forEachArray(array, iterator, context) {
  10841. for (var i = 0, len = array.length; i < len; i++) {
  10842. if (hasOwnProperty.call(array, i)) {
  10843. iterator.call(context, array[i], i, array)
  10844. }
  10845. }
  10846. }
  10847. function forEachString(string, iterator, context) {
  10848. for (var i = 0, len = string.length; i < len; i++) {
  10849. // no such thing as a sparse string.
  10850. iterator.call(context, string.charAt(i), i, string)
  10851. }
  10852. }
  10853. function forEachObject(object, iterator, context) {
  10854. for (var k in object) {
  10855. if (hasOwnProperty.call(object, k)) {
  10856. iterator.call(context, object[k], k, object)
  10857. }
  10858. }
  10859. }
  10860. /***/ }),
  10861. /* 44 */
  10862. /***/ (function(module, exports) {
  10863. module.exports = extend
  10864. var hasOwnProperty = Object.prototype.hasOwnProperty;
  10865. function extend() {
  10866. var target = {}
  10867. for (var i = 0; i < arguments.length; i++) {
  10868. var source = arguments[i]
  10869. for (var key in source) {
  10870. if (hasOwnProperty.call(source, key)) {
  10871. target[key] = source[key]
  10872. }
  10873. }
  10874. }
  10875. return target
  10876. }
  10877. /***/ }),
  10878. /* 45 */
  10879. /***/ (function(module, exports, __webpack_require__) {
  10880. 'use strict';
  10881. exports.__esModule = true;
  10882. var _browser = __webpack_require__(10);
  10883. var browser = _interopRequireWildcard(_browser);
  10884. var _document = __webpack_require__(8);
  10885. var _document2 = _interopRequireDefault(_document);
  10886. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  10887. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  10888. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
  10889. * @file html-track-element-list.js
  10890. */
  10891. /**
  10892. * The current list of {@link HtmlTrackElement}s.
  10893. */
  10894. var HtmlTrackElementList = function () {
  10895. /**
  10896. * Create an instance of this class.
  10897. *
  10898. * @param {HtmlTrackElement[]} [tracks=[]]
  10899. * A list of `HtmlTrackElement` to instantiate the list with.
  10900. */
  10901. function HtmlTrackElementList() {
  10902. var trackElements = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  10903. _classCallCheck(this, HtmlTrackElementList);
  10904. var list = this; // eslint-disable-line
  10905. if (browser.IS_IE8) {
  10906. list = _document2['default'].createElement('custom');
  10907. for (var prop in HtmlTrackElementList.prototype) {
  10908. if (prop !== 'constructor') {
  10909. list[prop] = HtmlTrackElementList.prototype[prop];
  10910. }
  10911. }
  10912. }
  10913. list.trackElements_ = [];
  10914. /**
  10915. * @member {number} length
  10916. * The current number of `Track`s in the this Trackist.
  10917. */
  10918. Object.defineProperty(list, 'length', {
  10919. get: function get() {
  10920. return this.trackElements_.length;
  10921. }
  10922. });
  10923. for (var i = 0, length = trackElements.length; i < length; i++) {
  10924. list.addTrackElement_(trackElements[i]);
  10925. }
  10926. if (browser.IS_IE8) {
  10927. return list;
  10928. }
  10929. }
  10930. /**
  10931. * Add an {@link HtmlTrackElement} to the `HtmlTrackElementList`
  10932. *
  10933. * @param {HtmlTrackElement} trackElement
  10934. * The track element to add to the list.
  10935. *
  10936. * @private
  10937. */
  10938. HtmlTrackElementList.prototype.addTrackElement_ = function addTrackElement_(trackElement) {
  10939. var index = this.trackElements_.length;
  10940. if (!('' + index in this)) {
  10941. Object.defineProperty(this, index, {
  10942. get: function get() {
  10943. return this.trackElements_[index];
  10944. }
  10945. });
  10946. }
  10947. // Do not add duplicate elements
  10948. if (this.trackElements_.indexOf(trackElement) === -1) {
  10949. this.trackElements_.push(trackElement);
  10950. }
  10951. };
  10952. /**
  10953. * Get an {@link HtmlTrackElement} from the `HtmlTrackElementList` given an
  10954. * {@link TextTrack}.
  10955. *
  10956. * @param {TextTrack} track
  10957. * The track associated with a track element.
  10958. *
  10959. * @return {HtmlTrackElement|undefined}
  10960. * The track element that was found or undefined.
  10961. *
  10962. * @private
  10963. */
  10964. HtmlTrackElementList.prototype.getTrackElementByTrack_ = function getTrackElementByTrack_(track) {
  10965. var trackElement_ = void 0;
  10966. for (var i = 0, length = this.trackElements_.length; i < length; i++) {
  10967. if (track === this.trackElements_[i].track) {
  10968. trackElement_ = this.trackElements_[i];
  10969. break;
  10970. }
  10971. }
  10972. return trackElement_;
  10973. };
  10974. /**
  10975. * Remove a {@link HtmlTrackElement} from the `HtmlTrackElementList`
  10976. *
  10977. * @param {HtmlTrackElement} trackElement
  10978. * The track element to remove from the list.
  10979. *
  10980. * @private
  10981. */
  10982. HtmlTrackElementList.prototype.removeTrackElement_ = function removeTrackElement_(trackElement) {
  10983. for (var i = 0, length = this.trackElements_.length; i < length; i++) {
  10984. if (trackElement === this.trackElements_[i]) {
  10985. this.trackElements_.splice(i, 1);
  10986. break;
  10987. }
  10988. }
  10989. };
  10990. return HtmlTrackElementList;
  10991. }();
  10992. exports['default'] = HtmlTrackElementList;
  10993. /***/ }),
  10994. /* 46 */
  10995. /***/ (function(module, exports, __webpack_require__) {
  10996. 'use strict';
  10997. exports.__esModule = true;
  10998. var _trackList = __webpack_require__(47);
  10999. var _trackList2 = _interopRequireDefault(_trackList);
  11000. var _fn = __webpack_require__(20);
  11001. var Fn = _interopRequireWildcard(_fn);
  11002. var _browser = __webpack_require__(10);
  11003. var browser = _interopRequireWildcard(_browser);
  11004. var _document = __webpack_require__(8);
  11005. var _document2 = _interopRequireDefault(_document);
  11006. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  11007. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  11008. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  11009. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  11010. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  11011. * @file text-track-list.js
  11012. */
  11013. /**
  11014. * The current list of {@link TextTrack} for a media file.
  11015. *
  11016. * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttracklist}
  11017. * @extends TrackList
  11018. */
  11019. var TextTrackList = function (_TrackList) {
  11020. _inherits(TextTrackList, _TrackList);
  11021. /**
  11022. * Create an instance of this class.
  11023. *
  11024. * @param {TextTrack[]} [tracks=[]]
  11025. * A list of `TextTrack` to instantiate the list with.
  11026. */
  11027. function TextTrackList() {
  11028. var _this, _ret;
  11029. var tracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  11030. _classCallCheck(this, TextTrackList);
  11031. var list = void 0;
  11032. // IE8 forces us to implement inheritance ourselves
  11033. // as it does not support Object.defineProperty properly
  11034. if (browser.IS_IE8) {
  11035. list = _document2['default'].createElement('custom');
  11036. for (var prop in _trackList2['default'].prototype) {
  11037. if (prop !== 'constructor') {
  11038. list[prop] = _trackList2['default'].prototype[prop];
  11039. }
  11040. }
  11041. for (var _prop in TextTrackList.prototype) {
  11042. if (_prop !== 'constructor') {
  11043. list[_prop] = TextTrackList.prototype[_prop];
  11044. }
  11045. }
  11046. }
  11047. list = (_this = _possibleConstructorReturn(this, _TrackList.call(this, tracks, list)), _this);
  11048. return _ret = list, _possibleConstructorReturn(_this, _ret);
  11049. }
  11050. /**
  11051. * Add a {@link TextTrack} to the `TextTrackList`
  11052. *
  11053. * @param {TextTrack} track
  11054. * The text track to add to the list.
  11055. *
  11056. * @fires TrackList#addtrack
  11057. * @private
  11058. */
  11059. TextTrackList.prototype.addTrack_ = function addTrack_(track) {
  11060. _TrackList.prototype.addTrack_.call(this, track);
  11061. /**
  11062. * @listens TextTrack#modechange
  11063. * @fires TrackList#change
  11064. */
  11065. track.addEventListener('modechange', Fn.bind(this, function () {
  11066. this.trigger('change');
  11067. }));
  11068. };
  11069. return TextTrackList;
  11070. }(_trackList2['default']);
  11071. exports['default'] = TextTrackList;
  11072. /***/ }),
  11073. /* 47 */
  11074. /***/ (function(module, exports, __webpack_require__) {
  11075. 'use strict';
  11076. exports.__esModule = true;
  11077. var _eventTarget = __webpack_require__(23);
  11078. var _eventTarget2 = _interopRequireDefault(_eventTarget);
  11079. var _browser = __webpack_require__(10);
  11080. var browser = _interopRequireWildcard(_browser);
  11081. var _document = __webpack_require__(8);
  11082. var _document2 = _interopRequireDefault(_document);
  11083. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  11084. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  11085. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  11086. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  11087. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  11088. * @file track-list.js
  11089. */
  11090. /**
  11091. * Common functionaliy between {@link TextTrackList}, {@link AudioTrackList}, and
  11092. * {@link VideoTrackList}
  11093. *
  11094. * @extends EventTarget
  11095. */
  11096. var TrackList = function (_EventTarget) {
  11097. _inherits(TrackList, _EventTarget);
  11098. /**
  11099. * Create an instance of this class
  11100. *
  11101. * @param {Track[]} tracks
  11102. * A list of tracks to initialize the list with.
  11103. *
  11104. * @param {Object} [list]
  11105. * The child object with inheritance done manually for ie8.
  11106. *
  11107. * @abstract
  11108. */
  11109. function TrackList() {
  11110. var tracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  11111. var _ret;
  11112. var list = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
  11113. _classCallCheck(this, TrackList);
  11114. var _this = _possibleConstructorReturn(this, _EventTarget.call(this));
  11115. if (!list) {
  11116. list = _this; // eslint-disable-line
  11117. if (browser.IS_IE8) {
  11118. list = _document2['default'].createElement('custom');
  11119. for (var prop in TrackList.prototype) {
  11120. if (prop !== 'constructor') {
  11121. list[prop] = TrackList.prototype[prop];
  11122. }
  11123. }
  11124. }
  11125. }
  11126. list.tracks_ = [];
  11127. /**
  11128. * @member {number} length
  11129. * The current number of `Track`s in the this Trackist.
  11130. */
  11131. Object.defineProperty(list, 'length', {
  11132. get: function get() {
  11133. return this.tracks_.length;
  11134. }
  11135. });
  11136. for (var i = 0; i < tracks.length; i++) {
  11137. list.addTrack_(tracks[i]);
  11138. }
  11139. // must return the object, as for ie8 it will not be this
  11140. // but a reference to a document object
  11141. return _ret = list, _possibleConstructorReturn(_this, _ret);
  11142. }
  11143. /**
  11144. * Add a {@link Track} to the `TrackList`
  11145. *
  11146. * @param {Track} track
  11147. * The audio, video, or text track to add to the list.
  11148. *
  11149. * @fires TrackList#addtrack
  11150. * @private
  11151. */
  11152. TrackList.prototype.addTrack_ = function addTrack_(track) {
  11153. var index = this.tracks_.length;
  11154. if (!('' + index in this)) {
  11155. Object.defineProperty(this, index, {
  11156. get: function get() {
  11157. return this.tracks_[index];
  11158. }
  11159. });
  11160. }
  11161. // Do not add duplicate tracks
  11162. if (this.tracks_.indexOf(track) === -1) {
  11163. this.tracks_.push(track);
  11164. /**
  11165. * Triggered when a track is added to a track list.
  11166. *
  11167. * @event TrackList#addtrack
  11168. * @type {EventTarget~Event}
  11169. * @property {Track} track
  11170. * A reference to track that was added.
  11171. */
  11172. this.trigger({
  11173. track: track,
  11174. type: 'addtrack'
  11175. });
  11176. }
  11177. };
  11178. /**
  11179. * Remove a {@link Track} from the `TrackList`
  11180. *
  11181. * @param {Track} track
  11182. * The audio, video, or text track to remove from the list.
  11183. *
  11184. * @fires TrackList#removetrack
  11185. * @private
  11186. */
  11187. TrackList.prototype.removeTrack_ = function removeTrack_(rtrack) {
  11188. var track = void 0;
  11189. for (var i = 0, l = this.length; i < l; i++) {
  11190. if (this[i] === rtrack) {
  11191. track = this[i];
  11192. if (track.off) {
  11193. track.off();
  11194. }
  11195. this.tracks_.splice(i, 1);
  11196. break;
  11197. }
  11198. }
  11199. if (!track) {
  11200. return;
  11201. }
  11202. /**
  11203. * Triggered when a track is removed from track list.
  11204. *
  11205. * @event TrackList#removetrack
  11206. * @type {EventTarget~Event}
  11207. * @property {Track} track
  11208. * A reference to track that was removed.
  11209. */
  11210. this.trigger({
  11211. track: track,
  11212. type: 'removetrack'
  11213. });
  11214. };
  11215. /**
  11216. * Get a Track from the TrackList by a tracks id
  11217. *
  11218. * @param {String} id - the id of the track to get
  11219. * @method getTrackById
  11220. * @return {Track}
  11221. * @private
  11222. */
  11223. TrackList.prototype.getTrackById = function getTrackById(id) {
  11224. var result = null;
  11225. for (var i = 0, l = this.length; i < l; i++) {
  11226. var track = this[i];
  11227. if (track.id === id) {
  11228. result = track;
  11229. break;
  11230. }
  11231. }
  11232. return result;
  11233. };
  11234. return TrackList;
  11235. }(_eventTarget2['default']);
  11236. /**
  11237. * Triggered when a different track is selected/enabled.
  11238. *
  11239. * @event TrackList#change
  11240. * @type {EventTarget~Event}
  11241. */
  11242. /**
  11243. * Events that can be called with on + eventName. See {@link EventHandler}.
  11244. *
  11245. * @property {Object} TrackList#allowedEvents_
  11246. * @private
  11247. */
  11248. TrackList.prototype.allowedEvents_ = {
  11249. change: 'change',
  11250. addtrack: 'addtrack',
  11251. removetrack: 'removetrack'
  11252. };
  11253. // emulate attribute EventHandler support to allow for feature detection
  11254. for (var event in TrackList.prototype.allowedEvents_) {
  11255. TrackList.prototype['on' + event] = null;
  11256. }
  11257. exports['default'] = TrackList;
  11258. /***/ }),
  11259. /* 48 */
  11260. /***/ (function(module, exports, __webpack_require__) {
  11261. 'use strict';
  11262. exports.__esModule = true;
  11263. var _trackList = __webpack_require__(47);
  11264. var _trackList2 = _interopRequireDefault(_trackList);
  11265. var _browser = __webpack_require__(10);
  11266. var browser = _interopRequireWildcard(_browser);
  11267. var _document = __webpack_require__(8);
  11268. var _document2 = _interopRequireDefault(_document);
  11269. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  11270. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  11271. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  11272. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  11273. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  11274. * @file video-track-list.js
  11275. */
  11276. /**
  11277. * Un-select all other {@link VideoTrack}s that are selected.
  11278. *
  11279. * @param {VideoTrackList} list
  11280. * list to work on
  11281. *
  11282. * @param {VideoTrack} track
  11283. * The track to skip
  11284. *
  11285. * @private
  11286. */
  11287. var disableOthers = function disableOthers(list, track) {
  11288. for (var i = 0; i < list.length; i++) {
  11289. if (track.id === list[i].id) {
  11290. continue;
  11291. }
  11292. // another video track is enabled, disable it
  11293. list[i].selected = false;
  11294. }
  11295. };
  11296. /**
  11297. * The current list of {@link VideoTrack} for a video.
  11298. *
  11299. * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#videotracklist}
  11300. * @extends TrackList
  11301. */
  11302. var VideoTrackList = function (_TrackList) {
  11303. _inherits(VideoTrackList, _TrackList);
  11304. /**
  11305. * Create an instance of this class.
  11306. *
  11307. * @param {VideoTrack[]} [tracks=[]]
  11308. * A list of `VideoTrack` to instantiate the list with.
  11309. */
  11310. function VideoTrackList() {
  11311. var _this, _ret;
  11312. var tracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  11313. _classCallCheck(this, VideoTrackList);
  11314. var list = void 0;
  11315. // make sure only 1 track is enabled
  11316. // sorted from last index to first index
  11317. for (var i = tracks.length - 1; i >= 0; i--) {
  11318. if (tracks[i].selected) {
  11319. disableOthers(tracks, tracks[i]);
  11320. break;
  11321. }
  11322. }
  11323. // IE8 forces us to implement inheritance ourselves
  11324. // as it does not support Object.defineProperty properly
  11325. if (browser.IS_IE8) {
  11326. list = _document2['default'].createElement('custom');
  11327. for (var prop in _trackList2['default'].prototype) {
  11328. if (prop !== 'constructor') {
  11329. list[prop] = _trackList2['default'].prototype[prop];
  11330. }
  11331. }
  11332. for (var _prop in VideoTrackList.prototype) {
  11333. if (_prop !== 'constructor') {
  11334. list[_prop] = VideoTrackList.prototype[_prop];
  11335. }
  11336. }
  11337. }
  11338. list = (_this = _possibleConstructorReturn(this, _TrackList.call(this, tracks, list)), _this);
  11339. list.changing_ = false;
  11340. /**
  11341. * @member {number} VideoTrackList#selectedIndex
  11342. * The current index of the selected {@link VideoTrack`}.
  11343. */
  11344. Object.defineProperty(list, 'selectedIndex', {
  11345. get: function get() {
  11346. for (var _i = 0; _i < this.length; _i++) {
  11347. if (this[_i].selected) {
  11348. return _i;
  11349. }
  11350. }
  11351. return -1;
  11352. },
  11353. set: function set() {}
  11354. });
  11355. return _ret = list, _possibleConstructorReturn(_this, _ret);
  11356. }
  11357. /**
  11358. * Add a {@link VideoTrack} to the `VideoTrackList`.
  11359. *
  11360. * @param {VideoTrack} track
  11361. * The VideoTrack to add to the list
  11362. *
  11363. * @fires TrackList#addtrack
  11364. * @private
  11365. */
  11366. VideoTrackList.prototype.addTrack_ = function addTrack_(track) {
  11367. var _this2 = this;
  11368. if (track.selected) {
  11369. disableOthers(this, track);
  11370. }
  11371. _TrackList.prototype.addTrack_.call(this, track);
  11372. // native tracks don't have this
  11373. if (!track.addEventListener) {
  11374. return;
  11375. }
  11376. /**
  11377. * @listens VideoTrack#selectedchange
  11378. * @fires TrackList#change
  11379. */
  11380. track.addEventListener('selectedchange', function () {
  11381. if (_this2.changing_) {
  11382. return;
  11383. }
  11384. _this2.changing_ = true;
  11385. disableOthers(_this2, track);
  11386. _this2.changing_ = false;
  11387. _this2.trigger('change');
  11388. });
  11389. };
  11390. /**
  11391. * Add a {@link VideoTrack} to the `VideoTrackList`.
  11392. *
  11393. * @param {VideoTrack} track
  11394. * The VideoTrack to add to the list
  11395. *
  11396. * @fires TrackList#addtrack
  11397. */
  11398. VideoTrackList.prototype.addTrack = function addTrack(track) {
  11399. this.addTrack_(track);
  11400. };
  11401. /**
  11402. * Remove a {@link VideoTrack} to the `VideoTrackList`.
  11403. *
  11404. * @param {VideoTrack} track
  11405. * The VideoTrack to remove from the list.
  11406. *
  11407. * @fires TrackList#removetrack
  11408. */
  11409. VideoTrackList.prototype.removeTrack = function removeTrack(track) {
  11410. _TrackList.prototype.removeTrack_.call(this, track);
  11411. };
  11412. return VideoTrackList;
  11413. }(_trackList2['default']);
  11414. exports['default'] = VideoTrackList;
  11415. /***/ }),
  11416. /* 49 */
  11417. /***/ (function(module, exports, __webpack_require__) {
  11418. 'use strict';
  11419. exports.__esModule = true;
  11420. var _trackList = __webpack_require__(47);
  11421. var _trackList2 = _interopRequireDefault(_trackList);
  11422. var _browser = __webpack_require__(10);
  11423. var browser = _interopRequireWildcard(_browser);
  11424. var _document = __webpack_require__(8);
  11425. var _document2 = _interopRequireDefault(_document);
  11426. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  11427. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  11428. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  11429. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  11430. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  11431. * @file audio-track-list.js
  11432. */
  11433. /**
  11434. * Anywhere we call this function we diverge from the spec
  11435. * as we only support one enabled audiotrack at a time
  11436. *
  11437. * @param {AudioTrackList} list
  11438. * list to work on
  11439. *
  11440. * @param {AudioTrack} track
  11441. * The track to skip
  11442. *
  11443. * @private
  11444. */
  11445. var disableOthers = function disableOthers(list, track) {
  11446. for (var i = 0; i < list.length; i++) {
  11447. if (track.id === list[i].id) {
  11448. continue;
  11449. }
  11450. // another audio track is enabled, disable it
  11451. list[i].enabled = false;
  11452. }
  11453. };
  11454. /**
  11455. * The current list of {@link AudioTrack} for a media file.
  11456. *
  11457. * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#audiotracklist}
  11458. * @extends TrackList
  11459. */
  11460. var AudioTrackList = function (_TrackList) {
  11461. _inherits(AudioTrackList, _TrackList);
  11462. /**
  11463. * Create an instance of this class.
  11464. *
  11465. * @param {AudioTrack[]} [tracks=[]]
  11466. * A list of `AudioTrack` to instantiate the list with.
  11467. */
  11468. function AudioTrackList() {
  11469. var _this, _ret;
  11470. var tracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  11471. _classCallCheck(this, AudioTrackList);
  11472. var list = void 0;
  11473. // make sure only 1 track is enabled
  11474. // sorted from last index to first index
  11475. for (var i = tracks.length - 1; i >= 0; i--) {
  11476. if (tracks[i].enabled) {
  11477. disableOthers(tracks, tracks[i]);
  11478. break;
  11479. }
  11480. }
  11481. // IE8 forces us to implement inheritance ourselves
  11482. // as it does not support Object.defineProperty properly
  11483. if (browser.IS_IE8) {
  11484. list = _document2['default'].createElement('custom');
  11485. for (var prop in _trackList2['default'].prototype) {
  11486. if (prop !== 'constructor') {
  11487. list[prop] = _trackList2['default'].prototype[prop];
  11488. }
  11489. }
  11490. for (var _prop in AudioTrackList.prototype) {
  11491. if (_prop !== 'constructor') {
  11492. list[_prop] = AudioTrackList.prototype[_prop];
  11493. }
  11494. }
  11495. }
  11496. list = (_this = _possibleConstructorReturn(this, _TrackList.call(this, tracks, list)), _this);
  11497. list.changing_ = false;
  11498. return _ret = list, _possibleConstructorReturn(_this, _ret);
  11499. }
  11500. /**
  11501. * Add an {@link AudioTrack} to the `AudioTrackList`.
  11502. *
  11503. * @param {AudioTrack} track
  11504. * The AudioTrack to add to the list
  11505. *
  11506. * @fires Track#addtrack
  11507. * @private
  11508. */
  11509. AudioTrackList.prototype.addTrack_ = function addTrack_(track) {
  11510. var _this2 = this;
  11511. if (track.enabled) {
  11512. disableOthers(this, track);
  11513. }
  11514. _TrackList.prototype.addTrack_.call(this, track);
  11515. // native tracks don't have this
  11516. if (!track.addEventListener) {
  11517. return;
  11518. }
  11519. /**
  11520. * @listens AudioTrack#enabledchange
  11521. * @fires TrackList#change
  11522. */
  11523. track.addEventListener('enabledchange', function () {
  11524. // when we are disabling other tracks (since we don't support
  11525. // more than one track at a time) we will set changing_
  11526. // to true so that we don't trigger additional change events
  11527. if (_this2.changing_) {
  11528. return;
  11529. }
  11530. _this2.changing_ = true;
  11531. disableOthers(_this2, track);
  11532. _this2.changing_ = false;
  11533. _this2.trigger('change');
  11534. });
  11535. };
  11536. /**
  11537. * Add an {@link AudioTrack} to the `AudioTrackList`.
  11538. *
  11539. * @param {AudioTrack} track
  11540. * The AudioTrack to add to the list
  11541. *
  11542. * @fires Track#addtrack
  11543. */
  11544. AudioTrackList.prototype.addTrack = function addTrack(track) {
  11545. this.addTrack_(track);
  11546. };
  11547. /**
  11548. * Remove an {@link AudioTrack} from the `AudioTrackList`.
  11549. *
  11550. * @param {AudioTrack} track
  11551. * The AudioTrack to remove from the list
  11552. *
  11553. * @fires Track#removetrack
  11554. */
  11555. AudioTrackList.prototype.removeTrack = function removeTrack(track) {
  11556. _TrackList.prototype.removeTrack_.call(this, track);
  11557. };
  11558. return AudioTrackList;
  11559. }(_trackList2['default']);
  11560. exports['default'] = AudioTrackList;
  11561. /***/ }),
  11562. /* 50 */
  11563. /***/ (function(module, exports, __webpack_require__) {
  11564. /**
  11565. * Copyright 2013 vtt.js Contributors
  11566. *
  11567. * Licensed under the Apache License, Version 2.0 (the "License");
  11568. * you may not use this file except in compliance with the License.
  11569. * You may obtain a copy of the License at
  11570. *
  11571. * http://www.apache.org/licenses/LICENSE-2.0
  11572. *
  11573. * Unless required by applicable law or agreed to in writing, software
  11574. * distributed under the License is distributed on an "AS IS" BASIS,
  11575. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11576. * See the License for the specific language governing permissions and
  11577. * limitations under the License.
  11578. */
  11579. // Default exports for Node. Export the extended versions of VTTCue and
  11580. // VTTRegion in Node since we likely want the capability to convert back and
  11581. // forth between JSON. If we don't then it's not that big of a deal since we're
  11582. // off browser.
  11583. var window = __webpack_require__(2);
  11584. var vttjs = module.exports = {
  11585. WebVTT: __webpack_require__(51),
  11586. VTTCue: __webpack_require__(52),
  11587. VTTRegion: __webpack_require__(53)
  11588. };
  11589. window.vttjs = vttjs;
  11590. window.WebVTT = vttjs.WebVTT;
  11591. var cueShim = vttjs.VTTCue;
  11592. var regionShim = vttjs.VTTRegion;
  11593. var nativeVTTCue = window.VTTCue;
  11594. var nativeVTTRegion = window.VTTRegion;
  11595. vttjs.shim = function() {
  11596. window.VTTCue = cueShim;
  11597. window.VTTRegion = regionShim;
  11598. };
  11599. vttjs.restore = function() {
  11600. window.VTTCue = nativeVTTCue;
  11601. window.VTTRegion = nativeVTTRegion;
  11602. };
  11603. if (!window.VTTCue) {
  11604. vttjs.shim();
  11605. }
  11606. /***/ }),
  11607. /* 51 */
  11608. /***/ (function(module, exports) {
  11609. /**
  11610. * Copyright 2013 vtt.js Contributors
  11611. *
  11612. * Licensed under the Apache License, Version 2.0 (the "License");
  11613. * you may not use this file except in compliance with the License.
  11614. * You may obtain a copy of the License at
  11615. *
  11616. * http://www.apache.org/licenses/LICENSE-2.0
  11617. *
  11618. * Unless required by applicable law or agreed to in writing, software
  11619. * distributed under the License is distributed on an "AS IS" BASIS,
  11620. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11621. * See the License for the specific language governing permissions and
  11622. * limitations under the License.
  11623. */
  11624. /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  11625. /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
  11626. var _objCreate = Object.create || (function() {
  11627. function F() {}
  11628. return function(o) {
  11629. if (arguments.length !== 1) {
  11630. throw new Error('Object.create shim only accepts one parameter.');
  11631. }
  11632. F.prototype = o;
  11633. return new F();
  11634. };
  11635. })();
  11636. // Creates a new ParserError object from an errorData object. The errorData
  11637. // object should have default code and message properties. The default message
  11638. // property can be overriden by passing in a message parameter.
  11639. // See ParsingError.Errors below for acceptable errors.
  11640. function ParsingError(errorData, message) {
  11641. this.name = "ParsingError";
  11642. this.code = errorData.code;
  11643. this.message = message || errorData.message;
  11644. }
  11645. ParsingError.prototype = _objCreate(Error.prototype);
  11646. ParsingError.prototype.constructor = ParsingError;
  11647. // ParsingError metadata for acceptable ParsingErrors.
  11648. ParsingError.Errors = {
  11649. BadSignature: {
  11650. code: 0,
  11651. message: "Malformed WebVTT signature."
  11652. },
  11653. BadTimeStamp: {
  11654. code: 1,
  11655. message: "Malformed time stamp."
  11656. }
  11657. };
  11658. // Try to parse input as a time stamp.
  11659. function parseTimeStamp(input) {
  11660. function computeSeconds(h, m, s, f) {
  11661. return (h | 0) * 3600 + (m | 0) * 60 + (s | 0) + (f | 0) / 1000;
  11662. }
  11663. var m = input.match(/^(\d+):(\d{2})(:\d{2})?\.(\d{3})/);
  11664. if (!m) {
  11665. return null;
  11666. }
  11667. if (m[3]) {
  11668. // Timestamp takes the form of [hours]:[minutes]:[seconds].[milliseconds]
  11669. return computeSeconds(m[1], m[2], m[3].replace(":", ""), m[4]);
  11670. } else if (m[1] > 59) {
  11671. // Timestamp takes the form of [hours]:[minutes].[milliseconds]
  11672. // First position is hours as it's over 59.
  11673. return computeSeconds(m[1], m[2], 0, m[4]);
  11674. } else {
  11675. // Timestamp takes the form of [minutes]:[seconds].[milliseconds]
  11676. return computeSeconds(0, m[1], m[2], m[4]);
  11677. }
  11678. }
  11679. // A settings object holds key/value pairs and will ignore anything but the first
  11680. // assignment to a specific key.
  11681. function Settings() {
  11682. this.values = _objCreate(null);
  11683. }
  11684. Settings.prototype = {
  11685. // Only accept the first assignment to any key.
  11686. set: function(k, v) {
  11687. if (!this.get(k) && v !== "") {
  11688. this.values[k] = v;
  11689. }
  11690. },
  11691. // Return the value for a key, or a default value.
  11692. // If 'defaultKey' is passed then 'dflt' is assumed to be an object with
  11693. // a number of possible default values as properties where 'defaultKey' is
  11694. // the key of the property that will be chosen; otherwise it's assumed to be
  11695. // a single value.
  11696. get: function(k, dflt, defaultKey) {
  11697. if (defaultKey) {
  11698. return this.has(k) ? this.values[k] : dflt[defaultKey];
  11699. }
  11700. return this.has(k) ? this.values[k] : dflt;
  11701. },
  11702. // Check whether we have a value for a key.
  11703. has: function(k) {
  11704. return k in this.values;
  11705. },
  11706. // Accept a setting if its one of the given alternatives.
  11707. alt: function(k, v, a) {
  11708. for (var n = 0; n < a.length; ++n) {
  11709. if (v === a[n]) {
  11710. this.set(k, v);
  11711. break;
  11712. }
  11713. }
  11714. },
  11715. // Accept a setting if its a valid (signed) integer.
  11716. integer: function(k, v) {
  11717. if (/^-?\d+$/.test(v)) { // integer
  11718. this.set(k, parseInt(v, 10));
  11719. }
  11720. },
  11721. // Accept a setting if its a valid percentage.
  11722. percent: function(k, v) {
  11723. var m;
  11724. if ((m = v.match(/^([\d]{1,3})(\.[\d]*)?%$/))) {
  11725. v = parseFloat(v);
  11726. if (v >= 0 && v <= 100) {
  11727. this.set(k, v);
  11728. return true;
  11729. }
  11730. }
  11731. return false;
  11732. }
  11733. };
  11734. // Helper function to parse input into groups separated by 'groupDelim', and
  11735. // interprete each group as a key/value pair separated by 'keyValueDelim'.
  11736. function parseOptions(input, callback, keyValueDelim, groupDelim) {
  11737. var groups = groupDelim ? input.split(groupDelim) : [input];
  11738. for (var i in groups) {
  11739. if (typeof groups[i] !== "string") {
  11740. continue;
  11741. }
  11742. var kv = groups[i].split(keyValueDelim);
  11743. if (kv.length !== 2) {
  11744. continue;
  11745. }
  11746. var k = kv[0];
  11747. var v = kv[1];
  11748. callback(k, v);
  11749. }
  11750. }
  11751. function parseCue(input, cue, regionList) {
  11752. // Remember the original input if we need to throw an error.
  11753. var oInput = input;
  11754. // 4.1 WebVTT timestamp
  11755. function consumeTimeStamp() {
  11756. var ts = parseTimeStamp(input);
  11757. if (ts === null) {
  11758. throw new ParsingError(ParsingError.Errors.BadTimeStamp,
  11759. "Malformed timestamp: " + oInput);
  11760. }
  11761. // Remove time stamp from input.
  11762. input = input.replace(/^[^\sa-zA-Z-]+/, "");
  11763. return ts;
  11764. }
  11765. // 4.4.2 WebVTT cue settings
  11766. function consumeCueSettings(input, cue) {
  11767. var settings = new Settings();
  11768. parseOptions(input, function (k, v) {
  11769. switch (k) {
  11770. case "region":
  11771. // Find the last region we parsed with the same region id.
  11772. for (var i = regionList.length - 1; i >= 0; i--) {
  11773. if (regionList[i].id === v) {
  11774. settings.set(k, regionList[i].region);
  11775. break;
  11776. }
  11777. }
  11778. break;
  11779. case "vertical":
  11780. settings.alt(k, v, ["rl", "lr"]);
  11781. break;
  11782. case "line":
  11783. var vals = v.split(","),
  11784. vals0 = vals[0];
  11785. settings.integer(k, vals0);
  11786. settings.percent(k, vals0) ? settings.set("snapToLines", false) : null;
  11787. settings.alt(k, vals0, ["auto"]);
  11788. if (vals.length === 2) {
  11789. settings.alt("lineAlign", vals[1], ["start", "middle", "end"]);
  11790. }
  11791. break;
  11792. case "position":
  11793. vals = v.split(",");
  11794. settings.percent(k, vals[0]);
  11795. if (vals.length === 2) {
  11796. settings.alt("positionAlign", vals[1], ["start", "middle", "end"]);
  11797. }
  11798. break;
  11799. case "size":
  11800. settings.percent(k, v);
  11801. break;
  11802. case "align":
  11803. settings.alt(k, v, ["start", "middle", "end", "left", "right"]);
  11804. break;
  11805. }
  11806. }, /:/, /\s/);
  11807. // Apply default values for any missing fields.
  11808. cue.region = settings.get("region", null);
  11809. cue.vertical = settings.get("vertical", "");
  11810. cue.line = settings.get("line", "auto");
  11811. cue.lineAlign = settings.get("lineAlign", "start");
  11812. cue.snapToLines = settings.get("snapToLines", true);
  11813. cue.size = settings.get("size", 100);
  11814. cue.align = settings.get("align", "middle");
  11815. cue.position = settings.get("position", {
  11816. start: 0,
  11817. left: 0,
  11818. middle: 50,
  11819. end: 100,
  11820. right: 100
  11821. }, cue.align);
  11822. cue.positionAlign = settings.get("positionAlign", {
  11823. start: "start",
  11824. left: "start",
  11825. middle: "middle",
  11826. end: "end",
  11827. right: "end"
  11828. }, cue.align);
  11829. }
  11830. function skipWhitespace() {
  11831. input = input.replace(/^\s+/, "");
  11832. }
  11833. // 4.1 WebVTT cue timings.
  11834. skipWhitespace();
  11835. cue.startTime = consumeTimeStamp(); // (1) collect cue start time
  11836. skipWhitespace();
  11837. if (input.substr(0, 3) !== "-->") { // (3) next characters must match "-->"
  11838. throw new ParsingError(ParsingError.Errors.BadTimeStamp,
  11839. "Malformed time stamp (time stamps must be separated by '-->'): " +
  11840. oInput);
  11841. }
  11842. input = input.substr(3);
  11843. skipWhitespace();
  11844. cue.endTime = consumeTimeStamp(); // (5) collect cue end time
  11845. // 4.1 WebVTT cue settings list.
  11846. skipWhitespace();
  11847. consumeCueSettings(input, cue);
  11848. }
  11849. var ESCAPE = {
  11850. "&amp;": "&",
  11851. "&lt;": "<",
  11852. "&gt;": ">",
  11853. "&lrm;": "\u200e",
  11854. "&rlm;": "\u200f",
  11855. "&nbsp;": "\u00a0"
  11856. };
  11857. var TAG_NAME = {
  11858. c: "span",
  11859. i: "i",
  11860. b: "b",
  11861. u: "u",
  11862. ruby: "ruby",
  11863. rt: "rt",
  11864. v: "span",
  11865. lang: "span"
  11866. };
  11867. var TAG_ANNOTATION = {
  11868. v: "title",
  11869. lang: "lang"
  11870. };
  11871. var NEEDS_PARENT = {
  11872. rt: "ruby"
  11873. };
  11874. // Parse content into a document fragment.
  11875. function parseContent(window, input) {
  11876. function nextToken() {
  11877. // Check for end-of-string.
  11878. if (!input) {
  11879. return null;
  11880. }
  11881. // Consume 'n' characters from the input.
  11882. function consume(result) {
  11883. input = input.substr(result.length);
  11884. return result;
  11885. }
  11886. var m = input.match(/^([^<]*)(<[^>]+>?)?/);
  11887. // If there is some text before the next tag, return it, otherwise return
  11888. // the tag.
  11889. return consume(m[1] ? m[1] : m[2]);
  11890. }
  11891. // Unescape a string 's'.
  11892. function unescape1(e) {
  11893. return ESCAPE[e];
  11894. }
  11895. function unescape(s) {
  11896. while ((m = s.match(/&(amp|lt|gt|lrm|rlm|nbsp);/))) {
  11897. s = s.replace(m[0], unescape1);
  11898. }
  11899. return s;
  11900. }
  11901. function shouldAdd(current, element) {
  11902. return !NEEDS_PARENT[element.localName] ||
  11903. NEEDS_PARENT[element.localName] === current.localName;
  11904. }
  11905. // Create an element for this tag.
  11906. function createElement(type, annotation) {
  11907. var tagName = TAG_NAME[type];
  11908. if (!tagName) {
  11909. return null;
  11910. }
  11911. var element = window.document.createElement(tagName);
  11912. element.localName = tagName;
  11913. var name = TAG_ANNOTATION[type];
  11914. if (name && annotation) {
  11915. element[name] = annotation.trim();
  11916. }
  11917. return element;
  11918. }
  11919. var rootDiv = window.document.createElement("div"),
  11920. current = rootDiv,
  11921. t,
  11922. tagStack = [];
  11923. while ((t = nextToken()) !== null) {
  11924. if (t[0] === '<') {
  11925. if (t[1] === "/") {
  11926. // If the closing tag matches, move back up to the parent node.
  11927. if (tagStack.length &&
  11928. tagStack[tagStack.length - 1] === t.substr(2).replace(">", "")) {
  11929. tagStack.pop();
  11930. current = current.parentNode;
  11931. }
  11932. // Otherwise just ignore the end tag.
  11933. continue;
  11934. }
  11935. var ts = parseTimeStamp(t.substr(1, t.length - 2));
  11936. var node;
  11937. if (ts) {
  11938. // Timestamps are lead nodes as well.
  11939. node = window.document.createProcessingInstruction("timestamp", ts);
  11940. current.appendChild(node);
  11941. continue;
  11942. }
  11943. var m = t.match(/^<([^.\s/0-9>]+)(\.[^\s\\>]+)?([^>\\]+)?(\\?)>?$/);
  11944. // If we can't parse the tag, skip to the next tag.
  11945. if (!m) {
  11946. continue;
  11947. }
  11948. // Try to construct an element, and ignore the tag if we couldn't.
  11949. node = createElement(m[1], m[3]);
  11950. if (!node) {
  11951. continue;
  11952. }
  11953. // Determine if the tag should be added based on the context of where it
  11954. // is placed in the cuetext.
  11955. if (!shouldAdd(current, node)) {
  11956. continue;
  11957. }
  11958. // Set the class list (as a list of classes, separated by space).
  11959. if (m[2]) {
  11960. node.className = m[2].substr(1).replace('.', ' ');
  11961. }
  11962. // Append the node to the current node, and enter the scope of the new
  11963. // node.
  11964. tagStack.push(m[1]);
  11965. current.appendChild(node);
  11966. current = node;
  11967. continue;
  11968. }
  11969. // Text nodes are leaf nodes.
  11970. current.appendChild(window.document.createTextNode(unescape(t)));
  11971. }
  11972. return rootDiv;
  11973. }
  11974. // This is a list of all the Unicode characters that have a strong
  11975. // right-to-left category. What this means is that these characters are
  11976. // written right-to-left for sure. It was generated by pulling all the strong
  11977. // right-to-left characters out of the Unicode data table. That table can
  11978. // found at: http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
  11979. var strongRTLRanges = [[0x5be, 0x5be], [0x5c0, 0x5c0], [0x5c3, 0x5c3], [0x5c6, 0x5c6],
  11980. [0x5d0, 0x5ea], [0x5f0, 0x5f4], [0x608, 0x608], [0x60b, 0x60b], [0x60d, 0x60d],
  11981. [0x61b, 0x61b], [0x61e, 0x64a], [0x66d, 0x66f], [0x671, 0x6d5], [0x6e5, 0x6e6],
  11982. [0x6ee, 0x6ef], [0x6fa, 0x70d], [0x70f, 0x710], [0x712, 0x72f], [0x74d, 0x7a5],
  11983. [0x7b1, 0x7b1], [0x7c0, 0x7ea], [0x7f4, 0x7f5], [0x7fa, 0x7fa], [0x800, 0x815],
  11984. [0x81a, 0x81a], [0x824, 0x824], [0x828, 0x828], [0x830, 0x83e], [0x840, 0x858],
  11985. [0x85e, 0x85e], [0x8a0, 0x8a0], [0x8a2, 0x8ac], [0x200f, 0x200f],
  11986. [0xfb1d, 0xfb1d], [0xfb1f, 0xfb28], [0xfb2a, 0xfb36], [0xfb38, 0xfb3c],
  11987. [0xfb3e, 0xfb3e], [0xfb40, 0xfb41], [0xfb43, 0xfb44], [0xfb46, 0xfbc1],
  11988. [0xfbd3, 0xfd3d], [0xfd50, 0xfd8f], [0xfd92, 0xfdc7], [0xfdf0, 0xfdfc],
  11989. [0xfe70, 0xfe74], [0xfe76, 0xfefc], [0x10800, 0x10805], [0x10808, 0x10808],
  11990. [0x1080a, 0x10835], [0x10837, 0x10838], [0x1083c, 0x1083c], [0x1083f, 0x10855],
  11991. [0x10857, 0x1085f], [0x10900, 0x1091b], [0x10920, 0x10939], [0x1093f, 0x1093f],
  11992. [0x10980, 0x109b7], [0x109be, 0x109bf], [0x10a00, 0x10a00], [0x10a10, 0x10a13],
  11993. [0x10a15, 0x10a17], [0x10a19, 0x10a33], [0x10a40, 0x10a47], [0x10a50, 0x10a58],
  11994. [0x10a60, 0x10a7f], [0x10b00, 0x10b35], [0x10b40, 0x10b55], [0x10b58, 0x10b72],
  11995. [0x10b78, 0x10b7f], [0x10c00, 0x10c48], [0x1ee00, 0x1ee03], [0x1ee05, 0x1ee1f],
  11996. [0x1ee21, 0x1ee22], [0x1ee24, 0x1ee24], [0x1ee27, 0x1ee27], [0x1ee29, 0x1ee32],
  11997. [0x1ee34, 0x1ee37], [0x1ee39, 0x1ee39], [0x1ee3b, 0x1ee3b], [0x1ee42, 0x1ee42],
  11998. [0x1ee47, 0x1ee47], [0x1ee49, 0x1ee49], [0x1ee4b, 0x1ee4b], [0x1ee4d, 0x1ee4f],
  11999. [0x1ee51, 0x1ee52], [0x1ee54, 0x1ee54], [0x1ee57, 0x1ee57], [0x1ee59, 0x1ee59],
  12000. [0x1ee5b, 0x1ee5b], [0x1ee5d, 0x1ee5d], [0x1ee5f, 0x1ee5f], [0x1ee61, 0x1ee62],
  12001. [0x1ee64, 0x1ee64], [0x1ee67, 0x1ee6a], [0x1ee6c, 0x1ee72], [0x1ee74, 0x1ee77],
  12002. [0x1ee79, 0x1ee7c], [0x1ee7e, 0x1ee7e], [0x1ee80, 0x1ee89], [0x1ee8b, 0x1ee9b],
  12003. [0x1eea1, 0x1eea3], [0x1eea5, 0x1eea9], [0x1eeab, 0x1eebb], [0x10fffd, 0x10fffd]];
  12004. function isStrongRTLChar(charCode) {
  12005. for (var i = 0; i < strongRTLRanges.length; i++) {
  12006. var currentRange = strongRTLRanges[i];
  12007. if (charCode >= currentRange[0] && charCode <= currentRange[1]) {
  12008. return true;
  12009. }
  12010. }
  12011. return false;
  12012. }
  12013. function determineBidi(cueDiv) {
  12014. var nodeStack = [],
  12015. text = "",
  12016. charCode;
  12017. if (!cueDiv || !cueDiv.childNodes) {
  12018. return "ltr";
  12019. }
  12020. function pushNodes(nodeStack, node) {
  12021. for (var i = node.childNodes.length - 1; i >= 0; i--) {
  12022. nodeStack.push(node.childNodes[i]);
  12023. }
  12024. }
  12025. function nextTextNode(nodeStack) {
  12026. if (!nodeStack || !nodeStack.length) {
  12027. return null;
  12028. }
  12029. var node = nodeStack.pop(),
  12030. text = node.textContent || node.innerText;
  12031. if (text) {
  12032. // TODO: This should match all unicode type B characters (paragraph
  12033. // separator characters). See issue #115.
  12034. var m = text.match(/^.*(\n|\r)/);
  12035. if (m) {
  12036. nodeStack.length = 0;
  12037. return m[0];
  12038. }
  12039. return text;
  12040. }
  12041. if (node.tagName === "ruby") {
  12042. return nextTextNode(nodeStack);
  12043. }
  12044. if (node.childNodes) {
  12045. pushNodes(nodeStack, node);
  12046. return nextTextNode(nodeStack);
  12047. }
  12048. }
  12049. pushNodes(nodeStack, cueDiv);
  12050. while ((text = nextTextNode(nodeStack))) {
  12051. for (var i = 0; i < text.length; i++) {
  12052. charCode = text.charCodeAt(i);
  12053. if (isStrongRTLChar(charCode)) {
  12054. return "rtl";
  12055. }
  12056. }
  12057. }
  12058. return "ltr";
  12059. }
  12060. function computeLinePos(cue) {
  12061. if (typeof cue.line === "number" &&
  12062. (cue.snapToLines || (cue.line >= 0 && cue.line <= 100))) {
  12063. return cue.line;
  12064. }
  12065. if (!cue.track || !cue.track.textTrackList ||
  12066. !cue.track.textTrackList.mediaElement) {
  12067. return -1;
  12068. }
  12069. var track = cue.track,
  12070. trackList = track.textTrackList,
  12071. count = 0;
  12072. for (var i = 0; i < trackList.length && trackList[i] !== track; i++) {
  12073. if (trackList[i].mode === "showing") {
  12074. count++;
  12075. }
  12076. }
  12077. return ++count * -1;
  12078. }
  12079. function StyleBox() {
  12080. }
  12081. // Apply styles to a div. If there is no div passed then it defaults to the
  12082. // div on 'this'.
  12083. StyleBox.prototype.applyStyles = function(styles, div) {
  12084. div = div || this.div;
  12085. for (var prop in styles) {
  12086. if (styles.hasOwnProperty(prop)) {
  12087. div.style[prop] = styles[prop];
  12088. }
  12089. }
  12090. };
  12091. StyleBox.prototype.formatStyle = function(val, unit) {
  12092. return val === 0 ? 0 : val + unit;
  12093. };
  12094. // Constructs the computed display state of the cue (a div). Places the div
  12095. // into the overlay which should be a block level element (usually a div).
  12096. function CueStyleBox(window, cue, styleOptions) {
  12097. var isIE8 = (/MSIE\s8\.0/).test(navigator.userAgent);
  12098. var color = "rgba(255, 255, 255, 1)";
  12099. var backgroundColor = "rgba(0, 0, 0, 0.8)";
  12100. if (isIE8) {
  12101. color = "rgb(255, 255, 255)";
  12102. backgroundColor = "rgb(0, 0, 0)";
  12103. }
  12104. StyleBox.call(this);
  12105. this.cue = cue;
  12106. // Parse our cue's text into a DOM tree rooted at 'cueDiv'. This div will
  12107. // have inline positioning and will function as the cue background box.
  12108. this.cueDiv = parseContent(window, cue.text);
  12109. var styles = {
  12110. color: color,
  12111. backgroundColor: backgroundColor,
  12112. position: "relative",
  12113. left: 0,
  12114. right: 0,
  12115. top: 0,
  12116. bottom: 0,
  12117. display: "inline"
  12118. };
  12119. if (!isIE8) {
  12120. styles.writingMode = cue.vertical === "" ? "horizontal-tb"
  12121. : cue.vertical === "lr" ? "vertical-lr"
  12122. : "vertical-rl";
  12123. styles.unicodeBidi = "plaintext";
  12124. }
  12125. this.applyStyles(styles, this.cueDiv);
  12126. // Create an absolutely positioned div that will be used to position the cue
  12127. // div. Note, all WebVTT cue-setting alignments are equivalent to the CSS
  12128. // mirrors of them except "middle" which is "center" in CSS.
  12129. this.div = window.document.createElement("div");
  12130. styles = {
  12131. textAlign: cue.align === "middle" ? "center" : cue.align,
  12132. font: styleOptions.font,
  12133. whiteSpace: "pre-line",
  12134. position: "absolute"
  12135. };
  12136. if (!isIE8) {
  12137. styles.direction = determineBidi(this.cueDiv);
  12138. styles.writingMode = cue.vertical === "" ? "horizontal-tb"
  12139. : cue.vertical === "lr" ? "vertical-lr"
  12140. : "vertical-rl".
  12141. stylesunicodeBidi = "plaintext";
  12142. }
  12143. this.applyStyles(styles);
  12144. this.div.appendChild(this.cueDiv);
  12145. // Calculate the distance from the reference edge of the viewport to the text
  12146. // position of the cue box. The reference edge will be resolved later when
  12147. // the box orientation styles are applied.
  12148. var textPos = 0;
  12149. switch (cue.positionAlign) {
  12150. case "start":
  12151. textPos = cue.position;
  12152. break;
  12153. case "middle":
  12154. textPos = cue.position - (cue.size / 2);
  12155. break;
  12156. case "end":
  12157. textPos = cue.position - cue.size;
  12158. break;
  12159. }
  12160. // Horizontal box orientation; textPos is the distance from the left edge of the
  12161. // area to the left edge of the box and cue.size is the distance extending to
  12162. // the right from there.
  12163. if (cue.vertical === "") {
  12164. this.applyStyles({
  12165. left: this.formatStyle(textPos, "%"),
  12166. width: this.formatStyle(cue.size, "%")
  12167. });
  12168. // Vertical box orientation; textPos is the distance from the top edge of the
  12169. // area to the top edge of the box and cue.size is the height extending
  12170. // downwards from there.
  12171. } else {
  12172. this.applyStyles({
  12173. top: this.formatStyle(textPos, "%"),
  12174. height: this.formatStyle(cue.size, "%")
  12175. });
  12176. }
  12177. this.move = function(box) {
  12178. this.applyStyles({
  12179. top: this.formatStyle(box.top, "px"),
  12180. bottom: this.formatStyle(box.bottom, "px"),
  12181. left: this.formatStyle(box.left, "px"),
  12182. right: this.formatStyle(box.right, "px"),
  12183. height: this.formatStyle(box.height, "px"),
  12184. width: this.formatStyle(box.width, "px")
  12185. });
  12186. };
  12187. }
  12188. CueStyleBox.prototype = _objCreate(StyleBox.prototype);
  12189. CueStyleBox.prototype.constructor = CueStyleBox;
  12190. // Represents the co-ordinates of an Element in a way that we can easily
  12191. // compute things with such as if it overlaps or intersects with another Element.
  12192. // Can initialize it with either a StyleBox or another BoxPosition.
  12193. function BoxPosition(obj) {
  12194. var isIE8 = (/MSIE\s8\.0/).test(navigator.userAgent);
  12195. // Either a BoxPosition was passed in and we need to copy it, or a StyleBox
  12196. // was passed in and we need to copy the results of 'getBoundingClientRect'
  12197. // as the object returned is readonly. All co-ordinate values are in reference
  12198. // to the viewport origin (top left).
  12199. var lh, height, width, top;
  12200. if (obj.div) {
  12201. height = obj.div.offsetHeight;
  12202. width = obj.div.offsetWidth;
  12203. top = obj.div.offsetTop;
  12204. var rects = (rects = obj.div.childNodes) && (rects = rects[0]) &&
  12205. rects.getClientRects && rects.getClientRects();
  12206. obj = obj.div.getBoundingClientRect();
  12207. // In certain cases the outter div will be slightly larger then the sum of
  12208. // the inner div's lines. This could be due to bold text, etc, on some platforms.
  12209. // In this case we should get the average line height and use that. This will
  12210. // result in the desired behaviour.
  12211. lh = rects ? Math.max((rects[0] && rects[0].height) || 0, obj.height / rects.length)
  12212. : 0;
  12213. }
  12214. this.left = obj.left;
  12215. this.right = obj.right;
  12216. this.top = obj.top || top;
  12217. this.height = obj.height || height;
  12218. this.bottom = obj.bottom || (top + (obj.height || height));
  12219. this.width = obj.width || width;
  12220. this.lineHeight = lh !== undefined ? lh : obj.lineHeight;
  12221. if (isIE8 && !this.lineHeight) {
  12222. this.lineHeight = 13;
  12223. }
  12224. }
  12225. // Move the box along a particular axis. Optionally pass in an amount to move
  12226. // the box. If no amount is passed then the default is the line height of the
  12227. // box.
  12228. BoxPosition.prototype.move = function(axis, toMove) {
  12229. toMove = toMove !== undefined ? toMove : this.lineHeight;
  12230. switch (axis) {
  12231. case "+x":
  12232. this.left += toMove;
  12233. this.right += toMove;
  12234. break;
  12235. case "-x":
  12236. this.left -= toMove;
  12237. this.right -= toMove;
  12238. break;
  12239. case "+y":
  12240. this.top += toMove;
  12241. this.bottom += toMove;
  12242. break;
  12243. case "-y":
  12244. this.top -= toMove;
  12245. this.bottom -= toMove;
  12246. break;
  12247. }
  12248. };
  12249. // Check if this box overlaps another box, b2.
  12250. BoxPosition.prototype.overlaps = function(b2) {
  12251. return this.left < b2.right &&
  12252. this.right > b2.left &&
  12253. this.top < b2.bottom &&
  12254. this.bottom > b2.top;
  12255. };
  12256. // Check if this box overlaps any other boxes in boxes.
  12257. BoxPosition.prototype.overlapsAny = function(boxes) {
  12258. for (var i = 0; i < boxes.length; i++) {
  12259. if (this.overlaps(boxes[i])) {
  12260. return true;
  12261. }
  12262. }
  12263. return false;
  12264. };
  12265. // Check if this box is within another box.
  12266. BoxPosition.prototype.within = function(container) {
  12267. return this.top >= container.top &&
  12268. this.bottom <= container.bottom &&
  12269. this.left >= container.left &&
  12270. this.right <= container.right;
  12271. };
  12272. // Check if this box is entirely within the container or it is overlapping
  12273. // on the edge opposite of the axis direction passed. For example, if "+x" is
  12274. // passed and the box is overlapping on the left edge of the container, then
  12275. // return true.
  12276. BoxPosition.prototype.overlapsOppositeAxis = function(container, axis) {
  12277. switch (axis) {
  12278. case "+x":
  12279. return this.left < container.left;
  12280. case "-x":
  12281. return this.right > container.right;
  12282. case "+y":
  12283. return this.top < container.top;
  12284. case "-y":
  12285. return this.bottom > container.bottom;
  12286. }
  12287. };
  12288. // Find the percentage of the area that this box is overlapping with another
  12289. // box.
  12290. BoxPosition.prototype.intersectPercentage = function(b2) {
  12291. var x = Math.max(0, Math.min(this.right, b2.right) - Math.max(this.left, b2.left)),
  12292. y = Math.max(0, Math.min(this.bottom, b2.bottom) - Math.max(this.top, b2.top)),
  12293. intersectArea = x * y;
  12294. return intersectArea / (this.height * this.width);
  12295. };
  12296. // Convert the positions from this box to CSS compatible positions using
  12297. // the reference container's positions. This has to be done because this
  12298. // box's positions are in reference to the viewport origin, whereas, CSS
  12299. // values are in referecne to their respective edges.
  12300. BoxPosition.prototype.toCSSCompatValues = function(reference) {
  12301. return {
  12302. top: this.top - reference.top,
  12303. bottom: reference.bottom - this.bottom,
  12304. left: this.left - reference.left,
  12305. right: reference.right - this.right,
  12306. height: this.height,
  12307. width: this.width
  12308. };
  12309. };
  12310. // Get an object that represents the box's position without anything extra.
  12311. // Can pass a StyleBox, HTMLElement, or another BoxPositon.
  12312. BoxPosition.getSimpleBoxPosition = function(obj) {
  12313. var height = obj.div ? obj.div.offsetHeight : obj.tagName ? obj.offsetHeight : 0;
  12314. var width = obj.div ? obj.div.offsetWidth : obj.tagName ? obj.offsetWidth : 0;
  12315. var top = obj.div ? obj.div.offsetTop : obj.tagName ? obj.offsetTop : 0;
  12316. obj = obj.div ? obj.div.getBoundingClientRect() :
  12317. obj.tagName ? obj.getBoundingClientRect() : obj;
  12318. var ret = {
  12319. left: obj.left,
  12320. right: obj.right,
  12321. top: obj.top || top,
  12322. height: obj.height || height,
  12323. bottom: obj.bottom || (top + (obj.height || height)),
  12324. width: obj.width || width
  12325. };
  12326. return ret;
  12327. };
  12328. // Move a StyleBox to its specified, or next best, position. The containerBox
  12329. // is the box that contains the StyleBox, such as a div. boxPositions are
  12330. // a list of other boxes that the styleBox can't overlap with.
  12331. function moveBoxToLinePosition(window, styleBox, containerBox, boxPositions) {
  12332. // Find the best position for a cue box, b, on the video. The axis parameter
  12333. // is a list of axis, the order of which, it will move the box along. For example:
  12334. // Passing ["+x", "-x"] will move the box first along the x axis in the positive
  12335. // direction. If it doesn't find a good position for it there it will then move
  12336. // it along the x axis in the negative direction.
  12337. function findBestPosition(b, axis) {
  12338. var bestPosition,
  12339. specifiedPosition = new BoxPosition(b),
  12340. percentage = 1; // Highest possible so the first thing we get is better.
  12341. for (var i = 0; i < axis.length; i++) {
  12342. while (b.overlapsOppositeAxis(containerBox, axis[i]) ||
  12343. (b.within(containerBox) && b.overlapsAny(boxPositions))) {
  12344. b.move(axis[i]);
  12345. }
  12346. // We found a spot where we aren't overlapping anything. This is our
  12347. // best position.
  12348. if (b.within(containerBox)) {
  12349. return b;
  12350. }
  12351. var p = b.intersectPercentage(containerBox);
  12352. // If we're outside the container box less then we were on our last try
  12353. // then remember this position as the best position.
  12354. if (percentage > p) {
  12355. bestPosition = new BoxPosition(b);
  12356. percentage = p;
  12357. }
  12358. // Reset the box position to the specified position.
  12359. b = new BoxPosition(specifiedPosition);
  12360. }
  12361. return bestPosition || specifiedPosition;
  12362. }
  12363. var boxPosition = new BoxPosition(styleBox),
  12364. cue = styleBox.cue,
  12365. linePos = computeLinePos(cue),
  12366. axis = [];
  12367. // If we have a line number to align the cue to.
  12368. if (cue.snapToLines) {
  12369. var size;
  12370. switch (cue.vertical) {
  12371. case "":
  12372. axis = [ "+y", "-y" ];
  12373. size = "height";
  12374. break;
  12375. case "rl":
  12376. axis = [ "+x", "-x" ];
  12377. size = "width";
  12378. break;
  12379. case "lr":
  12380. axis = [ "-x", "+x" ];
  12381. size = "width";
  12382. break;
  12383. }
  12384. var step = boxPosition.lineHeight,
  12385. position = step * Math.round(linePos),
  12386. maxPosition = containerBox[size] + step,
  12387. initialAxis = axis[0];
  12388. // If the specified intial position is greater then the max position then
  12389. // clamp the box to the amount of steps it would take for the box to
  12390. // reach the max position.
  12391. if (Math.abs(position) > maxPosition) {
  12392. position = position < 0 ? -1 : 1;
  12393. position *= Math.ceil(maxPosition / step) * step;
  12394. }
  12395. // If computed line position returns negative then line numbers are
  12396. // relative to the bottom of the video instead of the top. Therefore, we
  12397. // need to increase our initial position by the length or width of the
  12398. // video, depending on the writing direction, and reverse our axis directions.
  12399. if (linePos < 0) {
  12400. position += cue.vertical === "" ? containerBox.height : containerBox.width;
  12401. axis = axis.reverse();
  12402. }
  12403. // Move the box to the specified position. This may not be its best
  12404. // position.
  12405. boxPosition.move(initialAxis, position);
  12406. } else {
  12407. // If we have a percentage line value for the cue.
  12408. var calculatedPercentage = (boxPosition.lineHeight / containerBox.height) * 100;
  12409. switch (cue.lineAlign) {
  12410. case "middle":
  12411. linePos -= (calculatedPercentage / 2);
  12412. break;
  12413. case "end":
  12414. linePos -= calculatedPercentage;
  12415. break;
  12416. }
  12417. // Apply initial line position to the cue box.
  12418. switch (cue.vertical) {
  12419. case "":
  12420. styleBox.applyStyles({
  12421. top: styleBox.formatStyle(linePos, "%")
  12422. });
  12423. break;
  12424. case "rl":
  12425. styleBox.applyStyles({
  12426. left: styleBox.formatStyle(linePos, "%")
  12427. });
  12428. break;
  12429. case "lr":
  12430. styleBox.applyStyles({
  12431. right: styleBox.formatStyle(linePos, "%")
  12432. });
  12433. break;
  12434. }
  12435. axis = [ "+y", "-x", "+x", "-y" ];
  12436. // Get the box position again after we've applied the specified positioning
  12437. // to it.
  12438. boxPosition = new BoxPosition(styleBox);
  12439. }
  12440. var bestPosition = findBestPosition(boxPosition, axis);
  12441. styleBox.move(bestPosition.toCSSCompatValues(containerBox));
  12442. }
  12443. function WebVTT() {
  12444. // Nothing
  12445. }
  12446. // Helper to allow strings to be decoded instead of the default binary utf8 data.
  12447. WebVTT.StringDecoder = function() {
  12448. return {
  12449. decode: function(data) {
  12450. if (!data) {
  12451. return "";
  12452. }
  12453. if (typeof data !== "string") {
  12454. throw new Error("Error - expected string data.");
  12455. }
  12456. return decodeURIComponent(encodeURIComponent(data));
  12457. }
  12458. };
  12459. };
  12460. WebVTT.convertCueToDOMTree = function(window, cuetext) {
  12461. if (!window || !cuetext) {
  12462. return null;
  12463. }
  12464. return parseContent(window, cuetext);
  12465. };
  12466. var FONT_SIZE_PERCENT = 0.05;
  12467. var FONT_STYLE = "sans-serif";
  12468. var CUE_BACKGROUND_PADDING = "1.5%";
  12469. // Runs the processing model over the cues and regions passed to it.
  12470. // @param overlay A block level element (usually a div) that the computed cues
  12471. // and regions will be placed into.
  12472. WebVTT.processCues = function(window, cues, overlay) {
  12473. if (!window || !cues || !overlay) {
  12474. return null;
  12475. }
  12476. // Remove all previous children.
  12477. while (overlay.firstChild) {
  12478. overlay.removeChild(overlay.firstChild);
  12479. }
  12480. var paddedOverlay = window.document.createElement("div");
  12481. paddedOverlay.style.position = "absolute";
  12482. paddedOverlay.style.left = "0";
  12483. paddedOverlay.style.right = "0";
  12484. paddedOverlay.style.top = "0";
  12485. paddedOverlay.style.bottom = "0";
  12486. paddedOverlay.style.margin = CUE_BACKGROUND_PADDING;
  12487. overlay.appendChild(paddedOverlay);
  12488. // Determine if we need to compute the display states of the cues. This could
  12489. // be the case if a cue's state has been changed since the last computation or
  12490. // if it has not been computed yet.
  12491. function shouldCompute(cues) {
  12492. for (var i = 0; i < cues.length; i++) {
  12493. if (cues[i].hasBeenReset || !cues[i].displayState) {
  12494. return true;
  12495. }
  12496. }
  12497. return false;
  12498. }
  12499. // We don't need to recompute the cues' display states. Just reuse them.
  12500. if (!shouldCompute(cues)) {
  12501. for (var i = 0; i < cues.length; i++) {
  12502. paddedOverlay.appendChild(cues[i].displayState);
  12503. }
  12504. return;
  12505. }
  12506. var boxPositions = [],
  12507. containerBox = BoxPosition.getSimpleBoxPosition(paddedOverlay),
  12508. fontSize = Math.round(containerBox.height * FONT_SIZE_PERCENT * 100) / 100;
  12509. var styleOptions = {
  12510. font: fontSize + "px " + FONT_STYLE
  12511. };
  12512. (function() {
  12513. var styleBox, cue;
  12514. for (var i = 0; i < cues.length; i++) {
  12515. cue = cues[i];
  12516. // Compute the intial position and styles of the cue div.
  12517. styleBox = new CueStyleBox(window, cue, styleOptions);
  12518. paddedOverlay.appendChild(styleBox.div);
  12519. // Move the cue div to it's correct line position.
  12520. moveBoxToLinePosition(window, styleBox, containerBox, boxPositions);
  12521. // Remember the computed div so that we don't have to recompute it later
  12522. // if we don't have too.
  12523. cue.displayState = styleBox.div;
  12524. boxPositions.push(BoxPosition.getSimpleBoxPosition(styleBox));
  12525. }
  12526. })();
  12527. };
  12528. WebVTT.Parser = function(window, vttjs, decoder) {
  12529. if (!decoder) {
  12530. decoder = vttjs;
  12531. vttjs = {};
  12532. }
  12533. if (!vttjs) {
  12534. vttjs = {};
  12535. }
  12536. this.window = window;
  12537. this.vttjs = vttjs;
  12538. this.state = "INITIAL";
  12539. this.buffer = "";
  12540. this.decoder = decoder || new TextDecoder("utf8");
  12541. this.regionList = [];
  12542. };
  12543. WebVTT.Parser.prototype = {
  12544. // If the error is a ParsingError then report it to the consumer if
  12545. // possible. If it's not a ParsingError then throw it like normal.
  12546. reportOrThrowError: function(e) {
  12547. if (e instanceof ParsingError) {
  12548. this.onparsingerror && this.onparsingerror(e);
  12549. } else {
  12550. throw e;
  12551. }
  12552. },
  12553. parse: function (data) {
  12554. var self = this;
  12555. // If there is no data then we won't decode it, but will just try to parse
  12556. // whatever is in buffer already. This may occur in circumstances, for
  12557. // example when flush() is called.
  12558. if (data) {
  12559. // Try to decode the data that we received.
  12560. self.buffer += self.decoder.decode(data, {stream: true});
  12561. }
  12562. function collectNextLine() {
  12563. var buffer = self.buffer;
  12564. var pos = 0;
  12565. while (pos < buffer.length && buffer[pos] !== '\r' && buffer[pos] !== '\n') {
  12566. ++pos;
  12567. }
  12568. var line = buffer.substr(0, pos);
  12569. // Advance the buffer early in case we fail below.
  12570. if (buffer[pos] === '\r') {
  12571. ++pos;
  12572. }
  12573. if (buffer[pos] === '\n') {
  12574. ++pos;
  12575. }
  12576. self.buffer = buffer.substr(pos);
  12577. return line;
  12578. }
  12579. // 3.4 WebVTT region and WebVTT region settings syntax
  12580. function parseRegion(input) {
  12581. var settings = new Settings();
  12582. parseOptions(input, function (k, v) {
  12583. switch (k) {
  12584. case "id":
  12585. settings.set(k, v);
  12586. break;
  12587. case "width":
  12588. settings.percent(k, v);
  12589. break;
  12590. case "lines":
  12591. settings.integer(k, v);
  12592. break;
  12593. case "regionanchor":
  12594. case "viewportanchor":
  12595. var xy = v.split(',');
  12596. if (xy.length !== 2) {
  12597. break;
  12598. }
  12599. // We have to make sure both x and y parse, so use a temporary
  12600. // settings object here.
  12601. var anchor = new Settings();
  12602. anchor.percent("x", xy[0]);
  12603. anchor.percent("y", xy[1]);
  12604. if (!anchor.has("x") || !anchor.has("y")) {
  12605. break;
  12606. }
  12607. settings.set(k + "X", anchor.get("x"));
  12608. settings.set(k + "Y", anchor.get("y"));
  12609. break;
  12610. case "scroll":
  12611. settings.alt(k, v, ["up"]);
  12612. break;
  12613. }
  12614. }, /=/, /\s/);
  12615. // Create the region, using default values for any values that were not
  12616. // specified.
  12617. if (settings.has("id")) {
  12618. var region = new (self.vttjs.VTTRegion || self.window.VTTRegion)();
  12619. region.width = settings.get("width", 100);
  12620. region.lines = settings.get("lines", 3);
  12621. region.regionAnchorX = settings.get("regionanchorX", 0);
  12622. region.regionAnchorY = settings.get("regionanchorY", 100);
  12623. region.viewportAnchorX = settings.get("viewportanchorX", 0);
  12624. region.viewportAnchorY = settings.get("viewportanchorY", 100);
  12625. region.scroll = settings.get("scroll", "");
  12626. // Register the region.
  12627. self.onregion && self.onregion(region);
  12628. // Remember the VTTRegion for later in case we parse any VTTCues that
  12629. // reference it.
  12630. self.regionList.push({
  12631. id: settings.get("id"),
  12632. region: region
  12633. });
  12634. }
  12635. }
  12636. // draft-pantos-http-live-streaming-20
  12637. // https://tools.ietf.org/html/draft-pantos-http-live-streaming-20#section-3.5
  12638. // 3.5 WebVTT
  12639. function parseTimestampMap(input) {
  12640. var settings = new Settings();
  12641. parseOptions(input, function(k, v) {
  12642. switch(k) {
  12643. case "MPEGT":
  12644. settings.integer(k + 'S', v);
  12645. break;
  12646. case "LOCA":
  12647. settings.set(k + 'L', parseTimeStamp(v));
  12648. break;
  12649. }
  12650. }, /[^\d]:/, /,/);
  12651. self.ontimestampmap && self.ontimestampmap({
  12652. "MPEGTS": settings.get("MPEGTS"),
  12653. "LOCAL": settings.get("LOCAL")
  12654. });
  12655. }
  12656. // 3.2 WebVTT metadata header syntax
  12657. function parseHeader(input) {
  12658. if (input.match(/X-TIMESTAMP-MAP/)) {
  12659. // This line contains HLS X-TIMESTAMP-MAP metadata
  12660. parseOptions(input, function(k, v) {
  12661. switch(k) {
  12662. case "X-TIMESTAMP-MAP":
  12663. parseTimestampMap(v);
  12664. break;
  12665. }
  12666. }, /=/);
  12667. } else {
  12668. parseOptions(input, function (k, v) {
  12669. switch (k) {
  12670. case "Region":
  12671. // 3.3 WebVTT region metadata header syntax
  12672. parseRegion(v);
  12673. break;
  12674. }
  12675. }, /:/);
  12676. }
  12677. }
  12678. // 5.1 WebVTT file parsing.
  12679. try {
  12680. var line;
  12681. if (self.state === "INITIAL") {
  12682. // We can't start parsing until we have the first line.
  12683. if (!/\r\n|\n/.test(self.buffer)) {
  12684. return this;
  12685. }
  12686. line = collectNextLine();
  12687. var m = line.match(/^WEBVTT([ \t].*)?$/);
  12688. if (!m || !m[0]) {
  12689. throw new ParsingError(ParsingError.Errors.BadSignature);
  12690. }
  12691. self.state = "HEADER";
  12692. }
  12693. var alreadyCollectedLine = false;
  12694. while (self.buffer) {
  12695. // We can't parse a line until we have the full line.
  12696. if (!/\r\n|\n/.test(self.buffer)) {
  12697. return this;
  12698. }
  12699. if (!alreadyCollectedLine) {
  12700. line = collectNextLine();
  12701. } else {
  12702. alreadyCollectedLine = false;
  12703. }
  12704. switch (self.state) {
  12705. case "HEADER":
  12706. // 13-18 - Allow a header (metadata) under the WEBVTT line.
  12707. if (/:/.test(line)) {
  12708. parseHeader(line);
  12709. } else if (!line) {
  12710. // An empty line terminates the header and starts the body (cues).
  12711. self.state = "ID";
  12712. }
  12713. continue;
  12714. case "NOTE":
  12715. // Ignore NOTE blocks.
  12716. if (!line) {
  12717. self.state = "ID";
  12718. }
  12719. continue;
  12720. case "ID":
  12721. // Check for the start of NOTE blocks.
  12722. if (/^NOTE($|[ \t])/.test(line)) {
  12723. self.state = "NOTE";
  12724. break;
  12725. }
  12726. // 19-29 - Allow any number of line terminators, then initialize new cue values.
  12727. if (!line) {
  12728. continue;
  12729. }
  12730. self.cue = new (self.vttjs.VTTCue || self.window.VTTCue)(0, 0, "");
  12731. self.state = "CUE";
  12732. // 30-39 - Check if self line contains an optional identifier or timing data.
  12733. if (line.indexOf("-->") === -1) {
  12734. self.cue.id = line;
  12735. continue;
  12736. }
  12737. // Process line as start of a cue.
  12738. /*falls through*/
  12739. case "CUE":
  12740. // 40 - Collect cue timings and settings.
  12741. try {
  12742. parseCue(line, self.cue, self.regionList);
  12743. } catch (e) {
  12744. self.reportOrThrowError(e);
  12745. // In case of an error ignore rest of the cue.
  12746. self.cue = null;
  12747. self.state = "BADCUE";
  12748. continue;
  12749. }
  12750. self.state = "CUETEXT";
  12751. continue;
  12752. case "CUETEXT":
  12753. var hasSubstring = line.indexOf("-->") !== -1;
  12754. // 34 - If we have an empty line then report the cue.
  12755. // 35 - If we have the special substring '-->' then report the cue,
  12756. // but do not collect the line as we need to process the current
  12757. // one as a new cue.
  12758. if (!line || hasSubstring && (alreadyCollectedLine = true)) {
  12759. // We are done parsing self cue.
  12760. self.oncue && self.oncue(self.cue);
  12761. self.cue = null;
  12762. self.state = "ID";
  12763. continue;
  12764. }
  12765. if (self.cue.text) {
  12766. self.cue.text += "\n";
  12767. }
  12768. self.cue.text += line;
  12769. continue;
  12770. case "BADCUE": // BADCUE
  12771. // 54-62 - Collect and discard the remaining cue.
  12772. if (!line) {
  12773. self.state = "ID";
  12774. }
  12775. continue;
  12776. }
  12777. }
  12778. } catch (e) {
  12779. self.reportOrThrowError(e);
  12780. // If we are currently parsing a cue, report what we have.
  12781. if (self.state === "CUETEXT" && self.cue && self.oncue) {
  12782. self.oncue(self.cue);
  12783. }
  12784. self.cue = null;
  12785. // Enter BADWEBVTT state if header was not parsed correctly otherwise
  12786. // another exception occurred so enter BADCUE state.
  12787. self.state = self.state === "INITIAL" ? "BADWEBVTT" : "BADCUE";
  12788. }
  12789. return this;
  12790. },
  12791. flush: function () {
  12792. var self = this;
  12793. try {
  12794. // Finish decoding the stream.
  12795. self.buffer += self.decoder.decode();
  12796. // Synthesize the end of the current cue or region.
  12797. if (self.cue || self.state === "HEADER") {
  12798. self.buffer += "\n\n";
  12799. self.parse();
  12800. }
  12801. // If we've flushed, parsed, and we're still on the INITIAL state then
  12802. // that means we don't have enough of the stream to parse the first
  12803. // line.
  12804. if (self.state === "INITIAL") {
  12805. throw new ParsingError(ParsingError.Errors.BadSignature);
  12806. }
  12807. } catch(e) {
  12808. self.reportOrThrowError(e);
  12809. }
  12810. self.onflush && self.onflush();
  12811. return this;
  12812. }
  12813. };
  12814. module.exports = WebVTT;
  12815. /***/ }),
  12816. /* 52 */
  12817. /***/ (function(module, exports) {
  12818. /**
  12819. * Copyright 2013 vtt.js Contributors
  12820. *
  12821. * Licensed under the Apache License, Version 2.0 (the "License");
  12822. * you may not use this file except in compliance with the License.
  12823. * You may obtain a copy of the License at
  12824. *
  12825. * http://www.apache.org/licenses/LICENSE-2.0
  12826. *
  12827. * Unless required by applicable law or agreed to in writing, software
  12828. * distributed under the License is distributed on an "AS IS" BASIS,
  12829. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12830. * See the License for the specific language governing permissions and
  12831. * limitations under the License.
  12832. */
  12833. var autoKeyword = "auto";
  12834. var directionSetting = {
  12835. "": true,
  12836. "lr": true,
  12837. "rl": true
  12838. };
  12839. var alignSetting = {
  12840. "start": true,
  12841. "middle": true,
  12842. "end": true,
  12843. "left": true,
  12844. "right": true
  12845. };
  12846. function findDirectionSetting(value) {
  12847. if (typeof value !== "string") {
  12848. return false;
  12849. }
  12850. var dir = directionSetting[value.toLowerCase()];
  12851. return dir ? value.toLowerCase() : false;
  12852. }
  12853. function findAlignSetting(value) {
  12854. if (typeof value !== "string") {
  12855. return false;
  12856. }
  12857. var align = alignSetting[value.toLowerCase()];
  12858. return align ? value.toLowerCase() : false;
  12859. }
  12860. function extend(obj) {
  12861. var i = 1;
  12862. for (; i < arguments.length; i++) {
  12863. var cobj = arguments[i];
  12864. for (var p in cobj) {
  12865. obj[p] = cobj[p];
  12866. }
  12867. }
  12868. return obj;
  12869. }
  12870. function VTTCue(startTime, endTime, text) {
  12871. var cue = this;
  12872. var isIE8 = (/MSIE\s8\.0/).test(navigator.userAgent);
  12873. var baseObj = {};
  12874. if (isIE8) {
  12875. cue = document.createElement('custom');
  12876. } else {
  12877. baseObj.enumerable = true;
  12878. }
  12879. /**
  12880. * Shim implementation specific properties. These properties are not in
  12881. * the spec.
  12882. */
  12883. // Lets us know when the VTTCue's data has changed in such a way that we need
  12884. // to recompute its display state. This lets us compute its display state
  12885. // lazily.
  12886. cue.hasBeenReset = false;
  12887. /**
  12888. * VTTCue and TextTrackCue properties
  12889. * http://dev.w3.org/html5/webvtt/#vttcue-interface
  12890. */
  12891. var _id = "";
  12892. var _pauseOnExit = false;
  12893. var _startTime = startTime;
  12894. var _endTime = endTime;
  12895. var _text = text;
  12896. var _region = null;
  12897. var _vertical = "";
  12898. var _snapToLines = true;
  12899. var _line = "auto";
  12900. var _lineAlign = "start";
  12901. var _position = 50;
  12902. var _positionAlign = "middle";
  12903. var _size = 50;
  12904. var _align = "middle";
  12905. Object.defineProperty(cue,
  12906. "id", extend({}, baseObj, {
  12907. get: function() {
  12908. return _id;
  12909. },
  12910. set: function(value) {
  12911. _id = "" + value;
  12912. }
  12913. }));
  12914. Object.defineProperty(cue,
  12915. "pauseOnExit", extend({}, baseObj, {
  12916. get: function() {
  12917. return _pauseOnExit;
  12918. },
  12919. set: function(value) {
  12920. _pauseOnExit = !!value;
  12921. }
  12922. }));
  12923. Object.defineProperty(cue,
  12924. "startTime", extend({}, baseObj, {
  12925. get: function() {
  12926. return _startTime;
  12927. },
  12928. set: function(value) {
  12929. if (typeof value !== "number") {
  12930. throw new TypeError("Start time must be set to a number.");
  12931. }
  12932. _startTime = value;
  12933. this.hasBeenReset = true;
  12934. }
  12935. }));
  12936. Object.defineProperty(cue,
  12937. "endTime", extend({}, baseObj, {
  12938. get: function() {
  12939. return _endTime;
  12940. },
  12941. set: function(value) {
  12942. if (typeof value !== "number") {
  12943. throw new TypeError("End time must be set to a number.");
  12944. }
  12945. _endTime = value;
  12946. this.hasBeenReset = true;
  12947. }
  12948. }));
  12949. Object.defineProperty(cue,
  12950. "text", extend({}, baseObj, {
  12951. get: function() {
  12952. return _text;
  12953. },
  12954. set: function(value) {
  12955. _text = "" + value;
  12956. this.hasBeenReset = true;
  12957. }
  12958. }));
  12959. Object.defineProperty(cue,
  12960. "region", extend({}, baseObj, {
  12961. get: function() {
  12962. return _region;
  12963. },
  12964. set: function(value) {
  12965. _region = value;
  12966. this.hasBeenReset = true;
  12967. }
  12968. }));
  12969. Object.defineProperty(cue,
  12970. "vertical", extend({}, baseObj, {
  12971. get: function() {
  12972. return _vertical;
  12973. },
  12974. set: function(value) {
  12975. var setting = findDirectionSetting(value);
  12976. // Have to check for false because the setting an be an empty string.
  12977. if (setting === false) {
  12978. throw new SyntaxError("An invalid or illegal string was specified.");
  12979. }
  12980. _vertical = setting;
  12981. this.hasBeenReset = true;
  12982. }
  12983. }));
  12984. Object.defineProperty(cue,
  12985. "snapToLines", extend({}, baseObj, {
  12986. get: function() {
  12987. return _snapToLines;
  12988. },
  12989. set: function(value) {
  12990. _snapToLines = !!value;
  12991. this.hasBeenReset = true;
  12992. }
  12993. }));
  12994. Object.defineProperty(cue,
  12995. "line", extend({}, baseObj, {
  12996. get: function() {
  12997. return _line;
  12998. },
  12999. set: function(value) {
  13000. if (typeof value !== "number" && value !== autoKeyword) {
  13001. throw new SyntaxError("An invalid number or illegal string was specified.");
  13002. }
  13003. _line = value;
  13004. this.hasBeenReset = true;
  13005. }
  13006. }));
  13007. Object.defineProperty(cue,
  13008. "lineAlign", extend({}, baseObj, {
  13009. get: function() {
  13010. return _lineAlign;
  13011. },
  13012. set: function(value) {
  13013. var setting = findAlignSetting(value);
  13014. if (!setting) {
  13015. throw new SyntaxError("An invalid or illegal string was specified.");
  13016. }
  13017. _lineAlign = setting;
  13018. this.hasBeenReset = true;
  13019. }
  13020. }));
  13021. Object.defineProperty(cue,
  13022. "position", extend({}, baseObj, {
  13023. get: function() {
  13024. return _position;
  13025. },
  13026. set: function(value) {
  13027. if (value < 0 || value > 100) {
  13028. throw new Error("Position must be between 0 and 100.");
  13029. }
  13030. _position = value;
  13031. this.hasBeenReset = true;
  13032. }
  13033. }));
  13034. Object.defineProperty(cue,
  13035. "positionAlign", extend({}, baseObj, {
  13036. get: function() {
  13037. return _positionAlign;
  13038. },
  13039. set: function(value) {
  13040. var setting = findAlignSetting(value);
  13041. if (!setting) {
  13042. throw new SyntaxError("An invalid or illegal string was specified.");
  13043. }
  13044. _positionAlign = setting;
  13045. this.hasBeenReset = true;
  13046. }
  13047. }));
  13048. Object.defineProperty(cue,
  13049. "size", extend({}, baseObj, {
  13050. get: function() {
  13051. return _size;
  13052. },
  13053. set: function(value) {
  13054. if (value < 0 || value > 100) {
  13055. throw new Error("Size must be between 0 and 100.");
  13056. }
  13057. _size = value;
  13058. this.hasBeenReset = true;
  13059. }
  13060. }));
  13061. Object.defineProperty(cue,
  13062. "align", extend({}, baseObj, {
  13063. get: function() {
  13064. return _align;
  13065. },
  13066. set: function(value) {
  13067. var setting = findAlignSetting(value);
  13068. if (!setting) {
  13069. throw new SyntaxError("An invalid or illegal string was specified.");
  13070. }
  13071. _align = setting;
  13072. this.hasBeenReset = true;
  13073. }
  13074. }));
  13075. /**
  13076. * Other <track> spec defined properties
  13077. */
  13078. // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#text-track-cue-display-state
  13079. cue.displayState = undefined;
  13080. if (isIE8) {
  13081. return cue;
  13082. }
  13083. }
  13084. /**
  13085. * VTTCue methods
  13086. */
  13087. VTTCue.prototype.getCueAsHTML = function() {
  13088. // Assume WebVTT.convertCueToDOMTree is on the global.
  13089. return WebVTT.convertCueToDOMTree(window, this.text);
  13090. };
  13091. module.exports = VTTCue;
  13092. /***/ }),
  13093. /* 53 */
  13094. /***/ (function(module, exports) {
  13095. /**
  13096. * Copyright 2013 vtt.js Contributors
  13097. *
  13098. * Licensed under the Apache License, Version 2.0 (the "License");
  13099. * you may not use this file except in compliance with the License.
  13100. * You may obtain a copy of the License at
  13101. *
  13102. * http://www.apache.org/licenses/LICENSE-2.0
  13103. *
  13104. * Unless required by applicable law or agreed to in writing, software
  13105. * distributed under the License is distributed on an "AS IS" BASIS,
  13106. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13107. * See the License for the specific language governing permissions and
  13108. * limitations under the License.
  13109. */
  13110. var scrollSetting = {
  13111. "": true,
  13112. "up": true
  13113. };
  13114. function findScrollSetting(value) {
  13115. if (typeof value !== "string") {
  13116. return false;
  13117. }
  13118. var scroll = scrollSetting[value.toLowerCase()];
  13119. return scroll ? value.toLowerCase() : false;
  13120. }
  13121. function isValidPercentValue(value) {
  13122. return typeof value === "number" && (value >= 0 && value <= 100);
  13123. }
  13124. // VTTRegion shim http://dev.w3.org/html5/webvtt/#vttregion-interface
  13125. function VTTRegion() {
  13126. var _width = 100;
  13127. var _lines = 3;
  13128. var _regionAnchorX = 0;
  13129. var _regionAnchorY = 100;
  13130. var _viewportAnchorX = 0;
  13131. var _viewportAnchorY = 100;
  13132. var _scroll = "";
  13133. Object.defineProperties(this, {
  13134. "width": {
  13135. enumerable: true,
  13136. get: function() {
  13137. return _width;
  13138. },
  13139. set: function(value) {
  13140. if (!isValidPercentValue(value)) {
  13141. throw new Error("Width must be between 0 and 100.");
  13142. }
  13143. _width = value;
  13144. }
  13145. },
  13146. "lines": {
  13147. enumerable: true,
  13148. get: function() {
  13149. return _lines;
  13150. },
  13151. set: function(value) {
  13152. if (typeof value !== "number") {
  13153. throw new TypeError("Lines must be set to a number.");
  13154. }
  13155. _lines = value;
  13156. }
  13157. },
  13158. "regionAnchorY": {
  13159. enumerable: true,
  13160. get: function() {
  13161. return _regionAnchorY;
  13162. },
  13163. set: function(value) {
  13164. if (!isValidPercentValue(value)) {
  13165. throw new Error("RegionAnchorX must be between 0 and 100.");
  13166. }
  13167. _regionAnchorY = value;
  13168. }
  13169. },
  13170. "regionAnchorX": {
  13171. enumerable: true,
  13172. get: function() {
  13173. return _regionAnchorX;
  13174. },
  13175. set: function(value) {
  13176. if(!isValidPercentValue(value)) {
  13177. throw new Error("RegionAnchorY must be between 0 and 100.");
  13178. }
  13179. _regionAnchorX = value;
  13180. }
  13181. },
  13182. "viewportAnchorY": {
  13183. enumerable: true,
  13184. get: function() {
  13185. return _viewportAnchorY;
  13186. },
  13187. set: function(value) {
  13188. if (!isValidPercentValue(value)) {
  13189. throw new Error("ViewportAnchorY must be between 0 and 100.");
  13190. }
  13191. _viewportAnchorY = value;
  13192. }
  13193. },
  13194. "viewportAnchorX": {
  13195. enumerable: true,
  13196. get: function() {
  13197. return _viewportAnchorX;
  13198. },
  13199. set: function(value) {
  13200. if (!isValidPercentValue(value)) {
  13201. throw new Error("ViewportAnchorX must be between 0 and 100.");
  13202. }
  13203. _viewportAnchorX = value;
  13204. }
  13205. },
  13206. "scroll": {
  13207. enumerable: true,
  13208. get: function() {
  13209. return _scroll;
  13210. },
  13211. set: function(value) {
  13212. var setting = findScrollSetting(value);
  13213. // Have to check for false as an empty string is a legal value.
  13214. if (setting === false) {
  13215. throw new SyntaxError("An invalid or illegal string was specified.");
  13216. }
  13217. _scroll = setting;
  13218. }
  13219. }
  13220. });
  13221. }
  13222. module.exports = VTTRegion;
  13223. /***/ }),
  13224. /* 54 */
  13225. /***/ (function(module, exports, __webpack_require__) {
  13226. 'use strict';
  13227. exports.__esModule = true;
  13228. var _component = __webpack_require__(19);
  13229. var _component2 = _interopRequireDefault(_component);
  13230. var _tech = __webpack_require__(32);
  13231. var _tech2 = _interopRequireDefault(_tech);
  13232. var _toTitleCase = __webpack_require__(21);
  13233. var _toTitleCase2 = _interopRequireDefault(_toTitleCase);
  13234. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  13235. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  13236. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  13237. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  13238. * @file loader.js
  13239. */
  13240. /**
  13241. * The `MediaLoader` is the `Component` that decides which playback technology to load
  13242. * when a player is initialized.
  13243. *
  13244. * @extends Component
  13245. */
  13246. var MediaLoader = function (_Component) {
  13247. _inherits(MediaLoader, _Component);
  13248. /**
  13249. * Create an instance of this class.
  13250. *
  13251. * @param {Player} player
  13252. * The `Player` that this class should attach to.
  13253. *
  13254. * @param {Object} [options]
  13255. * The key/value stroe of player options.
  13256. *
  13257. * @param {Component~ReadyCallback} [ready]
  13258. * The function that is run when this component is ready.
  13259. */
  13260. function MediaLoader(player, options, ready) {
  13261. _classCallCheck(this, MediaLoader);
  13262. // If there are no sources when the player is initialized,
  13263. // load the first supported playback technology.
  13264. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options, ready));
  13265. if (!options.playerOptions.sources || options.playerOptions.sources.length === 0) {
  13266. for (var i = 0, j = options.playerOptions.techOrder; i < j.length; i++) {
  13267. var techName = (0, _toTitleCase2['default'])(j[i]);
  13268. var tech = _tech2['default'].getTech(techName);
  13269. // Support old behavior of techs being registered as components.
  13270. // Remove once that deprecated behavior is removed.
  13271. if (!techName) {
  13272. tech = _component2['default'].getComponent(techName);
  13273. }
  13274. // Check if the browser supports this technology
  13275. if (tech && tech.isSupported()) {
  13276. player.loadTech_(techName);
  13277. break;
  13278. }
  13279. }
  13280. } else {
  13281. // Loop through playback technologies (HTML5, Flash) and check for support.
  13282. // Then load the best source.
  13283. // A few assumptions here:
  13284. // All playback technologies respect preload false.
  13285. player.src(options.playerOptions.sources);
  13286. }
  13287. return _this;
  13288. }
  13289. return MediaLoader;
  13290. }(_component2['default']);
  13291. _component2['default'].registerComponent('MediaLoader', MediaLoader);
  13292. exports['default'] = MediaLoader;
  13293. /***/ }),
  13294. /* 55 */
  13295. /***/ (function(module, exports, __webpack_require__) {
  13296. 'use strict';
  13297. exports.__esModule = true;
  13298. var _tech = __webpack_require__(32);
  13299. var _tech2 = _interopRequireDefault(_tech);
  13300. var _dom = __webpack_require__(11);
  13301. var Dom = _interopRequireWildcard(_dom);
  13302. var _url = __webpack_require__(38);
  13303. var Url = _interopRequireWildcard(_url);
  13304. var _timeRanges = __webpack_require__(25);
  13305. var _flashRtmp = __webpack_require__(56);
  13306. var _flashRtmp2 = _interopRequireDefault(_flashRtmp);
  13307. var _component = __webpack_require__(19);
  13308. var _component2 = _interopRequireDefault(_component);
  13309. var _window = __webpack_require__(7);
  13310. var _window2 = _interopRequireDefault(_window);
  13311. var _obj = __webpack_require__(14);
  13312. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  13313. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  13314. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  13315. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  13316. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  13317. * @file flash.js
  13318. * VideoJS-SWF - Custom Flash Player with HTML5-ish API
  13319. * https://github.com/zencoder/video-js-swf
  13320. * Not using setupTriggers. Using global onEvent func to distribute events
  13321. */
  13322. var navigator = _window2['default'].navigator;
  13323. /**
  13324. * Flash Media Controller - Wrapper for Flash Media API
  13325. *
  13326. * @mixes FlashRtmpDecorator
  13327. * @mixes Tech~SouceHandlerAdditions
  13328. * @extends Tech
  13329. */
  13330. var Flash = function (_Tech) {
  13331. _inherits(Flash, _Tech);
  13332. /**
  13333. * Create an instance of this Tech.
  13334. *
  13335. * @param {Object} [options]
  13336. * The key/value store of player options.
  13337. *
  13338. * @param {Component~ReadyCallback} ready
  13339. * Callback function to call when the `Flash` Tech is ready.
  13340. */
  13341. function Flash(options, ready) {
  13342. _classCallCheck(this, Flash);
  13343. // Set the source when ready
  13344. var _this = _possibleConstructorReturn(this, _Tech.call(this, options, ready));
  13345. if (options.source) {
  13346. _this.ready(function () {
  13347. this.setSource(options.source);
  13348. }, true);
  13349. }
  13350. // Having issues with Flash reloading on certain page actions (hide/resize/fullscreen) in certain browsers
  13351. // This allows resetting the playhead when we catch the reload
  13352. if (options.startTime) {
  13353. _this.ready(function () {
  13354. this.load();
  13355. this.play();
  13356. this.currentTime(options.startTime);
  13357. }, true);
  13358. }
  13359. // Add global window functions that the swf expects
  13360. // A 4.x workflow we weren't able to solve for in 5.0
  13361. // because of the need to hard code these functions
  13362. // into the swf for security reasons
  13363. _window2['default'].videojs = _window2['default'].videojs || {};
  13364. _window2['default'].videojs.Flash = _window2['default'].videojs.Flash || {};
  13365. _window2['default'].videojs.Flash.onReady = Flash.onReady;
  13366. _window2['default'].videojs.Flash.onEvent = Flash.onEvent;
  13367. _window2['default'].videojs.Flash.onError = Flash.onError;
  13368. _this.on('seeked', function () {
  13369. this.lastSeekTarget_ = undefined;
  13370. });
  13371. return _this;
  13372. }
  13373. /**
  13374. * Create the `Flash` Tech's DOM element.
  13375. *
  13376. * @return {Element}
  13377. * The element that gets created.
  13378. */
  13379. Flash.prototype.createEl = function createEl() {
  13380. var options = this.options_;
  13381. // If video.js is hosted locally you should also set the location
  13382. // for the hosted swf, which should be relative to the page (not video.js)
  13383. // Otherwise this adds a CDN url.
  13384. // The CDN also auto-adds a swf URL for that specific version.
  13385. if (!options.swf) {
  13386. var ver = '5.4.1';
  13387. options.swf = '//vjs.zencdn.net/swf/' + ver + '/video-js.swf';
  13388. }
  13389. // Generate ID for swf object
  13390. var objId = options.techId;
  13391. // Merge default flashvars with ones passed in to init
  13392. var flashVars = (0, _obj.assign)({
  13393. // SWF Callback Functions
  13394. readyFunction: 'videojs.Flash.onReady',
  13395. eventProxyFunction: 'videojs.Flash.onEvent',
  13396. errorEventProxyFunction: 'videojs.Flash.onError',
  13397. // Player Settings
  13398. autoplay: options.autoplay,
  13399. preload: options.preload,
  13400. loop: options.loop,
  13401. muted: options.muted
  13402. }, options.flashVars);
  13403. // Merge default parames with ones passed in
  13404. var params = (0, _obj.assign)({
  13405. // Opaque is needed to overlay controls, but can affect playback performance
  13406. wmode: 'opaque',
  13407. // Using bgcolor prevents a white flash when the object is loading
  13408. bgcolor: '#000000'
  13409. }, options.params);
  13410. // Merge default attributes with ones passed in
  13411. var attributes = (0, _obj.assign)({
  13412. // Both ID and Name needed or swf to identify itself
  13413. id: objId,
  13414. name: objId,
  13415. 'class': 'vjs-tech'
  13416. }, options.attributes);
  13417. this.el_ = Flash.embed(options.swf, flashVars, params, attributes);
  13418. this.el_.tech = this;
  13419. return this.el_;
  13420. };
  13421. /**
  13422. * Called by {@link Player#play} to play using the `Flash` `Tech`.
  13423. */
  13424. Flash.prototype.play = function play() {
  13425. if (this.ended()) {
  13426. this.setCurrentTime(0);
  13427. }
  13428. this.el_.vjs_play();
  13429. };
  13430. /**
  13431. * Called by {@link Player#pause} to pause using the `Flash` `Tech`.
  13432. */
  13433. Flash.prototype.pause = function pause() {
  13434. this.el_.vjs_pause();
  13435. };
  13436. /**
  13437. * A getter/setter for the `Flash` Tech's source object.
  13438. * > Note: Please use {@link Flash#setSource}
  13439. *
  13440. * @param {Tech~SourceObject} [src]
  13441. * The source object you want to set on the `Flash` techs.
  13442. *
  13443. * @return {Tech~SourceObject|undefined}
  13444. * - The current source object when a source is not passed in.
  13445. * - undefined when setting
  13446. *
  13447. * @deprecated Since version 5.
  13448. */
  13449. Flash.prototype.src = function src(_src) {
  13450. if (_src === undefined) {
  13451. return this.currentSrc();
  13452. }
  13453. // Setting src through `src` not `setSrc` will be deprecated
  13454. return this.setSrc(_src);
  13455. };
  13456. /**
  13457. * A getter/setter for the `Flash` Tech's source object.
  13458. *
  13459. * @param {Tech~SourceObject} [src]
  13460. * The source object you want to set on the `Flash` techs.
  13461. *
  13462. * @return {Tech~SourceObject|undefined}
  13463. * - The current source object when a source is not passed in.
  13464. * - undefined when setting
  13465. */
  13466. Flash.prototype.setSrc = function setSrc(src) {
  13467. var _this2 = this;
  13468. // Make sure source URL is absolute.
  13469. src = Url.getAbsoluteURL(src);
  13470. this.el_.vjs_src(src);
  13471. // Currently the SWF doesn't autoplay if you load a source later.
  13472. // e.g. Load player w/ no source, wait 2s, set src.
  13473. if (this.autoplay()) {
  13474. this.setTimeout(function () {
  13475. return _this2.play();
  13476. }, 0);
  13477. }
  13478. };
  13479. /**
  13480. * Indicates whether the media is currently seeking to a new position or not.
  13481. *
  13482. * @return {boolean}
  13483. * - True if seeking to a new position
  13484. * - False otherwise
  13485. */
  13486. Flash.prototype.seeking = function seeking() {
  13487. return this.lastSeekTarget_ !== undefined;
  13488. };
  13489. /**
  13490. * Returns the current time in seconds that the media is at in playback.
  13491. *
  13492. * @param {number} time
  13493. * Current playtime of the media in seconds.
  13494. */
  13495. Flash.prototype.setCurrentTime = function setCurrentTime(time) {
  13496. var seekable = this.seekable();
  13497. if (seekable.length) {
  13498. // clamp to the current seekable range
  13499. time = time > seekable.start(0) ? time : seekable.start(0);
  13500. time = time < seekable.end(seekable.length - 1) ? time : seekable.end(seekable.length - 1);
  13501. this.lastSeekTarget_ = time;
  13502. this.trigger('seeking');
  13503. this.el_.vjs_setProperty('currentTime', time);
  13504. _Tech.prototype.setCurrentTime.call(this);
  13505. }
  13506. };
  13507. /**
  13508. * Get the current playback time in seconds
  13509. *
  13510. * @return {number}
  13511. * The current time of playback in seconds.
  13512. */
  13513. Flash.prototype.currentTime = function currentTime() {
  13514. // when seeking make the reported time keep up with the requested time
  13515. // by reading the time we're seeking to
  13516. if (this.seeking()) {
  13517. return this.lastSeekTarget_ || 0;
  13518. }
  13519. return this.el_.vjs_getProperty('currentTime');
  13520. };
  13521. /**
  13522. * Get the current source
  13523. *
  13524. * @method currentSrc
  13525. * @return {Tech~SourceObject}
  13526. * The current source
  13527. */
  13528. Flash.prototype.currentSrc = function currentSrc() {
  13529. if (this.currentSource_) {
  13530. return this.currentSource_.src;
  13531. }
  13532. return this.el_.vjs_getProperty('currentSrc');
  13533. };
  13534. /**
  13535. * Get the total duration of the current media.
  13536. *
  13537. * @return {number}
  13538. 8 The total duration of the current media.
  13539. */
  13540. Flash.prototype.duration = function duration() {
  13541. if (this.readyState() === 0) {
  13542. return NaN;
  13543. }
  13544. var duration = this.el_.vjs_getProperty('duration');
  13545. return duration >= 0 ? duration : Infinity;
  13546. };
  13547. /**
  13548. * Load media into Tech.
  13549. */
  13550. Flash.prototype.load = function load() {
  13551. this.el_.vjs_load();
  13552. };
  13553. /**
  13554. * Get the poster image that was set on the tech.
  13555. */
  13556. Flash.prototype.poster = function poster() {
  13557. this.el_.vjs_getProperty('poster');
  13558. };
  13559. /**
  13560. * Poster images are not handled by the Flash tech so make this is a no-op.
  13561. */
  13562. Flash.prototype.setPoster = function setPoster() {};
  13563. /**
  13564. * Determine the time ranges that can be seeked to in the media.
  13565. *
  13566. * @return {TimeRange}
  13567. * Returns the time ranges that can be seeked to.
  13568. */
  13569. Flash.prototype.seekable = function seekable() {
  13570. var duration = this.duration();
  13571. if (duration === 0) {
  13572. return (0, _timeRanges.createTimeRange)();
  13573. }
  13574. return (0, _timeRanges.createTimeRange)(0, duration);
  13575. };
  13576. /**
  13577. * Get and create a `TimeRange` object for buffering.
  13578. *
  13579. * @return {TimeRange}
  13580. * The time range object that was created.
  13581. */
  13582. Flash.prototype.buffered = function buffered() {
  13583. var ranges = this.el_.vjs_getProperty('buffered');
  13584. if (ranges.length === 0) {
  13585. return (0, _timeRanges.createTimeRange)();
  13586. }
  13587. return (0, _timeRanges.createTimeRange)(ranges[0][0], ranges[0][1]);
  13588. };
  13589. /**
  13590. * Get fullscreen support -
  13591. *
  13592. * Flash does not allow fullscreen through javascript
  13593. * so this always returns false.
  13594. *
  13595. * @return {boolean}
  13596. * The Flash tech does not support fullscreen, so it will always return false.
  13597. */
  13598. Flash.prototype.supportsFullScreen = function supportsFullScreen() {
  13599. // Flash does not allow fullscreen through javascript
  13600. return false;
  13601. };
  13602. /**
  13603. * Flash does not allow fullscreen through javascript
  13604. * so this always returns false.
  13605. *
  13606. * @return {boolean}
  13607. * The Flash tech does not support fullscreen, so it will always return false.
  13608. */
  13609. Flash.prototype.enterFullScreen = function enterFullScreen() {
  13610. return false;
  13611. };
  13612. /**
  13613. * Gets available media playback quality metrics as specified by the W3C's Media
  13614. * Playback Quality API.
  13615. *
  13616. * @see [Spec]{@link https://wicg.github.io/media-playback-quality}
  13617. *
  13618. * @return {Object}
  13619. * An object with supported media playback quality metrics
  13620. */
  13621. Flash.prototype.getVideoPlaybackQuality = function getVideoPlaybackQuality() {
  13622. var videoPlaybackQuality = this.el_.vjs_getProperty('getVideoPlaybackQuality');
  13623. if (_window2['default'].performance && typeof _window2['default'].performance.now === 'function') {
  13624. videoPlaybackQuality.creationTime = _window2['default'].performance.now();
  13625. } else if (_window2['default'].performance && _window2['default'].performance.timing && typeof _window2['default'].performance.timing.navigationStart === 'number') {
  13626. videoPlaybackQuality.creationTime = _window2['default'].Date.now() - _window2['default'].performance.timing.navigationStart;
  13627. }
  13628. return videoPlaybackQuality;
  13629. };
  13630. return Flash;
  13631. }(_tech2['default']);
  13632. // Create setters and getters for attributes
  13633. var _api = Flash.prototype;
  13634. var _readWrite = 'rtmpConnection,rtmpStream,preload,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted'.split(',');
  13635. var _readOnly = 'networkState,readyState,initialTime,startOffsetTime,paused,ended,videoWidth,videoHeight'.split(',');
  13636. function _createSetter(attr) {
  13637. var attrUpper = attr.charAt(0).toUpperCase() + attr.slice(1);
  13638. _api['set' + attrUpper] = function (val) {
  13639. return this.el_.vjs_setProperty(attr, val);
  13640. };
  13641. }
  13642. function _createGetter(attr) {
  13643. _api[attr] = function () {
  13644. return this.el_.vjs_getProperty(attr);
  13645. };
  13646. }
  13647. // Create getter and setters for all read/write attributes
  13648. for (var i = 0; i < _readWrite.length; i++) {
  13649. _createGetter(_readWrite[i]);
  13650. _createSetter(_readWrite[i]);
  13651. }
  13652. // Create getters for read-only attributes
  13653. for (var _i = 0; _i < _readOnly.length; _i++) {
  13654. _createGetter(_readOnly[_i]);
  13655. }
  13656. /** ------------------------------ Getters ------------------------------ **/
  13657. /**
  13658. * Get the value of `rtmpConnection` from the swf.
  13659. *
  13660. * @method Flash#rtmpConnection
  13661. * @return {string}
  13662. * The current value of `rtmpConnection` on the swf.
  13663. */
  13664. /**
  13665. * Get the value of `rtmpStream` from the swf.
  13666. *
  13667. * @method Flash#rtmpStream
  13668. * @return {string}
  13669. * The current value of `rtmpStream` on the swf.
  13670. */
  13671. /**
  13672. * Get the value of `preload` from the swf. `preload` indicates
  13673. * what should download before the media is interacted with. It can have the following
  13674. * values:
  13675. * - none: nothing should be downloaded
  13676. * - metadata: poster and the first few frames of the media may be downloaded to get
  13677. * media dimensions and other metadata
  13678. * - auto: allow the media and metadata for the media to be downloaded before
  13679. * interaction
  13680. *
  13681. * @method Flash#preload
  13682. * @return {string}
  13683. * The value of `preload` from the swf. Will be 'none', 'metadata',
  13684. * or 'auto'.
  13685. */
  13686. /**
  13687. * Get the value of `defaultPlaybackRate` from the swf.
  13688. *
  13689. * @method Flash#defaultPlaybackRate
  13690. * @return {number}
  13691. * The current value of `defaultPlaybackRate` on the swf.
  13692. */
  13693. /**
  13694. * Get the value of `playbackRate` from the swf. `playbackRate` indicates
  13695. * the rate at which the media is currently playing back. Examples:
  13696. * - if playbackRate is set to 2, media will play twice as fast.
  13697. * - if playbackRate is set to 0.5, media will play half as fast.
  13698. *
  13699. * @method Flash#playbackRate
  13700. * @return {number}
  13701. * The value of `playbackRate` from the swf. A number indicating
  13702. * the current playback speed of the media, where 1 is normal speed.
  13703. */
  13704. /**
  13705. * Get the value of `autoplay` from the swf. `autoplay` indicates
  13706. * that the media should start to play as soon as the page is ready.
  13707. *
  13708. * @method Flash#autoplay
  13709. * @return {boolean}
  13710. * - The value of `autoplay` from the swf.
  13711. * - True indicates that the media ashould start as soon as the page loads.
  13712. * - False indicates that the media should not start as soon as the page loads.
  13713. */
  13714. /**
  13715. * Get the value of `loop` from the swf. `loop` indicates
  13716. * that the media should return to the start of the media and continue playing once
  13717. * it reaches the end.
  13718. *
  13719. * @method Flash#loop
  13720. * @return {boolean}
  13721. * - The value of `loop` from the swf.
  13722. * - True indicates that playback should seek back to start once
  13723. * the end of a media is reached.
  13724. * - False indicates that playback should not loop back to the start when the
  13725. * end of the media is reached.
  13726. */
  13727. /**
  13728. * Get the value of `mediaGroup` from the swf.
  13729. *
  13730. * @method Flash#mediaGroup
  13731. * @return {string}
  13732. * The current value of `mediaGroup` on the swf.
  13733. */
  13734. /**
  13735. * Get the value of `controller` from the swf.
  13736. *
  13737. * @method Flash#controller
  13738. * @return {string}
  13739. * The current value of `controller` on the swf.
  13740. */
  13741. /**
  13742. * Get the value of `controls` from the swf. `controls` indicates
  13743. * whether the native flash controls should be shown or hidden.
  13744. *
  13745. * @method Flash#controls
  13746. * @return {boolean}
  13747. * - The value of `controls` from the swf.
  13748. * - True indicates that native controls should be showing.
  13749. * - False indicates that native controls should be hidden.
  13750. */
  13751. /**
  13752. * Get the value of the `volume` from the swf. `volume` indicates the current
  13753. * audio level as a percentage in decimal form. This means that 1 is 100%, 0.5 is 50%, and
  13754. * so on.
  13755. *
  13756. * @method Flash#volume
  13757. * @return {number}
  13758. * The volume percent as a decimal. Value will be between 0-1.
  13759. */
  13760. /**
  13761. * Get the value of the `muted` from the swf. `muted` indicates the current
  13762. * audio level should be silent.
  13763. *
  13764. * @method Flash#muted
  13765. * @return {boolean}
  13766. * - True if the audio should be set to silent
  13767. * - False otherwise
  13768. */
  13769. /**
  13770. * Get the value of `defaultMuted` from the swf. `defaultMuted` indicates
  13771. * whether the media should start muted or not. Only changes the default state of the
  13772. * media. `muted` and `defaultMuted` can have different values. `muted` indicates the
  13773. * current state.
  13774. *
  13775. * @method Flash#defaultMuted
  13776. * @return {boolean}
  13777. * - The value of `defaultMuted` from the swf.
  13778. * - True indicates that the media should start muted.
  13779. * - False indicates that the media should not start muted.
  13780. */
  13781. /**
  13782. * Get the value of `networkState` from the swf. `networkState` indicates
  13783. * the current network state. It returns an enumeration from the following list:
  13784. * - 0: NETWORK_EMPTY
  13785. * - 1: NEWORK_IDLE
  13786. * - 2: NETWORK_LOADING
  13787. * - 3: NETWORK_NO_SOURCE
  13788. *
  13789. * @method Flash#networkState
  13790. * @return {number}
  13791. * The value of `networkState` from the swf. This will be a number
  13792. * from the list in the description.
  13793. */
  13794. /**
  13795. * Get the value of `readyState` from the swf. `readyState` indicates
  13796. * the current state of the media element. It returns an enumeration from the
  13797. * following list:
  13798. * - 0: HAVE_NOTHING
  13799. * - 1: HAVE_METADATA
  13800. * - 2: HAVE_CURRENT_DATA
  13801. * - 3: HAVE_FUTURE_DATA
  13802. * - 4: HAVE_ENOUGH_DATA
  13803. *
  13804. * @method Flash#readyState
  13805. * @return {number}
  13806. * The value of `readyState` from the swf. This will be a number
  13807. * from the list in the description.
  13808. */
  13809. /**
  13810. * Get the value of `readyState` from the swf. `readyState` indicates
  13811. * the current state of the media element. It returns an enumeration from the
  13812. * following list:
  13813. * - 0: HAVE_NOTHING
  13814. * - 1: HAVE_METADATA
  13815. * - 2: HAVE_CURRENT_DATA
  13816. * - 3: HAVE_FUTURE_DATA
  13817. * - 4: HAVE_ENOUGH_DATA
  13818. *
  13819. * @method Flash#readyState
  13820. * @return {number}
  13821. * The value of `readyState` from the swf. This will be a number
  13822. * from the list in the description.
  13823. */
  13824. /**
  13825. * Get the value of `initialTime` from the swf.
  13826. *
  13827. * @method Flash#initialTime
  13828. * @return {number}
  13829. * The `initialTime` proprety on the swf.
  13830. */
  13831. /**
  13832. * Get the value of `startOffsetTime` from the swf.
  13833. *
  13834. * @method Flash#startOffsetTime
  13835. * @return {number}
  13836. * The `startOffsetTime` proprety on the swf.
  13837. */
  13838. /**
  13839. * Get the value of `paused` from the swf. `paused` indicates whether the swf
  13840. * is current paused or not.
  13841. *
  13842. * @method Flash#paused
  13843. * @return {boolean}
  13844. * The value of `paused` from the swf.
  13845. */
  13846. /**
  13847. * Get the value of `ended` from the swf. `ended` indicates whether
  13848. * the media has reached the end or not.
  13849. *
  13850. * @method Flash#ended
  13851. * @return {boolean}
  13852. * - True indicates that the media has ended.
  13853. * - False indicates that the media has not ended.
  13854. *
  13855. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-ended}
  13856. */
  13857. /**
  13858. * Get the value of `videoWidth` from the swf. `videoWidth` indicates
  13859. * the current width of the media in css pixels.
  13860. *
  13861. * @method Flash#videoWidth
  13862. * @return {number}
  13863. * The value of `videoWidth` from the swf. This will be a number
  13864. * in css pixels.
  13865. */
  13866. /**
  13867. * Get the value of `videoHeight` from the swf. `videoHeigth` indicates
  13868. * the current height of the media in css pixels.
  13869. *
  13870. * @method Flassh.prototype.videoHeight
  13871. * @return {number}
  13872. * The value of `videoHeight` from the swf. This will be a number
  13873. * in css pixels.
  13874. */
  13875. /** ------------------------------ Setters ------------------------------ **/
  13876. /**
  13877. * Set the value of `rtmpConnection` on the swf.
  13878. *
  13879. * @method Flash#setRtmpConnection
  13880. * @param {string} rtmpConnection
  13881. * New value to set the `rtmpConnection` property to.
  13882. */
  13883. /**
  13884. * Set the value of `rtmpStream` on the swf.
  13885. *
  13886. * @method Flash#setRtmpStream
  13887. * @param {string} rtmpStream
  13888. * New value to set the `rtmpStream` property to.
  13889. */
  13890. /**
  13891. * Set the value of `preload` on the swf. `preload` indicates
  13892. * what should download before the media is interacted with. It can have the following
  13893. * values:
  13894. * - none: nothing should be downloaded
  13895. * - metadata: poster and the first few frames of the media may be downloaded to get
  13896. * media dimensions and other metadata
  13897. * - auto: allow the media and metadata for the media to be downloaded before
  13898. * interaction
  13899. *
  13900. * @method Flash#setPreload
  13901. * @param {string} preload
  13902. * The value of `preload` to set on the swf. Should be 'none', 'metadata',
  13903. * or 'auto'.
  13904. */
  13905. /**
  13906. * Set the value of `defaultPlaybackRate` on the swf.
  13907. *
  13908. * @method Flash#setDefaultPlaybackRate
  13909. * @param {number} defaultPlaybackRate
  13910. * New value to set the `defaultPlaybackRate` property to.
  13911. */
  13912. /**
  13913. * Set the value of `playbackRate` on the swf. `playbackRate` indicates
  13914. * the rate at which the media is currently playing back. Examples:
  13915. * - if playbackRate is set to 2, media will play twice as fast.
  13916. * - if playbackRate is set to 0.5, media will play half as fast.
  13917. *
  13918. * @method Flash#setPlaybackRate
  13919. * @param {number} playbackRate
  13920. * New value of `playbackRate` on the swf. A number indicating
  13921. * the current playback speed of the media, where 1 is normal speed.
  13922. */
  13923. /**
  13924. * Set the value of `autoplay` on the swf. `autoplay` indicates
  13925. * that the media should start to play as soon as the page is ready.
  13926. *
  13927. * @method Flash#setAutoplay
  13928. * @param {boolean} autoplay
  13929. * - The value of `autoplay` from the swf.
  13930. * - True indicates that the media ashould start as soon as the page loads.
  13931. * - False indicates that the media should not start as soon as the page loads.
  13932. */
  13933. /**
  13934. * Set the value of `loop` on the swf. `loop` indicates
  13935. * that the media should return to the start of the media and continue playing once
  13936. * it reaches the end.
  13937. *
  13938. * @method Flash#setLoop
  13939. * @param {boolean} loop
  13940. * - True indicates that playback should seek back to start once
  13941. * the end of a media is reached.
  13942. * - False indicates that playback should not loop back to the start when the
  13943. * end of the media is reached.
  13944. */
  13945. /**
  13946. * Set the value of `mediaGroup` on the swf.
  13947. *
  13948. * @method Flash#setMediaGroup
  13949. * @param {string} mediaGroup
  13950. * New value of `mediaGroup` to set on the swf.
  13951. */
  13952. /**
  13953. * Set the value of `controller` on the swf.
  13954. *
  13955. * @method Flash#setController
  13956. * @param {string} controller
  13957. * New value the current value of `controller` on the swf.
  13958. */
  13959. /**
  13960. * Get the value of `controls` from the swf. `controls` indicates
  13961. * whether the native flash controls should be shown or hidden.
  13962. *
  13963. * @method Flash#controls
  13964. * @return {boolean}
  13965. * - The value of `controls` from the swf.
  13966. * - True indicates that native controls should be showing.
  13967. * - False indicates that native controls should be hidden.
  13968. */
  13969. /**
  13970. * Set the value of the `volume` on the swf. `volume` indicates the current
  13971. * audio level as a percentage in decimal form. This means that 1 is 100%, 0.5 is 50%, and
  13972. * so on.
  13973. *
  13974. * @method Flash#setVolume
  13975. * @param {number} percentAsDecimal
  13976. * The volume percent as a decimal. Value will be between 0-1.
  13977. */
  13978. /**
  13979. * Set the value of the `muted` on the swf. `muted` indicates that the current
  13980. * audio level should be silent.
  13981. *
  13982. * @method Flash#setMuted
  13983. * @param {boolean} muted
  13984. * - True if the audio should be set to silent
  13985. * - False otherwise
  13986. */
  13987. /**
  13988. * Set the value of `defaultMuted` on the swf. `defaultMuted` indicates
  13989. * whether the media should start muted or not. Only changes the default state of the
  13990. * media. `muted` and `defaultMuted` can have different values. `muted` indicates the
  13991. * current state.
  13992. *
  13993. * @method Flash#setDefaultMuted
  13994. * @param {boolean} defaultMuted
  13995. * - True indicates that the media should start muted.
  13996. * - False indicates that the media should not start muted.
  13997. */
  13998. /* Flash Support Testing -------------------------------------------------------- */
  13999. /**
  14000. * Check if the Flash tech is currently supported.
  14001. *
  14002. * @return {boolean}
  14003. * - True if the flash tech is supported.
  14004. * - False otherwise.
  14005. */
  14006. Flash.isSupported = function () {
  14007. return Flash.version()[0] >= 10;
  14008. // return swfobject.hasFlashPlayerVersion('10');
  14009. };
  14010. // Add Source Handler pattern functions to this tech
  14011. _tech2['default'].withSourceHandlers(Flash);
  14012. /*
  14013. * Native source handler for flash, simply passes the source to the swf element.
  14014. *
  14015. * @property {Tech~SourceObject} source
  14016. * The source object
  14017. *
  14018. * @property {Flash} tech
  14019. * The instance of the Flash tech
  14020. */
  14021. Flash.nativeSourceHandler = {};
  14022. /**
  14023. * Check if the Flash can play the given mime type.
  14024. *
  14025. * @param {string} type
  14026. * The mimetype to check
  14027. *
  14028. * @return {string}
  14029. * 'maybe', or '' (empty string)
  14030. */
  14031. Flash.nativeSourceHandler.canPlayType = function (type) {
  14032. if (type in Flash.formats) {
  14033. return 'maybe';
  14034. }
  14035. return '';
  14036. };
  14037. /**
  14038. * Check if the media element can handle a source natively.
  14039. *
  14040. * @param {Tech~SourceObject} source
  14041. * The source object
  14042. *
  14043. * @param {Object} [options]
  14044. * Options to be passed to the tech.
  14045. *
  14046. * @return {string}
  14047. * 'maybe', or '' (empty string).
  14048. */
  14049. Flash.nativeSourceHandler.canHandleSource = function (source, options) {
  14050. var type = void 0;
  14051. function guessMimeType(src) {
  14052. var ext = Url.getFileExtension(src);
  14053. if (ext) {
  14054. return 'video/' + ext;
  14055. }
  14056. return '';
  14057. }
  14058. if (!source.type) {
  14059. type = guessMimeType(source.src);
  14060. } else {
  14061. // Strip code information from the type because we don't get that specific
  14062. type = source.type.replace(/;.*/, '').toLowerCase();
  14063. }
  14064. return Flash.nativeSourceHandler.canPlayType(type);
  14065. };
  14066. /**
  14067. * Pass the source to the swf.
  14068. *
  14069. * @param {Tech~SourceObject} source
  14070. * The source object
  14071. *
  14072. * @param {Flash} tech
  14073. * The instance of the Flash tech
  14074. *
  14075. * @param {Object} [options]
  14076. * The options to pass to the source
  14077. */
  14078. Flash.nativeSourceHandler.handleSource = function (source, tech, options) {
  14079. tech.setSrc(source.src);
  14080. };
  14081. /**
  14082. * noop for native source handler dispose, as cleanup will happen automatically.
  14083. */
  14084. Flash.nativeSourceHandler.dispose = function () {};
  14085. // Register the native source handler
  14086. Flash.registerSourceHandler(Flash.nativeSourceHandler);
  14087. /**
  14088. * Flash supported mime types.
  14089. *
  14090. * @constant {Object}
  14091. */
  14092. Flash.formats = {
  14093. 'video/flv': 'FLV',
  14094. 'video/x-flv': 'FLV',
  14095. 'video/mp4': 'MP4',
  14096. 'video/m4v': 'MP4'
  14097. };
  14098. /**
  14099. * Called when the the swf is "ready", and makes sure that the swf is really
  14100. * ready using {@link Flash#checkReady}
  14101. */
  14102. Flash.onReady = function (currSwf) {
  14103. var el = Dom.getEl(currSwf);
  14104. var tech = el && el.tech;
  14105. // if there is no el then the tech has been disposed
  14106. // and the tech element was removed from the player div
  14107. if (tech && tech.el()) {
  14108. // check that the flash object is really ready
  14109. Flash.checkReady(tech);
  14110. }
  14111. };
  14112. /**
  14113. * The SWF isn't always ready when it says it is. Sometimes the API functions still
  14114. * need to be added to the object. If it's not ready, we set a timeout to check again
  14115. * shortly.
  14116. *
  14117. * @param {Flash} tech
  14118. * The instance of the flash tech to check.
  14119. */
  14120. Flash.checkReady = function (tech) {
  14121. // stop worrying if the tech has been disposed
  14122. if (!tech.el()) {
  14123. return;
  14124. }
  14125. // check if API property exists
  14126. if (tech.el().vjs_getProperty) {
  14127. // tell tech it's ready
  14128. tech.triggerReady();
  14129. } else {
  14130. // wait longer
  14131. this.setTimeout(function () {
  14132. Flash.checkReady(tech);
  14133. }, 50);
  14134. }
  14135. };
  14136. /**
  14137. * Trigger events from the swf on the Flash Tech.
  14138. *
  14139. * @param {number} swfID
  14140. * The id of the swf that had the event
  14141. *
  14142. * @param {string} eventName
  14143. * The name of the event to trigger
  14144. */
  14145. Flash.onEvent = function (swfID, eventName) {
  14146. var tech = Dom.getEl(swfID).tech;
  14147. var args = Array.prototype.slice.call(arguments, 2);
  14148. // dispatch Flash events asynchronously for two reasons:
  14149. // - Flash swallows any exceptions generated by javascript it
  14150. // invokes
  14151. // - Flash is suspended until the javascript returns which may cause
  14152. // playback performance issues
  14153. tech.setTimeout(function () {
  14154. tech.trigger(eventName, args);
  14155. }, 1);
  14156. };
  14157. /**
  14158. * Log errors from the swf on the Flash tech.
  14159. *
  14160. * @param {number} swfID
  14161. * The id of the swf that had an error.
  14162. *
  14163. * @param {string} The error string
  14164. * The error to set on the Flash Tech.
  14165. *
  14166. * @return {MediaError|undefined}
  14167. * - Returns a MediaError when err is 'srcnotfound'
  14168. * - Returns undefined otherwise.
  14169. */
  14170. Flash.onError = function (swfID, err) {
  14171. var tech = Dom.getEl(swfID).tech;
  14172. // trigger MEDIA_ERR_SRC_NOT_SUPPORTED
  14173. if (err === 'srcnotfound') {
  14174. return tech.error(4);
  14175. }
  14176. // trigger a custom error
  14177. tech.error('FLASH: ' + err);
  14178. };
  14179. /**
  14180. * Get the current version of Flash that is in use on the page.
  14181. *
  14182. * @return {Array}
  14183. * an array of versions that are available.
  14184. */
  14185. Flash.version = function () {
  14186. var version = '0,0,0';
  14187. // IE
  14188. try {
  14189. version = new _window2['default'].ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
  14190. // other browsers
  14191. } catch (e) {
  14192. try {
  14193. if (navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin) {
  14194. version = (navigator.plugins['Shockwave Flash 2.0'] || navigator.plugins['Shockwave Flash']).description.replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
  14195. }
  14196. } catch (err) {
  14197. // satisfy linter
  14198. }
  14199. }
  14200. return version.split(',');
  14201. };
  14202. /**
  14203. * Only use for non-iframe embeds.
  14204. *
  14205. * @param {Object} swf
  14206. * The videojs-swf object.
  14207. *
  14208. * @param {Object} flashVars
  14209. * Names and values to use as flash option variables.
  14210. *
  14211. * @param {Object} params
  14212. * Style parameters to set on the object.
  14213. *
  14214. * @param {Object} attributes
  14215. * Attributes to set on the element.
  14216. *
  14217. * @return {Element}
  14218. * The embeded Flash DOM element.
  14219. */
  14220. Flash.embed = function (swf, flashVars, params, attributes) {
  14221. var code = Flash.getEmbedCode(swf, flashVars, params, attributes);
  14222. // Get element by embedding code and retrieving created element
  14223. var obj = Dom.createEl('div', { innerHTML: code }).childNodes[0];
  14224. return obj;
  14225. };
  14226. /**
  14227. * Only use for non-iframe embeds.
  14228. *
  14229. * @param {Object} swf
  14230. * The videojs-swf object.
  14231. *
  14232. * @param {Object} flashVars
  14233. * Names and values to use as flash option variables.
  14234. *
  14235. * @param {Object} params
  14236. * Style parameters to set on the object.
  14237. *
  14238. * @param {Object} attributes
  14239. * Attributes to set on the element.
  14240. *
  14241. * @return {Element}
  14242. * The embeded Flash DOM element.
  14243. */
  14244. Flash.getEmbedCode = function (swf, flashVars, params, attributes) {
  14245. var objTag = '<object type="application/x-shockwave-flash" ';
  14246. var flashVarsString = '';
  14247. var paramsString = '';
  14248. var attrsString = '';
  14249. // Convert flash vars to string
  14250. if (flashVars) {
  14251. Object.getOwnPropertyNames(flashVars).forEach(function (key) {
  14252. flashVarsString += key + '=' + flashVars[key] + '&amp;';
  14253. });
  14254. }
  14255. // Add swf, flashVars, and other default params
  14256. params = (0, _obj.assign)({
  14257. movie: swf,
  14258. flashvars: flashVarsString,
  14259. // Required to talk to swf
  14260. allowScriptAccess: 'always',
  14261. // All should be default, but having security issues.
  14262. allowNetworking: 'all'
  14263. }, params);
  14264. // Create param tags string
  14265. Object.getOwnPropertyNames(params).forEach(function (key) {
  14266. paramsString += '<param name="' + key + '" value="' + params[key] + '" />';
  14267. });
  14268. attributes = (0, _obj.assign)({
  14269. // Add swf to attributes (need both for IE and Others to work)
  14270. data: swf,
  14271. // Default to 100% width/height
  14272. width: '100%',
  14273. height: '100%'
  14274. }, attributes);
  14275. // Create Attributes string
  14276. Object.getOwnPropertyNames(attributes).forEach(function (key) {
  14277. attrsString += key + '="' + attributes[key] + '" ';
  14278. });
  14279. return '' + objTag + attrsString + '>' + paramsString + '</object>';
  14280. };
  14281. // Run Flash through the RTMP decorator
  14282. (0, _flashRtmp2['default'])(Flash);
  14283. _component2['default'].registerComponent('Flash', Flash);
  14284. _tech2['default'].registerTech('Flash', Flash);
  14285. exports['default'] = Flash;
  14286. /***/ }),
  14287. /* 56 */
  14288. /***/ (function(module, exports) {
  14289. 'use strict';
  14290. exports.__esModule = true;
  14291. /**
  14292. * @file flash-rtmp.js
  14293. * @module flash-rtmp
  14294. */
  14295. /**
  14296. * Add RTMP properties to the {@link Flash} Tech.
  14297. *
  14298. * @param {Flash} Flash
  14299. * The flash tech class.
  14300. *
  14301. * @mixin FlashRtmpDecorator
  14302. */
  14303. function FlashRtmpDecorator(Flash) {
  14304. Flash.streamingFormats = {
  14305. 'rtmp/mp4': 'MP4',
  14306. 'rtmp/flv': 'FLV'
  14307. };
  14308. /**
  14309. * Join connection and stream with an ampersand.
  14310. *
  14311. * @param {string} connection
  14312. * The connection string.
  14313. *
  14314. * @param {string} stream
  14315. * The stream string.
  14316. */
  14317. Flash.streamFromParts = function (connection, stream) {
  14318. return connection + '&' + stream;
  14319. };
  14320. /**
  14321. * The flash parts object that contains connection and stream info.
  14322. *
  14323. * @typedef {Object} Flash~PartsObject
  14324. *
  14325. * @property {string} connection
  14326. * The connection string of a source, defaults to an empty string.
  14327. *
  14328. * @property {string} stream
  14329. * The stream string of the source, defaults to an empty string.
  14330. */
  14331. /**
  14332. * Convert a source url into a stream and connection parts.
  14333. *
  14334. * @param {string} src
  14335. * the source url
  14336. *
  14337. * @return {Flash~PartsObject}
  14338. * The parts object that contains a connection and a stream
  14339. */
  14340. Flash.streamToParts = function (src) {
  14341. var parts = {
  14342. connection: '',
  14343. stream: ''
  14344. };
  14345. if (!src) {
  14346. return parts;
  14347. }
  14348. // Look for the normal URL separator we expect, '&'.
  14349. // If found, we split the URL into two pieces around the
  14350. // first '&'.
  14351. var connEnd = src.search(/&(?!\w+=)/);
  14352. var streamBegin = void 0;
  14353. if (connEnd !== -1) {
  14354. streamBegin = connEnd + 1;
  14355. } else {
  14356. // If there's not a '&', we use the last '/' as the delimiter.
  14357. connEnd = streamBegin = src.lastIndexOf('/') + 1;
  14358. if (connEnd === 0) {
  14359. // really, there's not a '/'?
  14360. connEnd = streamBegin = src.length;
  14361. }
  14362. }
  14363. parts.connection = src.substring(0, connEnd);
  14364. parts.stream = src.substring(streamBegin, src.length);
  14365. return parts;
  14366. };
  14367. /**
  14368. * Check if the source type is a streaming type.
  14369. *
  14370. * @param {string} srcType
  14371. * The mime type to check.
  14372. *
  14373. * @return {boolean}
  14374. * - True if the source type is a streaming type.
  14375. * - False if the source type is not a streaming type.
  14376. */
  14377. Flash.isStreamingType = function (srcType) {
  14378. return srcType in Flash.streamingFormats;
  14379. };
  14380. // RTMP has four variations, any string starting
  14381. // with one of these protocols should be valid
  14382. /**
  14383. * Regular expression used to check if the source is an rtmp source.
  14384. *
  14385. * @property {RegExp} Flash.RTMP_RE
  14386. */
  14387. Flash.RTMP_RE = /^rtmp[set]?:\/\//i;
  14388. /**
  14389. * Check if the source itself is a streaming type.
  14390. *
  14391. * @param {string} src
  14392. * The url to the source.
  14393. *
  14394. * @return {boolean}
  14395. * - True if the source url indicates that the source is streaming.
  14396. * - False if the shource url indicates that the source url is not streaming.
  14397. */
  14398. Flash.isStreamingSrc = function (src) {
  14399. return Flash.RTMP_RE.test(src);
  14400. };
  14401. /**
  14402. * A source handler for RTMP urls
  14403. * @type {Object}
  14404. */
  14405. Flash.rtmpSourceHandler = {};
  14406. /**
  14407. * Check if Flash can play the given mime type.
  14408. *
  14409. * @param {string} type
  14410. * The mime type to check
  14411. *
  14412. * @return {string}
  14413. * 'maybe', or '' (empty string)
  14414. */
  14415. Flash.rtmpSourceHandler.canPlayType = function (type) {
  14416. if (Flash.isStreamingType(type)) {
  14417. return 'maybe';
  14418. }
  14419. return '';
  14420. };
  14421. /**
  14422. * Check if Flash can handle the source natively
  14423. *
  14424. * @param {Object} source
  14425. * The source object
  14426. *
  14427. * @param {Object} [options]
  14428. * The options passed to the tech
  14429. *
  14430. * @return {string}
  14431. * 'maybe', or '' (empty string)
  14432. */
  14433. Flash.rtmpSourceHandler.canHandleSource = function (source, options) {
  14434. var can = Flash.rtmpSourceHandler.canPlayType(source.type);
  14435. if (can) {
  14436. return can;
  14437. }
  14438. if (Flash.isStreamingSrc(source.src)) {
  14439. return 'maybe';
  14440. }
  14441. return '';
  14442. };
  14443. /**
  14444. * Pass the source to the flash object.
  14445. *
  14446. * @param {Object} source
  14447. * The source object
  14448. *
  14449. * @param {Flash} tech
  14450. * The instance of the Flash tech
  14451. *
  14452. * @param {Object} [options]
  14453. * The options to pass to the source
  14454. */
  14455. Flash.rtmpSourceHandler.handleSource = function (source, tech, options) {
  14456. var srcParts = Flash.streamToParts(source.src);
  14457. tech.setRtmpConnection(srcParts.connection);
  14458. tech.setRtmpStream(srcParts.stream);
  14459. };
  14460. // Register the native source handler
  14461. Flash.registerSourceHandler(Flash.rtmpSourceHandler);
  14462. return Flash;
  14463. }
  14464. exports['default'] = FlashRtmpDecorator;
  14465. /***/ }),
  14466. /* 57 */
  14467. /***/ (function(module, exports, __webpack_require__) {
  14468. 'use strict';
  14469. exports.__esModule = true;
  14470. var _clickableComponent = __webpack_require__(58);
  14471. var _clickableComponent2 = _interopRequireDefault(_clickableComponent);
  14472. var _component = __webpack_require__(19);
  14473. var _component2 = _interopRequireDefault(_component);
  14474. var _fn = __webpack_require__(20);
  14475. var Fn = _interopRequireWildcard(_fn);
  14476. var _dom = __webpack_require__(11);
  14477. var Dom = _interopRequireWildcard(_dom);
  14478. var _browser = __webpack_require__(10);
  14479. var browser = _interopRequireWildcard(_browser);
  14480. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  14481. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  14482. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  14483. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  14484. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  14485. * @file poster-image.js
  14486. */
  14487. /**
  14488. * A `ClickableComponent` that handles showing the poster image for the player.
  14489. *
  14490. * @extends ClickableComponent
  14491. */
  14492. var PosterImage = function (_ClickableComponent) {
  14493. _inherits(PosterImage, _ClickableComponent);
  14494. /**
  14495. * Create an instance of this class.
  14496. *
  14497. * @param {Player} player
  14498. * The `Player` that this class should attach to.
  14499. *
  14500. * @param {Object} [options]
  14501. * The key/value store of player options.
  14502. */
  14503. function PosterImage(player, options) {
  14504. _classCallCheck(this, PosterImage);
  14505. var _this = _possibleConstructorReturn(this, _ClickableComponent.call(this, player, options));
  14506. _this.update();
  14507. player.on('posterchange', Fn.bind(_this, _this.update));
  14508. return _this;
  14509. }
  14510. /**
  14511. * Clean up and dispose of the `PosterImage`.
  14512. */
  14513. PosterImage.prototype.dispose = function dispose() {
  14514. this.player().off('posterchange', this.update);
  14515. _ClickableComponent.prototype.dispose.call(this);
  14516. };
  14517. /**
  14518. * Create the `PosterImage`s DOM element.
  14519. *
  14520. * @return {Element}
  14521. * The element that gets created.
  14522. */
  14523. PosterImage.prototype.createEl = function createEl() {
  14524. var el = Dom.createEl('div', {
  14525. className: 'vjs-poster',
  14526. // Don't want poster to be tabbable.
  14527. tabIndex: -1
  14528. });
  14529. // To ensure the poster image resizes while maintaining its original aspect
  14530. // ratio, use a div with `background-size` when available. For browsers that
  14531. // do not support `background-size` (e.g. IE8), fall back on using a regular
  14532. // img element.
  14533. if (!browser.BACKGROUND_SIZE_SUPPORTED) {
  14534. this.fallbackImg_ = Dom.createEl('img');
  14535. el.appendChild(this.fallbackImg_);
  14536. }
  14537. return el;
  14538. };
  14539. /**
  14540. * An {@link EventTarget~EventListener} for {@link Player#posterchange} events.
  14541. *
  14542. * @listens Player#posterchange
  14543. *
  14544. * @param {EventTarget~Event} [event]
  14545. * The `Player#posterchange` event that triggered this function.
  14546. */
  14547. PosterImage.prototype.update = function update(event) {
  14548. var url = this.player().poster();
  14549. this.setSrc(url);
  14550. // If there's no poster source we should display:none on this component
  14551. // so it's not still clickable or right-clickable
  14552. if (url) {
  14553. this.show();
  14554. } else {
  14555. this.hide();
  14556. }
  14557. };
  14558. /**
  14559. * Set the source of the `PosterImage` depending on the display method.
  14560. *
  14561. * @param {string} url
  14562. * The URL to the source for the `PosterImage`.
  14563. */
  14564. PosterImage.prototype.setSrc = function setSrc(url) {
  14565. if (this.fallbackImg_) {
  14566. this.fallbackImg_.src = url;
  14567. } else {
  14568. var backgroundImage = '';
  14569. // Any falsey values should stay as an empty string, otherwise
  14570. // this will throw an extra error
  14571. if (url) {
  14572. backgroundImage = 'url("' + url + '")';
  14573. }
  14574. this.el_.style.backgroundImage = backgroundImage;
  14575. }
  14576. };
  14577. /**
  14578. * An {@link EventTarget~EventListener} for clicks on the `PosterImage`. See
  14579. * {@link ClickableComponent#handleClick} for instances where this will be triggered.
  14580. *
  14581. * @listens tap
  14582. * @listens click
  14583. * @listens keydown
  14584. *
  14585. * @param {EventTarget~Event} event
  14586. + The `click`, `tap` or `keydown` event that caused this function to be called.
  14587. */
  14588. PosterImage.prototype.handleClick = function handleClick(event) {
  14589. // We don't want a click to trigger playback when controls are disabled
  14590. if (!this.player_.controls()) {
  14591. return;
  14592. }
  14593. if (this.player_.paused()) {
  14594. this.player_.play();
  14595. } else {
  14596. this.player_.pause();
  14597. }
  14598. };
  14599. return PosterImage;
  14600. }(_clickableComponent2['default']);
  14601. _component2['default'].registerComponent('PosterImage', PosterImage);
  14602. exports['default'] = PosterImage;
  14603. /***/ }),
  14604. /* 58 */
  14605. /***/ (function(module, exports, __webpack_require__) {
  14606. 'use strict';
  14607. exports.__esModule = true;
  14608. var _component = __webpack_require__(19);
  14609. var _component2 = _interopRequireDefault(_component);
  14610. var _dom = __webpack_require__(11);
  14611. var Dom = _interopRequireWildcard(_dom);
  14612. var _events = __webpack_require__(17);
  14613. var Events = _interopRequireWildcard(_events);
  14614. var _fn = __webpack_require__(20);
  14615. var Fn = _interopRequireWildcard(_fn);
  14616. var _log = __webpack_require__(13);
  14617. var _log2 = _interopRequireDefault(_log);
  14618. var _document = __webpack_require__(8);
  14619. var _document2 = _interopRequireDefault(_document);
  14620. var _obj = __webpack_require__(14);
  14621. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  14622. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  14623. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  14624. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  14625. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  14626. * @file button.js
  14627. */
  14628. /**
  14629. * Clickable Component which is clickable or keyboard actionable,
  14630. * but is not a native HTML button.
  14631. *
  14632. * @extends Component
  14633. */
  14634. var ClickableComponent = function (_Component) {
  14635. _inherits(ClickableComponent, _Component);
  14636. /**
  14637. * Creates an instance of this class.
  14638. *
  14639. * @param {Player} player
  14640. * The `Player` that this class should be attached to.
  14641. *
  14642. * @param {Object} [options]
  14643. * The key/value store of player options.
  14644. */
  14645. function ClickableComponent(player, options) {
  14646. _classCallCheck(this, ClickableComponent);
  14647. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
  14648. _this.emitTapEvents();
  14649. _this.enable();
  14650. return _this;
  14651. }
  14652. /**
  14653. * Create the `Component`s DOM element.
  14654. *
  14655. * @param {string} [tag=div]
  14656. * The element's node type.
  14657. *
  14658. * @param {Object} [props={}]
  14659. * An object of properties that should be set on the element.
  14660. *
  14661. * @param {Object} [attributes={}]
  14662. * An object of attributes that should be set on the element.
  14663. *
  14664. * @return {Element}
  14665. * The element that gets created.
  14666. */
  14667. ClickableComponent.prototype.createEl = function createEl() {
  14668. var tag = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'div';
  14669. var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  14670. var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  14671. props = (0, _obj.assign)({
  14672. className: this.buildCSSClass(),
  14673. tabIndex: 0
  14674. }, props);
  14675. if (tag === 'button') {
  14676. _log2['default'].error('Creating a ClickableComponent with an HTML element of ' + tag + ' is not supported; use a Button instead.');
  14677. }
  14678. // Add ARIA attributes for clickable element which is not a native HTML button
  14679. attributes = (0, _obj.assign)({
  14680. 'role': 'button',
  14681. // let the screen reader user know that the text of the element may change
  14682. 'aria-live': 'polite'
  14683. }, attributes);
  14684. this.tabIndex_ = props.tabIndex;
  14685. var el = _Component.prototype.createEl.call(this, tag, props, attributes);
  14686. this.createControlTextEl(el);
  14687. return el;
  14688. };
  14689. /**
  14690. * Create a control text element on this `Component`
  14691. *
  14692. * @param {Element} [el]
  14693. * Parent element for the control text.
  14694. *
  14695. * @return {Element}
  14696. * The control text element that gets created.
  14697. */
  14698. ClickableComponent.prototype.createControlTextEl = function createControlTextEl(el) {
  14699. this.controlTextEl_ = Dom.createEl('span', {
  14700. className: 'vjs-control-text'
  14701. });
  14702. if (el) {
  14703. el.appendChild(this.controlTextEl_);
  14704. }
  14705. this.controlText(this.controlText_, el);
  14706. return this.controlTextEl_;
  14707. };
  14708. /**
  14709. * Get or set the localize text to use for the controls on the `Component`.
  14710. *
  14711. * @param {string} [text]
  14712. * Control text for element.
  14713. *
  14714. * @param {Element} [el=this.el()]
  14715. * Element to set the title on.
  14716. *
  14717. * @return {string|ClickableComponent}
  14718. * - The control text when getting
  14719. * - Returns itself when setting; method can be chained.
  14720. */
  14721. ClickableComponent.prototype.controlText = function controlText(text) {
  14722. var el = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.el();
  14723. if (!text) {
  14724. return this.controlText_ || 'Need Text';
  14725. }
  14726. var localizedText = this.localize(text);
  14727. this.controlText_ = text;
  14728. this.controlTextEl_.innerHTML = localizedText;
  14729. if (!this.nonIconControl) {
  14730. // Set title attribute if only an icon is shown
  14731. el.setAttribute('title', localizedText);
  14732. }
  14733. return this;
  14734. };
  14735. /**
  14736. * Builds the default DOM `className`.
  14737. *
  14738. * @return {string}
  14739. * The DOM `className` for this object.
  14740. */
  14741. ClickableComponent.prototype.buildCSSClass = function buildCSSClass() {
  14742. return 'vjs-control vjs-button ' + _Component.prototype.buildCSSClass.call(this);
  14743. };
  14744. /**
  14745. * Enable this `Component`s element.
  14746. *
  14747. * @return {ClickableComponent}
  14748. * Returns itself; method can be chained.
  14749. */
  14750. ClickableComponent.prototype.enable = function enable() {
  14751. this.removeClass('vjs-disabled');
  14752. this.el_.setAttribute('aria-disabled', 'false');
  14753. if (typeof this.tabIndex_ !== 'undefined') {
  14754. this.el_.setAttribute('tabIndex', this.tabIndex_);
  14755. }
  14756. this.off(['tap', 'click'], this.handleClick);
  14757. this.off('focus', this.handleFocus);
  14758. this.off('blur', this.handleBlur);
  14759. this.on(['tap', 'click'], this.handleClick);
  14760. this.on('focus', this.handleFocus);
  14761. this.on('blur', this.handleBlur);
  14762. return this;
  14763. };
  14764. /**
  14765. * Disable this `Component`s element.
  14766. *
  14767. * @return {ClickableComponent}
  14768. * Returns itself; method can be chained.
  14769. */
  14770. ClickableComponent.prototype.disable = function disable() {
  14771. this.addClass('vjs-disabled');
  14772. this.el_.setAttribute('aria-disabled', 'true');
  14773. if (typeof this.tabIndex_ !== 'undefined') {
  14774. this.el_.removeAttribute('tabIndex');
  14775. }
  14776. this.off(['tap', 'click'], this.handleClick);
  14777. this.off('focus', this.handleFocus);
  14778. this.off('blur', this.handleBlur);
  14779. return this;
  14780. };
  14781. /**
  14782. * This gets called when a `ClickableComponent` gets:
  14783. * - Clicked (via the `click` event, listening starts in the constructor)
  14784. * - Tapped (via the `tap` event, listening starts in the constructor)
  14785. * - The following things happen in order:
  14786. * 1. {@link ClickableComponent#handleFocus} is called via a `focus` event on the
  14787. * `ClickableComponent`.
  14788. * 2. {@link ClickableComponent#handleFocus} adds a listener for `keydown` on using
  14789. * {@link ClickableComponent#handleKeyPress}.
  14790. * 3. `ClickableComponent` has not had a `blur` event (`blur` means that focus was lost). The user presses
  14791. * the space or enter key.
  14792. * 4. {@link ClickableComponent#handleKeyPress} calls this function with the `keydown`
  14793. * event as a parameter.
  14794. *
  14795. * @param {EventTarget~Event} event
  14796. * The `keydown`, `tap`, or `click` event that caused this function to be
  14797. * called.
  14798. *
  14799. * @listens tap
  14800. * @listens click
  14801. * @abstract
  14802. */
  14803. ClickableComponent.prototype.handleClick = function handleClick(event) {};
  14804. /**
  14805. * This gets called when a `ClickableComponent` gains focus via a `focus` event.
  14806. * Turns on listening for `keydown` events. When they happen it
  14807. * calls `this.handleKeyPress`.
  14808. *
  14809. * @param {EventTarget~Event} event
  14810. * The `focus` event that caused this function to be called.
  14811. *
  14812. * @listens focus
  14813. */
  14814. ClickableComponent.prototype.handleFocus = function handleFocus(event) {
  14815. Events.on(_document2['default'], 'keydown', Fn.bind(this, this.handleKeyPress));
  14816. };
  14817. /**
  14818. * Called when this ClickableComponent has focus and a key gets pressed down. By
  14819. * default it will call `this.handleClick` when the key is space or enter.
  14820. *
  14821. * @param {EventTarget~Event} event
  14822. * The `keydown` event that caused this function to be called.
  14823. *
  14824. * @listens keydown
  14825. */
  14826. ClickableComponent.prototype.handleKeyPress = function handleKeyPress(event) {
  14827. // Support Space (32) or Enter (13) key operation to fire a click event
  14828. if (event.which === 32 || event.which === 13) {
  14829. event.preventDefault();
  14830. this.handleClick(event);
  14831. } else if (_Component.prototype.handleKeyPress) {
  14832. // Pass keypress handling up for unsupported keys
  14833. _Component.prototype.handleKeyPress.call(this, event);
  14834. }
  14835. };
  14836. /**
  14837. * Called when a `ClickableComponent` loses focus. Turns off the listener for
  14838. * `keydown` events. Which Stops `this.handleKeyPress` from getting called.
  14839. *
  14840. * @param {EventTarget~Event} event
  14841. * The `blur` event that caused this function to be called.
  14842. *
  14843. * @listens blur
  14844. */
  14845. ClickableComponent.prototype.handleBlur = function handleBlur(event) {
  14846. Events.off(_document2['default'], 'keydown', Fn.bind(this, this.handleKeyPress));
  14847. };
  14848. return ClickableComponent;
  14849. }(_component2['default']);
  14850. _component2['default'].registerComponent('ClickableComponent', ClickableComponent);
  14851. exports['default'] = ClickableComponent;
  14852. /***/ }),
  14853. /* 59 */
  14854. /***/ (function(module, exports, __webpack_require__) {
  14855. 'use strict';
  14856. exports.__esModule = true;
  14857. var _component = __webpack_require__(19);
  14858. var _component2 = _interopRequireDefault(_component);
  14859. var _fn = __webpack_require__(20);
  14860. var Fn = _interopRequireWildcard(_fn);
  14861. var _window = __webpack_require__(7);
  14862. var _window2 = _interopRequireDefault(_window);
  14863. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  14864. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  14865. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  14866. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  14867. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  14868. * @file text-track-display.js
  14869. */
  14870. var darkGray = '#222';
  14871. var lightGray = '#ccc';
  14872. var fontMap = {
  14873. monospace: 'monospace',
  14874. sansSerif: 'sans-serif',
  14875. serif: 'serif',
  14876. monospaceSansSerif: '"Andale Mono", "Lucida Console", monospace',
  14877. monospaceSerif: '"Courier New", monospace',
  14878. proportionalSansSerif: 'sans-serif',
  14879. proportionalSerif: 'serif',
  14880. casual: '"Comic Sans MS", Impact, fantasy',
  14881. script: '"Monotype Corsiva", cursive',
  14882. smallcaps: '"Andale Mono", "Lucida Console", monospace, sans-serif'
  14883. };
  14884. /**
  14885. * Construct an rgba color from a given hex color code.
  14886. *
  14887. * @param {number} color
  14888. * Hex number for color, like #f0e.
  14889. *
  14890. * @param {number} opacity
  14891. * Value for opacity, 0.0 - 1.0.
  14892. *
  14893. * @return {string}
  14894. * The rgba color that was created, like 'rgba(255, 0, 0, 0.3)'.
  14895. *
  14896. * @private
  14897. */
  14898. function constructColor(color, opacity) {
  14899. return 'rgba(' +
  14900. // color looks like "#f0e"
  14901. parseInt(color[1] + color[1], 16) + ',' + parseInt(color[2] + color[2], 16) + ',' + parseInt(color[3] + color[3], 16) + ',' + opacity + ')';
  14902. }
  14903. /**
  14904. * Try to update the style of a DOM element. Some style changes will throw an error,
  14905. * particularly in IE8. Those should be noops.
  14906. *
  14907. * @param {Element} el
  14908. * The DOM element to be styled.
  14909. *
  14910. * @param {string} style
  14911. * The CSS property on the element that should be styled.
  14912. *
  14913. * @param {string} rule
  14914. * The style rule that should be applied to the property.
  14915. */
  14916. function tryUpdateStyle(el, style, rule) {
  14917. try {
  14918. el.style[style] = rule;
  14919. } catch (e) {
  14920. // Satisfies linter.
  14921. return;
  14922. }
  14923. }
  14924. /**
  14925. * The component for displaying text track cues.
  14926. *
  14927. * @extends Component
  14928. */
  14929. var TextTrackDisplay = function (_Component) {
  14930. _inherits(TextTrackDisplay, _Component);
  14931. /**
  14932. * Creates an instance of this class.
  14933. *
  14934. * @param {Player} player
  14935. * The `Player` that this class should be attached to.
  14936. *
  14937. * @param {Object} [options]
  14938. * The key/value store of player options.
  14939. *
  14940. * @param {Component~ReadyCallback} [ready]
  14941. * The function to call when `TextTrackDisplay` is ready.
  14942. */
  14943. function TextTrackDisplay(player, options, ready) {
  14944. _classCallCheck(this, TextTrackDisplay);
  14945. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options, ready));
  14946. player.on('loadstart', Fn.bind(_this, _this.toggleDisplay));
  14947. player.on('texttrackchange', Fn.bind(_this, _this.updateDisplay));
  14948. // This used to be called during player init, but was causing an error
  14949. // if a track should show by default and the display hadn't loaded yet.
  14950. // Should probably be moved to an external track loader when we support
  14951. // tracks that don't need a display.
  14952. player.ready(Fn.bind(_this, function () {
  14953. if (player.tech_ && player.tech_.featuresNativeTextTracks) {
  14954. this.hide();
  14955. return;
  14956. }
  14957. player.on('fullscreenchange', Fn.bind(this, this.updateDisplay));
  14958. var tracks = this.options_.playerOptions.tracks || [];
  14959. for (var i = 0; i < tracks.length; i++) {
  14960. this.player_.addRemoteTextTrack(tracks[i], true);
  14961. }
  14962. var modes = { captions: 1, subtitles: 1 };
  14963. var trackList = this.player_.textTracks();
  14964. var firstDesc = void 0;
  14965. var firstCaptions = void 0;
  14966. if (trackList) {
  14967. for (var _i = 0; _i < trackList.length; _i++) {
  14968. var track = trackList[_i];
  14969. if (track['default']) {
  14970. if (track.kind === 'descriptions' && !firstDesc) {
  14971. firstDesc = track;
  14972. } else if (track.kind in modes && !firstCaptions) {
  14973. firstCaptions = track;
  14974. }
  14975. }
  14976. }
  14977. // We want to show the first default track but captions and subtitles
  14978. // take precedence over descriptions.
  14979. // So, display the first default captions or subtitles track
  14980. // and otherwise the first default descriptions track.
  14981. if (firstCaptions) {
  14982. firstCaptions.mode = 'showing';
  14983. } else if (firstDesc) {
  14984. firstDesc.mode = 'showing';
  14985. }
  14986. }
  14987. }));
  14988. return _this;
  14989. }
  14990. /**
  14991. * Turn display of {@link TextTrack}'s from the current state into the other state.
  14992. * There are only two states:
  14993. * - 'shown'
  14994. * - 'hidden'
  14995. *
  14996. * @listens Player#loadstart
  14997. */
  14998. TextTrackDisplay.prototype.toggleDisplay = function toggleDisplay() {
  14999. if (this.player_.tech_ && this.player_.tech_.featuresNativeTextTracks) {
  15000. this.hide();
  15001. } else {
  15002. this.show();
  15003. }
  15004. };
  15005. /**
  15006. * Create the {@link Component}'s DOM element.
  15007. *
  15008. * @return {Element}
  15009. * The element that was created.
  15010. */
  15011. TextTrackDisplay.prototype.createEl = function createEl() {
  15012. return _Component.prototype.createEl.call(this, 'div', {
  15013. className: 'vjs-text-track-display'
  15014. }, {
  15015. 'aria-live': 'off',
  15016. 'aria-atomic': 'true'
  15017. });
  15018. };
  15019. /**
  15020. * Clear all displayed {@link TextTrack}s.
  15021. */
  15022. TextTrackDisplay.prototype.clearDisplay = function clearDisplay() {
  15023. if (typeof _window2['default'].WebVTT === 'function') {
  15024. _window2['default'].WebVTT.processCues(_window2['default'], [], this.el_);
  15025. }
  15026. };
  15027. /**
  15028. * Update the displayed TextTrack when a either a {@link Player#texttrackchange} or
  15029. * a {@link Player#fullscreenchange} is fired.
  15030. *
  15031. * @listens Player#texttrackchange
  15032. * @listens Player#fullscreenchange
  15033. */
  15034. TextTrackDisplay.prototype.updateDisplay = function updateDisplay() {
  15035. var tracks = this.player_.textTracks();
  15036. this.clearDisplay();
  15037. if (!tracks) {
  15038. return;
  15039. }
  15040. // Track display prioritization model: if multiple tracks are 'showing',
  15041. // display the first 'subtitles' or 'captions' track which is 'showing',
  15042. // otherwise display the first 'descriptions' track which is 'showing'
  15043. var descriptionsTrack = null;
  15044. var captionsSubtitlesTrack = null;
  15045. var i = tracks.length;
  15046. while (i--) {
  15047. var track = tracks[i];
  15048. if (track.mode === 'showing') {
  15049. if (track.kind === 'descriptions') {
  15050. descriptionsTrack = track;
  15051. } else {
  15052. captionsSubtitlesTrack = track;
  15053. }
  15054. }
  15055. }
  15056. if (captionsSubtitlesTrack) {
  15057. if (this.getAttribute('aria-live') !== 'off') {
  15058. this.setAttribute('aria-live', 'off');
  15059. }
  15060. this.updateForTrack(captionsSubtitlesTrack);
  15061. } else if (descriptionsTrack) {
  15062. if (this.getAttribute('aria-live') !== 'assertive') {
  15063. this.setAttribute('aria-live', 'assertive');
  15064. }
  15065. this.updateForTrack(descriptionsTrack);
  15066. }
  15067. };
  15068. /**
  15069. * Add an {@link Texttrack} to to the {@link Tech}s {@link TextTrackList}.
  15070. *
  15071. * @param {TextTrack} track
  15072. * Text track object to be added to the list.
  15073. */
  15074. TextTrackDisplay.prototype.updateForTrack = function updateForTrack(track) {
  15075. if (typeof _window2['default'].WebVTT !== 'function' || !track.activeCues) {
  15076. return;
  15077. }
  15078. var overrides = this.player_.textTrackSettings.getValues();
  15079. var cues = [];
  15080. for (var _i2 = 0; _i2 < track.activeCues.length; _i2++) {
  15081. cues.push(track.activeCues[_i2]);
  15082. }
  15083. _window2['default'].WebVTT.processCues(_window2['default'], cues, this.el_);
  15084. var i = cues.length;
  15085. while (i--) {
  15086. var cue = cues[i];
  15087. if (!cue) {
  15088. continue;
  15089. }
  15090. var cueDiv = cue.displayState;
  15091. if (overrides.color) {
  15092. cueDiv.firstChild.style.color = overrides.color;
  15093. }
  15094. if (overrides.textOpacity) {
  15095. tryUpdateStyle(cueDiv.firstChild, 'color', constructColor(overrides.color || '#fff', overrides.textOpacity));
  15096. }
  15097. if (overrides.backgroundColor) {
  15098. cueDiv.firstChild.style.backgroundColor = overrides.backgroundColor;
  15099. }
  15100. if (overrides.backgroundOpacity) {
  15101. tryUpdateStyle(cueDiv.firstChild, 'backgroundColor', constructColor(overrides.backgroundColor || '#000', overrides.backgroundOpacity));
  15102. }
  15103. if (overrides.windowColor) {
  15104. if (overrides.windowOpacity) {
  15105. tryUpdateStyle(cueDiv, 'backgroundColor', constructColor(overrides.windowColor, overrides.windowOpacity));
  15106. } else {
  15107. cueDiv.style.backgroundColor = overrides.windowColor;
  15108. }
  15109. }
  15110. if (overrides.edgeStyle) {
  15111. if (overrides.edgeStyle === 'dropshadow') {
  15112. cueDiv.firstChild.style.textShadow = '2px 2px 3px ' + darkGray + ', 2px 2px 4px ' + darkGray + ', 2px 2px 5px ' + darkGray;
  15113. } else if (overrides.edgeStyle === 'raised') {
  15114. cueDiv.firstChild.style.textShadow = '1px 1px ' + darkGray + ', 2px 2px ' + darkGray + ', 3px 3px ' + darkGray;
  15115. } else if (overrides.edgeStyle === 'depressed') {
  15116. cueDiv.firstChild.style.textShadow = '1px 1px ' + lightGray + ', 0 1px ' + lightGray + ', -1px -1px ' + darkGray + ', 0 -1px ' + darkGray;
  15117. } else if (overrides.edgeStyle === 'uniform') {
  15118. cueDiv.firstChild.style.textShadow = '0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray;
  15119. }
  15120. }
  15121. if (overrides.fontPercent && overrides.fontPercent !== 1) {
  15122. var fontSize = _window2['default'].parseFloat(cueDiv.style.fontSize);
  15123. cueDiv.style.fontSize = fontSize * overrides.fontPercent + 'px';
  15124. cueDiv.style.height = 'auto';
  15125. cueDiv.style.top = 'auto';
  15126. cueDiv.style.bottom = '2px';
  15127. }
  15128. if (overrides.fontFamily && overrides.fontFamily !== 'default') {
  15129. if (overrides.fontFamily === 'small-caps') {
  15130. cueDiv.firstChild.style.fontVariant = 'small-caps';
  15131. } else {
  15132. cueDiv.firstChild.style.fontFamily = fontMap[overrides.fontFamily];
  15133. }
  15134. }
  15135. }
  15136. };
  15137. return TextTrackDisplay;
  15138. }(_component2['default']);
  15139. _component2['default'].registerComponent('TextTrackDisplay', TextTrackDisplay);
  15140. exports['default'] = TextTrackDisplay;
  15141. /***/ }),
  15142. /* 60 */
  15143. /***/ (function(module, exports, __webpack_require__) {
  15144. 'use strict';
  15145. exports.__esModule = true;
  15146. var _component = __webpack_require__(19);
  15147. var _component2 = _interopRequireDefault(_component);
  15148. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  15149. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  15150. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  15151. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  15152. * @file loading-spinner.js
  15153. */
  15154. /**
  15155. * A loading spinner for use during waiting/loading events.
  15156. *
  15157. * @extends Component
  15158. */
  15159. var LoadingSpinner = function (_Component) {
  15160. _inherits(LoadingSpinner, _Component);
  15161. function LoadingSpinner() {
  15162. _classCallCheck(this, LoadingSpinner);
  15163. return _possibleConstructorReturn(this, _Component.apply(this, arguments));
  15164. }
  15165. /**
  15166. * Create the `LoadingSpinner`s DOM element.
  15167. *
  15168. * @return {Element}
  15169. * The dom element that gets created.
  15170. */
  15171. LoadingSpinner.prototype.createEl = function createEl() {
  15172. return _Component.prototype.createEl.call(this, 'div', {
  15173. className: 'vjs-loading-spinner',
  15174. dir: 'ltr'
  15175. });
  15176. };
  15177. return LoadingSpinner;
  15178. }(_component2['default']);
  15179. _component2['default'].registerComponent('LoadingSpinner', LoadingSpinner);
  15180. exports['default'] = LoadingSpinner;
  15181. /***/ }),
  15182. /* 61 */
  15183. /***/ (function(module, exports, __webpack_require__) {
  15184. 'use strict';
  15185. exports.__esModule = true;
  15186. var _button = __webpack_require__(62);
  15187. var _button2 = _interopRequireDefault(_button);
  15188. var _component = __webpack_require__(19);
  15189. var _component2 = _interopRequireDefault(_component);
  15190. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  15191. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  15192. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  15193. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  15194. * @file big-play-button.js
  15195. */
  15196. /**
  15197. * The initial play button that shows before the video has played. The hiding of the
  15198. * `BigPlayButton` get done via CSS and `Player` states.
  15199. *
  15200. * @extends Button
  15201. */
  15202. var BigPlayButton = function (_Button) {
  15203. _inherits(BigPlayButton, _Button);
  15204. function BigPlayButton(player, options) {
  15205. _classCallCheck(this, BigPlayButton);
  15206. var _this = _possibleConstructorReturn(this, _Button.call(this, player, options));
  15207. _this.mouseused_ = false;
  15208. _this.on('mousedown', _this.handleMouseDown);
  15209. return _this;
  15210. }
  15211. /**
  15212. * Builds the default DOM `className`.
  15213. *
  15214. * @return {string}
  15215. * The DOM `className` for this object. Always returns 'vjs-big-play-button'.
  15216. */
  15217. BigPlayButton.prototype.buildCSSClass = function buildCSSClass() {
  15218. return 'vjs-big-play-button';
  15219. };
  15220. /**
  15221. * This gets called when a `BigPlayButton` "clicked". See {@link ClickableComponent}
  15222. * for more detailed information on what a click can be.
  15223. *
  15224. * @param {EventTarget~Event} event
  15225. * The `keydown`, `tap`, or `click` event that caused this function to be
  15226. * called.
  15227. *
  15228. * @listens tap
  15229. * @listens click
  15230. */
  15231. BigPlayButton.prototype.handleClick = function handleClick(event) {
  15232. var playPromise = this.player_.play();
  15233. // exit early if clicked via the mouse
  15234. if (this.mouseused_ && event.clientX && event.clientY) {
  15235. return;
  15236. }
  15237. var cb = this.player_.getChild('controlBar');
  15238. var playToggle = cb && cb.getChild('playToggle');
  15239. if (!playToggle) {
  15240. this.player_.focus();
  15241. return;
  15242. }
  15243. var playFocus = function playFocus() {
  15244. return playToggle.focus();
  15245. };
  15246. if (playPromise && playPromise.then) {
  15247. var ignoreRejectedPlayPromise = function ignoreRejectedPlayPromise() {};
  15248. playPromise.then(playFocus, ignoreRejectedPlayPromise);
  15249. } else {
  15250. this.setTimeout(playFocus, 1);
  15251. }
  15252. };
  15253. BigPlayButton.prototype.handleKeyPress = function handleKeyPress(event) {
  15254. this.mouseused_ = false;
  15255. _Button.prototype.handleKeyPress.call(this, event);
  15256. };
  15257. BigPlayButton.prototype.handleMouseDown = function handleMouseDown(event) {
  15258. this.mouseused_ = true;
  15259. };
  15260. return BigPlayButton;
  15261. }(_button2['default']);
  15262. /**
  15263. * The text that should display over the `BigPlayButton`s controls. Added to for localization.
  15264. *
  15265. * @type {string}
  15266. * @private
  15267. */
  15268. BigPlayButton.prototype.controlText_ = 'Play Video';
  15269. _component2['default'].registerComponent('BigPlayButton', BigPlayButton);
  15270. exports['default'] = BigPlayButton;
  15271. /***/ }),
  15272. /* 62 */
  15273. /***/ (function(module, exports, __webpack_require__) {
  15274. 'use strict';
  15275. exports.__esModule = true;
  15276. var _clickableComponent = __webpack_require__(58);
  15277. var _clickableComponent2 = _interopRequireDefault(_clickableComponent);
  15278. var _component = __webpack_require__(19);
  15279. var _component2 = _interopRequireDefault(_component);
  15280. var _log = __webpack_require__(13);
  15281. var _log2 = _interopRequireDefault(_log);
  15282. var _obj = __webpack_require__(14);
  15283. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  15284. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  15285. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  15286. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  15287. * @file button.js
  15288. */
  15289. /**
  15290. * Base class for all buttons.
  15291. *
  15292. * @extends ClickableComponent
  15293. */
  15294. var Button = function (_ClickableComponent) {
  15295. _inherits(Button, _ClickableComponent);
  15296. function Button() {
  15297. _classCallCheck(this, Button);
  15298. return _possibleConstructorReturn(this, _ClickableComponent.apply(this, arguments));
  15299. }
  15300. /**
  15301. * Create the `Button`s DOM element.
  15302. *
  15303. * @param {string} [tag=button]
  15304. * Element's node type. e.g. 'button'
  15305. *
  15306. * @param {Object} [props={}]
  15307. * An object of properties that should be set on the element.
  15308. *
  15309. * @param {Object} [attributes={}]
  15310. * An object of attributes that should be set on the element.
  15311. *
  15312. * @return {Element}
  15313. * The element that gets created.
  15314. */
  15315. Button.prototype.createEl = function createEl() {
  15316. var tag = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'button';
  15317. var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  15318. var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  15319. props = (0, _obj.assign)({
  15320. className: this.buildCSSClass()
  15321. }, props);
  15322. if (tag !== 'button') {
  15323. _log2['default'].warn('Creating a Button with an HTML element of ' + tag + ' is deprecated; use ClickableComponent instead.');
  15324. // Add properties for clickable element which is not a native HTML button
  15325. props = (0, _obj.assign)({
  15326. tabIndex: 0
  15327. }, props);
  15328. // Add ARIA attributes for clickable element which is not a native HTML button
  15329. attributes = (0, _obj.assign)({
  15330. role: 'button'
  15331. }, attributes);
  15332. }
  15333. // Add attributes for button element
  15334. attributes = (0, _obj.assign)({
  15335. // Necessary since the default button type is "submit"
  15336. 'type': 'button',
  15337. // let the screen reader user know that the text of the button may change
  15338. 'aria-live': 'polite'
  15339. }, attributes);
  15340. var el = _component2['default'].prototype.createEl.call(this, tag, props, attributes);
  15341. this.createControlTextEl(el);
  15342. return el;
  15343. };
  15344. /**
  15345. * Add a child `Component` inside of this `Button`.
  15346. *
  15347. * @param {string|Component} child
  15348. * The name or instance of a child to add.
  15349. *
  15350. * @param {Object} [options={}]
  15351. * The key/value store of options that will get passed to children of
  15352. * the child.
  15353. *
  15354. * @return {Component}
  15355. * The `Component` that gets added as a child. When using a string the
  15356. * `Component` will get created by this process.
  15357. *
  15358. * @deprecated since version 5
  15359. */
  15360. Button.prototype.addChild = function addChild(child) {
  15361. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  15362. var className = this.constructor.name;
  15363. _log2['default'].warn('Adding an actionable (user controllable) child to a Button (' + className + ') is not supported; use a ClickableComponent instead.');
  15364. // Avoid the error message generated by ClickableComponent's addChild method
  15365. return _component2['default'].prototype.addChild.call(this, child, options);
  15366. };
  15367. /**
  15368. * Enable the `Button` element so that it can be activated or clicked. Use this with
  15369. * {@link Button#disable}.
  15370. */
  15371. Button.prototype.enable = function enable() {
  15372. _ClickableComponent.prototype.enable.call(this);
  15373. this.el_.removeAttribute('disabled');
  15374. };
  15375. /**
  15376. * Enable the `Button` element so that it cannot be activated or clicked. Use this with
  15377. * {@link Button#enable}.
  15378. */
  15379. Button.prototype.disable = function disable() {
  15380. _ClickableComponent.prototype.disable.call(this);
  15381. this.el_.setAttribute('disabled', 'disabled');
  15382. };
  15383. /**
  15384. * This gets called when a `Button` has focus and `keydown` is triggered via a key
  15385. * press.
  15386. *
  15387. * @param {EventTarget~Event} event
  15388. * The event that caused this function to get called.
  15389. *
  15390. * @listens keydown
  15391. */
  15392. Button.prototype.handleKeyPress = function handleKeyPress(event) {
  15393. // Ignore Space (32) or Enter (13) key operation, which is handled by the browser for a button.
  15394. if (event.which === 32 || event.which === 13) {
  15395. return;
  15396. }
  15397. // Pass keypress handling up for unsupported keys
  15398. _ClickableComponent.prototype.handleKeyPress.call(this, event);
  15399. };
  15400. return Button;
  15401. }(_clickableComponent2['default']);
  15402. _component2['default'].registerComponent('Button', Button);
  15403. exports['default'] = Button;
  15404. /***/ }),
  15405. /* 63 */
  15406. /***/ (function(module, exports, __webpack_require__) {
  15407. 'use strict';
  15408. exports.__esModule = true;
  15409. var _button = __webpack_require__(62);
  15410. var _button2 = _interopRequireDefault(_button);
  15411. var _component = __webpack_require__(19);
  15412. var _component2 = _interopRequireDefault(_component);
  15413. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  15414. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  15415. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  15416. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  15417. * @file close-button.js
  15418. */
  15419. /**
  15420. * The `CloseButton` is a `{@link Button}` that fires a `close` event when
  15421. * it gets clicked.
  15422. *
  15423. * @extends Button
  15424. */
  15425. var CloseButton = function (_Button) {
  15426. _inherits(CloseButton, _Button);
  15427. /**
  15428. * Creates an instance of the this class.
  15429. *
  15430. * @param {Player} player
  15431. * The `Player` that this class should be attached to.
  15432. *
  15433. * @param {Object} [options]
  15434. * The key/value store of player options.
  15435. */
  15436. function CloseButton(player, options) {
  15437. _classCallCheck(this, CloseButton);
  15438. var _this = _possibleConstructorReturn(this, _Button.call(this, player, options));
  15439. _this.controlText(options && options.controlText || _this.localize('Close'));
  15440. return _this;
  15441. }
  15442. /**
  15443. * Builds the default DOM `className`.
  15444. *
  15445. * @return {string}
  15446. * The DOM `className` for this object.
  15447. */
  15448. CloseButton.prototype.buildCSSClass = function buildCSSClass() {
  15449. return 'vjs-close-button ' + _Button.prototype.buildCSSClass.call(this);
  15450. };
  15451. /**
  15452. * This gets called when a `CloseButton` gets clicked. See
  15453. * {@link ClickableComponent#handleClick} for more information on when this will be
  15454. * triggered
  15455. *
  15456. * @param {EventTarget~Event} event
  15457. * The `keydown`, `tap`, or `click` event that caused this function to be
  15458. * called.
  15459. *
  15460. * @listens tap
  15461. * @listens click
  15462. * @fires CloseButton#close
  15463. */
  15464. CloseButton.prototype.handleClick = function handleClick(event) {
  15465. /**
  15466. * Triggered when the a `CloseButton` is clicked.
  15467. *
  15468. * @event CloseButton#close
  15469. * @type {EventTarget~Event}
  15470. *
  15471. * @property {boolean} [bubbles=false]
  15472. * set to false so that the close event does not
  15473. * bubble up to parents if there is no listener
  15474. */
  15475. this.trigger({ type: 'close', bubbles: false });
  15476. };
  15477. return CloseButton;
  15478. }(_button2['default']);
  15479. _component2['default'].registerComponent('CloseButton', CloseButton);
  15480. exports['default'] = CloseButton;
  15481. /***/ }),
  15482. /* 64 */
  15483. /***/ (function(module, exports, __webpack_require__) {
  15484. 'use strict';
  15485. exports.__esModule = true;
  15486. var _component = __webpack_require__(19);
  15487. var _component2 = _interopRequireDefault(_component);
  15488. __webpack_require__(65);
  15489. __webpack_require__(66);
  15490. __webpack_require__(68);
  15491. __webpack_require__(69);
  15492. __webpack_require__(70);
  15493. __webpack_require__(71);
  15494. __webpack_require__(72);
  15495. __webpack_require__(80);
  15496. __webpack_require__(81);
  15497. __webpack_require__(84);
  15498. __webpack_require__(87);
  15499. __webpack_require__(88);
  15500. __webpack_require__(97);
  15501. __webpack_require__(98);
  15502. __webpack_require__(99);
  15503. __webpack_require__(101);
  15504. __webpack_require__(103);
  15505. __webpack_require__(105);
  15506. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  15507. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  15508. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  15509. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  15510. * @file control-bar.js
  15511. */
  15512. // Required children
  15513. /**
  15514. * Container of main controls.
  15515. *
  15516. * @extends Component
  15517. */
  15518. var ControlBar = function (_Component) {
  15519. _inherits(ControlBar, _Component);
  15520. function ControlBar() {
  15521. _classCallCheck(this, ControlBar);
  15522. return _possibleConstructorReturn(this, _Component.apply(this, arguments));
  15523. }
  15524. /**
  15525. * Create the `Component`'s DOM element
  15526. *
  15527. * @return {Element}
  15528. * The element that was created.
  15529. */
  15530. ControlBar.prototype.createEl = function createEl() {
  15531. return _Component.prototype.createEl.call(this, 'div', {
  15532. className: 'vjs-control-bar',
  15533. dir: 'ltr'
  15534. }, {
  15535. // The control bar is a group, so it can contain menuitems
  15536. role: 'group'
  15537. });
  15538. };
  15539. return ControlBar;
  15540. }(_component2['default']);
  15541. /**
  15542. * Default options for `ControlBar`
  15543. *
  15544. * @type {Object}
  15545. * @private
  15546. */
  15547. ControlBar.prototype.options_ = {
  15548. children: ['playToggle', 'volumeMenuButton', 'currentTimeDisplay', 'timeDivider', 'durationDisplay', 'progressControl', 'liveDisplay', 'remainingTimeDisplay', 'customControlSpacer', 'playbackRateMenuButton', 'chaptersButton', 'descriptionsButton', 'subtitlesButton', 'captionsButton', 'audioTrackButton', 'fullscreenToggle']
  15549. };
  15550. _component2['default'].registerComponent('ControlBar', ControlBar);
  15551. exports['default'] = ControlBar;
  15552. /***/ }),
  15553. /* 65 */
  15554. /***/ (function(module, exports, __webpack_require__) {
  15555. 'use strict';
  15556. exports.__esModule = true;
  15557. var _button = __webpack_require__(62);
  15558. var _button2 = _interopRequireDefault(_button);
  15559. var _component = __webpack_require__(19);
  15560. var _component2 = _interopRequireDefault(_component);
  15561. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  15562. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  15563. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  15564. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  15565. * @file play-toggle.js
  15566. */
  15567. /**
  15568. * Button to toggle between play and pause.
  15569. *
  15570. * @extends Button
  15571. */
  15572. var PlayToggle = function (_Button) {
  15573. _inherits(PlayToggle, _Button);
  15574. /**
  15575. * Creates an instance of this class.
  15576. *
  15577. * @param {Player} player
  15578. * The `Player` that this class should be attached to.
  15579. *
  15580. * @param {Object} [options]
  15581. * The key/value store of player options.
  15582. */
  15583. function PlayToggle(player, options) {
  15584. _classCallCheck(this, PlayToggle);
  15585. var _this = _possibleConstructorReturn(this, _Button.call(this, player, options));
  15586. _this.on(player, 'play', _this.handlePlay);
  15587. _this.on(player, 'pause', _this.handlePause);
  15588. return _this;
  15589. }
  15590. /**
  15591. * Builds the default DOM `className`.
  15592. *
  15593. * @return {string}
  15594. * The DOM `className` for this object.
  15595. */
  15596. PlayToggle.prototype.buildCSSClass = function buildCSSClass() {
  15597. return 'vjs-play-control ' + _Button.prototype.buildCSSClass.call(this);
  15598. };
  15599. /**
  15600. * This gets called when an `PlayToggle` is "clicked". See
  15601. * {@link ClickableComponent} for more detailed information on what a click can be.
  15602. *
  15603. * @param {EventTarget~Event} [event]
  15604. * The `keydown`, `tap`, or `click` event that caused this function to be
  15605. * called.
  15606. *
  15607. * @listens tap
  15608. * @listens click
  15609. */
  15610. PlayToggle.prototype.handleClick = function handleClick(event) {
  15611. if (this.player_.paused()) {
  15612. this.player_.play();
  15613. } else {
  15614. this.player_.pause();
  15615. }
  15616. };
  15617. /**
  15618. * Add the vjs-playing class to the element so it can change appearance.
  15619. *
  15620. * @param {EventTarget~Event} [event]
  15621. * The event that caused this function to run.
  15622. *
  15623. * @listens Player#play
  15624. */
  15625. PlayToggle.prototype.handlePlay = function handlePlay(event) {
  15626. this.removeClass('vjs-paused');
  15627. this.addClass('vjs-playing');
  15628. // change the button text to "Pause"
  15629. this.controlText('Pause');
  15630. };
  15631. /**
  15632. * Add the vjs-paused class to the element so it can change appearance.
  15633. *
  15634. * @param {EventTarget~Event} [event]
  15635. * The event that caused this function to run.
  15636. *
  15637. * @listens Player#pause
  15638. */
  15639. PlayToggle.prototype.handlePause = function handlePause(event) {
  15640. this.removeClass('vjs-playing');
  15641. this.addClass('vjs-paused');
  15642. // change the button text to "Play"
  15643. this.controlText('Play');
  15644. };
  15645. return PlayToggle;
  15646. }(_button2['default']);
  15647. /**
  15648. * The text that should display over the `PlayToggle`s controls. Added for localization.
  15649. *
  15650. * @type {string}
  15651. * @private
  15652. */
  15653. PlayToggle.prototype.controlText_ = 'Play';
  15654. _component2['default'].registerComponent('PlayToggle', PlayToggle);
  15655. exports['default'] = PlayToggle;
  15656. /***/ }),
  15657. /* 66 */
  15658. /***/ (function(module, exports, __webpack_require__) {
  15659. 'use strict';
  15660. exports.__esModule = true;
  15661. var _component = __webpack_require__(19);
  15662. var _component2 = _interopRequireDefault(_component);
  15663. var _dom = __webpack_require__(11);
  15664. var Dom = _interopRequireWildcard(_dom);
  15665. var _formatTime = __webpack_require__(67);
  15666. var _formatTime2 = _interopRequireDefault(_formatTime);
  15667. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  15668. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  15669. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  15670. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  15671. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  15672. * @file current-time-display.js
  15673. */
  15674. /**
  15675. * Displays the current time
  15676. *
  15677. * @extends Component
  15678. */
  15679. var CurrentTimeDisplay = function (_Component) {
  15680. _inherits(CurrentTimeDisplay, _Component);
  15681. /**
  15682. * Creates an instance of this class.
  15683. *
  15684. * @param {Player} player
  15685. * The `Player` that this class should be attached to.
  15686. *
  15687. * @param {Object} [options]
  15688. * The key/value store of player options.
  15689. */
  15690. function CurrentTimeDisplay(player, options) {
  15691. _classCallCheck(this, CurrentTimeDisplay);
  15692. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
  15693. _this.on(player, 'timeupdate', _this.updateContent);
  15694. return _this;
  15695. }
  15696. /**
  15697. * Create the `Component`'s DOM element
  15698. *
  15699. * @return {Element}
  15700. * The element that was created.
  15701. */
  15702. CurrentTimeDisplay.prototype.createEl = function createEl() {
  15703. var el = _Component.prototype.createEl.call(this, 'div', {
  15704. className: 'vjs-current-time vjs-time-control vjs-control'
  15705. });
  15706. this.contentEl_ = Dom.createEl('div', {
  15707. className: 'vjs-current-time-display',
  15708. // label the current time for screen reader users
  15709. innerHTML: '<span class="vjs-control-text">Current Time </span>' + '0:00'
  15710. }, {
  15711. // tell screen readers not to automatically read the time as it changes
  15712. 'aria-live': 'off'
  15713. });
  15714. el.appendChild(this.contentEl_);
  15715. return el;
  15716. };
  15717. /**
  15718. * Update current time display
  15719. *
  15720. * @param {EventTarget~Event} [event]
  15721. * The `timeupdate` event that caused this function to run.
  15722. *
  15723. * @listens Player#timeupdate
  15724. */
  15725. CurrentTimeDisplay.prototype.updateContent = function updateContent(event) {
  15726. // Allows for smooth scrubbing, when player can't keep up.
  15727. var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
  15728. var localizedText = this.localize('Current Time');
  15729. var formattedTime = (0, _formatTime2['default'])(time, this.player_.duration());
  15730. if (formattedTime !== this.formattedTime_) {
  15731. this.formattedTime_ = formattedTime;
  15732. this.contentEl_.innerHTML = '<span class="vjs-control-text">' + localizedText + '</span> ' + formattedTime;
  15733. }
  15734. };
  15735. return CurrentTimeDisplay;
  15736. }(_component2['default']);
  15737. _component2['default'].registerComponent('CurrentTimeDisplay', CurrentTimeDisplay);
  15738. exports['default'] = CurrentTimeDisplay;
  15739. /***/ }),
  15740. /* 67 */
  15741. /***/ (function(module, exports) {
  15742. 'use strict';
  15743. exports.__esModule = true;
  15744. /**
  15745. * @file format-time.js
  15746. * @module Format-time
  15747. */
  15748. /**
  15749. * Format seconds as a time string, H:MM:SS or M:SS. Supplying a guide (in seconds)
  15750. * will force a number of leading zeros to cover the length of the guide.
  15751. *
  15752. * @param {number} seconds
  15753. * Number of seconds to be turned into a string
  15754. *
  15755. * @param {number} guide
  15756. * Number (in seconds) to model the string after
  15757. *
  15758. * @return {string}
  15759. * Time formatted as H:MM:SS or M:SS
  15760. */
  15761. function formatTime(seconds) {
  15762. var guide = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : seconds;
  15763. seconds = seconds < 0 ? 0 : seconds;
  15764. var s = Math.floor(seconds % 60);
  15765. var m = Math.floor(seconds / 60 % 60);
  15766. var h = Math.floor(seconds / 3600);
  15767. var gm = Math.floor(guide / 60 % 60);
  15768. var gh = Math.floor(guide / 3600);
  15769. // handle invalid times
  15770. if (isNaN(seconds) || seconds === Infinity) {
  15771. // '-' is false for all relational operators (e.g. <, >=) so this setting
  15772. // will add the minimum number of fields specified by the guide
  15773. h = m = s = '-';
  15774. }
  15775. // Check if we need to show hours
  15776. h = h > 0 || gh > 0 ? h + ':' : '';
  15777. // If hours are showing, we may need to add a leading zero.
  15778. // Always show at least one digit of minutes.
  15779. m = ((h || gm >= 10) && m < 10 ? '0' + m : m) + ':';
  15780. // Check if leading zero is need for seconds
  15781. s = s < 10 ? '0' + s : s;
  15782. return h + m + s;
  15783. }
  15784. exports['default'] = formatTime;
  15785. /***/ }),
  15786. /* 68 */
  15787. /***/ (function(module, exports, __webpack_require__) {
  15788. 'use strict';
  15789. exports.__esModule = true;
  15790. var _component = __webpack_require__(19);
  15791. var _component2 = _interopRequireDefault(_component);
  15792. var _dom = __webpack_require__(11);
  15793. var Dom = _interopRequireWildcard(_dom);
  15794. var _formatTime = __webpack_require__(67);
  15795. var _formatTime2 = _interopRequireDefault(_formatTime);
  15796. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  15797. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  15798. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  15799. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  15800. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  15801. * @file duration-display.js
  15802. */
  15803. /**
  15804. * Displays the duration
  15805. *
  15806. * @extends Component
  15807. */
  15808. var DurationDisplay = function (_Component) {
  15809. _inherits(DurationDisplay, _Component);
  15810. /**
  15811. * Creates an instance of this class.
  15812. *
  15813. * @param {Player} player
  15814. * The `Player` that this class should be attached to.
  15815. *
  15816. * @param {Object} [options]
  15817. * The key/value store of player options.
  15818. */
  15819. function DurationDisplay(player, options) {
  15820. _classCallCheck(this, DurationDisplay);
  15821. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
  15822. _this.on(player, 'durationchange', _this.updateContent);
  15823. // Also listen for timeupdate and loadedmetadata because removing those
  15824. // listeners could have broken dependent applications/libraries. These
  15825. // can likely be removed for 6.0.
  15826. _this.on(player, 'timeupdate', _this.updateContent);
  15827. _this.on(player, 'loadedmetadata', _this.updateContent);
  15828. return _this;
  15829. }
  15830. /**
  15831. * Create the `Component`'s DOM element
  15832. *
  15833. * @return {Element}
  15834. * The element that was created.
  15835. */
  15836. DurationDisplay.prototype.createEl = function createEl() {
  15837. var el = _Component.prototype.createEl.call(this, 'div', {
  15838. className: 'vjs-duration vjs-time-control vjs-control'
  15839. });
  15840. this.contentEl_ = Dom.createEl('div', {
  15841. className: 'vjs-duration-display',
  15842. // label the duration time for screen reader users
  15843. innerHTML: '<span class="vjs-control-text">' + this.localize('Duration Time') + '</span> 0:00'
  15844. }, {
  15845. // tell screen readers not to automatically read the time as it changes
  15846. 'aria-live': 'off'
  15847. });
  15848. el.appendChild(this.contentEl_);
  15849. return el;
  15850. };
  15851. /**
  15852. * Update duration time display.
  15853. *
  15854. * @param {EventTarget~Event} [event]
  15855. * The `durationchange`, `timeupdate`, or `loadedmetadata` event that caused
  15856. * this function to be called.
  15857. *
  15858. * @listens Player#durationchange
  15859. * @listens Player#timeupdate
  15860. * @listens Player#loadedmetadata
  15861. */
  15862. DurationDisplay.prototype.updateContent = function updateContent(event) {
  15863. var duration = this.player_.duration();
  15864. if (duration && this.duration_ !== duration) {
  15865. this.duration_ = duration;
  15866. var localizedText = this.localize('Duration Time');
  15867. var formattedTime = (0, _formatTime2['default'])(duration);
  15868. // label the duration time for screen reader users
  15869. this.contentEl_.innerHTML = '<span class="vjs-control-text">' + localizedText + '</span> ' + formattedTime;
  15870. }
  15871. };
  15872. return DurationDisplay;
  15873. }(_component2['default']);
  15874. _component2['default'].registerComponent('DurationDisplay', DurationDisplay);
  15875. exports['default'] = DurationDisplay;
  15876. /***/ }),
  15877. /* 69 */
  15878. /***/ (function(module, exports, __webpack_require__) {
  15879. 'use strict';
  15880. exports.__esModule = true;
  15881. var _component = __webpack_require__(19);
  15882. var _component2 = _interopRequireDefault(_component);
  15883. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  15884. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  15885. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  15886. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  15887. * @file time-divider.js
  15888. */
  15889. /**
  15890. * The separator between the current time and duration.
  15891. * Can be hidden if it's not needed in the design.
  15892. *
  15893. * @extends Component
  15894. */
  15895. var TimeDivider = function (_Component) {
  15896. _inherits(TimeDivider, _Component);
  15897. function TimeDivider() {
  15898. _classCallCheck(this, TimeDivider);
  15899. return _possibleConstructorReturn(this, _Component.apply(this, arguments));
  15900. }
  15901. /**
  15902. * Create the component's DOM element
  15903. *
  15904. * @return {Element}
  15905. * The element that was created.
  15906. */
  15907. TimeDivider.prototype.createEl = function createEl() {
  15908. return _Component.prototype.createEl.call(this, 'div', {
  15909. className: 'vjs-time-control vjs-time-divider',
  15910. innerHTML: '<div><span>/</span></div>'
  15911. });
  15912. };
  15913. return TimeDivider;
  15914. }(_component2['default']);
  15915. _component2['default'].registerComponent('TimeDivider', TimeDivider);
  15916. exports['default'] = TimeDivider;
  15917. /***/ }),
  15918. /* 70 */
  15919. /***/ (function(module, exports, __webpack_require__) {
  15920. 'use strict';
  15921. exports.__esModule = true;
  15922. var _component = __webpack_require__(19);
  15923. var _component2 = _interopRequireDefault(_component);
  15924. var _dom = __webpack_require__(11);
  15925. var Dom = _interopRequireWildcard(_dom);
  15926. var _formatTime = __webpack_require__(67);
  15927. var _formatTime2 = _interopRequireDefault(_formatTime);
  15928. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  15929. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  15930. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  15931. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  15932. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  15933. * @file remaining-time-display.js
  15934. */
  15935. /**
  15936. * Displays the time left in the video
  15937. *
  15938. * @extends Component
  15939. */
  15940. var RemainingTimeDisplay = function (_Component) {
  15941. _inherits(RemainingTimeDisplay, _Component);
  15942. /**
  15943. * Creates an instance of this class.
  15944. *
  15945. * @param {Player} player
  15946. * The `Player` that this class should be attached to.
  15947. *
  15948. * @param {Object} [options]
  15949. * The key/value store of player options.
  15950. */
  15951. function RemainingTimeDisplay(player, options) {
  15952. _classCallCheck(this, RemainingTimeDisplay);
  15953. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
  15954. _this.on(player, 'timeupdate', _this.updateContent);
  15955. _this.on(player, 'durationchange', _this.updateContent);
  15956. return _this;
  15957. }
  15958. /**
  15959. * Create the `Component`'s DOM element
  15960. *
  15961. * @return {Element}
  15962. * The element that was created.
  15963. */
  15964. RemainingTimeDisplay.prototype.createEl = function createEl() {
  15965. var el = _Component.prototype.createEl.call(this, 'div', {
  15966. className: 'vjs-remaining-time vjs-time-control vjs-control'
  15967. });
  15968. this.contentEl_ = Dom.createEl('div', {
  15969. className: 'vjs-remaining-time-display',
  15970. // label the remaining time for screen reader users
  15971. innerHTML: '<span class="vjs-control-text">' + this.localize('Remaining Time') + '</span> -0:00'
  15972. }, {
  15973. // tell screen readers not to automatically read the time as it changes
  15974. 'aria-live': 'off'
  15975. });
  15976. el.appendChild(this.contentEl_);
  15977. return el;
  15978. };
  15979. /**
  15980. * Update remaining time display.
  15981. *
  15982. * @param {EventTarget~Event} [event]
  15983. * The `timeupdate` or `durationchange` event that caused this to run.
  15984. *
  15985. * @listens Player#timeupdate
  15986. * @listens Player#durationchange
  15987. */
  15988. RemainingTimeDisplay.prototype.updateContent = function updateContent(event) {
  15989. if (this.player_.duration()) {
  15990. var localizedText = this.localize('Remaining Time');
  15991. var formattedTime = (0, _formatTime2['default'])(this.player_.remainingTime());
  15992. if (formattedTime !== this.formattedTime_) {
  15993. this.formattedTime_ = formattedTime;
  15994. this.contentEl_.innerHTML = '<span class="vjs-control-text">' + localizedText + '</span> -' + formattedTime;
  15995. }
  15996. }
  15997. // Allows for smooth scrubbing, when player can't keep up.
  15998. // var time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
  15999. // this.contentEl_.innerHTML = vjs.formatTime(time, this.player_.duration());
  16000. };
  16001. return RemainingTimeDisplay;
  16002. }(_component2['default']);
  16003. _component2['default'].registerComponent('RemainingTimeDisplay', RemainingTimeDisplay);
  16004. exports['default'] = RemainingTimeDisplay;
  16005. /***/ }),
  16006. /* 71 */
  16007. /***/ (function(module, exports, __webpack_require__) {
  16008. 'use strict';
  16009. exports.__esModule = true;
  16010. var _component = __webpack_require__(19);
  16011. var _component2 = _interopRequireDefault(_component);
  16012. var _dom = __webpack_require__(11);
  16013. var Dom = _interopRequireWildcard(_dom);
  16014. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  16015. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  16016. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  16017. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  16018. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  16019. * @file live-display.js
  16020. */
  16021. // TODO - Future make it click to snap to live
  16022. /**
  16023. * Displays the live indicator when duration is Infinity.
  16024. *
  16025. * @extends Component
  16026. */
  16027. var LiveDisplay = function (_Component) {
  16028. _inherits(LiveDisplay, _Component);
  16029. /**
  16030. * Creates an instance of this class.
  16031. *
  16032. * @param {Player} player
  16033. * The `Player` that this class should be attached to.
  16034. *
  16035. * @param {Object} [options]
  16036. * The key/value store of player options.
  16037. */
  16038. function LiveDisplay(player, options) {
  16039. _classCallCheck(this, LiveDisplay);
  16040. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
  16041. _this.updateShowing();
  16042. _this.on(_this.player(), 'durationchange', _this.updateShowing);
  16043. return _this;
  16044. }
  16045. /**
  16046. * Create the `Component`'s DOM element
  16047. *
  16048. * @return {Element}
  16049. * The element that was created.
  16050. */
  16051. LiveDisplay.prototype.createEl = function createEl() {
  16052. var el = _Component.prototype.createEl.call(this, 'div', {
  16053. className: 'vjs-live-control vjs-control'
  16054. });
  16055. this.contentEl_ = Dom.createEl('div', {
  16056. className: 'vjs-live-display',
  16057. innerHTML: '<span class="vjs-control-text">' + this.localize('Stream Type') + '</span>' + this.localize('LIVE')
  16058. }, {
  16059. 'aria-live': 'off'
  16060. });
  16061. el.appendChild(this.contentEl_);
  16062. return el;
  16063. };
  16064. /**
  16065. * Check the duration to see if the LiveDisplay should be showing or not. Then show/hide
  16066. * it accordingly
  16067. *
  16068. * @param {EventTarget~Event} [event]
  16069. * The {@link Player#durationchange} event that caused this function to run.
  16070. *
  16071. * @listens Player#durationchange
  16072. */
  16073. LiveDisplay.prototype.updateShowing = function updateShowing(event) {
  16074. if (this.player().duration() === Infinity) {
  16075. this.show();
  16076. } else {
  16077. this.hide();
  16078. }
  16079. };
  16080. return LiveDisplay;
  16081. }(_component2['default']);
  16082. _component2['default'].registerComponent('LiveDisplay', LiveDisplay);
  16083. exports['default'] = LiveDisplay;
  16084. /***/ }),
  16085. /* 72 */
  16086. /***/ (function(module, exports, __webpack_require__) {
  16087. 'use strict';
  16088. exports.__esModule = true;
  16089. var _component = __webpack_require__(19);
  16090. var _component2 = _interopRequireDefault(_component);
  16091. __webpack_require__(73);
  16092. __webpack_require__(79);
  16093. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  16094. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  16095. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  16096. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  16097. * @file progress-control.js
  16098. */
  16099. /**
  16100. * The Progress Control component contains the seek bar, load progress,
  16101. * and play progress.
  16102. *
  16103. * @extends Component
  16104. */
  16105. var ProgressControl = function (_Component) {
  16106. _inherits(ProgressControl, _Component);
  16107. function ProgressControl() {
  16108. _classCallCheck(this, ProgressControl);
  16109. return _possibleConstructorReturn(this, _Component.apply(this, arguments));
  16110. }
  16111. /**
  16112. * Create the `Component`'s DOM element
  16113. *
  16114. * @return {Element}
  16115. * The element that was created.
  16116. */
  16117. ProgressControl.prototype.createEl = function createEl() {
  16118. return _Component.prototype.createEl.call(this, 'div', {
  16119. className: 'vjs-progress-control vjs-control'
  16120. });
  16121. };
  16122. return ProgressControl;
  16123. }(_component2['default']);
  16124. /**
  16125. * Default options for `ProgressControl`
  16126. *
  16127. * @type {Object}
  16128. * @private
  16129. */
  16130. ProgressControl.prototype.options_ = {
  16131. children: ['seekBar']
  16132. };
  16133. _component2['default'].registerComponent('ProgressControl', ProgressControl);
  16134. exports['default'] = ProgressControl;
  16135. /***/ }),
  16136. /* 73 */
  16137. /***/ (function(module, exports, __webpack_require__) {
  16138. 'use strict';
  16139. exports.__esModule = true;
  16140. var _slider = __webpack_require__(74);
  16141. var _slider2 = _interopRequireDefault(_slider);
  16142. var _component = __webpack_require__(19);
  16143. var _component2 = _interopRequireDefault(_component);
  16144. var _fn = __webpack_require__(20);
  16145. var Fn = _interopRequireWildcard(_fn);
  16146. var _formatTime = __webpack_require__(67);
  16147. var _formatTime2 = _interopRequireDefault(_formatTime);
  16148. var _computedStyle = __webpack_require__(75);
  16149. var _computedStyle2 = _interopRequireDefault(_computedStyle);
  16150. __webpack_require__(76);
  16151. __webpack_require__(77);
  16152. __webpack_require__(78);
  16153. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  16154. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  16155. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  16156. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  16157. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  16158. * @file seek-bar.js
  16159. */
  16160. /**
  16161. * Seek Bar and holder for the progress bars
  16162. *
  16163. * @extends Slider
  16164. */
  16165. var SeekBar = function (_Slider) {
  16166. _inherits(SeekBar, _Slider);
  16167. /**
  16168. * Creates an instance of this class.
  16169. *
  16170. * @param {Player} player
  16171. * The `Player` that this class should be attached to.
  16172. *
  16173. * @param {Object} [options]
  16174. * The key/value store of player options.
  16175. */
  16176. function SeekBar(player, options) {
  16177. _classCallCheck(this, SeekBar);
  16178. var _this = _possibleConstructorReturn(this, _Slider.call(this, player, options));
  16179. _this.on(player, 'timeupdate', _this.updateProgress);
  16180. _this.on(player, 'ended', _this.updateProgress);
  16181. player.ready(Fn.bind(_this, _this.updateProgress));
  16182. if (options.playerOptions && options.playerOptions.controlBar && options.playerOptions.controlBar.progressControl && options.playerOptions.controlBar.progressControl.keepTooltipsInside) {
  16183. _this.keepTooltipsInside = options.playerOptions.controlBar.progressControl.keepTooltipsInside;
  16184. }
  16185. if (_this.keepTooltipsInside) {
  16186. _this.tooltipProgressBar = _this.addChild('TooltipProgressBar');
  16187. }
  16188. return _this;
  16189. }
  16190. /**
  16191. * Create the `Component`'s DOM element
  16192. *
  16193. * @return {Element}
  16194. * The element that was created.
  16195. */
  16196. SeekBar.prototype.createEl = function createEl() {
  16197. return _Slider.prototype.createEl.call(this, 'div', {
  16198. className: 'vjs-progress-holder'
  16199. }, {
  16200. 'aria-label': 'progress bar'
  16201. });
  16202. };
  16203. /**
  16204. * Update the seek bars tooltip and width.
  16205. *
  16206. * @param {EventTarget~Event} [event]
  16207. * The `timeupdate` or `ended` event that caused this to run.
  16208. *
  16209. * @listens Player#timeupdate
  16210. * @listens Player#ended
  16211. */
  16212. SeekBar.prototype.updateProgress = function updateProgress(event) {
  16213. this.updateAriaAttributes(this.el_);
  16214. if (this.keepTooltipsInside) {
  16215. this.updateAriaAttributes(this.tooltipProgressBar.el_);
  16216. this.tooltipProgressBar.el_.style.width = this.bar.el_.style.width;
  16217. var playerWidth = parseFloat((0, _computedStyle2['default'])(this.player().el(), 'width'));
  16218. var tooltipWidth = parseFloat((0, _computedStyle2['default'])(this.tooltipProgressBar.tooltip, 'width'));
  16219. var tooltipStyle = this.tooltipProgressBar.el().style;
  16220. tooltipStyle.maxWidth = Math.floor(playerWidth - tooltipWidth / 2) + 'px';
  16221. tooltipStyle.minWidth = Math.ceil(tooltipWidth / 2) + 'px';
  16222. tooltipStyle.right = '-' + tooltipWidth / 2 + 'px';
  16223. }
  16224. };
  16225. /**
  16226. * Update ARIA accessibility attributes
  16227. *
  16228. * @param {Element} el
  16229. * The element to update with aria accessibility attributes.
  16230. */
  16231. SeekBar.prototype.updateAriaAttributes = function updateAriaAttributes(el) {
  16232. // Allows for smooth scrubbing, when player can't keep up.
  16233. var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
  16234. // machine readable value of progress bar (percentage complete)
  16235. el.setAttribute('aria-valuenow', (this.getPercent() * 100).toFixed(2));
  16236. // human readable value of progress bar (time complete)
  16237. el.setAttribute('aria-valuetext', (0, _formatTime2['default'])(time, this.player_.duration()));
  16238. };
  16239. /**
  16240. * Get percentage of video played
  16241. *
  16242. * @return {number}
  16243. * The percentage played
  16244. */
  16245. SeekBar.prototype.getPercent = function getPercent() {
  16246. var percent = this.player_.currentTime() / this.player_.duration();
  16247. return percent >= 1 ? 1 : percent;
  16248. };
  16249. /**
  16250. * Handle mouse down on seek bar
  16251. *
  16252. * @param {EventTarget~Event} event
  16253. * The `mousedown` event that caused this to run.
  16254. *
  16255. * @listens mousedown
  16256. */
  16257. SeekBar.prototype.handleMouseDown = function handleMouseDown(event) {
  16258. this.player_.scrubbing(true);
  16259. this.videoWasPlaying = !this.player_.paused();
  16260. this.player_.pause();
  16261. _Slider.prototype.handleMouseDown.call(this, event);
  16262. };
  16263. /**
  16264. * Handle mouse move on seek bar
  16265. *
  16266. * @param {EventTarget~Event} event
  16267. * The `mousemove` event that caused this to run.
  16268. *
  16269. * @listens mousemove
  16270. */
  16271. SeekBar.prototype.handleMouseMove = function handleMouseMove(event) {
  16272. var newTime = this.calculateDistance(event) * this.player_.duration();
  16273. // Don't let video end while scrubbing.
  16274. if (newTime === this.player_.duration()) {
  16275. newTime = newTime - 0.1;
  16276. }
  16277. // Set new time (tell player to seek to new time)
  16278. this.player_.currentTime(newTime);
  16279. };
  16280. /**
  16281. * Handle mouse up on seek bar
  16282. *
  16283. * @param {EventTarget~Event} event
  16284. * The `mouseup` event that caused this to run.
  16285. *
  16286. * @listens mouseup
  16287. */
  16288. SeekBar.prototype.handleMouseUp = function handleMouseUp(event) {
  16289. _Slider.prototype.handleMouseUp.call(this, event);
  16290. this.player_.scrubbing(false);
  16291. if (this.videoWasPlaying) {
  16292. this.player_.play();
  16293. }
  16294. };
  16295. /**
  16296. * Move more quickly fast forward for keyboard-only users
  16297. */
  16298. SeekBar.prototype.stepForward = function stepForward() {
  16299. // more quickly fast forward for keyboard-only users
  16300. this.player_.currentTime(this.player_.currentTime() + 5);
  16301. };
  16302. /**
  16303. * Move more quickly rewind for keyboard-only users
  16304. */
  16305. SeekBar.prototype.stepBack = function stepBack() {
  16306. // more quickly rewind for keyboard-only users
  16307. this.player_.currentTime(this.player_.currentTime() - 5);
  16308. };
  16309. return SeekBar;
  16310. }(_slider2['default']);
  16311. /**
  16312. * Default options for the `SeekBar`
  16313. *
  16314. * @type {Object}
  16315. * @private
  16316. */
  16317. SeekBar.prototype.options_ = {
  16318. children: ['loadProgressBar', 'mouseTimeDisplay', 'playProgressBar'],
  16319. barName: 'playProgressBar'
  16320. };
  16321. /**
  16322. * Call the update event for this Slider when this event happens on the player.
  16323. *
  16324. * @type {string}
  16325. */
  16326. SeekBar.prototype.playerEvent = 'timeupdate';
  16327. _component2['default'].registerComponent('SeekBar', SeekBar);
  16328. exports['default'] = SeekBar;
  16329. /***/ }),
  16330. /* 74 */
  16331. /***/ (function(module, exports, __webpack_require__) {
  16332. 'use strict';
  16333. exports.__esModule = true;
  16334. var _component = __webpack_require__(19);
  16335. var _component2 = _interopRequireDefault(_component);
  16336. var _dom = __webpack_require__(11);
  16337. var Dom = _interopRequireWildcard(_dom);
  16338. var _obj = __webpack_require__(14);
  16339. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  16340. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  16341. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  16342. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  16343. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  16344. * @file slider.js
  16345. */
  16346. /**
  16347. * The base functionality for a slider. Can be vertical or horizontal.
  16348. * For instance the volume bar or the seek bar on a video is a slider.
  16349. *
  16350. * @extends Component
  16351. */
  16352. var Slider = function (_Component) {
  16353. _inherits(Slider, _Component);
  16354. /**
  16355. * Create an instance of this class
  16356. *
  16357. * @param {Player} player
  16358. * The `Player` that this class should be attached to.
  16359. *
  16360. * @param {Object} [options]
  16361. * The key/value store of player options.
  16362. */
  16363. function Slider(player, options) {
  16364. _classCallCheck(this, Slider);
  16365. // Set property names to bar to match with the child Slider class is looking for
  16366. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
  16367. _this.bar = _this.getChild(_this.options_.barName);
  16368. // Set a horizontal or vertical class on the slider depending on the slider type
  16369. _this.vertical(!!_this.options_.vertical);
  16370. _this.on('mousedown', _this.handleMouseDown);
  16371. _this.on('touchstart', _this.handleMouseDown);
  16372. _this.on('focus', _this.handleFocus);
  16373. _this.on('blur', _this.handleBlur);
  16374. _this.on('click', _this.handleClick);
  16375. _this.on(player, 'controlsvisible', _this.update);
  16376. _this.on(player, _this.playerEvent, _this.update);
  16377. return _this;
  16378. }
  16379. /**
  16380. * Create the `Button`s DOM element.
  16381. *
  16382. * @param {string} type
  16383. * Type of element to create.
  16384. *
  16385. * @param {Object} [props={}]
  16386. * List of properties in Object form.
  16387. *
  16388. * @param {Object} [attributes={}]
  16389. * list of attributes in Object form.
  16390. *
  16391. * @return {Element}
  16392. * The element that gets created.
  16393. */
  16394. Slider.prototype.createEl = function createEl(type) {
  16395. var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  16396. var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  16397. // Add the slider element class to all sub classes
  16398. props.className = props.className + ' vjs-slider';
  16399. props = (0, _obj.assign)({
  16400. tabIndex: 0
  16401. }, props);
  16402. attributes = (0, _obj.assign)({
  16403. 'role': 'slider',
  16404. 'aria-valuenow': 0,
  16405. 'aria-valuemin': 0,
  16406. 'aria-valuemax': 100,
  16407. 'tabIndex': 0
  16408. }, attributes);
  16409. return _Component.prototype.createEl.call(this, type, props, attributes);
  16410. };
  16411. /**
  16412. * Handle `mousedown` or `touchstart` events on the `Slider`.
  16413. *
  16414. * @param {EventTarget~Event} event
  16415. * `mousedown` or `touchstart` event that triggered this function
  16416. *
  16417. * @listens mousedown
  16418. * @listens touchstart
  16419. * @fires Slider#slideractive
  16420. */
  16421. Slider.prototype.handleMouseDown = function handleMouseDown(event) {
  16422. var doc = this.bar.el_.ownerDocument;
  16423. event.preventDefault();
  16424. Dom.blockTextSelection();
  16425. this.addClass('vjs-sliding');
  16426. /**
  16427. * Triggered when the slider is in an active state
  16428. *
  16429. * @event Slider#slideractive
  16430. * @type {EventTarget~Event}
  16431. */
  16432. this.trigger('slideractive');
  16433. this.on(doc, 'mousemove', this.handleMouseMove);
  16434. this.on(doc, 'mouseup', this.handleMouseUp);
  16435. this.on(doc, 'touchmove', this.handleMouseMove);
  16436. this.on(doc, 'touchend', this.handleMouseUp);
  16437. this.handleMouseMove(event);
  16438. };
  16439. /**
  16440. * Handle the `mousemove`, `touchmove`, and `mousedown` events on this `Slider`.
  16441. * The `mousemove` and `touchmove` events will only only trigger this function during
  16442. * `mousedown` and `touchstart`. This is due to {@link Slider#handleMouseDown} and
  16443. * {@link Slider#handleMouseUp}.
  16444. *
  16445. * @param {EventTarget~Event} event
  16446. * `mousedown`, `mousemove`, `touchstart`, or `touchmove` event that triggered
  16447. * this function
  16448. *
  16449. * @listens mousemove
  16450. * @listens touchmove
  16451. */
  16452. Slider.prototype.handleMouseMove = function handleMouseMove(event) {};
  16453. /**
  16454. * Handle `mouseup` or `touchend` events on the `Slider`.
  16455. *
  16456. * @param {EventTarget~Event} event
  16457. * `mouseup` or `touchend` event that triggered this function.
  16458. *
  16459. * @listens touchend
  16460. * @listens mouseup
  16461. * @fires Slider#sliderinactive
  16462. */
  16463. Slider.prototype.handleMouseUp = function handleMouseUp() {
  16464. var doc = this.bar.el_.ownerDocument;
  16465. Dom.unblockTextSelection();
  16466. this.removeClass('vjs-sliding');
  16467. /**
  16468. * Triggered when the slider is no longer in an active state.
  16469. *
  16470. * @event Slider#sliderinactive
  16471. * @type {EventTarget~Event}
  16472. */
  16473. this.trigger('sliderinactive');
  16474. this.off(doc, 'mousemove', this.handleMouseMove);
  16475. this.off(doc, 'mouseup', this.handleMouseUp);
  16476. this.off(doc, 'touchmove', this.handleMouseMove);
  16477. this.off(doc, 'touchend', this.handleMouseUp);
  16478. this.update();
  16479. };
  16480. /**
  16481. * Update the progress bar of the `Slider`.
  16482. */
  16483. Slider.prototype.update = function update() {
  16484. // In VolumeBar init we have a setTimeout for update that pops and update to the end of the
  16485. // execution stack. The player is destroyed before then update will cause an error
  16486. if (!this.el_) {
  16487. return;
  16488. }
  16489. // If scrubbing, we could use a cached value to make the handle keep up with the user's mouse.
  16490. // On HTML5 browsers scrubbing is really smooth, but some flash players are slow, so we might want to utilize this later.
  16491. // var progress = (this.player_.scrubbing()) ? this.player_.getCache().currentTime / this.player_.duration() : this.player_.currentTime() / this.player_.duration();
  16492. var progress = this.getPercent();
  16493. var bar = this.bar;
  16494. // If there's no bar...
  16495. if (!bar) {
  16496. return;
  16497. }
  16498. // Protect against no duration and other division issues
  16499. if (typeof progress !== 'number' || progress !== progress || progress < 0 || progress === Infinity) {
  16500. progress = 0;
  16501. }
  16502. // Convert to a percentage for setting
  16503. var percentage = (progress * 100).toFixed(2) + '%';
  16504. // Set the new bar width or height
  16505. if (this.vertical()) {
  16506. bar.el().style.height = percentage;
  16507. } else {
  16508. bar.el().style.width = percentage;
  16509. }
  16510. };
  16511. /**
  16512. * Calculate distance for slider
  16513. *
  16514. * @param {EventTarget~Event} event
  16515. * The event that caused this function to run.
  16516. *
  16517. * @return {number}
  16518. * The current position of the Slider.
  16519. * - postition.x for vertical `Slider`s
  16520. * - postition.y for horizontal `Slider`s
  16521. */
  16522. Slider.prototype.calculateDistance = function calculateDistance(event) {
  16523. var position = Dom.getPointerPosition(this.el_, event);
  16524. if (this.vertical()) {
  16525. return position.y;
  16526. }
  16527. return position.x;
  16528. };
  16529. /**
  16530. * Handle a `focus` event on this `Slider`.
  16531. *
  16532. * @param {EventTarget~Event} event
  16533. * The `focus` event that caused this function to run.
  16534. *
  16535. * @listens focus
  16536. */
  16537. Slider.prototype.handleFocus = function handleFocus() {
  16538. this.on(this.bar.el_.ownerDocument, 'keydown', this.handleKeyPress);
  16539. };
  16540. /**
  16541. * Handle a `keydown` event on the `Slider`. Watches for left, rigth, up, and down
  16542. * arrow keys. This function will only be called when the slider has focus. See
  16543. * {@link Slider#handleFocus} and {@link Slider#handleBlur}.
  16544. *
  16545. * @param {EventTarget~Event} event
  16546. * the `keydown` event that caused this function to run.
  16547. *
  16548. * @listens keydown
  16549. */
  16550. Slider.prototype.handleKeyPress = function handleKeyPress(event) {
  16551. // Left and Down Arrows
  16552. if (event.which === 37 || event.which === 40) {
  16553. event.preventDefault();
  16554. this.stepBack();
  16555. // Up and Right Arrows
  16556. } else if (event.which === 38 || event.which === 39) {
  16557. event.preventDefault();
  16558. this.stepForward();
  16559. }
  16560. };
  16561. /**
  16562. * Handle a `blur` event on this `Slider`.
  16563. *
  16564. * @param {EventTarget~Event} event
  16565. * The `blur` event that caused this function to run.
  16566. *
  16567. * @listens blur
  16568. */
  16569. Slider.prototype.handleBlur = function handleBlur() {
  16570. this.off(this.bar.el_.ownerDocument, 'keydown', this.handleKeyPress);
  16571. };
  16572. /**
  16573. * Listener for click events on slider, used to prevent clicks
  16574. * from bubbling up to parent elements like button menus.
  16575. *
  16576. * @param {Object} event
  16577. * Event that caused this object to run
  16578. */
  16579. Slider.prototype.handleClick = function handleClick(event) {
  16580. event.stopImmediatePropagation();
  16581. event.preventDefault();
  16582. };
  16583. /**
  16584. * Get/set if slider is horizontal for vertical
  16585. *
  16586. * @param {boolean} [bool]
  16587. * - true if slider is vertical,
  16588. * - false is horizontal
  16589. *
  16590. * @return {boolean|Slider}
  16591. * - true if slider is vertical, and getting
  16592. * - false is horizontal, and getting
  16593. * - a reference to this object when setting
  16594. */
  16595. Slider.prototype.vertical = function vertical(bool) {
  16596. if (bool === undefined) {
  16597. return this.vertical_ || false;
  16598. }
  16599. this.vertical_ = !!bool;
  16600. if (this.vertical_) {
  16601. this.addClass('vjs-slider-vertical');
  16602. } else {
  16603. this.addClass('vjs-slider-horizontal');
  16604. }
  16605. return this;
  16606. };
  16607. return Slider;
  16608. }(_component2['default']);
  16609. _component2['default'].registerComponent('Slider', Slider);
  16610. exports['default'] = Slider;
  16611. /***/ }),
  16612. /* 75 */
  16613. /***/ (function(module, exports, __webpack_require__) {
  16614. 'use strict';
  16615. exports.__esModule = true;
  16616. exports['default'] = computedStyle;
  16617. var _window = __webpack_require__(7);
  16618. var _window2 = _interopRequireDefault(_window);
  16619. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  16620. /**
  16621. * A safe getComputedStyle with an IE8 fallback.
  16622. *
  16623. * This is needed because in Firefox, if the player is loaded in an iframe with
  16624. * `display:none`, then `getComputedStyle` returns `null`, so, we do a null-check to
  16625. * make sure that the player doesn't break in these cases.
  16626. *
  16627. * @param {Element} el
  16628. * The element you want the computed style of
  16629. *
  16630. * @param {string} prop
  16631. * The property name you want
  16632. *
  16633. * @see https://bugzilla.mozilla.org/show_bug.cgi?id=548397
  16634. */
  16635. function computedStyle(el, prop) {
  16636. if (!el || !prop) {
  16637. return '';
  16638. }
  16639. if (typeof _window2['default'].getComputedStyle === 'function') {
  16640. var cs = _window2['default'].getComputedStyle(el);
  16641. return cs ? cs[prop] : '';
  16642. }
  16643. return el.currentStyle[prop] || '';
  16644. } /**
  16645. * @file computed-style.js
  16646. * @module computed-style
  16647. */
  16648. /***/ }),
  16649. /* 76 */
  16650. /***/ (function(module, exports, __webpack_require__) {
  16651. 'use strict';
  16652. exports.__esModule = true;
  16653. var _component = __webpack_require__(19);
  16654. var _component2 = _interopRequireDefault(_component);
  16655. var _dom = __webpack_require__(11);
  16656. var Dom = _interopRequireWildcard(_dom);
  16657. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  16658. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  16659. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  16660. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  16661. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  16662. * @file load-progress-bar.js
  16663. */
  16664. /**
  16665. * Shows loading progress
  16666. *
  16667. * @extends Component
  16668. */
  16669. var LoadProgressBar = function (_Component) {
  16670. _inherits(LoadProgressBar, _Component);
  16671. /**
  16672. * Creates an instance of this class.
  16673. *
  16674. * @param {Player} player
  16675. * The `Player` that this class should be attached to.
  16676. *
  16677. * @param {Object} [options]
  16678. * The key/value store of player options.
  16679. */
  16680. function LoadProgressBar(player, options) {
  16681. _classCallCheck(this, LoadProgressBar);
  16682. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
  16683. _this.partEls_ = [];
  16684. _this.on(player, 'progress', _this.update);
  16685. return _this;
  16686. }
  16687. /**
  16688. * Create the `Component`'s DOM element
  16689. *
  16690. * @return {Element}
  16691. * The element that was created.
  16692. */
  16693. LoadProgressBar.prototype.createEl = function createEl() {
  16694. return _Component.prototype.createEl.call(this, 'div', {
  16695. className: 'vjs-load-progress',
  16696. innerHTML: '<span class="vjs-control-text"><span>' + this.localize('Loaded') + '</span>: 0%</span>'
  16697. });
  16698. };
  16699. /**
  16700. * Update progress bar
  16701. *
  16702. * @param {EventTarget~Event} [event]
  16703. * The `progress` event that caused this function to run.
  16704. *
  16705. * @listens Player#progress
  16706. */
  16707. LoadProgressBar.prototype.update = function update(event) {
  16708. var buffered = this.player_.buffered();
  16709. var duration = this.player_.duration();
  16710. var bufferedEnd = this.player_.bufferedEnd();
  16711. var children = this.partEls_;
  16712. // get the percent width of a time compared to the total end
  16713. var percentify = function percentify(time, end) {
  16714. // no NaN
  16715. var percent = time / end || 0;
  16716. return (percent >= 1 ? 1 : percent) * 100 + '%';
  16717. };
  16718. // update the width of the progress bar
  16719. this.el_.style.width = percentify(bufferedEnd, duration);
  16720. // add child elements to represent the individual buffered time ranges
  16721. for (var i = 0; i < buffered.length; i++) {
  16722. var start = buffered.start(i);
  16723. var end = buffered.end(i);
  16724. var part = children[i];
  16725. if (!part) {
  16726. part = this.el_.appendChild(Dom.createEl());
  16727. children[i] = part;
  16728. }
  16729. // set the percent based on the width of the progress bar (bufferedEnd)
  16730. part.style.left = percentify(start, bufferedEnd);
  16731. part.style.width = percentify(end - start, bufferedEnd);
  16732. }
  16733. // remove unused buffered range elements
  16734. for (var _i = children.length; _i > buffered.length; _i--) {
  16735. this.el_.removeChild(children[_i - 1]);
  16736. }
  16737. children.length = buffered.length;
  16738. };
  16739. return LoadProgressBar;
  16740. }(_component2['default']);
  16741. _component2['default'].registerComponent('LoadProgressBar', LoadProgressBar);
  16742. exports['default'] = LoadProgressBar;
  16743. /***/ }),
  16744. /* 77 */
  16745. /***/ (function(module, exports, __webpack_require__) {
  16746. 'use strict';
  16747. exports.__esModule = true;
  16748. var _component = __webpack_require__(19);
  16749. var _component2 = _interopRequireDefault(_component);
  16750. var _fn = __webpack_require__(20);
  16751. var Fn = _interopRequireWildcard(_fn);
  16752. var _formatTime = __webpack_require__(67);
  16753. var _formatTime2 = _interopRequireDefault(_formatTime);
  16754. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  16755. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  16756. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  16757. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  16758. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  16759. * @file play-progress-bar.js
  16760. */
  16761. /**
  16762. * Shows play progress
  16763. *
  16764. * @extends Component
  16765. */
  16766. var PlayProgressBar = function (_Component) {
  16767. _inherits(PlayProgressBar, _Component);
  16768. /**
  16769. * Creates an instance of this class.
  16770. *
  16771. * @param {Player} player
  16772. * The `Player` that this class should be attached to.
  16773. *
  16774. * @param {Object} [options]
  16775. * The key/value store of player options.
  16776. */
  16777. function PlayProgressBar(player, options) {
  16778. _classCallCheck(this, PlayProgressBar);
  16779. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
  16780. _this.updateDataAttr();
  16781. _this.on(player, 'timeupdate', _this.updateDataAttr);
  16782. player.ready(Fn.bind(_this, _this.updateDataAttr));
  16783. if (options.playerOptions && options.playerOptions.controlBar && options.playerOptions.controlBar.progressControl && options.playerOptions.controlBar.progressControl.keepTooltipsInside) {
  16784. _this.keepTooltipsInside = options.playerOptions.controlBar.progressControl.keepTooltipsInside;
  16785. }
  16786. if (_this.keepTooltipsInside) {
  16787. _this.addClass('vjs-keep-tooltips-inside');
  16788. }
  16789. return _this;
  16790. }
  16791. /**
  16792. * Create the `Component`'s DOM element
  16793. *
  16794. * @return {Element}
  16795. * The element that was created.
  16796. */
  16797. PlayProgressBar.prototype.createEl = function createEl() {
  16798. return _Component.prototype.createEl.call(this, 'div', {
  16799. className: 'vjs-play-progress vjs-slider-bar',
  16800. innerHTML: '<span class="vjs-control-text"><span>' + this.localize('Progress') + '</span>: 0%</span>'
  16801. });
  16802. };
  16803. /**
  16804. * Update the data-current-time attribute on the `PlayProgressBar`.
  16805. *
  16806. * @param {EventTarget~Event} [event]
  16807. * The `timeupdate` event that caused this to run.
  16808. *
  16809. * @listens Player#timeupdate
  16810. */
  16811. PlayProgressBar.prototype.updateDataAttr = function updateDataAttr(event) {
  16812. var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
  16813. this.el_.setAttribute('data-current-time', (0, _formatTime2['default'])(time, this.player_.duration()));
  16814. };
  16815. return PlayProgressBar;
  16816. }(_component2['default']);
  16817. _component2['default'].registerComponent('PlayProgressBar', PlayProgressBar);
  16818. exports['default'] = PlayProgressBar;
  16819. /***/ }),
  16820. /* 78 */
  16821. /***/ (function(module, exports, __webpack_require__) {
  16822. 'use strict';
  16823. exports.__esModule = true;
  16824. var _component = __webpack_require__(19);
  16825. var _component2 = _interopRequireDefault(_component);
  16826. var _fn = __webpack_require__(20);
  16827. var Fn = _interopRequireWildcard(_fn);
  16828. var _formatTime = __webpack_require__(67);
  16829. var _formatTime2 = _interopRequireDefault(_formatTime);
  16830. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  16831. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  16832. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  16833. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  16834. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  16835. * @file play-progress-bar.js
  16836. */
  16837. /**
  16838. * Shows play progress
  16839. *
  16840. * @extends Component
  16841. */
  16842. var TooltipProgressBar = function (_Component) {
  16843. _inherits(TooltipProgressBar, _Component);
  16844. /**
  16845. * Creates an instance of this class.
  16846. *
  16847. * @param {Player} player
  16848. * The `Player` that this class should be attached to.
  16849. *
  16850. * @param {Object} [options]
  16851. * The key/value store of player options.
  16852. */
  16853. function TooltipProgressBar(player, options) {
  16854. _classCallCheck(this, TooltipProgressBar);
  16855. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
  16856. _this.updateDataAttr();
  16857. _this.on(player, 'timeupdate', _this.updateDataAttr);
  16858. player.ready(Fn.bind(_this, _this.updateDataAttr));
  16859. return _this;
  16860. }
  16861. /**
  16862. * Create the `Component`'s DOM element
  16863. *
  16864. * @return {Element}
  16865. * The element that was created.
  16866. */
  16867. TooltipProgressBar.prototype.createEl = function createEl() {
  16868. var el = _Component.prototype.createEl.call(this, 'div', {
  16869. className: 'vjs-tooltip-progress-bar vjs-slider-bar',
  16870. innerHTML: '<div class="vjs-time-tooltip"></div>\n <span class="vjs-control-text"><span>' + this.localize('Progress') + '</span>: 0%</span>'
  16871. });
  16872. this.tooltip = el.querySelector('.vjs-time-tooltip');
  16873. return el;
  16874. };
  16875. /**
  16876. * Updatet the data-current-time attribute for TooltipProgressBar
  16877. *
  16878. * @param {EventTarget~Event} [event]
  16879. * The `timeupdate` event that caused this function to run.
  16880. *
  16881. * @listens Player#timeupdate
  16882. */
  16883. TooltipProgressBar.prototype.updateDataAttr = function updateDataAttr(event) {
  16884. var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
  16885. var formattedTime = (0, _formatTime2['default'])(time, this.player_.duration());
  16886. this.el_.setAttribute('data-current-time', formattedTime);
  16887. this.tooltip.innerHTML = formattedTime;
  16888. };
  16889. return TooltipProgressBar;
  16890. }(_component2['default']);
  16891. _component2['default'].registerComponent('TooltipProgressBar', TooltipProgressBar);
  16892. exports['default'] = TooltipProgressBar;
  16893. /***/ }),
  16894. /* 79 */
  16895. /***/ (function(module, exports, __webpack_require__) {
  16896. 'use strict';
  16897. exports.__esModule = true;
  16898. var _component = __webpack_require__(19);
  16899. var _component2 = _interopRequireDefault(_component);
  16900. var _dom = __webpack_require__(11);
  16901. var Dom = _interopRequireWildcard(_dom);
  16902. var _fn = __webpack_require__(20);
  16903. var Fn = _interopRequireWildcard(_fn);
  16904. var _formatTime = __webpack_require__(67);
  16905. var _formatTime2 = _interopRequireDefault(_formatTime);
  16906. var _computedStyle = __webpack_require__(75);
  16907. var _computedStyle2 = _interopRequireDefault(_computedStyle);
  16908. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  16909. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  16910. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  16911. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  16912. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  16913. * @file mouse-time-display.js
  16914. */
  16915. /**
  16916. * The Mouse Time Display component shows the time you will seek to
  16917. * when hovering over the progress bar
  16918. *
  16919. * @extends Component
  16920. */
  16921. var MouseTimeDisplay = function (_Component) {
  16922. _inherits(MouseTimeDisplay, _Component);
  16923. /**
  16924. * Creates an instance of this class.
  16925. *
  16926. * @param {Player} player
  16927. * The `Player` that this class should be attached to.
  16928. *
  16929. * @param {Object} [options]
  16930. * The key/value store of player options.
  16931. */
  16932. function MouseTimeDisplay(player, options) {
  16933. _classCallCheck(this, MouseTimeDisplay);
  16934. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
  16935. if (options.playerOptions && options.playerOptions.controlBar && options.playerOptions.controlBar.progressControl && options.playerOptions.controlBar.progressControl.keepTooltipsInside) {
  16936. _this.keepTooltipsInside = options.playerOptions.controlBar.progressControl.keepTooltipsInside;
  16937. }
  16938. if (_this.keepTooltipsInside) {
  16939. _this.tooltip = Dom.createEl('div', { className: 'vjs-time-tooltip' });
  16940. _this.el().appendChild(_this.tooltip);
  16941. _this.addClass('vjs-keep-tooltips-inside');
  16942. }
  16943. _this.update(0, 0);
  16944. player.on('ready', function () {
  16945. _this.on(player.controlBar.progressControl.el(), 'mousemove', Fn.throttle(Fn.bind(_this, _this.handleMouseMove), 25));
  16946. });
  16947. return _this;
  16948. }
  16949. /**
  16950. * Create the `Component`'s DOM element
  16951. *
  16952. * @return {Element}
  16953. * The element that was created.
  16954. */
  16955. MouseTimeDisplay.prototype.createEl = function createEl() {
  16956. return _Component.prototype.createEl.call(this, 'div', {
  16957. className: 'vjs-mouse-display'
  16958. });
  16959. };
  16960. /**
  16961. * Handle the mouse move event on the `MouseTimeDisplay`.
  16962. *
  16963. * @param {EventTarget~Event} event
  16964. * The `mousemove` event that caused this to event to run.
  16965. *
  16966. * @listen mousemove
  16967. */
  16968. MouseTimeDisplay.prototype.handleMouseMove = function handleMouseMove(event) {
  16969. var duration = this.player_.duration();
  16970. var newTime = this.calculateDistance(event) * duration;
  16971. var position = event.pageX - Dom.findElPosition(this.el().parentNode).left;
  16972. this.update(newTime, position);
  16973. };
  16974. /**
  16975. * Update the time and posistion of the `MouseTimeDisplay`.
  16976. *
  16977. * @param {number} newTime
  16978. * Time to change the `MouseTimeDisplay` to.
  16979. *
  16980. * @param {nubmer} position
  16981. * Postion from the left of the in pixels.
  16982. */
  16983. MouseTimeDisplay.prototype.update = function update(newTime, position) {
  16984. var time = (0, _formatTime2['default'])(newTime, this.player_.duration());
  16985. this.el().style.left = position + 'px';
  16986. this.el().setAttribute('data-current-time', time);
  16987. if (this.keepTooltipsInside) {
  16988. var clampedPosition = this.clampPosition_(position);
  16989. var difference = position - clampedPosition + 1;
  16990. var tooltipWidth = parseFloat((0, _computedStyle2['default'])(this.tooltip, 'width'));
  16991. var tooltipWidthHalf = tooltipWidth / 2;
  16992. this.tooltip.innerHTML = time;
  16993. this.tooltip.style.right = '-' + (tooltipWidthHalf - difference) + 'px';
  16994. }
  16995. };
  16996. /**
  16997. * Get the mouse pointers x coordinate in pixels.
  16998. *
  16999. * @param {EventTarget~Event} [event]
  17000. * The `mousemove` event that was passed to this function by
  17001. * {@link MouseTimeDisplay#handleMouseMove}
  17002. *
  17003. * @return {number}
  17004. * THe x position in pixels of the mouse pointer.
  17005. */
  17006. MouseTimeDisplay.prototype.calculateDistance = function calculateDistance(event) {
  17007. return Dom.getPointerPosition(this.el().parentNode, event).x;
  17008. };
  17009. /**
  17010. * This takes in a horizontal position for the bar and returns a clamped position.
  17011. * Clamped position means that it will keep the position greater than half the width
  17012. * of the tooltip and smaller than the player width minus half the width o the tooltip.
  17013. * It will only clamp the position if `keepTooltipsInside` option is set.
  17014. *
  17015. * @param {number} position
  17016. * The position the bar wants to be
  17017. *
  17018. * @return {number}
  17019. * The (potentially) new clamped position.
  17020. *
  17021. * @private
  17022. */
  17023. MouseTimeDisplay.prototype.clampPosition_ = function clampPosition_(position) {
  17024. if (!this.keepTooltipsInside) {
  17025. return position;
  17026. }
  17027. var playerWidth = parseFloat((0, _computedStyle2['default'])(this.player().el(), 'width'));
  17028. var tooltipWidth = parseFloat((0, _computedStyle2['default'])(this.tooltip, 'width'));
  17029. var tooltipWidthHalf = tooltipWidth / 2;
  17030. var actualPosition = position;
  17031. if (position < tooltipWidthHalf) {
  17032. actualPosition = Math.ceil(tooltipWidthHalf);
  17033. } else if (position > playerWidth - tooltipWidthHalf) {
  17034. actualPosition = Math.floor(playerWidth - tooltipWidthHalf);
  17035. }
  17036. return actualPosition;
  17037. };
  17038. return MouseTimeDisplay;
  17039. }(_component2['default']);
  17040. _component2['default'].registerComponent('MouseTimeDisplay', MouseTimeDisplay);
  17041. exports['default'] = MouseTimeDisplay;
  17042. /***/ }),
  17043. /* 80 */
  17044. /***/ (function(module, exports, __webpack_require__) {
  17045. 'use strict';
  17046. exports.__esModule = true;
  17047. var _button = __webpack_require__(62);
  17048. var _button2 = _interopRequireDefault(_button);
  17049. var _component = __webpack_require__(19);
  17050. var _component2 = _interopRequireDefault(_component);
  17051. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  17052. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  17053. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  17054. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  17055. * @file fullscreen-toggle.js
  17056. */
  17057. /**
  17058. * Toggle fullscreen video
  17059. *
  17060. * @extends Button
  17061. */
  17062. var FullscreenToggle = function (_Button) {
  17063. _inherits(FullscreenToggle, _Button);
  17064. /**
  17065. * Creates an instance of this class.
  17066. *
  17067. * @param {Player} player
  17068. * The `Player` that this class should be attached to.
  17069. *
  17070. * @param {Object} [options]
  17071. * The key/value store of player options.
  17072. */
  17073. function FullscreenToggle(player, options) {
  17074. _classCallCheck(this, FullscreenToggle);
  17075. var _this = _possibleConstructorReturn(this, _Button.call(this, player, options));
  17076. _this.on(player, 'fullscreenchange', _this.handleFullscreenChange);
  17077. return _this;
  17078. }
  17079. /**
  17080. * Builds the default DOM `className`.
  17081. *
  17082. * @return {string}
  17083. * The DOM `className` for this object.
  17084. */
  17085. FullscreenToggle.prototype.buildCSSClass = function buildCSSClass() {
  17086. return 'vjs-fullscreen-control ' + _Button.prototype.buildCSSClass.call(this);
  17087. };
  17088. /**
  17089. * Handles fullscreenchange on the player and change control text accordingly.
  17090. *
  17091. * @param {EventTarget~Event} [event]
  17092. * The {@link Player#fullscreenchange} event that caused this function to be
  17093. * called.
  17094. *
  17095. * @listens Player#fullscreenchange
  17096. */
  17097. FullscreenToggle.prototype.handleFullscreenChange = function handleFullscreenChange(event) {
  17098. if (this.player_.isFullscreen()) {
  17099. this.controlText('Non-Fullscreen');
  17100. } else {
  17101. this.controlText('Fullscreen');
  17102. }
  17103. };
  17104. /**
  17105. * This gets called when an `FullscreenToggle` is "clicked". See
  17106. * {@link ClickableComponent} for more detailed information on what a click can be.
  17107. *
  17108. * @param {EventTarget~Event} [event]
  17109. * The `keydown`, `tap`, or `click` event that caused this function to be
  17110. * called.
  17111. *
  17112. * @listens tap
  17113. * @listens click
  17114. */
  17115. FullscreenToggle.prototype.handleClick = function handleClick(event) {
  17116. if (!this.player_.isFullscreen()) {
  17117. this.player_.requestFullscreen();
  17118. } else {
  17119. this.player_.exitFullscreen();
  17120. }
  17121. };
  17122. return FullscreenToggle;
  17123. }(_button2['default']);
  17124. /**
  17125. * The text that should display over the `FullscreenToggle`s controls. Added for localization.
  17126. *
  17127. * @type {string}
  17128. * @private
  17129. */
  17130. FullscreenToggle.prototype.controlText_ = 'Fullscreen';
  17131. _component2['default'].registerComponent('FullscreenToggle', FullscreenToggle);
  17132. exports['default'] = FullscreenToggle;
  17133. /***/ }),
  17134. /* 81 */
  17135. /***/ (function(module, exports, __webpack_require__) {
  17136. 'use strict';
  17137. exports.__esModule = true;
  17138. var _component = __webpack_require__(19);
  17139. var _component2 = _interopRequireDefault(_component);
  17140. __webpack_require__(82);
  17141. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  17142. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  17143. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  17144. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  17145. * @file volume-control.js
  17146. */
  17147. // Required children
  17148. /**
  17149. * The component for controlling the volume level
  17150. *
  17151. * @extends Component
  17152. */
  17153. var VolumeControl = function (_Component) {
  17154. _inherits(VolumeControl, _Component);
  17155. /**
  17156. * Creates an instance of this class.
  17157. *
  17158. * @param {Player} player
  17159. * The `Player` that this class should be attached to.
  17160. *
  17161. * @param {Object} [options={}]
  17162. * The key/value store of player options.
  17163. */
  17164. function VolumeControl(player, options) {
  17165. _classCallCheck(this, VolumeControl);
  17166. // hide volume controls when they're not supported by the current tech
  17167. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
  17168. if (player.tech_ && player.tech_.featuresVolumeControl === false) {
  17169. _this.addClass('vjs-hidden');
  17170. }
  17171. _this.on(player, 'loadstart', function () {
  17172. if (player.tech_.featuresVolumeControl === false) {
  17173. this.addClass('vjs-hidden');
  17174. } else {
  17175. this.removeClass('vjs-hidden');
  17176. }
  17177. });
  17178. return _this;
  17179. }
  17180. /**
  17181. * Create the `Component`'s DOM element
  17182. *
  17183. * @return {Element}
  17184. * The element that was created.
  17185. */
  17186. VolumeControl.prototype.createEl = function createEl() {
  17187. return _Component.prototype.createEl.call(this, 'div', {
  17188. className: 'vjs-volume-control vjs-control'
  17189. });
  17190. };
  17191. return VolumeControl;
  17192. }(_component2['default']);
  17193. /**
  17194. * Default options for the `VolumeControl`
  17195. *
  17196. * @type {Object}
  17197. * @private
  17198. */
  17199. VolumeControl.prototype.options_ = {
  17200. children: ['volumeBar']
  17201. };
  17202. _component2['default'].registerComponent('VolumeControl', VolumeControl);
  17203. exports['default'] = VolumeControl;
  17204. /***/ }),
  17205. /* 82 */
  17206. /***/ (function(module, exports, __webpack_require__) {
  17207. 'use strict';
  17208. exports.__esModule = true;
  17209. var _slider = __webpack_require__(74);
  17210. var _slider2 = _interopRequireDefault(_slider);
  17211. var _component = __webpack_require__(19);
  17212. var _component2 = _interopRequireDefault(_component);
  17213. var _fn = __webpack_require__(20);
  17214. var Fn = _interopRequireWildcard(_fn);
  17215. __webpack_require__(83);
  17216. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  17217. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  17218. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  17219. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  17220. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  17221. * @file volume-bar.js
  17222. */
  17223. // Required children
  17224. /**
  17225. * The bar that contains the volume level and can be clicked on to adjust the level
  17226. *
  17227. * @extends Slider
  17228. */
  17229. var VolumeBar = function (_Slider) {
  17230. _inherits(VolumeBar, _Slider);
  17231. /**
  17232. * Creates an instance of this class.
  17233. *
  17234. * @param {Player} player
  17235. * The `Player` that this class should be attached to.
  17236. *
  17237. * @param {Object} [options]
  17238. * The key/value store of player options.
  17239. */
  17240. function VolumeBar(player, options) {
  17241. _classCallCheck(this, VolumeBar);
  17242. var _this = _possibleConstructorReturn(this, _Slider.call(this, player, options));
  17243. _this.on(player, 'volumechange', _this.updateARIAAttributes);
  17244. player.ready(Fn.bind(_this, _this.updateARIAAttributes));
  17245. return _this;
  17246. }
  17247. /**
  17248. * Create the `Component`'s DOM element
  17249. *
  17250. * @return {Element}
  17251. * The element that was created.
  17252. */
  17253. VolumeBar.prototype.createEl = function createEl() {
  17254. return _Slider.prototype.createEl.call(this, 'div', {
  17255. className: 'vjs-volume-bar vjs-slider-bar'
  17256. }, {
  17257. 'aria-label': 'volume level'
  17258. });
  17259. };
  17260. /**
  17261. * Handle movement events on the {@link VolumeMenuButton}.
  17262. *
  17263. * @param {EventTarget~Event} event
  17264. * The event that caused this function to run.
  17265. *
  17266. * @listens mousemove
  17267. */
  17268. VolumeBar.prototype.handleMouseMove = function handleMouseMove(event) {
  17269. this.checkMuted();
  17270. this.player_.volume(this.calculateDistance(event));
  17271. };
  17272. /**
  17273. * If the player is muted unmute it.
  17274. */
  17275. VolumeBar.prototype.checkMuted = function checkMuted() {
  17276. if (this.player_.muted()) {
  17277. this.player_.muted(false);
  17278. }
  17279. };
  17280. /**
  17281. * Get percent of volume level
  17282. *
  17283. * @return {number}
  17284. * Volume level percent as a decimal number.
  17285. */
  17286. VolumeBar.prototype.getPercent = function getPercent() {
  17287. if (this.player_.muted()) {
  17288. return 0;
  17289. }
  17290. return this.player_.volume();
  17291. };
  17292. /**
  17293. * Increase volume level for keyboard users
  17294. */
  17295. VolumeBar.prototype.stepForward = function stepForward() {
  17296. this.checkMuted();
  17297. this.player_.volume(this.player_.volume() + 0.1);
  17298. };
  17299. /**
  17300. * Decrease volume level for keyboard users
  17301. */
  17302. VolumeBar.prototype.stepBack = function stepBack() {
  17303. this.checkMuted();
  17304. this.player_.volume(this.player_.volume() - 0.1);
  17305. };
  17306. /**
  17307. * Update ARIA accessibility attributes
  17308. *
  17309. * @param {EventTarget~Event} [event]
  17310. * The `volumechange` event that caused this function to run.
  17311. *
  17312. * @listens Player#volumechange
  17313. */
  17314. VolumeBar.prototype.updateARIAAttributes = function updateARIAAttributes(event) {
  17315. // Current value of volume bar as a percentage
  17316. var volume = (this.player_.volume() * 100).toFixed(2);
  17317. this.el_.setAttribute('aria-valuenow', volume);
  17318. this.el_.setAttribute('aria-valuetext', volume + '%');
  17319. };
  17320. return VolumeBar;
  17321. }(_slider2['default']);
  17322. /**
  17323. * Default options for the `VolumeBar`
  17324. *
  17325. * @type {Object}
  17326. * @private
  17327. */
  17328. VolumeBar.prototype.options_ = {
  17329. children: ['volumeLevel'],
  17330. barName: 'volumeLevel'
  17331. };
  17332. /**
  17333. * Call the update event for this Slider when this event happens on the player.
  17334. *
  17335. * @type {string}
  17336. */
  17337. VolumeBar.prototype.playerEvent = 'volumechange';
  17338. _component2['default'].registerComponent('VolumeBar', VolumeBar);
  17339. exports['default'] = VolumeBar;
  17340. /***/ }),
  17341. /* 83 */
  17342. /***/ (function(module, exports, __webpack_require__) {
  17343. 'use strict';
  17344. exports.__esModule = true;
  17345. var _component = __webpack_require__(19);
  17346. var _component2 = _interopRequireDefault(_component);
  17347. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  17348. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  17349. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  17350. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  17351. * @file volume-level.js
  17352. */
  17353. /**
  17354. * Shows volume level
  17355. *
  17356. * @extends Component
  17357. */
  17358. var VolumeLevel = function (_Component) {
  17359. _inherits(VolumeLevel, _Component);
  17360. function VolumeLevel() {
  17361. _classCallCheck(this, VolumeLevel);
  17362. return _possibleConstructorReturn(this, _Component.apply(this, arguments));
  17363. }
  17364. /**
  17365. * Create the `Component`'s DOM element
  17366. *
  17367. * @return {Element}
  17368. * The element that was created.
  17369. */
  17370. VolumeLevel.prototype.createEl = function createEl() {
  17371. return _Component.prototype.createEl.call(this, 'div', {
  17372. className: 'vjs-volume-level',
  17373. innerHTML: '<span class="vjs-control-text"></span>'
  17374. });
  17375. };
  17376. return VolumeLevel;
  17377. }(_component2['default']);
  17378. _component2['default'].registerComponent('VolumeLevel', VolumeLevel);
  17379. exports['default'] = VolumeLevel;
  17380. /***/ }),
  17381. /* 84 */
  17382. /***/ (function(module, exports, __webpack_require__) {
  17383. 'use strict';
  17384. exports.__esModule = true;
  17385. var _fn = __webpack_require__(20);
  17386. var Fn = _interopRequireWildcard(_fn);
  17387. var _component = __webpack_require__(19);
  17388. var _component2 = _interopRequireDefault(_component);
  17389. var _popup = __webpack_require__(85);
  17390. var _popup2 = _interopRequireDefault(_popup);
  17391. var _popupButton = __webpack_require__(86);
  17392. var _popupButton2 = _interopRequireDefault(_popupButton);
  17393. var _muteToggle = __webpack_require__(87);
  17394. var _muteToggle2 = _interopRequireDefault(_muteToggle);
  17395. var _volumeBar = __webpack_require__(82);
  17396. var _volumeBar2 = _interopRequireDefault(_volumeBar);
  17397. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  17398. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  17399. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  17400. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  17401. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  17402. * @file volume-menu-button.js
  17403. */
  17404. /**
  17405. * Button for volume popup
  17406. *
  17407. * @extends PopupButton
  17408. */
  17409. var VolumeMenuButton = function (_PopupButton) {
  17410. _inherits(VolumeMenuButton, _PopupButton);
  17411. /**
  17412. * Creates an instance of this class.
  17413. *
  17414. * @param {Player} player
  17415. * The `Player` that this class should be attached to.
  17416. *
  17417. * @param {Object} [options={}]
  17418. * The key/value store of player options.
  17419. */
  17420. function VolumeMenuButton(player) {
  17421. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  17422. _classCallCheck(this, VolumeMenuButton);
  17423. // Default to inline
  17424. if (options.inline === undefined) {
  17425. options.inline = true;
  17426. }
  17427. // If the vertical option isn't passed at all, default to true.
  17428. if (options.vertical === undefined) {
  17429. // If an inline volumeMenuButton is used, we should default to using
  17430. // a horizontal slider for obvious reasons.
  17431. if (options.inline) {
  17432. options.vertical = false;
  17433. } else {
  17434. options.vertical = true;
  17435. }
  17436. }
  17437. // The vertical option needs to be set on the volumeBar as well,
  17438. // since that will need to be passed along to the VolumeBar constructor
  17439. options.volumeBar = options.volumeBar || {};
  17440. options.volumeBar.vertical = !!options.vertical;
  17441. // Same listeners as MuteToggle
  17442. var _this = _possibleConstructorReturn(this, _PopupButton.call(this, player, options));
  17443. _this.on(player, 'volumechange', _this.volumeUpdate);
  17444. _this.on(player, 'loadstart', _this.volumeUpdate);
  17445. // hide mute toggle if the current tech doesn't support volume control
  17446. function updateVisibility() {
  17447. if (player.tech_ && player.tech_.featuresVolumeControl === false) {
  17448. this.addClass('vjs-hidden');
  17449. } else {
  17450. this.removeClass('vjs-hidden');
  17451. }
  17452. }
  17453. updateVisibility.call(_this);
  17454. _this.on(player, 'loadstart', updateVisibility);
  17455. _this.on(_this.volumeBar, ['slideractive', 'focus'], function () {
  17456. this.addClass('vjs-slider-active');
  17457. });
  17458. _this.on(_this.volumeBar, ['sliderinactive', 'blur'], function () {
  17459. this.removeClass('vjs-slider-active');
  17460. });
  17461. _this.on(_this.volumeBar, ['focus'], function () {
  17462. this.addClass('vjs-lock-showing');
  17463. });
  17464. _this.on(_this.volumeBar, ['blur'], function () {
  17465. this.removeClass('vjs-lock-showing');
  17466. });
  17467. return _this;
  17468. }
  17469. /**
  17470. * Builds the default DOM `className`.
  17471. *
  17472. * @return {string}
  17473. * The DOM `className` for this object.
  17474. */
  17475. VolumeMenuButton.prototype.buildCSSClass = function buildCSSClass() {
  17476. var orientationClass = '';
  17477. if (this.options_.vertical) {
  17478. orientationClass = 'vjs-volume-menu-button-vertical';
  17479. } else {
  17480. orientationClass = 'vjs-volume-menu-button-horizontal';
  17481. }
  17482. return 'vjs-volume-menu-button ' + _PopupButton.prototype.buildCSSClass.call(this) + ' ' + orientationClass;
  17483. };
  17484. /**
  17485. * Create the VolumeMenuButton popup
  17486. *
  17487. * @return {Popup}
  17488. * The popup that was created
  17489. */
  17490. VolumeMenuButton.prototype.createPopup = function createPopup() {
  17491. var popup = new _popup2['default'](this.player_, {
  17492. contentElType: 'div'
  17493. });
  17494. var vb = new _volumeBar2['default'](this.player_, this.options_.volumeBar);
  17495. popup.addChild(vb);
  17496. this.menuContent = popup;
  17497. this.volumeBar = vb;
  17498. this.attachVolumeBarEvents();
  17499. return popup;
  17500. };
  17501. /**
  17502. * This gets called when an `VolumeMenuButton` is "clicked". See
  17503. * {@link ClickableComponent} for more detailed information on what a click can be.
  17504. *
  17505. * @param {EventTarget~Event} [event]
  17506. * The `keydown`, `tap`, or `click` event that caused this function to be
  17507. * called.
  17508. *
  17509. * @listens tap
  17510. * @listens click
  17511. */
  17512. VolumeMenuButton.prototype.handleClick = function handleClick(event) {
  17513. _muteToggle2['default'].prototype.handleClick.call(this);
  17514. _PopupButton.prototype.handleClick.call(this);
  17515. };
  17516. /**
  17517. * Add events listeners to the created `VolumeBar`.
  17518. */
  17519. VolumeMenuButton.prototype.attachVolumeBarEvents = function attachVolumeBarEvents() {
  17520. this.menuContent.on(['mousedown', 'touchdown'], Fn.bind(this, this.handleMouseDown));
  17521. };
  17522. /**
  17523. * Handle the `mousedown` and `touchdown` events on the `VolumeBar`
  17524. *
  17525. * @param {EventTarget~Event} [event]
  17526. * The `mousedown` or `touchdown` event that caused this to run.
  17527. *
  17528. * @listens mousedown
  17529. * @listens touchdown
  17530. */
  17531. VolumeMenuButton.prototype.handleMouseDown = function handleMouseDown(event) {
  17532. this.on(['mousemove', 'touchmove'], Fn.bind(this.volumeBar, this.volumeBar.handleMouseMove));
  17533. this.on(this.el_.ownerDocument, ['mouseup', 'touchend'], this.handleMouseUp);
  17534. };
  17535. /**
  17536. * Handle the `mouseup` and `touchend` events on the `VolumeBar`
  17537. *
  17538. * @param {EventTarget~Event} [event]
  17539. * The `mouseup` or `touchend` event that caused this to run.
  17540. *
  17541. * @listens mouseup
  17542. * @listens touchend
  17543. */
  17544. VolumeMenuButton.prototype.handleMouseUp = function handleMouseUp(event) {
  17545. this.off(['mousemove', 'touchmove'], Fn.bind(this.volumeBar, this.volumeBar.handleMouseMove));
  17546. };
  17547. return VolumeMenuButton;
  17548. }(_popupButton2['default']);
  17549. /**
  17550. * @borrows MuteToggle#update as VolumeMenuButton#volumeUpdate
  17551. */
  17552. VolumeMenuButton.prototype.volumeUpdate = _muteToggle2['default'].prototype.update;
  17553. /**
  17554. * The text that should display over the `VolumeMenuButton`s controls. Added for localization.
  17555. *
  17556. * @type {string}
  17557. * @private
  17558. */
  17559. VolumeMenuButton.prototype.controlText_ = 'Mute';
  17560. _component2['default'].registerComponent('VolumeMenuButton', VolumeMenuButton);
  17561. exports['default'] = VolumeMenuButton;
  17562. /***/ }),
  17563. /* 85 */
  17564. /***/ (function(module, exports, __webpack_require__) {
  17565. 'use strict';
  17566. exports.__esModule = true;
  17567. var _component = __webpack_require__(19);
  17568. var _component2 = _interopRequireDefault(_component);
  17569. var _dom = __webpack_require__(11);
  17570. var Dom = _interopRequireWildcard(_dom);
  17571. var _fn = __webpack_require__(20);
  17572. var Fn = _interopRequireWildcard(_fn);
  17573. var _events = __webpack_require__(17);
  17574. var Events = _interopRequireWildcard(_events);
  17575. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  17576. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  17577. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  17578. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  17579. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  17580. * @file popup.js
  17581. */
  17582. /**
  17583. * The Popup component is used to build pop up controls.
  17584. *
  17585. * @extends Component
  17586. */
  17587. var Popup = function (_Component) {
  17588. _inherits(Popup, _Component);
  17589. function Popup() {
  17590. _classCallCheck(this, Popup);
  17591. return _possibleConstructorReturn(this, _Component.apply(this, arguments));
  17592. }
  17593. /**
  17594. * Add a popup item to the popup
  17595. *
  17596. * @param {Object|string} component
  17597. * Component or component type to add
  17598. *
  17599. */
  17600. Popup.prototype.addItem = function addItem(component) {
  17601. this.addChild(component);
  17602. component.on('click', Fn.bind(this, function () {
  17603. this.unlockShowing();
  17604. }));
  17605. };
  17606. /**
  17607. * Create the `PopupButton`s DOM element.
  17608. *
  17609. * @return {Element}
  17610. * The element that gets created.
  17611. */
  17612. Popup.prototype.createEl = function createEl() {
  17613. var contentElType = this.options_.contentElType || 'ul';
  17614. this.contentEl_ = Dom.createEl(contentElType, {
  17615. className: 'vjs-menu-content'
  17616. });
  17617. var el = _Component.prototype.createEl.call(this, 'div', {
  17618. append: this.contentEl_,
  17619. className: 'vjs-menu'
  17620. });
  17621. el.appendChild(this.contentEl_);
  17622. // Prevent clicks from bubbling up. Needed for Popup Buttons,
  17623. // where a click on the parent is significant
  17624. Events.on(el, 'click', function (event) {
  17625. event.preventDefault();
  17626. event.stopImmediatePropagation();
  17627. });
  17628. return el;
  17629. };
  17630. return Popup;
  17631. }(_component2['default']);
  17632. _component2['default'].registerComponent('Popup', Popup);
  17633. exports['default'] = Popup;
  17634. /***/ }),
  17635. /* 86 */
  17636. /***/ (function(module, exports, __webpack_require__) {
  17637. 'use strict';
  17638. exports.__esModule = true;
  17639. var _clickableComponent = __webpack_require__(58);
  17640. var _clickableComponent2 = _interopRequireDefault(_clickableComponent);
  17641. var _component = __webpack_require__(19);
  17642. var _component2 = _interopRequireDefault(_component);
  17643. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  17644. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  17645. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  17646. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  17647. * @file popup-button.js
  17648. */
  17649. /**
  17650. * A button class for use with {@link Popup} controls
  17651. *
  17652. * @extends ClickableComponent
  17653. */
  17654. var PopupButton = function (_ClickableComponent) {
  17655. _inherits(PopupButton, _ClickableComponent);
  17656. /**
  17657. * Create an instance of this class.
  17658. *
  17659. * @param {Player} player
  17660. * The `Player` that this class should be attached to.
  17661. *
  17662. * @param {Object} [options]
  17663. * The key/value store of player options.
  17664. */
  17665. function PopupButton(player) {
  17666. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  17667. _classCallCheck(this, PopupButton);
  17668. var _this = _possibleConstructorReturn(this, _ClickableComponent.call(this, player, options));
  17669. _this.update();
  17670. return _this;
  17671. }
  17672. /**
  17673. * Update the `Popup` that this button is attached to.
  17674. */
  17675. PopupButton.prototype.update = function update() {
  17676. var popup = this.createPopup();
  17677. if (this.popup) {
  17678. this.removeChild(this.popup);
  17679. }
  17680. this.popup = popup;
  17681. this.addChild(popup);
  17682. if (this.items && this.items.length === 0) {
  17683. this.hide();
  17684. } else if (this.items && this.items.length > 1) {
  17685. this.show();
  17686. }
  17687. };
  17688. /**
  17689. * Create a `Popup`. - Override with specific functionality for component
  17690. *
  17691. * @abstract
  17692. */
  17693. PopupButton.prototype.createPopup = function createPopup() {};
  17694. /**
  17695. * Create the `PopupButton`s DOM element.
  17696. *
  17697. * @return {Element}
  17698. * The element that gets created.
  17699. */
  17700. PopupButton.prototype.createEl = function createEl() {
  17701. return _ClickableComponent.prototype.createEl.call(this, 'div', {
  17702. className: this.buildCSSClass()
  17703. });
  17704. };
  17705. /**
  17706. * Builds the default DOM `className`.
  17707. *
  17708. * @return {string}
  17709. * The DOM `className` for this object.
  17710. */
  17711. PopupButton.prototype.buildCSSClass = function buildCSSClass() {
  17712. var menuButtonClass = 'vjs-menu-button';
  17713. // If the inline option is passed, we want to use different styles altogether.
  17714. if (this.options_.inline === true) {
  17715. menuButtonClass += '-inline';
  17716. } else {
  17717. menuButtonClass += '-popup';
  17718. }
  17719. return 'vjs-menu-button ' + menuButtonClass + ' ' + _ClickableComponent.prototype.buildCSSClass.call(this);
  17720. };
  17721. return PopupButton;
  17722. }(_clickableComponent2['default']);
  17723. _component2['default'].registerComponent('PopupButton', PopupButton);
  17724. exports['default'] = PopupButton;
  17725. /***/ }),
  17726. /* 87 */
  17727. /***/ (function(module, exports, __webpack_require__) {
  17728. 'use strict';
  17729. exports.__esModule = true;
  17730. var _button = __webpack_require__(62);
  17731. var _button2 = _interopRequireDefault(_button);
  17732. var _component = __webpack_require__(19);
  17733. var _component2 = _interopRequireDefault(_component);
  17734. var _dom = __webpack_require__(11);
  17735. var Dom = _interopRequireWildcard(_dom);
  17736. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  17737. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  17738. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  17739. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  17740. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  17741. * @file mute-toggle.js
  17742. */
  17743. /**
  17744. * A button component for muting the audio.
  17745. *
  17746. * @extends Button
  17747. */
  17748. var MuteToggle = function (_Button) {
  17749. _inherits(MuteToggle, _Button);
  17750. /**
  17751. * Creates an instance of this class.
  17752. *
  17753. * @param {Player} player
  17754. * The `Player` that this class should be attached to.
  17755. *
  17756. * @param {Object} [options]
  17757. * The key/value store of player options.
  17758. */
  17759. function MuteToggle(player, options) {
  17760. _classCallCheck(this, MuteToggle);
  17761. var _this = _possibleConstructorReturn(this, _Button.call(this, player, options));
  17762. _this.on(player, 'volumechange', _this.update);
  17763. // hide mute toggle if the current tech doesn't support volume control
  17764. if (player.tech_ && player.tech_.featuresVolumeControl === false) {
  17765. _this.addClass('vjs-hidden');
  17766. }
  17767. _this.on(player, 'loadstart', function () {
  17768. // We need to update the button to account for a default muted state.
  17769. this.update();
  17770. if (player.tech_.featuresVolumeControl === false) {
  17771. this.addClass('vjs-hidden');
  17772. } else {
  17773. this.removeClass('vjs-hidden');
  17774. }
  17775. });
  17776. return _this;
  17777. }
  17778. /**
  17779. * Builds the default DOM `className`.
  17780. *
  17781. * @return {string}
  17782. * The DOM `className` for this object.
  17783. */
  17784. MuteToggle.prototype.buildCSSClass = function buildCSSClass() {
  17785. return 'vjs-mute-control ' + _Button.prototype.buildCSSClass.call(this);
  17786. };
  17787. /**
  17788. * This gets called when an `MuteToggle` is "clicked". See
  17789. * {@link ClickableComponent} for more detailed information on what a click can be.
  17790. *
  17791. * @param {EventTarget~Event} [event]
  17792. * The `keydown`, `tap`, or `click` event that caused this function to be
  17793. * called.
  17794. *
  17795. * @listens tap
  17796. * @listens click
  17797. */
  17798. MuteToggle.prototype.handleClick = function handleClick(event) {
  17799. this.player_.muted(this.player_.muted() ? false : true);
  17800. };
  17801. /**
  17802. * Update the state of volume.
  17803. *
  17804. * @param {EventTarget~Event} [event]
  17805. * The {@link Player#loadstart} event if this function was called through an
  17806. * event.
  17807. *
  17808. * @listens Player#loadstart
  17809. */
  17810. MuteToggle.prototype.update = function update(event) {
  17811. var vol = this.player_.volume();
  17812. var level = 3;
  17813. if (this.player_.muted()) {
  17814. level = 0;
  17815. } else if (vol < 0.33) {
  17816. level = 1;
  17817. } else if (vol < 0.67) {
  17818. level = 2;
  17819. }
  17820. // Don't rewrite the button text if the actual text doesn't change.
  17821. // This causes unnecessary and confusing information for screen reader users.
  17822. // This check is needed because this function gets called every time the volume level is changed.
  17823. var toMute = this.player_.muted() ? 'Unmute' : 'Mute';
  17824. if (this.controlText() !== toMute) {
  17825. this.controlText(toMute);
  17826. }
  17827. // TODO improve muted icon classes
  17828. for (var i = 0; i < 4; i++) {
  17829. Dom.removeElClass(this.el_, 'vjs-vol-' + i);
  17830. }
  17831. Dom.addElClass(this.el_, 'vjs-vol-' + level);
  17832. };
  17833. return MuteToggle;
  17834. }(_button2['default']);
  17835. /**
  17836. * The text that should display over the `MuteToggle`s controls. Added for localization.
  17837. *
  17838. * @type {string}
  17839. * @private
  17840. */
  17841. MuteToggle.prototype.controlText_ = 'Mute';
  17842. _component2['default'].registerComponent('MuteToggle', MuteToggle);
  17843. exports['default'] = MuteToggle;
  17844. /***/ }),
  17845. /* 88 */
  17846. /***/ (function(module, exports, __webpack_require__) {
  17847. 'use strict';
  17848. exports.__esModule = true;
  17849. var _textTrackButton = __webpack_require__(89);
  17850. var _textTrackButton2 = _interopRequireDefault(_textTrackButton);
  17851. var _component = __webpack_require__(19);
  17852. var _component2 = _interopRequireDefault(_component);
  17853. var _chaptersTrackMenuItem = __webpack_require__(96);
  17854. var _chaptersTrackMenuItem2 = _interopRequireDefault(_chaptersTrackMenuItem);
  17855. var _toTitleCase = __webpack_require__(21);
  17856. var _toTitleCase2 = _interopRequireDefault(_toTitleCase);
  17857. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  17858. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  17859. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  17860. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  17861. * @file chapters-button.js
  17862. */
  17863. /**
  17864. * The button component for toggling and selecting chapters
  17865. * Chapters act much differently than other text tracks
  17866. * Cues are navigation vs. other tracks of alternative languages
  17867. *
  17868. * @extends TextTrackButton
  17869. */
  17870. var ChaptersButton = function (_TextTrackButton) {
  17871. _inherits(ChaptersButton, _TextTrackButton);
  17872. /**
  17873. * Creates an instance of this class.
  17874. *
  17875. * @param {Player} player
  17876. * The `Player` that this class should be attached to.
  17877. *
  17878. * @param {Object} [options]
  17879. * The key/value store of player options.
  17880. *
  17881. * @param {Component~ReadyCallback} [ready]
  17882. * The function to call when this function is ready.
  17883. */
  17884. function ChaptersButton(player, options, ready) {
  17885. _classCallCheck(this, ChaptersButton);
  17886. var _this = _possibleConstructorReturn(this, _TextTrackButton.call(this, player, options, ready));
  17887. _this.el_.setAttribute('aria-label', 'Chapters Menu');
  17888. return _this;
  17889. }
  17890. /**
  17891. * Builds the default DOM `className`.
  17892. *
  17893. * @return {string}
  17894. * The DOM `className` for this object.
  17895. */
  17896. ChaptersButton.prototype.buildCSSClass = function buildCSSClass() {
  17897. return 'vjs-chapters-button ' + _TextTrackButton.prototype.buildCSSClass.call(this);
  17898. };
  17899. /**
  17900. * Update the menu based on the current state of its items.
  17901. *
  17902. * @param {EventTarget~Event} [event]
  17903. * An event that triggered this function to run.
  17904. *
  17905. * @listens TextTrackList#addtrack
  17906. * @listens TextTrackList#removetrack
  17907. * @listens TextTrackList#change
  17908. */
  17909. ChaptersButton.prototype.update = function update(event) {
  17910. if (!this.track_ || event && (event.type === 'addtrack' || event.type === 'removetrack')) {
  17911. this.setTrack(this.findChaptersTrack());
  17912. }
  17913. _TextTrackButton.prototype.update.call(this);
  17914. };
  17915. /**
  17916. * Set the currently selected track for the chapters button.
  17917. *
  17918. * @param {TextTrack} track
  17919. * The new track to select. Nothing will change if this is the currently selected
  17920. * track.
  17921. */
  17922. ChaptersButton.prototype.setTrack = function setTrack(track) {
  17923. if (this.track_ === track) {
  17924. return;
  17925. }
  17926. if (!this.updateHandler_) {
  17927. this.updateHandler_ = this.update.bind(this);
  17928. }
  17929. // here this.track_ refers to the old track instance
  17930. if (this.track_) {
  17931. var remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_);
  17932. if (remoteTextTrackEl) {
  17933. remoteTextTrackEl.removeEventListener('load', this.updateHandler_);
  17934. }
  17935. this.track_ = null;
  17936. }
  17937. this.track_ = track;
  17938. // here this.track_ refers to the new track instance
  17939. if (this.track_) {
  17940. this.track_.mode = 'hidden';
  17941. var _remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_);
  17942. if (_remoteTextTrackEl) {
  17943. _remoteTextTrackEl.addEventListener('load', this.updateHandler_);
  17944. }
  17945. }
  17946. };
  17947. /**
  17948. * Find the track object that is currently in use by this ChaptersButton
  17949. *
  17950. * @return {TextTrack|undefined}
  17951. * The current track or undefined if none was found.
  17952. */
  17953. ChaptersButton.prototype.findChaptersTrack = function findChaptersTrack() {
  17954. var tracks = this.player_.textTracks() || [];
  17955. for (var i = tracks.length - 1; i >= 0; i--) {
  17956. // We will always choose the last track as our chaptersTrack
  17957. var track = tracks[i];
  17958. if (track.kind === this.kind_) {
  17959. return track;
  17960. }
  17961. }
  17962. };
  17963. /**
  17964. * Get the caption for the ChaptersButton based on the track label. This will also
  17965. * use the current tracks localized kind as a fallback if a label does not exist.
  17966. *
  17967. * @return {string}
  17968. * The tracks current label or the localized track kind.
  17969. */
  17970. ChaptersButton.prototype.getMenuCaption = function getMenuCaption() {
  17971. if (this.track_ && this.track_.label) {
  17972. return this.track_.label;
  17973. }
  17974. return this.localize((0, _toTitleCase2['default'])(this.kind_));
  17975. };
  17976. /**
  17977. * Create menu from chapter track
  17978. *
  17979. * @return {Menu}
  17980. * New menu for the chapter buttons
  17981. */
  17982. ChaptersButton.prototype.createMenu = function createMenu() {
  17983. this.options_.title = this.getMenuCaption();
  17984. return _TextTrackButton.prototype.createMenu.call(this);
  17985. };
  17986. /**
  17987. * Create a menu item for each text track
  17988. *
  17989. * @return {TextTrackMenuItem[]}
  17990. * Array of menu items
  17991. */
  17992. ChaptersButton.prototype.createItems = function createItems() {
  17993. var items = [];
  17994. if (!this.track_) {
  17995. return items;
  17996. }
  17997. var cues = this.track_.cues;
  17998. if (!cues) {
  17999. return items;
  18000. }
  18001. for (var i = 0, l = cues.length; i < l; i++) {
  18002. var cue = cues[i];
  18003. var mi = new _chaptersTrackMenuItem2['default'](this.player_, { track: this.track_, cue: cue });
  18004. items.push(mi);
  18005. }
  18006. return items;
  18007. };
  18008. return ChaptersButton;
  18009. }(_textTrackButton2['default']);
  18010. /**
  18011. * `kind` of TextTrack to look for to associate it with this menu.
  18012. *
  18013. * @type {string}
  18014. * @private
  18015. */
  18016. ChaptersButton.prototype.kind_ = 'chapters';
  18017. /**
  18018. * The text that should display over the `ChaptersButton`s controls. Added for localization.
  18019. *
  18020. * @type {string}
  18021. * @private
  18022. */
  18023. ChaptersButton.prototype.controlText_ = 'Chapters';
  18024. _component2['default'].registerComponent('ChaptersButton', ChaptersButton);
  18025. exports['default'] = ChaptersButton;
  18026. /***/ }),
  18027. /* 89 */
  18028. /***/ (function(module, exports, __webpack_require__) {
  18029. 'use strict';
  18030. exports.__esModule = true;
  18031. var _trackButton = __webpack_require__(90);
  18032. var _trackButton2 = _interopRequireDefault(_trackButton);
  18033. var _component = __webpack_require__(19);
  18034. var _component2 = _interopRequireDefault(_component);
  18035. var _textTrackMenuItem = __webpack_require__(93);
  18036. var _textTrackMenuItem2 = _interopRequireDefault(_textTrackMenuItem);
  18037. var _offTextTrackMenuItem = __webpack_require__(95);
  18038. var _offTextTrackMenuItem2 = _interopRequireDefault(_offTextTrackMenuItem);
  18039. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  18040. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  18041. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  18042. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  18043. * @file text-track-button.js
  18044. */
  18045. /**
  18046. * The base class for buttons that toggle specific text track types (e.g. subtitles)
  18047. *
  18048. * @extends MenuButton
  18049. */
  18050. var TextTrackButton = function (_TrackButton) {
  18051. _inherits(TextTrackButton, _TrackButton);
  18052. /**
  18053. * Creates an instance of this class.
  18054. *
  18055. * @param {Player} player
  18056. * The `Player` that this class should be attached to.
  18057. *
  18058. * @param {Object} [options={}]
  18059. * The key/value store of player options.
  18060. */
  18061. function TextTrackButton(player) {
  18062. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  18063. _classCallCheck(this, TextTrackButton);
  18064. options.tracks = player.textTracks();
  18065. return _possibleConstructorReturn(this, _TrackButton.call(this, player, options));
  18066. }
  18067. /**
  18068. * Create a menu item for each text track
  18069. *
  18070. * @param {TextTrackMenuItem[]} [items=[]]
  18071. * Existing array of items to use during creation
  18072. *
  18073. * @return {TextTrackMenuItem[]}
  18074. * Array of menu items that were created
  18075. */
  18076. TextTrackButton.prototype.createItems = function createItems() {
  18077. var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  18078. // Add an OFF menu item to turn all tracks off
  18079. items.push(new _offTextTrackMenuItem2['default'](this.player_, { kind: this.kind_ }));
  18080. this.hideThreshold_ += 1;
  18081. var tracks = this.player_.textTracks();
  18082. if (!tracks) {
  18083. return items;
  18084. }
  18085. for (var i = 0; i < tracks.length; i++) {
  18086. var track = tracks[i];
  18087. // only add tracks that are of the appropriate kind and have a label
  18088. if (track.kind === this.kind_) {
  18089. items.push(new _textTrackMenuItem2['default'](this.player_, {
  18090. track: track,
  18091. // MenuItem is selectable
  18092. selectable: true
  18093. }));
  18094. }
  18095. }
  18096. return items;
  18097. };
  18098. return TextTrackButton;
  18099. }(_trackButton2['default']);
  18100. _component2['default'].registerComponent('TextTrackButton', TextTrackButton);
  18101. exports['default'] = TextTrackButton;
  18102. /***/ }),
  18103. /* 90 */
  18104. /***/ (function(module, exports, __webpack_require__) {
  18105. 'use strict';
  18106. exports.__esModule = true;
  18107. var _menuButton = __webpack_require__(91);
  18108. var _menuButton2 = _interopRequireDefault(_menuButton);
  18109. var _component = __webpack_require__(19);
  18110. var _component2 = _interopRequireDefault(_component);
  18111. var _fn = __webpack_require__(20);
  18112. var Fn = _interopRequireWildcard(_fn);
  18113. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  18114. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  18115. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  18116. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  18117. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  18118. * @file track-button.js
  18119. */
  18120. /**
  18121. * The base class for buttons that toggle specific track types (e.g. subtitles).
  18122. *
  18123. * @extends MenuButton
  18124. */
  18125. var TrackButton = function (_MenuButton) {
  18126. _inherits(TrackButton, _MenuButton);
  18127. /**
  18128. * Creates an instance of this class.
  18129. *
  18130. * @param {Player} player
  18131. * The `Player` that this class should be attached to.
  18132. *
  18133. * @param {Object} [options]
  18134. * The key/value store of player options.
  18135. */
  18136. function TrackButton(player, options) {
  18137. _classCallCheck(this, TrackButton);
  18138. var tracks = options.tracks;
  18139. var _this = _possibleConstructorReturn(this, _MenuButton.call(this, player, options));
  18140. if (_this.items.length <= 1) {
  18141. _this.hide();
  18142. }
  18143. if (!tracks) {
  18144. return _possibleConstructorReturn(_this);
  18145. }
  18146. var updateHandler = Fn.bind(_this, _this.update);
  18147. tracks.addEventListener('removetrack', updateHandler);
  18148. tracks.addEventListener('addtrack', updateHandler);
  18149. _this.player_.on('dispose', function () {
  18150. tracks.removeEventListener('removetrack', updateHandler);
  18151. tracks.removeEventListener('addtrack', updateHandler);
  18152. });
  18153. return _this;
  18154. }
  18155. return TrackButton;
  18156. }(_menuButton2['default']);
  18157. _component2['default'].registerComponent('TrackButton', TrackButton);
  18158. exports['default'] = TrackButton;
  18159. /***/ }),
  18160. /* 91 */
  18161. /***/ (function(module, exports, __webpack_require__) {
  18162. 'use strict';
  18163. exports.__esModule = true;
  18164. var _clickableComponent = __webpack_require__(58);
  18165. var _clickableComponent2 = _interopRequireDefault(_clickableComponent);
  18166. var _component = __webpack_require__(19);
  18167. var _component2 = _interopRequireDefault(_component);
  18168. var _menu = __webpack_require__(92);
  18169. var _menu2 = _interopRequireDefault(_menu);
  18170. var _dom = __webpack_require__(11);
  18171. var Dom = _interopRequireWildcard(_dom);
  18172. var _fn = __webpack_require__(20);
  18173. var Fn = _interopRequireWildcard(_fn);
  18174. var _toTitleCase = __webpack_require__(21);
  18175. var _toTitleCase2 = _interopRequireDefault(_toTitleCase);
  18176. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  18177. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  18178. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  18179. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  18180. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  18181. * @file menu-button.js
  18182. */
  18183. /**
  18184. * A `MenuButton` class for any popup {@link Menu}.
  18185. *
  18186. * @extends ClickableComponent
  18187. */
  18188. var MenuButton = function (_ClickableComponent) {
  18189. _inherits(MenuButton, _ClickableComponent);
  18190. /**
  18191. * Creates an instance of this class.
  18192. *
  18193. * @param {Player} player
  18194. * The `Player` that this class should be attached to.
  18195. *
  18196. * @param {Object} [options={}]
  18197. * The key/value store of player options.
  18198. */
  18199. function MenuButton(player) {
  18200. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  18201. _classCallCheck(this, MenuButton);
  18202. var _this = _possibleConstructorReturn(this, _ClickableComponent.call(this, player, options));
  18203. _this.update();
  18204. _this.enabled_ = true;
  18205. _this.el_.setAttribute('aria-haspopup', 'true');
  18206. _this.el_.setAttribute('role', 'menuitem');
  18207. _this.on('keydown', _this.handleSubmenuKeyPress);
  18208. return _this;
  18209. }
  18210. /**
  18211. * Update the menu based on the current state of its items.
  18212. */
  18213. MenuButton.prototype.update = function update() {
  18214. var menu = this.createMenu();
  18215. if (this.menu) {
  18216. this.removeChild(this.menu);
  18217. }
  18218. this.menu = menu;
  18219. this.addChild(menu);
  18220. /**
  18221. * Track the state of the menu button
  18222. *
  18223. * @type {Boolean}
  18224. * @private
  18225. */
  18226. this.buttonPressed_ = false;
  18227. this.el_.setAttribute('aria-expanded', 'false');
  18228. if (this.items && this.items.length <= this.hideThreshold_) {
  18229. this.hide();
  18230. } else {
  18231. this.show();
  18232. }
  18233. };
  18234. /**
  18235. * Create the menu and add all items to it.
  18236. *
  18237. * @return {Menu}
  18238. * The constructed menu
  18239. */
  18240. MenuButton.prototype.createMenu = function createMenu() {
  18241. var menu = new _menu2['default'](this.player_);
  18242. /**
  18243. * Hide the menu if the number of items is less than or equal to this threshold. This defaults
  18244. * to 0 and whenever we add items which can be hidden to the menu we'll increment it. We list
  18245. * it here because every time we run `createMenu` we need to reset the value.
  18246. *
  18247. * @protected
  18248. * @type {Number}
  18249. */
  18250. this.hideThreshold_ = 0;
  18251. // Add a title list item to the top
  18252. if (this.options_.title) {
  18253. var title = Dom.createEl('li', {
  18254. className: 'vjs-menu-title',
  18255. innerHTML: (0, _toTitleCase2['default'])(this.options_.title),
  18256. tabIndex: -1
  18257. });
  18258. this.hideThreshold_ += 1;
  18259. menu.children_.unshift(title);
  18260. Dom.insertElFirst(title, menu.contentEl());
  18261. }
  18262. this.items = this.createItems();
  18263. if (this.items) {
  18264. // Add menu items to the menu
  18265. for (var i = 0; i < this.items.length; i++) {
  18266. menu.addItem(this.items[i]);
  18267. }
  18268. }
  18269. return menu;
  18270. };
  18271. /**
  18272. * Create the list of menu items. Specific to each subclass.
  18273. *
  18274. * @abstract
  18275. */
  18276. MenuButton.prototype.createItems = function createItems() {};
  18277. /**
  18278. * Create the `MenuButtons`s DOM element.
  18279. *
  18280. * @return {Element}
  18281. * The element that gets created.
  18282. */
  18283. MenuButton.prototype.createEl = function createEl() {
  18284. return _ClickableComponent.prototype.createEl.call(this, 'div', {
  18285. className: this.buildCSSClass()
  18286. });
  18287. };
  18288. /**
  18289. * Builds the default DOM `className`.
  18290. *
  18291. * @return {string}
  18292. * The DOM `className` for this object.
  18293. */
  18294. MenuButton.prototype.buildCSSClass = function buildCSSClass() {
  18295. var menuButtonClass = 'vjs-menu-button';
  18296. // If the inline option is passed, we want to use different styles altogether.
  18297. if (this.options_.inline === true) {
  18298. menuButtonClass += '-inline';
  18299. } else {
  18300. menuButtonClass += '-popup';
  18301. }
  18302. return 'vjs-menu-button ' + menuButtonClass + ' ' + _ClickableComponent.prototype.buildCSSClass.call(this);
  18303. };
  18304. /**
  18305. * Handle a click on a `MenuButton`.
  18306. * See {@link ClickableComponent#handleClick} for instances where this is called.
  18307. *
  18308. * @param {EventTarget~Event} event
  18309. * The `keydown`, `tap`, or `click` event that caused this function to be
  18310. * called.
  18311. *
  18312. * @listens tap
  18313. * @listens click
  18314. */
  18315. MenuButton.prototype.handleClick = function handleClick(event) {
  18316. // When you click the button it adds focus, which will show the menu.
  18317. // So we'll remove focus when the mouse leaves the button. Focus is needed
  18318. // for tab navigation.
  18319. this.one(this.menu.contentEl(), 'mouseleave', Fn.bind(this, function (e) {
  18320. this.unpressButton();
  18321. this.el_.blur();
  18322. }));
  18323. if (this.buttonPressed_) {
  18324. this.unpressButton();
  18325. } else {
  18326. this.pressButton();
  18327. }
  18328. };
  18329. /**
  18330. * Handle tab, escape, down arrow, and up arrow keys for `MenuButton`. See
  18331. * {@link ClickableComponent#handleKeyPress} for instances where this is called.
  18332. *
  18333. * @param {EventTarget~Event} event
  18334. * The `keydown` event that caused this function to be called.
  18335. *
  18336. * @listens keydown
  18337. */
  18338. MenuButton.prototype.handleKeyPress = function handleKeyPress(event) {
  18339. // Escape (27) key or Tab (9) key unpress the 'button'
  18340. if (event.which === 27 || event.which === 9) {
  18341. if (this.buttonPressed_) {
  18342. this.unpressButton();
  18343. }
  18344. // Don't preventDefault for Tab key - we still want to lose focus
  18345. if (event.which !== 9) {
  18346. event.preventDefault();
  18347. }
  18348. // Up (38) key or Down (40) key press the 'button'
  18349. } else if (event.which === 38 || event.which === 40) {
  18350. if (!this.buttonPressed_) {
  18351. this.pressButton();
  18352. event.preventDefault();
  18353. }
  18354. } else {
  18355. _ClickableComponent.prototype.handleKeyPress.call(this, event);
  18356. }
  18357. };
  18358. /**
  18359. * Handle a `keydown` event on a sub-menu. The listener for this is added in
  18360. * the constructor.
  18361. *
  18362. * @param {EventTarget~Event} event
  18363. * Key press event
  18364. *
  18365. * @listens keydown
  18366. */
  18367. MenuButton.prototype.handleSubmenuKeyPress = function handleSubmenuKeyPress(event) {
  18368. // Escape (27) key or Tab (9) key unpress the 'button'
  18369. if (event.which === 27 || event.which === 9) {
  18370. if (this.buttonPressed_) {
  18371. this.unpressButton();
  18372. }
  18373. // Don't preventDefault for Tab key - we still want to lose focus
  18374. if (event.which !== 9) {
  18375. event.preventDefault();
  18376. }
  18377. }
  18378. };
  18379. /**
  18380. * Put the current `MenuButton` into a pressed state.
  18381. */
  18382. MenuButton.prototype.pressButton = function pressButton() {
  18383. if (this.enabled_) {
  18384. this.buttonPressed_ = true;
  18385. this.menu.lockShowing();
  18386. this.el_.setAttribute('aria-expanded', 'true');
  18387. // set the focus into the submenu
  18388. this.menu.focus();
  18389. }
  18390. };
  18391. /**
  18392. * Take the current `MenuButton` out of a pressed state.
  18393. */
  18394. MenuButton.prototype.unpressButton = function unpressButton() {
  18395. if (this.enabled_) {
  18396. this.buttonPressed_ = false;
  18397. this.menu.unlockShowing();
  18398. this.el_.setAttribute('aria-expanded', 'false');
  18399. // Set focus back to this menu button
  18400. this.el_.focus();
  18401. }
  18402. };
  18403. /**
  18404. * Disable the `MenuButton`. Don't allow it to be clicked.
  18405. *
  18406. * @return {MenuButton}
  18407. * Returns itself; method can be chained.
  18408. */
  18409. MenuButton.prototype.disable = function disable() {
  18410. // Unpress, but don't force focus on this button
  18411. this.buttonPressed_ = false;
  18412. this.menu.unlockShowing();
  18413. this.el_.setAttribute('aria-expanded', 'false');
  18414. this.enabled_ = false;
  18415. return _ClickableComponent.prototype.disable.call(this);
  18416. };
  18417. /**
  18418. * Enable the `MenuButton`. Allow it to be clicked.
  18419. *
  18420. * @return {MenuButton}
  18421. * Returns itself; method can be chained.
  18422. */
  18423. MenuButton.prototype.enable = function enable() {
  18424. this.enabled_ = true;
  18425. return _ClickableComponent.prototype.enable.call(this);
  18426. };
  18427. return MenuButton;
  18428. }(_clickableComponent2['default']);
  18429. _component2['default'].registerComponent('MenuButton', MenuButton);
  18430. exports['default'] = MenuButton;
  18431. /***/ }),
  18432. /* 92 */
  18433. /***/ (function(module, exports, __webpack_require__) {
  18434. 'use strict';
  18435. exports.__esModule = true;
  18436. var _component = __webpack_require__(19);
  18437. var _component2 = _interopRequireDefault(_component);
  18438. var _dom = __webpack_require__(11);
  18439. var Dom = _interopRequireWildcard(_dom);
  18440. var _fn = __webpack_require__(20);
  18441. var Fn = _interopRequireWildcard(_fn);
  18442. var _events = __webpack_require__(17);
  18443. var Events = _interopRequireWildcard(_events);
  18444. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  18445. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  18446. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  18447. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  18448. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  18449. * @file menu.js
  18450. */
  18451. /**
  18452. * The Menu component is used to build popup menus, including subtitle and
  18453. * captions selection menus.
  18454. *
  18455. * @extends Component
  18456. */
  18457. var Menu = function (_Component) {
  18458. _inherits(Menu, _Component);
  18459. /**
  18460. * Create an instance of this class.
  18461. *
  18462. * @param {Player} player
  18463. * the player that this component should attach to
  18464. *
  18465. * @param {Object} [options]
  18466. * Object of option names and values
  18467. *
  18468. */
  18469. function Menu(player, options) {
  18470. _classCallCheck(this, Menu);
  18471. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
  18472. _this.focusedChild_ = -1;
  18473. _this.on('keydown', _this.handleKeyPress);
  18474. return _this;
  18475. }
  18476. /**
  18477. * Add a {@link MenuItem} to the menu.
  18478. *
  18479. * @param {Object|string} component
  18480. * The name or instance of the `MenuItem` to add.
  18481. *
  18482. */
  18483. Menu.prototype.addItem = function addItem(component) {
  18484. this.addChild(component);
  18485. component.on('click', Fn.bind(this, function (event) {
  18486. this.unlockShowing();
  18487. // TODO: Need to set keyboard focus back to the menuButton
  18488. }));
  18489. };
  18490. /**
  18491. * Create the `Menu`s DOM element.
  18492. *
  18493. * @return {Element}
  18494. * the element that was created
  18495. */
  18496. Menu.prototype.createEl = function createEl() {
  18497. var contentElType = this.options_.contentElType || 'ul';
  18498. this.contentEl_ = Dom.createEl(contentElType, {
  18499. className: 'vjs-menu-content'
  18500. });
  18501. this.contentEl_.setAttribute('role', 'menu');
  18502. var el = _Component.prototype.createEl.call(this, 'div', {
  18503. append: this.contentEl_,
  18504. className: 'vjs-menu'
  18505. });
  18506. el.setAttribute('role', 'presentation');
  18507. el.appendChild(this.contentEl_);
  18508. // Prevent clicks from bubbling up. Needed for Menu Buttons,
  18509. // where a click on the parent is significant
  18510. Events.on(el, 'click', function (event) {
  18511. event.preventDefault();
  18512. event.stopImmediatePropagation();
  18513. });
  18514. return el;
  18515. };
  18516. /**
  18517. * Handle a `keydown` event on this menu. This listener is added in the constructor.
  18518. *
  18519. * @param {EventTarget~Event} event
  18520. * A `keydown` event that happened on the menu.
  18521. *
  18522. * @listens keydown
  18523. */
  18524. Menu.prototype.handleKeyPress = function handleKeyPress(event) {
  18525. // Left and Down Arrows
  18526. if (event.which === 37 || event.which === 40) {
  18527. event.preventDefault();
  18528. this.stepForward();
  18529. // Up and Right Arrows
  18530. } else if (event.which === 38 || event.which === 39) {
  18531. event.preventDefault();
  18532. this.stepBack();
  18533. }
  18534. };
  18535. /**
  18536. * Move to next (lower) menu item for keyboard users.
  18537. */
  18538. Menu.prototype.stepForward = function stepForward() {
  18539. var stepChild = 0;
  18540. if (this.focusedChild_ !== undefined) {
  18541. stepChild = this.focusedChild_ + 1;
  18542. }
  18543. this.focus(stepChild);
  18544. };
  18545. /**
  18546. * Move to previous (higher) menu item for keyboard users.
  18547. */
  18548. Menu.prototype.stepBack = function stepBack() {
  18549. var stepChild = 0;
  18550. if (this.focusedChild_ !== undefined) {
  18551. stepChild = this.focusedChild_ - 1;
  18552. }
  18553. this.focus(stepChild);
  18554. };
  18555. /**
  18556. * Set focus on a {@link MenuItem} in the `Menu`.
  18557. *
  18558. * @param {Object|string} [item=0]
  18559. * Index of child item set focus on.
  18560. */
  18561. Menu.prototype.focus = function focus() {
  18562. var item = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
  18563. var children = this.children().slice();
  18564. var haveTitle = children.length && children[0].className && /vjs-menu-title/.test(children[0].className);
  18565. if (haveTitle) {
  18566. children.shift();
  18567. }
  18568. if (children.length > 0) {
  18569. if (item < 0) {
  18570. item = 0;
  18571. } else if (item >= children.length) {
  18572. item = children.length - 1;
  18573. }
  18574. this.focusedChild_ = item;
  18575. children[item].el_.focus();
  18576. }
  18577. };
  18578. return Menu;
  18579. }(_component2['default']);
  18580. _component2['default'].registerComponent('Menu', Menu);
  18581. exports['default'] = Menu;
  18582. /***/ }),
  18583. /* 93 */
  18584. /***/ (function(module, exports, __webpack_require__) {
  18585. 'use strict';
  18586. exports.__esModule = true;
  18587. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  18588. var _menuItem = __webpack_require__(94);
  18589. var _menuItem2 = _interopRequireDefault(_menuItem);
  18590. var _component = __webpack_require__(19);
  18591. var _component2 = _interopRequireDefault(_component);
  18592. var _fn = __webpack_require__(20);
  18593. var Fn = _interopRequireWildcard(_fn);
  18594. var _window = __webpack_require__(7);
  18595. var _window2 = _interopRequireDefault(_window);
  18596. var _document = __webpack_require__(8);
  18597. var _document2 = _interopRequireDefault(_document);
  18598. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  18599. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  18600. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  18601. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  18602. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  18603. * @file text-track-menu-item.js
  18604. */
  18605. /**
  18606. * The specific menu item type for selecting a language within a text track kind
  18607. *
  18608. * @extends MenuItem
  18609. */
  18610. var TextTrackMenuItem = function (_MenuItem) {
  18611. _inherits(TextTrackMenuItem, _MenuItem);
  18612. /**
  18613. * Creates an instance of this class.
  18614. *
  18615. * @param {Player} player
  18616. * The `Player` that this class should be attached to.
  18617. *
  18618. * @param {Object} [options]
  18619. * The key/value store of player options.
  18620. */
  18621. function TextTrackMenuItem(player, options) {
  18622. _classCallCheck(this, TextTrackMenuItem);
  18623. var track = options.track;
  18624. var tracks = player.textTracks();
  18625. // Modify options for parent MenuItem class's init.
  18626. options.label = track.label || track.language || 'Unknown';
  18627. options.selected = track['default'] || track.mode === 'showing';
  18628. var _this = _possibleConstructorReturn(this, _MenuItem.call(this, player, options));
  18629. _this.track = track;
  18630. if (tracks) {
  18631. var changeHandler = Fn.bind(_this, _this.handleTracksChange);
  18632. player.on(['loadstart', 'texttrackchange'], changeHandler);
  18633. tracks.addEventListener('change', changeHandler);
  18634. _this.on('dispose', function () {
  18635. tracks.removeEventListener('change', changeHandler);
  18636. });
  18637. }
  18638. // iOS7 doesn't dispatch change events to TextTrackLists when an
  18639. // associated track's mode changes. Without something like
  18640. // Object.observe() (also not present on iOS7), it's not
  18641. // possible to detect changes to the mode attribute and polyfill
  18642. // the change event. As a poor substitute, we manually dispatch
  18643. // change events whenever the controls modify the mode.
  18644. if (tracks && tracks.onchange === undefined) {
  18645. var event = void 0;
  18646. _this.on(['tap', 'click'], function () {
  18647. if (_typeof(_window2['default'].Event) !== 'object') {
  18648. // Android 2.3 throws an Illegal Constructor error for window.Event
  18649. try {
  18650. event = new _window2['default'].Event('change');
  18651. } catch (err) {
  18652. // continue regardless of error
  18653. }
  18654. }
  18655. if (!event) {
  18656. event = _document2['default'].createEvent('Event');
  18657. event.initEvent('change', true, true);
  18658. }
  18659. tracks.dispatchEvent(event);
  18660. });
  18661. }
  18662. return _this;
  18663. }
  18664. /**
  18665. * This gets called when an `TextTrackMenuItem` is "clicked". See
  18666. * {@link ClickableComponent} for more detailed information on what a click can be.
  18667. *
  18668. * @param {EventTarget~Event} event
  18669. * The `keydown`, `tap`, or `click` event that caused this function to be
  18670. * called.
  18671. *
  18672. * @listens tap
  18673. * @listens click
  18674. */
  18675. TextTrackMenuItem.prototype.handleClick = function handleClick(event) {
  18676. var kind = this.track.kind;
  18677. var tracks = this.player_.textTracks();
  18678. _MenuItem.prototype.handleClick.call(this, event);
  18679. if (!tracks) {
  18680. return;
  18681. }
  18682. for (var i = 0; i < tracks.length; i++) {
  18683. var track = tracks[i];
  18684. if (track.kind !== kind) {
  18685. continue;
  18686. }
  18687. if (track === this.track) {
  18688. if (track.mode !== 'showing') {
  18689. track.mode = 'showing';
  18690. }
  18691. } else if (track.mode !== 'disabled') {
  18692. track.mode = 'disabled';
  18693. }
  18694. }
  18695. };
  18696. /**
  18697. * Handle text track list change
  18698. *
  18699. * @param {EventTarget~Event} event
  18700. * The `change` event that caused this function to be called.
  18701. *
  18702. * @listens TextTrackList#change
  18703. */
  18704. TextTrackMenuItem.prototype.handleTracksChange = function handleTracksChange(event) {
  18705. this.selected(this.track.mode === 'showing');
  18706. };
  18707. return TextTrackMenuItem;
  18708. }(_menuItem2['default']);
  18709. _component2['default'].registerComponent('TextTrackMenuItem', TextTrackMenuItem);
  18710. exports['default'] = TextTrackMenuItem;
  18711. /***/ }),
  18712. /* 94 */
  18713. /***/ (function(module, exports, __webpack_require__) {
  18714. 'use strict';
  18715. exports.__esModule = true;
  18716. var _clickableComponent = __webpack_require__(58);
  18717. var _clickableComponent2 = _interopRequireDefault(_clickableComponent);
  18718. var _component = __webpack_require__(19);
  18719. var _component2 = _interopRequireDefault(_component);
  18720. var _obj = __webpack_require__(14);
  18721. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  18722. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  18723. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  18724. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  18725. * @file menu-item.js
  18726. */
  18727. /**
  18728. * The component for a menu item. `<li>`
  18729. *
  18730. * @extends ClickableComponent
  18731. */
  18732. var MenuItem = function (_ClickableComponent) {
  18733. _inherits(MenuItem, _ClickableComponent);
  18734. /**
  18735. * Creates an instance of the this class.
  18736. *
  18737. * @param {Player} player
  18738. * The `Player` that this class should be attached to.
  18739. *
  18740. * @param {Object} [options={}]
  18741. * The key/value store of player options.
  18742. *
  18743. */
  18744. function MenuItem(player, options) {
  18745. _classCallCheck(this, MenuItem);
  18746. var _this = _possibleConstructorReturn(this, _ClickableComponent.call(this, player, options));
  18747. _this.selectable = options.selectable;
  18748. _this.selected(options.selected);
  18749. if (_this.selectable) {
  18750. // TODO: May need to be either menuitemcheckbox or menuitemradio,
  18751. // and may need logical grouping of menu items.
  18752. _this.el_.setAttribute('role', 'menuitemcheckbox');
  18753. } else {
  18754. _this.el_.setAttribute('role', 'menuitem');
  18755. }
  18756. return _this;
  18757. }
  18758. /**
  18759. * Create the `MenuItem's DOM element
  18760. *
  18761. * @param {string} [type=li]
  18762. * Element's node type, not actually used, always set to `li`.
  18763. *
  18764. * @param {Object} [props={}]
  18765. * An object of properties that should be set on the element
  18766. *
  18767. * @param {Object} [attrs={}]
  18768. * An object of attributes that should be set on the element
  18769. *
  18770. * @return {Element}
  18771. * The element that gets created.
  18772. */
  18773. MenuItem.prototype.createEl = function createEl(type, props, attrs) {
  18774. // The control is textual, not just an icon
  18775. this.nonIconControl = true;
  18776. return _ClickableComponent.prototype.createEl.call(this, 'li', (0, _obj.assign)({
  18777. className: 'vjs-menu-item',
  18778. innerHTML: this.localize(this.options_.label),
  18779. tabIndex: -1
  18780. }, props), attrs);
  18781. };
  18782. /**
  18783. * Any click on a `MenuItem` puts int into the selected state.
  18784. * See {@link ClickableComponent#handleClick} for instances where this is called.
  18785. *
  18786. * @param {EventTarget~Event} event
  18787. * The `keydown`, `tap`, or `click` event that caused this function to be
  18788. * called.
  18789. *
  18790. * @listens tap
  18791. * @listens click
  18792. */
  18793. MenuItem.prototype.handleClick = function handleClick(event) {
  18794. this.selected(true);
  18795. };
  18796. /**
  18797. * Set the state for this menu item as selected or not.
  18798. *
  18799. * @param {boolean} selected
  18800. * if the menu item is selected or not
  18801. */
  18802. MenuItem.prototype.selected = function selected(_selected) {
  18803. if (this.selectable) {
  18804. if (_selected) {
  18805. this.addClass('vjs-selected');
  18806. this.el_.setAttribute('aria-checked', 'true');
  18807. // aria-checked isn't fully supported by browsers/screen readers,
  18808. // so indicate selected state to screen reader in the control text.
  18809. this.controlText(', selected');
  18810. } else {
  18811. this.removeClass('vjs-selected');
  18812. this.el_.setAttribute('aria-checked', 'false');
  18813. // Indicate un-selected state to screen reader
  18814. // Note that a space clears out the selected state text
  18815. this.controlText(' ');
  18816. }
  18817. }
  18818. };
  18819. return MenuItem;
  18820. }(_clickableComponent2['default']);
  18821. _component2['default'].registerComponent('MenuItem', MenuItem);
  18822. exports['default'] = MenuItem;
  18823. /***/ }),
  18824. /* 95 */
  18825. /***/ (function(module, exports, __webpack_require__) {
  18826. 'use strict';
  18827. exports.__esModule = true;
  18828. var _textTrackMenuItem = __webpack_require__(93);
  18829. var _textTrackMenuItem2 = _interopRequireDefault(_textTrackMenuItem);
  18830. var _component = __webpack_require__(19);
  18831. var _component2 = _interopRequireDefault(_component);
  18832. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  18833. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  18834. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  18835. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  18836. * @file off-text-track-menu-item.js
  18837. */
  18838. /**
  18839. * A special menu item for turning of a specific type of text track
  18840. *
  18841. * @extends TextTrackMenuItem
  18842. */
  18843. var OffTextTrackMenuItem = function (_TextTrackMenuItem) {
  18844. _inherits(OffTextTrackMenuItem, _TextTrackMenuItem);
  18845. /**
  18846. * Creates an instance of this class.
  18847. *
  18848. * @param {Player} player
  18849. * The `Player` that this class should be attached to.
  18850. *
  18851. * @param {Object} [options]
  18852. * The key/value store of player options.
  18853. */
  18854. function OffTextTrackMenuItem(player, options) {
  18855. _classCallCheck(this, OffTextTrackMenuItem);
  18856. // Create pseudo track info
  18857. // Requires options['kind']
  18858. options.track = {
  18859. player: player,
  18860. kind: options.kind,
  18861. label: options.kind + ' off',
  18862. 'default': false,
  18863. mode: 'disabled'
  18864. };
  18865. // MenuItem is selectable
  18866. options.selectable = true;
  18867. var _this = _possibleConstructorReturn(this, _TextTrackMenuItem.call(this, player, options));
  18868. _this.selected(true);
  18869. return _this;
  18870. }
  18871. /**
  18872. * Handle text track change
  18873. *
  18874. * @param {EventTarget~Event} event
  18875. * The event that caused this function to run
  18876. */
  18877. OffTextTrackMenuItem.prototype.handleTracksChange = function handleTracksChange(event) {
  18878. var tracks = this.player().textTracks();
  18879. var selected = true;
  18880. for (var i = 0, l = tracks.length; i < l; i++) {
  18881. var track = tracks[i];
  18882. if (track.kind === this.track.kind && track.mode === 'showing') {
  18883. selected = false;
  18884. break;
  18885. }
  18886. }
  18887. this.selected(selected);
  18888. };
  18889. return OffTextTrackMenuItem;
  18890. }(_textTrackMenuItem2['default']);
  18891. _component2['default'].registerComponent('OffTextTrackMenuItem', OffTextTrackMenuItem);
  18892. exports['default'] = OffTextTrackMenuItem;
  18893. /***/ }),
  18894. /* 96 */
  18895. /***/ (function(module, exports, __webpack_require__) {
  18896. 'use strict';
  18897. exports.__esModule = true;
  18898. var _menuItem = __webpack_require__(94);
  18899. var _menuItem2 = _interopRequireDefault(_menuItem);
  18900. var _component = __webpack_require__(19);
  18901. var _component2 = _interopRequireDefault(_component);
  18902. var _fn = __webpack_require__(20);
  18903. var Fn = _interopRequireWildcard(_fn);
  18904. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  18905. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  18906. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  18907. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  18908. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  18909. * @file chapters-track-menu-item.js
  18910. */
  18911. /**
  18912. * The chapter track menu item
  18913. *
  18914. * @extends MenuItem
  18915. */
  18916. var ChaptersTrackMenuItem = function (_MenuItem) {
  18917. _inherits(ChaptersTrackMenuItem, _MenuItem);
  18918. /**
  18919. * Creates an instance of this class.
  18920. *
  18921. * @param {Player} player
  18922. * The `Player` that this class should be attached to.
  18923. *
  18924. * @param {Object} [options]
  18925. * The key/value store of player options.
  18926. */
  18927. function ChaptersTrackMenuItem(player, options) {
  18928. _classCallCheck(this, ChaptersTrackMenuItem);
  18929. var track = options.track;
  18930. var cue = options.cue;
  18931. var currentTime = player.currentTime();
  18932. // Modify options for parent MenuItem class's init.
  18933. options.selectable = true;
  18934. options.label = cue.text;
  18935. options.selected = cue.startTime <= currentTime && currentTime < cue.endTime;
  18936. var _this = _possibleConstructorReturn(this, _MenuItem.call(this, player, options));
  18937. _this.track = track;
  18938. _this.cue = cue;
  18939. track.addEventListener('cuechange', Fn.bind(_this, _this.update));
  18940. return _this;
  18941. }
  18942. /**
  18943. * This gets called when an `ChaptersTrackMenuItem` is "clicked". See
  18944. * {@link ClickableComponent} for more detailed information on what a click can be.
  18945. *
  18946. * @param {EventTarget~Event} [event]
  18947. * The `keydown`, `tap`, or `click` event that caused this function to be
  18948. * called.
  18949. *
  18950. * @listens tap
  18951. * @listens click
  18952. */
  18953. ChaptersTrackMenuItem.prototype.handleClick = function handleClick(event) {
  18954. _MenuItem.prototype.handleClick.call(this);
  18955. this.player_.currentTime(this.cue.startTime);
  18956. this.update(this.cue.startTime);
  18957. };
  18958. /**
  18959. * Update chapter menu item
  18960. *
  18961. * @param {EventTarget~Event} [event]
  18962. * The `cuechange` event that caused this function to run.
  18963. *
  18964. * @listens TextTrack#cuechange
  18965. */
  18966. ChaptersTrackMenuItem.prototype.update = function update(event) {
  18967. var cue = this.cue;
  18968. var currentTime = this.player_.currentTime();
  18969. // vjs.log(currentTime, cue.startTime);
  18970. this.selected(cue.startTime <= currentTime && currentTime < cue.endTime);
  18971. };
  18972. return ChaptersTrackMenuItem;
  18973. }(_menuItem2['default']);
  18974. _component2['default'].registerComponent('ChaptersTrackMenuItem', ChaptersTrackMenuItem);
  18975. exports['default'] = ChaptersTrackMenuItem;
  18976. /***/ }),
  18977. /* 97 */
  18978. /***/ (function(module, exports, __webpack_require__) {
  18979. 'use strict';
  18980. exports.__esModule = true;
  18981. var _textTrackButton = __webpack_require__(89);
  18982. var _textTrackButton2 = _interopRequireDefault(_textTrackButton);
  18983. var _component = __webpack_require__(19);
  18984. var _component2 = _interopRequireDefault(_component);
  18985. var _fn = __webpack_require__(20);
  18986. var Fn = _interopRequireWildcard(_fn);
  18987. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  18988. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  18989. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  18990. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  18991. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  18992. * @file descriptions-button.js
  18993. */
  18994. /**
  18995. * The button component for toggling and selecting descriptions
  18996. *
  18997. * @extends TextTrackButton
  18998. */
  18999. var DescriptionsButton = function (_TextTrackButton) {
  19000. _inherits(DescriptionsButton, _TextTrackButton);
  19001. /**
  19002. * Creates an instance of this class.
  19003. *
  19004. * @param {Player} player
  19005. * The `Player` that this class should be attached to.
  19006. *
  19007. * @param {Object} [options]
  19008. * The key/value store of player options.
  19009. *
  19010. * @param {Component~ReadyCallback} [ready]
  19011. * The function to call when this component is ready.
  19012. */
  19013. function DescriptionsButton(player, options, ready) {
  19014. _classCallCheck(this, DescriptionsButton);
  19015. var _this = _possibleConstructorReturn(this, _TextTrackButton.call(this, player, options, ready));
  19016. _this.el_.setAttribute('aria-label', 'Descriptions Menu');
  19017. var tracks = player.textTracks();
  19018. if (tracks) {
  19019. var changeHandler = Fn.bind(_this, _this.handleTracksChange);
  19020. tracks.addEventListener('change', changeHandler);
  19021. _this.on('dispose', function () {
  19022. tracks.removeEventListener('change', changeHandler);
  19023. });
  19024. }
  19025. return _this;
  19026. }
  19027. /**
  19028. * Handle text track change
  19029. *
  19030. * @param {EventTarget~Event} event
  19031. * The event that caused this function to run
  19032. *
  19033. * @listens TextTrackList#change
  19034. */
  19035. DescriptionsButton.prototype.handleTracksChange = function handleTracksChange(event) {
  19036. var tracks = this.player().textTracks();
  19037. var disabled = false;
  19038. // Check whether a track of a different kind is showing
  19039. for (var i = 0, l = tracks.length; i < l; i++) {
  19040. var track = tracks[i];
  19041. if (track.kind !== this.kind_ && track.mode === 'showing') {
  19042. disabled = true;
  19043. break;
  19044. }
  19045. }
  19046. // If another track is showing, disable this menu button
  19047. if (disabled) {
  19048. this.disable();
  19049. } else {
  19050. this.enable();
  19051. }
  19052. };
  19053. /**
  19054. * Builds the default DOM `className`.
  19055. *
  19056. * @return {string}
  19057. * The DOM `className` for this object.
  19058. */
  19059. DescriptionsButton.prototype.buildCSSClass = function buildCSSClass() {
  19060. return 'vjs-descriptions-button ' + _TextTrackButton.prototype.buildCSSClass.call(this);
  19061. };
  19062. return DescriptionsButton;
  19063. }(_textTrackButton2['default']);
  19064. /**
  19065. * `kind` of TextTrack to look for to associate it with this menu.
  19066. *
  19067. * @type {string}
  19068. * @private
  19069. */
  19070. DescriptionsButton.prototype.kind_ = 'descriptions';
  19071. /**
  19072. * The text that should display over the `DescriptionsButton`s controls. Added for localization.
  19073. *
  19074. * @type {string}
  19075. * @private
  19076. */
  19077. DescriptionsButton.prototype.controlText_ = 'Descriptions';
  19078. _component2['default'].registerComponent('DescriptionsButton', DescriptionsButton);
  19079. exports['default'] = DescriptionsButton;
  19080. /***/ }),
  19081. /* 98 */
  19082. /***/ (function(module, exports, __webpack_require__) {
  19083. 'use strict';
  19084. exports.__esModule = true;
  19085. var _textTrackButton = __webpack_require__(89);
  19086. var _textTrackButton2 = _interopRequireDefault(_textTrackButton);
  19087. var _component = __webpack_require__(19);
  19088. var _component2 = _interopRequireDefault(_component);
  19089. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  19090. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  19091. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  19092. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  19093. * @file subtitles-button.js
  19094. */
  19095. /**
  19096. * The button component for toggling and selecting subtitles
  19097. *
  19098. * @extends TextTrackButton
  19099. */
  19100. var SubtitlesButton = function (_TextTrackButton) {
  19101. _inherits(SubtitlesButton, _TextTrackButton);
  19102. /**
  19103. * Creates an instance of this class.
  19104. *
  19105. * @param {Player} player
  19106. * The `Player` that this class should be attached to.
  19107. *
  19108. * @param {Object} [options]
  19109. * The key/value store of player options.
  19110. *
  19111. * @param {Component~ReadyCallback} [ready]
  19112. * The function to call when this component is ready.
  19113. */
  19114. function SubtitlesButton(player, options, ready) {
  19115. _classCallCheck(this, SubtitlesButton);
  19116. var _this = _possibleConstructorReturn(this, _TextTrackButton.call(this, player, options, ready));
  19117. _this.el_.setAttribute('aria-label', 'Subtitles Menu');
  19118. return _this;
  19119. }
  19120. /**
  19121. * Builds the default DOM `className`.
  19122. *
  19123. * @return {string}
  19124. * The DOM `className` for this object.
  19125. */
  19126. SubtitlesButton.prototype.buildCSSClass = function buildCSSClass() {
  19127. return 'vjs-subtitles-button ' + _TextTrackButton.prototype.buildCSSClass.call(this);
  19128. };
  19129. return SubtitlesButton;
  19130. }(_textTrackButton2['default']);
  19131. /**
  19132. * `kind` of TextTrack to look for to associate it with this menu.
  19133. *
  19134. * @type {string}
  19135. * @private
  19136. */
  19137. SubtitlesButton.prototype.kind_ = 'subtitles';
  19138. /**
  19139. * The text that should display over the `SubtitlesButton`s controls. Added for localization.
  19140. *
  19141. * @type {string}
  19142. * @private
  19143. */
  19144. SubtitlesButton.prototype.controlText_ = 'Subtitles';
  19145. _component2['default'].registerComponent('SubtitlesButton', SubtitlesButton);
  19146. exports['default'] = SubtitlesButton;
  19147. /***/ }),
  19148. /* 99 */
  19149. /***/ (function(module, exports, __webpack_require__) {
  19150. 'use strict';
  19151. exports.__esModule = true;
  19152. var _textTrackButton = __webpack_require__(89);
  19153. var _textTrackButton2 = _interopRequireDefault(_textTrackButton);
  19154. var _component = __webpack_require__(19);
  19155. var _component2 = _interopRequireDefault(_component);
  19156. var _captionSettingsMenuItem = __webpack_require__(100);
  19157. var _captionSettingsMenuItem2 = _interopRequireDefault(_captionSettingsMenuItem);
  19158. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  19159. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  19160. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  19161. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  19162. * @file captions-button.js
  19163. */
  19164. /**
  19165. * The button component for toggling and selecting captions
  19166. *
  19167. * @extends TextTrackButton
  19168. */
  19169. var CaptionsButton = function (_TextTrackButton) {
  19170. _inherits(CaptionsButton, _TextTrackButton);
  19171. /**
  19172. * Creates an instance of this class.
  19173. *
  19174. * @param {Player} player
  19175. * The `Player` that this class should be attached to.
  19176. *
  19177. * @param {Object} [options]
  19178. * The key/value store of player options.
  19179. *
  19180. * @param {Component~ReadyCallback} [ready]
  19181. * The function to call when this component is ready.
  19182. */
  19183. function CaptionsButton(player, options, ready) {
  19184. _classCallCheck(this, CaptionsButton);
  19185. var _this = _possibleConstructorReturn(this, _TextTrackButton.call(this, player, options, ready));
  19186. _this.el_.setAttribute('aria-label', 'Captions Menu');
  19187. return _this;
  19188. }
  19189. /**
  19190. * Builds the default DOM `className`.
  19191. *
  19192. * @return {string}
  19193. * The DOM `className` for this object.
  19194. */
  19195. CaptionsButton.prototype.buildCSSClass = function buildCSSClass() {
  19196. return 'vjs-captions-button ' + _TextTrackButton.prototype.buildCSSClass.call(this);
  19197. };
  19198. /**
  19199. * Create caption menu items
  19200. *
  19201. * @return {CaptionSettingsMenuItem[]}
  19202. * The array of current menu items.
  19203. */
  19204. CaptionsButton.prototype.createItems = function createItems() {
  19205. var items = [];
  19206. if (!(this.player().tech_ && this.player().tech_.featuresNativeTextTracks)) {
  19207. items.push(new _captionSettingsMenuItem2['default'](this.player_, { kind: this.kind_ }));
  19208. this.hideThreshold_ += 1;
  19209. }
  19210. return _TextTrackButton.prototype.createItems.call(this, items);
  19211. };
  19212. return CaptionsButton;
  19213. }(_textTrackButton2['default']);
  19214. /**
  19215. * `kind` of TextTrack to look for to associate it with this menu.
  19216. *
  19217. * @type {string}
  19218. * @private
  19219. */
  19220. CaptionsButton.prototype.kind_ = 'captions';
  19221. /**
  19222. * The text that should display over the `CaptionsButton`s controls. Added for localization.
  19223. *
  19224. * @type {string}
  19225. * @private
  19226. */
  19227. CaptionsButton.prototype.controlText_ = 'Captions';
  19228. _component2['default'].registerComponent('CaptionsButton', CaptionsButton);
  19229. exports['default'] = CaptionsButton;
  19230. /***/ }),
  19231. /* 100 */
  19232. /***/ (function(module, exports, __webpack_require__) {
  19233. 'use strict';
  19234. exports.__esModule = true;
  19235. var _textTrackMenuItem = __webpack_require__(93);
  19236. var _textTrackMenuItem2 = _interopRequireDefault(_textTrackMenuItem);
  19237. var _component = __webpack_require__(19);
  19238. var _component2 = _interopRequireDefault(_component);
  19239. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  19240. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  19241. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  19242. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  19243. * @file caption-settings-menu-item.js
  19244. */
  19245. /**
  19246. * The menu item for caption track settings menu
  19247. *
  19248. * @extends TextTrackMenuItem
  19249. */
  19250. var CaptionSettingsMenuItem = function (_TextTrackMenuItem) {
  19251. _inherits(CaptionSettingsMenuItem, _TextTrackMenuItem);
  19252. /**
  19253. * Creates an instance of this class.
  19254. *
  19255. * @param {Player} player
  19256. * The `Player` that this class should be attached to.
  19257. *
  19258. * @param {Object} [options]
  19259. * The key/value store of player options.
  19260. */
  19261. function CaptionSettingsMenuItem(player, options) {
  19262. _classCallCheck(this, CaptionSettingsMenuItem);
  19263. options.track = {
  19264. player: player,
  19265. kind: options.kind,
  19266. label: options.kind + ' settings',
  19267. selectable: false,
  19268. 'default': false,
  19269. mode: 'disabled'
  19270. };
  19271. // CaptionSettingsMenuItem has no concept of 'selected'
  19272. options.selectable = false;
  19273. var _this = _possibleConstructorReturn(this, _TextTrackMenuItem.call(this, player, options));
  19274. _this.addClass('vjs-texttrack-settings');
  19275. _this.controlText(', opens ' + options.kind + ' settings dialog');
  19276. return _this;
  19277. }
  19278. /**
  19279. * This gets called when an `CaptionSettingsMenuItem` is "clicked". See
  19280. * {@link ClickableComponent} for more detailed information on what a click can be.
  19281. *
  19282. * @param {EventTarget~Event} [event]
  19283. * The `keydown`, `tap`, or `click` event that caused this function to be
  19284. * called.
  19285. *
  19286. * @listens tap
  19287. * @listens click
  19288. */
  19289. CaptionSettingsMenuItem.prototype.handleClick = function handleClick(event) {
  19290. this.player().getChild('textTrackSettings').show();
  19291. this.player().getChild('textTrackSettings').el_.focus();
  19292. };
  19293. return CaptionSettingsMenuItem;
  19294. }(_textTrackMenuItem2['default']);
  19295. _component2['default'].registerComponent('CaptionSettingsMenuItem', CaptionSettingsMenuItem);
  19296. exports['default'] = CaptionSettingsMenuItem;
  19297. /***/ }),
  19298. /* 101 */
  19299. /***/ (function(module, exports, __webpack_require__) {
  19300. 'use strict';
  19301. exports.__esModule = true;
  19302. var _trackButton = __webpack_require__(90);
  19303. var _trackButton2 = _interopRequireDefault(_trackButton);
  19304. var _component = __webpack_require__(19);
  19305. var _component2 = _interopRequireDefault(_component);
  19306. var _audioTrackMenuItem = __webpack_require__(102);
  19307. var _audioTrackMenuItem2 = _interopRequireDefault(_audioTrackMenuItem);
  19308. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  19309. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  19310. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  19311. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  19312. * @file audio-track-button.js
  19313. */
  19314. /**
  19315. * The base class for buttons that toggle specific {@link AudioTrack} types.
  19316. *
  19317. * @extends TrackButton
  19318. */
  19319. var AudioTrackButton = function (_TrackButton) {
  19320. _inherits(AudioTrackButton, _TrackButton);
  19321. /**
  19322. * Creates an instance of this class.
  19323. *
  19324. * @param {Player} player
  19325. * The `Player` that this class should be attached to.
  19326. *
  19327. * @param {Object} [options={}]
  19328. * The key/value store of player options.
  19329. */
  19330. function AudioTrackButton(player) {
  19331. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  19332. _classCallCheck(this, AudioTrackButton);
  19333. options.tracks = player.audioTracks && player.audioTracks();
  19334. var _this = _possibleConstructorReturn(this, _TrackButton.call(this, player, options));
  19335. _this.el_.setAttribute('aria-label', 'Audio Menu');
  19336. return _this;
  19337. }
  19338. /**
  19339. * Builds the default DOM `className`.
  19340. *
  19341. * @return {string}
  19342. * The DOM `className` for this object.
  19343. */
  19344. AudioTrackButton.prototype.buildCSSClass = function buildCSSClass() {
  19345. return 'vjs-audio-button ' + _TrackButton.prototype.buildCSSClass.call(this);
  19346. };
  19347. /**
  19348. * Create a menu item for each audio track
  19349. *
  19350. * @param {AudioTrackMenuItem[]} [items=[]]
  19351. * An array of existing menu items to use.
  19352. *
  19353. * @return {AudioTrackMenuItem[]}
  19354. * An array of menu items
  19355. */
  19356. AudioTrackButton.prototype.createItems = function createItems() {
  19357. var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  19358. // if there's only one audio track, there no point in showing it
  19359. this.hideThreshold_ = 1;
  19360. var tracks = this.player_.audioTracks && this.player_.audioTracks();
  19361. if (!tracks) {
  19362. return items;
  19363. }
  19364. for (var i = 0; i < tracks.length; i++) {
  19365. var track = tracks[i];
  19366. items.push(new _audioTrackMenuItem2['default'](this.player_, {
  19367. track: track,
  19368. // MenuItem is selectable
  19369. selectable: true
  19370. }));
  19371. }
  19372. return items;
  19373. };
  19374. return AudioTrackButton;
  19375. }(_trackButton2['default']);
  19376. /**
  19377. * The text that should display over the `AudioTrackButton`s controls. Added for localization.
  19378. *
  19379. * @type {string}
  19380. * @private
  19381. */
  19382. AudioTrackButton.prototype.controlText_ = 'Audio Track';
  19383. _component2['default'].registerComponent('AudioTrackButton', AudioTrackButton);
  19384. exports['default'] = AudioTrackButton;
  19385. /***/ }),
  19386. /* 102 */
  19387. /***/ (function(module, exports, __webpack_require__) {
  19388. 'use strict';
  19389. exports.__esModule = true;
  19390. var _menuItem = __webpack_require__(94);
  19391. var _menuItem2 = _interopRequireDefault(_menuItem);
  19392. var _component = __webpack_require__(19);
  19393. var _component2 = _interopRequireDefault(_component);
  19394. var _fn = __webpack_require__(20);
  19395. var Fn = _interopRequireWildcard(_fn);
  19396. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  19397. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  19398. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  19399. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  19400. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  19401. * @file audio-track-menu-item.js
  19402. */
  19403. /**
  19404. * An {@link AudioTrack} {@link MenuItem}
  19405. *
  19406. * @extends MenuItem
  19407. */
  19408. var AudioTrackMenuItem = function (_MenuItem) {
  19409. _inherits(AudioTrackMenuItem, _MenuItem);
  19410. /**
  19411. * Creates an instance of this class.
  19412. *
  19413. * @param {Player} player
  19414. * The `Player` that this class should be attached to.
  19415. *
  19416. * @param {Object} [options]
  19417. * The key/value store of player options.
  19418. */
  19419. function AudioTrackMenuItem(player, options) {
  19420. _classCallCheck(this, AudioTrackMenuItem);
  19421. var track = options.track;
  19422. var tracks = player.audioTracks();
  19423. // Modify options for parent MenuItem class's init.
  19424. options.label = track.label || track.language || 'Unknown';
  19425. options.selected = track.enabled;
  19426. var _this = _possibleConstructorReturn(this, _MenuItem.call(this, player, options));
  19427. _this.track = track;
  19428. if (tracks) {
  19429. var changeHandler = Fn.bind(_this, _this.handleTracksChange);
  19430. tracks.addEventListener('change', changeHandler);
  19431. _this.on('dispose', function () {
  19432. tracks.removeEventListener('change', changeHandler);
  19433. });
  19434. }
  19435. return _this;
  19436. }
  19437. /**
  19438. * This gets called when an `AudioTrackMenuItem is "clicked". See {@link ClickableComponent}
  19439. * for more detailed information on what a click can be.
  19440. *
  19441. * @param {EventTarget~Event} [event]
  19442. * The `keydown`, `tap`, or `click` event that caused this function to be
  19443. * called.
  19444. *
  19445. * @listens tap
  19446. * @listens click
  19447. */
  19448. AudioTrackMenuItem.prototype.handleClick = function handleClick(event) {
  19449. var tracks = this.player_.audioTracks();
  19450. _MenuItem.prototype.handleClick.call(this, event);
  19451. if (!tracks) {
  19452. return;
  19453. }
  19454. for (var i = 0; i < tracks.length; i++) {
  19455. var track = tracks[i];
  19456. track.enabled = track === this.track;
  19457. }
  19458. };
  19459. /**
  19460. * Handle any {@link AudioTrack} change.
  19461. *
  19462. * @param {EventTarget~Event} [event]
  19463. * The {@link AudioTrackList#change} event that caused this to run.
  19464. *
  19465. * @listens AudioTrackList#change
  19466. */
  19467. AudioTrackMenuItem.prototype.handleTracksChange = function handleTracksChange(event) {
  19468. this.selected(this.track.enabled);
  19469. };
  19470. return AudioTrackMenuItem;
  19471. }(_menuItem2['default']);
  19472. _component2['default'].registerComponent('AudioTrackMenuItem', AudioTrackMenuItem);
  19473. exports['default'] = AudioTrackMenuItem;
  19474. /***/ }),
  19475. /* 103 */
  19476. /***/ (function(module, exports, __webpack_require__) {
  19477. 'use strict';
  19478. exports.__esModule = true;
  19479. var _menuButton = __webpack_require__(91);
  19480. var _menuButton2 = _interopRequireDefault(_menuButton);
  19481. var _menu = __webpack_require__(92);
  19482. var _menu2 = _interopRequireDefault(_menu);
  19483. var _playbackRateMenuItem = __webpack_require__(104);
  19484. var _playbackRateMenuItem2 = _interopRequireDefault(_playbackRateMenuItem);
  19485. var _component = __webpack_require__(19);
  19486. var _component2 = _interopRequireDefault(_component);
  19487. var _dom = __webpack_require__(11);
  19488. var Dom = _interopRequireWildcard(_dom);
  19489. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  19490. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  19491. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  19492. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  19493. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  19494. * @file playback-rate-menu-button.js
  19495. */
  19496. /**
  19497. * The component for controlling the playback rate.
  19498. *
  19499. * @extends MenuButton
  19500. */
  19501. var PlaybackRateMenuButton = function (_MenuButton) {
  19502. _inherits(PlaybackRateMenuButton, _MenuButton);
  19503. /**
  19504. * Creates an instance of this class.
  19505. *
  19506. * @param {Player} player
  19507. * The `Player` that this class should be attached to.
  19508. *
  19509. * @param {Object} [options]
  19510. * The key/value store of player options.
  19511. */
  19512. function PlaybackRateMenuButton(player, options) {
  19513. _classCallCheck(this, PlaybackRateMenuButton);
  19514. var _this = _possibleConstructorReturn(this, _MenuButton.call(this, player, options));
  19515. _this.updateVisibility();
  19516. _this.updateLabel();
  19517. _this.on(player, 'loadstart', _this.updateVisibility);
  19518. _this.on(player, 'ratechange', _this.updateLabel);
  19519. return _this;
  19520. }
  19521. /**
  19522. * Create the `Component`'s DOM element
  19523. *
  19524. * @return {Element}
  19525. * The element that was created.
  19526. */
  19527. PlaybackRateMenuButton.prototype.createEl = function createEl() {
  19528. var el = _MenuButton.prototype.createEl.call(this);
  19529. this.labelEl_ = Dom.createEl('div', {
  19530. className: 'vjs-playback-rate-value',
  19531. innerHTML: 1.0
  19532. });
  19533. el.appendChild(this.labelEl_);
  19534. return el;
  19535. };
  19536. /**
  19537. * Builds the default DOM `className`.
  19538. *
  19539. * @return {string}
  19540. * The DOM `className` for this object.
  19541. */
  19542. PlaybackRateMenuButton.prototype.buildCSSClass = function buildCSSClass() {
  19543. return 'vjs-playback-rate ' + _MenuButton.prototype.buildCSSClass.call(this);
  19544. };
  19545. /**
  19546. * Create the playback rate menu
  19547. *
  19548. * @return {Menu}
  19549. * Menu object populated with {@link PlaybackRateMenuItem}s
  19550. */
  19551. PlaybackRateMenuButton.prototype.createMenu = function createMenu() {
  19552. var menu = new _menu2['default'](this.player());
  19553. var rates = this.playbackRates();
  19554. if (rates) {
  19555. for (var i = rates.length - 1; i >= 0; i--) {
  19556. menu.addChild(new _playbackRateMenuItem2['default'](this.player(), { rate: rates[i] + 'x' }));
  19557. }
  19558. }
  19559. return menu;
  19560. };
  19561. /**
  19562. * Updates ARIA accessibility attributes
  19563. */
  19564. PlaybackRateMenuButton.prototype.updateARIAAttributes = function updateARIAAttributes() {
  19565. // Current playback rate
  19566. this.el().setAttribute('aria-valuenow', this.player().playbackRate());
  19567. };
  19568. /**
  19569. * This gets called when an `PlaybackRateMenuButton` is "clicked". See
  19570. * {@link ClickableComponent} for more detailed information on what a click can be.
  19571. *
  19572. * @param {EventTarget~Event} [event]
  19573. * The `keydown`, `tap`, or `click` event that caused this function to be
  19574. * called.
  19575. *
  19576. * @listens tap
  19577. * @listens click
  19578. */
  19579. PlaybackRateMenuButton.prototype.handleClick = function handleClick(event) {
  19580. // select next rate option
  19581. var currentRate = this.player().playbackRate();
  19582. var rates = this.playbackRates();
  19583. // this will select first one if the last one currently selected
  19584. var newRate = rates[0];
  19585. for (var i = 0; i < rates.length; i++) {
  19586. if (rates[i] > currentRate) {
  19587. newRate = rates[i];
  19588. break;
  19589. }
  19590. }
  19591. this.player().playbackRate(newRate);
  19592. };
  19593. /**
  19594. * Get possible playback rates
  19595. *
  19596. * @return {Array}
  19597. * All possible playback rates
  19598. */
  19599. PlaybackRateMenuButton.prototype.playbackRates = function playbackRates() {
  19600. return this.options_.playbackRates || this.options_.playerOptions && this.options_.playerOptions.playbackRates;
  19601. };
  19602. /**
  19603. * Get whether playback rates is supported by the tech
  19604. * and an array of playback rates exists
  19605. *
  19606. * @return {boolean}
  19607. * Whether changing playback rate is supported
  19608. */
  19609. PlaybackRateMenuButton.prototype.playbackRateSupported = function playbackRateSupported() {
  19610. return this.player().tech_ && this.player().tech_.featuresPlaybackRate && this.playbackRates() && this.playbackRates().length > 0;
  19611. };
  19612. /**
  19613. * Hide playback rate controls when they're no playback rate options to select
  19614. *
  19615. * @param {EventTarget~Event} [event]
  19616. * The event that caused this function to run.
  19617. *
  19618. * @listens Player#loadstart
  19619. */
  19620. PlaybackRateMenuButton.prototype.updateVisibility = function updateVisibility(event) {
  19621. if (this.playbackRateSupported()) {
  19622. this.removeClass('vjs-hidden');
  19623. } else {
  19624. this.addClass('vjs-hidden');
  19625. }
  19626. };
  19627. /**
  19628. * Update button label when rate changed
  19629. *
  19630. * @param {EventTarget~Event} [event]
  19631. * The event that caused this function to run.
  19632. *
  19633. * @listens Player#ratechange
  19634. */
  19635. PlaybackRateMenuButton.prototype.updateLabel = function updateLabel(event) {
  19636. if (this.playbackRateSupported()) {
  19637. this.labelEl_.innerHTML = this.player().playbackRate() + 'x';
  19638. }
  19639. };
  19640. return PlaybackRateMenuButton;
  19641. }(_menuButton2['default']);
  19642. /**
  19643. * The text that should display over the `FullscreenToggle`s controls. Added for localization.
  19644. *
  19645. * @type {string}
  19646. * @private
  19647. */
  19648. PlaybackRateMenuButton.prototype.controlText_ = 'Playback Rate';
  19649. _component2['default'].registerComponent('PlaybackRateMenuButton', PlaybackRateMenuButton);
  19650. exports['default'] = PlaybackRateMenuButton;
  19651. /***/ }),
  19652. /* 104 */
  19653. /***/ (function(module, exports, __webpack_require__) {
  19654. 'use strict';
  19655. exports.__esModule = true;
  19656. var _menuItem = __webpack_require__(94);
  19657. var _menuItem2 = _interopRequireDefault(_menuItem);
  19658. var _component = __webpack_require__(19);
  19659. var _component2 = _interopRequireDefault(_component);
  19660. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  19661. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  19662. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  19663. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  19664. * @file playback-rate-menu-item.js
  19665. */
  19666. /**
  19667. * The specific menu item type for selecting a playback rate.
  19668. *
  19669. * @extends MenuItem
  19670. */
  19671. var PlaybackRateMenuItem = function (_MenuItem) {
  19672. _inherits(PlaybackRateMenuItem, _MenuItem);
  19673. /**
  19674. * Creates an instance of this class.
  19675. *
  19676. * @param {Player} player
  19677. * The `Player` that this class should be attached to.
  19678. *
  19679. * @param {Object} [options]
  19680. * The key/value store of player options.
  19681. */
  19682. function PlaybackRateMenuItem(player, options) {
  19683. _classCallCheck(this, PlaybackRateMenuItem);
  19684. var label = options.rate;
  19685. var rate = parseFloat(label, 10);
  19686. // Modify options for parent MenuItem class's init.
  19687. options.label = label;
  19688. options.selected = rate === 1;
  19689. options.selectable = true;
  19690. var _this = _possibleConstructorReturn(this, _MenuItem.call(this, player, options));
  19691. _this.label = label;
  19692. _this.rate = rate;
  19693. _this.on(player, 'ratechange', _this.update);
  19694. return _this;
  19695. }
  19696. /**
  19697. * This gets called when an `PlaybackRateMenuItem` is "clicked". See
  19698. * {@link ClickableComponent} for more detailed information on what a click can be.
  19699. *
  19700. * @param {EventTarget~Event} [event]
  19701. * The `keydown`, `tap`, or `click` event that caused this function to be
  19702. * called.
  19703. *
  19704. * @listens tap
  19705. * @listens click
  19706. */
  19707. PlaybackRateMenuItem.prototype.handleClick = function handleClick(event) {
  19708. _MenuItem.prototype.handleClick.call(this);
  19709. this.player().playbackRate(this.rate);
  19710. };
  19711. /**
  19712. * Update the PlaybackRateMenuItem when the playbackrate changes.
  19713. *
  19714. * @param {EventTarget~Event} [event]
  19715. * The `ratechange` event that caused this function to run.
  19716. *
  19717. * @listens Player#ratechange
  19718. */
  19719. PlaybackRateMenuItem.prototype.update = function update(event) {
  19720. this.selected(this.player().playbackRate() === this.rate);
  19721. };
  19722. return PlaybackRateMenuItem;
  19723. }(_menuItem2['default']);
  19724. /**
  19725. * The text that should display over the `PlaybackRateMenuItem`s controls. Added for localization.
  19726. *
  19727. * @type {string}
  19728. * @private
  19729. */
  19730. PlaybackRateMenuItem.prototype.contentElType = 'button';
  19731. _component2['default'].registerComponent('PlaybackRateMenuItem', PlaybackRateMenuItem);
  19732. exports['default'] = PlaybackRateMenuItem;
  19733. /***/ }),
  19734. /* 105 */
  19735. /***/ (function(module, exports, __webpack_require__) {
  19736. 'use strict';
  19737. exports.__esModule = true;
  19738. var _spacer = __webpack_require__(106);
  19739. var _spacer2 = _interopRequireDefault(_spacer);
  19740. var _component = __webpack_require__(19);
  19741. var _component2 = _interopRequireDefault(_component);
  19742. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  19743. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  19744. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  19745. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  19746. * @file custom-control-spacer.js
  19747. */
  19748. /**
  19749. * Spacer specifically meant to be used as an insertion point for new plugins, etc.
  19750. *
  19751. * @extends Spacer
  19752. */
  19753. var CustomControlSpacer = function (_Spacer) {
  19754. _inherits(CustomControlSpacer, _Spacer);
  19755. function CustomControlSpacer() {
  19756. _classCallCheck(this, CustomControlSpacer);
  19757. return _possibleConstructorReturn(this, _Spacer.apply(this, arguments));
  19758. }
  19759. /**
  19760. * Builds the default DOM `className`.
  19761. *
  19762. * @return {string}
  19763. * The DOM `className` for this object.
  19764. */
  19765. CustomControlSpacer.prototype.buildCSSClass = function buildCSSClass() {
  19766. return 'vjs-custom-control-spacer ' + _Spacer.prototype.buildCSSClass.call(this);
  19767. };
  19768. /**
  19769. * Create the `Component`'s DOM element
  19770. *
  19771. * @return {Element}
  19772. * The element that was created.
  19773. */
  19774. CustomControlSpacer.prototype.createEl = function createEl() {
  19775. var el = _Spacer.prototype.createEl.call(this, {
  19776. className: this.buildCSSClass()
  19777. });
  19778. // No-flex/table-cell mode requires there be some content
  19779. // in the cell to fill the remaining space of the table.
  19780. el.innerHTML = '&nbsp;';
  19781. return el;
  19782. };
  19783. return CustomControlSpacer;
  19784. }(_spacer2['default']);
  19785. _component2['default'].registerComponent('CustomControlSpacer', CustomControlSpacer);
  19786. exports['default'] = CustomControlSpacer;
  19787. /***/ }),
  19788. /* 106 */
  19789. /***/ (function(module, exports, __webpack_require__) {
  19790. 'use strict';
  19791. exports.__esModule = true;
  19792. var _component = __webpack_require__(19);
  19793. var _component2 = _interopRequireDefault(_component);
  19794. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  19795. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  19796. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  19797. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  19798. * @file spacer.js
  19799. */
  19800. /**
  19801. * Just an empty spacer element that can be used as an append point for plugins, etc.
  19802. * Also can be used to create space between elements when necessary.
  19803. *
  19804. * @extends Component
  19805. */
  19806. var Spacer = function (_Component) {
  19807. _inherits(Spacer, _Component);
  19808. function Spacer() {
  19809. _classCallCheck(this, Spacer);
  19810. return _possibleConstructorReturn(this, _Component.apply(this, arguments));
  19811. }
  19812. /**
  19813. * Builds the default DOM `className`.
  19814. *
  19815. * @return {string}
  19816. * The DOM `className` for this object.
  19817. */
  19818. Spacer.prototype.buildCSSClass = function buildCSSClass() {
  19819. return 'vjs-spacer ' + _Component.prototype.buildCSSClass.call(this);
  19820. };
  19821. /**
  19822. * Create the `Component`'s DOM element
  19823. *
  19824. * @return {Element}
  19825. * The element that was created.
  19826. */
  19827. Spacer.prototype.createEl = function createEl() {
  19828. return _Component.prototype.createEl.call(this, 'div', {
  19829. className: this.buildCSSClass()
  19830. });
  19831. };
  19832. return Spacer;
  19833. }(_component2['default']);
  19834. _component2['default'].registerComponent('Spacer', Spacer);
  19835. exports['default'] = Spacer;
  19836. /***/ }),
  19837. /* 107 */
  19838. /***/ (function(module, exports, __webpack_require__) {
  19839. 'use strict';
  19840. exports.__esModule = true;
  19841. var _component = __webpack_require__(19);
  19842. var _component2 = _interopRequireDefault(_component);
  19843. var _modalDialog = __webpack_require__(31);
  19844. var _modalDialog2 = _interopRequireDefault(_modalDialog);
  19845. var _mergeOptions = __webpack_require__(22);
  19846. var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
  19847. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  19848. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  19849. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  19850. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  19851. * @file error-display.js
  19852. */
  19853. /**
  19854. * A display that indicates an error has occurred. This means that the video
  19855. * is unplayable.
  19856. *
  19857. * @extends ModalDialog
  19858. */
  19859. var ErrorDisplay = function (_ModalDialog) {
  19860. _inherits(ErrorDisplay, _ModalDialog);
  19861. /**
  19862. * Creates an instance of this class.
  19863. *
  19864. * @param {Player} player
  19865. * The `Player` that this class should be attached to.
  19866. *
  19867. * @param {Object} [options]
  19868. * The key/value store of player options.
  19869. */
  19870. function ErrorDisplay(player, options) {
  19871. _classCallCheck(this, ErrorDisplay);
  19872. var _this = _possibleConstructorReturn(this, _ModalDialog.call(this, player, options));
  19873. _this.on(player, 'error', _this.open);
  19874. return _this;
  19875. }
  19876. /**
  19877. * Builds the default DOM `className`.
  19878. *
  19879. * @return {string}
  19880. * The DOM `className` for this object.
  19881. *
  19882. * @deprecated Since version 5.
  19883. */
  19884. ErrorDisplay.prototype.buildCSSClass = function buildCSSClass() {
  19885. return 'vjs-error-display ' + _ModalDialog.prototype.buildCSSClass.call(this);
  19886. };
  19887. /**
  19888. * Gets the localized error message based on the `Player`s error.
  19889. *
  19890. * @return {string}
  19891. * The `Player`s error message localized or an empty string.
  19892. */
  19893. ErrorDisplay.prototype.content = function content() {
  19894. var error = this.player().error();
  19895. return error ? this.localize(error.message) : '';
  19896. };
  19897. return ErrorDisplay;
  19898. }(_modalDialog2['default']);
  19899. /**
  19900. * The default options for an `ErrorDisplay`.
  19901. *
  19902. * @private
  19903. */
  19904. ErrorDisplay.prototype.options_ = (0, _mergeOptions2['default'])(_modalDialog2['default'].prototype.options_, {
  19905. pauseOnOpen: false,
  19906. fillAlways: true,
  19907. temporary: false,
  19908. uncloseable: true
  19909. });
  19910. _component2['default'].registerComponent('ErrorDisplay', ErrorDisplay);
  19911. exports['default'] = ErrorDisplay;
  19912. /***/ }),
  19913. /* 108 */
  19914. /***/ (function(module, exports, __webpack_require__) {
  19915. 'use strict';
  19916. exports.__esModule = true;
  19917. var _window = __webpack_require__(7);
  19918. var _window2 = _interopRequireDefault(_window);
  19919. var _component = __webpack_require__(19);
  19920. var _component2 = _interopRequireDefault(_component);
  19921. var _dom = __webpack_require__(11);
  19922. var _fn = __webpack_require__(20);
  19923. var Fn = _interopRequireWildcard(_fn);
  19924. var _obj = __webpack_require__(14);
  19925. var Obj = _interopRequireWildcard(_obj);
  19926. var _log = __webpack_require__(13);
  19927. var _log2 = _interopRequireDefault(_log);
  19928. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  19929. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  19930. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  19931. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  19932. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  19933. * @file text-track-settings.js
  19934. */
  19935. var LOCAL_STORAGE_KEY = 'vjs-text-track-settings';
  19936. var COLOR_BLACK = ['#000', 'Black'];
  19937. var COLOR_BLUE = ['#00F', 'Blue'];
  19938. var COLOR_CYAN = ['#0FF', 'Cyan'];
  19939. var COLOR_GREEN = ['#0F0', 'Green'];
  19940. var COLOR_MAGENTA = ['#F0F', 'Magenta'];
  19941. var COLOR_RED = ['#F00', 'Red'];
  19942. var COLOR_WHITE = ['#FFF', 'White'];
  19943. var COLOR_YELLOW = ['#FF0', 'Yellow'];
  19944. var OPACITY_OPAQUE = ['1', 'Opaque'];
  19945. var OPACITY_SEMI = ['0.5', 'Semi-Transparent'];
  19946. var OPACITY_TRANS = ['0', 'Transparent'];
  19947. // Configuration for the various <select> elements in the DOM of this component.
  19948. //
  19949. // Possible keys include:
  19950. //
  19951. // `default`:
  19952. // The default option index. Only needs to be provided if not zero.
  19953. // `parser`:
  19954. // A function which is used to parse the value from the selected option in
  19955. // a customized way.
  19956. // `selector`:
  19957. // The selector used to find the associated <select> element.
  19958. var selectConfigs = {
  19959. backgroundColor: {
  19960. selector: '.vjs-bg-color > select',
  19961. id: 'captions-background-color-%s',
  19962. label: 'Color',
  19963. options: [COLOR_BLACK, COLOR_WHITE, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_YELLOW, COLOR_MAGENTA, COLOR_CYAN]
  19964. },
  19965. backgroundOpacity: {
  19966. selector: '.vjs-bg-opacity > select',
  19967. id: 'captions-background-opacity-%s',
  19968. label: 'Transparency',
  19969. options: [OPACITY_OPAQUE, OPACITY_SEMI, OPACITY_TRANS]
  19970. },
  19971. color: {
  19972. selector: '.vjs-fg-color > select',
  19973. id: 'captions-foreground-color-%s',
  19974. label: 'Color',
  19975. options: [COLOR_WHITE, COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_YELLOW, COLOR_MAGENTA, COLOR_CYAN]
  19976. },
  19977. edgeStyle: {
  19978. selector: '.vjs-edge-style > select',
  19979. id: '%s',
  19980. label: 'Text Edge Style',
  19981. options: [['none', 'None'], ['raised', 'Raised'], ['depressed', 'Depressed'], ['uniform', 'Uniform'], ['dropshadow', 'Dropshadow']]
  19982. },
  19983. fontFamily: {
  19984. selector: '.vjs-font-family > select',
  19985. id: 'captions-font-family-%s',
  19986. label: 'Font Family',
  19987. options: [['proportionalSansSerif', 'Proportional Sans-Serif'], ['monospaceSansSerif', 'Monospace Sans-Serif'], ['proportionalSerif', 'Proportional Serif'], ['monospaceSerif', 'Monospace Serif'], ['casual', 'Casual'], ['script', 'Script'], ['small-caps', 'Small Caps']]
  19988. },
  19989. fontPercent: {
  19990. selector: '.vjs-font-percent > select',
  19991. id: 'captions-font-size-%s',
  19992. label: 'Font Size',
  19993. options: [['0.50', '50%'], ['0.75', '75%'], ['1.00', '100%'], ['1.25', '125%'], ['1.50', '150%'], ['1.75', '175%'], ['2.00', '200%'], ['3.00', '300%'], ['4.00', '400%']],
  19994. 'default': 2,
  19995. parser: function parser(v) {
  19996. return v === '1.00' ? null : Number(v);
  19997. }
  19998. },
  19999. textOpacity: {
  20000. selector: '.vjs-text-opacity > select',
  20001. id: 'captions-foreground-opacity-%s',
  20002. label: 'Transparency',
  20003. options: [OPACITY_OPAQUE, OPACITY_SEMI]
  20004. },
  20005. // Options for this object are defined below.
  20006. windowColor: {
  20007. selector: '.vjs-window-color > select',
  20008. id: 'captions-window-color-%s',
  20009. label: 'Color'
  20010. },
  20011. // Options for this object are defined below.
  20012. windowOpacity: {
  20013. selector: '.vjs-window-opacity > select',
  20014. id: 'captions-window-opacity-%s',
  20015. label: 'Transparency',
  20016. options: [OPACITY_TRANS, OPACITY_SEMI, OPACITY_OPAQUE]
  20017. }
  20018. };
  20019. selectConfigs.windowColor.options = selectConfigs.backgroundColor.options;
  20020. /**
  20021. * Get the actual value of an option.
  20022. *
  20023. * @param {string} value
  20024. * The value to get
  20025. *
  20026. * @param {Function} [parser]
  20027. * Optional function to adjust the value.
  20028. *
  20029. * @return {Mixed}
  20030. * - Will be `undefined` if no value exists
  20031. * - Will be `undefined` if the given value is "none".
  20032. * - Will be the actual value otherwise.
  20033. *
  20034. * @private
  20035. */
  20036. function parseOptionValue(value, parser) {
  20037. if (parser) {
  20038. value = parser(value);
  20039. }
  20040. if (value && value !== 'none') {
  20041. return value;
  20042. }
  20043. }
  20044. /**
  20045. * Gets the value of the selected <option> element within a <select> element.
  20046. *
  20047. * @param {Element} el
  20048. * the element to look in
  20049. *
  20050. * @param {Function} [parser]
  20051. * Optional function to adjust the value.
  20052. *
  20053. * @return {Mixed}
  20054. * - Will be `undefined` if no value exists
  20055. * - Will be `undefined` if the given value is "none".
  20056. * - Will be the actual value otherwise.
  20057. *
  20058. * @private
  20059. */
  20060. function getSelectedOptionValue(el, parser) {
  20061. var value = el.options[el.options.selectedIndex].value;
  20062. return parseOptionValue(value, parser);
  20063. }
  20064. /**
  20065. * Sets the selected <option> element within a <select> element based on a
  20066. * given value.
  20067. *
  20068. * @param {Element} el
  20069. * The element to look in.
  20070. *
  20071. * @param {string} value
  20072. * the property to look on.
  20073. *
  20074. * @param {Function} [parser]
  20075. * Optional function to adjust the value before comparing.
  20076. *
  20077. * @private
  20078. */
  20079. function setSelectedOption(el, value, parser) {
  20080. if (!value) {
  20081. return;
  20082. }
  20083. for (var i = 0; i < el.options.length; i++) {
  20084. if (parseOptionValue(el.options[i].value, parser) === value) {
  20085. el.selectedIndex = i;
  20086. break;
  20087. }
  20088. }
  20089. }
  20090. /**
  20091. * Manipulate Text Tracks settings.
  20092. *
  20093. * @extends Component
  20094. */
  20095. var TextTrackSettings = function (_Component) {
  20096. _inherits(TextTrackSettings, _Component);
  20097. /**
  20098. * Creates an instance of this class.
  20099. *
  20100. * @param {Player} player
  20101. * The `Player` that this class should be attached to.
  20102. *
  20103. * @param {Object} [options]
  20104. * The key/value store of player options.
  20105. */
  20106. function TextTrackSettings(player, options) {
  20107. _classCallCheck(this, TextTrackSettings);
  20108. var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
  20109. _this.setDefaults();
  20110. _this.hide();
  20111. _this.updateDisplay = Fn.bind(_this, _this.updateDisplay);
  20112. // Grab `persistTextTrackSettings` from the player options if not passed in child options
  20113. if (options.persistTextTrackSettings === undefined) {
  20114. _this.options_.persistTextTrackSettings = _this.options_.playerOptions.persistTextTrackSettings;
  20115. }
  20116. _this.on(_this.$('.vjs-done-button'), 'click', function () {
  20117. _this.saveSettings();
  20118. _this.hide();
  20119. });
  20120. _this.on(_this.$('.vjs-default-button'), 'click', function () {
  20121. _this.setDefaults();
  20122. _this.updateDisplay();
  20123. });
  20124. Obj.each(selectConfigs, function (config) {
  20125. _this.on(_this.$(config.selector), 'change', _this.updateDisplay);
  20126. });
  20127. if (_this.options_.persistTextTrackSettings) {
  20128. _this.restoreSettings();
  20129. }
  20130. return _this;
  20131. }
  20132. /**
  20133. * Create a <select> element with configured options.
  20134. *
  20135. * @param {string} key
  20136. * Configuration key to use during creation.
  20137. *
  20138. * @return {Element}
  20139. * The DOM element that gets created.
  20140. * @private
  20141. */
  20142. TextTrackSettings.prototype.createElSelect_ = function createElSelect_(key) {
  20143. var _this2 = this;
  20144. var config = selectConfigs[key];
  20145. var id = config.id.replace('%s', this.id_);
  20146. return [(0, _dom.createEl)('label', {
  20147. className: 'vjs-label',
  20148. textContent: config.label
  20149. }, {
  20150. 'for': id
  20151. }), (0, _dom.createEl)('select', { id: id }, undefined, config.options.map(function (o) {
  20152. return (0, _dom.createEl)('option', {
  20153. textContent: _this2.localize(o[1]),
  20154. value: o[0]
  20155. });
  20156. }))];
  20157. };
  20158. /**
  20159. * Create foreground color element for the component
  20160. *
  20161. * @return {Element}
  20162. * The element that was created.
  20163. *
  20164. * @private
  20165. */
  20166. TextTrackSettings.prototype.createElFgColor_ = function createElFgColor_() {
  20167. var legend = (0, _dom.createEl)('legend', {
  20168. textContent: this.localize('Text')
  20169. });
  20170. var select = this.createElSelect_('color');
  20171. var opacity = (0, _dom.createEl)('span', {
  20172. className: 'vjs-text-opacity vjs-opacity'
  20173. }, undefined, this.createElSelect_('textOpacity'));
  20174. return (0, _dom.createEl)('fieldset', {
  20175. className: 'vjs-fg-color vjs-tracksetting'
  20176. }, undefined, [legend].concat(select, opacity));
  20177. };
  20178. /**
  20179. * Create background color element for the component
  20180. *
  20181. * @return {Element}
  20182. * The element that was created
  20183. *
  20184. * @private
  20185. */
  20186. TextTrackSettings.prototype.createElBgColor_ = function createElBgColor_() {
  20187. var legend = (0, _dom.createEl)('legend', {
  20188. textContent: this.localize('Background')
  20189. });
  20190. var select = this.createElSelect_('backgroundColor');
  20191. var opacity = (0, _dom.createEl)('span', {
  20192. className: 'vjs-bg-opacity vjs-opacity'
  20193. }, undefined, this.createElSelect_('backgroundOpacity'));
  20194. return (0, _dom.createEl)('fieldset', {
  20195. className: 'vjs-bg-color vjs-tracksetting'
  20196. }, undefined, [legend].concat(select, opacity));
  20197. };
  20198. /**
  20199. * Create window color element for the component
  20200. *
  20201. * @return {Element}
  20202. * The element that was created
  20203. *
  20204. * @private
  20205. */
  20206. TextTrackSettings.prototype.createElWinColor_ = function createElWinColor_() {
  20207. var legend = (0, _dom.createEl)('legend', {
  20208. textContent: this.localize('Window')
  20209. });
  20210. var select = this.createElSelect_('windowColor');
  20211. var opacity = (0, _dom.createEl)('span', {
  20212. className: 'vjs-window-opacity vjs-opacity'
  20213. }, undefined, this.createElSelect_('windowOpacity'));
  20214. return (0, _dom.createEl)('fieldset', {
  20215. className: 'vjs-window-color vjs-tracksetting'
  20216. }, undefined, [legend].concat(select, opacity));
  20217. };
  20218. /**
  20219. * Create color elements for the component
  20220. *
  20221. * @return {Element}
  20222. * The element that was created
  20223. *
  20224. * @private
  20225. */
  20226. TextTrackSettings.prototype.createElColors_ = function createElColors_() {
  20227. return (0, _dom.createEl)('div', {
  20228. className: 'vjs-tracksettings-colors'
  20229. }, undefined, [this.createElFgColor_(), this.createElBgColor_(), this.createElWinColor_()]);
  20230. };
  20231. /**
  20232. * Create font elements for the component
  20233. *
  20234. * @return {Element}
  20235. * The element that was created.
  20236. *
  20237. * @private
  20238. */
  20239. TextTrackSettings.prototype.createElFont_ = function createElFont_() {
  20240. var fontPercent = (0, _dom.createEl)('div', {
  20241. className: 'vjs-font-percent vjs-tracksetting'
  20242. }, undefined, this.createElSelect_('fontPercent'));
  20243. var edgeStyle = (0, _dom.createEl)('div', {
  20244. className: 'vjs-edge-style vjs-tracksetting'
  20245. }, undefined, this.createElSelect_('edgeStyle'));
  20246. var fontFamily = (0, _dom.createEl)('div', {
  20247. className: 'vjs-font-family vjs-tracksetting'
  20248. }, undefined, this.createElSelect_('fontFamily'));
  20249. return (0, _dom.createEl)('div', {
  20250. className: 'vjs-tracksettings-font'
  20251. }, undefined, [fontPercent, edgeStyle, fontFamily]);
  20252. };
  20253. /**
  20254. * Create controls for the component
  20255. *
  20256. * @return {Element}
  20257. * The element that was created.
  20258. *
  20259. * @private
  20260. */
  20261. TextTrackSettings.prototype.createElControls_ = function createElControls_() {
  20262. var defaultsButton = (0, _dom.createEl)('button', {
  20263. className: 'vjs-default-button',
  20264. textContent: this.localize('Defaults')
  20265. });
  20266. var doneButton = (0, _dom.createEl)('button', {
  20267. className: 'vjs-done-button',
  20268. textContent: 'Done'
  20269. });
  20270. return (0, _dom.createEl)('div', {
  20271. className: 'vjs-tracksettings-controls'
  20272. }, undefined, [defaultsButton, doneButton]);
  20273. };
  20274. /**
  20275. * Create the component's DOM element
  20276. *
  20277. * @return {Element}
  20278. * The element that was created.
  20279. */
  20280. TextTrackSettings.prototype.createEl = function createEl() {
  20281. var settings = (0, _dom.createEl)('div', {
  20282. className: 'vjs-tracksettings'
  20283. }, undefined, [this.createElColors_(), this.createElFont_(), this.createElControls_()]);
  20284. var heading = (0, _dom.createEl)('div', {
  20285. className: 'vjs-control-text',
  20286. id: 'TTsettingsDialogLabel-' + this.id_,
  20287. textContent: 'Caption Settings Dialog'
  20288. }, {
  20289. 'aria-level': '1',
  20290. 'role': 'heading'
  20291. });
  20292. var description = (0, _dom.createEl)('div', {
  20293. className: 'vjs-control-text',
  20294. id: 'TTsettingsDialogDescription-' + this.id_,
  20295. textContent: 'Beginning of dialog window. Escape will cancel and close the window.'
  20296. });
  20297. var doc = (0, _dom.createEl)('div', undefined, {
  20298. role: 'document'
  20299. }, [heading, description, settings]);
  20300. return (0, _dom.createEl)('div', {
  20301. className: 'vjs-caption-settings vjs-modal-overlay',
  20302. tabIndex: -1
  20303. }, {
  20304. 'role': 'dialog',
  20305. 'aria-labelledby': heading.id,
  20306. 'aria-describedby': description.id
  20307. }, doc);
  20308. };
  20309. /**
  20310. * Gets an object of text track settings (or null).
  20311. *
  20312. * @return {Object}
  20313. * An object with config values parsed from the DOM or localStorage.
  20314. */
  20315. TextTrackSettings.prototype.getValues = function getValues() {
  20316. var _this3 = this;
  20317. return Obj.reduce(selectConfigs, function (accum, config, key) {
  20318. var value = getSelectedOptionValue(_this3.$(config.selector), config.parser);
  20319. if (value !== undefined) {
  20320. accum[key] = value;
  20321. }
  20322. return accum;
  20323. }, {});
  20324. };
  20325. /**
  20326. * Sets text track settings from an object of values.
  20327. *
  20328. * @param {Object} values
  20329. * An object with config values parsed from the DOM or localStorage.
  20330. */
  20331. TextTrackSettings.prototype.setValues = function setValues(values) {
  20332. var _this4 = this;
  20333. Obj.each(selectConfigs, function (config, key) {
  20334. setSelectedOption(_this4.$(config.selector), values[key], config.parser);
  20335. });
  20336. };
  20337. /**
  20338. * Sets all <select> elements to their default values.
  20339. */
  20340. TextTrackSettings.prototype.setDefaults = function setDefaults() {
  20341. var _this5 = this;
  20342. Obj.each(selectConfigs, function (config) {
  20343. var index = config.hasOwnProperty('default') ? config['default'] : 0;
  20344. _this5.$(config.selector).selectedIndex = index;
  20345. });
  20346. };
  20347. /**
  20348. * Restore texttrack settings from localStorage
  20349. */
  20350. TextTrackSettings.prototype.restoreSettings = function restoreSettings() {
  20351. var values = void 0;
  20352. try {
  20353. values = JSON.parse(_window2['default'].localStorage.getItem(LOCAL_STORAGE_KEY));
  20354. } catch (err) {
  20355. _log2['default'].warn(err);
  20356. }
  20357. if (values) {
  20358. this.setValues(values);
  20359. }
  20360. };
  20361. /**
  20362. * Save text track settings to localStorage
  20363. */
  20364. TextTrackSettings.prototype.saveSettings = function saveSettings() {
  20365. if (!this.options_.persistTextTrackSettings) {
  20366. return;
  20367. }
  20368. var values = this.getValues();
  20369. try {
  20370. if (Object.keys(values).length) {
  20371. _window2['default'].localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(values));
  20372. } else {
  20373. _window2['default'].localStorage.removeItem(LOCAL_STORAGE_KEY);
  20374. }
  20375. } catch (err) {
  20376. _log2['default'].warn(err);
  20377. }
  20378. };
  20379. /**
  20380. * Update display of text track settings
  20381. */
  20382. TextTrackSettings.prototype.updateDisplay = function updateDisplay() {
  20383. var ttDisplay = this.player_.getChild('textTrackDisplay');
  20384. if (ttDisplay) {
  20385. ttDisplay.updateDisplay();
  20386. }
  20387. };
  20388. return TextTrackSettings;
  20389. }(_component2['default']);
  20390. _component2['default'].registerComponent('TextTrackSettings', TextTrackSettings);
  20391. exports['default'] = TextTrackSettings;
  20392. /***/ }),
  20393. /* 109 */
  20394. /***/ (function(module, exports, __webpack_require__) {
  20395. 'use strict';
  20396. exports.__esModule = true;
  20397. var _templateObject = _taggedTemplateLiteralLoose(['Text Tracks are being loaded from another origin but the crossorigin attribute isn\'t used.\n This may prevent text tracks from loading.'], ['Text Tracks are being loaded from another origin but the crossorigin attribute isn\'t used.\n This may prevent text tracks from loading.']);
  20398. var _tech = __webpack_require__(32);
  20399. var _tech2 = _interopRequireDefault(_tech);
  20400. var _component = __webpack_require__(19);
  20401. var _component2 = _interopRequireDefault(_component);
  20402. var _dom = __webpack_require__(11);
  20403. var Dom = _interopRequireWildcard(_dom);
  20404. var _url = __webpack_require__(38);
  20405. var Url = _interopRequireWildcard(_url);
  20406. var _fn = __webpack_require__(20);
  20407. var Fn = _interopRequireWildcard(_fn);
  20408. var _log = __webpack_require__(13);
  20409. var _log2 = _interopRequireDefault(_log);
  20410. var _tsml = __webpack_require__(15);
  20411. var _tsml2 = _interopRequireDefault(_tsml);
  20412. var _browser = __webpack_require__(10);
  20413. var browser = _interopRequireWildcard(_browser);
  20414. var _document = __webpack_require__(8);
  20415. var _document2 = _interopRequireDefault(_document);
  20416. var _window = __webpack_require__(7);
  20417. var _window2 = _interopRequireDefault(_window);
  20418. var _obj = __webpack_require__(14);
  20419. var _mergeOptions = __webpack_require__(22);
  20420. var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
  20421. var _toTitleCase = __webpack_require__(21);
  20422. var _toTitleCase2 = _interopRequireDefault(_toTitleCase);
  20423. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  20424. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  20425. function _taggedTemplateLiteralLoose(strings, raw) { strings.raw = raw; return strings; }
  20426. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  20427. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  20428. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  20429. * @file html5.js
  20430. */
  20431. /**
  20432. * HTML5 Media Controller - Wrapper for HTML5 Media API
  20433. *
  20434. * @mixes Tech~SouceHandlerAdditions
  20435. * @extends Tech
  20436. */
  20437. var Html5 = function (_Tech) {
  20438. _inherits(Html5, _Tech);
  20439. /**
  20440. * Create an instance of this Tech.
  20441. *
  20442. * @param {Object} [options]
  20443. * The key/value store of player options.
  20444. *
  20445. * @param {Component~ReadyCallback} ready
  20446. * Callback function to call when the `HTML5` Tech is ready.
  20447. */
  20448. function Html5(options, ready) {
  20449. _classCallCheck(this, Html5);
  20450. var _this = _possibleConstructorReturn(this, _Tech.call(this, options, ready));
  20451. var source = options.source;
  20452. var crossoriginTracks = false;
  20453. // Set the source if one is provided
  20454. // 1) Check if the source is new (if not, we want to keep the original so playback isn't interrupted)
  20455. // 2) Check to see if the network state of the tag was failed at init, and if so, reset the source
  20456. // anyway so the error gets fired.
  20457. if (source && (_this.el_.currentSrc !== source.src || options.tag && options.tag.initNetworkState_ === 3)) {
  20458. _this.setSource(source);
  20459. } else {
  20460. _this.handleLateInit_(_this.el_);
  20461. }
  20462. if (_this.el_.hasChildNodes()) {
  20463. var nodes = _this.el_.childNodes;
  20464. var nodesLength = nodes.length;
  20465. var removeNodes = [];
  20466. while (nodesLength--) {
  20467. var node = nodes[nodesLength];
  20468. var nodeName = node.nodeName.toLowerCase();
  20469. if (nodeName === 'track') {
  20470. if (!_this.featuresNativeTextTracks) {
  20471. // Empty video tag tracks so the built-in player doesn't use them also.
  20472. // This may not be fast enough to stop HTML5 browsers from reading the tags
  20473. // so we'll need to turn off any default tracks if we're manually doing
  20474. // captions and subtitles. videoElement.textTracks
  20475. removeNodes.push(node);
  20476. } else {
  20477. // store HTMLTrackElement and TextTrack to remote list
  20478. _this.remoteTextTrackEls().addTrackElement_(node);
  20479. _this.remoteTextTracks().addTrack_(node.track);
  20480. if (!crossoriginTracks && !_this.el_.hasAttribute('crossorigin') && Url.isCrossOrigin(node.src)) {
  20481. crossoriginTracks = true;
  20482. }
  20483. }
  20484. }
  20485. }
  20486. for (var i = 0; i < removeNodes.length; i++) {
  20487. _this.el_.removeChild(removeNodes[i]);
  20488. }
  20489. }
  20490. // TODO: add text tracks into this list
  20491. var trackTypes = ['audio', 'video'];
  20492. // ProxyNative Video/Audio Track
  20493. trackTypes.forEach(function (type) {
  20494. var elTracks = _this.el()[type + 'Tracks'];
  20495. var techTracks = _this[type + 'Tracks']();
  20496. var capitalType = (0, _toTitleCase2['default'])(type);
  20497. if (!_this['featuresNative' + capitalType + 'Tracks'] || !elTracks || !elTracks.addEventListener) {
  20498. return;
  20499. }
  20500. _this['handle' + capitalType + 'TrackChange_'] = function (e) {
  20501. techTracks.trigger({
  20502. type: 'change',
  20503. target: techTracks,
  20504. currentTarget: techTracks,
  20505. srcElement: techTracks
  20506. });
  20507. };
  20508. _this['handle' + capitalType + 'TrackAdd_'] = function (e) {
  20509. return techTracks.addTrack(e.track);
  20510. };
  20511. _this['handle' + capitalType + 'TrackRemove_'] = function (e) {
  20512. return techTracks.removeTrack(e.track);
  20513. };
  20514. elTracks.addEventListener('change', _this['handle' + capitalType + 'TrackChange_']);
  20515. elTracks.addEventListener('addtrack', _this['handle' + capitalType + 'TrackAdd_']);
  20516. elTracks.addEventListener('removetrack', _this['handle' + capitalType + 'TrackRemove_']);
  20517. _this['removeOld' + capitalType + 'Tracks_'] = function (e) {
  20518. return _this.removeOldTracks_(techTracks, elTracks);
  20519. };
  20520. // Remove (native) tracks that are not used anymore
  20521. _this.on('loadstart', _this['removeOld' + capitalType + 'Tracks_']);
  20522. });
  20523. if (_this.featuresNativeTextTracks) {
  20524. if (crossoriginTracks) {
  20525. _log2['default'].warn((0, _tsml2['default'])(_templateObject));
  20526. }
  20527. _this.handleTextTrackChange_ = Fn.bind(_this, _this.handleTextTrackChange);
  20528. _this.handleTextTrackAdd_ = Fn.bind(_this, _this.handleTextTrackAdd);
  20529. _this.handleTextTrackRemove_ = Fn.bind(_this, _this.handleTextTrackRemove);
  20530. _this.proxyNativeTextTracks_();
  20531. }
  20532. // prevent iOS Safari from disabling metadata text tracks during native playback
  20533. _this.restoreMetadataTracksInIOSNativePlayer_();
  20534. // Determine if native controls should be used
  20535. // Our goal should be to get the custom controls on mobile solid everywhere
  20536. // so we can remove this all together. Right now this will block custom
  20537. // controls on touch enabled laptops like the Chrome Pixel
  20538. if ((browser.TOUCH_ENABLED || browser.IS_IPHONE || browser.IS_NATIVE_ANDROID) && options.nativeControlsForTouch === true) {
  20539. _this.setControls(true);
  20540. }
  20541. // on iOS, we want to proxy `webkitbeginfullscreen` and `webkitendfullscreen`
  20542. // into a `fullscreenchange` event
  20543. _this.proxyWebkitFullscreen_();
  20544. _this.triggerReady();
  20545. return _this;
  20546. }
  20547. /**
  20548. * Dispose of `HTML5` media element and remove all tracks.
  20549. */
  20550. Html5.prototype.dispose = function dispose() {
  20551. var _this2 = this;
  20552. // Un-ProxyNativeTracks
  20553. ['audio', 'video', 'text'].forEach(function (type) {
  20554. var capitalType = (0, _toTitleCase2['default'])(type);
  20555. var tl = _this2.el_[type + 'Tracks'];
  20556. if (tl && tl.removeEventListener) {
  20557. tl.removeEventListener('change', _this2['handle' + capitalType + 'TrackChange_']);
  20558. tl.removeEventListener('addtrack', _this2['handle' + capitalType + 'TrackAdd_']);
  20559. tl.removeEventListener('removetrack', _this2['handle' + capitalType + 'TrackRemove_']);
  20560. }
  20561. // Stop removing old text tracks
  20562. if (tl) {
  20563. _this2.off('loadstart', _this2['removeOld' + capitalType + 'Tracks_']);
  20564. }
  20565. });
  20566. Html5.disposeMediaElement(this.el_);
  20567. // tech will handle clearing of the emulated track list
  20568. _Tech.prototype.dispose.call(this);
  20569. };
  20570. /**
  20571. * When a captions track is enabled in the iOS Safari native player, all other
  20572. * tracks are disabled (including metadata tracks), which nulls all of their
  20573. * associated cue points. This will restore metadata tracks to their pre-fullscreen
  20574. * state in those cases so that cue points are not needlessly lost.
  20575. *
  20576. * @private
  20577. */
  20578. Html5.prototype.restoreMetadataTracksInIOSNativePlayer_ = function restoreMetadataTracksInIOSNativePlayer_() {
  20579. var textTracks = this.textTracks();
  20580. var metadataTracksPreFullscreenState = void 0;
  20581. // captures a snapshot of every metadata track's current state
  20582. var takeMetadataTrackSnapshot = function takeMetadataTrackSnapshot() {
  20583. metadataTracksPreFullscreenState = [];
  20584. for (var i = 0; i < textTracks.length; i++) {
  20585. var track = textTracks[i];
  20586. if (track.kind === 'metadata') {
  20587. metadataTracksPreFullscreenState.push({
  20588. track: track,
  20589. storedMode: track.mode
  20590. });
  20591. }
  20592. }
  20593. };
  20594. // snapshot each metadata track's initial state, and update the snapshot
  20595. // each time there is a track 'change' event
  20596. takeMetadataTrackSnapshot();
  20597. textTracks.addEventListener('change', takeMetadataTrackSnapshot);
  20598. var restoreTrackMode = function restoreTrackMode() {
  20599. for (var i = 0; i < metadataTracksPreFullscreenState.length; i++) {
  20600. var storedTrack = metadataTracksPreFullscreenState[i];
  20601. if (storedTrack.track.mode === 'disabled' && storedTrack.track.mode !== storedTrack.storedMode) {
  20602. storedTrack.track.mode = storedTrack.storedMode;
  20603. }
  20604. }
  20605. // we only want this handler to be executed on the first 'change' event
  20606. textTracks.removeEventListener('change', restoreTrackMode);
  20607. };
  20608. // when we enter fullscreen playback, stop updating the snapshot and
  20609. // restore all track modes to their pre-fullscreen state
  20610. this.on('webkitbeginfullscreen', function () {
  20611. textTracks.removeEventListener('change', takeMetadataTrackSnapshot);
  20612. // remove the listener before adding it just in case it wasn't previously removed
  20613. textTracks.removeEventListener('change', restoreTrackMode);
  20614. textTracks.addEventListener('change', restoreTrackMode);
  20615. });
  20616. // start updating the snapshot again after leaving fullscreen
  20617. this.on('webkitendfullscreen', function () {
  20618. // remove the listener before adding it just in case it wasn't previously removed
  20619. textTracks.removeEventListener('change', takeMetadataTrackSnapshot);
  20620. textTracks.addEventListener('change', takeMetadataTrackSnapshot);
  20621. // remove the restoreTrackMode handler in case it wasn't triggered during fullscreen playback
  20622. textTracks.removeEventListener('change', restoreTrackMode);
  20623. });
  20624. };
  20625. /**
  20626. * Create the `Html5` Tech's DOM element.
  20627. *
  20628. * @return {Element}
  20629. * The element that gets created.
  20630. */
  20631. Html5.prototype.createEl = function createEl() {
  20632. var el = this.options_.tag;
  20633. // Check if this browser supports moving the element into the box.
  20634. // On the iPhone video will break if you move the element,
  20635. // So we have to create a brand new element.
  20636. // If we ingested the player div, we do not need to move the media element.
  20637. if (!el || !(this.options_.playerElIngest || this.movingMediaElementInDOM)) {
  20638. // If the original tag is still there, clone and remove it.
  20639. if (el) {
  20640. var clone = el.cloneNode(true);
  20641. if (el.parentNode) {
  20642. el.parentNode.insertBefore(clone, el);
  20643. }
  20644. Html5.disposeMediaElement(el);
  20645. el = clone;
  20646. } else {
  20647. el = _document2['default'].createElement('video');
  20648. // determine if native controls should be used
  20649. var tagAttributes = this.options_.tag && Dom.getElAttributes(this.options_.tag);
  20650. var attributes = (0, _mergeOptions2['default'])({}, tagAttributes);
  20651. if (!browser.TOUCH_ENABLED || this.options_.nativeControlsForTouch !== true) {
  20652. delete attributes.controls;
  20653. }
  20654. Dom.setElAttributes(el, (0, _obj.assign)(attributes, {
  20655. id: this.options_.techId,
  20656. 'class': 'vjs-tech'
  20657. }));
  20658. }
  20659. el.playerId = this.options_.playerId;
  20660. }
  20661. // Update specific tag settings, in case they were overridden
  20662. var settingsAttrs = ['autoplay', 'preload', 'loop', 'muted', 'playsinline'];
  20663. for (var i = settingsAttrs.length - 1; i >= 0; i--) {
  20664. var attr = settingsAttrs[i];
  20665. var overwriteAttrs = {};
  20666. if (typeof this.options_[attr] !== 'undefined') {
  20667. overwriteAttrs[attr] = this.options_[attr];
  20668. }
  20669. Dom.setElAttributes(el, overwriteAttrs);
  20670. }
  20671. return el;
  20672. };
  20673. /**
  20674. * This will be triggered if the loadstart event has already fired, before videojs was
  20675. * ready. Two known examples of when this can happen are:
  20676. * 1. If we're loading the playback object after it has started loading
  20677. * 2. The media is already playing the (often with autoplay on) then
  20678. *
  20679. * This function will fire another loadstart so that videojs can catchup.
  20680. *
  20681. * @fires Tech#loadstart
  20682. *
  20683. * @return {undefined}
  20684. * returns nothing.
  20685. */
  20686. Html5.prototype.handleLateInit_ = function handleLateInit_(el) {
  20687. if (el.networkState === 0 || el.networkState === 3) {
  20688. // The video element hasn't started loading the source yet
  20689. // or didn't find a source
  20690. return;
  20691. }
  20692. if (el.readyState === 0) {
  20693. // NetworkState is set synchronously BUT loadstart is fired at the
  20694. // end of the current stack, usually before setInterval(fn, 0).
  20695. // So at this point we know loadstart may have already fired or is
  20696. // about to fire, and either way the player hasn't seen it yet.
  20697. // We don't want to fire loadstart prematurely here and cause a
  20698. // double loadstart so we'll wait and see if it happens between now
  20699. // and the next loop, and fire it if not.
  20700. // HOWEVER, we also want to make sure it fires before loadedmetadata
  20701. // which could also happen between now and the next loop, so we'll
  20702. // watch for that also.
  20703. var loadstartFired = false;
  20704. var setLoadstartFired = function setLoadstartFired() {
  20705. loadstartFired = true;
  20706. };
  20707. this.on('loadstart', setLoadstartFired);
  20708. var triggerLoadstart = function triggerLoadstart() {
  20709. // We did miss the original loadstart. Make sure the player
  20710. // sees loadstart before loadedmetadata
  20711. if (!loadstartFired) {
  20712. this.trigger('loadstart');
  20713. }
  20714. };
  20715. this.on('loadedmetadata', triggerLoadstart);
  20716. this.ready(function () {
  20717. this.off('loadstart', setLoadstartFired);
  20718. this.off('loadedmetadata', triggerLoadstart);
  20719. if (!loadstartFired) {
  20720. // We did miss the original native loadstart. Fire it now.
  20721. this.trigger('loadstart');
  20722. }
  20723. });
  20724. return;
  20725. }
  20726. // From here on we know that loadstart already fired and we missed it.
  20727. // The other readyState events aren't as much of a problem if we double
  20728. // them, so not going to go to as much trouble as loadstart to prevent
  20729. // that unless we find reason to.
  20730. var eventsToTrigger = ['loadstart'];
  20731. // loadedmetadata: newly equal to HAVE_METADATA (1) or greater
  20732. eventsToTrigger.push('loadedmetadata');
  20733. // loadeddata: newly increased to HAVE_CURRENT_DATA (2) or greater
  20734. if (el.readyState >= 2) {
  20735. eventsToTrigger.push('loadeddata');
  20736. }
  20737. // canplay: newly increased to HAVE_FUTURE_DATA (3) or greater
  20738. if (el.readyState >= 3) {
  20739. eventsToTrigger.push('canplay');
  20740. }
  20741. // canplaythrough: newly equal to HAVE_ENOUGH_DATA (4)
  20742. if (el.readyState >= 4) {
  20743. eventsToTrigger.push('canplaythrough');
  20744. }
  20745. // We still need to give the player time to add event listeners
  20746. this.ready(function () {
  20747. eventsToTrigger.forEach(function (type) {
  20748. this.trigger(type);
  20749. }, this);
  20750. });
  20751. };
  20752. /**
  20753. * Add event listeners to native text track events. This adds the native text tracks
  20754. * to our emulated {@link TextTrackList}.
  20755. */
  20756. Html5.prototype.proxyNativeTextTracks_ = function proxyNativeTextTracks_() {
  20757. var tt = this.el().textTracks;
  20758. if (tt) {
  20759. // Add tracks - if player is initialised after DOM loaded, textTracks
  20760. // will not trigger addtrack
  20761. for (var i = 0; i < tt.length; i++) {
  20762. this.textTracks().addTrack_(tt[i]);
  20763. }
  20764. if (tt.addEventListener) {
  20765. tt.addEventListener('change', this.handleTextTrackChange_);
  20766. tt.addEventListener('addtrack', this.handleTextTrackAdd_);
  20767. tt.addEventListener('removetrack', this.handleTextTrackRemove_);
  20768. }
  20769. // Remove (native) texttracks that are not used anymore
  20770. this.on('loadstart', this.removeOldTextTracks_);
  20771. }
  20772. };
  20773. /**
  20774. * Handle any {@link TextTrackList} `change` event.
  20775. *
  20776. * @param {EventTarget~Event} e
  20777. * The `change` event that caused this to run.
  20778. *
  20779. * @listens TextTrackList#change
  20780. */
  20781. Html5.prototype.handleTextTrackChange = function handleTextTrackChange(e) {
  20782. var tt = this.textTracks();
  20783. this.textTracks().trigger({
  20784. type: 'change',
  20785. target: tt,
  20786. currentTarget: tt,
  20787. srcElement: tt
  20788. });
  20789. };
  20790. /**
  20791. * Handle any {@link TextTrackList} `addtrack` event.
  20792. *
  20793. * @param {EventTarget~Event} e
  20794. * The `addtrack` event that caused this to run.
  20795. *
  20796. * @listens TextTrackList#addtrack
  20797. */
  20798. Html5.prototype.handleTextTrackAdd = function handleTextTrackAdd(e) {
  20799. this.textTracks().addTrack_(e.track);
  20800. };
  20801. /**
  20802. * Handle any {@link TextTrackList} `removetrack` event.
  20803. *
  20804. * @param {EventTarget~Event} e
  20805. * The `removetrack` event that caused this to run.
  20806. *
  20807. * @listens TextTrackList#removetrack
  20808. */
  20809. Html5.prototype.handleTextTrackRemove = function handleTextTrackRemove(e) {
  20810. this.textTracks().removeTrack_(e.track);
  20811. };
  20812. /**
  20813. * This function removes any {@link AudioTrack}s, {@link VideoTrack}s, or
  20814. * {@link TextTrack}s that are not in the media elements TrackList.
  20815. *
  20816. * @param {TrackList} techTracks
  20817. * HTML5 Tech's TrackList to search through
  20818. *
  20819. * @param {TrackList} elTracks
  20820. * HTML5 media elements TrackList to search trough.
  20821. *
  20822. * @private
  20823. */
  20824. Html5.prototype.removeOldTracks_ = function removeOldTracks_(techTracks, elTracks) {
  20825. // This will loop over the techTracks and check if they are still used by the HTML5 media element
  20826. // If not, they will be removed from the emulated list
  20827. var removeTracks = [];
  20828. if (!elTracks) {
  20829. return;
  20830. }
  20831. for (var i = 0; i < techTracks.length; i++) {
  20832. var techTrack = techTracks[i];
  20833. var found = false;
  20834. for (var j = 0; j < elTracks.length; j++) {
  20835. if (elTracks[j] === techTrack) {
  20836. found = true;
  20837. break;
  20838. }
  20839. }
  20840. if (!found) {
  20841. removeTracks.push(techTrack);
  20842. }
  20843. }
  20844. for (var _i = 0; _i < removeTracks.length; _i++) {
  20845. var track = removeTracks[_i];
  20846. techTracks.removeTrack_(track);
  20847. }
  20848. };
  20849. /**
  20850. * Remove {@link TextTrack}s that dont exist in the native track list from our
  20851. * emulated {@link TextTrackList}.
  20852. *
  20853. * @listens Tech#loadstart
  20854. */
  20855. Html5.prototype.removeOldTextTracks_ = function removeOldTextTracks_(e) {
  20856. var techTracks = this.textTracks();
  20857. var elTracks = this.el().textTracks;
  20858. this.removeOldTracks_(techTracks, elTracks);
  20859. };
  20860. /**
  20861. * Called by {@link Player#play} to play using the `Html5` `Tech`.
  20862. */
  20863. Html5.prototype.play = function play() {
  20864. var playPromise = this.el_.play();
  20865. // Catch/silence error when a pause interrupts a play request
  20866. // on browsers which return a promise
  20867. if (playPromise !== undefined && typeof playPromise.then === 'function') {
  20868. playPromise.then(null, function (e) {});
  20869. }
  20870. };
  20871. /**
  20872. * Set current time for the `HTML5` tech.
  20873. *
  20874. * @param {number} seconds
  20875. * Set the current time of the media to this.
  20876. */
  20877. Html5.prototype.setCurrentTime = function setCurrentTime(seconds) {
  20878. try {
  20879. this.el_.currentTime = seconds;
  20880. } catch (e) {
  20881. (0, _log2['default'])(e, 'Video is not ready. (Video.js)');
  20882. // this.warning(VideoJS.warnings.videoNotReady);
  20883. }
  20884. };
  20885. /**
  20886. * Get the current duration of the HTML5 media element.
  20887. *
  20888. * @return {number}
  20889. * The duration of the media or 0 if there is no duration.
  20890. */
  20891. Html5.prototype.duration = function duration() {
  20892. var _this3 = this;
  20893. // Android Chrome will report duration as Infinity for VOD HLS until after
  20894. // playback has started, which triggers the live display erroneously.
  20895. // Return NaN if playback has not started and trigger a durationupdate once
  20896. // the duration can be reliably known.
  20897. if (this.el_.duration === Infinity && browser.IS_ANDROID && browser.IS_CHROME) {
  20898. if (this.el_.currentTime === 0) {
  20899. // Wait for the first `timeupdate` with currentTime > 0 - there may be
  20900. // several with 0
  20901. var checkProgress = function checkProgress() {
  20902. if (_this3.el_.currentTime > 0) {
  20903. // Trigger durationchange for genuinely live video
  20904. if (_this3.el_.duration === Infinity) {
  20905. _this3.trigger('durationchange');
  20906. }
  20907. _this3.off('timeupdate', checkProgress);
  20908. }
  20909. };
  20910. this.on('timeupdate', checkProgress);
  20911. return NaN;
  20912. }
  20913. }
  20914. return this.el_.duration || NaN;
  20915. };
  20916. /**
  20917. * Get the current width of the HTML5 media element.
  20918. *
  20919. * @return {number}
  20920. * The width of the HTML5 media element.
  20921. */
  20922. Html5.prototype.width = function width() {
  20923. return this.el_.offsetWidth;
  20924. };
  20925. /**
  20926. * Get the current height of the HTML5 media element.
  20927. *
  20928. * @return {number}
  20929. * The heigth of the HTML5 media element.
  20930. */
  20931. Html5.prototype.height = function height() {
  20932. return this.el_.offsetHeight;
  20933. };
  20934. /**
  20935. * Proxy iOS `webkitbeginfullscreen` and `webkitendfullscreen` into
  20936. * `fullscreenchange` event.
  20937. *
  20938. * @private
  20939. * @fires fullscreenchange
  20940. * @listens webkitendfullscreen
  20941. * @listens webkitbeginfullscreen
  20942. * @listens webkitbeginfullscreen
  20943. */
  20944. Html5.prototype.proxyWebkitFullscreen_ = function proxyWebkitFullscreen_() {
  20945. var _this4 = this;
  20946. if (!('webkitDisplayingFullscreen' in this.el_)) {
  20947. return;
  20948. }
  20949. var endFn = function endFn() {
  20950. this.trigger('fullscreenchange', { isFullscreen: false });
  20951. };
  20952. var beginFn = function beginFn() {
  20953. if ('webkitPresentationMode' in this.el_ && this.el_.webkitPresentationMode !== 'picture-in-picture') {
  20954. this.one('webkitendfullscreen', endFn);
  20955. this.trigger('fullscreenchange', { isFullscreen: true });
  20956. }
  20957. };
  20958. this.on('webkitbeginfullscreen', beginFn);
  20959. this.on('dispose', function () {
  20960. _this4.off('webkitbeginfullscreen', beginFn);
  20961. _this4.off('webkitendfullscreen', endFn);
  20962. });
  20963. };
  20964. /**
  20965. * Check if fullscreen is supported on the current playback device.
  20966. *
  20967. * @return {boolean}
  20968. * - True if fullscreen is supported.
  20969. * - False if fullscreen is not supported.
  20970. */
  20971. Html5.prototype.supportsFullScreen = function supportsFullScreen() {
  20972. if (typeof this.el_.webkitEnterFullScreen === 'function') {
  20973. var userAgent = _window2['default'].navigator && _window2['default'].navigator.userAgent || '';
  20974. // Seems to be broken in Chromium/Chrome && Safari in Leopard
  20975. if (/Android/.test(userAgent) || !/Chrome|Mac OS X 10.5/.test(userAgent)) {
  20976. return true;
  20977. }
  20978. }
  20979. return false;
  20980. };
  20981. /**
  20982. * Request that the `HTML5` Tech enter fullscreen.
  20983. */
  20984. Html5.prototype.enterFullScreen = function enterFullScreen() {
  20985. var video = this.el_;
  20986. if (video.paused && video.networkState <= video.HAVE_METADATA) {
  20987. // attempt to prime the video element for programmatic access
  20988. // this isn't necessary on the desktop but shouldn't hurt
  20989. this.el_.play();
  20990. // playing and pausing synchronously during the transition to fullscreen
  20991. // can get iOS ~6.1 devices into a play/pause loop
  20992. this.setTimeout(function () {
  20993. video.pause();
  20994. video.webkitEnterFullScreen();
  20995. }, 0);
  20996. } else {
  20997. video.webkitEnterFullScreen();
  20998. }
  20999. };
  21000. /**
  21001. * Request that the `HTML5` Tech exit fullscreen.
  21002. */
  21003. Html5.prototype.exitFullScreen = function exitFullScreen() {
  21004. this.el_.webkitExitFullScreen();
  21005. };
  21006. /**
  21007. * A getter/setter for the `Html5` Tech's source object.
  21008. * > Note: Please use {@link Html5#setSource}
  21009. *
  21010. * @param {Tech~SourceObject} [src]
  21011. * The source object you want to set on the `HTML5` techs element.
  21012. *
  21013. * @return {Tech~SourceObject|undefined}
  21014. * - The current source object when a source is not passed in.
  21015. * - undefined when setting
  21016. *
  21017. * @deprecated Since version 5.
  21018. */
  21019. Html5.prototype.src = function src(_src) {
  21020. if (_src === undefined) {
  21021. return this.el_.src;
  21022. }
  21023. // Setting src through `src` instead of `setSrc` will be deprecated
  21024. this.setSrc(_src);
  21025. };
  21026. /**
  21027. * Reset the tech by removing all sources and then calling
  21028. * {@link Html5.resetMediaElement}.
  21029. */
  21030. Html5.prototype.reset = function reset() {
  21031. Html5.resetMediaElement(this.el_);
  21032. };
  21033. /**
  21034. * Get the current source on the `HTML5` Tech. Falls back to returning the source from
  21035. * the HTML5 media element.
  21036. *
  21037. * @return {Tech~SourceObject}
  21038. * The current source object from the HTML5 tech. With a fallback to the
  21039. * elements source.
  21040. */
  21041. Html5.prototype.currentSrc = function currentSrc() {
  21042. if (this.currentSource_) {
  21043. return this.currentSource_.src;
  21044. }
  21045. return this.el_.currentSrc;
  21046. };
  21047. /**
  21048. * Set controls attribute for the HTML5 media Element.
  21049. *
  21050. * @param {string} val
  21051. * Value to set the controls attribute to
  21052. */
  21053. Html5.prototype.setControls = function setControls(val) {
  21054. this.el_.controls = !!val;
  21055. };
  21056. /**
  21057. * Create and returns a remote {@link TextTrack} object.
  21058. *
  21059. * @param {string} kind
  21060. * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata)
  21061. *
  21062. * @param {string} [label]
  21063. * Label to identify the text track
  21064. *
  21065. * @param {string} [language]
  21066. * Two letter language abbreviation
  21067. *
  21068. * @return {TextTrack}
  21069. * The TextTrack that gets created.
  21070. */
  21071. Html5.prototype.addTextTrack = function addTextTrack(kind, label, language) {
  21072. if (!this.featuresNativeTextTracks) {
  21073. return _Tech.prototype.addTextTrack.call(this, kind, label, language);
  21074. }
  21075. return this.el_.addTextTrack(kind, label, language);
  21076. };
  21077. /**
  21078. * Creates either native TextTrack or an emulated TextTrack depending
  21079. * on the value of `featuresNativeTextTracks`
  21080. *
  21081. * @param {Object} options
  21082. * The object should contain the options to intialize the TextTrack with.
  21083. *
  21084. * @param {string} [options.kind]
  21085. * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata).
  21086. *
  21087. * @param {string} [options.label].
  21088. * Label to identify the text track
  21089. *
  21090. * @param {string} [options.language]
  21091. * Two letter language abbreviation.
  21092. *
  21093. * @param {boolean} [options.default]
  21094. * Default this track to on.
  21095. *
  21096. * @param {string} [options.id]
  21097. * The internal id to assign this track.
  21098. *
  21099. * @param {string} [options.src]
  21100. * A source url for the track.
  21101. *
  21102. * @return {HTMLTrackElement}
  21103. * The track element that gets created.
  21104. */
  21105. Html5.prototype.createRemoteTextTrack = function createRemoteTextTrack(options) {
  21106. if (!this.featuresNativeTextTracks) {
  21107. return _Tech.prototype.createRemoteTextTrack.call(this, options);
  21108. }
  21109. var htmlTrackElement = _document2['default'].createElement('track');
  21110. if (options.kind) {
  21111. htmlTrackElement.kind = options.kind;
  21112. }
  21113. if (options.label) {
  21114. htmlTrackElement.label = options.label;
  21115. }
  21116. if (options.language || options.srclang) {
  21117. htmlTrackElement.srclang = options.language || options.srclang;
  21118. }
  21119. if (options['default']) {
  21120. htmlTrackElement['default'] = options['default'];
  21121. }
  21122. if (options.id) {
  21123. htmlTrackElement.id = options.id;
  21124. }
  21125. if (options.src) {
  21126. htmlTrackElement.src = options.src;
  21127. }
  21128. return htmlTrackElement;
  21129. };
  21130. /**
  21131. * Creates a remote text track object and returns an html track element.
  21132. *
  21133. * @param {Object} options The object should contain values for
  21134. * kind, language, label, and src (location of the WebVTT file)
  21135. * @param {Boolean} [manualCleanup=true] if set to false, the TextTrack will be
  21136. * automatically removed from the video element whenever the source changes
  21137. * @return {HTMLTrackElement} An Html Track Element.
  21138. * This can be an emulated {@link HTMLTrackElement} or a native one.
  21139. * @deprecated The default value of the "manualCleanup" parameter will default
  21140. * to "false" in upcoming versions of Video.js
  21141. */
  21142. Html5.prototype.addRemoteTextTrack = function addRemoteTextTrack(options, manualCleanup) {
  21143. var htmlTrackElement = _Tech.prototype.addRemoteTextTrack.call(this, options, manualCleanup);
  21144. if (this.featuresNativeTextTracks) {
  21145. this.el().appendChild(htmlTrackElement);
  21146. }
  21147. return htmlTrackElement;
  21148. };
  21149. /**
  21150. * Remove remote `TextTrack` from `TextTrackList` object
  21151. *
  21152. * @param {TextTrack} track
  21153. * `TextTrack` object to remove
  21154. */
  21155. Html5.prototype.removeRemoteTextTrack = function removeRemoteTextTrack(track) {
  21156. _Tech.prototype.removeRemoteTextTrack.call(this, track);
  21157. if (this.featuresNativeTextTracks) {
  21158. var tracks = this.$$('track');
  21159. var i = tracks.length;
  21160. while (i--) {
  21161. if (track === tracks[i] || track === tracks[i].track) {
  21162. this.el().removeChild(tracks[i]);
  21163. }
  21164. }
  21165. }
  21166. };
  21167. /**
  21168. * Get the value of `playsinline` from the media element. `playsinline` indicates
  21169. * to the browser that non-fullscreen playback is preferred when fullscreen
  21170. * playback is the native default, such as in iOS Safari.
  21171. *
  21172. * @method Html5#playsinline
  21173. * @return {boolean}
  21174. * - The value of `playsinline` from the media element.
  21175. * - True indicates that the media should play inline.
  21176. * - False indicates that the media should not play inline.
  21177. *
  21178. * @see [Spec]{@link https://html.spec.whatwg.org/#attr-video-playsinline}
  21179. */
  21180. Html5.prototype.playsinline = function playsinline() {
  21181. return this.el_.hasAttribute('playsinline');
  21182. };
  21183. /**
  21184. * Set the value of `playsinline` from the media element. `playsinline` indicates
  21185. * to the browser that non-fullscreen playback is preferred when fullscreen
  21186. * playback is the native default, such as in iOS Safari.
  21187. *
  21188. * @method Html5#setPlaysinline
  21189. * @param {boolean} playsinline
  21190. * - True indicates that the media should play inline.
  21191. * - False indicates that the media should not play inline.
  21192. *
  21193. * @see [Spec]{@link https://html.spec.whatwg.org/#attr-video-playsinline}
  21194. */
  21195. Html5.prototype.setPlaysinline = function setPlaysinline(value) {
  21196. if (value) {
  21197. this.el_.setAttribute('playsinline', 'playsinline');
  21198. } else {
  21199. this.el_.removeAttribute('playsinline');
  21200. }
  21201. };
  21202. /**
  21203. * Gets available media playback quality metrics as specified by the W3C's Media
  21204. * Playback Quality API.
  21205. *
  21206. * @see [Spec]{@link https://wicg.github.io/media-playback-quality}
  21207. *
  21208. * @return {Object}
  21209. * An object with supported media playback quality metrics
  21210. */
  21211. Html5.prototype.getVideoPlaybackQuality = function getVideoPlaybackQuality() {
  21212. if (typeof this.el().getVideoPlaybackQuality === 'function') {
  21213. return this.el().getVideoPlaybackQuality();
  21214. }
  21215. var videoPlaybackQuality = {};
  21216. if (typeof this.el().webkitDroppedFrameCount !== 'undefined' && typeof this.el().webkitDecodedFrameCount !== 'undefined') {
  21217. videoPlaybackQuality.droppedVideoFrames = this.el().webkitDroppedFrameCount;
  21218. videoPlaybackQuality.totalVideoFrames = this.el().webkitDecodedFrameCount;
  21219. }
  21220. if (_window2['default'].performance && typeof _window2['default'].performance.now === 'function') {
  21221. videoPlaybackQuality.creationTime = _window2['default'].performance.now();
  21222. } else if (_window2['default'].performance && _window2['default'].performance.timing && typeof _window2['default'].performance.timing.navigationStart === 'number') {
  21223. videoPlaybackQuality.creationTime = _window2['default'].Date.now() - _window2['default'].performance.timing.navigationStart;
  21224. }
  21225. return videoPlaybackQuality;
  21226. };
  21227. return Html5;
  21228. }(_tech2['default']);
  21229. /* HTML5 Support Testing ---------------------------------------------------- */
  21230. if (Dom.isReal()) {
  21231. /**
  21232. * Element for testing browser HTML5 media capabilities
  21233. *
  21234. * @type {Element}
  21235. * @constant
  21236. * @private
  21237. */
  21238. Html5.TEST_VID = _document2['default'].createElement('video');
  21239. var track = _document2['default'].createElement('track');
  21240. track.kind = 'captions';
  21241. track.srclang = 'en';
  21242. track.label = 'English';
  21243. Html5.TEST_VID.appendChild(track);
  21244. }
  21245. /**
  21246. * Check if HTML5 media is supported by this browser/device.
  21247. *
  21248. * @return {boolean}
  21249. * - True if HTML5 media is supported.
  21250. * - False if HTML5 media is not supported.
  21251. */
  21252. Html5.isSupported = function () {
  21253. // IE9 with no Media Player is a LIAR! (#984)
  21254. try {
  21255. Html5.TEST_VID.volume = 0.5;
  21256. } catch (e) {
  21257. return false;
  21258. }
  21259. return !!(Html5.TEST_VID && Html5.TEST_VID.canPlayType);
  21260. };
  21261. /**
  21262. * Check if the volume can be changed in this browser/device.
  21263. * Volume cannot be changed in a lot of mobile devices.
  21264. * Specifically, it can't be changed from 1 on iOS.
  21265. *
  21266. * @return {boolean}
  21267. * - True if volume can be controlled
  21268. * - False otherwise
  21269. */
  21270. Html5.canControlVolume = function () {
  21271. // IE will error if Windows Media Player not installed #3315
  21272. try {
  21273. var volume = Html5.TEST_VID.volume;
  21274. Html5.TEST_VID.volume = volume / 2 + 0.1;
  21275. return volume !== Html5.TEST_VID.volume;
  21276. } catch (e) {
  21277. return false;
  21278. }
  21279. };
  21280. /**
  21281. * Check if the playback rate can be changed in this browser/device.
  21282. *
  21283. * @return {boolean}
  21284. * - True if playback rate can be controlled
  21285. * - False otherwise
  21286. */
  21287. Html5.canControlPlaybackRate = function () {
  21288. // Playback rate API is implemented in Android Chrome, but doesn't do anything
  21289. // https://github.com/videojs/video.js/issues/3180
  21290. if (browser.IS_ANDROID && browser.IS_CHROME && browser.CHROME_VERSION < 58) {
  21291. return false;
  21292. }
  21293. // IE will error if Windows Media Player not installed #3315
  21294. try {
  21295. var playbackRate = Html5.TEST_VID.playbackRate;
  21296. Html5.TEST_VID.playbackRate = playbackRate / 2 + 0.1;
  21297. return playbackRate !== Html5.TEST_VID.playbackRate;
  21298. } catch (e) {
  21299. return false;
  21300. }
  21301. };
  21302. /**
  21303. * Check to see if native `TextTrack`s are supported by this browser/device.
  21304. *
  21305. * @return {boolean}
  21306. * - True if native `TextTrack`s are supported.
  21307. * - False otherwise
  21308. */
  21309. Html5.supportsNativeTextTracks = function () {
  21310. return browser.IS_ANY_SAFARI;
  21311. };
  21312. /**
  21313. * Check to see if native `VideoTrack`s are supported by this browser/device
  21314. *
  21315. * @return {boolean}
  21316. * - True if native `VideoTrack`s are supported.
  21317. * - False otherwise
  21318. */
  21319. Html5.supportsNativeVideoTracks = function () {
  21320. return !!(Html5.TEST_VID && Html5.TEST_VID.videoTracks);
  21321. };
  21322. /**
  21323. * Check to see if native `AudioTrack`s are supported by this browser/device
  21324. *
  21325. * @return {boolean}
  21326. * - True if native `AudioTrack`s are supported.
  21327. * - False otherwise
  21328. */
  21329. Html5.supportsNativeAudioTracks = function () {
  21330. return !!(Html5.TEST_VID && Html5.TEST_VID.audioTracks);
  21331. };
  21332. /**
  21333. * An array of events available on the Html5 tech.
  21334. *
  21335. * @private
  21336. * @type {Array}
  21337. */
  21338. Html5.Events = ['loadstart', 'suspend', 'abort', 'error', 'emptied', 'stalled', 'loadedmetadata', 'loadeddata', 'canplay', 'canplaythrough', 'playing', 'waiting', 'seeking', 'seeked', 'ended', 'durationchange', 'timeupdate', 'progress', 'play', 'pause', 'ratechange', 'volumechange'];
  21339. /**
  21340. * Boolean indicating whether the `Tech` supports volume control.
  21341. *
  21342. * @type {boolean}
  21343. * @default {@link Html5.canControlVolume}
  21344. */
  21345. Html5.prototype.featuresVolumeControl = Html5.canControlVolume();
  21346. /**
  21347. * Boolean indicating whether the `Tech` supports changing the speed at which the media
  21348. * plays. Examples:
  21349. * - Set player to play 2x (twice) as fast
  21350. * - Set player to play 0.5x (half) as fast
  21351. *
  21352. * @type {boolean}
  21353. * @default {@link Html5.canControlPlaybackRate}
  21354. */
  21355. Html5.prototype.featuresPlaybackRate = Html5.canControlPlaybackRate();
  21356. /**
  21357. * Boolean indicating whether the `HTML5` tech currently supports the media element
  21358. * moving in the DOM. iOS breaks if you move the media element, so this is set this to
  21359. * false there. Everywhere else this should be true.
  21360. *
  21361. * @type {boolean}
  21362. * @default
  21363. */
  21364. Html5.prototype.movingMediaElementInDOM = !browser.IS_IOS;
  21365. // TODO: Previous comment: No longer appears to be used. Can probably be removed.
  21366. // Is this true?
  21367. /**
  21368. * Boolean indicating whether the `HTML5` tech currently supports automatic media resize
  21369. * when going into fullscreen.
  21370. *
  21371. * @type {boolean}
  21372. * @default
  21373. */
  21374. Html5.prototype.featuresFullscreenResize = true;
  21375. /**
  21376. * Boolean indicating whether the `HTML5` tech currently supports the progress event.
  21377. * If this is false, manual `progress` events will be triggred instead.
  21378. *
  21379. * @type {boolean}
  21380. * @default
  21381. */
  21382. Html5.prototype.featuresProgressEvents = true;
  21383. /**
  21384. * Boolean indicating whether the `HTML5` tech currently supports the timeupdate event.
  21385. * If this is false, manual `timeupdate` events will be triggred instead.
  21386. *
  21387. * @default
  21388. */
  21389. Html5.prototype.featuresTimeupdateEvents = true;
  21390. /**
  21391. * Boolean indicating whether the `HTML5` tech currently supports native `TextTrack`s.
  21392. *
  21393. * @type {boolean}
  21394. * @default {@link Html5.supportsNativeTextTracks}
  21395. */
  21396. Html5.prototype.featuresNativeTextTracks = Html5.supportsNativeTextTracks();
  21397. /**
  21398. * Boolean indicating whether the `HTML5` tech currently supports native `VideoTrack`s.
  21399. *
  21400. * @type {boolean}
  21401. * @default {@link Html5.supportsNativeVideoTracks}
  21402. */
  21403. Html5.prototype.featuresNativeVideoTracks = Html5.supportsNativeVideoTracks();
  21404. /**
  21405. * Boolean indicating whether the `HTML5` tech currently supports native `AudioTrack`s.
  21406. *
  21407. * @type {boolean}
  21408. * @default {@link Html5.supportsNativeAudioTracks}
  21409. */
  21410. Html5.prototype.featuresNativeAudioTracks = Html5.supportsNativeAudioTracks();
  21411. // HTML5 Feature detection and Device Fixes --------------------------------- //
  21412. var canPlayType = Html5.TEST_VID && Html5.TEST_VID.constructor.prototype.canPlayType;
  21413. var mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl/i;
  21414. var mp4RE = /^video\/mp4/i;
  21415. Html5.patchCanPlayType = function () {
  21416. // Android 4.0 and above can play HLS to some extent but it reports being unable to do so
  21417. if (browser.ANDROID_VERSION >= 4.0 && !browser.IS_FIREFOX) {
  21418. Html5.TEST_VID.constructor.prototype.canPlayType = function (type) {
  21419. if (type && mpegurlRE.test(type)) {
  21420. return 'maybe';
  21421. }
  21422. return canPlayType.call(this, type);
  21423. };
  21424. // Override Android 2.2 and less canPlayType method which is broken
  21425. } else if (browser.IS_OLD_ANDROID) {
  21426. Html5.TEST_VID.constructor.prototype.canPlayType = function (type) {
  21427. if (type && mp4RE.test(type)) {
  21428. return 'maybe';
  21429. }
  21430. return canPlayType.call(this, type);
  21431. };
  21432. }
  21433. };
  21434. Html5.unpatchCanPlayType = function () {
  21435. var r = Html5.TEST_VID.constructor.prototype.canPlayType;
  21436. Html5.TEST_VID.constructor.prototype.canPlayType = canPlayType;
  21437. return r;
  21438. };
  21439. // by default, patch the media element
  21440. Html5.patchCanPlayType();
  21441. Html5.disposeMediaElement = function (el) {
  21442. if (!el) {
  21443. return;
  21444. }
  21445. if (el.parentNode) {
  21446. el.parentNode.removeChild(el);
  21447. }
  21448. // remove any child track or source nodes to prevent their loading
  21449. while (el.hasChildNodes()) {
  21450. el.removeChild(el.firstChild);
  21451. }
  21452. // remove any src reference. not setting `src=''` because that causes a warning
  21453. // in firefox
  21454. el.removeAttribute('src');
  21455. // force the media element to update its loading state by calling load()
  21456. // however IE on Windows 7N has a bug that throws an error so need a try/catch (#793)
  21457. if (typeof el.load === 'function') {
  21458. // wrapping in an iife so it's not deoptimized (#1060#discussion_r10324473)
  21459. (function () {
  21460. try {
  21461. el.load();
  21462. } catch (e) {
  21463. // not supported
  21464. }
  21465. })();
  21466. }
  21467. };
  21468. Html5.resetMediaElement = function (el) {
  21469. if (!el) {
  21470. return;
  21471. }
  21472. var sources = el.querySelectorAll('source');
  21473. var i = sources.length;
  21474. while (i--) {
  21475. el.removeChild(sources[i]);
  21476. }
  21477. // remove any src reference.
  21478. // not setting `src=''` because that throws an error
  21479. el.removeAttribute('src');
  21480. if (typeof el.load === 'function') {
  21481. // wrapping in an iife so it's not deoptimized (#1060#discussion_r10324473)
  21482. (function () {
  21483. try {
  21484. el.load();
  21485. } catch (e) {
  21486. // satisfy linter
  21487. }
  21488. })();
  21489. }
  21490. };
  21491. /* Native HTML5 element property wrapping ----------------------------------- */
  21492. // Wrap native properties with a getter
  21493. [
  21494. /**
  21495. * Get the value of `paused` from the media element. `paused` indicates whether the media element
  21496. * is currently paused or not.
  21497. *
  21498. * @method Html5#paused
  21499. * @return {boolean}
  21500. * The value of `paused` from the media element.
  21501. *
  21502. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-paused}
  21503. */
  21504. 'paused',
  21505. /**
  21506. * Get the value of `currentTime` from the media element. `currentTime` indicates
  21507. * the current second that the media is at in playback.
  21508. *
  21509. * @method Html5#currentTime
  21510. * @return {number}
  21511. * The value of `currentTime` from the media element.
  21512. *
  21513. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-currenttime}
  21514. */
  21515. 'currentTime',
  21516. /**
  21517. * Get the value of `buffered` from the media element. `buffered` is a `TimeRange`
  21518. * object that represents the parts of the media that are already downloaded and
  21519. * available for playback.
  21520. *
  21521. * @method Html5#buffered
  21522. * @return {TimeRange}
  21523. * The value of `buffered` from the media element.
  21524. *
  21525. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-buffered}
  21526. */
  21527. 'buffered',
  21528. /**
  21529. * Get the value of `volume` from the media element. `volume` indicates
  21530. * the current playback volume of audio for a media. `volume` will be a value from 0
  21531. * (silent) to 1 (loudest and default).
  21532. *
  21533. * @method Html5#volume
  21534. * @return {number}
  21535. * The value of `volume` from the media element. Value will be between 0-1.
  21536. *
  21537. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-a-volume}
  21538. */
  21539. 'volume',
  21540. /**
  21541. * Get the value of `muted` from the media element. `muted` indicates
  21542. * that the volume for the media should be set to silent. This does not actually change
  21543. * the `volume` attribute.
  21544. *
  21545. * @method Html5#muted
  21546. * @return {boolean}
  21547. * - True if the value of `volume` should be ignored and the audio set to silent.
  21548. * - False if the value of `volume` should be used.
  21549. *
  21550. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-muted}
  21551. */
  21552. 'muted',
  21553. /**
  21554. * Get the value of `poster` from the media element. `poster` indicates
  21555. * that the url of an image file that can/will be shown when no media data is available.
  21556. *
  21557. * @method Html5#poster
  21558. * @return {string}
  21559. * The value of `poster` from the media element. Value will be a url to an
  21560. * image.
  21561. *
  21562. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-video-poster}
  21563. */
  21564. 'poster',
  21565. /**
  21566. * Get the value of `preload` from the media element. `preload` indicates
  21567. * what should download before the media is interacted with. It can have the following
  21568. * values:
  21569. * - none: nothing should be downloaded
  21570. * - metadata: poster and the first few frames of the media may be downloaded to get
  21571. * media dimensions and other metadata
  21572. * - auto: allow the media and metadata for the media to be downloaded before
  21573. * interaction
  21574. *
  21575. * @method Html5#preload
  21576. * @return {string}
  21577. * The value of `preload` from the media element. Will be 'none', 'metadata',
  21578. * or 'auto'.
  21579. *
  21580. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-preload}
  21581. */
  21582. 'preload',
  21583. /**
  21584. * Get the value of `autoplay` from the media element. `autoplay` indicates
  21585. * that the media should start to play as soon as the page is ready.
  21586. *
  21587. * @method Html5#autoplay
  21588. * @return {boolean}
  21589. * - The value of `autoplay` from the media element.
  21590. * - True indicates that the media should start as soon as the page loads.
  21591. * - False indicates that the media should not start as soon as the page loads.
  21592. *
  21593. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-autoplay}
  21594. */
  21595. 'autoplay',
  21596. /**
  21597. * Get the value of `controls` from the media element. `controls` indicates
  21598. * whether the native media controls should be shown or hidden.
  21599. *
  21600. * @method Html5#controls
  21601. * @return {boolean}
  21602. * - The value of `controls` from the media element.
  21603. * - True indicates that native controls should be showing.
  21604. * - False indicates that native controls should be hidden.
  21605. *
  21606. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-controls}
  21607. */
  21608. 'controls',
  21609. /**
  21610. * Get the value of `loop` from the media element. `loop` indicates
  21611. * that the media should return to the start of the media and continue playing once
  21612. * it reaches the end.
  21613. *
  21614. * @method Html5#loop
  21615. * @return {boolean}
  21616. * - The value of `loop` from the media element.
  21617. * - True indicates that playback should seek back to start once
  21618. * the end of a media is reached.
  21619. * - False indicates that playback should not loop back to the start when the
  21620. * end of the media is reached.
  21621. *
  21622. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-loop}
  21623. */
  21624. 'loop',
  21625. /**
  21626. * Get the value of the `error` from the media element. `error` indicates any
  21627. * MediaError that may have occured during playback. If error returns null there is no
  21628. * current error.
  21629. *
  21630. * @method Html5#error
  21631. * @return {MediaError|null}
  21632. * The value of `error` from the media element. Will be `MediaError` if there
  21633. * is a current error and null otherwise.
  21634. *
  21635. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-error}
  21636. */
  21637. 'error',
  21638. /**
  21639. * Get the value of `seeking` from the media element. `seeking` indicates whether the
  21640. * media is currently seeking to a new position or not.
  21641. *
  21642. * @method Html5#seeking
  21643. * @return {boolean}
  21644. * - The value of `seeking` from the media element.
  21645. * - True indicates that the media is currently seeking to a new position.
  21646. * - Flase indicates that the media is not seeking to a new position at this time.
  21647. *
  21648. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-seeking}
  21649. */
  21650. 'seeking',
  21651. /**
  21652. * Get the value of `seekable` from the media element. `seekable` returns a
  21653. * `TimeRange` object indicating ranges of time that can currently be `seeked` to.
  21654. *
  21655. * @method Html5#seekable
  21656. * @return {TimeRange}
  21657. * The value of `seekable` from the media element. A `TimeRange` object
  21658. * indicating the current ranges of time that can be seeked to.
  21659. *
  21660. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-seekable}
  21661. */
  21662. 'seekable',
  21663. /**
  21664. * Get the value of `ended` from the media element. `ended` indicates whether
  21665. * the media has reached the end or not.
  21666. *
  21667. * @method Html5#ended
  21668. * @return {boolean}
  21669. * - The value of `ended` from the media element.
  21670. * - True indicates that the media has ended.
  21671. * - False indicates that the media has not ended.
  21672. *
  21673. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-ended}
  21674. */
  21675. 'ended',
  21676. /**
  21677. * Get the value of `defaultMuted` from the media element. `defaultMuted` indicates
  21678. * whether the media should start muted or not. Only changes the default state of the
  21679. * media. `muted` and `defaultMuted` can have different values. `muted` indicates the
  21680. * current state.
  21681. *
  21682. * @method Html5#defaultMuted
  21683. * @return {boolean}
  21684. * - The value of `defaultMuted` from the media element.
  21685. * - True indicates that the media should start muted.
  21686. * - False indicates that the media should not start muted
  21687. *
  21688. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-defaultmuted}
  21689. */
  21690. 'defaultMuted',
  21691. /**
  21692. * Get the value of `playbackRate` from the media element. `playbackRate` indicates
  21693. * the rate at which the media is currently playing back. Examples:
  21694. * - if playbackRate is set to 2, media will play twice as fast.
  21695. * - if playbackRate is set to 0.5, media will play half as fast.
  21696. *
  21697. * @method Html5#playbackRate
  21698. * @return {number}
  21699. * The value of `playbackRate` from the media element. A number indicating
  21700. * the current playback speed of the media, where 1 is normal speed.
  21701. *
  21702. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-playbackrate}
  21703. */
  21704. 'playbackRate',
  21705. /**
  21706. * Get the value of `played` from the media element. `played` returns a `TimeRange`
  21707. * object representing points in the media timeline that have been played.
  21708. *
  21709. * @method Html5#played
  21710. * @return {TimeRange}
  21711. * The value of `played` from the media element. A `TimeRange` object indicating
  21712. * the ranges of time that have been played.
  21713. *
  21714. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-played}
  21715. */
  21716. 'played',
  21717. /**
  21718. * Get the value of `networkState` from the media element. `networkState` indicates
  21719. * the current network state. It returns an enumeration from the following list:
  21720. * - 0: NETWORK_EMPTY
  21721. * - 1: NEWORK_IDLE
  21722. * - 2: NETWORK_LOADING
  21723. * - 3: NETWORK_NO_SOURCE
  21724. *
  21725. * @method Html5#networkState
  21726. * @return {number}
  21727. * The value of `networkState` from the media element. This will be a number
  21728. * from the list in the description.
  21729. *
  21730. * @see [Spec] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-networkstate}
  21731. */
  21732. 'networkState',
  21733. /**
  21734. * Get the value of `readyState` from the media element. `readyState` indicates
  21735. * the current state of the media element. It returns an enumeration from the
  21736. * following list:
  21737. * - 0: HAVE_NOTHING
  21738. * - 1: HAVE_METADATA
  21739. * - 2: HAVE_CURRENT_DATA
  21740. * - 3: HAVE_FUTURE_DATA
  21741. * - 4: HAVE_ENOUGH_DATA
  21742. *
  21743. * @method Html5#readyState
  21744. * @return {number}
  21745. * The value of `readyState` from the media element. This will be a number
  21746. * from the list in the description.
  21747. *
  21748. * @see [Spec] {@link https://www.w3.org/TR/html5/embedded-content-0.html#ready-states}
  21749. */
  21750. 'readyState',
  21751. /**
  21752. * Get the value of `videoWidth` from the video element. `videoWidth` indicates
  21753. * the current width of the video in css pixels.
  21754. *
  21755. * @method Html5#videoWidth
  21756. * @return {number}
  21757. * The value of `videoWidth` from the video element. This will be a number
  21758. * in css pixels.
  21759. *
  21760. * @see [Spec] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-video-videowidth}
  21761. */
  21762. 'videoWidth',
  21763. /**
  21764. * Get the value of `videoHeight` from the video element. `videoHeigth` indicates
  21765. * the current height of the video in css pixels.
  21766. *
  21767. * @method Html5#videoHeight
  21768. * @return {number}
  21769. * The value of `videoHeight` from the video element. This will be a number
  21770. * in css pixels.
  21771. *
  21772. * @see [Spec] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-video-videowidth}
  21773. */
  21774. 'videoHeight'].forEach(function (prop) {
  21775. Html5.prototype[prop] = function () {
  21776. return this.el_[prop];
  21777. };
  21778. });
  21779. // Wrap native properties with a setter in this format:
  21780. // set + toTitleCase(name)
  21781. [
  21782. /**
  21783. * Set the value of `volume` on the media element. `volume` indicates the current
  21784. * audio level as a percentage in decimal form. This means that 1 is 100%, 0.5 is 50%, and
  21785. * so on.
  21786. *
  21787. * @method Html5#setVolume
  21788. * @param {number} percentAsDecimal
  21789. * The volume percent as a decimal. Valid range is from 0-1.
  21790. *
  21791. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-a-volume}
  21792. */
  21793. 'volume',
  21794. /**
  21795. * Set the value of `muted` on the media element. `muted` indicates the current
  21796. * audio level should be silent.
  21797. *
  21798. * @method Html5#setMuted
  21799. * @param {boolean} muted
  21800. * - True if the audio should be set to silent
  21801. * - False otherwise
  21802. *
  21803. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-muted}
  21804. */
  21805. 'muted',
  21806. /**
  21807. * Set the value of `src` on the media element. `src` indicates the current
  21808. * {@link Tech~SourceObject} for the media.
  21809. *
  21810. * @method Html5#setSrc
  21811. * @param {Tech~SourceObject} src
  21812. * The source object to set as the current source.
  21813. *
  21814. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-src}
  21815. */
  21816. 'src',
  21817. /**
  21818. * Set the value of `poster` on the media element. `poster` is the url to
  21819. * an image file that can/will be shown when no media data is available.
  21820. *
  21821. * @method Html5#setPoster
  21822. * @param {string} poster
  21823. * The url to an image that should be used as the `poster` for the media
  21824. * element.
  21825. *
  21826. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-poster}
  21827. */
  21828. 'poster',
  21829. /**
  21830. * Set the value of `preload` on the media element. `preload` indicates
  21831. * what should download before the media is interacted with. It can have the following
  21832. * values:
  21833. * - none: nothing should be downloaded
  21834. * - metadata: poster and the first few frames of the media may be downloaded to get
  21835. * media dimensions and other metadata
  21836. * - auto: allow the media and metadata for the media to be downloaded before
  21837. * interaction
  21838. *
  21839. * @method Html5#setPreload
  21840. * @param {string} preload
  21841. * The value of `preload` to set on the media element. Must be 'none', 'metadata',
  21842. * or 'auto'.
  21843. *
  21844. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-preload}
  21845. */
  21846. 'preload',
  21847. /**
  21848. * Set the value of `autoplay` on the media element. `autoplay` indicates
  21849. * that the media should start to play as soon as the page is ready.
  21850. *
  21851. * @method Html5#setAutoplay
  21852. * @param {boolean} autoplay
  21853. * - True indicates that the media should start as soon as the page loads.
  21854. * - False indicates that the media should not start as soon as the page loads.
  21855. *
  21856. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-autoplay}
  21857. */
  21858. 'autoplay',
  21859. /**
  21860. * Set the value of `loop` on the media element. `loop` indicates
  21861. * that the media should return to the start of the media and continue playing once
  21862. * it reaches the end.
  21863. *
  21864. * @method Html5#setLoop
  21865. * @param {boolean} loop
  21866. * - True indicates that playback should seek back to start once
  21867. * the end of a media is reached.
  21868. * - False indicates that playback should not loop back to the start when the
  21869. * end of the media is reached.
  21870. *
  21871. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-loop}
  21872. */
  21873. 'loop',
  21874. /**
  21875. * Set the value of `playbackRate` on the media element. `playbackRate` indicates
  21876. * the rate at which the media should play back. Examples:
  21877. * - if playbackRate is set to 2, media will play twice as fast.
  21878. * - if playbackRate is set to 0.5, media will play half as fast.
  21879. *
  21880. * @method Html5#setPlaybackRate
  21881. * @return {number}
  21882. * The value of `playbackRate` from the media element. A number indicating
  21883. * the current playback speed of the media, where 1 is normal speed.
  21884. *
  21885. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-playbackrate}
  21886. */
  21887. 'playbackRate'].forEach(function (prop) {
  21888. Html5.prototype['set' + (0, _toTitleCase2['default'])(prop)] = function (v) {
  21889. this.el_[prop] = v;
  21890. };
  21891. });
  21892. // wrap native functions with a function
  21893. [
  21894. /**
  21895. * A wrapper around the media elements `pause` function. This will call the `HTML5`
  21896. * media elements `pause` function.
  21897. *
  21898. * @method Html5#pause
  21899. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-pause}
  21900. */
  21901. 'pause',
  21902. /**
  21903. * A wrapper around the media elements `load` function. This will call the `HTML5`s
  21904. * media element `load` function.
  21905. *
  21906. * @method Html5#load
  21907. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-load}
  21908. */
  21909. 'load'].forEach(function (prop) {
  21910. Html5.prototype[prop] = function () {
  21911. return this.el_[prop]();
  21912. };
  21913. });
  21914. _tech2['default'].withSourceHandlers(Html5);
  21915. /**
  21916. * Native source handler for Html5, simply passes the source to the media element.
  21917. *
  21918. * @proprety {Tech~SourceObject} source
  21919. * The source object
  21920. *
  21921. * @proprety {Html5} tech
  21922. * The instance of the HTML5 tech.
  21923. */
  21924. Html5.nativeSourceHandler = {};
  21925. /**
  21926. * Check if the media element can play the given mime type.
  21927. *
  21928. * @param {string} type
  21929. * The mimetype to check
  21930. *
  21931. * @return {string}
  21932. * 'probably', 'maybe', or '' (empty string)
  21933. */
  21934. Html5.nativeSourceHandler.canPlayType = function (type) {
  21935. // IE9 on Windows 7 without MediaPlayer throws an error here
  21936. // https://github.com/videojs/video.js/issues/519
  21937. try {
  21938. return Html5.TEST_VID.canPlayType(type);
  21939. } catch (e) {
  21940. return '';
  21941. }
  21942. };
  21943. /**
  21944. * Check if the media element can handle a source natively.
  21945. *
  21946. * @param {Tech~SourceObject} source
  21947. * The source object
  21948. *
  21949. * @param {Object} [options]
  21950. * Options to be passed to the tech.
  21951. *
  21952. * @return {string}
  21953. * 'probably', 'maybe', or '' (empty string).
  21954. */
  21955. Html5.nativeSourceHandler.canHandleSource = function (source, options) {
  21956. // If a type was provided we should rely on that
  21957. if (source.type) {
  21958. return Html5.nativeSourceHandler.canPlayType(source.type);
  21959. // If no type, fall back to checking 'video/[EXTENSION]'
  21960. } else if (source.src) {
  21961. var ext = Url.getFileExtension(source.src);
  21962. return Html5.nativeSourceHandler.canPlayType('video/' + ext);
  21963. }
  21964. return '';
  21965. };
  21966. /**
  21967. * Pass the source to the native media element.
  21968. *
  21969. * @param {Tech~SourceObject} source
  21970. * The source object
  21971. *
  21972. * @param {Html5} tech
  21973. * The instance of the Html5 tech
  21974. *
  21975. * @param {Object} [options]
  21976. * The options to pass to the source
  21977. */
  21978. Html5.nativeSourceHandler.handleSource = function (source, tech, options) {
  21979. tech.setSrc(source.src);
  21980. };
  21981. /**
  21982. * A noop for the native dispose function, as cleanup is not needed.
  21983. */
  21984. Html5.nativeSourceHandler.dispose = function () {};
  21985. // Register the native source handler
  21986. Html5.registerSourceHandler(Html5.nativeSourceHandler);
  21987. _component2['default'].registerComponent('Html5', Html5);
  21988. _tech2['default'].registerTech('Html5', Html5);
  21989. exports['default'] = Html5;
  21990. /***/ }),
  21991. /* 110 */
  21992. /***/ (function(module, exports, __webpack_require__) {
  21993. 'use strict';
  21994. exports.__esModule = true;
  21995. var _player = __webpack_require__(24);
  21996. var _player2 = _interopRequireDefault(_player);
  21997. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  21998. /**
  21999. * The method for registering a video.js plugin. {@link videojs:videojs.registerPlugin].
  22000. *
  22001. * @param {string} name
  22002. * The name of the plugin that is being registered
  22003. *
  22004. * @param {plugins:PluginFn} init
  22005. * The function that gets run when a `Player` initializes.
  22006. */
  22007. var plugin = function plugin(name, init) {
  22008. _player2['default'].prototype[name] = init;
  22009. }; /**
  22010. * @file plugins.js
  22011. * @module plugins
  22012. */
  22013. exports['default'] = plugin;
  22014. /***/ }),
  22015. /* 111 */
  22016. /***/ (function(module, exports, __webpack_require__) {
  22017. 'use strict';
  22018. exports.__esModule = true;
  22019. var _trackEnums = __webpack_require__(36);
  22020. var _track = __webpack_require__(37);
  22021. var _track2 = _interopRequireDefault(_track);
  22022. var _mergeOptions = __webpack_require__(22);
  22023. var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
  22024. var _browser = __webpack_require__(10);
  22025. var browser = _interopRequireWildcard(_browser);
  22026. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  22027. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  22028. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  22029. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  22030. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  22031. /**
  22032. * A representation of a single `AudioTrack`. If it is part of an {@link AudioTrackList}
  22033. * only one `AudioTrack` in the list will be enabled at a time.
  22034. *
  22035. * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#audiotrack}
  22036. * @extends Track
  22037. */
  22038. var AudioTrack = function (_Track) {
  22039. _inherits(AudioTrack, _Track);
  22040. /**
  22041. * Create an instance of this class.
  22042. *
  22043. * @param {Object} [options={}]
  22044. * Object of option names and values
  22045. *
  22046. * @param {AudioTrack~Kind} [options.kind='']
  22047. * A valid audio track kind
  22048. *
  22049. * @param {string} [options.id='vjs_track_' + Guid.newGUID()]
  22050. * A unique id for this AudioTrack.
  22051. *
  22052. * @param {string} [options.label='']
  22053. * The menu label for this track.
  22054. *
  22055. * @param {string} [options.language='']
  22056. * A valid two character language code.
  22057. *
  22058. * @param {boolean} [options.enabled]
  22059. * If this track is the one that is currently playing. If this track is part of
  22060. * an {@link AudioTrackList}, only one {@link AudioTrack} will be enabled.
  22061. */
  22062. function AudioTrack() {
  22063. var _this, _ret;
  22064. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  22065. _classCallCheck(this, AudioTrack);
  22066. var settings = (0, _mergeOptions2['default'])(options, {
  22067. kind: _trackEnums.AudioTrackKind[options.kind] || ''
  22068. });
  22069. // on IE8 this will be a document element
  22070. // for every other browser this will be a normal object
  22071. var track = (_this = _possibleConstructorReturn(this, _Track.call(this, settings)), _this);
  22072. var enabled = false;
  22073. if (browser.IS_IE8) {
  22074. for (var prop in AudioTrack.prototype) {
  22075. if (prop !== 'constructor') {
  22076. track[prop] = AudioTrack.prototype[prop];
  22077. }
  22078. }
  22079. }
  22080. /**
  22081. * @member {boolean} enabled
  22082. * If this `AudioTrack` is enabled or not. When setting this will
  22083. * fire {@link AudioTrack#enabledchange} if the state of enabled is changed.
  22084. *
  22085. * @fires VideoTrack#selectedchange
  22086. */
  22087. Object.defineProperty(track, 'enabled', {
  22088. get: function get() {
  22089. return enabled;
  22090. },
  22091. set: function set(newEnabled) {
  22092. // an invalid or unchanged value
  22093. if (typeof newEnabled !== 'boolean' || newEnabled === enabled) {
  22094. return;
  22095. }
  22096. enabled = newEnabled;
  22097. /**
  22098. * An event that fires when enabled changes on this track. This allows
  22099. * the AudioTrackList that holds this track to act accordingly.
  22100. *
  22101. * > Note: This is not part of the spec! Native tracks will do
  22102. * this internally without an event.
  22103. *
  22104. * @event AudioTrack#enabledchange
  22105. * @type {EventTarget~Event}
  22106. */
  22107. this.trigger('enabledchange');
  22108. }
  22109. });
  22110. // if the user sets this track to selected then
  22111. // set selected to that true value otherwise
  22112. // we keep it false
  22113. if (settings.enabled) {
  22114. track.enabled = settings.enabled;
  22115. }
  22116. track.loaded_ = true;
  22117. return _ret = track, _possibleConstructorReturn(_this, _ret);
  22118. }
  22119. return AudioTrack;
  22120. }(_track2['default']);
  22121. exports['default'] = AudioTrack;
  22122. /***/ }),
  22123. /* 112 */
  22124. /***/ (function(module, exports, __webpack_require__) {
  22125. 'use strict';
  22126. exports.__esModule = true;
  22127. var _trackEnums = __webpack_require__(36);
  22128. var _track = __webpack_require__(37);
  22129. var _track2 = _interopRequireDefault(_track);
  22130. var _mergeOptions = __webpack_require__(22);
  22131. var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
  22132. var _browser = __webpack_require__(10);
  22133. var browser = _interopRequireWildcard(_browser);
  22134. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
  22135. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  22136. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  22137. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  22138. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  22139. /**
  22140. * A representation of a single `VideoTrack`.
  22141. *
  22142. * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#videotrack}
  22143. * @extends Track
  22144. */
  22145. var VideoTrack = function (_Track) {
  22146. _inherits(VideoTrack, _Track);
  22147. /**
  22148. * Create an instance of this class.
  22149. *
  22150. * @param {Object} [options={}]
  22151. * Object of option names and values
  22152. *
  22153. * @param {string} [options.kind='']
  22154. * A valid {@link VideoTrack~Kind}
  22155. *
  22156. * @param {string} [options.id='vjs_track_' + Guid.newGUID()]
  22157. * A unique id for this AudioTrack.
  22158. *
  22159. * @param {string} [options.label='']
  22160. * The menu label for this track.
  22161. *
  22162. * @param {string} [options.language='']
  22163. * A valid two character language code.
  22164. *
  22165. * @param {boolean} [options.selected]
  22166. * If this track is the one that is currently playing.
  22167. */
  22168. function VideoTrack() {
  22169. var _this, _ret;
  22170. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  22171. _classCallCheck(this, VideoTrack);
  22172. var settings = (0, _mergeOptions2['default'])(options, {
  22173. kind: _trackEnums.VideoTrackKind[options.kind] || ''
  22174. });
  22175. // on IE8 this will be a document element
  22176. // for every other browser this will be a normal object
  22177. var track = (_this = _possibleConstructorReturn(this, _Track.call(this, settings)), _this);
  22178. var selected = false;
  22179. if (browser.IS_IE8) {
  22180. for (var prop in VideoTrack.prototype) {
  22181. if (prop !== 'constructor') {
  22182. track[prop] = VideoTrack.prototype[prop];
  22183. }
  22184. }
  22185. }
  22186. /**
  22187. * @member {boolean} selected
  22188. * If this `VideoTrack` is selected or not. When setting this will
  22189. * fire {@link VideoTrack#selectedchange} if the state of selected changed.
  22190. *
  22191. * @fires VideoTrack#selectedchange
  22192. */
  22193. Object.defineProperty(track, 'selected', {
  22194. get: function get() {
  22195. return selected;
  22196. },
  22197. set: function set(newSelected) {
  22198. // an invalid or unchanged value
  22199. if (typeof newSelected !== 'boolean' || newSelected === selected) {
  22200. return;
  22201. }
  22202. selected = newSelected;
  22203. /**
  22204. * An event that fires when selected changes on this track. This allows
  22205. * the VideoTrackList that holds this track to act accordingly.
  22206. *
  22207. * > Note: This is not part of the spec! Native tracks will do
  22208. * this internally without an event.
  22209. *
  22210. * @event VideoTrack#selectedchange
  22211. * @type {EventTarget~Event}
  22212. */
  22213. this.trigger('selectedchange');
  22214. }
  22215. });
  22216. // if the user sets this track to selected then
  22217. // set selected to that true value otherwise
  22218. // we keep it false
  22219. if (settings.selected) {
  22220. track.selected = settings.selected;
  22221. }
  22222. return _ret = track, _possibleConstructorReturn(_this, _ret);
  22223. }
  22224. return VideoTrack;
  22225. }(_track2['default']);
  22226. exports['default'] = VideoTrack;
  22227. /***/ }),
  22228. /* 113 */
  22229. /***/ (function(module, exports, __webpack_require__) {
  22230. 'use strict';
  22231. exports.__esModule = true;
  22232. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  22233. var _log = __webpack_require__(13);
  22234. var _log2 = _interopRequireDefault(_log);
  22235. var _obj = __webpack_require__(14);
  22236. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  22237. /**
  22238. * @file extend.js
  22239. * @module extend
  22240. */
  22241. /**
  22242. * A combination of node inherits and babel's inherits (after transpile).
  22243. * Both work the same but node adds `super_` to the subClass
  22244. * and Bable adds the superClass as __proto__. Both seem useful.
  22245. *
  22246. * @param {Object} subClass
  22247. * The class to inherit to
  22248. *
  22249. * @param {Object} superClass
  22250. * The class to inherit from
  22251. *
  22252. * @private
  22253. */
  22254. var _inherits = function _inherits(subClass, superClass) {
  22255. if (typeof superClass !== 'function' && superClass !== null) {
  22256. throw new TypeError('Super expression must either be null or a function, not ' + (typeof superClass === 'undefined' ? 'undefined' : _typeof(superClass)));
  22257. }
  22258. subClass.prototype = Object.create(superClass && superClass.prototype, {
  22259. constructor: {
  22260. value: subClass,
  22261. enumerable: false,
  22262. writable: true,
  22263. configurable: true
  22264. }
  22265. });
  22266. if (superClass) {
  22267. // node
  22268. subClass.super_ = superClass;
  22269. }
  22270. };
  22271. /**
  22272. * Function for subclassing using the same inheritance that
  22273. * videojs uses internally
  22274. *
  22275. * @param {Object} superClass
  22276. * The class to inherit from
  22277. *
  22278. * @param {Object} [subClassMethods={}]
  22279. * The class to inherit to
  22280. *
  22281. * @return {Object}
  22282. * The new object with subClassMethods that inherited superClass.
  22283. */
  22284. var extendFn = function extendFn(superClass) {
  22285. var subClassMethods = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  22286. var subClass = function subClass() {
  22287. superClass.apply(this, arguments);
  22288. };
  22289. var methods = {};
  22290. if ((0, _obj.isObject)(subClassMethods)) {
  22291. if (typeof subClassMethods.init === 'function') {
  22292. _log2['default'].warn('Constructor logic via init() is deprecated; please use constructor() instead.');
  22293. subClassMethods.constructor = subClassMethods.init;
  22294. }
  22295. if (subClassMethods.constructor !== Object.prototype.constructor) {
  22296. subClass = subClassMethods.constructor;
  22297. }
  22298. methods = subClassMethods;
  22299. } else if (typeof subClassMethods === 'function') {
  22300. subClass = subClassMethods;
  22301. }
  22302. _inherits(subClass, superClass);
  22303. // Extend subObj's prototype with functions and other properties from props
  22304. for (var name in methods) {
  22305. if (methods.hasOwnProperty(name)) {
  22306. subClass.prototype[name] = methods[name];
  22307. }
  22308. }
  22309. return subClass;
  22310. };
  22311. exports['default'] = extendFn;
  22312. /***/ }),
  22313. /* 114 */
  22314. /***/ (function(module, exports, __webpack_require__) {
  22315. /**
  22316. * @file flash-source-buffer.js
  22317. */
  22318. 'use strict';
  22319. Object.defineProperty(exports, '__esModule', {
  22320. value: true
  22321. });
  22322. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  22323. var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
  22324. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  22325. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
  22326. function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  22327. var _globalWindow = __webpack_require__(2);
  22328. var _globalWindow2 = _interopRequireDefault(_globalWindow);
  22329. var _videoJs = __webpack_require__(6);
  22330. var _videoJs2 = _interopRequireDefault(_videoJs);
  22331. var _muxJsLibFlv = __webpack_require__(115);
  22332. var _muxJsLibFlv2 = _interopRequireDefault(_muxJsLibFlv);
  22333. var _removeCuesFromTrack = __webpack_require__(130);
  22334. var _removeCuesFromTrack2 = _interopRequireDefault(_removeCuesFromTrack);
  22335. var _createTextTracksIfNecessary = __webpack_require__(131);
  22336. var _createTextTracksIfNecessary2 = _interopRequireDefault(_createTextTracksIfNecessary);
  22337. var _addTextTrackData = __webpack_require__(132);
  22338. var _flashTransmuxerWorker = __webpack_require__(133);
  22339. var _flashTransmuxerWorker2 = _interopRequireDefault(_flashTransmuxerWorker);
  22340. var _webwackify = __webpack_require__(134);
  22341. var _webwackify2 = _interopRequireDefault(_webwackify);
  22342. var _flashConstants = __webpack_require__(135);
  22343. var _flashConstants2 = _interopRequireDefault(_flashConstants);
  22344. var resolveFlashTransmuxWorker = function resolveFlashTransmuxWorker() {
  22345. var result = undefined;
  22346. try {
  22347. result = /*require.resolve*/(133);
  22348. } catch (e) {
  22349. // no result
  22350. }
  22351. return result;
  22352. };
  22353. /**
  22354. * A wrapper around the setTimeout function that uses
  22355. * the flash constant time between ticks value.
  22356. *
  22357. * @param {Function} func the function callback to run
  22358. * @private
  22359. */
  22360. var scheduleTick = function scheduleTick(func) {
  22361. // Chrome doesn't invoke requestAnimationFrame callbacks
  22362. // in background tabs, so use setTimeout.
  22363. _globalWindow2['default'].setTimeout(func, _flashConstants2['default'].TIME_BETWEEN_CHUNKS);
  22364. };
  22365. /**
  22366. * Generates a random string of max length 6
  22367. *
  22368. * @return {String} the randomly generated string
  22369. * @function generateRandomString
  22370. * @private
  22371. */
  22372. var generateRandomString = function generateRandomString() {
  22373. return Math.random().toString(36).slice(2, 8);
  22374. };
  22375. /**
  22376. * Round a number to a specified number of places much like
  22377. * toFixed but return a number instead of a string representation.
  22378. *
  22379. * @param {Number} num A number
  22380. * @param {Number} places The number of decimal places which to
  22381. * round
  22382. * @private
  22383. */
  22384. var toDecimalPlaces = function toDecimalPlaces(num, places) {
  22385. if (typeof places !== 'number' || places < 0) {
  22386. places = 0;
  22387. }
  22388. var scale = Math.pow(10, places);
  22389. return Math.round(num * scale) / scale;
  22390. };
  22391. /**
  22392. * A SourceBuffer implementation for Flash rather than HTML.
  22393. *
  22394. * @link https://developer.mozilla.org/en-US/docs/Web/API/MediaSource
  22395. * @param {Object} mediaSource the flash media source
  22396. * @class FlashSourceBuffer
  22397. * @extends videojs.EventTarget
  22398. */
  22399. var FlashSourceBuffer = (function (_videojs$EventTarget) {
  22400. _inherits(FlashSourceBuffer, _videojs$EventTarget);
  22401. function FlashSourceBuffer(mediaSource) {
  22402. var _this = this;
  22403. _classCallCheck(this, FlashSourceBuffer);
  22404. _get(Object.getPrototypeOf(FlashSourceBuffer.prototype), 'constructor', this).call(this);
  22405. var encodedHeader = undefined;
  22406. // Start off using the globally defined value but refine
  22407. // as we append data into flash
  22408. this.chunkSize_ = _flashConstants2['default'].BYTES_PER_CHUNK;
  22409. // byte arrays queued to be appended
  22410. this.buffer_ = [];
  22411. // the total number of queued bytes
  22412. this.bufferSize_ = 0;
  22413. // to be able to determine the correct position to seek to, we
  22414. // need to retain information about the mapping between the
  22415. // media timeline and PTS values
  22416. this.basePtsOffset_ = NaN;
  22417. this.mediaSource_ = mediaSource;
  22418. this.audioBufferEnd_ = NaN;
  22419. this.videoBufferEnd_ = NaN;
  22420. // indicates whether the asynchronous continuation of an operation
  22421. // is still being processed
  22422. // see https://w3c.github.io/media-source/#widl-SourceBuffer-updating
  22423. this.updating = false;
  22424. this.timestampOffset_ = 0;
  22425. encodedHeader = _globalWindow2['default'].btoa(String.fromCharCode.apply(null, Array.prototype.slice.call(_muxJsLibFlv2['default'].getFlvHeader())));
  22426. // create function names with added randomness for the global callbacks flash will use
  22427. // to get data from javascript into the swf. Random strings are added as a safety
  22428. // measure for pages with multiple players since these functions will be global
  22429. // instead of per instance. When making a call to the swf, the browser generates a
  22430. // try catch code snippet, but just takes the function name and writes out an unquoted
  22431. // call to that function. If the player id has any special characters, this will result
  22432. // in an error, so safePlayerId replaces all special characters to '_'
  22433. var safePlayerId = this.mediaSource_.player_.id().replace(/[^a-zA-Z0-9]/g, '_');
  22434. this.flashEncodedHeaderName_ = 'vjs_flashEncodedHeader_' + safePlayerId + generateRandomString();
  22435. this.flashEncodedDataName_ = 'vjs_flashEncodedData_' + safePlayerId + generateRandomString();
  22436. _globalWindow2['default'][this.flashEncodedHeaderName_] = function () {
  22437. delete _globalWindow2['default'][_this.flashEncodedHeaderName_];
  22438. return encodedHeader;
  22439. };
  22440. this.mediaSource_.swfObj.vjs_appendChunkReady(this.flashEncodedHeaderName_);
  22441. this.transmuxer_ = (0, _webwackify2['default'])(_flashTransmuxerWorker2['default'], resolveFlashTransmuxWorker());
  22442. this.transmuxer_.postMessage({ action: 'init', options: {} });
  22443. this.transmuxer_.onmessage = function (event) {
  22444. if (event.data.action === 'data') {
  22445. _this.receiveBuffer_(event.data.segment);
  22446. }
  22447. };
  22448. this.one('updateend', function () {
  22449. _this.mediaSource_.tech_.trigger('loadedmetadata');
  22450. });
  22451. Object.defineProperty(this, 'timestampOffset', {
  22452. get: function get() {
  22453. return this.timestampOffset_;
  22454. },
  22455. set: function set(val) {
  22456. if (typeof val === 'number' && val >= 0) {
  22457. this.timestampOffset_ = val;
  22458. // We have to tell flash to expect a discontinuity
  22459. this.mediaSource_.swfObj.vjs_discontinuity();
  22460. // the media <-> PTS mapping must be re-established after
  22461. // the discontinuity
  22462. this.basePtsOffset_ = NaN;
  22463. this.audioBufferEnd_ = NaN;
  22464. this.videoBufferEnd_ = NaN;
  22465. this.transmuxer_.postMessage({ action: 'reset' });
  22466. }
  22467. }
  22468. });
  22469. Object.defineProperty(this, 'buffered', {
  22470. get: function get() {
  22471. if (!this.mediaSource_ || !this.mediaSource_.swfObj || !('vjs_getProperty' in this.mediaSource_.swfObj)) {
  22472. return _videoJs2['default'].createTimeRange();
  22473. }
  22474. var buffered = this.mediaSource_.swfObj.vjs_getProperty('buffered');
  22475. if (buffered && buffered.length) {
  22476. buffered[0][0] = toDecimalPlaces(buffered[0][0], 3);
  22477. buffered[0][1] = toDecimalPlaces(buffered[0][1], 3);
  22478. }
  22479. return _videoJs2['default'].createTimeRanges(buffered);
  22480. }
  22481. });
  22482. // On a seek we remove all text track data since flash has no concept
  22483. // of a buffered-range and everything else is reset on seek
  22484. this.mediaSource_.player_.on('seeked', function () {
  22485. (0, _removeCuesFromTrack2['default'])(0, Infinity, _this.metadataTrack_);
  22486. if (_this.inbandTextTracks_) {
  22487. for (var track in _this.inbandTextTracks_) {
  22488. (0, _removeCuesFromTrack2['default'])(0, Infinity, _this.inbandTextTracks_[track]);
  22489. }
  22490. }
  22491. });
  22492. var onHlsReset = this.onHlsReset_.bind(this);
  22493. // hls-reset is fired by videojs.Hls on to the tech after the main SegmentLoader
  22494. // resets its state and flushes the buffer
  22495. this.mediaSource_.player_.tech_.on('hls-reset', onHlsReset);
  22496. this.mediaSource_.player_.tech_.hls.on('dispose', function () {
  22497. _this.transmuxer_.terminate();
  22498. _this.mediaSource_.player_.tech_.off('hls-reset', onHlsReset);
  22499. });
  22500. }
  22501. /**
  22502. * Append bytes to the sourcebuffers buffer, in this case we
  22503. * have to append it to swf object.
  22504. *
  22505. * @link https://developer.mozilla.org/en-US/docs/Web/API/SourceBuffer/appendBuffer
  22506. * @param {Array} bytes
  22507. */
  22508. _createClass(FlashSourceBuffer, [{
  22509. key: 'appendBuffer',
  22510. value: function appendBuffer(bytes) {
  22511. var error = undefined;
  22512. if (this.updating) {
  22513. error = new Error('SourceBuffer.append() cannot be called ' + 'while an update is in progress');
  22514. error.name = 'InvalidStateError';
  22515. error.code = 11;
  22516. throw error;
  22517. }
  22518. this.updating = true;
  22519. this.mediaSource_.readyState = 'open';
  22520. this.trigger({ type: 'update' });
  22521. this.transmuxer_.postMessage({
  22522. action: 'push',
  22523. data: bytes.buffer,
  22524. byteOffset: bytes.byteOffset,
  22525. byteLength: bytes.byteLength
  22526. }, [bytes.buffer]);
  22527. this.transmuxer_.postMessage({ action: 'flush' });
  22528. }
  22529. /**
  22530. * Reset the parser and remove any data queued to be sent to the SWF.
  22531. *
  22532. * @link https://developer.mozilla.org/en-US/docs/Web/API/SourceBuffer/abort
  22533. */
  22534. }, {
  22535. key: 'abort',
  22536. value: function abort() {
  22537. this.buffer_ = [];
  22538. this.bufferSize_ = 0;
  22539. this.mediaSource_.swfObj.vjs_abort();
  22540. // report any outstanding updates have ended
  22541. if (this.updating) {
  22542. this.updating = false;
  22543. this.trigger({ type: 'updateend' });
  22544. }
  22545. }
  22546. /**
  22547. * Flash cannot remove ranges already buffered in the NetStream
  22548. * but seeking clears the buffer entirely. For most purposes,
  22549. * having this operation act as a no-op is acceptable.
  22550. *
  22551. * @link https://developer.mozilla.org/en-US/docs/Web/API/SourceBuffer/remove
  22552. * @param {Double} start start of the section to remove
  22553. * @param {Double} end end of the section to remove
  22554. */
  22555. }, {
  22556. key: 'remove',
  22557. value: function remove(start, end) {
  22558. (0, _removeCuesFromTrack2['default'])(start, end, this.metadataTrack_);
  22559. if (this.inbandTextTracks_) {
  22560. for (var track in this.inbandTextTracks_) {
  22561. (0, _removeCuesFromTrack2['default'])(start, end, this.inbandTextTracks_[track]);
  22562. }
  22563. }
  22564. this.trigger({ type: 'update' });
  22565. this.trigger({ type: 'updateend' });
  22566. }
  22567. /**
  22568. * Receive a buffer from the flv.
  22569. *
  22570. * @param {Object} segment
  22571. * @private
  22572. */
  22573. }, {
  22574. key: 'receiveBuffer_',
  22575. value: function receiveBuffer_(segment) {
  22576. var _this2 = this;
  22577. // create an in-band caption track if one is present in the segment
  22578. (0, _createTextTracksIfNecessary2['default'])(this, this.mediaSource_, segment);
  22579. (0, _addTextTrackData.addTextTrackData)(this, segment.captions, segment.metadata);
  22580. // Do this asynchronously since convertTagsToData_ can be time consuming
  22581. scheduleTick(function () {
  22582. var flvBytes = _this2.convertTagsToData_(segment);
  22583. if (_this2.buffer_.length === 0) {
  22584. scheduleTick(_this2.processBuffer_.bind(_this2));
  22585. }
  22586. if (flvBytes) {
  22587. _this2.buffer_.push(flvBytes);
  22588. _this2.bufferSize_ += flvBytes.byteLength;
  22589. }
  22590. });
  22591. }
  22592. /**
  22593. * Append a portion of the current buffer to the SWF.
  22594. *
  22595. * @private
  22596. */
  22597. }, {
  22598. key: 'processBuffer_',
  22599. value: function processBuffer_() {
  22600. var _this3 = this;
  22601. var chunkSize = _flashConstants2['default'].BYTES_PER_CHUNK;
  22602. if (!this.buffer_.length) {
  22603. if (this.updating !== false) {
  22604. this.updating = false;
  22605. this.trigger({ type: 'updateend' });
  22606. }
  22607. // do nothing if the buffer is empty
  22608. return;
  22609. }
  22610. // concatenate appends up to the max append size
  22611. var chunk = this.buffer_[0].subarray(0, chunkSize);
  22612. // requeue any bytes that won't make it this round
  22613. if (chunk.byteLength < chunkSize || this.buffer_[0].byteLength === chunkSize) {
  22614. this.buffer_.shift();
  22615. } else {
  22616. this.buffer_[0] = this.buffer_[0].subarray(chunkSize);
  22617. }
  22618. this.bufferSize_ -= chunk.byteLength;
  22619. // base64 encode the bytes
  22620. var binary = [];
  22621. var length = chunk.byteLength;
  22622. for (var i = 0; i < length; i++) {
  22623. binary.push(String.fromCharCode(chunk[i]));
  22624. }
  22625. var b64str = _globalWindow2['default'].btoa(binary.join(''));
  22626. _globalWindow2['default'][this.flashEncodedDataName_] = function () {
  22627. // schedule another processBuffer to process any left over data or to
  22628. // trigger updateend
  22629. scheduleTick(_this3.processBuffer_.bind(_this3));
  22630. delete _globalWindow2['default'][_this3.flashEncodedDataName_];
  22631. return b64str;
  22632. };
  22633. // Notify the swf that segment data is ready to be appended
  22634. this.mediaSource_.swfObj.vjs_appendChunkReady(this.flashEncodedDataName_);
  22635. }
  22636. /**
  22637. * Turns an array of flv tags into a Uint8Array representing the
  22638. * flv data. Also removes any tags that are before the current
  22639. * time so that playback begins at or slightly after the right
  22640. * place on a seek
  22641. *
  22642. * @private
  22643. * @param {Object} segmentData object of segment data
  22644. */
  22645. }, {
  22646. key: 'convertTagsToData_',
  22647. value: function convertTagsToData_(segmentData) {
  22648. var segmentByteLength = 0;
  22649. var tech = this.mediaSource_.tech_;
  22650. var videoTargetPts = 0;
  22651. var segment = undefined;
  22652. var videoTags = segmentData.tags.videoTags;
  22653. var audioTags = segmentData.tags.audioTags;
  22654. // Establish the media timeline to PTS translation if we don't
  22655. // have one already
  22656. if (isNaN(this.basePtsOffset_) && (videoTags.length || audioTags.length)) {
  22657. // We know there is at least one video or audio tag, but since we may not have both,
  22658. // we use pts: Infinity for the missing tag. The will force the following Math.min
  22659. // call will to use the proper pts value since it will always be less than Infinity
  22660. var firstVideoTag = videoTags[0] || { pts: Infinity };
  22661. var firstAudioTag = audioTags[0] || { pts: Infinity };
  22662. this.basePtsOffset_ = Math.min(firstAudioTag.pts, firstVideoTag.pts);
  22663. }
  22664. if (tech.seeking()) {
  22665. // Do not use previously saved buffer end values while seeking since buffer
  22666. // is cleared on all seeks
  22667. this.videoBufferEnd_ = NaN;
  22668. this.audioBufferEnd_ = NaN;
  22669. }
  22670. if (isNaN(this.videoBufferEnd_)) {
  22671. if (tech.buffered().length) {
  22672. videoTargetPts = tech.buffered().end(0) - this.timestampOffset;
  22673. }
  22674. // Trim to currentTime if seeking
  22675. if (tech.seeking()) {
  22676. videoTargetPts = Math.max(videoTargetPts, tech.currentTime() - this.timestampOffset);
  22677. }
  22678. // PTS values are represented in milliseconds
  22679. videoTargetPts *= 1e3;
  22680. videoTargetPts += this.basePtsOffset_;
  22681. } else {
  22682. // Add a fudge factor of 0.1 to the last video pts appended since a rendition change
  22683. // could append an overlapping segment, in which case there is a high likelyhood
  22684. // a tag could have a matching pts to videoBufferEnd_, which would cause
  22685. // that tag to get appended by the tag.pts >= targetPts check below even though it
  22686. // is a duplicate of what was previously appended
  22687. videoTargetPts = this.videoBufferEnd_ + 0.1;
  22688. }
  22689. // filter complete GOPs with a presentation time less than the seek target/end of buffer
  22690. var currentIndex = videoTags.length;
  22691. // if the last tag is beyond videoTargetPts, then do not search the list for a GOP
  22692. // since our videoTargetPts lies in a future segment
  22693. if (currentIndex && videoTags[currentIndex - 1].pts >= videoTargetPts) {
  22694. // Start by walking backwards from the end of the list until we reach a tag that
  22695. // is equal to or less than videoTargetPts
  22696. while (--currentIndex) {
  22697. var currentTag = videoTags[currentIndex];
  22698. if (currentTag.pts > videoTargetPts) {
  22699. continue;
  22700. }
  22701. // if we see a keyFrame or metadata tag once we've gone below videoTargetPts,
  22702. // exit the loop as this is the start of the GOP that we want to append
  22703. if (currentTag.keyFrame || currentTag.metaDataTag) {
  22704. break;
  22705. }
  22706. }
  22707. // We need to check if there are any metadata tags that come before currentIndex
  22708. // as those will be metadata tags associated with the GOP we are appending
  22709. // There could be 0 to 2 metadata tags that come before the currentIndex depending
  22710. // on what videoTargetPts is and whether the transmuxer prepended metadata tags to this
  22711. // key frame
  22712. while (currentIndex) {
  22713. var nextTag = videoTags[currentIndex - 1];
  22714. if (!nextTag.metaDataTag) {
  22715. break;
  22716. }
  22717. currentIndex--;
  22718. }
  22719. }
  22720. var filteredVideoTags = videoTags.slice(currentIndex);
  22721. var audioTargetPts = undefined;
  22722. if (isNaN(this.audioBufferEnd_)) {
  22723. audioTargetPts = videoTargetPts;
  22724. } else {
  22725. // Add a fudge factor of 0.1 to the last video pts appended since a rendition change
  22726. // could append an overlapping segment, in which case there is a high likelyhood
  22727. // a tag could have a matching pts to videoBufferEnd_, which would cause
  22728. // that tag to get appended by the tag.pts >= targetPts check below even though it
  22729. // is a duplicate of what was previously appended
  22730. audioTargetPts = this.audioBufferEnd_ + 0.1;
  22731. }
  22732. if (filteredVideoTags.length) {
  22733. // If targetPts intersects a GOP and we appended the tags for the GOP that came
  22734. // before targetPts, we want to make sure to trim audio tags at the pts
  22735. // of the first video tag to avoid brief moments of silence
  22736. audioTargetPts = Math.min(audioTargetPts, filteredVideoTags[0].pts);
  22737. }
  22738. // skip tags with a presentation time less than the seek target/end of buffer
  22739. currentIndex = 0;
  22740. while (currentIndex < audioTags.length) {
  22741. if (audioTags[currentIndex].pts >= audioTargetPts) {
  22742. break;
  22743. }
  22744. currentIndex++;
  22745. }
  22746. var filteredAudioTags = audioTags.slice(currentIndex);
  22747. // update the audio and video buffer ends
  22748. if (filteredAudioTags.length) {
  22749. this.audioBufferEnd_ = filteredAudioTags[filteredAudioTags.length - 1].pts;
  22750. }
  22751. if (filteredVideoTags.length) {
  22752. this.videoBufferEnd_ = filteredVideoTags[filteredVideoTags.length - 1].pts;
  22753. }
  22754. var tags = this.getOrderedTags_(filteredVideoTags, filteredAudioTags);
  22755. if (tags.length === 0) {
  22756. return;
  22757. }
  22758. // If we are appending data that comes before our target pts, we want to tell
  22759. // the swf to adjust its notion of current time to account for the extra tags
  22760. // we are appending to complete the GOP that intersects with targetPts
  22761. if (tags[0].pts < videoTargetPts && tech.seeking()) {
  22762. var fudgeFactor = 1 / 30;
  22763. var currentTime = tech.currentTime();
  22764. var diff = (videoTargetPts - tags[0].pts) / 1e3;
  22765. var adjustedTime = currentTime - diff;
  22766. if (adjustedTime < fudgeFactor) {
  22767. adjustedTime = 0;
  22768. }
  22769. try {
  22770. this.mediaSource_.swfObj.vjs_adjustCurrentTime(adjustedTime);
  22771. } catch (e) {
  22772. // no-op for backwards compatability of swf. If adjustCurrentTime fails,
  22773. // the swf may incorrectly report currentTime and buffered ranges
  22774. // but should not affect playback over than the time displayed on the
  22775. // progress bar is inaccurate
  22776. }
  22777. }
  22778. // concatenate the bytes into a single segment
  22779. for (var i = 0; i < tags.length; i++) {
  22780. segmentByteLength += tags[i].bytes.byteLength;
  22781. }
  22782. segment = new Uint8Array(segmentByteLength);
  22783. for (var i = 0, j = 0; i < tags.length; i++) {
  22784. segment.set(tags[i].bytes, j);
  22785. j += tags[i].bytes.byteLength;
  22786. }
  22787. return segment;
  22788. }
  22789. /**
  22790. * Assemble the FLV tags in decoder order.
  22791. *
  22792. * @private
  22793. * @param {Array} videoTags list of video tags
  22794. * @param {Array} audioTags list of audio tags
  22795. */
  22796. }, {
  22797. key: 'getOrderedTags_',
  22798. value: function getOrderedTags_(videoTags, audioTags) {
  22799. var tag = undefined;
  22800. var tags = [];
  22801. while (videoTags.length || audioTags.length) {
  22802. if (!videoTags.length) {
  22803. // only audio tags remain
  22804. tag = audioTags.shift();
  22805. } else if (!audioTags.length) {
  22806. // only video tags remain
  22807. tag = videoTags.shift();
  22808. } else if (audioTags[0].dts < videoTags[0].dts) {
  22809. // audio should be decoded next
  22810. tag = audioTags.shift();
  22811. } else {
  22812. // video should be decoded next
  22813. tag = videoTags.shift();
  22814. }
  22815. tags.push(tag);
  22816. }
  22817. return tags;
  22818. }
  22819. }, {
  22820. key: 'onHlsReset_',
  22821. value: function onHlsReset_() {
  22822. this.transmuxer_.postMessage({ action: 'resetCaptions' });
  22823. }
  22824. }]);
  22825. return FlashSourceBuffer;
  22826. })(_videoJs2['default'].EventTarget);
  22827. exports['default'] = FlashSourceBuffer;
  22828. module.exports = exports['default'];
  22829. /***/ }),
  22830. /* 115 */
  22831. /***/ (function(module, exports, __webpack_require__) {
  22832. module.exports = {
  22833. tag: __webpack_require__(116),
  22834. Transmuxer: __webpack_require__(117),
  22835. getFlvHeader: __webpack_require__(129)
  22836. };
  22837. /***/ }),
  22838. /* 116 */
  22839. /***/ (function(module, exports) {
  22840. /**
  22841. * An object that stores the bytes of an FLV tag and methods for
  22842. * querying and manipulating that data.
  22843. * @see http://download.macromedia.com/f4v/video_file_format_spec_v10_1.pdf
  22844. */
  22845. 'use strict';
  22846. var FlvTag;
  22847. // (type:uint, extraData:Boolean = false) extends ByteArray
  22848. FlvTag = function(type, extraData) {
  22849. var
  22850. // Counter if this is a metadata tag, nal start marker if this is a video
  22851. // tag. unused if this is an audio tag
  22852. adHoc = 0, // :uint
  22853. // The default size is 16kb but this is not enough to hold iframe
  22854. // data and the resizing algorithm costs a bit so we create a larger
  22855. // starting buffer for video tags
  22856. bufferStartSize = 16384,
  22857. // checks whether the FLV tag has enough capacity to accept the proposed
  22858. // write and re-allocates the internal buffers if necessary
  22859. prepareWrite = function(flv, count) {
  22860. var
  22861. bytes,
  22862. minLength = flv.position + count;
  22863. if (minLength < flv.bytes.byteLength) {
  22864. // there's enough capacity so do nothing
  22865. return;
  22866. }
  22867. // allocate a new buffer and copy over the data that will not be modified
  22868. bytes = new Uint8Array(minLength * 2);
  22869. bytes.set(flv.bytes.subarray(0, flv.position), 0);
  22870. flv.bytes = bytes;
  22871. flv.view = new DataView(flv.bytes.buffer);
  22872. },
  22873. // commonly used metadata properties
  22874. widthBytes = FlvTag.widthBytes || new Uint8Array('width'.length),
  22875. heightBytes = FlvTag.heightBytes || new Uint8Array('height'.length),
  22876. videocodecidBytes = FlvTag.videocodecidBytes || new Uint8Array('videocodecid'.length),
  22877. i;
  22878. if (!FlvTag.widthBytes) {
  22879. // calculating the bytes of common metadata names ahead of time makes the
  22880. // corresponding writes faster because we don't have to loop over the
  22881. // characters
  22882. // re-test with test/perf.html if you're planning on changing this
  22883. for (i = 0; i < 'width'.length; i++) {
  22884. widthBytes[i] = 'width'.charCodeAt(i);
  22885. }
  22886. for (i = 0; i < 'height'.length; i++) {
  22887. heightBytes[i] = 'height'.charCodeAt(i);
  22888. }
  22889. for (i = 0; i < 'videocodecid'.length; i++) {
  22890. videocodecidBytes[i] = 'videocodecid'.charCodeAt(i);
  22891. }
  22892. FlvTag.widthBytes = widthBytes;
  22893. FlvTag.heightBytes = heightBytes;
  22894. FlvTag.videocodecidBytes = videocodecidBytes;
  22895. }
  22896. this.keyFrame = false; // :Boolean
  22897. switch (type) {
  22898. case FlvTag.VIDEO_TAG:
  22899. this.length = 16;
  22900. // Start the buffer at 256k
  22901. bufferStartSize *= 6;
  22902. break;
  22903. case FlvTag.AUDIO_TAG:
  22904. this.length = 13;
  22905. this.keyFrame = true;
  22906. break;
  22907. case FlvTag.METADATA_TAG:
  22908. this.length = 29;
  22909. this.keyFrame = true;
  22910. break;
  22911. default:
  22912. throw new Error('Unknown FLV tag type');
  22913. }
  22914. this.bytes = new Uint8Array(bufferStartSize);
  22915. this.view = new DataView(this.bytes.buffer);
  22916. this.bytes[0] = type;
  22917. this.position = this.length;
  22918. this.keyFrame = extraData; // Defaults to false
  22919. // presentation timestamp
  22920. this.pts = 0;
  22921. // decoder timestamp
  22922. this.dts = 0;
  22923. // ByteArray#writeBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0)
  22924. this.writeBytes = function(bytes, offset, length) {
  22925. var
  22926. start = offset || 0,
  22927. end;
  22928. length = length || bytes.byteLength;
  22929. end = start + length;
  22930. prepareWrite(this, length);
  22931. this.bytes.set(bytes.subarray(start, end), this.position);
  22932. this.position += length;
  22933. this.length = Math.max(this.length, this.position);
  22934. };
  22935. // ByteArray#writeByte(value:int):void
  22936. this.writeByte = function(byte) {
  22937. prepareWrite(this, 1);
  22938. this.bytes[this.position] = byte;
  22939. this.position++;
  22940. this.length = Math.max(this.length, this.position);
  22941. };
  22942. // ByteArray#writeShort(value:int):void
  22943. this.writeShort = function(short) {
  22944. prepareWrite(this, 2);
  22945. this.view.setUint16(this.position, short);
  22946. this.position += 2;
  22947. this.length = Math.max(this.length, this.position);
  22948. };
  22949. // Negative index into array
  22950. // (pos:uint):int
  22951. this.negIndex = function(pos) {
  22952. return this.bytes[this.length - pos];
  22953. };
  22954. // The functions below ONLY work when this[0] == VIDEO_TAG.
  22955. // We are not going to check for that because we dont want the overhead
  22956. // (nal:ByteArray = null):int
  22957. this.nalUnitSize = function() {
  22958. if (adHoc === 0) {
  22959. return 0;
  22960. }
  22961. return this.length - (adHoc + 4);
  22962. };
  22963. this.startNalUnit = function() {
  22964. // remember position and add 4 bytes
  22965. if (adHoc > 0) {
  22966. throw new Error('Attempted to create new NAL wihout closing the old one');
  22967. }
  22968. // reserve 4 bytes for nal unit size
  22969. adHoc = this.length;
  22970. this.length += 4;
  22971. this.position = this.length;
  22972. };
  22973. // (nal:ByteArray = null):void
  22974. this.endNalUnit = function(nalContainer) {
  22975. var
  22976. nalStart, // :uint
  22977. nalLength; // :uint
  22978. // Rewind to the marker and write the size
  22979. if (this.length === adHoc + 4) {
  22980. // we started a nal unit, but didnt write one, so roll back the 4 byte size value
  22981. this.length -= 4;
  22982. } else if (adHoc > 0) {
  22983. nalStart = adHoc + 4;
  22984. nalLength = this.length - nalStart;
  22985. this.position = adHoc;
  22986. this.view.setUint32(this.position, nalLength);
  22987. this.position = this.length;
  22988. if (nalContainer) {
  22989. // Add the tag to the NAL unit
  22990. nalContainer.push(this.bytes.subarray(nalStart, nalStart + nalLength));
  22991. }
  22992. }
  22993. adHoc = 0;
  22994. };
  22995. /**
  22996. * Write out a 64-bit floating point valued metadata property. This method is
  22997. * called frequently during a typical parse and needs to be fast.
  22998. */
  22999. // (key:String, val:Number):void
  23000. this.writeMetaDataDouble = function(key, val) {
  23001. var i;
  23002. prepareWrite(this, 2 + key.length + 9);
  23003. // write size of property name
  23004. this.view.setUint16(this.position, key.length);
  23005. this.position += 2;
  23006. // this next part looks terrible but it improves parser throughput by
  23007. // 10kB/s in my testing
  23008. // write property name
  23009. if (key === 'width') {
  23010. this.bytes.set(widthBytes, this.position);
  23011. this.position += 5;
  23012. } else if (key === 'height') {
  23013. this.bytes.set(heightBytes, this.position);
  23014. this.position += 6;
  23015. } else if (key === 'videocodecid') {
  23016. this.bytes.set(videocodecidBytes, this.position);
  23017. this.position += 12;
  23018. } else {
  23019. for (i = 0; i < key.length; i++) {
  23020. this.bytes[this.position] = key.charCodeAt(i);
  23021. this.position++;
  23022. }
  23023. }
  23024. // skip null byte
  23025. this.position++;
  23026. // write property value
  23027. this.view.setFloat64(this.position, val);
  23028. this.position += 8;
  23029. // update flv tag length
  23030. this.length = Math.max(this.length, this.position);
  23031. ++adHoc;
  23032. };
  23033. // (key:String, val:Boolean):void
  23034. this.writeMetaDataBoolean = function(key, val) {
  23035. var i;
  23036. prepareWrite(this, 2);
  23037. this.view.setUint16(this.position, key.length);
  23038. this.position += 2;
  23039. for (i = 0; i < key.length; i++) {
  23040. // if key.charCodeAt(i) >= 255, handle error
  23041. prepareWrite(this, 1);
  23042. this.bytes[this.position] = key.charCodeAt(i);
  23043. this.position++;
  23044. }
  23045. prepareWrite(this, 2);
  23046. this.view.setUint8(this.position, 0x01);
  23047. this.position++;
  23048. this.view.setUint8(this.position, val ? 0x01 : 0x00);
  23049. this.position++;
  23050. this.length = Math.max(this.length, this.position);
  23051. ++adHoc;
  23052. };
  23053. // ():ByteArray
  23054. this.finalize = function() {
  23055. var
  23056. dtsDelta, // :int
  23057. len; // :int
  23058. switch (this.bytes[0]) {
  23059. // Video Data
  23060. case FlvTag.VIDEO_TAG:
  23061. // We only support AVC, 1 = key frame (for AVC, a seekable
  23062. // frame), 2 = inter frame (for AVC, a non-seekable frame)
  23063. this.bytes[11] = ((this.keyFrame || extraData) ? 0x10 : 0x20) | 0x07;
  23064. this.bytes[12] = extraData ? 0x00 : 0x01;
  23065. dtsDelta = this.pts - this.dts;
  23066. this.bytes[13] = (dtsDelta & 0x00FF0000) >>> 16;
  23067. this.bytes[14] = (dtsDelta & 0x0000FF00) >>> 8;
  23068. this.bytes[15] = (dtsDelta & 0x000000FF) >>> 0;
  23069. break;
  23070. case FlvTag.AUDIO_TAG:
  23071. this.bytes[11] = 0xAF; // 44 kHz, 16-bit stereo
  23072. this.bytes[12] = extraData ? 0x00 : 0x01;
  23073. break;
  23074. case FlvTag.METADATA_TAG:
  23075. this.position = 11;
  23076. this.view.setUint8(this.position, 0x02); // String type
  23077. this.position++;
  23078. this.view.setUint16(this.position, 0x0A); // 10 Bytes
  23079. this.position += 2;
  23080. // set "onMetaData"
  23081. this.bytes.set([0x6f, 0x6e, 0x4d, 0x65,
  23082. 0x74, 0x61, 0x44, 0x61,
  23083. 0x74, 0x61], this.position);
  23084. this.position += 10;
  23085. this.bytes[this.position] = 0x08; // Array type
  23086. this.position++;
  23087. this.view.setUint32(this.position, adHoc);
  23088. this.position = this.length;
  23089. this.bytes.set([0, 0, 9], this.position);
  23090. this.position += 3; // End Data Tag
  23091. this.length = this.position;
  23092. break;
  23093. }
  23094. len = this.length - 11;
  23095. // write the DataSize field
  23096. this.bytes[ 1] = (len & 0x00FF0000) >>> 16;
  23097. this.bytes[ 2] = (len & 0x0000FF00) >>> 8;
  23098. this.bytes[ 3] = (len & 0x000000FF) >>> 0;
  23099. // write the Timestamp
  23100. this.bytes[ 4] = (this.dts & 0x00FF0000) >>> 16;
  23101. this.bytes[ 5] = (this.dts & 0x0000FF00) >>> 8;
  23102. this.bytes[ 6] = (this.dts & 0x000000FF) >>> 0;
  23103. this.bytes[ 7] = (this.dts & 0xFF000000) >>> 24;
  23104. // write the StreamID
  23105. this.bytes[ 8] = 0;
  23106. this.bytes[ 9] = 0;
  23107. this.bytes[10] = 0;
  23108. // Sometimes we're at the end of the view and have one slot to write a
  23109. // uint32, so, prepareWrite of count 4, since, view is uint8
  23110. prepareWrite(this, 4);
  23111. this.view.setUint32(this.length, this.length);
  23112. this.length += 4;
  23113. this.position += 4;
  23114. // trim down the byte buffer to what is actually being used
  23115. this.bytes = this.bytes.subarray(0, this.length);
  23116. this.frameTime = FlvTag.frameTime(this.bytes);
  23117. // if bytes.bytelength isn't equal to this.length, handle error
  23118. return this;
  23119. };
  23120. };
  23121. FlvTag.AUDIO_TAG = 0x08; // == 8, :uint
  23122. FlvTag.VIDEO_TAG = 0x09; // == 9, :uint
  23123. FlvTag.METADATA_TAG = 0x12; // == 18, :uint
  23124. // (tag:ByteArray):Boolean {
  23125. FlvTag.isAudioFrame = function(tag) {
  23126. return FlvTag.AUDIO_TAG === tag[0];
  23127. };
  23128. // (tag:ByteArray):Boolean {
  23129. FlvTag.isVideoFrame = function(tag) {
  23130. return FlvTag.VIDEO_TAG === tag[0];
  23131. };
  23132. // (tag:ByteArray):Boolean {
  23133. FlvTag.isMetaData = function(tag) {
  23134. return FlvTag.METADATA_TAG === tag[0];
  23135. };
  23136. // (tag:ByteArray):Boolean {
  23137. FlvTag.isKeyFrame = function(tag) {
  23138. if (FlvTag.isVideoFrame(tag)) {
  23139. return tag[11] === 0x17;
  23140. }
  23141. if (FlvTag.isAudioFrame(tag)) {
  23142. return true;
  23143. }
  23144. if (FlvTag.isMetaData(tag)) {
  23145. return true;
  23146. }
  23147. return false;
  23148. };
  23149. // (tag:ByteArray):uint {
  23150. FlvTag.frameTime = function(tag) {
  23151. var pts = tag[ 4] << 16; // :uint
  23152. pts |= tag[ 5] << 8;
  23153. pts |= tag[ 6] << 0;
  23154. pts |= tag[ 7] << 24;
  23155. return pts;
  23156. };
  23157. module.exports = FlvTag;
  23158. /***/ }),
  23159. /* 117 */
  23160. /***/ (function(module, exports, __webpack_require__) {
  23161. 'use strict';
  23162. var Stream = __webpack_require__(118);
  23163. var FlvTag = __webpack_require__(116);
  23164. var m2ts = __webpack_require__(119);
  23165. var AdtsStream = __webpack_require__(124);
  23166. var H264Stream = __webpack_require__(125).H264Stream;
  23167. var CoalesceStream = __webpack_require__(127);
  23168. var TagList = __webpack_require__(128);
  23169. var
  23170. Transmuxer,
  23171. VideoSegmentStream,
  23172. AudioSegmentStream,
  23173. collectTimelineInfo,
  23174. metaDataTag,
  23175. extraDataTag;
  23176. /**
  23177. * Store information about the start and end of the tracka and the
  23178. * duration for each frame/sample we process in order to calculate
  23179. * the baseMediaDecodeTime
  23180. */
  23181. collectTimelineInfo = function(track, data) {
  23182. if (typeof data.pts === 'number') {
  23183. if (track.timelineStartInfo.pts === undefined) {
  23184. track.timelineStartInfo.pts = data.pts;
  23185. } else {
  23186. track.timelineStartInfo.pts =
  23187. Math.min(track.timelineStartInfo.pts, data.pts);
  23188. }
  23189. }
  23190. if (typeof data.dts === 'number') {
  23191. if (track.timelineStartInfo.dts === undefined) {
  23192. track.timelineStartInfo.dts = data.dts;
  23193. } else {
  23194. track.timelineStartInfo.dts =
  23195. Math.min(track.timelineStartInfo.dts, data.dts);
  23196. }
  23197. }
  23198. };
  23199. metaDataTag = function(track, pts) {
  23200. var
  23201. tag = new FlvTag(FlvTag.METADATA_TAG); // :FlvTag
  23202. tag.dts = pts;
  23203. tag.pts = pts;
  23204. tag.writeMetaDataDouble('videocodecid', 7);
  23205. tag.writeMetaDataDouble('width', track.width);
  23206. tag.writeMetaDataDouble('height', track.height);
  23207. return tag;
  23208. };
  23209. extraDataTag = function(track, pts) {
  23210. var
  23211. i,
  23212. tag = new FlvTag(FlvTag.VIDEO_TAG, true);
  23213. tag.dts = pts;
  23214. tag.pts = pts;
  23215. tag.writeByte(0x01);// version
  23216. tag.writeByte(track.profileIdc);// profile
  23217. tag.writeByte(track.profileCompatibility);// compatibility
  23218. tag.writeByte(track.levelIdc);// level
  23219. tag.writeByte(0xFC | 0x03); // reserved (6 bits), NULA length size - 1 (2 bits)
  23220. tag.writeByte(0xE0 | 0x01); // reserved (3 bits), num of SPS (5 bits)
  23221. tag.writeShort(track.sps[0].length); // data of SPS
  23222. tag.writeBytes(track.sps[0]); // SPS
  23223. tag.writeByte(track.pps.length); // num of PPS (will there ever be more that 1 PPS?)
  23224. for (i = 0; i < track.pps.length; ++i) {
  23225. tag.writeShort(track.pps[i].length); // 2 bytes for length of PPS
  23226. tag.writeBytes(track.pps[i]); // data of PPS
  23227. }
  23228. return tag;
  23229. };
  23230. /**
  23231. * Constructs a single-track, media segment from AAC data
  23232. * events. The output of this stream can be fed to flash.
  23233. */
  23234. AudioSegmentStream = function(track) {
  23235. var
  23236. adtsFrames = [],
  23237. videoKeyFrames = [],
  23238. oldExtraData;
  23239. AudioSegmentStream.prototype.init.call(this);
  23240. this.push = function(data) {
  23241. collectTimelineInfo(track, data);
  23242. if (track) {
  23243. track.audioobjecttype = data.audioobjecttype;
  23244. track.channelcount = data.channelcount;
  23245. track.samplerate = data.samplerate;
  23246. track.samplingfrequencyindex = data.samplingfrequencyindex;
  23247. track.samplesize = data.samplesize;
  23248. track.extraData = (track.audioobjecttype << 11) |
  23249. (track.samplingfrequencyindex << 7) |
  23250. (track.channelcount << 3);
  23251. }
  23252. data.pts = Math.round(data.pts / 90);
  23253. data.dts = Math.round(data.dts / 90);
  23254. // buffer audio data until end() is called
  23255. adtsFrames.push(data);
  23256. };
  23257. this.flush = function() {
  23258. var currentFrame, adtsFrame, lastMetaPts, tags = new TagList();
  23259. // return early if no audio data has been observed
  23260. if (adtsFrames.length === 0) {
  23261. this.trigger('done', 'AudioSegmentStream');
  23262. return;
  23263. }
  23264. lastMetaPts = -Infinity;
  23265. while (adtsFrames.length) {
  23266. currentFrame = adtsFrames.shift();
  23267. // write out a metadata frame at every video key frame
  23268. if (videoKeyFrames.length && currentFrame.pts >= videoKeyFrames[0]) {
  23269. lastMetaPts = videoKeyFrames.shift();
  23270. this.writeMetaDataTags(tags, lastMetaPts);
  23271. }
  23272. // also write out metadata tags every 1 second so that the decoder
  23273. // is re-initialized quickly after seeking into a different
  23274. // audio configuration.
  23275. if (track.extraData !== oldExtraData || currentFrame.pts - lastMetaPts >= 1000) {
  23276. this.writeMetaDataTags(tags, currentFrame.pts);
  23277. oldExtraData = track.extraData;
  23278. lastMetaPts = currentFrame.pts;
  23279. }
  23280. adtsFrame = new FlvTag(FlvTag.AUDIO_TAG);
  23281. adtsFrame.pts = currentFrame.pts;
  23282. adtsFrame.dts = currentFrame.dts;
  23283. adtsFrame.writeBytes(currentFrame.data);
  23284. tags.push(adtsFrame.finalize());
  23285. }
  23286. videoKeyFrames.length = 0;
  23287. oldExtraData = null;
  23288. this.trigger('data', {track: track, tags: tags.list});
  23289. this.trigger('done', 'AudioSegmentStream');
  23290. };
  23291. this.writeMetaDataTags = function(tags, pts) {
  23292. var adtsFrame;
  23293. adtsFrame = new FlvTag(FlvTag.METADATA_TAG);
  23294. // For audio, DTS is always the same as PTS. We want to set the DTS
  23295. // however so we can compare with video DTS to determine approximate
  23296. // packet order
  23297. adtsFrame.pts = pts;
  23298. adtsFrame.dts = pts;
  23299. // AAC is always 10
  23300. adtsFrame.writeMetaDataDouble('audiocodecid', 10);
  23301. adtsFrame.writeMetaDataBoolean('stereo', track.channelcount === 2);
  23302. adtsFrame.writeMetaDataDouble('audiosamplerate', track.samplerate);
  23303. // Is AAC always 16 bit?
  23304. adtsFrame.writeMetaDataDouble('audiosamplesize', 16);
  23305. tags.push(adtsFrame.finalize());
  23306. adtsFrame = new FlvTag(FlvTag.AUDIO_TAG, true);
  23307. // For audio, DTS is always the same as PTS. We want to set the DTS
  23308. // however so we can compare with video DTS to determine approximate
  23309. // packet order
  23310. adtsFrame.pts = pts;
  23311. adtsFrame.dts = pts;
  23312. adtsFrame.view.setUint16(adtsFrame.position, track.extraData);
  23313. adtsFrame.position += 2;
  23314. adtsFrame.length = Math.max(adtsFrame.length, adtsFrame.position);
  23315. tags.push(adtsFrame.finalize());
  23316. };
  23317. this.onVideoKeyFrame = function(pts) {
  23318. videoKeyFrames.push(pts);
  23319. };
  23320. };
  23321. AudioSegmentStream.prototype = new Stream();
  23322. /**
  23323. * Store FlvTags for the h264 stream
  23324. * @param track {object} track metadata configuration
  23325. */
  23326. VideoSegmentStream = function(track) {
  23327. var
  23328. nalUnits = [],
  23329. config,
  23330. h264Frame;
  23331. VideoSegmentStream.prototype.init.call(this);
  23332. this.finishFrame = function(tags, frame) {
  23333. if (!frame) {
  23334. return;
  23335. }
  23336. // Check if keyframe and the length of tags.
  23337. // This makes sure we write metadata on the first frame of a segment.
  23338. if (config && track && track.newMetadata &&
  23339. (frame.keyFrame || tags.length === 0)) {
  23340. // Push extra data on every IDR frame in case we did a stream change + seek
  23341. var metaTag = metaDataTag(config, frame.dts).finalize();
  23342. var extraTag = extraDataTag(track, frame.dts).finalize();
  23343. metaTag.metaDataTag = extraTag.metaDataTag = true;
  23344. tags.push(metaTag);
  23345. tags.push(extraTag);
  23346. track.newMetadata = false;
  23347. this.trigger('keyframe', frame.dts);
  23348. }
  23349. frame.endNalUnit();
  23350. tags.push(frame.finalize());
  23351. h264Frame = null;
  23352. };
  23353. this.push = function(data) {
  23354. collectTimelineInfo(track, data);
  23355. data.pts = Math.round(data.pts / 90);
  23356. data.dts = Math.round(data.dts / 90);
  23357. // buffer video until flush() is called
  23358. nalUnits.push(data);
  23359. };
  23360. this.flush = function() {
  23361. var
  23362. currentNal,
  23363. tags = new TagList();
  23364. // Throw away nalUnits at the start of the byte stream until we find
  23365. // the first AUD
  23366. while (nalUnits.length) {
  23367. if (nalUnits[0].nalUnitType === 'access_unit_delimiter_rbsp') {
  23368. break;
  23369. }
  23370. nalUnits.shift();
  23371. }
  23372. // return early if no video data has been observed
  23373. if (nalUnits.length === 0) {
  23374. this.trigger('done', 'VideoSegmentStream');
  23375. return;
  23376. }
  23377. while (nalUnits.length) {
  23378. currentNal = nalUnits.shift();
  23379. // record the track config
  23380. if (currentNal.nalUnitType === 'seq_parameter_set_rbsp') {
  23381. track.newMetadata = true;
  23382. config = currentNal.config;
  23383. track.width = config.width;
  23384. track.height = config.height;
  23385. track.sps = [currentNal.data];
  23386. track.profileIdc = config.profileIdc;
  23387. track.levelIdc = config.levelIdc;
  23388. track.profileCompatibility = config.profileCompatibility;
  23389. h264Frame.endNalUnit();
  23390. } else if (currentNal.nalUnitType === 'pic_parameter_set_rbsp') {
  23391. track.newMetadata = true;
  23392. track.pps = [currentNal.data];
  23393. h264Frame.endNalUnit();
  23394. } else if (currentNal.nalUnitType === 'access_unit_delimiter_rbsp') {
  23395. if (h264Frame) {
  23396. this.finishFrame(tags, h264Frame);
  23397. }
  23398. h264Frame = new FlvTag(FlvTag.VIDEO_TAG);
  23399. h264Frame.pts = currentNal.pts;
  23400. h264Frame.dts = currentNal.dts;
  23401. } else {
  23402. if (currentNal.nalUnitType === 'slice_layer_without_partitioning_rbsp_idr') {
  23403. // the current sample is a key frame
  23404. h264Frame.keyFrame = true;
  23405. }
  23406. h264Frame.endNalUnit();
  23407. }
  23408. h264Frame.startNalUnit();
  23409. h264Frame.writeBytes(currentNal.data);
  23410. }
  23411. if (h264Frame) {
  23412. this.finishFrame(tags, h264Frame);
  23413. }
  23414. this.trigger('data', {track: track, tags: tags.list});
  23415. // Continue with the flush process now
  23416. this.trigger('done', 'VideoSegmentStream');
  23417. };
  23418. };
  23419. VideoSegmentStream.prototype = new Stream();
  23420. /**
  23421. * An object that incrementally transmuxes MPEG2 Trasport Stream
  23422. * chunks into an FLV.
  23423. */
  23424. Transmuxer = function(options) {
  23425. var
  23426. self = this,
  23427. packetStream, parseStream, elementaryStream,
  23428. videoTimestampRolloverStream, audioTimestampRolloverStream,
  23429. timedMetadataTimestampRolloverStream,
  23430. adtsStream, h264Stream,
  23431. videoSegmentStream, audioSegmentStream, captionStream,
  23432. coalesceStream;
  23433. Transmuxer.prototype.init.call(this);
  23434. options = options || {};
  23435. // expose the metadata stream
  23436. this.metadataStream = new m2ts.MetadataStream();
  23437. options.metadataStream = this.metadataStream;
  23438. // set up the parsing pipeline
  23439. packetStream = new m2ts.TransportPacketStream();
  23440. parseStream = new m2ts.TransportParseStream();
  23441. elementaryStream = new m2ts.ElementaryStream();
  23442. videoTimestampRolloverStream = new m2ts.TimestampRolloverStream('video');
  23443. audioTimestampRolloverStream = new m2ts.TimestampRolloverStream('audio');
  23444. timedMetadataTimestampRolloverStream = new m2ts.TimestampRolloverStream('timed-metadata');
  23445. adtsStream = new AdtsStream();
  23446. h264Stream = new H264Stream();
  23447. coalesceStream = new CoalesceStream(options);
  23448. // disassemble MPEG2-TS packets into elementary streams
  23449. packetStream
  23450. .pipe(parseStream)
  23451. .pipe(elementaryStream);
  23452. // !!THIS ORDER IS IMPORTANT!!
  23453. // demux the streams
  23454. elementaryStream
  23455. .pipe(videoTimestampRolloverStream)
  23456. .pipe(h264Stream);
  23457. elementaryStream
  23458. .pipe(audioTimestampRolloverStream)
  23459. .pipe(adtsStream);
  23460. elementaryStream
  23461. .pipe(timedMetadataTimestampRolloverStream)
  23462. .pipe(this.metadataStream)
  23463. .pipe(coalesceStream);
  23464. // if CEA-708 parsing is available, hook up a caption stream
  23465. captionStream = new m2ts.CaptionStream();
  23466. h264Stream.pipe(captionStream)
  23467. .pipe(coalesceStream);
  23468. // hook up the segment streams once track metadata is delivered
  23469. elementaryStream.on('data', function(data) {
  23470. var i, videoTrack, audioTrack;
  23471. if (data.type === 'metadata') {
  23472. i = data.tracks.length;
  23473. // scan the tracks listed in the metadata
  23474. while (i--) {
  23475. if (data.tracks[i].type === 'video') {
  23476. videoTrack = data.tracks[i];
  23477. } else if (data.tracks[i].type === 'audio') {
  23478. audioTrack = data.tracks[i];
  23479. }
  23480. }
  23481. // hook up the video segment stream to the first track with h264 data
  23482. if (videoTrack && !videoSegmentStream) {
  23483. coalesceStream.numberOfTracks++;
  23484. videoSegmentStream = new VideoSegmentStream(videoTrack);
  23485. // Set up the final part of the video pipeline
  23486. h264Stream
  23487. .pipe(videoSegmentStream)
  23488. .pipe(coalesceStream);
  23489. }
  23490. if (audioTrack && !audioSegmentStream) {
  23491. // hook up the audio segment stream to the first track with aac data
  23492. coalesceStream.numberOfTracks++;
  23493. audioSegmentStream = new AudioSegmentStream(audioTrack);
  23494. // Set up the final part of the audio pipeline
  23495. adtsStream
  23496. .pipe(audioSegmentStream)
  23497. .pipe(coalesceStream);
  23498. if (videoSegmentStream) {
  23499. videoSegmentStream.on('keyframe', audioSegmentStream.onVideoKeyFrame);
  23500. }
  23501. }
  23502. }
  23503. });
  23504. // feed incoming data to the front of the parsing pipeline
  23505. this.push = function(data) {
  23506. packetStream.push(data);
  23507. };
  23508. // flush any buffered data
  23509. this.flush = function() {
  23510. // Start at the top of the pipeline and flush all pending work
  23511. packetStream.flush();
  23512. };
  23513. // Caption data has to be reset when seeking outside buffered range
  23514. this.resetCaptions = function() {
  23515. captionStream.reset();
  23516. };
  23517. // Re-emit any data coming from the coalesce stream to the outside world
  23518. coalesceStream.on('data', function(event) {
  23519. self.trigger('data', event);
  23520. });
  23521. // Let the consumer know we have finished flushing the entire pipeline
  23522. coalesceStream.on('done', function() {
  23523. self.trigger('done');
  23524. });
  23525. };
  23526. Transmuxer.prototype = new Stream();
  23527. // forward compatibility
  23528. module.exports = Transmuxer;
  23529. /***/ }),
  23530. /* 118 */
  23531. /***/ (function(module, exports) {
  23532. /**
  23533. * mux.js
  23534. *
  23535. * Copyright (c) 2014 Brightcove
  23536. * All rights reserved.
  23537. *
  23538. * A lightweight readable stream implemention that handles event dispatching.
  23539. * Objects that inherit from streams should call init in their constructors.
  23540. */
  23541. 'use strict';
  23542. var Stream = function() {
  23543. this.init = function() {
  23544. var listeners = {};
  23545. /**
  23546. * Add a listener for a specified event type.
  23547. * @param type {string} the event name
  23548. * @param listener {function} the callback to be invoked when an event of
  23549. * the specified type occurs
  23550. */
  23551. this.on = function(type, listener) {
  23552. if (!listeners[type]) {
  23553. listeners[type] = [];
  23554. }
  23555. listeners[type] = listeners[type].concat(listener);
  23556. };
  23557. /**
  23558. * Remove a listener for a specified event type.
  23559. * @param type {string} the event name
  23560. * @param listener {function} a function previously registered for this
  23561. * type of event through `on`
  23562. */
  23563. this.off = function(type, listener) {
  23564. var index;
  23565. if (!listeners[type]) {
  23566. return false;
  23567. }
  23568. index = listeners[type].indexOf(listener);
  23569. listeners[type] = listeners[type].slice();
  23570. listeners[type].splice(index, 1);
  23571. return index > -1;
  23572. };
  23573. /**
  23574. * Trigger an event of the specified type on this stream. Any additional
  23575. * arguments to this function are passed as parameters to event listeners.
  23576. * @param type {string} the event name
  23577. */
  23578. this.trigger = function(type) {
  23579. var callbacks, i, length, args;
  23580. callbacks = listeners[type];
  23581. if (!callbacks) {
  23582. return;
  23583. }
  23584. // Slicing the arguments on every invocation of this method
  23585. // can add a significant amount of overhead. Avoid the
  23586. // intermediate object creation for the common case of a
  23587. // single callback argument
  23588. if (arguments.length === 2) {
  23589. length = callbacks.length;
  23590. for (i = 0; i < length; ++i) {
  23591. callbacks[i].call(this, arguments[1]);
  23592. }
  23593. } else {
  23594. args = [];
  23595. i = arguments.length;
  23596. for (i = 1; i < arguments.length; ++i) {
  23597. args.push(arguments[i]);
  23598. }
  23599. length = callbacks.length;
  23600. for (i = 0; i < length; ++i) {
  23601. callbacks[i].apply(this, args);
  23602. }
  23603. }
  23604. };
  23605. /**
  23606. * Destroys the stream and cleans up.
  23607. */
  23608. this.dispose = function() {
  23609. listeners = {};
  23610. };
  23611. };
  23612. };
  23613. /**
  23614. * Forwards all `data` events on this stream to the destination stream. The
  23615. * destination stream should provide a method `push` to receive the data
  23616. * events as they arrive.
  23617. * @param destination {stream} the stream that will receive all `data` events
  23618. * @param autoFlush {boolean} if false, we will not call `flush` on the destination
  23619. * when the current stream emits a 'done' event
  23620. * @see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options
  23621. */
  23622. Stream.prototype.pipe = function(destination) {
  23623. this.on('data', function(data) {
  23624. destination.push(data);
  23625. });
  23626. this.on('done', function(flushSource) {
  23627. destination.flush(flushSource);
  23628. });
  23629. return destination;
  23630. };
  23631. // Default stream functions that are expected to be overridden to perform
  23632. // actual work. These are provided by the prototype as a sort of no-op
  23633. // implementation so that we don't have to check for their existence in the
  23634. // `pipe` function above.
  23635. Stream.prototype.push = function(data) {
  23636. this.trigger('data', data);
  23637. };
  23638. Stream.prototype.flush = function(flushSource) {
  23639. this.trigger('done', flushSource);
  23640. };
  23641. module.exports = Stream;
  23642. /***/ }),
  23643. /* 119 */
  23644. /***/ (function(module, exports, __webpack_require__) {
  23645. /**
  23646. * mux.js
  23647. *
  23648. * Copyright (c) 2015 Brightcove
  23649. * All rights reserved.
  23650. *
  23651. * A stream-based mp2t to mp4 converter. This utility can be used to
  23652. * deliver mp4s to a SourceBuffer on platforms that support native
  23653. * Media Source Extensions.
  23654. */
  23655. 'use strict';
  23656. var Stream = __webpack_require__(118),
  23657. CaptionStream = __webpack_require__(120),
  23658. StreamTypes = __webpack_require__(121),
  23659. TimestampRolloverStream = __webpack_require__(122).TimestampRolloverStream;
  23660. var m2tsStreamTypes = __webpack_require__(121);
  23661. // object types
  23662. var TransportPacketStream, TransportParseStream, ElementaryStream;
  23663. // constants
  23664. var
  23665. MP2T_PACKET_LENGTH = 188, // bytes
  23666. SYNC_BYTE = 0x47;
  23667. /**
  23668. * Splits an incoming stream of binary data into MPEG-2 Transport
  23669. * Stream packets.
  23670. */
  23671. TransportPacketStream = function() {
  23672. var
  23673. buffer = new Uint8Array(MP2T_PACKET_LENGTH),
  23674. bytesInBuffer = 0;
  23675. TransportPacketStream.prototype.init.call(this);
  23676. // Deliver new bytes to the stream.
  23677. this.push = function(bytes) {
  23678. var
  23679. startIndex = 0,
  23680. endIndex = MP2T_PACKET_LENGTH,
  23681. everything;
  23682. // If there are bytes remaining from the last segment, prepend them to the
  23683. // bytes that were pushed in
  23684. if (bytesInBuffer) {
  23685. everything = new Uint8Array(bytes.byteLength + bytesInBuffer);
  23686. everything.set(buffer.subarray(0, bytesInBuffer));
  23687. everything.set(bytes, bytesInBuffer);
  23688. bytesInBuffer = 0;
  23689. } else {
  23690. everything = bytes;
  23691. }
  23692. // While we have enough data for a packet
  23693. while (endIndex < everything.byteLength) {
  23694. // Look for a pair of start and end sync bytes in the data..
  23695. if (everything[startIndex] === SYNC_BYTE && everything[endIndex] === SYNC_BYTE) {
  23696. // We found a packet so emit it and jump one whole packet forward in
  23697. // the stream
  23698. this.trigger('data', everything.subarray(startIndex, endIndex));
  23699. startIndex += MP2T_PACKET_LENGTH;
  23700. endIndex += MP2T_PACKET_LENGTH;
  23701. continue;
  23702. }
  23703. // If we get here, we have somehow become de-synchronized and we need to step
  23704. // forward one byte at a time until we find a pair of sync bytes that denote
  23705. // a packet
  23706. startIndex++;
  23707. endIndex++;
  23708. }
  23709. // If there was some data left over at the end of the segment that couldn't
  23710. // possibly be a whole packet, keep it because it might be the start of a packet
  23711. // that continues in the next segment
  23712. if (startIndex < everything.byteLength) {
  23713. buffer.set(everything.subarray(startIndex), 0);
  23714. bytesInBuffer = everything.byteLength - startIndex;
  23715. }
  23716. };
  23717. this.flush = function() {
  23718. // If the buffer contains a whole packet when we are being flushed, emit it
  23719. // and empty the buffer. Otherwise hold onto the data because it may be
  23720. // important for decoding the next segment
  23721. if (bytesInBuffer === MP2T_PACKET_LENGTH && buffer[0] === SYNC_BYTE) {
  23722. this.trigger('data', buffer);
  23723. bytesInBuffer = 0;
  23724. }
  23725. this.trigger('done');
  23726. };
  23727. };
  23728. TransportPacketStream.prototype = new Stream();
  23729. /**
  23730. * Accepts an MP2T TransportPacketStream and emits data events with parsed
  23731. * forms of the individual transport stream packets.
  23732. */
  23733. TransportParseStream = function() {
  23734. var parsePsi, parsePat, parsePmt, self;
  23735. TransportParseStream.prototype.init.call(this);
  23736. self = this;
  23737. this.packetsWaitingForPmt = [];
  23738. this.programMapTable = undefined;
  23739. parsePsi = function(payload, psi) {
  23740. var offset = 0;
  23741. // PSI packets may be split into multiple sections and those
  23742. // sections may be split into multiple packets. If a PSI
  23743. // section starts in this packet, the payload_unit_start_indicator
  23744. // will be true and the first byte of the payload will indicate
  23745. // the offset from the current position to the start of the
  23746. // section.
  23747. if (psi.payloadUnitStartIndicator) {
  23748. offset += payload[offset] + 1;
  23749. }
  23750. if (psi.type === 'pat') {
  23751. parsePat(payload.subarray(offset), psi);
  23752. } else {
  23753. parsePmt(payload.subarray(offset), psi);
  23754. }
  23755. };
  23756. parsePat = function(payload, pat) {
  23757. pat.section_number = payload[7]; // eslint-disable-line camelcase
  23758. pat.last_section_number = payload[8]; // eslint-disable-line camelcase
  23759. // skip the PSI header and parse the first PMT entry
  23760. self.pmtPid = (payload[10] & 0x1F) << 8 | payload[11];
  23761. pat.pmtPid = self.pmtPid;
  23762. };
  23763. /**
  23764. * Parse out the relevant fields of a Program Map Table (PMT).
  23765. * @param payload {Uint8Array} the PMT-specific portion of an MP2T
  23766. * packet. The first byte in this array should be the table_id
  23767. * field.
  23768. * @param pmt {object} the object that should be decorated with
  23769. * fields parsed from the PMT.
  23770. */
  23771. parsePmt = function(payload, pmt) {
  23772. var sectionLength, tableEnd, programInfoLength, offset;
  23773. // PMTs can be sent ahead of the time when they should actually
  23774. // take effect. We don't believe this should ever be the case
  23775. // for HLS but we'll ignore "forward" PMT declarations if we see
  23776. // them. Future PMT declarations have the current_next_indicator
  23777. // set to zero.
  23778. if (!(payload[5] & 0x01)) {
  23779. return;
  23780. }
  23781. // overwrite any existing program map table
  23782. self.programMapTable = {
  23783. video: null,
  23784. audio: null,
  23785. 'timed-metadata': {}
  23786. };
  23787. // the mapping table ends at the end of the current section
  23788. sectionLength = (payload[1] & 0x0f) << 8 | payload[2];
  23789. tableEnd = 3 + sectionLength - 4;
  23790. // to determine where the table is, we have to figure out how
  23791. // long the program info descriptors are
  23792. programInfoLength = (payload[10] & 0x0f) << 8 | payload[11];
  23793. // advance the offset to the first entry in the mapping table
  23794. offset = 12 + programInfoLength;
  23795. while (offset < tableEnd) {
  23796. var streamType = payload[offset];
  23797. var pid = (payload[offset + 1] & 0x1F) << 8 | payload[offset + 2];
  23798. // only map a single elementary_pid for audio and video stream types
  23799. // TODO: should this be done for metadata too? for now maintain behavior of
  23800. // multiple metadata streams
  23801. if (streamType === StreamTypes.H264_STREAM_TYPE &&
  23802. self.programMapTable.video === null) {
  23803. self.programMapTable.video = pid;
  23804. } else if (streamType === StreamTypes.ADTS_STREAM_TYPE &&
  23805. self.programMapTable.audio === null) {
  23806. self.programMapTable.audio = pid;
  23807. } else if (streamType === StreamTypes.METADATA_STREAM_TYPE) {
  23808. // map pid to stream type for metadata streams
  23809. self.programMapTable['timed-metadata'][pid] = streamType;
  23810. }
  23811. // move to the next table entry
  23812. // skip past the elementary stream descriptors, if present
  23813. offset += ((payload[offset + 3] & 0x0F) << 8 | payload[offset + 4]) + 5;
  23814. }
  23815. // record the map on the packet as well
  23816. pmt.programMapTable = self.programMapTable;
  23817. };
  23818. /**
  23819. * Deliver a new MP2T packet to the stream.
  23820. */
  23821. this.push = function(packet) {
  23822. var
  23823. result = {},
  23824. offset = 4;
  23825. result.payloadUnitStartIndicator = !!(packet[1] & 0x40);
  23826. // pid is a 13-bit field starting at the last bit of packet[1]
  23827. result.pid = packet[1] & 0x1f;
  23828. result.pid <<= 8;
  23829. result.pid |= packet[2];
  23830. // if an adaption field is present, its length is specified by the
  23831. // fifth byte of the TS packet header. The adaptation field is
  23832. // used to add stuffing to PES packets that don't fill a complete
  23833. // TS packet, and to specify some forms of timing and control data
  23834. // that we do not currently use.
  23835. if (((packet[3] & 0x30) >>> 4) > 0x01) {
  23836. offset += packet[offset] + 1;
  23837. }
  23838. // parse the rest of the packet based on the type
  23839. if (result.pid === 0) {
  23840. result.type = 'pat';
  23841. parsePsi(packet.subarray(offset), result);
  23842. this.trigger('data', result);
  23843. } else if (result.pid === this.pmtPid) {
  23844. result.type = 'pmt';
  23845. parsePsi(packet.subarray(offset), result);
  23846. this.trigger('data', result);
  23847. // if there are any packets waiting for a PMT to be found, process them now
  23848. while (this.packetsWaitingForPmt.length) {
  23849. this.processPes_.apply(this, this.packetsWaitingForPmt.shift());
  23850. }
  23851. } else if (this.programMapTable === undefined) {
  23852. // When we have not seen a PMT yet, defer further processing of
  23853. // PES packets until one has been parsed
  23854. this.packetsWaitingForPmt.push([packet, offset, result]);
  23855. } else {
  23856. this.processPes_(packet, offset, result);
  23857. }
  23858. };
  23859. this.processPes_ = function(packet, offset, result) {
  23860. // set the appropriate stream type
  23861. if (result.pid === this.programMapTable.video) {
  23862. result.streamType = StreamTypes.H264_STREAM_TYPE;
  23863. } else if (result.pid === this.programMapTable.audio) {
  23864. result.streamType = StreamTypes.ADTS_STREAM_TYPE;
  23865. } else {
  23866. // if not video or audio, it is timed-metadata or unknown
  23867. // if unknown, streamType will be undefined
  23868. result.streamType = this.programMapTable['timed-metadata'][result.pid];
  23869. }
  23870. result.type = 'pes';
  23871. result.data = packet.subarray(offset);
  23872. this.trigger('data', result);
  23873. };
  23874. };
  23875. TransportParseStream.prototype = new Stream();
  23876. TransportParseStream.STREAM_TYPES = {
  23877. h264: 0x1b,
  23878. adts: 0x0f
  23879. };
  23880. /**
  23881. * Reconsistutes program elementary stream (PES) packets from parsed
  23882. * transport stream packets. That is, if you pipe an
  23883. * mp2t.TransportParseStream into a mp2t.ElementaryStream, the output
  23884. * events will be events which capture the bytes for individual PES
  23885. * packets plus relevant metadata that has been extracted from the
  23886. * container.
  23887. */
  23888. ElementaryStream = function() {
  23889. var
  23890. self = this,
  23891. // PES packet fragments
  23892. video = {
  23893. data: [],
  23894. size: 0
  23895. },
  23896. audio = {
  23897. data: [],
  23898. size: 0
  23899. },
  23900. timedMetadata = {
  23901. data: [],
  23902. size: 0
  23903. },
  23904. parsePes = function(payload, pes) {
  23905. var ptsDtsFlags;
  23906. // get the packet length, this will be 0 for video
  23907. pes.packetLength = 6 + ((payload[4] << 8) | payload[5]);
  23908. // find out if this packets starts a new keyframe
  23909. pes.dataAlignmentIndicator = (payload[6] & 0x04) !== 0;
  23910. // PES packets may be annotated with a PTS value, or a PTS value
  23911. // and a DTS value. Determine what combination of values is
  23912. // available to work with.
  23913. ptsDtsFlags = payload[7];
  23914. // PTS and DTS are normally stored as a 33-bit number. Javascript
  23915. // performs all bitwise operations on 32-bit integers but javascript
  23916. // supports a much greater range (52-bits) of integer using standard
  23917. // mathematical operations.
  23918. // We construct a 31-bit value using bitwise operators over the 31
  23919. // most significant bits and then multiply by 4 (equal to a left-shift
  23920. // of 2) before we add the final 2 least significant bits of the
  23921. // timestamp (equal to an OR.)
  23922. if (ptsDtsFlags & 0xC0) {
  23923. // the PTS and DTS are not written out directly. For information
  23924. // on how they are encoded, see
  23925. // http://dvd.sourceforge.net/dvdinfo/pes-hdr.html
  23926. pes.pts = (payload[9] & 0x0E) << 27 |
  23927. (payload[10] & 0xFF) << 20 |
  23928. (payload[11] & 0xFE) << 12 |
  23929. (payload[12] & 0xFF) << 5 |
  23930. (payload[13] & 0xFE) >>> 3;
  23931. pes.pts *= 4; // Left shift by 2
  23932. pes.pts += (payload[13] & 0x06) >>> 1; // OR by the two LSBs
  23933. pes.dts = pes.pts;
  23934. if (ptsDtsFlags & 0x40) {
  23935. pes.dts = (payload[14] & 0x0E) << 27 |
  23936. (payload[15] & 0xFF) << 20 |
  23937. (payload[16] & 0xFE) << 12 |
  23938. (payload[17] & 0xFF) << 5 |
  23939. (payload[18] & 0xFE) >>> 3;
  23940. pes.dts *= 4; // Left shift by 2
  23941. pes.dts += (payload[18] & 0x06) >>> 1; // OR by the two LSBs
  23942. }
  23943. }
  23944. // the data section starts immediately after the PES header.
  23945. // pes_header_data_length specifies the number of header bytes
  23946. // that follow the last byte of the field.
  23947. pes.data = payload.subarray(9 + payload[8]);
  23948. },
  23949. flushStream = function(stream, type, forceFlush) {
  23950. var
  23951. packetData = new Uint8Array(stream.size),
  23952. event = {
  23953. type: type
  23954. },
  23955. i = 0,
  23956. offset = 0,
  23957. packetFlushable = false,
  23958. fragment;
  23959. // do nothing if there is not enough buffered data for a complete
  23960. // PES header
  23961. if (!stream.data.length || stream.size < 9) {
  23962. return;
  23963. }
  23964. event.trackId = stream.data[0].pid;
  23965. // reassemble the packet
  23966. for (i = 0; i < stream.data.length; i++) {
  23967. fragment = stream.data[i];
  23968. packetData.set(fragment.data, offset);
  23969. offset += fragment.data.byteLength;
  23970. }
  23971. // parse assembled packet's PES header
  23972. parsePes(packetData, event);
  23973. // non-video PES packets MUST have a non-zero PES_packet_length
  23974. // check that there is enough stream data to fill the packet
  23975. packetFlushable = type === 'video' || event.packetLength <= stream.size;
  23976. // flush pending packets if the conditions are right
  23977. if (forceFlush || packetFlushable) {
  23978. stream.size = 0;
  23979. stream.data.length = 0;
  23980. }
  23981. // only emit packets that are complete. this is to avoid assembling
  23982. // incomplete PES packets due to poor segmentation
  23983. if (packetFlushable) {
  23984. self.trigger('data', event);
  23985. }
  23986. };
  23987. ElementaryStream.prototype.init.call(this);
  23988. this.push = function(data) {
  23989. ({
  23990. pat: function() {
  23991. // we have to wait for the PMT to arrive as well before we
  23992. // have any meaningful metadata
  23993. },
  23994. pes: function() {
  23995. var stream, streamType;
  23996. switch (data.streamType) {
  23997. case StreamTypes.H264_STREAM_TYPE:
  23998. case m2tsStreamTypes.H264_STREAM_TYPE:
  23999. stream = video;
  24000. streamType = 'video';
  24001. break;
  24002. case StreamTypes.ADTS_STREAM_TYPE:
  24003. stream = audio;
  24004. streamType = 'audio';
  24005. break;
  24006. case StreamTypes.METADATA_STREAM_TYPE:
  24007. stream = timedMetadata;
  24008. streamType = 'timed-metadata';
  24009. break;
  24010. default:
  24011. // ignore unknown stream types
  24012. return;
  24013. }
  24014. // if a new packet is starting, we can flush the completed
  24015. // packet
  24016. if (data.payloadUnitStartIndicator) {
  24017. flushStream(stream, streamType, true);
  24018. }
  24019. // buffer this fragment until we are sure we've received the
  24020. // complete payload
  24021. stream.data.push(data);
  24022. stream.size += data.data.byteLength;
  24023. },
  24024. pmt: function() {
  24025. var
  24026. event = {
  24027. type: 'metadata',
  24028. tracks: []
  24029. },
  24030. programMapTable = data.programMapTable;
  24031. // translate audio and video streams to tracks
  24032. if (programMapTable.video !== null) {
  24033. event.tracks.push({
  24034. timelineStartInfo: {
  24035. baseMediaDecodeTime: 0
  24036. },
  24037. id: +programMapTable.video,
  24038. codec: 'avc',
  24039. type: 'video'
  24040. });
  24041. }
  24042. if (programMapTable.audio !== null) {
  24043. event.tracks.push({
  24044. timelineStartInfo: {
  24045. baseMediaDecodeTime: 0
  24046. },
  24047. id: +programMapTable.audio,
  24048. codec: 'adts',
  24049. type: 'audio'
  24050. });
  24051. }
  24052. self.trigger('data', event);
  24053. }
  24054. })[data.type]();
  24055. };
  24056. /**
  24057. * Flush any remaining input. Video PES packets may be of variable
  24058. * length. Normally, the start of a new video packet can trigger the
  24059. * finalization of the previous packet. That is not possible if no
  24060. * more video is forthcoming, however. In that case, some other
  24061. * mechanism (like the end of the file) has to be employed. When it is
  24062. * clear that no additional data is forthcoming, calling this method
  24063. * will flush the buffered packets.
  24064. */
  24065. this.flush = function() {
  24066. // !!THIS ORDER IS IMPORTANT!!
  24067. // video first then audio
  24068. flushStream(video, 'video');
  24069. flushStream(audio, 'audio');
  24070. flushStream(timedMetadata, 'timed-metadata');
  24071. this.trigger('done');
  24072. };
  24073. };
  24074. ElementaryStream.prototype = new Stream();
  24075. var m2ts = {
  24076. PAT_PID: 0x0000,
  24077. MP2T_PACKET_LENGTH: MP2T_PACKET_LENGTH,
  24078. TransportPacketStream: TransportPacketStream,
  24079. TransportParseStream: TransportParseStream,
  24080. ElementaryStream: ElementaryStream,
  24081. TimestampRolloverStream: TimestampRolloverStream,
  24082. CaptionStream: CaptionStream.CaptionStream,
  24083. Cea608Stream: CaptionStream.Cea608Stream,
  24084. MetadataStream: __webpack_require__(123)
  24085. };
  24086. for (var type in StreamTypes) {
  24087. if (StreamTypes.hasOwnProperty(type)) {
  24088. m2ts[type] = StreamTypes[type];
  24089. }
  24090. }
  24091. module.exports = m2ts;
  24092. /***/ }),
  24093. /* 120 */
  24094. /***/ (function(module, exports, __webpack_require__) {
  24095. /**
  24096. * mux.js
  24097. *
  24098. * Copyright (c) 2015 Brightcove
  24099. * All rights reserved.
  24100. *
  24101. * Reads in-band caption information from a video elementary
  24102. * stream. Captions must follow the CEA-708 standard for injection
  24103. * into an MPEG-2 transport streams.
  24104. * @see https://en.wikipedia.org/wiki/CEA-708
  24105. * @see https://www.gpo.gov/fdsys/pkg/CFR-2007-title47-vol1/pdf/CFR-2007-title47-vol1-sec15-119.pdf
  24106. */
  24107. 'use strict';
  24108. // -----------------
  24109. // Link To Transport
  24110. // -----------------
  24111. // Supplemental enhancement information (SEI) NAL units have a
  24112. // payload type field to indicate how they are to be
  24113. // interpreted. CEAS-708 caption content is always transmitted with
  24114. // payload type 0x04.
  24115. var USER_DATA_REGISTERED_ITU_T_T35 = 4,
  24116. RBSP_TRAILING_BITS = 128,
  24117. Stream = __webpack_require__(118);
  24118. /**
  24119. * Parse a supplemental enhancement information (SEI) NAL unit.
  24120. * Stops parsing once a message of type ITU T T35 has been found.
  24121. *
  24122. * @param bytes {Uint8Array} the bytes of a SEI NAL unit
  24123. * @return {object} the parsed SEI payload
  24124. * @see Rec. ITU-T H.264, 7.3.2.3.1
  24125. */
  24126. var parseSei = function(bytes) {
  24127. var
  24128. i = 0,
  24129. result = {
  24130. payloadType: -1,
  24131. payloadSize: 0
  24132. },
  24133. payloadType = 0,
  24134. payloadSize = 0;
  24135. // go through the sei_rbsp parsing each each individual sei_message
  24136. while (i < bytes.byteLength) {
  24137. // stop once we have hit the end of the sei_rbsp
  24138. if (bytes[i] === RBSP_TRAILING_BITS) {
  24139. break;
  24140. }
  24141. // Parse payload type
  24142. while (bytes[i] === 0xFF) {
  24143. payloadType += 255;
  24144. i++;
  24145. }
  24146. payloadType += bytes[i++];
  24147. // Parse payload size
  24148. while (bytes[i] === 0xFF) {
  24149. payloadSize += 255;
  24150. i++;
  24151. }
  24152. payloadSize += bytes[i++];
  24153. // this sei_message is a 608/708 caption so save it and break
  24154. // there can only ever be one caption message in a frame's sei
  24155. if (!result.payload && payloadType === USER_DATA_REGISTERED_ITU_T_T35) {
  24156. result.payloadType = payloadType;
  24157. result.payloadSize = payloadSize;
  24158. result.payload = bytes.subarray(i, i + payloadSize);
  24159. break;
  24160. }
  24161. // skip the payload and parse the next message
  24162. i += payloadSize;
  24163. payloadType = 0;
  24164. payloadSize = 0;
  24165. }
  24166. return result;
  24167. };
  24168. // see ANSI/SCTE 128-1 (2013), section 8.1
  24169. var parseUserData = function(sei) {
  24170. // itu_t_t35_contry_code must be 181 (United States) for
  24171. // captions
  24172. if (sei.payload[0] !== 181) {
  24173. return null;
  24174. }
  24175. // itu_t_t35_provider_code should be 49 (ATSC) for captions
  24176. if (((sei.payload[1] << 8) | sei.payload[2]) !== 49) {
  24177. return null;
  24178. }
  24179. // the user_identifier should be "GA94" to indicate ATSC1 data
  24180. if (String.fromCharCode(sei.payload[3],
  24181. sei.payload[4],
  24182. sei.payload[5],
  24183. sei.payload[6]) !== 'GA94') {
  24184. return null;
  24185. }
  24186. // finally, user_data_type_code should be 0x03 for caption data
  24187. if (sei.payload[7] !== 0x03) {
  24188. return null;
  24189. }
  24190. // return the user_data_type_structure and strip the trailing
  24191. // marker bits
  24192. return sei.payload.subarray(8, sei.payload.length - 1);
  24193. };
  24194. // see CEA-708-D, section 4.4
  24195. var parseCaptionPackets = function(pts, userData) {
  24196. var results = [], i, count, offset, data;
  24197. // if this is just filler, return immediately
  24198. if (!(userData[0] & 0x40)) {
  24199. return results;
  24200. }
  24201. // parse out the cc_data_1 and cc_data_2 fields
  24202. count = userData[0] & 0x1f;
  24203. for (i = 0; i < count; i++) {
  24204. offset = i * 3;
  24205. data = {
  24206. type: userData[offset + 2] & 0x03,
  24207. pts: pts
  24208. };
  24209. // capture cc data when cc_valid is 1
  24210. if (userData[offset + 2] & 0x04) {
  24211. data.ccData = (userData[offset + 3] << 8) | userData[offset + 4];
  24212. results.push(data);
  24213. }
  24214. }
  24215. return results;
  24216. };
  24217. var CaptionStream = function() {
  24218. CaptionStream.prototype.init.call(this);
  24219. this.captionPackets_ = [];
  24220. this.ccStreams_ = [
  24221. new Cea608Stream(0, 0), // eslint-disable-line no-use-before-define
  24222. new Cea608Stream(0, 1), // eslint-disable-line no-use-before-define
  24223. new Cea608Stream(1, 0), // eslint-disable-line no-use-before-define
  24224. new Cea608Stream(1, 1) // eslint-disable-line no-use-before-define
  24225. ];
  24226. this.reset();
  24227. // forward data and done events from CCs to this CaptionStream
  24228. this.ccStreams_.forEach(function(cc) {
  24229. cc.on('data', this.trigger.bind(this, 'data'));
  24230. cc.on('done', this.trigger.bind(this, 'done'));
  24231. }, this);
  24232. };
  24233. CaptionStream.prototype = new Stream();
  24234. CaptionStream.prototype.push = function(event) {
  24235. var sei, userData;
  24236. // only examine SEI NALs
  24237. if (event.nalUnitType !== 'sei_rbsp') {
  24238. return;
  24239. }
  24240. // parse the sei
  24241. sei = parseSei(event.escapedRBSP);
  24242. // ignore everything but user_data_registered_itu_t_t35
  24243. if (sei.payloadType !== USER_DATA_REGISTERED_ITU_T_T35) {
  24244. return;
  24245. }
  24246. // parse out the user data payload
  24247. userData = parseUserData(sei);
  24248. // ignore unrecognized userData
  24249. if (!userData) {
  24250. return;
  24251. }
  24252. // Sometimes, the same segment # will be downloaded twice. To stop the
  24253. // caption data from being processed twice, we track the latest dts we've
  24254. // received and ignore everything with a dts before that. However, since
  24255. // data for a specific dts can be split across 2 packets on either side of
  24256. // a segment boundary, we need to make sure we *don't* ignore the second
  24257. // dts packet we receive that has dts === this.latestDts_. And thus, the
  24258. // ignoreNextEqualDts_ flag was born.
  24259. if (event.dts < this.latestDts_) {
  24260. // We've started getting older data, so set the flag.
  24261. this.ignoreNextEqualDts_ = true;
  24262. return;
  24263. } else if ((event.dts === this.latestDts_) && (this.ignoreNextEqualDts_)) {
  24264. // We've received the last duplicate packet, time to start processing again
  24265. this.ignoreNextEqualDts_ = false;
  24266. return;
  24267. }
  24268. // parse out CC data packets and save them for later
  24269. this.captionPackets_ = this.captionPackets_.concat(parseCaptionPackets(event.pts, userData));
  24270. this.latestDts_ = event.dts;
  24271. };
  24272. CaptionStream.prototype.flush = function() {
  24273. // make sure we actually parsed captions before proceeding
  24274. if (!this.captionPackets_.length) {
  24275. this.ccStreams_.forEach(function(cc) {
  24276. cc.flush();
  24277. }, this);
  24278. return;
  24279. }
  24280. // In Chrome, the Array#sort function is not stable so add a
  24281. // presortIndex that we can use to ensure we get a stable-sort
  24282. this.captionPackets_.forEach(function(elem, idx) {
  24283. elem.presortIndex = idx;
  24284. });
  24285. // sort caption byte-pairs based on their PTS values
  24286. this.captionPackets_.sort(function(a, b) {
  24287. if (a.pts === b.pts) {
  24288. return a.presortIndex - b.presortIndex;
  24289. }
  24290. return a.pts - b.pts;
  24291. });
  24292. this.captionPackets_.forEach(function(packet) {
  24293. if (packet.type < 2) {
  24294. // Dispatch packet to the right Cea608Stream
  24295. this.dispatchCea608Packet(packet);
  24296. }
  24297. // this is where an 'else' would go for a dispatching packets
  24298. // to a theoretical Cea708Stream that handles SERVICEn data
  24299. }, this);
  24300. this.captionPackets_.length = 0;
  24301. this.ccStreams_.forEach(function(cc) {
  24302. cc.flush();
  24303. }, this);
  24304. return;
  24305. };
  24306. CaptionStream.prototype.reset = function() {
  24307. this.latestDts_ = null;
  24308. this.ignoreNextEqualDts_ = false;
  24309. this.activeCea608Channel_ = [null, null];
  24310. this.ccStreams_.forEach(function(ccStream) {
  24311. ccStream.reset();
  24312. });
  24313. };
  24314. CaptionStream.prototype.dispatchCea608Packet = function(packet) {
  24315. // NOTE: packet.type is the CEA608 field
  24316. if (this.setsChannel1Active(packet)) {
  24317. this.activeCea608Channel_[packet.type] = 0;
  24318. } else if (this.setsChannel2Active(packet)) {
  24319. this.activeCea608Channel_[packet.type] = 1;
  24320. }
  24321. if (this.activeCea608Channel_[packet.type] === null) {
  24322. // If we haven't received anything to set the active channel, discard the
  24323. // data; we don't want jumbled captions
  24324. return;
  24325. }
  24326. this.ccStreams_[(packet.type << 1) + this.activeCea608Channel_[packet.type]].push(packet);
  24327. };
  24328. CaptionStream.prototype.setsChannel1Active = function(packet) {
  24329. return ((packet.ccData & 0x7800) === 0x1000);
  24330. };
  24331. CaptionStream.prototype.setsChannel2Active = function(packet) {
  24332. return ((packet.ccData & 0x7800) === 0x1800);
  24333. };
  24334. // ----------------------
  24335. // Session to Application
  24336. // ----------------------
  24337. var CHARACTER_TRANSLATION = {
  24338. 0x2a: 0xe1, // á
  24339. 0x5c: 0xe9, // é
  24340. 0x5e: 0xed, // í
  24341. 0x5f: 0xf3, // ó
  24342. 0x60: 0xfa, // ú
  24343. 0x7b: 0xe7, // ç
  24344. 0x7c: 0xf7, // ÷
  24345. 0x7d: 0xd1, // Ñ
  24346. 0x7e: 0xf1, // ñ
  24347. 0x7f: 0x2588, // █
  24348. 0x0130: 0xae, // ®
  24349. 0x0131: 0xb0, // °
  24350. 0x0132: 0xbd, // ½
  24351. 0x0133: 0xbf, // ¿
  24352. 0x0134: 0x2122, // ™
  24353. 0x0135: 0xa2, // ¢
  24354. 0x0136: 0xa3, // £
  24355. 0x0137: 0x266a, // ♪
  24356. 0x0138: 0xe0, // à
  24357. 0x0139: 0xa0, //
  24358. 0x013a: 0xe8, // è
  24359. 0x013b: 0xe2, // â
  24360. 0x013c: 0xea, // ê
  24361. 0x013d: 0xee, // î
  24362. 0x013e: 0xf4, // ô
  24363. 0x013f: 0xfb, // û
  24364. 0x0220: 0xc1, // Á
  24365. 0x0221: 0xc9, // É
  24366. 0x0222: 0xd3, // Ó
  24367. 0x0223: 0xda, // Ú
  24368. 0x0224: 0xdc, // Ü
  24369. 0x0225: 0xfc, // ü
  24370. 0x0226: 0x2018, // ‘
  24371. 0x0227: 0xa1, // ¡
  24372. 0x0228: 0x2a, // *
  24373. 0x0229: 0x27, // '
  24374. 0x022a: 0x2014, // —
  24375. 0x022b: 0xa9, // ©
  24376. 0x022c: 0x2120, // ℠
  24377. 0x022d: 0x2022, // •
  24378. 0x022e: 0x201c, // “
  24379. 0x022f: 0x201d, // ”
  24380. 0x0230: 0xc0, // À
  24381. 0x0231: 0xc2, // Â
  24382. 0x0232: 0xc7, // Ç
  24383. 0x0233: 0xc8, // È
  24384. 0x0234: 0xca, // Ê
  24385. 0x0235: 0xcb, // Ë
  24386. 0x0236: 0xeb, // ë
  24387. 0x0237: 0xce, // Î
  24388. 0x0238: 0xcf, // Ï
  24389. 0x0239: 0xef, // ï
  24390. 0x023a: 0xd4, // Ô
  24391. 0x023b: 0xd9, // Ù
  24392. 0x023c: 0xf9, // ù
  24393. 0x023d: 0xdb, // Û
  24394. 0x023e: 0xab, // «
  24395. 0x023f: 0xbb, // »
  24396. 0x0320: 0xc3, // Ã
  24397. 0x0321: 0xe3, // ã
  24398. 0x0322: 0xcd, // Í
  24399. 0x0323: 0xcc, // Ì
  24400. 0x0324: 0xec, // ì
  24401. 0x0325: 0xd2, // Ò
  24402. 0x0326: 0xf2, // ò
  24403. 0x0327: 0xd5, // Õ
  24404. 0x0328: 0xf5, // õ
  24405. 0x0329: 0x7b, // {
  24406. 0x032a: 0x7d, // }
  24407. 0x032b: 0x5c, // \
  24408. 0x032c: 0x5e, // ^
  24409. 0x032d: 0x5f, // _
  24410. 0x032e: 0x7c, // |
  24411. 0x032f: 0x7e, // ~
  24412. 0x0330: 0xc4, // Ä
  24413. 0x0331: 0xe4, // ä
  24414. 0x0332: 0xd6, // Ö
  24415. 0x0333: 0xf6, // ö
  24416. 0x0334: 0xdf, // ß
  24417. 0x0335: 0xa5, // ¥
  24418. 0x0336: 0xa4, // ¤
  24419. 0x0337: 0x2502, // │
  24420. 0x0338: 0xc5, // Å
  24421. 0x0339: 0xe5, // å
  24422. 0x033a: 0xd8, // Ø
  24423. 0x033b: 0xf8, // ø
  24424. 0x033c: 0x250c, // ┌
  24425. 0x033d: 0x2510, // ┐
  24426. 0x033e: 0x2514, // └
  24427. 0x033f: 0x2518 // ┘
  24428. };
  24429. var getCharFromCode = function(code) {
  24430. if (code === null) {
  24431. return '';
  24432. }
  24433. code = CHARACTER_TRANSLATION[code] || code;
  24434. return String.fromCharCode(code);
  24435. };
  24436. // the index of the last row in a CEA-608 display buffer
  24437. var BOTTOM_ROW = 14;
  24438. // This array is used for mapping PACs -> row #, since there's no way of
  24439. // getting it through bit logic.
  24440. var ROWS = [0x1100, 0x1120, 0x1200, 0x1220, 0x1500, 0x1520, 0x1600, 0x1620,
  24441. 0x1700, 0x1720, 0x1000, 0x1300, 0x1320, 0x1400, 0x1420];
  24442. // CEA-608 captions are rendered onto a 34x15 matrix of character
  24443. // cells. The "bottom" row is the last element in the outer array.
  24444. var createDisplayBuffer = function() {
  24445. var result = [], i = BOTTOM_ROW + 1;
  24446. while (i--) {
  24447. result.push('');
  24448. }
  24449. return result;
  24450. };
  24451. var Cea608Stream = function(field, dataChannel) {
  24452. Cea608Stream.prototype.init.call(this);
  24453. this.field_ = field || 0;
  24454. this.dataChannel_ = dataChannel || 0;
  24455. this.name_ = 'CC' + (((this.field_ << 1) | this.dataChannel_) + 1);
  24456. this.setConstants();
  24457. this.reset();
  24458. this.push = function(packet) {
  24459. var data, swap, char0, char1, text;
  24460. // remove the parity bits
  24461. data = packet.ccData & 0x7f7f;
  24462. // ignore duplicate control codes; the spec demands they're sent twice
  24463. if (data === this.lastControlCode_) {
  24464. this.lastControlCode_ = null;
  24465. return;
  24466. }
  24467. // Store control codes
  24468. if ((data & 0xf000) === 0x1000) {
  24469. this.lastControlCode_ = data;
  24470. } else if (data !== this.PADDING_) {
  24471. this.lastControlCode_ = null;
  24472. }
  24473. char0 = data >>> 8;
  24474. char1 = data & 0xff;
  24475. if (data === this.PADDING_) {
  24476. return;
  24477. } else if (data === this.RESUME_CAPTION_LOADING_) {
  24478. this.mode_ = 'popOn';
  24479. } else if (data === this.END_OF_CAPTION_) {
  24480. this.clearFormatting(packet.pts);
  24481. // if a caption was being displayed, it's gone now
  24482. this.flushDisplayed(packet.pts);
  24483. // flip memory
  24484. swap = this.displayed_;
  24485. this.displayed_ = this.nonDisplayed_;
  24486. this.nonDisplayed_ = swap;
  24487. // start measuring the time to display the caption
  24488. this.startPts_ = packet.pts;
  24489. } else if (data === this.ROLL_UP_2_ROWS_) {
  24490. this.topRow_ = BOTTOM_ROW - 1;
  24491. this.mode_ = 'rollUp';
  24492. } else if (data === this.ROLL_UP_3_ROWS_) {
  24493. this.topRow_ = BOTTOM_ROW - 2;
  24494. this.mode_ = 'rollUp';
  24495. } else if (data === this.ROLL_UP_4_ROWS_) {
  24496. this.topRow_ = BOTTOM_ROW - 3;
  24497. this.mode_ = 'rollUp';
  24498. } else if (data === this.CARRIAGE_RETURN_) {
  24499. this.clearFormatting(packet.pts);
  24500. this.flushDisplayed(packet.pts);
  24501. this.shiftRowsUp_();
  24502. this.startPts_ = packet.pts;
  24503. } else if (data === this.BACKSPACE_) {
  24504. if (this.mode_ === 'popOn') {
  24505. this.nonDisplayed_[BOTTOM_ROW] = this.nonDisplayed_[BOTTOM_ROW].slice(0, -1);
  24506. } else {
  24507. this.displayed_[BOTTOM_ROW] = this.displayed_[BOTTOM_ROW].slice(0, -1);
  24508. }
  24509. } else if (data === this.ERASE_DISPLAYED_MEMORY_) {
  24510. this.flushDisplayed(packet.pts);
  24511. this.displayed_ = createDisplayBuffer();
  24512. } else if (data === this.ERASE_NON_DISPLAYED_MEMORY_) {
  24513. this.nonDisplayed_ = createDisplayBuffer();
  24514. } else if (data === this.RESUME_DIRECT_CAPTIONING_) {
  24515. this.mode_ = 'paintOn';
  24516. // Append special characters to caption text
  24517. } else if (this.isSpecialCharacter(char0, char1)) {
  24518. // Bitmask char0 so that we can apply character transformations
  24519. // regardless of field and data channel.
  24520. // Then byte-shift to the left and OR with char1 so we can pass the
  24521. // entire character code to `getCharFromCode`.
  24522. char0 = (char0 & 0x03) << 8;
  24523. text = getCharFromCode(char0 | char1);
  24524. this[this.mode_](packet.pts, text);
  24525. this.column_++;
  24526. // Append extended characters to caption text
  24527. } else if (this.isExtCharacter(char0, char1)) {
  24528. // Extended characters always follow their "non-extended" equivalents.
  24529. // IE if a "è" is desired, you'll always receive "eè"; non-compliant
  24530. // decoders are supposed to drop the "è", while compliant decoders
  24531. // backspace the "e" and insert "è".
  24532. // Delete the previous character
  24533. if (this.mode_ === 'popOn') {
  24534. this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
  24535. } else {
  24536. this.displayed_[BOTTOM_ROW] = this.displayed_[BOTTOM_ROW].slice(0, -1);
  24537. }
  24538. // Bitmask char0 so that we can apply character transformations
  24539. // regardless of field and data channel.
  24540. // Then byte-shift to the left and OR with char1 so we can pass the
  24541. // entire character code to `getCharFromCode`.
  24542. char0 = (char0 & 0x03) << 8;
  24543. text = getCharFromCode(char0 | char1);
  24544. this[this.mode_](packet.pts, text);
  24545. this.column_++;
  24546. // Process mid-row codes
  24547. } else if (this.isMidRowCode(char0, char1)) {
  24548. // Attributes are not additive, so clear all formatting
  24549. this.clearFormatting(packet.pts);
  24550. // According to the standard, mid-row codes
  24551. // should be replaced with spaces, so add one now
  24552. this[this.mode_](packet.pts, ' ');
  24553. this.column_++;
  24554. if ((char1 & 0xe) === 0xe) {
  24555. this.addFormatting(packet.pts, ['i']);
  24556. }
  24557. if ((char1 & 0x1) === 0x1) {
  24558. this.addFormatting(packet.pts, ['u']);
  24559. }
  24560. // Detect offset control codes and adjust cursor
  24561. } else if (this.isOffsetControlCode(char0, char1)) {
  24562. // Cursor position is set by indent PAC (see below) in 4-column
  24563. // increments, with an additional offset code of 1-3 to reach any
  24564. // of the 32 columns specified by CEA-608. So all we need to do
  24565. // here is increment the column cursor by the given offset.
  24566. this.column_ += (char1 & 0x03);
  24567. // Detect PACs (Preamble Address Codes)
  24568. } else if (this.isPAC(char0, char1)) {
  24569. // There's no logic for PAC -> row mapping, so we have to just
  24570. // find the row code in an array and use its index :(
  24571. var row = ROWS.indexOf(data & 0x1f20);
  24572. if (row !== this.row_) {
  24573. // formatting is only persistent for current row
  24574. this.clearFormatting(packet.pts);
  24575. this.row_ = row;
  24576. }
  24577. // All PACs can apply underline, so detect and apply
  24578. // (All odd-numbered second bytes set underline)
  24579. if ((char1 & 0x1) && (this.formatting_.indexOf('u') === -1)) {
  24580. this.addFormatting(packet.pts, ['u']);
  24581. }
  24582. if ((data & 0x10) === 0x10) {
  24583. // We've got an indent level code. Each successive even number
  24584. // increments the column cursor by 4, so we can get the desired
  24585. // column position by bit-shifting to the right (to get n/2)
  24586. // and multiplying by 4.
  24587. this.column_ = ((data & 0xe) >> 1) * 4;
  24588. }
  24589. if (this.isColorPAC(char1)) {
  24590. // it's a color code, though we only support white, which
  24591. // can be either normal or italicized. white italics can be
  24592. // either 0x4e or 0x6e depending on the row, so we just
  24593. // bitwise-and with 0xe to see if italics should be turned on
  24594. if ((char1 & 0xe) === 0xe) {
  24595. this.addFormatting(packet.pts, ['i']);
  24596. }
  24597. }
  24598. // We have a normal character in char0, and possibly one in char1
  24599. } else if (this.isNormalChar(char0)) {
  24600. if (char1 === 0x00) {
  24601. char1 = null;
  24602. }
  24603. text = getCharFromCode(char0);
  24604. text += getCharFromCode(char1);
  24605. this[this.mode_](packet.pts, text);
  24606. this.column_ += text.length;
  24607. } // finish data processing
  24608. };
  24609. };
  24610. Cea608Stream.prototype = new Stream();
  24611. // Trigger a cue point that captures the current state of the
  24612. // display buffer
  24613. Cea608Stream.prototype.flushDisplayed = function(pts) {
  24614. var content = this.displayed_
  24615. // remove spaces from the start and end of the string
  24616. .map(function(row) {
  24617. return row.trim();
  24618. })
  24619. // combine all text rows to display in one cue
  24620. .join('\n')
  24621. // and remove blank rows from the start and end, but not the middle
  24622. .replace(/^\n+|\n+$/g, '');
  24623. if (content.length) {
  24624. this.trigger('data', {
  24625. startPts: this.startPts_,
  24626. endPts: pts,
  24627. text: content,
  24628. stream: this.name_
  24629. });
  24630. }
  24631. };
  24632. /**
  24633. * Zero out the data, used for startup and on seek
  24634. */
  24635. Cea608Stream.prototype.reset = function() {
  24636. this.mode_ = 'popOn';
  24637. // When in roll-up mode, the index of the last row that will
  24638. // actually display captions. If a caption is shifted to a row
  24639. // with a lower index than this, it is cleared from the display
  24640. // buffer
  24641. this.topRow_ = 0;
  24642. this.startPts_ = 0;
  24643. this.displayed_ = createDisplayBuffer();
  24644. this.nonDisplayed_ = createDisplayBuffer();
  24645. this.lastControlCode_ = null;
  24646. // Track row and column for proper line-breaking and spacing
  24647. this.column_ = 0;
  24648. this.row_ = BOTTOM_ROW;
  24649. // This variable holds currently-applied formatting
  24650. this.formatting_ = [];
  24651. };
  24652. /**
  24653. * Sets up control code and related constants for this instance
  24654. */
  24655. Cea608Stream.prototype.setConstants = function() {
  24656. // The following attributes have these uses:
  24657. // ext_ : char0 for mid-row codes, and the base for extended
  24658. // chars (ext_+0, ext_+1, and ext_+2 are char0s for
  24659. // extended codes)
  24660. // control_: char0 for control codes, except byte-shifted to the
  24661. // left so that we can do this.control_ | CONTROL_CODE
  24662. // offset_: char0 for tab offset codes
  24663. //
  24664. // It's also worth noting that control codes, and _only_ control codes,
  24665. // differ between field 1 and field2. Field 2 control codes are always
  24666. // their field 1 value plus 1. That's why there's the "| field" on the
  24667. // control value.
  24668. if (this.dataChannel_ === 0) {
  24669. this.BASE_ = 0x10;
  24670. this.EXT_ = 0x11;
  24671. this.CONTROL_ = (0x14 | this.field_) << 8;
  24672. this.OFFSET_ = 0x17;
  24673. } else if (this.dataChannel_ === 1) {
  24674. this.BASE_ = 0x18;
  24675. this.EXT_ = 0x19;
  24676. this.CONTROL_ = (0x1c | this.field_) << 8;
  24677. this.OFFSET_ = 0x1f;
  24678. }
  24679. // Constants for the LSByte command codes recognized by Cea608Stream. This
  24680. // list is not exhaustive. For a more comprehensive listing and semantics see
  24681. // http://www.gpo.gov/fdsys/pkg/CFR-2010-title47-vol1/pdf/CFR-2010-title47-vol1-sec15-119.pdf
  24682. // Padding
  24683. this.PADDING_ = 0x0000;
  24684. // Pop-on Mode
  24685. this.RESUME_CAPTION_LOADING_ = this.CONTROL_ | 0x20;
  24686. this.END_OF_CAPTION_ = this.CONTROL_ | 0x2f;
  24687. // Roll-up Mode
  24688. this.ROLL_UP_2_ROWS_ = this.CONTROL_ | 0x25;
  24689. this.ROLL_UP_3_ROWS_ = this.CONTROL_ | 0x26;
  24690. this.ROLL_UP_4_ROWS_ = this.CONTROL_ | 0x27;
  24691. this.CARRIAGE_RETURN_ = this.CONTROL_ | 0x2d;
  24692. // paint-on mode (not supported)
  24693. this.RESUME_DIRECT_CAPTIONING_ = this.CONTROL_ | 0x29;
  24694. // Erasure
  24695. this.BACKSPACE_ = this.CONTROL_ | 0x21;
  24696. this.ERASE_DISPLAYED_MEMORY_ = this.CONTROL_ | 0x2c;
  24697. this.ERASE_NON_DISPLAYED_MEMORY_ = this.CONTROL_ | 0x2e;
  24698. };
  24699. /**
  24700. * Detects if the 2-byte packet data is a special character
  24701. *
  24702. * Special characters have a second byte in the range 0x30 to 0x3f,
  24703. * with the first byte being 0x11 (for data channel 1) or 0x19 (for
  24704. * data channel 2).
  24705. *
  24706. * @param {Integer} char0 The first byte
  24707. * @param {Integer} char1 The second byte
  24708. * @return {Boolean} Whether the 2 bytes are an special character
  24709. */
  24710. Cea608Stream.prototype.isSpecialCharacter = function(char0, char1) {
  24711. return (char0 === this.EXT_ && char1 >= 0x30 && char1 <= 0x3f);
  24712. };
  24713. /**
  24714. * Detects if the 2-byte packet data is an extended character
  24715. *
  24716. * Extended characters have a second byte in the range 0x20 to 0x3f,
  24717. * with the first byte being 0x12 or 0x13 (for data channel 1) or
  24718. * 0x1a or 0x1b (for data channel 2).
  24719. *
  24720. * @param {Integer} char0 The first byte
  24721. * @param {Integer} char1 The second byte
  24722. * @return {Boolean} Whether the 2 bytes are an extended character
  24723. */
  24724. Cea608Stream.prototype.isExtCharacter = function(char0, char1) {
  24725. return ((char0 === (this.EXT_ + 1) || char0 === (this.EXT_ + 2)) &&
  24726. (char1 >= 0x20 && char1 <= 0x3f));
  24727. };
  24728. /**
  24729. * Detects if the 2-byte packet is a mid-row code
  24730. *
  24731. * Mid-row codes have a second byte in the range 0x20 to 0x2f, with
  24732. * the first byte being 0x11 (for data channel 1) or 0x19 (for data
  24733. * channel 2).
  24734. *
  24735. * @param {Integer} char0 The first byte
  24736. * @param {Integer} char1 The second byte
  24737. * @return {Boolean} Whether the 2 bytes are a mid-row code
  24738. */
  24739. Cea608Stream.prototype.isMidRowCode = function(char0, char1) {
  24740. return (char0 === this.EXT_ && (char1 >= 0x20 && char1 <= 0x2f));
  24741. };
  24742. /**
  24743. * Detects if the 2-byte packet is an offset control code
  24744. *
  24745. * Offset control codes have a second byte in the range 0x21 to 0x23,
  24746. * with the first byte being 0x17 (for data channel 1) or 0x1f (for
  24747. * data channel 2).
  24748. *
  24749. * @param {Integer} char0 The first byte
  24750. * @param {Integer} char1 The second byte
  24751. * @return {Boolean} Whether the 2 bytes are an offset control code
  24752. */
  24753. Cea608Stream.prototype.isOffsetControlCode = function(char0, char1) {
  24754. return (char0 === this.OFFSET_ && (char1 >= 0x21 && char1 <= 0x23));
  24755. };
  24756. /**
  24757. * Detects if the 2-byte packet is a Preamble Address Code
  24758. *
  24759. * PACs have a first byte in the range 0x10 to 0x17 (for data channel 1)
  24760. * or 0x18 to 0x1f (for data channel 2), with the second byte in the
  24761. * range 0x40 to 0x7f.
  24762. *
  24763. * @param {Integer} char0 The first byte
  24764. * @param {Integer} char1 The second byte
  24765. * @return {Boolean} Whether the 2 bytes are a PAC
  24766. */
  24767. Cea608Stream.prototype.isPAC = function(char0, char1) {
  24768. return (char0 >= this.BASE_ && char0 < (this.BASE_ + 8) &&
  24769. (char1 >= 0x40 && char1 <= 0x7f));
  24770. };
  24771. /**
  24772. * Detects if a packet's second byte is in the range of a PAC color code
  24773. *
  24774. * PAC color codes have the second byte be in the range 0x40 to 0x4f, or
  24775. * 0x60 to 0x6f.
  24776. *
  24777. * @param {Integer} char1 The second byte
  24778. * @return {Boolean} Whether the byte is a color PAC
  24779. */
  24780. Cea608Stream.prototype.isColorPAC = function(char1) {
  24781. return ((char1 >= 0x40 && char1 <= 0x4f) || (char1 >= 0x60 && char1 <= 0x7f));
  24782. };
  24783. /**
  24784. * Detects if a single byte is in the range of a normal character
  24785. *
  24786. * Normal text bytes are in the range 0x20 to 0x7f.
  24787. *
  24788. * @param {Integer} char The byte
  24789. * @return {Boolean} Whether the byte is a normal character
  24790. */
  24791. Cea608Stream.prototype.isNormalChar = function(char) {
  24792. return (char >= 0x20 && char <= 0x7f);
  24793. };
  24794. // Adds the opening HTML tag for the passed character to the caption text,
  24795. // and keeps track of it for later closing
  24796. Cea608Stream.prototype.addFormatting = function(pts, format) {
  24797. this.formatting_ = this.formatting_.concat(format);
  24798. var text = format.reduce(function(text, format) {
  24799. return text + '<' + format + '>';
  24800. }, '');
  24801. this[this.mode_](pts, text);
  24802. };
  24803. // Adds HTML closing tags for current formatting to caption text and
  24804. // clears remembered formatting
  24805. Cea608Stream.prototype.clearFormatting = function(pts) {
  24806. if (!this.formatting_.length) {
  24807. return;
  24808. }
  24809. var text = this.formatting_.reverse().reduce(function(text, format) {
  24810. return text + '</' + format + '>';
  24811. }, '');
  24812. this.formatting_ = [];
  24813. this[this.mode_](pts, text);
  24814. };
  24815. // Mode Implementations
  24816. Cea608Stream.prototype.popOn = function(pts, text) {
  24817. var baseRow = this.nonDisplayed_[this.row_];
  24818. // buffer characters
  24819. baseRow += text;
  24820. this.nonDisplayed_[this.row_] = baseRow;
  24821. };
  24822. Cea608Stream.prototype.rollUp = function(pts, text) {
  24823. var baseRow = this.displayed_[BOTTOM_ROW];
  24824. baseRow += text;
  24825. this.displayed_[BOTTOM_ROW] = baseRow;
  24826. };
  24827. Cea608Stream.prototype.shiftRowsUp_ = function() {
  24828. var i;
  24829. // clear out inactive rows
  24830. for (i = 0; i < this.topRow_; i++) {
  24831. this.displayed_[i] = '';
  24832. }
  24833. // shift displayed rows up
  24834. for (i = this.topRow_; i < BOTTOM_ROW; i++) {
  24835. this.displayed_[i] = this.displayed_[i + 1];
  24836. }
  24837. // clear out the bottom row
  24838. this.displayed_[BOTTOM_ROW] = '';
  24839. };
  24840. // paintOn mode is not implemented
  24841. Cea608Stream.prototype.paintOn = function() {};
  24842. // exports
  24843. module.exports = {
  24844. CaptionStream: CaptionStream,
  24845. Cea608Stream: Cea608Stream
  24846. };
  24847. /***/ }),
  24848. /* 121 */
  24849. /***/ (function(module, exports) {
  24850. 'use strict';
  24851. module.exports = {
  24852. H264_STREAM_TYPE: 0x1B,
  24853. ADTS_STREAM_TYPE: 0x0F,
  24854. METADATA_STREAM_TYPE: 0x15
  24855. };
  24856. /***/ }),
  24857. /* 122 */
  24858. /***/ (function(module, exports, __webpack_require__) {
  24859. /**
  24860. * mux.js
  24861. *
  24862. * Copyright (c) 2016 Brightcove
  24863. * All rights reserved.
  24864. *
  24865. * Accepts program elementary stream (PES) data events and corrects
  24866. * decode and presentation time stamps to account for a rollover
  24867. * of the 33 bit value.
  24868. */
  24869. 'use strict';
  24870. var Stream = __webpack_require__(118);
  24871. var MAX_TS = 8589934592;
  24872. var RO_THRESH = 4294967296;
  24873. var handleRollover = function(value, reference) {
  24874. var direction = 1;
  24875. if (value > reference) {
  24876. // If the current timestamp value is greater than our reference timestamp and we detect a
  24877. // timestamp rollover, this means the roll over is happening in the opposite direction.
  24878. // Example scenario: Enter a long stream/video just after a rollover occurred. The reference
  24879. // point will be set to a small number, e.g. 1. The user then seeks backwards over the
  24880. // rollover point. In loading this segment, the timestamp values will be very large,
  24881. // e.g. 2^33 - 1. Since this comes before the data we loaded previously, we want to adjust
  24882. // the time stamp to be `value - 2^33`.
  24883. direction = -1;
  24884. }
  24885. // Note: A seek forwards or back that is greater than the RO_THRESH (2^32, ~13 hours) will
  24886. // cause an incorrect adjustment.
  24887. while (Math.abs(reference - value) > RO_THRESH) {
  24888. value += (direction * MAX_TS);
  24889. }
  24890. return value;
  24891. };
  24892. var TimestampRolloverStream = function(type) {
  24893. var lastDTS, referenceDTS;
  24894. TimestampRolloverStream.prototype.init.call(this);
  24895. this.type_ = type;
  24896. this.push = function(data) {
  24897. if (data.type !== this.type_) {
  24898. return;
  24899. }
  24900. if (referenceDTS === undefined) {
  24901. referenceDTS = data.dts;
  24902. }
  24903. data.dts = handleRollover(data.dts, referenceDTS);
  24904. data.pts = handleRollover(data.pts, referenceDTS);
  24905. lastDTS = data.dts;
  24906. this.trigger('data', data);
  24907. };
  24908. this.flush = function() {
  24909. referenceDTS = lastDTS;
  24910. this.trigger('done');
  24911. };
  24912. this.discontinuity = function() {
  24913. referenceDTS = void 0;
  24914. lastDTS = void 0;
  24915. };
  24916. };
  24917. TimestampRolloverStream.prototype = new Stream();
  24918. module.exports = {
  24919. TimestampRolloverStream: TimestampRolloverStream,
  24920. handleRollover: handleRollover
  24921. };
  24922. /***/ }),
  24923. /* 123 */
  24924. /***/ (function(module, exports, __webpack_require__) {
  24925. /**
  24926. * Accepts program elementary stream (PES) data events and parses out
  24927. * ID3 metadata from them, if present.
  24928. * @see http://id3.org/id3v2.3.0
  24929. */
  24930. 'use strict';
  24931. var
  24932. Stream = __webpack_require__(118),
  24933. StreamTypes = __webpack_require__(121),
  24934. // return a percent-encoded representation of the specified byte range
  24935. // @see http://en.wikipedia.org/wiki/Percent-encoding
  24936. percentEncode = function(bytes, start, end) {
  24937. var i, result = '';
  24938. for (i = start; i < end; i++) {
  24939. result += '%' + ('00' + bytes[i].toString(16)).slice(-2);
  24940. }
  24941. return result;
  24942. },
  24943. // return the string representation of the specified byte range,
  24944. // interpreted as UTf-8.
  24945. parseUtf8 = function(bytes, start, end) {
  24946. return decodeURIComponent(percentEncode(bytes, start, end));
  24947. },
  24948. // return the string representation of the specified byte range,
  24949. // interpreted as ISO-8859-1.
  24950. parseIso88591 = function(bytes, start, end) {
  24951. return unescape(percentEncode(bytes, start, end)); // jshint ignore:line
  24952. },
  24953. parseSyncSafeInteger = function(data) {
  24954. return (data[0] << 21) |
  24955. (data[1] << 14) |
  24956. (data[2] << 7) |
  24957. (data[3]);
  24958. },
  24959. tagParsers = {
  24960. TXXX: function(tag) {
  24961. var i;
  24962. if (tag.data[0] !== 3) {
  24963. // ignore frames with unrecognized character encodings
  24964. return;
  24965. }
  24966. for (i = 1; i < tag.data.length; i++) {
  24967. if (tag.data[i] === 0) {
  24968. // parse the text fields
  24969. tag.description = parseUtf8(tag.data, 1, i);
  24970. // do not include the null terminator in the tag value
  24971. tag.value = parseUtf8(tag.data, i + 1, tag.data.length).replace(/\0*$/, '');
  24972. break;
  24973. }
  24974. }
  24975. tag.data = tag.value;
  24976. },
  24977. WXXX: function(tag) {
  24978. var i;
  24979. if (tag.data[0] !== 3) {
  24980. // ignore frames with unrecognized character encodings
  24981. return;
  24982. }
  24983. for (i = 1; i < tag.data.length; i++) {
  24984. if (tag.data[i] === 0) {
  24985. // parse the description and URL fields
  24986. tag.description = parseUtf8(tag.data, 1, i);
  24987. tag.url = parseUtf8(tag.data, i + 1, tag.data.length);
  24988. break;
  24989. }
  24990. }
  24991. },
  24992. PRIV: function(tag) {
  24993. var i;
  24994. for (i = 0; i < tag.data.length; i++) {
  24995. if (tag.data[i] === 0) {
  24996. // parse the description and URL fields
  24997. tag.owner = parseIso88591(tag.data, 0, i);
  24998. break;
  24999. }
  25000. }
  25001. tag.privateData = tag.data.subarray(i + 1);
  25002. tag.data = tag.privateData;
  25003. }
  25004. },
  25005. MetadataStream;
  25006. MetadataStream = function(options) {
  25007. var
  25008. settings = {
  25009. debug: !!(options && options.debug),
  25010. // the bytes of the program-level descriptor field in MP2T
  25011. // see ISO/IEC 13818-1:2013 (E), section 2.6 "Program and
  25012. // program element descriptors"
  25013. descriptor: options && options.descriptor
  25014. },
  25015. // the total size in bytes of the ID3 tag being parsed
  25016. tagSize = 0,
  25017. // tag data that is not complete enough to be parsed
  25018. buffer = [],
  25019. // the total number of bytes currently in the buffer
  25020. bufferSize = 0,
  25021. i;
  25022. MetadataStream.prototype.init.call(this);
  25023. // calculate the text track in-band metadata track dispatch type
  25024. // https://html.spec.whatwg.org/multipage/embedded-content.html#steps-to-expose-a-media-resource-specific-text-track
  25025. this.dispatchType = StreamTypes.METADATA_STREAM_TYPE.toString(16);
  25026. if (settings.descriptor) {
  25027. for (i = 0; i < settings.descriptor.length; i++) {
  25028. this.dispatchType += ('00' + settings.descriptor[i].toString(16)).slice(-2);
  25029. }
  25030. }
  25031. this.push = function(chunk) {
  25032. var tag, frameStart, frameSize, frame, i, frameHeader;
  25033. if (chunk.type !== 'timed-metadata') {
  25034. return;
  25035. }
  25036. // if data_alignment_indicator is set in the PES header,
  25037. // we must have the start of a new ID3 tag. Assume anything
  25038. // remaining in the buffer was malformed and throw it out
  25039. if (chunk.dataAlignmentIndicator) {
  25040. bufferSize = 0;
  25041. buffer.length = 0;
  25042. }
  25043. // ignore events that don't look like ID3 data
  25044. if (buffer.length === 0 &&
  25045. (chunk.data.length < 10 ||
  25046. chunk.data[0] !== 'I'.charCodeAt(0) ||
  25047. chunk.data[1] !== 'D'.charCodeAt(0) ||
  25048. chunk.data[2] !== '3'.charCodeAt(0))) {
  25049. if (settings.debug) {
  25050. // eslint-disable-next-line no-console
  25051. console.log('Skipping unrecognized metadata packet');
  25052. }
  25053. return;
  25054. }
  25055. // add this chunk to the data we've collected so far
  25056. buffer.push(chunk);
  25057. bufferSize += chunk.data.byteLength;
  25058. // grab the size of the entire frame from the ID3 header
  25059. if (buffer.length === 1) {
  25060. // the frame size is transmitted as a 28-bit integer in the
  25061. // last four bytes of the ID3 header.
  25062. // The most significant bit of each byte is dropped and the
  25063. // results concatenated to recover the actual value.
  25064. tagSize = parseSyncSafeInteger(chunk.data.subarray(6, 10));
  25065. // ID3 reports the tag size excluding the header but it's more
  25066. // convenient for our comparisons to include it
  25067. tagSize += 10;
  25068. }
  25069. // if the entire frame has not arrived, wait for more data
  25070. if (bufferSize < tagSize) {
  25071. return;
  25072. }
  25073. // collect the entire frame so it can be parsed
  25074. tag = {
  25075. data: new Uint8Array(tagSize),
  25076. frames: [],
  25077. pts: buffer[0].pts,
  25078. dts: buffer[0].dts
  25079. };
  25080. for (i = 0; i < tagSize;) {
  25081. tag.data.set(buffer[0].data.subarray(0, tagSize - i), i);
  25082. i += buffer[0].data.byteLength;
  25083. bufferSize -= buffer[0].data.byteLength;
  25084. buffer.shift();
  25085. }
  25086. // find the start of the first frame and the end of the tag
  25087. frameStart = 10;
  25088. if (tag.data[5] & 0x40) {
  25089. // advance the frame start past the extended header
  25090. frameStart += 4; // header size field
  25091. frameStart += parseSyncSafeInteger(tag.data.subarray(10, 14));
  25092. // clip any padding off the end
  25093. tagSize -= parseSyncSafeInteger(tag.data.subarray(16, 20));
  25094. }
  25095. // parse one or more ID3 frames
  25096. // http://id3.org/id3v2.3.0#ID3v2_frame_overview
  25097. do {
  25098. // determine the number of bytes in this frame
  25099. frameSize = parseSyncSafeInteger(tag.data.subarray(frameStart + 4, frameStart + 8));
  25100. if (frameSize < 1) {
  25101. // eslint-disable-next-line no-console
  25102. return console.log('Malformed ID3 frame encountered. Skipping metadata parsing.');
  25103. }
  25104. frameHeader = String.fromCharCode(tag.data[frameStart],
  25105. tag.data[frameStart + 1],
  25106. tag.data[frameStart + 2],
  25107. tag.data[frameStart + 3]);
  25108. frame = {
  25109. id: frameHeader,
  25110. data: tag.data.subarray(frameStart + 10, frameStart + frameSize + 10)
  25111. };
  25112. frame.key = frame.id;
  25113. if (tagParsers[frame.id]) {
  25114. tagParsers[frame.id](frame);
  25115. // handle the special PRIV frame used to indicate the start
  25116. // time for raw AAC data
  25117. if (frame.owner === 'com.apple.streaming.transportStreamTimestamp') {
  25118. var
  25119. d = frame.data,
  25120. size = ((d[3] & 0x01) << 30) |
  25121. (d[4] << 22) |
  25122. (d[5] << 14) |
  25123. (d[6] << 6) |
  25124. (d[7] >>> 2);
  25125. size *= 4;
  25126. size += d[7] & 0x03;
  25127. frame.timeStamp = size;
  25128. // in raw AAC, all subsequent data will be timestamped based
  25129. // on the value of this frame
  25130. // we couldn't have known the appropriate pts and dts before
  25131. // parsing this ID3 tag so set those values now
  25132. if (tag.pts === undefined && tag.dts === undefined) {
  25133. tag.pts = frame.timeStamp;
  25134. tag.dts = frame.timeStamp;
  25135. }
  25136. this.trigger('timestamp', frame);
  25137. }
  25138. }
  25139. tag.frames.push(frame);
  25140. frameStart += 10; // advance past the frame header
  25141. frameStart += frameSize; // advance past the frame body
  25142. } while (frameStart < tagSize);
  25143. this.trigger('data', tag);
  25144. };
  25145. };
  25146. MetadataStream.prototype = new Stream();
  25147. module.exports = MetadataStream;
  25148. /***/ }),
  25149. /* 124 */
  25150. /***/ (function(module, exports, __webpack_require__) {
  25151. 'use strict';
  25152. var Stream = __webpack_require__(118);
  25153. var AdtsStream;
  25154. var
  25155. ADTS_SAMPLING_FREQUENCIES = [
  25156. 96000,
  25157. 88200,
  25158. 64000,
  25159. 48000,
  25160. 44100,
  25161. 32000,
  25162. 24000,
  25163. 22050,
  25164. 16000,
  25165. 12000,
  25166. 11025,
  25167. 8000,
  25168. 7350
  25169. ];
  25170. /*
  25171. * Accepts a ElementaryStream and emits data events with parsed
  25172. * AAC Audio Frames of the individual packets. Input audio in ADTS
  25173. * format is unpacked and re-emitted as AAC frames.
  25174. *
  25175. * @see http://wiki.multimedia.cx/index.php?title=ADTS
  25176. * @see http://wiki.multimedia.cx/?title=Understanding_AAC
  25177. */
  25178. AdtsStream = function() {
  25179. var buffer;
  25180. AdtsStream.prototype.init.call(this);
  25181. this.push = function(packet) {
  25182. var
  25183. i = 0,
  25184. frameNum = 0,
  25185. frameLength,
  25186. protectionSkipBytes,
  25187. frameEnd,
  25188. oldBuffer,
  25189. sampleCount,
  25190. adtsFrameDuration;
  25191. if (packet.type !== 'audio') {
  25192. // ignore non-audio data
  25193. return;
  25194. }
  25195. // Prepend any data in the buffer to the input data so that we can parse
  25196. // aac frames the cross a PES packet boundary
  25197. if (buffer) {
  25198. oldBuffer = buffer;
  25199. buffer = new Uint8Array(oldBuffer.byteLength + packet.data.byteLength);
  25200. buffer.set(oldBuffer);
  25201. buffer.set(packet.data, oldBuffer.byteLength);
  25202. } else {
  25203. buffer = packet.data;
  25204. }
  25205. // unpack any ADTS frames which have been fully received
  25206. // for details on the ADTS header, see http://wiki.multimedia.cx/index.php?title=ADTS
  25207. while (i + 5 < buffer.length) {
  25208. // Loook for the start of an ADTS header..
  25209. if (buffer[i] !== 0xFF || (buffer[i + 1] & 0xF6) !== 0xF0) {
  25210. // If a valid header was not found, jump one forward and attempt to
  25211. // find a valid ADTS header starting at the next byte
  25212. i++;
  25213. continue;
  25214. }
  25215. // The protection skip bit tells us if we have 2 bytes of CRC data at the
  25216. // end of the ADTS header
  25217. protectionSkipBytes = (~buffer[i + 1] & 0x01) * 2;
  25218. // Frame length is a 13 bit integer starting 16 bits from the
  25219. // end of the sync sequence
  25220. frameLength = ((buffer[i + 3] & 0x03) << 11) |
  25221. (buffer[i + 4] << 3) |
  25222. ((buffer[i + 5] & 0xe0) >> 5);
  25223. sampleCount = ((buffer[i + 6] & 0x03) + 1) * 1024;
  25224. adtsFrameDuration = (sampleCount * 90000) /
  25225. ADTS_SAMPLING_FREQUENCIES[(buffer[i + 2] & 0x3c) >>> 2];
  25226. frameEnd = i + frameLength;
  25227. // If we don't have enough data to actually finish this ADTS frame, return
  25228. // and wait for more data
  25229. if (buffer.byteLength < frameEnd) {
  25230. return;
  25231. }
  25232. // Otherwise, deliver the complete AAC frame
  25233. this.trigger('data', {
  25234. pts: packet.pts + (frameNum * adtsFrameDuration),
  25235. dts: packet.dts + (frameNum * adtsFrameDuration),
  25236. sampleCount: sampleCount,
  25237. audioobjecttype: ((buffer[i + 2] >>> 6) & 0x03) + 1,
  25238. channelcount: ((buffer[i + 2] & 1) << 2) |
  25239. ((buffer[i + 3] & 0xc0) >>> 6),
  25240. samplerate: ADTS_SAMPLING_FREQUENCIES[(buffer[i + 2] & 0x3c) >>> 2],
  25241. samplingfrequencyindex: (buffer[i + 2] & 0x3c) >>> 2,
  25242. // assume ISO/IEC 14496-12 AudioSampleEntry default of 16
  25243. samplesize: 16,
  25244. data: buffer.subarray(i + 7 + protectionSkipBytes, frameEnd)
  25245. });
  25246. // If the buffer is empty, clear it and return
  25247. if (buffer.byteLength === frameEnd) {
  25248. buffer = undefined;
  25249. return;
  25250. }
  25251. frameNum++;
  25252. // Remove the finished frame from the buffer and start the process again
  25253. buffer = buffer.subarray(frameEnd);
  25254. }
  25255. };
  25256. this.flush = function() {
  25257. this.trigger('done');
  25258. };
  25259. };
  25260. AdtsStream.prototype = new Stream();
  25261. module.exports = AdtsStream;
  25262. /***/ }),
  25263. /* 125 */
  25264. /***/ (function(module, exports, __webpack_require__) {
  25265. 'use strict';
  25266. var Stream = __webpack_require__(118);
  25267. var ExpGolomb = __webpack_require__(126);
  25268. var H264Stream, NalByteStream;
  25269. var PROFILES_WITH_OPTIONAL_SPS_DATA;
  25270. /**
  25271. * Accepts a NAL unit byte stream and unpacks the embedded NAL units.
  25272. */
  25273. NalByteStream = function() {
  25274. var
  25275. syncPoint = 0,
  25276. i,
  25277. buffer;
  25278. NalByteStream.prototype.init.call(this);
  25279. this.push = function(data) {
  25280. var swapBuffer;
  25281. if (!buffer) {
  25282. buffer = data.data;
  25283. } else {
  25284. swapBuffer = new Uint8Array(buffer.byteLength + data.data.byteLength);
  25285. swapBuffer.set(buffer);
  25286. swapBuffer.set(data.data, buffer.byteLength);
  25287. buffer = swapBuffer;
  25288. }
  25289. // Rec. ITU-T H.264, Annex B
  25290. // scan for NAL unit boundaries
  25291. // a match looks like this:
  25292. // 0 0 1 .. NAL .. 0 0 1
  25293. // ^ sync point ^ i
  25294. // or this:
  25295. // 0 0 1 .. NAL .. 0 0 0
  25296. // ^ sync point ^ i
  25297. // advance the sync point to a NAL start, if necessary
  25298. for (; syncPoint < buffer.byteLength - 3; syncPoint++) {
  25299. if (buffer[syncPoint + 2] === 1) {
  25300. // the sync point is properly aligned
  25301. i = syncPoint + 5;
  25302. break;
  25303. }
  25304. }
  25305. while (i < buffer.byteLength) {
  25306. // look at the current byte to determine if we've hit the end of
  25307. // a NAL unit boundary
  25308. switch (buffer[i]) {
  25309. case 0:
  25310. // skip past non-sync sequences
  25311. if (buffer[i - 1] !== 0) {
  25312. i += 2;
  25313. break;
  25314. } else if (buffer[i - 2] !== 0) {
  25315. i++;
  25316. break;
  25317. }
  25318. // deliver the NAL unit if it isn't empty
  25319. if (syncPoint + 3 !== i - 2) {
  25320. this.trigger('data', buffer.subarray(syncPoint + 3, i - 2));
  25321. }
  25322. // drop trailing zeroes
  25323. do {
  25324. i++;
  25325. } while (buffer[i] !== 1 && i < buffer.length);
  25326. syncPoint = i - 2;
  25327. i += 3;
  25328. break;
  25329. case 1:
  25330. // skip past non-sync sequences
  25331. if (buffer[i - 1] !== 0 ||
  25332. buffer[i - 2] !== 0) {
  25333. i += 3;
  25334. break;
  25335. }
  25336. // deliver the NAL unit
  25337. this.trigger('data', buffer.subarray(syncPoint + 3, i - 2));
  25338. syncPoint = i - 2;
  25339. i += 3;
  25340. break;
  25341. default:
  25342. // the current byte isn't a one or zero, so it cannot be part
  25343. // of a sync sequence
  25344. i += 3;
  25345. break;
  25346. }
  25347. }
  25348. // filter out the NAL units that were delivered
  25349. buffer = buffer.subarray(syncPoint);
  25350. i -= syncPoint;
  25351. syncPoint = 0;
  25352. };
  25353. this.flush = function() {
  25354. // deliver the last buffered NAL unit
  25355. if (buffer && buffer.byteLength > 3) {
  25356. this.trigger('data', buffer.subarray(syncPoint + 3));
  25357. }
  25358. // reset the stream state
  25359. buffer = null;
  25360. syncPoint = 0;
  25361. this.trigger('done');
  25362. };
  25363. };
  25364. NalByteStream.prototype = new Stream();
  25365. // values of profile_idc that indicate additional fields are included in the SPS
  25366. // see Recommendation ITU-T H.264 (4/2013),
  25367. // 7.3.2.1.1 Sequence parameter set data syntax
  25368. PROFILES_WITH_OPTIONAL_SPS_DATA = {
  25369. 100: true,
  25370. 110: true,
  25371. 122: true,
  25372. 244: true,
  25373. 44: true,
  25374. 83: true,
  25375. 86: true,
  25376. 118: true,
  25377. 128: true,
  25378. 138: true,
  25379. 139: true,
  25380. 134: true
  25381. };
  25382. /**
  25383. * Accepts input from a ElementaryStream and produces H.264 NAL unit data
  25384. * events.
  25385. */
  25386. H264Stream = function() {
  25387. var
  25388. nalByteStream = new NalByteStream(),
  25389. self,
  25390. trackId,
  25391. currentPts,
  25392. currentDts,
  25393. discardEmulationPreventionBytes,
  25394. readSequenceParameterSet,
  25395. skipScalingList;
  25396. H264Stream.prototype.init.call(this);
  25397. self = this;
  25398. this.push = function(packet) {
  25399. if (packet.type !== 'video') {
  25400. return;
  25401. }
  25402. trackId = packet.trackId;
  25403. currentPts = packet.pts;
  25404. currentDts = packet.dts;
  25405. nalByteStream.push(packet);
  25406. };
  25407. nalByteStream.on('data', function(data) {
  25408. var
  25409. event = {
  25410. trackId: trackId,
  25411. pts: currentPts,
  25412. dts: currentDts,
  25413. data: data
  25414. };
  25415. switch (data[0] & 0x1f) {
  25416. case 0x05:
  25417. event.nalUnitType = 'slice_layer_without_partitioning_rbsp_idr';
  25418. break;
  25419. case 0x06:
  25420. event.nalUnitType = 'sei_rbsp';
  25421. event.escapedRBSP = discardEmulationPreventionBytes(data.subarray(1));
  25422. break;
  25423. case 0x07:
  25424. event.nalUnitType = 'seq_parameter_set_rbsp';
  25425. event.escapedRBSP = discardEmulationPreventionBytes(data.subarray(1));
  25426. event.config = readSequenceParameterSet(event.escapedRBSP);
  25427. break;
  25428. case 0x08:
  25429. event.nalUnitType = 'pic_parameter_set_rbsp';
  25430. break;
  25431. case 0x09:
  25432. event.nalUnitType = 'access_unit_delimiter_rbsp';
  25433. break;
  25434. default:
  25435. break;
  25436. }
  25437. self.trigger('data', event);
  25438. });
  25439. nalByteStream.on('done', function() {
  25440. self.trigger('done');
  25441. });
  25442. this.flush = function() {
  25443. nalByteStream.flush();
  25444. };
  25445. /**
  25446. * Advance the ExpGolomb decoder past a scaling list. The scaling
  25447. * list is optionally transmitted as part of a sequence parameter
  25448. * set and is not relevant to transmuxing.
  25449. * @param count {number} the number of entries in this scaling list
  25450. * @param expGolombDecoder {object} an ExpGolomb pointed to the
  25451. * start of a scaling list
  25452. * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
  25453. */
  25454. skipScalingList = function(count, expGolombDecoder) {
  25455. var
  25456. lastScale = 8,
  25457. nextScale = 8,
  25458. j,
  25459. deltaScale;
  25460. for (j = 0; j < count; j++) {
  25461. if (nextScale !== 0) {
  25462. deltaScale = expGolombDecoder.readExpGolomb();
  25463. nextScale = (lastScale + deltaScale + 256) % 256;
  25464. }
  25465. lastScale = (nextScale === 0) ? lastScale : nextScale;
  25466. }
  25467. };
  25468. /**
  25469. * Expunge any "Emulation Prevention" bytes from a "Raw Byte
  25470. * Sequence Payload"
  25471. * @param data {Uint8Array} the bytes of a RBSP from a NAL
  25472. * unit
  25473. * @return {Uint8Array} the RBSP without any Emulation
  25474. * Prevention Bytes
  25475. */
  25476. discardEmulationPreventionBytes = function(data) {
  25477. var
  25478. length = data.byteLength,
  25479. emulationPreventionBytesPositions = [],
  25480. i = 1,
  25481. newLength, newData;
  25482. // Find all `Emulation Prevention Bytes`
  25483. while (i < length - 2) {
  25484. if (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 0x03) {
  25485. emulationPreventionBytesPositions.push(i + 2);
  25486. i += 2;
  25487. } else {
  25488. i++;
  25489. }
  25490. }
  25491. // If no Emulation Prevention Bytes were found just return the original
  25492. // array
  25493. if (emulationPreventionBytesPositions.length === 0) {
  25494. return data;
  25495. }
  25496. // Create a new array to hold the NAL unit data
  25497. newLength = length - emulationPreventionBytesPositions.length;
  25498. newData = new Uint8Array(newLength);
  25499. var sourceIndex = 0;
  25500. for (i = 0; i < newLength; sourceIndex++, i++) {
  25501. if (sourceIndex === emulationPreventionBytesPositions[0]) {
  25502. // Skip this byte
  25503. sourceIndex++;
  25504. // Remove this position index
  25505. emulationPreventionBytesPositions.shift();
  25506. }
  25507. newData[i] = data[sourceIndex];
  25508. }
  25509. return newData;
  25510. };
  25511. /**
  25512. * Read a sequence parameter set and return some interesting video
  25513. * properties. A sequence parameter set is the H264 metadata that
  25514. * describes the properties of upcoming video frames.
  25515. * @param data {Uint8Array} the bytes of a sequence parameter set
  25516. * @return {object} an object with configuration parsed from the
  25517. * sequence parameter set, including the dimensions of the
  25518. * associated video frames.
  25519. */
  25520. readSequenceParameterSet = function(data) {
  25521. var
  25522. frameCropLeftOffset = 0,
  25523. frameCropRightOffset = 0,
  25524. frameCropTopOffset = 0,
  25525. frameCropBottomOffset = 0,
  25526. sarScale = 1,
  25527. expGolombDecoder, profileIdc, levelIdc, profileCompatibility,
  25528. chromaFormatIdc, picOrderCntType,
  25529. numRefFramesInPicOrderCntCycle, picWidthInMbsMinus1,
  25530. picHeightInMapUnitsMinus1,
  25531. frameMbsOnlyFlag,
  25532. scalingListCount,
  25533. sarRatio,
  25534. aspectRatioIdc,
  25535. i;
  25536. expGolombDecoder = new ExpGolomb(data);
  25537. profileIdc = expGolombDecoder.readUnsignedByte(); // profile_idc
  25538. profileCompatibility = expGolombDecoder.readUnsignedByte(); // constraint_set[0-5]_flag
  25539. levelIdc = expGolombDecoder.readUnsignedByte(); // level_idc u(8)
  25540. expGolombDecoder.skipUnsignedExpGolomb(); // seq_parameter_set_id
  25541. // some profiles have more optional data we don't need
  25542. if (PROFILES_WITH_OPTIONAL_SPS_DATA[profileIdc]) {
  25543. chromaFormatIdc = expGolombDecoder.readUnsignedExpGolomb();
  25544. if (chromaFormatIdc === 3) {
  25545. expGolombDecoder.skipBits(1); // separate_colour_plane_flag
  25546. }
  25547. expGolombDecoder.skipUnsignedExpGolomb(); // bit_depth_luma_minus8
  25548. expGolombDecoder.skipUnsignedExpGolomb(); // bit_depth_chroma_minus8
  25549. expGolombDecoder.skipBits(1); // qpprime_y_zero_transform_bypass_flag
  25550. if (expGolombDecoder.readBoolean()) { // seq_scaling_matrix_present_flag
  25551. scalingListCount = (chromaFormatIdc !== 3) ? 8 : 12;
  25552. for (i = 0; i < scalingListCount; i++) {
  25553. if (expGolombDecoder.readBoolean()) { // seq_scaling_list_present_flag[ i ]
  25554. if (i < 6) {
  25555. skipScalingList(16, expGolombDecoder);
  25556. } else {
  25557. skipScalingList(64, expGolombDecoder);
  25558. }
  25559. }
  25560. }
  25561. }
  25562. }
  25563. expGolombDecoder.skipUnsignedExpGolomb(); // log2_max_frame_num_minus4
  25564. picOrderCntType = expGolombDecoder.readUnsignedExpGolomb();
  25565. if (picOrderCntType === 0) {
  25566. expGolombDecoder.readUnsignedExpGolomb(); // log2_max_pic_order_cnt_lsb_minus4
  25567. } else if (picOrderCntType === 1) {
  25568. expGolombDecoder.skipBits(1); // delta_pic_order_always_zero_flag
  25569. expGolombDecoder.skipExpGolomb(); // offset_for_non_ref_pic
  25570. expGolombDecoder.skipExpGolomb(); // offset_for_top_to_bottom_field
  25571. numRefFramesInPicOrderCntCycle = expGolombDecoder.readUnsignedExpGolomb();
  25572. for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) {
  25573. expGolombDecoder.skipExpGolomb(); // offset_for_ref_frame[ i ]
  25574. }
  25575. }
  25576. expGolombDecoder.skipUnsignedExpGolomb(); // max_num_ref_frames
  25577. expGolombDecoder.skipBits(1); // gaps_in_frame_num_value_allowed_flag
  25578. picWidthInMbsMinus1 = expGolombDecoder.readUnsignedExpGolomb();
  25579. picHeightInMapUnitsMinus1 = expGolombDecoder.readUnsignedExpGolomb();
  25580. frameMbsOnlyFlag = expGolombDecoder.readBits(1);
  25581. if (frameMbsOnlyFlag === 0) {
  25582. expGolombDecoder.skipBits(1); // mb_adaptive_frame_field_flag
  25583. }
  25584. expGolombDecoder.skipBits(1); // direct_8x8_inference_flag
  25585. if (expGolombDecoder.readBoolean()) { // frame_cropping_flag
  25586. frameCropLeftOffset = expGolombDecoder.readUnsignedExpGolomb();
  25587. frameCropRightOffset = expGolombDecoder.readUnsignedExpGolomb();
  25588. frameCropTopOffset = expGolombDecoder.readUnsignedExpGolomb();
  25589. frameCropBottomOffset = expGolombDecoder.readUnsignedExpGolomb();
  25590. }
  25591. if (expGolombDecoder.readBoolean()) {
  25592. // vui_parameters_present_flag
  25593. if (expGolombDecoder.readBoolean()) {
  25594. // aspect_ratio_info_present_flag
  25595. aspectRatioIdc = expGolombDecoder.readUnsignedByte();
  25596. switch (aspectRatioIdc) {
  25597. case 1: sarRatio = [1, 1]; break;
  25598. case 2: sarRatio = [12, 11]; break;
  25599. case 3: sarRatio = [10, 11]; break;
  25600. case 4: sarRatio = [16, 11]; break;
  25601. case 5: sarRatio = [40, 33]; break;
  25602. case 6: sarRatio = [24, 11]; break;
  25603. case 7: sarRatio = [20, 11]; break;
  25604. case 8: sarRatio = [32, 11]; break;
  25605. case 9: sarRatio = [80, 33]; break;
  25606. case 10: sarRatio = [18, 11]; break;
  25607. case 11: sarRatio = [15, 11]; break;
  25608. case 12: sarRatio = [64, 33]; break;
  25609. case 13: sarRatio = [160, 99]; break;
  25610. case 14: sarRatio = [4, 3]; break;
  25611. case 15: sarRatio = [3, 2]; break;
  25612. case 16: sarRatio = [2, 1]; break;
  25613. case 255: {
  25614. sarRatio = [expGolombDecoder.readUnsignedByte() << 8 |
  25615. expGolombDecoder.readUnsignedByte(),
  25616. expGolombDecoder.readUnsignedByte() << 8 |
  25617. expGolombDecoder.readUnsignedByte() ];
  25618. break;
  25619. }
  25620. }
  25621. if (sarRatio) {
  25622. sarScale = sarRatio[0] / sarRatio[1];
  25623. }
  25624. }
  25625. }
  25626. return {
  25627. profileIdc: profileIdc,
  25628. levelIdc: levelIdc,
  25629. profileCompatibility: profileCompatibility,
  25630. width: Math.ceil((((picWidthInMbsMinus1 + 1) * 16) - frameCropLeftOffset * 2 - frameCropRightOffset * 2) * sarScale),
  25631. height: ((2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16) - (frameCropTopOffset * 2) - (frameCropBottomOffset * 2)
  25632. };
  25633. };
  25634. };
  25635. H264Stream.prototype = new Stream();
  25636. module.exports = {
  25637. H264Stream: H264Stream,
  25638. NalByteStream: NalByteStream
  25639. };
  25640. /***/ }),
  25641. /* 126 */
  25642. /***/ (function(module, exports) {
  25643. 'use strict';
  25644. var ExpGolomb;
  25645. /**
  25646. * Parser for exponential Golomb codes, a variable-bitwidth number encoding
  25647. * scheme used by h264.
  25648. */
  25649. ExpGolomb = function(workingData) {
  25650. var
  25651. // the number of bytes left to examine in workingData
  25652. workingBytesAvailable = workingData.byteLength,
  25653. // the current word being examined
  25654. workingWord = 0, // :uint
  25655. // the number of bits left to examine in the current word
  25656. workingBitsAvailable = 0; // :uint;
  25657. // ():uint
  25658. this.length = function() {
  25659. return (8 * workingBytesAvailable);
  25660. };
  25661. // ():uint
  25662. this.bitsAvailable = function() {
  25663. return (8 * workingBytesAvailable) + workingBitsAvailable;
  25664. };
  25665. // ():void
  25666. this.loadWord = function() {
  25667. var
  25668. position = workingData.byteLength - workingBytesAvailable,
  25669. workingBytes = new Uint8Array(4),
  25670. availableBytes = Math.min(4, workingBytesAvailable);
  25671. if (availableBytes === 0) {
  25672. throw new Error('no bytes available');
  25673. }
  25674. workingBytes.set(workingData.subarray(position,
  25675. position + availableBytes));
  25676. workingWord = new DataView(workingBytes.buffer).getUint32(0);
  25677. // track the amount of workingData that has been processed
  25678. workingBitsAvailable = availableBytes * 8;
  25679. workingBytesAvailable -= availableBytes;
  25680. };
  25681. // (count:int):void
  25682. this.skipBits = function(count) {
  25683. var skipBytes; // :int
  25684. if (workingBitsAvailable > count) {
  25685. workingWord <<= count;
  25686. workingBitsAvailable -= count;
  25687. } else {
  25688. count -= workingBitsAvailable;
  25689. skipBytes = Math.floor(count / 8);
  25690. count -= (skipBytes * 8);
  25691. workingBytesAvailable -= skipBytes;
  25692. this.loadWord();
  25693. workingWord <<= count;
  25694. workingBitsAvailable -= count;
  25695. }
  25696. };
  25697. // (size:int):uint
  25698. this.readBits = function(size) {
  25699. var
  25700. bits = Math.min(workingBitsAvailable, size), // :uint
  25701. valu = workingWord >>> (32 - bits); // :uint
  25702. // if size > 31, handle error
  25703. workingBitsAvailable -= bits;
  25704. if (workingBitsAvailable > 0) {
  25705. workingWord <<= bits;
  25706. } else if (workingBytesAvailable > 0) {
  25707. this.loadWord();
  25708. }
  25709. bits = size - bits;
  25710. if (bits > 0) {
  25711. return valu << bits | this.readBits(bits);
  25712. }
  25713. return valu;
  25714. };
  25715. // ():uint
  25716. this.skipLeadingZeros = function() {
  25717. var leadingZeroCount; // :uint
  25718. for (leadingZeroCount = 0; leadingZeroCount < workingBitsAvailable; ++leadingZeroCount) {
  25719. if ((workingWord & (0x80000000 >>> leadingZeroCount)) !== 0) {
  25720. // the first bit of working word is 1
  25721. workingWord <<= leadingZeroCount;
  25722. workingBitsAvailable -= leadingZeroCount;
  25723. return leadingZeroCount;
  25724. }
  25725. }
  25726. // we exhausted workingWord and still have not found a 1
  25727. this.loadWord();
  25728. return leadingZeroCount + this.skipLeadingZeros();
  25729. };
  25730. // ():void
  25731. this.skipUnsignedExpGolomb = function() {
  25732. this.skipBits(1 + this.skipLeadingZeros());
  25733. };
  25734. // ():void
  25735. this.skipExpGolomb = function() {
  25736. this.skipBits(1 + this.skipLeadingZeros());
  25737. };
  25738. // ():uint
  25739. this.readUnsignedExpGolomb = function() {
  25740. var clz = this.skipLeadingZeros(); // :uint
  25741. return this.readBits(clz + 1) - 1;
  25742. };
  25743. // ():int
  25744. this.readExpGolomb = function() {
  25745. var valu = this.readUnsignedExpGolomb(); // :int
  25746. if (0x01 & valu) {
  25747. // the number is odd if the low order bit is set
  25748. return (1 + valu) >>> 1; // add 1 to make it even, and divide by 2
  25749. }
  25750. return -1 * (valu >>> 1); // divide by two then make it negative
  25751. };
  25752. // Some convenience functions
  25753. // :Boolean
  25754. this.readBoolean = function() {
  25755. return this.readBits(1) === 1;
  25756. };
  25757. // ():int
  25758. this.readUnsignedByte = function() {
  25759. return this.readBits(8);
  25760. };
  25761. this.loadWord();
  25762. };
  25763. module.exports = ExpGolomb;
  25764. /***/ }),
  25765. /* 127 */
  25766. /***/ (function(module, exports, __webpack_require__) {
  25767. 'use strict';
  25768. var Stream = __webpack_require__(118);
  25769. /**
  25770. * The final stage of the transmuxer that emits the flv tags
  25771. * for audio, video, and metadata. Also tranlates in time and
  25772. * outputs caption data and id3 cues.
  25773. */
  25774. var CoalesceStream = function(options) {
  25775. // Number of Tracks per output segment
  25776. // If greater than 1, we combine multiple
  25777. // tracks into a single segment
  25778. this.numberOfTracks = 0;
  25779. this.metadataStream = options.metadataStream;
  25780. this.videoTags = [];
  25781. this.audioTags = [];
  25782. this.videoTrack = null;
  25783. this.audioTrack = null;
  25784. this.pendingCaptions = [];
  25785. this.pendingMetadata = [];
  25786. this.pendingTracks = 0;
  25787. this.processedTracks = 0;
  25788. CoalesceStream.prototype.init.call(this);
  25789. // Take output from multiple
  25790. this.push = function(output) {
  25791. // buffer incoming captions until the associated video segment
  25792. // finishes
  25793. if (output.text) {
  25794. return this.pendingCaptions.push(output);
  25795. }
  25796. // buffer incoming id3 tags until the final flush
  25797. if (output.frames) {
  25798. return this.pendingMetadata.push(output);
  25799. }
  25800. if (output.track.type === 'video') {
  25801. this.videoTrack = output.track;
  25802. this.videoTags = output.tags;
  25803. this.pendingTracks++;
  25804. }
  25805. if (output.track.type === 'audio') {
  25806. this.audioTrack = output.track;
  25807. this.audioTags = output.tags;
  25808. this.pendingTracks++;
  25809. }
  25810. };
  25811. };
  25812. CoalesceStream.prototype = new Stream();
  25813. CoalesceStream.prototype.flush = function(flushSource) {
  25814. var
  25815. id3,
  25816. caption,
  25817. i,
  25818. timelineStartPts,
  25819. event = {
  25820. tags: {},
  25821. captions: [],
  25822. captionStreams: {},
  25823. metadata: []
  25824. };
  25825. if (this.pendingTracks < this.numberOfTracks) {
  25826. if (flushSource !== 'VideoSegmentStream' &&
  25827. flushSource !== 'AudioSegmentStream') {
  25828. // Return because we haven't received a flush from a data-generating
  25829. // portion of the segment (meaning that we have only recieved meta-data
  25830. // or captions.)
  25831. return;
  25832. } else if (this.pendingTracks === 0) {
  25833. // In the case where we receive a flush without any data having been
  25834. // received we consider it an emitted track for the purposes of coalescing
  25835. // `done` events.
  25836. // We do this for the case where there is an audio and video track in the
  25837. // segment but no audio data. (seen in several playlists with alternate
  25838. // audio tracks and no audio present in the main TS segments.)
  25839. this.processedTracks++;
  25840. if (this.processedTracks < this.numberOfTracks) {
  25841. return;
  25842. }
  25843. }
  25844. }
  25845. this.processedTracks += this.pendingTracks;
  25846. this.pendingTracks = 0;
  25847. if (this.processedTracks < this.numberOfTracks) {
  25848. return;
  25849. }
  25850. if (this.videoTrack) {
  25851. timelineStartPts = this.videoTrack.timelineStartInfo.pts;
  25852. } else if (this.audioTrack) {
  25853. timelineStartPts = this.audioTrack.timelineStartInfo.pts;
  25854. }
  25855. event.tags.videoTags = this.videoTags;
  25856. event.tags.audioTags = this.audioTags;
  25857. // Translate caption PTS times into second offsets into the
  25858. // video timeline for the segment, and add track info
  25859. for (i = 0; i < this.pendingCaptions.length; i++) {
  25860. caption = this.pendingCaptions[i];
  25861. caption.startTime = caption.startPts - timelineStartPts;
  25862. caption.startTime /= 90e3;
  25863. caption.endTime = caption.endPts - timelineStartPts;
  25864. caption.endTime /= 90e3;
  25865. event.captionStreams[caption.stream] = true;
  25866. event.captions.push(caption);
  25867. }
  25868. // Translate ID3 frame PTS times into second offsets into the
  25869. // video timeline for the segment
  25870. for (i = 0; i < this.pendingMetadata.length; i++) {
  25871. id3 = this.pendingMetadata[i];
  25872. id3.cueTime = id3.pts - timelineStartPts;
  25873. id3.cueTime /= 90e3;
  25874. event.metadata.push(id3);
  25875. }
  25876. // We add this to every single emitted segment even though we only need
  25877. // it for the first
  25878. event.metadata.dispatchType = this.metadataStream.dispatchType;
  25879. // Reset stream state
  25880. this.videoTrack = null;
  25881. this.audioTrack = null;
  25882. this.videoTags = [];
  25883. this.audioTags = [];
  25884. this.pendingCaptions.length = 0;
  25885. this.pendingMetadata.length = 0;
  25886. this.pendingTracks = 0;
  25887. this.processedTracks = 0;
  25888. // Emit the final segment
  25889. this.trigger('data', event);
  25890. this.trigger('done');
  25891. };
  25892. module.exports = CoalesceStream;
  25893. /***/ }),
  25894. /* 128 */
  25895. /***/ (function(module, exports) {
  25896. 'use strict';
  25897. var TagList = function() {
  25898. var self = this;
  25899. this.list = [];
  25900. this.push = function(tag) {
  25901. this.list.push({
  25902. bytes: tag.bytes,
  25903. dts: tag.dts,
  25904. pts: tag.pts,
  25905. keyFrame: tag.keyFrame,
  25906. metaDataTag: tag.metaDataTag
  25907. });
  25908. };
  25909. Object.defineProperty(this, 'length', {
  25910. get: function() {
  25911. return self.list.length;
  25912. }
  25913. });
  25914. };
  25915. module.exports = TagList;
  25916. /***/ }),
  25917. /* 129 */
  25918. /***/ (function(module, exports, __webpack_require__) {
  25919. 'use strict';
  25920. var FlvTag = __webpack_require__(116);
  25921. // For information on the FLV format, see
  25922. // http://download.macromedia.com/f4v/video_file_format_spec_v10_1.pdf.
  25923. // Technically, this function returns the header and a metadata FLV tag
  25924. // if duration is greater than zero
  25925. // duration in seconds
  25926. // @return {object} the bytes of the FLV header as a Uint8Array
  25927. var getFlvHeader = function(duration, audio, video) { // :ByteArray {
  25928. var
  25929. headBytes = new Uint8Array(3 + 1 + 1 + 4),
  25930. head = new DataView(headBytes.buffer),
  25931. metadata,
  25932. result,
  25933. metadataLength;
  25934. // default arguments
  25935. duration = duration || 0;
  25936. audio = audio === undefined ? true : audio;
  25937. video = video === undefined ? true : video;
  25938. // signature
  25939. head.setUint8(0, 0x46); // 'F'
  25940. head.setUint8(1, 0x4c); // 'L'
  25941. head.setUint8(2, 0x56); // 'V'
  25942. // version
  25943. head.setUint8(3, 0x01);
  25944. // flags
  25945. head.setUint8(4, (audio ? 0x04 : 0x00) | (video ? 0x01 : 0x00));
  25946. // data offset, should be 9 for FLV v1
  25947. head.setUint32(5, headBytes.byteLength);
  25948. // init the first FLV tag
  25949. if (duration <= 0) {
  25950. // no duration available so just write the first field of the first
  25951. // FLV tag
  25952. result = new Uint8Array(headBytes.byteLength + 4);
  25953. result.set(headBytes);
  25954. result.set([0, 0, 0, 0], headBytes.byteLength);
  25955. return result;
  25956. }
  25957. // write out the duration metadata tag
  25958. metadata = new FlvTag(FlvTag.METADATA_TAG);
  25959. metadata.pts = metadata.dts = 0;
  25960. metadata.writeMetaDataDouble('duration', duration);
  25961. metadataLength = metadata.finalize().length;
  25962. result = new Uint8Array(headBytes.byteLength + metadataLength);
  25963. result.set(headBytes);
  25964. result.set(head.byteLength, metadataLength);
  25965. return result;
  25966. };
  25967. module.exports = getFlvHeader;
  25968. /***/ }),
  25969. /* 130 */
  25970. /***/ (function(module, exports) {
  25971. /**
  25972. * @file remove-cues-from-track.js
  25973. */
  25974. /**
  25975. * Remove cues from a track on video.js.
  25976. *
  25977. * @param {Double} start start of where we should remove the cue
  25978. * @param {Double} end end of where the we should remove the cue
  25979. * @param {Object} track the text track to remove the cues from
  25980. * @private
  25981. */
  25982. "use strict";
  25983. Object.defineProperty(exports, "__esModule", {
  25984. value: true
  25985. });
  25986. var removeCuesFromTrack = function removeCuesFromTrack(start, end, track) {
  25987. var i = undefined;
  25988. var cue = undefined;
  25989. if (!track) {
  25990. return;
  25991. }
  25992. if (!track.cues) {
  25993. return;
  25994. }
  25995. i = track.cues.length;
  25996. while (i--) {
  25997. cue = track.cues[i];
  25998. // Remove any overlapping cue
  25999. if (cue.startTime <= end && cue.endTime >= start) {
  26000. track.removeCue(cue);
  26001. }
  26002. }
  26003. };
  26004. exports["default"] = removeCuesFromTrack;
  26005. module.exports = exports["default"];
  26006. /***/ }),
  26007. /* 131 */
  26008. /***/ (function(module, exports) {
  26009. /**
  26010. * @file create-text-tracks-if-necessary.js
  26011. */
  26012. /**
  26013. * Create text tracks on video.js if they exist on a segment.
  26014. *
  26015. * @param {Object} sourceBuffer the VSB or FSB
  26016. * @param {Object} mediaSource the HTML or Flash media source
  26017. * @param {Object} segment the segment that may contain the text track
  26018. * @private
  26019. */
  26020. 'use strict';
  26021. Object.defineProperty(exports, '__esModule', {
  26022. value: true
  26023. });
  26024. var createTextTracksIfNecessary = function createTextTracksIfNecessary(sourceBuffer, mediaSource, segment) {
  26025. var player = mediaSource.player_;
  26026. // create an in-band caption track if one is present in the segment
  26027. if (segment.captions && segment.captions.length) {
  26028. if (!sourceBuffer.inbandTextTracks_) {
  26029. sourceBuffer.inbandTextTracks_ = {};
  26030. }
  26031. for (var trackId in segment.captionStreams) {
  26032. if (!sourceBuffer.inbandTextTracks_[trackId]) {
  26033. player.tech_.trigger({ type: 'usage', name: 'hls-608' });
  26034. var track = player.textTracks().getTrackById(trackId);
  26035. if (track) {
  26036. // Resuse an existing track with a CC# id because this was
  26037. // very likely created by videojs-contrib-hls from information
  26038. // in the m3u8 for us to use
  26039. sourceBuffer.inbandTextTracks_[trackId] = track;
  26040. } else {
  26041. // Otherwise, create a track with the default `CC#` label and
  26042. // without a language
  26043. sourceBuffer.inbandTextTracks_[trackId] = player.addRemoteTextTrack({
  26044. kind: 'captions',
  26045. id: trackId,
  26046. label: trackId
  26047. }, false).track;
  26048. }
  26049. }
  26050. }
  26051. }
  26052. if (segment.metadata && segment.metadata.length && !sourceBuffer.metadataTrack_) {
  26053. sourceBuffer.metadataTrack_ = player.addRemoteTextTrack({
  26054. kind: 'metadata',
  26055. label: 'Timed Metadata'
  26056. }, false).track;
  26057. sourceBuffer.metadataTrack_.inBandMetadataTrackDispatchType = segment.metadata.dispatchType;
  26058. }
  26059. };
  26060. exports['default'] = createTextTracksIfNecessary;
  26061. module.exports = exports['default'];
  26062. /***/ }),
  26063. /* 132 */
  26064. /***/ (function(module, exports, __webpack_require__) {
  26065. /**
  26066. * @file add-text-track-data.js
  26067. */
  26068. 'use strict';
  26069. Object.defineProperty(exports, '__esModule', {
  26070. value: true
  26071. });
  26072. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  26073. var _globalWindow = __webpack_require__(2);
  26074. var _globalWindow2 = _interopRequireDefault(_globalWindow);
  26075. var _videoJs = __webpack_require__(6);
  26076. var _videoJs2 = _interopRequireDefault(_videoJs);
  26077. /**
  26078. * Define properties on a cue for backwards compatability,
  26079. * but warn the user that the way that they are using it
  26080. * is depricated and will be removed at a later date.
  26081. *
  26082. * @param {Cue} cue the cue to add the properties on
  26083. * @private
  26084. */
  26085. var deprecateOldCue = function deprecateOldCue(cue) {
  26086. Object.defineProperties(cue.frame, {
  26087. id: {
  26088. get: function get() {
  26089. _videoJs2['default'].log.warn('cue.frame.id is deprecated. Use cue.value.key instead.');
  26090. return cue.value.key;
  26091. }
  26092. },
  26093. value: {
  26094. get: function get() {
  26095. _videoJs2['default'].log.warn('cue.frame.value is deprecated. Use cue.value.data instead.');
  26096. return cue.value.data;
  26097. }
  26098. },
  26099. privateData: {
  26100. get: function get() {
  26101. _videoJs2['default'].log.warn('cue.frame.privateData is deprecated. Use cue.value.data instead.');
  26102. return cue.value.data;
  26103. }
  26104. }
  26105. });
  26106. };
  26107. var durationOfVideo = function durationOfVideo(duration) {
  26108. var dur = undefined;
  26109. if (isNaN(duration) || Math.abs(duration) === Infinity) {
  26110. dur = Number.MAX_VALUE;
  26111. } else {
  26112. dur = duration;
  26113. }
  26114. return dur;
  26115. };
  26116. /**
  26117. * Add text track data to a source handler given the captions and
  26118. * metadata from the buffer.
  26119. *
  26120. * @param {Object} sourceHandler the flash or virtual source buffer
  26121. * @param {Array} captionArray an array of caption data
  26122. * @param {Array} metadataArray an array of meta data
  26123. * @private
  26124. */
  26125. var addTextTrackData = function addTextTrackData(sourceHandler, captionArray, metadataArray) {
  26126. var Cue = _globalWindow2['default'].WebKitDataCue || _globalWindow2['default'].VTTCue;
  26127. if (captionArray) {
  26128. captionArray.forEach(function (caption) {
  26129. var track = caption.stream;
  26130. this.inbandTextTracks_[track].addCue(new Cue(caption.startTime + this.timestampOffset, caption.endTime + this.timestampOffset, caption.text));
  26131. }, sourceHandler);
  26132. }
  26133. if (metadataArray) {
  26134. (function () {
  26135. var videoDuration = durationOfVideo(sourceHandler.mediaSource_.duration);
  26136. metadataArray.forEach(function (metadata) {
  26137. var time = metadata.cueTime + this.timestampOffset;
  26138. metadata.frames.forEach(function (frame) {
  26139. var cue = new Cue(time, time, frame.value || frame.url || frame.data || '');
  26140. cue.frame = frame;
  26141. cue.value = frame;
  26142. deprecateOldCue(cue);
  26143. this.metadataTrack_.addCue(cue);
  26144. }, this);
  26145. }, sourceHandler);
  26146. // Updating the metadeta cues so that
  26147. // the endTime of each cue is the startTime of the next cue
  26148. // the endTime of last cue is the duration of the video
  26149. if (sourceHandler.metadataTrack_ && sourceHandler.metadataTrack_.cues && sourceHandler.metadataTrack_.cues.length) {
  26150. (function () {
  26151. var cues = sourceHandler.metadataTrack_.cues;
  26152. var cuesArray = [];
  26153. // Create a copy of the TextTrackCueList...
  26154. // ...disregarding cues with a falsey value
  26155. for (var i = 0; i < cues.length; i++) {
  26156. if (cues[i]) {
  26157. cuesArray.push(cues[i]);
  26158. }
  26159. }
  26160. // Group cues by their startTime value
  26161. var cuesGroupedByStartTime = cuesArray.reduce(function (obj, cue) {
  26162. var timeSlot = obj[cue.startTime] || [];
  26163. timeSlot.push(cue);
  26164. obj[cue.startTime] = timeSlot;
  26165. return obj;
  26166. }, {});
  26167. // Sort startTimes by ascending order
  26168. var sortedStartTimes = Object.keys(cuesGroupedByStartTime).sort(function (a, b) {
  26169. return Number(a) - Number(b);
  26170. });
  26171. // Map each cue group's endTime to the next group's startTime
  26172. sortedStartTimes.forEach(function (startTime, idx) {
  26173. var cueGroup = cuesGroupedByStartTime[startTime];
  26174. var nextTime = Number(sortedStartTimes[idx + 1]) || videoDuration;
  26175. // Map each cue's endTime the next group's startTime
  26176. cueGroup.forEach(function (cue) {
  26177. cue.endTime = nextTime;
  26178. });
  26179. });
  26180. })();
  26181. }
  26182. })();
  26183. }
  26184. };
  26185. exports['default'] = {
  26186. addTextTrackData: addTextTrackData,
  26187. durationOfVideo: durationOfVideo
  26188. };
  26189. module.exports = exports['default'];
  26190. /***/ }),
  26191. /* 133 */
  26192. /***/ (function(module, exports, __webpack_require__) {
  26193. /**
  26194. * @file flash-transmuxer-worker.js
  26195. */
  26196. 'use strict';
  26197. Object.defineProperty(exports, '__esModule', {
  26198. value: true
  26199. });
  26200. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  26201. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  26202. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
  26203. var _globalWindow = __webpack_require__(2);
  26204. var _globalWindow2 = _interopRequireDefault(_globalWindow);
  26205. var _muxJsLibFlv = __webpack_require__(115);
  26206. var _muxJsLibFlv2 = _interopRequireDefault(_muxJsLibFlv);
  26207. /**
  26208. * Re-emits transmuxer events by converting them into messages to the
  26209. * world outside the worker.
  26210. *
  26211. * @param {Object} transmuxer the transmuxer to wire events on
  26212. * @private
  26213. */
  26214. var wireTransmuxerEvents = function wireTransmuxerEvents(transmuxer) {
  26215. transmuxer.on('data', function (segment) {
  26216. _globalWindow2['default'].postMessage({
  26217. action: 'data',
  26218. segment: segment
  26219. });
  26220. });
  26221. transmuxer.on('done', function (data) {
  26222. _globalWindow2['default'].postMessage({ action: 'done' });
  26223. });
  26224. };
  26225. /**
  26226. * All incoming messages route through this hash. If no function exists
  26227. * to handle an incoming message, then we ignore the message.
  26228. *
  26229. * @class MessageHandlers
  26230. * @param {Object} options the options to initialize with
  26231. */
  26232. var MessageHandlers = (function () {
  26233. function MessageHandlers(options) {
  26234. _classCallCheck(this, MessageHandlers);
  26235. this.options = options || {};
  26236. this.init();
  26237. }
  26238. /**
  26239. * Our web wroker interface so that things can talk to mux.js
  26240. * that will be running in a web worker. The scope is passed to this by
  26241. * webworkify.
  26242. *
  26243. * @param {Object} self the scope for the web worker
  26244. */
  26245. /**
  26246. * initialize our web worker and wire all the events.
  26247. */
  26248. _createClass(MessageHandlers, [{
  26249. key: 'init',
  26250. value: function init() {
  26251. if (this.transmuxer) {
  26252. this.transmuxer.dispose();
  26253. }
  26254. this.transmuxer = new _muxJsLibFlv2['default'].Transmuxer(this.options);
  26255. wireTransmuxerEvents(this.transmuxer);
  26256. }
  26257. /**
  26258. * Adds data (a ts segment) to the start of the transmuxer pipeline for
  26259. * processing.
  26260. *
  26261. * @param {ArrayBuffer} data data to push into the muxer
  26262. */
  26263. }, {
  26264. key: 'push',
  26265. value: function push(data) {
  26266. // Cast array buffer to correct type for transmuxer
  26267. var segment = new Uint8Array(data.data, data.byteOffset, data.byteLength);
  26268. this.transmuxer.push(segment);
  26269. }
  26270. /**
  26271. * Recreate the transmuxer so that the next segment added via `push`
  26272. * start with a fresh transmuxer.
  26273. */
  26274. }, {
  26275. key: 'reset',
  26276. value: function reset() {
  26277. this.init();
  26278. }
  26279. /**
  26280. * Forces the pipeline to finish processing the last segment and emit its
  26281. * results.
  26282. */
  26283. }, {
  26284. key: 'flush',
  26285. value: function flush() {
  26286. this.transmuxer.flush();
  26287. }
  26288. }, {
  26289. key: 'resetCaptions',
  26290. value: function resetCaptions() {
  26291. this.transmuxer.resetCaptions();
  26292. }
  26293. }]);
  26294. return MessageHandlers;
  26295. })();
  26296. var FlashTransmuxerWorker = function FlashTransmuxerWorker(self) {
  26297. self.onmessage = function (event) {
  26298. if (event.data.action === 'init' && event.data.options) {
  26299. this.messageHandlers = new MessageHandlers(event.data.options);
  26300. return;
  26301. }
  26302. if (!this.messageHandlers) {
  26303. this.messageHandlers = new MessageHandlers();
  26304. }
  26305. if (event.data && event.data.action && event.data.action !== 'init') {
  26306. if (this.messageHandlers[event.data.action]) {
  26307. this.messageHandlers[event.data.action](event.data);
  26308. }
  26309. }
  26310. };
  26311. };
  26312. exports['default'] = function (self) {
  26313. return new FlashTransmuxerWorker(self);
  26314. };
  26315. module.exports = exports['default'];
  26316. /***/ }),
  26317. /* 134 */
  26318. /***/ (function(module, exports, __webpack_require__) {
  26319. // By default assume browserify was used to bundle app. These arguments are passed to
  26320. // the module by browserify.
  26321. var bundleFn = arguments[3];
  26322. var sources = arguments[4];
  26323. var cache = arguments[5];
  26324. var stringify = JSON.stringify;
  26325. var webpack = false;
  26326. // webpackBootstrap
  26327. var webpackBootstrapFn = function(modules) {
  26328. // The module cache
  26329. var installedModules = {};
  26330. // The require function
  26331. function __webpack_require__(moduleId) {
  26332. // Check if module is in cache
  26333. if(installedModules[moduleId]) {
  26334. return installedModules[moduleId].exports;
  26335. }
  26336. // Create a new module (and put it into the cache)
  26337. var module = installedModules[moduleId] = {
  26338. i: moduleId,
  26339. l: false,
  26340. exports: {}
  26341. };
  26342. // Execute the module function
  26343. modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  26344. // Flag the module as loaded
  26345. module.l = true;
  26346. // Return the exports of the module
  26347. return module.exports;
  26348. }
  26349. // expose the modules object (__webpack_modules__)
  26350. __webpack_require__.m = modules;
  26351. // expose the module cache
  26352. __webpack_require__.c = installedModules;
  26353. // define getter function for harmony exports
  26354. __webpack_require__.d = function(exports, name, getter) {
  26355. if(!__webpack_require__.o(exports, name)) {
  26356. Object.defineProperty(exports, name, {
  26357. configurable: false,
  26358. enumerable: true,
  26359. get: getter
  26360. });
  26361. }
  26362. };
  26363. // getDefaultExport function for compatibility with non-harmony modules
  26364. __webpack_require__.n = function(module) {
  26365. var getter = module && module.__esModule ?
  26366. function getDefault() { return module['default']; } :
  26367. function getModuleExports() { return module; };
  26368. __webpack_require__.d(getter, 'a', getter);
  26369. return getter;
  26370. };
  26371. // Object.prototype.hasOwnProperty.call
  26372. __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
  26373. // __webpack_public_path__
  26374. __webpack_require__.p = "";
  26375. // Load entry module and return exports
  26376. return __webpack_require__(__webpack_require__.s = entryModule);
  26377. }
  26378. if (typeof bundleFn === 'undefined') {
  26379. // Assume this was bundled with webpack and not browserify
  26380. webpack = true;
  26381. bundleFn = webpackBootstrapFn;
  26382. sources = __webpack_require__.m;
  26383. }
  26384. var bundleWithBrowserify = function(fn) {
  26385. // with browserify we must find the module key ourselves
  26386. var cacheKeys = Object.keys(cache);
  26387. var fnModuleKey;
  26388. for (var i = 0; i < cacheKeys.length; i++) {
  26389. var cacheKey = cacheKeys[i];
  26390. var cacheExports = cache[cacheKey].exports;
  26391. // Using babel as a transpiler to use esmodule, the export will always
  26392. // be an object with the default export as a property of it. To ensure
  26393. // the existing api and babel esmodule exports are both supported we
  26394. // check for both
  26395. if (cacheExports === fn || cacheExports && cacheExports.default === fn) {
  26396. fnModuleKey = cacheKey;
  26397. break;
  26398. }
  26399. }
  26400. // if we couldn't find one, lets make one
  26401. if (!fnModuleKey) {
  26402. fnModuleKey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);
  26403. var fnModuleCache = {};
  26404. for (var i = 0; i < cacheKeys.length; i++) {
  26405. var cacheKey = cacheKeys[i];
  26406. fnModuleCache[cacheKey] = cacheKey;
  26407. }
  26408. sources[fnModuleKey] = [
  26409. 'function(require,module,exports){' + fn + '(self); }',
  26410. fnModuleCache
  26411. ];
  26412. }
  26413. var entryKey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);
  26414. var entryCache = {};
  26415. entryCache[fnModuleKey] = fnModuleKey;
  26416. sources[entryKey] = [
  26417. 'function(require,module,exports){' +
  26418. // try to call default if defined to also support babel esmodule exports
  26419. 'var f = require(' + stringify(fnModuleKey) + ');' +
  26420. '(f.default ? f.default : f)(self);' +
  26421. '}',
  26422. entryCache
  26423. ];
  26424. return '(' + bundleFn + ')({'
  26425. + Object.keys(sources).map(function(key) {
  26426. return stringify(key) + ':['
  26427. + sources[key][0] + ','
  26428. + stringify(sources[key][1]) + ']';
  26429. }).join(',')
  26430. + '},{},[' + stringify(entryKey) + '])';
  26431. };
  26432. var bundleWithWebpack = function(fn, fnModuleId) {
  26433. var devMode = typeof fnModuleId === 'string';
  26434. var sourceStrings;
  26435. if (devMode) {
  26436. sourceStrings = {};
  26437. } else {
  26438. sourceStrings = [];
  26439. }
  26440. Object.keys(sources).forEach(function(sKey) {
  26441. if (!sources[sKey]) {
  26442. return;
  26443. }
  26444. sourceStrings[sKey] = sources[sKey].toString();
  26445. });
  26446. var fnModuleExports = __webpack_require__(fnModuleId);
  26447. // Using babel as a transpiler to use esmodule, the export will always
  26448. // be an object with the default export as a property of it. To ensure
  26449. // the existing api and babel esmodule exports are both supported we
  26450. // check for both
  26451. if (!(fnModuleExports && (fnModuleExports === fn || fnModuleExports.default === fn))) {
  26452. var fnSourceString = sourceStrings[fnModuleId];
  26453. sourceStrings[fnModuleId] = fnSourceString.substring(0, fnSourceString.length - 1) +
  26454. '\n' + fn.name + '();\n}';
  26455. }
  26456. var modulesString;
  26457. if (devMode) {
  26458. // must escape quotes to support webpack loader options
  26459. fnModuleId = stringify(fnModuleId);
  26460. // dev mode in webpack4, modules are passed as an object
  26461. var mappedSourceStrings = Object.keys(sourceStrings).map(function(sKey) {
  26462. return stringify(sKey) + ':' + sourceStrings[sKey];
  26463. });
  26464. modulesString = '{' + mappedSourceStrings.join(',') + '}';
  26465. } else {
  26466. modulesString = '[' + sourceStrings.join(',') + ']';
  26467. }
  26468. return 'var fn = (' + bundleFn.toString().replace('entryModule', fnModuleId) + ')('
  26469. + modulesString
  26470. + ');\n'
  26471. // not a function when calling a function from the current scope
  26472. + '(typeof fn === "function") && fn(self);';
  26473. };
  26474. module.exports = function webwackify(fn, fnModuleId) {
  26475. var src;
  26476. if (webpack) {
  26477. src = bundleWithWebpack(fn, fnModuleId);
  26478. } else {
  26479. src = bundleWithBrowserify(fn);
  26480. }
  26481. var blob = new Blob([src], { type: 'text/javascript' });
  26482. var URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
  26483. var workerUrl = URL.createObjectURL(blob);
  26484. var worker = new Worker(workerUrl);
  26485. worker.objectURL = workerUrl;
  26486. return worker;
  26487. };
  26488. /***/ }),
  26489. /* 135 */
  26490. /***/ (function(module, exports) {
  26491. /**
  26492. * @file flash-constants.js
  26493. */
  26494. /**
  26495. * The maximum size in bytes for append operations to the video.js
  26496. * SWF. Calling through to Flash blocks and can be expensive so
  26497. * we chunk data and pass through 4KB at a time, yielding to the
  26498. * browser between chunks. This gives a theoretical maximum rate of
  26499. * 1MB/s into Flash. Any higher and we begin to drop frames and UI
  26500. * responsiveness suffers.
  26501. *
  26502. * @private
  26503. */
  26504. "use strict";
  26505. Object.defineProperty(exports, "__esModule", {
  26506. value: true
  26507. });
  26508. var flashConstants = {
  26509. // times in milliseconds
  26510. TIME_BETWEEN_CHUNKS: 1,
  26511. BYTES_PER_CHUNK: 1024 * 32
  26512. };
  26513. exports["default"] = flashConstants;
  26514. module.exports = exports["default"];
  26515. /***/ }),
  26516. /* 136 */
  26517. /***/ (function(module, exports) {
  26518. /**
  26519. * @file codec-utils.js
  26520. */
  26521. /**
  26522. * Check if a codec string refers to an audio codec.
  26523. *
  26524. * @param {String} codec codec string to check
  26525. * @return {Boolean} if this is an audio codec
  26526. * @private
  26527. */
  26528. 'use strict';
  26529. Object.defineProperty(exports, '__esModule', {
  26530. value: true
  26531. });
  26532. var isAudioCodec = function isAudioCodec(codec) {
  26533. return (/mp4a\.\d+.\d+/i.test(codec)
  26534. );
  26535. };
  26536. /**
  26537. * Check if a codec string refers to a video codec.
  26538. *
  26539. * @param {String} codec codec string to check
  26540. * @return {Boolean} if this is a video codec
  26541. * @private
  26542. */
  26543. var isVideoCodec = function isVideoCodec(codec) {
  26544. return (/avc1\.[\da-f]+/i.test(codec)
  26545. );
  26546. };
  26547. /**
  26548. * Parse a content type header into a type and parameters
  26549. * object
  26550. *
  26551. * @param {String} type the content type header
  26552. * @return {Object} the parsed content-type
  26553. * @private
  26554. */
  26555. var parseContentType = function parseContentType(type) {
  26556. var object = { type: '', parameters: {} };
  26557. var parameters = type.trim().split(';');
  26558. // first parameter should always be content-type
  26559. object.type = parameters.shift().trim();
  26560. parameters.forEach(function (parameter) {
  26561. var pair = parameter.trim().split('=');
  26562. if (pair.length > 1) {
  26563. var _name = pair[0].replace(/"/g, '').trim();
  26564. var value = pair[1].replace(/"/g, '').trim();
  26565. object.parameters[_name] = value;
  26566. }
  26567. });
  26568. return object;
  26569. };
  26570. /**
  26571. * Replace the old apple-style `avc1.<dd>.<dd>` codec string with the standard
  26572. * `avc1.<hhhhhh>`
  26573. *
  26574. * @param {Array} codecs an array of codec strings to fix
  26575. * @return {Array} the translated codec array
  26576. * @private
  26577. */
  26578. var translateLegacyCodecs = function translateLegacyCodecs(codecs) {
  26579. return codecs.map(function (codec) {
  26580. return codec.replace(/avc1\.(\d+)\.(\d+)/i, function (orig, profile, avcLevel) {
  26581. var profileHex = ('00' + Number(profile).toString(16)).slice(-2);
  26582. var avcLevelHex = ('00' + Number(avcLevel).toString(16)).slice(-2);
  26583. return 'avc1.' + profileHex + '00' + avcLevelHex;
  26584. });
  26585. });
  26586. };
  26587. exports['default'] = {
  26588. isAudioCodec: isAudioCodec,
  26589. parseContentType: parseContentType,
  26590. isVideoCodec: isVideoCodec,
  26591. translateLegacyCodecs: translateLegacyCodecs
  26592. };
  26593. module.exports = exports['default'];
  26594. /***/ }),
  26595. /* 137 */
  26596. /***/ (function(module, exports, __webpack_require__) {
  26597. /**
  26598. * @file html-media-source.js
  26599. */
  26600. 'use strict';
  26601. Object.defineProperty(exports, '__esModule', {
  26602. value: true
  26603. });
  26604. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  26605. var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
  26606. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  26607. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
  26608. function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  26609. var _globalWindow = __webpack_require__(2);
  26610. var _globalWindow2 = _interopRequireDefault(_globalWindow);
  26611. var _globalDocument = __webpack_require__(4);
  26612. var _globalDocument2 = _interopRequireDefault(_globalDocument);
  26613. var _videoJs = __webpack_require__(6);
  26614. var _videoJs2 = _interopRequireDefault(_videoJs);
  26615. var _virtualSourceBuffer = __webpack_require__(138);
  26616. var _virtualSourceBuffer2 = _interopRequireDefault(_virtualSourceBuffer);
  26617. var _addTextTrackData = __webpack_require__(132);
  26618. var _codecUtils = __webpack_require__(136);
  26619. /**
  26620. * Our MediaSource implementation in HTML, mimics native
  26621. * MediaSource where/if possible.
  26622. *
  26623. * @link https://developer.mozilla.org/en-US/docs/Web/API/MediaSource
  26624. * @class HtmlMediaSource
  26625. * @extends videojs.EventTarget
  26626. */
  26627. var HtmlMediaSource = (function (_videojs$EventTarget) {
  26628. _inherits(HtmlMediaSource, _videojs$EventTarget);
  26629. function HtmlMediaSource() {
  26630. var _this = this;
  26631. _classCallCheck(this, HtmlMediaSource);
  26632. _get(Object.getPrototypeOf(HtmlMediaSource.prototype), 'constructor', this).call(this);
  26633. var property = undefined;
  26634. this.nativeMediaSource_ = new _globalWindow2['default'].MediaSource();
  26635. // delegate to the native MediaSource's methods by default
  26636. for (property in this.nativeMediaSource_) {
  26637. if (!(property in HtmlMediaSource.prototype) && typeof this.nativeMediaSource_[property] === 'function') {
  26638. this[property] = this.nativeMediaSource_[property].bind(this.nativeMediaSource_);
  26639. }
  26640. }
  26641. // emulate `duration` and `seekable` until seeking can be
  26642. // handled uniformly for live streams
  26643. // see https://github.com/w3c/media-source/issues/5
  26644. this.duration_ = NaN;
  26645. Object.defineProperty(this, 'duration', {
  26646. get: function get() {
  26647. if (this.duration_ === Infinity) {
  26648. return this.duration_;
  26649. }
  26650. return this.nativeMediaSource_.duration;
  26651. },
  26652. set: function set(duration) {
  26653. this.duration_ = duration;
  26654. if (duration !== Infinity) {
  26655. this.nativeMediaSource_.duration = duration;
  26656. return;
  26657. }
  26658. }
  26659. });
  26660. Object.defineProperty(this, 'seekable', {
  26661. get: function get() {
  26662. if (this.duration_ === Infinity) {
  26663. return _videoJs2['default'].createTimeRanges([[0, this.nativeMediaSource_.duration]]);
  26664. }
  26665. return this.nativeMediaSource_.seekable;
  26666. }
  26667. });
  26668. Object.defineProperty(this, 'readyState', {
  26669. get: function get() {
  26670. return this.nativeMediaSource_.readyState;
  26671. }
  26672. });
  26673. Object.defineProperty(this, 'activeSourceBuffers', {
  26674. get: function get() {
  26675. return this.activeSourceBuffers_;
  26676. }
  26677. });
  26678. // the list of virtual and native SourceBuffers created by this
  26679. // MediaSource
  26680. this.sourceBuffers = [];
  26681. this.activeSourceBuffers_ = [];
  26682. /**
  26683. * update the list of active source buffers based upon various
  26684. * imformation from HLS and video.js
  26685. *
  26686. * @private
  26687. */
  26688. this.updateActiveSourceBuffers_ = function () {
  26689. // Retain the reference but empty the array
  26690. _this.activeSourceBuffers_.length = 0;
  26691. // If there is only one source buffer, then it will always be active and audio will
  26692. // be disabled based on the codec of the source buffer
  26693. if (_this.sourceBuffers.length === 1) {
  26694. var sourceBuffer = _this.sourceBuffers[0];
  26695. sourceBuffer.appendAudioInitSegment_ = true;
  26696. sourceBuffer.audioDisabled_ = !sourceBuffer.audioCodec_;
  26697. _this.activeSourceBuffers_.push(sourceBuffer);
  26698. return;
  26699. }
  26700. // There are 2 source buffers, a combined (possibly video only) source buffer and
  26701. // and an audio only source buffer.
  26702. // By default, the audio in the combined virtual source buffer is enabled
  26703. // and the audio-only source buffer (if it exists) is disabled.
  26704. var disableCombined = false;
  26705. var disableAudioOnly = true;
  26706. // TODO: maybe we can store the sourcebuffers on the track objects?
  26707. // safari may do something like this
  26708. for (var i = 0; i < _this.player_.audioTracks().length; i++) {
  26709. var track = _this.player_.audioTracks()[i];
  26710. if (track.enabled && track.kind !== 'main') {
  26711. // The enabled track is an alternate audio track so disable the audio in
  26712. // the combined source buffer and enable the audio-only source buffer.
  26713. disableCombined = true;
  26714. disableAudioOnly = false;
  26715. break;
  26716. }
  26717. }
  26718. _this.sourceBuffers.forEach(function (sourceBuffer) {
  26719. /* eslinst-disable */
  26720. // TODO once codecs are required, we can switch to using the codecs to determine
  26721. // what stream is the video stream, rather than relying on videoTracks
  26722. /* eslinst-enable */
  26723. sourceBuffer.appendAudioInitSegment_ = true;
  26724. if (sourceBuffer.videoCodec_ && sourceBuffer.audioCodec_) {
  26725. // combined
  26726. sourceBuffer.audioDisabled_ = disableCombined;
  26727. } else if (sourceBuffer.videoCodec_ && !sourceBuffer.audioCodec_) {
  26728. // If the "combined" source buffer is video only, then we do not want
  26729. // disable the audio-only source buffer (this is mostly for demuxed
  26730. // audio and video hls)
  26731. sourceBuffer.audioDisabled_ = true;
  26732. disableAudioOnly = false;
  26733. } else if (!sourceBuffer.videoCodec_ && sourceBuffer.audioCodec_) {
  26734. // audio only
  26735. sourceBuffer.audioDisabled_ = disableAudioOnly;
  26736. if (disableAudioOnly) {
  26737. return;
  26738. }
  26739. }
  26740. _this.activeSourceBuffers_.push(sourceBuffer);
  26741. });
  26742. };
  26743. this.onPlayerMediachange_ = function () {
  26744. _this.sourceBuffers.forEach(function (sourceBuffer) {
  26745. sourceBuffer.appendAudioInitSegment_ = true;
  26746. });
  26747. };
  26748. this.onHlsReset_ = function () {
  26749. _this.sourceBuffers.forEach(function (sourceBuffer) {
  26750. if (sourceBuffer.transmuxer_) {
  26751. sourceBuffer.transmuxer_.postMessage({ action: 'resetCaptions' });
  26752. }
  26753. });
  26754. };
  26755. this.onHlsSegmentTimeMapping_ = function (event) {
  26756. _this.sourceBuffers.forEach(function (buffer) {
  26757. return buffer.timeMapping_ = event.mapping;
  26758. });
  26759. };
  26760. // Re-emit MediaSource events on the polyfill
  26761. ['sourceopen', 'sourceclose', 'sourceended'].forEach(function (eventName) {
  26762. this.nativeMediaSource_.addEventListener(eventName, this.trigger.bind(this));
  26763. }, this);
  26764. // capture the associated player when the MediaSource is
  26765. // successfully attached
  26766. this.on('sourceopen', function (event) {
  26767. // Get the player this MediaSource is attached to
  26768. var video = _globalDocument2['default'].querySelector('[src="' + _this.url_ + '"]');
  26769. if (!video) {
  26770. return;
  26771. }
  26772. _this.player_ = (0, _videoJs2['default'])(video.parentNode);
  26773. // hls-reset is fired by videojs.Hls on to the tech after the main SegmentLoader
  26774. // resets its state and flushes the buffer
  26775. _this.player_.tech_.on('hls-reset', _this.onHlsReset_);
  26776. // hls-segment-time-mapping is fired by videojs.Hls on to the tech after the main
  26777. // SegmentLoader inspects an MTS segment and has an accurate stream to display
  26778. // time mapping
  26779. _this.player_.tech_.on('hls-segment-time-mapping', _this.onHlsSegmentTimeMapping_);
  26780. if (_this.player_.audioTracks && _this.player_.audioTracks()) {
  26781. _this.player_.audioTracks().on('change', _this.updateActiveSourceBuffers_);
  26782. _this.player_.audioTracks().on('addtrack', _this.updateActiveSourceBuffers_);
  26783. _this.player_.audioTracks().on('removetrack', _this.updateActiveSourceBuffers_);
  26784. }
  26785. _this.player_.on('mediachange', _this.onPlayerMediachange_);
  26786. });
  26787. this.on('sourceended', function (event) {
  26788. var duration = (0, _addTextTrackData.durationOfVideo)(_this.duration);
  26789. for (var i = 0; i < _this.sourceBuffers.length; i++) {
  26790. var sourcebuffer = _this.sourceBuffers[i];
  26791. var cues = sourcebuffer.metadataTrack_ && sourcebuffer.metadataTrack_.cues;
  26792. if (cues && cues.length) {
  26793. cues[cues.length - 1].endTime = duration;
  26794. }
  26795. }
  26796. });
  26797. // explicitly terminate any WebWorkers that were created
  26798. // by SourceHandlers
  26799. this.on('sourceclose', function (event) {
  26800. this.sourceBuffers.forEach(function (sourceBuffer) {
  26801. if (sourceBuffer.transmuxer_) {
  26802. sourceBuffer.transmuxer_.terminate();
  26803. }
  26804. });
  26805. this.sourceBuffers.length = 0;
  26806. if (!this.player_) {
  26807. return;
  26808. }
  26809. if (this.player_.audioTracks && this.player_.audioTracks()) {
  26810. this.player_.audioTracks().off('change', this.updateActiveSourceBuffers_);
  26811. this.player_.audioTracks().off('addtrack', this.updateActiveSourceBuffers_);
  26812. this.player_.audioTracks().off('removetrack', this.updateActiveSourceBuffers_);
  26813. }
  26814. // We can only change this if the player hasn't been disposed of yet
  26815. // because `off` eventually tries to use the el_ property. If it has
  26816. // been disposed of, then don't worry about it because there are no
  26817. // event handlers left to unbind anyway
  26818. if (this.player_.el_) {
  26819. this.player_.off('mediachange', this.onPlayerMediachange_);
  26820. this.player_.tech_.off('hls-reset', this.onHlsReset_);
  26821. this.player_.tech_.off('hls-segment-time-mapping', this.onHlsSegmentTimeMapping_);
  26822. }
  26823. });
  26824. }
  26825. /**
  26826. * Add a range that that can now be seeked to.
  26827. *
  26828. * @param {Double} start where to start the addition
  26829. * @param {Double} end where to end the addition
  26830. * @private
  26831. */
  26832. _createClass(HtmlMediaSource, [{
  26833. key: 'addSeekableRange_',
  26834. value: function addSeekableRange_(start, end) {
  26835. var error = undefined;
  26836. if (this.duration !== Infinity) {
  26837. error = new Error('MediaSource.addSeekableRange() can only be invoked ' + 'when the duration is Infinity');
  26838. error.name = 'InvalidStateError';
  26839. error.code = 11;
  26840. throw error;
  26841. }
  26842. if (end > this.nativeMediaSource_.duration || isNaN(this.nativeMediaSource_.duration)) {
  26843. this.nativeMediaSource_.duration = end;
  26844. }
  26845. }
  26846. /**
  26847. * Add a source buffer to the media source.
  26848. *
  26849. * @link https://developer.mozilla.org/en-US/docs/Web/API/MediaSource/addSourceBuffer
  26850. * @param {String} type the content-type of the content
  26851. * @return {Object} the created source buffer
  26852. */
  26853. }, {
  26854. key: 'addSourceBuffer',
  26855. value: function addSourceBuffer(type) {
  26856. var buffer = undefined;
  26857. var parsedType = (0, _codecUtils.parseContentType)(type);
  26858. // Create a VirtualSourceBuffer to transmux MPEG-2 transport
  26859. // stream segments into fragmented MP4s
  26860. if (/^(video|audio)\/mp2t$/i.test(parsedType.type)) {
  26861. var codecs = [];
  26862. if (parsedType.parameters && parsedType.parameters.codecs) {
  26863. codecs = parsedType.parameters.codecs.split(',');
  26864. codecs = (0, _codecUtils.translateLegacyCodecs)(codecs);
  26865. codecs = codecs.filter(function (codec) {
  26866. return (0, _codecUtils.isAudioCodec)(codec) || (0, _codecUtils.isVideoCodec)(codec);
  26867. });
  26868. }
  26869. if (codecs.length === 0) {
  26870. codecs = ['avc1.4d400d', 'mp4a.40.2'];
  26871. }
  26872. buffer = new _virtualSourceBuffer2['default'](this, codecs);
  26873. if (this.sourceBuffers.length !== 0) {
  26874. // If another VirtualSourceBuffer already exists, then we are creating a
  26875. // SourceBuffer for an alternate audio track and therefore we know that
  26876. // the source has both an audio and video track.
  26877. // That means we should trigger the manual creation of the real
  26878. // SourceBuffers instead of waiting for the transmuxer to return data
  26879. this.sourceBuffers[0].createRealSourceBuffers_();
  26880. buffer.createRealSourceBuffers_();
  26881. // Automatically disable the audio on the first source buffer if
  26882. // a second source buffer is ever created
  26883. this.sourceBuffers[0].audioDisabled_ = true;
  26884. }
  26885. } else {
  26886. // delegate to the native implementation
  26887. buffer = this.nativeMediaSource_.addSourceBuffer(type);
  26888. }
  26889. this.sourceBuffers.push(buffer);
  26890. return buffer;
  26891. }
  26892. }]);
  26893. return HtmlMediaSource;
  26894. })(_videoJs2['default'].EventTarget);
  26895. exports['default'] = HtmlMediaSource;
  26896. module.exports = exports['default'];
  26897. /***/ }),
  26898. /* 138 */
  26899. /***/ (function(module, exports, __webpack_require__) {
  26900. /**
  26901. * @file virtual-source-buffer.js
  26902. */
  26903. 'use strict';
  26904. Object.defineProperty(exports, '__esModule', {
  26905. value: true
  26906. });
  26907. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  26908. var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
  26909. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  26910. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
  26911. function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  26912. var _videoJs = __webpack_require__(6);
  26913. var _videoJs2 = _interopRequireDefault(_videoJs);
  26914. var _createTextTracksIfNecessary = __webpack_require__(131);
  26915. var _createTextTracksIfNecessary2 = _interopRequireDefault(_createTextTracksIfNecessary);
  26916. var _removeCuesFromTrack = __webpack_require__(130);
  26917. var _removeCuesFromTrack2 = _interopRequireDefault(_removeCuesFromTrack);
  26918. var _addTextTrackData = __webpack_require__(132);
  26919. var _webwackify = __webpack_require__(134);
  26920. var _webwackify2 = _interopRequireDefault(_webwackify);
  26921. var _transmuxerWorker = __webpack_require__(139);
  26922. var _transmuxerWorker2 = _interopRequireDefault(_transmuxerWorker);
  26923. var _codecUtils = __webpack_require__(136);
  26924. var resolveTransmuxWorker = function resolveTransmuxWorker() {
  26925. var result = undefined;
  26926. try {
  26927. result = /*require.resolve*/(139);
  26928. } catch (e) {
  26929. // no result
  26930. }
  26931. return result;
  26932. };
  26933. // We create a wrapper around the SourceBuffer so that we can manage the
  26934. // state of the `updating` property manually. We have to do this because
  26935. // Firefox changes `updating` to false long before triggering `updateend`
  26936. // events and that was causing strange problems in videojs-contrib-hls
  26937. var makeWrappedSourceBuffer = function makeWrappedSourceBuffer(mediaSource, mimeType) {
  26938. var sourceBuffer = mediaSource.addSourceBuffer(mimeType);
  26939. var wrapper = Object.create(null);
  26940. wrapper.updating = false;
  26941. wrapper.realBuffer_ = sourceBuffer;
  26942. var _loop = function (key) {
  26943. if (typeof sourceBuffer[key] === 'function') {
  26944. wrapper[key] = function () {
  26945. return sourceBuffer[key].apply(sourceBuffer, arguments);
  26946. };
  26947. } else if (typeof wrapper[key] === 'undefined') {
  26948. Object.defineProperty(wrapper, key, {
  26949. get: function get() {
  26950. return sourceBuffer[key];
  26951. },
  26952. set: function set(v) {
  26953. return sourceBuffer[key] = v;
  26954. }
  26955. });
  26956. }
  26957. };
  26958. for (var key in sourceBuffer) {
  26959. _loop(key);
  26960. }
  26961. return wrapper;
  26962. };
  26963. /**
  26964. * Returns a list of gops in the buffer that have a pts value of 3 seconds or more in
  26965. * front of current time.
  26966. *
  26967. * @param {Array} buffer
  26968. * The current buffer of gop information
  26969. * @param {Player} player
  26970. * The player instance
  26971. * @param {Double} mapping
  26972. * Offset to map display time to stream presentation time
  26973. * @return {Array}
  26974. * List of gops considered safe to append over
  26975. */
  26976. var gopsSafeToAlignWith = function gopsSafeToAlignWith(buffer, player, mapping) {
  26977. if (!player || !buffer.length) {
  26978. return [];
  26979. }
  26980. // pts value for current time + 3 seconds to give a bit more wiggle room
  26981. var currentTimePts = Math.ceil((player.currentTime() - mapping + 3) * 90000);
  26982. var i = undefined;
  26983. for (i = 0; i < buffer.length; i++) {
  26984. if (buffer[i].pts > currentTimePts) {
  26985. break;
  26986. }
  26987. }
  26988. return buffer.slice(i);
  26989. };
  26990. exports.gopsSafeToAlignWith = gopsSafeToAlignWith;
  26991. /**
  26992. * Appends gop information (timing and byteLength) received by the transmuxer for the
  26993. * gops appended in the last call to appendBuffer
  26994. *
  26995. * @param {Array} buffer
  26996. * The current buffer of gop information
  26997. * @param {Array} gops
  26998. * List of new gop information
  26999. * @param {boolean} replace
  27000. * If true, replace the buffer with the new gop information. If false, append the
  27001. * new gop information to the buffer in the right location of time.
  27002. * @return {Array}
  27003. * Updated list of gop information
  27004. */
  27005. var updateGopBuffer = function updateGopBuffer(buffer, gops, replace) {
  27006. if (!gops.length) {
  27007. return buffer;
  27008. }
  27009. if (replace) {
  27010. // If we are in safe append mode, then completely overwrite the gop buffer
  27011. // with the most recent appeneded data. This will make sure that when appending
  27012. // future segments, we only try to align with gops that are both ahead of current
  27013. // time and in the last segment appended.
  27014. return gops.slice();
  27015. }
  27016. var start = gops[0].pts;
  27017. var i = 0;
  27018. for (i; i < buffer.length; i++) {
  27019. if (buffer[i].pts >= start) {
  27020. break;
  27021. }
  27022. }
  27023. return buffer.slice(0, i).concat(gops);
  27024. };
  27025. exports.updateGopBuffer = updateGopBuffer;
  27026. /**
  27027. * Removes gop information in buffer that overlaps with provided start and end
  27028. *
  27029. * @param {Array} buffer
  27030. * The current buffer of gop information
  27031. * @param {Double} start
  27032. * position to start the remove at
  27033. * @param {Double} end
  27034. * position to end the remove at
  27035. * @param {Double} mapping
  27036. * Offset to map display time to stream presentation time
  27037. */
  27038. var removeGopBuffer = function removeGopBuffer(buffer, start, end, mapping) {
  27039. var startPts = Math.ceil((start - mapping) * 90000);
  27040. var endPts = Math.ceil((end - mapping) * 90000);
  27041. var updatedBuffer = buffer.slice();
  27042. var i = buffer.length;
  27043. while (i--) {
  27044. if (buffer[i].pts <= endPts) {
  27045. break;
  27046. }
  27047. }
  27048. if (i === -1) {
  27049. // no removal because end of remove range is before start of buffer
  27050. return updatedBuffer;
  27051. }
  27052. var j = i + 1;
  27053. while (j--) {
  27054. if (buffer[j].pts <= startPts) {
  27055. break;
  27056. }
  27057. }
  27058. // clamp remove range start to 0 index
  27059. j = Math.max(j, 0);
  27060. updatedBuffer.splice(j, i - j + 1);
  27061. return updatedBuffer;
  27062. };
  27063. exports.removeGopBuffer = removeGopBuffer;
  27064. /**
  27065. * VirtualSourceBuffers exist so that we can transmux non native formats
  27066. * into a native format, but keep the same api as a native source buffer.
  27067. * It creates a transmuxer, that works in its own thread (a web worker) and
  27068. * that transmuxer muxes the data into a native format. VirtualSourceBuffer will
  27069. * then send all of that data to the naive sourcebuffer so that it is
  27070. * indestinguishable from a natively supported format.
  27071. *
  27072. * @param {HtmlMediaSource} mediaSource the parent mediaSource
  27073. * @param {Array} codecs array of codecs that we will be dealing with
  27074. * @class VirtualSourceBuffer
  27075. * @extends video.js.EventTarget
  27076. */
  27077. var VirtualSourceBuffer = (function (_videojs$EventTarget) {
  27078. _inherits(VirtualSourceBuffer, _videojs$EventTarget);
  27079. function VirtualSourceBuffer(mediaSource, codecs) {
  27080. var _this = this;
  27081. _classCallCheck(this, VirtualSourceBuffer);
  27082. _get(Object.getPrototypeOf(VirtualSourceBuffer.prototype), 'constructor', this).call(this, _videoJs2['default'].EventTarget);
  27083. this.timestampOffset_ = 0;
  27084. this.pendingBuffers_ = [];
  27085. this.bufferUpdating_ = false;
  27086. this.mediaSource_ = mediaSource;
  27087. this.codecs_ = codecs;
  27088. this.audioCodec_ = null;
  27089. this.videoCodec_ = null;
  27090. this.audioDisabled_ = false;
  27091. this.appendAudioInitSegment_ = true;
  27092. this.gopBuffer_ = [];
  27093. this.timeMapping_ = 0;
  27094. this.safeAppend_ = _videoJs2['default'].browser.IE_VERSION >= 11;
  27095. var options = {
  27096. remux: false,
  27097. alignGopsAtEnd: this.safeAppend_
  27098. };
  27099. this.codecs_.forEach(function (codec) {
  27100. if ((0, _codecUtils.isAudioCodec)(codec)) {
  27101. _this.audioCodec_ = codec;
  27102. } else if ((0, _codecUtils.isVideoCodec)(codec)) {
  27103. _this.videoCodec_ = codec;
  27104. }
  27105. });
  27106. // append muxed segments to their respective native buffers as
  27107. // soon as they are available
  27108. this.transmuxer_ = (0, _webwackify2['default'])(_transmuxerWorker2['default'], resolveTransmuxWorker());
  27109. this.transmuxer_.postMessage({ action: 'init', options: options });
  27110. this.transmuxer_.onmessage = function (event) {
  27111. if (event.data.action === 'data') {
  27112. return _this.data_(event);
  27113. }
  27114. if (event.data.action === 'done') {
  27115. return _this.done_(event);
  27116. }
  27117. if (event.data.action === 'gopInfo') {
  27118. return _this.appendGopInfo_(event);
  27119. }
  27120. };
  27121. // this timestampOffset is a property with the side-effect of resetting
  27122. // baseMediaDecodeTime in the transmuxer on the setter
  27123. Object.defineProperty(this, 'timestampOffset', {
  27124. get: function get() {
  27125. return this.timestampOffset_;
  27126. },
  27127. set: function set(val) {
  27128. if (typeof val === 'number' && val >= 0) {
  27129. this.timestampOffset_ = val;
  27130. this.appendAudioInitSegment_ = true;
  27131. // reset gop buffer on timestampoffset as this signals a change in timeline
  27132. this.gopBuffer_.length = 0;
  27133. this.timeMapping_ = 0;
  27134. // We have to tell the transmuxer to set the baseMediaDecodeTime to
  27135. // the desired timestampOffset for the next segment
  27136. this.transmuxer_.postMessage({
  27137. action: 'setTimestampOffset',
  27138. timestampOffset: val
  27139. });
  27140. }
  27141. }
  27142. });
  27143. // setting the append window affects both source buffers
  27144. Object.defineProperty(this, 'appendWindowStart', {
  27145. get: function get() {
  27146. return (this.videoBuffer_ || this.audioBuffer_).appendWindowStart;
  27147. },
  27148. set: function set(start) {
  27149. if (this.videoBuffer_) {
  27150. this.videoBuffer_.appendWindowStart = start;
  27151. }
  27152. if (this.audioBuffer_) {
  27153. this.audioBuffer_.appendWindowStart = start;
  27154. }
  27155. }
  27156. });
  27157. // this buffer is "updating" if either of its native buffers are
  27158. Object.defineProperty(this, 'updating', {
  27159. get: function get() {
  27160. return !!(this.bufferUpdating_ || !this.audioDisabled_ && this.audioBuffer_ && this.audioBuffer_.updating || this.videoBuffer_ && this.videoBuffer_.updating);
  27161. }
  27162. });
  27163. // the buffered property is the intersection of the buffered
  27164. // ranges of the native source buffers
  27165. Object.defineProperty(this, 'buffered', {
  27166. get: function get() {
  27167. var start = null;
  27168. var end = null;
  27169. var arity = 0;
  27170. var extents = [];
  27171. var ranges = [];
  27172. // neither buffer has been created yet
  27173. if (!this.videoBuffer_ && !this.audioBuffer_) {
  27174. return _videoJs2['default'].createTimeRange();
  27175. }
  27176. // only one buffer is configured
  27177. if (!this.videoBuffer_) {
  27178. return this.audioBuffer_.buffered;
  27179. }
  27180. if (!this.audioBuffer_) {
  27181. return this.videoBuffer_.buffered;
  27182. }
  27183. // both buffers are configured
  27184. if (this.audioDisabled_) {
  27185. return this.videoBuffer_.buffered;
  27186. }
  27187. // both buffers are empty
  27188. if (this.videoBuffer_.buffered.length === 0 && this.audioBuffer_.buffered.length === 0) {
  27189. return _videoJs2['default'].createTimeRange();
  27190. }
  27191. // Handle the case where we have both buffers and create an
  27192. // intersection of the two
  27193. var videoBuffered = this.videoBuffer_.buffered;
  27194. var audioBuffered = this.audioBuffer_.buffered;
  27195. var count = videoBuffered.length;
  27196. // A) Gather up all start and end times
  27197. while (count--) {
  27198. extents.push({ time: videoBuffered.start(count), type: 'start' });
  27199. extents.push({ time: videoBuffered.end(count), type: 'end' });
  27200. }
  27201. count = audioBuffered.length;
  27202. while (count--) {
  27203. extents.push({ time: audioBuffered.start(count), type: 'start' });
  27204. extents.push({ time: audioBuffered.end(count), type: 'end' });
  27205. }
  27206. // B) Sort them by time
  27207. extents.sort(function (a, b) {
  27208. return a.time - b.time;
  27209. });
  27210. // C) Go along one by one incrementing arity for start and decrementing
  27211. // arity for ends
  27212. for (count = 0; count < extents.length; count++) {
  27213. if (extents[count].type === 'start') {
  27214. arity++;
  27215. // D) If arity is ever incremented to 2 we are entering an
  27216. // overlapping range
  27217. if (arity === 2) {
  27218. start = extents[count].time;
  27219. }
  27220. } else if (extents[count].type === 'end') {
  27221. arity--;
  27222. // E) If arity is ever decremented to 1 we leaving an
  27223. // overlapping range
  27224. if (arity === 1) {
  27225. end = extents[count].time;
  27226. }
  27227. }
  27228. // F) Record overlapping ranges
  27229. if (start !== null && end !== null) {
  27230. ranges.push([start, end]);
  27231. start = null;
  27232. end = null;
  27233. }
  27234. }
  27235. return _videoJs2['default'].createTimeRanges(ranges);
  27236. }
  27237. });
  27238. }
  27239. /**
  27240. * When we get a data event from the transmuxer
  27241. * we call this function and handle the data that
  27242. * was sent to us
  27243. *
  27244. * @private
  27245. * @param {Event} event the data event from the transmuxer
  27246. */
  27247. _createClass(VirtualSourceBuffer, [{
  27248. key: 'data_',
  27249. value: function data_(event) {
  27250. var segment = event.data.segment;
  27251. // Cast ArrayBuffer to TypedArray
  27252. segment.data = new Uint8Array(segment.data, event.data.byteOffset, event.data.byteLength);
  27253. segment.initSegment = new Uint8Array(segment.initSegment.data, segment.initSegment.byteOffset, segment.initSegment.byteLength);
  27254. (0, _createTextTracksIfNecessary2['default'])(this, this.mediaSource_, segment);
  27255. // Add the segments to the pendingBuffers array
  27256. this.pendingBuffers_.push(segment);
  27257. return;
  27258. }
  27259. /**
  27260. * When we get a done event from the transmuxer
  27261. * we call this function and we process all
  27262. * of the pending data that we have been saving in the
  27263. * data_ function
  27264. *
  27265. * @private
  27266. * @param {Event} event the done event from the transmuxer
  27267. */
  27268. }, {
  27269. key: 'done_',
  27270. value: function done_(event) {
  27271. // Don't process and append data if the mediaSource is closed
  27272. if (this.mediaSource_.readyState === 'closed') {
  27273. this.pendingBuffers_.length = 0;
  27274. return;
  27275. }
  27276. // All buffers should have been flushed from the muxer
  27277. // start processing anything we have received
  27278. this.processPendingSegments_();
  27279. return;
  27280. }
  27281. /**
  27282. * Create our internal native audio/video source buffers and add
  27283. * event handlers to them with the following conditions:
  27284. * 1. they do not already exist on the mediaSource
  27285. * 2. this VSB has a codec for them
  27286. *
  27287. * @private
  27288. */
  27289. }, {
  27290. key: 'createRealSourceBuffers_',
  27291. value: function createRealSourceBuffers_() {
  27292. var _this2 = this;
  27293. var types = ['audio', 'video'];
  27294. types.forEach(function (type) {
  27295. // Don't create a SourceBuffer of this type if we don't have a
  27296. // codec for it
  27297. if (!_this2[type + 'Codec_']) {
  27298. return;
  27299. }
  27300. // Do nothing if a SourceBuffer of this type already exists
  27301. if (_this2[type + 'Buffer_']) {
  27302. return;
  27303. }
  27304. var buffer = null;
  27305. // If the mediasource already has a SourceBuffer for the codec
  27306. // use that
  27307. if (_this2.mediaSource_[type + 'Buffer_']) {
  27308. buffer = _this2.mediaSource_[type + 'Buffer_'];
  27309. // In multiple audio track cases, the audio source buffer is disabled
  27310. // on the main VirtualSourceBuffer by the HTMLMediaSource much earlier
  27311. // than createRealSourceBuffers_ is called to create the second
  27312. // VirtualSourceBuffer because that happens as a side-effect of
  27313. // videojs-contrib-hls starting the audioSegmentLoader. As a result,
  27314. // the audioBuffer is essentially "ownerless" and no one will toggle
  27315. // the `updating` state back to false once the `updateend` event is received
  27316. //
  27317. // Setting `updating` to false manually will work around this
  27318. // situation and allow work to continue
  27319. buffer.updating = false;
  27320. } else {
  27321. var codecProperty = type + 'Codec_';
  27322. var mimeType = type + '/mp4;codecs="' + _this2[codecProperty] + '"';
  27323. buffer = makeWrappedSourceBuffer(_this2.mediaSource_.nativeMediaSource_, mimeType);
  27324. _this2.mediaSource_[type + 'Buffer_'] = buffer;
  27325. }
  27326. _this2[type + 'Buffer_'] = buffer;
  27327. // Wire up the events to the SourceBuffer
  27328. ['update', 'updatestart', 'updateend'].forEach(function (event) {
  27329. buffer.addEventListener(event, function () {
  27330. // if audio is disabled
  27331. if (type === 'audio' && _this2.audioDisabled_) {
  27332. return;
  27333. }
  27334. if (event === 'updateend') {
  27335. _this2[type + 'Buffer_'].updating = false;
  27336. }
  27337. var shouldTrigger = types.every(function (t) {
  27338. // skip checking audio's updating status if audio
  27339. // is not enabled
  27340. if (t === 'audio' && _this2.audioDisabled_) {
  27341. return true;
  27342. }
  27343. // if the other type if updating we don't trigger
  27344. if (type !== t && _this2[t + 'Buffer_'] && _this2[t + 'Buffer_'].updating) {
  27345. return false;
  27346. }
  27347. return true;
  27348. });
  27349. if (shouldTrigger) {
  27350. return _this2.trigger(event);
  27351. }
  27352. });
  27353. });
  27354. });
  27355. }
  27356. /**
  27357. * Emulate the native mediasource function, but our function will
  27358. * send all of the proposed segments to the transmuxer so that we
  27359. * can transmux them before we append them to our internal
  27360. * native source buffers in the correct format.
  27361. *
  27362. * @link https://developer.mozilla.org/en-US/docs/Web/API/SourceBuffer/appendBuffer
  27363. * @param {Uint8Array} segment the segment to append to the buffer
  27364. */
  27365. }, {
  27366. key: 'appendBuffer',
  27367. value: function appendBuffer(segment) {
  27368. // Start the internal "updating" state
  27369. this.bufferUpdating_ = true;
  27370. if (this.audioBuffer_ && this.audioBuffer_.buffered.length) {
  27371. var audioBuffered = this.audioBuffer_.buffered;
  27372. this.transmuxer_.postMessage({
  27373. action: 'setAudioAppendStart',
  27374. appendStart: audioBuffered.end(audioBuffered.length - 1)
  27375. });
  27376. }
  27377. if (this.videoBuffer_) {
  27378. this.transmuxer_.postMessage({
  27379. action: 'alignGopsWith',
  27380. gopsToAlignWith: gopsSafeToAlignWith(this.gopBuffer_, this.mediaSource_.player_, this.timeMapping_)
  27381. });
  27382. }
  27383. this.transmuxer_.postMessage({
  27384. action: 'push',
  27385. // Send the typed-array of data as an ArrayBuffer so that
  27386. // it can be sent as a "Transferable" and avoid the costly
  27387. // memory copy
  27388. data: segment.buffer,
  27389. // To recreate the original typed-array, we need information
  27390. // about what portion of the ArrayBuffer it was a view into
  27391. byteOffset: segment.byteOffset,
  27392. byteLength: segment.byteLength
  27393. }, [segment.buffer]);
  27394. this.transmuxer_.postMessage({ action: 'flush' });
  27395. }
  27396. /**
  27397. * Appends gop information (timing and byteLength) received by the transmuxer for the
  27398. * gops appended in the last call to appendBuffer
  27399. *
  27400. * @param {Event} event
  27401. * The gopInfo event from the transmuxer
  27402. * @param {Array} event.data.gopInfo
  27403. * List of gop info to append
  27404. */
  27405. }, {
  27406. key: 'appendGopInfo_',
  27407. value: function appendGopInfo_(event) {
  27408. this.gopBuffer_ = updateGopBuffer(this.gopBuffer_, event.data.gopInfo, this.safeAppend_);
  27409. }
  27410. /**
  27411. * Emulate the native mediasource function and remove parts
  27412. * of the buffer from any of our internal buffers that exist
  27413. *
  27414. * @link https://developer.mozilla.org/en-US/docs/Web/API/SourceBuffer/remove
  27415. * @param {Double} start position to start the remove at
  27416. * @param {Double} end position to end the remove at
  27417. */
  27418. }, {
  27419. key: 'remove',
  27420. value: function remove(start, end) {
  27421. if (this.videoBuffer_) {
  27422. this.videoBuffer_.updating = true;
  27423. this.videoBuffer_.remove(start, end);
  27424. this.gopBuffer_ = removeGopBuffer(this.gopBuffer_, start, end, this.timeMapping_);
  27425. }
  27426. if (!this.audioDisabled_ && this.audioBuffer_) {
  27427. this.audioBuffer_.updating = true;
  27428. this.audioBuffer_.remove(start, end);
  27429. }
  27430. // Remove Metadata Cues (id3)
  27431. (0, _removeCuesFromTrack2['default'])(start, end, this.metadataTrack_);
  27432. // Remove Any Captions
  27433. if (this.inbandTextTracks_) {
  27434. for (var track in this.inbandTextTracks_) {
  27435. (0, _removeCuesFromTrack2['default'])(start, end, this.inbandTextTracks_[track]);
  27436. }
  27437. }
  27438. }
  27439. /**
  27440. * Process any segments that the muxer has output
  27441. * Concatenate segments together based on type and append them into
  27442. * their respective sourceBuffers
  27443. *
  27444. * @private
  27445. */
  27446. }, {
  27447. key: 'processPendingSegments_',
  27448. value: function processPendingSegments_() {
  27449. var sortedSegments = {
  27450. video: {
  27451. segments: [],
  27452. bytes: 0
  27453. },
  27454. audio: {
  27455. segments: [],
  27456. bytes: 0
  27457. },
  27458. captions: [],
  27459. metadata: []
  27460. };
  27461. // Sort segments into separate video/audio arrays and
  27462. // keep track of their total byte lengths
  27463. sortedSegments = this.pendingBuffers_.reduce(function (segmentObj, segment) {
  27464. var type = segment.type;
  27465. var data = segment.data;
  27466. var initSegment = segment.initSegment;
  27467. segmentObj[type].segments.push(data);
  27468. segmentObj[type].bytes += data.byteLength;
  27469. segmentObj[type].initSegment = initSegment;
  27470. // Gather any captions into a single array
  27471. if (segment.captions) {
  27472. segmentObj.captions = segmentObj.captions.concat(segment.captions);
  27473. }
  27474. if (segment.info) {
  27475. segmentObj[type].info = segment.info;
  27476. }
  27477. // Gather any metadata into a single array
  27478. if (segment.metadata) {
  27479. segmentObj.metadata = segmentObj.metadata.concat(segment.metadata);
  27480. }
  27481. return segmentObj;
  27482. }, sortedSegments);
  27483. // Create the real source buffers if they don't exist by now since we
  27484. // finally are sure what tracks are contained in the source
  27485. if (!this.videoBuffer_ && !this.audioBuffer_) {
  27486. // Remove any codecs that may have been specified by default but
  27487. // are no longer applicable now
  27488. if (sortedSegments.video.bytes === 0) {
  27489. this.videoCodec_ = null;
  27490. }
  27491. if (sortedSegments.audio.bytes === 0) {
  27492. this.audioCodec_ = null;
  27493. }
  27494. this.createRealSourceBuffers_();
  27495. }
  27496. if (sortedSegments.audio.info) {
  27497. this.mediaSource_.trigger({ type: 'audioinfo', info: sortedSegments.audio.info });
  27498. }
  27499. if (sortedSegments.video.info) {
  27500. this.mediaSource_.trigger({ type: 'videoinfo', info: sortedSegments.video.info });
  27501. }
  27502. if (this.appendAudioInitSegment_) {
  27503. if (!this.audioDisabled_ && this.audioBuffer_) {
  27504. sortedSegments.audio.segments.unshift(sortedSegments.audio.initSegment);
  27505. sortedSegments.audio.bytes += sortedSegments.audio.initSegment.byteLength;
  27506. }
  27507. this.appendAudioInitSegment_ = false;
  27508. }
  27509. var triggerUpdateend = false;
  27510. // Merge multiple video and audio segments into one and append
  27511. if (this.videoBuffer_ && sortedSegments.video.bytes) {
  27512. sortedSegments.video.segments.unshift(sortedSegments.video.initSegment);
  27513. sortedSegments.video.bytes += sortedSegments.video.initSegment.byteLength;
  27514. this.concatAndAppendSegments_(sortedSegments.video, this.videoBuffer_);
  27515. // TODO: are video tracks the only ones with text tracks?
  27516. (0, _addTextTrackData.addTextTrackData)(this, sortedSegments.captions, sortedSegments.metadata);
  27517. } else if (this.videoBuffer_ && (this.audioDisabled_ || !this.audioBuffer_)) {
  27518. // The transmuxer did not return any bytes of video, meaning it was all trimmed
  27519. // for gop alignment. Since we have a video buffer and audio is disabled, updateend
  27520. // will never be triggered by this source buffer, which will cause contrib-hls
  27521. // to be stuck forever waiting for updateend. If audio is not disabled, updateend
  27522. // will be triggered by the audio buffer, which will be sent upwards since the video
  27523. // buffer will not be in an updating state.
  27524. triggerUpdateend = true;
  27525. }
  27526. if (!this.audioDisabled_ && this.audioBuffer_) {
  27527. this.concatAndAppendSegments_(sortedSegments.audio, this.audioBuffer_);
  27528. }
  27529. this.pendingBuffers_.length = 0;
  27530. if (triggerUpdateend) {
  27531. this.trigger('updateend');
  27532. }
  27533. // We are no longer in the internal "updating" state
  27534. this.bufferUpdating_ = false;
  27535. }
  27536. /**
  27537. * Combine all segments into a single Uint8Array and then append them
  27538. * to the destination buffer
  27539. *
  27540. * @param {Object} segmentObj
  27541. * @param {SourceBuffer} destinationBuffer native source buffer to append data to
  27542. * @private
  27543. */
  27544. }, {
  27545. key: 'concatAndAppendSegments_',
  27546. value: function concatAndAppendSegments_(segmentObj, destinationBuffer) {
  27547. var offset = 0;
  27548. var tempBuffer = undefined;
  27549. if (segmentObj.bytes) {
  27550. tempBuffer = new Uint8Array(segmentObj.bytes);
  27551. // Combine the individual segments into one large typed-array
  27552. segmentObj.segments.forEach(function (segment) {
  27553. tempBuffer.set(segment, offset);
  27554. offset += segment.byteLength;
  27555. });
  27556. try {
  27557. destinationBuffer.updating = true;
  27558. destinationBuffer.appendBuffer(tempBuffer);
  27559. } catch (error) {
  27560. if (this.mediaSource_.player_) {
  27561. this.mediaSource_.player_.error({
  27562. code: -3,
  27563. type: 'APPEND_BUFFER_ERR',
  27564. message: error.message,
  27565. originalError: error
  27566. });
  27567. }
  27568. }
  27569. }
  27570. }
  27571. /**
  27572. * Emulate the native mediasource function. abort any soureBuffer
  27573. * actions and throw out any un-appended data.
  27574. *
  27575. * @link https://developer.mozilla.org/en-US/docs/Web/API/SourceBuffer/abort
  27576. */
  27577. }, {
  27578. key: 'abort',
  27579. value: function abort() {
  27580. if (this.videoBuffer_) {
  27581. this.videoBuffer_.abort();
  27582. }
  27583. if (!this.audioDisabled_ && this.audioBuffer_) {
  27584. this.audioBuffer_.abort();
  27585. }
  27586. if (this.transmuxer_) {
  27587. this.transmuxer_.postMessage({ action: 'reset' });
  27588. }
  27589. this.pendingBuffers_.length = 0;
  27590. this.bufferUpdating_ = false;
  27591. }
  27592. }]);
  27593. return VirtualSourceBuffer;
  27594. })(_videoJs2['default'].EventTarget);
  27595. exports['default'] = VirtualSourceBuffer;
  27596. /***/ }),
  27597. /* 139 */
  27598. /***/ (function(module, exports, __webpack_require__) {
  27599. /**
  27600. * @file transmuxer-worker.js
  27601. */
  27602. /**
  27603. * videojs-contrib-media-sources
  27604. *
  27605. * Copyright (c) 2015 Brightcove
  27606. * All rights reserved.
  27607. *
  27608. * Handles communication between the browser-world and the mux.js
  27609. * transmuxer running inside of a WebWorker by exposing a simple
  27610. * message-based interface to a Transmuxer object.
  27611. */
  27612. 'use strict';
  27613. Object.defineProperty(exports, '__esModule', {
  27614. value: true
  27615. });
  27616. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  27617. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  27618. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
  27619. var _globalWindow = __webpack_require__(2);
  27620. var _globalWindow2 = _interopRequireDefault(_globalWindow);
  27621. var _muxJsLibMp4 = __webpack_require__(140);
  27622. var _muxJsLibMp42 = _interopRequireDefault(_muxJsLibMp4);
  27623. /**
  27624. * Re-emits transmuxer events by converting them into messages to the
  27625. * world outside the worker.
  27626. *
  27627. * @param {Object} transmuxer the transmuxer to wire events on
  27628. * @private
  27629. */
  27630. var wireTransmuxerEvents = function wireTransmuxerEvents(transmuxer) {
  27631. transmuxer.on('data', function (segment) {
  27632. // transfer ownership of the underlying ArrayBuffer
  27633. // instead of doing a copy to save memory
  27634. // ArrayBuffers are transferable but generic TypedArrays are not
  27635. // @link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#Passing_data_by_transferring_ownership_(transferable_objects)
  27636. var initArray = segment.initSegment;
  27637. segment.initSegment = {
  27638. data: initArray.buffer,
  27639. byteOffset: initArray.byteOffset,
  27640. byteLength: initArray.byteLength
  27641. };
  27642. var typedArray = segment.data;
  27643. segment.data = typedArray.buffer;
  27644. _globalWindow2['default'].postMessage({
  27645. action: 'data',
  27646. segment: segment,
  27647. byteOffset: typedArray.byteOffset,
  27648. byteLength: typedArray.byteLength
  27649. }, [segment.data]);
  27650. });
  27651. if (transmuxer.captionStream) {
  27652. transmuxer.captionStream.on('data', function (caption) {
  27653. _globalWindow2['default'].postMessage({
  27654. action: 'caption',
  27655. data: caption
  27656. });
  27657. });
  27658. }
  27659. transmuxer.on('done', function (data) {
  27660. _globalWindow2['default'].postMessage({ action: 'done' });
  27661. });
  27662. transmuxer.on('gopInfo', function (gopInfo) {
  27663. _globalWindow2['default'].postMessage({
  27664. action: 'gopInfo',
  27665. gopInfo: gopInfo
  27666. });
  27667. });
  27668. };
  27669. /**
  27670. * All incoming messages route through this hash. If no function exists
  27671. * to handle an incoming message, then we ignore the message.
  27672. *
  27673. * @class MessageHandlers
  27674. * @param {Object} options the options to initialize with
  27675. */
  27676. var MessageHandlers = (function () {
  27677. function MessageHandlers(options) {
  27678. _classCallCheck(this, MessageHandlers);
  27679. this.options = options || {};
  27680. this.init();
  27681. }
  27682. /**
  27683. * Our web wroker interface so that things can talk to mux.js
  27684. * that will be running in a web worker. the scope is passed to this by
  27685. * webworkify.
  27686. *
  27687. * @param {Object} self the scope for the web worker
  27688. */
  27689. /**
  27690. * initialize our web worker and wire all the events.
  27691. */
  27692. _createClass(MessageHandlers, [{
  27693. key: 'init',
  27694. value: function init() {
  27695. if (this.transmuxer) {
  27696. this.transmuxer.dispose();
  27697. }
  27698. this.transmuxer = new _muxJsLibMp42['default'].Transmuxer(this.options);
  27699. wireTransmuxerEvents(this.transmuxer);
  27700. }
  27701. /**
  27702. * Adds data (a ts segment) to the start of the transmuxer pipeline for
  27703. * processing.
  27704. *
  27705. * @param {ArrayBuffer} data data to push into the muxer
  27706. */
  27707. }, {
  27708. key: 'push',
  27709. value: function push(data) {
  27710. // Cast array buffer to correct type for transmuxer
  27711. var segment = new Uint8Array(data.data, data.byteOffset, data.byteLength);
  27712. this.transmuxer.push(segment);
  27713. }
  27714. /**
  27715. * Recreate the transmuxer so that the next segment added via `push`
  27716. * start with a fresh transmuxer.
  27717. */
  27718. }, {
  27719. key: 'reset',
  27720. value: function reset() {
  27721. this.init();
  27722. }
  27723. /**
  27724. * Set the value that will be used as the `baseMediaDecodeTime` time for the
  27725. * next segment pushed in. Subsequent segments will have their `baseMediaDecodeTime`
  27726. * set relative to the first based on the PTS values.
  27727. *
  27728. * @param {Object} data used to set the timestamp offset in the muxer
  27729. */
  27730. }, {
  27731. key: 'setTimestampOffset',
  27732. value: function setTimestampOffset(data) {
  27733. var timestampOffset = data.timestampOffset || 0;
  27734. this.transmuxer.setBaseMediaDecodeTime(Math.round(timestampOffset * 90000));
  27735. }
  27736. }, {
  27737. key: 'setAudioAppendStart',
  27738. value: function setAudioAppendStart(data) {
  27739. this.transmuxer.setAudioAppendStart(Math.ceil(data.appendStart * 90000));
  27740. }
  27741. /**
  27742. * Forces the pipeline to finish processing the last segment and emit it's
  27743. * results.
  27744. *
  27745. * @param {Object} data event data, not really used
  27746. */
  27747. }, {
  27748. key: 'flush',
  27749. value: function flush(data) {
  27750. this.transmuxer.flush();
  27751. }
  27752. }, {
  27753. key: 'resetCaptions',
  27754. value: function resetCaptions() {
  27755. this.transmuxer.resetCaptions();
  27756. }
  27757. }, {
  27758. key: 'alignGopsWith',
  27759. value: function alignGopsWith(data) {
  27760. this.transmuxer.alignGopsWith(data.gopsToAlignWith.slice());
  27761. }
  27762. }]);
  27763. return MessageHandlers;
  27764. })();
  27765. var TransmuxerWorker = function TransmuxerWorker(self) {
  27766. self.onmessage = function (event) {
  27767. if (event.data.action === 'init' && event.data.options) {
  27768. this.messageHandlers = new MessageHandlers(event.data.options);
  27769. return;
  27770. }
  27771. if (!this.messageHandlers) {
  27772. this.messageHandlers = new MessageHandlers();
  27773. }
  27774. if (event.data && event.data.action && event.data.action !== 'init') {
  27775. if (this.messageHandlers[event.data.action]) {
  27776. this.messageHandlers[event.data.action](event.data);
  27777. }
  27778. }
  27779. };
  27780. };
  27781. exports['default'] = function (self) {
  27782. return new TransmuxerWorker(self);
  27783. };
  27784. module.exports = exports['default'];
  27785. /***/ }),
  27786. /* 140 */
  27787. /***/ (function(module, exports, __webpack_require__) {
  27788. module.exports = {
  27789. generator: __webpack_require__(141),
  27790. Transmuxer: __webpack_require__(142).Transmuxer,
  27791. AudioSegmentStream: __webpack_require__(142).AudioSegmentStream,
  27792. VideoSegmentStream: __webpack_require__(142).VideoSegmentStream
  27793. };
  27794. /***/ }),
  27795. /* 141 */
  27796. /***/ (function(module, exports) {
  27797. /**
  27798. * mux.js
  27799. *
  27800. * Copyright (c) 2015 Brightcove
  27801. * All rights reserved.
  27802. *
  27803. * Functions that generate fragmented MP4s suitable for use with Media
  27804. * Source Extensions.
  27805. */
  27806. 'use strict';
  27807. var UINT32_MAX = Math.pow(2, 32) - 1;
  27808. var box, dinf, esds, ftyp, mdat, mfhd, minf, moof, moov, mvex, mvhd,
  27809. trak, tkhd, mdia, mdhd, hdlr, sdtp, stbl, stsd, traf, trex,
  27810. trun, types, MAJOR_BRAND, MINOR_VERSION, AVC1_BRAND, VIDEO_HDLR,
  27811. AUDIO_HDLR, HDLR_TYPES, VMHD, SMHD, DREF, STCO, STSC, STSZ, STTS;
  27812. // pre-calculate constants
  27813. (function() {
  27814. var i;
  27815. types = {
  27816. avc1: [], // codingname
  27817. avcC: [],
  27818. btrt: [],
  27819. dinf: [],
  27820. dref: [],
  27821. esds: [],
  27822. ftyp: [],
  27823. hdlr: [],
  27824. mdat: [],
  27825. mdhd: [],
  27826. mdia: [],
  27827. mfhd: [],
  27828. minf: [],
  27829. moof: [],
  27830. moov: [],
  27831. mp4a: [], // codingname
  27832. mvex: [],
  27833. mvhd: [],
  27834. sdtp: [],
  27835. smhd: [],
  27836. stbl: [],
  27837. stco: [],
  27838. stsc: [],
  27839. stsd: [],
  27840. stsz: [],
  27841. stts: [],
  27842. styp: [],
  27843. tfdt: [],
  27844. tfhd: [],
  27845. traf: [],
  27846. trak: [],
  27847. trun: [],
  27848. trex: [],
  27849. tkhd: [],
  27850. vmhd: []
  27851. };
  27852. // In environments where Uint8Array is undefined (e.g., IE8), skip set up so that we
  27853. // don't throw an error
  27854. if (typeof Uint8Array === 'undefined') {
  27855. return;
  27856. }
  27857. for (i in types) {
  27858. if (types.hasOwnProperty(i)) {
  27859. types[i] = [
  27860. i.charCodeAt(0),
  27861. i.charCodeAt(1),
  27862. i.charCodeAt(2),
  27863. i.charCodeAt(3)
  27864. ];
  27865. }
  27866. }
  27867. MAJOR_BRAND = new Uint8Array([
  27868. 'i'.charCodeAt(0),
  27869. 's'.charCodeAt(0),
  27870. 'o'.charCodeAt(0),
  27871. 'm'.charCodeAt(0)
  27872. ]);
  27873. AVC1_BRAND = new Uint8Array([
  27874. 'a'.charCodeAt(0),
  27875. 'v'.charCodeAt(0),
  27876. 'c'.charCodeAt(0),
  27877. '1'.charCodeAt(0)
  27878. ]);
  27879. MINOR_VERSION = new Uint8Array([0, 0, 0, 1]);
  27880. VIDEO_HDLR = new Uint8Array([
  27881. 0x00, // version 0
  27882. 0x00, 0x00, 0x00, // flags
  27883. 0x00, 0x00, 0x00, 0x00, // pre_defined
  27884. 0x76, 0x69, 0x64, 0x65, // handler_type: 'vide'
  27885. 0x00, 0x00, 0x00, 0x00, // reserved
  27886. 0x00, 0x00, 0x00, 0x00, // reserved
  27887. 0x00, 0x00, 0x00, 0x00, // reserved
  27888. 0x56, 0x69, 0x64, 0x65,
  27889. 0x6f, 0x48, 0x61, 0x6e,
  27890. 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'VideoHandler'
  27891. ]);
  27892. AUDIO_HDLR = new Uint8Array([
  27893. 0x00, // version 0
  27894. 0x00, 0x00, 0x00, // flags
  27895. 0x00, 0x00, 0x00, 0x00, // pre_defined
  27896. 0x73, 0x6f, 0x75, 0x6e, // handler_type: 'soun'
  27897. 0x00, 0x00, 0x00, 0x00, // reserved
  27898. 0x00, 0x00, 0x00, 0x00, // reserved
  27899. 0x00, 0x00, 0x00, 0x00, // reserved
  27900. 0x53, 0x6f, 0x75, 0x6e,
  27901. 0x64, 0x48, 0x61, 0x6e,
  27902. 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'SoundHandler'
  27903. ]);
  27904. HDLR_TYPES = {
  27905. video: VIDEO_HDLR,
  27906. audio: AUDIO_HDLR
  27907. };
  27908. DREF = new Uint8Array([
  27909. 0x00, // version 0
  27910. 0x00, 0x00, 0x00, // flags
  27911. 0x00, 0x00, 0x00, 0x01, // entry_count
  27912. 0x00, 0x00, 0x00, 0x0c, // entry_size
  27913. 0x75, 0x72, 0x6c, 0x20, // 'url' type
  27914. 0x00, // version 0
  27915. 0x00, 0x00, 0x01 // entry_flags
  27916. ]);
  27917. SMHD = new Uint8Array([
  27918. 0x00, // version
  27919. 0x00, 0x00, 0x00, // flags
  27920. 0x00, 0x00, // balance, 0 means centered
  27921. 0x00, 0x00 // reserved
  27922. ]);
  27923. STCO = new Uint8Array([
  27924. 0x00, // version
  27925. 0x00, 0x00, 0x00, // flags
  27926. 0x00, 0x00, 0x00, 0x00 // entry_count
  27927. ]);
  27928. STSC = STCO;
  27929. STSZ = new Uint8Array([
  27930. 0x00, // version
  27931. 0x00, 0x00, 0x00, // flags
  27932. 0x00, 0x00, 0x00, 0x00, // sample_size
  27933. 0x00, 0x00, 0x00, 0x00 // sample_count
  27934. ]);
  27935. STTS = STCO;
  27936. VMHD = new Uint8Array([
  27937. 0x00, // version
  27938. 0x00, 0x00, 0x01, // flags
  27939. 0x00, 0x00, // graphicsmode
  27940. 0x00, 0x00,
  27941. 0x00, 0x00,
  27942. 0x00, 0x00 // opcolor
  27943. ]);
  27944. }());
  27945. box = function(type) {
  27946. var
  27947. payload = [],
  27948. size = 0,
  27949. i,
  27950. result,
  27951. view;
  27952. for (i = 1; i < arguments.length; i++) {
  27953. payload.push(arguments[i]);
  27954. }
  27955. i = payload.length;
  27956. // calculate the total size we need to allocate
  27957. while (i--) {
  27958. size += payload[i].byteLength;
  27959. }
  27960. result = new Uint8Array(size + 8);
  27961. view = new DataView(result.buffer, result.byteOffset, result.byteLength);
  27962. view.setUint32(0, result.byteLength);
  27963. result.set(type, 4);
  27964. // copy the payload into the result
  27965. for (i = 0, size = 8; i < payload.length; i++) {
  27966. result.set(payload[i], size);
  27967. size += payload[i].byteLength;
  27968. }
  27969. return result;
  27970. };
  27971. dinf = function() {
  27972. return box(types.dinf, box(types.dref, DREF));
  27973. };
  27974. esds = function(track) {
  27975. return box(types.esds, new Uint8Array([
  27976. 0x00, // version
  27977. 0x00, 0x00, 0x00, // flags
  27978. // ES_Descriptor
  27979. 0x03, // tag, ES_DescrTag
  27980. 0x19, // length
  27981. 0x00, 0x00, // ES_ID
  27982. 0x00, // streamDependenceFlag, URL_flag, reserved, streamPriority
  27983. // DecoderConfigDescriptor
  27984. 0x04, // tag, DecoderConfigDescrTag
  27985. 0x11, // length
  27986. 0x40, // object type
  27987. 0x15, // streamType
  27988. 0x00, 0x06, 0x00, // bufferSizeDB
  27989. 0x00, 0x00, 0xda, 0xc0, // maxBitrate
  27990. 0x00, 0x00, 0xda, 0xc0, // avgBitrate
  27991. // DecoderSpecificInfo
  27992. 0x05, // tag, DecoderSpecificInfoTag
  27993. 0x02, // length
  27994. // ISO/IEC 14496-3, AudioSpecificConfig
  27995. // for samplingFrequencyIndex see ISO/IEC 13818-7:2006, 8.1.3.2.2, Table 35
  27996. (track.audioobjecttype << 3) | (track.samplingfrequencyindex >>> 1),
  27997. (track.samplingfrequencyindex << 7) | (track.channelcount << 3),
  27998. 0x06, 0x01, 0x02 // GASpecificConfig
  27999. ]));
  28000. };
  28001. ftyp = function() {
  28002. return box(types.ftyp, MAJOR_BRAND, MINOR_VERSION, MAJOR_BRAND, AVC1_BRAND);
  28003. };
  28004. hdlr = function(type) {
  28005. return box(types.hdlr, HDLR_TYPES[type]);
  28006. };
  28007. mdat = function(data) {
  28008. return box(types.mdat, data);
  28009. };
  28010. mdhd = function(track) {
  28011. var result = new Uint8Array([
  28012. 0x00, // version 0
  28013. 0x00, 0x00, 0x00, // flags
  28014. 0x00, 0x00, 0x00, 0x02, // creation_time
  28015. 0x00, 0x00, 0x00, 0x03, // modification_time
  28016. 0x00, 0x01, 0x5f, 0x90, // timescale, 90,000 "ticks" per second
  28017. (track.duration >>> 24) & 0xFF,
  28018. (track.duration >>> 16) & 0xFF,
  28019. (track.duration >>> 8) & 0xFF,
  28020. track.duration & 0xFF, // duration
  28021. 0x55, 0xc4, // 'und' language (undetermined)
  28022. 0x00, 0x00
  28023. ]);
  28024. // Use the sample rate from the track metadata, when it is
  28025. // defined. The sample rate can be parsed out of an ADTS header, for
  28026. // instance.
  28027. if (track.samplerate) {
  28028. result[12] = (track.samplerate >>> 24) & 0xFF;
  28029. result[13] = (track.samplerate >>> 16) & 0xFF;
  28030. result[14] = (track.samplerate >>> 8) & 0xFF;
  28031. result[15] = (track.samplerate) & 0xFF;
  28032. }
  28033. return box(types.mdhd, result);
  28034. };
  28035. mdia = function(track) {
  28036. return box(types.mdia, mdhd(track), hdlr(track.type), minf(track));
  28037. };
  28038. mfhd = function(sequenceNumber) {
  28039. return box(types.mfhd, new Uint8Array([
  28040. 0x00,
  28041. 0x00, 0x00, 0x00, // flags
  28042. (sequenceNumber & 0xFF000000) >> 24,
  28043. (sequenceNumber & 0xFF0000) >> 16,
  28044. (sequenceNumber & 0xFF00) >> 8,
  28045. sequenceNumber & 0xFF // sequence_number
  28046. ]));
  28047. };
  28048. minf = function(track) {
  28049. return box(types.minf,
  28050. track.type === 'video' ? box(types.vmhd, VMHD) : box(types.smhd, SMHD),
  28051. dinf(),
  28052. stbl(track));
  28053. };
  28054. moof = function(sequenceNumber, tracks) {
  28055. var
  28056. trackFragments = [],
  28057. i = tracks.length;
  28058. // build traf boxes for each track fragment
  28059. while (i--) {
  28060. trackFragments[i] = traf(tracks[i]);
  28061. }
  28062. return box.apply(null, [
  28063. types.moof,
  28064. mfhd(sequenceNumber)
  28065. ].concat(trackFragments));
  28066. };
  28067. /**
  28068. * Returns a movie box.
  28069. * @param tracks {array} the tracks associated with this movie
  28070. * @see ISO/IEC 14496-12:2012(E), section 8.2.1
  28071. */
  28072. moov = function(tracks) {
  28073. var
  28074. i = tracks.length,
  28075. boxes = [];
  28076. while (i--) {
  28077. boxes[i] = trak(tracks[i]);
  28078. }
  28079. return box.apply(null, [types.moov, mvhd(0xffffffff)].concat(boxes).concat(mvex(tracks)));
  28080. };
  28081. mvex = function(tracks) {
  28082. var
  28083. i = tracks.length,
  28084. boxes = [];
  28085. while (i--) {
  28086. boxes[i] = trex(tracks[i]);
  28087. }
  28088. return box.apply(null, [types.mvex].concat(boxes));
  28089. };
  28090. mvhd = function(duration) {
  28091. var
  28092. bytes = new Uint8Array([
  28093. 0x00, // version 0
  28094. 0x00, 0x00, 0x00, // flags
  28095. 0x00, 0x00, 0x00, 0x01, // creation_time
  28096. 0x00, 0x00, 0x00, 0x02, // modification_time
  28097. 0x00, 0x01, 0x5f, 0x90, // timescale, 90,000 "ticks" per second
  28098. (duration & 0xFF000000) >> 24,
  28099. (duration & 0xFF0000) >> 16,
  28100. (duration & 0xFF00) >> 8,
  28101. duration & 0xFF, // duration
  28102. 0x00, 0x01, 0x00, 0x00, // 1.0 rate
  28103. 0x01, 0x00, // 1.0 volume
  28104. 0x00, 0x00, // reserved
  28105. 0x00, 0x00, 0x00, 0x00, // reserved
  28106. 0x00, 0x00, 0x00, 0x00, // reserved
  28107. 0x00, 0x01, 0x00, 0x00,
  28108. 0x00, 0x00, 0x00, 0x00,
  28109. 0x00, 0x00, 0x00, 0x00,
  28110. 0x00, 0x00, 0x00, 0x00,
  28111. 0x00, 0x01, 0x00, 0x00,
  28112. 0x00, 0x00, 0x00, 0x00,
  28113. 0x00, 0x00, 0x00, 0x00,
  28114. 0x00, 0x00, 0x00, 0x00,
  28115. 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix
  28116. 0x00, 0x00, 0x00, 0x00,
  28117. 0x00, 0x00, 0x00, 0x00,
  28118. 0x00, 0x00, 0x00, 0x00,
  28119. 0x00, 0x00, 0x00, 0x00,
  28120. 0x00, 0x00, 0x00, 0x00,
  28121. 0x00, 0x00, 0x00, 0x00, // pre_defined
  28122. 0xff, 0xff, 0xff, 0xff // next_track_ID
  28123. ]);
  28124. return box(types.mvhd, bytes);
  28125. };
  28126. sdtp = function(track) {
  28127. var
  28128. samples = track.samples || [],
  28129. bytes = new Uint8Array(4 + samples.length),
  28130. flags,
  28131. i;
  28132. // leave the full box header (4 bytes) all zero
  28133. // write the sample table
  28134. for (i = 0; i < samples.length; i++) {
  28135. flags = samples[i].flags;
  28136. bytes[i + 4] = (flags.dependsOn << 4) |
  28137. (flags.isDependedOn << 2) |
  28138. (flags.hasRedundancy);
  28139. }
  28140. return box(types.sdtp,
  28141. bytes);
  28142. };
  28143. stbl = function(track) {
  28144. return box(types.stbl,
  28145. stsd(track),
  28146. box(types.stts, STTS),
  28147. box(types.stsc, STSC),
  28148. box(types.stsz, STSZ),
  28149. box(types.stco, STCO));
  28150. };
  28151. (function() {
  28152. var videoSample, audioSample;
  28153. stsd = function(track) {
  28154. return box(types.stsd, new Uint8Array([
  28155. 0x00, // version 0
  28156. 0x00, 0x00, 0x00, // flags
  28157. 0x00, 0x00, 0x00, 0x01
  28158. ]), track.type === 'video' ? videoSample(track) : audioSample(track));
  28159. };
  28160. videoSample = function(track) {
  28161. var
  28162. sps = track.sps || [],
  28163. pps = track.pps || [],
  28164. sequenceParameterSets = [],
  28165. pictureParameterSets = [],
  28166. i;
  28167. // assemble the SPSs
  28168. for (i = 0; i < sps.length; i++) {
  28169. sequenceParameterSets.push((sps[i].byteLength & 0xFF00) >>> 8);
  28170. sequenceParameterSets.push((sps[i].byteLength & 0xFF)); // sequenceParameterSetLength
  28171. sequenceParameterSets = sequenceParameterSets.concat(Array.prototype.slice.call(sps[i])); // SPS
  28172. }
  28173. // assemble the PPSs
  28174. for (i = 0; i < pps.length; i++) {
  28175. pictureParameterSets.push((pps[i].byteLength & 0xFF00) >>> 8);
  28176. pictureParameterSets.push((pps[i].byteLength & 0xFF));
  28177. pictureParameterSets = pictureParameterSets.concat(Array.prototype.slice.call(pps[i]));
  28178. }
  28179. return box(types.avc1, new Uint8Array([
  28180. 0x00, 0x00, 0x00,
  28181. 0x00, 0x00, 0x00, // reserved
  28182. 0x00, 0x01, // data_reference_index
  28183. 0x00, 0x00, // pre_defined
  28184. 0x00, 0x00, // reserved
  28185. 0x00, 0x00, 0x00, 0x00,
  28186. 0x00, 0x00, 0x00, 0x00,
  28187. 0x00, 0x00, 0x00, 0x00, // pre_defined
  28188. (track.width & 0xff00) >> 8,
  28189. track.width & 0xff, // width
  28190. (track.height & 0xff00) >> 8,
  28191. track.height & 0xff, // height
  28192. 0x00, 0x48, 0x00, 0x00, // horizresolution
  28193. 0x00, 0x48, 0x00, 0x00, // vertresolution
  28194. 0x00, 0x00, 0x00, 0x00, // reserved
  28195. 0x00, 0x01, // frame_count
  28196. 0x13,
  28197. 0x76, 0x69, 0x64, 0x65,
  28198. 0x6f, 0x6a, 0x73, 0x2d,
  28199. 0x63, 0x6f, 0x6e, 0x74,
  28200. 0x72, 0x69, 0x62, 0x2d,
  28201. 0x68, 0x6c, 0x73, 0x00,
  28202. 0x00, 0x00, 0x00, 0x00,
  28203. 0x00, 0x00, 0x00, 0x00,
  28204. 0x00, 0x00, 0x00, // compressorname
  28205. 0x00, 0x18, // depth = 24
  28206. 0x11, 0x11 // pre_defined = -1
  28207. ]), box(types.avcC, new Uint8Array([
  28208. 0x01, // configurationVersion
  28209. track.profileIdc, // AVCProfileIndication
  28210. track.profileCompatibility, // profile_compatibility
  28211. track.levelIdc, // AVCLevelIndication
  28212. 0xff // lengthSizeMinusOne, hard-coded to 4 bytes
  28213. ].concat([
  28214. sps.length // numOfSequenceParameterSets
  28215. ]).concat(sequenceParameterSets).concat([
  28216. pps.length // numOfPictureParameterSets
  28217. ]).concat(pictureParameterSets))), // "PPS"
  28218. box(types.btrt, new Uint8Array([
  28219. 0x00, 0x1c, 0x9c, 0x80, // bufferSizeDB
  28220. 0x00, 0x2d, 0xc6, 0xc0, // maxBitrate
  28221. 0x00, 0x2d, 0xc6, 0xc0
  28222. ])) // avgBitrate
  28223. );
  28224. };
  28225. audioSample = function(track) {
  28226. return box(types.mp4a, new Uint8Array([
  28227. // SampleEntry, ISO/IEC 14496-12
  28228. 0x00, 0x00, 0x00,
  28229. 0x00, 0x00, 0x00, // reserved
  28230. 0x00, 0x01, // data_reference_index
  28231. // AudioSampleEntry, ISO/IEC 14496-12
  28232. 0x00, 0x00, 0x00, 0x00, // reserved
  28233. 0x00, 0x00, 0x00, 0x00, // reserved
  28234. (track.channelcount & 0xff00) >> 8,
  28235. (track.channelcount & 0xff), // channelcount
  28236. (track.samplesize & 0xff00) >> 8,
  28237. (track.samplesize & 0xff), // samplesize
  28238. 0x00, 0x00, // pre_defined
  28239. 0x00, 0x00, // reserved
  28240. (track.samplerate & 0xff00) >> 8,
  28241. (track.samplerate & 0xff),
  28242. 0x00, 0x00 // samplerate, 16.16
  28243. // MP4AudioSampleEntry, ISO/IEC 14496-14
  28244. ]), esds(track));
  28245. };
  28246. }());
  28247. tkhd = function(track) {
  28248. var result = new Uint8Array([
  28249. 0x00, // version 0
  28250. 0x00, 0x00, 0x07, // flags
  28251. 0x00, 0x00, 0x00, 0x00, // creation_time
  28252. 0x00, 0x00, 0x00, 0x00, // modification_time
  28253. (track.id & 0xFF000000) >> 24,
  28254. (track.id & 0xFF0000) >> 16,
  28255. (track.id & 0xFF00) >> 8,
  28256. track.id & 0xFF, // track_ID
  28257. 0x00, 0x00, 0x00, 0x00, // reserved
  28258. (track.duration & 0xFF000000) >> 24,
  28259. (track.duration & 0xFF0000) >> 16,
  28260. (track.duration & 0xFF00) >> 8,
  28261. track.duration & 0xFF, // duration
  28262. 0x00, 0x00, 0x00, 0x00,
  28263. 0x00, 0x00, 0x00, 0x00, // reserved
  28264. 0x00, 0x00, // layer
  28265. 0x00, 0x00, // alternate_group
  28266. 0x01, 0x00, // non-audio track volume
  28267. 0x00, 0x00, // reserved
  28268. 0x00, 0x01, 0x00, 0x00,
  28269. 0x00, 0x00, 0x00, 0x00,
  28270. 0x00, 0x00, 0x00, 0x00,
  28271. 0x00, 0x00, 0x00, 0x00,
  28272. 0x00, 0x01, 0x00, 0x00,
  28273. 0x00, 0x00, 0x00, 0x00,
  28274. 0x00, 0x00, 0x00, 0x00,
  28275. 0x00, 0x00, 0x00, 0x00,
  28276. 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix
  28277. (track.width & 0xFF00) >> 8,
  28278. track.width & 0xFF,
  28279. 0x00, 0x00, // width
  28280. (track.height & 0xFF00) >> 8,
  28281. track.height & 0xFF,
  28282. 0x00, 0x00 // height
  28283. ]);
  28284. return box(types.tkhd, result);
  28285. };
  28286. /**
  28287. * Generate a track fragment (traf) box. A traf box collects metadata
  28288. * about tracks in a movie fragment (moof) box.
  28289. */
  28290. traf = function(track) {
  28291. var trackFragmentHeader, trackFragmentDecodeTime, trackFragmentRun,
  28292. sampleDependencyTable, dataOffset,
  28293. upperWordBaseMediaDecodeTime, lowerWordBaseMediaDecodeTime;
  28294. trackFragmentHeader = box(types.tfhd, new Uint8Array([
  28295. 0x00, // version 0
  28296. 0x00, 0x00, 0x3a, // flags
  28297. (track.id & 0xFF000000) >> 24,
  28298. (track.id & 0xFF0000) >> 16,
  28299. (track.id & 0xFF00) >> 8,
  28300. (track.id & 0xFF), // track_ID
  28301. 0x00, 0x00, 0x00, 0x01, // sample_description_index
  28302. 0x00, 0x00, 0x00, 0x00, // default_sample_duration
  28303. 0x00, 0x00, 0x00, 0x00, // default_sample_size
  28304. 0x00, 0x00, 0x00, 0x00 // default_sample_flags
  28305. ]));
  28306. upperWordBaseMediaDecodeTime = Math.floor(track.baseMediaDecodeTime / (UINT32_MAX + 1));
  28307. lowerWordBaseMediaDecodeTime = Math.floor(track.baseMediaDecodeTime % (UINT32_MAX + 1));
  28308. trackFragmentDecodeTime = box(types.tfdt, new Uint8Array([
  28309. 0x01, // version 1
  28310. 0x00, 0x00, 0x00, // flags
  28311. // baseMediaDecodeTime
  28312. (upperWordBaseMediaDecodeTime >>> 24) & 0xFF,
  28313. (upperWordBaseMediaDecodeTime >>> 16) & 0xFF,
  28314. (upperWordBaseMediaDecodeTime >>> 8) & 0xFF,
  28315. upperWordBaseMediaDecodeTime & 0xFF,
  28316. (lowerWordBaseMediaDecodeTime >>> 24) & 0xFF,
  28317. (lowerWordBaseMediaDecodeTime >>> 16) & 0xFF,
  28318. (lowerWordBaseMediaDecodeTime >>> 8) & 0xFF,
  28319. lowerWordBaseMediaDecodeTime & 0xFF
  28320. ]));
  28321. // the data offset specifies the number of bytes from the start of
  28322. // the containing moof to the first payload byte of the associated
  28323. // mdat
  28324. dataOffset = (32 + // tfhd
  28325. 20 + // tfdt
  28326. 8 + // traf header
  28327. 16 + // mfhd
  28328. 8 + // moof header
  28329. 8); // mdat header
  28330. // audio tracks require less metadata
  28331. if (track.type === 'audio') {
  28332. trackFragmentRun = trun(track, dataOffset);
  28333. return box(types.traf,
  28334. trackFragmentHeader,
  28335. trackFragmentDecodeTime,
  28336. trackFragmentRun);
  28337. }
  28338. // video tracks should contain an independent and disposable samples
  28339. // box (sdtp)
  28340. // generate one and adjust offsets to match
  28341. sampleDependencyTable = sdtp(track);
  28342. trackFragmentRun = trun(track,
  28343. sampleDependencyTable.length + dataOffset);
  28344. return box(types.traf,
  28345. trackFragmentHeader,
  28346. trackFragmentDecodeTime,
  28347. trackFragmentRun,
  28348. sampleDependencyTable);
  28349. };
  28350. /**
  28351. * Generate a track box.
  28352. * @param track {object} a track definition
  28353. * @return {Uint8Array} the track box
  28354. */
  28355. trak = function(track) {
  28356. track.duration = track.duration || 0xffffffff;
  28357. return box(types.trak,
  28358. tkhd(track),
  28359. mdia(track));
  28360. };
  28361. trex = function(track) {
  28362. var result = new Uint8Array([
  28363. 0x00, // version 0
  28364. 0x00, 0x00, 0x00, // flags
  28365. (track.id & 0xFF000000) >> 24,
  28366. (track.id & 0xFF0000) >> 16,
  28367. (track.id & 0xFF00) >> 8,
  28368. (track.id & 0xFF), // track_ID
  28369. 0x00, 0x00, 0x00, 0x01, // default_sample_description_index
  28370. 0x00, 0x00, 0x00, 0x00, // default_sample_duration
  28371. 0x00, 0x00, 0x00, 0x00, // default_sample_size
  28372. 0x00, 0x01, 0x00, 0x01 // default_sample_flags
  28373. ]);
  28374. // the last two bytes of default_sample_flags is the sample
  28375. // degradation priority, a hint about the importance of this sample
  28376. // relative to others. Lower the degradation priority for all sample
  28377. // types other than video.
  28378. if (track.type !== 'video') {
  28379. result[result.length - 1] = 0x00;
  28380. }
  28381. return box(types.trex, result);
  28382. };
  28383. (function() {
  28384. var audioTrun, videoTrun, trunHeader;
  28385. // This method assumes all samples are uniform. That is, if a
  28386. // duration is present for the first sample, it will be present for
  28387. // all subsequent samples.
  28388. // see ISO/IEC 14496-12:2012, Section 8.8.8.1
  28389. trunHeader = function(samples, offset) {
  28390. var durationPresent = 0, sizePresent = 0,
  28391. flagsPresent = 0, compositionTimeOffset = 0;
  28392. // trun flag constants
  28393. if (samples.length) {
  28394. if (samples[0].duration !== undefined) {
  28395. durationPresent = 0x1;
  28396. }
  28397. if (samples[0].size !== undefined) {
  28398. sizePresent = 0x2;
  28399. }
  28400. if (samples[0].flags !== undefined) {
  28401. flagsPresent = 0x4;
  28402. }
  28403. if (samples[0].compositionTimeOffset !== undefined) {
  28404. compositionTimeOffset = 0x8;
  28405. }
  28406. }
  28407. return [
  28408. 0x00, // version 0
  28409. 0x00,
  28410. durationPresent | sizePresent | flagsPresent | compositionTimeOffset,
  28411. 0x01, // flags
  28412. (samples.length & 0xFF000000) >>> 24,
  28413. (samples.length & 0xFF0000) >>> 16,
  28414. (samples.length & 0xFF00) >>> 8,
  28415. samples.length & 0xFF, // sample_count
  28416. (offset & 0xFF000000) >>> 24,
  28417. (offset & 0xFF0000) >>> 16,
  28418. (offset & 0xFF00) >>> 8,
  28419. offset & 0xFF // data_offset
  28420. ];
  28421. };
  28422. videoTrun = function(track, offset) {
  28423. var bytes, samples, sample, i;
  28424. samples = track.samples || [];
  28425. offset += 8 + 12 + (16 * samples.length);
  28426. bytes = trunHeader(samples, offset);
  28427. for (i = 0; i < samples.length; i++) {
  28428. sample = samples[i];
  28429. bytes = bytes.concat([
  28430. (sample.duration & 0xFF000000) >>> 24,
  28431. (sample.duration & 0xFF0000) >>> 16,
  28432. (sample.duration & 0xFF00) >>> 8,
  28433. sample.duration & 0xFF, // sample_duration
  28434. (sample.size & 0xFF000000) >>> 24,
  28435. (sample.size & 0xFF0000) >>> 16,
  28436. (sample.size & 0xFF00) >>> 8,
  28437. sample.size & 0xFF, // sample_size
  28438. (sample.flags.isLeading << 2) | sample.flags.dependsOn,
  28439. (sample.flags.isDependedOn << 6) |
  28440. (sample.flags.hasRedundancy << 4) |
  28441. (sample.flags.paddingValue << 1) |
  28442. sample.flags.isNonSyncSample,
  28443. sample.flags.degradationPriority & 0xF0 << 8,
  28444. sample.flags.degradationPriority & 0x0F, // sample_flags
  28445. (sample.compositionTimeOffset & 0xFF000000) >>> 24,
  28446. (sample.compositionTimeOffset & 0xFF0000) >>> 16,
  28447. (sample.compositionTimeOffset & 0xFF00) >>> 8,
  28448. sample.compositionTimeOffset & 0xFF // sample_composition_time_offset
  28449. ]);
  28450. }
  28451. return box(types.trun, new Uint8Array(bytes));
  28452. };
  28453. audioTrun = function(track, offset) {
  28454. var bytes, samples, sample, i;
  28455. samples = track.samples || [];
  28456. offset += 8 + 12 + (8 * samples.length);
  28457. bytes = trunHeader(samples, offset);
  28458. for (i = 0; i < samples.length; i++) {
  28459. sample = samples[i];
  28460. bytes = bytes.concat([
  28461. (sample.duration & 0xFF000000) >>> 24,
  28462. (sample.duration & 0xFF0000) >>> 16,
  28463. (sample.duration & 0xFF00) >>> 8,
  28464. sample.duration & 0xFF, // sample_duration
  28465. (sample.size & 0xFF000000) >>> 24,
  28466. (sample.size & 0xFF0000) >>> 16,
  28467. (sample.size & 0xFF00) >>> 8,
  28468. sample.size & 0xFF]); // sample_size
  28469. }
  28470. return box(types.trun, new Uint8Array(bytes));
  28471. };
  28472. trun = function(track, offset) {
  28473. if (track.type === 'audio') {
  28474. return audioTrun(track, offset);
  28475. }
  28476. return videoTrun(track, offset);
  28477. };
  28478. }());
  28479. module.exports = {
  28480. ftyp: ftyp,
  28481. mdat: mdat,
  28482. moof: moof,
  28483. moov: moov,
  28484. initSegment: function(tracks) {
  28485. var
  28486. fileType = ftyp(),
  28487. movie = moov(tracks),
  28488. result;
  28489. result = new Uint8Array(fileType.byteLength + movie.byteLength);
  28490. result.set(fileType);
  28491. result.set(movie, fileType.byteLength);
  28492. return result;
  28493. }
  28494. };
  28495. /***/ }),
  28496. /* 142 */
  28497. /***/ (function(module, exports, __webpack_require__) {
  28498. /**
  28499. * mux.js
  28500. *
  28501. * Copyright (c) 2015 Brightcove
  28502. * All rights reserved.
  28503. *
  28504. * A stream-based mp2t to mp4 converter. This utility can be used to
  28505. * deliver mp4s to a SourceBuffer on platforms that support native
  28506. * Media Source Extensions.
  28507. */
  28508. 'use strict';
  28509. var Stream = __webpack_require__(118);
  28510. var mp4 = __webpack_require__(141);
  28511. var m2ts = __webpack_require__(119);
  28512. var AdtsStream = __webpack_require__(124);
  28513. var H264Stream = __webpack_require__(125).H264Stream;
  28514. var AacStream = __webpack_require__(143);
  28515. var coneOfSilence = __webpack_require__(144);
  28516. var clock = __webpack_require__(145);
  28517. // constants
  28518. var AUDIO_PROPERTIES = [
  28519. 'audioobjecttype',
  28520. 'channelcount',
  28521. 'samplerate',
  28522. 'samplingfrequencyindex',
  28523. 'samplesize'
  28524. ];
  28525. var VIDEO_PROPERTIES = [
  28526. 'width',
  28527. 'height',
  28528. 'profileIdc',
  28529. 'levelIdc',
  28530. 'profileCompatibility'
  28531. ];
  28532. var ONE_SECOND_IN_TS = 90000; // 90kHz clock
  28533. // object types
  28534. var VideoSegmentStream, AudioSegmentStream, Transmuxer, CoalesceStream;
  28535. // Helper functions
  28536. var
  28537. createDefaultSample,
  28538. isLikelyAacData,
  28539. collectDtsInfo,
  28540. clearDtsInfo,
  28541. calculateTrackBaseMediaDecodeTime,
  28542. arrayEquals,
  28543. sumFrameByteLengths;
  28544. /**
  28545. * Default sample object
  28546. * see ISO/IEC 14496-12:2012, section 8.6.4.3
  28547. */
  28548. createDefaultSample = function() {
  28549. return {
  28550. size: 0,
  28551. flags: {
  28552. isLeading: 0,
  28553. dependsOn: 1,
  28554. isDependedOn: 0,
  28555. hasRedundancy: 0,
  28556. degradationPriority: 0
  28557. }
  28558. };
  28559. };
  28560. isLikelyAacData = function(data) {
  28561. if ((data[0] === 'I'.charCodeAt(0)) &&
  28562. (data[1] === 'D'.charCodeAt(0)) &&
  28563. (data[2] === '3'.charCodeAt(0))) {
  28564. return true;
  28565. }
  28566. return false;
  28567. };
  28568. /**
  28569. * Compare two arrays (even typed) for same-ness
  28570. */
  28571. arrayEquals = function(a, b) {
  28572. var
  28573. i;
  28574. if (a.length !== b.length) {
  28575. return false;
  28576. }
  28577. // compare the value of each element in the array
  28578. for (i = 0; i < a.length; i++) {
  28579. if (a[i] !== b[i]) {
  28580. return false;
  28581. }
  28582. }
  28583. return true;
  28584. };
  28585. /**
  28586. * Sum the `byteLength` properties of the data in each AAC frame
  28587. */
  28588. sumFrameByteLengths = function(array) {
  28589. var
  28590. i,
  28591. currentObj,
  28592. sum = 0;
  28593. // sum the byteLength's all each nal unit in the frame
  28594. for (i = 0; i < array.length; i++) {
  28595. currentObj = array[i];
  28596. sum += currentObj.data.byteLength;
  28597. }
  28598. return sum;
  28599. };
  28600. /**
  28601. * Constructs a single-track, ISO BMFF media segment from AAC data
  28602. * events. The output of this stream can be fed to a SourceBuffer
  28603. * configured with a suitable initialization segment.
  28604. */
  28605. AudioSegmentStream = function(track) {
  28606. var
  28607. adtsFrames = [],
  28608. sequenceNumber = 0,
  28609. earliestAllowedDts = 0,
  28610. audioAppendStartTs = 0,
  28611. videoBaseMediaDecodeTime = Infinity;
  28612. AudioSegmentStream.prototype.init.call(this);
  28613. this.push = function(data) {
  28614. collectDtsInfo(track, data);
  28615. if (track) {
  28616. AUDIO_PROPERTIES.forEach(function(prop) {
  28617. track[prop] = data[prop];
  28618. });
  28619. }
  28620. // buffer audio data until end() is called
  28621. adtsFrames.push(data);
  28622. };
  28623. this.setEarliestDts = function(earliestDts) {
  28624. earliestAllowedDts = earliestDts - track.timelineStartInfo.baseMediaDecodeTime;
  28625. };
  28626. this.setVideoBaseMediaDecodeTime = function(baseMediaDecodeTime) {
  28627. videoBaseMediaDecodeTime = baseMediaDecodeTime;
  28628. };
  28629. this.setAudioAppendStart = function(timestamp) {
  28630. audioAppendStartTs = timestamp;
  28631. };
  28632. this.flush = function() {
  28633. var
  28634. frames,
  28635. moof,
  28636. mdat,
  28637. boxes;
  28638. // return early if no audio data has been observed
  28639. if (adtsFrames.length === 0) {
  28640. this.trigger('done', 'AudioSegmentStream');
  28641. return;
  28642. }
  28643. frames = this.trimAdtsFramesByEarliestDts_(adtsFrames);
  28644. track.baseMediaDecodeTime = calculateTrackBaseMediaDecodeTime(track);
  28645. this.prefixWithSilence_(track, frames);
  28646. // we have to build the index from byte locations to
  28647. // samples (that is, adts frames) in the audio data
  28648. track.samples = this.generateSampleTable_(frames);
  28649. // concatenate the audio data to constuct the mdat
  28650. mdat = mp4.mdat(this.concatenateFrameData_(frames));
  28651. adtsFrames = [];
  28652. moof = mp4.moof(sequenceNumber, [track]);
  28653. boxes = new Uint8Array(moof.byteLength + mdat.byteLength);
  28654. // bump the sequence number for next time
  28655. sequenceNumber++;
  28656. boxes.set(moof);
  28657. boxes.set(mdat, moof.byteLength);
  28658. clearDtsInfo(track);
  28659. this.trigger('data', {track: track, boxes: boxes});
  28660. this.trigger('done', 'AudioSegmentStream');
  28661. };
  28662. // Possibly pad (prefix) the audio track with silence if appending this track
  28663. // would lead to the introduction of a gap in the audio buffer
  28664. this.prefixWithSilence_ = function(track, frames) {
  28665. var
  28666. baseMediaDecodeTimeTs,
  28667. frameDuration = 0,
  28668. audioGapDuration = 0,
  28669. audioFillFrameCount = 0,
  28670. audioFillDuration = 0,
  28671. silentFrame,
  28672. i;
  28673. if (!frames.length) {
  28674. return;
  28675. }
  28676. baseMediaDecodeTimeTs = clock.audioTsToVideoTs(track.baseMediaDecodeTime, track.samplerate);
  28677. // determine frame clock duration based on sample rate, round up to avoid overfills
  28678. frameDuration = Math.ceil(ONE_SECOND_IN_TS / (track.samplerate / 1024));
  28679. if (audioAppendStartTs && videoBaseMediaDecodeTime) {
  28680. // insert the shortest possible amount (audio gap or audio to video gap)
  28681. audioGapDuration =
  28682. baseMediaDecodeTimeTs - Math.max(audioAppendStartTs, videoBaseMediaDecodeTime);
  28683. // number of full frames in the audio gap
  28684. audioFillFrameCount = Math.floor(audioGapDuration / frameDuration);
  28685. audioFillDuration = audioFillFrameCount * frameDuration;
  28686. }
  28687. // don't attempt to fill gaps smaller than a single frame or larger
  28688. // than a half second
  28689. if (audioFillFrameCount < 1 || audioFillDuration > ONE_SECOND_IN_TS / 2) {
  28690. return;
  28691. }
  28692. silentFrame = coneOfSilence[track.samplerate];
  28693. if (!silentFrame) {
  28694. // we don't have a silent frame pregenerated for the sample rate, so use a frame
  28695. // from the content instead
  28696. silentFrame = frames[0].data;
  28697. }
  28698. for (i = 0; i < audioFillFrameCount; i++) {
  28699. frames.splice(i, 0, {
  28700. data: silentFrame
  28701. });
  28702. }
  28703. track.baseMediaDecodeTime -=
  28704. Math.floor(clock.videoTsToAudioTs(audioFillDuration, track.samplerate));
  28705. };
  28706. // If the audio segment extends before the earliest allowed dts
  28707. // value, remove AAC frames until starts at or after the earliest
  28708. // allowed DTS so that we don't end up with a negative baseMedia-
  28709. // DecodeTime for the audio track
  28710. this.trimAdtsFramesByEarliestDts_ = function(adtsFrames) {
  28711. if (track.minSegmentDts >= earliestAllowedDts) {
  28712. return adtsFrames;
  28713. }
  28714. // We will need to recalculate the earliest segment Dts
  28715. track.minSegmentDts = Infinity;
  28716. return adtsFrames.filter(function(currentFrame) {
  28717. // If this is an allowed frame, keep it and record it's Dts
  28718. if (currentFrame.dts >= earliestAllowedDts) {
  28719. track.minSegmentDts = Math.min(track.minSegmentDts, currentFrame.dts);
  28720. track.minSegmentPts = track.minSegmentDts;
  28721. return true;
  28722. }
  28723. // Otherwise, discard it
  28724. return false;
  28725. });
  28726. };
  28727. // generate the track's raw mdat data from an array of frames
  28728. this.generateSampleTable_ = function(frames) {
  28729. var
  28730. i,
  28731. currentFrame,
  28732. samples = [];
  28733. for (i = 0; i < frames.length; i++) {
  28734. currentFrame = frames[i];
  28735. samples.push({
  28736. size: currentFrame.data.byteLength,
  28737. duration: 1024 // For AAC audio, all samples contain 1024 samples
  28738. });
  28739. }
  28740. return samples;
  28741. };
  28742. // generate the track's sample table from an array of frames
  28743. this.concatenateFrameData_ = function(frames) {
  28744. var
  28745. i,
  28746. currentFrame,
  28747. dataOffset = 0,
  28748. data = new Uint8Array(sumFrameByteLengths(frames));
  28749. for (i = 0; i < frames.length; i++) {
  28750. currentFrame = frames[i];
  28751. data.set(currentFrame.data, dataOffset);
  28752. dataOffset += currentFrame.data.byteLength;
  28753. }
  28754. return data;
  28755. };
  28756. };
  28757. AudioSegmentStream.prototype = new Stream();
  28758. /**
  28759. * Constructs a single-track, ISO BMFF media segment from H264 data
  28760. * events. The output of this stream can be fed to a SourceBuffer
  28761. * configured with a suitable initialization segment.
  28762. * @param track {object} track metadata configuration
  28763. * @param options {object} transmuxer options object
  28764. * @param options.alignGopsAtEnd {boolean} If true, start from the end of the
  28765. * gopsToAlignWith list when attempting to align gop pts
  28766. */
  28767. VideoSegmentStream = function(track, options) {
  28768. var
  28769. sequenceNumber = 0,
  28770. nalUnits = [],
  28771. gopsToAlignWith = [],
  28772. config,
  28773. pps;
  28774. options = options || {};
  28775. VideoSegmentStream.prototype.init.call(this);
  28776. delete track.minPTS;
  28777. this.gopCache_ = [];
  28778. this.push = function(nalUnit) {
  28779. collectDtsInfo(track, nalUnit);
  28780. // record the track config
  28781. if (nalUnit.nalUnitType === 'seq_parameter_set_rbsp' && !config) {
  28782. config = nalUnit.config;
  28783. track.sps = [nalUnit.data];
  28784. VIDEO_PROPERTIES.forEach(function(prop) {
  28785. track[prop] = config[prop];
  28786. }, this);
  28787. }
  28788. if (nalUnit.nalUnitType === 'pic_parameter_set_rbsp' &&
  28789. !pps) {
  28790. pps = nalUnit.data;
  28791. track.pps = [nalUnit.data];
  28792. }
  28793. // buffer video until flush() is called
  28794. nalUnits.push(nalUnit);
  28795. };
  28796. this.flush = function() {
  28797. var
  28798. frames,
  28799. gopForFusion,
  28800. gops,
  28801. moof,
  28802. mdat,
  28803. boxes;
  28804. // Throw away nalUnits at the start of the byte stream until
  28805. // we find the first AUD
  28806. while (nalUnits.length) {
  28807. if (nalUnits[0].nalUnitType === 'access_unit_delimiter_rbsp') {
  28808. break;
  28809. }
  28810. nalUnits.shift();
  28811. }
  28812. // Return early if no video data has been observed
  28813. if (nalUnits.length === 0) {
  28814. this.resetStream_();
  28815. this.trigger('done', 'VideoSegmentStream');
  28816. return;
  28817. }
  28818. // Organize the raw nal-units into arrays that represent
  28819. // higher-level constructs such as frames and gops
  28820. // (group-of-pictures)
  28821. frames = this.groupNalsIntoFrames_(nalUnits);
  28822. gops = this.groupFramesIntoGops_(frames);
  28823. // If the first frame of this fragment is not a keyframe we have
  28824. // a problem since MSE (on Chrome) requires a leading keyframe.
  28825. //
  28826. // We have two approaches to repairing this situation:
  28827. // 1) GOP-FUSION:
  28828. // This is where we keep track of the GOPS (group-of-pictures)
  28829. // from previous fragments and attempt to find one that we can
  28830. // prepend to the current fragment in order to create a valid
  28831. // fragment.
  28832. // 2) KEYFRAME-PULLING:
  28833. // Here we search for the first keyframe in the fragment and
  28834. // throw away all the frames between the start of the fragment
  28835. // and that keyframe. We then extend the duration and pull the
  28836. // PTS of the keyframe forward so that it covers the time range
  28837. // of the frames that were disposed of.
  28838. //
  28839. // #1 is far prefereable over #2 which can cause "stuttering" but
  28840. // requires more things to be just right.
  28841. if (!gops[0][0].keyFrame) {
  28842. // Search for a gop for fusion from our gopCache
  28843. gopForFusion = this.getGopForFusion_(nalUnits[0], track);
  28844. if (gopForFusion) {
  28845. gops.unshift(gopForFusion);
  28846. // Adjust Gops' metadata to account for the inclusion of the
  28847. // new gop at the beginning
  28848. gops.byteLength += gopForFusion.byteLength;
  28849. gops.nalCount += gopForFusion.nalCount;
  28850. gops.pts = gopForFusion.pts;
  28851. gops.dts = gopForFusion.dts;
  28852. gops.duration += gopForFusion.duration;
  28853. } else {
  28854. // If we didn't find a candidate gop fall back to keyrame-pulling
  28855. gops = this.extendFirstKeyFrame_(gops);
  28856. }
  28857. }
  28858. // Trim gops to align with gopsToAlignWith
  28859. if (gopsToAlignWith.length) {
  28860. var alignedGops;
  28861. if (options.alignGopsAtEnd) {
  28862. alignedGops = this.alignGopsAtEnd_(gops);
  28863. } else {
  28864. alignedGops = this.alignGopsAtStart_(gops);
  28865. }
  28866. if (!alignedGops) {
  28867. // save all the nals in the last GOP into the gop cache
  28868. this.gopCache_.unshift({
  28869. gop: gops.pop(),
  28870. pps: track.pps,
  28871. sps: track.sps
  28872. });
  28873. // Keep a maximum of 6 GOPs in the cache
  28874. this.gopCache_.length = Math.min(6, this.gopCache_.length);
  28875. // Clear nalUnits
  28876. nalUnits = [];
  28877. // return early no gops can be aligned with desired gopsToAlignWith
  28878. this.resetStream_();
  28879. this.trigger('done', 'VideoSegmentStream');
  28880. return;
  28881. }
  28882. // Some gops were trimmed. clear dts info so minSegmentDts and pts are correct
  28883. // when recalculated before sending off to CoalesceStream
  28884. clearDtsInfo(track);
  28885. gops = alignedGops;
  28886. }
  28887. collectDtsInfo(track, gops);
  28888. // First, we have to build the index from byte locations to
  28889. // samples (that is, frames) in the video data
  28890. track.samples = this.generateSampleTable_(gops);
  28891. // Concatenate the video data and construct the mdat
  28892. mdat = mp4.mdat(this.concatenateNalData_(gops));
  28893. track.baseMediaDecodeTime = calculateTrackBaseMediaDecodeTime(track);
  28894. this.trigger('processedGopsInfo', gops.map(function(gop) {
  28895. return {
  28896. pts: gop.pts,
  28897. dts: gop.dts,
  28898. byteLength: gop.byteLength
  28899. };
  28900. }));
  28901. // save all the nals in the last GOP into the gop cache
  28902. this.gopCache_.unshift({
  28903. gop: gops.pop(),
  28904. pps: track.pps,
  28905. sps: track.sps
  28906. });
  28907. // Keep a maximum of 6 GOPs in the cache
  28908. this.gopCache_.length = Math.min(6, this.gopCache_.length);
  28909. // Clear nalUnits
  28910. nalUnits = [];
  28911. this.trigger('baseMediaDecodeTime', track.baseMediaDecodeTime);
  28912. this.trigger('timelineStartInfo', track.timelineStartInfo);
  28913. moof = mp4.moof(sequenceNumber, [track]);
  28914. // it would be great to allocate this array up front instead of
  28915. // throwing away hundreds of media segment fragments
  28916. boxes = new Uint8Array(moof.byteLength + mdat.byteLength);
  28917. // Bump the sequence number for next time
  28918. sequenceNumber++;
  28919. boxes.set(moof);
  28920. boxes.set(mdat, moof.byteLength);
  28921. this.trigger('data', {track: track, boxes: boxes});
  28922. this.resetStream_();
  28923. // Continue with the flush process now
  28924. this.trigger('done', 'VideoSegmentStream');
  28925. };
  28926. this.resetStream_ = function() {
  28927. clearDtsInfo(track);
  28928. // reset config and pps because they may differ across segments
  28929. // for instance, when we are rendition switching
  28930. config = undefined;
  28931. pps = undefined;
  28932. };
  28933. // Search for a candidate Gop for gop-fusion from the gop cache and
  28934. // return it or return null if no good candidate was found
  28935. this.getGopForFusion_ = function(nalUnit) {
  28936. var
  28937. halfSecond = 45000, // Half-a-second in a 90khz clock
  28938. allowableOverlap = 10000, // About 3 frames @ 30fps
  28939. nearestDistance = Infinity,
  28940. dtsDistance,
  28941. nearestGopObj,
  28942. currentGop,
  28943. currentGopObj,
  28944. i;
  28945. // Search for the GOP nearest to the beginning of this nal unit
  28946. for (i = 0; i < this.gopCache_.length; i++) {
  28947. currentGopObj = this.gopCache_[i];
  28948. currentGop = currentGopObj.gop;
  28949. // Reject Gops with different SPS or PPS
  28950. if (!(track.pps && arrayEquals(track.pps[0], currentGopObj.pps[0])) ||
  28951. !(track.sps && arrayEquals(track.sps[0], currentGopObj.sps[0]))) {
  28952. continue;
  28953. }
  28954. // Reject Gops that would require a negative baseMediaDecodeTime
  28955. if (currentGop.dts < track.timelineStartInfo.dts) {
  28956. continue;
  28957. }
  28958. // The distance between the end of the gop and the start of the nalUnit
  28959. dtsDistance = (nalUnit.dts - currentGop.dts) - currentGop.duration;
  28960. // Only consider GOPS that start before the nal unit and end within
  28961. // a half-second of the nal unit
  28962. if (dtsDistance >= -allowableOverlap &&
  28963. dtsDistance <= halfSecond) {
  28964. // Always use the closest GOP we found if there is more than
  28965. // one candidate
  28966. if (!nearestGopObj ||
  28967. nearestDistance > dtsDistance) {
  28968. nearestGopObj = currentGopObj;
  28969. nearestDistance = dtsDistance;
  28970. }
  28971. }
  28972. }
  28973. if (nearestGopObj) {
  28974. return nearestGopObj.gop;
  28975. }
  28976. return null;
  28977. };
  28978. this.extendFirstKeyFrame_ = function(gops) {
  28979. var currentGop;
  28980. if (!gops[0][0].keyFrame && gops.length > 1) {
  28981. // Remove the first GOP
  28982. currentGop = gops.shift();
  28983. gops.byteLength -= currentGop.byteLength;
  28984. gops.nalCount -= currentGop.nalCount;
  28985. // Extend the first frame of what is now the
  28986. // first gop to cover the time period of the
  28987. // frames we just removed
  28988. gops[0][0].dts = currentGop.dts;
  28989. gops[0][0].pts = currentGop.pts;
  28990. gops[0][0].duration += currentGop.duration;
  28991. }
  28992. return gops;
  28993. };
  28994. // Convert an array of nal units into an array of frames with each frame being
  28995. // composed of the nal units that make up that frame
  28996. // Also keep track of cummulative data about the frame from the nal units such
  28997. // as the frame duration, starting pts, etc.
  28998. this.groupNalsIntoFrames_ = function(nalUnits) {
  28999. var
  29000. i,
  29001. currentNal,
  29002. currentFrame = [],
  29003. frames = [];
  29004. currentFrame.byteLength = 0;
  29005. for (i = 0; i < nalUnits.length; i++) {
  29006. currentNal = nalUnits[i];
  29007. // Split on 'aud'-type nal units
  29008. if (currentNal.nalUnitType === 'access_unit_delimiter_rbsp') {
  29009. // Since the very first nal unit is expected to be an AUD
  29010. // only push to the frames array when currentFrame is not empty
  29011. if (currentFrame.length) {
  29012. currentFrame.duration = currentNal.dts - currentFrame.dts;
  29013. frames.push(currentFrame);
  29014. }
  29015. currentFrame = [currentNal];
  29016. currentFrame.byteLength = currentNal.data.byteLength;
  29017. currentFrame.pts = currentNal.pts;
  29018. currentFrame.dts = currentNal.dts;
  29019. } else {
  29020. // Specifically flag key frames for ease of use later
  29021. if (currentNal.nalUnitType === 'slice_layer_without_partitioning_rbsp_idr') {
  29022. currentFrame.keyFrame = true;
  29023. }
  29024. currentFrame.duration = currentNal.dts - currentFrame.dts;
  29025. currentFrame.byteLength += currentNal.data.byteLength;
  29026. currentFrame.push(currentNal);
  29027. }
  29028. }
  29029. // For the last frame, use the duration of the previous frame if we
  29030. // have nothing better to go on
  29031. if (frames.length &&
  29032. (!currentFrame.duration ||
  29033. currentFrame.duration <= 0)) {
  29034. currentFrame.duration = frames[frames.length - 1].duration;
  29035. }
  29036. // Push the final frame
  29037. frames.push(currentFrame);
  29038. return frames;
  29039. };
  29040. // Convert an array of frames into an array of Gop with each Gop being composed
  29041. // of the frames that make up that Gop
  29042. // Also keep track of cummulative data about the Gop from the frames such as the
  29043. // Gop duration, starting pts, etc.
  29044. this.groupFramesIntoGops_ = function(frames) {
  29045. var
  29046. i,
  29047. currentFrame,
  29048. currentGop = [],
  29049. gops = [];
  29050. // We must pre-set some of the values on the Gop since we
  29051. // keep running totals of these values
  29052. currentGop.byteLength = 0;
  29053. currentGop.nalCount = 0;
  29054. currentGop.duration = 0;
  29055. currentGop.pts = frames[0].pts;
  29056. currentGop.dts = frames[0].dts;
  29057. // store some metadata about all the Gops
  29058. gops.byteLength = 0;
  29059. gops.nalCount = 0;
  29060. gops.duration = 0;
  29061. gops.pts = frames[0].pts;
  29062. gops.dts = frames[0].dts;
  29063. for (i = 0; i < frames.length; i++) {
  29064. currentFrame = frames[i];
  29065. if (currentFrame.keyFrame) {
  29066. // Since the very first frame is expected to be an keyframe
  29067. // only push to the gops array when currentGop is not empty
  29068. if (currentGop.length) {
  29069. gops.push(currentGop);
  29070. gops.byteLength += currentGop.byteLength;
  29071. gops.nalCount += currentGop.nalCount;
  29072. gops.duration += currentGop.duration;
  29073. }
  29074. currentGop = [currentFrame];
  29075. currentGop.nalCount = currentFrame.length;
  29076. currentGop.byteLength = currentFrame.byteLength;
  29077. currentGop.pts = currentFrame.pts;
  29078. currentGop.dts = currentFrame.dts;
  29079. currentGop.duration = currentFrame.duration;
  29080. } else {
  29081. currentGop.duration += currentFrame.duration;
  29082. currentGop.nalCount += currentFrame.length;
  29083. currentGop.byteLength += currentFrame.byteLength;
  29084. currentGop.push(currentFrame);
  29085. }
  29086. }
  29087. if (gops.length && currentGop.duration <= 0) {
  29088. currentGop.duration = gops[gops.length - 1].duration;
  29089. }
  29090. gops.byteLength += currentGop.byteLength;
  29091. gops.nalCount += currentGop.nalCount;
  29092. gops.duration += currentGop.duration;
  29093. // push the final Gop
  29094. gops.push(currentGop);
  29095. return gops;
  29096. };
  29097. // generate the track's sample table from an array of gops
  29098. this.generateSampleTable_ = function(gops, baseDataOffset) {
  29099. var
  29100. h, i,
  29101. sample,
  29102. currentGop,
  29103. currentFrame,
  29104. dataOffset = baseDataOffset || 0,
  29105. samples = [];
  29106. for (h = 0; h < gops.length; h++) {
  29107. currentGop = gops[h];
  29108. for (i = 0; i < currentGop.length; i++) {
  29109. currentFrame = currentGop[i];
  29110. sample = createDefaultSample();
  29111. sample.dataOffset = dataOffset;
  29112. sample.compositionTimeOffset = currentFrame.pts - currentFrame.dts;
  29113. sample.duration = currentFrame.duration;
  29114. sample.size = 4 * currentFrame.length; // Space for nal unit size
  29115. sample.size += currentFrame.byteLength;
  29116. if (currentFrame.keyFrame) {
  29117. sample.flags.dependsOn = 2;
  29118. }
  29119. dataOffset += sample.size;
  29120. samples.push(sample);
  29121. }
  29122. }
  29123. return samples;
  29124. };
  29125. // generate the track's raw mdat data from an array of gops
  29126. this.concatenateNalData_ = function(gops) {
  29127. var
  29128. h, i, j,
  29129. currentGop,
  29130. currentFrame,
  29131. currentNal,
  29132. dataOffset = 0,
  29133. nalsByteLength = gops.byteLength,
  29134. numberOfNals = gops.nalCount,
  29135. totalByteLength = nalsByteLength + 4 * numberOfNals,
  29136. data = new Uint8Array(totalByteLength),
  29137. view = new DataView(data.buffer);
  29138. // For each Gop..
  29139. for (h = 0; h < gops.length; h++) {
  29140. currentGop = gops[h];
  29141. // For each Frame..
  29142. for (i = 0; i < currentGop.length; i++) {
  29143. currentFrame = currentGop[i];
  29144. // For each NAL..
  29145. for (j = 0; j < currentFrame.length; j++) {
  29146. currentNal = currentFrame[j];
  29147. view.setUint32(dataOffset, currentNal.data.byteLength);
  29148. dataOffset += 4;
  29149. data.set(currentNal.data, dataOffset);
  29150. dataOffset += currentNal.data.byteLength;
  29151. }
  29152. }
  29153. }
  29154. return data;
  29155. };
  29156. // trim gop list to the first gop found that has a matching pts with a gop in the list
  29157. // of gopsToAlignWith starting from the START of the list
  29158. this.alignGopsAtStart_ = function(gops) {
  29159. var alignIndex, gopIndex, align, gop, byteLength, nalCount, duration, alignedGops;
  29160. byteLength = gops.byteLength;
  29161. nalCount = gops.nalCount;
  29162. duration = gops.duration;
  29163. alignIndex = gopIndex = 0;
  29164. while (alignIndex < gopsToAlignWith.length && gopIndex < gops.length) {
  29165. align = gopsToAlignWith[alignIndex];
  29166. gop = gops[gopIndex];
  29167. if (align.pts === gop.pts) {
  29168. break;
  29169. }
  29170. if (gop.pts > align.pts) {
  29171. // this current gop starts after the current gop we want to align on, so increment
  29172. // align index
  29173. alignIndex++;
  29174. continue;
  29175. }
  29176. // current gop starts before the current gop we want to align on. so increment gop
  29177. // index
  29178. gopIndex++;
  29179. byteLength -= gop.byteLength;
  29180. nalCount -= gop.nalCount;
  29181. duration -= gop.duration;
  29182. }
  29183. if (gopIndex === 0) {
  29184. // no gops to trim
  29185. return gops;
  29186. }
  29187. if (gopIndex === gops.length) {
  29188. // all gops trimmed, skip appending all gops
  29189. return null;
  29190. }
  29191. alignedGops = gops.slice(gopIndex);
  29192. alignedGops.byteLength = byteLength;
  29193. alignedGops.duration = duration;
  29194. alignedGops.nalCount = nalCount;
  29195. alignedGops.pts = alignedGops[0].pts;
  29196. alignedGops.dts = alignedGops[0].dts;
  29197. return alignedGops;
  29198. };
  29199. // trim gop list to the first gop found that has a matching pts with a gop in the list
  29200. // of gopsToAlignWith starting from the END of the list
  29201. this.alignGopsAtEnd_ = function(gops) {
  29202. var alignIndex, gopIndex, align, gop, alignEndIndex, matchFound;
  29203. alignIndex = gopsToAlignWith.length - 1;
  29204. gopIndex = gops.length - 1;
  29205. alignEndIndex = null;
  29206. matchFound = false;
  29207. while (alignIndex >= 0 && gopIndex >= 0) {
  29208. align = gopsToAlignWith[alignIndex];
  29209. gop = gops[gopIndex];
  29210. if (align.pts === gop.pts) {
  29211. matchFound = true;
  29212. break;
  29213. }
  29214. if (align.pts > gop.pts) {
  29215. alignIndex--;
  29216. continue;
  29217. }
  29218. if (alignIndex === gopsToAlignWith.length - 1) {
  29219. // gop.pts is greater than the last alignment candidate. If no match is found
  29220. // by the end of this loop, we still want to append gops that come after this
  29221. // point
  29222. alignEndIndex = gopIndex;
  29223. }
  29224. gopIndex--;
  29225. }
  29226. if (!matchFound && alignEndIndex === null) {
  29227. return null;
  29228. }
  29229. var trimIndex;
  29230. if (matchFound) {
  29231. trimIndex = gopIndex;
  29232. } else {
  29233. trimIndex = alignEndIndex;
  29234. }
  29235. if (trimIndex === 0) {
  29236. return gops;
  29237. }
  29238. var alignedGops = gops.slice(trimIndex);
  29239. var metadata = alignedGops.reduce(function(total, gop) {
  29240. total.byteLength += gop.byteLength;
  29241. total.duration += gop.duration;
  29242. total.nalCount += gop.nalCount;
  29243. return total;
  29244. }, { byteLength: 0, duration: 0, nalCount: 0 });
  29245. alignedGops.byteLength = metadata.byteLength;
  29246. alignedGops.duration = metadata.duration;
  29247. alignedGops.nalCount = metadata.nalCount;
  29248. alignedGops.pts = alignedGops[0].pts;
  29249. alignedGops.dts = alignedGops[0].dts;
  29250. return alignedGops;
  29251. };
  29252. this.alignGopsWith = function(newGopsToAlignWith) {
  29253. gopsToAlignWith = newGopsToAlignWith;
  29254. };
  29255. };
  29256. VideoSegmentStream.prototype = new Stream();
  29257. /**
  29258. * Store information about the start and end of the track and the
  29259. * duration for each frame/sample we process in order to calculate
  29260. * the baseMediaDecodeTime
  29261. */
  29262. collectDtsInfo = function(track, data) {
  29263. if (typeof data.pts === 'number') {
  29264. if (track.timelineStartInfo.pts === undefined) {
  29265. track.timelineStartInfo.pts = data.pts;
  29266. }
  29267. if (track.minSegmentPts === undefined) {
  29268. track.minSegmentPts = data.pts;
  29269. } else {
  29270. track.minSegmentPts = Math.min(track.minSegmentPts, data.pts);
  29271. }
  29272. if (track.maxSegmentPts === undefined) {
  29273. track.maxSegmentPts = data.pts;
  29274. } else {
  29275. track.maxSegmentPts = Math.max(track.maxSegmentPts, data.pts);
  29276. }
  29277. }
  29278. if (typeof data.dts === 'number') {
  29279. if (track.timelineStartInfo.dts === undefined) {
  29280. track.timelineStartInfo.dts = data.dts;
  29281. }
  29282. if (track.minSegmentDts === undefined) {
  29283. track.minSegmentDts = data.dts;
  29284. } else {
  29285. track.minSegmentDts = Math.min(track.minSegmentDts, data.dts);
  29286. }
  29287. if (track.maxSegmentDts === undefined) {
  29288. track.maxSegmentDts = data.dts;
  29289. } else {
  29290. track.maxSegmentDts = Math.max(track.maxSegmentDts, data.dts);
  29291. }
  29292. }
  29293. };
  29294. /**
  29295. * Clear values used to calculate the baseMediaDecodeTime between
  29296. * tracks
  29297. */
  29298. clearDtsInfo = function(track) {
  29299. delete track.minSegmentDts;
  29300. delete track.maxSegmentDts;
  29301. delete track.minSegmentPts;
  29302. delete track.maxSegmentPts;
  29303. };
  29304. /**
  29305. * Calculate the track's baseMediaDecodeTime based on the earliest
  29306. * DTS the transmuxer has ever seen and the minimum DTS for the
  29307. * current track
  29308. */
  29309. calculateTrackBaseMediaDecodeTime = function(track) {
  29310. var
  29311. baseMediaDecodeTime,
  29312. scale,
  29313. // Calculate the distance, in time, that this segment starts from the start
  29314. // of the timeline (earliest time seen since the transmuxer initialized)
  29315. timeSinceStartOfTimeline = track.minSegmentDts - track.timelineStartInfo.dts;
  29316. // track.timelineStartInfo.baseMediaDecodeTime is the location, in time, where
  29317. // we want the start of the first segment to be placed
  29318. baseMediaDecodeTime = track.timelineStartInfo.baseMediaDecodeTime;
  29319. // Add to that the distance this segment is from the very first
  29320. baseMediaDecodeTime += timeSinceStartOfTimeline;
  29321. // baseMediaDecodeTime must not become negative
  29322. baseMediaDecodeTime = Math.max(0, baseMediaDecodeTime);
  29323. if (track.type === 'audio') {
  29324. // Audio has a different clock equal to the sampling_rate so we need to
  29325. // scale the PTS values into the clock rate of the track
  29326. scale = track.samplerate / ONE_SECOND_IN_TS;
  29327. baseMediaDecodeTime *= scale;
  29328. baseMediaDecodeTime = Math.floor(baseMediaDecodeTime);
  29329. }
  29330. return baseMediaDecodeTime;
  29331. };
  29332. /**
  29333. * A Stream that can combine multiple streams (ie. audio & video)
  29334. * into a single output segment for MSE. Also supports audio-only
  29335. * and video-only streams.
  29336. */
  29337. CoalesceStream = function(options, metadataStream) {
  29338. // Number of Tracks per output segment
  29339. // If greater than 1, we combine multiple
  29340. // tracks into a single segment
  29341. this.numberOfTracks = 0;
  29342. this.metadataStream = metadataStream;
  29343. if (typeof options.remux !== 'undefined') {
  29344. this.remuxTracks = !!options.remux;
  29345. } else {
  29346. this.remuxTracks = true;
  29347. }
  29348. this.pendingTracks = [];
  29349. this.videoTrack = null;
  29350. this.pendingBoxes = [];
  29351. this.pendingCaptions = [];
  29352. this.pendingMetadata = [];
  29353. this.pendingBytes = 0;
  29354. this.emittedTracks = 0;
  29355. CoalesceStream.prototype.init.call(this);
  29356. // Take output from multiple
  29357. this.push = function(output) {
  29358. // buffer incoming captions until the associated video segment
  29359. // finishes
  29360. if (output.text) {
  29361. return this.pendingCaptions.push(output);
  29362. }
  29363. // buffer incoming id3 tags until the final flush
  29364. if (output.frames) {
  29365. return this.pendingMetadata.push(output);
  29366. }
  29367. // Add this track to the list of pending tracks and store
  29368. // important information required for the construction of
  29369. // the final segment
  29370. this.pendingTracks.push(output.track);
  29371. this.pendingBoxes.push(output.boxes);
  29372. this.pendingBytes += output.boxes.byteLength;
  29373. if (output.track.type === 'video') {
  29374. this.videoTrack = output.track;
  29375. }
  29376. if (output.track.type === 'audio') {
  29377. this.audioTrack = output.track;
  29378. }
  29379. };
  29380. };
  29381. CoalesceStream.prototype = new Stream();
  29382. CoalesceStream.prototype.flush = function(flushSource) {
  29383. var
  29384. offset = 0,
  29385. event = {
  29386. captions: [],
  29387. captionStreams: {},
  29388. metadata: [],
  29389. info: {}
  29390. },
  29391. caption,
  29392. id3,
  29393. initSegment,
  29394. timelineStartPts = 0,
  29395. i;
  29396. if (this.pendingTracks.length < this.numberOfTracks) {
  29397. if (flushSource !== 'VideoSegmentStream' &&
  29398. flushSource !== 'AudioSegmentStream') {
  29399. // Return because we haven't received a flush from a data-generating
  29400. // portion of the segment (meaning that we have only recieved meta-data
  29401. // or captions.)
  29402. return;
  29403. } else if (this.remuxTracks) {
  29404. // Return until we have enough tracks from the pipeline to remux (if we
  29405. // are remuxing audio and video into a single MP4)
  29406. return;
  29407. } else if (this.pendingTracks.length === 0) {
  29408. // In the case where we receive a flush without any data having been
  29409. // received we consider it an emitted track for the purposes of coalescing
  29410. // `done` events.
  29411. // We do this for the case where there is an audio and video track in the
  29412. // segment but no audio data. (seen in several playlists with alternate
  29413. // audio tracks and no audio present in the main TS segments.)
  29414. this.emittedTracks++;
  29415. if (this.emittedTracks >= this.numberOfTracks) {
  29416. this.trigger('done');
  29417. this.emittedTracks = 0;
  29418. }
  29419. return;
  29420. }
  29421. }
  29422. if (this.videoTrack) {
  29423. timelineStartPts = this.videoTrack.timelineStartInfo.pts;
  29424. VIDEO_PROPERTIES.forEach(function(prop) {
  29425. event.info[prop] = this.videoTrack[prop];
  29426. }, this);
  29427. } else if (this.audioTrack) {
  29428. timelineStartPts = this.audioTrack.timelineStartInfo.pts;
  29429. AUDIO_PROPERTIES.forEach(function(prop) {
  29430. event.info[prop] = this.audioTrack[prop];
  29431. }, this);
  29432. }
  29433. if (this.pendingTracks.length === 1) {
  29434. event.type = this.pendingTracks[0].type;
  29435. } else {
  29436. event.type = 'combined';
  29437. }
  29438. this.emittedTracks += this.pendingTracks.length;
  29439. initSegment = mp4.initSegment(this.pendingTracks);
  29440. // Create a new typed array to hold the init segment
  29441. event.initSegment = new Uint8Array(initSegment.byteLength);
  29442. // Create an init segment containing a moov
  29443. // and track definitions
  29444. event.initSegment.set(initSegment);
  29445. // Create a new typed array to hold the moof+mdats
  29446. event.data = new Uint8Array(this.pendingBytes);
  29447. // Append each moof+mdat (one per track) together
  29448. for (i = 0; i < this.pendingBoxes.length; i++) {
  29449. event.data.set(this.pendingBoxes[i], offset);
  29450. offset += this.pendingBoxes[i].byteLength;
  29451. }
  29452. // Translate caption PTS times into second offsets into the
  29453. // video timeline for the segment, and add track info
  29454. for (i = 0; i < this.pendingCaptions.length; i++) {
  29455. caption = this.pendingCaptions[i];
  29456. caption.startTime = (caption.startPts - timelineStartPts);
  29457. caption.startTime /= 90e3;
  29458. caption.endTime = (caption.endPts - timelineStartPts);
  29459. caption.endTime /= 90e3;
  29460. event.captionStreams[caption.stream] = true;
  29461. event.captions.push(caption);
  29462. }
  29463. // Translate ID3 frame PTS times into second offsets into the
  29464. // video timeline for the segment
  29465. for (i = 0; i < this.pendingMetadata.length; i++) {
  29466. id3 = this.pendingMetadata[i];
  29467. id3.cueTime = (id3.pts - timelineStartPts);
  29468. id3.cueTime /= 90e3;
  29469. event.metadata.push(id3);
  29470. }
  29471. // We add this to every single emitted segment even though we only need
  29472. // it for the first
  29473. event.metadata.dispatchType = this.metadataStream.dispatchType;
  29474. // Reset stream state
  29475. this.pendingTracks.length = 0;
  29476. this.videoTrack = null;
  29477. this.pendingBoxes.length = 0;
  29478. this.pendingCaptions.length = 0;
  29479. this.pendingBytes = 0;
  29480. this.pendingMetadata.length = 0;
  29481. // Emit the built segment
  29482. this.trigger('data', event);
  29483. // Only emit `done` if all tracks have been flushed and emitted
  29484. if (this.emittedTracks >= this.numberOfTracks) {
  29485. this.trigger('done');
  29486. this.emittedTracks = 0;
  29487. }
  29488. };
  29489. /**
  29490. * A Stream that expects MP2T binary data as input and produces
  29491. * corresponding media segments, suitable for use with Media Source
  29492. * Extension (MSE) implementations that support the ISO BMFF byte
  29493. * stream format, like Chrome.
  29494. */
  29495. Transmuxer = function(options) {
  29496. var
  29497. self = this,
  29498. hasFlushed = true,
  29499. videoTrack,
  29500. audioTrack;
  29501. Transmuxer.prototype.init.call(this);
  29502. options = options || {};
  29503. this.baseMediaDecodeTime = options.baseMediaDecodeTime || 0;
  29504. this.transmuxPipeline_ = {};
  29505. this.setupAacPipeline = function() {
  29506. var pipeline = {};
  29507. this.transmuxPipeline_ = pipeline;
  29508. pipeline.type = 'aac';
  29509. pipeline.metadataStream = new m2ts.MetadataStream();
  29510. // set up the parsing pipeline
  29511. pipeline.aacStream = new AacStream();
  29512. pipeline.audioTimestampRolloverStream = new m2ts.TimestampRolloverStream('audio');
  29513. pipeline.timedMetadataTimestampRolloverStream = new m2ts.TimestampRolloverStream('timed-metadata');
  29514. pipeline.adtsStream = new AdtsStream();
  29515. pipeline.coalesceStream = new CoalesceStream(options, pipeline.metadataStream);
  29516. pipeline.headOfPipeline = pipeline.aacStream;
  29517. pipeline.aacStream
  29518. .pipe(pipeline.audioTimestampRolloverStream)
  29519. .pipe(pipeline.adtsStream);
  29520. pipeline.aacStream
  29521. .pipe(pipeline.timedMetadataTimestampRolloverStream)
  29522. .pipe(pipeline.metadataStream)
  29523. .pipe(pipeline.coalesceStream);
  29524. pipeline.metadataStream.on('timestamp', function(frame) {
  29525. pipeline.aacStream.setTimestamp(frame.timeStamp);
  29526. });
  29527. pipeline.aacStream.on('data', function(data) {
  29528. if (data.type === 'timed-metadata' && !pipeline.audioSegmentStream) {
  29529. audioTrack = audioTrack || {
  29530. timelineStartInfo: {
  29531. baseMediaDecodeTime: self.baseMediaDecodeTime
  29532. },
  29533. codec: 'adts',
  29534. type: 'audio'
  29535. };
  29536. // hook up the audio segment stream to the first track with aac data
  29537. pipeline.coalesceStream.numberOfTracks++;
  29538. pipeline.audioSegmentStream = new AudioSegmentStream(audioTrack);
  29539. // Set up the final part of the audio pipeline
  29540. pipeline.adtsStream
  29541. .pipe(pipeline.audioSegmentStream)
  29542. .pipe(pipeline.coalesceStream);
  29543. }
  29544. });
  29545. // Re-emit any data coming from the coalesce stream to the outside world
  29546. pipeline.coalesceStream.on('data', this.trigger.bind(this, 'data'));
  29547. // Let the consumer know we have finished flushing the entire pipeline
  29548. pipeline.coalesceStream.on('done', this.trigger.bind(this, 'done'));
  29549. };
  29550. this.setupTsPipeline = function() {
  29551. var pipeline = {};
  29552. this.transmuxPipeline_ = pipeline;
  29553. pipeline.type = 'ts';
  29554. pipeline.metadataStream = new m2ts.MetadataStream();
  29555. // set up the parsing pipeline
  29556. pipeline.packetStream = new m2ts.TransportPacketStream();
  29557. pipeline.parseStream = new m2ts.TransportParseStream();
  29558. pipeline.elementaryStream = new m2ts.ElementaryStream();
  29559. pipeline.videoTimestampRolloverStream = new m2ts.TimestampRolloverStream('video');
  29560. pipeline.audioTimestampRolloverStream = new m2ts.TimestampRolloverStream('audio');
  29561. pipeline.timedMetadataTimestampRolloverStream = new m2ts.TimestampRolloverStream('timed-metadata');
  29562. pipeline.adtsStream = new AdtsStream();
  29563. pipeline.h264Stream = new H264Stream();
  29564. pipeline.captionStream = new m2ts.CaptionStream();
  29565. pipeline.coalesceStream = new CoalesceStream(options, pipeline.metadataStream);
  29566. pipeline.headOfPipeline = pipeline.packetStream;
  29567. // disassemble MPEG2-TS packets into elementary streams
  29568. pipeline.packetStream
  29569. .pipe(pipeline.parseStream)
  29570. .pipe(pipeline.elementaryStream);
  29571. // !!THIS ORDER IS IMPORTANT!!
  29572. // demux the streams
  29573. pipeline.elementaryStream
  29574. .pipe(pipeline.videoTimestampRolloverStream)
  29575. .pipe(pipeline.h264Stream);
  29576. pipeline.elementaryStream
  29577. .pipe(pipeline.audioTimestampRolloverStream)
  29578. .pipe(pipeline.adtsStream);
  29579. pipeline.elementaryStream
  29580. .pipe(pipeline.timedMetadataTimestampRolloverStream)
  29581. .pipe(pipeline.metadataStream)
  29582. .pipe(pipeline.coalesceStream);
  29583. // Hook up CEA-608/708 caption stream
  29584. pipeline.h264Stream.pipe(pipeline.captionStream)
  29585. .pipe(pipeline.coalesceStream);
  29586. pipeline.elementaryStream.on('data', function(data) {
  29587. var i;
  29588. if (data.type === 'metadata') {
  29589. i = data.tracks.length;
  29590. // scan the tracks listed in the metadata
  29591. while (i--) {
  29592. if (!videoTrack && data.tracks[i].type === 'video') {
  29593. videoTrack = data.tracks[i];
  29594. videoTrack.timelineStartInfo.baseMediaDecodeTime = self.baseMediaDecodeTime;
  29595. } else if (!audioTrack && data.tracks[i].type === 'audio') {
  29596. audioTrack = data.tracks[i];
  29597. audioTrack.timelineStartInfo.baseMediaDecodeTime = self.baseMediaDecodeTime;
  29598. }
  29599. }
  29600. // hook up the video segment stream to the first track with h264 data
  29601. if (videoTrack && !pipeline.videoSegmentStream) {
  29602. pipeline.coalesceStream.numberOfTracks++;
  29603. pipeline.videoSegmentStream = new VideoSegmentStream(videoTrack, options);
  29604. pipeline.videoSegmentStream.on('timelineStartInfo', function(timelineStartInfo) {
  29605. // When video emits timelineStartInfo data after a flush, we forward that
  29606. // info to the AudioSegmentStream, if it exists, because video timeline
  29607. // data takes precedence.
  29608. if (audioTrack) {
  29609. audioTrack.timelineStartInfo = timelineStartInfo;
  29610. // On the first segment we trim AAC frames that exist before the
  29611. // very earliest DTS we have seen in video because Chrome will
  29612. // interpret any video track with a baseMediaDecodeTime that is
  29613. // non-zero as a gap.
  29614. pipeline.audioSegmentStream.setEarliestDts(timelineStartInfo.dts);
  29615. }
  29616. });
  29617. pipeline.videoSegmentStream.on('processedGopsInfo',
  29618. self.trigger.bind(self, 'gopInfo'));
  29619. pipeline.videoSegmentStream.on('baseMediaDecodeTime', function(baseMediaDecodeTime) {
  29620. if (audioTrack) {
  29621. pipeline.audioSegmentStream.setVideoBaseMediaDecodeTime(baseMediaDecodeTime);
  29622. }
  29623. });
  29624. // Set up the final part of the video pipeline
  29625. pipeline.h264Stream
  29626. .pipe(pipeline.videoSegmentStream)
  29627. .pipe(pipeline.coalesceStream);
  29628. }
  29629. if (audioTrack && !pipeline.audioSegmentStream) {
  29630. // hook up the audio segment stream to the first track with aac data
  29631. pipeline.coalesceStream.numberOfTracks++;
  29632. pipeline.audioSegmentStream = new AudioSegmentStream(audioTrack);
  29633. // Set up the final part of the audio pipeline
  29634. pipeline.adtsStream
  29635. .pipe(pipeline.audioSegmentStream)
  29636. .pipe(pipeline.coalesceStream);
  29637. }
  29638. }
  29639. });
  29640. // Re-emit any data coming from the coalesce stream to the outside world
  29641. pipeline.coalesceStream.on('data', this.trigger.bind(this, 'data'));
  29642. // Let the consumer know we have finished flushing the entire pipeline
  29643. pipeline.coalesceStream.on('done', this.trigger.bind(this, 'done'));
  29644. };
  29645. // hook up the segment streams once track metadata is delivered
  29646. this.setBaseMediaDecodeTime = function(baseMediaDecodeTime) {
  29647. var pipeline = this.transmuxPipeline_;
  29648. this.baseMediaDecodeTime = baseMediaDecodeTime;
  29649. if (audioTrack) {
  29650. audioTrack.timelineStartInfo.dts = undefined;
  29651. audioTrack.timelineStartInfo.pts = undefined;
  29652. clearDtsInfo(audioTrack);
  29653. audioTrack.timelineStartInfo.baseMediaDecodeTime = baseMediaDecodeTime;
  29654. if (pipeline.audioTimestampRolloverStream) {
  29655. pipeline.audioTimestampRolloverStream.discontinuity();
  29656. }
  29657. }
  29658. if (videoTrack) {
  29659. if (pipeline.videoSegmentStream) {
  29660. pipeline.videoSegmentStream.gopCache_ = [];
  29661. pipeline.videoTimestampRolloverStream.discontinuity();
  29662. }
  29663. videoTrack.timelineStartInfo.dts = undefined;
  29664. videoTrack.timelineStartInfo.pts = undefined;
  29665. clearDtsInfo(videoTrack);
  29666. pipeline.captionStream.reset();
  29667. videoTrack.timelineStartInfo.baseMediaDecodeTime = baseMediaDecodeTime;
  29668. }
  29669. if (pipeline.timedMetadataTimestampRolloverStream) {
  29670. pipeline.timedMetadataTimestampRolloverStream.discontinuity();
  29671. }
  29672. };
  29673. this.setAudioAppendStart = function(timestamp) {
  29674. if (audioTrack) {
  29675. this.transmuxPipeline_.audioSegmentStream.setAudioAppendStart(timestamp);
  29676. }
  29677. };
  29678. this.alignGopsWith = function(gopsToAlignWith) {
  29679. if (videoTrack && this.transmuxPipeline_.videoSegmentStream) {
  29680. this.transmuxPipeline_.videoSegmentStream.alignGopsWith(gopsToAlignWith);
  29681. }
  29682. };
  29683. // feed incoming data to the front of the parsing pipeline
  29684. this.push = function(data) {
  29685. if (hasFlushed) {
  29686. var isAac = isLikelyAacData(data);
  29687. if (isAac && this.transmuxPipeline_.type !== 'aac') {
  29688. this.setupAacPipeline();
  29689. } else if (!isAac && this.transmuxPipeline_.type !== 'ts') {
  29690. this.setupTsPipeline();
  29691. }
  29692. hasFlushed = false;
  29693. }
  29694. this.transmuxPipeline_.headOfPipeline.push(data);
  29695. };
  29696. // flush any buffered data
  29697. this.flush = function() {
  29698. hasFlushed = true;
  29699. // Start at the top of the pipeline and flush all pending work
  29700. this.transmuxPipeline_.headOfPipeline.flush();
  29701. };
  29702. // Caption data has to be reset when seeking outside buffered range
  29703. this.resetCaptions = function() {
  29704. if (this.transmuxPipeline_.captionStream) {
  29705. this.transmuxPipeline_.captionStream.reset();
  29706. }
  29707. };
  29708. };
  29709. Transmuxer.prototype = new Stream();
  29710. module.exports = {
  29711. Transmuxer: Transmuxer,
  29712. VideoSegmentStream: VideoSegmentStream,
  29713. AudioSegmentStream: AudioSegmentStream,
  29714. AUDIO_PROPERTIES: AUDIO_PROPERTIES,
  29715. VIDEO_PROPERTIES: VIDEO_PROPERTIES
  29716. };
  29717. /***/ }),
  29718. /* 143 */
  29719. /***/ (function(module, exports, __webpack_require__) {
  29720. /**
  29721. * mux.js
  29722. *
  29723. * Copyright (c) 2016 Brightcove
  29724. * All rights reserved.
  29725. *
  29726. * A stream-based aac to mp4 converter. This utility can be used to
  29727. * deliver mp4s to a SourceBuffer on platforms that support native
  29728. * Media Source Extensions.
  29729. */
  29730. 'use strict';
  29731. var Stream = __webpack_require__(118);
  29732. // Constants
  29733. var AacStream;
  29734. /**
  29735. * Splits an incoming stream of binary data into ADTS and ID3 Frames.
  29736. */
  29737. AacStream = function() {
  29738. var
  29739. everything = new Uint8Array(),
  29740. timeStamp = 0;
  29741. AacStream.prototype.init.call(this);
  29742. this.setTimestamp = function(timestamp) {
  29743. timeStamp = timestamp;
  29744. };
  29745. this.parseId3TagSize = function(header, byteIndex) {
  29746. var
  29747. returnSize = (header[byteIndex + 6] << 21) |
  29748. (header[byteIndex + 7] << 14) |
  29749. (header[byteIndex + 8] << 7) |
  29750. (header[byteIndex + 9]),
  29751. flags = header[byteIndex + 5],
  29752. footerPresent = (flags & 16) >> 4;
  29753. if (footerPresent) {
  29754. return returnSize + 20;
  29755. }
  29756. return returnSize + 10;
  29757. };
  29758. this.parseAdtsSize = function(header, byteIndex) {
  29759. var
  29760. lowThree = (header[byteIndex + 5] & 0xE0) >> 5,
  29761. middle = header[byteIndex + 4] << 3,
  29762. highTwo = header[byteIndex + 3] & 0x3 << 11;
  29763. return (highTwo | middle) | lowThree;
  29764. };
  29765. this.push = function(bytes) {
  29766. var
  29767. frameSize = 0,
  29768. byteIndex = 0,
  29769. bytesLeft,
  29770. chunk,
  29771. packet,
  29772. tempLength;
  29773. // If there are bytes remaining from the last segment, prepend them to the
  29774. // bytes that were pushed in
  29775. if (everything.length) {
  29776. tempLength = everything.length;
  29777. everything = new Uint8Array(bytes.byteLength + tempLength);
  29778. everything.set(everything.subarray(0, tempLength));
  29779. everything.set(bytes, tempLength);
  29780. } else {
  29781. everything = bytes;
  29782. }
  29783. while (everything.length - byteIndex >= 3) {
  29784. if ((everything[byteIndex] === 'I'.charCodeAt(0)) &&
  29785. (everything[byteIndex + 1] === 'D'.charCodeAt(0)) &&
  29786. (everything[byteIndex + 2] === '3'.charCodeAt(0))) {
  29787. // Exit early because we don't have enough to parse
  29788. // the ID3 tag header
  29789. if (everything.length - byteIndex < 10) {
  29790. break;
  29791. }
  29792. // check framesize
  29793. frameSize = this.parseId3TagSize(everything, byteIndex);
  29794. // Exit early if we don't have enough in the buffer
  29795. // to emit a full packet
  29796. if (frameSize > everything.length) {
  29797. break;
  29798. }
  29799. chunk = {
  29800. type: 'timed-metadata',
  29801. data: everything.subarray(byteIndex, byteIndex + frameSize)
  29802. };
  29803. this.trigger('data', chunk);
  29804. byteIndex += frameSize;
  29805. continue;
  29806. } else if ((everything[byteIndex] & 0xff === 0xff) &&
  29807. ((everything[byteIndex + 1] & 0xf0) === 0xf0)) {
  29808. // Exit early because we don't have enough to parse
  29809. // the ADTS frame header
  29810. if (everything.length - byteIndex < 7) {
  29811. break;
  29812. }
  29813. frameSize = this.parseAdtsSize(everything, byteIndex);
  29814. // Exit early if we don't have enough in the buffer
  29815. // to emit a full packet
  29816. if (frameSize > everything.length) {
  29817. break;
  29818. }
  29819. packet = {
  29820. type: 'audio',
  29821. data: everything.subarray(byteIndex, byteIndex + frameSize),
  29822. pts: timeStamp,
  29823. dts: timeStamp
  29824. };
  29825. this.trigger('data', packet);
  29826. byteIndex += frameSize;
  29827. continue;
  29828. }
  29829. byteIndex++;
  29830. }
  29831. bytesLeft = everything.length - byteIndex;
  29832. if (bytesLeft > 0) {
  29833. everything = everything.subarray(byteIndex);
  29834. } else {
  29835. everything = new Uint8Array();
  29836. }
  29837. };
  29838. };
  29839. AacStream.prototype = new Stream();
  29840. module.exports = AacStream;
  29841. /***/ }),
  29842. /* 144 */
  29843. /***/ (function(module, exports) {
  29844. var highPrefix = [33, 16, 5, 32, 164, 27];
  29845. var lowPrefix = [33, 65, 108, 84, 1, 2, 4, 8, 168, 2, 4, 8, 17, 191, 252];
  29846. var zeroFill = function(count) {
  29847. var a = [];
  29848. while (count--) {
  29849. a.push(0);
  29850. }
  29851. return a;
  29852. };
  29853. var makeTable = function(metaTable) {
  29854. return Object.keys(metaTable).reduce(function(obj, key) {
  29855. obj[key] = new Uint8Array(metaTable[key].reduce(function(arr, part) {
  29856. return arr.concat(part);
  29857. }, []));
  29858. return obj;
  29859. }, {});
  29860. };
  29861. // Frames-of-silence to use for filling in missing AAC frames
  29862. var coneOfSilence = {
  29863. 96000: [highPrefix, [227, 64], zeroFill(154), [56]],
  29864. 88200: [highPrefix, [231], zeroFill(170), [56]],
  29865. 64000: [highPrefix, [248, 192], zeroFill(240), [56]],
  29866. 48000: [highPrefix, [255, 192], zeroFill(268), [55, 148, 128], zeroFill(54), [112]],
  29867. 44100: [highPrefix, [255, 192], zeroFill(268), [55, 163, 128], zeroFill(84), [112]],
  29868. 32000: [highPrefix, [255, 192], zeroFill(268), [55, 234], zeroFill(226), [112]],
  29869. 24000: [highPrefix, [255, 192], zeroFill(268), [55, 255, 128], zeroFill(268), [111, 112], zeroFill(126), [224]],
  29870. 16000: [highPrefix, [255, 192], zeroFill(268), [55, 255, 128], zeroFill(268), [111, 255], zeroFill(269), [223, 108], zeroFill(195), [1, 192]],
  29871. 12000: [lowPrefix, zeroFill(268), [3, 127, 248], zeroFill(268), [6, 255, 240], zeroFill(268), [13, 255, 224], zeroFill(268), [27, 253, 128], zeroFill(259), [56]],
  29872. 11025: [lowPrefix, zeroFill(268), [3, 127, 248], zeroFill(268), [6, 255, 240], zeroFill(268), [13, 255, 224], zeroFill(268), [27, 255, 192], zeroFill(268), [55, 175, 128], zeroFill(108), [112]],
  29873. 8000: [lowPrefix, zeroFill(268), [3, 121, 16], zeroFill(47), [7]]
  29874. };
  29875. module.exports = makeTable(coneOfSilence);
  29876. /***/ }),
  29877. /* 145 */
  29878. /***/ (function(module, exports) {
  29879. var
  29880. ONE_SECOND_IN_TS = 90000, // 90kHz clock
  29881. secondsToVideoTs,
  29882. secondsToAudioTs,
  29883. videoTsToSeconds,
  29884. audioTsToSeconds,
  29885. audioTsToVideoTs,
  29886. videoTsToAudioTs;
  29887. secondsToVideoTs = function(seconds) {
  29888. return seconds * ONE_SECOND_IN_TS;
  29889. };
  29890. secondsToAudioTs = function(seconds, sampleRate) {
  29891. return seconds * sampleRate;
  29892. };
  29893. videoTsToSeconds = function(timestamp) {
  29894. return timestamp / ONE_SECOND_IN_TS;
  29895. };
  29896. audioTsToSeconds = function(timestamp, sampleRate) {
  29897. return timestamp / sampleRate;
  29898. };
  29899. audioTsToVideoTs = function(timestamp, sampleRate) {
  29900. return secondsToVideoTs(audioTsToSeconds(timestamp, sampleRate));
  29901. };
  29902. videoTsToAudioTs = function(timestamp, sampleRate) {
  29903. return secondsToAudioTs(videoTsToSeconds(timestamp), sampleRate);
  29904. };
  29905. module.exports = {
  29906. secondsToVideoTs: secondsToVideoTs,
  29907. secondsToAudioTs: secondsToAudioTs,
  29908. videoTsToSeconds: videoTsToSeconds,
  29909. audioTsToSeconds: audioTsToSeconds,
  29910. audioTsToVideoTs: audioTsToVideoTs,
  29911. videoTsToAudioTs: videoTsToAudioTs
  29912. };
  29913. /***/ })
  29914. /******/ ]);