mirror of
https://github.com/ggerganov/ggwave.git
synced 2026-04-20 21:26:30 +08:00
ggwave-gui : polishing UX
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
#include "ggwave-common-sdl2.h"
|
#include "ggwave-common-sdl2.h"
|
||||||
|
|
||||||
#include "ggwave/ggwave.h"
|
|
||||||
|
|
||||||
#include "ggwave-common.h"
|
#include "ggwave-common.h"
|
||||||
|
|
||||||
|
#include "ggwave/ggwave.h"
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
#include <SDL_opengl.h>
|
#include <SDL_opengl.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
@@ -14,8 +15,6 @@
|
|||||||
#define EMSCRIPTEN_KEEPALIVE
|
#define EMSCRIPTEN_KEEPALIVE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr double kBaseSampleRate = 48000.0;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
std::string g_defaultCaptureDeviceName = "";
|
std::string g_defaultCaptureDeviceName = "";
|
||||||
@@ -31,6 +30,7 @@ GGWave *g_ggWave = nullptr;
|
|||||||
}
|
}
|
||||||
|
|
||||||
// JS interface
|
// JS interface
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
EMSCRIPTEN_KEEPALIVE
|
EMSCRIPTEN_KEEPALIVE
|
||||||
int sendData(int textLength, const char * text, int protocolId, int volume) {
|
int sendData(int textLength, const char * text, int protocolId, int volume) {
|
||||||
@@ -117,7 +117,7 @@ bool GGWave_init(
|
|||||||
SDL_AudioSpec playbackSpec;
|
SDL_AudioSpec playbackSpec;
|
||||||
SDL_zero(playbackSpec);
|
SDL_zero(playbackSpec);
|
||||||
|
|
||||||
playbackSpec.freq = ::kBaseSampleRate;
|
playbackSpec.freq = GGWave::kBaseSampleRate;
|
||||||
playbackSpec.format = AUDIO_S16SYS;
|
playbackSpec.format = AUDIO_S16SYS;
|
||||||
playbackSpec.channels = 1;
|
playbackSpec.channels = 1;
|
||||||
playbackSpec.samples = 16*1024;
|
playbackSpec.samples = 16*1024;
|
||||||
@@ -160,7 +160,7 @@ bool GGWave_init(
|
|||||||
if (g_devIdIn == 0) {
|
if (g_devIdIn == 0) {
|
||||||
SDL_AudioSpec captureSpec;
|
SDL_AudioSpec captureSpec;
|
||||||
captureSpec = g_obtainedSpecOut;
|
captureSpec = g_obtainedSpecOut;
|
||||||
captureSpec.freq = ::kBaseSampleRate;
|
captureSpec.freq = GGWave::kBaseSampleRate;
|
||||||
captureSpec.format = AUDIO_F32SYS;
|
captureSpec.format = AUDIO_F32SYS;
|
||||||
captureSpec.samples = 4096;
|
captureSpec.samples = 4096;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL.h>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class GGWave;
|
class GGWave;
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
// some basic helper methods for the examples
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
float getTime_ms(const T & tStart, const T & tEnd) {
|
float getTime_ms(const T & tStart, const T & tEnd) {
|
||||||
return ((float)(std::chrono::duration_cast<std::chrono::microseconds>(tEnd - tStart).count()))/1000.0;
|
return ((float)(std::chrono::duration_cast<std::chrono::microseconds>(tEnd - tStart).count()))/1000.0;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
@@ -60,10 +61,59 @@ void ScrollWhenDraggingOnVoid(const ImVec2& delta, ImGuiMouseButton mouse_button
|
|||||||
if (held && delta.y != 0.0f)
|
if (held && delta.y != 0.0f)
|
||||||
ImGui::SetScrollY(window, window->Scroll.y + delta.y);
|
ImGui::SetScrollY(window, window->Scroll.y + delta.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * kFileBroadcastPrefix = "\xbc";
|
namespace ImGui {
|
||||||
|
bool ButtonDisabled(const char* label, const ImVec2& size = ImVec2(0, 0)) {
|
||||||
|
{
|
||||||
|
auto col = ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled);
|
||||||
|
col.x *= 0.8;
|
||||||
|
col.y *= 0.8;
|
||||||
|
col.z *= 0.8;
|
||||||
|
PushStyleColor(ImGuiCol_Button, col);
|
||||||
|
PushStyleColor(ImGuiCol_ButtonHovered, col);
|
||||||
|
PushStyleColor(ImGuiCol_ButtonActive, col);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto col = ImGui::GetStyleColorVec4(ImGuiCol_Text);
|
||||||
|
col.x *= 0.75;
|
||||||
|
col.y *= 0.75;
|
||||||
|
col.z *= 0.75;
|
||||||
|
PushStyleColor(ImGuiCol_Text, col);
|
||||||
|
}
|
||||||
|
bool result = Button(label, size);
|
||||||
|
PopStyleColor(4);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ButtonDisablable(const char* label, const ImVec2& size = ImVec2(0, 0), bool isDisabled = false) {
|
||||||
|
if (isDisabled) {
|
||||||
|
ButtonDisabled(label, size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Button(label, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ButtonSelected(const char* label, const ImVec2& size = ImVec2(0, 0)) {
|
||||||
|
auto col = ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive);
|
||||||
|
PushStyleColor(ImGuiCol_Button, col);
|
||||||
|
PushStyleColor(ImGuiCol_ButtonHovered, col);
|
||||||
|
bool result = Button(label, size);
|
||||||
|
PopStyleColor(2);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ButtonSelectable(const char* label, const ImVec2& size = ImVec2(0, 0), bool isSelected = false) {
|
||||||
|
if (isSelected) return ButtonSelected(label, size);
|
||||||
|
return Button(label, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char * kFileBroadcastPrefix = "\xba\xbc\xbb";
|
||||||
static const int kMaxSimultaneousChunkRequests = 4;
|
static const int kMaxSimultaneousChunkRequests = 4;
|
||||||
|
static const float kBroadcastTime_sec = 60.0f;
|
||||||
|
|
||||||
struct Message {
|
struct Message {
|
||||||
enum Type {
|
enum Type {
|
||||||
@@ -157,7 +207,14 @@ Buffer g_buffer;
|
|||||||
std::atomic<bool> g_isRunning;
|
std::atomic<bool> g_isRunning;
|
||||||
|
|
||||||
// file send data
|
// file send data
|
||||||
|
struct BroadcastInfo {
|
||||||
|
std::string ip;
|
||||||
|
int port;
|
||||||
|
int key;
|
||||||
|
};
|
||||||
|
|
||||||
bool g_focusFileSend = false;
|
bool g_focusFileSend = false;
|
||||||
|
float g_tLastBroadcast = -100.0f;
|
||||||
GGSock::FileServer g_fileServer;
|
GGSock::FileServer g_fileServer;
|
||||||
|
|
||||||
// file received data
|
// file received data
|
||||||
@@ -238,8 +295,8 @@ bool confirmReceive(const char * uri) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_receivedFiles.erase(uri);
|
|
||||||
g_receivedFileInfosExtended[uri].readyToShare = true;
|
g_receivedFileInfosExtended[uri].readyToShare = true;
|
||||||
|
g_receivedFiles.erase(uri);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -264,7 +321,7 @@ void addFile(
|
|||||||
std::memcpy(file.data.data(), dataBuffer, dataSize);
|
std::memcpy(file.data.data(), dataBuffer, dataSize);
|
||||||
|
|
||||||
g_fileServer.addFile(std::move(file));
|
g_fileServer.addFile(std::move(file));
|
||||||
g_focusFileSend = true;
|
//g_focusFileSend = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addFile(
|
void addFile(
|
||||||
@@ -277,31 +334,83 @@ void addFile(
|
|||||||
file.data = std::move(data);
|
file.data = std::move(data);
|
||||||
|
|
||||||
g_fileServer.addFile(std::move(file));
|
g_fileServer.addFile(std::move(file));
|
||||||
g_focusFileSend = true;
|
//g_focusFileSend = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string generateFileBroadcastMessage() {
|
std::string generateFileBroadcastMessage() {
|
||||||
// todo : to binary
|
// todo : to binary
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
result = kFileBroadcastPrefix;
|
int plen = strlen(kFileBroadcastPrefix);
|
||||||
result += ' ';
|
result.resize(plen + 4 + 2 + 2);
|
||||||
result += GGSock::Communicator::getLocalAddress();
|
|
||||||
result += ' ';
|
char *p = &result[0];
|
||||||
result += std::to_string(g_fileServer.getParameters().listenPort);
|
for (int i = 0; i < (int) plen; ++i) {
|
||||||
result += ' ';
|
*p++ = kFileBroadcastPrefix[i];
|
||||||
result += std::to_string(rand()%32000); // todo : generated key should be used to authorize incoming messages
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto ip = GGSock::Communicator::getLocalAddress();
|
||||||
|
std::replace(ip.begin(), ip.end(), '.', ' ');
|
||||||
|
std::stringstream ss(ip);
|
||||||
|
|
||||||
|
{ int b; ss >> b; *p++ = b; }
|
||||||
|
{ int b; ss >> b; *p++ = b; }
|
||||||
|
{ int b; ss >> b; *p++ = b; }
|
||||||
|
{ int b; ss >> b; *p++ = b; }
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
uint16_t port = g_fileServer.getParameters().listenPort;
|
||||||
|
|
||||||
|
{ int b = port/256; *p++ = b; }
|
||||||
|
{ int b = port%256; *p++ = b; }
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
uint16_t key = rand()%65536;
|
||||||
|
|
||||||
|
{ int b = key/256; *p++ = b; }
|
||||||
|
{ int b = key%256; *p++ = b; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
BroadcastInfo parseBroadcastInfo(const std::string & message) {
|
||||||
|
BroadcastInfo result;
|
||||||
|
|
||||||
|
const uint8_t *p = (uint8_t *) message.data();
|
||||||
|
p += strlen(kFileBroadcastPrefix);
|
||||||
|
|
||||||
|
result.ip += std::to_string((uint8_t)(*p++));
|
||||||
|
result.ip += '.';
|
||||||
|
result.ip += std::to_string((uint8_t)(*p++));
|
||||||
|
result.ip += '.';
|
||||||
|
result.ip += std::to_string((uint8_t)(*p++));
|
||||||
|
result.ip += '.';
|
||||||
|
result.ip += std::to_string((uint8_t)(*p++));
|
||||||
|
|
||||||
|
result.port = 256*((int)(*p++));
|
||||||
|
result.port += ((int)(*p++));
|
||||||
|
|
||||||
|
result.key = 256*((int)(*p++));
|
||||||
|
result.key += ((int)(*p++));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFileBroadcastMessage(const std::string & message) {
|
bool isFileBroadcastMessage(const std::string & message) {
|
||||||
|
if (message.size() != strlen(kFileBroadcastPrefix) + 4 + 2 + 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
||||||
auto pSrc = kFileBroadcastPrefix;
|
auto pSrc = kFileBroadcastPrefix;
|
||||||
auto pDst = message.data();
|
auto pDst = message.data();
|
||||||
|
|
||||||
while (pSrc != 0) {
|
while (*pSrc != 0) {
|
||||||
if (*pDst == 0 || *pSrc++ != *pDst++) {
|
if (*pDst == 0 || *pSrc++ != *pDst++) {
|
||||||
result = false;
|
result = false;
|
||||||
break;
|
break;
|
||||||
@@ -390,6 +499,7 @@ std::thread initMain() {
|
|||||||
lastRxDataLength = g_ggWave->takeRxData(lastRxData);
|
lastRxDataLength = g_ggWave->takeRxData(lastRxData);
|
||||||
if (lastRxDataLength > 0) {
|
if (lastRxDataLength > 0) {
|
||||||
auto message = std::string((char *) lastRxData.data(), lastRxDataLength);
|
auto message = std::string((char *) lastRxData.data(), lastRxDataLength);
|
||||||
|
const Message::Type type = isFileBroadcastMessage(message) ? Message::FileBroadcast : Message::Text;
|
||||||
g_buffer.stateCore.update = true;
|
g_buffer.stateCore.update = true;
|
||||||
g_buffer.stateCore.flags.newMessage = true;
|
g_buffer.stateCore.flags.newMessage = true;
|
||||||
g_buffer.stateCore.message = {
|
g_buffer.stateCore.message = {
|
||||||
@@ -398,7 +508,7 @@ std::thread initMain() {
|
|||||||
std::move(message),
|
std::move(message),
|
||||||
g_ggWave->getRxProtocolId(),
|
g_ggWave->getRxProtocolId(),
|
||||||
0,
|
0,
|
||||||
isFileBroadcastMessage(message) ? Message::FileBroadcast : Message::Text,
|
type,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,6 +546,10 @@ std::thread initMain() {
|
|||||||
void renderMain() {
|
void renderMain() {
|
||||||
g_fileServer.update();
|
g_fileServer.update();
|
||||||
|
|
||||||
|
if (ImGui::GetTime() - g_tLastBroadcast > kBroadcastTime_sec && g_fileServer.isListening()) {
|
||||||
|
g_fileServer.stopListening();
|
||||||
|
}
|
||||||
|
|
||||||
if (g_fileClient.isConnected()) {
|
if (g_fileClient.isConnected()) {
|
||||||
if (!g_hasRequestedFileInfos) {
|
if (!g_hasRequestedFileInfos) {
|
||||||
g_receivedFileInfos.clear();
|
g_receivedFileInfos.clear();
|
||||||
@@ -482,23 +596,6 @@ void renderMain() {
|
|||||||
++fileInfoExtended.nRequestedChunks;
|
++fileInfoExtended.nRequestedChunks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//for (const auto & fileInfo : g_receivedFileInfos) {
|
|
||||||
// for (int i = 0; i < fileInfo.second.nChunks; ++i) {
|
|
||||||
// GGSock::FileServer::FileChunkRequestData data;
|
|
||||||
// data.uri = fileInfo.second.uri;
|
|
||||||
// data.chunkId = i;
|
|
||||||
// data.nChunksHave = 0;
|
|
||||||
// data.nChunksExpected = fileInfo.second.nChunks;
|
|
||||||
|
|
||||||
// GGSock::SerializationBuffer buffer;
|
|
||||||
// GGSock::Serialize()(data, buffer);
|
|
||||||
// g_fileClient.send(GGSock::FileServer::MsgFileChunkRequest, buffer.data(), (int32_t) buffer.size());
|
|
||||||
// g_fileClient.update();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//g_hasReceivedFiles = true;
|
|
||||||
//g_receivedId++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,22 +721,22 @@ void renderMain() {
|
|||||||
|
|
||||||
ImGui::InvisibleButton("StatusBar", { ImGui::GetContentRegionAvailWidth(), statusBarHeight });
|
ImGui::InvisibleButton("StatusBar", { ImGui::GetContentRegionAvailWidth(), statusBarHeight });
|
||||||
|
|
||||||
if (ImGui::Button(ICON_FA_COGS, { menuButtonHeight, menuButtonHeight } )) {
|
if (ImGui::ButtonSelectable(ICON_FA_COGS, { menuButtonHeight, menuButtonHeight }, windowId == WindowId::Settings )) {
|
||||||
windowId = WindowId::Settings;
|
windowId = WindowId::Settings;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if (ImGui::Button(ICON_FA_COMMENT_ALT " Messages", { 0.35f*ImGui::GetContentRegionAvailWidth(), menuButtonHeight })) {
|
if (ImGui::ButtonSelectable(ICON_FA_COMMENT_ALT " Messages", { 0.35f*ImGui::GetContentRegionAvailWidth(), menuButtonHeight }, windowId == WindowId::Messages)) {
|
||||||
windowId = WindowId::Messages;
|
windowId = WindowId::Messages;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if (ImGui::Button(ICON_FA_FILE " Files", { 0.40f*ImGui::GetContentRegionAvailWidth(), menuButtonHeight })) {
|
if (ImGui::ButtonSelectable(ICON_FA_FILE " Files", { 0.40f*ImGui::GetContentRegionAvailWidth(), menuButtonHeight }, windowId == WindowId::Files)) {
|
||||||
windowId = WindowId::Files;
|
windowId = WindowId::Files;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if (ImGui::Button(ICON_FA_SIGNAL " Spectrum", { 1.0f*ImGui::GetContentRegionAvailWidth(), menuButtonHeight })) {
|
if (ImGui::ButtonSelectable(ICON_FA_SIGNAL " Spectrum", { 1.0f*ImGui::GetContentRegionAvailWidth(), menuButtonHeight }, windowId == WindowId::Spectrum)) {
|
||||||
windowId = WindowId::Spectrum;
|
windowId = WindowId::Spectrum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -806,8 +903,8 @@ void renderMain() {
|
|||||||
if (message.type == Message::FileBroadcast) {
|
if (message.type == Message::FileBroadcast) {
|
||||||
auto col = ImVec4 { 0.0f, 1.0f, 1.0f, 1.0f };
|
auto col = ImVec4 { 0.0f, 1.0f, 1.0f, 1.0f };
|
||||||
col.w = interp;
|
col.w = interp;
|
||||||
ImGui::TextColored(col, "-=[ File Broadcast ]=-");
|
auto broadcastInfo = parseBroadcastInfo(message.data);
|
||||||
ImGui::TextColored(col, "%s", message.data.c_str());
|
ImGui::TextColored(col, "-=[ File Broadcast from %s:%d ]=-", broadcastInfo.ip.c_str(), broadcastInfo.port);
|
||||||
} else {
|
} else {
|
||||||
auto col = style.Colors[ImGuiCol_Text];
|
auto col = style.Colors[ImGuiCol_Text];
|
||||||
col.w = interp;
|
col.w = interp;
|
||||||
@@ -851,7 +948,7 @@ void renderMain() {
|
|||||||
if (ImGui::BeginPopup("Message options")) {
|
if (ImGui::BeginPopup("Message options")) {
|
||||||
const auto & messageSelected = messageHistory[messageIdHolding];
|
const auto & messageSelected = messageHistory[messageIdHolding];
|
||||||
|
|
||||||
if (ImGui::Button("Resend")) {
|
if (ImGui::ButtonDisablable("Resend", {}, messageSelected.type != Message::Text)) {
|
||||||
g_buffer.inputUI.update = true;
|
g_buffer.inputUI.update = true;
|
||||||
g_buffer.inputUI.message = { false, std::chrono::system_clock::now(), messageSelected.data, messageSelected.protocolId, settings.volume, Message::Text };
|
g_buffer.inputUI.message = { false, std::chrono::system_clock::now(), messageSelected.data, messageSelected.protocolId, settings.volume, Message::Text };
|
||||||
|
|
||||||
@@ -863,23 +960,21 @@ void renderMain() {
|
|||||||
ImGui::TextDisabled("|");
|
ImGui::TextDisabled("|");
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Copy")) {
|
if (ImGui::ButtonDisablable("Copy", {}, messageSelected.type != Message::Text)) {
|
||||||
SDL_SetClipboardText(messageSelected.data.c_str());
|
SDL_SetClipboardText(messageSelected.data.c_str());
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (messageSelected.received && messageSelected.type == Message::FileBroadcast) {
|
|
||||||
if (messageSelected.type == Message::FileBroadcast) {
|
if (messageSelected.type == Message::FileBroadcast) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::TextDisabled("|");
|
ImGui::TextDisabled("|");
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Receive")) {
|
if (ImGui::ButtonDisablable("Receive", {}, !messageSelected.received || messageSelected.type != Message::FileBroadcast)) {
|
||||||
std::string tmp = messageSelected.data.data() + strlen(kFileBroadcastPrefix);
|
auto broadcastInfo = parseBroadcastInfo(messageSelected.data);
|
||||||
std::stringstream ss(tmp);
|
|
||||||
|
|
||||||
ss >> g_remoteIP;
|
g_remoteIP = broadcastInfo.ip;
|
||||||
ss >> g_remotePort;
|
g_remotePort = broadcastInfo.port;
|
||||||
g_hasRemoteInfo = true;
|
g_hasRemoteInfo = true;
|
||||||
|
|
||||||
g_fileClient.disconnect();
|
g_fileClient.disconnect();
|
||||||
@@ -1053,26 +1148,29 @@ void renderMain() {
|
|||||||
if (windowId == WindowId::Files) {
|
if (windowId == WindowId::Files) {
|
||||||
const float subWindowButtonHeight = menuButtonHeight;
|
const float subWindowButtonHeight = menuButtonHeight;
|
||||||
|
|
||||||
if (ImGui::Button("Send", { 0.50f*ImGui::GetContentRegionAvailWidth(), subWindowButtonHeight })) {
|
if (ImGui::ButtonSelectable("Send", { 0.50f*ImGui::GetContentRegionAvailWidth(), subWindowButtonHeight }, subWindowId == SubWindowId::Send)) {
|
||||||
subWindowId = SubWindowId::Send;
|
subWindowId = SubWindowId::Send;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if (ImGui::Button("Receive", { 1.0f*ImGui::GetContentRegionAvailWidth(), subWindowButtonHeight })) {
|
if (ImGui::ButtonSelectable("Receive", { 1.0f*ImGui::GetContentRegionAvailWidth(), subWindowButtonHeight }, subWindowId == SubWindowId::Receive)) {
|
||||||
subWindowId = SubWindowId::Receive;
|
subWindowId = SubWindowId::Receive;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (subWindowId) {
|
switch (subWindowId) {
|
||||||
case SubWindowId::Send:
|
case SubWindowId::Send:
|
||||||
{
|
{
|
||||||
|
const float statusWindowHeight = 2*style.ItemInnerSpacing.y + 4*ImGui::GetTextLineHeightWithSpacing();
|
||||||
|
|
||||||
|
bool hasAtLeastOneFile = false;
|
||||||
{
|
{
|
||||||
const auto wSize = ImVec2 { ImGui::GetContentRegionAvailWidth(), 0.60f*ImGui::GetContentRegionAvail().y };
|
const auto wSize = ImVec2 { ImGui::GetContentRegionAvailWidth(), ImGui::GetContentRegionAvail().y - subWindowButtonHeight - statusWindowHeight - 2*style.ItemInnerSpacing.y };
|
||||||
|
|
||||||
ImGui::BeginChild("Files:Send:fileInfos", wSize, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
ImGui::BeginChild("Files:Send:fileInfos", wSize, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
||||||
|
|
||||||
//ImGui::PushTextWrapPos();
|
|
||||||
auto fileInfos = g_fileServer.getFileInfos();
|
auto fileInfos = g_fileServer.getFileInfos();
|
||||||
for (const auto & fileInfo : fileInfos) {
|
for (const auto & fileInfo : fileInfos) {
|
||||||
|
hasAtLeastOneFile = true;
|
||||||
ImGui::PushID(fileInfo.first);
|
ImGui::PushID(fileInfo.first);
|
||||||
ImGui::Text("File: '%s' (%4.2f MB)\n", fileInfo.second.filename.c_str(), float(fileInfo.second.filesize)/1024.0f/1024.0f);
|
ImGui::Text("File: '%s' (%4.2f MB)\n", fileInfo.second.filename.c_str(), float(fileInfo.second.filesize)/1024.0f/1024.0f);
|
||||||
if (ImGui::Button("Save")) {
|
if (ImGui::Button("Save")) {
|
||||||
@@ -1093,49 +1191,32 @@ void renderMain() {
|
|||||||
|
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
//ImGui::PopTextWrapPos();
|
|
||||||
|
ImGui::PushTextWrapPos();
|
||||||
|
if (hasAtLeastOneFile == false) {
|
||||||
|
ImGui::TextColored({ 1.0f, 1.0f, 0.0f, 1.0f }, "There are currently no files availble to share.");
|
||||||
|
#if defined(IOS) || defined(ANDROID)
|
||||||
|
ImGui::TextColored({ 1.0f, 1.0f, 0.0f, 1.0f }, "Share some files with this app to be able to broadcast them to nearby devices through sound.");
|
||||||
|
#else
|
||||||
|
ImGui::TextColored({ 1.0f, 1.0f, 0.0f, 1.0f }, "Drag and drop some files on this window to be able to broadcast them to nearby devices through sound.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
ImGui::PopTextWrapPos();
|
||||||
|
|
||||||
ScrollWhenDraggingOnVoid(ImVec2(-mouse_delta.x, -mouse_delta.y), ImGuiMouseButton_Left);
|
ScrollWhenDraggingOnVoid(ImVec2(-mouse_delta.x, -mouse_delta.y), ImGuiMouseButton_Left);
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
if (ImGui::Button("Broadcast", { 0.40f*ImGui::GetContentRegionAvailWidth(), subWindowButtonHeight })) {
|
|
||||||
g_buffer.inputUI.update = true;
|
|
||||||
g_buffer.inputUI.message = {
|
|
||||||
false,
|
|
||||||
std::chrono::system_clock::now(),
|
|
||||||
::generateFileBroadcastMessage(),
|
|
||||||
settings.protocolId,
|
|
||||||
settings.volume,
|
|
||||||
Message::FileBroadcast
|
|
||||||
};
|
|
||||||
|
|
||||||
messageHistory.push_back(g_buffer.inputUI.message);
|
|
||||||
|
|
||||||
g_fileServer.startListening();
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
if (ImGui::Button("Stop", { 0.50f*ImGui::GetContentRegionAvailWidth(), subWindowButtonHeight })) {
|
|
||||||
g_fileServer.stopListening();
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
if (ImGui::Button("Clear", { 1.0f*ImGui::GetContentRegionAvailWidth(), subWindowButtonHeight })) {
|
|
||||||
g_deleteInfo.uri = "###ALL-FILES###";
|
|
||||||
g_deleteInfo.filename = "";
|
|
||||||
g_deleteId++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto wSize = ImVec2 { ImGui::GetContentRegionAvailWidth(), ImGui::GetContentRegionAvail().y };
|
const auto wSize = ImVec2 { ImGui::GetContentRegionAvailWidth(), ImGui::GetContentRegionAvail().y - subWindowButtonHeight - style.ItemInnerSpacing.y };
|
||||||
|
|
||||||
ImGui::BeginChild("Files:Send:clientInfos", wSize, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
ImGui::BeginChild("Files:Send:clientInfos", wSize, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
||||||
|
|
||||||
if (g_fileServer.isListening() == false) {
|
if (g_fileServer.isListening() == false) {
|
||||||
ImGui::TextColored({ 1.0f, 1.0f, 0.0f, 1.0f }, "Not accepting new connections");
|
ImGui::TextColored({ 1.0f, 1.0f, 0.0f, 1.0f }, "Not accepting new connections.");
|
||||||
} else {
|
} else {
|
||||||
ImGui::TextColored({ 0.0f, 1.0f, 0.0f, 1.0f }, "Accepting new connections at %s:%d",
|
ImGui::TextColored({ 0.0f, 1.0f, 0.0f, 1.0f }, "Accepting new connections at: %s:%d (%4.1f sec)",
|
||||||
GGSock::Communicator::getLocalAddress().c_str(), g_fileServer.getParameters().listenPort);
|
GGSock::Communicator::getLocalAddress().c_str(), g_fileServer.getParameters().listenPort, kBroadcastTime_sec - ImGui::GetTime() + g_tLastBroadcast);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto clientInfos = g_fileServer.getClientInfos();
|
auto clientInfos = g_fileServer.getClientInfos();
|
||||||
@@ -1150,6 +1231,37 @@ void renderMain() {
|
|||||||
ScrollWhenDraggingOnVoid(ImVec2(-mouse_delta.x, -mouse_delta.y), ImGuiMouseButton_Left);
|
ScrollWhenDraggingOnVoid(ImVec2(-mouse_delta.x, -mouse_delta.y), ImGuiMouseButton_Left);
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
if (ImGui::Button("Broadcast", { 0.40f*ImGui::GetContentRegionAvailWidth(), subWindowButtonHeight })) {
|
||||||
|
g_buffer.inputUI.update = true;
|
||||||
|
g_buffer.inputUI.message = {
|
||||||
|
false,
|
||||||
|
std::chrono::system_clock::now(),
|
||||||
|
::generateFileBroadcastMessage(),
|
||||||
|
settings.protocolId,
|
||||||
|
settings.volume,
|
||||||
|
Message::FileBroadcast
|
||||||
|
};
|
||||||
|
|
||||||
|
messageHistory.push_back(g_buffer.inputUI.message);
|
||||||
|
|
||||||
|
g_tLastBroadcast = ImGui::GetTime();
|
||||||
|
g_fileServer.startListening();
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if (ImGui::ButtonDisablable("Stop", { 0.50f*ImGui::GetContentRegionAvailWidth(), subWindowButtonHeight }, !g_fileServer.isListening())) {
|
||||||
|
g_fileServer.stopListening();
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if (ImGui::ButtonDisablable("Clear", { 1.0f*ImGui::GetContentRegionAvailWidth(), subWindowButtonHeight }, !hasAtLeastOneFile)) {
|
||||||
|
g_deleteInfo.uri = "###ALL-FILES###";
|
||||||
|
g_deleteInfo.filename = "";
|
||||||
|
g_deleteId++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SubWindowId::Receive:
|
case SubWindowId::Receive:
|
||||||
@@ -1183,7 +1295,7 @@ void renderMain() {
|
|||||||
if (fileInfoExtended.readyToShare) {
|
if (fileInfoExtended.readyToShare) {
|
||||||
ImGui::TextColored({ 0.0f, 1.0f, 0.0f, 1.0f }, "Ready to share!");
|
ImGui::TextColored({ 0.0f, 1.0f, 0.0f, 1.0f }, "Ready to share!");
|
||||||
}
|
}
|
||||||
} else if (fileInfoExtended.isReceiving || fileInfoExtended.nReceivedChunks > 0) {
|
} else if (g_fileClient.isConnected() && (fileInfoExtended.isReceiving || fileInfoExtended.nReceivedChunks > 0)) {
|
||||||
if (fileInfoExtended.isReceiving) {
|
if (fileInfoExtended.isReceiving) {
|
||||||
if (ImGui::Button("Pause")) {
|
if (ImGui::Button("Pause")) {
|
||||||
fileInfoExtended.isReceiving = false;
|
fileInfoExtended.isReceiving = false;
|
||||||
@@ -1196,12 +1308,14 @@ void renderMain() {
|
|||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::ProgressBar(float(fileInfoExtended.nReceivedChunks)/fileInfo.second.nChunks);
|
ImGui::ProgressBar(float(fileInfoExtended.nReceivedChunks)/fileInfo.second.nChunks);
|
||||||
} else {
|
} else if (g_fileClient.isConnected()) {
|
||||||
if (ImGui::Button("Receive")) {
|
if (ImGui::Button("Receive")) {
|
||||||
fileInfoExtended.isReceiving = true;
|
fileInfoExtended.isReceiving = true;
|
||||||
fileInfoExtended.isChunkReceived.resize(fileInfo.second.nChunks);
|
fileInfoExtended.isChunkReceived.resize(fileInfo.second.nChunks);
|
||||||
fileInfoExtended.isChunkRequested.resize(fileInfo.second.nChunks);
|
fileInfoExtended.isChunkRequested.resize(fileInfo.second.nChunks);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ImGui::Text("%s", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fileInfoExtended.isReceiving == false || isReceived) && fileInfoExtended.requestToShare == false) {
|
if ((fileInfoExtended.isReceiving == false || isReceived) && fileInfoExtended.requestToShare == false) {
|
||||||
@@ -1225,6 +1339,7 @@ void renderMain() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
const auto wSize = ImVec2 { ImGui::GetContentRegionAvailWidth(), ImGui::GetContentRegionAvail().y - subWindowButtonHeight - style.ItemInnerSpacing.y };
|
const auto wSize = ImVec2 { ImGui::GetContentRegionAvailWidth(), ImGui::GetContentRegionAvail().y - subWindowButtonHeight - style.ItemInnerSpacing.y };
|
||||||
|
|
||||||
ImGui::BeginChild("Files:Receive:status", wSize, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
ImGui::BeginChild("Files:Receive:status", wSize, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
||||||
|
|
||||||
ImGui::PushTextWrapPos();
|
ImGui::PushTextWrapPos();
|
||||||
@@ -1243,25 +1358,27 @@ void renderMain() {
|
|||||||
ImGui::TextColored({ 1.0f, 1.0f, 0.0f, 1.0f }, "Attempting to connect ...");
|
ImGui::TextColored({ 1.0f, 1.0f, 0.0f, 1.0f }, "Attempting to connect ...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::PopTextWrapPos();
|
||||||
|
|
||||||
|
ScrollWhenDraggingOnVoid(ImVec2(-mouse_delta.x, -mouse_delta.y), ImGuiMouseButton_Left);
|
||||||
|
ImGui::EndChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PopTextWrapPos();
|
{
|
||||||
|
if (g_fileClient.isConnecting() == false && g_fileClient.isConnected() == false) {
|
||||||
ScrollWhenDraggingOnVoid(ImVec2(-mouse_delta.x, -mouse_delta.y), ImGuiMouseButton_Left);
|
if (ImGui::ButtonDisablable("Connect", { 1.00f*ImGui::GetContentRegionAvailWidth(), subWindowButtonHeight }, !g_hasRemoteInfo)) {
|
||||||
ImGui::EndChild();
|
g_fileClient.connect(g_remoteIP, g_remotePort, 0);
|
||||||
|
}
|
||||||
if (g_hasRemoteInfo && g_fileClient.isConnecting() == false && g_fileClient.isConnected() == false) {
|
|
||||||
if (ImGui::Button("Connect", { 1.00f*ImGui::GetContentRegionAvailWidth(), subWindowButtonHeight })) {
|
|
||||||
g_fileClient.connect(g_remoteIP, g_remotePort, 0);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (g_fileClient.isConnecting() || g_fileClient.isConnected()) {
|
if (g_fileClient.isConnecting() || g_fileClient.isConnected()) {
|
||||||
if (ImGui::Button("Disconnect", { 1.00f*ImGui::GetContentRegionAvailWidth(), subWindowButtonHeight })) {
|
if (ImGui::Button("Disconnect", { 1.00f*ImGui::GetContentRegionAvailWidth(), subWindowButtonHeight })) {
|
||||||
g_fileClient.disconnect();
|
g_fileClient.disconnect();
|
||||||
g_hasReceivedFileInfos = false;
|
g_hasReceivedFileInfos = false;
|
||||||
g_hasRequestedFileInfos = false;
|
g_hasRequestedFileInfos = false;
|
||||||
g_hasReceivedFiles = false;
|
g_hasReceivedFiles = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,10 @@ bool ImGui_BeginFrame(SDL_Window * window) {
|
|||||||
printf("Dropped file: '%s'\n", event.drop.file);
|
printf("Dropped file: '%s'\n", event.drop.file);
|
||||||
auto data = readFile(event.drop.file);
|
auto data = readFile(event.drop.file);
|
||||||
std::string uri = event.drop.file;
|
std::string uri = event.drop.file;
|
||||||
auto filename = uri.substr(uri.find_last_of("/\\") + 1);
|
std::string filename = event.drop.file;
|
||||||
|
if (uri.find("/") || uri.find("\\")) {
|
||||||
|
filename = uri.substr(uri.find_last_of("/\\") + 1);
|
||||||
|
}
|
||||||
addFile(uri.c_str(), filename.c_str(), std::move(data));
|
addFile(uri.c_str(), filename.c_str(), std::move(data));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -175,9 +178,9 @@ int main(int argc, char** argv) {
|
|||||||
auto worker = initMain();
|
auto worker = initMain();
|
||||||
|
|
||||||
// tmp
|
// tmp
|
||||||
addFile("test0.raw", "test0.raw", std::vector<char>(1024));
|
//addFile("test0.raw", "test0.raw", std::vector<char>(1024));
|
||||||
addFile("test1.jpg", "test0.jpg", std::vector<char>(1024*1024 + 624));
|
//addFile("test1.jpg", "test0.jpg", std::vector<char>(1024*1024 + 624));
|
||||||
addFile("test2.mpv", "test0.mov", std::vector<char>(1024*1024*234 + 53827));
|
//addFile("test2.mpv", "test0.mov", std::vector<char>(1024*1024*234 + 53827));
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (ImGui_BeginFrame(window) == false) {
|
if (ImGui_BeginFrame(window) == false) {
|
||||||
|
|||||||
2
examples/third-party/ggsock
vendored
2
examples/third-party/ggsock
vendored
Submodule examples/third-party/ggsock updated: 13852a1cf9...75b9ee1bcf
Reference in New Issue
Block a user