UI: Add thumbnail option to YouTube broadcast setup
parent
2dd8049aef
commit
39bbbb41dc
|
@ -1205,6 +1205,11 @@ YouTube.Actions.Privacy.Public="Public"
|
|||
YouTube.Actions.Privacy.Unlisted="Unlisted"
|
||||
YouTube.Actions.Category="Category"
|
||||
|
||||
YouTube.Actions.Thumbnail="Thumbnail"
|
||||
YouTube.Actions.Thumbnail.SelectFile="Select file..."
|
||||
YouTube.Actions.Thumbnail.NoFileSelected="No file selected"
|
||||
YouTube.Actions.Thumbnail.ClearFile="Clear"
|
||||
|
||||
YouTube.Actions.MadeForKids="Is this video made for kids?*"
|
||||
YouTube.Actions.MadeForKids.Yes="Yes, it's made for kids"
|
||||
YouTube.Actions.MadeForKids.No="No, it's not made for kids"
|
||||
|
@ -1238,6 +1243,9 @@ YouTube.Actions.Error.NoBroadcastCreated="Broadcast creation error '%1'.<br/>A d
|
|||
YouTube.Actions.Error.NoStreamCreated="No stream created. Please relink your account."
|
||||
YouTube.Actions.Error.YouTubeApi="YouTube API Error. Please see the log file for more information."
|
||||
YouTube.Actions.Error.BroadcastNotFound="The selected broadcast was not found."
|
||||
YouTube.Actions.Error.FileMissing="Selected file does not exist."
|
||||
YouTube.Actions.Error.FileOpeningFailed="Failed opening selected file."
|
||||
YouTube.Actions.Error.FileTooLarge="Selected file is too large (Limit: 2 MiB)."
|
||||
|
||||
YouTube.Actions.EventsLoading="Loading list of events..."
|
||||
YouTube.Actions.EventCreated.Title="Event Created"
|
||||
|
|
|
@ -1165,6 +1165,14 @@ QSlider::handle:horizontal[themeID="tBarSlider"] {
|
|||
}
|
||||
|
||||
/* YouTube Integration */
|
||||
OBSYoutubeActions {
|
||||
qproperty-thumbPlaceholder: url(./Dark/sources/image.svg);
|
||||
}
|
||||
|
||||
#thumbnailPreview {
|
||||
background-color: rgb(40,40,42);
|
||||
}
|
||||
|
||||
#ytEventList QLabel {
|
||||
color: rgb(225,224,225);
|
||||
background-color: #162458;
|
||||
|
|
|
@ -896,6 +896,10 @@ QSlider::handle:horizontal[themeID="tBarSlider"] {
|
|||
}
|
||||
|
||||
/* YouTube Integration */
|
||||
OBSYoutubeActions {
|
||||
qproperty-thumbPlaceholder: url(./Dark/sources/image.svg);
|
||||
}
|
||||
|
||||
#broadcastButton[broadcastState=ready] {
|
||||
background: blue;
|
||||
}
|
||||
|
|
|
@ -1465,6 +1465,10 @@ QPushButton#sourceFiltersButton {
|
|||
}
|
||||
|
||||
/* YouTube Integration */
|
||||
OBSYoutubeActions {
|
||||
qproperty-thumbPlaceholder: url(./Dark/sources/image.svg);
|
||||
}
|
||||
|
||||
#ytEventList QLabel {
|
||||
background-color: rgb(0, 188, 212);; /* Cyan (Primary) */
|
||||
color: rgb(239, 240, 241); /* White */
|
||||
|
|
|
@ -302,6 +302,10 @@ QSlider::handle:horizontal[themeID="tBarSlider"] {
|
|||
}
|
||||
|
||||
/* YouTube Integration */
|
||||
OBSYoutubeActions {
|
||||
qproperty-thumbPlaceholder: url(:res/images/sources/image.svg);
|
||||
}
|
||||
|
||||
#ytEventList QLabel {
|
||||
background-color: #e1e1e1;
|
||||
border: 1px solid #ddd;
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>585</width>
|
||||
<height>536</height>
|
||||
<width>616</width>
|
||||
<height>645</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -22,6 +22,12 @@
|
|||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>720</width>
|
||||
<height>880</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>YouTube.Actions.WindowTitle</string>
|
||||
</property>
|
||||
|
@ -37,7 +43,7 @@
|
|||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab_1">
|
||||
<widget class="QWidget" name="ytEventCreate">
|
||||
<attribute name="title">
|
||||
<string>YouTube.Actions.CreateNewEvent</string>
|
||||
</attribute>
|
||||
|
@ -175,13 +181,20 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>YouTube.Actions.Thumbnail</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>YouTube.Actions.AdditionalSettings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="9" column="1">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -194,7 +207,7 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<item row="10" column="0">
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -207,7 +220,7 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="10" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
|
@ -228,7 +241,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="11" column="0">
|
||||
<spacer name="horizontalSpacer_14">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -241,7 +254,7 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="11" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkDVR">
|
||||
|
@ -255,7 +268,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<item row="12" column="0">
|
||||
<spacer name="horizontalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -268,7 +281,7 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<item row="12" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="check360Video">
|
||||
|
@ -308,7 +321,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<item row="13" column="0">
|
||||
<spacer name="horizontalSpacer_12">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -321,7 +334,7 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<item row="13" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkScheduledLater">
|
||||
|
@ -335,7 +348,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<item row="14" column="0">
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -348,7 +361,7 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<item row="14" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkAutoStart">
|
||||
|
@ -397,7 +410,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<item row="15" column="0">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -410,7 +423,7 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<item row="15" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkAutoStop">
|
||||
|
@ -427,7 +440,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<item row="16" column="0">
|
||||
<spacer name="horizontalSpacer_13">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -440,7 +453,7 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<item row="16" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<item>
|
||||
<widget class="QDateTimeEdit" name="scheduledTime">
|
||||
|
@ -460,7 +473,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<item row="17" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkRememberSettings">
|
||||
|
@ -471,7 +484,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<item row="17" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -484,6 +497,64 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_13">
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="selectFileButton">
|
||||
<property name="text">
|
||||
<string>YouTube.Actions.Thumbnail.SelectFile</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="selectedFileName">
|
||||
<property name="text">
|
||||
<string>YouTube.Actions.Thumbnail.NoFileSelected</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="ClickableLabel" name="thumbnailPreview">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>162</width>
|
||||
<height>92</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>162</width>
|
||||
<height>92</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="ytEventList">
|
||||
|
@ -504,7 +575,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>524</width>
|
||||
<width>555</width>
|
||||
<height>192</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -633,6 +704,13 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ClickableLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>clickable-label.hpp</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
#include <QToolTip>
|
||||
#include <QDateTime>
|
||||
#include <QDesktopServices>
|
||||
#include <QFileInfo>
|
||||
#include <QStandardPaths>
|
||||
#include <QImageReader>
|
||||
|
||||
const QString SchedulDateAndTimeFormat = "yyyy-MM-dd'T'hh:mm:ss'Z'";
|
||||
const QString RepresentSchedulDateAndTimeFormat = "dddd, MMMM d, yyyy h:m";
|
||||
|
@ -91,6 +94,55 @@ OBSYoutubeActions::OBSYoutubeActions(QWidget *parent, Auth *auth,
|
|||
|
||||
ui->scheduledTime->setDateTime(QDateTime::currentDateTime());
|
||||
|
||||
auto thumbSelectionHandler = [&]() {
|
||||
if (thumbnailFile.isEmpty()) {
|
||||
QString filePath = OpenFile(
|
||||
this,
|
||||
QTStr("YouTube.Actions.Thumbnail.SelectFile"),
|
||||
QStandardPaths::writableLocation(
|
||||
QStandardPaths::PicturesLocation),
|
||||
QString("Images (*.png *.jpg *.jpeg *.gif)"));
|
||||
|
||||
if (!filePath.isEmpty()) {
|
||||
QFileInfo tFile(filePath);
|
||||
if (!tFile.exists()) {
|
||||
return ShowErrorDialog(
|
||||
this,
|
||||
QTStr("YouTube.Actions.Error.FileMissing"));
|
||||
} else if (tFile.size() > 2 * 1024 * 1024) {
|
||||
return ShowErrorDialog(
|
||||
this,
|
||||
QTStr("YouTube.Actions.Error.FileTooLarge"));
|
||||
}
|
||||
|
||||
thumbnailFile = filePath;
|
||||
ui->selectedFileName->setText(thumbnailFile);
|
||||
ui->selectFileButton->setText(QTStr(
|
||||
"YouTube.Actions.Thumbnail.ClearFile"));
|
||||
|
||||
QImageReader imgReader(filePath);
|
||||
imgReader.setAutoTransform(true);
|
||||
const QImage newImage = imgReader.read();
|
||||
ui->thumbnailPreview->setPixmap(
|
||||
QPixmap::fromImage(newImage).scaled(
|
||||
160, 90, Qt::KeepAspectRatio));
|
||||
}
|
||||
} else {
|
||||
thumbnailFile.clear();
|
||||
ui->selectedFileName->setText(QTStr(
|
||||
"YouTube.Actions.Thumbnail.NoFileSelected"));
|
||||
ui->selectFileButton->setText(
|
||||
QTStr("YouTube.Actions.Thumbnail.SelectFile"));
|
||||
ui->thumbnailPreview->setPixmap(
|
||||
GetPlaceholder().pixmap(QSize(16, 16)));
|
||||
}
|
||||
};
|
||||
|
||||
connect(ui->selectFileButton, &QPushButton::clicked, this,
|
||||
thumbSelectionHandler);
|
||||
connect(ui->thumbnailPreview, &ClickableLabel::clicked, this,
|
||||
thumbSelectionHandler);
|
||||
|
||||
if (!apiYouTube) {
|
||||
blog(LOG_DEBUG, "YouTube API auth NOT found.");
|
||||
Cancel();
|
||||
|
@ -245,6 +297,14 @@ OBSYoutubeActions::OBSYoutubeActions(QWidget *parent, Auth *auth,
|
|||
valid = true;
|
||||
}
|
||||
|
||||
void OBSYoutubeActions::showEvent(QShowEvent *event)
|
||||
{
|
||||
QDialog::showEvent(event);
|
||||
if (thumbnailFile.isEmpty())
|
||||
ui->thumbnailPreview->setPixmap(
|
||||
GetPlaceholder().pixmap(QSize(16, 16)));
|
||||
}
|
||||
|
||||
OBSYoutubeActions::~OBSYoutubeActions()
|
||||
{
|
||||
workerThread->stop();
|
||||
|
@ -421,6 +481,15 @@ bool OBSYoutubeActions::CreateEventAction(YoutubeApiWrappers *api,
|
|||
blog(LOG_DEBUG, "No category set.");
|
||||
return false;
|
||||
}
|
||||
if (!thumbnailFile.isEmpty()) {
|
||||
blog(LOG_INFO, "Uploading thumbnail file \"%s\"...",
|
||||
thumbnailFile.toStdString().c_str());
|
||||
if (!apiYouTube->SetVideoThumbnail(broadcast.id,
|
||||
thumbnailFile)) {
|
||||
blog(LOG_DEBUG, "No thumbnail set.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!stream_later || ready_broadcast) {
|
||||
stream = {"", "", "OBS Studio Video Stream"};
|
||||
|
@ -664,6 +733,8 @@ void OBSYoutubeActions::SaveSettings(BroadcastDescription &broadcast)
|
|||
broadcast.schedul_for_later);
|
||||
config_set_string(main->basicConfig, "YouTube", "Projection",
|
||||
QT_TO_UTF8(broadcast.projection));
|
||||
config_set_string(main->basicConfig, "YouTube", "ThumbnailFile",
|
||||
QT_TO_UTF8(thumbnailFile));
|
||||
config_set_bool(main->basicConfig, "YouTube", "RememberSettings", true);
|
||||
}
|
||||
|
||||
|
@ -724,6 +795,26 @@ void OBSYoutubeActions::LoadSettings()
|
|||
else
|
||||
ui->check360Video->setChecked(false);
|
||||
}
|
||||
|
||||
const char *thumbFile = config_get_string(main->basicConfig, "YouTube",
|
||||
"ThumbnailFile");
|
||||
if (thumbFile && *thumbFile) {
|
||||
QFileInfo tFile(thumbFile);
|
||||
// Re-check validity before setting path again
|
||||
if (tFile.exists() && tFile.size() <= 2 * 1024 * 1024) {
|
||||
thumbnailFile = tFile.absoluteFilePath();
|
||||
ui->selectedFileName->setText(thumbnailFile);
|
||||
ui->selectFileButton->setText(
|
||||
QTStr("YouTube.Actions.Thumbnail.ClearFile"));
|
||||
|
||||
QImageReader imgReader(thumbnailFile);
|
||||
imgReader.setAutoTransform(true);
|
||||
const QImage newImage = imgReader.read();
|
||||
ui->thumbnailPreview->setPixmap(
|
||||
QPixmap::fromImage(newImage).scaled(
|
||||
160, 90, Qt::KeepAspectRatio));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OBSYoutubeActions::OpenYouTubeDashboard()
|
||||
|
|
|
@ -30,6 +30,8 @@ signals:
|
|||
|
||||
class OBSYoutubeActions : public QDialog {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QIcon thumbPlaceholder READ GetPlaceholder WRITE
|
||||
SetPlaceholder DESIGNABLE true)
|
||||
|
||||
std::unique_ptr<Ui::OBSYoutubeActions> ui;
|
||||
|
||||
|
@ -38,6 +40,7 @@ signals:
|
|||
bool autostop, bool start_now);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *event);
|
||||
void UpdateOkButtonStatus();
|
||||
|
||||
bool CreateEventAction(YoutubeApiWrappers *api,
|
||||
|
@ -65,10 +68,15 @@ private:
|
|||
void SaveSettings(BroadcastDescription &broadcast);
|
||||
void LoadSettings();
|
||||
|
||||
QIcon GetPlaceholder() { return thumbPlaceholder; }
|
||||
void SetPlaceholder(const QIcon &icon) { thumbPlaceholder = icon; }
|
||||
|
||||
QString selectedBroadcast;
|
||||
bool autostart, autostop;
|
||||
bool valid = false;
|
||||
bool broadcastReady = false;
|
||||
YoutubeApiWrappers *apiYouTube;
|
||||
WorkerThread *workerThread;
|
||||
QString thumbnailFile;
|
||||
QIcon thumbPlaceholder;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "youtube-api-wrappers.hpp"
|
||||
|
||||
#include <QUrl>
|
||||
#include <QMimeDatabase>
|
||||
#include <QFile>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
@ -27,6 +29,8 @@ using namespace json11;
|
|||
#define YOUTUBE_LIVE_TOKEN_URL "https://oauth2.googleapis.com/token"
|
||||
#define YOUTUBE_LIVE_VIDEOCATEGORIES_URL YOUTUBE_LIVE_API_URL "/videoCategories"
|
||||
#define YOUTUBE_LIVE_VIDEOS_URL YOUTUBE_LIVE_API_URL "/videos"
|
||||
#define YOUTUBE_LIVE_THUMBNAIL_URL \
|
||||
"https://www.googleapis.com/upload/youtube/v3/thumbnails/set"
|
||||
|
||||
#define DEFAULT_BROADCASTS_PER_QUERY \
|
||||
"50" // acceptable values are 0 to 50, inclusive
|
||||
|
@ -58,22 +62,25 @@ bool YoutubeApiWrappers::TryInsertCommand(const char *url,
|
|||
const char *content_type,
|
||||
std::string request_type,
|
||||
const char *data, Json &json_out,
|
||||
long *error_code)
|
||||
long *error_code, int data_size)
|
||||
{
|
||||
long httpStatusCode = 0;
|
||||
|
||||
#ifdef _DEBUG
|
||||
blog(LOG_DEBUG, "YouTube API command URL: %s", url);
|
||||
blog(LOG_DEBUG, "YouTube API command data: %s", data);
|
||||
if (data && data[0] == '{') // only log JSON data
|
||||
blog(LOG_DEBUG, "YouTube API command data: %s", data);
|
||||
#endif
|
||||
if (token.empty())
|
||||
return false;
|
||||
std::string output;
|
||||
std::string error;
|
||||
// Increase timeout by the time it takes to transfer `data_size` at 1 Mbps
|
||||
int timeout = 5 + data_size / 125000;
|
||||
bool success = GetRemoteFile(url, output, error, &httpStatusCode,
|
||||
content_type, request_type, data,
|
||||
{"Authorization: Bearer " + token},
|
||||
nullptr, 5, false);
|
||||
nullptr, timeout, false, data_size);
|
||||
if (error_code)
|
||||
*error_code = httpStatusCode;
|
||||
|
||||
|
@ -126,18 +133,20 @@ bool YoutubeApiWrappers::UpdateAccessToken()
|
|||
bool YoutubeApiWrappers::InsertCommand(const char *url,
|
||||
const char *content_type,
|
||||
std::string request_type,
|
||||
const char *data, Json &json_out)
|
||||
const char *data, Json &json_out,
|
||||
int data_size)
|
||||
{
|
||||
long error_code;
|
||||
bool success = TryInsertCommand(url, content_type, request_type, data,
|
||||
json_out, &error_code);
|
||||
json_out, &error_code, data_size);
|
||||
|
||||
if (error_code == 401) {
|
||||
// Attempt to update access token and try again
|
||||
if (!UpdateAccessToken())
|
||||
return false;
|
||||
success = TryInsertCommand(url, content_type, request_type,
|
||||
data, json_out, &error_code);
|
||||
data, json_out, &error_code,
|
||||
data_size);
|
||||
}
|
||||
|
||||
if (json_out.object_items().find("error") !=
|
||||
|
@ -361,6 +370,36 @@ bool YoutubeApiWrappers::SetVideoCategory(const QString &video_id,
|
|||
data.dump().c_str(), json_out);
|
||||
}
|
||||
|
||||
bool YoutubeApiWrappers::SetVideoThumbnail(const QString &video_id,
|
||||
const QString &thumbnail_file)
|
||||
{
|
||||
lastErrorMessage.clear();
|
||||
lastErrorReason.clear();
|
||||
|
||||
// Make sure the file hasn't been deleted since originally selecting it
|
||||
if (!QFile::exists(thumbnail_file)) {
|
||||
lastErrorMessage = QTStr("YouTube.Actions.Error.FileMissing");
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile thumbFile(thumbnail_file);
|
||||
if (!thumbFile.open(QFile::ReadOnly)) {
|
||||
lastErrorMessage =
|
||||
QTStr("YouTube.Actions.Error.FileOpeningFailed");
|
||||
return false;
|
||||
}
|
||||
|
||||
const QByteArray fileContents = thumbFile.readAll();
|
||||
const QString mime =
|
||||
QMimeDatabase().mimeTypeForData(fileContents).name();
|
||||
|
||||
const QString url = YOUTUBE_LIVE_THUMBNAIL_URL "?videoId=" + video_id;
|
||||
Json json_out;
|
||||
return InsertCommand(QT_TO_UTF8(url), QT_TO_UTF8(mime), "POST",
|
||||
fileContents.constData(), json_out,
|
||||
fileContents.size());
|
||||
}
|
||||
|
||||
bool YoutubeApiWrappers::StartBroadcast(const QString &broadcast_id)
|
||||
{
|
||||
lastErrorMessage.clear();
|
||||
|
|
|
@ -44,11 +44,12 @@ class YoutubeApiWrappers : public YoutubeAuth {
|
|||
|
||||
bool TryInsertCommand(const char *url, const char *content_type,
|
||||
std::string request_type, const char *data,
|
||||
json11::Json &ret, long *error_code = nullptr);
|
||||
json11::Json &ret, long *error_code = nullptr,
|
||||
int data_size = 0);
|
||||
bool UpdateAccessToken();
|
||||
bool InsertCommand(const char *url, const char *content_type,
|
||||
std::string request_type, const char *data,
|
||||
json11::Json &ret);
|
||||
json11::Json &ret, int data_size = 0);
|
||||
|
||||
public:
|
||||
YoutubeApiWrappers(const Def &d);
|
||||
|
@ -65,6 +66,8 @@ public:
|
|||
const QString &video_title,
|
||||
const QString &video_description,
|
||||
const QString &categorie_id);
|
||||
bool SetVideoThumbnail(const QString &video_id,
|
||||
const QString &thumbnail_file);
|
||||
bool StartBroadcast(const QString &broadcast_id);
|
||||
bool StopBroadcast(const QString &broadcast_id);
|
||||
bool ResetBroadcast(const QString &broadcast_id);
|
||||
|
|
Loading…
Reference in New Issue