mirror of
https://github.com/ggerganov/ggwave.git
synced 2026-02-06 16:47:59 +08:00
ggwave-gui : add volume and protocol selection
This commit is contained in:
@@ -96,7 +96,8 @@ int main(int argc, char** argv) {
|
||||
bool received;
|
||||
std::time_t timestamp;
|
||||
std::string data;
|
||||
std::string protocol;
|
||||
int protocolId;
|
||||
float volume;
|
||||
};
|
||||
|
||||
struct State {
|
||||
@@ -137,7 +138,12 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
if (inputCurrent.update) {
|
||||
ggWave->init(inputCurrent.message.data.size(), inputCurrent.message.data.data(), ggWave->getTxProtocols()[2], 50);
|
||||
ggWave->init(
|
||||
inputCurrent.message.data.size(),
|
||||
inputCurrent.message.data.data(),
|
||||
ggWave->getTxProtocols()[inputCurrent.message.protocolId],
|
||||
100*inputCurrent.message.volume);
|
||||
|
||||
inputCurrent.update = false;
|
||||
}
|
||||
|
||||
@@ -146,7 +152,13 @@ int main(int argc, char** argv) {
|
||||
lastRxDataLength = ggWave->takeRxData(lastRxData);
|
||||
if (lastRxDataLength > 0) {
|
||||
buffer.stateCore.update = true;
|
||||
buffer.stateCore.message = { true, std::time(nullptr), std::string((char *) lastRxData.data(), lastRxDataLength), "" };
|
||||
buffer.stateCore.message = {
|
||||
true,
|
||||
std::time(nullptr),
|
||||
std::string((char *) lastRxData.data(), lastRxDataLength),
|
||||
ggWave->getRxProtocolId(),
|
||||
0,
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
@@ -176,6 +188,20 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
enum class WindowId {
|
||||
Settings,
|
||||
Messages,
|
||||
Commands,
|
||||
};
|
||||
|
||||
struct Settings {
|
||||
int protocolId = 1;
|
||||
float volume = 0.25f;
|
||||
};
|
||||
|
||||
static WindowId windowId = WindowId::Messages;
|
||||
static Settings settings;
|
||||
|
||||
static char inputBuf[256];
|
||||
|
||||
static bool doInputFocus = false;
|
||||
@@ -222,106 +248,162 @@ int main(int argc, char** argv) {
|
||||
ImGui::InvisibleButton("StatusBar", { ImGui::GetContentRegionAvailWidth(), statusBarHeight });
|
||||
|
||||
if (ImGui::Button(ICON_FA_COGS, { menuButtonHeight, menuButtonHeight } )) {
|
||||
windowId = WindowId::Settings;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button(ICON_FA_COMMENT_ALT " Messages", { 0.5f*ImGui::GetContentRegionAvailWidth(), menuButtonHeight })) {
|
||||
windowId = WindowId::Messages;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button(ICON_FA_LIST_UL " Commands", { 1.0f*ImGui::GetContentRegionAvailWidth(), menuButtonHeight })) {
|
||||
windowId = WindowId::Commands;
|
||||
}
|
||||
|
||||
const float messagesInputHeight = ImGui::GetTextLineHeightWithSpacing();
|
||||
const float messagesHistoryHeigthMax = ImGui::GetContentRegionAvail().y - messagesInputHeight - 2.0f*style.ItemSpacing.x;
|
||||
float messagesHistoryHeigth = messagesHistoryHeigthMax;
|
||||
if (windowId == WindowId::Settings) {
|
||||
ImGui::BeginChild("Settings:main", ImGui::GetContentRegionAvail(), true);
|
||||
ImGui::Text("Waver v0.1");
|
||||
ImGui::Separator();
|
||||
|
||||
// no automatic screen resize support for iOS
|
||||
ImGui::Text("%s", "");
|
||||
ImGui::Text("Sample rate (capture): %g, %d B/sample", ggWave->getSampleRateIn(), ggWave->getSampleSizeBytesIn());
|
||||
ImGui::Text("Sample rate (playback): %g, %d B/sample", ggWave->getSampleRateOut(), ggWave->getSampleSizeBytesOut());
|
||||
|
||||
static float kLabelWidth = 100.0f;
|
||||
|
||||
// volume
|
||||
ImGui::Text("%s", "");
|
||||
{
|
||||
auto posSave = ImGui::GetCursorScreenPos();
|
||||
ImGui::Text("Volume: ");
|
||||
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
|
||||
}
|
||||
ImGui::SliderFloat("##volume", &settings.volume, 0.0f, 1.0f);
|
||||
|
||||
// protocol
|
||||
ImGui::Text("%s", "");
|
||||
{
|
||||
auto posSave = ImGui::GetCursorScreenPos();
|
||||
ImGui::Text("Tx Protocol: ");
|
||||
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::BeginCombo("##protocol", ggWave->getTxProtocols()[settings.protocolId].name)) {
|
||||
for (int i = 0; i < (int) ggWave->getTxProtocols().size(); ++i) {
|
||||
const bool isSelected = (settings.protocolId == i);
|
||||
if (ImGui::Selectable(ggWave->getTxProtocols()[i].name, isSelected)) {
|
||||
settings.protocolId = i;
|
||||
}
|
||||
|
||||
if (isSelected) {
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
if (windowId == WindowId::Messages) {
|
||||
const float messagesInputHeight = ImGui::GetTextLineHeightWithSpacing();
|
||||
const float messagesHistoryHeigthMax = ImGui::GetContentRegionAvail().y - messagesInputHeight - 2.0f*style.ItemSpacing.x;
|
||||
float messagesHistoryHeigth = messagesHistoryHeigthMax;
|
||||
|
||||
// no automatic screen resize support for iOS
|
||||
#ifdef IOS
|
||||
if (displaySize.x < displaySize.y) {
|
||||
if (isTextInput) {
|
||||
messagesHistoryHeigth -= 0.5f*messagesHistoryHeigthMax*std::min(tShowKeyboard, ImGui::GetTime() - tStartInput) / tShowKeyboard;
|
||||
if (displaySize.x < displaySize.y) {
|
||||
if (isTextInput) {
|
||||
messagesHistoryHeigth -= 0.5f*messagesHistoryHeigthMax*std::min(tShowKeyboard, ImGui::GetTime() - tStartInput) / tShowKeyboard;
|
||||
} else {
|
||||
messagesHistoryHeigth -= 0.5f*messagesHistoryHeigthMax - 0.5f*messagesHistoryHeigthMax*std::min(tShowKeyboard, ImGui::GetTime() - tEndInput) / tShowKeyboard;
|
||||
}
|
||||
} else {
|
||||
messagesHistoryHeigth -= 0.5f*messagesHistoryHeigthMax - 0.5f*messagesHistoryHeigthMax*std::min(tShowKeyboard, ImGui::GetTime() - tEndInput) / tShowKeyboard;
|
||||
if (isTextInput) {
|
||||
messagesHistoryHeigth -= 0.5f*displaySize.y*std::min(tShowKeyboard, ImGui::GetTime() - tStartInput) / tShowKeyboard;
|
||||
} else {
|
||||
messagesHistoryHeigth -= 0.5f*displaySize.y - 0.5f*displaySize.y*std::min(tShowKeyboard, ImGui::GetTime() - tEndInput) / tShowKeyboard;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isTextInput) {
|
||||
messagesHistoryHeigth -= 0.5f*displaySize.y*std::min(tShowKeyboard, ImGui::GetTime() - tStartInput) / tShowKeyboard;
|
||||
} else {
|
||||
messagesHistoryHeigth -= 0.5f*displaySize.y - 0.5f*displaySize.y*std::min(tShowKeyboard, ImGui::GetTime() - tEndInput) / tShowKeyboard;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ImGui::BeginChild("Messages:history", { ImGui::GetContentRegionAvailWidth(), messagesHistoryHeigth }, true);
|
||||
ImGui::BeginChild("Messages:history", { ImGui::GetContentRegionAvailWidth(), messagesHistoryHeigth }, true);
|
||||
|
||||
for (int i = 0; i < (int) messageHistory.size(); ++i) {
|
||||
ImGui::PushID(i);
|
||||
const auto & message = messageHistory[i];
|
||||
if (message.received) {
|
||||
ImGui::TextColored({ 0.0f, 1.0f, 0.0f, 1.0f }, "[%s] Recv:", ::toTimeString(message.timestamp));
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SmallButton("Resend")) {
|
||||
buffer.inputUI.update = true;
|
||||
buffer.inputUI.message = { false, std::time(nullptr), message.data, "" };
|
||||
for (int i = 0; i < (int) messageHistory.size(); ++i) {
|
||||
ImGui::PushID(i);
|
||||
const auto & message = messageHistory[i];
|
||||
if (message.received) {
|
||||
ImGui::TextColored({ 0.0f, 1.0f, 0.0f, 1.0f }, "[%s] Recv (%s):", ::toTimeString(message.timestamp), ggWave->getTxProtocols()[message.protocolId].name);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SmallButton("Resend")) {
|
||||
buffer.inputUI.update = true;
|
||||
buffer.inputUI.message = { false, std::time(nullptr), message.data, message.protocolId, settings.volume };
|
||||
|
||||
messageHistory.push_back(buffer.inputUI.message);
|
||||
messageHistory.push_back(buffer.inputUI.message);
|
||||
}
|
||||
ImGui::Text("%s", message.data.c_str());
|
||||
} else {
|
||||
ImGui::TextColored({ 1.0f, 1.0f, 0.0f, 1.0f }, "[%s] Sent (%s):", ::toTimeString(message.timestamp), ggWave->getTxProtocols()[message.protocolId].name);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SmallButton("Resend")) {
|
||||
buffer.inputUI.update = true;
|
||||
buffer.inputUI.message = { false, std::time(nullptr), message.data, message.protocolId, settings.volume };
|
||||
|
||||
messageHistory.push_back(buffer.inputUI.message);
|
||||
}
|
||||
ImGui::Text("%s", message.data.c_str());
|
||||
}
|
||||
ImGui::Text("%s", message.data.c_str());
|
||||
} else {
|
||||
ImGui::TextColored({ 1.0f, 1.0f, 0.0f, 1.0f }, "[%s] Sent:", ::toTimeString(message.timestamp));
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SmallButton("Resend")) {
|
||||
buffer.inputUI.update = true;
|
||||
buffer.inputUI.message = { false, std::time(nullptr), message.data, "" };
|
||||
|
||||
messageHistory.push_back(buffer.inputUI.message);
|
||||
}
|
||||
ImGui::Text("%s", message.data.c_str());
|
||||
ImGui::Text("%s", "");
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
if (scrollMessagesToBottom) {
|
||||
ImGui::SetScrollHereY();
|
||||
scrollMessagesToBottom = false;
|
||||
}
|
||||
|
||||
ImVec2 mouse_delta = ImGui::GetIO().MouseDelta;
|
||||
ScrollWhenDraggingOnVoid(ImVec2(0.0f, -mouse_delta.y), ImGuiMouseButton_Left);
|
||||
ImGui::EndChild();
|
||||
|
||||
if (doInputFocus) {
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
doInputFocus = false;
|
||||
}
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() - ImGui::CalcTextSize(sendButtonText).x - 2*style.ItemSpacing.x);
|
||||
ImGui::InputText("##Messages:Input", inputBuf, 256, ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
ImGui::PopItemWidth();
|
||||
if (ImGui::IsItemActive() && isTextInput == false) {
|
||||
SDL_StartTextInput();
|
||||
isTextInput = true;
|
||||
tStartInput = ImGui::GetTime();
|
||||
}
|
||||
bool requestStopTextInput = false;
|
||||
if (ImGui::IsItemDeactivated()) {
|
||||
requestStopTextInput = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(sendButtonText) && inputBuf[0] != 0) {
|
||||
buffer.inputUI.update = true;
|
||||
buffer.inputUI.message = { false, std::time(nullptr), std::string(inputBuf), settings.protocolId, settings.volume };
|
||||
|
||||
messageHistory.push_back(buffer.inputUI.message);
|
||||
|
||||
inputBuf[0] = 0;
|
||||
doInputFocus = true;
|
||||
}
|
||||
if (!ImGui::IsItemHovered() && requestStopTextInput) {
|
||||
SDL_StopTextInput();
|
||||
isTextInput = false;
|
||||
tEndInput = ImGui::GetTime();
|
||||
}
|
||||
ImGui::Text("%s", "");
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
if (scrollMessagesToBottom) {
|
||||
ImGui::SetScrollHereY();
|
||||
scrollMessagesToBottom = false;
|
||||
}
|
||||
|
||||
ImVec2 mouse_delta = ImGui::GetIO().MouseDelta;
|
||||
ScrollWhenDraggingOnVoid(ImVec2(0.0f, -mouse_delta.y), ImGuiMouseButton_Left);
|
||||
ImGui::EndChild();
|
||||
|
||||
if (doInputFocus) {
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
doInputFocus = false;
|
||||
}
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() - ImGui::CalcTextSize(sendButtonText).x - 2*style.ItemSpacing.x);
|
||||
ImGui::InputText("##Messages:Input", inputBuf, 256, ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
ImGui::PopItemWidth();
|
||||
if (ImGui::IsItemActive() && isTextInput == false) {
|
||||
SDL_StartTextInput();
|
||||
isTextInput = true;
|
||||
tStartInput = ImGui::GetTime();
|
||||
}
|
||||
bool requestStopTextInput = false;
|
||||
if (ImGui::IsItemDeactivated()) {
|
||||
requestStopTextInput = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(sendButtonText) && inputBuf[0] != 0) {
|
||||
buffer.inputUI.update = true;
|
||||
buffer.inputUI.message = { false, std::time(nullptr), std::string(inputBuf), "" };
|
||||
|
||||
messageHistory.push_back(buffer.inputUI.message);
|
||||
|
||||
inputBuf[0] = 0;
|
||||
doInputFocus = true;
|
||||
}
|
||||
if (!ImGui::IsItemHovered() && requestStopTextInput) {
|
||||
SDL_StopTextInput();
|
||||
isTextInput = false;
|
||||
tEndInput = ImGui::GetTime();
|
||||
if (windowId == WindowId::Commands) {
|
||||
ImGui::BeginChild("Commands:main", ImGui::GetContentRegionAvail(), true);
|
||||
ImGui::Text("Todo");
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
@@ -72,12 +72,14 @@ public:
|
||||
const int & getSampleSizeBytesOut() const { return m_sampleSizeBytesOut; }
|
||||
|
||||
const float & getSampleRateIn() const { return m_sampleRateIn; }
|
||||
const float & getSampleRateOut() const { return m_sampleRateOut; }
|
||||
|
||||
const TxProtocol & getDefultTxProtocol() const { return kTxProtocols[1]; }
|
||||
const TxProtocols & getTxProtocols() const { return kTxProtocols; }
|
||||
|
||||
const TxRxData & getRxData() const { return m_rxData; }
|
||||
const TxProtocol & getRxProtocol() const { return m_rxProtocol; }
|
||||
const int & getRxProtocolId() const { return m_rxProtocolId; }
|
||||
int takeRxData(TxRxData & dst);
|
||||
|
||||
private:
|
||||
@@ -128,6 +130,7 @@ private:
|
||||
int m_lastRxDataLength;
|
||||
TxRxData m_rxData;
|
||||
TxProtocol m_rxProtocol;
|
||||
int m_rxProtocolId;
|
||||
|
||||
int m_historyId = 0;
|
||||
AmplitudeData m_sampleAmplitudeAverage;
|
||||
|
||||
@@ -427,7 +427,9 @@ void GGWave::receive(const CBDequeueAudio & CBDequeueAudio) {
|
||||
std::unique_ptr<RS::ReedSolomon> rsData;
|
||||
|
||||
bool isValid = false;
|
||||
for (const auto & rxProtocol : kTxProtocols) {
|
||||
for (int rxProtocolId = 0; rxProtocolId < (int) kTxProtocols.size(); ++rxProtocolId) {
|
||||
const auto & rxProtocol = kTxProtocols[rxProtocolId];
|
||||
|
||||
// skip Rx protocol if start frequency is different from detected one
|
||||
if (rxProtocol.freqStart != m_markerFreqStart) {
|
||||
continue;
|
||||
@@ -517,6 +519,7 @@ void GGWave::receive(const CBDequeueAudio & CBDequeueAudio) {
|
||||
m_hasNewRxData = true;
|
||||
m_lastRxDataLength = decodedLength;
|
||||
m_rxProtocol = rxProtocol;
|
||||
m_rxProtocolId = rxProtocolId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user