153 lines
4.7 KiB
Python
153 lines
4.7 KiB
Python
import os
|
|
class PlaysoundException(Exception):
|
|
pass
|
|
|
|
def _playsoundWin(sound, block = True):
|
|
'''
|
|
Utilizes windll.winmm. Tested and known to work with MP3 and WAVE on
|
|
Windows 7 with Python 2.7. Probably works with more file formats.
|
|
Probably works on Windows XP thru Windows 10. Probably works with all
|
|
versions of Python.
|
|
|
|
Inspired by (but not copied from) Michael Gundlach <gundlach@gmail.com>'s mp3play:
|
|
https://github.com/michaelgundlach/mp3play
|
|
|
|
I never would have tried using windll.winmm without seeing his code.
|
|
'''
|
|
from ctypes import c_buffer, windll
|
|
from random import random
|
|
from time import sleep
|
|
from sys import getfilesystemencoding
|
|
# sound=r'C:\software\Anaconda/'+sound
|
|
# print(sound)
|
|
# print(os.getcwd())
|
|
def winCommand(*command):
|
|
buf = c_buffer(255)
|
|
command = ' '.join(command).encode(getfilesystemencoding())
|
|
errorCode = int(windll.winmm.mciSendStringA(command, buf, 254, 0))
|
|
if errorCode:
|
|
errorBuffer = c_buffer(255)
|
|
windll.winmm.mciGetErrorStringA(errorCode, errorBuffer, 254)
|
|
exceptionMessage = ('\n Error ' + str(errorCode) + ' for command:'
|
|
'\n ' + command.decode() +
|
|
'\n ' + errorBuffer.value.decode())
|
|
raise PlaysoundException(exceptionMessage)
|
|
return buf.value
|
|
|
|
alias = 'playsound_' + str(random())
|
|
winCommand('open "' + sound + '" alias', alias)
|
|
winCommand('set', alias, 'time format milliseconds')
|
|
durationInMS = winCommand('status', alias, 'length')
|
|
winCommand('play', alias, 'from 0 to', durationInMS.decode())
|
|
|
|
if block:
|
|
sleep(float(durationInMS) / 1000.0)
|
|
|
|
def _playsoundOSX(sound, block = True):
|
|
'''
|
|
Utilizes AppKit.NSSound. Tested and known to work with MP3 and WAVE on
|
|
OS X 10.11 with Python 2.7. Probably works with anything QuickTime supports.
|
|
Probably works on OS X 10.5 and newer. Probably works with all versions of
|
|
Python.
|
|
|
|
Inspired by (but not copied from) Aaron's Stack Overflow answer here:
|
|
http://stackoverflow.com/a/34568298/901641
|
|
|
|
I never would have tried using AppKit.NSSound without seeing his code.
|
|
'''
|
|
from AppKit import NSSound
|
|
from Foundation import NSURL
|
|
from time import sleep
|
|
|
|
if '://' not in sound:
|
|
if not sound.startswith('/'):
|
|
from os import getcwd
|
|
sound = getcwd() + '/' + sound
|
|
sound = 'file://' + sound
|
|
url = NSURL.URLWithString_(sound)
|
|
nssound = NSSound.alloc().initWithContentsOfURL_byReference_(url, True)
|
|
if not nssound:
|
|
raise IOError('Unable to load sound named: ' + sound)
|
|
nssound.play()
|
|
|
|
if block:
|
|
sleep(nssound.duration())
|
|
|
|
def _playsoundNix(sound, block=True):
|
|
"""Play a sound using GStreamer.
|
|
|
|
Inspired by this:
|
|
https://gstreamer.freedesktop.org/documentation/tutorials/playback/playbin-usage.html
|
|
"""
|
|
if not block:
|
|
raise NotImplementedError(
|
|
"block=False cannot be used on this platform yet")
|
|
|
|
# pathname2url escapes non-URL-safe characters
|
|
import os
|
|
try:
|
|
from urllib.request import pathname2url
|
|
except ImportError:
|
|
# python 2
|
|
from urllib import pathname2url
|
|
|
|
import gi
|
|
gi.require_version('Gst', '1.0')
|
|
from gi.repository import Gst
|
|
|
|
Gst.init(None)
|
|
|
|
playbin = Gst.ElementFactory.make('playbin', 'playbin')
|
|
if sound.startswith(('http://', 'https://')):
|
|
playbin.props.uri = sound
|
|
else:
|
|
playbin.props.uri = 'file://' + pathname2url(os.path.abspath(sound))
|
|
|
|
set_result = playbin.set_state(Gst.State.PLAYING)
|
|
if set_result != Gst.StateChangeReturn.ASYNC:
|
|
raise PlaysoundException(
|
|
"playbin.set_state returned " + repr(set_result))
|
|
|
|
# FIXME: use some other bus method than poll() with block=False
|
|
# https://lazka.github.io/pgi-docs/#Gst-1.0/classes/Bus.html
|
|
bus = playbin.get_bus()
|
|
bus.poll(Gst.MessageType.EOS, Gst.CLOCK_TIME_NONE)
|
|
playbin.set_state(Gst.State.NULL)
|
|
|
|
|
|
from platform import system
|
|
system = system()
|
|
|
|
if system == 'Windows':
|
|
playsound = _playsoundWin
|
|
elif system == 'Darwin':
|
|
playsound = _playsoundOSX
|
|
else:
|
|
playsound = _playsoundNix
|
|
|
|
del system
|
|
|
|
class alert_when_finished:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"images": ("IMAGE", ),
|
|
"sound_path": ("STRING", {"default": "sound_path"}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ()
|
|
FUNCTION = "alert"
|
|
|
|
OUTPUT_NODE = True
|
|
|
|
CATEGORY = "AInseven"
|
|
|
|
def alert(self, images,sound_path):
|
|
playsound(sound_path)
|
|
return (None,)
|