diff --git a/.gitignore b/.gitignore index 3879cd0ba..260b9d72d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ wiki TODO.md gosonic.log var -Artwork \ No newline at end of file +Artwork +gosonic.toml \ No newline at end of file diff --git a/api/browsing.go b/api/browsing.go index e2bd9f060..595bbd989 100644 --- a/api/browsing.go +++ b/api/browsing.go @@ -6,6 +6,7 @@ import ( "github.com/astaxie/beego" "github.com/deluan/gosonic/api/responses" + "github.com/deluan/gosonic/conf" "github.com/deluan/gosonic/domain" "github.com/deluan/gosonic/engine" "github.com/deluan/gosonic/utils" @@ -40,7 +41,7 @@ func (c *BrowsingController) getArtistIndex(ifModifiedSince time.Time) responses } res := responses.Indexes{ - IgnoredArticles: beego.AppConfig.String("ignoredArticles"), + IgnoredArticles: conf.GoSonic.IgnoredArticles, LastModified: fmt.Sprint(utils.ToMillis(lastModified)), } diff --git a/api/validation.go b/api/validation.go index d4dd068e3..0d8616fd9 100644 --- a/api/validation.go +++ b/api/validation.go @@ -8,6 +8,7 @@ import ( "github.com/astaxie/beego" "github.com/deluan/gosonic/api/responses" + "github.com/deluan/gosonic/conf" ) type ControllerInterface interface { @@ -17,7 +18,7 @@ type ControllerInterface interface { } func Validate(controller BaseAPIController) { - if beego.AppConfig.String("disableValidation") != "true" { + if !conf.GoSonic.DisableValidation { checkParameters(controller) authenticate(controller) // TODO Validate version @@ -40,7 +41,7 @@ func checkParameters(c BaseAPIController) { } func authenticate(c BaseAPIController) { - password := beego.AppConfig.String("password") + password := conf.GoSonic.Password user := c.GetString("u") pass := c.GetString("p") salt := c.GetString("s") @@ -61,7 +62,7 @@ func authenticate(c BaseAPIController) { valid = (t == token) } - if user != beego.AppConfig.String("user") || !valid { + if user != conf.GoSonic.User || !valid { logWarn(c, fmt.Sprintf(`Invalid login for user "%s"`, user)) abortRequest(c, responses.ErrorAuthenticationFail) } diff --git a/conf/app.conf b/conf/app.conf index 897c11e59..127171256 100644 --- a/conf/app.conf +++ b/conf/app.conf @@ -1,34 +1,15 @@ appname = github.com/deluan/gosonic serverName = GoSonic -httpPort = 8080 runMode = dev autoRender = false copyRequestBody = true -enableAdmin = true +enableAdmin = false apiVersion = 1.8.0 -ignoredArticles="The El La Los Las Le Les Os As O A" -indexGroups=A B C D E F G H I J K L M N O P Q R S T U V W X-Z(XYZ) [Unknown]([) - -musicFolder=./iTunes1.xml -user=deluan -password=wordpass -dbPath=./devDb -enableDownsampling = true -downsampleCommand=ffmpeg -i %s -map 0:0 -b:a %bk -v 0 -f mp3 - -plsIgnoreFolders = true -plsIgnoredPatterns = ^iCloud;^CDs para;^Skipped;Christian [dev] -disableValidation = true enableAdmin = true [test] enableAdmin = false -disableValidation = false httpPort = 8081 -user = deluan -password = wordpass -dbPath = /tmp/testDb -musicFolder = ./tests/itunes-library.xml -downsampleCommand = ffmpeg -i %s -b:a %bk mp3 - diff --git a/conf/configuration.go b/conf/configuration.go new file mode 100644 index 000000000..1858c91cc --- /dev/null +++ b/conf/configuration.go @@ -0,0 +1,57 @@ +package conf + +import ( + "fmt" + "os" + + "github.com/koding/multiconfig" +) + +type goSonic struct { + Port int `default:"8080"` + MusicFolder string `default:"./iTunes1.xml"` + DbPath string `default:"./devDb"` + + IgnoredArticles string `default:"The El La Los Las Le Les Os As O A"` + IndexGroups string `default:"A B C D E F G H I J K L M N O P Q R S T U V W X-Z(XYZ) [Unknown]([)"` + + User string `default:"deluan"` + Password string `default:"wordpass"` + + DisableDownsampling bool `default:"false"` + DisableValidation bool `default:"false"` + DownsampleCommand string `default:"ffmpeg -i %s -map 0:0 -b:a %bk -v 0 -f mp3 -"` + PlsIgnoreFolders bool `default:"true"` + PlsIgnoredPatterns string `default:"^iCloud;^CDs para;^Skipped;Christian"` + RunMode string `default:"dev"` +} + +var GoSonic *goSonic + +func LoadFromFlags() { + l := &multiconfig.FlagLoader{} + l.Load(GoSonic) +} + +func LoadFromFile(tomlFile string) { + l := &multiconfig.TOMLLoader{Path: tomlFile} + err := l.Load(GoSonic) + if err != nil { + fmt.Printf("Error loading %s: %v\n", tomlFile, err) + } +} + +func LoadFromLocalFile() { + if _, err := os.Stat("./gosonic.toml"); err == nil { + LoadFromFile("./gosonic.toml") + } +} + +func init() { + GoSonic = new(goSonic) + var l multiconfig.Loader + l = &multiconfig.TagLoader{} + l.Load(GoSonic) + l = &multiconfig.EnvironmentLoader{} + l.Load(GoSonic) +} diff --git a/engine/stream.go b/engine/stream.go index cd82d8830..86677078d 100644 --- a/engine/stream.go +++ b/engine/stream.go @@ -8,14 +8,15 @@ import ( "strings" "github.com/astaxie/beego" + "github.com/deluan/gosonic/conf" ) // TODO Encapsulate as a io.Reader func Stream(path string, bitRate int, maxBitRate int, w io.Writer) error { var f io.Reader var err error - ds, _ := beego.AppConfig.Bool("enableDownsampling") - if ds && maxBitRate > 0 && bitRate > maxBitRate { + enabled := !conf.GoSonic.DisableDownsampling + if enabled && maxBitRate > 0 && bitRate > maxBitRate { f, err = downsample(path, maxBitRate) } else { f, err = os.Open(path) @@ -44,7 +45,7 @@ func downsample(path string, maxBitRate int) (f io.Reader, err error) { } func createDownsamplingCommand(path string, maxBitRate int) (string, []string) { - cmd := beego.AppConfig.String("downsampleCommand") + cmd := conf.GoSonic.DownsampleCommand split := strings.Split(cmd, " ") for i, s := range split { diff --git a/main.go b/main.go index 5a46622e1..fa3794e3c 100644 --- a/main.go +++ b/main.go @@ -4,15 +4,23 @@ import ( "fmt" "github.com/astaxie/beego" + "github.com/deluan/gosonic/conf" + _ "github.com/deluan/gosonic/conf" _ "github.com/deluan/gosonic/init" _ "github.com/deluan/gosonic/tasks" ) func main() { + conf.LoadFromLocalFile() + conf.LoadFromFlags() + + beego.BConfig.RunMode = conf.GoSonic.RunMode + beego.BConfig.Listen.HTTPPort = conf.GoSonic.Port + fmt.Printf("\nGoSonic v%s (%s mode)\n\n", "0.1", beego.BConfig.RunMode) if beego.BConfig.RunMode == "prod" { beego.SetLevel(beego.LevelInformational) } - //beego.BConfig.Log.FileLineNum = false + beego.Run() } diff --git a/persistence/ledis.go b/persistence/ledis.go index bf2cd00c6..99500b04d 100644 --- a/persistence/ledis.go +++ b/persistence/ledis.go @@ -3,7 +3,7 @@ package persistence import ( "sync" - "github.com/astaxie/beego" + "github.com/deluan/gosonic/conf" "github.com/siddontang/ledisdb/config" "github.com/siddontang/ledisdb/ledis" ) @@ -17,7 +17,7 @@ var ( func Db() *ledis.DB { once.Do(func() { config := config.NewConfigDefault() - config.DataDir = beego.AppConfig.String("dbPath") + config.DataDir = conf.GoSonic.DbPath l, _ := ledis.Open(config) instance, err := l.Select(0) if err != nil { diff --git a/persistence/mediafolders_repository.go b/persistence/mediafolders_repository.go index 08b7a7426..68039674c 100644 --- a/persistence/mediafolders_repository.go +++ b/persistence/mediafolders_repository.go @@ -1,7 +1,7 @@ package persistence import ( - "github.com/astaxie/beego" + "github.com/deluan/gosonic/conf" "github.com/deluan/gosonic/domain" ) @@ -14,7 +14,7 @@ func NewMediaFolderRepository() domain.MediaFolderRepository { } func (*mediaFolderRepository) GetAll() (domain.MediaFolders, error) { - mediaFolder := domain.MediaFolder{Id: "0", Name: "iTunes Library", Path: beego.AppConfig.String("musicFolder")} + mediaFolder := domain.MediaFolder{Id: "0", Name: "iTunes Library", Path: conf.GoSonic.MusicFolder} result := make(domain.MediaFolders, 1) result[0] = mediaFolder return result, nil diff --git a/scanner/importer.go b/scanner/importer.go index ffdab435a..85abb9d93 100644 --- a/scanner/importer.go +++ b/scanner/importer.go @@ -8,6 +8,7 @@ import ( "time" "github.com/astaxie/beego" + "github.com/deluan/gosonic/conf" "github.com/deluan/gosonic/domain" "github.com/deluan/gosonic/engine" "github.com/deluan/gosonic/utils" @@ -49,7 +50,7 @@ func CheckForUpdates(force bool) { func startImport() { go func() { - itunesLibrary = beego.AppConfig.String("musicFolder") + itunesLibrary = conf.GoSonic.MusicFolder info, err := os.Stat(itunesLibrary) if err != nil { @@ -64,7 +65,7 @@ func startImport() { lastCheck = time.Now() // TODO Move all to DI - i := &Importer{mediaFolder: beego.AppConfig.String("musicFolder")} + i := &Importer{mediaFolder: itunesLibrary} utils.ResolveDependencies(&i.mfRepo, &i.albumRepo, &i.artistRepo, &i.idxRepo, &i.plsRepo, &i.propertyRepo, &i.search, &i.scanner) i.Run() @@ -263,7 +264,7 @@ func (i *Importer) importArtists() domain.Artists { } func (i *Importer) importArtistIndex() { - indexGroups := utils.ParseIndexGroups(beego.AppConfig.String("indexGroups")) + indexGroups := utils.ParseIndexGroups(conf.GoSonic.IndexGroups) artistIndex := make(map[string]tempIndex) for _, ar := range i.scanner.Artists() { @@ -280,7 +281,7 @@ func (i *Importer) importPlaylists() domain.Playlists { j := 0 for _, pl := range i.scanner.Playlists() { pl.Public = true - pl.Owner = beego.AppConfig.String("user") + pl.Owner = conf.GoSonic.User pl.Comment = "Original: " + pl.FullPath pls[j] = *pl j++ diff --git a/scanner/itunes_scanner.go b/scanner/itunes_scanner.go index d92ff6644..09f20184d 100644 --- a/scanner/itunes_scanner.go +++ b/scanner/itunes_scanner.go @@ -14,6 +14,7 @@ import ( "time" "github.com/astaxie/beego" + "github.com/deluan/gosonic/conf" "github.com/deluan/gosonic/domain" "github.com/deluan/itl" "github.com/dhowden/tag" @@ -102,8 +103,8 @@ func (s *ItunesScanner) ScanLibrary(lastModifiedSince time.Time, path string) (i beego.Debug("Saved", len(s.newSums), "checksums") } - ignFolders, _ := beego.AppConfig.Bool("plsIgnoreFolders") - ignPatterns := beego.AppConfig.Strings("plsIgnoredPatterns") + ignFolders := conf.GoSonic.PlsIgnoreFolders + ignPatterns := strings.Split(conf.GoSonic.PlsIgnoredPatterns, ";") for _, p := range l.Playlists { rel := plsRelation{pID: p.PlaylistPersistentID, parentPID: p.ParentPersistentID, name: unescape(p.Name)} s.pplaylists[p.PlaylistPersistentID] = rel diff --git a/tests/gosonic-test.toml b/tests/gosonic-test.toml new file mode 100644 index 000000000..9e3f4ea59 --- /dev/null +++ b/tests/gosonic-test.toml @@ -0,0 +1,6 @@ +DisableValidation = false +User = "deluan" +Password = "wordpass" +DbPath = "/tmp/testDb" +MusicFolder = "./tests/itunes-library.xml" +DownsampleCommand = "ffmpeg -i %s -b:a %bk mp3 -" diff --git a/tests/init_tests.go b/tests/init_tests.go index e6929b7c7..7fac7f2c2 100644 --- a/tests/init_tests.go +++ b/tests/init_tests.go @@ -7,10 +7,12 @@ import ( "testing" "github.com/astaxie/beego" + "github.com/deluan/gosonic/conf" "github.com/deluan/gosonic/utils" ) func Init(t *testing.T, skipOnShort bool) { + conf.LoadFromFile("../tests/gosonic-test.toml") if skipOnShort && testing.Short() { t.Skip("skipping test in short mode.") } diff --git a/utils/strings.go b/utils/strings.go index 16904af80..8b5deff8a 100644 --- a/utils/strings.go +++ b/utils/strings.go @@ -3,11 +3,11 @@ package utils import ( "strings" - "github.com/astaxie/beego" + "github.com/deluan/gosonic/conf" ) func NoArticle(name string) string { - articles := strings.Split(beego.AppConfig.String("ignoredArticles"), " ") + articles := strings.Split(conf.GoSonic.IgnoredArticles, " ") for _, a := range articles { n := strings.TrimPrefix(name, a+" ") if n != name {