- Explain what
on_tickdoes and when it fires - Write a tick handler that receives the elapsed time in seconds
- Format a number of seconds as a
m:ssstring - Update the timestamp label and progress bar on the Now Playing page
Part 1 β The tick: a heartbeat for your app
Once a song is playing you need the screen to keep updating β the timestamp counting up, the progress bar filling in. But your code has already finished running from top to bottom. Who does the updating?
The pypod module contains a hidden timer. Every 500 milliseconds (half a
second) while a song is playing it fires a tick. If you have registered an
on_tick callback, the timer calls your function automatically and passes in
how many seconds have elapsed so far.
Think of the tick like a clock ticking in the background. Your function is the clock hand β every tick, it moves forward and updates what is shown on screen.
Part 2 β Registering an on_tick callback
on_tick works exactly like on_song_selected from Lesson 4 β
register a function and it will be called automatically. The only difference is that
your function receives one argument: the number of seconds elapsed.
from pypod import on_tick
@on_tick
def update_display(elapsed):
print(elapsed) # 0, 0, 1, 1, 2, 2, 3 β¦ (twice per second)
Part 3 β Formatting the time as m:ss
The elapsed value is just a plain number of seconds β e.g. 79.
The timestamp label on screen expects a string like "1:19".
Here is how to convert it:
def format_time(seconds):
m = seconds // 60 # integer division β how many whole minutes?
s = seconds % 60 # remainder β how many seconds left over?
return "{:d}:{:02d}".format(m, s)
print(format_time(79)) # 1:19
print(format_time(4)) # 0:04
print(format_time(183)) # 3:03
:02d mean?
Inside a format string, {:02d} means: print an integer (d),
at least 2 digits wide (2), padding with zeroes if needed (0).
So 4 becomes "04" and 33 stays "33".
That is how you get the proper 0:04 rather than 0:4.
Part 4 β Updating the timestamp label
show_timestamp() takes a number of seconds and updates the label on screen.
Call it inside your tick handler:
from pypod import on_tick, show_timestamp
@on_tick
def update_display(elapsed):
show_timestamp(elapsed)
Part 5 β Updating the progress bar
show_progress(elapsed, total) fills the progress bar proportionally.
total is the total duration of the track in seconds. Because we do not
always know the exact length, using a safe upper bound of 400
(about 6.5 minutes) works well enough:
from pypod import on_tick, show_timestamp, show_progress
@on_tick
def update_display(elapsed):
show_timestamp(elapsed)
show_progress(elapsed, 400)
The progress bar will advance steadily and simply stop growing once the song ends.
Part 6 β The full main.py so far
main.py
from pypod import (
Track, add_track,
play, next_track,
on_song_selected, on_track_ended, on_tick,
show_timestamp, show_progress,
list_music_files, music_path, lyrics_path,
start,
)
# --- functions from previous lessons ---
def parse_filename(filename): ...
def load_lyrics(path): ...
# --- build the track list ---
for filename in list_music_files():
title, artist = parse_filename(filename)
track = Track(title=title, artist=artist,
file_path=music_path(filename),
lyrics=load_lyrics(lyrics_path(title)))
add_track(track)
# --- callbacks ---
current_track = None
@on_song_selected
def handle_selection(track):
global current_track
current_track = track
play(track)
@on_track_ended
def handle_end():
next_track()
@on_tick
def update_display(elapsed):
show_timestamp(elapsed)
show_progress(elapsed, 400)
start()
- Add the
on_tickimport and theupdate_displayfunction to yourmain.py. - Play a song β the timestamp and progress bar should now update every half-second.
- Pause and resume β does the timestamp pause and resume correctly?
-
Can you also display the remaining time (total β elapsed) somewhere?
You could print it to the console, or β if you feel adventurous β update the
timestamp_lblwidget to show both. -
What is the largest number of seconds that your
format_timefunction handles correctly? What goes wrong with very long durations? Does it matter for songs?