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 include/rootstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ typedef struct {
uint32_t video_bitrate; /* Target bitrate (bits/sec) */
uint32_t video_framerate; /* Target framerate (fps) */
char video_codec[16]; /* Codec: "h264", "h265" */
int display_index; /* Preferred display index */

/* Audio settings */
bool audio_enabled; /* Enable audio streaming */
Expand Down
36 changes: 31 additions & 5 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,30 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <pwd.h>

#ifdef _WIN32
#include <direct.h>
#include <io.h>
#define getuid() 0
#else
#include <unistd.h>
#include <sys/stat.h>
#include <pwd.h>
#endif

/*
* Get configuration directory path
*
* @return Configuration directory path (never NULL)
*
* Priority:
* Priority (Linux):
* 1. $XDG_CONFIG_HOME/rootstream
* 2. $HOME/.config/rootstream
* 3. /tmp/rootstream (fallback if no home)
*
* Priority (Windows):
* 1. %APPDATA%\RootStream (via platform layer)
*/
const char* config_get_dir(void) {
static char config_dir[512] = {0};
Expand All @@ -39,6 +49,17 @@ const char* config_get_dir(void) {
return config_dir; /* Already computed */
}

#ifdef _WIN32
/* Use platform layer for Windows */
const char *platform_dir = rs_config_dir();
if (platform_dir) {
strncpy(config_dir, platform_dir, sizeof(config_dir) - 1);
return config_dir;
}
/* Fallback */
snprintf(config_dir, sizeof(config_dir), "C:\\RootStream");
return config_dir;
#else
/* Try XDG_CONFIG_HOME */
const char *xdg_config = getenv("XDG_CONFIG_HOME");
if (xdg_config && xdg_config[0] != '\0') {
Expand All @@ -64,6 +85,7 @@ const char* config_get_dir(void) {
/* Fallback to /tmp (not ideal, but works) */
snprintf(config_dir, sizeof(config_dir), "/tmp/rootstream-%d", getuid());
fprintf(stderr, "WARNING: Using fallback config directory: %s\n", config_dir);
#endif

return config_dir;
}
Expand All @@ -76,6 +98,7 @@ static void config_init_defaults(settings_t *settings) {
settings->video_bitrate = 10000000; /* 10 Mbps */
settings->video_framerate = 60; /* 60 fps */
strncpy(settings->video_codec, "h264", sizeof(settings->video_codec) - 1);
settings->display_index = 0;

/* Audio defaults */
settings->audio_enabled = true;
Expand Down Expand Up @@ -182,6 +205,8 @@ static int config_load_ini(settings_t *settings, const char *config_dir) {
settings->video_framerate = (uint32_t)atoi(value);
} else if (strcmp(key, "codec") == 0) {
strncpy(settings->video_codec, value, sizeof(settings->video_codec) - 1);
} else if (strcmp(key, "display") == 0) {
settings->display_index = atoi(value);
}
}
/* Audio settings */
Expand Down Expand Up @@ -247,7 +272,8 @@ static int config_save_ini(const settings_t *settings, const char *config_dir) {
fprintf(fp, "[video]\n");
fprintf(fp, "bitrate = %u\n", settings->video_bitrate);
fprintf(fp, "framerate = %u\n", settings->video_framerate);
fprintf(fp, "codec = %s\n\n", settings->video_codec);
fprintf(fp, "codec = %s\n", settings->video_codec);
fprintf(fp, "display = %d\n\n", settings->display_index);

/* Audio settings */
fprintf(fp, "[audio]\n");
Expand Down
6 changes: 5 additions & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ int main(int argc, char **argv) {
bool service_mode = false;
bool no_discovery = false;
uint16_t port = 9876;
int display_idx = 0;
int display_idx = -1;
int bitrate = 10000;
const char *record_file = NULL;
bool latency_log = false;
Expand Down Expand Up @@ -390,6 +390,10 @@ int main(int argc, char **argv) {
ctx.encoder.bitrate = (uint32_t)bitrate * 1000;
ctx.is_host = false;

if (display_idx < 0) {
display_idx = ctx.settings.display_index;
}

/* Handle --list-displays flag */
if (list_displays) {
display_info_t displays[MAX_DISPLAYS];
Expand Down
37 changes: 37 additions & 0 deletions src/tray.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <gtk/gtk.h>
#include <gdk/gdk.h>
Expand Down Expand Up @@ -365,6 +366,38 @@ static void on_settings(GtkMenuItem *item, gpointer user_data) {
GtkWidget *codec_label = gtk_label_new(codec_text);
gtk_box_pack_start(GTK_BOX(video_box), codec_label, FALSE, FALSE, 0);

/* Display selection */
GtkWidget *display_label = gtk_label_new("Display:");
GtkWidget *display_combo = gtk_combo_box_text_new();
display_info_t displays[MAX_DISPLAYS];
int num_displays = rootstream_detect_displays(displays, MAX_DISPLAYS);
int active_index = 0;
if (num_displays > 0) {
for (int i = 0; i < num_displays; i++) {
char item[128];
snprintf(item, sizeof(item), "%d: %s (%dx%d @ %d Hz)",
i, displays[i].name, displays[i].width,
displays[i].height, displays[i].refresh_rate);
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(display_combo), item);
if (i == ctx->settings.display_index) {
active_index = i;
}
}
for (int i = 0; i < num_displays; i++) {
if (displays[i].fd >= 0) {
close(displays[i].fd);
}
}
gtk_combo_box_set_active(GTK_COMBO_BOX(display_combo), active_index);
} else {
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(display_combo),
"No displays detected");
gtk_combo_box_set_active(GTK_COMBO_BOX(display_combo), 0);
gtk_widget_set_sensitive(display_combo, FALSE);
}
gtk_box_pack_start(GTK_BOX(video_box), display_label, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(video_box), display_combo, FALSE, FALSE, 0);

gtk_notebook_append_page(GTK_NOTEBOOK(notebook), video_box,
gtk_label_new("Video"));

Expand Down Expand Up @@ -422,6 +455,10 @@ static void on_settings(GtkMenuItem *item, gpointer user_data) {
gtk_spin_button_get_value(GTK_SPIN_BUTTON(bitrate_spin)) * 1000000);
ctx->settings.video_framerate = (uint32_t)
gtk_spin_button_get_value(GTK_SPIN_BUTTON(fps_spin));
if (num_displays > 0) {
ctx->settings.display_index =
gtk_combo_box_get_active(GTK_COMBO_BOX(display_combo));
}
ctx->settings.audio_enabled =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(audio_enabled));
ctx->settings.audio_bitrate = (uint32_t)(
Expand Down
Loading