Skip to content

Fix Issue #29 Fix error when you have non-ascii (eg. Cyrillic) characters in the path to the mediafile#32

Closed
insolor wants to merge 2 commits into
TaylorSMarks:masterfrom
insolor:master
Closed

Fix Issue #29 Fix error when you have non-ascii (eg. Cyrillic) characters in the path to the mediafile#32
insolor wants to merge 2 commits into
TaylorSMarks:masterfrom
insolor:master

Conversation

@insolor
Copy link
Copy Markdown

@insolor insolor commented Jun 12, 2019

No description provided.

@ghost
Copy link
Copy Markdown

ghost commented Oct 14, 2019

Why it's not accepted yet?

@insolor
Copy link
Copy Markdown
Author

insolor commented Oct 14, 2019

@tdakkota see this discussion: #29

Copy link
Copy Markdown

@tkp30 tkp30 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import playsound
playsound.playsound("tts.mp3")
Traceback (most recent call last):
File "", line 1, in
File "D:\Python\Python37\lib\site-packages\playsound.py", line 35, in _playsoundWin
winCommand('open "' + sound + '" alias', alias)
File "D:\Python\Python37\lib\site-packages\playsound.py", line 31, in winCommand
raise PlaysoundException(exceptionMessage)
playsound.PlaysoundException:
Error 277 for command:
open "tts.mp3" alias playsound_0.3437596793925783
初始化 MCI 时发生问题。
playsound.playsound("hello.mp3")
Traceback (most recent call last):
File "", line 1, in
File "D:\Python\Python37\lib\site-packages\playsound.py", line 36, in _playsoundWin
winCommand('set', alias, 'time format milliseconds')
File "D:\Python\Python37\lib\site-packages\playsound.py", line 31, in winCommand
raise PlaysoundException(exceptionMessage)
playsound.PlaysoundException:
Error 263 for command:
set playsound_0.6573933232852508 time format milliseconds
指定的设备未打开,或不被 MCI 所识别。

What's this?
(Run in Windows10 Chinese version,you can translate the info.)

@insolor
Copy link
Copy Markdown
Author

insolor commented Jan 22, 2020

@XHG78999 I have no idea. These messages aren't very descriptive.

@tkp30
Copy link
Copy Markdown

tkp30 commented Jan 28, 2020

@ XHG78999我不知道。这些消息不是很描述。

Yes,I know it is not a good question,and you can read the official Microsoft C API documentation to solve the problem

@insolor
Copy link
Copy Markdown
Author

insolor commented Jan 28, 2020

The problem is that I'm not going to solve the problem: I am not using playsound at all, and I am not using Windows anymore. Sorry.

@tkp30
Copy link
Copy Markdown

tkp30 commented Jan 29, 2020

I modified the MCI instruction to make it work. Now, playsound.py looks like this.
`
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 randint
from time import sleep

def winCommand(*command):
    buf = c_buffer(512)
    command = ' '.join(command).encode('utf-16')
    #command = ' '.join(command).encode(encoding)
    errorCode = int(windll.winmm.mciSendStringW(command, buf, 511, 0))  # use widestring version of the function
    if errorCode:
        errorBuffer = c_buffer(512)
        windll.winmm.mciGetErrorStringW(errorCode, errorBuffer, 511)  # use widestring version of the function
        exceptionMessage = ('\n    Error ' + str(errorCode) + ' for command:'
                            '\n        ' + command.decode('utf-16') +
                            '\n    ' + errorBuffer.value.decode('utf-16'))
        raise PlaysoundException(exceptionMessage)
    return buf.value

#WRONG!WRONG!WRONG!
#alias = 'playsound_' + str(randint(1,1000))
winCommand('open "' + sound +'"')
#WRONG!WRONG!WRONG!
#winCommand('open "' + sound +'"'+ '" alias', alias)
#winCommand('set', alias, 'time format milliseconds')
durationInMS = winCommand('status', sound, 'length')
winCommand('play', sound)
#WRONG!WRONG!WRONG!
#winCommand('play', sound, 'from 0 to', durationInMS.decode())

if block:
    sleep(float(durationInMS)*15)

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

#Test code
#import os
#os.chdir("C:/Users/朋友的朋")

^

Chinese at there

#playsound("hello.mp3")
`
Who can pull this code?

@Salim9304
Copy link
Copy Markdown

This PR is inoperative (it actually causes a problem)

alias playsound_0.473288688209733
Указанная команда не распознана драйвером.

@Salim9304
Copy link
Copy Markdown

I modified the MCI instruction to make it work. Now, playsound.py looks like this.
`
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 randint
from time import sleep

def winCommand(*command):
    buf = c_buffer(512)
    command = ' '.join(command).encode('utf-16')
    #command = ' '.join(command).encode(encoding)
    errorCode = int(windll.winmm.mciSendStringW(command, buf, 511, 0))  # use widestring version of the function
    if errorCode:
        errorBuffer = c_buffer(512)
        windll.winmm.mciGetErrorStringW(errorCode, errorBuffer, 511)  # use widestring version of the function
        exceptionMessage = ('\n    Error ' + str(errorCode) + ' for command:'
                            '\n        ' + command.decode('utf-16') +
                            '\n    ' + errorBuffer.value.decode('utf-16'))
        raise PlaysoundException(exceptionMessage)
    return buf.value

#WRONG!WRONG!WRONG!
#alias = 'playsound_' + str(randint(1,1000))
winCommand('open "' + sound +'"')
#WRONG!WRONG!WRONG!
#winCommand('open "' + sound +'"'+ '" alias', alias)
#winCommand('set', alias, 'time format milliseconds')
durationInMS = winCommand('status', sound, 'length')
winCommand('play', sound)
#WRONG!WRONG!WRONG!
#winCommand('play', sound, 'from 0 to', durationInMS.decode())

if block:
    sleep(float(durationInMS)*15)

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

#Test code
#import os
#os.chdir("C:/Users/朋友的朋")

^

Chinese at there

#playsound("hello.mp3")
`
Who can pull this code?

err
line 36, in
winCommand('open "' + sound +'"')
NameError: name 'sound' is not defined

@TaylorSMarks
Copy link
Copy Markdown
Owner

TaylorSMarks commented Jul 5, 2020 via email

@TaylorSMarks
Copy link
Copy Markdown
Owner

This is now fixed on master. I have added in a test scenario, testBlockingCYRIL_WAV, which should ensure that it doesn't regress.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants