aboutsummaryrefslogtreecommitdiff
path: root/challenge-103/paulo-custodio/forth/ch-2.fs
blob: 584b62a48fbbf80b2edb95ed8c053f5ae53b7038 (plain)
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