cheofusi/just_playback

issue when continually pausing and playing just_playback.ma_result.MiniaudioError: MA_INVALID_OPERATION

Closed this issue · 2 comments

First thank you so much for this module, it is everything I need and more! So simple to use thanks.

However, I'm getting the following error:

Traceback (most recent call last): File "/home/forgetmenot/forgetmenot/forgetmenot_reader_v3.py", line 110, in <module> players[audio_filename_wav].pause() File "/home/forgetmenot/pythonEnv/lib/python3.11/site-packages/just_playback/playback.py", line 107, in pause self.__bind(lib.stop_audio_stream(self.__ma_attrs)) File "/home/forgetmenot/pythonEnv/lib/python3.11/site-packages/just_playback/playback.py", line 235, in __bind raise MiniaudioError(MA_RESULT_STR[ma_res]) just_playback.ma_result.MiniaudioError: MA_INVALID_OPERATION

Some context:
I am reading an NFC card, when the card is first presented I use .play()
When the card is removed from the reader the .pause() is called.
Once the the NFC card if back I use .paused to call .resume()

I've tried to recreate the issue in interactive python3 terminal

If I spam player.play() over and over again whilst its playing it eventually causes the issue.

This is my relevant code:

import RPi.GPIO as GPIO
import MFRC522
import os
import time
from just_playback import Playback
from glob import glob

# Create an object of the class MFRC522
MIFAREReader = MFRC522.MFRC522()

# Welcome message
print("Welcome to the MFRC522 data read example")
print("Press Ctrl-C to stop.")

# create a dictionary to store the different players
# if any wavs store
players = {}
for wav in glob('*.wav'):
    players[wav] = Playback()
    players[wav].load_file(wav)
print('Loaded all wav files')

audio_filename_wav = False

try:
    while True:
        # Scan for cards
        (status, TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)

        # If a card is found
        if status == MIFAREReader.MI_OK:
            # Get the UID of the card
            (status, uid) = MIFAREReader.MFRC522_SelectTagSN()
            
            # If we have the UID, continue
            if status == MIFAREReader.MI_OK:
                # want to convert to hex nums to match audio
                hex_nums = []
                for number in uid:
                    hex_nums.append(f'{number:x}')
                audio_filename_m4a = f"{''.join(hex_nums)}.m4a"
                audio_filename_wav = f"{''.join(hex_nums)}.wav"

                wavFileExists = False

                if os.path.exists(audio_filename_wav):
                    wavFileExists = True
                    try:
                        # play if it isn't playing or paused from start
                        if players[audio_filename_wav].active is False:
                            try:
                                players[audio_filename_wav].play()
                            except  just_playback.ma_result.MiniaudioError:
                                continue
                        
                        # if its paused then resume playing
                        if players[audio_filename_wav].paused:
                            try:
                                players[audio_filename_wav].resume()
                            except just_playback.ma_result.MiniaudioError:
                                continue
                        
                        # wait 0.2 of a second to make sure the scan doesn't spam reads
                        time.sleep(0.2)
                        # take the time
                        start = time.time()
                        print('play')
                    except AttributeError:
                        players[audio_filename_wav] = Playback()
                        players[audio_filename_wav].load_file(audio_filename_wav)
                else:
                    print(f'No {audio_filename_wav} file')
         
            else:
                print("Authentication error")
        
        if audio_filename_wav is not False:
            if players[audio_filename_wav].paused is False and players[audio_filename_wav].playing is True:
                end = time.time()
                length = end - start
                print(length)
                # if number of nanoseconds is above 10 pause play
                if length > 0.2:
                    players[audio_filename_wav].pause()
                    print(f'{audio_filename_wav} paused')
     
finally:
    GPIO.cleanup()
    print('Cleaned up')

Any help would be greatly appreciated! I'm happy to either try and handle the error? Or work around the error somehow

Hi Henry,

Please avoid creating to many Playback objects as each represents an independent audio thread and you're guaranteed to run out resources.

You could instead have one Playback object and then load the appropriate audio file on demand. Loading a file automatically kills any ongoing playback.

Hey Cheofusi,

That's fixed the error yes! I think I was just going about it wrong. Thanks for your help!