Hello community,
here is the log from the commit of package python-SoundCard for
openSUSE:Factory checked in at 2020-07-21 15:48:42
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-SoundCard (Old)
and /work/SRC/openSUSE:Factory/.python-SoundCard.new.3592 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-SoundCard"
Tue Jul 21 15:48:42 2020 rev:6 rq:821996 version:0.4.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-SoundCard/python-SoundCard.changes
2019-12-03 15:21:43.858524714 +0100
+++
/work/SRC/openSUSE:Factory/.python-SoundCard.new.3592/python-SoundCard.changes
2020-07-21 15:50:20.708292311 +0200
@@ -1,0 +2,10 @@
+Tue Jul 21 05:39:41 UTC 2020 - Steve Kowalik <[email protected]>
+
+- Update to 0.4.0:
+ * fixes silent recordings on Windows
+ * get and set the pulseaudio program name on Linux
+ * fixes error with unicode soundcard names on Windows
+ * adds support for pyinstaller (v4)
+ * adds compatibility with Windows 7
+
+-------------------------------------------------------------------
Old:
----
SoundCard-0.3.3.tar.gz
New:
----
SoundCard-0.4.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-SoundCard.spec ++++++
--- /var/tmp/diff_new_pack.wpbUlV/_old 2020-07-21 15:50:22.172294121 +0200
+++ /var/tmp/diff_new_pack.wpbUlV/_new 2020-07-21 15:50:22.176294126 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-SoundCard
#
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -19,11 +19,10 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%define skip_python2 1
Name: python-SoundCard
-Version: 0.3.3
+Version: 0.4.0
Release: 0
Summary: Python package to play and record audio
License: BSD-3-Clause
-Group: Development/Languages/Python
URL: https://github.com/bastibe/SoundCard
Source0:
https://files.pythonhosted.org/packages/source/S/SoundCard/SoundCard-%{version}.tar.gz
Source1:
https://raw.githubusercontent.com/bastibe/SoundCard/master/LICENSE
++++++ SoundCard-0.3.3.tar.gz -> SoundCard-0.4.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/SoundCard-0.3.3/PKG-INFO new/SoundCard-0.4.0/PKG-INFO
--- old/SoundCard-0.3.3/PKG-INFO 2019-10-08 10:29:17.000000000 +0200
+++ new/SoundCard-0.4.0/PKG-INFO 2020-05-26 08:39:19.095513000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.2
Name: SoundCard
-Version: 0.3.3
+Version: 0.4.0
Summary: Play and record audio without resorting to CPython extensions
Home-page: https://github.com/bastibe/SoundCard
Author: Bastian Bechtold
@@ -130,6 +130,19 @@
how these buffers are handled by the operating system, though, and
might be
significantly higher.
+ Additionally, it might help to experiment with advice from here:
https://askubuntu.com/questions/707171/how-can-i-fix-choppy-audio and edit your
/etc/pulse/default.pa file to replace the line saying ::
+
+ load-module module-udev-detect
+
+ with ::
+
+ load-module module-udev-detect tsched=0
+
+ and then do not forget to restart pulseaudio with ::
+
+ pulseaudio -k
+
+
Channel Maps
------------
@@ -178,8 +191,17 @@
(Thank you, Inti Pelupessy!)
- 2019-06-18 fixes crash when opening many streams on Linux
- 2019-08-23 fixes attribute error when accessing stream state on Linux
- (Thank you, Davíð Sindri Pétursson)
+ (Thank you, Davíð Sindri Pétursson!)
- 2019-10-08 fixes inconsistent dtypes when recording on Linux
+ - 2020-01-06 fixes silent recordings on Windows
+ - 2020-04-28 get and set the pulseaudio program name on Linux
+ (Thank you, Philipp A.!)
+ - 2020-05-14 fixes error with unicode soundcard names on Windows
+ (Thank you, BAKEZQ!)
+ - 2020-05-18 adds support for pyinstaller (v4)
+ (Thank you, Bob Thomas!)
+ - 2020-05-19 adds compatibility with Windows 7
+ (Thank you, demberto!)
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
@@ -191,6 +213,7 @@
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
Classifier: Topic :: Multimedia :: Sound/Audio :: Capture/Recording
Classifier: Topic :: Multimedia :: Sound/Audio :: Players
Requires-Python: >=3.5
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/SoundCard-0.3.3/README.rst
new/SoundCard-0.4.0/README.rst
--- old/SoundCard-0.3.3/README.rst 2019-10-08 10:16:13.000000000 +0200
+++ new/SoundCard-0.4.0/README.rst 2020-05-26 08:37:41.000000000 +0200
@@ -123,6 +123,19 @@
how these buffers are handled by the operating system, though, and might be
significantly higher.
+Additionally, it might help to experiment with advice from here:
https://askubuntu.com/questions/707171/how-can-i-fix-choppy-audio and edit your
/etc/pulse/default.pa file to replace the line saying ::
+
+ load-module module-udev-detect
+
+with ::
+
+ load-module module-udev-detect tsched=0
+
+and then do not forget to restart pulseaudio with ::
+
+ pulseaudio -k
+
+
Channel Maps
------------
@@ -171,5 +184,14 @@
(Thank you, Inti Pelupessy!)
- 2019-06-18 fixes crash when opening many streams on Linux
- 2019-08-23 fixes attribute error when accessing stream state on Linux
- (Thank you, Davíð Sindri Pétursson)
+ (Thank you, Davíð Sindri Pétursson!)
- 2019-10-08 fixes inconsistent dtypes when recording on Linux
+- 2020-01-06 fixes silent recordings on Windows
+- 2020-04-28 get and set the pulseaudio program name on Linux
+ (Thank you, Philipp A.!)
+- 2020-05-14 fixes error with unicode soundcard names on Windows
+ (Thank you, BAKEZQ!)
+- 2020-05-18 adds support for pyinstaller (v4)
+ (Thank you, Bob Thomas!)
+- 2020-05-19 adds compatibility with Windows 7
+ (Thank you, demberto!)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/SoundCard-0.3.3/SoundCard.egg-info/PKG-INFO
new/SoundCard-0.4.0/SoundCard.egg-info/PKG-INFO
--- old/SoundCard-0.3.3/SoundCard.egg-info/PKG-INFO 2019-10-08
10:29:17.000000000 +0200
+++ new/SoundCard-0.4.0/SoundCard.egg-info/PKG-INFO 2020-05-26
08:39:18.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.2
Name: SoundCard
-Version: 0.3.3
+Version: 0.4.0
Summary: Play and record audio without resorting to CPython extensions
Home-page: https://github.com/bastibe/SoundCard
Author: Bastian Bechtold
@@ -130,6 +130,19 @@
how these buffers are handled by the operating system, though, and
might be
significantly higher.
+ Additionally, it might help to experiment with advice from here:
https://askubuntu.com/questions/707171/how-can-i-fix-choppy-audio and edit your
/etc/pulse/default.pa file to replace the line saying ::
+
+ load-module module-udev-detect
+
+ with ::
+
+ load-module module-udev-detect tsched=0
+
+ and then do not forget to restart pulseaudio with ::
+
+ pulseaudio -k
+
+
Channel Maps
------------
@@ -178,8 +191,17 @@
(Thank you, Inti Pelupessy!)
- 2019-06-18 fixes crash when opening many streams on Linux
- 2019-08-23 fixes attribute error when accessing stream state on Linux
- (Thank you, Davíð Sindri Pétursson)
+ (Thank you, Davíð Sindri Pétursson!)
- 2019-10-08 fixes inconsistent dtypes when recording on Linux
+ - 2020-01-06 fixes silent recordings on Windows
+ - 2020-04-28 get and set the pulseaudio program name on Linux
+ (Thank you, Philipp A.!)
+ - 2020-05-14 fixes error with unicode soundcard names on Windows
+ (Thank you, BAKEZQ!)
+ - 2020-05-18 adds support for pyinstaller (v4)
+ (Thank you, Bob Thomas!)
+ - 2020-05-19 adds compatibility with Windows 7
+ (Thank you, demberto!)
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
@@ -191,6 +213,7 @@
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
Classifier: Topic :: Multimedia :: Sound/Audio :: Capture/Recording
Classifier: Topic :: Multimedia :: Sound/Audio :: Players
Requires-Python: >=3.5
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/SoundCard-0.3.3/SoundCard.egg-info/SOURCES.txt
new/SoundCard-0.4.0/SoundCard.egg-info/SOURCES.txt
--- old/SoundCard-0.3.3/SoundCard.egg-info/SOURCES.txt 2019-10-08
10:29:17.000000000 +0200
+++ new/SoundCard-0.4.0/SoundCard.egg-info/SOURCES.txt 2020-05-26
08:39:18.000000000 +0200
@@ -3,6 +3,7 @@
SoundCard.egg-info/PKG-INFO
SoundCard.egg-info/SOURCES.txt
SoundCard.egg-info/dependency_links.txt
+SoundCard.egg-info/entry_points.txt
SoundCard.egg-info/requires.txt
SoundCard.egg-info/top_level.txt
soundcard/__init__.py
@@ -12,4 +13,8 @@
soundcard/mediafoundation.py
soundcard/mediafoundation.py.h
soundcard/pulseaudio.py
-soundcard/pulseaudio.py.h
\ No newline at end of file
+soundcard/pulseaudio.py.h
+soundcard/__pyinstaller/__init__.py
+soundcard/__pyinstaller/conftest.py
+soundcard/__pyinstaller/hook-soundcard.py
+soundcard/__pyinstaller/test_soundcard.py
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/SoundCard-0.3.3/SoundCard.egg-info/entry_points.txt
new/SoundCard-0.4.0/SoundCard.egg-info/entry_points.txt
--- old/SoundCard-0.3.3/SoundCard.egg-info/entry_points.txt 1970-01-01
01:00:00.000000000 +0100
+++ new/SoundCard-0.4.0/SoundCard.egg-info/entry_points.txt 2020-05-26
08:39:18.000000000 +0200
@@ -0,0 +1,4 @@
+[pyinstaller40]
+hook-dirs = soundcard.__pyinstaller:get_hook_dirs
+tests = soundcard.__pyinstaller:get_test_dirs
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/SoundCard-0.3.3/SoundCard.egg-info/requires.txt
new/SoundCard-0.4.0/SoundCard.egg-info/requires.txt
--- old/SoundCard-0.3.3/SoundCard.egg-info/requires.txt 2019-10-08
10:29:17.000000000 +0200
+++ new/SoundCard-0.4.0/SoundCard.egg-info/requires.txt 2020-05-26
08:39:18.000000000 +0200
@@ -1,2 +1,2 @@
-numpy
cffi
+numpy
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/SoundCard-0.3.3/setup.py new/SoundCard-0.4.0/setup.py
--- old/SoundCard-0.3.3/setup.py 2019-10-08 10:10:49.000000000 +0200
+++ new/SoundCard-0.4.0/setup.py 2020-05-26 08:37:56.000000000 +0200
@@ -2,12 +2,12 @@
setup(
name='SoundCard',
- version='0.3.3',
+ version='0.4.0',
description='Play and record audio without resorting to CPython
extensions',
author='Bastian Bechtold',
url='https://github.com/bastibe/SoundCard',
license='BSD 3-clause',
- packages=['soundcard'],
+ packages=['soundcard', 'soundcard.__pyinstaller'],
package_data={'soundcard': ['*.py.h']},
install_requires=['numpy', 'cffi'],
python_requires='>=3.5',
@@ -21,8 +21,15 @@
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
'Topic :: Multimedia :: Sound/Audio :: Capture/Recording',
'Topic :: Multimedia :: Sound/Audio :: Players',
],
long_description=open('README.rst').read(),
+ entry_points={
+ "pyinstaller40": [
+ "hook-dirs = soundcard.__pyinstaller:get_hook_dirs",
+ "tests = soundcard.__pyinstaller:get_test_dirs",
+ ],
+ },
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/SoundCard-0.3.3/soundcard/__pyinstaller/__init__.py
new/SoundCard-0.4.0/soundcard/__pyinstaller/__init__.py
--- old/SoundCard-0.3.3/soundcard/__pyinstaller/__init__.py 1970-01-01
01:00:00.000000000 +0100
+++ new/SoundCard-0.4.0/soundcard/__pyinstaller/__init__.py 2020-05-26
08:29:37.000000000 +0200
@@ -0,0 +1,12 @@
+from os.path import dirname
+
+
+HERE = dirname(__file__)
+
+
+def get_hook_dirs():
+ return [HERE]
+
+
+def get_test_dirs():
+ return [HERE]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/SoundCard-0.3.3/soundcard/__pyinstaller/conftest.py
new/SoundCard-0.4.0/soundcard/__pyinstaller/conftest.py
--- old/SoundCard-0.3.3/soundcard/__pyinstaller/conftest.py 1970-01-01
01:00:00.000000000 +0100
+++ new/SoundCard-0.4.0/soundcard/__pyinstaller/conftest.py 2020-05-26
08:29:37.000000000 +0200
@@ -0,0 +1 @@
+from PyInstaller.utils.conftest import * # noqa
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/SoundCard-0.3.3/soundcard/__pyinstaller/hook-soundcard.py
new/SoundCard-0.4.0/soundcard/__pyinstaller/hook-soundcard.py
--- old/SoundCard-0.3.3/soundcard/__pyinstaller/hook-soundcard.py
1970-01-01 01:00:00.000000000 +0100
+++ new/SoundCard-0.4.0/soundcard/__pyinstaller/hook-soundcard.py
2020-05-26 08:29:37.000000000 +0200
@@ -0,0 +1,7 @@
+"""
+Hook for https://pypi.org/project/SoundCard/
+"""
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files('soundcard')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/SoundCard-0.3.3/soundcard/__pyinstaller/test_soundcard.py
new/SoundCard-0.4.0/soundcard/__pyinstaller/test_soundcard.py
--- old/SoundCard-0.3.3/soundcard/__pyinstaller/test_soundcard.py
1970-01-01 01:00:00.000000000 +0100
+++ new/SoundCard-0.4.0/soundcard/__pyinstaller/test_soundcard.py
2020-05-26 08:29:37.000000000 +0200
@@ -0,0 +1,6 @@
+def test_pyi_soundcard(pyi_builder):
+ pyi_builder.test_source(
+ """
+ import soundcard
+ """
+ )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/SoundCard-0.3.3/soundcard/coreaudio.py
new/SoundCard-0.4.0/soundcard/coreaudio.py
--- old/SoundCard-0.3.3/soundcard/coreaudio.py 2019-10-08 10:01:45.000000000
+0200
+++ new/SoundCard-0.4.0/soundcard/coreaudio.py 2020-04-28 16:14:27.000000000
+0200
@@ -105,6 +105,14 @@
raise IndexError('no device with id {}'.format(id))
+def get_name():
+ raise NotImplementedError()
+
+
+def set_name(name):
+ raise NotImplementedError()
+
+
class _Soundcard:
"""A soundcard. This is meant to be subclassed.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/SoundCard-0.3.3/soundcard/mediafoundation.py
new/SoundCard-0.4.0/soundcard/mediafoundation.py
--- old/SoundCard-0.3.3/soundcard/mediafoundation.py 2019-10-08
10:01:45.000000000 +0200
+++ new/SoundCard-0.4.0/soundcard/mediafoundation.py 2020-05-26
08:29:37.000000000 +0200
@@ -6,13 +6,13 @@
import time
import re
import collections
+import platform
_ffi = cffi.FFI()
_package_dir, _ = os.path.split(__file__)
with open(os.path.join(_package_dir, 'mediafoundation.py.h'), 'rt') as f:
_ffi.cdef(f.read())
-_combase = _ffi.dlopen('combase')
_ole32 = _ffi.dlopen('ole32')
class _COMLibrary:
@@ -27,7 +27,15 @@
def __init__(self):
COINIT_MULTITHREADED = 0x0
- hr = _combase.CoInitializeEx(_ffi.NULL, COINIT_MULTITHREADED)
+ if platform.win32_ver()[0] == '8':
+ # On Windows 8, according to Microsoft, the first use of
+ # IAudioClient should be from the STA thread. Calls from
+ # an MTA thread may result in undefined behavior.
+
+ # CoInitialize initialises calling thread to STA.
+ hr = _ole32.CoInitialize(_ffi.NULL)
+ else:
+ hr = _ole32.CoInitializeEx(_ffi.NULL, COINIT_MULTITHREADED)
try:
self.check_error(hr)
@@ -53,7 +61,7 @@
# Don't un-initialize COM if COM was not initialized directly
# by this class:
if self.com_loaded:
- _combase.CoUninitialize()
+ _ole32.CoUninitialize()
@staticmethod
def check_error(hresult):
@@ -174,10 +182,19 @@
IID = _ffi.new('LPIID')
# convert to zero terminated wide string
uuid = _str2wstr(uuid_str)
- hr = _combase.IIDFromString(_ffi.cast("char*", uuid), IID)
+ hr = _ole32.IIDFromString(_ffi.cast("char*", uuid), IID)
_com.check_error(hr)
return IID
+
+def get_name():
+ raise NotImplementedError()
+
+
+def set_name(name):
+ raise NotImplementedError()
+
+
class _DeviceEnumerator:
"""Wrapper class for an IMMDeviceEnumerator**.
@@ -192,7 +209,7 @@
IID_IMMDeviceEnumerator =
_guidof("{A95664D2-9614-4F35-A746-DE8DB63617E6}")
# see shared/WTypesbase.h and um/combaseapi.h:
CLSCTX_ALL = 23
- hr = _combase.CoCreateInstance(IID_MMDeviceEnumerator, _ffi.NULL,
CLSCTX_ALL,
+ hr = _ole32.CoCreateInstance(IID_MMDeviceEnumerator, _ffi.NULL,
CLSCTX_ALL,
IID_IMMDeviceEnumerator, _ffi.cast("void
**", self._ptr))
_com.check_error(hr)
@@ -303,7 +320,7 @@
"""
def __init__(self):
- self.ptr = _combase.CoTaskMemAlloc(_ffi.sizeof('PROPVARIANT'))
+ self.ptr = _ole32.CoTaskMemAlloc(_ffi.sizeof('PROPVARIANT'))
self.ptr = _ffi.cast("PROPVARIANT *", self.ptr)
def __del__(self):
@@ -511,9 +528,9 @@
# ppMixFormat[0][0].dwChannelMask=channelmask
if exclusive_mode:
- sharemode = _combase.AUDCLNT_SHAREMODE_EXCLUSIVE
+ sharemode = _ole32.AUDCLNT_SHAREMODE_EXCLUSIVE
else:
- sharemode = _combase.AUDCLNT_SHAREMODE_SHARED
+ sharemode = _ole32.AUDCLNT_SHAREMODE_SHARED
# resample | remix | better-SRC | nopersist
streamflags = 0x00100000 | 0x80000000 | 0x08000000 | 0x00080000
if isloopback:
@@ -521,7 +538,7 @@
bufferduration = int(blocksize/samplerate * 10000000) # in
hecto-nanoseconds (1000_000_0)
hr = self._ptr[0][0].lpVtbl.Initialize(self._ptr[0], sharemode,
streamflags, bufferduration, 0, ppMixFormat[0], _ffi.NULL)
_com.check_error(hr)
- _combase.CoTaskMemFree(ppMixFormat[0])
+ _ole32.CoTaskMemFree(ppMixFormat[0])
@property
def buffersize(self):
@@ -698,7 +715,12 @@
"""
+ empty_frames = 0
while not self._capture_available_frames():
+ empty_frames += 1
+ if empty_frames > 10:
+ # no data for 10 ms: give up.
+ return numpy.zeros([0], dtype='float32')
time.sleep(0.001)
data_ptr, nframes, flags = self._capture_buffer()
if data_ptr != _ffi.NULL:
@@ -709,7 +731,7 @@
self._capture_release(nframes)
return chunk
else:
- return numpy.zeros([0])
+ return numpy.zeros([0], dtype='float32')
def record(self, numframes=None):
"""Record a block of audio data.
@@ -741,6 +763,10 @@
required_frames = numframes*len(set(self.channelmap))
while recorded_frames < required_frames:
chunk = self._record_chunk()
+ if len(chunk) == 0:
+ # no data forthcoming: return zeros
+ chunk = numpy.zeros(required_frames-recorded_frames,
+ dtype='float32')
recorded_data.append(chunk)
recorded_frames += len(chunk)
if recorded_frames > required_frames:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/SoundCard-0.3.3/soundcard/pulseaudio.py
new/SoundCard-0.4.0/soundcard/pulseaudio.py
--- old/SoundCard-0.3.3/soundcard/pulseaudio.py 2019-10-08 10:07:30.000000000
+0200
+++ new/SoundCard-0.4.0/soundcard/pulseaudio.py 2020-04-28 16:14:27.000000000
+0200
@@ -63,13 +63,35 @@
# don't need to hold the lock:
self.mainloop = _pa.pa_threaded_mainloop_new()
self.mainloop_api = _pa.pa_threaded_mainloop_get_api(self.mainloop)
- self.context = _pa.pa_context_new(self.mainloop_api, b"audio")
+ self.context = _pa.pa_context_new(self.mainloop_api,
self._infer_program_name().encode())
_pa.pa_context_connect(self.context, _ffi.NULL,
_pa.PA_CONTEXT_NOFLAGS, _ffi.NULL)
_pa.pa_threaded_mainloop_start(self.mainloop)
while self._pa_context_get_state(self.context) != _pa.PA_CONTEXT_READY:
time.sleep(0.001)
+ @staticmethod
+ def _infer_program_name():
+ """Get current progam name.
+
+ Will handle `./script.py`, `python path/to/script.py`,
+ `python -m module.submodule` and `python -c 'code(x=y)'`.
+ See https://docs.python.org/3/using/cmdline.html#interface-options
+ """
+ import sys
+ prog_name = sys.argv[0]
+ if prog_name == "-c":
+ return sys.argv[1][:30] + "..."
+ if prog_name == "-m":
+ prog_name = sys.argv[1]
+ # Usually even with -m, sys.argv[0] will already be a path,
+ # so do the following outside the above check
+ main_str = "/__main__.py"
+ if prog_name.endswith(main_str):
+ prog_name = prog_name[:-len(main_str)]
+ # Not handled: sys.argv[0] == "-"
+ return os.path.basename(prog_name)
+
def _shutdown(self):
operation = self._pa_context_drain(self.context, _ffi.NULL, _ffi.NULL)
self._block_operation(operation)
@@ -87,6 +109,34 @@
time.sleep(0.001)
@property
+ def name(self):
+ """Return application name stored in client proplist"""
+ idx = self._pa_context_get_index(self.context)
+ if idx < 0: # PA_INVALID_INDEX == -1
+ raise RuntimeError("Could not get client index of PulseAudio
context.")
+ name = None
+ @_ffi.callback("pa_client_info_cb_t")
+ def callback(context, client_info, eol, userdata):
+ nonlocal name
+ if not eol:
+ name = _ffi.string(client_info.name).decode('utf-8')
+ self._pa_context_get_client_info(self.context, idx, callback,
_ffi.NULL)
+ assert name is not None
+ return name
+
+ @name.setter
+ def name(self, name):
+ rv = None
+ @_ffi.callback("pa_context_success_cb_t")
+ def callback(context, success, userdata):
+ nonlocal rv
+ rv = success
+ self._pa_context_set_name(self.context, name.encode(), callback,
_ffi.NULL)
+ assert rv is not None
+ if rv == 0:
+ raise RuntimeError("Setting PulseAudio context name failed")
+
+ @property
def source_list(self):
"""Return a list of dicts of information about available sources."""
info = []
@@ -178,8 +228,11 @@
_pa_context_get_source_info_by_name =
_lock_and_block(_pa.pa_context_get_source_info_by_name)
_pa_context_get_sink_info_list =
_lock_and_block(_pa.pa_context_get_sink_info_list)
_pa_context_get_sink_info_by_name =
_lock_and_block(_pa.pa_context_get_sink_info_by_name)
+ _pa_context_get_client_info =
_lock_and_block(_pa.pa_context_get_client_info)
_pa_context_get_server_info =
_lock_and_block(_pa.pa_context_get_server_info)
+ _pa_context_get_index = _lock(_pa.pa_context_get_index)
_pa_context_get_state = _lock(_pa.pa_context_get_state)
+ _pa_context_set_name = _lock_and_block(_pa.pa_context_set_name)
_pa_context_drain = _lock(_pa.pa_context_drain)
_pa_context_disconnect = _lock(_pa.pa_context_disconnect)
_pa_context_unref = _lock(_pa.pa_context_unref)
@@ -345,6 +398,34 @@
raise IndexError('no soundcard with id {}'.format(id))
+def get_name():
+ """Get application name.
+
+ .. note::
+ Currently only works on Linux.
+
+ Returns
+ -------
+ name : str
+ """
+ return _pulse.name
+
+
+def set_name(name):
+ """Set application name.
+
+ .. note::
+ Currently only works on Linux.
+
+ Parameters
+ ----------
+ name : str
+ The application using the soundcard
+ will be identified by the OS using this name.
+ """
+ _pulse.name = name
+
+
class _SoundCard:
def __init__(self, *, id):
self._id = id
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/SoundCard-0.3.3/soundcard/pulseaudio.py.h
new/SoundCard-0.4.0/soundcard/pulseaudio.py.h
--- old/SoundCard-0.3.3/soundcard/pulseaudio.py.h 2019-10-08
10:01:45.000000000 +0200
+++ new/SoundCard-0.4.0/soundcard/pulseaudio.py.h 2020-04-28
16:14:27.000000000 +0200
@@ -322,7 +322,20 @@
pa_operation* pa_context_get_source_info_list(pa_context *c,
pa_source_info_cb_t cb, void *userdata);
pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char
*name, pa_source_info_cb_t cb, void *userdata);
typedef void (*pa_context_notify_cb)(pa_context *c, void *userdata);
-pa_operation *pa_context_drain(pa_context *c, pa_context_notify_cb cb, void
*userdata);
+pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb cb, void
*userdata);
+typedef void (*pa_context_success_cb_t)(pa_context *c, int success, void
*userdata);
+pa_operation* pa_context_set_name(pa_context *c, const char *name,
pa_context_success_cb_t cb, void *userdata);
+uint32_t pa_context_get_index(const pa_context *s);
+
+typedef struct pa_client_info {
+ uint32_t index;
+ const char *name;
+ uint32_t owner_module;
+ const char *driver;
+ pa_proplist *proplist;
+} pa_client_info;
+typedef void (*pa_client_info_cb_t) (pa_context *c, const pa_client_info*i,
int eol, void *userdata);
+pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx,
pa_client_info_cb_t cb, void *userdata);
typedef struct pa_server_info {
const char *user_name;