HLE/Qt: implement sys_tty_read

This commit is contained in:
Megamouse 2018-06-29 07:59:56 +02:00 committed by Ivan
parent 29270ed673
commit a19113025c
4 changed files with 170 additions and 6 deletions

View File

@ -1,17 +1,87 @@
#include "stdafx.h"
#include "sys_tty.h"
#include <deque>
#include <mutex>
logs::channel sys_tty("sys_tty");
extern fs::file g_tty;
extern atomic_t<s64> g_tty_size;
extern std::array<std::deque<std::string>, 16> g_tty_input;
extern std::mutex g_tty_mutex;
error_code sys_tty_read(s32 ch, vm::ptr<char> buf, u32 len, vm::ptr<u32> preadlen)
{
sys_tty.fatal("sys_tty_read(ch=%d, buf=*0x%x, len=%d, preadlen=*0x%x)", ch, buf, len, preadlen);
sys_tty.trace("sys_tty_read(ch=%d, buf=*0x%x, len=%d, preadlen=*0x%x)", ch, buf, len, preadlen);
// We currently do not support reading from the Console
fmt::throw_exception("Unimplemented" HERE);
if (false) // TODO: debug mode check
{
return CELL_EIO;
}
if (ch > 15 || !buf)
{
return CELL_EINVAL;
}
if (ch < SYS_TTYP_USER1)
{
sys_tty.warning("sys_tty_read called with system channel %d", ch);
}
size_t chars_to_read = 0; // number of chars that will be read from the input string
std::string tty_read; // string for storage of read chars
if (len > 0)
{
std::lock_guard<std::mutex> lock(g_tty_mutex);
if (g_tty_input[ch].size() > 0)
{
// reference to our first queue element
std::string& input = g_tty_input[ch].front();
// we have to stop reading at either a new line, the param len, or our input string size
size_t new_line_pos = input.find_first_of("\n");
if (new_line_pos != input.npos)
{
chars_to_read = std::min(new_line_pos, static_cast<size_t>(len));
}
else
{
chars_to_read = std::min(input.size(), static_cast<size_t>(len));
}
// read the previously calculated number of chars from the beginning of the input string
tty_read = input.substr(0, chars_to_read);
// remove the just read text from the input string
input = input.substr(chars_to_read, input.size() - 1);
if (input.size() == 0)
{
// pop the first queue element if it was completely consumed
g_tty_input[ch].pop_front();
}
}
}
if (!preadlen)
{
return CELL_EFAULT;
}
*preadlen = (u32)chars_to_read;
if (chars_to_read > 0)
{
std::memcpy(buf.get_ptr(), tty_read.c_str(), chars_to_read);
sys_tty.success("sys_tty_read(ch=%d, len=%d) read %s with length %d", ch, len, tty_read, *preadlen);
}
return CELL_OK;
}
error_code sys_tty_write(s32 ch, vm::cptr<char> buf, u32 len, vm::ptr<u32> pwritelen)

View File

@ -64,6 +64,8 @@ extern void network_thread_init();
fs::file g_tty;
atomic_t<s64> g_tty_size{0};
std::array<std::deque<std::string>, 16> g_tty_input;
std::mutex g_tty_mutex;
// Progress display server synchronization variables
atomic_t<const char*> g_progr{nullptr};

View File

@ -9,8 +9,15 @@
#include <QActionGroup>
#include <QScrollBar>
#include <QTabBar>
#include <QVBoxLayout>
#include <deque>
#include "Utilities/sema.h"
extern fs::file g_tty;
extern atomic_t<s64> g_tty_size;
extern std::array<std::deque<std::string>, 16> g_tty_input;
extern std::mutex g_tty_mutex;
constexpr auto qstr = QString::fromStdString;
@ -123,8 +130,26 @@ log_frame::log_frame(std::shared_ptr<gui_settings> guiSettings, QWidget *parent)
m_tty->setContextMenuPolicy(Qt::CustomContextMenu);
m_tty->installEventFilter(this);
m_tty_input = new QLineEdit();
if (m_tty_channel >= 0)
{
m_tty_input->setPlaceholderText(tr("Channel %0").arg(m_tty_channel));
}
else
{
m_tty_input->setPlaceholderText(tr("All User Channels"));
}
QVBoxLayout* tty_layout = new QVBoxLayout();
tty_layout->addWidget(m_tty);
tty_layout->addWidget(m_tty_input);
tty_layout->setContentsMargins(0, 0, 0, 0);
m_tty_container = new QWidget();
m_tty_container->setLayout(tty_layout);
m_tabWidget->addTab(m_log, tr("Log"));
m_tabWidget->addTab(m_tty, tr("TTY"));
m_tabWidget->addTab(m_tty_container, tr("TTY"));
setWidget(m_tabWidget);
@ -212,6 +237,30 @@ void log_frame::CreateAndConnectActions()
m_clearTTYAct = new QAction(tr("Clear"), this);
connect(m_clearTTYAct, &QAction::triggered, m_tty, &QTextEdit::clear);
m_tty_channel_acts = new QActionGroup(this);
// Special Channel: All
QAction* all_channels_act = new QAction(tr("All user channels"), m_tty_channel_acts);
all_channels_act->setCheckable(true);
all_channels_act->setChecked(m_tty_channel == -1);
connect(all_channels_act, &QAction::triggered, [this]()
{
m_tty_channel = -1;
m_tty_input->setPlaceholderText(tr("All user channels"));
});
for (int i = 3; i < 16; i++)
{
QAction* act = new QAction(tr("Channel %0").arg(i), m_tty_channel_acts);
act->setCheckable(true);
act->setChecked(i == m_tty_channel);
connect(act, &QAction::triggered, [this, i]()
{
m_tty_channel = i;
m_tty_input->setPlaceholderText(tr("Channel %0").arg(m_tty_channel));
});
}
// Action groups make these actions mutually exclusive.
m_logLevels = new QActionGroup(this);
m_nothingAct = new QAction(tr("Nothing"), m_logLevels);
@ -253,7 +302,7 @@ void log_frame::CreateAndConnectActions()
QMenu* menu = m_log->createStandardContextMenu();
menu->addAction(m_clearAct);
menu->addSeparator();
menu->addActions({ m_nothingAct, m_fatalAct, m_errorAct, m_todoAct, m_successAct, m_warningAct, m_noticeAct, m_traceAct });
menu->addActions(m_logLevels->actions());
menu->addSeparator();
menu->addAction(m_stackAct);
menu->addSeparator();
@ -265,6 +314,8 @@ void log_frame::CreateAndConnectActions()
{
QMenu* menu = m_tty->createStandardContextMenu();
menu->addAction(m_clearTTYAct);
menu->addSeparator();
menu->addActions(m_tty_channel_acts->actions());
menu->exec(mapToGlobal(pos));
});
@ -274,6 +325,42 @@ void log_frame::CreateAndConnectActions()
m_find_dialog->close();
});
connect(m_tty_input, &QLineEdit::returnPressed, [this]()
{
std::string text = m_tty_input->text().toStdString();
{
std::lock_guard<std::mutex> lock(g_tty_mutex);
if (m_tty_channel == -1)
{
for (int i = 3; i < 16; i++)
{
g_tty_input[i].push_back(text + "\n");
}
}
else
{
g_tty_input[m_tty_channel].push_back(text + "\n");
}
}
// Write to tty
if (m_tty_channel == -1)
{
text = "All channels > " + text + "\n";
}
else
{
text = fmt::format("%s > %s\n", "Ch.%d", m_tty_channel, text);
}
g_tty_size -= (1ll << 48);
g_tty.write(text.c_str(), text.size());
g_tty_size += (1ll << 48) + text.size();
m_tty_input->clear();
});
LoadSettings();
}

View File

@ -49,12 +49,15 @@ private:
QList<QColor> m_color;
QColor m_color_stack;
QTextEdit* m_log;
QTextEdit* m_tty;
QString m_old_text;
ullong m_log_counter;
bool m_stack_log;
fs::file m_tty_file;
QWidget* m_tty_container;
QTextEdit* m_tty;
QLineEdit* m_tty_input;
int m_tty_channel = -1;
QAction* m_clearAct;
QAction* m_clearTTYAct;
@ -73,5 +76,7 @@ private:
QAction* m_TTYAct;
QActionGroup* m_tty_channel_acts;
std::shared_ptr<gui_settings> xgui_settings;
};