/* Ċ Ġ* Ġ***************************************************************** ******* Ċ Ġ* Ġ ĠVideo Stats Delegate . kt Ċ Ġ* Ġ************************************************************************* Ċ Ġ* ĠCopyright ĠÂ© Ġ 2 0 2 0 ĠV LC Ġauthors Ġand ĠVideo LAN Ċ Ġ* ĠAuthor : ĠN icol as ĠPO ME PU Y Ċ Ġ* ĠThis Ġprogram Ġis Ġfree Ġsoftware ; Ġyou Ġcan Ġredistribute Ġit Ġand / or Ġmodify Ċ Ġ* Ġit Ġunder Ġthe Ġterms Ġof Ġthe ĠGNU ĠGeneral ĠPublic ĠLicense Ġas Ġpublished Ġby Ċ Ġ* Ġthe ĠFree ĠSoftware ĠFoundation ; Ġeither Ġversion Ġ 2 Ġof Ġthe ĠLicense , Ġor Ċ Ġ* Ġ( at Ġyour Ġoption ) Ġany Ġlater Ġversion . Ċ Ġ* Ċ Ġ* ĠThis Ġprogram Ġis Ġdistributed Ġin Ġthe Ġhope Ġthat Ġit Ġwill Ġbe Ġuseful , Ċ Ġ* Ġbut ĠWITHOUT ĠANY ĠWARRANTY ; Ġwithout Ġeven Ġthe Ġimplied Ġwarranty Ġof Ċ Ġ* ĠMERCHANTABILITY Ġor ĠFITNESS ĠFOR ĠA ĠPARTICULAR ĠPURPOSE . Ġ ĠSee Ġthe Ċ Ġ* ĠGNU ĠGeneral ĠPublic ĠLicense Ġfor Ġmore Ġdetails . Ċ Ġ* Ċ Ġ* ĠYou Ġshould Ġhave Ġreceived Ġa Ġcopy Ġof Ġthe ĠGNU ĠGeneral ĠPublic ĠLicense Ċ Ġ* Ġalong Ġwith Ġthis Ġprogram ; Ġif Ġnot , Ġwrite Ġto Ġthe ĠFree ĠSoftware Ċ Ġ* ĠFoundation , ĠInc ., Ġ 5 1 ĠFranklin ĠStreet , ĠFifth ĠFloor , ĠBoston ĠMA Ġ 0 2 1 1 0 - 1 3 0 1 , ĠUSA . Ċ Ġ* Ġ************************************************************************* * Ċ Ġ* Ċ Ġ* Ċ Ġ*/ Ċ Ċ package Ġorg . vide ol an . v lc . gui . video Ċ Ċ import Ġandroid . annotation . Suppress Lint Ċ import Ġandroid . net . Uri Ċ import Ġandroid . os . Handler Ċ import Ġandroid . util . Log Ċ import Ġandroid . view . Motion Event Ċ import Ġandroid . view . View Ċ import Ġandroid . widget . GridLayout Ċ import Ġandroid . widget . LinearLayout Ċ import Ġandroid . widget . TextView Ċ import Ġandroidx . constraint layout . widget . Constraint Layout Ċ import Ġandroidx . constraint layout . widget . Constraint Set Ċ import Ġandroidx . core . content . Context Compat Ċ import Ġandroidx . core . widget . Nested ScrollView Ċ import Ġkotlinx . coroutines . Experimental Cor outines Api Ċ import Ġkotlinx . coroutines . Obsolete Cor outines Api Ċ import Ġorg . vide ol an . lib v lc . Media Ċ import Ġorg . vide ol an . lib v lc . interfaces . IM edia Ċ import Ġorg . vide ol an . live plot graph . Line Graph Ċ import Ġorg . vide ol an . tools . dp Ċ import Ġorg . vide ol an . tools . readable Size Ċ import Ġorg . vide ol an . v lc . Build Config Ċ import Ġorg . vide ol an . v lc . R Ċ import Ġorg . vide ol an . v lc . databinding . Player Hud Binding Ċ import Ġorg . vide ol an . v lc . util . get Screen Width Ċ import Ġjava . lang . Double Ċ Ċ @ Experimental Cor outines Api Ċ @ Obsolete Cor outines Api Ċ class ĠVideo Stats Delegate ( private Ġval Ġplayer : ĠVideo Player Activity , Ġval Ġscrolling : Ġ() Ġ-> ĠUnit , Ġval Ġidle : Ġ() Ġ-> ĠUnit ) Ġ{ ĊĠĠĠ Ġlateinit Ġvar Ġcontainer : ĠConstraint Layout ĊĠĠĠ Ġprivate Ġvar Ġstarted Ġ= Ġfalse ĊĠĠĠ Ġprivate Ġval Ġplot Handler : ĠHandler Ġ= ĠHandler () ĊĠĠĠ Ġprivate Ġval Ġfirst Time code Ġ= ĠSystem . currentTimeMillis () ĊĠĠĠ Ġlateinit Ġvar Ġbinding : ĠPlayer Hud Binding ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġconstraint Set : ĠConstraint Set ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġconstraint Set Large : ĠConstraint Set ĊĊĠĠĠ Ġfun Ġstop () Ġ{ ĊĠĠĠĠĠĠĠ Ġstarted Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġplot Handler . remove Callbacks ( run nable ) ĊĠĠĠĠĠĠĠ Ġcontainer . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠ Ġbinding . plot View . clear () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġstart () Ġ{ ĊĠĠĠĠĠĠĠ Ġstarted Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġplot Handler . post Delayed ( run nable , Ġ 3 0 0 ) ĊĠĠĠĠĠĠĠ Ġcontainer . visibility Ġ= ĠView . VISIBLE ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġinit Plot View ( binding : ĠPlayer Hud Binding ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . binding Ġ= Ġbinding ĊĠĠĠĠĠĠĠ Ġif Ġ(! :: constraint Set . isInitialized ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconstraint Set Ġ= ĠConstraint Set () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconstraint Set Large Ġ= ĠConstraint Set () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconstraint Set . clone ( binding . stats Scroll view Content ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconstraint Set Large . clone ( binding . stats Scroll view Content ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconstraint Set Large . connect ( R . id . stats _ graphs , ĠConstraint Set . TOP , ĠConstraint Set . PARENT _ ID , ĠConstraint Set . TOP ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconstraint Set Large . clear ( R . id . info _ grids , ĠConstraint Set . END ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconstraint Set Large . connect ( R . id . info _ grids , ĠConstraint Set . END , ĠR . id . stats _ graphs , ĠConstraint Set . START ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconstraint Set Large . connect ( R . id . stats _ graphs , ĠConstraint Set . START , ĠR . id . info _ grids , ĠConstraint Set . END ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġbinding . stats Scroll view . scroll State ({ Ġidle () Ġ}, Ġ{ Ġscrolling () Ġ}) ĊĠĠĠĠĠĠĠ Ġbinding . plot View . add Line ( Line Graph ( Stat Index . DE MUX _ BIT RATE . ordinal , Ġplayer . getString ( R . string . dem ux _ bit rate ), ĠContext Compat . getColor ( player , ĠR . color . material _ blue ))) ĊĠĠĠĠĠĠĠ Ġbinding . plot View . add Line ( Line Graph ( Stat Index . INPUT _ BIT RATE . ordinal , Ġplayer . getString ( R . string . input _ bit rate ), ĠContext Compat . getColor ( player , ĠR . color . material _ pink ))) ĊĠĠĠĠĠĠĠ Ġsetup Layout () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġvar Ġlast Media Uri : Uri ?= Ġnull ĊĊĠĠĠ Ġ@ Suppress Lint (" SetText I 1 8 n ") ĊĠĠĠ Ġprivate Ġval Ġrunnable Ġ= ĠRunnable Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġmedia Ġ= Ġplayer . service ?. medi ap layer ?. media Ġas ? ĠMedia Ġ?: Ġreturn @ Runnable ĊĊĠĠĠĠĠĠĠ Ġif Ġ( Build Config . DEBUG ) ĠLog . i ( this :: class . java . simple Name , Ġ" Stats : Ġdem ux Bit rate : Ġ${ media . stats ?. dem ux Bit rate } Ġdem ux Cor rupted : Ġ${ media . stats ?. dem ux Cor rupted } Ġdem ux Dis continu ity : Ġ${ media . stats ?. dem ux Dis continu ity } Ġdem ux Read Bytes : Ġ${ media . stats ?. dem ux Read Bytes }") ĊĠĠĠĠĠĠĠ Ġval Ġnow Ġ= ĠSystem . currentTimeMillis () Ġ- Ġfirst Time code ĊĠĠĠĠĠĠĠ Ġmedia . stats ?. dem ux Bit rate ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . plot View . addData ( Stat Index . DE MUX _ BIT RATE . ordinal , ĠPair ( now , Ġit Ġ* Ġ 8 Ġ* Ġ 1 0 2 4 )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġmedia . stats ?. input Bit rate ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . plot View . addData ( Stat Index . INPUT _ BIT RATE . ordinal , ĠPair ( now , Ġit Ġ* Ġ 8 Ġ* Ġ 1 0 2 4 )) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( last Media Uri Ġ!= Ġmedia . uri ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlast Media Uri Ġ= Ġmedia . uri ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . info Grid s . removeAll Views () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġmedia . track Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġgrid Ġ= ĠGrid Layout ( player ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġgrid . column Count Ġ= Ġ 2 ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtrack Ġ= Ġmedia . get Track ( i ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( track . bit rate Ġ> Ġ 0 ) Ġadd Stream GridView ( grid , Ġplayer . getString ( R . string . bit rate ), Ġplayer . getString ( R . string . bit rate _ value , Ġtrack . bit rate . to Long (). readable Size ())) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd Stream GridView ( grid , Ġplayer . getString ( R . string . codec ), Ġtrack . codec ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( track . language Ġ!= Ġnull Ġ&& Ġ! track . language . equals (" und ", Ġignore Case Ġ= Ġtrue )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd Stream GridView ( grid , Ġplayer . getString ( R . string . language ), Ġtrack . language ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( track . type ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠI Media . Track . Type . Audio Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( track Ġas ? ĠI Media . Audio Track )?. let Ġ{ Ġtrack Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd Stream GridView ( grid , Ġplayer . getString ( R . string . channels ), Ġtrack . channels . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd Stream GridView ( grid , Ġplayer . getString ( R . string . track _ sampler ate ), Ġplayer . getString ( R . string . track _ sampler ate _ value , Ġtrack . rate )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠI Media . Track . Type . Video Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( track Ġas ? ĠI Media . Video Track )?. let Ġ{ Ġtrack Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfram erate Ġ= Ġtrack . frame Rate Num Ġ/ Ġtrack . frame Rate Den . toDouble () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( track . width Ġ!= Ġ 0 Ġ&& Ġtrack . height Ġ!= Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd Stream GridView ( grid , Ġplayer . getString ( R . string . resolution ), Ġplayer . getString ( R . string . resolution _ value , Ġtrack . width , Ġtrack . height )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! Double . isNaN ( fram erate )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd Stream GridView ( grid , Ġplayer . getString ( R . string . fram erate ), Ġplayer . getString ( R . string . fram erate _ value , Ġfram erate )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtrack Title Ġ= ĠTextView ( player , Ġnull , ĠR . style . TextAppearance _ Material Components _ Head line 2 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrack Title . setTextColor ( Context Compat . getColor ( player , ĠR . color . orange 5 0 0 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrack Title . text Ġ= Ġwhen Ġ( track . type ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠI Media . Track . Type . Video Ġ-> Ġplayer . getString ( R . string . video ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠI Media . Track . Type . Audio Ġ-> Ġplayer . getString ( R . string . audio ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠI Media . Track . Type . Text Ġ-> Ġplayer . getString ( R . string . text ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġplayer . getString ( R . string . unknown ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlayout Params Ġ= ĠLinearLayout . LayoutParams ( LinearLayout . LayoutParams . WRAP _ CONTENT , ĠLinearLayout . LayoutParams . WRAP _ CONTENT ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlayout Params . bottom Margin Ġ= Ġ 4 . dp ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlayout Params . top Margin Ġ= Ġ 8 . dp ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrack Title . layout Params Ġ= Ġlayout Params ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( grid . child Count Ġ!= Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . info Grid s . addView ( track Title ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . info Grid s . addView ( grid ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( started ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstart () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġadd Stream GridView ( grid : ĠGrid Layout , Ġtitle String : ĠString , Ġvalue String : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġtitle Ġ= ĠTextView ( player , Ġnull , ĠR . style . TextAppearance _ Material Components _ Subtitle 1 ) ĊĠĠĠĠĠĠĠ Ġtitle . text Ġ= Ġtitle String ĊĠĠĠĠĠĠĠ Ġgrid . addView ( title ) ĊĊĠĠĠĠĠĠĠ Ġval Ġvalue Ġ= ĠTextView ( player ) ĊĠĠĠĠĠĠĠ Ġvalue . text Ġ= Ġvalue String ĊĠĠĠĠĠĠĠ Ġval Ġlayout Params Ġ= ĠGrid Layout . LayoutParams () ĊĠĠĠĠĠĠĠ Ġlayout Params . left Margin Ġ= Ġ 4 . dp ĊĠĠĠĠĠĠĠ Ġvalue . layout Params Ġ= Ġlayout Params ĊĠĠĠĠĠĠĠ Ġgrid . addView ( value ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġon Configuration Changed () Ġ{ ĊĠĠĠĠĠĠĠ Ġsetup Layout () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsetup Layout () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! :: constraint Set Large . isInitialized ) Ġreturn ĊĠĠĠĠĠĠĠ Ġif Ġ( player . get Screen Width () Ġ> Ġ 6 0 0 . dp ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconstraint Set Large . apply To ( binding . stats Scroll view Content ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconstraint Set . apply To ( binding . stats Scroll view Content ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ enum Ġclass ĠStat Index Ġ{ ĊĠĠĠ ĠINPUT _ BIT RATE , ĠDE MUX _ BIT RATE Ċ } Ċ Ċ inline Ġfun ĠNested ScrollView . scroll State ( cross inline Ġidle : Ġ() Ġ-> ĠUnit , Ġcross inline Ġscrolling : Ġ() Ġ-> ĠUnit ) Ġ{ ĊĠĠĠ Ġset On Touch Listener Ġ{ Ġ_, Ġevent Ġ-> ĊĠĠĠĠĠĠĠ Ġwhen Ġ( event . action ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠMotion Event . ACTION _ SCROLL , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠMotion Event . ACTION _ MOVE , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠMotion Event . ACTION _ DOWN Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġscrolling () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠMotion Event . ACTION _ CANCEL , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠMotion Event . ACTION _ UP Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġidle () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġfalse ĊĠĠĠ Ġ} Ċ }