
    qi$                        d Z ddlZddlZddlmZ ddlmZ ddlZ	ddl
mZ ddlmZmZmZmZ ddlmZ ddlmZ dd	lmZmZ 	 ddlZ	 ddlZ G d de      Z G d de      Z G d de      Z G d de      Z y# e$ r7Z ej6                  d
e         ej6                  d        ede       dZ[ww xY w# e$ r7Z ej6                  d
e         ej6                  d        ede       dZ[ww xY w)zTkinter-based local transport implementation for Pipecat.

This module provides a local transport using Tkinter for video display and
PyAudio for audio I/O, suitable for desktop applications and testing.
    N)ThreadPoolExecutor)Optional)logger)InputAudioRawFrameOutputAudioRawFrameOutputImageRawFrame
StartFrame)BaseInputTransport)BaseOutputTransport)BaseTransportTransportParamszException: z~In order to use local audio, you need to `pip install pipecat-ai[local]`. On MacOS, you also need to `brew install portaudio`.zMissing module: zOtkinter missing. Try `apt install python3-tk` or `brew install python-tk@3.10`.c                   :    e Zd ZU dZdZee   ed<   dZee   ed<   y)TkTransportParamsa  Configuration parameters for Tkinter transport.

    Parameters:
        audio_input_device_index: PyAudio device index for audio input. If None, uses default.
        audio_output_device_index: PyAudio device index for audio output. If None, uses default.
    Naudio_input_device_indexaudio_output_device_index)	__name__
__module____qualname____doc__r   r   int__annotations__r        M/opt/pipecat/venv/lib/python3.12/site-packages/pipecat/transports/local/tk.pyr   r   0   s'     /3hsm2/3x}3r   r   c                   l     e Zd ZU dZeed<   dej                  def fdZde	f fdZ
 fdZd	 Z xZS )
TkInputTransportzTkinter-based audio input transport.

    Captures audio from the system's audio input device using PyAudio and
    converts it to InputAudioRawFrame objects for pipeline processing.
    _paramspy_audioparamsc                 N    t         |   |       || _        d| _        d| _        y)zInitialize the Tkinter input transport.

        Args:
            py_audio: PyAudio instance for audio device management.
            params: Transport configuration parameters.
        Nr   )super__init__	_py_audio
_in_stream_sample_rate)selfr   r   	__class__s      r   r"   zTkInputTransport.__init__E   s(     	 !r   framec           	      F  K   t         |   |       d{    | j                  ry| j                  j                  xs |j                  | _        t        | j
                  dz        dz  }| j                  j                  | j                  j                  d      | j                  j                  | j
                  || j                  d| j                  j                        | _        | j                  j                          | j                  |       d{    y7 7 w)z~Start the audio input stream.

        Args:
            frame: The start frame containing initialization parameters.
        Nd      T)formatchannelsrateframes_per_bufferstream_callbackinputinput_device_index)r!   startr$   r   audio_in_sample_rater%   r   r#   openget_format_from_widthaudio_in_channels_audio_in_callbackr   start_streamset_transport_ready)r&   r(   
num_framesr'   s      r   r3   zTkInputTransport.startQ   s      gmE"""?? LL==[A[A[**S01A5
..-->>77:\\33""( 33#||DD . 
 	$$&&&u---' 	#& 	.s"   D!DC?D!DD!D!c                    K   t         |           d{    | j                  r<| j                  j                          | j                  j	                          d| _        yy7 Mw)z(Stop and cleanup the audio input stream.N)r!   cleanupr$   stop_streamcloser&   r'   s    r   r=   zTkInputTransport.cleanupl   sO     go??OO'')OO!!#"DO  	    A%A#AA%c                     t        || j                  | j                  j                        }t	        j
                  | j                  |      | j                                dt        j                  fS )z+Callback function for PyAudio input stream.)audiosample_ratenum_channelsN)
r   r%   r   r7   asynciorun_coroutine_threadsafepush_audio_frameget_event_looppyaudio
paContinue)r&   in_dataframe_count	time_infostatusr(   s         r   r8   z#TkInputTransport._audio_in_callbackt   s\    "))77
 	(()>)>u)EtGZGZG\]g(())r   )r   r   r   r   r   r   rJ   PyAudior"   r	   r3   r=   r8   __classcell__r'   s   @r   r   r   <   s>     
 
:K 
. .6#
*r   r   c                        e Zd ZU dZeed<   dej                  dej                  def fdZ
def fdZ fd	Zded
efdZded
efdZdefdZ xZS )TkOutputTransportzTkinter-based audio and video output transport.

    Plays audio through PyAudio and displays video frames in a Tkinter window,
    providing a complete multimedia output solution for desktop applications.
    r   tk_rootr   r   c                    t         |   |       || _        d| _        d| _        t        d      | _        t        j                  d      dz  }dd d	d d
j                         |j                  t        j                        j                         z   }t        j                  dd|d      }t        j                  ||      | _        | j                   j#                          y)zInitialize the Tkinter output transport.

        Args:
            tk_root: The root Tkinter window for video display.
            py_audio: PyAudio instance for audio device management.
            params: Transport configuration parameters.
        Nr      )max_workers)   rY         zP5 rY     255 PPMwidthheightdatar,   image)r!   r"   r#   _out_streamr%   r   	_executornponesencodeastypeuint8tobytestk
