
    ^j+H                         d dl mZ d dlZd dlZd dlmZmZ d dlZd dlm	Z	 d dl
mZmZ  ed          Z G d d          Z G d	 d
e          Z G d de          Z G d d          ZdS )    )dequeN)ABCMetaabstractmethod)	AudioData)debug_printnext_or_equal_power_of_twodebug_mediac                   *    e Zd ZdZd Zd Zd Zd ZdS )SourcePrecisionBuffera7  Wrap non-precise sources that may over- or undershoot.

    This class's purpose is to always return data whose length is equal or
    less than the requested size, where less hints at definite source
    exhaustion.

    This class erases AudioData-contained timestamp/duration information and
    events.
    c                 l    t          j        |          | _        t                      | _        d| _        d S NF)weakrefproxy_source	bytearray_buffer
_exhaustedselfsources     T/home/agentuser/manim-venv/lib/python3.11/site-packages/pyglet/media/drivers/base.py__init__zSourcePrecisionBuffer.__init__   s)    }V,, {{    c                 d   | j         rd S t          | j                  |k     r|t          | j                  z
  }t          t	          d|dz                       }|||dz  |dz  f}d}d}	 |dz   dk     r|dz  }| j                            ||                   }|d| _         n5|j        dk    r|dz  }|dk    rd| _         nd}| xj        |j        z  c_        t          | j                  |k    s| j         rn| j        d |         }|sd S | j        d |= t          |t          |                    S )	Ni            r      T   )
r   lenr   r   maxr   get_audio_datalengthdatar   )r   requested_sizerequired_bytesbase_attemptattemptscur_attempt_idxempty_bailoutress           r   r"   z$SourcePrecisionBuffer.get_audio_data   sm   ? 	4t|~-- ,c$,.?.??N 6c$QS@S6T6TUUL$lL14DlUVFVWHO M"Q&**#q(Ol11(?2KLL;&*DOOZ1__!Q&M$))*.$%MLLCH,LLt|$$66$/6!$ l?N?+ 	4L.)c#hh'''r   c                 8    t          j        |          | _        d S N)r   r   r   r   s     r   
set_sourcez SourcePrecisionBuffer.set_sourceJ   s    }V,,r   c                 F    | j                                          d| _        d S r   )r   clearr   r   s    r   resetzSourcePrecisionBuffer.resetM   s!    r   N)__name__
__module____qualname____doc__r   r"   r.   r2    r   r   r   r      s[              
*( *( *(X- - -         r   r   c                   L   e Zd ZdZdZdZdZdZdZd Z	d Z
d	 Zd
 Zed             Zed             Zed             Zed             Zed             Zed             Zed             Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd&dZd Zd Z d Z!d  Z"d! Z#d" Z$d# Z%d$ Z&d% Z'dS )'AbstractAudioPlayerzBase class for driver audio players to be used by the high-level
    player. Relies on a thread to regularly call a `work` method in order
    for it to operate.
    r   gQ?gQ?g~jt?g?c                    t          j        |          | _        t          j        |          | _        |                                rdnt          |          | _        |j        }t          d|	                    | j
                            | _        t          | j        dz            | _        t                      | _        |	                    | j                  | _        |	                    | j                  | _        |	                    | j                  | _        t          | j                  | _        d| _        d| _        dS )zCreate a new audio player.

        :Parameters:
            `source` : `Source`
                Source to play from.
            `player` : `Player`
                Player to receive EOS and video frame sync events.

        Ni   gUUUUUU?)maxlenr   )r   r   r   player
is_preciser   _precision_bufferaudio_formatr!   timestamp_to_bytes_alignedaudio_buffer_length_buffered_data_ideal_sizeint _buffered_data_comfortable_limitr   _eventsaudio_desync_time_criticaldesync_bytes_criticalaudio_desync_time_minordesync_bytes_minor"audio_minor_desync_correction_timedesync_correction_bytes_minor audio_sync_required_measurementsaudio_sync_measurementsaudio_sync_cumul_measurements_compensated_bytes)r   r   r<   afmts       r   r   zAbstractAudioPlayer.__init___   s2    mF++mF++)/):):)<)<!_BWX^B_B_"),++D,DEE*
 *
& 14D4RVY4Z0[0[- ww &*%D%D+&- &-""&"A"A(#* #*-1-L-L3.5 .5* (-D4Y'Z'Z'Z$-.*
 #$r   c                     dS )zLCalled before the audio driver is going to be destroyed (a planned destroy).Nr7   r1   s    r   on_driver_destroyz%AbstractAudioPlayer.on_driver_destroy       r   c                     dS )z6Called after the audio driver has been re-initialized.Nr7   r1   s    r   on_driver_resetz#AbstractAudioPlayer.on_driver_reset   rS   r   c                 6   | j         j        |j        k    sJ |                                  t          j        |          | _         |                                r	d| _        dS | j        t          |          | _        dS | j                            |           dS )zChange the player's source for a new one.
        It must be of the same audio format.
        Will clear the player, make sure you paused it beforehand.
        N)	r   r?   r0   r   r   r=   r>   r   r.   r   s     r   r.   zAbstractAudioPlayer.set_source   s    
 {'6+>>>>>

mF++ 	6%)D"""#+%:6%B%BD""""--f55555r   c                     dS )zPrefill the audio buffer with audio data.

        This method is called before the audio player starts in order to
        have it play as soon as possible.
        Nr7   r1   s    r   prefill_audioz!AbstractAudioPlayer.prefill_audio         r   c                     dS )zRan regularly by the worker thread. This method should fill up
        the player's buffers if required, and dispatch any necessary events.
        Nr7   r1   s    r   workzAbstractAudioPlayer.work   s	     	r   c                     dS )zBegin playback.Nr7   r1   s    r   playzAbstractAudioPlayer.play   rY   r   c                     dS )zStop (pause) playback.Nr7   r1   s    r   stopzAbstractAudioPlayer.stop   rY   r   c                     | j                                          d| _        | j                                         d| _        | j        | j                                         dS dS )zClear all buffered data and prepare for replacement data.

        The player must be stopped before calling this method.
        r   N)rE   r0   rO   rM   rN   r>   r2   r1   s    r   r0   zAbstractAudioPlayer.clear   si     	"#$**,,,-.*!-"((***** .-r   c                     dS )z7Stop playing and clean up all resources used by player.Nr7   r1   s    r   deletezAbstractAudioPlayer.delete   rY   r   c                     dS )zGet this player's most recent play cursor/read index/byte offset,
        starting from the last clear operation or initialization.

        ``0`` is an acceptable return value when unavailable or unknown.
        Nr7   r1   s    r   get_play_cursorz#AbstractAudioPlayer.get_play_cursor   rY   r   c                 j    |                      |                                           | j        j        z   S )zRetrieve the time in the current source the player is at, in seconds.
        By default, calculated using :meth:`get_play_cursor`, divided by the
        bytes per second played.
        )_raw_play_cursor_to_timerd   r<   last_seek_timer1   s    r   get_timezAbstractAudioPlayer.get_time   s.     ,,T-A-A-C-CDDt{Gaaar   c                 X    |d S |                      |          | j        j        j        z  S r-   )_to_perceived_play_cursorr   r?   bytes_per_second)r   cursors     r   rf   z,AbstractAudioPlayer._raw_play_cursor_to_time   s-    >4--f558P8aaar   c                     || j         z
  S r-   )rO   )r   play_cursors     r   rj   z-AbstractAudioPlayer._to_perceived_play_cursor   s    T444r   c                 8    |D ]}|                                  dS )z7Begin simultaneous playback on a list of audio players.N)r]   r   audio_playersr<   s      r   _play_groupzAbstractAudioPlayer._play_group   ,     $ 	 	FKKMMMM	 	r   c                 8    |D ]}|                                  dS )z6Stop simultaneous playback on a list of audio players.N)r_   rp   s      r   _stop_groupzAbstractAudioPlayer._stop_group   rs   r   c                     | j         j        j        }| j        j        }|D ]S}|t          d|j        |z
            |z  z   }t          d| d|           sJ | j        	                    ||f           TdS )a8  Append the given :class:`MediaEvent`s to the events deque using
        the current source's audio format and the supplied ``start_index``
        to convert their timestamps to dispatch indices.

        The high level player's ``last_seek_time`` will be subtracted from
        each event's timestamp.
                z"AbstractAudioPlayer: Adding event z at N)
