# Path: asciinema/asciicast/events.py
# def to_relative_time(
#     events: Generator[List[Any], None, None]
# ) -> Generator[List[Any], None, None]:
# def to_absolute_time(
#     events: Generator[List[Any], None, None]
# ) -> Generator[List[Any], None, None]:
# def cap_relative_time(
#     events: Generator[List[Any], None, None], time_limit: Optional[float]
# ) -> Generator[List[Any], None, None]:
# def adjust_speed(
#     events: Generator[List[Any], None, None], speed: Any
# ) -> Generator[List[Any], None, None]:
# 
# Path: asciinema/asciicast/v1.py
# class Asciicast:
#     def __init__(self, attrs: Dict[str, Any]) -> None:
#         self.version: int = 1
#         self.__attrs = attrs
#         self.idle_time_limit = None  # v1 doesn't store it
# 
#     @property
#     def v2_header(self) -> Dict[str, Any]:
#         keys = ["width", "height", "duration", "command", "title", "env"]
#         header = {
#             k: v
#             for k, v in self.__attrs.items()
#             if k in keys and v is not None
#         }
#         return header
# 
#     def __stdout_events(self) -> Generator[List[Any], None, None]:
#         for time, data in self.__attrs["stdout"]:
#             yield [time, "o", data]
# 
#     def events(self) -> Any:
#         return self.stdout_events()
# 
#     def stdout_events(self) -> Generator[List[Any], None, None]:
#         return to_absolute_time(self.__stdout_events())
# 
# Path: asciinema/asciicast/v2.py
# class Asciicast:
#     def __init__(
#         self, f: Union[TextIO, StreamReader], header: Dict[str, Any]
#     ) -> None:
#         self.version: int = 2
#         self.__file = f
#         self.v2_header = header
#         self.idle_time_limit = header.get("idle_time_limit")
# 
#     def events(self) -> Generator[Any, None, None]:
#         for line in self.__file:
#             yield json.loads(line)
# 
#     def stdout_events(self) -> Generator[List[Any], None, None]:
#         for time, type_, data in self.events():
#             if type_ == "o":
#                 yield [time, type_, data]
# 
# Path: asciinema/term.py
# class raw:
#     def __init__(self, fd: Union[IO[str], int]) -> None:
#         self.fd = fd
#         self.restore: bool = False
#         self.mode: Optional[List[Any]] = None
# 
#     def __enter__(self) -> None:
#         try:
#             self.mode = tty.tcgetattr(self.fd)
#             setraw(self.fd)
#             self.restore = True
#         except tty.error:  # this is `termios.error`
#             pass
# 
#     def __exit__(self, type_: str, value: str, traceback: str) -> None:
#         if self.restore:
#             sleep(0.01)  # give the terminal time to send answerbacks
#             assert isinstance(self.mode, list)
#             tty.tcsetattr(self.fd, tty.TCSAFLUSH, self.mode)
# 
# def read_blocking(fd: int, timeout: Any) -> bytes:
#     if fd in select.select([fd], [], [], timeout)[0]:
#         return os.read(fd, 1024)
# 
#     return b""


import sys
import time
from typing import Any, Dict, Optional, TextIO, Union
from .asciicast import events as ev
from .asciicast.v1 import Asciicast as v1
from .asciicast.v2 import Asciicast as v2
from .term import raw, read_blocking
        asciicast: Union[v1, v2],
        idle_time_limit: Optional[int] = None,
        speed: float = 1.0,
        key_bindings: Optional[Dict[str, Any]] = None,
    ) -> None:
        if key_bindings is None:
            key_bindings = {}
        try:
            with open("/dev/tty", "rt", encoding="utf-8") as stdin:
                with raw(stdin.fileno()):
                    self._play(
                        asciicast, idle_time_limit, speed, stdin, key_bindings
                    )
        except Exception:  # pylint: disable=broad-except
            self._play(asciicast, idle_time_limit, speed, None, key_bindings)

    @staticmethod
    def _play(  # pylint: disable=too-many-locals
        asciicast: Union[v1, v2],
        idle_time_limit: Optional[int],
        speed: float,
        stdin: Optional[TextIO],
        key_bindings: Dict[str, Any],
    ) -> None:
        idle_time_limit = idle_time_limit or asciicast.idle_time_limit
        pause_key = key_bindings.get("pause")
        step_key = key_bindings.get("step")

        stdout = asciicast.stdout_events()
        stdout = ev.to_relative_time(stdout)

