
    iS                    4   S r SSKJr  SSKJr  SSKJr  SSKrSSKrSSK	J
r
JrJr  SSKJr  SS	KJrJr  SS
KJr  SSKJr  SSKJrJr  SSKJr  SSKJr  \
(       a  SSKJr  SSKJ r   SSK!J"r"  SSK#J$r$  Sr%Sr&Sr'Sr(Sr)Sr*Sr+Sr,Sr-Sr.Sr/Sr0S r1S!r2S"r3S#r4S$r5SSSSS%S%S&S&S%S'S%S%S(S%S\&S)S*SSS%SSSSS+4                                                       S4S, jjr6 " S- S.\5      r7\8S5S/ j5       r9 " S0 S1\5      r: " S2 S3\:5      r;g)6z,
Controller to interface with the Plex-app.
    )annotations)deepcopy)partialN)TYPE_CHECKINGAnycast)urlparse   )CallbackTypeBaseController)MediaStatus   )MESSAGE_TYPE)ControllerNotRegisteredRequestFailed)CastMessage)chain_on_success)Playable)Media)	PlayQueue)
PlexServerUNKNOWNBUFFEREDLIVEcurrentTimePLAYPAUSESTOPSTEPFORWARDSTEPBACKPREVIOUSNEXTLOADSHOWDETAILSSEEKMEDIA_STATUS
GET_STATUSEDIT_TRACKS_INFOTd   Fvideoi~  httpz1.10.1.4602c                   SnSnU Gb  [        U [        5      (       a  U S   R                  OU R                  n[        UR                  5      nUR
                  nUR                  nUR                  nUR                  nUR                  nUR                  nUR                  n[        U SS5      S:X  a  U(       a  U R                  n OU nUc  UR                  U US9nUR                  nUR                   R"                  nUR                  S   R$                  nUR&                  nUS:w  a  UnUUUUUUUUUUUUU	U
UUUUUUUSU0S.SU S	3S
.UUSS.S.nUR)                  U5        U$ )ay  Create the message that chromecast requires. Use pass of plexapi media object or
   set all the needed kwargs manually. See the code for what to set.

Args:
    media (None, optional): a :class:`~plexapi.base.Playable
    type (str): Default LOAD, SHOWDETAILS.
    requestId (int): The requestId, Chromecasts may use this.
    offset (int): Offset of the playback in seconds.
    directPlay (bool): Default True
    directStream (bool): Default True
    subtitleSize (int): Set the subtitle size, possibly only 100 & 200.
    audioBoost (int): Default 100
    transcoderVideo (bool): Default True
    transcoderVideoRemuxOnly (bool): Default False
    transcoderAudio (bool): Default True
    isVerifiedHostname (bool): Default True
    contentType (str): Default 'video', 'audio'
    myPlexSubscription (bool): True if user has a PlexPass.
    contentId (str): The key Chromecasts use to start playback.
    streamType (str): Default BUFFERED, LIVE
    port (int): PMS port
    address (str): PMS host, without scheme.
    username (None): Username of the user that started playback.
    autoplay (bool): Auto play after the video is done.
    currentTime (int): Set playback from this time. default 0
    version (str): PMS version. Default 1.10.1.4602
    startItem (:class:`~plexapi.media.Media`, optional): Media item in list/playlist/playqueue where playback should
                                                         start. Overrides existing startItem for playqueues if set.
    **kwargs: To allow overrides, this will be merged with the rest of the msg.

Returns:
    dict: Returs a dict formatted correctly to start playback on a Chromecast.
Nr   TYPE	playqueue)	startItemusername)machineIdentifiertranscoderVideotranscoderVideoRemuxOnlytranscoderAudioversionmyPlexSubscriptionisVerifiedHostnameprotocoladdressportaccessTokenuserz/playQueues/z?own=1&window=200)offset
directPlaydirectStreamsubtitleSize
audioBoostservercontainerKey)	contentId
streamTypecontentType
customDataautoplayr   activeTrackIds)type	requestIdmedia)
isinstancelist_serverr	   _baseurlschemehostnamer:   r1   _tokenmyPlexUsernamer6   getattritemscreatePlayQueueplayQueueIDselectedItemkeylistTyper5   update) rL   rJ   rK   r=   r>   r?   r@   rA   r2   r3   r4   r7   rF   r6   rD   rE   r:   r8   r9   r0   rH   r   	playQueuerX   r/   r5   kwargsr1   tokenrB   
server_urlmsgs                                    T/home/sebas/venvs/catt/lib/python3.13/site-packages/pychromecast/controllers/plex.pymedia_to_chromecast_commandrc   0   s   ~ E !+5$ 7 7E!HU]] 	 foo.
$$%%"44((#665&$';6!	..u	.JI++**..	ooa(11.. { "$& ( , ,():'60H'6&*<*< (& #('2 #/{m;L M), !&"9
!CH JJvJ    c                  ,    \ rS rSrSr\SS j5       rSrg)PlexMediaStatus   zClass to hold the media status.c                8    U R                   R                  S5      $ zReturn episode title.subtitlemedia_metadatagetselfs    rb   episode_titlePlexMediaStatus.episode_title   s     ""&&z22rd    N)return
str | None)__name__
__module____qualname____firstlineno____doc__propertyrp   __static_attributes__rr   rd   rb   rf   rf      s    )3 3rd   rf   c                8    U R                   R                  S5      $ ri   rk   rn   s    rb   rp   rp      s     "":..rd   c                    ^  \ rS rSrSrS U 4S jjr    S!           S"S jjrS#S jrS S jrS$S jr	SS	.S%S
 jjr
S S jrS S jrS S jrS S jrS S jrS&S'S jjrS S jrS(S jrS)S*S jjrS)S*S jjrS+S,S jjrS+S-S jjrS S jr\S.S j5       rS+S/S jjrS+S-S jjr S0       S1S jjrS+S-S jjrS+S2S jjrS+S2S jjrSr U =r!$ )3PlexController   z+Controller to interact with Plex namespace.c                   > [         TU ]  SS5        SU l        SU l        SU l        [
        R                  " 5       U l        0 U l        g )Nzurn:x-cast:plex9AC194DCr   )	super__init__app_id	namespace
request_id	threadingEventplay_media_event_last_play_msg)ro   	__class__s    rb   r   PlexController.__init__   s?    *J7 * ) 1.0rd   Nc                   U R                   R                  SUUUUU5        U(       a  U R                  5         U(       a+  U R                  n X l        U R	                  UUUS9  X`l        gU R	                  XUS9  g! X`l        f = f)a  Wrapper for the commands.

Args:
    msg (dict): The actual command that will be sent.
    namespace (None, optional): What namespace should be used to send this.
    inc_session_id (bool, optional): Include session ID.
    callback_function (None, optional): If callback is provided it is
                                        executed after the command.
    inc (bool, optional): Increase the requestsId.
zSending msg %r %s %s %s %s.)inc_session_idcallback_functionN)loggerdebug_inc_requestr   send_message)ro   ra   r   r   r   incolds          rb   	_send_cmdPlexController._send_cmd   s    $ 	)	
 ..C%!*!!#1&7 "  "%FW   "%s   A; ;Bc                D    U =R                   S-  sl         U R                   $ )Nr
   )r   rn   s    rb   r   PlexController._inc_request  s    1rd   c                $    U R                  5         g)z1Updates status when a media channel is connected.N)update_statusrn   s    rb   channel_connected PlexController.channel_connected	  s    rd   c                `    U[            [        :X  a  U R                  R                  SU5        gg)a:  Called when a message from Plex to our controller is received.

I haven't seen any message for it, but lets keep for for now.
I have done minimal testing.

Args:
    message (dict): Description
    data (dict): message.payload_utf8 interpreted as a JSON dict.

Returns:
    bool: True if the message is handled.


z&(PlexController) MESSAGE RECEIVED: %r.TF)r   TYPE_MEDIA_STATUSr   r   )ro   _messagedatas      rb   receive_messagePlexController.receive_message  s-     !22KKFMrd   r   c               8    U R                  [        [        0US9  g)zSend message to update status.r   N)r   r   TYPE_GET_STATUS)ro   r   s     rb   r   PlexController.update_status"  s     ?+?P 	 	
rd   c                :    U R                  [        [        05        g)zSend stop command.N)r   r   	TYPE_STOPrn   s    rb   stopPlexController.stop(      i01rd   c                :    U R                  [        [        05        g)zSend pause command.N)r   r   
TYPE_PAUSErn   s    rb   pausePlexController.pause,  s    j12rd   c                :    U R                  [        [        05        g)zSend play command.N)r   r   	TYPE_PLAYrn   s    rb   playPlexController.play0  r   rd   c                :    U R                  [        [        05        g)zSend previous command.N)r   r   TYPE_PREVIOUSrn   s    rb   previousPlexController.previous4  s    m45rd   c                :    U R                  [        [        05        g)zSend next command.N)r   r   	TYPE_NEXTrn   s    rb   nextPlexController.next8  r   rd   c                J    U R                  [        [        [        USU05        g)zqSend seek command.

Args:
    position (int): Offset in seconds.
    resume_state (str, default): PLAYBACK_START
resumeStateN)r   r   	TYPE_SEEKSEEK_KEY)ro   positionresume_states      rb   seekPlexController.seek<  s      	9h-V	
rd   c                &    U R                  S5        g)zRewind back to the start.r   N)r   rn   s    rb   rewindPlexController.rewindG  s    		!rd   c                x    U R                   c  [        eU R                   R                  R                  US-  5      $ )zZSet the volume in percent (1-100).

Args:
    percent (int): Percent of volume to be set.
r)   )_socket_clientr   receiver_controller
set_volume)ro   percents     rb   r   PlexController.set_volumeK  s7     &))""66AA'C-PPrd   c                z    US::  a  [        SU 35      eU R                  U R                  R                  U-   5      $ )zJIncrement volume by 0.1 (or delta) unless at max.
Returns the new volume.
r   ,volume delta must be greater than zero, not 
ValueErrorr   statusvolume_levelro   deltas     rb   	volume_upPlexController.volume_upV  <     A:KE7STTt{{77%?@@rd   c                z    US::  a  [        SU 35      eU R                  U R                  R                  U-
  5      $ )zLDecrement the volume by 0.1 (or delta) unless at 0.
Returns the new volume.
r   r   r   r   s     rb   volume_downPlexController.volume_down^  r   rd   c                    U R                   c  [        eUc  U R                  R                  (       + nU R                   R                  R                  U5        g)zQToggle muting of audio.

Args:
    status (None, optional): Override for on/off.
N)r   r   r   volume_mutedr   set_volume_mutedro   r   s     rb   mutePlexController.mutef  sG     &))>111F//@@Hrd   c                    [        U4[        U R                  5       S.UD6nSS jnU R                  [	        [        U R                  USSS9U5      S9  g)	z!Show media item's info on screen.)rJ   rK   c                (    U (       d  [        S5      eg )NzPlexController.show_media)r   )msg_sent	_responses     rb   callback+PlexController.show_media.<locals>.callbackz  s    #$?@@ rd   TF)r   r   r   Nr   boolr   zdict | Noners   None)rc   TYPE_DETAILSr   launchr   r   r   )ro   rL   r^   ra   r   s        rb   
show_mediaPlexController.show_mediat  s_    )
$0A0A0C
GM
	A 	.DeLh 	 	
