diskplayer

package module
v0.0.0-...-9f15ffa Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 25, 2023 License: MIT Imports: 18 Imported by: 0

README

Note: This was the first Go code I wrote, it's probably not so great

diskplayer

diskplayer is essentially a Spotify "play and pause controller", written in Go, built around zmb3's existing Spotify Web API wrapper.

This software is part of the larger diskplayer project of mine: a Spotify music player running on a Raspberry Pi, which uses a 3.5" floppy disks as it's "media". In addition to the player and recorder code in this repo, the project makes use of Spotifyd as a Spotify client, also running on the Pi. This is detailed in my blog post on the project.

There is also a YouTube video of Diskplayer here: https://youtu.be/1usBGe_ZiGc

Diskplayer

There are two components to the core diskplayer software. The "player" binary and the "recorder" binary. The player binary can be used to obtain a new long-lived Spotify client authentication token, as well as accepting Spotify URI or a path to a file containing a Spotify URI which it will attempt to play.

Playback occurs on an existing Spotify playback device, which is specified in a configuration file.

The recorder binary runs as an HTTP server, and exposes a simple UI which can be used to record a Spotify URI to a chosen location.

Note: I do not intend to "support" this code. It was a great learning exercise for me in my journey to learn some basic Go, but it's not something I see myself continuing to develop.

Build

Requirements

displayer was developed using Go 1.13 on Ubuntu 19.10, and uses go modules to install its required dependencies. Follow the instructions here to download and install the latest version of Go: https://golang.org/doc/install

Player build

To build the player binary, run the following command from the terminal:

$ go build -o player ./cmd/player/main.go

This will produce a player binary file in current directory. You will probably want to make this an executable binary file:

$ chmod a+x player 
Recorder build

To build the recorder binary, run the following command from the terminal:

$ go build -o recorder ./cmd/recorder/main.go

This will produce a recorder binary file in current directory. You will probably want to make this an executable binary file:

$ chmod a+x recorder 

Tests

Tests can be run by issuing the following command from the project directory:

$ go test

Configuration

In this repository there exists a diskplayer.yaml configuration file which must be updated with the relevant config values.

diskplayer will search for the diskplayer.yaml configuration file in one of the following locations:

  • /etc/diskplayer/
  • $HOME/.config/diskplayer/
  • or the current directory from which the player or recorder binary is being run.

For the Spotify-related config values see the documentation for the zmb3's Spotify wrapper. The callback URL must match that as configured when you set up your Spotify API application.

The recorder.folder_path configuration value represents to the folder to which the disk device will be mounted during the recording process. You will need to ensure that this folder exists.

Player Usage

Retrieving a new authentication token

Once the Spotify API application has been registered and the appropriate configuration values stored in the diskplayer.yaml file, the player binary can be run to create an authentication token which is stored and used for playback operations.

Before playback can be achieved a client OAuth2.0 access token must be retrieved. This must be run on a device where the user has access to a browser, as the user will be prompted to allow the diskplayer application permission to access and control the user's Spotify playback devices. This token is saved in json format to the file specified in the diskplayer.yaml configuration file, and can be copied across to a different device from which the player binary will be used (e.g. you can run the auth command from your laptop, and copy the json file across to a headless Raspberry Pi device).

To retreive a new authentication token, run the following command, and follow text that appears in the terminal.

$ ./player -auth
Play

Once a token file has been saved, you can begin playback operations. There are two methods of playing an album or playlist.

  • by specifying a Spotify URI. E.g. :
$ ./player -uri spotify:album:3oyu7chRauu88JYPYfFB55
  • or by specifying a path to a file which contains a single Spotify URI:
$ ./player -path /tmp/diskplayer.contents
Pause

Playback can be paused on the diskplayer device by running the following command:

$ ./player -pause

Recorder Usage

The recorder binary runs an HTTP server which offers a simple HTML form which can be used to translate a record a Spotify URI to the location as specified in the diskplayer.yaml configuration file.

Run the server by executing the following command:

$ ./recorder

This will run an HTTP server on the port specfied in the diskplayer.yaml configuration file. If you visit http://<IP address of device>:<diskplayer recorder port>/ you should see the following page:

Recorder home page

The section titled lsblk output: does exactly that - it lists the devices that can found on the machine running the recorder server. The intention is to provide to the user an indication of where a disk drive can be found. From the above screenshot the user can assume that the disk drive device can be found at /dev/sda. If you don't see any sdx device listed you may need to insert a disk and refresh the page.

To record a Spotify URI you will need a device path (i.e. /dev/sda) and a Spotify web URL (note that this is not a Spotify URI). I've done this as it is easy to copy a web URL from one tab into the Recorder tab.

To obtain a Spotify URL for an album or playlist, open https://play.spotify.com in your browser and locate an album that you wish to record:

Spotify album page

Copy the full URL for this page, and enter into the diskplayer record page, along with the path to the device to which the disk drive is attached:

Recorder album

Cick the "Record disk" button, and you should see a success page telling you that the recording was successful:

Recording success

This disk can now be played :)

Documentation

Index

Constants

View Source
const (
	DEFAULT_CONFIG_NAME   = "diskplayer"
	STATE_IDENTIFIER      = "abc123"
	RECORD_FILENAME       = "recorder.filename"
	RECORD_FOLDER_PATH    = "recorder.folder_path"
	RECORD_SERVER_PORT    = "recorder.server_port"
	SPOTIFY_CALLBACK_URL  = "spotify.callback_url"
	SPOTIFY_CLIENT_ID     = "spotify.client_id"
	SPOTIFY_CLIENT_SECRET = "spotify.client_secret"
	SPOTIFY_DEVICE_NAME   = "spotify.device_name"
	TOKEN_PATH            = "token.path"
)

