Linux · Open Source · GPLv3

Quran Player

Verse-by-verse Quran recitation, controlled from your Linux desktop. A background daemon drives the audio; a live Conky overlay keeps the current ayah in front of you — no cloud, no account, no window stealing focus.

v2.0.0 ·Released 2026-10-20 ·Python 3.9+ ·X11 / XWayland ·No root required
Quran Player's Conky overlay showing an Arabic verse on a Linux desktop
The Conky overlay — the current verse, right on the desktop

👤 Who is this for?

Quran Player is a Linux-native background daemon for verse-by-verse Quran audio playback with a live Conky overlay that renders the current verse right on your desktop. It stays in sync — when the verse advances, the overlay updates within half a second.

  • Linux users who want Quran playback integrated into their desktop — not a separate app window
  • Anyone using a tiling WM / minimal setup who prefers a Conky overlay to a GUI
  • People who script their environment and want a programmable daemon over a Unix socket
  • Users on X11 or XWayland (feh-based overlay solutions do not survive there; Conky does)

Looking for a full-featured GUI? See Quran Browser instead — Quran Player is the lean, daemon-native sibling.

✨ Key Features

🖼️

Conky Desktop Overlay

  • Live verse display, updates within 0.5 s
  • Daemon-managed lifecycle (start / stop / toggle)
  • Survives daemon restarts; orphans reaped automatically
  • X11 native; works under XWayland on compatible compositors
🎵

Verse-by-Verse Playback

  • Auto-advance through the entire Quran
  • Repeat modes: single ayah, range, whole surah
  • goto, next, prev, ns, ps
  • Persistent state across sessions
⚙️

Daemon + Unix Socket

  • JSON status for scripting
  • Any language can control it via the socket
  • Socket permissions locked to 0600
  • Atomic lock file, crash-safe PID management
🎛️

Optional GUI Tray

  • PyQt5 tray controller
  • Keyboard: Space / ← / → / Esc
  • Conky toggle button
  • Edit config in-place
🔍

Arabic Search Tool

  • Full-text Uthmani + simplified search
  • Hamza / diacritic normalization
  • Interactive RTL dialog
  • CLI mode for scripting
📦

One-Command Install

  • python install.py — no root
  • Installs under ~/.quran-player/
  • Incremental updates via --clean
  • Clean uninstall with --uninstall

🖥️ Screenshots

Conky overlay showing the current verse on the desktop
Conky overlay — the verse sits on the desktop while you work
Quran Player GUI controller
The optional PyQt5 tray controller

🚀 Install

terminal
# 1. Prerequisites (Debian / Ubuntu — adapt for your distro)
sudo apt install conky-all python3 python3-venv

# 2. Clone and install (no sudo for step 2)
git clone https://github.com/neoMOSAID/quran-player.git
cd quran-player
python install.py

# 3. Start the daemon — Conky launches automatically
quran-daemon start
quran-daemon play

The installer drops everything under ~/.quran-player/ and creates CLI wrappers in ~/.local/bin/ — quran-daemon, quran-gui, and quran-search.

Audio ships with the install. A 19-file sample (Surah 1 complete, Surah 2:1–10) is copied into ~/.config/quran-player/sample/ on first run — so playback works immediately, out of the box. To play the full Quran, download a recitation set from EveryAyah.com (or your own collection) into that directory, or point the daemon at it with quran-daemon dir /path/to/audio.
Other distributions: sudo pacman -S conky (Arch) · sudo dnf install conky (Fedora). For Arabic shaping in Conky, install fonts-hosny-amiri (sudo apt install fonts-hosny-amiri).
Wayland note. Quran Player is developed and tested on X11. Under Wayland, Conky runs through XWayland, and whether its override-type window is honoured depends on the compositor (GNOME and KDE work; some wlroots compositors do not render override windows). Audio playback, the daemon, and the CLI are compositor-agnostic and work everywhere.

📥 Download

Current version: v2.0.0 (released 2026-10-20)

The ZIP archive is a source snapshot of the main branch — install by running python install.py inside the extracted directory. For tagged releases, use the GitHub Releases page.

System requirements: Linux (X11 or XWayland) · Python 3.9+ · Conky · pactl (PulseAudio / PipeWire). No root required.

💻 Usage

terminal
quran-daemon start              # daemon starts + conky launches
quran-daemon play | pause | toggle
quran-daemon next | prev
quran-daemon load 2:255         # surah:ayah
quran-daemon repeat 2:1:20      # repeat surah 2, ayahs 1–20
quran-daemon conky_off          # hide desktop overlay (audio keeps playing)
quran-daemon conky_on           # show it again
quran-daemon status             # JSON status
quran-daemon info               # full diagnostic dump
quran-daemon stop               # daemon + conky both go down

🖥️ Real-world i3 Integration advanced

This is how I actually use Quran Player day-to-day: the daemon hides in the background, the multimedia keys on my keyboard drive playback, and the current verse sits quietly in my i3blocks status bar. Everything below ships in my personal dotfiles — copy, trim, or adapt to your WM. The wrapper path ~/bin/qd is my personal choice; put it anywhere on your $PATH and update the references below accordingly.

🔑 Media keys

Drop this into any i3 config file that's included from your main ~/.config/i3/config. The qd wrapper (next section) is what makes these one-liners; the daemon does the actual work.

~/.config/i3/config_files/multimedia.conf
# Media player (Quran / mpd)
bindsym XF86AudioPlay          exec --no-startup-id ~/bin/qd toggle
bindsym shift+XF86AudioPlay    exec --no-startup-id ~/bin/qd conky_toggle
bindsym XF86AudioPause         exec --no-startup-id ~/bin/qd pause
bindsym XF86AudioNext          exec --no-startup-id ~/bin/qd next
bindsym XF86AudioPrev          exec --no-startup-id ~/bin/qd prev
bindsym ctrl+XF86AudioNext     exec --no-startup-id ~/bin/qd ns
bindsym ctrl+XF86AudioPrev     exec --no-startup-id ~/bin/qd ps
bindsym shift+XF86AudioNext    exec --no-startup-id ~/bin/qd ns
bindsym shift+XF86AudioPrev    exec --no-startup-id ~/bin/qd ps
bindsym XF86AudioStop          exec --no-startup-id ~/bin/qd stop
KeyAction
XF86AudioPlayPlay / pause (auto-starts daemon if needed)
Shift + XF86AudioPlayToggle Conky overlay
XF86AudioNext / PrevNext / previous ayah
Ctrl or Shift + Next / PrevNext / previous surah
XF86AudioStopStop the daemon (Conky goes down with it)

🧰 The qd wrapper

A thin, stateless shell wrapper around the daemon's CLI. Two deliberate design choices:

  • Auto-starts for transport commands (play, toggle, next, prev, ns, ps, goto, load, repeat, bare N) — you can press Play with nothing running and it just works.
  • Does not auto-start for pause, stop, or conky_* — those must fail loudly if the daemon isn't up, rather than silently spawn it to perform a no-op.

Liveness is determined by asking the daemon over its Unix socket, never by reading the PID file — so it stays correct even after a crash or an unclean shutdown.

Show full ~/bin/qd source
~/bin/qd
#!/bin/bash
# qd — Quran Player Daemon control wrapper.
#
# State ownership:
#   - PID file   : ~/.quran-player/control/daemon.pid
#   - Liveness   : ~/.quran-player/control/daemon.lock
#   - Socket     : ~/.quran-player/control/daemon.sock
#
# This wrapper is stateless. It never writes or deletes a PID file.

PY="$HOME/.quran-player/env/bin/python"
DAEMON="$HOME/.quran-player/daemon.py"

daemon_ready() {
    "$PY" "$DAEMON" status >/dev/null 2>&1
}

# Start the daemon if needed, wait until its socket answers.
ensure_running() {
    daemon_ready && return 0
    "$PY" "$DAEMON" start >/dev/null &
    local i
    for i in $(seq 1 30); do
        daemon_ready && return 0
        sleep 0.1
    done
    echo "Error: daemon failed to become ready within 3s" >&2
    echo "       see ~/.quran-player/control/daemon.log" >&2
    return 1
}

# Nudge i3blocks for an instant status refresh. No-op if absent.
refresh_bar() { pkill -RTMIN+8 i3blocks 2>/dev/null || true; }

case "$1" in
    start)
        if daemon_ready; then echo "OK (already running)"; exit 0; fi
        ensure_running && echo "OK" && exit 0
        exit 1
        ;;
    stop)
        if ! daemon_ready; then echo "OK (already stopped)"; exit 0; fi
        "$PY" "$DAEMON" stop
        ;;
    dir)
        shift
        if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
            "$PY" "$DAEMON" dir "-h"; exit 0
        fi
        path="$*"
        [[ "$path" != /* ]] && path="$(realpath "$path")"
        "$PY" "$DAEMON" dir "$path"
        ;;
    [0-9]*)
        ensure_running || exit 1
        "$PY" "$DAEMON" goto "$1"
        ;;
    load|repeat)
        command=$1; shift
        arg=$(IFS=:; echo "$*")
        ensure_running || exit 1
        "$PY" "$DAEMON" "$command" "$arg"
        ;;
    play|resume|toggle|next|prev|ns|ps|goto)
        ensure_running || exit 1
        "$PY" "$DAEMON" "$@"
        ;;
    *)
        # status, info, log, config, cleanup, about, conky_*, pause, stop
        # — do NOT auto-start; they must fail loudly if the daemon is down.
        "$PY" "$DAEMON" "$@"
        ;;
esac

# Ask i3blocks to re-poll on next tick. Silently skipped if absent.
refresh_bar
Why isn't conky_toggle in the wrapper? It already is — it's one of the daemon's built-in commands. The wrapper just forwards it. The daemon owns the Conky process handle and the conky.enable config, so managing Conky anywhere else would split state.

📊 Status bar widget (i3blocks)

The current surah and ayah live in the i3blocks status bar. Left-clicking the block opens the GUI; right-clicking toggles play/pause. Requires jq (sudo apt install jq).

Show full ~/.config/i3blocks/ayat.sh
~/.config/i3blocks/ayat.sh
#!/bin/bash
daemon="$HOME/bin/qd"

case $BLOCK_BUTTON in
    1)  # Left click → open GUI
        nohup "$HOME/.local/bin/quran-gui" >/dev/null 2>&1 </dev/null &
        ;;
    3)  # Right click → toggle pause/resume
        $daemon toggle
        ;;
esac

status_data="$($daemon status)"

# Check if daemon is running and playing
if echo "$status_data" | grep -q '"daemon_running": true'; then
    paused=$(echo "$status_data" | jq -r '.paused')
    surah_num=$(echo "$status_data" | jq -r '.surah')
    ayah_num=$(echo "$status_data" | jq -r '.ayah')

    if [[ -n "$surah_num" && "$surah_num" != "null" ]]; then
        surah_name=$("$HOME/.local/bin/quran-search" "$surah_num")

        # Add pause icon if paused
        if [[ "$paused" == "true" ]]; then
            icon="⏸️"
        else
            icon=""
        fi

        # i3blocks convention: full_text then short_text (do not dedupe!)
        echo "$icon $surah_name $ayah_num"
        echo "$icon $surah_name $ayah_num"
        echo "#FFD700"
    fi
fi
Show full ~/.config/i3blocks/config entry
~/.config/i3blocks/config
[ayat]
command=~/.config/i3blocks/ayat.sh
interval=1
signal=8

Tip: signal=8 lets the wrapper force an instant refresh with pkill -RTMIN+8 i3blocks — which the qd script above does automatically at the end of every invocation. With interval=1 the widget polls every second anyway, so the signal is optional and safe to drop if you prefer a quieter setup.

The status block output looks like الفاتحة 3 — surah name + ayah number, with a ⏸️ prefix when paused, rendered in gold (#FFD700) in the bar.

🛠️ Technology

Python 3.9+ Conky pygame-ce PyQt5 (tray) UNIX domain socket portalocker arabic-reshaper + python-bidi

💬 Support & Community

📝 Release History

Version history for Quran Player.

# Changelog

2.0.0 — 2026-10-20

•Linux-native, Conky-only. Dropped Windows/macOS support, removed feh and the PyQt viewer.

•Conky desktop verse display — daemon-managed lifecycle (start/stop/toggle with the daemon).

•New commands: conky_on, conky_off, conky_toggle.

•Crash-safe: orphaned conky processes are reaped on next start/stop.

•qd stop now guarantees conky is gone before returning.

•One-command installer: python install.py (no root, no venv management required from user).

•Replaced pillow with arabic-reshaper + python-bidi (needed by the Conky shaper).

•Socket permissions hardened to 0600; daemon lock acquired atomically before PID write.

•info command now queries the live daemon state over the socket (was reading stale state).

1.3.0 — 2026-10-18

•Cross-platform daemon (Linux/macOS/Windows)

•feh-based verse image display with PyQt fallback

•Initial public source release

Visits: 0

Leave a comment

5000 characters max.