diff --git a/docs/README.pod b/docs/README.pod index c9c976f..20e99b2 100644 --- a/docs/README.pod +++ b/docs/README.pod @@ -149,6 +149,10 @@ Try streaming if GFE version or options are unsupported Send quit app request to remote after quitting session +=item B<-viewonly> + +Disable all input processing (view-only mode) + =item B<-verbose> Enable verbose output diff --git a/moonlight.conf b/moonlight.conf index 01836d7..0dd5e98 100644 --- a/moonlight.conf +++ b/moonlight.conf @@ -43,6 +43,9 @@ ## Send quit app request to remote after quitting session #quitappafter = false +## Disable all input processing (view-only mode) +#viewonly = false + ## Select audio device to play sound on #audio = sysdefault diff --git a/src/config.c b/src/config.c index 4414739..7cf42ed 100644 --- a/src/config.c +++ b/src/config.c @@ -66,6 +66,7 @@ static struct option long_options[] = { {"codec", required_argument, NULL, 'x'}, {"unsupported", no_argument, NULL, 'y'}, {"quitappafter", no_argument, NULL, '1'}, + {"viewonly", no_argument, NULL, '2'}, {"verbose", no_argument, NULL, 'z'}, {"debug", no_argument, NULL, 'Z'}, {0, 0, 0, 0}, @@ -216,6 +217,9 @@ static void parse_argument(int c, char* value, PCONFIGURATION config) { case '1': config->quitappafter = true; break; + case '2': + config->viewonly = true; + break; case 'z': config->debug_level = 1; break; @@ -289,6 +293,8 @@ void config_save(char* filename, PCONFIGURATION config) { write_config_bool(fd, "localaudio", config->localaudio); if (config->quitappafter) write_config_bool(fd, "quitappafter", config->quitappafter); + if (config->viewonly) + write_config_bool(fd, "viewonly", config->viewonly); if (strcmp(config->app, "Steam") != 0) write_config_string(fd, "app", config->app); @@ -320,6 +326,7 @@ void config_parse(int argc, char* argv[], PCONFIGURATION config) { config->fullscreen = true; config->unsupported = false; config->quitappafter = false; + config->viewonly = false; config->codec = CODEC_UNSPECIFIED; config->inputsCount = 0; diff --git a/src/config.h b/src/config.h index 3f2ddf7..ecd3961 100644 --- a/src/config.h +++ b/src/config.h @@ -41,6 +41,7 @@ typedef struct _CONFIGURATION { bool fullscreen; bool unsupported; bool quitappafter; + bool viewonly; char* inputs[MAX_INPUTS]; int inputsCount; enum codecs codec; diff --git a/src/main.c b/src/main.c index ab179b0..6802b30 100644 --- a/src/main.c +++ b/src/main.c @@ -128,9 +128,11 @@ static void stream(PSERVER_DATA server, PCONFIGURATION config, enum platform sys LiStartConnection(&server->serverInfo, &config->stream, &connection_callbacks, platform_get_video(system), platform_get_audio(system, config->audio_device), NULL, drFlags, config->audio_device, 0); if (IS_EMBEDDED(system)) { - evdev_start(); + if (!config->viewonly) + evdev_start(); loop_main(); - evdev_stop(); + if (!config->viewonly) + evdev_stop(); } #ifdef HAVE_SDL else if (system == SDL) @@ -185,6 +187,7 @@ static void help() { printf("\t-platform \tSpecify system used for audio, video and input: pi/imx/aml/rk/x11/x11_vdpau/sdl/fake (default auto)\n"); printf("\t-unsupported\t\tTry streaming if GFE version or options are unsupported\n"); printf("\t-quitappafter\t\tSend quit app request to remote after quitting session\n"); + printf("\t-viewonly\t\tDisable all input processing (view-only mode)\n"); #if defined(HAVE_SDL) || defined(HAVE_X11) printf("\n WM options (SDL and X11 only)\n\n"); printf("\t-windowed\t\tDisplay screen in a window\n"); @@ -288,50 +291,59 @@ int main(int argc, char* argv[]) { } config.stream.supportsHevc = config.codec != CODEC_H264 && (config.codec == CODEC_HEVC || platform_supports_hevc(system)); - if (IS_EMBEDDED(system)) { - char* mapping_env = getenv("SDL_GAMECONTROLLERCONFIG"); - if (config.mapping == NULL && mapping_env == NULL) { - fprintf(stderr, "Please specify mapping file as default mapping could not be found.\n"); - exit(-1); - } - - struct mapping* mappings = NULL; - if (config.mapping != NULL) - mappings = mapping_load(config.mapping, config.debug_level > 0); - - if (mapping_env != NULL) { - struct mapping* map = mapping_parse(mapping_env); - map->next = mappings; - mappings = map; - } - - for (int i=0;i 0) - printf("Add input %s...\n", config.inputs[i]); - - evdev_create(config.inputs[i], mappings, config.debug_level > 0); - } - - udev_init(!inputAdded, mappings, config.debug_level > 0); - evdev_init(); - rumble_handler = evdev_rumble; - #ifdef HAVE_LIBCEC - cec_init(); - #endif /* HAVE_LIBCEC */ - } #ifdef HAVE_SDL - else if (system == SDL) { - if (config.inputsCount > 0) { - fprintf(stderr, "You can't select input devices as SDL will automatically use all available controllers\n"); - exit(-1); - } - + if (system == SDL) sdl_init(config.stream.width, config.stream.height, config.fullscreen); - sdlinput_init(config.mapping); - rumble_handler = sdlinput_rumble; - } #endif + if (config.viewonly) { + if (config.debug_level > 0) + printf("View-only mode enabled, no input will be sent to the host computer\n"); + } else { + if (IS_EMBEDDED(system)) { + char* mapping_env = getenv("SDL_GAMECONTROLLERCONFIG"); + if (config.mapping == NULL && mapping_env == NULL) { + fprintf(stderr, "Please specify mapping file as default mapping could not be found.\n"); + exit(-1); + } + + struct mapping* mappings = NULL; + if (config.mapping != NULL) + mappings = mapping_load(config.mapping, config.debug_level > 0); + + if (mapping_env != NULL) { + struct mapping* map = mapping_parse(mapping_env); + map->next = mappings; + mappings = map; + } + + for (int i=0;i 0) + printf("Add input %s...\n", config.inputs[i]); + + evdev_create(config.inputs[i], mappings, config.debug_level > 0); + } + + udev_init(!inputAdded, mappings, config.debug_level > 0); + evdev_init(); + rumble_handler = evdev_rumble; + #ifdef HAVE_LIBCEC + cec_init(); + #endif /* HAVE_LIBCEC */ + } + #ifdef HAVE_SDL + else if (system == SDL) { + if (config.inputsCount > 0) { + fprintf(stderr, "You can't select input devices as SDL will automatically use all available controllers\n"); + exit(-1); + } + + sdlinput_init(config.mapping); + rumble_handler = sdlinput_rumble; + } + #endif + } + stream(&server, &config, system); } else if (strcmp("pair", config.action) == 0) { char pin[5];