Skip to content

Commit

Permalink
wip: delegate to moonlight-embedded if no valid decoder found
Browse files Browse the repository at this point in the history
  • Loading branch information
mariotaku committed Mar 17, 2024
1 parent c05eb6a commit d151fe0
Show file tree
Hide file tree
Showing 19 changed files with 191 additions and 17 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ set(FEATURE_SURROUND_SOUND ON)
set(FEATURE_CHECK_MODULE_OS_VERSION OFF)
set(FEATURE_INPUT_EVMOUSE OFF)
set(FEATURE_INPUT_LIBCEC ON)
set(FEATURE_EMBEDDED_SHELL OFF)
set(FEATURE_WINDOW_FULLSCREEN_DESKTOP ON)

include(LintOptions)
Expand Down Expand Up @@ -270,6 +271,7 @@ else ()
target_compile_definitions(moonlight-lib PUBLIC OS_DARWIN)
target_compile_definitions(moonlight-lib PUBLIC GAMECONTROLLERDB_PLATFORM="Mac OS X")
elseif (OS_LINUX)
set(FEATURE_EMBEDDED_SHELL ON)
target_compile_definitions(moonlight-lib PUBLIC OS_LINUX _GNU_SOURCE)
target_compile_definitions(moonlight-lib PUBLIC GAMECONTROLLERDB_PLATFORM="Linux")
elseif (OS_WINDOWS)
Expand Down
28 changes: 28 additions & 0 deletions src/app/app.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "ui/fatal_error.h"
#include "app_error.h"
#include "app_session.h"
#include "stream/embed_wrapper.h"

PCONFIGURATION app_configuration = NULL;