Variables

This section is empty.

Functions

func ConfigValue

func ConfigValue(key string) string

ConfigValue returns the configuration value identified by the provided key. If none is found the application quits with an error message and exit code 1.

func NewAuthenticator

func NewAuthenticator() (*spotify.Authenticator, error)

NewAuthenticator returns a Spotify authenticator object configured with the required callback URL, client IT and client secret. An error is returned if one is encountered

func NewToken

func NewToken(ds DiskplayerServer) (*oauth2.Token, error)

NewToken will create a new OAuth2 token request. The user will be prompted to visit a URL, and after access is granted a new OAuth2 token is returned. An error is returned if encountered.

func Pause

func Pause(c Client) error

Pause will pause the Spotify playback if the Diskplayer is the currently active Spotify device. An error is returned if one is encountered.

func PlayPath

func PlayPath(c Client, p string) error

PlayPath will play an album or playlist by reading a Spotify URI from a file whose filepath is passed into the function. An error is returned if one is encountered.

func PlayUri

func PlayUri(c Client, u string) error

PlayURI will play the album or playlist Spotify URI that is passed in to the function. An error is returned if one is encountered.

func ReadConfig

func ReadConfig(n string)

ReadConfig reads in the configuration values from the diskplayer.yaml configuration file.

func ReadToken

func ReadToken() (*oauth2.Token, error)

ReadToken will attempt to deserialize a token whose path is defined in the diskplayer.yaml configuration file under the token.file_path field. Returns a pointer to an oauth2 token object or any error encountered.

func Record

func Record(url string, fullPath string) error

Record takes in a web URL which links to a Spotify album or playlist and records the corresponding Spotify ID to the filepath specified in the diskplayer.yaml configuration file under the recorder.file_path field. The web URL should be something like https://open.spotify.com/album/1S7mumn7D4riEX2gVWYgPO Returns an error if one is encountered.

func SaveToken

func SaveToken(token *oauth2.Token) error

SaveToken will serialize the provided token and save it to the file whose path is defined in the diskplayer. yaml configuration file under the token.file_path field. Returns an error if one is encountered.

Types

type CallbackHandler

type CallbackHandler struct {
	// contains filtered or unexported fields
}

func (CallbackHandler) ServeHTTP

func (h CallbackHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

An implementation of the Handler ServeHTTP function for the CallbackHandler struct.

type Client

type Client interface {
	PlayerDevices() ([]spotify.PlayerDevice, error)
	Pause() error
	TransferPlayback(deviceID spotify.ID, play bool) error
	PlayOpt(opt *spotify.PlayOptions) error
}

type DiskplayerServer

type DiskplayerServer interface {
	RunRecordServer() error
	RunCallbackServer() (*http.Server, error)
	TokenChannel() chan *oauth2.Token
	Authenticator() *spotify.Authenticator
}

type ErrorPage

type ErrorPage struct {
	Body []byte
}

type IndexPage

type IndexPage struct {
	Lsblk []byte
}

type RealDiskplayerServer

type RealDiskplayerServer struct {
	// contains filtered or unexported fields
}

func NewDiskplayerServer

func NewDiskplayerServer(a *spotify.Authenticator, ch chan *oauth2.Token) *RealDiskplayerServer

NewDiskplayerServer returns a new DiskplayerServer instance. The arguments are required if the server instance is to be used to obtain a new Spotify auth token.

func (*RealDiskplayerServer) Authenticator

func (s *RealDiskplayerServer) Authenticator() *spotify.Authenticator

func (*RealDiskplayerServer) RunCallbackServer

func (s *RealDiskplayerServer) RunCallbackServer() (*http.Server, error)

RunCallbackServer creates a web server running on the port defined in the configuration file under the spotify. callback_url field. A pointer to the server object is returned so that it can be shutdown when no longer needed.

func (*RealDiskplayerServer) RunRecordServer

func (s *RealDiskplayerServer) RunRecordServer() error

RunRecordServer creates a web server running on the port defined in the configuration file under the recorder. server_port field. Files are served directly from the "static" folder.

func (*RealDiskplayerServer) TokenChannel

func (s *RealDiskplayerServer) TokenChannel() chan *oauth2.Token

type SpotifyClient

type SpotifyClient struct {
	// contains filtered or unexported fields
}

func NewClient

func NewClient(a *spotify.Authenticator, t *oauth2.Token) *SpotifyClient

Returns an authenticated Spotify client object, or an error if encountered.

func (*SpotifyClient) Pause

func (sc *SpotifyClient) Pause() error

Pause will pause playback for the currently active device.

func (*SpotifyClient) PlayOpt

func (sc *SpotifyClient) PlayOpt(opt *spotify.PlayOptions) error

PlayOpt will initiate playback on the device as specified in the PlayOptions.

func (*SpotifyClient) PlayerDevices

func (sc *SpotifyClient) PlayerDevices() ([]spotify.PlayerDevice, error)

PlayerDevices will return a list of available Spotify devices. An error is returned if encountered.

func (*SpotifyClient) TransferPlayback

func (sc *SpotifyClient) TransferPlayback(deviceID spotify.ID, play bool) error

TransferPlayback will transfer the Spotify playback to the specified device.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL