mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Improve Streamlink documentation (#5076)
Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
parent
5c9747e08f
commit
06f950a55b
|
@ -22,6 +22,7 @@
|
||||||
- Minor: The whisper highlight color can now be configured through the settings. (#5053)
|
- Minor: The whisper highlight color can now be configured through the settings. (#5053)
|
||||||
- Minor: Added missing periods at various moderator messages and commands. (#5061)
|
- Minor: Added missing periods at various moderator messages and commands. (#5061)
|
||||||
- Minor: Improved color selection and display. (#5057)
|
- Minor: Improved color selection and display. (#5057)
|
||||||
|
- Minor: Improved Streamlink documentation in the settings dialog. (#5076)
|
||||||
- Bugfix: Fixed an issue where certain emojis did not send to Twitch chat correctly. (#4840)
|
- Bugfix: Fixed an issue where certain emojis did not send to Twitch chat correctly. (#4840)
|
||||||
- Bugfix: Fixed capitalized channel names in log inclusion list not being logged. (#4848)
|
- Bugfix: Fixed capitalized channel names in log inclusion list not being logged. (#4848)
|
||||||
- Bugfix: Trimmed custom streamlink paths on all platforms making sure you don't accidentally add spaces at the beginning or end of its path. (#4834)
|
- Bugfix: Trimmed custom streamlink paths on all platforms making sure you don't accidentally add spaces at the beginning or end of its path. (#4834)
|
||||||
|
|
|
@ -15,118 +15,92 @@
|
||||||
#include <QErrorMessage>
|
#include <QErrorMessage>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
#include <QStringBuilder>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
namespace chatterino {
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const char *getBinaryName()
|
using namespace chatterino;
|
||||||
|
|
||||||
|
QString getStreamlinkPath()
|
||||||
|
{
|
||||||
|
if (getSettings()->streamlinkUseCustomPath)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
const QString path = getSettings()->streamlinkPath;
|
||||||
return "streamlink.exe";
|
return path.trimmed() % "/" % STREAMLINK_BINARY_NAME;
|
||||||
#else
|
|
||||||
return "streamlink";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *getDefaultBinaryPath()
|
return STREAMLINK_BINARY_NAME.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void showStreamlinkNotFoundError()
|
||||||
|
{
|
||||||
|
static auto *msg = new QErrorMessage;
|
||||||
|
msg->setWindowTitle("Chatterino - streamlink not found");
|
||||||
|
|
||||||
|
if (getSettings()->streamlinkUseCustomPath)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
msg->showMessage("Unable to find Streamlink executable\nMake sure "
|
||||||
return "C:\\Program Files (x86)\\Streamlink\\bin\\streamlink.exe";
|
"your custom path is pointing to the DIRECTORY "
|
||||||
#else
|
"where the streamlink executable is located");
|
||||||
return "/usr/bin/streamlink";
|
}
|
||||||
#endif
|
else
|
||||||
|
{
|
||||||
|
msg->showMessage(
|
||||||
|
"Unable to find Streamlink executable.\nIf you have Streamlink "
|
||||||
|
"installed, you might need to enable the custom path option");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QProcess *createStreamlinkProcess()
|
||||||
|
{
|
||||||
|
auto *p = new QProcess;
|
||||||
|
|
||||||
|
const auto path = getStreamlinkPath();
|
||||||
|
|
||||||
|
if (Version::instance().isFlatpak())
|
||||||
|
{
|
||||||
|
p->setProgram("flatpak-spawn");
|
||||||
|
p->setArguments({"--host", path});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p->setProgram(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkStreamlinkPath(const QString &path)
|
QObject::connect(p, &QProcess::errorOccurred, [=](auto err) {
|
||||||
{
|
if (err == QProcess::FailedToStart)
|
||||||
QFileInfo fileinfo(path);
|
|
||||||
|
|
||||||
if (!fileinfo.exists())
|
|
||||||
{
|
{
|
||||||
return false;
|
showStreamlinkNotFoundError();
|
||||||
// throw Exception(fS("Streamlink path ({}) is invalid, file does
|
|
||||||
// not exist", path));
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileinfo.isExecutable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void showStreamlinkNotFoundError()
|
|
||||||
{
|
|
||||||
static QErrorMessage *msg = new QErrorMessage;
|
|
||||||
msg->setWindowTitle("Chatterino - streamlink not found");
|
|
||||||
|
|
||||||
if (getSettings()->streamlinkUseCustomPath)
|
|
||||||
{
|
|
||||||
msg->showMessage("Unable to find Streamlink executable\nMake sure "
|
|
||||||
"your custom path is pointing to the DIRECTORY "
|
|
||||||
"where the streamlink executable is located");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
msg->showMessage(
|
qCWarning(chatterinoStreamlink) << "Error occurred" << err;
|
||||||
"Unable to find Streamlink executable.\nIf you have Streamlink "
|
|
||||||
"installed, you might need to enable the custom path option");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QProcess *createStreamlinkProcess()
|
|
||||||
{
|
|
||||||
auto *p = new QProcess;
|
|
||||||
|
|
||||||
const QString path = []() -> QString {
|
|
||||||
if (getSettings()->streamlinkUseCustomPath)
|
|
||||||
{
|
|
||||||
const QString path = getSettings()->streamlinkPath;
|
|
||||||
return path.trimmed() + "/" + getBinaryName();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {getBinaryName()};
|
|
||||||
}();
|
|
||||||
|
|
||||||
if (Version::instance().isFlatpak())
|
|
||||||
{
|
|
||||||
p->setProgram("flatpak-spawn");
|
|
||||||
p->setArguments({"--host", path});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
p->setProgram(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject::connect(p, &QProcess::errorOccurred, [=](auto err) {
|
p->deleteLater();
|
||||||
if (err == QProcess::FailedToStart)
|
});
|
||||||
{
|
|
||||||
showStreamlinkNotFoundError();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qCWarning(chatterinoStreamlink) << "Error occurred" << err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
p,
|
||||||
|
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(
|
||||||
|
&QProcess::finished),
|
||||||
|
[=](int /*exitCode*/, QProcess::ExitStatus /*exitStatus*/) {
|
||||||
p->deleteLater();
|
p->deleteLater();
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(
|
return p;
|
||||||
p,
|
}
|
||||||
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(
|
|
||||||
&QProcess::finished),
|
|
||||||
[=](int /*exitCode*/, QProcess::ExitStatus /*exitStatus*/) {
|
|
||||||
p->deleteLater();
|
|
||||||
});
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
void getStreamQualities(const QString &channelURL,
|
void getStreamQualities(const QString &channelURL,
|
||||||
std::function<void(QStringList)> cb)
|
std::function<void(QStringList)> cb)
|
||||||
{
|
{
|
||||||
auto p = createStreamlinkProcess();
|
auto *p = createStreamlinkProcess();
|
||||||
|
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
p,
|
p,
|
||||||
|
@ -146,7 +120,7 @@ void getStreamQualities(const QString &channelURL,
|
||||||
QStringList split =
|
QStringList split =
|
||||||
lastLine.right(lastLine.length() - 19).split(", ");
|
lastLine.right(lastLine.length() - 19).split(", ");
|
||||||
|
|
||||||
for (int i = split.length() - 1; i >= 0; i--)
|
for (auto i = split.length() - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
QString option = split.at(i);
|
QString option = split.at(i);
|
||||||
if (option == "best)")
|
if (option == "best)")
|
||||||
|
@ -186,7 +160,7 @@ void getStreamQualities(const QString &channelURL,
|
||||||
void openStreamlink(const QString &channelURL, const QString &quality,
|
void openStreamlink(const QString &channelURL, const QString &quality,
|
||||||
QStringList extraArguments)
|
QStringList extraArguments)
|
||||||
{
|
{
|
||||||
auto proc = createStreamlinkProcess();
|
auto *proc = createStreamlinkProcess();
|
||||||
auto arguments = proc->arguments()
|
auto arguments = proc->arguments()
|
||||||
<< extraArguments << channelURL << quality;
|
<< extraArguments << channelURL << quality;
|
||||||
|
|
||||||
|
@ -214,8 +188,8 @@ void openStreamlinkForChannel(const QString &channel)
|
||||||
getApp()->windows->getMainWindow().getNotebook().getSelectedPage());
|
getApp()->windows->getMainWindow().getNotebook().getSelectedPage());
|
||||||
if (currentPage != nullptr)
|
if (currentPage != nullptr)
|
||||||
{
|
{
|
||||||
if (auto currentSplit = currentPage->getSelectedSplit();
|
auto *currentSplit = currentPage->getSelectedSplit();
|
||||||
currentSplit != nullptr)
|
if (currentSplit != nullptr)
|
||||||
{
|
{
|
||||||
currentSplit->getChannel()->addMessage(
|
currentSplit->getChannel()->addMessage(
|
||||||
makeSystemMessage(INFO_TEMPLATE.arg(channel)));
|
makeSystemMessage(INFO_TEMPLATE.arg(channel)));
|
||||||
|
|
|
@ -14,6 +14,12 @@ public:
|
||||||
using std::runtime_error::runtime_error;
|
using std::runtime_error::runtime_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
constexpr inline QStringView STREAMLINK_BINARY_NAME = u"streamlink.exe";
|
||||||
|
#else
|
||||||
|
constexpr inline QStringView STREAMLINK_BINARY_NAME = u"streamlink";
|
||||||
|
#endif
|
||||||
|
|
||||||
// Open streamlink for given channel, quality and extra arguments
|
// Open streamlink for given channel, quality and extra arguments
|
||||||
// the "Additional arguments" are fetched and added at the beginning of the
|
// the "Additional arguments" are fetched and added at the beginning of the
|
||||||
// streamlink call
|
// streamlink call
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#include "ExternalToolsPage.hpp"
|
#include "widgets/settingspages/ExternalToolsPage.hpp"
|
||||||
|
|
||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
#include "util/Helpers.hpp"
|
#include "util/Helpers.hpp"
|
||||||
#include "util/LayoutCreator.hpp"
|
#include "util/LayoutCreator.hpp"
|
||||||
#include "util/RemoveScrollAreaBackground.hpp"
|
#include "util/RemoveScrollAreaBackground.hpp"
|
||||||
|
#include "util/StreamLink.hpp"
|
||||||
|
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
|
@ -28,7 +29,7 @@ ExternalToolsPage::ExternalToolsPage()
|
||||||
auto group = layout.emplace<QGroupBox>("Streamlink");
|
auto group = layout.emplace<QGroupBox>("Streamlink");
|
||||||
auto groupLayout = group.setLayoutType<QFormLayout>();
|
auto groupLayout = group.setLayoutType<QFormLayout>();
|
||||||
|
|
||||||
auto description = new QLabel(
|
auto *description = new QLabel(
|
||||||
"Streamlink is a command-line utility that pipes video streams "
|
"Streamlink is a command-line utility that pipes video streams "
|
||||||
"from various "
|
"from various "
|
||||||
"services into a video player, such as VLC. Make sure to edit the "
|
"services into a video player, such as VLC. Make sure to edit the "
|
||||||
|
@ -36,7 +37,7 @@ ExternalToolsPage::ExternalToolsPage()
|
||||||
description->setWordWrap(true);
|
description->setWordWrap(true);
|
||||||
description->setStyleSheet("color: #bbb");
|
description->setStyleSheet("color: #bbb");
|
||||||
|
|
||||||
auto links = new QLabel(
|
auto *links = new QLabel(
|
||||||
formatRichNamedLink("https://streamlink.github.io/", "Website") +
|
formatRichNamedLink("https://streamlink.github.io/", "Website") +
|
||||||
" " +
|
" " +
|
||||||
formatRichNamedLink(
|
formatRichNamedLink(
|
||||||
|
@ -54,13 +55,21 @@ ExternalToolsPage::ExternalToolsPage()
|
||||||
groupLayout->setWidget(0, QFormLayout::SpanningRole, description);
|
groupLayout->setWidget(0, QFormLayout::SpanningRole, description);
|
||||||
groupLayout->setWidget(1, QFormLayout::SpanningRole, links);
|
groupLayout->setWidget(1, QFormLayout::SpanningRole, links);
|
||||||
|
|
||||||
auto customPathCb =
|
auto *customPathCb =
|
||||||
this->createCheckBox("Use custom path (Enable if using "
|
this->createCheckBox("Use custom path (Enable if using "
|
||||||
"non-standard streamlink installation path)",
|
"non-standard streamlink installation path)",
|
||||||
getSettings()->streamlinkUseCustomPath);
|
getSettings()->streamlinkUseCustomPath);
|
||||||
groupLayout->setWidget(2, QFormLayout::SpanningRole, customPathCb);
|
groupLayout->setWidget(2, QFormLayout::SpanningRole, customPathCb);
|
||||||
|
|
||||||
auto customPath = this->createLineEdit(getSettings()->streamlinkPath);
|
auto *note = new QLabel(
|
||||||
|
QStringLiteral(
|
||||||
|
"Chatterino expects the executable to be called \"%1\".")
|
||||||
|
.arg(STREAMLINK_BINARY_NAME));
|
||||||
|
note->setWordWrap(true);
|
||||||
|
note->setStyleSheet("color: #bbb");
|
||||||
|
groupLayout->setWidget(3, QFormLayout::SpanningRole, note);
|
||||||
|
|
||||||
|
auto *customPath = this->createLineEdit(getSettings()->streamlinkPath);
|
||||||
customPath->setPlaceholderText(
|
customPath->setPlaceholderText(
|
||||||
"Path to folder where Streamlink executable can be found");
|
"Path to folder where Streamlink executable can be found");
|
||||||
groupLayout->addRow("Custom streamlink path:", customPath);
|
groupLayout->addRow("Custom streamlink path:", customPath);
|
||||||
|
@ -84,7 +93,7 @@ ExternalToolsPage::ExternalToolsPage()
|
||||||
auto group = layout.emplace<QGroupBox>("Custom stream player");
|
auto group = layout.emplace<QGroupBox>("Custom stream player");
|
||||||
auto groupLayout = group.setLayoutType<QFormLayout>();
|
auto groupLayout = group.setLayoutType<QFormLayout>();
|
||||||
|
|
||||||
const auto description = new QLabel(
|
auto *description = new QLabel(
|
||||||
"You can open Twitch streams directly in any video player that "
|
"You can open Twitch streams directly in any video player that "
|
||||||
"has built-in Twitch support and has own URI Scheme.\nE.g.: "
|
"has built-in Twitch support and has own URI Scheme.\nE.g.: "
|
||||||
"IINA for macOS and Potplayer (with extension) for "
|
"IINA for macOS and Potplayer (with extension) for "
|
||||||
|
@ -96,7 +105,7 @@ ExternalToolsPage::ExternalToolsPage()
|
||||||
|
|
||||||
groupLayout->setWidget(0, QFormLayout::SpanningRole, description);
|
groupLayout->setWidget(0, QFormLayout::SpanningRole, description);
|
||||||
|
|
||||||
auto lineEdit = this->createLineEdit(getSettings()->customURIScheme);
|
auto *lineEdit = this->createLineEdit(getSettings()->customURIScheme);
|
||||||
lineEdit->setPlaceholderText("custom-player-scheme://");
|
lineEdit->setPlaceholderText("custom-player-scheme://");
|
||||||
groupLayout->addRow("Custom stream player URI Scheme:", lineEdit);
|
groupLayout->addRow("Custom stream player URI Scheme:", lineEdit);
|
||||||
}
|
}
|
||||||
|
@ -106,7 +115,7 @@ ExternalToolsPage::ExternalToolsPage()
|
||||||
auto group = layout.emplace<QGroupBox>("Image Uploader");
|
auto group = layout.emplace<QGroupBox>("Image Uploader");
|
||||||
auto groupLayout = group.setLayoutType<QFormLayout>();
|
auto groupLayout = group.setLayoutType<QFormLayout>();
|
||||||
|
|
||||||
const auto description = new QLabel(
|
auto *description = new QLabel(
|
||||||
"You can set custom host for uploading images, like "
|
"You can set custom host for uploading images, like "
|
||||||
"imgur.com or s-ul.eu.<br>Check " +
|
"imgur.com or s-ul.eu.<br>Check " +
|
||||||
formatRichNamedLink("https://chatterino.com/help/image-uploader",
|
formatRichNamedLink("https://chatterino.com/help/image-uploader",
|
||||||
|
|
Loading…
Reference in a new issue