package Ġio . case y . mus ik cube . remote . playback Ċ Ċ import Ġio . case y . mus ik cube . remote . Application Ċ import Ġio . case y . mus ik cube . remote . offline . Offline Track Ċ import Ġio . case y . mus ik cube . remote . util . Preconditions Ċ import Ġio . reactivex . Single Ċ import Ġio . reactivex . android . schedul ers . Android Schedulers Ċ import Ġio . reactivex . schedul ers . Schedulers Ċ import Ġorg . json . JSONObject Ċ import Ġjava . util .* Ċ Ċ abstract Ġclass ĠPlayer Wrapper Ġ{ ĊĠĠĠ Ġprivate Ġenum Ġclass ĠType Ġ{ ĊĠĠĠĠĠĠĠ ĠMedia Player , ĠEx o Player ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġenum Ġclass ĠState Ġ{ ĊĠĠĠĠĠĠĠ ĠSto pped , ĊĠĠĠĠĠĠĠ ĠPre paring , ĊĠĠĠĠĠĠĠ ĠPrepared , ĊĠĠĠĠĠĠĠ ĠPlay ing , ĊĠĠĠĠĠĠĠ ĠBuffer ing , ĊĠĠĠĠĠĠĠ ĠPause d , ĊĠĠĠĠĠĠĠ ĠError , ĊĠĠĠĠĠĠĠ ĠFinished , ĊĠĠĠĠĠĠĠ ĠK illing , ĊĠĠĠĠĠĠĠ ĠDis posed ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġvar Ġlistener : Ġ(( Player Wrapper , ĠState ) Ġ-> ĠUnit )? Ġ= Ġnull ĊĊĠĠĠ Ġvar Ġstate Ġ= ĠState . Stopped ĊĠĠĠĠĠĠĠ Ġprotected Ġset ( state ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( this . state Ġ!= Ġstate ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfield Ġ= Ġstate ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlistener ?. invoke ( this , state ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġabstract Ġfun Ġplay ( uri : ĠString , Ġmetadata : ĠJSONObject ) ĊĠĠĠ Ġabstract Ġfun Ġprefetch ( uri : ĠString , Ġmetadata : ĠJSONObject ) ĊĠĠĠ Ġabstract Ġfun Ġpause () ĊĠĠĠ Ġabstract Ġfun Ġresume () ĊĠĠĠ Ġabstract Ġfun Ġupdate Volume () ĊĠĠĠ Ġabstract Ġfun Ġset Next MediaPlayer ( wrapper : ĠPlayer Wrapper ?) ĊĠĠĠ Ġabstract Ġfun Ġdispose () ĊĠĠĠ Ġabstract Ġvar Ġposition : ĠInt ĊĠĠĠ Ġabstract Ġval Ġduration : ĠInt ĊĠĠĠ Ġabstract Ġval Ġbuffered Percent : ĠInt ĊĊĠĠĠ Ġopen Ġfun Ġset On StateChanged Listener ( listener : Ġ(( Player Wrapper , ĠState ) Ġ-> ĠUnit )? ) Ġ{ ĊĠĠĠĠĠĠĠ ĠPreconditions . throw IfNot On MainThread () ĊĠĠĠĠĠĠĠ Ġthis . listener Ġ= Ġlistener ĊĠĠĠĠĠĠĠ Ġthis . listener ?. invoke ( this , Ġthis . state ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠTYPE Ġ= ĠType . Exo Player ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠD U CK _ CO EF Ġ= Ġ 0 . 2 f Ġ/* Ġvolume Ġ= Ġ 2 0 % Ġwhen Ġdu ck ed Ġ*/ ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠD U CK _ NONE Ġ= Ġ- 1 . 0 f ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġactive Players Ġ= ĠHashSet < Player Wrapper >() ĊĠĠĠĠĠĠĠ Ġprivate Ġvar Ġglobal Volume Ġ= Ġ 1 . 0 f ĊĠĠĠĠĠĠĠ Ġprivate Ġvar Ġglobal Mut ed Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġprivate Ġvar Ġpre Duck Global Volume Ġ= ĠD U CK _ NONE ĊĊĠĠĠĠĠĠĠ Ġfun Ġstore Offline ( uri : ĠString , Ġjson : ĠJSONObject ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠSingle . from Callable Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtrack Ġ= ĠOff line Track () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( track . from JSONObject ( uri , Ġjson )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠApplication . offline Db ?. track Dao ()?. insert Track ( track ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠApplication . offline Db ?. prune () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe On ( Schedulers . io ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe On ( Android Schedulers . main Thread ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġdu ck () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠPreconditions . throw IfNot On MainThread () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( pre Duck Global Volume Ġ== ĠD U CK _ NONE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlast Volume Ġ= Ġglobal Volume ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Volume ( global Volume Ġ* ĠD U CK _ CO EF ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpre Duck Global Volume Ġ= Ġlast Volume ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġund uck () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠPreconditions . throw IfNot On MainThread () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( pre Duck Global Volume Ġ!= ĠD U CK _ NONE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtemp Ġ= Ġpre Duck Global Volume ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpre Duck Global Volume Ġ= ĠD U CK _ NONE ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Volume ( temp ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġset Volume ( volume : ĠFloat ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġcomputed Volume Ġ= Ġvolume ĊĠĠĠĠĠĠĠĠĠĠĠ ĠPreconditions . throw IfNot On MainThread () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( pre Duck Global Volume Ġ!= ĠD U CK _ NONE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpre Duck Global Volume Ġ= Ġvolume ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcomputed Volume Ġ*= ĠD U CK _ CO EF ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( computed Volume Ġ!= Ġglobal Volume ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġglobal Volume Ġ= Ġcomputed Volume ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( w Ġin Ġactive Players ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġw . update Volume () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġget Volume (): ĠFloat Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠPreconditions . throw IfNot On MainThread () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( global Mut ed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġ 0 f ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( pre Duck Global Volume Ġ== ĠD U CK _ NONE ) Ġglobal Volume Ġelse Ġpre Duck Global Volume ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġset Mute ( muted : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠPreconditions . throw IfNot On MainThread () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( Player Wrapper . global Mut ed Ġ!= Ġmut ed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPlayer Wrapper . global Mut ed Ġ= Ġmut ed ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( w Ġin Ġactive Players ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġw . update Volume () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġnew Instance (): ĠPlayer Wrapper Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( TYPE Ġ== ĠType . Exo Player ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠEx o Player Wrapper () Ġelse ĠMedia Player Wrapper () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġadd Active Player ( player : ĠPlayer Wrapper ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠPreconditions . throw IfNot On MainThread () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġactive Players . add ( player ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġremove Active Player ( player : ĠPlayer Wrapper ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠPreconditions . throw IfNot On MainThread () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġactive Players . remove ( player ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