Add type stubs for mido MIDI library
- Created type stubs for various modules in the mido library including messages, midifiles, parser, ports, sockets, syx, tokenizer, and version. - Implemented type hints for functions and classes to improve type checking and code clarity. - Added support for MIDI over TCP/IP in sockets module. - Included methods for reading and writing SYX files in syx module. - Enhanced the parser functionality with a dedicated Parser class for MIDI byte streams. - Established a structure for MIDI file handling with MidiFile and MidiTrack classes.
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
"""
|
||||
MIDI file reading and playback.
|
||||
|
||||
References:
|
||||
|
||||
http://home.roadrunner.com/~jgglatt/
|
||||
http://home.roadrunner.com/~jgglatt/tech/miditech.htm
|
||||
http://home.roadrunner.com/~jgglatt/tech/midifile.htm
|
||||
|
||||
http://www.sonicspot.com/guide/midifiles.html
|
||||
http://www.ccarh.org/courses/253/assignment/midifile/
|
||||
https://code.google.com/p/binasc/wiki/mainpage
|
||||
http://stackoverflow.com/questions/2984608/midi-delta-time
|
||||
http://www.recordingblogs.com/sa/tabid/82/EntryId/44/MIDI-Part-XIII-Delta-time-a
|
||||
http://www.sonicspot.com/guide/midifiles.html
|
||||
"""
|
||||
|
||||
from collections.abc import Callable, Generator, Iterable, Sequence
|
||||
from numbers import Real
|
||||
from typing import IO, Literal, Never, Self, overload
|
||||
|
||||
from ..messages import BaseMessage, Message
|
||||
from .meta import MetaMessage, UnknownMetaMessage
|
||||
from .tracks import MidiTrack
|
||||
|
||||
type _RealNumber = int | float | Real
|
||||
|
||||
# The default tempo is 120 BPM.
|
||||
# (500000 microseconds per beat (quarter note).)
|
||||
DEFAULT_TEMPO: int = 500000
|
||||
DEFAULT_TICKS_PER_BEAT: int = 480
|
||||
|
||||
# Maximum message length to attempt to read.
|
||||
MAX_MESSAGE_LENGTH: int = 1000000
|
||||
|
||||
def print_byte(byte: int, pos: int = 0) -> None: ...
|
||||
|
||||
class DebugFileWrapper:
|
||||
def __init__(self, file: IO[bytes]) -> None: ...
|
||||
def read(self, size: int) -> bytes: ...
|
||||
def tell(self) -> int: ...
|
||||
|
||||
def read_byte(self: IO[bytes]) -> int: ...
|
||||
def read_bytes(infile: IO[bytes], size: int) -> list[int]: ...
|
||||
def read_chunk_header(infile: IO[bytes]) -> tuple[str, int]: ...
|
||||
def read_file_header(infile: IO[bytes]) -> tuple[int, int, int]: ...
|
||||
def read_message(
|
||||
infile: IO[bytes], status_byte: int, peek_data: Sequence[int], delta: int, clip: bool = False
|
||||
) -> Message: ...
|
||||
def read_sysex(infile: IO[bytes], delta: int, clip: bool = False) -> Message: ...
|
||||
def read_variable_int(infile: IO[bytes]) -> int: ...
|
||||
def read_meta_message(infile: IO[bytes], delta: int) -> MetaMessage | UnknownMetaMessage: ...
|
||||
def read_track(infile: IO[bytes], debug: bool = False, clip: bool = False) -> MidiTrack: ...
|
||||
def write_chunk(outfile: IO[bytes], name: bytes, data: bytes) -> None:
|
||||
"""Write an IFF chunk to the file.
|
||||
|
||||
`name` must be a bytestring."""
|
||||
|
||||
def write_track(outfile: IO[bytes], track: Iterable[BaseMessage]) -> None: ...
|
||||
def get_seconds_per_tick(tempo: _RealNumber, ticks_per_beat: _RealNumber) -> float: ...
|
||||
|
||||
class MidiFile:
|
||||
filename: str | None
|
||||
type: Literal[0, 1, 2]
|
||||
ticks_per_beat: int
|
||||
charset: str
|
||||
debug: bool
|
||||
clip: bool
|
||||
tracks: list[MidiTrack]
|
||||
def __init__(
|
||||
self,
|
||||
filename: str | None = ...,
|
||||
file: IO[bytes] | None = ...,
|
||||
type: Literal[0, 1, 2] = 1,
|
||||
ticks_per_beat: int = DEFAULT_TICKS_PER_BEAT, # noqa: PYI011
|
||||
charset: str = "latin1",
|
||||
debug: bool = False,
|
||||
clip: bool = False,
|
||||
tracks: list[MidiTrack] | None = ...,
|
||||
) -> None: ...
|
||||
@property
|
||||
def merged_track(self) -> MidiTrack: ...
|
||||
@merged_track.deleter
|
||||
def merged_track(self) -> None: ...
|
||||
def add_track(self, name: str | None = ...) -> MidiTrack:
|
||||
"""Add a new track to the file.
|
||||
|
||||
This will create a new `MidiTrack` object and append it to the
|
||||
track list.
|
||||
"""
|
||||
|
||||
@property
|
||||
def length(self) -> int | float:
|
||||
"""Playback time in seconds.
|
||||
|
||||
This will be computed by going through every message in every
|
||||
track and adding up delta times.
|
||||
"""
|
||||
|
||||
def __iter__(self) -> Generator[Message | MetaMessage | UnknownMetaMessage, Never]: ...
|
||||
@overload
|
||||
def play(
|
||||
self, meta_messages: Literal[False] = False, now: Callable[[], float] = ...
|
||||
) -> Generator[Message, Never]: ...
|
||||
@overload
|
||||
def play(
|
||||
self, meta_messages: bool, now: Callable[[], float] = ...
|
||||
) -> Generator[Message | MetaMessage | UnknownMetaMessage, Never]: ...
|
||||
def play(
|
||||
self, meta_messages: bool = False, now: Callable[[], float] = ...
|
||||
) -> Generator[Message | MetaMessage | UnknownMetaMessage, Never]:
|
||||
"""Play back all tracks.
|
||||
|
||||
The generator will sleep between each message by
|
||||
default. Messages are yielded with correct timing. The time
|
||||
attribute is set to the number of seconds slept since the
|
||||
previous message.
|
||||
|
||||
By default you will only get normal MIDI messages. Pass
|
||||
`meta_messages=True` if you also want meta messages.
|
||||
|
||||
You will receive copies of the original messages, so you can
|
||||
safely modify them without ruining the tracks.
|
||||
|
||||
By default the system clock is used for the timing of yielded
|
||||
MIDI events. To use a different clock (e.g. to synchronize to
|
||||
an audio stream), pass `now=time_fn` where `time_fn` is a zero
|
||||
argument function that yields the current time in seconds.
|
||||
"""
|
||||
|
||||
def save(self, filename: str | None = ..., file: IO[bytes] | None = ...) -> None:
|
||||
"""Save to a file.
|
||||
|
||||
If file is passed the data will be saved to that file. This is
|
||||
typically an in-memory file or and already open file like `sys.stdout`.
|
||||
|
||||
If filename is passed the data will be saved to that file.
|
||||
|
||||
Raises `ValueError` if both file and filename are None,
|
||||
or if a type 0 file has != one track.
|
||||
"""
|
||||
|
||||
def print_tracks(self, meta_only: bool = False) -> None:
|
||||
"""Prints out all messages in a .midi file.
|
||||
|
||||
May take argument `meta_only` to show only meta messages.
|
||||
|
||||
Use:
|
||||
`print_tracks()` -> will print all messages
|
||||
`print_tracks(meta_only=True)` -> will print only MetaMessages
|
||||
"""
|
||||
|
||||
def __enter__(self) -> Self: ...
|
||||
def __exit__(self, type: object, value: object, traceback: object) -> Literal[False]: ...
|
||||
Reference in New Issue
Block a user