r   r?   rk   r<   rg   r!   	timestamp_debugrE   append)r   start_indexeventsbpslsteventevent_cursors          r   append_eventsz!AbstractAudioPlayer.append_events   s     k&7k( 	7 	7E&#c5?S3H*I*IC*OPLXuXX,XXYYYYYLu 56666	7 	7r   c                 "   |                      |          }| j        rn| j        d         d         |k    r[| j                                        d                             | j                   | j        r| j        d         d         |k    UdS dS dS dS )a%  Dispatch all :class:`MediaEvent`s whose index is less than or equal
        to the specified ``until_cursor`` (which should be a very recent play
        cursor position).
        Please note that :attr:`_compensated_bytes` will be subtracted from
        the passed ``until_cursor``.
        r   r   N)rj   rE   popleftsync_dispatch_to_playerr<   )r   until_cursors     r   dispatch_media_eventsz)AbstractAudioPlayer.dispatch_media_events  s     55lCCl 	Kt|Aq1\AAL  ""1%==dkJJJ l 	Kt|Aq1\AAAA 	K 	K 	K 	KAAr   c                    | j         j        }|| j        j        }|| j        j        z  }| j        j                            ||z
            }t          |          | j	        k    r$| j         
                                 d| _        |dfS t          | j                   |k    r| xj        | j         d         z  c_        | j                             |           | xj        |z  c_        t          | j                   |k    rC| j        j                            | j        |z            }t          |          | j        k    r|dfS dS )a  Query the difference between the provided time and the high
        level `Player`'s master clock.

        The time difference returned is calculated as an average on previous
        audio time differences.

        Return a tuple of the bytes the player is off by, aligned to correspond
        to an integer number of audio frames, as well as bool designating
        whether the difference is extreme. If it is, it should be rectified
        immediately and all previous measurements will have been cleared.

        This method will return ``0, False`` if the difference is not
        significant or ``audio_time`` is ``None``.

        :rtype: int, bool
        Nr   TF)r   F)rM   r;   r<   timerg   r   r?   r@   absrG   r0   rN   r    rz   alignrI   )r   
audio_timerequired_measurement_countp_time
diff_bytesavg_diffs         r   get_audio_time_diffz'AbstractAudioPlayer.get_audio_time_diff  sN   " &*%A%H"![%F$+44J1LLZZ`M`aaJ:$"<<<,22444562!4''4/004NNN22d6RST6UU22(//
;;;..*<..t+,,0JJJ{/5526PPR RH 8}}t666& xr   c                 x    | j         | j                            |          S | j                             |          S r-   )r>   r   r"   )r   r%   s     r   _get_audio_dataz#AbstractAudioPlayer._get_audio_dataM  s8    !);--n===%44^DDDr   Nc                 >   |                      |          }|                     |          \  }}|dk    r|                     |          S d}| j        j        }t          d|d|          sJ ||j        z  dk    sJ |dk    rt          ||                    d          z
  || j	                  }|                     ||z
            }||j
        |j        k     rt          d          t          j        |j        |j                  }	t          |j
        |z             }
|	||j        z  z  |
d|<   |j        |
|d<   t#          |
t%          |
          |j                  }n|dk     r|r| nt          | | j	                  }|                     ||z             }|\|j
        |k    r|j
         }d}nFt#          t          j        |j        |z   |j
        |z
            |j
        |z
  |j                  }|dz  }t          d| d	          sJ | xj        |z  c_        |S )
zE
        Retrieve a packet of `AudioData` of the given size.
        r   zAudio desync, desync_bytes=z, extreme_desync=i   NzPartial audio frame returned?zCompensated z after audio desync)rf   r   r   r   r?   ry   bytes_per_framemin
