run gofumpt / format comments / comment blocks
This commit is contained in:
@@ -18,16 +18,12 @@ import (
|
||||
// once i had this written with ~100% text/template but it was very
|
||||
// slow. now this thing is not nice on the eyes or easy to change
|
||||
// but it's pretty fast. which i needed it to for live reloading stuff
|
||||
|
||||
const (
|
||||
byteCols = 24
|
||||
|
||||
// begin file template
|
||||
fileHeader = `// file generated with embed tool
|
||||
// do not edit
|
||||
|
||||
// %s
|
||||
|
||||
package %s
|
||||
import "time"
|
||||
type EmbeddedAsset struct {
|
||||
@@ -37,7 +33,6 @@ type EmbeddedAsset struct {
|
||||
var %s = map[string]*EmbeddedAsset{`
|
||||
fileFooter = `
|
||||
}`
|
||||
|
||||
// begin asset template
|
||||
assetHeader = `
|
||||
%q: &EmbeddedAsset{
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
)
|
||||
|
||||
// $ date '+%Y%m%d%H%M'
|
||||
|
||||
// not really a migration
|
||||
var migrationInitSchema = gormigrate.Migration{
|
||||
ID: "202002192100",
|
||||
|
||||
@@ -81,8 +81,7 @@ func (s *Scanner) Start() error {
|
||||
s.seenTracksNew = 0
|
||||
s.seenTracksErr = 0
|
||||
}()
|
||||
//
|
||||
// being walking
|
||||
// ** begin being walking
|
||||
start := time.Now()
|
||||
err := godirwalk.Walk(s.musicPath, &godirwalk.Options{
|
||||
Callback: s.callbackItem,
|
||||
@@ -99,8 +98,7 @@ func (s *Scanner) Start() error {
|
||||
len(s.seenTracks),
|
||||
s.seenTracksErr,
|
||||
)
|
||||
//
|
||||
// begin cleaning
|
||||
// ** begin cleaning
|
||||
start = time.Now()
|
||||
var deleted uint
|
||||
// delete tracks not on filesystem
|
||||
@@ -301,8 +299,7 @@ func (s *Scanner) handleTrack(it *item) error {
|
||||
s.trTx = s.db.Begin()
|
||||
s.trTxOpen = true
|
||||
}
|
||||
//
|
||||
// set track basics
|
||||
// ** begin set track basics
|
||||
track := &db.Track{}
|
||||
err := s.trTx.
|
||||
Select("id, updated_at").
|
||||
@@ -339,8 +336,7 @@ func (s *Scanner) handleTrack(it *item) error {
|
||||
track.TagBrainzID = trTags.BrainzID()
|
||||
track.Length = trTags.Length() // these two should be calculated
|
||||
track.Bitrate = trTags.Bitrate() // ...from the file instead of tags
|
||||
//
|
||||
// set album artist basics
|
||||
// ** begin set album artist basics
|
||||
artistName := func() string {
|
||||
if r := trTags.AlbumArtist(); r != "" {
|
||||
return r
|
||||
@@ -362,8 +358,7 @@ func (s *Scanner) handleTrack(it *item) error {
|
||||
s.trTx.Save(artist)
|
||||
}
|
||||
track.ArtistID = artist.ID
|
||||
//
|
||||
// set genre
|
||||
// ** begin set genre
|
||||
genreName := func() string {
|
||||
if r := trTags.Genre(); r != "" {
|
||||
return r
|
||||
@@ -381,13 +376,11 @@ func (s *Scanner) handleTrack(it *item) error {
|
||||
s.trTx.Save(genre)
|
||||
}
|
||||
track.TagGenreID = genre.ID
|
||||
//
|
||||
// save the track
|
||||
// ** begin save the track
|
||||
s.trTx.Save(track)
|
||||
s.seenTracks[track.ID] = struct{}{}
|
||||
s.seenTracksNew++
|
||||
//
|
||||
// set album if this is the first track in the folder
|
||||
// ** begin set album if this is the first track in the folder
|
||||
folder := s.curFolders.Peek()
|
||||
if !folder.ReceivedPaths || folder.ReceivedTags {
|
||||
// the folder hasn't been modified or already has it's tags
|
||||
|
||||
@@ -32,7 +32,6 @@ func (t *Tags) firstTag(keys ...string) string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (t *Tags) Title() string { return t.firstTag("title") }
|
||||
func (t *Tags) BrainzID() string { return t.firstTag("musicbrainz_trackid") }
|
||||
func (t *Tags) Artist() string { return t.firstTag("artist") }
|
||||
@@ -45,7 +44,6 @@ func (t *Tags) TrackNumber() int { return intSep(t.firstTag("tracknumber"),
|
||||
func (t *Tags) DiscNumber() int { return intSep(t.firstTag("discnumber"), "/") } // eg. 1/2
|
||||
func (t *Tags) Length() int { return t.props.Length }
|
||||
func (t *Tags) Bitrate() int { return t.props.Bitrate }
|
||||
|
||||
func intSep(in, sep string) int {
|
||||
if in == "" {
|
||||
return 0
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/sessions"
|
||||
|
||||
"senan.xyz/g/gonic/db"
|
||||
)
|
||||
|
||||
|
||||
@@ -44,10 +44,8 @@ func runQueryCases(t *testing.T, h subsonicHandler, cases []*queryCase) {
|
||||
qc := qc // pin
|
||||
t.Run(qc.expectPath, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
//
|
||||
// ensure the handlers give us json
|
||||
qc.params.Add("f", "json")
|
||||
//
|
||||
// request from the handler in question
|
||||
req, _ := http.NewRequest("", "?"+qc.params.Encode(), nil)
|
||||
params := params.New(req)
|
||||
@@ -59,13 +57,11 @@ func runQueryCases(t *testing.T, h subsonicHandler, cases []*queryCase) {
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Fatalf("didn't give a 200\n%s", body)
|
||||
}
|
||||
//
|
||||
// convert test name to query case path
|
||||
snake := testCamelExpr.ReplaceAllString(t.Name(), "${1}_${2}")
|
||||
lower := strings.ToLower(snake)
|
||||
relPath := strings.Replace(lower, "/", "_", -1)
|
||||
absExpPath := path.Join(testDataDir, relPath)
|
||||
//
|
||||
// read case to differ with handler result
|
||||
expected, err := jd.ReadJsonFile(absExpPath)
|
||||
if err != nil {
|
||||
@@ -80,7 +76,6 @@ func runQueryCases(t *testing.T, h subsonicHandler, cases []*queryCase) {
|
||||
diffOpts = append(diffOpts, jd.SET)
|
||||
}
|
||||
diff := expected.Diff(actual, diffOpts...)
|
||||
//
|
||||
// pass or fail
|
||||
if len(diff) == 0 {
|
||||
return
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
// we can't access artists. so instead we'll consider the artist of
|
||||
// an track to be the it's respective folder that comes directly
|
||||
// under the root directory
|
||||
|
||||
func (c *Controller) ServeGetIndexes(r *http.Request) *spec.Response {
|
||||
var folders []*db.Album
|
||||
c.DB.
|
||||
@@ -64,8 +63,7 @@ func (c *Controller) ServeGetMusicDirectory(r *http.Request) *spec.Response {
|
||||
childrenObj := []*spec.TrackChild{}
|
||||
folder := &db.Album{}
|
||||
c.DB.First(folder, id)
|
||||
//
|
||||
// start looking for child childFolders in the current dir
|
||||
// ** begin start looking for child childFolders in the current dir
|
||||
var childFolders []*db.Album
|
||||
c.DB.
|
||||
Where("parent_id=?", id).
|
||||
@@ -73,8 +71,7 @@ func (c *Controller) ServeGetMusicDirectory(r *http.Request) *spec.Response {
|
||||
for _, c := range childFolders {
|
||||
childrenObj = append(childrenObj, spec.NewTCAlbumByFolder(c))
|
||||
}
|
||||
//
|
||||
// start looking for child childTracks in the current dir
|
||||
// ** begin start looking for child childTracks in the current dir
|
||||
var childTracks []*db.Track
|
||||
c.DB.
|
||||
Where("album_id=?", id).
|
||||
@@ -90,8 +87,7 @@ func (c *Controller) ServeGetMusicDirectory(r *http.Request) *spec.Response {
|
||||
}
|
||||
childrenObj = append(childrenObj, toAppend)
|
||||
}
|
||||
//
|
||||
// respond section
|
||||
// ** begin respond section
|
||||
sub := spec.NewResponse()
|
||||
sub.Directory = spec.NewDirectoryByFolder(folder, childrenObj)
|
||||
return sub
|
||||
@@ -165,8 +161,7 @@ func (c *Controller) ServeSearchTwo(r *http.Request) *spec.Response {
|
||||
}
|
||||
query = fmt.Sprintf("%%%s%%", strings.TrimSuffix(query, "*"))
|
||||
results := &spec.SearchResultTwo{}
|
||||
//
|
||||
// search "artists"
|
||||
// ** begin search "artists"
|
||||
var artists []*db.Album
|
||||
c.DB.
|
||||
Where(`
|
||||
@@ -181,8 +176,7 @@ func (c *Controller) ServeSearchTwo(r *http.Request) *spec.Response {
|
||||
results.Artists = append(results.Artists,
|
||||
spec.NewDirectoryByFolder(a, nil))
|
||||
}
|
||||
//
|
||||
// search "albums"
|
||||
// ** begin search "albums"
|
||||
var albums []*db.Album
|
||||
c.DB.
|
||||
Where(`
|
||||
@@ -196,8 +190,7 @@ func (c *Controller) ServeSearchTwo(r *http.Request) *spec.Response {
|
||||
for _, a := range albums {
|
||||
results.Albums = append(results.Albums, spec.NewTCAlbumByFolder(a))
|
||||
}
|
||||
//
|
||||
// search tracks
|
||||
// ** begin search tracks
|
||||
var tracks []*db.Track
|
||||
c.DB.
|
||||
Preload("Album").
|
||||
|
||||
@@ -166,8 +166,7 @@ func (c *Controller) ServeSearchThree(r *http.Request) *spec.Response {
|
||||
query = fmt.Sprintf("%%%s%%",
|
||||
strings.TrimSuffix(query, "*"))
|
||||
results := &spec.SearchResultThree{}
|
||||
//
|
||||
// search "artists"
|
||||
// ** begin search "artists"
|
||||
var artists []*db.Artist
|
||||
c.DB.
|
||||
Where("name LIKE ? OR name_u_dec LIKE ?",
|
||||
@@ -179,8 +178,7 @@ func (c *Controller) ServeSearchThree(r *http.Request) *spec.Response {
|
||||
results.Artists = append(results.Artists,
|
||||
spec.NewArtistByTags(a))
|
||||
}
|
||||
//
|
||||
// search "albums"
|
||||
// ** begin search "albums"
|
||||
var albums []*db.Album
|
||||
c.DB.
|
||||
Preload("TagArtist").
|
||||
@@ -193,8 +191,7 @@ func (c *Controller) ServeSearchThree(r *http.Request) *spec.Response {
|
||||
results.Albums = append(results.Albums,
|
||||
spec.NewAlbumByTags(a, a.TagArtist))
|
||||
}
|
||||
//
|
||||
// search tracks
|
||||
// ** begin search tracks
|
||||
var tracks []*db.Track
|
||||
c.DB.
|
||||
Preload("Album").
|
||||
@@ -287,7 +284,6 @@ func (c *Controller) ServeGetGenres(r *http.Request) *spec.Response {
|
||||
(SELECT count(id) FROM tracks WHERE tag_genre_id=genres.id) track_count`).
|
||||
Group("genres.id").
|
||||
Find(&genres)
|
||||
|
||||
sub := spec.NewResponse()
|
||||
sub.Genres = &spec.Genres{
|
||||
List: make([]*spec.Genre, len(genres)),
|
||||
@@ -304,10 +300,8 @@ func (c *Controller) ServeGetSongsByGenre(r *http.Request) *spec.Response {
|
||||
if genre == "" {
|
||||
return spec.NewError(10, "please provide an `genre` parameter")
|
||||
}
|
||||
|
||||
// TODO: add musicFolderId parameter:
|
||||
// (Since 1.12.0) Only return albums in the music folder with the given ID.
|
||||
|
||||
// TODO: add musicFolderId parameter
|
||||
// (since 1.12.0) only return albums in the music folder with the given id
|
||||
var tracks []*db.Track
|
||||
c.DB.
|
||||
Joins("JOIN albums ON tracks.album_id=albums.id").
|
||||
@@ -316,7 +310,6 @@ func (c *Controller) ServeGetSongsByGenre(r *http.Request) *spec.Response {
|
||||
Offset(params.GetIntOr("offset", 0)).
|
||||
Limit(params.GetIntOr("count", 10)).
|
||||
Find(&tracks)
|
||||
|
||||
sub := spec.NewResponse()
|
||||
sub.TracksByGenre = &spec.TracksByGenre{
|
||||
List: make([]*spec.TrackChild, len(tracks)),
|
||||
|
||||
@@ -287,13 +287,11 @@ func (c *Controller) ServeGetSong(r *http.Request) *spec.Response {
|
||||
func (c *Controller) ServeGetRandomSongs(r *http.Request) *spec.Response {
|
||||
params := r.Context().Value(CtxParams).(params.Params)
|
||||
var tracks []*db.Track
|
||||
|
||||
q := c.DB.DB.
|
||||
Joins("JOIN albums ON tracks.album_id=albums.id").
|
||||
Limit(params.GetIntOr("size", 10)).
|
||||
Preload("Album").
|
||||
Order(gorm.Expr("random()"))
|
||||
|
||||
if year, err := params.GetInt("fromYear"); err == nil {
|
||||
q = q.Where("albums.tag_year >= ?", year)
|
||||
}
|
||||
@@ -307,7 +305,6 @@ func (c *Controller) ServeGetRandomSongs(r *http.Request) *spec.Response {
|
||||
)
|
||||
}
|
||||
q.Find(&tracks)
|
||||
|
||||
sub := spec.NewResponse()
|
||||
sub.RandomTracks = &spec.RandomTracks{}
|
||||
sub.RandomTracks.List = make([]*spec.TrackChild, len(tracks))
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
// a) write to response writer
|
||||
// b) return a non-nil spec.Response
|
||||
// _but not both_
|
||||
|
||||
func (c *Controller) ServeGetCoverArt(w http.ResponseWriter, r *http.Request) *spec.Response {
|
||||
params := r.Context().Value(CtxParams).(params.Params)
|
||||
id, err := params.GetInt("id")
|
||||
|
||||
@@ -63,7 +63,6 @@ func NewResponse() *Response {
|
||||
// 50 user is not authorized for the given operation
|
||||
// 60 the trial period for the subsonic server is over
|
||||
// 70 the requested data was not found
|
||||
|
||||
type Error struct {
|
||||
Code int `xml:"code,attr" json:"code"`
|
||||
Message string `xml:"message,attr" json:"message"`
|
||||
|
||||
BIN
server/ctrlsubsonic/testdata/db
vendored
BIN
server/ctrlsubsonic/testdata/db
vendored
Binary file not shown.
@@ -2,10 +2,9 @@ package encode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
@@ -30,20 +29,19 @@ var (
|
||||
bufLen = 4096
|
||||
)
|
||||
|
||||
// Copy command output to HTTP response body using io.Copy (simpler, but may increase TTFB)
|
||||
// copy command output to http response body using io.copy (simpler, but may increase ttfb)
|
||||
//nolint:deadcode,unused
|
||||
func copyCmdOutput(out, cache io.Writer, pipeReader io.Reader) {
|
||||
// Set up a MultiWriter to feed the command output
|
||||
// to both cache file and HTTP response:
|
||||
// set up a multiwriter to feed the command output
|
||||
// to both cache file and http response
|
||||
w := io.MultiWriter(out, cache)
|
||||
|
||||
// Start copying!
|
||||
// start copying!
|
||||
if _, err := io.Copy(w, pipeReader); err != nil {
|
||||
log.Printf("error while writing encoded output: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Copy command output to HTTP response manually with a buffer (should reduce TTFB)
|
||||
// copy command output to http response manually with a buffer (should reduce ttfb)
|
||||
//nolint:deadcode,unused
|
||||
func writeCmdOutput(out, cache io.Writer, pipeReader io.ReadCloser) {
|
||||
buffer := make([]byte, bufLen)
|
||||
@@ -53,18 +51,15 @@ func writeCmdOutput(out, cache io.Writer, pipeReader io.ReadCloser) {
|
||||
pipeReader.Close()
|
||||
break
|
||||
}
|
||||
|
||||
data := buffer[0:n]
|
||||
_, err = out.Write(data)
|
||||
if err != nil {
|
||||
log.Printf("error while writing HTTP response: %s\n", err)
|
||||
}
|
||||
|
||||
_, err = cache.Write(data)
|
||||
if err != nil {
|
||||
log.Printf("error while writing cache file: %s\n", err)
|
||||
}
|
||||
|
||||
if f, ok := out.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
@@ -75,7 +70,7 @@ func writeCmdOutput(out, cache io.Writer, pipeReader io.ReadCloser) {
|
||||
}
|
||||
}
|
||||
|
||||
// Pre-format the FFmpeg command with needed options:
|
||||
// pre-format the ffmpeg command with needed options
|
||||
func ffmpegCommand(filePath string, profile *Profile, bitrate string) *exec.Cmd {
|
||||
ffmpegArgs := []string{
|
||||
"-v", "0", "-i", filePath, "-map", "0:0",
|
||||
@@ -84,9 +79,9 @@ func ffmpegCommand(filePath string, profile *Profile, bitrate string) *exec.Cmd
|
||||
ffmpegArgs = append(ffmpegArgs, profile.ffmpegOptions...)
|
||||
if profile.forceRG {
|
||||
ffmpegArgs = append(ffmpegArgs,
|
||||
// Set up ReplayGain processing
|
||||
// set up replaygain processing
|
||||
"-af", "volume=replaygain=track:replaygain_preamp=6dB:replaygain_noclip=0, alimiter=level=disabled",
|
||||
// Drop redundant ReplayGain tags
|
||||
// drop redundant replaygain tags
|
||||
"-metadata", "replaygain_album_gain=",
|
||||
"-metadata", "replaygain_album_peak=",
|
||||
"-metadata", "replaygain_track_gain=",
|
||||
@@ -94,35 +89,32 @@ func ffmpegCommand(filePath string, profile *Profile, bitrate string) *exec.Cmd
|
||||
)
|
||||
}
|
||||
ffmpegArgs = append(ffmpegArgs, "-f", profile.Format, "-")
|
||||
|
||||
return exec.Command("/usr/bin/ffmpeg", ffmpegArgs...)
|
||||
}
|
||||
|
||||
func Encode(out io.Writer, trackPath, cachePath string, profile *Profile, bitrate string) error {
|
||||
// Prepare the command and file descriptors:
|
||||
// prepare the command and file descriptors
|
||||
cmd := ffmpegCommand(trackPath, profile, bitrate)
|
||||
pipeReader, pipeWriter := io.Pipe()
|
||||
cmd.Stdout = pipeWriter
|
||||
cmd.Stderr = pipeWriter
|
||||
|
||||
// Create cache file:
|
||||
// create cache file
|
||||
cacheFile, err := os.Create(cachePath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "writing to cache file %q: %v", cachePath)
|
||||
return errors.Wrapf(err, "writing to cache file %q: %v", cachePath, err)
|
||||
}
|
||||
|
||||
//// I'm still unsure if buffer version (writeCmdOutput) is any better than io.Copy-based one (copyCmdOutput).
|
||||
//// My initial goal here is to start streaming response ASAP, with smallest TTFB. More testing needed. -- @spijet
|
||||
// Start up writers for cache file and HTTP response:
|
||||
// still unsure if buffer version (writeCmdOutput) is any better than io.Copy-based one (copyCmdOutput)
|
||||
// initial goal here is to start streaming response asap, with smallest ttfb. more testing needed
|
||||
// -- @spijet
|
||||
//
|
||||
// start up writers for cache file and http response
|
||||
// go copyCmdOutput(w, cacheFile, pipeReader)
|
||||
go writeCmdOutput(out, cacheFile, pipeReader)
|
||||
|
||||
// Run FFmpeg:
|
||||
// run ffmpeg
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.Wrapf(err, "running ffmpeg")
|
||||
}
|
||||
|
||||
// Close all pipes and flush cache file:
|
||||
// close all pipes and flush cache file
|
||||
pipeWriter.Close()
|
||||
if err := cacheFile.Sync(); err != nil {
|
||||
return errors.Wrapf(err, "flushing %q", cachePath)
|
||||
@@ -131,14 +123,14 @@ func Encode(out io.Writer, trackPath, cachePath string, profile *Profile, bitrat
|
||||
return nil
|
||||
}
|
||||
|
||||
// Generate cache key (file name). For, you know, encoded tracks cache.
|
||||
// generate cache key (file name). for, you know, encoded tracks cache
|
||||
func CacheKey(sourcePath string, profile, bitrate string) string {
|
||||
format := Profiles[profile].Format
|
||||
hash := xxhash.Sum64String(sourcePath)
|
||||
return fmt.Sprintf("%x-%s-%s.%s", hash, profile, bitrate, format)
|
||||
}
|
||||
|
||||
// Check if client forces bitrate lower than set in profile:
|
||||
// check if client forces bitrate lower than set in profile
|
||||
func GetBitrate(clientBitrate int, profile *Profile) string {
|
||||
bitrate := profile.Bitrate
|
||||
if clientBitrate != 0 && clientBitrate < bitrate {
|
||||
|
||||
Reference in New Issue
Block a user