Compare commits
No commits in common. "master" and "v1.0.0" have entirely different histories.
24
README.MD
24
README.MD
@ -8,7 +8,7 @@ Soundr is able to play multiple audio files at the same time. It is able to inti
|
||||
Swagger Documentation for that endpoint is available in `apiDocs.yml`.
|
||||
The software it self is written in go and uses the BEEP library. It is made to be shipped as a single executable.
|
||||
Another target was a minimal dependency tree.
|
||||
Initally it was written to be used with [Bitfocus Companion](https://bitfocus.io/companion) in a more professional envoriment. [An companion module is now available!](https://github.com/bitfocus/companion-module-pnh-soundr)
|
||||
Initally it was written to be used with [Bitfocus Companion](https://bitfocus.io/companion) in a more professional envoriment. (A client for Companion is currently WiP)
|
||||
|
||||
# Installation
|
||||
Installation is as simple as it gets as it is a single executable.
|
||||
@ -23,29 +23,9 @@ This is the basic json configuration file layout:
|
||||
}
|
||||
```
|
||||
|
||||
> All sounds should be in the same bitrate. It will assume the bitrate of the first loaded sample.
|
||||
|
||||
# Usage
|
||||
Drop your sounds into the /sounds. You can play them by sending a GET request to the /v1/play endpoint.
|
||||
You need to know the base64 encoded file name of the sound you want to play. You can get started by querying /v1/list. It will return a list of all sounds with their respective base64 encoded file name.
|
||||
Use that base64 as the `file` parameter in the request. The response also includes sample request urls.
|
||||
|
||||
## Vanity IDs
|
||||
When playing a sound file it will get an incrementing ID. You can use that ID to stop the sound. These are not really predictable and can change at any time. You can also use a vanity ID. This is an integer that you can use to identify the sound. You can set the vanity ID by adding a `id` parameter to the request. The response will include the vanity ID. You can then use that ID to stop the sound.
|
||||
|
||||
# Endpoints
|
||||
> All endpoints are prefixed with `/v1/`
|
||||
|
||||
`GET /list` - Returns a list of all sounds with their respective base64 encoded file name. <br>
|
||||
`GET /play` - Plays a sound. The `file` parameter is required. It is the base64 encoded file name of the sound you want to play. Also supports `loop` to be either `true` or `false` (default). It also supports the `id` parameter to set a vanity ID.<br>
|
||||
`GET /stop` - Stops a sound. The `id` parameter is required. It is the ID of the sound you want to stop.<br>
|
||||
`GET /stopAll` - Stops all sounds.<br>
|
||||
`GET /buffer` - Buffers a sound. The `file` parameter is required. It is the base64 encoded file name of the sound you want to buffer.<br>
|
||||
`GET /bufferAll` - Buffers all sounds. **Note**: This may take a while. And should probably be run before a show.<br>
|
||||
`GET /current` - Returns a list of all currently playing sounds.<br>
|
||||
`GET /remaining` - Takes a `id` parameter. Returns the remaining time of the sound with the given ID.<br>
|
||||
Use that base64 as the `file` parameter in the request.
|
||||
|
||||
**Note**: The sounds must be in the format `*.mp3`, `*.wav`, `*.flac` or `*.ogg` (`flac` files may take longer time to buffer).
|
||||
|
||||
|
||||
Version 1.1.3
|
@ -14,11 +14,6 @@ paths:
|
||||
description: A base64 encoded version of the file name
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: loop
|
||||
description: Defaults to false; if true, will loop the sound until stopped
|
||||
schema:
|
||||
type: boolean
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
|
26
go.mod
26
go.mod
@ -1,27 +1,21 @@
|
||||
module pnh/soundr
|
||||
|
||||
go 1.21
|
||||
|
||||
toolchain go1.21.0
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/ebitengine/oto/v3 v3.1.0 // indirect
|
||||
github.com/ebitengine/purego v0.7.1 // indirect
|
||||
github.com/getsentry/sentry-go v0.19.0 // indirect
|
||||
github.com/gopxl/beep v1.4.1 // indirect
|
||||
github.com/faiface/beep v1.1.0 // indirect
|
||||
github.com/h2non/filetype v1.1.3 // indirect
|
||||
github.com/hajimehoshi/go-mp3 v0.3.4 // indirect
|
||||
github.com/hajimehoshi/go-mp3 v0.3.3 // indirect
|
||||
github.com/hajimehoshi/oto v1.0.1 // indirect
|
||||
github.com/icza/bitio v1.1.0 // indirect
|
||||
github.com/jfreymuth/oggvorbis v1.0.5 // indirect
|
||||
github.com/jfreymuth/vorbis v1.0.2 // indirect
|
||||
github.com/mewkiz/flac v1.0.8 // indirect
|
||||
github.com/mewkiz/pkg v0.0.0-20230226050401-4010bf0fec14 // indirect
|
||||
github.com/icza/bitio v1.0.0 // indirect
|
||||
github.com/jfreymuth/oggvorbis v1.0.1 // indirect
|
||||
github.com/jfreymuth/vorbis v1.0.0 // indirect
|
||||
github.com/mewkiz/flac v1.0.7 // indirect
|
||||
github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect
|
||||
golang.org/x/exp/shiny v0.0.0-20220428152302-39d4317da171 // indirect
|
||||
golang.org/x/image v0.5.0 // indirect
|
||||
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect
|
||||
golang.org/x/mobile v0.0.0-20220504144722-50dca8fc073d // indirect
|
||||
golang.org/x/sys v0.12.0 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a // indirect
|
||||
)
|
||||
|
50
go.sum
50
go.sum
@ -1,67 +1,42 @@
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo=
|
||||
github.com/ebitengine/oto/v3 v3.1.0 h1:9tChG6rizyeR2w3vsygTTTVVJ9QMMyu00m2yBOCch6U=
|
||||
github.com/ebitengine/oto/v3 v3.1.0/go.mod h1:IK1QTnlfZK2GIB6ziyECm433hAdTaPpOsGMLhEyEGTg=
|
||||
github.com/ebitengine/purego v0.7.1 h1:6/55d26lG3o9VCZX8lping+bZcmShseiqlh2bnUDiPA=
|
||||
github.com/ebitengine/purego v0.7.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
|
||||
github.com/faiface/beep v1.1.0 h1:A2gWP6xf5Rh7RG/p9/VAW2jRSDEGQm5sbOb38sf5d4c=
|
||||
github.com/faiface/beep v1.1.0/go.mod h1:6I8p6kK2q4opL/eWb+kAkk38ehnTunWeToJB+s51sT4=
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
|
||||
github.com/getsentry/sentry-go v0.19.0 h1:BcCH3CN5tXt5aML+gwmbFwVptLLQA+eT866fCO9wVOM=
|
||||
github.com/getsentry/sentry-go v0.19.0/go.mod h1:y3+lGEFEFexZtpbG1GUE2WD/f9zGyKYwpEqryTOC/nE=
|
||||
github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs=
|
||||
github.com/go-audio/riff v1.0.0/go.mod h1:l3cQwc85y79NQFCRB7TiPoNiaijp6q8Z0Uv38rVG498=
|
||||
github.com/go-audio/wav v1.0.0/go.mod h1:3yoReyQOsiARkvPl3ERCi8JFjihzG6WhjYpZCf5zAWE=
|
||||
github.com/go-audio/wav v1.1.0/go.mod h1:mpe9qfwbScEbkd8uybLuIpTgHyrISw/OTuvjUW2iGtE=
|
||||
github.com/gopxl/beep v1.4.1 h1:WqNs9RsDAhG9M3khMyc1FaVY50dTdxG/6S6a3qsUHqE=
|
||||
github.com/gopxl/beep v1.4.1/go.mod h1:A1dmiUkuY8kxsvcNJNUBIEcchmiP6eUyCHSxpXl0YO0=
|
||||
github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg=
|
||||
github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
|
||||
github.com/hajimehoshi/go-mp3 v0.3.0/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
|
||||
github.com/hajimehoshi/go-mp3 v0.3.3 h1:cWnfRdpye2m9ElSoVqneYRcpt/l3ijttgjMeQh+r+FE=
|
||||
github.com/hajimehoshi/go-mp3 v0.3.3/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
|
||||
github.com/hajimehoshi/go-mp3 v0.3.4 h1:NUP7pBYH8OguP4diaTZ9wJbUbk3tC0KlfzsEpWmYj68=
|
||||
github.com/hajimehoshi/go-mp3 v0.3.4/go.mod h1:fRtZraRFcWb0pu7ok0LqyFhCUrPeMsGRSVop0eemFmo=
|
||||
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
|
||||
github.com/hajimehoshi/oto v0.7.1/go.mod h1:wovJ8WWMfFKvP587mhHgot/MBr4DnNy9m6EepeVGnos=
|
||||
github.com/hajimehoshi/oto v1.0.1 h1:8AMnq0Yr2YmzaiqTg/k1Yzd6IygUGk2we9nmjgbgPn4=
|
||||
github.com/hajimehoshi/oto v1.0.1/go.mod h1:wovJ8WWMfFKvP587mhHgot/MBr4DnNy9m6EepeVGnos=
|
||||
github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo=
|
||||
github.com/icza/bitio v1.0.0 h1:squ/m1SHyFeCA6+6Gyol1AxV9nmPPlJFT8c2vKdj3U8=
|
||||
github.com/icza/bitio v1.0.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr9A=
|
||||
github.com/icza/bitio v1.1.0 h1:ysX4vtldjdi3Ygai5m1cWy4oLkhWTAi+SyO6HC8L9T0=
|
||||
github.com/icza/bitio v1.1.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr9A=
|
||||
github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA=
|
||||
github.com/jfreymuth/oggvorbis v1.0.1 h1:NT0eXBgE2WHzu6RT/6zcb2H10Kxj6Fm3PccT0LE6bqw=
|
||||
github.com/jfreymuth/oggvorbis v1.0.1/go.mod h1:NqS+K+UXKje0FUYUPosyQ+XTVvjmVjps1aEZH1sumIk=
|
||||
github.com/jfreymuth/oggvorbis v1.0.5 h1:u+Ck+R0eLSRhgq8WTmffYnrVtSztJcYrl588DM4e3kQ=
|
||||
github.com/jfreymuth/oggvorbis v1.0.5/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII=
|
||||
github.com/jfreymuth/vorbis v1.0.0 h1:SmDf783s82lIjGZi8EGUUaS7YxPHgRj4ZXW/h7rUi7U=
|
||||
github.com/jfreymuth/vorbis v1.0.0/go.mod h1:8zy3lUAm9K/rJJk223RKy6vjCZTWC61NA2QD06bfOE0=
|
||||
github.com/jfreymuth/vorbis v1.0.2 h1:m1xH6+ZI4thH927pgKD8JOH4eaGRm18rEE9/0WKjvNE=
|
||||
github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ=
|
||||
github.com/jszwec/csvutil v1.5.1/go.mod h1:Rpu7Uu9giO9subDyMCIQfHVDuLrcaC36UA4YcJjGBkg=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mewkiz/flac v1.0.7 h1:uIXEjnuXqdRaZttmSFM5v5Ukp4U6orrZsnYGGR3yow8=
|
||||
github.com/mewkiz/flac v1.0.7/go.mod h1:yU74UH277dBUpqxPouHSQIar3G1X/QIclVbFahSd1pU=
|
||||
github.com/mewkiz/flac v1.0.8 h1:cophRjvafteDGmqsfXRK28YAX6l8wy19QxTHruEEg1s=
|
||||
github.com/mewkiz/flac v1.0.8/go.mod h1:l7dt5uFY724eKVkHQtAJAQSkhpC3helU3RDxN0ESAqo=
|
||||
github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2 h1:EyTNMdePWaoWsRSGQnXiSoQu0r6RS1eA557AwJhlzHU=
|
||||
github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2/go.mod h1:3E2FUC/qYUfM8+r9zAwpeHJzqRVVMIYnpzD/clwWxyA=
|
||||
github.com/mewkiz/pkg v0.0.0-20230226050401-4010bf0fec14 h1:tnAPMExbRERsyEYkmR1YjhTgDM0iqyiBYf8ojRXxdbA=
|
||||
github.com/mewkiz/pkg v0.0.0-20230226050401-4010bf0fec14/go.mod h1:QYCFBiH5q6XTHEbWhR0uhR3M9qNPoD2CSQzr0g75kE4=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 h1:estk1glOnSVeJ9tdEZZc5mAMDZk5lNJNyJ6DvrBkTEU=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
@ -72,26 +47,19 @@ golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMx
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 h1:LRtI4W37N+KFebI/qV0OFiLUv4GLOWeEW5hn/KEJvxE=
|
||||
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
|
||||
golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mobile v0.0.0-20220504144722-50dca8fc073d h1:t1D1QwHyJFPzEHb1npu06EYJstXU9Pm517vGvJiACJU=
|
||||
golang.org/x/mobile v0.0.0-20220504144722-50dca8fc073d/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -99,34 +67,16 @@ golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a h1:N2T1jUrTQE9Re6TFF5PhvEHXHCguynGhKjWVsIUt5cY=
|
||||
golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI=
|
||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
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-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -7,69 +7,48 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gopxl/beep"
|
||||
"github.com/gopxl/beep/flac"
|
||||
"github.com/gopxl/beep/mp3"
|
||||
"github.com/gopxl/beep/speaker"
|
||||
"github.com/gopxl/beep/vorbis"
|
||||
"github.com/gopxl/beep/wav"
|
||||
"github.com/faiface/beep"
|
||||
"github.com/faiface/beep/flac"
|
||||
"github.com/faiface/beep/mp3"
|
||||
"github.com/faiface/beep/speaker"
|
||||
"github.com/faiface/beep/vorbis"
|
||||
"github.com/faiface/beep/wav"
|
||||
"github.com/h2non/filetype"
|
||||
)
|
||||
|
||||
var firstLoad = true
|
||||
|
||||
func BufferSound(file string) bool {
|
||||
_, ok := streamMap[file]
|
||||
if !ok {
|
||||
fmt.Println("----Not in memory, loading----")
|
||||
fmt.Println("Not in memory, loading")
|
||||
f, err := os.Open("./sounds/" + file)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println("Opened file")
|
||||
buf, err := ioutil.ReadFile("sounds/" + string(file))
|
||||
if err != nil {
|
||||
log.Fatal("Fatal error while opening: " + err.Error())
|
||||
return false
|
||||
}
|
||||
buf, _ := ioutil.ReadFile("sounds/" + string(file))
|
||||
|
||||
kind, err := filetype.Match(buf)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal("Fatal error while detecting file type: " + err.Error())
|
||||
return false
|
||||
}
|
||||
kind, _ := filetype.Match(buf)
|
||||
|
||||
fmt.Println("File type: " + kind.MIME.Subtype)
|
||||
var streamer beep.StreamSeekCloser
|
||||
var format beep.Format
|
||||
if kind.MIME.Subtype == "mpeg" {
|
||||
streamer, format, err = mp3.Decode(f)
|
||||
streamer, format, _ = mp3.Decode(f)
|
||||
} else if kind.MIME.Subtype == "x-wav" {
|
||||
streamer, format, err = wav.Decode(f)
|
||||
streamer, format, _ = wav.Decode(f)
|
||||
} else if kind.MIME.Subtype == "x-flac" {
|
||||
streamer, format, err = flac.Decode(f)
|
||||
streamer, format, _ = flac.Decode(f)
|
||||
} else if kind.MIME.Subtype == "ogg" {
|
||||
streamer, format, err = vorbis.Decode(f)
|
||||
streamer, format, _ = vorbis.Decode(f)
|
||||
} else {
|
||||
fmt.Println("!!!!! Unsupported file type for " + file)
|
||||
return false
|
||||
}
|
||||
if firstLoad {
|
||||
|
||||
speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
|
||||
firstLoad = false
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println("Error while decoding file: " + file)
|
||||
fmt.Println("Error: " + fmt.Sprintf("%v", err))
|
||||
return false
|
||||
}
|
||||
|
||||
fmt.Println("Decoded file")
|
||||
fmt.Println("Current file: " + file)
|
||||
fmt.Println("Current streamer: " + fmt.Sprintf("%v", streamer))
|
||||
fmt.Println("Error: " + fmt.Sprintf("%v", err))
|
||||
buffer := beep.NewBuffer(format)
|
||||
buffer.Append(streamer)
|
||||
streamer.Close()
|
||||
@ -87,46 +66,37 @@ func BufferSound(file string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func PlaySound(file string, index int, loop bool) int {
|
||||
func PlaySound(file string, index int) int {
|
||||
playbacks[index] = playback{
|
||||
File: file,
|
||||
IsLoaded: false,
|
||||
Streamer: nil,
|
||||
Control: nil,
|
||||
Loop: loop,
|
||||
Format: streamMap[file].Format,
|
||||
}
|
||||
|
||||
fmt.Println("Playing sound: " + file)
|
||||
var buffer *beep.Buffer
|
||||
BufferSound(file)
|
||||
buffer = streamMap[file].Buffer
|
||||
// streamer := streamMap[file].Streamer
|
||||
streamer := streamMap[file].Streamer
|
||||
|
||||
fmt.Println("Trying to play sound")
|
||||
amountOfLoops := 1
|
||||
if loop {
|
||||
amountOfLoops = -1
|
||||
fmt.Println("Looping sound: " + file)
|
||||
}
|
||||
shot := buffer.Streamer(0, buffer.Len())
|
||||
|
||||
done := make(chan bool)
|
||||
ctrl := &beep.Ctrl{Streamer: beep.Loop(amountOfLoops, shot), Paused: false}
|
||||
ctrl := &beep.Ctrl{Streamer: beep.Seq(shot, beep.Callback(func() {
|
||||
done <- true
|
||||
})), Paused: false}
|
||||
|
||||
playbacks[index] = playback{
|
||||
File: file,
|
||||
IsLoaded: true,
|
||||
Streamer: shot,
|
||||
Streamer: streamer,
|
||||
Control: ctrl,
|
||||
Loop: loop,
|
||||
Format: streamMap[file].Format,
|
||||
Done: done,
|
||||
}
|
||||
speaker.Play(ctrl)
|
||||
<-done
|
||||
fmt.Println("Finished playing sound: " + file)
|
||||
delete(playbacks, index)
|
||||
|
||||
return 1
|
||||
}
|
||||
|
11
soundr.go
11
soundr.go
@ -8,17 +8,14 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/gopxl/beep"
|
||||
"github.com/faiface/beep"
|
||||
)
|
||||
|
||||
type playback struct {
|
||||
File string
|
||||
IsLoaded bool
|
||||
Streamer beep.StreamSeeker
|
||||
Streamer beep.Streamer
|
||||
Control *beep.Ctrl
|
||||
Loop bool
|
||||
Format beep.Format
|
||||
Done chan bool
|
||||
}
|
||||
|
||||
type playbackWebReturn struct {
|
||||
@ -35,7 +32,6 @@ type streamBuf struct {
|
||||
|
||||
type Configuration struct {
|
||||
Port int
|
||||
AllowSentry bool
|
||||
}
|
||||
|
||||
var playbacks map[int]playback
|
||||
@ -70,7 +66,6 @@ func main() {
|
||||
// Write the default config to the file
|
||||
json.NewEncoder(file).Encode(Configuration{
|
||||
Port: 8080,
|
||||
AllowSentry: true,
|
||||
})
|
||||
fmt.Println("Wrote to conf.json")
|
||||
}
|
||||
@ -94,8 +89,6 @@ func main() {
|
||||
http.HandleFunc("/v1/stopAll", handleStopAll)
|
||||
http.HandleFunc("/v1/current", handleCurrent)
|
||||
http.HandleFunc("/v1/list", handleListing)
|
||||
http.HandleFunc("/v1/remaining", handleRemaining)
|
||||
http.HandleFunc("/", handleRoot)
|
||||
|
||||
fmt.Println("Listening on port " + fmt.Sprint(configuration.Port))
|
||||
log.Fatal(http.ListenAndServe(":"+fmt.Sprint(configuration.Port), nil))
|
||||
|
94
webRoutes.go
94
webRoutes.go
@ -10,9 +10,8 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gopxl/beep/speaker"
|
||||
"github.com/faiface/beep/speaker"
|
||||
"github.com/h2non/filetype"
|
||||
)
|
||||
|
||||
@ -26,16 +25,8 @@ func handlePlay(w http.ResponseWriter, r *http.Request) {
|
||||
var cnt = r.URL.Query().Get("file") // Retrieve the file name from the query string
|
||||
bytArr, err := base64.StdEncoding.DecodeString(cnt) // Decode the base64 string
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "{\"status\":\"fail\", \"reason\":\""+err.Error()+"\"}")
|
||||
return
|
||||
log.Fatal(err)
|
||||
}
|
||||
loop := r.URL.Query().Get("loop") // Retrieve the loop value from the query string
|
||||
loopBool := false
|
||||
if loop == "true" {
|
||||
loopBool = true
|
||||
}
|
||||
|
||||
wantedId := r.URL.Query().Get("id") // Retrieve the id value from the query string, it's optional
|
||||
|
||||
t, err := os.Stat("./sounds/" + string(bytArr[:])) // Check if the file exists
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
@ -64,23 +55,9 @@ func handlePlay(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
var currIndex = len(playbacks) // Create a new index for the playback
|
||||
|
||||
if len(wantedId) > 0 { // If the id is set, check if it is already in use
|
||||
id, err := strconv.Atoi(wantedId)
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "{\"status\":\"fail\", \"reason\":\"id is not a number\"}")
|
||||
return
|
||||
}
|
||||
if _, ok := playbacks[id]; ok {
|
||||
fmt.Fprintf(w, "{\"status\":\"fail\", \"reason\":\"id is already in use\"}")
|
||||
return
|
||||
}
|
||||
currIndex = id
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "{\"status\":\"ok\", \"id\":%d}", currIndex) // Return a JSON object to the user
|
||||
|
||||
go PlaySound(string(bytArr[:]), currIndex, loopBool) // Play the sound
|
||||
go PlaySound(string(bytArr[:]), currIndex) // Play the sound
|
||||
|
||||
}
|
||||
|
||||
@ -97,8 +74,7 @@ func handleBufferAll(w http.ResponseWriter, r *http.Request) {
|
||||
var temp []string
|
||||
files, err := ioutil.ReadDir("./sounds/") // Read the directory
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "{\"status\":\"fail\", \"reason\":\""+err.Error()+"\"}")
|
||||
return
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Loop through the files and add the file name to the temp array
|
||||
// Also triggers the buffer process for the file
|
||||
@ -117,7 +93,6 @@ func handleBufferAll(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
temp = append(temp, f.Name())
|
||||
go BufferSound(f.Name())
|
||||
time.Sleep(200 * time.Millisecond) // Wait a bit to not overload the system
|
||||
}
|
||||
// Return the amount of files buffered
|
||||
fmt.Fprintf(w, "{\"status\":\"ok\", \"amount\":%d}", len(temp))
|
||||
@ -134,8 +109,7 @@ func handleBuffer(w http.ResponseWriter, r *http.Request) {
|
||||
var cnt = r.URL.Query().Get("file") // Retrieve the file name from the query string
|
||||
bytArr, err := base64.StdEncoding.DecodeString(cnt) // Decode the base64 string
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "{\"status\":\"fail\", \"reason\":\""+err.Error()+"\"}")
|
||||
return
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
t, err := os.Stat("./sounds/" + string(bytArr[:])) // Check if the file exists
|
||||
@ -225,23 +199,6 @@ func handleCurrent(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json") // Set the content type to json
|
||||
|
||||
for i := 0; i < len(playbacks); i++ {
|
||||
plyB := playbacks[i]
|
||||
seeker := plyB.Streamer
|
||||
format := plyB.Format
|
||||
|
||||
if seeker != nil {
|
||||
fmt.Println(format.SampleRate)
|
||||
// fmt.Println(plyB.Seeker.)
|
||||
position := plyB.Format.SampleRate.D(seeker.Position())
|
||||
length := plyB.Format.SampleRate.D(seeker.Len())
|
||||
remaining := length - position
|
||||
if remaining == 0 {
|
||||
plyB.Done <- true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var tempResultSet map[int]playbackWebReturn = make(map[int]playbackWebReturn) // Create a new map to store the results
|
||||
// Iterate through the playbacks map and add important information to the tempResultSet map
|
||||
for index, element := range playbacks {
|
||||
@ -302,44 +259,3 @@ func handleListing(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, string(j))
|
||||
}
|
||||
}
|
||||
|
||||
func handleRemaining(w http.ResponseWriter, r *http.Request) {
|
||||
// Rejct everything else then GET requests
|
||||
if r.Method != "GET" {
|
||||
http.Error(w, "Method is not supported.", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json") // Set the content type to json
|
||||
var cnt, err = strconv.Atoi(r.URL.Query().Get("id")) // Retrieve the id, first convert it to an int
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "{\"status\":\"fail\", \"reason\":\"invalid id\"}")
|
||||
return
|
||||
}
|
||||
fmt.Println(cnt)
|
||||
plyB := playbacks[cnt]
|
||||
// fmt.Println(beep.SampleRate.D(plyB.Streamer.Stream().Len()))
|
||||
seeker := plyB.Streamer
|
||||
format := plyB.Format
|
||||
n := plyB.Format.SampleRate // Streamer.Stream() // .At(beep.SampleRate.D(plyB.Streamer.Stream().Len()))
|
||||
|
||||
if seeker != nil {
|
||||
fmt.Println(format.SampleRate)
|
||||
// fmt.Println(plyB.Seeker.)
|
||||
position := plyB.Format.SampleRate.D(seeker.Position())
|
||||
length := plyB.Format.SampleRate.D(seeker.Len())
|
||||
remaining := length - position
|
||||
if remaining == 0 {
|
||||
plyB.Done <- true
|
||||
}
|
||||
fmt.Println(position)
|
||||
fmt.Fprintf(w, "{\"status\":\"ok\", \"id\":%d, \"SampleRate\":%d, \"Length\":%d, \"Position\":%d, \"Remaining\": %d, \"LengthSec\":\"%v\", \"PosSec\":\"%v\", \"RemaningSec\":\"%v\"}", cnt, n, length, position, remaining, length, position, remaining)
|
||||
} else {
|
||||
fmt.Println("Seeker is nil")
|
||||
fmt.Fprintf(w, "{\"status\":\"ok\", \"SampleRate\":%d}", n)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func handleRoot(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Soundr is running.")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user