Nyan Cat

On your display
Display the nyan cat GIF and play rtttl
- Works with
- AWTRIX NG
- Topic
- Miscellaneous
- Includes
- Script · 1 icon
Choose your display in the next step.
Flow description
Display the nyan cat GIF and play rtttl
lXejz0qEBwXH.ax
# Nyan Cat - draws the 32x8 animated GIF and plays the melody under it.
#
# The app starts the tune the first time it is shown, keeps the GIF on screen
# while the buzzer is playing, and steps aside once the last note has sounded.
# A press on any button stops both and lets the rotation move on.
#
# Needs an icon called "nyan" (a 32x8 GIF) and a melody called "nyancat".
#
# @author QINZY8
# @name Nyan Cat
# @desc Nyan Cat GIF with the tune under it.
# @config melody bool "Play the melody" default=true help="Off shows the GIF for the usual app duration instead"
# @config tune text "Melody name" default="nyancat" maxlen=24
# @config icon text "Icon name" default="nyan" maxlen=24
# @config volume slider "Volume" default=100 min=0 max=100 unit=% help="Restored to the device setting after the tune"
class Nyan
var started # the tune has been kicked off for this appearance
var stopping # the user asked to stop, so do not linger
var savedVolume # the buzzer volume to put back, or nil when untouched
def init()
self.started = false
self.stopping = false
self.savedVolume = nil
end
# With the melody off there is nothing to wait for, so the rotation keeps its
# own clock and the app behaves like any other: a plain duration, no pause.
def wants_melody()
return store.get("melody") != false
end
# The volume is a device-wide setting, not a per-app one, so this app borrows
# it for the length of the tune and hands it back. Without the restore a
# quieter cat would leave every later melody quiet too.
def apply_volume()
if self.savedVolume != nil return end
self.savedVolume = settings.get("buzzerVolume")
settings.set("buzzerVolume", store.get("volume"))
end
def restore_volume()
if self.savedVolume == nil return end
settings.set("buzzerVolume", self.savedVolume)
self.savedVolume = nil
end
# on_show() runs the moment the rotation brings this app in, before the first
# draw(), so the GIF is already on screen when the first note lands. This is
# the one hook that fires exactly once per appearance.
def on_show()
self.stopping = false
if !self.wants_melody()
self.started = false
return
end
self.apply_volume()
sound.melody(store.get("tune"))
self.started = true
# Hold the rotation while the tune plays: the melody is the clock, and a
# fixed duration cannot know how long it runs. resume() in loop() releases
# it once the last note has sounded.
rotation.pause()
end
# Leaving the screen stops the tune: the melody belongs to the picture, and a
# rotation that moved on must not leave it playing behind another app. The
# volume goes back with it.
def on_hide()
if self.started sound.stop() end
self.started = false
self.restore_volume()
end
# Only takes a turn in the rotation when there is something to play. On a
# device with no buzzer, or with sound switched off, this app stays out of
# the way instead of showing a silent cat - unless the melody is off, in
# which case it is a plain GIF and runs anywhere.
def should_show()
if !self.wants_melody() return true end
if !sound.sinks()['buzzer'] return false end
return settings.get("soundEnabled") != false
end
# With the melody off, ask for the usual slot so the rotation has a clock to
# work from. With it on, loop() ends the appearance instead.
def duration()
if self.wants_melody() return 60000 end
return 0
end
# loop() runs about once a second, on screen or not, and is where the tune is
# watched. draw() must not do this: it runs per frame, so checking there
# would be 40 times the work for the same answer.
def loop()
if !self.started return end
# The last note has sounded, or the user stopped it: hand the panel back.
if self.stopping || !sound.playing()
self.stopping = true
self.started = false
self.restore_volume()
rotation.resume()
rotation.next()
end
end
def draw()
clear()
# The GIF animates on its own clock, so nothing here has to count frames.
if !icon(store.get("icon"), 0, 0)
# No icon stored: say so rather than showing an empty panel.
font("small")
text(1, 6, "no nyan", 0xFF00FF)
end
end
# A press stops the tune and leaves at once, which is what a viewer expects
# from a jingle that has worn out its welcome.
def on_button(btn)
self.stopping = true
if self.started
sound.stop()
self.restore_volume()
rotation.resume()
end
rotation.next()
return true
end
end
return Nyan()
These icons are attached to the flow. Send them to your AWTRIX separately; they are not included in the script installation.
32×8 px
Sign in to download these icons or send them to your AWTRIX.
Discussion 0
Ask a question, suggest a change or share how you use it.
No comments yet. Start the conversation.
More flows for AWTRIX NG Scripts or Miscellaneous
Something wrong with this flow? Report it.
Have an idea?
Sign in to ask questions and join the conversation.