
    :jj                    
   d Z ddlmZ ddlZddlmZ ddlZddlZddlZddl	Z	ddl
Z
ddlZddlmZ ddlZddlmZmZmZmZ ddlmZmZmZ dd	lmZmZmZmZ d
ZddgZ ej        e           Z! G d dej"                  Z#d:dZ$d;dZ% G d de#          Z& G d dej'                  Z( G d d          Z)dZ*d
Z+ G d  d!e
j,                  Z- G d" d#          Z. G d$ d%e.          Z/d<d)Z0d=d+Z1deddfd>d4Z2ddeddfd?d9Z3dS )@z9Discovers Chromecasts on the network using mDNS/zeroconf.    )annotationsN)Callable)UUID   )CAST_TYPE_AUDIOCAST_TYPE_GROUP
CAST_TYPES	MF_GOOGLE)get_device_infoget_multizone_statusget_ssl_context)ZEROCONF_ERRORSCastInfoHostServiceInfoMDNSServiceInfo   HKJBLc                  x    e Zd ZdZej        dd            Zej        dd            Zej        dd            ZdS )AbstractCastListenerz%Listener for discovering chromecasts.uuidr   servicestrreturnNonec                    dS )zA cast has been discovered.

        uuid: The cast's uuid, this is the dictionary key to find
        the chromecast metadata in CastBrowser.devices.
        service: First known MDNS service name or host:port
        N selfr   r   s      L/home/user/adhan/venv/lib/python3.11/site-packages/pychromecast/discovery.pyadd_castzAbstractCastListener.add_cast#             	cast_infor   c                    dS )zA cast has been removed, meaning there are no longer any known services.

        uuid: The cast's uuid
        service: Last valid MDNS service name or host:port
        cast_info: CastInfo for the service to aid cleanup
        Nr   r   r   r   r$   s       r    remove_castz AbstractCastListener.remove_cast,   r"   r#   c                    dS )zpA cast has been updated.

        uuid: The cast's uuid
        service: MDNS service name or host:port
        Nr   r   s      r    update_castz AbstractCastListener.update_cast5   r"   r#   Nr   r   r   r   r   r   r   r   r   r   r$   r   r   r   )	__name__
