Git Repository

miniaudiolib

miniaudiolib scannt lokale Musik- und Hörbuchordner, liest Audio-Metadaten und Cover, verwaltet Favoriten und Playlists und streamt Titel direkt an den Browser.

Projektseite ↗
HTTPShttps://zanvex.de/git/miniaudiolib.git

cmd/miniaudiolib/main.go

Zum Verzeichnis
package main

import (
	"context"
	"flag"
	"io"
	"log/slog"
	"miniaudiolib/internal/config"
	"miniaudiolib/internal/logging"
	"miniaudiolib/internal/musicdb"
	"miniaudiolib/internal/musiclib"
	"miniaudiolib/internal/musicscanner"
	"miniaudiolib/internal/musicweb"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	configPath := flag.String("config", "config.toml", "path to configuration")
	scanOnly := flag.Bool("scan", false, "scan once and exit")
	flag.Parse()
	logs := logging.NewStore(1000)
	out := io.Writer(os.Stdout)
	if f, e := logging.NewRotatingWriter("data/logs/miniaudiolib.log", 10<<20); e == nil {
		defer f.Close()
		out = io.MultiWriter(out, f)
	}
	logger := slog.New(logging.NewHandler(slog.NewTextHandler(out, nil), logs))
	cfg, e := config.Load(*configPath)
	if e != nil {
		logger.Error("load config", "error", e)
		os.Exit(1)
	}
	db, e := musicdb.Open(cfg.DatabasePath)
	if e != nil {
		logger.Error("open database", "error", e)
		os.Exit(1)
	}
	defer db.Close()
	scan := musicscanner.New(db, cfg, logger)
	ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
	defer cancel()
	if *scanOnly {
		if e = scan.Run(ctx); e != nil && e != context.Canceled {
			logger.Error("scan", "error", e)
			os.Exit(1)
		}
		return
	}
	lib := musiclib.New(db)
	handler, e := musicweb.New(lib, db, scan, cfg, *configPath, logger)
	if e != nil {
		logger.Error("web", "error", e)
		os.Exit(1)
	}
	srv := &http.Server{Addr: cfg.ListenAddress, Handler: handler, ReadHeaderTimeout: 10 * time.Second}
	go func() {
		logger.Info("music library ready", "url", "http://"+cfg.ListenAddress)
		if e := srv.ListenAndServe(); e != nil && e != http.ErrServerClosed {
			logger.Error("server", "error", e)
			cancel()
		}
	}()
	<-ctx.Done()
	shutdown, stop := context.WithTimeout(context.Background(), 10*time.Second)
	defer stop()
	_ = srv.Shutdown(shutdown)
}