o
    i!                     @   s   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 deZdS )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                       s   e Zd ZdZdddddee dedef fd	d
Z fddZde	de
f fddZdefddZdefddZdefddZdd Ze
jfde	de
fddZdee	 fddZdeded efd!d"Zdeded efd#d$Zd%d& Zd'd( Z  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                   s   t  jd
i | | d | d | d | d t|p"t |d| _| jd| j | jd| j | jd| j	 | jd| j
 | jd| j t|d| _| jd| j d	S )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__r   U/home/ubuntu/.local/lib/python3.10/site-packages/pipecat/turns/user_turn_processor.pyr    @   s,   



zUserTurnProcessor.__init__c                    s$   t   I dH  |  I dH  dS )zClean up processor resources.N)r   cleanup_cleanupr+   r-   r   r/   r0   n   s   zUserTurnProcessor.cleanupframe	directionc                    s   t  ||I dH  t|tr"| ||I dH  | |I dH  n7t|tr9| ||I dH  | |I dH  n t|trP| 	|I dH  | ||I dH  n	| ||I dH  | j
|I dH  | j|I dH  dS )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+   r3   r4   r-   r   r/   r5   s   s   


zUserTurnProcessor.process_framec                    s.   | j | jI d H  | j| jI d H  d S N)r"   setuptask_managerr)   r+   r3   r   r   r/   r8      s   zUserTurnProcessor._startc                       |   I d H  d S r;   r1   r>   r   r   r/   r9         zUserTurnProcessor._stopc                    r?   r;   r@   r>   r   r   r/   r:      rA   zUserTurnProcessor._cancelc                    s&   | j  I d H  | j I d H  d S r;   )r"   r0   r)   r2   r   r   r/   r1      s   zUserTurnProcessor._cleanupc                    s   |  ||I d H  d S r;   )r7   )r+   
controllerr3   r4   r   r   r/   r$      s   z UserTurnProcessor._on_push_frame	frame_clsc                    s   | j |fi |I d H  d S r;   )broadcast_frame)r+   rB   rC   r,   r   r   r/   r%      s   z%UserTurnProcessor._on_broadcast_framerB   strategyparamsc                    sr   t |  d| d |jr| tI d H  | jt I d H  |jr.| jr.| 	 I d H  | 
d|I d H  d S )Nz#: User started speaking (strategy: )r   )r   debugenable_user_speaking_framesrD   r	   r)   r5   enable_interruptions_allow_interruptionsbroadcast_interruption_call_event_handlerr+   rB   rE   rF   r   r   r/   r&      s   z'UserTurnProcessor._on_user_turn_startedc                    sX   t |  d| d |jr| tI d H  | jt I d H  | d|I d H  d S )Nz#: User stopped speaking (strategy: rG   r   )r   rH   rI   rD   r
   r)   r5   rM   rN   r   r   r/   r'      s   z'UserTurnProcessor._on_user_turn_stoppedc                       |  dI d H  d S )Nr   rM   r+   rB   r   r   r/   r(         z,UserTurnProcessor._on_user_turn_stop_timeoutc                    rO   )Nr   rP   rQ   r   r   r/   r*      rR   z$UserTurnProcessor._on_user_turn_idle)!__name__
__module____qualname____doc__r   r   floatr    r0   r   r   r5   r   r8   r   r9   r   r:   r1   
DOWNSTREAMr$   r   r%   r   r   r   r&   r   r   r'   r(   r*   __classcell__r   r   r-   r/   r      sR    %."


r   N)rV   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   r   r   r/   <module>   s    