__module____qualname____doc__abcabstractmethodr!   r'   r)   r   r#   r    r   r       s        //    	    	     r#   r   itemr   
block_list	list[str]	item_typer   boolc                x    |D ]6}|                      |          rt                              d||             dS 7dS )Nz(%s %s is blocked from host based pollingTF)
startswith_LOGGERdebug)r2   r3   r5   blocked_prefixs       r    _is_blocked_from_host_browserr<   >   sR     %  ??>** 	MMDiQUVVV44	 5r#   modelc                .    t          | t          d          S )NModel)r<   #HOST_BROWSER_BLOCKED_MODEL_PREFIXES)r=   s    r    #_is_model_blocked_from_host_browserrA   H   s    (2G  r#   c                  :    e Zd ZdZ	 	 	 dddZddZddZddZdS )SimpleCastListenerz#Helper for backwards compatibility.Nadd_callback"Callable[[UUID, str], None] | Noneremove_callback,Callable[[UUID, str, CastInfo], None] | Noneupdate_callbackc                0    || _         || _        || _        d S N)_add_callback_remove_callback_update_callback)r   rD   rF   rH   s       r    __init__zSimpleCastListener.__init__Q   s"     * / /r#   r   r   r   r   r   r   c                D    | j         r|                      ||           d S d S rJ   )rK   r   s      r    r!   zSimpleCastListener.add_cast[   s3     	.tW-----	. 	.r#   r$   r   c                F    | j         r|                      |||           d S d S rJ   )rL   r&   s       r    r'   zSimpleCastListener.remove_cast_   s5      	<!!$;;;;;	< 	<r#   c                D    | j         r|                      ||           d S d S rJ   )rM   r   s      r    r)   zSimpleCastListener.update_castc   s3      	1!!$00000	1 	1r#   NNNrD   rE   rF   rG   rH   rE   r*   r+   )r,   r-   r.   r/   rN   r!   r'   r)   r   r#   r    rC   rC   N   s{        -- <@HL>B	0 0 0 0 0. . . .< < < <1 1 1 1 1 1r#   rC   c                  :    e Zd ZdZddZddZddZddZddZdS )ZeroConfListenerz&Listener for ZeroConf service browser.cast_listenerr   devicesdict[UUID, CastInfo]host_browserHostBrowserlockthreading.Lockr   r   c                >    || _         || _        || _        || _        d S rJ   )_cast_listener_devices_host_browser_services_lock)r   rV   rW   rY   r[   s        r    rN   zZeroConfListener.__init__k   s)     ,)"r#   zczeroconf.Zeroconftype_r   namec                   t                               d||           d}d}t          |          }| j        5  | j                                        D ]F\  }}||j        v r8|}|j                            |           t          |j                  dk    rd} nGddd           n# 1 swxY w Y   |st                               d||           dS |r| j	        
                    |||           dS | j	                            ||           dS )z0Called by zeroconf when an mDNS service is lost.zremove_service %s, %sNFr   Tzremove_service unknown %s, %s)r9   r:   r   ra   r_   itemsservicesremovelenr^   r'   r)   )	r   rb   rd   re   r$   device_removedservice_infor   info_for_uuids	            r    remove_servicezZeroConfListener.remove_servicew   sm   -ud;;;	&t,,  	 	'+}':':'<'<  #m=#999 -I!*11,???=122a77)-E :	 	 	 	 	 	 	 	 	 	 	 	 	 	 	  	MM95$GGGF 	8++D$	BBBBB++D$77777s   A!B$$B(+B(c                    t                               d||           |                     |||| j        j                   dS )z3Called by zeroconf when an mDNS service is updated.zupdate_service %s, %sN)r9   r:   _add_update_servicer^   r)   r   rb   rd   re   s       r    update_servicezZeroConfListener.update_service   s?    -ud;;;  UD$2E2QRRRRRr#   c                    t                               d||           |                     |||| j        j                   dS )z6Called by zeroconf when an mDNS service is discovered.zadd_service %s, %sN)r9   r:   rp   r^   r!   rq   s       r    add_servicezZeroConfListener.add_service   s?    *E4888  UD$2E2NOOOOOr#   zconftypcallbackCallable[[UUID, str], None]c                h   dd}|                     d          rt                              d||           dS V|dk     rP	 |                    ||          n+# t          $ r t                              d           Y nw xY w|dz  }|dk     Pst                              d||           dS j        t                              d	           dS dfd}                                }|r|d         nj        }|t                              d||           dS | j        	                    |g            |d          }	 |d          pd}
 |d          }|st                              d||           dS 	 t          |          }n.# t          $ r! t                              d|||
           Y dS w xY wt          |          }| j        5  j        dk    rt          }t          }n*t!          j        |
                                d          \  }}|| j        vr%t)          |h||
|	|j        ||          | j        |<   nJ| j        |         j        }|                    |           t)          |||
|	|j        ||          | j        |<   ddd           n# 1 swxY w Y    |||           dS )zAdd or update a service.Nr   z_sub._googlecast._tcp.local.z#_add_update_service ignoring %s, %s   z2get_info_from_service failed to resolve service %sr   z(_add_update_service failed to add %s, %sz _add_update_service port is Nonekeyr   r   
str | Nonec                    j                             |                     d                    }|t          |t                    r|S |                    d          S )z#Retrieve value and decode to UTF-8.zutf-8)
propertiesgetencode
isinstancer   decode)r{   valuer   s     r    	get_valuez7ZeroConfListener._add_update_service.<locals>.get_value   sQ    &**3::g+>+>??E
 }
5# 6 6}<<(((r#   z1_add_update_service failed to get host for %s, %sfnmdzUnknown model nameidz1_add_update_service failed to get uuid for %s, %sz?_add_update_service failed due to bad uuid for %s, %s, model %sI  NN)r{   r   r   r|   )endswithr9   r:   get_service_infor   portparsed_addressesserverr`   	add_hostsr   
ValueErrorr   ra   r   r
   r	   r   lowerr_   r   rh   add)r   ru   rv   re   rw   triesr   	addresseshostfriendly_name
