
    qi!                         d Z ddlmZmZ ddlmZ ddlmZmZm	Z	m
Z
mZmZ ddlmZmZ ddlmZ ddlmZmZ ddlmZmZ dd	lmZ dd
lmZ  G d de      Zy)z5Frame processor for managing the user turn lifecycle.    )OptionalType)logger)CancelFrameEndFrameFrame
StartFrameUserStartedSpeakingFrameUserStoppedSpeakingFrame)FrameDirectionFrameProcessor)UserIdleController)BaseUserTurnStartStrategyUserTurnStartedParams)BaseUserTurnStopStrategyUserTurnStoppedParams)UserTurnController)UserTurnStrategiesc                        e Zd ZdZdddddee   dedef fd	Z fd
Zde	de
f fdZdefdZdefdZdefdZd Ze
j&                  fde	de
fdZdee	   fdZdededefdZdededefdZd Zd Z xZ S )UserTurnProcessora  Frame processor for managing the user turn lifecycle.

    This processor uses a turn controller to determine when a user turn starts
    or stops. The actual frames emitted (e.g., UserStartedSpeakingFrame,
    UserStoppedSpeakingFrame) or interruptions depend on the configured
    strategies.

    Event handlers available:

    - on_user_turn_started: Emitted when a user turn starts.
    - on_user_turn_stopped: Emitted when a user turn stops.
    - on_user_turn_stop_timeout: Emitted if no stop strategy triggers before timeout.
    - on_user_turn_idle: Emitted when the user has been idle for the configured timeout.

    Example::

        @processor.event_handler("on_user_turn_started")
        async def on_user_turn_started(processor, strategy: BaseUserTurnStartStrategy):
            ...

        @processor.event_handler("on_user_turn_stopped")
        async def on_user_turn_stopped(processor, strategy: BaseUserTurnStopStrategy):
            ...

        @processor.event_handler("on_user_turn_stop_timeout")
        async def on_user_turn_stop_timeout(processor):
            ...

        @processor.event_handler("on_user_turn_idle")
        async def on_user_turn_idle(processor):
            ...

    Ng      @r   )user_turn_strategiesuser_turn_stop_timeoutuser_idle_timeoutr   r   r   c                   t        |   d
i | | j                  d       | j                  d       | j                  d       | j                  d       t        |xs
 t	               |      | _        | j
                  j                  d| j                         | j
                  j                  d| j                         | j
                  j                  d| j                         | j
                  j                  d| j                         | j
                  j                  d| j                         t        |      | _        | j                  j                  d| j                         y	)aj  Initialize the user turn processor.

        Args:
            user_turn_strategies: Configured strategies for starting and stopping user turns.
            user_turn_stop_timeout: Timeout in seconds to automatically stop a user turn
                if no activity is detected.
            user_idle_timeout: Timeout in seconds for detecting user idle state.
                The processor will emit an `on_user_turn_idle` event when the user
                has been idle (not speaking) for this duration. Set to 0 to disable
                idle detection.
            **kwargs: Additional keyword arguments.
        on_user_turn_startedon_user_turn_stoppedon_user_turn_stop_timeouton_user_turn_idle)r   r   on_push_frameon_broadcast_frame)r   N )super__init___register_event_handlerr   r   _user_turn_controlleradd_event_handler_on_push_frame_on_broadcast_frame_on_user_turn_started_on_user_turn_stopped_on_user_turn_stop_timeoutr   _user_idle_controller_on_user_turn_idle)selfr   r   r   kwargs	__class__s        S/opt/pipecat/venv/lib/python3.12/site-packages/pipecat/turns/user_turn_processor.pyr#   zUserTurnProcessor.__init__@   s6   ( 	"6"$$%;<$$%;<$$%@A$$%89%7!5!M9K9M#9&