align_ceilrK   r#   RuntimeErrorctypes	string_atpointerr   r$   r   r    r|   rO   )r   r%   audio_positionr   desync_bytesextreme_desynccompensated_bytesrP   
audio_datafirst_frameads              r   _get_and_compensate_audio_dataz2AbstractAudioPlayer._get_and_compensate_audio_dataR  s    22>BB
'+'?'?
'K'K$n1''777{'I|IIIIJJJJJd22a7777!
 !$!6!662! ! --n?P.PQQJ%$t';;;&'FGGG$.z/A4CWXXz03DDEE*59JdNb9b*c1&&')3$%%&&r3r77J4EFF
A %3"],&)<-9[&\&\  --n?P.PQQJ%$(999)3):(:%!%JJ!*(&.1BB&-0AA  #),==")" "J &+%K%6KKKLLLLL#44r   c                     dS )zSee `Player.volume`.Nr7   )r   volumes     r   
set_volumezAbstractAudioPlayer.set_volume  rS   r   c                     dS )z-See :py:attr:`~pyglet.media.Player.position`.Nr7   )r   positions     r   set_positionz AbstractAudioPlayer.set_position  rS   r   c                     dS )zSee `Player.min_distance`.Nr7   )r   min_distances     r   set_min_distancez$AbstractAudioPlayer.set_min_distance  rS   r   c                     dS )zSee `Player.max_distance`.Nr7   )r   max_distances     r   set_max_distancez$AbstractAudioPlayer.set_max_distance  rS   r   c                     dS )z*See :py:attr:`~pyglet.media.Player.pitch`.Nr7   )r   pitchs     r   	set_pitchzAbstractAudioPlayer.set_pitch  rS   r   c                     dS )zSee `Player.cone_orientation`.Nr7   )r   cone_orientations     r   set_cone_orientationz(AbstractAudioPlayer.set_cone_orientation  rS   r   c                     dS )zSee `Player.cone_inner_angle`.Nr7   )r   cone_inner_angles     r   set_cone_inner_anglez(AbstractAudioPlayer.set_cone_inner_angle  rS   r   c                     dS )zSee `Player.cone_outer_angle`.Nr7   )r   cone_outer_angles     r   set_cone_outer_anglez(AbstractAudioPlayer.set_cone_outer_angle  rS   r   c                     dS )zSee `Player.cone_outer_gain`.Nr7   )r   cone_outer_gains     r   set_cone_outer_gainz'AbstractAudioPlayer.set_cone_outer_gain  rS   r   r-   )(r3   r4   r5   r6   rL   rF   rH   rJ   rA   r   rR   rU   r.   r   rX   r[   r]   r_   r0   rb   rd   rh   rf   rj   rr   ru   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r7   r   r   r9   r9   R   so        
 ()$!&#).&-$ -$ -$^    6 6 6"   ^   ^   ^ % % ^% 
+ 
+ ^
+ F F ^F
   ^b b bb b b
5 5 5    7 7 7
K 
K 
K4 4 4lE E E
C C C CJ                    r   r9   )	metaclassc                   P    e Zd Zed             Zed             Zed             ZdS )AbstractAudioDriverc                     d S r-   r7   )r   r   r<   s      r   create_audio_playerz'AbstractAudioDriver.create_audio_player  rS   r   c                     d S r-   r7   r1   s    r   get_listenerz AbstractAudioDriver.get_listener  rS   r   c                     d S r-   r7   r1   s    r   rb   zAbstractAudioDriver.delete  rS   r   N)r3   r4   r5   r   r   r   rb   r7   r   r   r   r     sc          ^   ^   ^  r   r   c                   0    e Zd ZdZdZd	dZd Zd Zd ZdS )

MediaEventa  Representation of a media event.

    These events are used internally by some audio driver implementation to
    communicate events to the :class:`~pyglet.media.player.Player`.
    One example is the ``on_eos`` event.

    Args:
        event (str): Event description.
        timestamp (float): The time when this event happens.
        *args: Any required positional argument to go along with this event.
    r   rx   argsrw   c                 0    || _         || _        || _        d S r-   r   )r   r   rx   r   s       r   r   zMediaEvent.__init__  s    
"			r   c                 T    t          j        j        j        || j        g| j        R   d S r-   )pygletappplatform_event_loop
post_eventr   r   )r   r<   s     r   r   z"MediaEvent.sync_dispatch_to_player  s,    
&1&$*QtyQQQQQQr   c                 8    d| j          d| j         d| j         dS )NzMediaEvent(z, )r   r1   s    r   __repr__zMediaEvent.__repr__  s)    ITZII4>IITYIIIIr   c                 Z    t          |t                    st          S | j        |j        k     S r-   )
isinstancer   NotImplementedrx   )r   others     r   __lt__zMediaEvent.__lt__  s)    %,, 	"!!~//r   N)rw   )	r3   r4   r5   r6   	__slots__r   r   r   r   r7   r   r   r   r     sl        
 
 -I   R R RJ J J0 0 0 0 0r   r   )collectionsr   r   r   abcr   r   r   pyglet.media.codecsr   pyglet.utilr   r   ry   r   r9   r   r   r7   r   r   <module>r      sP           ' ' ' ' ' ' ' '  ) ) ) ) ) ) ? ? ? ? ? ? ? ? 
]	#	#A  A  A  A  A  A  A  A Hg g g g gG g g g gT    G    0 0 0 0 0 0 0 0 0 0r   