Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ jobs:
/tmp/npd-packaging-venv/bin/now-playing --help
/tmp/npd-packaging-venv/bin/python -m now_playing_desktops --help

- name: PyInstaller Linux release binary
run: |
pip install -e ".[linux]"
pyinstaller --noconfirm packaging/now-playing-linux.spec
dist/now-playing-linux --help

- name: Tests
run: pytest --cov=now_playing_desktops --cov-report=term-missing -q

Expand Down
70 changes: 69 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
workflow_dispatch:
inputs:
dry_run:
description: "Build Windows .exe as artifact only (no GitHub Release or PyPI)"
description: "Build Windows/macOS/Linux binaries as artifacts only (no GitHub Release or PyPI)"
type: boolean
default: true

Expand Down Expand Up @@ -51,6 +51,74 @@ jobs:
files: dist/now-playing-windows.exe
generate_release_notes: true

macos-app:
name: macOS executable
runs-on: macos-latest
steps:
- uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: "3.12"
cache: pip

- name: Install package and PyInstaller
run: |
python -m pip install --upgrade pip
pip install -e ".[macos]"
pip install pyinstaller

- name: Build now-playing-macos
run: pyinstaller --noconfirm packaging/now-playing-macos.spec

- name: Upload dry-run artifact
if: github.event_name == 'workflow_dispatch'
uses: actions/upload-artifact@v4
with:
name: now-playing-macos
path: dist/now-playing-macos

- name: Attach to GitHub Release
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2
with:
files: dist/now-playing-macos

linux-app:
name: Linux executable
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: "3.12"
cache: pip

- name: Install package and PyInstaller
run: |
python -m pip install --upgrade pip
pip install -e ".[linux]"
pip install pyinstaller

- name: Build now-playing-linux
run: pyinstaller --noconfirm packaging/now-playing-linux.spec

- name: Upload dry-run artifact
if: github.event_name == 'workflow_dispatch'
uses: actions/upload-artifact@v4
with:
name: now-playing-linux
path: dist/now-playing-linux

- name: Attach to GitHub Release
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2
with:
files: dist/now-playing-linux

publish-pypi:
name: Publish to PyPI
runs-on: ubuntu-latest
Expand Down
24 changes: 21 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,21 @@

<p align="center"><img src="docs/demo.gif" alt="Glass album-art tile updating as the track changes, then the original wallpaper restoring on pause" width="720"></p>

## Download (pre-built)

GitHub [Releases](https://github.com/hippi345/nowPlayingDesktops/releases) attach one-file PyInstaller builds per OS (also available as workflow artifacts from **Actions → Release → Run workflow** with dry run enabled):

| OS | Download | Run |
|----|----------|-----|
| **Windows** | `now-playing-windows.exe` | Double-click or run from a terminal |
| **macOS** | `now-playing-macos` | `chmod +x now-playing-macos && ./now-playing-macos run --source local` |
| **Linux** | `now-playing-linux` | `chmod +x now-playing-linux && ./now-playing-linux run --source local` |

Or install with [pipx](https://pipx.pypa.io/): `pipx install now-playing-desktops`

## Quick start (Windows)

1. **Get the app** — download `now-playing-windows.exe` from [Releases](https://github.com/hippi345/nowPlayingDesktops/releases), or install with [pipx](https://pipx.pypa.io/): `pipx install now-playing-desktops`
1. **Get the app** — download `now-playing-windows.exe` from [Releases](https://github.com/hippi345/nowPlayingDesktops/releases), or use pipx (above)
2. **Run it** — double-click the `.exe`, or run `now-playing run --source local` (pipx puts `now-playing` on your PATH)
3. **Done** — play something in the Spotify desktop app; pause or exit to restore your wallpaper

Expand Down Expand Up @@ -59,7 +71,10 @@ now-playing run --source local

### Linux (local)

**Prerequisites**
1. **Get the app** — download `now-playing-linux` from [Releases](https://github.com/hippi345/nowPlayingDesktops/releases), `chmod +x` it, and run `./now-playing-linux run --source local`, or install from source below.
2. **Player** — Spotify desktop or another **MPRIS** player; pause or exit restores your wallpaper.

**Prerequisites (source install)**

- **Python 3.12+**
- **Install:** `pip install -e ".[linux]"` (`dbus-next` for MPRIS).
Expand All @@ -78,7 +93,10 @@ now-playing run --source local

### macOS (local)

**Prerequisites**
1. **Get the app** — download `now-playing-macos` from [Releases](https://github.com/hippi345/nowPlayingDesktops/releases), `chmod +x` it, and run `./now-playing-macos run --source local`, or install from source below.
2. **Player** — **Spotify.app** on this Mac; pause or exit restores your wallpaper.

**Prerequisites (source install)**

- **Python 3.12+**
- **Install:** `pip install -e ".[macos]"` (`appscript` for Spotify AppleScript control).
Expand Down
48 changes: 48 additions & 0 deletions packaging/now-playing-linux.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# -*- mode: python ; coding: utf-8 -*-
"""PyInstaller spec for now-playing-linux (run on ubuntu-latest)."""

from PyInstaller.utils.hooks import collect_all

block_cipher = None

pkg_datas, pkg_binaries, pkg_hidden = collect_all("now_playing_desktops")
dbus_datas, dbus_binaries, dbus_hidden = collect_all("dbus_next")
pkg_datas += dbus_datas
pkg_binaries += dbus_binaries
hiddenimports = list(pkg_hidden) + list(dbus_hidden)

a = Analysis(
["pyinstaller_linux_entry.py"],
pathex=["../src"],
binaries=pkg_binaries,
datas=pkg_datas,
hiddenimports=hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name="now-playing-linux",
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
48 changes: 48 additions & 0 deletions packaging/now-playing-macos.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# -*- mode: python ; coding: utf-8 -*-
"""PyInstaller spec for now-playing-macos (run on macos-latest)."""

from PyInstaller.utils.hooks import collect_all

block_cipher = None

pkg_datas, pkg_binaries, pkg_hidden = collect_all("now_playing_desktops")
app_datas, app_binaries, app_hidden = collect_all("appscript")
pkg_datas += app_datas
pkg_binaries += app_binaries
hiddenimports = list(pkg_hidden) + list(app_hidden)

a = Analysis(
["pyinstaller_macos_entry.py"],
pathex=["../src"],
binaries=pkg_binaries,
datas=pkg_datas,
hiddenimports=hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name="now-playing-macos",
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
6 changes: 6 additions & 0 deletions packaging/pyinstaller_linux_entry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""PyInstaller entry point for the Linux console build."""

from now_playing_desktops.cli import main

if __name__ == "__main__":
raise SystemExit(main())
6 changes: 6 additions & 0 deletions packaging/pyinstaller_macos_entry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""PyInstaller entry point for the macOS console build."""

from now_playing_desktops.cli import main_macos

if __name__ == "__main__":
main_macos()
Loading