Skip to content

Conversation

@colinmcardell
Copy link
Contributor

@colinmcardell colinmcardell commented Sep 2, 2025

what:
Adds pause/resume functionality for both record and playback. Also exposes loop control API. Includes reworking of tape state machine w/threading safety improvements and additional fixes:

  • pauseRecord(bool), pausePlayback(bool)
  • setLooping(bool), isLooping(), isPaused()

...

  • /tape/record/pausetape_record_pause()Audio.tape_record_pause()
  • /tape/play/pausetape_play_pause()Audio.tape_play_pause()
  • /tape/play/looptape_play_loop()Audio.tape_play_loop()

Mostly addresses #1789, #766, and partially address #1758 with an E3 debounce in fileselect on preview.

why:
Working on exposing tape loop control, I went down a bit of a rabbit hole, and ended up adding pause as well, by way of a command queue between the tape public API and the audio thread. I also addressed some threading race conditions.

how:

  • Command queue thread-safe tape state transitions
  • Safe ringbuffer cleanup and thread management
  • Fixed buffer dimensions and underrun handling in reader
  • Adds OSC and Lua bindings for new functionality

notes:

  • This should be a non-breaking API change, fully wired through all three layers (OSC → C bindings → Lua API).
  • Lua tape scripting has not been updated to use the new functionality, although the API is fully available. I can follow up with this but would like to get the core changes reviewed and tested first, as well as discuss how best to update the Lua tape scripts.
  • Tested on aluminum norns CM3 hardware and is stable. I will also test on a norns shield Pi3 and shield Pi4 when I get a chance.

- Add Tape::Reader setLoopFile/getLoopFile
- Add Tape::setLooping/isLooping
- Add MixerClient::setTapeLoop
- Add OSC /tape/play/loop (int 0/1) to set loop value
- Expose loop control to Lua
@colinmcardell
Copy link
Contributor Author

I worked out a patch to tape.lua last night. It takes into account the discussed UI/UX changes in #1789. I will amend it to this PR later tonight.

@tehn
Copy link
Member

tehn commented Sep 3, 2025

Thank you Colin! I'll get this tested shortly, it's been a much desired feature by several people.

@colinmcardell
Copy link
Contributor Author

Didn't get the tape.lua changes pushed out last night. I will have time tonight!

@colinmcardell
Copy link
Contributor Author

Ok. I've pushed up the changes to tape.lua, that allow testing from the UI. There are a few considerations still that I can either get around to now or later. Open to other feedback!

  • Playback EOF when not in loop mode re-opens and places the file in the starting/idle position. It would probably be more ideal that it just doesn't unload the file?
  • Playback PLAY/PAUSE/RESUME and LOOP indicators are a bit crowded...

@tehn
Copy link
Member

tehn commented Sep 6, 2025

reviewed the code, looks great! still haven't had a chance to test on device.

agreed that it makes sense to maybe not unload the file on EOF. if complete, an issued PLAY command should just play it again, right?

@colinmcardell
Copy link
Contributor Author

if complete, an issued PLAY command should just play it again, right?

Yes. tape.lua is reloading the file and parking at the top, waiting for the PLAY command. This UX is implemented in this PR, works well and feels right.

An optimization would be to prevent the underlying Tape class from unloading the file until explicitly told to. This is not blocking the merge of this work in my opinion.

@colinmcardell
Copy link
Contributor Author

colinmcardell commented Sep 6, 2025

I've added a debounce to fileselect preview as mentioned in #1758. It's true that this doesn't resolve the underlying race conditioning in the Tape state, but it does seem to address the issue of Tape getting into a broken state (on aluminum norns hardware) and doesn't hurt to have the debounce in place. Once the underlying race is addressed in Tape it's possible that the debounce time could be reduced.

@colinmcardell
Copy link
Contributor Author

Come to think of it once #1528 is resolved (Tape state getter), fileselect preview thrashing should not be an issue. The issue at this point is the state synchronization and not a race condition within Tape. I've guarded the Tape command queue and API thoroughly against transport state race conditions in this PR.

@colinmcardell
Copy link
Contributor Author

Playback PLAY/PAUSE/RESUME and LOOP indicators are a bit crowded...

I've updated the UI to address this. I will attach screenshots shortly.

@colinmcardell
Copy link
Contributor Author

01_idle

idle (no loop)

02_idle_loop

idle (loop)

03_play_loop

play (loop)

04_pause_loop

pause (loop)

05_rec_mode_loop

rec mode (playback looping)

@tehn
Copy link
Member

tehn commented Sep 8, 2025

This looks great! Tested on device, code looks good to me. Thank you!

@tehn tehn merged commit 44dc502 into monome:main Sep 8, 2025
3 checks passed
@colinmcardell colinmcardell deleted the tape-loop branch September 9, 2025 01:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants