mirror of https://github.com/Xaymar/obs-StreamFX
Compare commits
8 Commits
5bdcefd618
...
8b97c2b23d
Author | SHA1 | Date |
---|---|---|
Michael Fabian 'Xaymar' Dirks | 8b97c2b23d | |
Michael Fabian 'Xaymar' Dirks | 9df2f01963 | |
Michael Fabian 'Xaymar' Dirks | ffb7a6c5d7 | |
Michael Fabian 'Xaymar' Dirks | f66fabc5d4 | |
Michael Fabian 'Xaymar' Dirks | 38d87f6fcf | |
Michael Fabian 'Xaymar' Dirks | 3e13126f89 | |
Michael Fabian 'Xaymar' Dirks | 9d0233a740 | |
Michael Fabian 'Xaymar' Dirks | 07182d2f89 |
|
@ -293,6 +293,7 @@ set(${PREFIX}ENABLE_ENCODER_FFMPEG_AMF ${FEATURE_DEPRECATED} CACHE BOOL "Enable
|
|||
set(${PREFIX}ENABLE_ENCODER_FFMPEG_NVENC ${FEATURE_STABLE} CACHE BOOL "Enable NVENC Encoder in FFmpeg.")
|
||||
set(${PREFIX}ENABLE_ENCODER_FFMPEG_PRORES ${FEATURE_STABLE} CACHE BOOL "Enable ProRes Encoder in FFmpeg.")
|
||||
set(${PREFIX}ENABLE_ENCODER_FFMPEG_DNXHR ${FEATURE_STABLE} CACHE BOOL "Enable DNXHR Encoder in FFmpeg.")
|
||||
set(${PREFIX}ENABLE_ENCODER_FFMPEG_CFHD ${FEATURE_STABLE} CACHE BOOL "Enable CineForm Encoder in FFmpeg.")
|
||||
|
||||
## Filters
|
||||
set(${PREFIX}ENABLE_FILTER_AUTOFRAMING ${FEATURE_EXPERIMENTAL} CACHE BOOL "Enable Auto-Framing Filter")
|
||||
|
@ -476,6 +477,9 @@ function(feature_encoder_ffmpeg RESOLVE)
|
|||
|
||||
# DNxHR
|
||||
is_feature_enabled(ENCODER_FFMPEG_DNXHR T_CHECK)
|
||||
|
||||
# CineForm
|
||||
is_feature_enabled(ENCODER_FFMPEG_CFHD T_CHECK)
|
||||
endif()
|
||||
elseif(T_CHECK)
|
||||
set(REQUIRE_FFMPEG ON PARENT_SCOPE)
|
||||
|
@ -1202,6 +1206,18 @@ if(T_CHECK)
|
|||
ENABLE_ENCODER_FFMPEG_DNXHR
|
||||
)
|
||||
endif()
|
||||
|
||||
# CineForm HD
|
||||
is_feature_enabled(ENCODER_FFMPEG_CFHD T_CHECK)
|
||||
if(T_CHECK)
|
||||
list(APPEND PROJECT_PRIVATE_SOURCE
|
||||
"source/encoders/ffmpeg/cfhd.hpp"
|
||||
"source/encoders/ffmpeg/cfhd.cpp"
|
||||
)
|
||||
list(APPEND PROJECT_DEFINITIONS
|
||||
ENABLE_ENCODER_FFMPEG_CFHD
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Filter/Auto-Framing
|
||||
|
|
|
@ -235,6 +235,22 @@ Encoder.FFmpeg.NVENC.Other.NonReferencePFrames="Non-reference P-Frames"
|
|||
Encoder.FFmpeg.NVENC.Other.ReferenceFrames="Reference Frames"
|
||||
Encoder.FFmpeg.NVENC.Other.LowDelayKeyFrameScale="Low Delay Key-Frame Scale"
|
||||
|
||||
# Encoder/FFmpeg/CFHD
|
||||
Encoder.FFmpeg.CineForm.Quality="Quality"
|
||||
Encoder.FFmpeg.CineForm.Quality.low="Low"
|
||||
Encoder.FFmpeg.CineForm.Quality.low+="Low+"
|
||||
Encoder.FFmpeg.CineForm.Quality.medium="Medium"
|
||||
Encoder.FFmpeg.CineForm.Quality.medium+="Medium+"
|
||||
Encoder.FFmpeg.CineForm.Quality.high="High"
|
||||
Encoder.FFmpeg.CineForm.Quality.high+="High+"
|
||||
Encoder.FFmpeg.CineForm.Quality.film1="Film 1"
|
||||
Encoder.FFmpeg.CineForm.Quality.film1+="Film 1+"
|
||||
Encoder.FFmpeg.CineForm.Quality.film1.5="Film 1.5"
|
||||
Encoder.FFmpeg.CineForm.Quality.film2="Film 2"
|
||||
Encoder.FFmpeg.CineForm.Quality.film2+="Film 2+"
|
||||
Encoder.FFmpeg.CineForm.Quality.film3="Film 3"
|
||||
Encoder.FFmpeg.CineForm.Quality.film3+="Film 3+"
|
||||
|
||||
# Blur
|
||||
Blur.Type.Box="Box"
|
||||
Blur.Type.BoxLinear="Box Linear"
|
||||
|
|
|
@ -404,46 +404,44 @@ bool ffmpeg_instance::encode_video(uint32_t handle, int64_t pts, uint64_t lock_k
|
|||
|
||||
void ffmpeg_instance::initialize_sw(obs_data_t* settings)
|
||||
{
|
||||
if (_codec->type == AVMEDIA_TYPE_VIDEO) {
|
||||
// Initialize Video Encoding
|
||||
auto voi = video_output_get_info(obs_encoder_video(_self));
|
||||
// Initialize Video Encoding
|
||||
auto voi = video_output_get_info(obs_encoder_video(_self));
|
||||
|
||||
// Figure out a suitable pixel format to convert to if necessary.
|
||||
AVPixelFormat pix_fmt_source = ::streamfx::ffmpeg::tools::obs_videoformat_to_avpixelformat(voi->format);
|
||||
AVPixelFormat pix_fmt_target = AV_PIX_FMT_NONE;
|
||||
{
|
||||
if (_codec->pix_fmts) {
|
||||
pix_fmt_target = ::streamfx::ffmpeg::tools::get_least_lossy_format(_codec->pix_fmts, pix_fmt_source);
|
||||
} else { // If there are no supported formats, just pass in the current one.
|
||||
pix_fmt_target = pix_fmt_source;
|
||||
}
|
||||
|
||||
if (_handler) // Allow Handler to override the automatic color format for sanity reasons.
|
||||
_handler->override_colorformat(this->_factory, this, settings, pix_fmt_target);
|
||||
// Figure out a suitable pixel format to convert to if necessary.
|
||||
AVPixelFormat pix_fmt_source = ::streamfx::ffmpeg::tools::obs_videoformat_to_avpixelformat(voi->format);
|
||||
AVPixelFormat pix_fmt_target = AV_PIX_FMT_NONE;
|
||||
{
|
||||
if (_codec->pix_fmts) {
|
||||
pix_fmt_target = ::streamfx::ffmpeg::tools::get_least_lossy_format(_codec->pix_fmts, pix_fmt_source);
|
||||
} else { // If there are no supported formats, just pass in the current one.
|
||||
pix_fmt_target = pix_fmt_source;
|
||||
}
|
||||
|
||||
// Setup from OBS information.
|
||||
::streamfx::ffmpeg::tools::context_setup_from_obs(voi, _context);
|
||||
if (_handler) // Allow Handler to override the automatic color format for sanity reasons.
|
||||
_handler->override_colorformat(this->_factory, this, settings, pix_fmt_target);
|
||||
}
|
||||
|
||||
// Override with other information.
|
||||
_context->width = static_cast<int>(obs_encoder_get_width(_self));
|
||||
_context->height = static_cast<int>(obs_encoder_get_height(_self));
|
||||
_context->pix_fmt = pix_fmt_target;
|
||||
// Setup from OBS information.
|
||||
::streamfx::ffmpeg::tools::context_setup_from_obs(voi, _context);
|
||||
|
||||
_scaler.set_source_size(static_cast<uint32_t>(_context->width), static_cast<uint32_t>(_context->height));
|
||||
_scaler.set_source_color(_context->color_range == AVCOL_RANGE_JPEG, _context->colorspace);
|
||||
_scaler.set_source_format(pix_fmt_source);
|
||||
// Override with other information.
|
||||
_context->width = static_cast<int>(obs_encoder_get_width(_self));
|
||||
_context->height = static_cast<int>(obs_encoder_get_height(_self));
|
||||
_context->pix_fmt = pix_fmt_target;
|
||||
|
||||
_scaler.set_target_size(static_cast<uint32_t>(_context->width), static_cast<uint32_t>(_context->height));
|
||||
_scaler.set_target_color(_context->color_range == AVCOL_RANGE_JPEG, _context->colorspace);
|
||||
_scaler.set_target_format(pix_fmt_target);
|
||||
_scaler.set_source_size(static_cast<uint32_t>(_context->width), static_cast<uint32_t>(_context->height));
|
||||
_scaler.set_source_color(_context->color_range == AVCOL_RANGE_JPEG, _context->colorspace);
|
||||
_scaler.set_source_format(pix_fmt_source);
|
||||
|
||||
// Create Scaler
|
||||
if (!_scaler.initialize(SWS_SINC | SWS_FULL_CHR_H_INT | SWS_FULL_CHR_H_INP | SWS_ACCURATE_RND | SWS_BITEXACT)) {
|
||||
std::stringstream sstr;
|
||||
sstr << "Initializing scaler failed for conversion from '" << ::streamfx::ffmpeg::tools::get_pixel_format_name(_scaler.get_source_format()) << "' to '" << ::streamfx::ffmpeg::tools::get_pixel_format_name(_scaler.get_target_format()) << "' with color space '" << ::streamfx::ffmpeg::tools::get_color_space_name(_scaler.get_source_colorspace()) << "' and " << (_scaler.is_source_full_range() ? "full" : "partial") << " range.";
|
||||
throw std::runtime_error(sstr.str());
|
||||
}
|
||||
_scaler.set_target_size(static_cast<uint32_t>(_context->width), static_cast<uint32_t>(_context->height));
|
||||
_scaler.set_target_color(_context->color_range == AVCOL_RANGE_JPEG, _context->colorspace);
|
||||
_scaler.set_target_format(pix_fmt_target);
|
||||
|
||||
// Create Scaler
|
||||
if (!_scaler.initialize(SWS_SINC | SWS_FULL_CHR_H_INT | SWS_FULL_CHR_H_INP | SWS_ACCURATE_RND | SWS_BITEXACT)) {
|
||||
std::stringstream sstr;
|
||||
sstr << "Initializing scaler failed for conversion from '" << ::streamfx::ffmpeg::tools::get_pixel_format_name(_scaler.get_source_format()) << "' to '" << ::streamfx::ffmpeg::tools::get_pixel_format_name(_scaler.get_target_format()) << "' with color space '" << ::streamfx::ffmpeg::tools::get_color_space_name(_scaler.get_source_colorspace()) << "' and " << (_scaler.is_source_full_range() ? "full" : "partial") << " range.";
|
||||
throw std::runtime_error(sstr.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1138,7 +1136,7 @@ ffmpeg_manager::ffmpeg_manager() : _factories()
|
|||
if (!av_codec_is_encoder(codec))
|
||||
continue;
|
||||
|
||||
if ((codec->type == AVMediaType::AVMEDIA_TYPE_AUDIO) || (codec->type == AVMediaType::AVMEDIA_TYPE_VIDEO)) {
|
||||
if (codec->type == AVMediaType::AVMEDIA_TYPE_VIDEO) {
|
||||
try {
|
||||
_factories.emplace(codec, std::make_shared<ffmpeg_factory>(this, codec));
|
||||
} catch (const std::exception& ex) {
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
// AUTOGENERATED COPYRIGHT HEADER START
|
||||
// Copyright (C) 2023 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
|
||||
// AUTOGENERATED COPYRIGHT HEADER END
|
||||
// Copyright (C) 2020-2023 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
|
||||
// Copyright (C) 2020 Daniel Molkentin <daniel@molkentin.de>
|
||||
|
||||
#include "cfhd.hpp"
|
||||
#include "common.hpp"
|
||||
#include "encoders/encoder-ffmpeg.hpp"
|
||||
#include "ffmpeg/tools.hpp"
|
||||
#include "handler.hpp"
|
||||
#include "plugin.hpp"
|
||||
|
||||
#include "warning-disable.hpp"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
extern "C" {
|
||||
#include <libavutil/opt.h>
|
||||
}
|
||||
#include "warning-enable.hpp"
|
||||
|
||||
using namespace streamfx::encoder::ffmpeg;
|
||||
|
||||
struct strings {
|
||||
struct quality {
|
||||
static constexpr const char* ffmpeg = "quality";
|
||||
static constexpr const char* obs = "Quality";
|
||||
static constexpr const char* i18n = "Encoder.FFmpeg.CineForm.Quality";
|
||||
};
|
||||
};
|
||||
|
||||
cfhd::cfhd() : handler("cfhd") {}
|
||||
|
||||
bool cfhd::has_keyframes(ffmpeg_factory* factory)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void cfhd::properties(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_properties_t* props)
|
||||
{
|
||||
// Try and acquire a valid context.
|
||||
std::shared_ptr<AVCodecContext> ctx;
|
||||
if (instance) {
|
||||
ctx = std::shared_ptr<AVCodecContext>(instance->get_avcodeccontext(), [](AVCodecContext*) {});
|
||||
} else { // If we don't have a context, create a temporary one that is automatically freed.
|
||||
ctx = std::shared_ptr<AVCodecContext>(avcodec_alloc_context3(factory->get_avcodec()), [](AVCodecContext* v) { avcodec_free_context(&v); });
|
||||
if (!ctx->priv_data) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{ // Quality parameter
|
||||
auto to_string = [](const char* v) {
|
||||
char buffer[1024];
|
||||
snprintf(buffer, sizeof(buffer), "%s.%s", strings::quality::i18n, v);
|
||||
return D_TRANSLATE(buffer);
|
||||
};
|
||||
|
||||
auto p = obs_properties_add_list(props, strings::quality::obs, D_TRANSLATE(strings::quality::i18n), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
|
||||
streamfx::ffmpeg::tools::avoption_list_add_entries(ctx->priv_data, strings::quality::ffmpeg, [&p, &to_string](const AVOption* opt) {
|
||||
// FFmpeg returns this list in the wrong order. We want to start at the lowest, and go to the highest.
|
||||
// So simply always insert at the top, and this will reverse the list.
|
||||
obs_property_list_insert_string(p, 0, to_string(opt->name), opt->name);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
std::string cfhd::help(ffmpeg_factory* factory)
|
||||
{
|
||||
return "https://github.com/Xaymar/obs-StreamFX/wiki/Encoder-FFmpeg-GoPro-CineForm";
|
||||
}
|
||||
|
||||
void cfhd::defaults(ffmpeg_factory* factory, obs_data_t* settings)
|
||||
{
|
||||
obs_data_set_string(settings, strings::quality::obs, "film3+");
|
||||
}
|
||||
|
||||
void cfhd::migrate(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings, uint64_t version) {}
|
||||
|
||||
void cfhd::update(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings)
|
||||
{
|
||||
if (const char* v = obs_data_get_string(settings, strings::quality::obs); v && (v[0] != '\0')) {
|
||||
av_opt_set(instance->get_avcodeccontext()->priv_data, strings::quality::ffmpeg, v, AV_OPT_SEARCH_CHILDREN);
|
||||
}
|
||||
}
|
||||
|
||||
static cfhd handler = cfhd();
|
|
@ -0,0 +1,26 @@
|
|||
// AUTOGENERATED COPYRIGHT HEADER START
|
||||
// Copyright (C) 2023 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
|
||||
// AUTOGENERATED COPYRIGHT HEADER END
|
||||
|
||||
#pragma once
|
||||
#include "handler.hpp"
|
||||
|
||||
namespace streamfx::encoder::ffmpeg {
|
||||
class cfhd : public handler {
|
||||
public:
|
||||
cfhd();
|
||||
virtual ~cfhd(){};
|
||||
|
||||
bool has_keyframes(ffmpeg_factory* factory) override;
|
||||
|
||||
std::string help(ffmpeg_factory* factory) override;
|
||||
|
||||
void defaults(ffmpeg_factory* factory, obs_data_t* settings) override;
|
||||
|
||||
void properties(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_properties_t* props) override;
|
||||
|
||||
void migrate(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings, uint64_t version) override;
|
||||
|
||||
void update(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings) override;
|
||||
};
|
||||
} // namespace streamfx::encoder::ffmpeg
|
|
@ -48,16 +48,17 @@ void dnxhd::defaults(ffmpeg_factory* factory, obs_data_t* settings)
|
|||
|
||||
void dnxhd::properties(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_properties_t* props)
|
||||
{
|
||||
AVCodecContext* ctx = instance->get_avcodeccontext();
|
||||
|
||||
//Create dummy context if null was passed to the function
|
||||
if (!ctx) {
|
||||
ctx = avcodec_alloc_context3(factory->get_avcodec());
|
||||
// Try and acquire a valid context.
|
||||
std::shared_ptr<AVCodecContext> ctx;
|
||||
if (instance) {
|
||||
ctx = std::shared_ptr<AVCodecContext>(instance->get_avcodeccontext(), [](AVCodecContext*) {});
|
||||
} else { // If we don't have a context, create a temporary one that is automatically freed.
|
||||
ctx = std::shared_ptr<AVCodecContext>(avcodec_alloc_context3(factory->get_avcodec()), [](AVCodecContext* v) { avcodec_free_context(&v); });
|
||||
if (!ctx->priv_data) {
|
||||
avcodec_free_context(&ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto p = obs_properties_add_list(props, S_CODEC_DNXHR_PROFILE, D_TRANSLATE(S_CODEC_DNXHR_PROFILE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
|
||||
|
||||
streamfx::ffmpeg::tools::avoption_list_add_entries(ctx->priv_data, "profile", [&p](const AVOption* opt) {
|
||||
|
@ -72,11 +73,6 @@ void dnxhd::properties(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_p
|
|||
//Therefore, new entries will always be inserted at the top, effectively reversing the list
|
||||
obs_property_list_insert_string(p, 0, dnx_profile_to_display_name(opt->name), opt->name);
|
||||
});
|
||||
|
||||
//Free context if we created it here
|
||||
if (ctx && ctx != instance->get_avcodeccontext()) {
|
||||
avcodec_free_context(&ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void dnxhd::update(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings)
|
||||
|
|
|
@ -136,7 +136,6 @@ MODULE_EXPORT void obs_module_unload(void)
|
|||
_streamfx_gfx_opengl.reset();
|
||||
}
|
||||
|
||||
|
||||
DLOG_INFO("Unloaded Version %s", STREAMFX_VERSION_STRING);
|
||||
} catch (std::exception const& ex) {
|
||||
DLOG_ERROR("Unexpected exception in function '%s': %s", __FUNCTION_NAME__, ex.what());
|
||||
|
|
|
@ -4,9 +4,25 @@
|
|||
|
||||
#include "warning-disable.hpp"
|
||||
#include <Windows.h>
|
||||
#include <mutex>
|
||||
#include "warning-enable.hpp"
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
|
||||
std::shared_ptr<void> local_mutex;
|
||||
std::shared_ptr<void> global_mutex;
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE, DWORD dwReason, LPVOID)
|
||||
{
|
||||
if (dwReason == DLL_PROCESS_ATTACH) {
|
||||
// Prevent installer from progressing while StreamFX is still active.
|
||||
local_mutex = std::shared_ptr<void>(CreateMutexW(NULL, TRUE, L"Local\\StreamFX-Setup"), [](HANDLE p) {
|
||||
ReleaseMutex(p);
|
||||
CloseHandle(p);
|
||||
});
|
||||
global_mutex = std::shared_ptr<void>(CreateMutexW(NULL, TRUE, L"Global\\StreamFX-Setup"), [](HANDLE p) {
|
||||
ReleaseMutex(p);
|
||||
CloseHandle(p);
|
||||
});
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ function user32_SendTextMessageTimeoutA(
|
|||
uTimeout: UINT;
|
||||
out lpdwResult: DWORD): LRESULT;
|
||||
external 'SendMessageTimeoutA@user32.dll stdcall';
|
||||
|
||||
|
||||
procedure RefreshEnvironment();
|
||||
var
|
||||
S: AnsiString;
|
||||
|
@ -238,7 +238,10 @@ var
|
|||
begin
|
||||
// Attempt to remove old version if it exists.
|
||||
if (IsUpgrade()) then begin
|
||||
UninstallOldVersion();
|
||||
if (UninstallOldVersion() <> 0) then begin
|
||||
Result := 'Removal of older @PROJECT_NAME@ version was cancelled. Unable to continue with normal installation process, Setup will now abort.';
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Also ensure that we have the necessary prerequisites installed to run the program.
|
||||
|
@ -247,11 +250,11 @@ begin
|
|||
|
||||
// If this is a User install, register the necessary environment changes.
|
||||
if (IsUserMode()) then begin
|
||||
sPluginsPath := ExpandConstant('{userpf}\obs-studio\plugins\%module%\bin\');
|
||||
sPluginsPath := ExpandConstant('{usercf}\obs-studio\plugins\%module%\bin\');
|
||||
StringChangeEx(sPluginsPath, '\', '/', True);
|
||||
RegWriteExpandStringValue(HKEY_CURRENT_USER, 'Environment', 'OBS_PLUGINS_PATH', sPluginsPath);
|
||||
|
||||
sPluginsDataPath := ExpandConstant('{userpf}\obs-studio\plugins\%module%\data\');
|
||||
sPluginsDataPath := ExpandConstant('{usercf}\obs-studio\plugins\%module%\data\');
|
||||
StringChangeEx(sPluginsDataPath, '\', '/', True);
|
||||
RegWriteExpandStringValue(HKEY_CURRENT_USER, 'Environment', 'OBS_PLUGINS_DATA_PATH', sPluginsDataPath);
|
||||
|
||||
|
@ -268,8 +271,8 @@ begin
|
|||
if (IsSystemMode()) then begin
|
||||
// Default to ProgramData/obs-studio/@PROJECT_NAME@
|
||||
Result := ExpandConstant('{commonappdata}\obs-studio\plugins\@PROJECT_NAME@');
|
||||
end else if (IsUserMode()) then begin
|
||||
Result := ExpandConstant('{userpf}\obs-studio\plugins\@PROJECT_NAME@');
|
||||
end else if (IsUserMode()) then begin
|
||||
Result := ExpandConstant('{usercf}\obs-studio\plugins\@PROJECT_NAME@');
|
||||
end else begin
|
||||
// If a path was given as an argument, use it.
|
||||
if (Value <> '') then begin
|
||||
|
@ -340,7 +343,7 @@ begin
|
|||
Result := '';
|
||||
if (RegQueryStringValue(HKCU64, AppRegistryKey(), 'UninstallString', sPath)) then begin
|
||||
Result := sPath;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function IsUserInstallPresent(): Boolean;
|
||||
|
@ -404,7 +407,7 @@ begin
|
|||
sUninstallerPath := GetUninstallerPath();
|
||||
if (sUninstallerPath <> '') then begin
|
||||
sUninstallerPath := RemoveQuotes(sUninstallerPath);
|
||||
if Exec(sUninstallerPath, '/VERYSILENT /NORESTART /SUPPRESSMSGBOXES', '', SW_HIDE, ewWaitUntilTerminated, iResultCode) then begin
|
||||
if Exec(sUninstallerPath, '', '', SW_HIDE, ewWaitUntilTerminated, iResultCode) then begin
|
||||
Result := iResultCode
|
||||
end else begin
|
||||
Result := 1
|
||||
|
@ -440,7 +443,7 @@ begin
|
|||
bIsSystemMode := False;
|
||||
bIsUserMode := True;
|
||||
bIsPortableMode := False;
|
||||
|
||||
|
||||
WizardSelectComponents('startmenu');
|
||||
end;
|
||||
end;
|
||||
|
@ -453,7 +456,7 @@ begin
|
|||
bIsSystemMode := False;
|
||||
bIsUserMode := False;
|
||||
bIsPortableMode := True;
|
||||
|
||||
|
||||
WizardSelectComponents('!startmenu');
|
||||
end;
|
||||
|
||||
|
@ -521,7 +524,7 @@ begin
|
|||
oSystemText.WordWrap := True
|
||||
oSystemText.Caption := 'Install for all users of this System, which will require Administrator rights for future updates. May cause problems with Portable and Current User installations.';
|
||||
oSystemText.OnClick := @OnModePageSystemChoiceClick;
|
||||
|
||||
|
||||
// Not available without Administrator rights.
|
||||
if (not IsAdmin()) then begin
|
||||
oSystemWarningText := TLabel.Create(oSystemPanel);
|
||||
|
@ -598,7 +601,7 @@ begin
|
|||
oUserText.WordWrap := True
|
||||
oUserText.Caption := 'Install for the current user only, which will allow you to use @PROJECT_NAME@. Updating will not require Administrator rights.';
|
||||
oUserText.OnClick := @OnModePageUserChoiceClick;
|
||||
|
||||
|
||||
// Not available with Administrator rights.
|
||||
if (IsAdmin()) then begin
|
||||
oUserWarningText := TLabel.Create(oUserPanel);
|
||||
|
@ -680,7 +683,7 @@ begin
|
|||
oPortableText.WordWrap := True
|
||||
oPortableText.Caption := 'Install for a portable OBS Studio environment.';
|
||||
oPortableText.OnClick := @OnModePagePortableChoiceClick;
|
||||
|
||||
|
||||
// Warn about Administrator rights
|
||||
if (IsAdmin()) then begin
|
||||
oPortableWarningText := TLabel.Create(oPortablePanel);
|
||||
|
|
Loading…
Reference in New Issue