text: import reapy_boost
  from reapy_boost import reascript_api as RPR
  from reapy_boost.core import ReapyObject
  from reapy_boost.tools import depends_on_sws
  import typing as ty
  
  
  class Send(ReapyObject):
      """Track send.
  
      Attributes
      ----------
      index : int
          position on the track
      is_muted : bool
      is_phase_flipped : bool
      track_id : str
      type : str
          can be 'send', 'hardware' or 'receive'
      """
  
      _class_name = "Send"
  
      def __init__(
          self,
          track: ty.Optional['reapy_boost.Track'] = None,
          index: int = 0,
          track_id: ty.Optional[ty.Union[str, int]] = None,
          type: str = "send"
      ) -> None:
          if track_id is None:
              message = "One of `track` or `track_id` must be specified."
              assert track is not None, message
              track_id = track.id
          self.index = index
          self.track_id = track_id
          self.type = type
  
      def _get_int_type(self) -> int:
          types = {
              "hardware": 1,
              "send": 0,
              "receive": -1,
          }
          int_type = types[self.type]
          return int_type
  
      @property
      def _kwargs(self) -> ty.Dict[str, object]:
          return {
              "index": self.index,
              "track_id": self.track_id,
              "type": self.type
          }
  
      def delete(self) -> bool:  # type:ignore
          """
          Delete send.
          """
          RPR.RemoveTrackSend(  # type:ignore
              self.track_id, self._get_int_type(), self.index)
  
      @property
      def dest_track(self) -> 'reapy_boost.Track':
          """
          Destination track.
  
          :type: Track
          """
          pointer = self.get_info('P_DESTTRACK')
          track_id = reapy_boost.Track._get_id_from_pointer(pointer)
          return reapy_boost.Track(track_id)
  
      @reapy_boost.inside_reaper()
      def flip_phase(self) -> None:
          """
          Toggle whether phase is flipped.
          """
          self.is_phase_flipped = not self.is_phase_flipped
  
      def get_info(self, param_name: str) -> ty.Union[bool, int, str]:
          """Get raw info from GetTrackSendInfo_Value.
  
          Parameters
          ----------
          param_name : str
              B_MUTE : bool *
              B_PHASE : bool *, true to flip phase
              B_MONO : bool *
              D_VOL : double *, 1.0 = +0dB etc
              D_PAN : double *, -1..+1
              D_PANLAW : double *,1.0=+0.0db, 0.5=-6dB, -1.0 = projdef etc
              I_SENDMODE : int *, 0=post-fader, 1=pre-fx, 2=post-fx (deprecated),
                                  3=post-fx
              I_AUTOMODE : int * : automation mode (-1=use track automode,
                                  0=trim/off, 1=read, 2=touch, 3=write, 4=latch)
              I_SRCCHAN : int *, index,&1024=mono, -1 for none
              I_DSTCHAN : int *, index, &1024=mono, otherwise stereo pair,
                                  hwout:&512=rearoute
              I_MIDIFLAGS : int *, low 5 bits=source channel 0=all, 1-16,
                                  next 5 bits=dest channel, 0=orig,
                                  1-16=chan
              P_DESTTRACK : read only, returns MediaTrack *,
                                  destination track,
                                  only applies for sends/recvs
              P_SRCTRACK : read only, returns MediaTrack *,
                                  source track, only applies for sends/recvs
              P_ENV:<envchunkname : read only, returns TrackEnvelope *.
                                  Call with :<VOLENV, :<PANENV, etc appended.
  
  
          Returns
          -------
          Union[bool, track id(str)]
          """
          value = RPR.GetTrackSendInfo_Value(  # type:ignore
              self.track_id, self._get_int_type(), self.index, param_name)
          return value
  
      @depends_on_sws
      def get_sws_info(self, param_name: str) -> float:
          """Raw value from BR_GetSetTrackSendInfo.
  
          Parameters
          ----------
          param_name : str
              B_MUTE : send mute state (1.0 if muted, otherwise 0.0)
              B_PHASE : send phase state (1.0 if phase is inverted, otherwise 0.0)
              B_MONO : send mono state (1.0 if send is set to mono, otherwise 0.0)
              D_VOL : send volume (1.0=+0dB etc...)
              D_PAN : send pan (-1.0=100%L, 0=center, 1.0=100%R)
              D_PANLAW : send pan law (1.0=+0.0db, 0.5=-6dB,
                          -1.0=project default etc...)
              I_SENDMODE : send mode (0=post-fader, 1=pre-fx, 2=post-fx(deprecated),
                          3=post-fx)
              I_SRCCHAN : audio source starting channel index or -1 if audio send
                          is disabled (&1024=mono...note that in that case, when
                          reading index, you should do (index XOR 1024) to get
                          starting channel index)
              I_DSTCHAN : audio destination starting channel index (&1024=mono
                          (and in case of hardware output &512=rearoute)...
                          note that in that case, when reading index, you should do
                          (index XOR (1024 OR 512)) to get starting channel index)
              I_MIDI_SRCCHAN : source MIDI channel, -1 if MIDI send is disabled
                              (0=all, 1-16)
              I_MIDI_DSTCHAN : destination MIDI channel, -1 if MIDI send is disabled
                              (0=original, 1-16)
              I_MIDI_SRCBUS : source MIDI bus, -1 if MIDI send is disabled
                              (0=all, otherwise bus index)
              I_MIDI_DSTBUS : receive MIDI bus, -1 if MIDI send is disabled
                              (0=all, otherwise bus index)
              I_MIDI_LINK_VOLPAN : link volume/pan controls to MIDI
  
          Returns
          -------
          float
          """
          value = RPR.BR_GetSetTrackSendInfo(  # type:ignore
              self.track_id, self._get_int_type(), self.index, param_name, False,
              0.0)
          return value
  
      @property
      def is_mono(self) -> bool:
          """
          Whether send is mono or stereo.
  
          :type: bool
          """
          is_mono = bool(self.get_info("B_MONO"))
          return is_mono
  
      @is_mono.setter
      def is_mono(self, mono: bool) -> None:
          self.set_info("B_MONO", mono)
  
      @property
      def is_muted(self) -> bool:
          """
          Whether send is muted.
  
          :type: bool
          """
          is_muted = bool(self.get_info("B_MUTE"))
          return is_muted
  
      @is_muted.setter
      def is_muted(self, is_muted: bool) -> None:
          """
          Mute or unmute send.
  
          Parameters
          ----------
          is_muted : bool
              Whether to mute or unmute send.
          """
          self.set_info("B_MUTE", is_muted)
  
      @property
      def is_phase_flipped(self) -> bool:
          """
          Whether send phase is flipped (i.e. signal multiplied by -1).
  
          :type: bool
          """
          is_phase_flipped = bool(self.get_info("B_PHASE"))
          return is_phase_flipped
  
      @is_phase_flipped.setter
      def is_phase_flipped(self, flipped: bool) -> None:
          self.set_info("B_PHASE", flipped)
  
      @property
      def _midi_flags_unpacked(
          self
      ) -> ty.Tuple[ty.Tuple[int, int], ty.Tuple[int, int]]:
          flags = int(self.get_info('I_MIDIFLAGS'))
          if flags == 0b1111111100000000011111:
              return ((-1, -1), (-1, -1))
          ch_flags = flags % 0b10000000000
          bus_flags = flags >> 14
          # bus
          src_bus = bus_flags % 0b100000
          dst_bus = bus_flags >> 8
          # channel
          src_ch = ch_flags % 0b100000
          dst_ch = ch_flags >> 5
  
          return ((src_bus, src_ch), (dst_bus, dst_ch))
  
      @_midi_flags_unpacked.setter
      def _midi_flags_unpacked(
          self, in_tuple: ty.Tuple[ty.Tuple[int, int], ty.Tuple[int, int]]
      ) -> None:
          src_bus, src_ch, dst_bus, dst_ch = (*in_tuple[0], *in_tuple[1])
          dst_ch <<= 5
          src_bus <<= 14
          dst_bus <<= 22
          flags = src_bus | src_ch | dst_bus | dst_ch
          if flags == -1:
              flags = 0b1111111100000000011111
          self.set_info('I_MIDIFLAGS', flags)
  
      @property
      def midi_source(self) -> ty.Tuple[int, int]:
          """
          Send MIDI properties on the send track.
  
          Returns
          -------
          Tuple[int bus, int channel]
          """
          return self._midi_flags_unpacked[0]
  
      @midi_source.setter
      def midi_source(self, source: ty.Tuple[int, int]) -> None:
          return self._midi_source_inside(source)
  
      @reapy_boost.inside_reaper()
      def _midi_source_inside(self, source: ty.Tuple[int, int]) -> None:
          dest = self._midi_flags_unpacked[1]
          self._midi_flags_unpacked = (source, dest)
  
      @property
      def midi_dest(self) -> ty.Tuple[int, int]:
          """
          Send MIDI properties on the receive track.
  
          Returns
          -------
          Tuple[int bus, int channel]
          """
          return self._midi_flags_unpacked[1]
  
      @midi_dest.setter
      def midi_dest(self, dest: ty.Tuple[int, int]) -> None:
          return self._midi_dest_inside(dest)
  
      @reapy_boost.inside_reaper()
      def _midi_dest_inside(self, dest: ty.Tuple[int, int]) -> None:
          source = self._midi_flags_unpacked[0]
          self._midi_flags_unpacked = (source, dest)
  
      def mute(self) -> None:
          """
          Mute send.
          """
          self.is_muted = True
  
      @property
      def pan(self) -> float:
          """
          Send pan (from -1=left to 1=right).
  
          :type: float
          """
          pan = ty.cast(float, self.get_info("D_PAN"))
          return pan
  
      @pan.setter
      def pan(self, pan: float) -> None:
          """
          Set send pan.
  
          Parameters
          ----------
          pan : float
              New pan between -1 (left) and 1 (right).
          """
          self.set_info("D_PAN", pan)
  
      def set_info(self, param_name: str, value: ty.Union[bool, float]) -> None:
          RPR.SetTrackSendInfo_Value(  # type:ignore
              self.track_id, self._get_int_type(), self.index, param_name, value)
  
      @depends_on_sws
      def set_sws_info(
          self, param_name: str, value: ty.Union[bool, float]
      ) -> None:
          RPR.BR_GetSetTrackSendInfo(  # type:ignore
              self.track_id, self._get_int_type(), self.index, param_name, True,
              value)
  
      @property
      def source_track(self) -> 'reapy_boost.Track':
          """
          Source track.
  
          :type: Track
          """
          pointer = ty.cast(str, self.get_info('P_SRCTRACK'))
          track_id = reapy_boost.Track._get_id_from_pointer(pointer)
          return reapy_boost.Track(track_id)
  
      def unmute(self) -> None:
          """
          Unmute send.
          """
          self.is_muted = False
  
      @property
      def volume(self) -> float:
          """
          Send volume.
  
          :type: float
          """
          volume = ty.cast(float, self.get_info("D_VOL"))
          return volume
  
      @volume.setter
      def volume(self, volume: float) -> None:
          self.set_info("D_VOL", volume)
  