model_nameuuid_strr   rl   	cast_typemanufacturerrh   r   s                    @r    rp   z$ZeroConfListener._add_update_service   s    ==788 	MM?dKKKFo%!))00d;;" 	 	 	
 H   	 QJE o%!))  	MMDc4PPPF<MM<===F		) 		) 		) 		) 		) 		) ,,..	(<y||gn<MMCS$   F 	$$dV,,,!	$Yt__<(<
9T?? 	MMCS$   F		>>DD 	 	 	MMQ	   FF	 't,,   "	 "	 |t##+	(*4.$$&&+ +'	< 4=((&.!N!L 	' 	'd##  =.7\***&.!L 	' 	'd#3"	 "	 "	 "	 "	 "	 "	 "	 "	 "	 "	 "	 "	 "	 "	H 	ts7   A %B B>F 'F98F9B=JJ"JN)
rV   r   rW   rX   rY   rZ   r[   r\   r   r   )rb   rc   rd   r   re   r   r   r   )
ru   rc   rv   r   re   r   rw   rx   r   r   )	r,   r-   r.   r/   rN   rn   rr   rt   rp   r   r#   r    rU   rU   h   s        00
# 
# 
# 
#8 8 8 84S S S S
P P P Px x x x x xr#   rU   c                      e Zd ZdZddZdS )
HostStatuszStatus of known host.r   r   c                "    d| _         d| _        d S )Nr   F)	failcount
no_pollingr   s    r    rN   zHostStatus.__init__  s    r#   Nr   r   )r,   r-   r.   r/   rN   r   r#   r    r   r     s.                   r#   r      c                  \     e Zd ZdZd$ fd
Zd%dZd&dZd'dZd'dZd(dZ	d)d"Z
d*d#Z xZS )+rZ   z&Repeateadly poll a set of known hosts.rV   r   rW   rX   r[   r\   r   r   c                    t                                          d           || _        || _        i | _        t          j                    | _        || _        d| _        d | _	        t          j                    | _        d S )NT)daemonF)superrN   r^   r_   _known_hoststime_next_updatera   _start_requested_context	threadingEventstop)r   rV   rW   r[   	__class__s       r    rN   zHostBrowser.__init__&  so     	%%%+35 IKK" %/3O%%			r#   known_hostsr4   c                    |D ]<}|| j         vr1t                              d|           t                      | j         |<   =dS )z%Add a list of known hosts to the set.zAddded host %sN)r   r9   r:   r   r   r   r   s      r    r   zHostBrowser.add_hosts6  sP     	7 	7D4,,,.555*4,,!$'	7 	7r#   list[str] | Nonec                    |g }|                      |           t          | j                                                  D ];}||vr5t                              d|           | j                            |           <dS )zUpdate the set of known hosts.

        Note: Removed hosts will no longer be polled, but services of any associated
        cast devices will not be purged.
        NzRemoved host %s)r   listr   keysr9   r:   popr   s      r    update_hostszHostBrowser.update_hosts=  s     K{###*//1122 	, 	,D;&&/666!%%d+++	, 	,r#   c                "   t                               d           t                      | _        	 | j                                        s|                                  | xj        t          z  c_        | j        	                    t          | j        t          j                    z
  d                     | j                                        n)# t          $ r t                               d            w xY wt                               d           dS )zStart worker thread.zHostBrowser thread startedr   z$Unhandled exception in worker threadzHostBrowser thread doneN)r9   r:   r   r   r   is_set_poll_hostsr   HOSTLISTENER_CYCLE_TIMEwaitmaxr   	Exception	exceptionr   s    r    runzHostBrowser.runM  s    2333'))	i&&(( H  """!!%<<!!	s4#4ty{{#BAFFGGG i&&(( H  	 	 	DEEE	 	/00000s   BC &C2c           
        t          | j                                                  }|D ]M}g }g }| j                                        r d S 	 | j        |         }n# t
          $ r Y >w xY w|j        rJt          |d| j                  }|sZ|xj	        dz  c_	        |j	        t          k    r|                     |||           t          |j	        t          dz             |_	        |j        st                              d|           |j        t"          k    st%          |j                  rd|_        d|_	        |                    d|j        |j        |j        |j        |j        f           |                    |j                   |j        rt1          || j                  nd }|rt3          j        |j        |j                  D ]}|j        r)|j        | j        vr|                     |j        g           |j        |j        |j        |k    rL|                    |j        |j        d	|j        t@          d
