Compare commits

...

No commits in common. "acb051d7a36ca0e27bb85d9c791dfd84f173b787" and "30a50b775fe10624f41fb1462236b0332ab32108" have entirely different histories.

15 changed files with 135 additions and 203 deletions

View File

@ -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:

View File

@ -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()

View File

@ -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)
})

3
app.go
View File

@ -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)

View File

@ -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
}

View File

@ -18,7 +18,6 @@ type Config struct {
ActionsDir string
RoutinesDir string
Timezone Timezone
SampleRate int
}

View File

@ -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
}

View File

@ -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)

10
go.mod
View File

@ -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

13
go.sum
View File

@ -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=

View File

@ -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)
}

View File

@ -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

View File

@ -1,22 +0,0 @@
<script>
import {
Toast,
ToastBody,
ToastHeader,
} from 'sveltestrap';
import { ToastsStore } from '$lib/stores/toasts';
</script>
<div class="toast-container position-absolute top-0 end-0 p-3">
{#each $ToastsStore.toasts as toast}
<Toast>
<ToastHeader toggle={toast.close} icon={toast.color}>
{#if toast.title}{toast.title}{:else}Réveil{/if}
</ToastHeader>
<ToastBody>
{toast.msg}
</ToastBody>
</Toast>
{/each}
</div>

View File

@ -8,14 +8,6 @@
import Header from '$lib/components/Header.svelte';
import Toaster from '$lib/components/Toaster.svelte';
import { ToastsStore } from '$lib/stores/toasts';
window.onunhandledrejection = (e) => {
ToastsStore.addErrorToast({
message: e.reason,
timeout: 7500,
})
}
</script>
<svelte:head>

View File

@ -1,7 +1,7 @@
{
"manifest_version": 2,
"short_name": "Réveil",
"name": "Réveil",
"short_name": "Gustus",
"name": "Gustus",
"version": "0.1",
"author": "nemucorp",
"start_url": "/",
@ -12,9 +12,9 @@
"sizes": "512x512"
}
],
"background_color": "#e83e8c",
"background_color": "#d62a49",
"display": "standalone",
"scope": "/",
"theme_color": "#ffffff",
"description": "Quand est-ce qu'on se lève ?"
"description": "Retrouvez facilement toutes vos recettes préférées"
}