Skip to content

Commit

Permalink
Added dbus service for playing sounds
Browse files Browse the repository at this point in the history
  • Loading branch information
CameronRP committed Apr 12, 2021
1 parent bc3bea7 commit e72a7ff
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 3 deletions.
1 change: 1 addition & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ nfpms:
bindir: /usr/bin
files:
"_release/audiobait.service": "/etc/systemd/system/audiobait.service"
"_release/org.cacophony.Audiobait.conf": "/etc/dbus-1/system.d/org.cacophony.Audiobait.conf"
scripts:
postinstall: "_release/postinstall.sh"
14 changes: 14 additions & 0 deletions _release/org.cacophony.Audiobait.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->

<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="root">
<allow own="org.cacophony.Audiobait"/>
</policy>

<policy context="default">
<allow send_destination="org.cacophony.Audiobait"/>
</policy>
</busconfig>
13 changes: 10 additions & 3 deletions cmd/audiobait/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ func runMain() error {
return err
}

soundCard := NewSoundCardPlayer(conf.Card, conf.VolumeControl)

service, err := startService(conf.Dir, soundCard)
if err != nil {
return err
}
log.Println("started audiobait dbus servie")

// Make sure the path to where we keep the schedule and audio files is OK.
if err := createAudioPath(conf.Dir); err != nil {
// This is a pretty fundamental error. We can't do anything without this.
Expand All @@ -85,12 +93,11 @@ func runMain() error {
// Start checking for new schedules
dl := NewDownloader(conf.Dir)

soundCard := NewSoundCardPlayer(conf.Card, conf.VolumeControl)

var playTime <-chan time.Time
for {
log.Print("loading schedule from disk")
player, schedule, err := createPlayer(soundCard, conf.Dir)
player, schedule, err := createPlayer(soundCard, conf.Dir) //TODO add trigger output
service.setPlayer(player)
if err != nil {
log.Printf("error creating player: %v (will wait for schedule update)", err)
playTime = nil
Expand Down
127 changes: 127 additions & 0 deletions cmd/audiobait/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
audiobait - play sounds to lure animals for The Cacophony Project API.
Copyright (C) 2021, The Cacophony Project
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package main

import (
"errors"
"sync"

"github.com/TheCacophonyProject/audiobait/audiofilelibrary"
"github.com/TheCacophonyProject/audiobait/playlist"
"github.com/godbus/dbus"
"github.com/godbus/dbus/introspect"
)

const (
dbusName = "org.cacophony.Audiobait"
dbusPath = "/org/cacophony/Audiobait"
)

var mu = sync.RWMutex{}

type service struct {
soundCard SoundCardPlayer
player *playlist.SchedulePlayer
soundDir string
}

func startService(soundDir string, soundCard SoundCardPlayer) (*service, error) {
conn, err := dbus.SystemBus()
if err != nil {
return nil, err
}
reply, err := conn.RequestName(dbusName, dbus.NameFlagDoNotQueue)
if err != nil {
return nil, err
}
if reply != dbus.RequestNameReplyPrimaryOwner {
return nil, errors.New("name already taken")
}

s := &service{
soundDir: soundDir,
soundCard: soundCard,
}
if err := conn.Export(s, dbusPath, dbusName); err != nil {
return nil, err
}
if err := conn.Export(genIntrospectable(s), dbusPath, "org.freedesktop.DBus.Introspectable"); err != nil {
return nil, err
}
return s, nil
}

func (s *service) setPlayer(player *playlist.SchedulePlayer) {
mu.Lock()
defer mu.Unlock()
s.player = player
}

func (s service) Play(audioFileId, volume, priority int, makeEvent bool) (bool, *dbus.Error) {
mu.Lock()
defer mu.Unlock()
library, err := audiofilelibrary.OpenLibrary(s.soundDir, scheduleFilename)
if err != nil {
return false, dbusErr("Play", err)
}
path := s.soundDir + "/" + library.FilesByID[audioFileId]
if err := s.soundCard.Play(path, volume); err != nil {
return false, dbusErr("Play", err)
}
return true, nil
}

func dbusErr(name string, err error) *dbus.Error {
if err == nil {
return nil
}
return &dbus.Error{
Name: dbusName + "." + name,
Body: []interface{}{err.Error()},
}
}

func genIntrospectable(v interface{}) introspect.Introspectable {
node := &introspect.Node{
Interfaces: []introspect.Interface{{
Name: dbusName,
Methods: introspect.Methods(v),
}},
}
return introspect.NewIntrospectable(node)
}

/* //TODO
func (s *service) PlayTrigger(trigger string, volume, priority int, makeEvent bool) (bool, *dbus.Error) {
mu.Lock()
defer mu.Unlock()
return true, nil
}
func (s service) Status() *dbus.Error {
mu.Lock()
defer mu.Unlock()
return nil
}
func (s service) Mute(priority int) *dbus.Error {
return nil
}
*/
1 change: 1 addition & 0 deletions playlist/schedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type Combo struct {
Waits []int
Volumes []int
Sounds []string
Trigger string
}

func ParseJSONConfigFile(jsonAsString string, schedule *Schedule) error {
Expand Down

0 comments on commit e72a7ff

Please sign in to comment.