Skip to main content
Glama
emicklei

melrōse musical expression player

by emicklei
recording.go2.67 kB
package control import ( "fmt" "time" "github.com/emicklei/melrose/core" "github.com/emicklei/melrose/notify" ) type Recording struct { deviceID int timeline *core.Timeline variableName string bpm float64 } func NewRecording(deviceID int, variableName string, bpm float64) *Recording { tim := core.NewTimeline() return &Recording{ deviceID: deviceID, timeline: tim, variableName: variableName, bpm: bpm, } } func (r *Recording) GetTargetFrom(other *Recording) { // only overwrite variable // listener may have been started so timeline is not empty, so device is listened to r.variableName = other.variableName } func (r *Recording) Play(ctx core.Context, at time.Time) time.Time { notify.Debugf("start recording...") // flush r.timeline.Reset() ctx.Device().Listen(r.deviceID, r, true) return time.Now() } // Stop is part of Stoppable func (r *Recording) Stop(ctx core.Context) error { notify.Debugf("... stopped recording") // nothing there or already stopped if r.timeline.Len() == 0 { if notify.IsDebug() { notify.Debugf("empty timeline on stop recording") } return nil } seq := r.S() if notify.IsDebug() { notify.Debugf("recording.stop seq:%v", seq) // TODO temporary store the recording for the test in ui/img/draw_test.go fmt.Println("writing /tmp/melrose-recording.json") core.NotesEventsToFile(r.timeline.NoteEvents(), "/tmp/melrose-recording.json") } ctx.Variables().Put(r.variableName, seq) ctx.Device().Listen(r.deviceID, r, false) // flush r.timeline.Reset() return nil } func (r *Recording) IsPlaying() bool { return true } func (r *Recording) Storex() string { return fmt.Sprintf("record(device(%d,%s))", r.deviceID, r.variableName) } func (r *Recording) S() core.Sequenceable { periods := r.timeline.BuildNotePeriods() builder := core.NewSequenceBuilder(periods, r.bpm) return builder.Build() } func (r *Recording) NoteOn(channel int, n core.Note) { when := time.Now() change := core.NewNoteChange(true, int64(n.MIDI()), int64(n.Velocity)) if notify.IsDebug() { notify.Debugf("recording.noteon note:%v t:%s", n, when.Format("04:05.000")) } r.timeline.Schedule(change, when) } func (r *Recording) NoteOff(channel int, n core.Note) { when := time.Now() change := core.NewNoteChange(false, int64(n.MIDI()), int64(n.Velocity)) if notify.IsDebug() { notify.Debugf("recording.noteoff note:%v t:%s", n, when.Format("04:05.000")) } r.timeline.Schedule(change, when) } // ControlChange is ignored func (r *Recording) ControlChange(channel, number, value int) {} func (r *Recording) Inspect(i core.Inspection) { i.Properties["sequence"] = r.S() }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/emicklei/melrose'

If you have feedback or need assistance with the MCP directory API, please join our Discord server