From 0827cb811986ac3bb1ee82ce704f035e8372499b Mon Sep 17 00:00:00 2001 From: Michele Date: Thu, 21 Nov 2024 00:52:23 +0100 Subject: [PATCH] Restore windows code --- playsound3/playsound3.py | 69 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/playsound3/playsound3.py b/playsound3/playsound3.py index d03a3b0..c7fc154 100755 --- a/playsound3/playsound3.py +++ b/playsound3/playsound3.py @@ -8,7 +8,6 @@ _SYSTEM = platform.system() _DOWNLOAD_CACHE = {} - class PlaysoundException(Exception): pass @@ -27,7 +26,7 @@ def playsound(sound, block: bool = True, backend: Union[str, None] = None, daemo path = _prepare_path(sound) if block: - _play(path) + _play(path) # type: ignore else: from threading import Thread thread = Thread(target=_play, args=(path,), daemon=daemon) @@ -111,6 +110,70 @@ def _playsound_alsa(sound: str) -> None: else: raise PlaysoundException(f"Backend not supported for {suffix} files") +def _playsound_gst_legacy(sound: str) -> None: + from logging import debug as logdebug + from urllib import request as urlrequest + """Play a sound using gstreamer (built-in Linux).""" + + if not sound.startswith("file://"): + sound = "file://" + urlrequest.pathname2url(sound) + + try: + import gi + except ImportError: + raise PlaysoundException("PyGObject not found. Run 'pip install pygobject'") + + # Silences gi warning + gi.require_version("Gst", "1.0") + + try: + # Gst will be available only if GStreamer is installed + from gi.repository import Gst + except ImportError: + raise PlaysoundException("GStreamer not found. Install GStreamer on your system") + + Gst.init(None) + + playbin = Gst.ElementFactory.make("playbin", "playbin") + playbin.props.uri = sound + + logdebug("gstreamer: starting playing %s", sound) + set_result = playbin.set_state(Gst.State.PLAYING) + if set_result != Gst.StateChangeReturn.ASYNC: + raise PlaysoundException("playbin.set_state returned " + repr(set_result)) + bus = playbin.get_bus() + try: + bus.poll(Gst.MessageType.EOS, Gst.CLOCK_TIME_NONE) + finally: + playbin.set_state(Gst.State.NULL) + logdebug("gstreamer: finishing play %s", sound) + + +def _send_winmm_mci_command(command): + from logging import error as logerror + from ctypes import WinDLL, create_string_buffer, c_char_p + winmm = WinDLL("winmm.dll") + buffer = create_string_buffer(255) + error_code = winmm.mciSendStringA(c_char_p(command.encode()), buffer, 254, 0) + if error_code: + logerror("MCI error code: %s", error_code) + return buffer.value + + +def _playsound_mci_winmm(sound: str) -> None: + """Play a sound utilizing windll.winmm.""" + + # Select a unique alias for the sound + from logging import debug as logdebug + from uuid import uuid4 + alias = str(uuid4()) + logdebug("winmm: starting playing %s", sound) + _send_winmm_mci_command(f'open "{sound}" type mpegvideo alias {alias}') + _send_winmm_mci_command(f"play {alias} wait") + _send_winmm_mci_command(f"close {alias}") + logdebug("winmm: finishing play %s", sound) + + def _playsound_afplay(sound: str) -> None: """Uses afplay utility (built-in macOS).""" from subprocess import run @@ -138,6 +201,8 @@ def _remove_cached_downloads(cache: Dict[str, str]) -> None: "alsa_mpg123": _playsound_alsa, "ffplay": _playsound_ffplay, "gst_play": _playsound_gst_play, + "gst_legacy": _playsound_gst_legacy, + "mci_winmm": _playsound_mci_winmm } AVAILABLE_BACKENDS = list(_BACKEND_MAPPING.keys())