feat(playout): improve generate_*_events (#2088)
This commit is contained in:
parent
1edd941eb1
commit
510d55c7c1
|
@ -1,4 +1,5 @@
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from operator import itemgetter
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
from dateutil.parser import isoparse
|
from dateutil.parser import isoparse
|
||||||
|
@ -18,6 +19,22 @@ def datetime_to_event_key(value: datetime) -> str:
|
||||||
return value.strftime(EVENT_KEY_FORMAT)
|
return value.strftime(EVENT_KEY_FORMAT)
|
||||||
|
|
||||||
|
|
||||||
|
def insert_event(events: dict, event_key: str, event: dict):
|
||||||
|
key = event_key
|
||||||
|
|
||||||
|
# Search for an empty slot
|
||||||
|
index = 0
|
||||||
|
while key in events:
|
||||||
|
# Ignore duplicate event
|
||||||
|
if event == events[key]:
|
||||||
|
return
|
||||||
|
|
||||||
|
key = f"{event_key}_{index}"
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
events[key] = event
|
||||||
|
|
||||||
|
|
||||||
def get_schedule(api_client: ApiClient):
|
def get_schedule(api_client: ApiClient):
|
||||||
current_time = datetime.utcnow()
|
current_time = datetime.utcnow()
|
||||||
end_time = current_time + timedelta(days=1)
|
end_time = current_time + timedelta(days=1)
|
||||||
|
@ -34,8 +51,8 @@ def get_schedule(api_client: ApiClient):
|
||||||
}
|
}
|
||||||
).json()
|
).json()
|
||||||
|
|
||||||
events = {}
|
events: Dict[str, dict] = {}
|
||||||
for item in schedule:
|
for item in sorted(schedule, key=itemgetter("starts_at")):
|
||||||
item["starts_at"] = isoparse(item["starts_at"])
|
item["starts_at"] = isoparse(item["starts_at"])
|
||||||
item["ends_at"] = isoparse(item["ends_at"])
|
item["ends_at"] = isoparse(item["ends_at"])
|
||||||
|
|
||||||
|
@ -44,29 +61,28 @@ def get_schedule(api_client: ApiClient):
|
||||||
|
|
||||||
if item["file"]:
|
if item["file"]:
|
||||||
file = api_client.get_file(item["file"]).json()
|
file = api_client.get_file(item["file"]).json()
|
||||||
events.update(generate_file_events(item, file, show))
|
generate_file_events(events, item, file, show)
|
||||||
|
|
||||||
elif item["stream"]:
|
elif item["stream"]:
|
||||||
webstream = api_client.get_webstream(item["stream"]).json()
|
webstream = api_client.get_webstream(item["stream"]).json()
|
||||||
events.update(generate_webstream_events(item, webstream, show))
|
generate_webstream_events(events, item, webstream, show)
|
||||||
|
|
||||||
return {"media": events}
|
return {"media": dict(sorted(events.items()))}
|
||||||
|
|
||||||
|
|
||||||
def generate_file_events(
|
def generate_file_events(
|
||||||
|
events: dict,
|
||||||
schedule: dict,
|
schedule: dict,
|
||||||
file: dict,
|
file: dict,
|
||||||
show: dict,
|
show: dict,
|
||||||
) -> Dict[str, dict]:
|
):
|
||||||
"""
|
"""
|
||||||
Generate events for a scheduled file.
|
Generate events for a scheduled file.
|
||||||
"""
|
"""
|
||||||
events = {}
|
|
||||||
|
|
||||||
schedule_start_event_key = datetime_to_event_key(schedule["starts_at"])
|
schedule_start_event_key = datetime_to_event_key(schedule["starts_at"])
|
||||||
schedule_end_event_key = datetime_to_event_key(schedule["ends_at"])
|
schedule_end_event_key = datetime_to_event_key(schedule["ends_at"])
|
||||||
|
|
||||||
events[schedule_start_event_key] = {
|
event = {
|
||||||
"type": EventKind.FILE,
|
"type": EventKind.FILE,
|
||||||
"row_id": schedule["id"],
|
"row_id": schedule["id"],
|
||||||
"start": schedule_start_event_key,
|
"start": schedule_start_event_key,
|
||||||
|
@ -88,24 +104,22 @@ def generate_file_events(
|
||||||
"replay_gain": file["replay_gain"],
|
"replay_gain": file["replay_gain"],
|
||||||
"filesize": file["size"],
|
"filesize": file["size"],
|
||||||
}
|
}
|
||||||
|
insert_event(events, schedule_start_event_key, event)
|
||||||
return events
|
|
||||||
|
|
||||||
|
|
||||||
def generate_webstream_events(
|
def generate_webstream_events(
|
||||||
|
events: dict,
|
||||||
schedule: dict,
|
schedule: dict,
|
||||||
webstream: dict,
|
webstream: dict,
|
||||||
show: dict,
|
show: dict,
|
||||||
) -> Dict[str, dict]:
|
):
|
||||||
"""
|
"""
|
||||||
Generate events for a scheduled webstream.
|
Generate events for a scheduled webstream.
|
||||||
"""
|
"""
|
||||||
events = {}
|
|
||||||
|
|
||||||
schedule_start_event_key = datetime_to_event_key(schedule["starts_at"])
|
schedule_start_event_key = datetime_to_event_key(schedule["starts_at"])
|
||||||
schedule_end_event_key = datetime_to_event_key(schedule["ends_at"])
|
schedule_end_event_key = datetime_to_event_key(schedule["ends_at"])
|
||||||
|
|
||||||
events[schedule_start_event_key] = {
|
stream_buffer_start_event = {
|
||||||
"type": EventKind.STREAM_BUFFER_START,
|
"type": EventKind.STREAM_BUFFER_START,
|
||||||
"row_id": schedule["id"],
|
"row_id": schedule["id"],
|
||||||
"start": datetime_to_event_key(schedule["starts_at"] - timedelta(seconds=5)),
|
"start": datetime_to_event_key(schedule["starts_at"] - timedelta(seconds=5)),
|
||||||
|
@ -113,8 +127,9 @@ def generate_webstream_events(
|
||||||
"uri": webstream["url"],
|
"uri": webstream["url"],
|
||||||
"id": webstream["id"],
|
"id": webstream["id"],
|
||||||
}
|
}
|
||||||
|
insert_event(events, schedule_start_event_key, stream_buffer_start_event)
|
||||||
|
|
||||||
events[f"{schedule_start_event_key}_0"] = {
|
stream_output_start_event = {
|
||||||
"type": EventKind.STREAM_OUTPUT_START,
|
"type": EventKind.STREAM_OUTPUT_START,
|
||||||
"row_id": schedule["id"],
|
"row_id": schedule["id"],
|
||||||
"start": schedule_start_event_key,
|
"start": schedule_start_event_key,
|
||||||
|
@ -124,10 +139,11 @@ def generate_webstream_events(
|
||||||
# Show data
|
# Show data
|
||||||
"show_name": show["name"],
|
"show_name": show["name"],
|
||||||
}
|
}
|
||||||
|
insert_event(events, schedule_start_event_key, stream_output_start_event)
|
||||||
|
|
||||||
# NOTE: stream_*_end were previously triggered 1 second before
|
# NOTE: stream_*_end were previously triggered 1 second before
|
||||||
# the schedule end.
|
# the schedule end.
|
||||||
events[schedule_end_event_key] = {
|
stream_buffer_end_event = {
|
||||||
"type": EventKind.STREAM_BUFFER_END,
|
"type": EventKind.STREAM_BUFFER_END,
|
||||||
"row_id": schedule["id"],
|
"row_id": schedule["id"],
|
||||||
"start": schedule_end_event_key,
|
"start": schedule_end_event_key,
|
||||||
|
@ -135,8 +151,9 @@ def generate_webstream_events(
|
||||||
"uri": webstream["url"],
|
"uri": webstream["url"],
|
||||||
"id": webstream["id"],
|
"id": webstream["id"],
|
||||||
}
|
}
|
||||||
|
insert_event(events, schedule_end_event_key, stream_buffer_end_event)
|
||||||
|
|
||||||
events[f"{schedule_end_event_key}_0"] = {
|
stream_output_end_event = {
|
||||||
"type": EventKind.STREAM_OUTPUT_END,
|
"type": EventKind.STREAM_OUTPUT_END,
|
||||||
"row_id": schedule["id"],
|
"row_id": schedule["id"],
|
||||||
"start": schedule_end_event_key,
|
"start": schedule_end_event_key,
|
||||||
|
@ -144,5 +161,4 @@ def generate_webstream_events(
|
||||||
"uri": webstream["url"],
|
"uri": webstream["url"],
|
||||||
"id": webstream["id"],
|
"id": webstream["id"],
|
||||||
}
|
}
|
||||||
|
insert_event(events, schedule_end_event_key, stream_output_end_event)
|
||||||
return events
|
|
||||||
|
|
|
@ -1,141 +1,585 @@
|
||||||
|
import random
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from dateutil.parser import isoparse
|
||||||
from libretime_api_client.v2 import ApiClient
|
from libretime_api_client.v2 import ApiClient
|
||||||
|
|
||||||
from libretime_playout.player.schedule import get_schedule
|
from libretime_playout.player.events import EventKind
|
||||||
|
from libretime_playout.player.schedule import (
|
||||||
|
generate_file_events,
|
||||||
|
generate_webstream_events,
|
||||||
|
get_schedule,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="api_client_mock")
|
@pytest.fixture(name="api_client")
|
||||||
def _api_client_mock(requests_mock):
|
def _api_client_fixture():
|
||||||
base_url = "http://localhost"
|
base_url = "http://localhost"
|
||||||
api_client = ApiClient(base_url=base_url, api_key="test_key")
|
return ApiClient(base_url=base_url, api_key="test_key")
|
||||||
|
|
||||||
requests_mock.get(
|
|
||||||
f"{base_url}/api/v2/schedule",
|
SHOW_1 = {"id": 1, "name": "Show 1"}
|
||||||
json=[
|
SHOW_2 = {"id": 2, "name": "Show 2"}
|
||||||
{
|
SHOW_3 = {"id": 3, "name": "Show 3"}
|
||||||
"id": 17,
|
SHOW_4 = {"id": 4, "name": "Show 4"}
|
||||||
"starts_at": "2022-03-04T15:30:00Z",
|
|
||||||
"ends_at": "2022-03-04T15:33:50.674340Z",
|
SHOW_INSTANCE_1 = {
|
||||||
"file": 1,
|
"id": 1,
|
||||||
"stream": None,
|
"starts_at": "2022-09-05T11:00:00Z",
|
||||||
"fade_in": "00:00:00.500000",
|
"ends_at": "2022-09-05T11:10:00Z",
|
||||||
"fade_out": "00:00:00.500000",
|
"show": 1,
|
||||||
"cue_in": "00:00:01.310660",
|
}
|
||||||
"cue_out": "00:03:51.985000",
|
SHOW_INSTANCE_2 = {
|
||||||
"instance": 3,
|
"id": 2,
|
||||||
|
"starts_at": "2022-09-05T11:10:00Z",
|
||||||
|
"ends_at": "2022-09-05T12:10:00Z",
|
||||||
|
"show": 2,
|
||||||
|
}
|
||||||
|
SHOW_INSTANCE_3 = {
|
||||||
|
"id": 3,
|
||||||
|
"starts_at": "2022-09-05T12:10:00Z",
|
||||||
|
"ends_at": "2022-09-05T13:00:00Z",
|
||||||
|
"show": 3,
|
||||||
|
}
|
||||||
|
SHOW_INSTANCE_4 = {
|
||||||
|
"id": 4,
|
||||||
|
"starts_at": "2022-09-05T13:00:00Z",
|
||||||
|
"ends_at": "2022-09-05T14:10:00Z",
|
||||||
|
"show": 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE_1 = {
|
||||||
|
"id": 1,
|
||||||
|
"mime": "audio/flac",
|
||||||
|
"length": "00:03:41.041723",
|
||||||
|
"replay_gain": "4.52",
|
||||||
|
"cue_in": "00:00:08.252450",
|
||||||
|
"cue_out": "00:03:27.208000",
|
||||||
|
"artist_name": "Nils Frahm",
|
||||||
|
"album_title": "Tripping with Nils Frahm",
|
||||||
|
"track_title": "The Dane",
|
||||||
|
"url": None,
|
||||||
|
"size": 10000,
|
||||||
|
}
|
||||||
|
FILE_2 = {
|
||||||
|
"id": 2,
|
||||||
|
"mime": "audio/flac",
|
||||||
|
"length": "00:06:08.668798",
|
||||||
|
"replay_gain": "11.46",
|
||||||
|
"cue_in": "00:00:13.700800",
|
||||||
|
"cue_out": "00:05:15.845000",
|
||||||
|
"artist_name": "Nils Frahm",
|
||||||
|
"album_title": "Tripping with Nils Frahm",
|
||||||
|
"track_title": "My Friend the Forest",
|
||||||
|
"url": None,
|
||||||
|
"size": 10000,
|
||||||
|
}
|
||||||
|
FILE_3 = {
|
||||||
|
"id": 3,
|
||||||
|
"mime": "audio/flac",
|
||||||
|
"length": "00:14:18.400000",
|
||||||
|
"replay_gain": "-2.13",
|
||||||
|
"cue_in": "00:00:55.121100",
|
||||||
|
"cue_out": "00:14:18.400000",
|
||||||
|
"artist_name": "Nils Frahm",
|
||||||
|
"album_title": "Tripping with Nils Frahm",
|
||||||
|
"track_title": "All Melody",
|
||||||
|
"url": None,
|
||||||
|
"size": 10000,
|
||||||
|
}
|
||||||
|
FILE_4 = {
|
||||||
|
"id": 4,
|
||||||
|
"mime": "audio/flac",
|
||||||
|
"length": "00:10:45.472200",
|
||||||
|
"replay_gain": "-1.65",
|
||||||
|
"cue_in": "00:00:00",
|
||||||
|
"cue_out": "00:10:26.891000",
|
||||||
|
"artist_name": "Nils Frahm",
|
||||||
|
"album_title": "Tripping with Nils Frahm",
|
||||||
|
"track_title": "#2",
|
||||||
|
"url": None,
|
||||||
|
"size": 10000,
|
||||||
|
}
|
||||||
|
FILE_5 = {
|
||||||
|
"id": 5,
|
||||||
|
"mime": "audio/mp3",
|
||||||
|
"length": "00:59:04.989000",
|
||||||
|
"replay_gain": "-1.39",
|
||||||
|
"cue_in": "00:00:00",
|
||||||
|
"cue_out": "00:58:59.130000",
|
||||||
|
"artist_name": "Democracy Now! Audio",
|
||||||
|
"album_title": "Democracy Now! Audio",
|
||||||
|
"track_title": "Democracy Now! 2022-09-05 Monday",
|
||||||
|
"url": None,
|
||||||
|
"size": 10000,
|
||||||
|
}
|
||||||
|
|
||||||
|
WEBSTREAM_1 = {
|
||||||
|
"id": 1,
|
||||||
|
"name": "External radio",
|
||||||
|
"url": "http://stream.radio.org/main.ogg",
|
||||||
|
}
|
||||||
|
|
||||||
|
SCHEDULE_1 = {
|
||||||
|
"id": 1,
|
||||||
|
"starts_at": "2022-09-05T11:00:00Z",
|
||||||
|
"ends_at": "2022-09-05T11:05:02.144200Z",
|
||||||
|
"cue_in": "00:00:13.700800",
|
||||||
|
"cue_out": "00:05:15.845000",
|
||||||
|
"fade_in": "00:00:00.500000",
|
||||||
|
"fade_out": "00:00:00.500000",
|
||||||
|
"file": 2,
|
||||||
|
"instance": 1,
|
||||||
|
"length": "00:05:02.144200",
|
||||||
|
"stream": None,
|
||||||
|
}
|
||||||
|
SCHEDULE_2 = {
|
||||||
|
"id": 2,
|
||||||
|
"starts_at": "2022-09-05T11:05:02.144200Z",
|
||||||
|
"ends_at": "2022-09-05T11:10:00Z",
|
||||||
|
"cue_in": "00:00:00",
|
||||||
|
"cue_out": "00:04:57.855800",
|
||||||
|
"fade_in": "00:00:00.500000",
|
||||||
|
"fade_out": "00:00:00.500000",
|
||||||
|
"file": 4,
|
||||||
|
"instance": 1,
|
||||||
|
"length": "00:10:26.891000",
|
||||||
|
"stream": None,
|
||||||
|
}
|
||||||
|
SCHEDULE_3 = {
|
||||||
|
"id": 3,
|
||||||
|
"starts_at": "2022-09-05T11:10:00Z",
|
||||||
|
"ends_at": "2022-09-05T12:08:59Z",
|
||||||
|
"cue_in": "00:00:00",
|
||||||
|
"cue_out": "00:58:59.130000",
|
||||||
|
"fade_in": "00:00:00.500000",
|
||||||
|
"fade_out": "00:00:00.500000",
|
||||||
|
"file": 5,
|
||||||
|
"instance": 2,
|
||||||
|
"length": "00:58:59.130000",
|
||||||
|
"stream": None,
|
||||||
|
}
|
||||||
|
SCHEDULE_4 = {
|
||||||
|
"id": 4,
|
||||||
|
"starts_at": "2022-09-05T12:08:59Z",
|
||||||
|
"ends_at": "2022-09-05T12:10:00Z",
|
||||||
|
"cue_in": "00:00:00",
|
||||||
|
"cue_out": "00:01:01",
|
||||||
|
"fade_in": "00:00:00.500000",
|
||||||
|
"fade_out": "00:00:00.500000",
|
||||||
|
"file": 4,
|
||||||
|
"instance": 2,
|
||||||
|
"length": "00:10:26.891000",
|
||||||
|
"stream": None,
|
||||||
|
}
|
||||||
|
SCHEDULE_5 = {
|
||||||
|
"id": 5,
|
||||||
|
"starts_at": "2022-09-05T12:10:00Z",
|
||||||
|
"ends_at": "2022-09-05T12:40:00Z",
|
||||||
|
"cue_in": "00:00:00",
|
||||||
|
"cue_out": "00:30:00",
|
||||||
|
"fade_in": "00:00:00.500000",
|
||||||
|
"fade_out": "00:00:00.500000",
|
||||||
|
"file": None,
|
||||||
|
"instance": 3,
|
||||||
|
"length": "00:30:00",
|
||||||
|
"stream": 1,
|
||||||
|
}
|
||||||
|
SCHEDULE_6 = {
|
||||||
|
"id": 6,
|
||||||
|
"starts_at": "2022-09-05T12:40:00Z",
|
||||||
|
"ends_at": "2022-09-05T12:53:23Z",
|
||||||
|
"cue_in": "00:00:55.121100",
|
||||||
|
"cue_out": "00:14:18.400000",
|
||||||
|
"fade_in": "00:00:00.500000",
|
||||||
|
"fade_out": "00:00:00.500000",
|
||||||
|
"file": 3,
|
||||||
|
"instance": 3,
|
||||||
|
"length": "00:13:23.278900",
|
||||||
|
"stream": None,
|
||||||
|
}
|
||||||
|
SCHEDULE_7 = {
|
||||||
|
"id": 7,
|
||||||
|
"starts_at": "2022-09-05T12:53:23Z",
|
||||||
|
"ends_at": "2022-09-05T12:58:25Z",
|
||||||
|
"cue_in": "00:00:13.700800",
|
||||||
|
"cue_out": "00:05:15.845000",
|
||||||
|
"fade_in": "00:00:00.500000",
|
||||||
|
"fade_out": "00:00:00.500000",
|
||||||
|
"file": 2,
|
||||||
|
"instance": 3,
|
||||||
|
"length": "00:05:02.144200",
|
||||||
|
"stream": None,
|
||||||
|
}
|
||||||
|
SCHEDULE_8 = {
|
||||||
|
"id": 8,
|
||||||
|
"starts_at": "2022-09-05T12:58:25Z",
|
||||||
|
"ends_at": "2022-09-05T13:00:00Z",
|
||||||
|
"cue_in": "00:00:08.252450",
|
||||||
|
"cue_out": "00:01:35",
|
||||||
|
"fade_in": "00:00:00.500000",
|
||||||
|
"fade_out": "00:00:00.500000",
|
||||||
|
"file": 1,
|
||||||
|
"instance": 3,
|
||||||
|
"length": "00:03:18.955550",
|
||||||
|
"stream": None,
|
||||||
|
}
|
||||||
|
SCHEDULE_9 = {
|
||||||
|
"id": 9,
|
||||||
|
"starts_at": "2022-09-05T13:00:00Z",
|
||||||
|
"ends_at": "2022-09-05T13:05:02.144200Z",
|
||||||
|
"cue_in": "00:00:13.700800",
|
||||||
|
"cue_out": "00:05:15.845000",
|
||||||
|
"fade_in": "00:00:00.500000",
|
||||||
|
"fade_out": "00:00:00.500000",
|
||||||
|
"file": 2,
|
||||||
|
"instance": 4,
|
||||||
|
"length": "00:05:02.144200",
|
||||||
|
"stream": None,
|
||||||
|
}
|
||||||
|
SCHEDULE_10 = {
|
||||||
|
"id": 10,
|
||||||
|
"starts_at": "2022-09-05T13:05:02.144200Z",
|
||||||
|
"ends_at": "2022-09-05T13:10:00Z",
|
||||||
|
"cue_in": "00:00:00",
|
||||||
|
"cue_out": "00:04:57.855800",
|
||||||
|
"fade_in": "00:00:00.500000",
|
||||||
|
"fade_out": "00:00:00.500000",
|
||||||
|
"file": 4,
|
||||||
|
"instance": 4,
|
||||||
|
"length": "00:10:26.891000",
|
||||||
|
"stream": None,
|
||||||
|
}
|
||||||
|
SCHEDULE = [
|
||||||
|
SCHEDULE_1,
|
||||||
|
SCHEDULE_2,
|
||||||
|
SCHEDULE_3,
|
||||||
|
SCHEDULE_4,
|
||||||
|
SCHEDULE_5,
|
||||||
|
SCHEDULE_6,
|
||||||
|
SCHEDULE_7,
|
||||||
|
SCHEDULE_8,
|
||||||
|
SCHEDULE_9,
|
||||||
|
SCHEDULE_10,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_generate_file_events():
|
||||||
|
schedule_1 = SCHEDULE_1.copy()
|
||||||
|
schedule_1["starts_at"] = isoparse(schedule_1["starts_at"])
|
||||||
|
schedule_1["ends_at"] = isoparse(schedule_1["ends_at"])
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
generate_file_events(result, schedule_1, FILE_2, SHOW_1)
|
||||||
|
assert result == {
|
||||||
|
"2022-09-05-11-00-00": {
|
||||||
|
"type": EventKind.FILE,
|
||||||
|
"row_id": 1,
|
||||||
|
"start": "2022-09-05-11-00-00",
|
||||||
|
"end": "2022-09-05-11-05-02",
|
||||||
|
"uri": None,
|
||||||
|
"id": 2,
|
||||||
|
"show_name": "Show 1",
|
||||||
|
"fade_in": 500.0,
|
||||||
|
"fade_out": 500.0,
|
||||||
|
"cue_in": 13.7008,
|
||||||
|
"cue_out": 315.845,
|
||||||
|
"metadata": {
|
||||||
|
"track_title": "My Friend the Forest",
|
||||||
|
"artist_name": "Nils Frahm",
|
||||||
|
"mime": "audio/flac",
|
||||||
},
|
},
|
||||||
{
|
"replay_gain": "11.46",
|
||||||
"id": 18,
|
"filesize": 10000,
|
||||||
"starts_at": "2022-03-04T15:33:50.674340Z",
|
}
|
||||||
"ends_at": "2022-03-04T16:03:50.674340Z",
|
}
|
||||||
"file": None,
|
|
||||||
"stream": 1,
|
|
||||||
"fade_in": "00:00:00.500000",
|
|
||||||
"fade_out": "00:00:00.500000",
|
|
||||||
"cue_in": "00:00:00",
|
|
||||||
"cue_out": "00:30:00",
|
|
||||||
"instance": 3,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
requests_mock.get(
|
|
||||||
f"{base_url}/api/v2/show-instances/3",
|
|
||||||
json={
|
|
||||||
"show": 3,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
requests_mock.get(
|
def test_generate_webstream_events():
|
||||||
f"{base_url}/api/v2/shows/3",
|
schedule_5 = SCHEDULE_5.copy()
|
||||||
json={
|
schedule_5["starts_at"] = isoparse(schedule_5["starts_at"])
|
||||||
"name": "Test",
|
schedule_5["ends_at"] = isoparse(schedule_5["ends_at"])
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
requests_mock.get(
|
result = {}
|
||||||
f"{base_url}/api/v2/files/1",
|
generate_webstream_events(result, schedule_5, WEBSTREAM_1, SHOW_3)
|
||||||
json={
|
assert result == {
|
||||||
|
"2022-09-05-12-10-00": {
|
||||||
|
"type": EventKind.STREAM_BUFFER_START,
|
||||||
|
"row_id": 5,
|
||||||
|
"start": "2022-09-05-12-09-55",
|
||||||
|
"end": "2022-09-05-12-09-55",
|
||||||
|
"uri": "http://stream.radio.org/main.ogg",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"url": None,
|
|
||||||
"replay_gain": "-8.77",
|
|
||||||
"size": 9505222,
|
|
||||||
"artist_name": "Bag Raiders",
|
|
||||||
"track_title": "Shooting Stars",
|
|
||||||
"mime": "audio/mp3",
|
|
||||||
},
|
},
|
||||||
)
|
"2022-09-05-12-10-00_0": {
|
||||||
|
"type": EventKind.STREAM_OUTPUT_START,
|
||||||
requests_mock.get(
|
"row_id": 5,
|
||||||
f"{base_url}/api/v2/webstreams/1",
|
"start": "2022-09-05-12-10-00",
|
||||||
json={
|
"end": "2022-09-05-12-40-00",
|
||||||
|
"uri": "http://stream.radio.org/main.ogg",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"name": "Test",
|
"show_name": "Show 3",
|
||||||
"url": "http://some-other-radio:8800/main.ogg",
|
|
||||||
},
|
},
|
||||||
)
|
"2022-09-05-12-40-00": {
|
||||||
|
"type": EventKind.STREAM_BUFFER_END,
|
||||||
return api_client
|
"row_id": 5,
|
||||||
|
"start": "2022-09-05-12-40-00",
|
||||||
|
"end": "2022-09-05-12-40-00",
|
||||||
|
"uri": "http://stream.radio.org/main.ogg",
|
||||||
|
"id": 1,
|
||||||
|
},
|
||||||
|
"2022-09-05-12-40-00_0": {
|
||||||
|
"type": EventKind.STREAM_OUTPUT_END,
|
||||||
|
"row_id": 5,
|
||||||
|
"start": "2022-09-05-12-40-00",
|
||||||
|
"end": "2022-09-05-12-40-00",
|
||||||
|
"uri": "http://stream.radio.org/main.ogg",
|
||||||
|
"id": 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_get_schedule(api_client_mock: ApiClient):
|
@pytest.mark.parametrize(
|
||||||
assert get_schedule(api_client_mock) == {
|
"schedule",
|
||||||
|
[
|
||||||
|
(SCHEDULE),
|
||||||
|
(random.sample(SCHEDULE, len(SCHEDULE))),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_get_schedule(schedule, requests_mock, api_client: ApiClient):
|
||||||
|
base_url = api_client.base_url
|
||||||
|
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/schedule", json=schedule)
|
||||||
|
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/shows/1", json=SHOW_1)
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/shows/2", json=SHOW_2)
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/shows/3", json=SHOW_3)
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/shows/4", json=SHOW_4)
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/show-instances/1", json=SHOW_INSTANCE_1)
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/show-instances/2", json=SHOW_INSTANCE_2)
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/show-instances/3", json=SHOW_INSTANCE_3)
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/show-instances/4", json=SHOW_INSTANCE_4)
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/files/1", json=FILE_1)
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/files/2", json=FILE_2)
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/files/3", json=FILE_3)
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/files/4", json=FILE_4)
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/files/5", json=FILE_5)
|
||||||
|
requests_mock.get(f"{base_url}/api/v2/webstreams/1", json=WEBSTREAM_1)
|
||||||
|
|
||||||
|
assert get_schedule(api_client) == {
|
||||||
"media": {
|
"media": {
|
||||||
"2022-03-04-15-30-00": {
|
"2022-09-05-11-00-00": {
|
||||||
"type": "file",
|
"type": EventKind.FILE,
|
||||||
"row_id": 17,
|
"row_id": 1,
|
||||||
"start": "2022-03-04-15-30-00",
|
"start": "2022-09-05-11-00-00",
|
||||||
"end": "2022-03-04-15-33-50",
|
"end": "2022-09-05-11-05-02",
|
||||||
# NOTE: The legacy schedule generator creates an url,
|
|
||||||
# but playout download the file using the file id, so
|
|
||||||
# we can safely ignore it here.
|
|
||||||
"uri": None,
|
"uri": None,
|
||||||
"id": 1,
|
"id": 2,
|
||||||
"show_name": "Test",
|
"show_name": "Show 1",
|
||||||
"fade_in": 500.0,
|
"fade_in": 500.0,
|
||||||
"fade_out": 500.0,
|
"fade_out": 500.0,
|
||||||
"cue_in": 1.31066,
|
"cue_in": 13.7008,
|
||||||
"cue_out": 231.985,
|
"cue_out": 315.845,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"artist_name": "Bag Raiders",
|
"track_title": "My Friend the Forest",
|
||||||
"track_title": "Shooting Stars",
|
"artist_name": "Nils Frahm",
|
||||||
|
"mime": "audio/flac",
|
||||||
|
},
|
||||||
|
"replay_gain": "11.46",
|
||||||
|
"filesize": 10000,
|
||||||
|
},
|
||||||
|
"2022-09-05-11-05-02": {
|
||||||
|
"type": EventKind.FILE,
|
||||||
|
"row_id": 2,
|
||||||
|
"start": "2022-09-05-11-05-02",
|
||||||
|
"end": "2022-09-05-11-10-00",
|
||||||
|
"uri": None,
|
||||||
|
"id": 4,
|
||||||
|
"show_name": "Show 1",
|
||||||
|
"fade_in": 500.0,
|
||||||
|
"fade_out": 500.0,
|
||||||
|
"cue_in": 0.0,
|
||||||
|
"cue_out": 297.8558,
|
||||||
|
"metadata": {
|
||||||
|
"track_title": "#2",
|
||||||
|
"artist_name": "Nils Frahm",
|
||||||
|
"mime": "audio/flac",
|
||||||
|
},
|
||||||
|
"replay_gain": "-1.65",
|
||||||
|
"filesize": 10000,
|
||||||
|
},
|
||||||
|
"2022-09-05-11-10-00": {
|
||||||
|
"type": EventKind.FILE,
|
||||||
|
"row_id": 3,
|
||||||
|
"start": "2022-09-05-11-10-00",
|
||||||
|
"end": "2022-09-05-12-08-59",
|
||||||
|
"uri": None,
|
||||||
|
"id": 5,
|
||||||
|
"show_name": "Show 2",
|
||||||
|
"fade_in": 500.0,
|
||||||
|
"fade_out": 500.0,
|
||||||
|
"cue_in": 0.0,
|
||||||
|
"cue_out": 3539.13,
|
||||||
|
"metadata": {
|
||||||
|
"track_title": "Democracy Now! 2022-09-05 Monday",
|
||||||
|
"artist_name": "Democracy Now! Audio",
|
||||||
"mime": "audio/mp3",
|
"mime": "audio/mp3",
|
||||||
},
|
},
|
||||||
"replay_gain": "-8.77",
|
"replay_gain": "-1.39",
|
||||||
"filesize": 9505222,
|
"filesize": 10000,
|
||||||
},
|
},
|
||||||
"2022-03-04-15-33-50": {
|
"2022-09-05-12-08-59": {
|
||||||
"type": "stream_buffer_start",
|
"type": EventKind.FILE,
|
||||||
"row_id": 18,
|
"row_id": 4,
|
||||||
"start": "2022-03-04-15-33-45",
|
"start": "2022-09-05-12-08-59",
|
||||||
"end": "2022-03-04-15-33-45",
|
"end": "2022-09-05-12-10-00",
|
||||||
"uri": "http://some-other-radio:8800/main.ogg",
|
"uri": None,
|
||||||
|
"id": 4,
|
||||||
|
"show_name": "Show 2",
|
||||||
|
"fade_in": 500.0,
|
||||||
|
"fade_out": 500.0,
|
||||||
|
"cue_in": 0.0,
|
||||||
|
"cue_out": 61.0,
|
||||||
|
"metadata": {
|
||||||
|
"track_title": "#2",
|
||||||
|
"artist_name": "Nils Frahm",
|
||||||
|
"mime": "audio/flac",
|
||||||
|
},
|
||||||
|
"replay_gain": "-1.65",
|
||||||
|
"filesize": 10000,
|
||||||
|
},
|
||||||
|
"2022-09-05-12-10-00": {
|
||||||
|
"type": EventKind.STREAM_BUFFER_START,
|
||||||
|
"row_id": 5,
|
||||||
|
"start": "2022-09-05-12-09-55",
|
||||||
|
"end": "2022-09-05-12-09-55",
|
||||||
|
"uri": "http://stream.radio.org/main.ogg",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
},
|
},
|
||||||
"2022-03-04-15-33-50_0": {
|
"2022-09-05-12-10-00_0": {
|
||||||
"type": "stream_output_start",
|
"type": EventKind.STREAM_OUTPUT_START,
|
||||||
"row_id": 18,
|
"row_id": 5,
|
||||||
"start": "2022-03-04-15-33-50",
|
"start": "2022-09-05-12-10-00",
|
||||||
"end": "2022-03-04-16-03-50",
|
"end": "2022-09-05-12-40-00",
|
||||||
"uri": "http://some-other-radio:8800/main.ogg",
|
"uri": "http://stream.radio.org/main.ogg",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"show_name": "Test",
|
"show_name": "Show 3",
|
||||||
},
|
},
|
||||||
"2022-03-04-16-03-50": {
|
"2022-09-05-12-40-00": {
|
||||||
"type": "stream_buffer_end",
|
"type": EventKind.STREAM_BUFFER_END,
|
||||||
"row_id": 18,
|
"row_id": 5,
|
||||||
"start": "2022-03-04-16-03-50",
|
"start": "2022-09-05-12-40-00",
|
||||||
"end": "2022-03-04-16-03-50",
|
"end": "2022-09-05-12-40-00",
|
||||||
"uri": "http://some-other-radio:8800/main.ogg",
|
"uri": "http://stream.radio.org/main.ogg",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
},
|
},
|
||||||
"2022-03-04-16-03-50_0": {
|
"2022-09-05-12-40-00_0": {
|
||||||
"type": "stream_output_end",
|
"type": EventKind.STREAM_OUTPUT_END,
|
||||||
"row_id": 18,
|
"row_id": 5,
|
||||||
"start": "2022-03-04-16-03-50",
|
"start": "2022-09-05-12-40-00",
|
||||||
"end": "2022-03-04-16-03-50",
|
"end": "2022-09-05-12-40-00",
|
||||||
"uri": "http://some-other-radio:8800/main.ogg",
|
"uri": "http://stream.radio.org/main.ogg",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
},
|
},
|
||||||
|
"2022-09-05-12-40-00_1": {
|
||||||
|
"type": EventKind.FILE,
|
||||||
|
"row_id": 6,
|
||||||
|
"start": "2022-09-05-12-40-00",
|
||||||
|
"end": "2022-09-05-12-53-23",
|
||||||
|
"uri": None,
|
||||||
|
"id": 3,
|
||||||
|
"show_name": "Show 3",
|
||||||
|
"fade_in": 500.0,
|
||||||
|
"fade_out": 500.0,
|
||||||
|
"cue_in": 55.1211,
|
||||||
|
"cue_out": 858.4,
|
||||||
|
"metadata": {
|
||||||
|
"track_title": "All Melody",
|
||||||
|
"artist_name": "Nils Frahm",
|
||||||
|
"mime": "audio/flac",
|
||||||
|
},
|
||||||
|
"replay_gain": "-2.13",
|
||||||
|
"filesize": 10000,
|
||||||
|
},
|
||||||
|
"2022-09-05-12-53-23": {
|
||||||
|
"type": EventKind.FILE,
|
||||||
|
"row_id": 7,
|
||||||
|
"start": "2022-09-05-12-53-23",
|
||||||
|
"end": "2022-09-05-12-58-25",
|
||||||
|
"uri": None,
|
||||||
|
"id": 2,
|
||||||
|
"show_name": "Show 3",
|
||||||
|
"fade_in": 500.0,
|
||||||
|
"fade_out": 500.0,
|
||||||
|
"cue_in": 13.7008,
|
||||||
|
"cue_out": 315.845,
|
||||||
|
"metadata": {
|
||||||
|
"track_title": "My Friend the Forest",
|
||||||
|
"artist_name": "Nils Frahm",
|
||||||
|
"mime": "audio/flac",
|
||||||
|
},
|
||||||
|
"replay_gain": "11.46",
|
||||||
|
"filesize": 10000,
|
||||||
|
},
|
||||||
|
"2022-09-05-12-58-25": {
|
||||||
|
"type": EventKind.FILE,
|
||||||
|
"row_id": 8,
|
||||||
|
"start": "2022-09-05-12-58-25",
|
||||||
|
"end": "2022-09-05-13-00-00",
|
||||||
|
"uri": None,
|
||||||
|
"id": 1,
|
||||||
|
"show_name": "Show 3",
|
||||||
|
"fade_in": 500.0,
|
||||||
|
"fade_out": 500.0,
|
||||||
|
"cue_in": 8.25245,
|
||||||
|
"cue_out": 95.0,
|
||||||
|
"metadata": {
|
||||||
|
"track_title": "The Dane",
|
||||||
|
"artist_name": "Nils Frahm",
|
||||||
|
"mime": "audio/flac",
|
||||||
|
},
|
||||||
|
"replay_gain": "4.52",
|
||||||
|
"filesize": 10000,
|
||||||
|
},
|
||||||
|
"2022-09-05-13-00-00": {
|
||||||
|
"type": EventKind.FILE,
|
||||||
|
"row_id": 9,
|
||||||
|
"start": "2022-09-05-13-00-00",
|
||||||
|
"end": "2022-09-05-13-05-02",
|
||||||
|
"uri": None,
|
||||||
|
"id": 2,
|
||||||
|
"show_name": "Show 4",
|
||||||
|
"fade_in": 500.0,
|
||||||
|
"fade_out": 500.0,
|
||||||
|
"cue_in": 13.7008,
|
||||||
|
"cue_out": 315.845,
|
||||||
|
"metadata": {
|
||||||
|
"track_title": "My Friend the Forest",
|
||||||
|
"artist_name": "Nils Frahm",
|
||||||
|
"mime": "audio/flac",
|
||||||
|
},
|
||||||
|
"replay_gain": "11.46",
|
||||||
|
"filesize": 10000,
|
||||||
|
},
|
||||||
|
"2022-09-05-13-05-02": {
|
||||||
|
"type": EventKind.FILE,
|
||||||
|
"row_id": 10,
|
||||||
|
"start": "2022-09-05-13-05-02",
|
||||||
|
"end": "2022-09-05-13-10-00",
|
||||||
|
"uri": None,
|
||||||
|
"id": 4,
|
||||||
|
"show_name": "Show 4",
|
||||||
|
"fade_in": 500.0,
|
||||||
|
"fade_out": 500.0,
|
||||||
|
"cue_in": 0.0,
|
||||||
|
"cue_out": 297.8558,
|
||||||
|
"metadata": {
|
||||||
|
"track_title": "#2",
|
||||||
|
"artist_name": "Nils Frahm",
|
||||||
|
"mime": "audio/flac",
|
||||||
|
},
|
||||||
|
"replay_gain": "-1.65",
|
||||||
|
"filesize": 10000,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue