Skip to content

Commit

Permalink
Merge pull request obsproject#51 from amazon-contributing/ruwen/plugi…
Browse files Browse the repository at this point in the history
…n-config

Add branding for Amazon IVS
  • Loading branch information
palana committed Sep 4, 2023
2 parents 4e6d78d + ddfc5bf commit b94441f
Show file tree
Hide file tree
Showing 11 changed files with 192 additions and 41 deletions.
25 changes: 25 additions & 0 deletions plugins/simulcast/data/locale/en-US-ivs.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Settings.StreamKey="Stream Key"
Settings.MenuName="Amazon IVS Settings"
Settings.WindowTitle="Amazon IVS Settings"
Settings.EnableTelemetry="Allow runtime telemetry collection (Does not apply to Go Live Config request)"
Settings.UseServerConfig="Use Amazon IVS Go Live Config (disable to enter custom config below)"
Settings.CustomConfig="Custom config (JSON or URL)"
Settings.RTMPURL="RTMP URL"
VisibilityPrompt.Title="Show Amazon IVS Dock"
VisibilityPrompt.Text="Streaming using the newest Amazon IVS features requires using the Start Stream button on the Amazon IVS dock.\n\nShow Dock now?"
VisibilityPrompt.RemindOneWeek="Ask me again in 7 days"
ConfigDownloadError.Title="Amazon IVS Go Live Config Download Error"
FailedToStartStream.Title="Failed to start stream"
FailedToStartStream.NoStreamKey="No stream key set in Amazon IVS Settings"
FailedToStartStream.OpenSettings="Open Amazon IVS Settings"
FailedToStartStream.InvalidCustomConfig="Invalid custom config"
FailedToStartStream.CustomConfigURLInvalidConfig="Custom config URL returned invalid config, check log for details"
FailedToStartStream.GoLiveConfigInvalid="API returned invalid config; try again later"
FailedToStartStream.FailedToCreateSimulcastService="Failed to create simulcast service"
FailedToStartStream.FailedToCreateSimulcastOutput="Failed to create simulcast rtmp output"
FailedToStartStream.EncoderNotAvailble="NVENC not available.\n\nFailed to find encoder type '%s'"
FailedToStartStream.FailedToCreateVideoEncoder="Failed to create video encoder '%s' (type: '%s')"
FailedToStartStream.FailedToGetOBSVideoInfo="Failed to get obs video info while creating encoder '%s' (type: '%s')"
FailedToStartStream.FailedToCreateAudioEncoder="Failed to create audio encoder"
FailedToStartStream.OBSOutputStartFailed="Failed to start stream (obs_output_start returned false)"
FailedToStartStream.NoRTMPURLInConfig="Config does not contain stream target RTMP(S) URL"
1 change: 1 addition & 0 deletions plugins/simulcast/data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Settings.WindowTitle="Twitch Settings"
Settings.EnableTelemetry="Allow runtime telemetry collection (Does not apply to Go Live Config request)"
Settings.UseServerConfig="Use Twitch Go Live Config (disable to enter custom config below)"
Settings.CustomConfig="Custom config (JSON or URL)"
Settings.RTMPURL="RTMP URL"
VisibilityPrompt.Title="Show Twitch Dock"
VisibilityPrompt.Text="Streaming using the newest Twitch features requires using the Start Stream button on the Twitch dock.\n\nShow Dock now?"
VisibilityPrompt.RemindOneWeek="Ask me again in 7 days"
Expand Down
9 changes: 9 additions & 0 deletions plugins/simulcast/data/plugin-ivs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"dock": {
"id": "amazon-ivs-go-live",
"title": "Amazon IVS"
},
"settings": {
"override_rtmp_url": true
}
}
11 changes: 11 additions & 0 deletions plugins/simulcast/data/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"dock": {
"id": "twitch-go-live",
"title": "Twitch",
"color": "white",
"background_color": "#644186"
},
"settings": {
"get_stream_key_url": "https://dashboard.twitch.tv/settings/stream"
}
}
33 changes: 30 additions & 3 deletions plugins/simulcast/src/simulcast-dock-widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ handle_stream_start(SimulcastDockWidget *self, QPushButton *streamingButton,
self->Output()
.StartStreaming(self->DeviceId(),
self->OBSSessionId(),
self->RTMPURL(),
self->StreamKey(), config_used)
.then(self,
[=](bool started) {
Expand Down Expand Up @@ -345,6 +346,7 @@ static OBSDataAutoRelease load_or_create_obj(obs_data_t *data, const char *name)
#define DATA_KEY_CUSTOM_CONFIG "custom_config"
#define DATA_KEY_DEVICE_ID "device_id"
#define DATA_KEY_PROFILES "profiles"
#define DATA_KEY_RTMP_URL "rtmp_url"
#define DATA_KEY_STREAM_KEY "stream_key"
#define DATA_KEY_TELEMETRY_ENABLED "telemetry"
#define DATA_KEY_USE_TWITCH_CONFIG "use_twitch_config"
Expand All @@ -363,6 +365,13 @@ void SimulcastDockWidget::SaveConfig()
os_mkdirs(module_config_path(""));

// Set modified config values here
if (!rtmp_url_.isEmpty()) {
obs_data_set_string(profile_, DATA_KEY_RTMP_URL,
rtmp_url_.toUtf8().constData());
} else {
obs_data_unset_user_value(profile_, DATA_KEY_RTMP_URL);
}

obs_data_set_string(profile_, DATA_KEY_STREAM_KEY,
stream_key_.toUtf8().constData());
obs_data_set_bool(profile_, DATA_KEY_TELEMETRY_ENABLED,
Expand Down Expand Up @@ -412,6 +421,10 @@ void SimulcastDockWidget::LoadConfig()
// Migrate old config values above

// Set modified config values here
if (obs_data_has_user_value(profile_, DATA_KEY_RTMP_URL)) {
rtmp_url_ = obs_data_get_string(profile_, DATA_KEY_RTMP_URL);
}

stream_key_ = obs_data_get_string(profile_, DATA_KEY_STREAM_KEY);
telemetry_enabled_ =
obs_data_get_bool(profile_, DATA_KEY_TELEMETRY_ENABLED);
Expand Down Expand Up @@ -538,8 +551,22 @@ SimulcastDockWidget::StreamAttemptStartTime() const
return stream_attempt_start_time_;
}

void SimulcastDockWidget::SetParentStyleSheet()
void SimulcastDockWidget::SetParentStyleSheet(obs_data_t *dock_config)
{
parentWidget()->setStyleSheet(
"QDockWidget::title { background-color: #644186; color: white; }");
QString styles;
if (obs_data_has_user_value(dock_config, "color")) {
styles += QString::asprintf("color: %s;",
obs_data_get_string(dock_config,
"color"));
}
if (obs_data_has_user_value(dock_config, "background_color")) {
styles += QString::asprintf(
"background-color: %s;",
obs_data_get_string(dock_config, "background_color"));
}

if (styles.isEmpty())
return;

parentWidget()->setStyleSheet("QDockWidget::title {" + styles + "}");
}
4 changes: 3 additions & 1 deletion plugins/simulcast/src/simulcast-dock-widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class SimulcastDockWidget : public QWidget {

const QString &OBSSessionId() { return obs_session_id_; }

QString &RTMPURL() { return rtmp_url_; }
QString &StreamKey() { return stream_key_; }
bool &TelemetryEanbled() { return telemetry_enabled_; }
bool &UseServerConfig() { return use_server_config_; }
Expand All @@ -51,7 +52,7 @@ class SimulcastDockWidget : public QWidget {
const ImmutableDateTime &GenerateStreamAttemptStartTime();
const std::optional<ImmutableDateTime> &StreamAttemptStartTime() const;

void SetParentStyleSheet();
void SetParentStyleSheet(obs_data_t *dock_config);

signals:
void ProfileChanged();
Expand All @@ -66,6 +67,7 @@ class SimulcastDockWidget : public QWidget {
QString obs_session_id_;

// Add config vars here
QString rtmp_url_;
QString stream_key_;
bool telemetry_enabled_;
bool use_server_config_;
Expand Down
50 changes: 31 additions & 19 deletions plugins/simulcast/src/simulcast-output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,37 @@
static OBSServiceAutoRelease create_service(const QString &device_id,
const QString &obs_session_id,
obs_data_t *go_live_config,
const QString &rtmp_url,
const QString &stream_key)
{
const char *url = nullptr;
OBSDataArrayAutoRelease ingest_endpoints =
obs_data_get_array(go_live_config, "ingest_endpoints");
for (size_t i = 0; i < obs_data_array_count(ingest_endpoints); i++) {
OBSDataAutoRelease item =
obs_data_array_item(ingest_endpoints, i);
if (qstrnicmp("RTMP", obs_data_get_string(item, "protocol"), 4))
continue;

url = obs_data_get_string(item, "url_template");
blog(LOG_INFO, "Using URL template: '%s'", url);
break;
}
QByteArray rtmp_url_utf8_data;
if (!rtmp_url.isEmpty()) {
rtmp_url_utf8_data = rtmp_url.toUtf8();
url = rtmp_url_utf8_data.constData();

blog(LOG_INFO, "Using custom rtmp URL: '%s'", url);
} else {
OBSDataArrayAutoRelease ingest_endpoints =
obs_data_get_array(go_live_config, "ingest_endpoints");
for (size_t i = 0; i < obs_data_array_count(ingest_endpoints);
i++) {
OBSDataAutoRelease item =
obs_data_array_item(ingest_endpoints, i);
if (qstrnicmp("RTMP",
obs_data_get_string(item, "protocol"), 4))
continue;

url = obs_data_get_string(item, "url_template");
blog(LOG_INFO, "Using URL template: '%s'", url);
break;
}

if (!url) {
blog(LOG_ERROR, "No RTMP URL in go live config");
throw QString{obs_module_text(
"FailedToStartStream.NoRTMPURLInConfig")};
if (!url) {
blog(LOG_ERROR, "No RTMP URL in go live config");
throw QString{obs_module_text(
"FailedToStartStream.NoRTMPURLInConfig")};
}
}

DStr str;
Expand Down Expand Up @@ -355,6 +366,7 @@ struct OutputObjects {

QFuture<bool> SimulcastOutput::StartStreaming(const QString &device_id,
const QString &obs_session_id,
const QString &rtmp_url,
const QString &stream_key,
obs_data_t *go_live_config_)
{
Expand All @@ -363,8 +375,8 @@ QFuture<bool> SimulcastOutput::StartStreaming(const QString &device_id,
return CreateFuture()
.then(QThreadPool::globalInstance(),
[=, device_id = device_id,
obs_session_id = obs_session_id, stream_key = stream_key,
self = this,
obs_session_id = obs_session_id, rtmp_url = rtmp_url,
stream_key = stream_key, self = this,
video_encoders = std::move(video_encoders_)]() mutable
-> std::optional<OutputObjects> {
auto config = go_live_config_data
Expand All @@ -388,7 +400,7 @@ QFuture<bool> SimulcastOutput::StartStreaming(const QString &device_id,

auto simulcast_service = create_service(
device_id, obs_session_id, go_live_config,
stream_key);
rtmp_url, stream_key);
if (!simulcast_service)
return std::nullopt;

Expand Down
1 change: 1 addition & 0 deletions plugins/simulcast/src/simulcast-output.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class SimulcastOutput : public QObject {
public:
QFuture<bool> StartStreaming(const QString &device_id,
const QString &obs_session_id,
const QString &rtmp_url,
const QString &stream_key,
obs_data_t *go_live_config);
void StopStreaming();
Expand Down
31 changes: 27 additions & 4 deletions plugins/simulcast/src/simulcast-plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ with this program. If not, see <https://www.gnu.org/licenses/>

#include <QAction>
#include <QMainWindow>
#include <obs.hpp>
#include <obs-module.h>
#include <obs-frontend-api.h>
#include <util/util.hpp>

OBS_DECLARE_MODULE()
OBS_MODULE_USE_DEFAULT_LOCALE("simulcast", "en-US")
Expand All @@ -39,7 +41,8 @@ const char *obs_module_description(void)
}

void register_service();
void register_settings_window(SimulcastDockWidget *dock);
void register_settings_window(SimulcastDockWidget *dock,
obs_data_t *plugin_config);

static void obs_event_handler(obs_frontend_event event,
SimulcastDockWidget *simulcastWidget)
Expand Down Expand Up @@ -77,18 +80,38 @@ bool obs_module_load(void)
if (mainWindow == nullptr)
return false;

auto plugin_config_file = BPtr<char>{obs_module_file("plugin.json")};
if (!plugin_config_file) {
blog(LOG_WARNING, "Could not find 'plugin.json'");
return false;
}

OBSDataAutoRelease plugin_config =
obs_data_create_from_json_file(plugin_config_file);

OBSDataAutoRelease dock_config =
obs_data_get_obj(plugin_config, "dock");
if (!dock_config || !obs_data_has_user_value(dock_config, "id") ||
!obs_data_has_user_value(dock_config, "title")) {
blog(LOG_ERROR, "Invalid dock config");
return false;
}

QMetaObject::invokeMethod(mainWindow, []() {
GetGlobalService().setCurrentThreadAsDefault();
});

auto dock = new SimulcastDockWidget(mainWindow);

register_settings_window(dock);
register_settings_window(dock, OBSDataAutoRelease{obs_data_get_obj(
plugin_config, "settings")});

obs_frontend_add_dock_by_id("twitch-go-live", "Twitch", dock);
obs_frontend_add_dock_by_id(obs_data_get_string(dock_config, "id"),
obs_data_get_string(dock_config, "title"),
dock);

// Parent is set by `obs_frontend_add_dock_by_id`, so we need to call this externally/later
dock->SetParentStyleSheet();
dock->SetParentStyleSheet(dock_config);

obs_frontend_add_event_callback(
[](enum obs_frontend_event event, void *private_data) {
Expand Down
Loading

0 comments on commit b94441f

Please sign in to comment.