f           |                    |j                   |                     |||           Od S )Nr   )timeoutcontextr   zhost %s does not report UUIDTr   r   )r   zGoogle Cast GroupzGoogle Inc.)!r   r   r   r   r   KeyErrorr   r   r   r   HOSTLISTENER_MAX_FAIL_update_devicesminr   r9   r:   r   r   rA   r   appendr   r   multizone_supportedr   	itertoolschaindynamic_groupsgroupsr   r   r   r   )	r   r   r   rW   uuids
hoststatusdevice_statusmultizone_statusgroups	            r    r   zHostBrowser._poll_hosts[  s   4,113344 U	7 U	7DBDG "Ey!! !.t4

    $ +D"dmTTTM  $$)$$'+@@@((w>>>'*(*?!*C( (
$  % <dCCC '?::6}7OPP ; )-
% $%J NN!/!,!&!+!.	 	 	 LL+,,, !4$T4=AAAA    -&_$35E5L  - -E
 z 5ej8I&I&I
|444z)UZ-?5:QUCUCU NN!J!//!J+)	 	 	 LL,,,,  w6666kU	7 U	7s   A
A('A(r   r   *list[tuple[int, str, str, UUID, str, str]]
host_uuids
list[UUID]c                   g }| j         5  |D ]%\  }}}}}	}
|                     |||||||	|
           &| j        D ]d}| j        |         j                                        D ]=}t          |t                    r&|j        |k    r||vr|                     |||           >e	 d d d            n# 1 swxY w Y   |D ]} |             d S rJ   )	ra   _add_host_servicer_   rh   copyr   r   r   _remove_host_service)r   r   rW   r   	callbacksr   r   r   r   r   r   r   rw   s                r    r   zHostBrowser._update_devices  s    /1	   	I 	I   &&! 	 	 	 	  I I#}T2;@@BB I IG"7O<<I#LD00 
2211$iHHHII)	I 	I 	I 	I 	I 	I 	I 	I 	I 	I 	I 	I 	I 	I 	I< " 	 	HHJJJJ	 	s   BB,,B03B0r   intr   r   r   r   r   list[Callable[[], None]]r   r   c	           
     8   t          ||          }	| j        j        }
|| j        v r:| j        j        }
| j        |         }|	|j        v r|j        |k    r|j        |k    rd S || j        vr t          |	h|||||||          | j        |<   nE| j        |         j        }|	                    |	           t          ||||||||          | j        |<   | d| }t                              d||           |                    t          j        |
||                     d S )N:z6Host %s (%s) up, adding or updating host based service)r   r^   r!   r_   r)   rh   r   r   r   r   r9   r:   r   	functoolspartial)r   r   r   r   r   r   r   r   r   rl   rw   r$   rh   re   s                 r    r   zHostBrowser._add_host_service  sa    'tT22&/4=  *6Hd+I	 222(J66+}<< t}$$"*	# 	#DM$ }T*3HLL&&&"*	# 	#DM$ DdD	
 	
 	
 	*8T4@@AAAAAr#   c           	        || j         vrd S | j         |         }|j        D ]}t          |t                    r|j        |k    r|j                            |           |j        }| d| }t                              d||           t          |j                  dk    r5|
                    t          j        | j        j        |||                     n3|
                    t          j        | j        j        ||                      d S d S )Nr   zFHost %s down or no longer handles uuid %s, removing host based servicer   )r_   rh   r   r   r   ri   r   r9   r:   rj   r   r   r   r^   r'   r)   )r   r   r   r   rm   r   r   re   s           r    r   z HostBrowser._remove_host_service  s=    t}$$Fd+$- 	 	G'?33 8L8L&--g666|''''\  
 }-..!33$$!) /;T4     $$!)$*=*I4QUVV   )	 	r#   )rV   r   rW   rX   r[   r\   r   r   )r   r4   r   r   )r   r   r   r   r   )r   r   rW   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   )r,   r-   r.   r/   rN   r   r   r   r   r   r   r   __classcell__r   s   @r    rZ   rZ   #  s        00& & & & & & 7 7 7 7, , , , 1 1 1 1X7 X7 X7 X7t( ( ( (T7B 7B 7B 7Br       r#   rZ   c                  P    e Zd ZdZ	 	 dddZedd            ZddZddZddZ	dS )CastBrowseraz  Discover Chromecasts on the network.

    When a Chromecast is found, cast_listener.add_cast is called
    When a Chromecast is updated, cast_listener.update_cast is called
    When a Chromecast is lost, the cast_listener.remove_cast is called

    A shared zeroconf instance can be passed as zeroconf_instance. If no
    instance is passed, a new instance will be created.
    NrV   r   zeroconf_instancezeroconf.Zeroconf | Noner   r   r   r   c                b   || _         || _        d | _        i | _        | j        | _        t          j                    | _        t          | j         | j        | j                  | _	        t          | j         | j        | j	        | j                  | _        |r| j	                            |           d S d S rJ   )r^   rb   _zc_browserrW   rh   r   Lockra   rZ   rY   rU   zeroconf_listenerr   )r   rV   r   r   s       r    rN   zCastBrowser.__init__D  s     ,#;?-/'n..'t/B
 
 "2t/@$BU"
 "
  	5''44444	5 	5r#   r   c                *    t          | j                  S )z"Number of discovered cast devices.)rj   rW   r   s    r    countzCastBrowser.countY  s     4<   r#   rc   c                &    | j         rdS || _         dS )zSet zeroconf_instance.N)rb   )r   r   s     r    set_zeroconf_instancez!CastBrowser.set_zeroconf_instance^  s    7 	F#r#   c                    | j         r%t          j        | j         d| j                  | _        | j                                         dS )a  
        This method will start discovering chromecasts on separate threads. When
        a chromecast is discovered, callback will be called with the
        discovered chromecast's zeroconf name. This is the dictionary key to find
        the chromecast metadata in CastBrowser.devices.

        A shared zeroconf instance can be passed as zeroconf_instance. If no
        instance is passed, a new instance will be created.
        z_googlecast._tcp.local.N)rb   zeroconfServiceBrowserr   r   rY   startr   s    r    start_discoveryzCastBrowser.start_discoveryd  sN     7 	'6)&   D
 	!!!!!r#   c                   | j         rI	 | j                                          n# t          $ r Y nw xY w| j         j                                         | j        j                                         | j                                         dS )z&Stop the chromecast discovery threads.N)	r   cancelRuntimeErrorrb   closerY   r   setjoinr   s    r    stop_discoveryzCastBrowser.stop_discoveryw  s     	( ''))))    %%'''""$$$     s   # 
00r   )rV   r   r   r   r   r   r   r   )r   r   )r   rc   r   r   r   )
r,   r-   r.   r/   rN   propertyr   r   r   r   r   r#   r    r   r   9  s          7;(,	5 5 5 5 5* ! ! ! X!$ $ $ $" " " "&
! 
! 
! 
! 
! 
!r#   r   c                  ,     e Zd ZdZ	 	 	 d	d
 fdZ xZS )CastListenerzjBackwards compatible helper class.

    Deprecated as of February 2021, will be removed in June 2024.
    NrD   rE   rF   rG   rH   c                    t                               d           t          |||          }t                                          |           d S )Nz^CastListener is deprecated and will be removed in June 2024, update to use CastBrowser instead)r9   inforC   r   rN   )r   rD   rF   rH   listenerr   s        r    rN   zCastListener.__init__  sO     	l	
 	
 	
 &lO_UU"""""r#   rR   rS   )r,   r-   r.   r/   rN   r   r   s   @r    r   r     sX          <@HL>B	
# 
# 
# 
# 
# 
# 
# 
# 
# 
# 
#r#   r   cast_browserr   rc   c                    t                               d           |                     |           |                                  | S )zuStart discovering chromecasts on the network.

    Deprecated as of February 2021, will be removed in June 2024.
    zjstart_discovery is deprecated and will be removed in June 2024, call CastBrowser.start_discovery() instead)r9   r  r   r   )r  r   s     r    r   r     sL     LLt   &&'8999  """r#   r   c                b    t                               d           |                                  dS )znStop the chromecast discovery threads.

    Deprecated as of February 2021, will be removed in June 2024.
    zhstop_discovery is deprecated and will be removed in June 2024, call CastBrowser.stop_discovery() insteadN)r9   r  r   )r  s    r    r   r     s7    
 LLr   !!!!!r#   max_devices