rd   c                r    U R                   c  [        eU R                   R                  R                  5         g)zQuit the Plex app.N)r   r   r   stop_apprn   s    rb   quit_appPlexController.quit_app  s,    &))//88:rd   c                    U R                   c  [        eU R                   R                  R                  n[        Ul        [        [        U5      $ )zGet the Chromecast's playing status.

Returns:
    pychromecast.controllers.media.MediaStatus: Slightly modified status with patched
                                                method for episode_title.
)r   r   media_controllerr   rp   r   rf   r   s     rb   r   PlexController.status  sB     &))$$55<<,OV,,rd   c                    U R                   (       aR  U R                  R                  n[        U R                   5      nUc  UOUUS   S   S'   X#S'   U R	                  USSSS	9  gU R
                  R                  S
5        g)zReset playback.

Args:
    offset (None, optional): Start playback from this offset in seconds,
                             otherwise playback will start from current time.

NrL   rG   r=   current_time urn:x-cast:com.google.cast.mediaTFr   r   r   zKCan not reset the stream, _last_play_msg was not set with _send_start_play.)r   r   adjusted_current_timer   r   r   r   )ro   r=   
offset_nowra   s       rb   _reset_playbackPlexController._reset_playback  s     ::J4../C %n
& L&x0 #-NN<#	   KK5rd   c                    [        U4SU R                  5       0UD6nU R                  R                  S[        R
                  " USS95        X0l        U R                  USSSS9  g	)
zHelper to send a playback command.

Args:
    media (None, optional): :class:`~plexapi.base.Playable
    **kwargs: media_to_chromecast_command docs string.

requestiIdzCreate command: 
%r
   )indentr   TFr   N)rc   r   r   r   jsondumpsr   r   )ro   rL   r^   ra   s       rb   _send_start_playPlexController._send_start_play  so     *
"//1
5;
 	2DJJs14MN!8	 	 	
rd   c                    U R                   R                  5         U R                  " U40 UD6  U R                   R                  U5        U R                   R                  5         g)a  Block until media is playing, typically useful in a script.

Another way to do the same is to check if the
controller is_active or by using self.status.player_state.

Args:
    media (None, optional): Can also be :class:`~plexapi.base.Playable
                            if not, you need to fill out all the kwargs.
    timeout (None, int): default None
    **kwargs: See media_to_chromecast_command docs string.

N)r   clear
play_mediawait)ro   rL   timeoutr^   s       rb   block_until_playing"PlexController.block_until_playing  sM      	##%((""7+##%rd   c                p   ^ ^^ T R                   R                  5         SUUU 4S jjnT R                  US9  g)zStart playback on the Chromecast.

Args:
    media (None, optional): Can also be :class:`~plexapi.base.Playable
                            if not, you need to fill out all the kwargs.
    **kwargs: See media_to_chromecast_command docs string.
c                   > U (       d  [        S5      e TR                  " T40 TD6  TR                  R                  5         g ! TR                  R                  5         f = f)NzPlexController.play_media)r   r  r   set)r   r   r^   rL   ro   s     rb   app_launched_callback8PlexController.play_media.<locals>.app_launched_callback  sO    #$?@@,%%e6v6%%))+%%))+s   A Ar   Nr   )r   r  r   )ro   rL   r^   r  s   ``` rb   r  PlexController.play_media  s2     	##%	, 	, 	&;<rd   c                \    U R                   c  [        eU R                   R                  US9  g)zJoin the thread.Nr
  )r   r   joinro   r
  s     rb   r  PlexController.join  s+    &))   1rd   c                |    U R                   c  [        eU R                   R                  5         U R                  US9  g)zDisconnect the controller.

:param timeout: A floating point number specifying a timeout for the
                operation in seconds (or fractions thereof). Or None
                to block forever. Set to 0 to not block.
Nr  )r   r   
disconnectr  r  s     rb   r  PlexController.disconnect  s6     &))&&(		'	"rd   )r   r   r   r   r   rs   r   )NFNT)ra   dictr   rt   r   r   r   CallbackType | Noner   r   rs   r   )rs   int)r   r   r   r  rs   r   )r   r  rs   r   )PLAYBACK_START)r   r  r   strrs   r   )r   floatrs   r!  )g?)r   r!  rs   r!  N)r   zbool | Noners   r   rL   Playable | Noner^   r   rs   r   )rs   rf   )r=   float | Noners   r   )NN)rL   r$  r
  r%  r^   r   rs   r   )r
  r%  rs   r   )"ru   rv   rw   rx   ry   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rz   r   r   r  r  r  r  r  r{   __classcell__r   s   @rb   r~   r~      s   51 !%$15,, , 	,
 /, , 
,\
* IM 
23262	
	QAAI
 ; - -:
( FJ&$&6B&UX&	&*=(2# #rd   r~   c                     ^  \ rS rSrSrSU 4S jjrSS jr S       SS jjrSS jrSS jr	SS jr
SSU 4S	 jjjrS
rU =r$ )PlexApiControlleri	  z"A controller that can use PlexAPI.c                .   > [         TU ]  5         Xl        g r"  )r   r   pms)ro   r+  r   s     rb   r   PlexApiController.__init__  s    rd   c                   [        [        [        U R                  R                  5      R                  S5      S   5      nU R                  R                  U5      R                  5       nU R                  R                  R                  SS5      nU R                  R                  R                  SS5      nUR                  U   nUR                  U   nX%U4$ )z.Get current media_item, media, & part for PMS./
mediaIndexr   	partIndex)r  r   r   r   
content_idsplitr+  	fetchItemreloadmedia_custom_datarm   rL   parts)ro   rZ   
media_item	media_idxpart_idxrL   parts          rb   _get_current_media$PlexApiController._get_current_media  s     $sDKK22399#>rBCXX'',335
KK1155lAF	;;0044[!D  +{{8$$&&rd   c                   U R                  5       u  pEnUS:X  a  UR                  5       nUR                  nO.US:X  a  UR                  5       nUR                  nO[        S5      eU HO  n	XR                  U	R                  U	R                  4;   d  M+  U R                  R                  SX!5        U" U	5          O   UR                  5         U(       a  U R                  5         gg)a-  Sets a new default audio/subtitle track.

Args:
    track (None): The chosen track.
    type_ (str): The type of track.
    reset_playback (bool, optional): Reset playback after the track has
                                     been changed.

Raises:
    ValueError: If type isn't subtitle or audio.
rj   audioz(Set type parameter as subtitle or audio.zChange %s to %s.N)r<  subtitleStreamssetDefaultSubtitleStreamaudioStreamssetDefaultAudioStreamr   indexlanguagelanguageCoder   r   r5  r   )
ro   tracktype_reset_playbackitem_r;  methoddefaulttrack_s
             rb   _change_trackPlexApiController._change_track  s     //1J))+F33Gg&&(F00GGHHFv8K8KLL!!"4eC	  	  " rd   c                (    U R                  US5        g)zVEnable an audiotrack.

Args:
    audio (str): Can be index, language or languageCode.
r?  NrO  )ro   r?  s     rb   enable_audiotrack#PlexApiController.enable_audiotrack@  s     	5'*rd   c                l    U R                  5       u  nnnUR                  5         U R                  5         g)zDisable a subtitle track.N)r<  resetDefaultSubtitleStreamr   )ro   rK  __r;  s       rb   disable_subtitle"PlexApiController.disable_subtitleH  s6     ##%		
'')rd   c                &    U R                  U5        g)z\Enable a subtitle track.