Expand All @@ -46,6 +47,9 @@ int app_init(app_t *app, app_settings_loader *settings_loader, int argc, char *a
app->main_thread_id = SDL_ThreadID();
app->running = true;
app->focused = false;
#if FEATURE_EMBEDDED_SHELL
app->embed_version.major = -1;
#endif
app_configuration = &app->settings;
if (os_info_get(&app->os_info) == 0) {
char *info_str = os_info_str(&app->os_info);
Expand Down Expand Up @@ -270,6 +274,19 @@ bool app_is_running() {
return global->running;
}

bool app_is_decoder_valid(app_t *app) {
return app->ss4s.selection.video_module != NULL && app->ss4s.selection.audio_module != NULL;
}

bool app_has_embedded(app_t *app) {
return version_info_valid(&app->embed_version);
}

bool app_decoder_or_embedded_present(app_t *app) {
return app_is_decoder_valid(app) || app_has_embedded(app);
}


static void libs_init(app_t *app, int argc, char *argv[]) {

int errno;
Expand All @@ -286,6 +303,17 @@ static void libs_init(app_t *app, int argc, char *argv[]) {
commons_log_info("APP", "Audio module: %s (requested %s)", SS4S_ModuleInfoGetName(app->ss4s.selection.audio_module),
module_preferences.audio_module);

#if FEATURE_EMBEDDED_SHELL
if (!app_is_decoder_valid(app)) {
// Check if moonlight-embedded is installed
if (embed_check_version(&app->embed_version) == 0) {
char *embed_version_str = version_info_str(&app->embed_version);
commons_log_info("APP", "Moonlight Embedded version: %s", embed_version_str);
free(embed_version_str);
}
}
#endif

SS4S_Config ss4s_config = {
.audioDriver = SS4S_ModuleInfoGetId(app->ss4s.selection.audio_module),
.videoDriver = SS4S_ModuleInfoGetId(app->ss4s.selection.video_module),
Expand Down
9 changes: 9 additions & 0 deletions src/app/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ typedef struct app_t {
SS4S_AudioCapabilities audio_cap;
SS4S_VideoCapabilities video_cap;
} ss4s;
#if FEATURE_EMBEDDED_SHELL
version_info_t embed_version;
#endif
#if FEATURE_INPUT_LIBCEC
cec_sdl_ctx_t cec;
#endif
Expand All @@ -70,6 +73,12 @@ void app_quit_confirm();

bool ui_render_queue_submit(void *data, unsigned int pts);

bool app_is_decoder_valid(app_t *app);

bool app_has_embedded(app_t *app);

bool app_decoder_or_embedded_present(app_t *app);

GS_CLIENT app_gs_client_new(app_t *app);

void app_set_mouse_grab(app_input_t *input, bool grab);
Expand Down
4 changes: 2 additions & 2 deletions src/app/app_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
#include "app.h"
#include "stream/session.h"

int app_session_begin(app_t *app, const uuidstr_t *uuid, int app_id) {
int app_session_begin(app_t *app, const uuidstr_t *uuid, const APP_LIST *gs_app) {
if (app->session != NULL) {
return -1;
}
const pclist_t *node = pcmanager_node(pcmanager, uuid);
if (node == NULL) {
return -1;
}
app->session = session_create(app, app_configuration, node->server, app_id);
app->session = session_create(app, app_configuration, node->server, gs_app);
return 0;
}

Expand Down
3 changes: 2 additions & 1 deletion src/app/app_session.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#pragma once

#include "uuidstr.h"
#include "client.h"

typedef struct app_t app_t;

int app_session_begin(app_t *app, const uuidstr_t *uuid, int app_id);
int app_session_begin(app_t *app, const uuidstr_t *uuid, const APP_LIST *gs_app);

void app_session_destroy(app_t *app);
4 changes: 4 additions & 0 deletions src/app/backend/apploader/apploader.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ void apploader_load(apploader_t *loader) {
if (state == EXECUTOR_TASK_STATE_PENDING || state == EXECUTOR_TASK_STATE_ACTIVE) {
return;
}
if (loader->state == APPLOADER_STATE_LOADING) {
commons_log_warn("AppLoader", "[loader %p] already loading", loader);
return;
}
loader->state = APPLOADER_STATE_LOADING;
if (loader->callback.start != NULL) {
loader->callback.start(loader->userdata);
Expand Down
1 change: 1 addition & 0 deletions src/app/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
#cmakedefine01 FEATURE_INPUT_EVMOUSE
#cmakedefine01 FEATURE_INPUT_LIBCEC
#cmakedefine01 FEATURE_WINDOW_FULLSCREEN_DESKTOP
#cmakedefine01 FEATURE_EMBEDDED_SHELL
#define I18N_LOCALES "@I18N_LOCALES@"
#define I18N_LOCALES_LEN @I18N_LOCALES_LEN@
3 changes: 2 additions & 1 deletion src/app/stream/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
target_sources(moonlight-lib PRIVATE session.c
session_events.c
session_worker.c
session_priv.c)
session_priv.c
embed_wrapper.c)

add_subdirectory(input)
add_subdirectory(connection)
Expand Down
44 changes: 44 additions & 0 deletions src/app/stream/embed_wrapper.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2024 Mariotaku <https://github.com/mariotaku>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

#include "embed_wrapper.h"

#include <stdio.h>
#include <string.h>

int embed_check_version(version_info_t *version_info) {
FILE *f = popen("moonlight help", "r");
if (f == NULL) {
return -1;
}
// Get first line of output
char buf[64];
if (fgets(buf, sizeof(buf), f) == NULL) {
pclose(f);
return -1;
}
buf[sizeof(buf) - 1] = '\0';
int ret = pclose(f);
if (ret != 0) {
return ret;
}
if (strncmp(buf, "Moonlight Embedded ", 19) != 0) {
return -1;
}
return version_info_parse(version_info, buf + 19);
}
23 changes: 23 additions & 0 deletions src/app/stream/embed_wrapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2024 Mariotaku <https://github.com/mariotaku>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

#pragma once

#include "version_info.h"

int embed_check_version(version_info_t *version_info);
1 change: 1 addition & 0 deletions src/app/stream/input/session_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "session_input.h"
#include "stream/session.h"
#include "stream/session_priv.h"
#include "session_evmouse.h"

void session_input_init(stream_input_t *input, session_t *session, app_input_t *app_input,
Expand Down
24 changes: 20 additions & 4 deletions src/app/stream/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ static bool streaming_sops_supported(PDISPLAY_MODE modes, int w, int h, int fps)
static void session_config_init(app_t *app, session_config_t *config, const SERVER_DATA *server,
const CONFIGURATION *app_config);

session_t *session_create(app_t *app, const CONFIGURATION *config, const SERVER_DATA *server, int app_id) {
session_t *session_create(app_t *app, const CONFIGURATION *config, const SERVER_DATA *server, const APP_LIST *gs_app) {
session_t *session = malloc(sizeof(session_t));
SDL_memset(session, 0, sizeof(session_t));
session_config_init(app, &session->config, server, config);
Expand All @@ -53,10 +53,14 @@ session_t *session_create(app_t *app, const CONFIGURATION *config, const SERVER_
if (session->config.stream.supportedVideoFormats & VIDEO_FORMAT_AV1_MAIN10) {
session->server->serverInfo.serverCodecModeSupport |= SCM_AV1_MAIN10;
}
session->app_id = app_id;
session->app_id = gs_app->id;
session->app_name = strdup(gs_app->name);
session->mutex = SDL_CreateMutex();
session->state_lock = SDL_CreateMutex();
session->cond = SDL_CreateCond();
if (!app_is_decoder_valid(app)) {
session->embed = app_has_embedded(session->app);
}
session_input_init(&session->input, session, &app->input, &session->config);
session->thread = SDL_CreateThread((SDL_ThreadFunction) session_worker, "session", session);
return session;
Expand All @@ -69,6 +73,8 @@ void session_destroy(session_t *session) {
serverdata_free(session->server);
SDL_DestroyCond(session->cond);
SDL_DestroyMutex(session->mutex);
SDL_DestroyMutex(session->state_lock);
free(session->app_name);
free(session);
}

Expand Down Expand Up @@ -109,14 +115,22 @@ bool session_accepting_input(session_t *session) {
return session->input.started && !ui_should_block_input();
}

void session_start_input(session_t *session) {
bool session_start_input(session_t *session) {
if (session->embed) {
return false;
}
session_input_started(&session->input);
return true;
}

void session_stop_input(session_t *session) {
session_input_stopped(&session->input);
}

bool session_has_input(session_t *session) {
return session->input.started;
}

void session_toggle_vmouse(session_t *session) {
bool value = session->config.vmouse && !session_input_is_vmouse_active(&session->input.vmouse);
session_input_set_vmouse_active(&session->input.vmouse, value);
Expand All @@ -128,7 +142,9 @@ void streaming_display_size(session_t *session, short width, short height) {
}

void streaming_enter_fullscreen(session_t *session) {
app_set_mouse_grab(&session->app->input, true);
if (!session->player) {
return;
}
if ((session->video_cap.transform & SS4S_VIDEO_CAP_TRANSFORM_UI_COMPOSITING) == 0) {
SS4S_PlayerVideoSetDisplayArea(session->player, NULL, NULL);
}
Expand Down
6 changes: 4 additions & 2 deletions src/app/stream/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,18 @@ typedef struct app_t app_t;
typedef struct app_settings_t app_settings_t;
typedef struct session_t session_t;

session_t *session_create(app_t *app, const app_settings_t *config, const SERVER_DATA *server, int app_id);
session_t *session_create(app_t *app, const app_settings_t *config, const SERVER_DATA *server, const APP_LIST *gs_app);

void session_destroy(session_t *session);

void session_interrupt(session_t *session, bool quitapp, streaming_interrupt_reason_t reason);

void session_start_input(session_t *session);
bool session_start_input(session_t *session);

void session_stop_input(session_t *session);

bool session_has_input(session_t *session);

void session_toggle_vmouse(session_t *session);

bool session_accepting_input(session_t *session);
Expand Down
4 changes: 4 additions & 0 deletions src/app/stream/session_priv.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ void session_set_state(session_t *session, STREAMING_STATE state) {
session->state = state;
SDL_UnlockMutex(session->state_lock);
}

bool session_use_embedded(session_t *session) {
return session->embed;
}
6 changes: 5 additions & 1 deletion src/app/stream/session_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ struct session_t {
/* SERVER_DATA and CONFIGURATION is cloned rather than referenced */
SERVER_DATA *server;
int app_id;
char *app_name;
bool interrupted;
bool quitapp;
bool embed;
SS4S_AudioCapabilities audio_cap;
SS4S_VideoCapabilities video_cap;
SDL_cond *cond;
Expand All @@ -33,4 +35,6 @@ struct session_t {
SS4S_Player *player;
};

void session_set_state(session_t *session, STREAMING_STATE state);
void session_set_state(session_t *session, STREAMING_STATE state);

bool session_use_embedded(session_t *session);
30 changes: 30 additions & 0 deletions src/app/stream/session_worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@
#include "app_session.h"
#include "backend/pcmanager/worker/worker.h"

static int session_worker_embedded(session_t *session);

int session_worker(session_t *session) {
if (session_use_embedded(session)) {
return session_worker_embedded(session);
}
app_t *app = session->app;
session_set_state(session, STREAMING_CONNECTING);
bus_pushevent(USER_STREAM_CONNECTING, NULL, NULL);
Expand Down Expand Up @@ -116,6 +121,31 @@ int session_worker(session_t *session) {
#if FEATURE_INPUT_EVMOUSE
session_evmouse_deinit(&session->input.evmouse);
#endif
app_bus_post(app, (bus_actionfunc) app_session_destroy, app);
return 0;
}

int session_worker_embedded(session_t *session) {
app_t *app = session->app;
session_set_state(session, STREAMING_CONNECTING);
bus_pushevent(USER_STREAM_CONNECTING, NULL, NULL);
streaming_error(session, GS_OK, "");

// SDL_Delay(5000);

session_set_state(session, STREAMING_STREAMING);
bus_pushevent(USER_STREAM_OPEN, NULL, NULL);
SDL_LockMutex(session->mutex);

app_bus_post_sync(app, (bus_actionfunc) app_ui_close, &app->ui);

// SDL_Delay(10000);

SDL_UnlockMutex(session->mutex);
bus_pushevent(USER_STREAM_CLOSE, NULL, NULL);

session_set_state(session, STREAMING_DISCONNECTING);

app_bus_post(app, (bus_actionfunc) app_session_destroy, app);
return 0;
}
Loading

0 comments on commit d151fe0

Please sign in to comment.