void OBSBasicSourceSelect::on_buttonBox_accepted()
{
	bool useExisting = ui->selectExisting->isChecked();
	bool visible = ui->sourceVisible->isChecked();

	if (useExisting) {
		QListWidgetItem *item = ui->sourceList->currentItem();
		if (!item)
			return;

		AddExisting(QT_TO_UTF8(item->text()), visible, false);
	} else {
		if (ui->sourceName->text().isEmpty()) {
			OBSMessageBox::warning(this,
					QTStr("NoNameEntered.Title"),
					QTStr("NoNameEntered.Text"));
			return;
		}

		if (!AddNew(this, id, QT_TO_UTF8(ui->sourceName->text()),
					visible, newSource))
			return;
	}

	done(DialogCode::Accepted);
}
void OBSBasic::ChangeSceneCollection()
{
	QAction *action = reinterpret_cast<QAction*>(sender());
	std::string fileName;

	if (!action)
		return;

	fileName = QT_TO_UTF8(action->property("fileName").value<QString>());
	if (fileName.empty())
		return;

	const char *oldName = config_get_string(App()->GlobalConfig(),
			"Basic", "SceneCollection");
	if (action->text().compare(QT_UTF8(oldName)) == 0) {
		action->setChecked(true);
		return;
	}

	SaveProjectNow();

	Load(fileName.c_str());
	RefreshSceneCollections();

	const char *newName = config_get_string(App()->GlobalConfig(),
			"Basic", "SceneCollection");
	const char *newFile = config_get_string(App()->GlobalConfig(),
			"Basic", "SceneCollectionFile");

	blog(LOG_INFO, "Switched to scene collection '%s' (%s.json)",
			newName, newFile);
	blog(LOG_INFO, "------------------------------------------------");

	UpdateTitleBar();
}
void AutoConfigStreamPage::on_disconnectAccount_clicked()
{
	QMessageBox::StandardButton button;

	button = OBSMessageBox::question(this,
			QTStr(DISCONNECT_COMFIRM_TITLE),
			QTStr(DISCONNECT_COMFIRM_TEXT));

	if (button == QMessageBox::No) {
		return;
	}

	OBSBasic *main = OBSBasic::Get();

	main->auth.reset();
	auth.reset();

	std::string service = QT_TO_UTF8(ui->service->currentText());

#ifdef BROWSER_AVAILABLE
	OAuth::DeleteCookies(service);
#endif

	ui->streamKeyWidget->setVisible(true);
	ui->streamKeyLabel->setVisible(true);
	ui->connectAccount2->setVisible(true);
	ui->disconnectAccount->setVisible(false);
	ui->key->setText("");
}
void AutoConfigStreamPage::OnAuthConnected()
{
	std::string service = QT_TO_UTF8(ui->service->currentText());
	Auth::Type type = Auth::AuthType(service);

	if (type == Auth::Type::OAuth_StreamKey) {
		OnOAuthStreamKeyConnected();
	}
}
void AutoConfigStreamPage::on_connectAccount_clicked()
{
#ifdef BROWSER_AVAILABLE
	std::string service = QT_TO_UTF8(ui->service->currentText());

	auth = OAuthStreamKey::Login(this, service);
	if (!!auth)
		OnAuthConnected();
#endif
}
OBSBasicSourceSelect::OBSBasicSourceSelect(OBSBasic *parent, const char *id_)
	: QDialog (parent),
	  ui      (new Ui::OBSBasicSourceSelect),
	  id      (id_)
{
	setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);

	ui->setupUi(this);

	ui->sourceList->setAttribute(Qt::WA_MacShowFocusRect, false);

	QString placeHolderText{QT_UTF8(GetSourceDisplayName(id))};

	QString text{placeHolderText};
	int i = 2;
	obs_source_t *source = nullptr;
	while ((source = obs_get_source_by_name(QT_TO_UTF8(text)))) {
		obs_source_release(source);
		text = QString("%1 %2").arg(placeHolderText).arg(i++);
	}

	ui->sourceName->setText(text);
	ui->sourceName->setFocus();	//Fixes deselect of text.
	ui->sourceName->selectAll();

	installEventFilter(CreateShortcutFilter());

	if (strcmp(id_, "scene") == 0) {
		OBSBasic *main = reinterpret_cast<OBSBasic*>(
				App()->GetMainWindow());
		OBSSource curSceneSource = main->GetCurrentSceneSource();

		ui->selectExisting->setChecked(true);
		ui->createNew->setChecked(false);
		ui->createNew->setEnabled(false);
		ui->sourceName->setEnabled(false);

		int count = main->ui->scenes->count();
		for (int i = 0; i < count; i++) {
			QListWidgetItem *item = main->ui->scenes->item(i);
			OBSScene scene = GetOBSRef<OBSScene>(item);
			OBSSource sceneSource = obs_scene_get_source(scene);

			if (curSceneSource == sceneSource)
				continue;

			const char *name = obs_source_get_name(sceneSource);
			ui->sourceList->addItem(QT_UTF8(name));
		}
	} else if (strcmp(id_, "group") == 0) {
		obs_enum_sources(EnumGroups, this);
	} else {
		obs_enum_sources(EnumSources, this);
	}
}
void OBSBasic::CurrentTabSceneChanged(int idx)
{
	QString sceneName = ui->sceneTabBar->tabText(idx);
	obs_source_t * source = obs_get_source_by_name(QT_TO_UTF8(sceneName));
	if ( source )
	{
		SetCurrentScene(source);
		CurrentTabSceneUpdateControls();
		obs_source_release(source);
	}
}
void OBSBasic::ChangeProfile()
{
	QAction *action = reinterpret_cast<QAction*>(sender());
	ConfigFile config;
	std::string path;

	if (!action)
		return;

	path = QT_TO_UTF8(action->property("file_name").value<QString>());
	if (path.empty())
		return;

	const char *oldName = config_get_string(App()->GlobalConfig(),
			"Basic", "Profile");
	if (action->text().compare(QT_UTF8(oldName)) == 0) {
		action->setChecked(true);
		return;
	}

	size_t path_len = path.size();
	path += "/basic.ini";

	if (config.Open(path.c_str(), CONFIG_OPEN_ALWAYS) != 0) {
		blog(LOG_ERROR, "ChangeProfile: Failed to load file '%s'",
				path.c_str());
		return;
	}

	path.resize(path_len);

	const char *newName = config_get_string(config, "General", "Name");
	const char *newDir = strrchr(path.c_str(), '/') + 1;

	config_set_string(App()->GlobalConfig(), "Basic", "Profile", newName);
	config_set_string(App()->GlobalConfig(), "Basic", "ProfileDir",
			newDir);

	config.Swap(basicConfig);
	InitBasicConfigDefaults();
	ResetProfileData();
	RefreshProfiles();
	config_save_safe(App()->GlobalConfig(), "tmp", nullptr);
	UpdateTitleBar();

	blog(LOG_INFO, "Switched to profile '%s' (%s)",
			newName, newDir);
	blog(LOG_INFO, "------------------------------------------------");

	if (api)
		api->on_event(OBS_FRONTEND_EVENT_PROFILE_CHANGED);
}
void OBSBasicSourceSelect::on_buttonBox_accepted()
{
	bool useExisting = ui->selectExisting->isChecked();

	if (useExisting) {
		QListWidgetItem *item = ui->sourceList->currentItem();
		if (!item)
			return;

		AddExisting(QT_TO_UTF8(item->text()));
	} else {
		if (ui->sourceName->text().isEmpty()) {
			QMessageBox::information(this,
					QTStr("NoNameEntered"),
					QTStr("NoNameEntered"));
			return;
		}

		if (!AddNew(this, id, QT_TO_UTF8(ui->sourceName->text())))
			return;
	}

	done(DialogCode::Accepted);
}
void OBSBasic::on_tabAddSceneBtn_clicked()
{
	QString format{ QTStr("Basic.Main.DefaultSceneName.Text") };

	QString sceneName = format.arg(m_curNewSceneNameIndex++);

	{
		std::string name = QT_TO_UTF8(sceneName);
		obs_scene_t *scene = obs_scene_create(name.c_str());

		obs_source_t *source = obs_scene_get_source(scene);
		AddScene(source);
		SetCurrentScene(source);
		obs_scene_release(scene);
	}
}
obs_data_array_t *BiLiOBSMainWid::mSaveSceneListOrder() {

	obs_data_array_t *sceneOrder = obs_data_array_create();

#if 1
	obs_source_t* currentScene = obs_get_output_source(0);
	std::list<std::string> tmpSceneOrder;

	//获取所有场景
	for (OBSSource& src : OBSEnumSources())
	{
		if (strcmp(obs_source_get_id(src), "scene") == 0)
			tmpSceneOrder.push_back(obs_source_get_name(src));
	}

	//当前场景放在第一个
	if (currentScene)
	{
		std::string currentSceneName = obs_source_get_name(currentScene);
		auto x = std::find(tmpSceneOrder.begin(), tmpSceneOrder.end(), currentSceneName);
		assert(x != tmpSceneOrder.end());
		tmpSceneOrder.erase(x);
		tmpSceneOrder.push_front(obs_source_get_name(currentScene));
	}

	//保存场景顺序
	for (auto& x : tmpSceneOrder) {
		obs_data_t *data = obs_data_create();
		obs_data_set_string(data, "name", x.c_str());
		obs_data_array_push_back(sceneOrder, data);
		obs_data_release(data);
	}

	obs_source_release(currentScene);
#else
	for (int i = 0; i < ui->scenes->count(); i++) {
		obs_data_t *data = obs_data_create();
		obs_data_set_string(data, "name",
				QT_TO_UTF8(ui->scenes->item(i)->text()));
		obs_data_array_push_back(sceneOrder, data);
		obs_data_release(data);
	}
#endif

	return sceneOrder;
}
OBSBasicSourceSelect::OBSBasicSourceSelect(OBSBasic *parent, const char *id_)
	: QDialog (parent),
	  ui      (new Ui::OBSBasicSourceSelect),
	  id      (id_)
{
	ui->setupUi(this);

	QString placeHolderText{QT_UTF8(obs_source_get_display_name(
				OBS_SOURCE_TYPE_INPUT, id))};

	QString text{placeHolderText};
	int i = 1;
	obs_source_t source = nullptr;
	while ((source = obs_get_source_by_name(QT_TO_UTF8(text)))) {
		obs_source_release(source);
		text = QString("%1 %2").arg(placeHolderText).arg(i++);
	}

	ui->sourceName->setText(text);
	ui->sourceName->setFocus();	//Fixes deselect of text.
	ui->sourceName->selectAll();

	obs_enum_sources(EnumSources, this);
}
void AutoConfigStreamPage::UpdateServerList()
{
	QString serviceName = ui->service->currentText();
	bool showMore =
		ui->service->currentData().toInt() == (int)ListOpt::ShowAll;

	if (showMore) {
		LoadServices(true);
		ui->service->showPopup();
		return;
	} else {
		lastService = serviceName;
	}

	obs_properties_t *props = obs_get_service_properties("rtmp_common");
	obs_property_t *services = obs_properties_get(props, "service");

	OBSData settings = obs_data_create();
	obs_data_release(settings);

	obs_data_set_string(settings, "service", QT_TO_UTF8(serviceName));
	obs_property_modified(services, settings);

	obs_property_t *servers = obs_properties_get(props, "server");

	ui->server->clear();

	size_t servers_count = obs_property_list_item_count(servers);
	for (size_t i = 0; i < servers_count; i++) {
		const char *name = obs_property_list_item_name(servers, i);
		const char *server = obs_property_list_item_string(servers, i);
		ui->server->addItem(name, server);
	}

	obs_properties_destroy(props);
}
void AutoConfigStreamPage::ServiceChanged()
{
	bool showMore =
		ui->service->currentData().toInt() == (int)ListOpt::ShowAll;
	if (showMore)
		return;

	std::string service = QT_TO_UTF8(ui->service->currentText());
	bool regionBased = service == "Twitch" ||
	                   service == "Smashcast";
	bool testBandwidth = ui->doBandwidthTest->isChecked();
	bool custom = IsCustom();

	ui->disconnectAccount->setVisible(false);

#ifdef BROWSER_AVAILABLE
	if (cef) {
		if (lastService != service.c_str()) {
			bool can_auth = is_auth_service(service);
			int page = can_auth
				? (int)Section::Connect
				: (int)Section::StreamKey;

			ui->stackedWidget->setCurrentIndex(page);
			ui->streamKeyWidget->setVisible(true);
			ui->streamKeyLabel->setVisible(true);
			ui->connectAccount2->setVisible(can_auth);
			auth.reset();

			if (lastService.isEmpty())
				lastService = service.c_str();
		}
	} else {
		ui->connectAccount2->setVisible(false);
	}
#else
	ui->connectAccount2->setVisible(false);
#endif

	/* Test three closest servers if "Auto" is available for Twitch */
	if (service == "Twitch" && wiz->twitchAuto)
		regionBased = false;

	ui->streamkeyPageLayout->removeWidget(ui->serverLabel);
	ui->streamkeyPageLayout->removeWidget(ui->serverStackedWidget);

	if (custom) {
		ui->streamkeyPageLayout->insertRow(1, ui->serverLabel,
				ui->serverStackedWidget);

		ui->region->setVisible(false);
		ui->serverStackedWidget->setCurrentIndex(1);
		ui->serverStackedWidget->setVisible(true);
		ui->serverLabel->setVisible(true);
	} else {
		if (!testBandwidth)
			ui->streamkeyPageLayout->insertRow(2, ui->serverLabel,
					ui->serverStackedWidget);

		ui->region->setVisible(regionBased && testBandwidth);
		ui->serverStackedWidget->setCurrentIndex(0);
		ui->serverStackedWidget->setHidden(testBandwidth);
		ui->serverLabel->setHidden(testBandwidth);
	}

	wiz->testRegions = regionBased && testBandwidth;

	ui->bitrateLabel->setHidden(testBandwidth);
	ui->bitrate->setHidden(testBandwidth);

#ifdef BROWSER_AVAILABLE
	OBSBasic *main = OBSBasic::Get();

	if (!!main->auth &&
	    service.find(main->auth->service()) != std::string::npos) {
		auth = main->auth;
		OnAuthConnected();
	}
#endif

	UpdateCompleted();
}
bool AutoConfigStreamPage::validatePage()
{
	OBSData service_settings = obs_data_create();
	obs_data_release(service_settings);

	wiz->customServer = IsCustom();

	const char *serverType = wiz->customServer
		? "rtmp_custom"
		: "rtmp_common";

	if (!wiz->customServer) {
		obs_data_set_string(service_settings, "service",
				QT_TO_UTF8(ui->service->currentText()));
	}

	OBSService service = obs_service_create(serverType, "temp_service",
			service_settings, nullptr);
	obs_service_release(service);

	int bitrate = 10000;
	if (!ui->doBandwidthTest->isChecked()) {
		bitrate = ui->bitrate->value();
		wiz->idealBitrate = bitrate;
	}

	OBSData settings = obs_data_create();
	obs_data_release(settings);
	obs_data_set_int(settings, "bitrate", bitrate);
	obs_service_apply_encoder_settings(service, settings, nullptr);

	if (wiz->customServer) {
		QString server = ui->customServer->text();
		wiz->server = wiz->serverName = QT_TO_UTF8(server);
	} else {
		wiz->serverName = QT_TO_UTF8(ui->server->currentText());
		wiz->server = QT_TO_UTF8(ui->server->currentData().toString());
	}

	wiz->bandwidthTest = ui->doBandwidthTest->isChecked();
	wiz->startingBitrate = (int)obs_data_get_int(settings, "bitrate");
	wiz->idealBitrate = wiz->startingBitrate;
	wiz->regionUS = ui->regionUS->isChecked();
	wiz->regionEU = ui->regionEU->isChecked();
	wiz->regionAsia = ui->regionAsia->isChecked();
	wiz->regionOther = ui->regionOther->isChecked();
	wiz->serviceName = QT_TO_UTF8(ui->service->currentText());
	if (ui->preferHardware)
		wiz->preferHardware = ui->preferHardware->isChecked();
	wiz->key = QT_TO_UTF8(ui->key->text());

	if (!wiz->customServer) {
		if (wiz->serviceName == "Twitch")
			wiz->service = AutoConfig::Service::Twitch;
		else if (wiz->serviceName == "Smashcast")
			wiz->service = AutoConfig::Service::Smashcast;
		else
			wiz->service = AutoConfig::Service::Other;
	} else {
		wiz->service = AutoConfig::Service::Other;
	}

	if (wiz->service != AutoConfig::Service::Twitch && wiz->bandwidthTest) {
		QMessageBox::StandardButton button;
#define WARNING_TEXT(x) QTStr("Basic.AutoConfig.StreamPage.StreamWarning." x)
		button = OBSMessageBox::question(this,
				WARNING_TEXT("Title"),
				WARNING_TEXT("Text"));
#undef WARNING_TEXT

		if (button == QMessageBox::No)
			return false;
	}

	return true;
}