Skip to content

Commit

Permalink
Merge branch 'main' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
spezifisch committed Aug 7, 2024
2 parents 8b82a2c + c287513 commit 65c5a0a
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 68 deletions.
1 change: 1 addition & 0 deletions .markdownlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
MD013: false
146 changes: 91 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# STMPS (Subsonic Terminal Music Player S)

A terminal client for *sonic music servers. Inspired by ncmpcpp and musickube.
*Stamps* is a terminal client for *sonic music servers, inspired by ncmpcpp and musickube.

Main Branch:
[![Build macOS arm64](https://github.com/spezifisch/stmps/actions/workflows/build-macos-arm.yml/badge.svg)](https://github.com/spezifisch/stmps/actions/workflows/build-macos-arm.yml)
Expand All @@ -12,106 +12,142 @@ Dev Branch:

## Features

* browse by folder
* queue songs and albums
* create and play playlists
* favorites
* volume control
* server-side scrobbling (e.g. on Navidrome, gonic)
* [MPRIS2](https://mpris2.readthedocs.io/en/latest/) control
- Browse by folder
- Queue songs and albums
- Create and play playlists
- Mark favorites
- Volume control
- Server-side scrobbling (e.g., on Navidrome, gonic)
- [MPRIS2](https://mpris2.readthedocs.io/en/latest/) control and metadata

## Screenshots

These are using [Navidrome's demo server](https://demo.navidrome.org/) ([config file](./stmp-navidromedemo.toml)).
These screenshots use [Navidrome's demo server](https://demo.navidrome.org/) ([config file](./stmp-navidromedemo.toml)).

Queue:
### Queue

![Queue View](./docs/screenshots/queue.png)

Browser:
### Browser

![Browser View](./docs/screenshots/browser.png)

## Dependencies

[mpv](https://mpv.io):
### Required Software

* Linux (Debian/Ubuntu): `apt install pkg-config libmpv libmpv-dev`
* MacOS (Homebrew): `brew install pkg-config mpv` (not the cask)
- [mpv](https://mpv.io)
- Linux (Debian/Ubuntu): `apt install pkg-config libmpv libmpv-dev`
- MacOS (Homebrew): `brew install pkg-config mpv` (not the cask)

Go build dependencies)
### Go Build Dependencies

* Go 1.19+
* [tview](https://github.com/rivo/tview)
* [go-mpv](https://github.com/supersonic-app/go-mpv) (supersonic's fork)

## Compiling

stmp should compile normally with `go build`. Cgo is needed for linking with libmpv.
Compile STMPS with `go build`. Cgo is needed for interfacing with libmpv.

## Configuration

stmp looks for a config file called `stmp.toml` in either `$HOME/.config/stmp`
or the directory in which the executable is placed.
STMPS looks for a configuration file named `stmp.toml` in either `$HOME/.config/stmp` or the directory containing the executable.

### Example configuration
### Example Configuration

```toml
[auth]
username = 'admin'
password = 'password'
plaintext = true # Use 'legacy' unsalted password auth. (default: false)
plaintext = true # Use 'legacy' unsalted password authentication (default: false)

[server]
host = 'https://your-subsonic-host.tld'
scrobble = true # Use Subsonic scrobbling for last.fm/ListenBrainz (default: false)
scrobble = true # Use Subsonic scrobbling for last.fm/ListenBrainz (default: false)

[client]
random-songs = 50
```

## Usage

* Q - quit
* 1 - folder view
* 2 - queue view
* 3 - playlist view
* 4 - log (errors, etc) view
* Escape/Return - close modal if open
### General Navigation

### Playback
- `Q`: Quit
- `1`: Folder view
- `2`: Queue view
- `3`: Playlist view
- `4`: Log (errors, etc.) view
- `Escape`/`Return`: Close modal if open

These are accessible in every view.
### Playback Controls

* p - play/pause
* P - stop
* > - next song
* -/= volume down/volume up
* ,/. seek -10/+10 seconds
* r - add 50 random songs to the queue
These controls are accessible from any view:

### Browser
- `p`: Play/pause
- `P`: Stop
- `>`: Next song
- `-`/`=`: Volume down/volume up
- `,`/`.`: Seek -10/+10 seconds
- `r`: Add 50 random songs to the queue

* Enter - play song (clears current queue)
* a - add album or song to queue
* y - toggle star on song/album
* A - add song to playlist
* R - refresh the list (if in artist directory, only refreshes that artist)
* / - Search artists
* n - Continue search forward
* N - Continue search backwards
### Browser Controls

### Queue
- `Enter`: Play song (clears current queue)
- `a`: Add album or song to queue
- `y`: Toggle star on song/album
- `A`: Add song to playlist
- `R`: Refresh the list (if in artist directory, only refreshes that artist)
- `/`: Search artists
- `n`: Continue search forward
- `N`: Continue search backward

### Queue Controls

* d/Delete - remove currently selected song from the queue
* D - remove all songs from queue
* y - toggle star on song
- `d`/`Delete`: Remove currently selected song from the queue
- `D`: Remove all songs from queue
- `y`: Toggle star on song

### Playlist
### Playlist Controls

* n - new playlist
* d - delete playlist
* a - add playlist or song to queue
- `n`: New playlist
- `d`: Delete playlist
- `a`: Add playlist or song to queue

## Credits

* This is a fork of [STMP](https://github.com/wildeyedskies/stmp), see
[AUTHORS](./AUTHORS). I decided to rename my fork as its codebase has diverged
quite a bit.
This is a fork of [STMP](https://github.com/wildeyedskies/stmp). See [AUTHORS](./AUTHORS) for more information. The codebase has diverged significantly from the original.

## Advanced Configuration and Features

### MPRIS2 Integration

To enable MPRIS2 support (Linux only), run STMPS with the `-mpris` flag. Ensure you have D-Bus set up correctly on your system.

### MacOS Media Control

On MacOS, STMPS integrates with the native MediaPlayer framework to handle system media controls. This is automatically enabled if running on MacOS. *Note:* This is work in progress.

### Profiling

To profile the application, use the following flags:

- `-cpuprofile=<file>`: Write CPU profile to `file`
- `-memprofile=<file>`: Write memory profile to `file`

These flags are useful for performance debugging and analysis.

### Debugging and Logs

View logs and error messages in the log view by pressing `4`. This can help diagnose issues with server connections, playback, or other functionalities.

## Contributing

Contributions are welcome! Feel free to open issues or submit pull requests on GitHub. For major changes, please discuss first to ensure alignment with the project goals.

## Licensing

STMPS is licensed under the GNU General Public License v3.0 (GPL-3.0-only). This license allows you to freely use, modify, and distribute the software, provided that any distributed versions of the software, or derivative works, are also licensed under the GPL-3.0-only.

For more details, refer to the [LICENSE](./LICENSE) file in the repository.
4 changes: 2 additions & 2 deletions remote/mpris2.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,9 @@ func (m *MprisPlayer) Previous() *dbus.Error {
return nil
}

func (m *MprisPlayer) Seek(offset int64, _ int) *dbus.Error {
func (m *MprisPlayer) Seek(offset int64, _ int) (int64, error) {
// TODO not implemented
return nil
return 0, nil
}

func (m *MprisPlayer) SetPosition(trackId dbus.ObjectPath, position int64) *dbus.Error {
Expand Down
1 change: 1 addition & 0 deletions stmps.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ func main() {
connection.Host = viper.GetString("server.host")
connection.PlaintextAuth = viper.GetBool("auth.plaintext")
connection.Scrobble = viper.GetBool("server.scrobble")
connection.RandomSongNumber = viper.GetUint("client.random-songs")

indexResponse, err := connection.GetIndexes()
if err != nil {
Expand Down
27 changes: 16 additions & 11 deletions subsonic/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@ import (
)

type SubsonicConnection struct {
Username string
Password string
Host string
PlaintextAuth bool
Scrobble bool
Username string
Password string
Host string
PlaintextAuth bool
Scrobble bool
RandomSongNumber uint

clientName string
clientVersion string
clientName string
clientVersion string

logger logger.LoggerInterface
directoryCache map[string]SubsonicResponse
logger logger.LoggerInterface
directoryCache map[string]SubsonicResponse
}

func Init(logger logger.LoggerInterface) *SubsonicConnection {
Expand Down Expand Up @@ -241,8 +242,12 @@ func (connection *SubsonicConnection) GetMusicDirectory(id string) (*SubsonicRes

func (connection *SubsonicConnection) GetRandomSongs() (*SubsonicResponse, error) {
query := defaultQuery(connection)
// Let's get 50 random songs, default is 10
query.Set("size", "50")
// Try loading the number of random songs from the config file (and clamp it to 500) if not, default to 50
if connection.RandomSongNumber > 0 && connection.RandomSongNumber < 500 {
query.Set("size", strconv.FormatInt(int64(connection.RandomSongNumber), 10))
} else {
query.Set("size", "50")
}
requestUrl := connection.Host + "/rest/getRandomSongs" + "?" + query.Encode()
resp, err := connection.getResponse("GetRandomSongs", requestUrl)
if err != nil {
Expand Down

0 comments on commit 65c5a0a

Please sign in to comment.