# Path: asciinema/asciicast/events.py
# def to_relative_time(
#     events: Generator[List[Any], None, None]
# ) -> Generator[List[Any], None, None]:
# def to_absolute_time(
#     events: Generator[List[Any], None, None]
# ) -> Generator[List[Any], None, None]:
# def cap_relative_time(
#     events: Generator[List[Any], None, None], time_limit: Optional[float]
# ) -> Generator[List[Any], None, None]:
# def adjust_speed(
#     events: Generator[List[Any], None, None], speed: Any
# ) -> Generator[List[Any], None, None]:
# 
# Path: asciinema/asciicast/v1.py
# class Asciicast:
#     def __init__(self, attrs: Dict[str, Any]) -> None:
#         self.version: int = 1
#         self.__attrs = attrs
#         self.idle_time_limit = None  # v1 doesn't store it
# 
#     @property
#     def v2_header(self) -> Dict[str, Any]:
#         keys = ["width", "height", "duration", "command", "title", "env"]
#         header = {
#             k: v
#             for k, v in self.__attrs.items()
#             if k in keys and v is not None
#         }
#         return header
# 
#     def __stdout_events(self) -> Generator[List[Any], None, None]:
#         for time, data in self.__attrs["stdout"]:
#             yield [time, "o", data]
# 
#     def events(self) -> Any:
#         return self.stdout_events()
# 
#     def stdout_events(self) -> Generator[List[Any], None, None]:
#         return to_absolute_time(self.__stdout_events())
# 
# Path: asciinema/asciicast/v2.py
# class Asciicast:
#     def __init__(
#         self, f: Union[TextIO, StreamReader], header: Dict[str, Any]
#     ) -> None:
#         self.version: int = 2
#         self.__file = f
#         self.v2_header = header
#         self.idle_time_limit = header.get("idle_time_limit")
# 
#     def events(self) -> Generator[Any, None, None]:
#         for line in self.__file:
#             yield json.loads(line)
# 
#     def stdout_events(self) -> Generator[List[Any], None, None]:
#         for time, type_, data in self.events():
#             if type_ == "o":
#                 yield [time, type_, data]
# 
# Path: asciinema/term.py
# class raw:
#     def __init__(self, fd: Union[IO[str], int]) -> None:
#         self.fd = fd
#         self.restore: bool = False
#         self.mode: Optional[List[Any]] = None
# 
#     def __enter__(self) -> None:
#         try:
#             self.mode = tty.tcgetattr(self.fd)
#             setraw(self.fd)
#             self.restore = True
#         except tty.error:  # this is `termios.error`
#             pass
# 
#     def __exit__(self, type_: str, value: str, traceback: str) -> None:
#         if self.restore:
#             sleep(0.01)  # give the terminal time to send answerbacks
#             assert isinstance(self.mode, list)
#             tty.tcsetattr(self.fd, tty.TCSAFLUSH, self.mode)
# 
# def read_blocking(fd: int, timeout: Any) -> bytes:
#     if fd in select.select([fd], [], [], timeout)[0]:
#         return os.read(fd, 1024)
# 
#     return b""


# Path: asciinema/player.py
import sys
import time
from typing import Any, Dict, Optional, TextIO, Union
from .asciicast import events as ev
from .asciicast.v1 import Asciicast as v1
from .asciicast.v2 import Asciicast as v2
from .term import raw, read_blocking

        asciicast: Union[v1, v2],
        idle_time_limit: Optional[int] = None,
        speed: float = 1.0,
        key_bindings: Optional[Dict[str, Any]] = None,
    ) -> None:
        if key_bindings is None:
            key_bindings = {}
        try:
            with open("/dev/tty", "rt", encoding="utf-8") as stdin:
                with raw(stdin.fileno()):
                    self._play(
                        asciicast, idle_time_limit, speed, stdin, key_bindings
                    )
        except Exception:  # pylint: disable=broad-except
            self._play(asciicast, idle_time_limit, speed, None, key_bindings)

    @staticmethod
    def _play(  # pylint: disable=too-many-locals
        asciicast: Union[v1, v2],
        idle_time_limit: Optional[int],
        speed: float,
        stdin: Optional[TextIO],
        key_bindings: Dict[str, Any],
    ) -> None:
        idle_time_limit = idle_time_limit or asciicast.idle_time_limit
        pause_key = key_bindings.get("pause")
        step_key = key_bindings.get("step")

        stdout = asciicast.stdout_events()
        stdout = ev.to_relative_time(stdout)

        stdout = ev.cap_relative_time(stdout, idle_time_limit)