0

I am trying to make a simple audio player with the ability to play, stop, pause and resume songs.

What I am trying to do

  • Run the audio on a separate thread with the ability to then use MCI from the main thread to pause and resume it.

What doesn't work

  • When trying to call a function to play a song using threading or multiprocessing MCI returns an error code with a value of 263 (unfortunately there is no documentation about number error codes anywhere online that i've been able to find) and instantly ends the whole program.

What does work

  • Playing, pausing and resuming without the use of threading/multiprocessing.

My code

from ctypes import windll
import threading
import time

class WinPlayAudio():
    def __init__(self):
        self.alias = "A{}".format(id(self))

    def _MCI_command(self,command):
        windll.winmm.mciSendStringW(command,0,0,0) # If printed, this returns 263 == unrecognized audio device

    # This does not play anything even tho wait is turned to: True
    def _play(self, start=0, wait = False):
        th = threading.Thread(target=self._MCI_command, args=(f'play {self.alias} from {start} {"wait" if wait else ""}',))
        th.start()

    def _open_song(self, audio_path):
        self._MCI_command(f'open {audio_path} alias {self.alias}')
    
    def _set_volume(self):
        self._MCI_command(f'setaudio {self.alias} volume to 500')

    def _pause(self):
        self._MCI_command(f'pause {self.alias}')

    def _resume(self):
        self._MCI_command(f'resume {self.alias}')

    def _stop(self):
        self._MCI_command(f'stop {self.alias}')
    

if __name__ == '__main__':
    p = WinPlayAudio()
    p._open_song(r"D:\songs\bee.mp3")
    p._play(0, True)

1 Answers1

0

Fixed Code Stay away from aliasing if you wish to multithread

import threading
from ctypes import windll


class WinPlayAudio():
    def __init__(self):
        self.alias = "A{}".format(id(self))
        self.audio_path = ""

    def _MCI_command(self, command):
        print(command)
        err = windll.winmm.mciSendStringW(command, 0, 0, 0)  # If printed, this returns 263 == unrecognized audio device
        print(err)

    def _play(self, start=0, wait=True):
        th = threading.Thread(target=self.__play__, args=(start, wait))
        th.start()

    def __play__(self, start, wait):
        self._MCI_command(f'play {self.audio_path} from {start} {"wait" if wait else ""}', )

    def _open_song(self, audio_path):
        self.audio_path = audio_path
        self._MCI_command(f'open {audio_path} alias {self.alias}')

    def _set_volume(self):
        self._MCI_command(f'setaudio {self.alias} volume to 500')

    def _pause(self):
        self._MCI_command(f'pause {self.alias}')

    def _resume(self):
        self._MCI_command(f'resume {self.alias}')

    def _stop(self):
        self._MCI_command(f'stop {self.alias}')


if __name__ == '__main__':
    p = WinPlayAudio()
    p._open_song("start.mp3")
    p._play()