mirror of
https://github.com/vsariola/sointu.git
synced 2025-06-03 09:08:18 -04:00
The RPC and sync library mechanisms were removed for now; they never really worked and contained several obvious bugs. Need to consider if syncs are useful at all during the compose time, or just used during intro.
172 lines
4.2 KiB
Go
172 lines
4.2 KiB
Go
//go:build !js
|
|
// +build !js
|
|
|
|
package gioui
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
|
|
"github.com/vsariola/sointu"
|
|
)
|
|
|
|
func (t *Tracker) OpenSongFile(forced bool) {
|
|
if !forced && t.ChangedSinceSave() {
|
|
t.ConfirmSongActionType = ConfirmLoad
|
|
t.ConfirmSongDialog.Visible = true
|
|
return
|
|
}
|
|
if p := t.FilePath(); p != "" {
|
|
d, _ := filepath.Split(p)
|
|
d = filepath.Clean(d)
|
|
t.OpenSongDialog.Directory.SetText(d)
|
|
t.OpenSongDialog.FileName.SetText("")
|
|
}
|
|
t.OpenSongDialog.Visible = true
|
|
}
|
|
|
|
func (t *Tracker) SaveSongFile() bool {
|
|
if p := t.FilePath(); p != "" {
|
|
return t.saveSong(p)
|
|
}
|
|
t.SaveSongAsFile()
|
|
return false
|
|
}
|
|
|
|
func (t *Tracker) SaveSongAsFile() {
|
|
t.SaveSongDialog.Visible = true
|
|
if p := t.FilePath(); p != "" {
|
|
d, f := filepath.Split(p)
|
|
d = filepath.Clean(d)
|
|
t.SaveSongDialog.Directory.SetText(d)
|
|
t.SaveSongDialog.FileName.SetText(f)
|
|
}
|
|
}
|
|
|
|
func (t *Tracker) ExportWav() {
|
|
t.ExportWavDialog.Visible = true
|
|
if p := t.FilePath(); p != "" {
|
|
d, _ := filepath.Split(p)
|
|
d = filepath.Clean(d)
|
|
t.ExportWavDialog.Directory.SetText(d)
|
|
}
|
|
}
|
|
|
|
func (t *Tracker) LoadInstrument() {
|
|
t.OpenInstrumentDialog.Visible = true
|
|
}
|
|
|
|
func (t *Tracker) SaveInstrument() {
|
|
t.SaveInstrumentDialog.Visible = true
|
|
}
|
|
|
|
func (t *Tracker) loadSong(filename string) {
|
|
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 {
|
|
t.Alert.Update(fmt.Sprintf("Error unmarshaling a song file: %v / %v", errYaml, errJSON), Error, time.Second*3)
|
|
return
|
|
}
|
|
}
|
|
if song.Score.Length <= 0 || len(song.Score.Tracks) == 0 || len(song.Patch) == 0 {
|
|
t.Alert.Update("The song file is malformed", Error, time.Second*3)
|
|
return
|
|
}
|
|
t.SetSong(song)
|
|
t.SetFilePath(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 {
|
|
t.Alert.Update(fmt.Sprintf("Error marshaling a song file: %v", err), Error, time.Second*3)
|
|
return false
|
|
}
|
|
if extension == "" {
|
|
filename = filename + ".yml"
|
|
}
|
|
ioutil.WriteFile(filename, contents, 0644)
|
|
t.SetFilePath(filename)
|
|
t.SetChangedSinceSave(false)
|
|
return true
|
|
}
|
|
|
|
func (t *Tracker) exportWav(filename string, pcm16 bool) {
|
|
var extension = filepath.Ext(filename)
|
|
if extension == "" {
|
|
filename = filename + ".wav"
|
|
}
|
|
data, err := sointu.Play(t.synthService, t.Song(), true) // 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)
|
|
}
|
|
|
|
func (t *Tracker) saveInstrument(filename string) bool {
|
|
var extension = filepath.Ext(filename)
|
|
var contents []byte
|
|
var err error
|
|
if extension == ".json" {
|
|
contents, err = json.Marshal(t.Instrument())
|
|
} else {
|
|
contents, err = yaml.Marshal(t.Instrument())
|
|
}
|
|
if err != nil {
|
|
t.Alert.Update(fmt.Sprintf("Error marshaling a ínstrument file: %v", err), Error, time.Second*3)
|
|
return false
|
|
}
|
|
if extension == "" {
|
|
filename = filename + ".yml"
|
|
}
|
|
ioutil.WriteFile(filename, contents, 0644)
|
|
return true
|
|
}
|
|
|
|
func (t *Tracker) loadInstrument(filename string) bool {
|
|
bytes, err := ioutil.ReadFile(filename)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
var instrument sointu.Instrument
|
|
if errJSON := json.Unmarshal(bytes, &instrument); errJSON != nil {
|
|
if errYaml := yaml.Unmarshal(bytes, &instrument); errYaml != nil {
|
|
t.Alert.Update(fmt.Sprintf("Error unmarshaling an instrument file: %v / %v", errYaml, errJSON), Error, time.Second*3)
|
|
return false
|
|
}
|
|
}
|
|
if len(instrument.Units) == 0 {
|
|
t.Alert.Update("The instrument file is malformed", Error, time.Second*3)
|
|
return false
|
|
}
|
|
t.SetInstrument(instrument)
|
|
if t.Instrument().Comment != "" {
|
|
t.InstrumentEditor.ExpandComment()
|
|
}
|
|
return true
|
|
}
|