Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pygame.mixer.Channel.queue does not support pygame.mixer.Sound derivative class instances #2589

Closed
fortwoone opened this issue Nov 24, 2023 · 0 comments · Fixed by #2590
Closed
Labels
bug Not working as intended mixer pygame.mixer

Comments

@fortwoone
Copy link

If you attempt using pygame.mixer.Channel.queue with a Sound derived class, pygame will raise an error as if you didn't pass a Sound-based class at all. Here is the class I use, which netted me the error:

# _SoundBase is an alias for pygame.mixer.Sound
class Sound(_SoundBase):
    def __init__(self, file: str|ndarray|_SoundBase):
        if isinstance(file,str):
            super().__init__(resource_path(file)) # Keep the source directory in case it's needed, and use an absolute path instead of a relative one
            self.dir = file
        elif isinstance(file, _SoundBase):
            super().__init__(file) # Clone the original Sound object
        else:
            super().__init__(array=file)

    volume = property(
        _SoundBase.get_volume, _SoundBase.set_volume, doc="The current sound's volume."
    ) # Access the volume as a property for convenience.

    num_channels = property(_SoundBase.get_num_channels)

    # Convenience conversion methods
    def __bytes__(self):
        return self.get_raw()

    def __len__(self):
        return self.get_length()

    def __copy__(self):
        return self.__class__(self.dir)

    def play(self, loops: int = 0, maxtime: int = 0, fade_ms: int = 0):
        if is_played(self): # is_played is a function checking if a sound is played by at least one channel.
            super().stop() # Stop the previous playback to avoid sound overlapping
        return super().play(loops, maxtime, fade_ms)

    copy = __copy__
    __deepcopy__ = __copy__

And here is the error I got (pygame-ce 2.3.2 (SDL 2.26.5, Python 3.12.0)):

Traceback (most recent call last):
  File "C:\Users\XXXXXXX\Documents\Python\Oracle-Project\testEngine.py", line 1733, in <module>
    get_channel(wooshpart1).queue(wooshpart2) # wooshpart1 and wooshpart2 are both instances of Sound (the derived class)
TypeError: The argument must be an instance of Sound

Line 1070 in src_c/mixer.c reveals Channel.queue's code uses an exact type check instead of the usual instance verification to block non-sound classes from being queued, like this :

#define pgSound_Check(x) (Py_TYPE(x) == &pgSound_Type) //i.e. type(x) == pygame.mixer.Sound
...
if (!pgSound_Check(sound)) { //Line 1070
        return RAISE(PyExc_TypeError,
                     "The argument must be an instance of Sound");
}
@Starbuck5 Starbuck5 added bug Not working as intended mixer pygame.mixer labels Nov 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Not working as intended mixer pygame.mixer
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants