diff --git a/.github/workflows/linux_test.yml b/.github/workflows/linux_test.yml index 38a723a..3480145 100644 --- a/.github/workflows/linux_test.yml +++ b/.github/workflows/linux_test.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: os: [ubuntu-20.04] - python-version: [3.6, 3.7, 3.8, 3.9, 3.10.0, 3.11.0] + python-version: [3.7, 3.8, 3.9, 3.10.0, 3.11.0] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/.github/workflows/macOS_test.yml b/.github/workflows/macOS_test.yml index d737539..9b4f436 100644 --- a/.github/workflows/macOS_test.yml +++ b/.github/workflows/macOS_test.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: os: [macOS-12, macOS-11] - python-version: [3.6, 3.7, 3.8, 3.9, 3.10.0, 3.11.0] + python-version: [3.7, 3.8, 3.9, 3.10.0, 3.11.0] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/.github/workflows/windows_test.yml b/.github/workflows/windows_test.yml index c48ed48..31153db 100644 --- a/.github/workflows/windows_test.yml +++ b/.github/workflows/windows_test.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: os: [windows-2022, windows-2019] - python-version: [3.6, 3.7, 3.8, 3.9, 3.10.0, 3.11.0] + python-version: [3.7, 3.8, 3.9, 3.10.0, 3.11.0] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/.gitignore b/.gitignore index 73358ad..a81c8ee 100644 --- a/.gitignore +++ b/.gitignore @@ -136,4 +136,3 @@ dmypy.json # Cython debug symbols cython_debug/ - diff --git a/AUTHORS.md b/AUTHORS.md index 27f620d..e1540c2 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -11,3 +11,4 @@ # Other Contributors # ---------- - Zahra Mobasher ([Instagram](https://www.instagram.com/littleblackoyster/?hl=en)) +- Nima Samadi ([Github](https://github.com/NimaSamadi007)) \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a5cc63a..3d092dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- `play_async` function +- `__play_win_async` function +- `__play_linux_async` function +- `__play_mac_async` function +### Changed +- Python 3.6 support dropped. ## [0.2] - 2023-07-10 ### Added - Logo diff --git a/README.md b/README.md index e381355..20796c8 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,22 @@ from nava import play play("alarm.wav") ``` +### Async +```python +import asyncio +from nava import play_async + +async def my_task(): + # the task you wanted to run it asynchronously while sound is playing. + pass + +async def main(): + asyncio.create_task(my_task()) + await asyncio.create_task(play_async("alarm.wav")) + +asyncio.run(main()) +``` + ### Error ```python diff --git a/nava/__init__.py b/nava/__init__.py index 3f535d0..3c89119 100644 --- a/nava/__init__.py +++ b/nava/__init__.py @@ -2,6 +2,6 @@ """Nava modules.""" from .params import NAVA_VERSION from .errors import NavaBaseError -from .functions import play +from .functions import play, play_async __version__ = NAVA_VERSION diff --git a/nava/functions.py b/nava/functions.py index f7c531b..9a2c2b6 100644 --- a/nava/functions.py +++ b/nava/functions.py @@ -5,6 +5,7 @@ import os import shlex from functools import wraps +import asyncio from .params import OVERVIEW from .params import SOUND_FILE_PLAY_ERROR, SOUND_FILE_EXIST_ERROR @@ -59,6 +60,18 @@ def __play_win(sound_path): winsound.PlaySound(sound_path, winsound.SND_FILENAME) +def __play_win_async(sound_path): + """ + Play sound in asynchronously Windows. + + :param sound_path: sound path + :type sound_path: str + :return: None + """ + import winsound + winsound.PlaySound(sound_path, winsound.SND_FILENAME | winsound.SND_ASYNC) + + @quote def __play_linux(sound_path): """ @@ -76,6 +89,24 @@ def __play_linux(sound_path): stdout=subprocess.PIPE) +@quote +async def __play_linux_async(sound_path): + """ + Play sound asynchronously in Linux. + + :param sound_path: sound path + :type sound_path: str + :return: None + """ + proc = await asyncio.subprocess.create_subprocess_exec("aplay", + sound_path, + shell=False, + stderr=asyncio.subprocess.PIPE, + stdin=asyncio.subprocess.PIPE, + stdout=asyncio.subprocess.PIPE) + await proc.communicate() + + @quote def __play_mac(sound_path): """ @@ -93,6 +124,24 @@ def __play_mac(sound_path): stdout=subprocess.PIPE) +@quote +async def __play_mac_async(sound_path): + """ + Play sound asynchronously in macOS. + + :param sound_path: sound path + :type sound_path: str + :return: None + """ + proc = await asyncio.subprocess.create_subprocess_exec("afplay", + sound_path, + shell=False, + stderr=asyncio.subprocess.PIPE, + stdin=asyncio.subprocess.PIPE, + stdout=asyncio.subprocess.PIPE) + await proc.communicate() + + def path_check(func): """ Check the given path to be a string and a valid file directory. @@ -121,6 +170,27 @@ def path_checker(sound_path, *args, **kwargs): return path_checker +@path_check +async def play_async(sound_path): + """ + Play sound. + + :param sound_path: sound path + :type sound_path: str + :return: None + """ + try: + sys_platform = sys.platform + if sys_platform == "win32": + __play_win_async(sound_path) + elif sys_platform == "darwin": + await asyncio.create_task(__play_mac_async(sound_path)) + else: + await asyncio.create_task(__play_linux_async(sound_path)) + except Exception: # pragma: no cover + raise NavaBaseError(SOUND_FILE_PLAY_ERROR) + + @path_check def play(sound_path): """ @@ -138,5 +208,5 @@ def play(sound_path): __play_mac(sound_path) else: __play_linux(sound_path) - except Exception: # pragma: no cover + except Exception: # pragma: no cover raise NavaBaseError(SOUND_FILE_PLAY_ERROR) diff --git a/others/meta.yaml b/others/meta.yaml index 14bdca8..79b6d34 100644 --- a/others/meta.yaml +++ b/others/meta.yaml @@ -15,10 +15,10 @@ requirements: host: - pip - setuptools - - python >=3.6 + - python >=3.7 run: - art >=1.8 - - python >=3.6 + - python >=3.7 about: home: https://github.com/openscilab/nava license: MIT diff --git a/setup.py b/setup.py index a823ceb..5a740b5 100644 --- a/setup.py +++ b/setup.py @@ -47,14 +47,13 @@ def read_description(): 'Discord': 'https://discord.gg/MCbPKCFBs3', }, install_requires=get_requires(), - python_requires='>=3.6', + python_requires='>=3.7', classifiers=[ 'Development Status :: 2 - Pre-Alpha', 'Intended Audience :: Developers', 'Natural Language :: English', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', - 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', diff --git a/test/function_test.py b/test/function_test.py index ce58a04..3fffe20 100644 --- a/test/function_test.py +++ b/test/function_test.py @@ -1,8 +1,18 @@ # -*- coding: utf-8 -*- """ >>> import os ->>> from nava import play ->>> play(os.path.join("others", "test.wav")) +>>> import asyncio +>>> from time import time +>>> from nava import play, play_async +>>> PATH2TEST_WAV = os.path.join("others", "test.wav") +>>> play(PATH2TEST_WAV) +>>> async def sleep_test(): +... while True: +... await asyncio.sleep(0.1) +>>> async def play_async_test(): +... asyncio.create_task(sleep_test()) +... await asyncio.create_task(play_async(PATH2TEST_WAV)) +>>> asyncio.run(play_async_test()) >>> from nava.functions import nava_help >>> nava_help()