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
| #
# api: streamtuner2
# title: Recording timer
# description: Schedules play/record events for bookmarked radio stations.
# type: feature
# category: hook
# depends: kronos, action >= 1.1.1
# version: 0.7.4
# config:
# { name: timer_duration, type: select, select: "auto|streamripper|fpls", value: none, description: support for time ranges }
# priority: optional
# support: unsupported
#
# Provides an internal timer, to configure recording and playback times/intervals
# for stations. It accepts a natural language time string when registering a stream.
#
# Context menu > Extension > Add timer
#
# Programmed events are visible in "timer" under the "bookmarks" channel. Times
# are stored in the description field, and can thus be edited. However, after editing
# times manually, streamtuner2 must be restarted for any changes to take effect.
#
# Allowable time specifications are "Mon,Wed,Fri 18:00-20:00 record"
# or even "Any 7:00-12:00 play". The duration is only honored for
# recording via streamripper or fIcy/fPls currently.
#
from config import *
from channels import *
import bundle.kronos as kronos # Doesn't work with Python3
from uikit import uikit
import action
import copy
import re
| |
|
|
>
|
|
| 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 | # encoding: utf-8
# api: streamtuner2
# title: Recording timer
# description: Schedules play/record events for bookmarked radio stations.
# type: feature
# category: hook
# depends: kronos, action >= 1.1.1
# version: 0.7.5
# config:
# { name: timer_duration, type: select, select: "auto|streamripper|fpls", value: none, description: "Support for time ranges" }
# { name: timer_crontab, type: bool, value: 0, description: "Utilize cron instead of runtime scheduler. (not implemented yet)"}
# priority: optional
# support: basic
#
# Provides an internal timer, to configure recording and playback times/intervals
# for stations. It accepts a natural language time string when registering a stream.
#
# Context menu > Extension > Add timer
#
# Programmed events are visible in "timer" under the "bookmarks" channel. Times
# are stored in the description field, and can thus be edited. However, after editing
# times manually, streamtuner2 must be restarted for any changes to take effect.
#
# Allowable time specifications are "Mon,Wed,Fri 18:00-20:00 record"
# or even "Any 7:00-12:00 play". The duration is only honored for
# recording via streamripper or fIcy/fPls currently.
#
from config import *
from channels import *
import bundle.kronos as kronos # unmaintend pkg, but py3-compatibilized version distributed within bundle/
from uikit import uikit
import action
import copy
import re
|
|
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 | # widgets
uikit.add_signals(parent, {
("timer_ok", "clicked"): self.add_timer,
("timer_cancel", "clicked"): self.hide,
("timer_dialog", "close"): self.hide,
("timer_dialog", "delete-event"): self.hide,
})
# prepare spool
self.sched = kronos.ThreadedScheduler()
for row in self.streams:
try: self.queue(row)
except Exception as e: log.ERR("queuing error", e)
self.sched.start()
|
|
>
>
>
>
>
>
|
| 74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 | # widgets
uikit.add_signals(parent, {
("timer_ok", "clicked"): self.add_timer,
("timer_cancel", "clicked"): self.hide,
("timer_dialog", "close"): self.hide,
("timer_dialog", "delete-event"): self.hide,
})
#-- crontab mode?
# if "timer_crontab" in conf and conf.timer_crontab:
# pass
# elif "timer_crontab_dequeue" in conf:
# pass
#-- prepare scheduler
self.sched = kronos.ThreadedScheduler()
for row in self.streams:
try: self.queue(row)
except Exception as e: log.ERR("queuing error", e)
self.sched.start()
|
|
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129 | def save_timer(self, row):
self.streams.append(row)
self.bookmarks.save()
self.queue(row)
pass
# add event to list
def queue(self, row):
# chk
if not row.get(self.timefield) or not row.get("url"):
#log.DATA("NO TIME DATA", row)
return
|
|
| 122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 | def save_timer(self, row):
self.streams.append(row)
self.bookmarks.save()
self.queue(row)
pass
# Add timer/recording events to scheduler (or later crontab)
def queue(self, row):
# chk
if not row.get(self.timefield) or not row.get("url"):
#log.DATA("NO TIME DATA", row)
return
|
|
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192 | def play(self, row, *args, **kwargs):
action.play(
row = row,
audioformat = row.get("format","audio/mpeg"),
source = row.get("listformat","href")
)
# action wrapper
def record(self, row, *args, **kwargs):
log.TIMER("TIMED RECORD", *args)
# extra params
# make streamripper record a timed broadcast
duration = self.duration(row.get(self.timefield))
append = None |
|
| 185
186
187
188
189
190
191
192
193
194
195
196
197
198
199 | def play(self, row, *args, **kwargs):
action.play(
row = row,
audioformat = row.get("format","audio/mpeg"),
source = row.get("listformat","href")
)
# kronos/sched callback: action wrapper
def record(self, row, *args, **kwargs):
log.TIMER("TIMED RECORD", *args)
# extra params
# make streamripper record a timed broadcast
duration = self.duration(row.get(self.timefield))
append = None |
|
201
202
203
204
205
206
207
208
209
210
211
| action.record(
row = row,
audioformat = row.get("format","audio/mpeg"),
source = row.get("listformat","href"),
append = append,
)
def test(self, row, *args, **kwargs):
log.TEST("KRONOS", row)
|
>
>
>
>
>
>
>
>
>
>
>
> | 208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230 | action.record(
row = row,
audioformat = row.get("format","audio/mpeg"),
source = row.get("listformat","href"),
append = append,
)
# kronos/sched callback for testing
def test(self, row, *args, **kwargs):
log.TEST("KRONOS", row)
# crontab handlers
def cron_queue(self, row):
pass
# crontab cleanup
"""
All streamtuner2 events will be preceded with a `# streamtuner2: …` comment
"""
def cron_dequeue_all(self):
pass
|