Skip to content
Merged
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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE BOOL "Export compile commands for IDE

set(MOONLIGHT_BUILD_KIND "HOST" CACHE STRING "Internal Moonlight build mode")
set_property(CACHE MOONLIGHT_BUILD_KIND PROPERTY STRINGS HOST XBOX)
option(MOONLIGHT_INPUT_DIAGNOSTICS "Display digital controller state while diagnosing stream input" OFF)

if(MOONLIGHT_BUILD_KIND STREQUAL "XBOX")
project(Moonlight C CXX)
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@
![Apps Screen](./docs/images/screenshots/03-apps.png)


## Streaming controls

To quit a stream, press **Back/Select + Black + White (LB + RB)** together on any connected controller.
The client displays **Stopping stream...** before returning to the menu. If the end-of-stream statistics
summary is enabled, release the buttons and press a button to dismiss it.

The opt-in CMake option `MOONLIGHT_INPUT_DIAGNOSTICS` displays controller state and event counters
for troubleshooting; it is disabled by default.

## 🛠️ Build

### Prerequisites
Expand Down
1 change: 1 addition & 0 deletions cmake/nxdk.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ function(moonlight_add_xbox_build)
-DMOONLIGHT_MAKE_PROGRAM:FILEPATH=${xbox_make_program}
-DMOONLIGHT_TOOLCHAIN_FILE:FILEPATH=${toolchain_file}
-DMOONLIGHT_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
-DMOONLIGHT_INPUT_DIAGNOSTICS:BOOL=${MOONLIGHT_INPUT_DIAGNOSTICS}
-P "${driver_script}"
)
set(build_command
Expand Down
1 change: 1 addition & 0 deletions cmake/run-child-build.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ if(MOONLIGHT_COMMAND_MODE STREQUAL "configure")
-S "${MOONLIGHT_SOURCE_DIR}"
-B "${MOONLIGHT_BINARY_DIR}"
-DMOONLIGHT_BUILD_KIND:STRING=XBOX
"-DMOONLIGHT_INPUT_DIAGNOSTICS:BOOL=${MOONLIGHT_INPUT_DIAGNOSTICS}"
"-DMOONLIGHT_NXDK_DIR:PATH=${MOONLIGHT_NXDK_SOURCE_DIR}"
"-DMOONLIGHT_NXDK_BUILD_DIR:PATH=${MOONLIGHT_NXDK_DIR}"
-DBUILD_DOCS:BOOL=OFF
Expand Down
2 changes: 2 additions & 0 deletions cmake/xbox-build.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ target_compile_definitions(${CMAKE_PROJECT_NAME}
NXDK
TOML_EXCEPTIONS=0
TOML_ENABLE_WINDOWS_COMPAT=0)
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE
MOONLIGHT_INPUT_DIAGNOSTICS=$<BOOL:${MOONLIGHT_INPUT_DIAGNOSTICS}>)
add_dependencies(${CMAKE_PROJECT_NAME} moonlight-common-c)

if(BUILD_DOCS)
Expand Down
28 changes: 28 additions & 0 deletions src/input/stream_exit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @file src/input/stream_exit.cpp
* @brief Recognizes the digital Back, Black and White exit chord from snapshots and events.
*/
#include "src/input/stream_exit.h"

#include "third-party/moonlight-common-c/src/Limelight.h"

namespace input {
bool is_stream_exit_requested(std::uint32_t buttons, bool controllerPresent) {
constexpr std::uint32_t required = BACK_FLAG | LB_FLAG | RB_FLAG;
return controllerPresent && (buttons & required) == required;
}

bool StreamExitChord::update(std::uint32_t buttons, bool controllerPresent) {
buttons_ = controllerPresent ? buttons : 0;
return is_stream_exit_requested(buttons_, controllerPresent);
}

bool StreamExitChord::update_button(std::uint32_t buttonFlag, bool pressed) {
if (pressed) {
buttons_ |= buttonFlag;
} else {
buttons_ &= ~buttonFlag;
}
return is_stream_exit_requested(buttons_, true);
}
} // namespace input
47 changes: 47 additions & 0 deletions src/input/stream_exit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* @file src/input/stream_exit.h
* @brief Defines a digital stream exit chord that does not invoke xemu's Start and Back menu.
*/
#pragma once

#include <cstdint>

namespace input {
constexpr const char *STREAM_EXIT_HINT = "Press Back/Select + Black + White (LB + RB) together to stop streaming. No hold required."; ///< Shared startup and streaming instruction.

/**
* @brief Recognize the digital exit chord without consulting axes or a clock.
*
* @param buttons Current Moonlight controller button flags.
* @param controllerPresent True when the sampled controller is connected.
* @return True when Back and both shoulders are pressed on a connected controller.
*/
bool is_stream_exit_requested(std::uint32_t buttons, bool controllerPresent);

/**
* @brief Track digital button events so a complete chord is detected before queued releases are drained.
*/
class StreamExitChord {
public:
/**
* @brief Synchronize event state with a sampled controller, clearing it on disconnect.
*
* @param buttons Current Moonlight controller button flags.
* @param controllerPresent True when the sampled controller is connected.
* @return True when the complete digital chord is pressed.
*/
bool update(std::uint32_t buttons, bool controllerPresent);

/**
* @brief Apply one digital button transition in event order.
*
* @param buttonFlag Moonlight flag for the button reported by the event.
* @param pressed True for a press, false for a release.
* @return True as soon as the transition completes the chord.
*/
bool update_button(std::uint32_t buttonFlag, bool pressed);

private:
std::uint32_t buttons_ = 0; ///< Digital buttons currently down in event order.
};
} // namespace input
Loading
Loading