" 	""44_dFYFYZ""445I4KcKcd""44"D$>$>	
 	""44"D$>$>	
 	""44')H)H	
 &8J[%\"""445H$JaJab    c                 r   K   t         |           d{    | j                          d{    y7 7 w)zClean up processor resources.N)r"   cleanup_cleanup)r.   r0   s    r1   r4   zUserTurnProcessor.cleanupn   s/     gommo 	 s   737577frame	directionc                   K   t         |   ||       d{    t        |t              r4| j	                  ||       d{    | j                  |       d{    nt        |t              r4| j	                  ||       d{    | j                  |       d{    n^t        |t              r4| j                  |       d{    | j	                  ||       d{    n| j	                  ||       d{    | j                  j                  |       d{    | j                  j                  |       d{    y7 27 7 7 7 7 7 t7 [7 :7 w)ar  Process an incoming frame to detect user turn start or stop.

        The frame is passed to the user turn controlled which is responsible for
        deciding when a user turn starts or stops and emitting the corresponding
        events.

        Args:
            frame: The frame to be processed.
            direction: The direction of the incoming frame.

        N)r"   process_frame
isinstancer	   
push_frame_startr   _stopr   _cancelr%   r,   )r.   r6   r7   r0   s      r1   r9   zUserTurnProcessor.process_frames   s'     g#E9555eZ( //%333++e$$$x( //%333**U###{+,,u%%%//%333//%333((66u===((66u===) 	6
 4$ 4#%33==s   EE	)EEEE*EEEE)EE	E"E#E=E>"E E!"EEEEEEEEEEEEc                    K   | j                   j                  | j                         d {    | j                  j                  | j                         d {    y 7 27 wN)r%   setuptask_managerr,   r.   r6   s     r1   r<   zUserTurnProcessor._start   sP     ((..t/@/@AAA((..t/@/@AAA 	BAs!   )A"A,A"A A" A"c                 @   K   | j                          d {    y 7 wr@   r5   rC   s     r1   r=   zUserTurnProcessor._stop        mmo   c                 @   K   | j                          d {    y 7 wr@   rE   rC   s     r1   r>   zUserTurnProcessor._cancel   rF   rG   c                    K   | j                   j                          d {    | j                  j                          d {    y 7 '7 wr@   )r%   r4   r,   )r.   s    r1   r5   zUserTurnProcessor._cleanup   s?     ((00222((00222 	32s!   AA!AA
A
Ac                 D   K   | j                  ||       d {    y 7 wr@   )r;   )r.   
controllerr6   r7   s       r1   r'   z UserTurnProcessor._on_push_frame   s      ooeY///s     	frame_clsc                 F   K    | j                   |fi | d {    y 7 wr@   )broadcast_frame)r.   rK   rL   r/   s       r1   r(   z%UserTurnProcessor._on_broadcast_frame   s!     "d""97777s   !!rK   strategyparamsc                   K   t        j                  |  d| d       |j                  r| j                  t               d {    | j
                  j                  t	                      d {    |j                  r$| j                  r| j                          d {    | j                  d|       d {    y 7 z7 Q7 #7 w)Nz#: User started speaking (strategy: )r   )r   debugenable_user_speaking_framesrN   r
   r,   r9   enable_interruptions_allow_interruptionsbroadcast_interruption_call_event_handlerr.   rK   rO   rP   s       r1   r)   z'UserTurnProcessor._on_user_turn_started   s      	v@
!LM--&&'?@@@((667O7QRRR&&4+D+D--///&&'=xHHH AR 0HsH   A CB=*C-B?./CCC7C8C?CCCc                 *  K   t        j                  |  d| d       |j                  r| j                  t               d {    | j
                  j                  t	                      d {    | j                  d|       d {    y 7 J7 !7 	w)Nz#: User stopped speaking (strategy: rR   r   )r   rS   rT   rN   r   r,   r9   rX   rY   s       r1   r*   z'UserTurnProcessor._on_user_turn_stopped   s      	v@
!LM--&&'?@@@((667O7QRRR&&'=xHHH	 ARHs6   A BB*B-B.BBBBBc                 B   K   | j                  d       d {    y 7 w)Nr   rX   r.   rK   s     r1   r+   z,UserTurnProcessor._on_user_turn_stop_timeout   s     &&'BCCC   c                 B   K   | j                  d       d {    y 7 w)Nr   r\   r]   s     r1   r-   z$UserTurnProcessor._on_user_turn_idle   s     &&':;;;r^   )!__name__
__module____qualname____doc__r   r   floatr#   r4   r   r   r9   r	   r<   r   r=   r   r>   r5   
DOWNSTREAMr'   r   r(   r   r   r   r)   r   r   r*   r+   r-   __classcell__)r0   s   @r1   r   r      s    J >B(+#$,c ''9:,c !&	,c
 !,c\
 >  >>  >DB* B ; 3
 ESD]D]0!&03A0
8tE{ 8I&I ,I &	I$I&I +I &	ID<r2   r   N)rc   typingr   r   logurur   pipecat.frames.framesr   r   r   r	   r
   r   "pipecat.processors.frame_processorr   r   "pipecat.turns.user_idle_controllerr   pipecat.turns.user_startr   r   pipecat.turns.user_stopr   r   "pipecat.turns.user_turn_controllerr   "pipecat.turns.user_turn_strategiesr   r   r!   r2   r1   <module>rp      s=    < !   N A U S A As< s<r2   