aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO14
-rw-r--r--backend.go (renamed from dummyBackend.go)5
-rw-r--r--config.go7
-rw-r--r--go.mod18
-rw-r--r--go.sum58
-rw-r--r--llog/llog.go2
-rw-r--r--localBackend.go103
-rw-r--r--main.go18
-rw-r--r--player.go38
-rw-r--r--playlist.go2
-rw-r--r--web/client.html15
-rw-r--r--wrms.go9
-rw-r--r--youtube.go6
13 files changed, 241 insertions, 54 deletions
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..4bd1d60
--- /dev/null
+++ b/TODO
@@ -0,0 +1,14 @@
+## Fronted
+
+## Web Backend
+
+- [ ] Implement a event endpoint
+
+## Backends
+
+- [X] Implement local storage backend
+- [ ] Fix youtube search
+
+## Configuration
+- [ ] Implement command line flags
+- [ ] Implement config file support
diff --git a/dummyBackend.go b/backend.go
index 460dd5e..9cb42f8 100644
--- a/dummyBackend.go
+++ b/backend.go
@@ -5,6 +5,11 @@ import (
"encoding/base64"
)
+type Backend interface {
+ Play(song *Song, player *Player)
+ Search(keyword string) []Song
+}
+
type DummyBackend struct{}
func (dummy *DummyBackend) Play(song *Song, player *Player) {
diff --git a/config.go b/config.go
new file mode 100644
index 0000000..ff56936
--- /dev/null
+++ b/config.go
@@ -0,0 +1,7 @@
+package main
+
+type Config struct {
+ port int
+ backends string
+ localMusicDir string
+}
diff --git a/go.mod b/go.mod
index 5840c4d..c2d9525 100644
--- a/go.mod
+++ b/go.mod
@@ -4,6 +4,7 @@ go 1.18
require (
github.com/AnjanaMadu/YTSearch v1.0.0
+ github.com/dhowden/tag v0.0.0-20220618230019-adf36e896086
github.com/google/uuid v1.3.0
github.com/librespot-org/librespot-golang v0.0.0-20220325184705-31669e5a889f
nhooyr.io/websocket v1.8.7
@@ -12,12 +13,15 @@ require (
require (
github.com/badfortrains/mdns v0.0.0-20160325001438-447166384f51 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
- github.com/golang/protobuf v1.5.0 // indirect
- github.com/klauspost/compress v1.10.4 // indirect
- github.com/miekg/dns v1.1.8 // indirect
+ github.com/golang/protobuf v1.5.2 // indirect
+ github.com/klauspost/compress v1.15.13 // indirect
+ github.com/miekg/dns v1.1.50 // indirect
github.com/stretchr/testify v1.5.1 // indirect
- golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 // indirect
- golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
- golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect
- google.golang.org/protobuf v1.27.1 // indirect
+ golang.org/x/crypto v0.4.0 // indirect
+ golang.org/x/mod v0.7.0 // indirect
+ golang.org/x/net v0.4.0 // indirect
+ golang.org/x/sys v0.3.0 // indirect
+ golang.org/x/tools v0.4.0 // indirect
+ golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
+ google.golang.org/protobuf v1.28.1 // indirect
)
diff --git a/go.sum b/go.sum
index 2e5ce48..8a7deb3 100644
--- a/go.sum
+++ b/go.sum
@@ -7,6 +7,8 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dhowden/tag v0.0.0-20220618230019-adf36e896086 h1:ORubSQoKnncsBnR4zD9CuYFJCPOCuSNEpWEZrDdBXkc=
+github.com/dhowden/tag v0.0.0-20220618230019-adf36e896086/go.mod h1:Z3Lomva4pyMWYezjMAU5QWRh0p1VvO4199OHlFnyKkM=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
@@ -26,8 +28,9 @@ github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
-github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -39,16 +42,17 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
-github.com/klauspost/compress v1.10.4 h1:jFzIFaf586tquEB5EhzQG0HwGNSlgAJpG53G6Ss11wc=
-github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.15.13 h1:NFn1Wr8cfnenSJSA46lLq4wHCcBzKTSjnBIexDMMOV0=
+github.com/klauspost/compress v1.15.13/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/librespot-org/librespot-golang v0.0.0-20220325184705-31669e5a889f h1:tTMPsyVClxxV+CnlLqzgxTTTFM6J7i//rSejN1Md0b0=
github.com/librespot-org/librespot-golang v0.0.0-20220325184705-31669e5a889f/go.mod h1:LeHPXRci2Bg6RBmw8BDEFH5nfb8oGU6mll+qTH8UIzw=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/miekg/dns v1.1.8 h1:1QYRAKU3lN5cRfLCkPU08hwvLJFhvjP6MqNMmQz6ZVI=
github.com/miekg/dns v1.1.8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
+github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
+github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
@@ -66,28 +70,58 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/xlab/portaudio-go v0.0.0-20170905165025-132d041879db/go.mod h1:r57mRacDQMS6Fz8ubv1nE8zZ0DbQ/sY0NkCmdxeUXmY=
github.com/xlab/vorbis-go v0.0.0-20190125051917-087364aef51d/go.mod h1:AMqfx3jFwPqem3u8mF2lsRodZs30jG/Mag5HZ3mB3sA=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 h1:O5YqonU5IWby+w98jVUG9h7zlCWCcH4RHyPVReBmhzk=
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
+golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
+golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190420063019-afa5a82059c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
-golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
+golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
+golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4=
+golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
+golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
diff --git a/llog/llog.go b/llog/llog.go
index e7fb924..52ffc40 100644
--- a/llog/llog.go
+++ b/llog/llog.go
@@ -16,7 +16,7 @@ const (
l_DDebug
)
-var Level LogLevel = l_Warning
+var Level LogLevel = l_DDebug
func getLevelNames() []string {
return []string{"Fatal", "Error", "Warning", "Info", "Debug", "DDebug"}
diff --git a/localBackend.go b/localBackend.go
new file mode 100644
index 0000000..a09d9a1
--- /dev/null
+++ b/localBackend.go
@@ -0,0 +1,103 @@
+package main
+
+import (
+ "fmt"
+ "github.com/dhowden/tag"
+ "muhq.space/go/wrms/llog"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+ "sync"
+)
+
+type LocalBackend struct {
+ musicDir string
+ lock sync.RWMutex
+ songs map[string]*Song
+}
+
+func NewLocalBackend(musicDir string) *LocalBackend {
+ b := LocalBackend{musicDir, sync.RWMutex{}, map[string]*Song{}}
+
+ go b.findSongs()
+ return &b
+}
+
+func (b *LocalBackend) insert(song *Song) {
+ b.lock.Lock()
+ defer b.lock.Unlock()
+ b.songs[song.Uri] = song
+}
+
+func (b *LocalBackend) findSongs() {
+ llog.Debug(fmt.Sprintf("Starting song search under: %s", b.musicDir))
+
+ // Insert some Songs
+ song := NewSong("No!", "Bukahara", "local", "Bukahara/Phantasma/01-No!.ogg")
+
+ for _, s := range []*Song{&song} {
+ b.insert(s)
+ }
+
+ err := filepath.Walk(b.musicDir, func(p string, finfo os.FileInfo, err error) error {
+ if err != nil {
+ llog.Warning(fmt.Sprintf("error %v at path %s\n", err, p))
+ return err
+ }
+
+ if !finfo.Mode().IsRegular() {
+ return nil
+ }
+
+ ext := strings.ToLower(path.Ext(p))
+ for _, excluded := range []string{".png", ".jpg", ".txt", ".pdf", ".m3u"} {
+ if ext == excluded {
+ return nil
+ }
+ }
+
+ f, err := os.Open(p)
+ defer f.Close()
+ if err != nil {
+ llog.Warning(fmt.Sprintf("error %v opening file %s", err, p))
+ return err
+ }
+
+ m, err := tag.ReadFrom(f)
+ if err != nil {
+ llog.Warning(fmt.Sprintf("error reading tags from %s: %v", p, err))
+ // Contiune walking
+ return nil
+ }
+
+ s := NewSong(m.Title(), m.Artist(), "local", p)
+ b.insert(&s)
+ return nil
+ })
+
+ if err != nil {
+ llog.Error(fmt.Sprintf("error walking the path %q: %v", b.musicDir, err))
+ }
+}
+
+func (b *LocalBackend) Play(song *Song, player *Player) {
+ player.PlayUri("file://" + song.Uri)
+}
+
+func (b *LocalBackend) Search(keyword string) []Song {
+ pattern := strings.ToLower(keyword)
+ results := []Song{}
+
+ b.lock.RLock()
+ defer b.lock.RUnlock()
+
+ for _, s := range b.songs {
+ if strings.Contains(strings.ToLower(s.Title), pattern) ||
+ strings.Contains(strings.ToLower(s.Artist), pattern) {
+ results = append(results, *s)
+ }
+ }
+
+ return results
+}
diff --git a/main.go b/main.go
index 4067f63..9eefc83 100644
--- a/main.go
+++ b/main.go
@@ -3,20 +3,21 @@ package main
import (
"context"
"encoding/json"
+ "flag"
"fmt"
"html/template"
"io/ioutil"
"log"
"net/http"
- "muhq.space/wrms/llog"
+ "muhq.space/go/wrms/llog"
"github.com/google/uuid"
"nhooyr.io/websocket"
)
-var wrms = NewWrms()
+var wrms *Wrms
func landingPage(w http.ResponseWriter, r *http.Request) {
if _, err := r.Cookie("UUID"); err != nil {
@@ -212,12 +213,21 @@ func setupRoutes() {
}
func main() {
+ config := Config{}
+ flag.IntVar(&config.port, "port", 8080, "port to listen to")
+ flag.StringVar(&config.backends, "backends", "dummy youtube spotify", "music backend to use")
+ flag.StringVar(&config.localMusicDir, "serve-music-dir", "", "local music directory to serve")
+ flag.Parse()
+
+ wrms = NewWrms(config)
+ defer wrms.Close()
+
setupRoutes()
// wrms.AddSong(NewDummySong("Lala", "SNFMT"))
// wrms.AddSong(NewDummySong("Hobelbank", "MC Wankwichtel"))
log.Println(wrms)
- defer wrms.Close()
- log.Fatal(http.ListenAndServe(":8080", nil))
+
+ log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", config.port), nil))
}
diff --git a/player.go b/player.go
index c7a9390..94efa27 100644
--- a/player.go
+++ b/player.go
@@ -6,32 +6,40 @@ import (
"os/exec"
"syscall"
- "muhq.space/wrms/llog"
+ "muhq.space/go/wrms/llog"
)
-type Backend interface {
- Play(song *Song, player *Player)
- Search(keyword string) []Song
-}
-
type Player struct {
Backends map[string]Backend
mpv *exec.Cmd
wrms *Wrms
}
-func NewPlayer(wrms *Wrms) Player {
+func NewPlayer(wrms *Wrms, backends []string) Player {
available_backends := map[string]Backend{}
- spotify, err := NewSpotify()
- if err != nil {
- // log.Fatalln("Error during initialization of the spotify backend:", err.Error())
- llog.Error(fmt.Sprintf("Error during initialization of the spotify backend: %s", err.Error()))
- }
- available_backends["spotify"] = spotify
- available_backends["youtube"] = &YoutubeBackend{}
+ var b Backend
+ var err error
+ for _, backend := range backends {
+ switch backend {
+ case "spotify":
+ b, err = NewSpotify()
+ case "youtube":
+ b = &YoutubeBackend{}
+ case "dummy":
+ b = &DummyBackend{}
+ case "local":
+ b = NewLocalBackend(wrms.Config.localMusicDir)
+ default:
+ llog.Error(fmt.Sprintf("Not supported backend %s", backend))
+ }
- available_backends["dummy"] = &DummyBackend{}
+ if err != nil {
+ llog.Error(fmt.Sprintf("Error during initialization of the %s backend: %s", backend, err.Error()))
+ } else {
+ available_backends[backend] = b
+ }
+ }
return Player{available_backends, nil, wrms}
}
diff --git a/playlist.go b/playlist.go
index 1c177e0..c5fa9e1 100644
--- a/playlist.go
+++ b/playlist.go
@@ -3,7 +3,7 @@ package main
import (
"container/heap"
"fmt"
- "muhq.space/wrms/llog"
+ "muhq.space/go/wrms/llog"
)
type Playlist []*Song
diff --git a/web/client.html b/web/client.html
index 20a53ed..87ca51a 100644
--- a/web/client.html
+++ b/web/client.html
@@ -122,10 +122,10 @@
votes.set(song.uri, "down")
}
- url = "/" + (isUpvoteBtn ? "up" : "down") + "?song=" + song.uri;
+ url = "/" + (isUpvoteBtn ? "up" : "down") + "?song=" + encodeURIComponent(song.uri);
} else {
votes.delete(song.uri);
- url = "/unvote?song=" + song.uri;
+ url = "/unvote?song=" + encodeURIComponent(song.uri);
}
console.log("Get " + url);
@@ -137,8 +137,10 @@
listItem.appendChild(upvoteBtn);
listItem.appendChild(downvoteBtn);
- const itemValue = document.createTextNode(song.weight + ' ' + formatSong(song));
- listItem.appendChild(itemValue);
+ listItem.appendChild(document.createTextNode(song.weight + ' ' + formatSong(song)));
+ const sourceLabel = document.createElement("SMALL");
+ sourceLabel.innerHTML = " (" + song.source + ")";
+ listItem.appendChild(sourceLabel);
playlist.appendChild(listItem);
}
}
@@ -257,10 +259,7 @@
});
listItem.classList.add("searchResult")
-
- let searchResultLabel = document.createTextNode(formatSong(song));
- listItem.appendChild(searchResultLabel);
-
+ listItem.innerHTML = formatSong(song) + " <small>(" + song.source + ")</small>";
searchResults.appendChild(listItem);
}
diff --git a/wrms.go b/wrms.go
index 252c14e..ee3274c 100644
--- a/wrms.go
+++ b/wrms.go
@@ -3,8 +3,9 @@ package main
import (
"encoding/json"
"fmt"
+ "strings"
- "muhq.space/wrms/llog"
+ "muhq.space/go/wrms/llog"
"github.com/google/uuid"
@@ -63,11 +64,13 @@ type Wrms struct {
CurrentSong Song
Player Player
Playing bool
+ Config Config
}
-func NewWrms() *Wrms {
+func NewWrms(config Config) *Wrms {
wrms := Wrms{}
- wrms.Player = NewPlayer(&wrms)
+ wrms.Config = config
+ wrms.Player = NewPlayer(&wrms, strings.Split(config.backends, " "))
return &wrms
}
diff --git a/youtube.go b/youtube.go
index a3f92d7..ad715ce 100644
--- a/youtube.go
+++ b/youtube.go
@@ -3,7 +3,7 @@ package main
import (
"fmt"
"github.com/AnjanaMadu/YTSearch"
- "log"
+ "muhq.space/go/wrms/llog"
)
type YoutubeBackend struct{}
@@ -15,7 +15,7 @@ func (youtube *YoutubeBackend) Play(song *Song, player *Player) {
func (youtube *YoutubeBackend) Search(pattern string) []Song {
results, err := ytsearch.Search(pattern)
if err != nil {
- log.Fatal("Youtube search failed with", err)
+ llog.Error(fmt.Sprintf("Youtube search failed with", err))
}
songs := []Song{}
@@ -31,6 +31,6 @@ func (youtube *YoutubeBackend) Search(pattern string) []Song {
songs = append(songs, NewSong(result.Title, "", "youtube", result.VideoId))
}
- log.Println(fmt.Sprintf("youtube found %d matching videos", len(songs)))
+ llog.Debug(fmt.Sprintf("youtube found %d matching videos", len(songs)))
return songs
}