Skip to content

Commit

Permalink
Merge branch 'release/v20230322'
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreMiras committed Mar 22, 2023
2 parents 2a5d923 + 7b9dac2 commit 6397c68
Show file tree
Hide file tree
Showing 29 changed files with 1,201 additions and 514 deletions.
11 changes: 6 additions & 5 deletions .github/workflows/pypi-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ jobs:
twine check dist/*
- name: Publish package
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
uses: pypa/[email protected]
with:
verbose: true
user: __token__
password: ${{ secrets.pypi_password }}
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python -m pip install twine
python -m twine upload dist/*
10 changes: 7 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Tests

on: [push]
on: [push, pull_request]

jobs:
linter:
Expand All @@ -9,8 +9,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- run: pip install tox
- run: tox -e pep8
- run: tox -e isort
- run: tox -e lint-check
test:
runs-on: windows-2019
strategy:
Expand All @@ -32,3 +31,8 @@ jobs:
python-version: ${{ matrix.python }}
- run: pip install tox
- run: tox -e py
- name: Run Coverage
if: matrix.python == '3.10'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: tox -e coveralls
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Change Log

## [20230322]
- CI and testing improvements
- Improve audioclient, audiopolicy and mmdeviceapi support, refs #70 (@dot-Eagle96)
- Fix IPropertyStore.SetValue parameters, refs #71 (@Invisi)

## [20220416]
- Migrate to GitHub Actions
- CI tests via virtual sound card
Expand Down
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
# pycaw

[![Tests](https://github.com/AndreMiras/pycaw/actions/workflows/tests.yml/badge.svg)](https://github.com/AndreMiras/pycaw/actions/workflows/tests.yml)
[![PyPI release](https://github.com/AndreMiras/pycaw/actions/workflows/pypi-release.yml/badge.svg)](https://github.com/AndreMiras/pycaw/actions/workflows/pypi-release.yml)
[![Tests](https://github.com/AndreMiras/pycaw/workflows/Tests/badge.svg)](https://github.com/AndreMiras/pycaw/actions/workflows/tests.yml)
[![Coverage Status](https://coveralls.io/repos/github/AndreMiras/pycaw/badge.svg?branch=develop)](https://coveralls.io/github/AndreMiras/pycaw?branch=develop)
[![PyPI release](https://github.com/AndreMiras/pycaw/workflows/PyPI%20release/badge.svg)](https://github.com/AndreMiras/pycaw/actions/workflows/pypi-release.yml)
[![PyPI version](https://badge.fury.io/py/pycaw.svg)](https://badge.fury.io/py/pycaw)

Python Core Audio Windows Library, working for both Python2 and Python3.

## Install

Latest stable release:
```bash
```bat
pip install pycaw
```

Development branch:
```bash
```bat
pip install https://github.com/AndreMiras/pycaw/archive/develop.zip
```

System requirements:
```bash
choco install visualcppbuildtools
```bat
choco install visualcpp-build-tools
```

## Usage
Expand Down
18 changes: 9 additions & 9 deletions examples/audio_controller_class_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@ def mute(self):
interface = session.SimpleAudioVolume
if session.Process and session.Process.name() == self.process_name:
interface.SetMute(1, None)
print(self.process_name, 'has been muted.') # debug
print(self.process_name, "has been muted.") # debug

def unmute(self):
sessions = AudioUtilities.GetAllSessions()
for session in sessions:
interface = session.SimpleAudioVolume
if session.Process and session.Process.name() == self.process_name:
interface.SetMute(0, None)
print(self.process_name, 'has been unmuted.') # debug
print(self.process_name, "has been unmuted.") # debug

def process_volume(self):
sessions = AudioUtilities.GetAllSessions()
for session in sessions:
interface = session.SimpleAudioVolume
if session.Process and session.Process.name() == self.process_name:
print('Volume:', interface.GetMasterVolume()) # debug
print("Volume:", interface.GetMasterVolume()) # debug
return interface.GetMasterVolume()

def set_volume(self, decibels):
Expand All @@ -42,31 +42,31 @@ def set_volume(self, decibels):
# only set volume in the range 0.0 to 1.0
self.volume = min(1.0, max(0.0, decibels))
interface.SetMasterVolume(self.volume, None)
print('Volume set to', self.volume) # debug
print("Volume set to", self.volume) # debug

def decrease_volume(self, decibels):
sessions = AudioUtilities.GetAllSessions()
for session in sessions:
interface = session.SimpleAudioVolume
if session.Process and session.Process.name() == self.process_name:
# 0.0 is the min value, reduce by decibels
self.volume = max(0.0, self.volume-decibels)
self.volume = max(0.0, self.volume - decibels)
interface.SetMasterVolume(self.volume, None)
print('Volume reduced to', self.volume) # debug
print("Volume reduced to", self.volume) # debug

def increase_volume(self, decibels):
sessions = AudioUtilities.GetAllSessions()
for session in sessions:
interface = session.SimpleAudioVolume
if session.Process and session.Process.name() == self.process_name:
# 1.0 is the max value, raise by decibels
self.volume = min(1.0, self.volume+decibels)
self.volume = min(1.0, self.volume + decibels)
interface.SetMasterVolume(self.volume, None)
print('Volume raised to', self.volume) # debug
print("Volume raised to", self.volume) # debug


def main():
audio_controller = AudioController('chrome.exe')
audio_controller = AudioController("chrome.exe")
audio_controller.set_volume(1.0)
audio_controller.mute()
audio_controller.decrease_volume(0.25)
Expand Down
3 changes: 1 addition & 2 deletions examples/audio_endpoint_volume_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@

def main():
devices = AudioUtilities.GetSpeakers()
interface = devices.Activate(
IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
volume = cast(interface, POINTER(IAudioEndpointVolume))
print("volume.GetMute(): %s" % volume.GetMute())
print("volume.GetMasterVolumeLevel(): %s" % volume.GetMasterVolumeLevel())
Expand Down
14 changes: 8 additions & 6 deletions examples/magic_app_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,13 @@ def handle_all(*args):
print(args)


magic = MagicApp({"msedge.exe"},
volume_callback=handle_all,
mute_callback=handle_all,
state_callback=handle_all,
session_callback=handle_all)
magic = MagicApp(
{"msedge.exe"},
volume_callback=handle_all,
mute_callback=handle_all,
state_callback=handle_all,
session_callback=handle_all,
)


def main():
Expand Down Expand Up @@ -97,5 +99,5 @@ def main():
print("\nTschüss")


if __name__ == '__main__':
if __name__ == "__main__":
main()
29 changes: 15 additions & 14 deletions examples/session_callback_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,25 @@


class MyCustomCallback(AudioSessionEvents):

def on_simple_volume_changed(self, new_volume, new_mute, event_context):
print(':: OnSimpleVolumeChanged callback\n'
f"new_volume: {new_volume}; "
f"new_mute: {new_mute}; "
f"event_context: {event_context.contents}")
print(
":: OnSimpleVolumeChanged callback\n"
f"new_volume: {new_volume}; "
f"new_mute: {new_mute}; "
f"event_context: {event_context.contents}"
)

def on_state_changed(self, new_state, new_state_id):
print(':: OnStateChanged callback\n'
f"new_state: {new_state}; id: {new_state_id}")
print(
":: OnStateChanged callback\n" f"new_state: {new_state}; id: {new_state_id}"
)

def on_session_disconnected(self, disconnect_reason, disconnect_reason_id):
print(':: OnSessionDisconnected callback\n'
f"disconnect_reason: {disconnect_reason}; "
f"id: {disconnect_reason_id}")
print(
":: OnSessionDisconnected callback\n"
f"disconnect_reason: {disconnect_reason}; "
f"id: {disconnect_reason_id}"
)


def add_callback(app_name):
Expand All @@ -58,7 +62,6 @@ def add_callback(app_name):
app_found = False
for session in sessions:
if session.Process and session.Process.name() == app_name:

app_found = True
callback = MyCustomCallback()
# Adding the callback
Expand All @@ -68,8 +71,7 @@ def add_callback(app_name):
exit("Enter the right 'app_name', start it and play something")

print("Ready to go!")
print("Change the volume / mute state "
"/ close the app or unplug your speaker")
print("Change the volume / mute state " "/ close the app or unplug your speaker")
print("and watch the callbacks ;)\n")

try:
Expand All @@ -78,7 +80,6 @@ def add_callback(app_name):
except KeyboardInterrupt:
pass
finally:

# unregister callback(s)
# unregister_notification()
# (only if it was also registered.)
Expand Down
12 changes: 7 additions & 5 deletions examples/volume_callback_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,23 @@

from comtypes import CLSCTX_ALL, COMObject

from pycaw.pycaw import (AudioUtilities, IAudioEndpointVolume,
IAudioEndpointVolumeCallback)
from pycaw.pycaw import (
AudioUtilities,
IAudioEndpointVolume,
IAudioEndpointVolumeCallback,
)


class AudioEndpointVolumeCallback(COMObject):
_com_interfaces_ = [IAudioEndpointVolumeCallback]

def OnNotify(self, pNotify):
print('OnNotify callback')
print("OnNotify callback")


def main():
devices = AudioUtilities.GetSpeakers()
interface = devices.Activate(
IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
volume = cast(interface, POINTER(IAudioEndpointVolume))
callback = AudioEndpointVolumeCallback()
volume.RegisterControlChangeNotify(callback)
Expand Down
Loading

0 comments on commit 6397c68

Please sign in to comment.