Skip to content

Commit

Permalink
working embedded shell mode
Browse files Browse the repository at this point in the history
  • Loading branch information
mariotaku committed Mar 19, 2024
1 parent 8a2b369 commit 5ce2e0d
Show file tree
Hide file tree
Showing 16 changed files with 310 additions and 72 deletions.
3 changes: 2 additions & 1 deletion src/app/app.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,14 +278,15 @@ bool app_is_decoder_valid(app_t *app) {
return app->ss4s.selection.video_module != NULL && app->ss4s.selection.audio_module != NULL;
}

#if FEATURE_EMBEDDED_SHELL
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);
}

#endif

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

Expand Down
6 changes: 5 additions & 1 deletion src/app/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,13 @@ bool ui_render_queue_submit(void *data, unsigned int pts);

bool app_is_decoder_valid(app_t *app);

#if FEATURE_EMBEDDED_SHELL
bool app_has_embedded(app_t *app);

bool app_decoder_or_embedded_present(app_t *app);
#else
#define app_decoder_or_embedded_present(app) app_is_decoder_valid(app)
#endif


GS_CLIENT app_gs_client_new(app_t *app);

Expand Down
7 changes: 5 additions & 2 deletions src/app/stream/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
target_sources(moonlight-lib PRIVATE session.c
session_events.c
session_worker.c
session_priv.c
embed_wrapper.c)
session_priv.c)

if (FEATURE_EMBEDDED_SHELL)
target_sources(moonlight-lib PRIVATE embed_wrapper.c session_worker_embedded.c)
endif ()

add_subdirectory(input)
add_subdirectory(connection)
Expand Down
104 changes: 103 additions & 1 deletion src/app/stream/embed_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,18 @@

#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/wait.h>

struct embed_process_t {
FILE *output;
pid_t pid;
};

int embed_check_version(version_info_t *version_info) {
FILE *f = popen("moonlight help", "r");
FILE *f = popen("moonlight help 2>/dev/null", "r");
if (f == NULL) {
return -1;
}
Expand All @@ -41,4 +50,97 @@ int embed_check_version(version_info_t *version_info) {
return -1;
}
return version_info_parse(version_info, buf + 19);
}

embed_process_t *embed_spawn(const char *app_name, const char *key_dir, const char *server_address,
int width, int height, int fps, int bitrate, bool localaudio, bool viewonly) {
int fds[2];
if (pipe(fds) != 0) {
return NULL;
}

char args_tmp[4096];
size_t args_tmp_start = 0;
char *app_name_tmp = args_tmp;
args_tmp_start += snprintf(app_name_tmp, sizeof(args_tmp), "%s", app_name) + 1;
char *key_dir_tmp = args_tmp + args_tmp_start;
args_tmp_start += snprintf(key_dir_tmp, sizeof(args_tmp) - args_tmp_start, "%s", key_dir) + 1;
char *width_tmp = args_tmp + args_tmp_start;
args_tmp_start += snprintf(width_tmp, sizeof(args_tmp) - args_tmp_start, "%d", width) + 1;
char *height_tmp = args_tmp + args_tmp_start;
args_tmp_start += snprintf(height_tmp, sizeof(args_tmp) - args_tmp_start, "%d", height) + 1;
char *fps_tmp = args_tmp + args_tmp_start;
args_tmp_start += snprintf(fps_tmp, sizeof(args_tmp) - args_tmp_start, "%d", fps) + 1;
char *bitrate_tmp = args_tmp + args_tmp_start;
args_tmp_start += snprintf(bitrate_tmp, sizeof(args_tmp) - args_tmp_start, "%d", bitrate) + 1;
char *server_address_tmp = args_tmp + args_tmp_start;
snprintf(server_address_tmp, sizeof(args_tmp) - args_tmp_start, "%s", server_address);


pid_t pid = fork();
if (pid == -1) {
close(fds[0]);
close(fds[1]);
return NULL;
}

if (pid == 0) {
close(fds[0]);
dup2(fds[1], STDOUT_FILENO);
dup2(fds[1], STDERR_FILENO);

char *argv[32];
int argc = 0;
argv[argc++] = "moonlight";
argv[argc++] = "stream";
argv[argc++] = "-app";
argv[argc++] = app_name_tmp;
argv[argc++] = "-keydir";
argv[argc++] = key_dir_tmp;
argv[argc++] = "-width";
argv[argc++] = width_tmp;
argv[argc++] = "-height";
argv[argc++] = height_tmp;
argv[argc++] = "-fps";
argv[argc++] = fps_tmp;
argv[argc++] = "-bitrate";
argv[argc++] = bitrate_tmp;
if (localaudio) {
argv[argc++] = "-localaudio";
}
if (viewonly) {
argv[argc++] = "-viewonly";
}
argv[argc++] = server_address_tmp;
argv[argc++] = NULL;
execvp("moonlight", argv);
exit(0);
}
close(fds[1]);

FILE *f = fdopen(fds[0], "r");
if (f == NULL) {
close(fds[0]);
kill(pid, SIGTERM);
return NULL;
}
embed_process_t *process = malloc(sizeof(embed_process_t));
assert(process != NULL);
process->output = f;
process->pid = pid;
return process;
}

char *embed_read(embed_process_t *proc, char *buf, size_t size) {
return fgets(buf, (int) size, proc->output);
}

int embed_interrupt(embed_process_t *proc) {
return kill(proc->pid, SIGINT);
}

int embed_wait(embed_process_t *proc) {
int status;
waitpid(proc->pid, &status, 0);
return status;
}
13 changes: 12 additions & 1 deletion src/app/stream/embed_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,15 @@

#include "version_info.h"

int embed_check_version(version_info_t *version_info);
typedef struct embed_process_t embed_process_t;

int embed_check_version(version_info_t *version_info);

embed_process_t *embed_spawn(const char *app_name, const char *key_dir, const char *server_address,
int width, int height, int fps, int bitrate, bool localaudio, bool viewonly);

char *embed_read(embed_process_t *proc, char *buf, size_t size);

int embed_interrupt(embed_process_t *proc);

int embed_wait(embed_process_t *proc);
21 changes: 20 additions & 1 deletion src/app/stream/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,19 @@ session_t *session_create(app_t *app, const CONFIGURATION *config, const SERVER_
session->mutex = SDL_CreateMutex();
session->state_lock = SDL_CreateMutex();
session->cond = SDL_CreateCond();
#if FEATURE_EMBEDDED_SHELL
if (!app_is_decoder_valid(app)) {
session->embed = app_has_embedded(session->app);
}
#endif
session_input_init(&session->input, session, &app->input, &session->config);
session->thread = SDL_CreateThread((SDL_ThreadFunction) session_worker, "session", session);
SDL_ThreadFunction worker_fn = (SDL_ThreadFunction) session_worker;
#if FEATURE_EMBEDDED_SHELL
if (session_use_embedded(session)) {
worker_fn = (SDL_ThreadFunction) session_worker_embedded;
}
#endif
session->thread = SDL_CreateThread(worker_fn, "session", session);
return session;
}

Expand Down Expand Up @@ -90,6 +98,11 @@ void session_interrupt(session_t *session, bool quitapp, streaming_interrupt_rea
session_input_interrupt(&session->input);
session->quitapp = quitapp;
session->interrupted = true;
#if FEATURE_EMBEDDED_SHELL
if (session->embed && session->embed_process) {
embed_interrupt(session->embed_process);
}
#endif
if (reason >= STREAMING_INTERRUPT_ERROR) {
switch (reason) {
case STREAMING_INTERRUPT_WATCHDOG:
Expand All @@ -116,9 +129,11 @@ bool session_accepting_input(session_t *session) {
}

bool session_start_input(session_t *session) {
#if FEATURE_EMBEDDED_SHELL
if (session->embed) {
return false;
}
#endif
session_input_started(&session->input);
return true;
}
Expand Down Expand Up @@ -261,6 +276,10 @@ void session_config_init(app_t *app, session_config_t *config, const SERVER_DATA
config->stream.supportedVideoFormats |= VIDEO_FORMAT_AV1_MAIN10;
}
}
// If no video format is supported, default to H.264
if (config->stream.supportedVideoFormats == 0) {
config->stream.supportedVideoFormats = VIDEO_FORMAT_H264;
}
config->stream.colorSpace = COLORSPACE_REC_709/* TODO: get from video capabilities */;
config->stream.colorRange = video_cap.fullColorRange ? COLOR_RANGE_FULL : COLOR_RANGE_LIMITED;
#if FEATURE_SURROUND_SOUND
Expand Down
4 changes: 3 additions & 1 deletion src/app/stream/session_priv.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ void session_set_state(session_t *session, STREAMING_STATE state) {
SDL_UnlockMutex(session->state_lock);
}

#if FEATURE_EMBEDDED_SHELL
bool session_use_embedded(session_t *session) {
return session->embed;
}
}
#endif
8 changes: 7 additions & 1 deletion src/app/stream/session_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "app_settings.h"
#include "stream/input/session_input.h"
#include "stream/session.h"
#include "embed_wrapper.h"

typedef struct app_t app_t;

Expand All @@ -26,7 +27,10 @@ struct session_t {
char *app_name;
bool interrupted;
bool quitapp;
#if FEATURE_EMBEDDED_SHELL
bool embed;
embed_process_t *embed_process;
#endif
SS4S_AudioCapabilities audio_cap;
SS4S_VideoCapabilities video_cap;
SDL_cond *cond;
Expand All @@ -37,4 +41,6 @@ struct session_t {

void session_set_state(session_t *session, STREAMING_STATE state);

bool session_use_embedded(session_t *session);
#if FEATURE_EMBEDDED_SHELL
bool session_use_embedded(session_t *session);
#endif
33 changes: 0 additions & 33 deletions src/app/stream/session_worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,7 @@
#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 @@ -72,9 +67,6 @@ int session_worker(session_t *session) {
case CALLBACKS_SESSION_ERROR_ADEC_ERROR:
streaming_error(session, GS_WRONG_STATE, "Failed to open audio backend.");
break;
// case ERROR_AUDIO_OPUS_INIT_FAILED:
// streaming_error(GS_WRONG_STATE, "Opus init failed.");
// break;
default: {
if (!streaming_errno) {
streaming_error(session, GS_WRONG_STATE, "Failed to start connection: Limelight returned %d (%s)",
Expand Down Expand Up @@ -121,31 +113,6 @@ 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;
}
2 changes: 2 additions & 0 deletions src/app/stream/session_worker.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
typedef struct session_t session_t;

int session_worker(session_t *session);

int session_worker_embedded(session_t *session);
Loading

0 comments on commit 5ce2e0d

Please sign in to comment.