Skip to content

Commit

Permalink
feat: Sectional Audio (#2190)
Browse files Browse the repository at this point in the history
* Add Sectional as screen that can play audio.

* Remove Busway exception in Inspector.

* Version bump for screens_config.

* Add now to widget instance struct.

* Only return 2 times if both are < 2 minutes away.

* Change track # readout for bus.

* Fix logic for readouts.

* Always read out train headsigns.

* Address PR feedback.

* Moved now into options list.

* Fix comment.

* Removed unnecessary parameter and made function private.

* Add ID to serialized route pill.

* Improved test.

* Made now it's own required parameter.
  • Loading branch information
cmaddox5 authored Sep 12, 2024
1 parent eb1ee29 commit b0b685c
Show file tree
Hide file tree
Showing 22 changed files with 564 additions and 182 deletions.
36 changes: 5 additions & 31 deletions assets/src/components/admin/inspector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const Inspector: ComponentType = () => {
<ConfigControls screen={screen} />
<ViewControls zoom={zoom} setZoom={setZoom} />
<DataControls sendToFrame={sendToFrame} />
<AudioControls config={config} screen={screen} />
<AudioControls screen={screen} />
</>
)}
</>
Expand Down Expand Up @@ -305,10 +305,7 @@ const DataControls: ComponentType<{
);
};

const AudioControls: ComponentType<{
config: Config;
screen: ScreenWithId;
}> = ({ config, screen }) => {
const AudioControls: ComponentType<{ screen: ScreenWithId }> = ({ screen }) => {
const [isPlaying, setIsPlaying] = useState(false);
const [ssml, setSSML] = useState<string | null>(null);
const dialogRef = useRef<HTMLDialogElement>(null);
Expand All @@ -318,24 +315,9 @@ const AudioControls: ComponentType<{
[dialogRef, ssml],
);

let audioPath: string | null = null;
let v1ScreenId: string | null = null;

if (AUDIO_SCREEN_TYPES.has(screen.config.app_id)) {
// Temporarily special-case Busway screens while V2 doesn't support audio
// yet, in a way that aligns with how they're configured in reality (using
// the audio endpoint of a corresponding V1 screen).
if (screen.config.app_id == "busway_v2") {
const maybeV1Id = screen.id.replace(/-V2$/, "");

if (maybeV1Id != screen.id && config.screens[maybeV1Id]) {
audioPath = `/audio/${maybeV1Id}`;
v1ScreenId = maybeV1Id;
}
} else {
audioPath = `/v2/audio/${screen.id}`;
}
}
const audioPath = AUDIO_SCREEN_TYPES.has(screen.config.app_id)
? `/v2/audio/${screen.id}`
: null;

return (
<fieldset>
Expand All @@ -361,14 +343,6 @@ const AudioControls: ComponentType<{
</button>
</div>

{v1ScreenId && (
<div>
<span>
(from v1 screen <code>{v1ScreenId}</code>)
</span>
</div>
)}

<dialog className="viewer__modal" ref={dialogRef}>
<button
className="viewer__modal__close-button"
Expand Down
4 changes: 2 additions & 2 deletions lib/screens/v2/candidate_generator/bus_eink.ex
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ defmodule Screens.V2.CandidateGenerator.BusEink do
_opts,
now \\ DateTime.utc_now(),
fetch_stop_name_fn \\ &Stop.fetch_stop_name/1,
departures_instances_fn \\ &Widgets.Departures.departures_instances/1,
departures_instances_fn \\ &Widgets.Departures.departures_instances/2,
alert_instances_fn \\ &Widgets.Alerts.alert_instances/1,
evergreen_content_instances_fn \\ &Widgets.Evergreen.evergreen_content_instances/1,
subway_status_instances_fn \\ &Widgets.SubwayStatus.subway_status_instances/2
) do
[
fn -> header_instances(config, now, fetch_stop_name_fn) end,
fn -> departures_instances_fn.(config) end,
fn -> departures_instances_fn.(config, now) end,
fn -> alert_instances_fn.(config) end,
fn -> footer_instances(config) end,
fn -> evergreen_content_instances_fn.(config) end,
Expand Down
4 changes: 2 additions & 2 deletions lib/screens/v2/candidate_generator/bus_shelter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ defmodule Screens.V2.CandidateGenerator.BusShelter do
_opts,
now \\ DateTime.utc_now(),
fetch_stop_name_fn \\ &Stop.fetch_stop_name/1,
departures_instances_fn \\ &Widgets.Departures.departures_instances/1,
departures_instances_fn \\ &Widgets.Departures.departures_instances/2,
alert_instances_fn \\ &Widgets.Alerts.alert_instances/1,
evergreen_content_instances_fn \\ &Widgets.Evergreen.evergreen_content_instances/1,
subway_status_instances_fn \\ &Widgets.SubwayStatus.subway_status_instances/2
) do
[
fn -> header_instances(config, now, fetch_stop_name_fn) end,
fn -> departures_instances_fn.(config) end,
fn -> departures_instances_fn.(config, now) end,
fn -> alert_instances_fn.(config) end,
fn -> footer_instances(config) end,
fn -> subway_status_instances_fn.(config, now) end,
Expand Down
8 changes: 5 additions & 3 deletions lib/screens/v2/candidate_generator/busway.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ defmodule Screens.V2.CandidateGenerator.Busway do
defmodule Deps do
@moduledoc false
defstruct now: &DateTime.utc_now/0,
departures_instances: &Widgets.Departures.departures_instances/1
departures_instances: &Widgets.Departures.departures_instances/2
end

@behaviour CandidateGenerator
Expand All @@ -31,9 +31,11 @@ defmodule Screens.V2.CandidateGenerator.Busway do

@impl CandidateGenerator
def candidate_instances(config, _opts, deps \\ %Deps{}) do
now = deps.now.()

[
fn -> header_instances(config, deps.now.()) end,
fn -> deps.departures_instances.(config) end,
fn -> header_instances(config, now) end,
fn -> deps.departures_instances.(config, now) end,
fn -> placeholder_instances() end
]
|> Task.async_stream(& &1.(), timeout: 15_000)
Expand Down
3 changes: 2 additions & 1 deletion lib/screens/v2/candidate_generator/dup/departures.ex
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.Departures do
%DeparturesWidget{
screen: config,
section_data: sections,
slot_names: [slot_id]
slot_names: [slot_id],
now: now
}
end
end)
Expand Down
4 changes: 3 additions & 1 deletion lib/screens/v2/candidate_generator/gl_eink.ex
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ defmodule Screens.V2.CandidateGenerator.GlEink do
) do
[
fn -> header_instances(config, now, fetch_destination_fn) end,
fn -> departures_instances_fn.(config, post_process_fn: &departures_post_processing/2) end,
fn ->
departures_instances_fn.(config, now, post_process_fn: &departures_post_processing/2)
end,
fn -> alert_instances_fn.(config) end,
fn -> footer_instances(config) end,
fn -> line_map_instances(config, now) end,
Expand Down
4 changes: 2 additions & 2 deletions lib/screens/v2/candidate_generator/solari_large.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ defmodule Screens.V2.CandidateGenerator.SolariLarge do
config,
_opts,
now \\ DateTime.utc_now(),
departures_instances_fn \\ &Widgets.Departures.departures_instances/1
departures_instances_fn \\ &Widgets.Departures.departures_instances/2
) do
[
fn -> header_instances(config, now) end,
fn -> departures_instances_fn.(config) end,
fn -> departures_instances_fn.(config, now) end,
fn -> placeholder_instances() end
]
|> Task.async_stream(& &1.(), timeout: 15_000)
Expand Down
14 changes: 8 additions & 6 deletions lib/screens/v2/candidate_generator/widgets/departures.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ defmodule Screens.V2.CandidateGenerator.Widgets.Departures do
departure_fetch_fn: Departure.fetch(),
disabled_modes_fn: (-> RouteType.t()),
post_process_fn: (Departure.result(), Screen.t() -> Departure.result() | :overnight),
route_fetch_fn: (Route.params() -> {:ok, [Route.t()]} | :error)
route_fetch_fn: (Route.params() -> {:ok, [Route.t()]} | :error),
now: DateTime.t()
]

@type widget ::
Expand All @@ -34,9 +35,8 @@ defmodule Screens.V2.CandidateGenerator.Widgets.Departures do
| DeparturesWidget.t()
| OvernightDepartures.t()

@spec departures_instances(Screen.t()) :: [widget()]
@spec departures_instances(Screen.t(), options()) :: [widget()]
def departures_instances(%Screen{app_params: %app{}} = config, options \\ [])
def departures_instances(%Screen{app_params: %app{}} = config, now, options \\ [])
when app in [BusEink, BusShelter, Busway, GlEink, SolariLarge] do
disabled_modes =
Keyword.get(options, :disabled_modes_fn, &Screens.Config.Cache.disabled_modes/0).()
Expand All @@ -49,7 +49,8 @@ defmodule Screens.V2.CandidateGenerator.Widgets.Departures do
disabled_modes,
Keyword.get(options, :departure_fetch_fn, &Departure.fetch/2),
Keyword.get(options, :post_process_fn, fn results, _config -> results end),
Keyword.get(options, :route_fetch_fn, &Route.fetch/1)
Keyword.get(options, :route_fetch_fn, &Route.fetch/1),
now
)
end
end
Expand All @@ -60,7 +61,8 @@ defmodule Screens.V2.CandidateGenerator.Widgets.Departures do
disabled_modes,
departure_fetch_fn,
post_process_fn,
route_fetch_fn
route_fetch_fn,
now
) do
has_multiple_sections = match?([_, _ | _], sections)

Expand Down Expand Up @@ -102,7 +104,7 @@ defmodule Screens.V2.CandidateGenerator.Widgets.Departures do
}
end)

%DeparturesWidget{screen: config, section_data: sections}
%DeparturesWidget{screen: config, section_data: sections, now: now}
end

[departures_instance]
Expand Down
4 changes: 2 additions & 2 deletions lib/screens/v2/screen_audio_data.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ defmodule Screens.V2.ScreenAudioData do
alias Screens.V2.ScreenData.Parameters
alias Screens.V2.WidgetInstance
alias ScreensConfig.Screen
alias ScreensConfig.V2.{Audio, BusShelter, GlEink, PreFare}
alias ScreensConfig.V2.{Audio, BusShelter, Busway, GlEink, PreFare}

@type screen_id :: String.t()

Expand All @@ -23,7 +23,7 @@ defmodule Screens.V2.ScreenAudioData do
{:ok, now} = DateTime.shift_zone(now, "America/New_York")

case config do
%Screen{app_params: %app{}} when app not in [BusShelter, PreFare, GlEink] ->
%Screen{app_params: %app{}} when app not in [BusShelter, PreFare, GlEink, Busway] ->
:error

%Screen{app_params: %_app{audio: audio}} ->
Expand Down
Loading

0 comments on commit b0b685c

Please sign in to comment.