tidal-cli 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tidal_cli-1.0.0/PKG-INFO +171 -0
- tidal_cli-1.0.0/README.md +139 -0
- tidal_cli-1.0.0/pyproject.toml +52 -0
- tidal_cli-1.0.0/setup.cfg +4 -0
- tidal_cli-1.0.0/setup.py +31 -0
- tidal_cli-1.0.0/ticli/__init__.py +3 -0
- tidal_cli-1.0.0/ticli/cli.py +19 -0
- tidal_cli-1.0.0/ticli/player.py +1452 -0
- tidal_cli-1.0.0/ticli/tests/__init__.py +0 -0
- tidal_cli-1.0.0/ticli/tests/test_full_e2e.py +70 -0
- tidal_cli-1.0.0/ticli/utils/__init__.py +1 -0
- tidal_cli-1.0.0/ticli/utils/credential_store.py +94 -0
- tidal_cli-1.0.0/tidal_cli.egg-info/PKG-INFO +171 -0
- tidal_cli-1.0.0/tidal_cli.egg-info/SOURCES.txt +16 -0
- tidal_cli-1.0.0/tidal_cli.egg-info/dependency_links.txt +1 -0
- tidal_cli-1.0.0/tidal_cli.egg-info/entry_points.txt +2 -0
- tidal_cli-1.0.0/tidal_cli.egg-info/requires.txt +6 -0
- tidal_cli-1.0.0/tidal_cli.egg-info/top_level.txt +1 -0
tidal_cli-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tidal-cli
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Terminal music player for TIDAL — search, browse, queue, and stream lossless audio from your terminal
|
|
5
|
+
Author: odonald
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/odonald/ticli
|
|
8
|
+
Project-URL: Repository, https://github.com/odonald/ticli
|
|
9
|
+
Project-URL: Issues, https://github.com/odonald/ticli/issues
|
|
10
|
+
Project-URL: Funding, https://buymeacoffee.com/odonald
|
|
11
|
+
Keywords: tidal,music,terminal,cli,player,tui,streaming,lossless,hifi
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: Operating System :: MacOS
|
|
16
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Players
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
Requires-Dist: click>=8.0
|
|
27
|
+
Requires-Dist: rich>=13.0
|
|
28
|
+
Requires-Dist: tidalapi>=0.8.0
|
|
29
|
+
Provides-Extra: keyring
|
|
30
|
+
Requires-Dist: keyring>=24.0; extra == "keyring"
|
|
31
|
+
Dynamic: requires-python
|
|
32
|
+
|
|
33
|
+
# Ticli
|
|
34
|
+
|
|
35
|
+
A terminal music player for TIDAL. Search, browse, queue, and play music — all from your terminal.
|
|
36
|
+
|
|
37
|
+
Ticli connects directly to TIDAL's API using your premium account. No desktop app needed. Just authenticate, search, and play.
|
|
38
|
+
|
|
39
|
+
Works on **macOS** and **Linux**.
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
╭──────────────────────── Ticli ────────────────────────╮
|
|
43
|
+
│ │
|
|
44
|
+
│ ▶ ♥ Arlo Parks - Sophie │
|
|
45
|
+
│ Super Sad Generation │
|
|
46
|
+
│ 1:47 ━━━━━━━━●━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3:28 │
|
|
47
|
+
│ Queue: 3/12 LOSSLESS │
|
|
48
|
+
│ Next: Cola • Arlo Parks │
|
|
49
|
+
│ │
|
|
50
|
+
│ [space] play/pause [n/→] next [←] prev │
|
|
51
|
+
│ [s] search [q] queue [p] playlists │
|
|
52
|
+
│ [l] like [r] radio [t] mini [m] more │
|
|
53
|
+
│ │
|
|
54
|
+
╰────────────────────────────────────────────────────────╯
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
- **Search** — Find tracks, albums, artists, and playlists
|
|
60
|
+
- **Browse** — Navigate album and playlist tracklists
|
|
61
|
+
- **Queue** — Manage your playback queue, reorder, remove tracks
|
|
62
|
+
- **Playlists** — Browse and play your saved playlists
|
|
63
|
+
- **Likes** — Toggle favorites on any track
|
|
64
|
+
- **Radio** — Generate a station from any track
|
|
65
|
+
- **Mini mode** — Condensed single-line display
|
|
66
|
+
- **Session restore** — Picks up where you left off
|
|
67
|
+
- **Lossless & Hi-Res** — Stream up to 24-bit/192kHz FLAC
|
|
68
|
+
- **Secure auth** — OAuth tokens stored in your OS keychain
|
|
69
|
+
|
|
70
|
+
## Install
|
|
71
|
+
|
|
72
|
+
Requires Python 3.10+ and [ffmpeg](https://ffmpeg.org).
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# macOS
|
|
76
|
+
brew install ffmpeg python3
|
|
77
|
+
pip install tidal-cli
|
|
78
|
+
|
|
79
|
+
# Ubuntu / Debian
|
|
80
|
+
sudo apt install ffmpeg python3-pip
|
|
81
|
+
pip install tidal-cli
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
For secure token storage in your OS keychain (recommended):
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pip install "tidal-cli[keyring]"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Usage
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
ticli
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
On first run you'll get a URL to authorize with your TIDAL account. After that, your session is cached and you go straight to the player.
|
|
97
|
+
|
|
98
|
+
### Quality
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
ticli --quality HIRES # 24-bit hi-res FLAC
|
|
102
|
+
ticli --quality LOSSLESS # 16-bit FLAC
|
|
103
|
+
ticli --quality HIGH # lossless FLAC (default)
|
|
104
|
+
ticli --quality LOW # 320kbps
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Keybindings
|
|
108
|
+
|
|
109
|
+
#### Player
|
|
110
|
+
|
|
111
|
+
| Key | Action |
|
|
112
|
+
|-----|--------|
|
|
113
|
+
| `space` | Play / pause |
|
|
114
|
+
| `n` `→` | Next track |
|
|
115
|
+
| `←` | Previous track |
|
|
116
|
+
| `s` | Search |
|
|
117
|
+
| `q` | Queue |
|
|
118
|
+
| `p` | Playlists |
|
|
119
|
+
| `l` | Like / unlike track |
|
|
120
|
+
| `r` | Start radio from track |
|
|
121
|
+
| `t` | Toggle mini player |
|
|
122
|
+
| `m` | Show more controls |
|
|
123
|
+
| `esc` | Quit |
|
|
124
|
+
|
|
125
|
+
#### Search
|
|
126
|
+
|
|
127
|
+
| Key | Action |
|
|
128
|
+
|-----|--------|
|
|
129
|
+
| `↑` `↓` | Navigate results |
|
|
130
|
+
| `enter` `→` | Play track / open album or artist |
|
|
131
|
+
| `backspace` | Delete character |
|
|
132
|
+
| `esc` `←` | Back |
|
|
133
|
+
|
|
134
|
+
#### Queue
|
|
135
|
+
|
|
136
|
+
| Key | Action |
|
|
137
|
+
|-----|--------|
|
|
138
|
+
| `↑` `↓` | Navigate |
|
|
139
|
+
| `enter` | Jump to track |
|
|
140
|
+
| `x` | Remove track |
|
|
141
|
+
| `esc` `←` | Back |
|
|
142
|
+
|
|
143
|
+
## How it works
|
|
144
|
+
|
|
145
|
+
Ticli uses [tidalapi](https://github.com/tamland/python-tidal) to authenticate and fetch audio stream URLs. Audio is played through [ffplay](https://ffmpeg.org/ffplay.html). The TUI is built with [Rich](https://github.com/Textualize/rich).
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
┌─────────┐ OAuth ┌───────────┐ stream URL ┌───────────┐
|
|
149
|
+
│ Ticli │ ──────────────► │ TIDAL │ ──────────────► │ ffplay │
|
|
150
|
+
│ (TUI) │ ◄────────────── │ API │ │ │
|
|
151
|
+
└─────────┘ metadata └───────────┘ └───────────┘
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Auth & credentials
|
|
155
|
+
|
|
156
|
+
OAuth tokens are stored in your OS keychain (macOS Keychain or GNOME Keyring). Falls back to `~/.config/ticli/session.json` with `0600` permissions if keyring is unavailable.
|
|
157
|
+
|
|
158
|
+
## Requirements
|
|
159
|
+
|
|
160
|
+
- macOS or Linux
|
|
161
|
+
- Python 3.10+
|
|
162
|
+
- TIDAL Premium subscription
|
|
163
|
+
- ffmpeg
|
|
164
|
+
|
|
165
|
+
## Support
|
|
166
|
+
|
|
167
|
+
If you enjoy Ticli, consider [buying me a coffee](https://buymeacoffee.com/odonald).
|
|
168
|
+
|
|
169
|
+
## License
|
|
170
|
+
|
|
171
|
+
MIT
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Ticli
|
|
2
|
+
|
|
3
|
+
A terminal music player for TIDAL. Search, browse, queue, and play music — all from your terminal.
|
|
4
|
+
|
|
5
|
+
Ticli connects directly to TIDAL's API using your premium account. No desktop app needed. Just authenticate, search, and play.
|
|
6
|
+
|
|
7
|
+
Works on **macOS** and **Linux**.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
╭──────────────────────── Ticli ────────────────────────╮
|
|
11
|
+
│ │
|
|
12
|
+
│ ▶ ♥ Arlo Parks - Sophie │
|
|
13
|
+
│ Super Sad Generation │
|
|
14
|
+
│ 1:47 ━━━━━━━━●━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3:28 │
|
|
15
|
+
│ Queue: 3/12 LOSSLESS │
|
|
16
|
+
│ Next: Cola • Arlo Parks │
|
|
17
|
+
│ │
|
|
18
|
+
│ [space] play/pause [n/→] next [←] prev │
|
|
19
|
+
│ [s] search [q] queue [p] playlists │
|
|
20
|
+
│ [l] like [r] radio [t] mini [m] more │
|
|
21
|
+
│ │
|
|
22
|
+
╰────────────────────────────────────────────────────────╯
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
- **Search** — Find tracks, albums, artists, and playlists
|
|
28
|
+
- **Browse** — Navigate album and playlist tracklists
|
|
29
|
+
- **Queue** — Manage your playback queue, reorder, remove tracks
|
|
30
|
+
- **Playlists** — Browse and play your saved playlists
|
|
31
|
+
- **Likes** — Toggle favorites on any track
|
|
32
|
+
- **Radio** — Generate a station from any track
|
|
33
|
+
- **Mini mode** — Condensed single-line display
|
|
34
|
+
- **Session restore** — Picks up where you left off
|
|
35
|
+
- **Lossless & Hi-Res** — Stream up to 24-bit/192kHz FLAC
|
|
36
|
+
- **Secure auth** — OAuth tokens stored in your OS keychain
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
Requires Python 3.10+ and [ffmpeg](https://ffmpeg.org).
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# macOS
|
|
44
|
+
brew install ffmpeg python3
|
|
45
|
+
pip install tidal-cli
|
|
46
|
+
|
|
47
|
+
# Ubuntu / Debian
|
|
48
|
+
sudo apt install ffmpeg python3-pip
|
|
49
|
+
pip install tidal-cli
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
For secure token storage in your OS keychain (recommended):
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install "tidal-cli[keyring]"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Usage
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
ticli
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
On first run you'll get a URL to authorize with your TIDAL account. After that, your session is cached and you go straight to the player.
|
|
65
|
+
|
|
66
|
+
### Quality
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
ticli --quality HIRES # 24-bit hi-res FLAC
|
|
70
|
+
ticli --quality LOSSLESS # 16-bit FLAC
|
|
71
|
+
ticli --quality HIGH # lossless FLAC (default)
|
|
72
|
+
ticli --quality LOW # 320kbps
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Keybindings
|
|
76
|
+
|
|
77
|
+
#### Player
|
|
78
|
+
|
|
79
|
+
| Key | Action |
|
|
80
|
+
|-----|--------|
|
|
81
|
+
| `space` | Play / pause |
|
|
82
|
+
| `n` `→` | Next track |
|
|
83
|
+
| `←` | Previous track |
|
|
84
|
+
| `s` | Search |
|
|
85
|
+
| `q` | Queue |
|
|
86
|
+
| `p` | Playlists |
|
|
87
|
+
| `l` | Like / unlike track |
|
|
88
|
+
| `r` | Start radio from track |
|
|
89
|
+
| `t` | Toggle mini player |
|
|
90
|
+
| `m` | Show more controls |
|
|
91
|
+
| `esc` | Quit |
|
|
92
|
+
|
|
93
|
+
#### Search
|
|
94
|
+
|
|
95
|
+
| Key | Action |
|
|
96
|
+
|-----|--------|
|
|
97
|
+
| `↑` `↓` | Navigate results |
|
|
98
|
+
| `enter` `→` | Play track / open album or artist |
|
|
99
|
+
| `backspace` | Delete character |
|
|
100
|
+
| `esc` `←` | Back |
|
|
101
|
+
|
|
102
|
+
#### Queue
|
|
103
|
+
|
|
104
|
+
| Key | Action |
|
|
105
|
+
|-----|--------|
|
|
106
|
+
| `↑` `↓` | Navigate |
|
|
107
|
+
| `enter` | Jump to track |
|
|
108
|
+
| `x` | Remove track |
|
|
109
|
+
| `esc` `←` | Back |
|
|
110
|
+
|
|
111
|
+
## How it works
|
|
112
|
+
|
|
113
|
+
Ticli uses [tidalapi](https://github.com/tamland/python-tidal) to authenticate and fetch audio stream URLs. Audio is played through [ffplay](https://ffmpeg.org/ffplay.html). The TUI is built with [Rich](https://github.com/Textualize/rich).
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
┌─────────┐ OAuth ┌───────────┐ stream URL ┌───────────┐
|
|
117
|
+
│ Ticli │ ──────────────► │ TIDAL │ ──────────────► │ ffplay │
|
|
118
|
+
│ (TUI) │ ◄────────────── │ API │ │ │
|
|
119
|
+
└─────────┘ metadata └───────────┘ └───────────┘
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Auth & credentials
|
|
123
|
+
|
|
124
|
+
OAuth tokens are stored in your OS keychain (macOS Keychain or GNOME Keyring). Falls back to `~/.config/ticli/session.json` with `0600` permissions if keyring is unavailable.
|
|
125
|
+
|
|
126
|
+
## Requirements
|
|
127
|
+
|
|
128
|
+
- macOS or Linux
|
|
129
|
+
- Python 3.10+
|
|
130
|
+
- TIDAL Premium subscription
|
|
131
|
+
- ffmpeg
|
|
132
|
+
|
|
133
|
+
## Support
|
|
134
|
+
|
|
135
|
+
If you enjoy Ticli, consider [buying me a coffee](https://buymeacoffee.com/odonald).
|
|
136
|
+
|
|
137
|
+
## License
|
|
138
|
+
|
|
139
|
+
MIT
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=64", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "tidal-cli"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Terminal music player for TIDAL — search, browse, queue, and stream lossless audio from your terminal"
|
|
9
|
+
license = "MIT"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
readme = {file = "README.md", content-type = "text/markdown"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "odonald"},
|
|
14
|
+
]
|
|
15
|
+
keywords = ["tidal", "music", "terminal", "cli", "player", "tui", "streaming", "lossless", "hifi"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: End Users/Desktop",
|
|
20
|
+
"Operating System :: MacOS",
|
|
21
|
+
"Operating System :: POSIX :: Linux",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Programming Language :: Python :: 3.14",
|
|
28
|
+
"Topic :: Multimedia :: Sound/Audio :: Players",
|
|
29
|
+
]
|
|
30
|
+
dependencies = [
|
|
31
|
+
"click>=8.0",
|
|
32
|
+
"rich>=13.0",
|
|
33
|
+
"tidalapi>=0.8.0",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
keyring = ["keyring>=24.0"]
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://github.com/odonald/ticli"
|
|
41
|
+
Repository = "https://github.com/odonald/ticli"
|
|
42
|
+
Issues = "https://github.com/odonald/ticli/issues"
|
|
43
|
+
Funding = "https://buymeacoffee.com/odonald"
|
|
44
|
+
|
|
45
|
+
[project.scripts]
|
|
46
|
+
ticli = "ticli.cli:main"
|
|
47
|
+
|
|
48
|
+
[tool.setuptools.packages.find]
|
|
49
|
+
include = ["ticli", "ticli.*"]
|
|
50
|
+
|
|
51
|
+
[tool.pytest.ini_options]
|
|
52
|
+
testpaths = ["ticli/tests"]
|
tidal_cli-1.0.0/setup.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Setup for ticli package."""
|
|
2
|
+
|
|
3
|
+
from setuptools import find_packages, setup
|
|
4
|
+
|
|
5
|
+
setup(
|
|
6
|
+
name="tidal-cli",
|
|
7
|
+
version="1.0.0",
|
|
8
|
+
description="Ticli - Terminal music player for TIDAL",
|
|
9
|
+
author="Ticli",
|
|
10
|
+
license="MIT",
|
|
11
|
+
packages=find_packages(include=["ticli", "ticli.*"]),
|
|
12
|
+
python_requires=">=3.10",
|
|
13
|
+
install_requires=[
|
|
14
|
+
"click>=8.0",
|
|
15
|
+
"rich>=13.0",
|
|
16
|
+
"tidalapi>=0.8.0",
|
|
17
|
+
],
|
|
18
|
+
extras_require={
|
|
19
|
+
"keyring": ["keyring>=24.0"],
|
|
20
|
+
},
|
|
21
|
+
entry_points={
|
|
22
|
+
"console_scripts": [
|
|
23
|
+
"ticli=ticli.cli:main",
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
classifiers=[
|
|
27
|
+
"Programming Language :: Python :: 3",
|
|
28
|
+
"License :: OSI Approved :: MIT License",
|
|
29
|
+
"Operating System :: OS Independent",
|
|
30
|
+
],
|
|
31
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Ticli - Terminal music player for TIDAL."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@click.command()
|
|
7
|
+
@click.option("--quality", default="HIGH", type=click.Choice(["LOW", "HIGH", "LOSSLESS", "HIRES"], case_sensitive=False), help="Audio quality")
|
|
8
|
+
def cli(quality):
|
|
9
|
+
"""Ticli - Terminal music player for TIDAL."""
|
|
10
|
+
from ticli.player import HeadlessTidalPlayer
|
|
11
|
+
HeadlessTidalPlayer(quality=quality).run()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main():
|
|
15
|
+
cli()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
if __name__ == "__main__":
|
|
19
|
+
main()
|