Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,38 @@ GreenOvercast is experimental.
| B | Back or cancel | Xbox B |
| X | Search or delete a letter | Xbox X |
| Y | Favorite a game or clear search | Xbox Y |
| L1 / R1 | Switch All / Favorites | Xbox LB / RB |
| L1 / R1 | Switch All / Favorites / Consoles | Xbox LB / RB |
| L2 / R2 | Jump by first letter | Xbox LT / RT |
| Start | Settings or apply search | Xbox Menu |
| Select | — | Xbox View |
| L3 + R3 | — | Xbox Guide |
| Select + Start | Exit after holding for one second | Exit after holding for one second |

Settings include Xbox/Nintendo face-button layouts, game artwork, and Sign
out. Games that return a 16:9 stream remain letterboxed on 4:3 displays.
Settings include Xbox/Nintendo face-button layouts, game artwork, the video
decoder, video smoothing, and Sign out. Games that return a 16:9 stream remain
letterboxed on 4:3 displays.

The **video decoder** can be switched from Auto to Software. On some streams
the Cedar hardware decoder leaves blocky artifacts on the right side of the
picture; software decoding avoids them at the cost of CPU time. **Smooth video**
keeps a second frame queued so bursts of decoded frames are not dropped, at the
cost of up to one frame of extra latency.

## Home streaming

Besides Xbox Cloud Gaming, GreenOvercast can stream from your own Xbox console
(Xbox remote play, "xHome"). It uses the same WebRTC and hardware-decode
pipeline, so cloud streaming is unchanged.

When your account has a console, a **CONSOLES** tab appears next to Favorites.
Switch to it with L1 / R1, pick your console, and press A. The console must be
on, with remote play enabled in its settings. The list shows each console's
power state. Tested with an Xbox Series X on the local network.

Home streaming needs no extra sign-in: it reuses the cloud login.

If a game that was already running when you connected ignores the controller,
close it on the console and start it again from the stream.

## Supported devices

Expand Down
47 changes: 30 additions & 17 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const release_zig_roots = [_]struct {
.path = "src/session/cloud_session.zig",
.imports = &.{.{ .name = "json_reader", .path = "src/net/json_reader.zig" }},
},
.{ .name = "greenovercast-consoles", .path = "src/catalog/consoles.zig" },
.{
.name = "greenovercast-webrtc",
.path = "src/session/webrtc_session.zig",
Expand Down Expand Up @@ -457,29 +458,41 @@ pub fn build(b: *std.Build) void {
rocknix_build_regression_test.setCwd(b.path("."));
test_step.dependOn(&rocknix_build_regression_test.step);

const test_roots = [_][]const u8{
"src/app/state.zig",
"src/catalog/catalog_parser.zig",
"src/catalog/catalog_search.zig",
"src/input/wire_encoder.zig",
"src/input/guide_chord.zig",
"src/session/message_protocol.zig",
"src/ui/keyboard.zig",
"src/ui/control_icons.zig",
"src/ui/navigation_repeat.zig",
"src/ui/persistent_settings.zig",
"src/ui/stream_dimensions.zig",
"src/media/rtp/h264_depacketizer.zig",
"src/net/json_reader.zig",
"src/net/json_writer.zig",
"src/net/form_writer.zig",
const test_roots = [_]struct {
path: []const u8,
imports: []const ZigImport = &.{},
}{
.{ .path = "src/app/state.zig" },
.{ .path = "src/catalog/catalog_parser.zig" },
.{ .path = "src/catalog/catalog_search.zig" },
.{ .path = "src/catalog/consoles_parser.zig" },
.{ .path = "src/input/wire_encoder.zig" },
.{ .path = "src/input/guide_chord.zig" },
.{ .path = "src/session/message_protocol.zig" },
.{ .path = "src/ui/keyboard.zig" },
.{ .path = "src/ui/control_icons.zig" },
.{ .path = "src/ui/navigation_repeat.zig" },
.{
.path = "src/ui/library_view.zig",
.imports = &.{.{ .name = "catalog_search", .path = "src/catalog/catalog_search.zig" }},
},
.{ .path = "src/ui/persistent_settings.zig" },
.{ .path = "src/ui/stream_dimensions.zig" },
.{ .path = "src/media/rtp/h264_depacketizer.zig" },
.{ .path = "src/net/json_reader.zig" },
.{ .path = "src/net/json_writer.zig" },
.{ .path = "src/net/form_writer.zig" },
};
for (test_roots) |root| {
const unit_tests = b.addTest(.{
.root_source_file = b.path(root),
.root_source_file = b.path(root.path),
.target = b.graph.host,
.optimize = .Debug,
.link_libc = true,
});
addProjectIncludes(b, unit_tests.root_module);
for (root.imports) |item|
addZigImport(b, unit_tests.root_module, b.graph.host, .Debug, item.name, item.path);
test_step.dependOn(&b.addRunArtifact(unit_tests).step);
}

Expand Down
Loading