Skip to content

pygame.music.Music implementation #3108

@bilhox

Description

@bilhox

Hello everyone,

As discussed on discord and on #3058 , I want to introduce a new pygame object that will help users to manipulate their musics in a better way, and also in a more pythonic way.
The goal of this issue to collect feedbacks on how it should be implemented before opening a PR for its implementation.

Implementation

pygame.Music is an alias of pygame.music.Music.
pygame.music should be an alias for pygame.mixer_music.

class Music:
    def __init__(self, path):

        self.metadata : dict
        # or
        self.title : str
        self.album : str
        self.artist : str
        self.copyright : str

        self.position : float # Settable / Gettable (set/get from where it should/is play(ing))
        self.duration : float # Read-only (returned time is in seconds just like SDL Mixer 2.6.0 functions use)
        self.playing : bool # Read-only (Could be pygame.mixer.music.is_playing(Music) ?)
        self.fade_in : float # Gettable / Settable (the value is in seconds)
        self.fade_out : float # Gettable / Settable (the value is in seconds)
        self.paused : bool # Gettable / Settable
        self.ended : bool # Read-only (True only if the position >= duration or music stopped)

        # If one day it's doable to play multiple musics at the same time, we could have
        self.volume : float # Gettable / Settable
    
    # For each method below, their equivalent in pygame.mixer.music has the same behaviour

    def play() -> None: ... 
    def rewind() -> None: ...
    def stop() -> None: ...

# New module functions
pygame.mixer_music.get_music() -> pygame.Music | None # Returns the music loaded

path is not necessary a str but support all types that pygame supported before.

I don't like how pygame.mixer.music.set|get_endevent works, it's not something the user have to setup. This is why I propose a better way IMO, when Music.stop() or pygame.mixer.music.stop() is called, or when the music ended peacefully, a pygame.MUSICENDED is sent to the event queue. This event would have a single attribute, music which is the music object that ended.

I highly support the metadata attributes than an actual metadata dict attribute, imo it doesn't look cool to write. Btw, what about an attribute for the music format type (ogg, wav, mp3 ...) ?

Why the need of this feature ?

For many reasons :

  • It helps pygame users to correctly configure their musics in a more pythonic way.
  • It allows to queue a music with specific fade_in and fade_out, which wasn't possible with the old implementation.
  • If in a future, one day, we can play multiple musics at the same time, the system would be more friendly.
  • Fixes how pygame.mixer.music.set_pos worked on the old implementation, which was definitly wrong. Also bring a homogeneous measure system (before get_pos was returning the value in ms, and set_pos needed a value in seconds).
  • So we can forget the cursed code we can see in music.c

Updates

  • Music.is_playing got renamed to Music.playing
  • MUSICENDED event could have a stopped attribute so the user can now if the music got brutally stopped by a hater or not.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions