From 3fd5e3f2920f28684c472557e4c6d111970f90a3 Mon Sep 17 00:00:00 2001 From: Umberto Date: Wed, 17 Sep 2025 23:57:44 +0200 Subject: [PATCH] feat: allow different send & receive ports --- linux/PwarController.cpp | 35 +++++++++++++++++-------- linux/PwarController.h | 12 ++++++--- linux/libpwar.c | 6 ++--- linux/libpwar.h | 3 ++- linux/pwar_cli.c | 10 +++++--- linux/pwar_gui.qml | 55 +++++++++++++++++++++++++++++++++++++--- linux/windows_sim.c | 1 + 7 files changed, 96 insertions(+), 26 deletions(-) diff --git a/linux/PwarController.cpp b/linux/PwarController.cpp index 7df4a72..062d7e4 100644 --- a/linux/PwarController.cpp +++ b/linux/PwarController.cpp @@ -16,7 +16,8 @@ PwarController::PwarController(QObject *parent) // Initialize default config strcpy(m_config.stream_ip, "192.168.66.3"); - m_config.stream_port = 8321; + m_config.connect_port = 8321; + m_config.listen_port = 8321; m_config.passthrough_test = 0; m_config.oneshot_mode = 0; m_config.buffer_size = 64; @@ -71,14 +72,28 @@ void PwarController::setStreamIp(const QString &ip) { } } -int PwarController::streamPort() const { - return m_config.stream_port; +int PwarController::connectPort() const { + return m_config.connect_port; } -void PwarController::setStreamPort(int port) { - if (m_config.stream_port != port) { - m_config.stream_port = port; - emit streamPortChanged(); +void PwarController::setConnectPort(int port) { + if (m_config.connect_port != port) { + m_config.connect_port = port; + emit connectPortChanged(); + if (pwar_is_running()) { + setStatus("Port changed - stop and start to apply"); + } + } +} + +int PwarController::listenPort() const { + return m_config.listen_port; +} + +void PwarController::setListenPort(int port) { + if (m_config.listen_port != port) { + m_config.listen_port = port; + emit listenPortChanged(); if (pwar_is_running()) { setStatus("Port changed - stop and start to apply"); } @@ -249,8 +264,8 @@ void PwarController::loadSettings() { QString savedIp = m_settings->value("network/streamIp", QString(m_config.stream_ip)).toString(); setStreamIp(savedIp); - int savedPort = m_settings->value("network/streamPort", m_config.stream_port).toInt(); - setStreamPort(savedPort); + int savedPort = m_settings->value("network/connectPort", m_config.connect_port).toInt(); + setConnectPort(savedPort); // Load audio settings bool savedPassthrough = m_settings->value("audio/passthroughTest", m_config.passthrough_test).toBool(); @@ -278,7 +293,7 @@ void PwarController::saveSettings() { // Save network settings m_settings->setValue("network/streamIp", streamIp()); - m_settings->setValue("network/streamPort", streamPort()); + m_settings->setValue("network/connectPort", connectPort()); // Save audio settings m_settings->setValue("audio/passthroughTest", passthroughTest()); diff --git a/linux/PwarController.h b/linux/PwarController.h index 7430c20..42b31c3 100644 --- a/linux/PwarController.h +++ b/linux/PwarController.h @@ -9,7 +9,8 @@ class PwarController : public QObject { Q_PROPERTY(QString status READ status WRITE setStatus NOTIFY statusChanged) Q_PROPERTY(bool isRunning READ isRunning NOTIFY isRunningChanged) Q_PROPERTY(QString streamIp READ streamIp WRITE setStreamIp NOTIFY streamIpChanged) - Q_PROPERTY(int streamPort READ streamPort WRITE setStreamPort NOTIFY streamPortChanged) + Q_PROPERTY(int connectPort READ connectPort WRITE setConnectPort NOTIFY connectPortChanged) + Q_PROPERTY(int listenPort READ listenPort WRITE setListenPort NOTIFY listenPortChanged) Q_PROPERTY(bool passthroughTest READ passthroughTest WRITE setPassthroughTest NOTIFY passthroughTestChanged) Q_PROPERTY(bool oneshotMode READ oneshotMode WRITE setOneshotMode NOTIFY oneshotModeChanged) Q_PROPERTY(int bufferSize READ bufferSize WRITE setBufferSize NOTIFY bufferSizeChanged) @@ -44,8 +45,10 @@ class PwarController : public QObject { bool isRunning() const; QString streamIp() const; void setStreamIp(const QString &ip); - int streamPort() const; - void setStreamPort(int port); + int connectPort() const; + void setConnectPort(int port); + int listenPort() const; + void setListenPort(int port); bool passthroughTest() const; void setPassthroughTest(bool enabled); bool oneshotMode() const; @@ -91,7 +94,8 @@ class PwarController : public QObject { void statusChanged(); void isRunningChanged(); void streamIpChanged(); - void streamPortChanged(); + void connectPortChanged(); + void listenPortChanged(); void passthroughTestChanged(); void oneshotModeChanged(); void bufferSizeChanged(); diff --git a/linux/libpwar.c b/linux/libpwar.c index bc2a0eb..791e0a6 100644 --- a/linux/libpwar.c +++ b/linux/libpwar.c @@ -302,8 +302,8 @@ static void *pipewire_thread_func(void *userdata) { static int init_data_structure(struct data *data, const pwar_config_t *config) { memset(data, 0, sizeof(struct data)); - setup_socket(data, config->stream_ip, config->stream_port); - setup_recv_socket(data, DEFAULT_STREAM_PORT); + setup_socket(data, config->stream_ip, config->connect_port); + setup_recv_socket(data, config->listen_port); pthread_mutex_init(&data->packet_mutex, NULL); pthread_cond_init(&data->packet_cond, NULL); data->packet_available = 0; @@ -382,7 +382,7 @@ static int create_pipewire_filter(struct data *data) { int pwar_requires_restart(const pwar_config_t *old_config, const pwar_config_t *new_config) { if (old_config->buffer_size != new_config->buffer_size || strcmp(old_config->stream_ip, new_config->stream_ip) != 0 || - old_config->stream_port != new_config->stream_port) { + old_config->connect_port != new_config->connect_port) { return 1; } return 0; diff --git a/linux/libpwar.h b/linux/libpwar.h index 1f45da4..1edf360 100644 --- a/linux/libpwar.h +++ b/linux/libpwar.h @@ -12,7 +12,8 @@ extern "C" { typedef struct { char stream_ip[PWAR_MAX_IP_LEN]; - int stream_port; + int connect_port; + int listen_port; int passthrough_test; int oneshot_mode; int buffer_size; diff --git a/linux/pwar_cli.c b/linux/pwar_cli.c index 3ca0e3b..d0d37da 100644 --- a/linux/pwar_cli.c +++ b/linux/pwar_cli.c @@ -18,7 +18,7 @@ int main(int argc, char *argv[]) { pwar_config_t config; memset(&config, 0, sizeof(config)); strncpy(config.stream_ip, DEFAULT_STREAM_IP, sizeof(config.stream_ip) - 1); - config.stream_port = DEFAULT_STREAM_PORT; + config.listen_port = config.connect_port = DEFAULT_STREAM_PORT; config.passthrough_test = 0; config.oneshot_mode = 0; config.buffer_size = DEFAULT_BUFFER_SIZE; @@ -27,8 +27,10 @@ int main(int argc, char *argv[]) { if ((strcmp(argv[i], "--ip") == 0 || strcmp(argv[i], "-i") == 0) && i + 1 < argc) { strncpy(config.stream_ip, argv[++i], sizeof(config.stream_ip) - 1); config.stream_ip[sizeof(config.stream_ip) - 1] = '\0'; - } else if ((strcmp(argv[i], "--port") == 0 || (strcmp(argv[i], "-p") == 0)) && i + 1 < argc) { - config.stream_port = atoi(argv[++i]); + } else if ((strcmp(argv[i], "--connect-port") == 0 || (strcmp(argv[i], "-p") == 0)) && i + 1 < argc) { + config.connect_port = atoi(argv[++i]); + } else if ((strcmp(argv[i], "--listen-port") == 0 || (strcmp(argv[i], "-l") == 0)) && i + 1 < argc) { + config.listen_port = atoi(argv[++i]); } else if ((strcmp(argv[i], "--passthrough_test") == 0) || (strcmp(argv[i], "-pt") == 0)) { config.passthrough_test = 1; } else if ((strcmp(argv[i], "--oneshot") == 0)) { @@ -40,7 +42,7 @@ int main(int argc, char *argv[]) { printf("Starting PWAR with config:\n"); printf(" Stream IP: %s\n", config.stream_ip); - printf(" Stream Port: %d\n", config.stream_port); + printf(" Stream Port: %d\n", config.connect_port); printf(" Passthrough Test: %s\n", config.passthrough_test ? "Enabled" : "Disabled"); printf(" Oneshot Mode: %s\n", config.oneshot_mode ? "Enabled" : "Disabled"); printf(" Buffer Size: %d\n", config.buffer_size); diff --git a/linux/pwar_gui.qml b/linux/pwar_gui.qml index 3a8f2a4..3392056 100644 --- a/linux/pwar_gui.qml +++ b/linux/pwar_gui.qml @@ -306,7 +306,7 @@ ApplicationWindow { } Label { - text: "Port" + text: "Connect Port" color: textPrimary font.bold: true } @@ -319,11 +319,58 @@ ApplicationWindow { color: textPrimary placeholderTextColor: textSecondary selectByMouse: true - text: pwarController.streamPort.toString() + text: pwarController.connectPort.toString() onTextChanged: { var portNumber = parseInt(text); - if (!isNaN(portNumber) && portNumber !== pwarController.streamPort) { - pwarController.streamPort = portNumber; + if (!isNaN(portNumber) && portNumber !== pwarController.connectPort) { + pwarController.connectPort = portNumber; + } + } + + background: Rectangle { + color: graphiteMedium + radius: 4 + border.color: parent.activeFocus ? orangeAccent : (parent.hovered ? orangeHover : "#555555") + border.width: parent.activeFocus ? 2 : 1 + + Behavior on border.color { ColorAnimation { duration: 150 } } + Behavior on border.width { NumberAnimation { duration: 150 } } + + // Subtle glow when focused + Rectangle { + anchors.fill: parent + anchors.margins: -2 + radius: parent.radius + 2 + color: "transparent" + border.color: orangeAccent + border.width: parent.parent.activeFocus ? 1 : 0 + opacity: parent.parent.activeFocus ? 0.3 : 0 + + Behavior on opacity { NumberAnimation { duration: 150 } } + Behavior on border.width { NumberAnimation { duration: 150 } } + } + } + } + + Label { + text: "Listen Port" + color: textPrimary + font.bold: true + } + TextField { + id: listenPortField + Layout.fillWidth: true + placeholderText: "e.g. 5600" + inputMethodHints: Qt.ImhDigitsOnly + validator: IntValidator { bottom: 1; top: 65535 } + color: textPrimary + placeholderTextColor: textSecondary + selectByMouse: true + text: pwarController.listenPort.toString() + onTextChanged: { + var portNumber = parseInt(text); + if (!isNaN(portNumber) && portNumber !== pwarController.listenPort) { + pwarController.listenPort = portNumber; } } diff --git a/linux/windows_sim.c b/linux/windows_sim.c index 653ea58..9c32ea1 100644 --- a/linux/windows_sim.c +++ b/linux/windows_sim.c @@ -49,6 +49,7 @@ static void setup_recv_socket(int port) { recv_addr.sin_family = AF_INET; recv_addr.sin_addr.s_addr = INADDR_ANY; recv_addr.sin_port = htons(port); + printf("about to bind on local port %d...\n", port); if (bind(recv_sockfd, (struct sockaddr *)&recv_addr, sizeof(recv_addr)) < 0) { perror("recv socket bind failed"); exit(EXIT_FAILURE);