PhotoImageLabel_image_labelpack)r&   rU   r   r   arrayrb   photor'   s          r   r"   zTkOutputTransport.__init__   s     	 ! ,: (3.TF!D6'..05<<3I3Q3Q3SSDDOHHWE: r   r(   c                   K   t         |   |       d{    | j                  ry| j                  j                  xs |j                  | _        | j                  j                  | j                  j                  d      | j                  j                  | j
                  d| j                  j                        | _        | j                  j                          | j                  |       d{    y7 7 w)zStart the audio output stream.

        Args:
            frame: The start frame containing initialization parameters.
        Nr+   T)r,   r-   r.   outputoutput_device_index)r!   r3   re   r   audio_out_sample_rater%   r#   r5   r6   audio_out_channelsr   r9   r:   )r&   r(   r'   s     r   r3   zTkOutputTransport.start   s      gmE""" LL>>]%B]B]>>..>>77:\\44"" $ F F / 
 	%%'&&u---! 	#  	.s"   C9C5CC9/C70C97C9c                    K   t         |           d{    | j                  r<| j                  j                          | j                  j	                          d| _        yy7 Mw)z)Stop and cleanup the audio output stream.N)r!   r=   re   r>   r?   r@   s    r   r=   zTkOutputTransport.cleanup   sV     go((*""$#D  	 rA   returnc                    K   | j                   rR| j                         j                  | j                  | j                   j                  |j
                         d{    yy7 w)zWrite an audio frame to the output stream.

        Args:
            frame: The audio frame to write to the output device.

        Returns:
            True if the audio frame was written successfully, False otherwise.
        NTF)re   rI   run_in_executorrf   writerC   r&   r(   s     r   write_audio_framez#TkOutputTransport.write_audio_frame   sZ      %%'77 0 0 6 6   	s   AA$A"A$c                 `   K   | j                         j                  | j                  |       yw)zWrite a video frame to the Tkinter display.

        Args:
            frame: The video frame to display in the Tkinter window.

        Returns:
            True if the video frame was written successfully, False otherwise.
        T)rI   	call_soon_write_frame_to_tkr~   s     r   write_video_framez#TkOutputTransport.write_video_frame   s*      	''(?(?Gs   ,.c                    |j                   d   }|j                   d   }d| d| dj                         |j                  z   }t        j                  |||d      }| j
                  j                  |       || j
                  _        y	)
z,Write frame data to the Tkinter image label.r   rW   zP6 r\   r]   r^   r_   rc   N)sizeri   rd   rm   rn   rp   config)r&   r(   r`   ra   rb   rs   s         r   r   z$TkOutputTransport._write_frame_to_tk   s}    

1AUG1VHE*113ekkAE&tER  u - #(r   )r   r   r   r   r   r   rm   TkrJ   rP   r"   r	   r3   r=   r   boolr   r   r   r   rQ   rR   s   @r   rT   rT      sy     ! ! !J[ !0. .0$-@ T  
-@ 
T 

((; 
(r   rT   c                   X     e Zd ZdZdej
                  def fdZdefdZ	de
fdZ xZS )TkLocalTransportzComplete Tkinter-based local transport with audio and video capabilities.

    Provides a unified interface for local multimedia I/O using Tkinter for video
    display and PyAudio for audio, suitable for desktop applications and testing.
    rU   r   c                     t         |           || _        || _        t	        j
                         | _        d| _        d| _        y)zInitialize the Tkinter local transport.

        Args:
            tk_root: The root Tkinter window for video display.
            params: Transport configuration parameters.
        N)	r!   r"   _tk_rootr   rJ   rP   _pyaudio_input_output)r&   rU   r   r'   s      r   r"   zTkLocalTransport.__init__   s:     	)2648r   rz   c                 |    | j                   s%t        | j                  | j                        | _         | j                   S )zGet the input frame processor for this transport.

        Returns:
            The Tkinter input transport processor.
        )r   r   r   r   r&   s    r   r1   zTkLocalTransport.input  s+     {{*4==$,,GDK{{r   c                     | j                   s0t        | j                  | j                  | j                        | _         | j                   S )zGet the output frame processor for this transport.

        Returns:
            The Tkinter output transport processor.
        )r   rT   r   r   r   r   s    r   ru   zTkLocalTransport.output  s1     ||,T]]DMM4<<XDL||r   )r   r   r   r   rm   r   r   r"   r   r1   rT   ru   rQ   rR   s   @r   r   r      s:    9 9/@ 9&' ) r   r   )!r   rF   tkinterrm   concurrent.futuresr   typingr   numpyrg   logurur   pipecat.frames.framesr   r   r   r	   pipecat.transports.base_inputr
   pipecat.transports.base_outputr   !pipecat.transports.base_transportr   r   rJ   ModuleNotFoundErroreerror	Exceptionr   r   rT   r   r   r   r   <module>r      s     1     = > L,,	4 	4B*) B*Jg(+ g(T,} ,U  ,FLL;qc"#FLL 	I &qc*
++,  ,FLL;qc"#FLLbc
&qc*
++,s0   A8 B7 8B4=2B//B47C3<2C..C3