diff --git a/.drone.yml b/.drone.yml index 894af72..9551cff 100644 --- a/.drone.yml +++ b/.drone.yml @@ -47,17 +47,6 @@ steps: event: - tag -- name: gitea release - image: plugins/gitea-release - settings: - api_key: - from_secret: gitea_api_key - base_url: https://git.nemunai.re/ - files: deploy/reveil-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} - when: - event: - - tag - - name: docker image: plugins/docker settings: diff --git a/api/alarm.go b/api/alarm.go index 071073d..7b1e9d0 100644 --- a/api/alarm.go +++ b/api/alarm.go @@ -33,17 +33,6 @@ func declareAlarmRoutes(cfg *config.Config, router *gin.RouterGroup) { c.JSON(http.StatusOK, true) }) - router.POST("/alarm/next", func(c *gin.Context) { - if player.CommonPlayer == nil { - c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "No player currently playing"}) - return - } else { - player.CommonPlayer.NextTrack() - } - - c.JSON(http.StatusOK, true) - }) - router.DELETE("/alarm", func(c *gin.Context) { if player.CommonPlayer != nil { err := player.CommonPlayer.Stop() diff --git a/api/alarms.go b/api/alarms.go index e27771c..59dfe98 100644 --- a/api/alarms.go +++ b/api/alarms.go @@ -13,7 +13,7 @@ import ( func declareAlarmsRoutes(cfg *config.Config, db *reveil.LevelDBStorage, resetTimer func(), router *gin.RouterGroup) { router.GET("/alarms/next", func(c *gin.Context) { - alarm, err := reveil.GetNextAlarm(cfg, db) + alarm, err := reveil.GetNextAlarm(db) if err != nil { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()}) return @@ -200,8 +200,8 @@ func declareAlarmsRoutes(cfg *config.Config, db *reveil.LevelDBStorage, resetTim repeatedAlarmsRoutes.GET("", func(c *gin.Context) { alarm := c.MustGet("alarm").(*reveil.AlarmRepeated) - alarm.FillExcepts(cfg, db) - alarm.NextTime = alarm.GetNextOccurence(cfg, db) + alarm.FillExcepts(db) + alarm.NextTime = alarm.GetNextOccurence(db) c.JSON(http.StatusOK, alarm) }) diff --git a/app.go b/app.go index 0867a7e..778abd6 100644 --- a/app.go +++ b/app.go @@ -64,7 +64,6 @@ func (app *App) Start() { Handler: app.router, } - log.Println("Current timezone:", app.cfg.Timezone.String()) app.ResetTimer() log.Printf("Ready, listening on %s\n", app.cfg.Bind) @@ -79,7 +78,7 @@ func (app *App) ResetTimer() { app.nextAlarm = nil } - if na, err := reveil.GetNextAlarm(app.cfg, app.db); err == nil && na != nil { + if na, err := reveil.GetNextAlarm(app.db); err == nil && na != nil { app.nextAlarm = time.AfterFunc(time.Until(*na), func() { app.nextAlarm = nil reveil.RemoveOldAlarmsSingle(app.db) diff --git a/config/cli.go b/config/cli.go index 4677a69..1894daa 100644 --- a/config/cli.go +++ b/config/cli.go @@ -17,7 +17,6 @@ func (c *Config) declareFlags() { flag.StringVar(&c.ActionsDir, "actions-dir", c.ActionsDir, "Path to the directory containing the actions") flag.StringVar(&c.RoutinesDir, "routines-dir", c.RoutinesDir, "Path to the directory containing the routines") flag.IntVar(&c.SampleRate, "samplerate", c.SampleRate, "Samplerate for unifying output stream") - flag.Var(&c.Timezone, "timezone", "Timezone to use when dealing with times") // Others flags are declared in some other files when they need specials configurations } diff --git a/config/config.go b/config/config.go index 26f791a..26fe5c1 100644 --- a/config/config.go +++ b/config/config.go @@ -18,7 +18,6 @@ type Config struct { ActionsDir string RoutinesDir string - Timezone Timezone SampleRate int } diff --git a/config/custom.go b/config/custom.go index be0437b..716a2f7 100644 --- a/config/custom.go +++ b/config/custom.go @@ -3,7 +3,6 @@ package config import ( "encoding/base64" "net/url" - "time" ) type JWTSecretKey []byte @@ -43,33 +42,3 @@ func (i *URL) Set(value string) error { i.URL = u return nil } - -type Timezone struct { - tz *time.Location -} - -func (tz *Timezone) GetLocation() *time.Location { - if tz.tz != nil { - return tz.tz - } else { - return time.Local - } -} - -func (tz *Timezone) String() string { - if tz.tz != nil { - return tz.tz.String() - } else { - return time.Local.String() - } -} - -func (tz *Timezone) Set(value string) error { - newtz, err := time.LoadLocation(value) - if err != nil { - return err - } - - tz.tz = newtz - return nil -} diff --git a/config/env.go b/config/env.go index adac3ea..ae852a3 100644 --- a/config/env.go +++ b/config/env.go @@ -7,10 +7,10 @@ import ( ) // FromEnv analyzes all the environment variables to find each one -// starting by REVEIL_ +// starting by GUSTUS_ func (c *Config) FromEnv() error { for _, line := range os.Environ() { - if strings.HasPrefix(line, "REVEIL_") { + if strings.HasPrefix(line, "GUSTUS_") { err := c.parseLine(line) if err != nil { return fmt.Errorf("error in environment (%q): %w", line, err) diff --git a/go.mod b/go.mod index d3afff1..23551b2 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,13 @@ module git.nemunai.re/nemunaire/reveil go 1.18 require ( - github.com/faiface/beep v1.1.0 + github.com/faiface/beep v0.0.0-00010101000000-000000000000 github.com/gin-gonic/gin v1.8.1 github.com/syndtr/goleveldb v1.0.0 ) require ( + github.com/ebitengine/purego v0.0.0-20220907032450-cf3e27c364c7 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect @@ -16,7 +17,7 @@ require ( github.com/goccy/go-json v0.9.7 // indirect github.com/golang/snappy v0.0.1 // indirect github.com/hajimehoshi/go-mp3 v0.3.0 // indirect - github.com/hajimehoshi/oto v0.7.1 // indirect + github.com/hajimehoshi/oto/v2 v2.4.0-alpha.4 // indirect github.com/icza/bitio v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/leodido/go-urn v1.2.1 // indirect @@ -29,12 +30,11 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/ugorji/go/codec v1.2.7 // indirect golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect - golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8 // indirect - golang.org/x/image v0.0.0-20190227222117-0694c2d4d067 // indirect - golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6 // indirect golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/protobuf v1.28.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) + +replace github.com/faiface/beep => github.com/MarkKremer/beep v1.0.3-0.20221013180303-756ceb286755 diff --git a/go.sum b/go.sum index 56c0f5f..9d932f0 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,13 @@ github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/MarkKremer/beep v1.0.3-0.20221013180303-756ceb286755 h1:rkuKNEd+Izze/hA44R1kzPs9BXa544xXeufys8x0fkc= +github.com/MarkKremer/beep v1.0.3-0.20221013180303-756ceb286755/go.mod h1:PWWzyIlbyHQjQ/gJzGiMyDAvjo/t5L8TC8qkyX8UfWs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo= 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/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/ebitengine/purego v0.0.0-20220907032450-cf3e27c364c7 h1:tmSauY5l3s/Cp5n+cEiG1epUR2AejmdHeMJMycMFxb0= +github.com/ebitengine/purego v0.0.0-20220907032450-cf3e27c364c7/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 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= @@ -37,8 +39,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/hajimehoshi/go-mp3 v0.3.0 h1:fTM5DXjp/DL2G74HHAs/aBGiS9Tg7wnp+jkU38bHy4g= github.com/hajimehoshi/go-mp3 v0.3.0/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM= github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI= -github.com/hajimehoshi/oto v0.7.1 h1:I7maFPz5MBCwiutOrz++DLdbr4rTzBsbBuV2VpgU9kk= -github.com/hajimehoshi/oto v0.7.1/go.mod h1:wovJ8WWMfFKvP587mhHgot/MBr4DnNy9m6EepeVGnos= +github.com/hajimehoshi/oto/v2 v2.4.0-alpha.4 h1:m29xzbn3Pv5MgvgjMPs7m28uhUgVt3B3AIGjQLgkqUI= +github.com/hajimehoshi/oto/v2 v2.4.0-alpha.4/go.mod h1:OdGUICBjy7upAjvqqacbB63XIuYR3fqXZ7kYtlVYJgQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/icza/bitio v1.0.0 h1:squ/m1SHyFeCA6+6Gyol1AxV9nmPPlJFT8c2vKdj3U8= @@ -101,12 +103,9 @@ github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8 h1:idBdZTd9UioThJp8KpM/rTSinK/ChZFBE43/WtIy8zg= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067 h1:KYGJGHOQy8oSi1fDlSpcZF0+juKwk/hEMv5SiwHogR0= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6 h1:vyLBGJPIl9ZYbcQFM2USFmJBK6KI+t+z6jL0lbwjrnc= golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/model/alarm.go b/model/alarm.go index 12920b9..e6a8bbd 100644 --- a/model/alarm.go +++ b/model/alarm.go @@ -4,8 +4,6 @@ import ( "fmt" "sort" "time" - - "git.nemunai.re/nemunaire/reveil/config" ) type Date time.Time @@ -40,7 +38,7 @@ func (h *Hour) UnmarshalJSON(src []byte) error { return nil } -func GetNextAlarm(cfg *config.Config, db *LevelDBStorage) (*time.Time, error) { +func GetNextAlarm(db *LevelDBStorage) (*time.Time, error) { alarmsRepeated, err := GetAlarmsRepeated(db) if err != nil { return nil, err @@ -48,7 +46,7 @@ func GetNextAlarm(cfg *config.Config, db *LevelDBStorage) (*time.Time, error) { var closestAlarm *time.Time for _, alarm := range alarmsRepeated { - next := alarm.GetNextOccurence(cfg, db) + next := alarm.GetNextOccurence(db) if next != nil && (closestAlarm == nil || closestAlarm.After(*next)) { closestAlarm = next } @@ -94,7 +92,7 @@ type AlarmRepeated struct { NextTime *time.Time `json:"next_time,omitempty"` } -func (a *AlarmRepeated) FillExcepts(cfg *config.Config, db *LevelDBStorage) error { +func (a *AlarmRepeated) FillExcepts(db *LevelDBStorage) error { if a.IgnoreExceptions { return nil } @@ -114,7 +112,7 @@ func (a *AlarmRepeated) FillExcepts(cfg *config.Config, db *LevelDBStorage) erro end := time.Time(*exception.End).AddDate(0, 0, 1) for t := time.Time(*exception.Start); end.After(t); t = t.AddDate(0, 0, 1) { if t.Weekday() == a.Weekday { - a.Excepts = append(a.Excepts, time.Date(t.Year(), t.Month(), t.Day(), time.Time(*a.StartTime).Hour(), time.Time(*a.StartTime).Minute(), time.Time(*a.StartTime).Second(), 0, cfg.Timezone.GetLocation())) + a.Excepts = append(a.Excepts, time.Date(t.Year(), t.Month(), t.Day(), time.Time(*a.StartTime).Hour(), time.Time(*a.StartTime).Minute(), time.Time(*a.StartTime).Second(), 0, now.Location())) t.AddDate(0, 0, 6) } } @@ -125,14 +123,14 @@ func (a *AlarmRepeated) FillExcepts(cfg *config.Config, db *LevelDBStorage) erro return nil } -func (a *AlarmRepeated) GetNextOccurence(cfg *config.Config, db *LevelDBStorage) *time.Time { +func (a *AlarmRepeated) GetNextOccurence(db *LevelDBStorage) *time.Time { if len(a.Excepts) == 0 { - a.FillExcepts(cfg, db) + a.FillExcepts(db) } now := time.Now() - today := time.Date(now.Year(), now.Month(), now.Day(), time.Time(*a.StartTime).Hour(), time.Time(*a.StartTime).Minute(), time.Time(*a.StartTime).Second(), 0, cfg.Timezone.GetLocation()) + today := time.Date(now.Year(), now.Month(), now.Day(), time.Time(*a.StartTime).Hour(), time.Time(*a.StartTime).Minute(), time.Time(*a.StartTime).Second(), 0, now.Location()) if now.After(today) { today = today.AddDate(0, 0, 1) } diff --git a/player/player.go b/player/player.go index d543c77..2162fd1 100644 --- a/player/player.go +++ b/player/player.go @@ -6,12 +6,19 @@ import ( "math" "math/rand" "os" - "os/exec" "os/signal" + "path" "strings" "syscall" "time" + "github.com/faiface/beep" + "github.com/faiface/beep/effects" + "github.com/faiface/beep/flac" + "github.com/faiface/beep/mp3" + "github.com/faiface/beep/speaker" + "github.com/faiface/beep/wav" + "git.nemunai.re/nemunaire/reveil/config" "git.nemunai.re/nemunaire/reveil/model" ) @@ -19,11 +26,11 @@ import ( var CommonPlayer *Player type Player struct { - Playlist []string - MaxRunTime time.Duration - Stopper chan bool - currentCmd *exec.Cmd - currentCmdCh chan bool + Playlist []string + MaxRunTime time.Duration + Stopper chan bool + + sampleRate beep.SampleRate claironTime time.Duration claironFile string @@ -31,7 +38,7 @@ type Player struct { ntick int64 hasClaironed bool launched time.Time - volume uint16 + volume *effects.Volume dontUpdateVolume bool reverseOrder bool playedItem int @@ -42,10 +49,6 @@ func WakeUp(cfg *config.Config) (err error) { return fmt.Errorf("Unable to start the player: a player is already running") } - seed := time.Now().Unix() - seed -= seed % 172800 - rand.Seed(seed) - CommonPlayer, err = NewPlayer(cfg) if err != nil { return err @@ -63,12 +66,11 @@ func NewPlayer(cfg *config.Config) (*Player, error) { } p := Player{ - Stopper: make(chan bool, 1), - currentCmdCh: make(chan bool, 1), - MaxRunTime: settings.MaxRunTime * time.Minute, - claironTime: settings.GongInterval * time.Minute, - claironFile: reveil.CurrentGongPath(cfg), - reverseOrder: int(time.Now().Unix()/86400)%2 == 0, + Stopper: make(chan bool, 1), + MaxRunTime: settings.MaxRunTime * time.Minute, + sampleRate: beep.SampleRate(cfg.SampleRate), + claironTime: settings.GongInterval * time.Minute, + claironFile: reveil.CurrentGongPath(cfg), } // Load our track list @@ -98,27 +100,95 @@ func NewPlayer(cfg *config.Config) (*Player, error) { return &p, nil } -func (p *Player) playFile(filepath string) (err error) { - p.currentCmd = exec.Command("paplay", filepath) - if err = p.currentCmd.Start(); err != nil { - log.Println("Running paplay err: ", err.Error()) - p.currentCmdCh <- true +func loadFile(filepath string) (name string, s beep.StreamSeekCloser, format beep.Format, err error) { + var fd *os.File + + name = path.Base(filepath) + + fd, err = os.Open(filepath) + if err != nil { return } - log.Println("Running paplay ", filepath) + switch strings.ToLower(path.Ext(filepath)) { + case ".flac": + s, format, err = flac.Decode(fd) + case ".mp3": + s, format, err = mp3.Decode(fd) + default: + s, format, err = wav.Decode(fd) + } - err = p.currentCmd.Wait() - p.currentCmdCh <- true + if err != nil { + fd.Close() + return + } return } func (p *Player) WakeUp() { + log.Println("RUN WAKEUP FUNC") + log.Println("Playlist in use:", strings.Join(p.Playlist, " ; ")) + // Create infinite stream + stream := beep.Iterate(func() beep.Streamer { + if !p.hasClaironed && time.Since(p.launched) >= p.claironTime { + log.Println("clairon time!") + p.claironTime += p.claironTime / 2 + _, sample, format, err := loadFile(p.claironFile) + if err == nil { + p.volume.Volume = 0.1 + p.dontUpdateVolume = true + if format.SampleRate != p.sampleRate { + return beep.Resample(3, format.SampleRate, p.sampleRate, sample) + } else { + return sample + } + } else { + log.Println("Error loading clairon:", err) + } + } + + p.dontUpdateVolume = false + p.volume.Volume = -2 - math.Log(5/float64(p.ntick))/3 + + if p.reverseOrder { + p.playedItem -= 1 + } else { + p.playedItem += 1 + } + + if p.playedItem >= len(p.Playlist) { + p.playedItem = 0 + } else if p.playedItem < 0 { + p.playedItem = len(p.Playlist) - 1 + } + + // Load our current item + _, sample, format, err := loadFile(p.Playlist[p.playedItem]) + if err != nil { + log.Println("Error loading audio file %s: %s", p.Playlist[p.playedItem], err.Error()) + return nil + } + + // Resample if needed + log.Println("playing list item:", p.playedItem, "/", len(p.Playlist), ":", p.Playlist[p.playedItem]) + if format.SampleRate != p.sampleRate { + return beep.Resample(3, format.SampleRate, p.sampleRate, sample) + } else { + return sample + } + }) + // Prepare sound player - p.volume = 3500 + log.Println("Initializing sound player...") + speaker.Init(p.sampleRate, p.sampleRate.N(time.Second/10)) + defer speaker.Close() + + p.volume = &effects.Volume{stream, 10, -2, false} + speaker.Play(p.volume) ticker := time.NewTicker(time.Second) defer ticker.Stop() @@ -130,53 +200,20 @@ func (p *Player) WakeUp() { interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt, syscall.SIGHUP) - p.currentCmdCh <- true loop: for { select { - case <-p.currentCmdCh: - if !p.hasClaironed && time.Since(p.launched) >= p.claironTime { - log.Println("clairon time!") - p.claironTime += p.claironTime / 2 - p.SetVolume(65535) - p.dontUpdateVolume = true - go p.playFile(p.claironFile) - } else { - p.dontUpdateVolume = false - p.volume = 3500 + uint16(math.Log(1+float64(p.ntick)/8)*9500) - p.SetVolume(p.volume) - - if p.reverseOrder { - p.playedItem -= 1 - } else { - p.playedItem += 1 - } - - if p.playedItem >= len(p.Playlist) { - p.playedItem = 0 - } else if p.playedItem < 0 { - p.playedItem = len(p.Playlist) - 1 - } - - log.Println("Next track: ", p.Playlist[p.playedItem]) - go p.playFile(p.Playlist[p.playedItem]) - } - - case <-ticker.C: - p.ntick += 1 - if !p.dontUpdateVolume { - p.volume = 3500 + uint16(math.Log(1+float64(p.ntick)/8)*9500) - p.SetVolume(p.volume) - } - case <-p.Stopper: log.Println("Stopper activated") break loop - case <-maxRun: log.Println("Max run time exhausted") break loop - + case <-ticker.C: + p.ntick += 1 + if !p.dontUpdateVolume { + p.volume.Volume = -2 - math.Log(5/float64(p.ntick))/3 + } case <-interrupt: break loop } @@ -186,47 +223,31 @@ loop: // Calm down music loopcalm: - for i := 0; i < 128 && p.volume >= 15000; i += 1 { - timer := time.NewTimer(40 * time.Millisecond) - - p.volume -= 256 - p.SetVolume(p.volume) + for i := 0; i < 2000; i += 1 { + p.volume.Volume -= 0.001 + timer := time.NewTimer(4 * time.Millisecond) select { case <-p.Stopper: log.Println("Hard stop received...") timer.Stop() - p.volume = 0 + p.volume.Volume = 0 break loopcalm case <-timer.C: break } } - if p.currentCmd != nil && p.currentCmd.Process != nil { - p.currentCmd.Process.Kill() - } - - p.SetVolume(65535) - if p == CommonPlayer { log.Println("Destoying common player") CommonPlayer = nil - } -} -func (p *Player) NextTrack() { - if p.currentCmd != nil && p.currentCmd.Process != nil { - p.currentCmd.Process.Kill() + // TODO: find a better way to deallocate the card + os.Exit(42) } } -func (p *Player) SetVolume(volume uint16) error { - cmd := exec.Command("amixer", "-D", "pulse", "set", "Master", fmt.Sprintf("%d", volume)) - return cmd.Run() -} - func (p *Player) Stop() error { log.Println("Trying to stop the player") p.Stopper <- true diff --git a/ui/src/lib/Toaster.svelte b/ui/src/lib/Toaster.svelte deleted file mode 100644 index a8d7345..0000000 --- a/ui/src/lib/Toaster.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - -