Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: play notification sound when pomodoro ends #14

Merged
merged 9 commits into from
Apr 22, 2022
5 changes: 4 additions & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
name: build
on: push
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Dev dependencies
run: sudo apt-get update && sudo apt-get install gcc libgl1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev libx11-dev xorg-dev
run: sudo apt-get update && sudo apt-get install gcc libgl1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev libx11-dev xorg-dev libasound2-dev
- uses: WillAbides/setup-go-faster@v1.7.0
with:
go-version: '1.17.x'
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/codeql-analysis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ on:
schedule:
- cron: '16 18 * * 3'

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
analyze:
name: Analyze
Expand Down
14 changes: 14 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ gomod:
builds:
- targets:
- linux_amd64
env:
# Required by oto (sound library)
- CGO_ENABLED=1
# Reproducible build
# https://goreleaser.com/customization/build/#reproducible-builds
mod_timestamp: '{{ .CommitTimestamp }}'
Expand Down Expand Up @@ -40,6 +43,17 @@ nfpms:
dst: /usr/share/pixmaps/fynodoro.png
- src: assets/fynodoro.desktop
dst: /usr/local/share/applications/fynodoro.desktop
- src: assets/notification.mp3
dst: /usr/share/fynodoro/notification.mp3
overrides:
deb:
dependencies:
# Required by oto (sound library)
- libasound2-dev
rpm:
dependencies:
# Required by oto (sound library)
- alsa-lib-devel
release:
draft: true
footer: |
Expand Down
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
- [Timer](#timer)
- [Settings](#settings)
- [Features](#features)
- [Configuration](#configuration)
- [Changelog](#changelog)
- [Configuration](#configuration)
- [Notification sound](#notification-sound)
- [Install](#install)
- [Install Ubuntu/Debian (.deb)](#install-ubuntudebian-deb)
- [Install Fedora/Redhat (.rpm)](#install-fedoraredhat-rpm)
Expand Down Expand Up @@ -49,6 +50,10 @@
- 🏆 Small download size
- 💼 Releases for Ubuntu/Debian, Fedora/Redhat, and as linux binary

## Changelog

See the [Releases](https://github.com/tomsquest/fynodoro/releases) section on GitHub.

## Configuration

The Pomodoro technique defaults to 4 work rounds of 25 minutes, with a 5 minutes pause ("short break") in-between and a final 15 minutes pause (the "long" break), for a total of 2 hours (4x25m Work + 3x5m Short breaks + 1x15m Long break).
Expand All @@ -66,9 +71,10 @@ You can **disable** Short breaks by setting the duration of Short breaks to `0`.

Tips: you can **disable** both Short and Long breaks by setting them to `0`. The timer will then act as a ticker, notifying you after each Work period.

## Changelog
### Notification sound

See the [Releases](https://github.com/tomsquest/fynodoro/releases) section.
The notification sound is stored in: `/usr/share/fynodoro/notification.mp3`.
You can override it if you wish with another **mp3** file.

## Install

Expand Down Expand Up @@ -125,10 +131,11 @@ TAG=v1.0.0 && git tag $TAG && git push origin $TAG
## TODO

- [ ] Pico/Nano/Normal UI
- [ ] Tons of options (run script on pomodoro end, notification sound, ...)
- [ ] Tons of options (run script on pomodoro end, notification sound on/off, ...)
- [ ] Release Windows, macOS, Android, IOS versions

## Credits

- Icon made by [Freepik](https://www.freepik.com) from [Flaticon](https://www.flaticon.com/free-icon/tomato_877814)
- Screenshot pimped with [PrettySnap](https://prettysnap.app)
- Notification sound from [Zedge](https://www.zedge.net/ringtones)
Binary file added assets/notification.mp3
Binary file not shown.
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ require (
github.com/benbjohnson/clock v1.3.0
github.com/gen2brain/beeep v0.0.0-20210529141713-5586760f0cc1
github.com/godbus/dbus/v5 v5.0.6 // indirect
github.com/hajimehoshi/go-mp3 v0.3.0
github.com/hajimehoshi/oto v0.7.1
github.com/stretchr/testify v1.7.0
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 // indirect
golang.org/x/text v0.3.5 // indirect
Expand All @@ -29,6 +31,8 @@ require (
github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 // indirect
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect
github.com/yuin/goldmark v1.3.8 // indirect
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8 // indirect
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 // indirect
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6 // indirect
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
)
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c h1:16eHWuMGvCjSf
github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherwasm v1.1.0 h1:fA2uLoctU5+T3OhOn2vYP0DVT6pxc7xhTlBB1paATqQ=
github.com/gopherjs/gopherwasm v1.1.0/go.mod h1:SkZ8z7CWBz5VXbhJel8TxCmAcsQqzgWGR/8nMhyhZSI=
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/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc=
github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
Expand Down Expand Up @@ -69,8 +74,13 @@ github.com/yuin/goldmark v1.3.8 h1:Nw158Q8QN+CPgTmVRByhVwapp8Mm1e2blinhmx4wx5E=
github.com/yuin/goldmark v1.3.8/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
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-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
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/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
Expand All @@ -79,7 +89,9 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
11 changes: 10 additions & 1 deletion ui/notify.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,19 @@ import (
"fmt"
"github.com/gen2brain/beeep"
"github.com/tomsquest/fynodoro/pomodoro"
"log"
)

func notifyPomodoroDone(kind pomodoro.Kind) {
title := fmt.Sprintf("%s done", kind)
message := fmt.Sprintf("You just finished a %s pomodoro.", kind)
_ = beeep.Notify(title, message, "/usr/share/pixmaps/fynodoro.png")
err := beeep.Notify(title, message, "/usr/share/pixmaps/fynodoro.png")
if err != nil {
log.Printf("unable to notify: %v\n", err)
}

err = playNotificationSound()
if err != nil {
log.Printf("unable to play notification sound: %v\n", err)
}
}
47 changes: 47 additions & 0 deletions ui/playback.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package ui

import (
"fmt"
"github.com/hajimehoshi/go-mp3"
"github.com/hajimehoshi/oto"
"io"
"os"
"sync"
)

var once sync.Once
var context *oto.Context

func playNotificationSound() error {
fileName := "/usr/share/fynodoro/notification.mp3"
f, err := os.Open(fileName)
if err != nil {
return fmt.Errorf("unable to read %s: %w", fileName, err)
}

decoder, err := mp3.NewDecoder(f)
if err != nil {
return fmt.Errorf("unable to decode %s: %w", fileName, err)
}

once.Do(func() {
context, err = oto.NewContext(decoder.SampleRate(), 2, 2, 8192)
})
if err != nil {
return fmt.Errorf("unable to create oto context: %w", err)
}

go func() {
player := context.NewPlayer()
defer func() {
err = player.Close()
}()

_, err = io.Copy(player, decoder)
}()
if err != nil {
return fmt.Errorf("unable to play: %w", err)
}

return nil
}