Args:
    subtitle (str): Can be index, language or languageCode.
NrR  )ro   rj   s     rb   enable_subtitle!PlexApiController.enable_subtitleR  s     	8$rd   c                z   > SU R                   R                  0nUR                  U5        [        TU ]  " U40 UD6  g)aM  Start playback on the Chromecast.

Args:
    media (None, optional): Can also be :class:`~plexapi.base.Playable
                            if not, you need to fill out all the kwargs.
    **kwargs: See media_to_chromecast_command docs string. `version` is set
              to the version of the PMS reported by the API by default.
r5   N)r+  r5   r\   r   r  )ro   rL   r^   argsr   s       rb   r  PlexApiController.play_mediaZ  s7     488++,F5)D)rd   )r+  )r+  r   rs   r   )rs   ztuple[Any, Any, Any])rj   T)rG  r   rH  r   rI  r   rs   r   )r?  r   rs   r   r  )rj   r   rs   r   r"  r#  )ru   rv   rw   rx   ry   r   r<  rO  rS  rX  r[  r  r{   r&  r'  s   @rb   r)  r)  	  sV    ,' KO!#!#!$!#CG!#	!#F+%* *rd   r)  )8rL   r$  rJ   r   rK   r  r=   r  r>   r   r?   r   r@   r  rA   r  r2   r   r3   r   r4   r   r7   r   rF   r   r6   r   rD   rt   rE   r   r:   r  r8   r   r9   rt   r0   rt   rH   r   r   r  r]   zPlayQueue | NonerX   z
int | Noner/   zMedia | Noner5   r   r^   r   rs   zdict[str, Any])ro   rf   rs   rt   )<ry   
__future__r   copyr   	functoolsr   r  r   typingr   r   r   urllib.parser	    r   r   rL   r   constr   errorr   r   generated.cast_channel_pb2r   response_handlerr   plexapi.baser   plexapi.mediar   plexapi.playqueuer   plexapi.serverr   STREAM_TYPE_UNKNOWNSTREAM_TYPE_BUFFEREDSTREAM_TYPE_LIVEr   r   r   r   TYPE_STEPFORWARDTYPE_STEPBACKWARDr   r   	TYPE_LOADr   r   r   r   TYPE_EDIT_TRACKS_INFOrc   rf   rz   rp   r~   r)  rr   rd   rb   <module>ru     si   #     + + ! *    : 0%#+) !  	
	   			" *  " %* ## *"&"" 5GG
G G 	G
 G G G G G #G G G G G G  !G" #G$ %G& 'G( )G* +G, -G.  /G0 1G2 3G4 5G6 7G8 9GT3k 3 
/ 
/
{#^ {#~	\* \*rd   