From f9d276820cef5658feb448a060e94354df6b4356 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Fri, 7 Apr 2023 23:38:28 +0200 Subject: [PATCH 01/10] :construction: Post release dev0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b300801..5583487 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ def read(fname): install_requires = ["comtypes", "psutil"] setup( name="pycaw", - version="20230407", + version="20230407.dev0", description="Python Core Audio Windows Library", long_description=read("README.md"), long_description_content_type="text/markdown", From c3cc4d78ee8f9b5e73036896988c3e88eb046080 Mon Sep 17 00:00:00 2001 From: Mike Roberts <42875462+mrob95@users.noreply.github.com> Date: Mon, 1 May 2023 13:42:47 +0100 Subject: [PATCH 02/10] fix double free due to using cast rather than QueryInterface (#74) * fix: potential double free in README example #19 * fix: potential double free in examples #19 * fix: potential double free in utils #19 --- README.md | 3 +-- examples/audio_endpoint_volume_example.py | 4 +--- examples/volume_callback_example.py | 4 +--- pycaw/utils.py | 3 +-- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index e3633ae..0f7012c 100644 --- a/README.md +++ b/README.md @@ -27,13 +27,12 @@ choco install visualcpp-build-tools ## Usage ```Python -from ctypes import cast, POINTER from comtypes import CLSCTX_ALL from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume devices = AudioUtilities.GetSpeakers() interface = devices.Activate( IAudioEndpointVolume._iid_, CLSCTX_ALL, None) -volume = cast(interface, POINTER(IAudioEndpointVolume)) +volume = interface.QueryInterface(IAudioEndpointVolume) volume.GetMute() volume.GetMasterVolumeLevel() volume.GetVolumeRange() diff --git a/examples/audio_endpoint_volume_example.py b/examples/audio_endpoint_volume_example.py index eb8bd2a..f857af8 100644 --- a/examples/audio_endpoint_volume_example.py +++ b/examples/audio_endpoint_volume_example.py @@ -1,8 +1,6 @@ """ Get and set access to master volume example. """ -from ctypes import POINTER, cast - from comtypes import CLSCTX_ALL from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume @@ -11,7 +9,7 @@ def main(): devices = AudioUtilities.GetSpeakers() interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None) - volume = cast(interface, POINTER(IAudioEndpointVolume)) + volume = interface.QueryInterface(IAudioEndpointVolume) print("volume.GetMute(): %s" % volume.GetMute()) print("volume.GetMasterVolumeLevel(): %s" % volume.GetMasterVolumeLevel()) print("volume.GetVolumeRange(): (%s, %s, %s)" % volume.GetVolumeRange()) diff --git a/examples/volume_callback_example.py b/examples/volume_callback_example.py index 13a4293..d199eb5 100644 --- a/examples/volume_callback_example.py +++ b/examples/volume_callback_example.py @@ -2,8 +2,6 @@ IAudioEndpointVolumeCallback.OnNotify() example. The OnNotify() callback method gets called on volume change. """ -from ctypes import POINTER, cast - from comtypes import CLSCTX_ALL, COMObject from pycaw.pycaw import ( @@ -23,7 +21,7 @@ def OnNotify(self, pNotify): def main(): devices = AudioUtilities.GetSpeakers() interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None) - volume = cast(interface, POINTER(IAudioEndpointVolume)) + volume = interface.QueryInterface(IAudioEndpointVolume) callback = AudioEndpointVolumeCallback() volume.RegisterControlChangeNotify(callback) for i in range(3): diff --git a/pycaw/utils.py b/pycaw/utils.py index 192f82e..8f88001 100644 --- a/pycaw/utils.py +++ b/pycaw/utils.py @@ -1,5 +1,4 @@ import warnings -from ctypes import POINTER, cast import comtypes import psutil @@ -49,7 +48,7 @@ def EndpointVolume(self): iface = self._dev.Activate( IAudioEndpointVolume._iid_, comtypes.CLSCTX_ALL, None ) - self._volume = cast(iface, POINTER(IAudioEndpointVolume)) + self._volume = iface.QueryInterface(IAudioEndpointVolume) return self._volume From 33deb7fef5ebd965df96eef7efa10ce421a01839 Mon Sep 17 00:00:00 2001 From: Yannick Linke Date: Sun, 14 May 2023 15:27:21 +0200 Subject: [PATCH 03/10] add: example for IMMNotificationClient --- examples/notification_client_example.py | 98 +++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 examples/notification_client_example.py diff --git a/examples/notification_client_example.py b/examples/notification_client_example.py new file mode 100644 index 0000000..708d59c --- /dev/null +++ b/examples/notification_client_example.py @@ -0,0 +1,98 @@ +""" +This file contains example usage of MMNotificationClient, the following +callbacks are implemented: + +:: Gets called when the state of an audio endpoint device has changed +IMMNotificationClient.OnDeviceStateChanged() +-> on_device_state_changed() + +:: Gets called when the value of an audio endpoint property has changed +IMMNotificationClient.OnPropertyValueChanged() +-> on_property_value_changed() + +https://learn.microsoft.com/en-us/windows/win32/api/mmdeviceapi/nn-mmdeviceapi-immnotificationclient + +""" + +import time + +from comtypes import GUID, COMError +from comtypes.automation import VT_BLOB +from comtypes.persist import STGM_READ + +from pycaw.callbacks import MMNotificationClient +from pycaw.utils import AudioUtilities + +known_keys = { + # Recording + "{24DBB0FC-9311-4B3D-9CF0-18FF155639D4} 0": "Playback through this device", + "{24DBB0FC-9311-4B3D-9CF0-18FF155639D4} 1": "Listen to this device", + # Playback & Recording + "{9855C4CD-DF8C-449C-A181-8191B68BD06C} 0": "Volume", + "{9855C4CD-DF8C-449C-A181-8191B68BD06C} 1": "Device muted", +} + + +class Client(MMNotificationClient): + def __init__(self): + self.enumerator = AudioUtilities.GetDeviceEnumerator() + + def on_device_state_changed(self, device_id, new_state, new_state_id): + print(f"on_device_state_changed: {device_id} {new_state} {new_state_id}") + + def on_property_value_changed(self, device_id, property_struct, fmtid, pid): + key = f"{fmtid} {pid}" + + value = self._find_property(device_id, fmtid, pid) + print( + f"on_property_value_changed: key={key} " + f"purpose=\"{known_keys.get(key, '?')}\" value={value}", + ) + + def _find_property(self, device_id: str, fmtid: GUID, pid: int) -> str | None: + """Helper function to find the value of a property""" + dev = self.enumerator.GetDevice(device_id) + store = dev.OpenPropertyStore(STGM_READ) + if store is None: + print("no store") + return + + search_value = bytes(fmtid) + for j in range(store.GetCount()): + try: + pk = store.GetAt(j) + + if not (bytes(pk.fmtid) == search_value and pk.pid == pid): + continue + + value = store.GetValue(pk) + if value.vt == VT_BLOB: + return bytes(value).hex(" ") + + return value.GetValue() + except COMError as exc: + print( + f"COMError attempting to get property {j} " + f"from device {dev}: {exc}" + ) + continue + + +def add_callback(): + cb = Client() + enumerator = AudioUtilities.GetDeviceEnumerator() + enumerator.RegisterEndpointNotificationCallback(cb) + print("registered") + + try: + # wait for callbacks + time.sleep(300) + except KeyboardInterrupt: + pass + finally: + print("unregistering") + enumerator.UnregisterEndpointNotificationCallback(cb) + + +if __name__ == "__main__": + add_callback() From 80436d06aed2e76bd2f80c55b804225487349525 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 5 Sep 2023 13:14:07 +0200 Subject: [PATCH 04/10] :memo: Update doc to https links --- docs/Release.md | 2 +- pycaw/utils.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/Release.md b/docs/Release.md index aa7322f..9ec27b7 100644 --- a/docs/Release.md +++ b/docs/Release.md @@ -5,7 +5,7 @@ This is documenting the release process. ## Git flow & CHANGELOG.md -Make sure the CHANGELOG.md is up to date and follows the http://keepachangelog.com guidelines. +Make sure the CHANGELOG.md is up to date and follows the https://keepachangelog.com guidelines. Start the release with git flow: ```batch git flow release start vYYYYMMDD diff --git a/pycaw/utils.py b/pycaw/utils.py index 8f88001..09a9b17 100644 --- a/pycaw/utils.py +++ b/pycaw/utils.py @@ -21,7 +21,7 @@ class AudioDevice: """ - http://stackoverflow.com/a/20982715/185510 + https://stackoverflow.com/a/20982715/185510 """ def __init__(self, id, state, properties, dev): @@ -54,7 +54,7 @@ def EndpointVolume(self): class AudioSession: """ - http://stackoverflow.com/a/20982715/185510 + https://stackoverflow.com/a/20982715/185510 """ def __init__(self, audio_session_control2): @@ -157,7 +157,7 @@ def unregister_notification(self): class AudioUtilities: """ - http://stackoverflow.com/a/20982715/185510 + https://stackoverflow.com/a/20982715/185510 """ @staticmethod From 1d9ea0e142f5315ab8e81b6bfacb5b708034e8a0 Mon Sep 17 00:00:00 2001 From: mltony Date: Fri, 9 Feb 2024 10:57:36 -0800 Subject: [PATCH 05/10] Adding IChannelAudioVolume --- examples/channel_audio_volume_example.py | 22 ++++++++++++++++++++++ pycaw/api/audioclient/__init__.py | 24 ++++++++++++++++++++++++ pycaw/utils.py | 8 +++++++- 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 examples/channel_audio_volume_example.py diff --git a/examples/channel_audio_volume_example.py b/examples/channel_audio_volume_example.py new file mode 100644 index 0000000..339bb84 --- /dev/null +++ b/examples/channel_audio_volume_example.py @@ -0,0 +1,22 @@ +""" +Adjusting volume of left channel using IChannelAudioVolume. +""" + +from pycaw.pycaw import AudioUtilities + + +def main(): + sessions = AudioUtilities.GetAllSessions() + for session in sessions: + volume = session.channelAudioVolume() + print(f"Session {session}") + count = volume.GetChannelCount() + volumes = [volume.GetChannelVolume(i) for i in range(count)] + print(f" volumes = {volumes}") + if count == 2: + volume.SetChannelVolume(0, 0.1, None) + print(" Set the volume of left channel to 0.5!") + + +if __name__ == "__main__": + main() diff --git a/pycaw/api/audioclient/__init__.py b/pycaw/api/audioclient/__init__.py index 4b55afb..e39d72d 100644 --- a/pycaw/api/audioclient/__init__.py +++ b/pycaw/api/audioclient/__init__.py @@ -137,3 +137,27 @@ class IAudioClient(IUnknown): (["out"], POINTER(POINTER(IUnknown)), "ppv"), ), ) + + +class IChannelAudioVolume(IUnknown): + _iid_ = GUID("{1c158861-b533-4b30-b1cf-e853e51c59b8}") + _methods_ = ( + COMMETHOD( + [], HRESULT, "GetChannelCount", (["out"], POINTER(UINT32), "pnChannelCount") + ), + COMMETHOD( + [], + HRESULT, + "SetChannelVolume", + (["in"], UINT32, "dwIndex"), + (["in"], c_float, "fLevel"), + (["in"], POINTER(GUID), "EventContext"), + ), + COMMETHOD( + [], + HRESULT, + "GetChannelVolume", + (["in"], UINT32, "dwIndex"), + (["out"], POINTER(c_float), "pfLevel"), + ), + ) diff --git a/pycaw/utils.py b/pycaw/utils.py index 09a9b17..e3fd056 100644 --- a/pycaw/utils.py +++ b/pycaw/utils.py @@ -4,7 +4,7 @@ import psutil from _ctypes import COMError -from pycaw.api.audioclient import ISimpleAudioVolume +from pycaw.api.audioclient import IChannelAudioVolume, ISimpleAudioVolume from pycaw.api.audiopolicy import IAudioSessionControl2, IAudioSessionManager2 from pycaw.api.endpointvolume import IAudioEndpointVolume from pycaw.api.mmdeviceapi import IMMDeviceEnumerator, IMMEndpoint @@ -61,6 +61,7 @@ def __init__(self, audio_session_control2): self._ctl = audio_session_control2 self._process = None self._volume = None + self._channelVolume = None self._callback = None def __str__(self): @@ -145,6 +146,11 @@ def SimpleAudioVolume(self): self._volume = self._ctl.QueryInterface(ISimpleAudioVolume) return self._volume + def channelAudioVolume(self): + if self._channelVolume is None: + self._channelVolume = self._ctl.QueryInterface(IChannelAudioVolume) + return self._channelVolume + def register_notification(self, callback): if self._callback is None: self._callback = callback From be25d080eb543a1d986e9ad76680c4392a9ecb61 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Fri, 9 Feb 2024 22:01:25 +0100 Subject: [PATCH 06/10] :rotating_light: Format fix Most likely a `black` update --- examples/audio_controller_class_example.py | 1 + examples/audio_endpoint_volume_example.py | 1 + examples/session_callback_example.py | 1 + examples/simple_audio_volume_example.py | 1 + examples/volume_by_process_example.py | 1 + examples/volume_callback_example.py | 1 + pycaw/pycaw.py | 1 + tests/test_core.py | 1 + tests/test_examples.py | 1 + 9 files changed, 9 insertions(+) diff --git a/examples/audio_controller_class_example.py b/examples/audio_controller_class_example.py index 92adaa9..e87784c 100644 --- a/examples/audio_controller_class_example.py +++ b/examples/audio_controller_class_example.py @@ -2,6 +2,7 @@ Per session GetMute() SetMute() GetMasterVolume() SetMasterVolume() using SimpleAudioVolume. """ + from pycaw.pycaw import AudioUtilities diff --git a/examples/audio_endpoint_volume_example.py b/examples/audio_endpoint_volume_example.py index f857af8..c94e055 100644 --- a/examples/audio_endpoint_volume_example.py +++ b/examples/audio_endpoint_volume_example.py @@ -1,6 +1,7 @@ """ Get and set access to master volume example. """ + from comtypes import CLSCTX_ALL from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume diff --git a/examples/session_callback_example.py b/examples/session_callback_example.py index 4a2d153..2a0163c 100644 --- a/examples/session_callback_example.py +++ b/examples/session_callback_example.py @@ -20,6 +20,7 @@ https://docs.microsoft.com/en-us/windows/win32/api/audiopolicy/nn-audiopolicy-iaudiosessionevents """ + import time from comtypes import COMError diff --git a/examples/simple_audio_volume_example.py b/examples/simple_audio_volume_example.py index fa94ed9..eed5b78 100644 --- a/examples/simple_audio_volume_example.py +++ b/examples/simple_audio_volume_example.py @@ -1,6 +1,7 @@ """ Per session GetMute() SetMute() using ISimpleAudioVolume. """ + from pycaw.pycaw import AudioUtilities, ISimpleAudioVolume diff --git a/examples/volume_by_process_example.py b/examples/volume_by_process_example.py index a9f1b7c..3ec709e 100644 --- a/examples/volume_by_process_example.py +++ b/examples/volume_by_process_example.py @@ -1,6 +1,7 @@ """ Mutes the volume of all processes, but unmutes chrome.exe process. """ + from pycaw.pycaw import AudioUtilities diff --git a/examples/volume_callback_example.py b/examples/volume_callback_example.py index d199eb5..e27b60c 100644 --- a/examples/volume_callback_example.py +++ b/examples/volume_callback_example.py @@ -2,6 +2,7 @@ IAudioEndpointVolumeCallback.OnNotify() example. The OnNotify() callback method gets called on volume change. """ + from comtypes import CLSCTX_ALL, COMObject from pycaw.pycaw import ( diff --git a/pycaw/pycaw.py b/pycaw/pycaw.py index 0f2f826..e4339eb 100644 --- a/pycaw/pycaw.py +++ b/pycaw/pycaw.py @@ -1,6 +1,7 @@ """ Python wrapper around the Core Audio Windows API. """ + # import here all newly split up modules, # to keep backwards compatibility diff --git a/tests/test_core.py b/tests/test_core.py index 5448c81..437aa4a 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1,6 +1,7 @@ """ Verifies core features run as expected. """ + import sys import warnings from contextlib import contextmanager diff --git a/tests/test_examples.py b/tests/test_examples.py index f229c35..8c53e73 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -1,6 +1,7 @@ """ Verifies examples run as expected. """ + import pytest from examples import ( From ccd4b8181ca6383bf2d987b4f7c0ca32d5547fa3 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Fri, 9 Feb 2024 21:38:38 +0100 Subject: [PATCH 07/10] :arrow_up: GitHub Actions versions bumps --- .github/workflows/pypi-release.yml | 4 ++-- .github/workflows/tests.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pypi-release.yml b/.github/workflows/pypi-release.yml index 0e78b0c..47f6151 100644 --- a/.github/workflows/pypi-release.yml +++ b/.github/workflows/pypi-release.yml @@ -6,8 +6,8 @@ jobs: pypi: runs-on: windows-2019 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 - name: Install dependencies run: python -m pip install --upgrade setuptools wheel twine - name: Build diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8c487d6..4898b03 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -6,8 +6,8 @@ jobs: linter: runs-on: windows-2019 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 - run: pip install tox - run: tox -e lint-check test: @@ -17,7 +17,7 @@ jobs: python: ['3.7', '3.8', '3.9', '3.10'] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # Virtual network sound card for Microsoft Windows - name: Install Scream shell: powershell @@ -26,7 +26,7 @@ jobs: Expand-Archive -Path Scream3.8.zip -DestinationPath Scream Import-Certificate -FilePath Scream\Install\driver\x64\Scream.cat -CertStoreLocation Cert:\LocalMachine\TrustedPublisher Scream\Install\helpers\devcon-x64.exe install Scream\Install\driver\x64\Scream.inf *Scream - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - run: pip install tox From dff7d1efa216597c9cafa73f80d0c37c8b29abc9 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Fri, 9 Feb 2024 21:56:57 +0100 Subject: [PATCH 08/10] :arrow_up: Bump Python versions Drops Python 3.7 (EOL), add 3.11 and 3.12 --- .github/workflows/tests.yml | 2 +- CHANGELOG.md | 5 +++++ tox.ini | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4898b03..fc173ba 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,7 +14,7 @@ jobs: runs-on: windows-2019 strategy: matrix: - python: ['3.7', '3.8', '3.9', '3.10'] + python: ['3.8', '3.9', '3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 947865f..68e6f51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## [unreleased] + - fix double free due to using cast rather than QueryInterface, refs #74 (@mrob95) + - add: example for IMMNotificationClient, refs #77 (@Invisi) + - IChannelAudioVolume support, refs #87 (@mltony) + ## [20230407] - Fixes memory leak from PROPVARIANT, refs #72 (@KillerBOSS2019) diff --git a/tox.ini b/tox.ini index c91fe6a..b4a7578 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = lint-check,py{37,38,39,310} +envlist = lint-check,py{38,39,310,311,312} skipsdist = True [testenv] From 325ca7ec541380e25cc9edb8f475e9c5773b2b30 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 5 Sep 2023 20:24:06 +0200 Subject: [PATCH 09/10] :construction_worker: Fix CI virtual audio install Change the system date as a workaround for the expired Scream certs. The job was driver install job was hanging, the error log was: ``` Updating drivers for *Scream from D:\a\pycaw\pycaw\Scream\Install\driver\x64\Scream.inf. Error: The operation was canceled. ``` Refs: https://github.com/duncanthrax/scream/issues/202 Also bump Windows and Scream versions. --- .github/workflows/pypi-release.yml | 2 +- .github/workflows/tests.yml | 32 ++++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pypi-release.yml b/.github/workflows/pypi-release.yml index 47f6151..dc2b0f6 100644 --- a/.github/workflows/pypi-release.yml +++ b/.github/workflows/pypi-release.yml @@ -4,7 +4,7 @@ on: [push] jobs: pypi: - runs-on: windows-2019 + runs-on: windows-2022 steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index fc173ba..332aef3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,35 +4,51 @@ on: [push, pull_request] jobs: linter: - runs-on: windows-2019 + runs-on: windows-2022 steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 - run: pip install tox - run: tox -e lint-check test: - runs-on: windows-2019 + runs-on: windows-2022 strategy: matrix: python: ['3.8', '3.9', '3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v4 - # Virtual network sound card for Microsoft Windows - - name: Install Scream + - name: Start audio server + run: net start audiosrv + - name: Disable time sync with Hyper-V & setting system date time + # TODO: Remove the time workaround when virtual audio device certificate is valid again, refs: + # https://github.com/duncanthrax/scream/issues/202 + run: | + Set-Service -Name vmictimesync -Status stopped -StartupType disabled + Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\services\W32Time\Parameters -Name 'Type' -Value 'NoSync' + net stop w32time; Set-Date (Get-Date "2023-07-04 12:00:00") + - name: Install virtual audio device (Scream) + timeout-minutes: 3 + env: + VERSION: '4.0' shell: powershell run: | - Invoke-WebRequest https://github.com/duncanthrax/scream/releases/download/3.8/Scream3.8.zip -OutFile Scream3.8.zip - Expand-Archive -Path Scream3.8.zip -DestinationPath Scream - Import-Certificate -FilePath Scream\Install\driver\x64\Scream.cat -CertStoreLocation Cert:\LocalMachine\TrustedPublisher + Invoke-WebRequest https://github.com/duncanthrax/scream/releases/download/${{ env.VERSION }}/Scream${{ env.VERSION }}.zip -OutFile Scream${{ env.VERSION }}.zip + Expand-Archive -Path Scream${{ env.VERSION }}.zip -DestinationPath Scream + Import-Certificate -FilePath Scream\Install\driver\x64\scream.cat -CertStoreLocation Cert:\LocalMachine\TrustedPublisher Scream\Install\helpers\devcon-x64.exe install Scream\Install\driver\x64\Scream.inf *Scream + - name: Resetting system date time + run: | + Set-Service -Name vmictimesync -Status running -StartupType automatic + Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\services\W32Time\Parameters -Name 'Type' -Value 'NTP' + net start w32time; w32tm /resync /force; $currentDate = Get-Date; Write-Host "Current System Date: $currentDate"; - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - run: pip install tox - run: tox -e py - name: Run Coverage - if: matrix.python == '3.10' + if: matrix.python == '3.12' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: tox -e coveralls From ced4f3f601023cfcf2f2426ae6e3056bcf4cb9a7 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Wed, 21 Feb 2024 11:52:00 +0100 Subject: [PATCH 10/10] :bookmark: v20240210 --- CHANGELOG.md | 6 +++++- setup.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68e6f51..dd8cfec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,13 @@ # Change Log -## [unreleased] +## [20240210] - fix double free due to using cast rather than QueryInterface, refs #74 (@mrob95) - add: example for IMMNotificationClient, refs #77 (@Invisi) - IChannelAudioVolume support, refs #87 (@mltony) + - Format fix (@AndreMiras), refs #89 + - GitHub Actions versions bumps (@AndreMiras), refs #88 + - Bump Python versions (@AndreMiras), refs #90 + - Fix CI virtual audio install (@AndreMiras), refs #91 ## [20230407] - Fixes memory leak from PROPVARIANT, refs #72 (@KillerBOSS2019) diff --git a/setup.py b/setup.py index 5583487..2b02824 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ def read(fname): install_requires = ["comtypes", "psutil"] setup( name="pycaw", - version="20230407.dev0", + version="20240210", description="Python Core Audio Windows Library", long_description=read("README.md"), long_description_content_type="text/markdown",