2020-08-19 11:40:31 -08:00
GO_VERSION = $( shell grep "^go " go.mod | cut -f 2 -d ' ' )
2020-03-06 07:50:39 -09:00
NODE_VERSION = $( shell cat .nvmrc)
2020-01-13 18:53:23 -09:00
2021-10-23 17:27:19 -08:00
i f n e q ( "$(wildcard .git/HEAD)" , "" )
2020-01-26 08:36:24 -09:00
GIT_SHA = $( shell git rev-parse --short HEAD)
2024-10-15 12:46:01 -08:00
GIT_TAG = $( shell git describe --tags ` git rev-list --tags --max-count= 1` ) -SNAPSHOT
2021-09-06 17:26:04 -08:00
e l s e
GIT_SHA = source_archive
2024-10-15 12:46:01 -08:00
GIT_TAG = $( patsubst navidrome-%,v%,$( notdir $( PWD) ) ) -SNAPSHOT
2021-07-15 05:49:34 -08:00
e n d i f
2020-01-25 07:06:04 -09:00
2024-10-15 12:46:01 -08:00
SUPPORTED_PLATFORMS ?= linux/amd64,linux/arm64,linux/arm/v5,linux/arm/v6,linux/arm/v7,linux/386,darwin/amd64,darwin/arm64,windows/amd64,windows/386
2024-10-15 18:47:05 -08:00
IMAGE_PLATFORMS ?= $( shell echo $( SUPPORTED_PLATFORMS) | tr ',' '\n' | grep "linux" | grep -v "arm/v5" | tr '\n' ',' | sed 's/,$$//' )
2024-10-15 12:46:01 -08:00
PLATFORMS ?= $( SUPPORTED_PLATFORMS)
DOCKER_TAG ?= deluan/navidrome:develop
# Taglib version to use in cross-compilation, from https://github.com/navidrome/cross-taglib
CROSS_TAGLIB_VERSION ?= 2.0.2-1
2020-03-20 08:21:41 -08:00
2024-08-07 11:36:29 -08:00
UI_SRC_FILES := $( shell find ui -type f -not -path "ui/build/*" -not -path "ui/node_modules/*" )
2021-08-21 09:45:34 -08:00
setup : check_env download -deps setup -git ##@1_Run_First Install dependencies and prepare development environment
2021-05-01 07:14:24 -08:00
@echo Downloading Node dependencies...
@( cd ./ui && npm ci)
.PHONY : setup
dev : check_env ##@Development Start Navidrome in development mode, with hot-reload for both frontend and backend
2020-04-28 19:24:57 -08:00
npx foreman -j Procfile.dev -p 4533 start
2020-03-20 08:21:41 -08:00
.PHONY : dev
2020-01-19 18:48:36 -09:00
2024-08-07 11:36:29 -08:00
server : check_go_env buildjs ##@Development Start the backend in development mode
2023-03-30 11:33:47 -08:00
@go run github.com/cespare/reflex@latest -d none -c reflex.conf
2020-03-20 08:21:41 -08:00
.PHONY : server
2020-01-20 09:43:51 -09:00
2021-05-01 07:14:24 -08:00
watch : ##@Development Start Go tests in watch mode (re-run when code changes)
2024-10-26 09:28:23 -08:00
go run github.com/onsi/ginkgo/v2/ginkgo@latest watch -tags netgo -notify ./...
2020-03-20 08:21:41 -08:00
.PHONY : watch
2020-01-15 19:40:22 -09:00
2021-05-01 07:14:24 -08:00
test : ##@Development Run Go tests
2024-10-26 09:28:23 -08:00
go test -tags netgo -race -shuffle= on ./...
2020-03-20 08:21:41 -08:00
.PHONY : test
2020-01-13 18:53:23 -09:00
2021-05-01 07:14:24 -08:00
testall : test ##@Development Run Go and JS tests
2024-09-28 07:54:36 -08:00
@( cd ./ui && npm run test:ci)
2020-03-20 08:21:41 -08:00
.PHONY : testall
2020-01-19 15:34:54 -09:00
2021-05-01 07:14:24 -08:00
lint : ##@Development Lint Go code
2023-03-30 11:33:47 -08:00
go run github.com/golangci/golangci-lint/cmd/golangci-lint@latest run -v --timeout 5m
2020-10-24 18:43:59 -08:00
.PHONY : lint
2021-05-01 07:14:24 -08:00
lintall : lint ##@Development Lint Go and JS code
2023-04-06 07:45:32 -08:00
@( cd ./ui && npm run check-formatting) || ( echo "\n\nPlease run 'npm run prettier' to fix formatting issues." && exit 1)
@( cd ./ui && npm run lint)
2021-03-24 08:21:20 -08:00
.PHONY : lintall
2023-06-19 07:15:51 -08:00
format : ##@Development Format code
@( cd ./ui && npm run prettier)
2023-11-27 09:53:08 -09:00
@go run golang.org/x/tools/cmd/goimports@latest -w ` find . -name '*.go' | grep -v _gen.go$$ `
2023-06-19 07:15:51 -08:00
@go mod tidy
.PHONY : format
2021-05-20 09:42:29 -08:00
wire : check_go_env ##@Development Update Dependency Injection
2023-03-30 11:33:47 -08:00
go run github.com/google/wire/cmd/wire@latest ./...
2021-05-20 09:42:29 -08:00
.PHONY : wire
snapshots : ##@Development Update (GoLang) Snapshot tests
2023-04-04 05:57:00 -08:00
UPDATE_SNAPSHOTS = true go run github.com/onsi/ginkgo/v2/ginkgo@latest ./server/subsonic/...
2021-05-20 09:42:29 -08:00
.PHONY : snapshots
2020-05-09 17:00:38 -08:00
2023-04-04 06:30:28 -08:00
migration-sql : ##@Development Create an empty SQL migration file
@if [ -z " ${ name } " ] ; then echo "Usage: make migration-sql name=name_of_migration_file" ; exit 1; fi
2024-05-08 15:54:48 -08:00
go run github.com/pressly/goose/v3/cmd/goose@latest -dir db/migrations create ${ name } sql
2023-04-04 06:30:28 -08:00
.PHONY : migration
migration-go : ##@Development Create an empty Go migration file
@if [ -z " ${ name } " ] ; then echo "Usage: make migration-go name=name_of_migration_file" ; exit 1; fi
2024-05-08 15:54:48 -08:00
go run github.com/pressly/goose/v3/cmd/goose@latest -dir db/migrations create ${ name }
2020-07-31 05:55:44 -08:00
.PHONY : migration
2020-06-08 13:29:09 -08:00
2021-05-01 07:14:24 -08:00
setup-dev : setup
2021-05-01 04:49:34 -08:00
.PHONY : setup -dev
2020-04-26 12:10:40 -08:00
2021-05-01 07:14:24 -08:00
setup-git : ##@Development Setup Git hooks (pre-commit and pre-push)
2020-10-03 07:01:16 -08:00
@echo Setting up git hooks
2020-07-16 13:52:59 -08:00
@mkdir -p .git/hooks
2020-10-03 07:01:16 -08:00
@( cd .git/hooks && ln -sf ../../git/* .)
2020-07-16 13:52:59 -08:00
.PHONY : setup -git
2024-08-07 12:19:02 -08:00
build : check_go_env buildjs ##@Build Build the project
2024-10-15 12:46:01 -08:00
go build -ldflags= " -X github.com/navidrome/navidrome/consts.gitSha= $( GIT_SHA) -X github.com/navidrome/navidrome/consts.gitTag= $( GIT_TAG) " -tags= netgo
2021-05-01 07:14:24 -08:00
.PHONY : build
2024-08-07 12:19:02 -08:00
buildall : deprecated build
.PHONY : buildall
debug-build : check_go_env buildjs ##@Build Build the project (with remote debug on)
2024-10-15 12:46:01 -08:00
go build -gcflags= "all=-N -l" -ldflags= " -X github.com/navidrome/navidrome/consts.gitSha= $( GIT_SHA) -X github.com/navidrome/navidrome/consts.gitTag= $( GIT_TAG) " -tags= netgo
Jukebox mode (#2289)
* Adding cache directory to ignore-list
* Adding jukebox-related config options
* Adding DevEnableJukebox config option pls. dummy server
* Adding types and routers
* Now without panic
* First draft on parsing the action
* Some cleanups
* Adding playback server
* Verify audio device configuration
* Adding debug-build target to have full symbol support
* Adding beep sound library pls some example code. Not working yet
* Play a fixed mp3 on any interface access for testing purposes
* Put action code into separate file, adding stringer, more debug output, prepare structs, validation
* Put action parameter parser code where it belongs
* Have a single Action transporting all information
* User fmt.Errorf for error-generation
* Adding wide playback interface
* Use action map for parsing, stringer instead switch stmt.
* Use but only one switch case and direct dispatch, refactoring
* Add error handling and pushing to client
* send decent errormessage, no internal server error
* Adding playback devices slice and load it from config
* Combine config-verification and structure init
* Return user-specific device
* Separate playback server from device
* Use dataStore to retrieve mediafile by id
* WIP: Playlist and start/stop handling. Doing start/stop the hard way as of now
* WIP: set, start and stop work on one single song. More to come
* Dont need to wait for the end
* Merge jukebox_action.go into jukebox.go
* Remove getParameterAsInt64(). Use existing requiredParamInt() instead
* Dont need to call newFailure() explicitly
* Remove int64, use int instead.
* Add and set action now accept multiple ids
* Kickout copy of childFromMediaFile(). It is not needed here.
* Refactoring devices and playbackServer
* Turn (internal) playback.DeviceStatus into subsonic JukeboxStatus when rendering output. Indexes int64 -> int
* Now we have a position and playing status
* Switching gain to float32, xs:float is defined as 32 bit. Fixing nasty copy/pointer bug
* Now with volume control
* Start working the queue
* Remove user from device interface
* Rename function GetDevice -> GetDeviceForUser to make intention clearer
* Have a nice stringer for the queue
* User Prepared boolean for now to allow pause/unpause
* Skipping works, but without offsets
* Make ChildFromMediaFile public to be used in jukebox get() implementation
* Return position in seconds and implement offset-skip in seconds
* Default offset to 0
* Adding a simple setGain implementation
* Prepare for transcoding AAC
* WIP: transcode to WAV to use beeps wav decoder. Not done yet.
* WIP: out of sheer desparation: convert to MP3 (which works) rather than WAV to troubleshoot issue.
* Use FLAC as intermediate format to play Apple AAC
* A bit of cleanup
* Catching the end-of-stream event for further reactions
* Have a trackSwitching goroutine waiting on channel when track ends
* Move decoder code into own file. Restructure code a bit
* Now with going on to play the next song in the playlist
* Adding shuffle feature
* Implementing remove action
* Cleanup code
* Remove templates for ffmpeg mp3 generation. Not needed anymore.
* Adding some documentation
* Check whether offset into track is in range. Fixing potential remove track bug. Documentation
* Make golangci-lint happy: handling return values
* Adding test suite and example dummy for playback package
* Adding some basic queue tests
* Only use Jukebox.Enabled config option
* Adding stream closing handling
* Pass context.Context to all PlaybackDevice methods
* Remove unneeded function
* Correct spelling
* Reduce visibility of ChildFromMediaFile
* Decomplicate action-parsing
* Adding simple tempfile-based AAC->FLAC transcoding. No parallel reading and writing yet.
* Try to optimize pipe-writing, tempfile-handling and reading. Not done yet.
* Do a synchronous copy of the tempfile. Racecondition detected
* More debugging statements and fixing the play/pause bug. More work needed
* Start the trackSwitcher() with each device once. Return JSON position even if its 0. More debug-output
* Moving all track-handling code into own module
* Fix typo. Do not pass ctx around when not applicable
* WIP: More refactoring, debugging output
* Fix nil pointer
* Repairing MP3 playback by pinning indirect dependencies: hajimehoshi/go-mp3 and hajimehoshi/oto
* Do not forget to cleanup after a skip action
* Make resync with master easy
* Adding missing mocks
* Adding missing error-handling found by linter
* Updating github.com/hajimehoshi/oto
* Removing duplicate function
* Move BEEP-related code into own package
* Juggle beep-related code around as preparation for interface access
* More refactoring for interface separation
* Gather CloseDevice() behind Track interface.
* Adding skeleton, draft audio-interface using mpv.io
* Adding majority of interface commands using messages to mpv socket.
* Adding end-of-stream handling
* MPV: start/stop are working
* postition is given in float in mpv
* Unify Close() and CloseDevice(). Using temp filename for controlling socket
* Wait until control-socket shows up. Cleanup socket in Close()
* Use canceable command. Rename to Executor
* Skipping tracks works now
* Now with actually setting the position
* Fix regain
* Add missing error-handling found by linter
* Adding retry mode on time-pos property getter
* Remove unneeded code on queue
* Putting build-tag beep onto beep files
* Remove deprecated call to rand.Seed()
"As of Go 1.20 there is no reason to call Seed with a random value. Programs that call Seed with a known value to get a specific sequence of results should use New(NewSource(seed)) to obtain a local random generator."
* Using int32 to conform to Subsonic API spec
* Fix merge error
* Minor style changes
* Get username from context
---------
Co-authored-by: Deluan <deluan@navidrome.org>
2023-09-10 07:25:22 -08:00
.PHONY : debug -build
2024-08-07 11:36:29 -08:00
buildjs : check_node_env ui /build /index .html ##@Build Build only frontend
2021-05-01 07:14:24 -08:00
.PHONY : buildjs
2024-10-15 12:46:01 -08:00
docker-buildjs : ##@Build Build only frontend using Docker
docker build --output "./ui" --target ui-bundle .
.PHONY : docker -buildjs
2024-08-07 11:36:29 -08:00
ui/build/index.html : $( UI_SRC_FILES )
@( cd ./ui && npm run build)
2024-10-15 12:46:01 -08:00
docker-platforms : ##@Cross_Compilation List supported platforms
@echo "Supported platforms:"
@echo " $( SUPPORTED_PLATFORMS) " | tr ',' '\n' | sort | sed 's/^/ /'
@echo "\nUsage: make PLATFORMS=\"linux/amd64\" docker-build"
@echo " make IMAGE_PLATFORMS=\"linux/amd64\" docker-image"
.PHONY : docker -platforms
docker-build : ##@Cross_Compilation Cross-compile for any supported platform (check `make docker-platforms`)
2024-10-19 07:55:03 -08:00
docker buildx build \
2024-10-15 12:46:01 -08:00
--platform $( PLATFORMS) \
--build-arg GIT_TAG = ${ GIT_TAG } \
--build-arg GIT_SHA = ${ GIT_SHA } \
--build-arg CROSS_TAGLIB_VERSION = ${ CROSS_TAGLIB_VERSION } \
2024-10-22 15:32:56 -08:00
--output "./binaries" --target binary .
2024-10-15 12:46:01 -08:00
.PHONY : docker -build
docker-image : ##@Cross_Compilation Build Docker image, tagged as `deluan/navidrome:develop`, override with DOCKER_TAG var. Use IMAGE_PLATFORMS to specify target platforms
@echo $( IMAGE_PLATFORMS) | grep -q "windows" && echo "ERROR: Windows is not supported for Docker builds" && exit 1 || true
@echo $( IMAGE_PLATFORMS) | grep -q "darwin" && echo "ERROR: macOS is not supported for Docker builds" && exit 1 || true
2024-10-15 18:47:05 -08:00
@echo $( IMAGE_PLATFORMS) | grep -q "arm/v5" && echo "ERROR: Linux ARMv5 is not supported for Docker builds" && exit 1 || true
2024-10-19 07:55:03 -08:00
docker buildx build \
2024-10-15 12:46:01 -08:00
--platform $( IMAGE_PLATFORMS) \
--build-arg GIT_TAG = ${ GIT_TAG } \
--build-arg GIT_SHA = ${ GIT_SHA } \
--build-arg CROSS_TAGLIB_VERSION = ${ CROSS_TAGLIB_VERSION } \
--tag $( DOCKER_TAG) .
.PHONY : docker -image
2024-04-13 09:29:45 -08:00
2024-10-22 15:32:56 -08:00
docker-msi : ##@Cross_Compilation Build MSI installer for Windows
make docker-build PLATFORMS = windows/386,windows/amd64
DOCKER_CLI_HINTS = false docker build -q -t navidrome-msi-builder -f release/wix/msitools.dockerfile .
@rm -rf binaries/msi
docker run -it --rm -v $( PWD) :/workspace -v $( PWD) /binaries:/workspace/binaries -e GIT_TAG = ${ GIT_TAG } \
navidrome-msi-builder sh -c "release/wix/build_msi.sh /workspace 386 && release/wix/build_msi.sh /workspace amd64"
@du -h binaries/msi/*.msi
.PHONY : docker -msi
2022-09-30 19:10:33 -08:00
get-music : ##@Development Download some free music from Navidrome's demo instance
mkdir -p music
( cd music; \
curl "https://demo.navidrome.org/rest/download?u=demo&p=demo&f=json&v=1.8.0&c=dev_download&id=ec2093ec4801402f1e17cc462195cdbb" > brock.zip; \
2023-06-02 13:14:11 -08:00
curl "https://demo.navidrome.org/rest/download?u=demo&p=demo&f=json&v=1.8.0&c=dev_download&id=b376eeb4652d2498aa2b25ba0696725e" > back_on_earth.zip; \
curl "https://demo.navidrome.org/rest/download?u=demo&p=demo&f=json&v=1.8.0&c=dev_download&id=e49c609b542fc51899ee8b53aa858cb4" > ugress.zip; \
curl "https://demo.navidrome.org/rest/download?u=demo&p=demo&f=json&v=1.8.0&c=dev_download&id=350bcab3a4c1d93869e39ce496464f03" > voodoocuts.zip; \
2022-09-30 19:10:33 -08:00
for file in *.zip; do unzip -n $$ { file} ; done )
@echo "Done. Remember to set your MusicFolder to ./music"
.PHONY : get -music
2021-05-01 07:14:24 -08:00
##########################################
#### Miscellaneous
2024-10-22 15:32:56 -08:00
clean :
@rm -rf ./binaries ./dist ./ui/build/*
@touch ./ui/build/.gitkeep
.PHONY : clean
2021-05-01 07:14:24 -08:00
release :
@if [ [ ! " ${ V } " = ~ ^[ 0-9] +\. [ 0-9] +\. [ 0-9] +.*$$ ] ] ; then echo "Usage: make release V=X.X.X" ; exit 1; fi
go mod tidy
@if [ -n "`git status -s`" ] ; then echo "\n\nThere are pending changes. Please commit or stash first" ; exit 1; fi
make pre-push
git tag v${ V }
git push origin v${ V } --no-verify
.PHONY : release
2021-05-01 04:49:34 -08:00
download-deps :
@echo Downloading Go dependencies...
2022-09-28 16:27:53 -08:00
@go mod download
2021-05-01 04:49:34 -08:00
@go mod tidy # To revert any changes made by the `go mod download` command
.PHONY : download -deps
2021-03-10 11:36:57 -09:00
2021-05-01 04:49:34 -08:00
check_env : check_go_env check_node_env
.PHONY : check_env
check_go_env :
2021-03-10 11:36:57 -09:00
@( hash go) || ( echo "\nERROR: GO environment not setup properly!\n" ; exit 1)
@current_go_version= ` go version | cut -d ' ' -f 3 | cut -c3-` && \
echo " $( GO_VERSION) $$ current_go_version " | \
tr ' ' '\n' | sort -V | tail -1 | \
grep -q " ^ $$ {current_go_version} $$ " || \
( echo " \nERROR: Please upgrade your GO version\nThis project requires at least the version $( GO_VERSION) " ; exit 1)
2021-05-01 04:49:34 -08:00
.PHONY : check_go_env
2021-03-10 11:36:57 -09:00
2021-05-01 04:49:34 -08:00
check_node_env :
2021-03-10 11:36:57 -09:00
@( hash node) || ( echo "\nERROR: Node environment not setup properly!\n" ; exit 1)
@current_node_version= ` node --version` && \
echo " $( NODE_VERSION) $$ current_node_version " | \
tr ' ' '\n' | sort -V | tail -1 | \
grep -q " ^ $$ {current_node_version} $$ " || \
( echo " \nERROR: Please check your Node version. Should be at least $( NODE_VERSION) \n " ; exit 1)
2020-03-20 08:21:41 -08:00
.PHONY : check_node_env
2020-01-08 07:13:05 -09:00
2021-03-24 08:21:20 -08:00
pre-push : lintall testall
2020-09-24 13:23:46 -08:00
.PHONY : pre -push
2024-08-07 12:19:02 -08:00
deprecated :
@echo "WARNING: This target is deprecated and will be removed in future releases. Use 'make build' instead."
.PHONY : deprecated
2021-05-01 07:14:24 -08:00
.DEFAULT_GOAL := help
2020-01-30 12:33:27 -09:00
2021-05-01 07:14:24 -08:00
HELP_FUN = \
%help; while ( <>) { push@{ $$ help{ $$ 2//'options' } } ,[ $$ 1,$$ 3] \
if /^( [ \w -_] +) \s *:.*\# \# ( ?:@( \w +) ) ?\s ( .*) $$ /} ; \
print" $$ _:\n " , map" $$ _->[0] " .( " " x( 20-length( $$ _->[ 0] ) ) ) ." $$ _->[1]\n " ,\
@{ $$ help{ $$ _} } ,"\n" for sort keys %help; \
2021-04-26 13:21:59 -08:00
2021-05-01 07:14:24 -08:00
help : ##@Miscellaneous Show this help
@echo "Usage: make [target] ...\n"
@perl -e '$(HELP_FUN)' $( MAKEFILE_LIST)