sointu/tracker/gioui/files.go

159 lines
3.9 KiB
Go

// +build !js
package gioui
import (
"encoding/json"
"fmt"
"io/ioutil"
"path/filepath"
"time"
"gioui.org/app"
"gopkg.in/yaml.v3"
"github.com/sqweek/dialog"
"github.com/vsariola/sointu"
)
func (t *Tracker) LoadSongFile() {
if t.ChangedSinceSave() {
t.ConfirmSongActionType = ConfirmLoad
t.ConfirmSongDialog.Visible = true
return
}
t.loadSong()
}
func (t *Tracker) SaveSongFile() bool {
if p := t.FilePath(); p != "" {
return t.saveSong(p)
}
return t.SaveSongAsFile()
}
func (t *Tracker) SaveSongAsFile() bool {
filename, err := dialog.File().Filter("Sointu YAML song", "yml").Filter("Sointu JSON song", "json").Title("Save song").Save()
if err != nil {
return false
}
return t.saveSong(filename)
}
func (t *Tracker) loadSong() {
filename, err := dialog.File().Filter("Sointu YAML song", "yml").Filter("Sointu JSON song", "json").Title("Load song").Load()
if err != nil {
return
}
bytes, err := ioutil.ReadFile(filename)
if err != nil {
return
}
var song sointu.Song
if errJSON := json.Unmarshal(bytes, &song); errJSON != nil {
if errYaml := yaml.Unmarshal(bytes, &song); errYaml != nil {
return
}
}
if song.Score.Length <= 0 || len(song.Score.Tracks) == 0 || len(song.Patch) == 0 {
return
}
t.SetSong(song)
t.SetFilePath(filename)
t.window.Option(app.Title(fmt.Sprintf("Sointu Tracker - %v", filename)))
t.ClearUndoHistory()
t.SetChangedSinceSave(false)
}
func (t *Tracker) saveSong(filename string) bool {
var extension = filepath.Ext(filename)
var contents []byte
var err error
if extension == "json" {
contents, err = json.Marshal(t.Song())
} else {
contents, err = yaml.Marshal(t.Song())
}
if err != nil {
return false
}
if extension == "" {
filename = filename + ".yml"
}
ioutil.WriteFile(filename, contents, 0644)
t.SetFilePath(filename)
t.window.Option(app.Title(fmt.Sprintf("Sointu Tracker - %v", filename)))
t.SetChangedSinceSave(false)
return true
}
func (t *Tracker) SaveInstrument() bool {
filename, err := dialog.File().Filter("Sointu YAML instrument", "yml").Filter("Sointu JSON song", "json").Title(fmt.Sprintf("Save instrument %v", t.Instrument().Name)).Save()
if err != nil {
return false
}
var extension = filepath.Ext(filename)
var contents []byte
if extension == "json" {
contents, err = json.Marshal(t.Instrument())
} else {
contents, err = yaml.Marshal(t.Instrument())
}
if err != nil {
return false
}
if extension == "" {
filename = filename + ".yml"
}
ioutil.WriteFile(filename, contents, 0644)
return true
}
func (t *Tracker) LoadInstrument() {
filename, err := dialog.File().Filter("Sointu YAML instrument", "yml").Filter("Sointu JSON instrument", "json").Title("Load instrument").Load()
if err != nil {
return
}
bytes, err := ioutil.ReadFile(filename)
if err != nil {
return
}
var instrument sointu.Instrument
if errJSON := json.Unmarshal(bytes, &instrument); errJSON != nil {
if errYaml := yaml.Unmarshal(bytes, &instrument); errYaml != nil {
return
}
}
t.SetInstrument(instrument)
}
func (t *Tracker) exportWav(pcm16 bool) {
filename, err := dialog.File().Filter(".wav file", "wav").Title("Export .wav").Save()
if err != nil {
return
}
var extension = filepath.Ext(filename)
if extension == "" {
filename = filename + ".wav"
}
synth, err := t.synthService.Compile(t.Song().Patch)
if err != nil {
t.Alert.Update(fmt.Sprintf("Error compiling the patch during export: %v", err), Error, time.Second*3)
return
}
for i := 0; i < 32; i++ {
synth.Release(i)
}
data, _, err := sointu.Play(synth, t.Song()) // render the song to calculate its length
if err != nil {
t.Alert.Update(fmt.Sprintf("Error rendering the song during export: %v", err), Error, time.Second*3)
return
}
buffer, err := sointu.Wav(data, pcm16)
if err != nil {
t.Alert.Update(fmt.Sprintf("Error converting to .wav: %v", err), Error, time.Second*3)
return
}
ioutil.WriteFile(filename, buffer, 0644)
}