int | Noner   floatr   r   r   "tuple[list[CastInfo], CastBrowser]c                z    t                               d           d	 fd}t          j                    |pt	          j                    }t          t          |          ||                                           	                    |           t          j                                                  fS )
a  
    Discover chromecasts on the network.

    Deprecated as of February 2021, will be removed in June 2024.


    Returns a tuple of:
      A list of chromecast devices, or an empty list if no chromecasts were found.
      A service browser to keep the Chromecast mDNS data updated. When updates
      are (no longer) needed, call browser.stop_discovery().

    :param zeroconf_instance: An existing zeroconf instance.
    zgdiscover_chromecasts is deprecated and will be removed in June 2024, update to use CastBrowser instead._uuidr   _servicer   r   r   c                R    !j         k    r                                 dS dS dS )z1Called when a new chromecast has been discovered.N)r   r   )r  r  browserdiscover_completer  s     r    rD   z*discover_chromecasts.<locals>.add_callback  s;    "w}'C'C!!##### #"'C'Cr#   )r  r   r  r   r   r   )r9   r  r   r   r   Zeroconfr   rC   r   r   r   rW   values)r  r   r   r   rD   ru   r  r  s   `     @@r    discover_chromecastsr    s    ( LLq  $ $ $ $ $ $ $ $
 "))4!2!4!4E,\::E;OOG 7###''))**G44r#   friendly_namesr   list[UUID] | Nonediscovery_timeoutc                H   	 i d	 fd}t          j                    	|pt          j                    }t	          t          |          ||                                           	                    |           t          	                                          fS )	a  
    Searches the network for chromecast devices matching a list of friendly
    names or a list of UUIDs.

    Returns a tuple of:
      A list of chromecast devices matching the criteria,
      or an empty list if no matching chromecasts were found.
      A service browser to keep the Chromecast mDNS data updated. When updates
      are (no longer) needed, call browser.stop_discovery().

    :param friendly_names: A list of wanted friendly names
    :param uuids: A list of wanted uuids
    :param discovery_timeout: A floating point number specifying the time to wait
                               devices matching the criteria have been found.
    :param zeroconf_instance: An existing zeroconf instance.
    r   r   r   r   r   r   c                L   t                               d| |           j        |          }|j        }r)| v r%j        |          | <                       |            r)|v r%j        |          | <                       |           ss                                 d S d S d S )NzGot cast %s, %s)r9   r:   rW   r   ri   r   )	r   r   r$   r   r  cc_listr  r  r   s	       r    rD   z1discover_listed_chromecasts.<locals>.add_callback  s    'w777OD)	!/ 	TU]]#OD1GDMLL 	1m~==#OD1GDM!!-000 	$e 	$!!#####	$ 	$ 	$ 	$r#   r*   )
r   r   r   r  r   rC   r   r   r   r  )
r  r   r  r   r   rD   ru   r  r  r  s
   ``     @@@r    discover_listed_chromecastsr    s    0 %'G$ $ $ $ $ $ $ $ $ $ "))4!2!4!4E,\::E;OOG ,---!!""G,,r#   )r2   r   r3   r4   r5   r   r   r6   )r=   r   r   r6   )r  r   r   rc   r   r   )r  r   r   r   )
r  r  r   r  r   r   r   r   r   r	  )r  r   r   r  r  r  r   r   r   r   r   r	  )4r/   
__future__r   r0   collections.abcr   r   r   loggingsslr   r   r   r   r   constr   r   r	   r
   dialr   r   r   modelsr   r   r   r   DISCOVER_TIMEOUTr@   	getLoggerr,   r9   ABCr   r<   rA   rC   ServiceListenerrU   r   r   r   ThreadrZ   r   r   r   r   r  r  r   r#   r    <module>r&     s"   ? ? " " " " " " 



 $ $ $ $ $ $          



             J J J J J J J J J J J J H H H H H H H H H H O O O O O O O O O O O O  		' #
 '
H
%
%    37   <      1 1 1 1 1- 1 1 14l l l l lx/ l l l^                  S S S S S)" S S SlH! H! H! H! H! H! H! H!V# # # # #; # # #&   " " " " #%26$(	%5 %5 %5 %5 %5R (,#/26$(/- /- /- /- /- /- /-r#   