# 🔊 Play sounds in Python scripts
`minsound` provides a simple cross-platform API to play sounds in Python scripts. It includes a [synchronous API](https://github.com/alexdelorenzo/minsound/blob/main/README.md#synchronous-api) and an equivalent [asynchronous API](https://github.com/alexdelorenzo/minsound/blob/main/README.md#asynchronous-api) that is compatible with `asyncio` and `trio`.

For code examples, you can check out [`onhold`](https://github.com/alexdelorenzo/onhold) and [`ding`](https://github.com/alexdelorenzo/ding), or scroll down to the [Usage section](https://github.com/alexdelorenzo/minsound#usage).

# Why `minsound`?
[`boombox`](https://pypi.org/project/boombox/) is great and 90% of the way there, however it is limited to only playing WAV files on Windows. [`playsound`](https://pypi.org/project/playsound/) will play other formats than WAV on Windows, but it requires GStreamer and `PyGObject` bindings on Linux, while `boombox` has several playback backends for Linux other than, and including, GStreamer.

Neither `boombox` or `playsound` provide `asyncio` and `async/await` compatible APIs, but `minsound` does.

If you're targeting multiple desktop platforms and don't want to get mired down in the details of when and where to use `playsound` or `boombox`, or if your project uses `async/await`, you can just reach for `minsound` and call it a day.

# Installation
```bash
$ python3 -m pip install minsound
```

# Usage
This library uses [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) objects when pointing to filenames and paths. It can use  [`aiopath.AsyncPath`](https://github.com/alexdelorenzo/aiopath) objects, too.

There's a synchronous API and an [asynchronous API](https://github.com/alexdelorenzo/minsound/blob/main/README.md#asynchronous-api) that you can use with the `async/await` syntax and `asyncio`. 

## Synchronous API
### Play a file
```python
from minsound import play_file, DEFAULT_SONG


play_file(DEFAULT_SONG)  # blocks by default

# play without blocking
play_file(DEFAULT_SONG, block=False) 
```

### Play while work completes
```python
from time import sleep
from minsound import play_while_running, DEFAULT_SONG


WAIT: int = 60


with play_while_running(DEFAULT_SONG):
  sleep(WAIT)
```

### Play a file after work completes
```python
from time import sleep
from minsound import play_after, DEFAULT_SOUND


with play_after(DEFAULT_SOUND):  # blocks by default
  sleep(WAIT)

# play without blocking
with play_after(DEFAULT_SOUND, block=False):
  sleep(WAIT)
```

### Ring the [terminal bell](https://en.wikipedia.org/wiki/Bell_character)
```python
from minsound import bell, bell_after


# play bell
bell()

# ensure the bell is played even if an exception is thrown
with bell_after():
  raise Exception("Bye")
```

## Asynchronous API
To run the following examples with top-level `await` expressions, [launch an asynchronous Python REPL](https://www.integralist.co.uk/posts/python-asyncio/#running-async-code-in-the-repl) using `python3 -m asyncio` or an [IPython shell](https://ipython.org/).

### Play a file
```python
from minsound import play_file_async, DEFAULT_SONG


await play_file_async(DEFAULT_SONG)  # blocks by default

# play without blocking
await play_file_async(DEFAULT_SONG, block=False) 
```

### Play while work completes
```python
from asyncio import sleep
from minsound import play_while_running_async, DEFAULT_SONG


async with play_while_running_async(DEFAULT_SONG):
  await sleep(WAIT)
```

### Play a file after work completes
```python
from asyncio import sleep
from minsound import play_after_async, DEFAULT_SOUND


async with play_after_async(DEFAULT_SOUND):  # blocks by default
  await sleep(WAIT)

# play without blocking
async with play_after_async(DEFAULT_SOUND, block=False):
  await sleep(WAIT)
```

# Support
Want to support this project and [other open-source projects](https://github.com/alexdelorenzo) like it?

<a href="https://www.buymeacoffee.com/alexdelorenzo" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="60px" style="height: 60px !important;width: 217px !important;max-width:25%" ></a>

# Copyright
See `CREDIT.md`.

# License
See `LICENSE`.
