1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#! /usr/bin/env gforth
\ Challenge 103
\
\ TASK #2 � What�s playing?
\ Submitted by: Albert Croft
\ Working from home, you decided that on occasion you wanted some background
\ noise while working. You threw together a network streamer to continuously
\ loop through the files and launched it in a tmux (or screen) session, giving
\ it a directory tree of files to play. During the day, you connected an audio
\ player to the stream, listening through the workday, closing it when done.
\
\ For weeks you connect to the stream daily, slowly noticing a gradual drift of
\ the media. After several weeks, you take vacation. When you return, you are
\ pleasantly surprised to find the streamer still running. Before connecting,
\ however, if you consider the puzzle of determining which track is playing.
\
\ After looking at a few modules to read info regarding the media, a quick bit
\ of coding gave you a file list. The file list is in a simple CSV format, each
\ line containing two fields: the first the number of milliseconds in length,
\ the latter the media�s title (this example is of several episodes available
\ from the MercuryTheatre.info):
\
\ 1709363,"Les Miserables Episode 1: The Bishop (broadcast date: 1937-07-23)"
\ 1723781,"Les Miserables Episode 2: Javert (broadcast date: 1937-07-30)"
\ 1723781,"Les Miserables Episode 3: The Trial (broadcast date: 1937-08-06)"
\ 1678356,"Les Miserables Episode 4: Cosette (broadcast date: 1937-08-13)"
\ 1646043,"Les Miserables Episode 5: The Grave (broadcast date: 1937-08-20)"
\ 1714640,"Les Miserables Episode 6: The Barricade (broadcast date: 1937-08-27)"
\ 1714640,"Les Miserables Episode 7: Conclusion (broadcast date: 1937-09-03)"
\ For this script, you can assume to be provided the following information:
\
\ * the value of $^T ($BASETIME) of the streamer script,
\ * the value of time(), and
\ * a CSV file containing the media to play consisting of the length in
\ milliseconds and an identifier for the media (title, filename, or other).
\ Write a program to output which file is currently playing. For purposes of
\ this script, you may assume gapless playback, and format the output as you
\ see fit.
\
\ Optional: Also display the current position in the media as a time-like value.
\
\ Example:
\
\ Input: 3 command line parameters: start time, current time, file name
\
\ # Streamer start time: Tue Nov 23 12:22:03 2020
\ 1606134123
\
\ # Current time: Mon Mar 1 09:34:36 2021
\ 1614591276
\
\ # filelist.csv
\
\ Output:
\
\ "Les Miserables Episode 1: The Bishop (broadcast date: 1937-07-23)"
\ 00:17:33
VARIABLE current_secs
VARIABLE playlist_total_secs
2VARIABLE playlist_file
: get-args
NEXT-ARG S>NUMBER? 0= THROW DROP ( start_secs )
NEXT-ARG S>NUMBER? 0= THROW DROP ( start_secs current_secs )
SWAP - current_secs ! \ store in current secs
NEXT-ARG DUP 0= THROW playlist_file 2!
;
\ get secs from ms in PAD
: get-secs ( -- ms )
\ find ','
PAD
BEGIN DUP C@ ',' <> WHILE 1+ REPEAT
\ parse number
PAD - PAD SWAP
S>NUMBER? 0= THROW DROP 500 + 1000 / ;
\ print title in PAD
: .title ( -- )
PAD
BEGIN DUP C@ '"' <> WHILE 1+ REPEAT
1+
BEGIN DUP C@ '"' <> WHILE DUP C@ EMIT 1+ REPEAT
SPACE DROP ;
\ compute size of playlist
: get-playlist-size ( -- )
playlist_file 2@ R/O OPEN-FILE THROW { fileid }
0 playlist_total_secs !
BEGIN
PAD 128 fileid READ-LINE THROW
WHILE
DROP
get-secs playlist_total_secs +!
REPEAT
DROP
fileid CLOSE-FILE THROW
;
: .nn ( n -- )
0 <# # # #> TYPE
;
: .time { n secs -- n%secs }
n secs / .nn ':' EMIT
n secs MOD ;
: .track ( -- )
current_secs @ playlist_total_secs @ MOD current_secs !
playlist_file 2@ R/O OPEN-FILE THROW { fileid }
BEGIN
PAD 128 fileid READ-LINE THROW
WHILE
get-secs
current_secs @ OVER < IF
DROP current_secs @
.title CR
3600 .time 60 .time .nn CR
EXIT
ELSE
current_secs @ SWAP - current_secs !
THEN
REPEAT
;
get-args get-playlist-size .track BYE
|