New upstream version 26.0.2+dfsg1

This commit is contained in:
Sebastian Ramacher 2020-10-12 22:28:36 +02:00
parent bc27b6c1ca
commit 040dcc3fc2
23 changed files with 226 additions and 184 deletions

View file

@ -9,7 +9,7 @@ env:
task: task:
install_script: install_script:
- pkg install -y - pkg install -y
v4l_compat swig30 ffmpeg curl dbus fdk-aac fontconfig v4l_compat swig ffmpeg curl dbus fdk-aac fontconfig
freetype2 jackit jansson luajit mbedtls pulseaudio speexdsp freetype2 jackit jansson luajit mbedtls pulseaudio speexdsp
libsysinfo libudev-devd libv4l libx264 cmake ninja libsysinfo libudev-devd libv4l libx264 cmake ninja
mesa-libs lua52 pkgconf mesa-libs lua52 pkgconf

View file

@ -236,8 +236,14 @@ jobs:
cp ../CI/scripts/macos/app/OBSPublicDSAKey.pem ./OBS.app/Contents/Resources cp ../CI/scripts/macos/app/OBSPublicDSAKey.pem ./OBS.app/Contents/Resources
if [ "${GITHUB_REF:0:10}" = "refs/tags/" ]; then
plutil -insert CFBundleVersion -string ${{ env.OBS_GIT_TAG }} ./OBS.app/Contents/Info.plist
plutil -insert CFBundleShortVersionString -string ${{ env.OBS_GIT_TAG }} ./OBS.app/Contents/Info.plist
else
plutil -insert CFBundleVersion -string ${{ env.OBS_GIT_TAG }}-${{ env.OBS_GIT_HASH }} ./OBS.app/Contents/Info.plist plutil -insert CFBundleVersion -string ${{ env.OBS_GIT_TAG }}-${{ env.OBS_GIT_HASH }} ./OBS.app/Contents/Info.plist
plutil -insert CFBundleShortVersionString -string ${{ env.OBS_GIT_TAG }}-${{ env.OBS_GIT_HASH }} ./OBS.app/Contents/Info.plist plutil -insert CFBundleShortVersionString -string ${{ env.OBS_GIT_TAG }}-${{ env.OBS_GIT_HASH }} ./OBS.app/Contents/Info.plist
fi
plutil -insert OBSFeedsURL -string https://obsproject.com/osx_update/feeds.xml ./OBS.app/Contents/Info.plist plutil -insert OBSFeedsURL -string https://obsproject.com/osx_update/feeds.xml ./OBS.app/Contents/Info.plist
plutil -insert SUFeedURL -string https://obsproject.com/osx_update/stable/updates.xml ./OBS.app/Contents/Info.plist plutil -insert SUFeedURL -string https://obsproject.com/osx_update/stable/updates.xml ./OBS.app/Contents/Info.plist
plutil -insert SUPublicDSAKeyFile -string OBSPublicDSAKey.pem ./OBS.app/Contents/Info.plist plutil -insert SUPublicDSAKeyFile -string OBSPublicDSAKey.pem ./OBS.app/Contents/Info.plist

View file

@ -219,6 +219,13 @@ Var dllFilesInUse
Function checkDLLs Function checkDLLs
OBSInstallerUtils::ResetInUseFileChecks OBSInstallerUtils::ResetInUseFileChecks
!ifdef INSTALL64
OBSInstallerUtils::AddInUseFileCheck "$INSTDIR\bin\64bit\avutil-56.dll"
OBSInstallerUtils::AddInUseFileCheck "$INSTDIR\bin\64bit\swscale-5.dll"
!else
OBSInstallerUtils::AddInUseFileCheck "$INSTDIR\bin\32bit\avutil-56.dll"
OBSInstallerUtils::AddInUseFileCheck "$INSTDIR\bin\32bit\swscale-5.dll"
!endif
OBSInstallerUtils::AddInUseFileCheck "$INSTDIR\data\obs-plugins\win-capture\graphics-hook32.dll" OBSInstallerUtils::AddInUseFileCheck "$INSTDIR\data\obs-plugins\win-capture\graphics-hook32.dll"
OBSInstallerUtils::AddInUseFileCheck "$INSTDIR\data\obs-plugins\win-capture\graphics-hook64.dll" OBSInstallerUtils::AddInUseFileCheck "$INSTDIR\data\obs-plugins\win-capture\graphics-hook64.dll"
OBSInstallerUtils::AddInUseFileCheck "$INSTDIR\data\obs-plugins\win-dshow\obs-virtualcam-module32.dll" OBSInstallerUtils::AddInUseFileCheck "$INSTDIR\data\obs-plugins\win-dshow\obs-virtualcam-module32.dll"

View file

@ -1981,7 +1981,7 @@ static int run_program(fstream &logFile, int argc, char *argv[])
run: run:
#endif #endif
#if !defined(_WIN32) && !defined(__APPLE__) #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__FreeBSD__)
// Mounted by termina during chromeOS linux container startup // Mounted by termina during chromeOS linux container startup
// https://chromium.googlesource.com/chromiumos/overlays/board-overlays/+/master/project-termina/chromeos-base/termina-lxd-scripts/files/lxd_setup.sh // https://chromium.googlesource.com/chromiumos/overlays/board-overlays/+/master/project-termina/chromeos-base/termina-lxd-scripts/files/lxd_setup.sh
os_dir_t *crosDir = os_opendir("/opt/google/cros-containers"); os_dir_t *crosDir = os_opendir("/opt/google/cros-containers");

View file

@ -144,6 +144,13 @@ bool IsAlwaysOnTop(QWidget *window)
return (window->windowFlags() & Qt::WindowStaysOnTopHint) != 0; return (window->windowFlags() & Qt::WindowStaysOnTopHint) != 0;
} }
void disableColorSpaceConversion(QWidget *window)
{
NSView *view =
(__bridge NSView *)reinterpret_cast<void *>(window->winId());
view.window.colorSpace = NSColorSpace.sRGBColorSpace;
}
void SetAlwaysOnTop(QWidget *window, bool enable) void SetAlwaysOnTop(QWidget *window, bool enable)
{ {
Qt::WindowFlags flags = window->windowFlags(); Qt::WindowFlags flags = window->windowFlags();

View file

@ -67,4 +67,5 @@ QString GetMonitorName(const QString &id);
void EnableOSXVSync(bool enable); void EnableOSXVSync(bool enable);
void EnableOSXDockIcon(bool enable); void EnableOSXDockIcon(bool enable);
void InstallNSApplicationSubclass(); void InstallNSApplicationSubclass();
void disableColorSpaceConversion(QWidget *window);
#endif #endif

View file

@ -531,6 +531,8 @@ VolumeMeter::VolumeMeter(QWidget *parent, obs_volmeter_t *obs_volmeter,
bool vertical) bool vertical)
: QWidget(parent), obs_volmeter(obs_volmeter), vertical(vertical) : QWidget(parent), obs_volmeter(obs_volmeter), vertical(vertical)
{ {
setAttribute(Qt::WA_OpaquePaintEvent, true);
// Use a font that can be rendered small. // Use a font that can be rendered small.
tickFont = QFont("Arial"); tickFont = QFont("Arial");
tickFont.setPixelSize(7); tickFont.setPixelSize(7);
@ -1041,6 +1043,11 @@ void VolumeMeter::paintEvent(QPaintEvent *event)
// Actual painting of the widget starts here. // Actual painting of the widget starts here.
QPainter painter(this); QPainter painter(this);
// Paint window background color (as widget is opaque)
QColor background = palette().color(QPalette::ColorRole::Window);
painter.fillRect(rect, background);
if (vertical) { if (vertical) {
// Invert the Y axis to ease the math // Invert the Y axis to ease the math
painter.translate(0, height); painter.translate(0, height);

View file

@ -45,11 +45,13 @@ void StringToHash(const wchar_t *in, BYTE *out)
bool CalculateFileHash(const wchar_t *path, BYTE *hash) bool CalculateFileHash(const wchar_t *path, BYTE *hash)
{ {
static BYTE hashBuffer[1048576]; static __declspec(thread) vector<BYTE> hashBuffer;
blake2b_state blake2; blake2b_state blake2;
if (blake2b_init(&blake2, BLAKE2_HASH_LENGTH) != 0) if (blake2b_init(&blake2, BLAKE2_HASH_LENGTH) != 0)
return false; return false;
hashBuffer.resize(1048576);
WinHandle handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, WinHandle handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ,
nullptr, OPEN_EXISTING, 0, nullptr); nullptr, OPEN_EXISTING, 0, nullptr);
if (handle == INVALID_HANDLE_VALUE) if (handle == INVALID_HANDLE_VALUE)
@ -57,14 +59,14 @@ bool CalculateFileHash(const wchar_t *path, BYTE *hash)
for (;;) { for (;;) {
DWORD read = 0; DWORD read = 0;
if (!ReadFile(handle, hashBuffer, sizeof(hashBuffer), &read, if (!ReadFile(handle, &hashBuffer[0], hashBuffer.size(), &read,
nullptr)) nullptr))
return false; return false;
if (!read) if (!read)
break; break;
if (blake2b_update(&blake2, hashBuffer, read) != 0) if (blake2b_update(&blake2, &hashBuffer[0], read) != 0)
return false; return false;
} }

View file

@ -1427,6 +1427,23 @@ static bool Update(wchar_t *cmdLine)
/* ------------------------------------- * /* ------------------------------------- *
* Install virtual camera */ * Install virtual camera */
auto runcommand = [](wchar_t *cmd) {
STARTUPINFO si = {};
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
PROCESS_INFORMATION pi;
bool success = !!CreateProcessW(nullptr, cmd, nullptr, nullptr,
false, CREATE_NEW_CONSOLE,
nullptr, nullptr, &si, &pi);
if (success) {
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
};
if (!bIsPortable) { if (!bIsPortable) {
wchar_t regsvr[MAX_PATH]; wchar_t regsvr[MAX_PATH];
wchar_t src[MAX_PATH]; wchar_t src[MAX_PATH];
@ -1441,20 +1458,20 @@ static bool Update(wchar_t *cmdLine)
StringCbCat(src, sizeof(src), StringCbCat(src, sizeof(src),
L"\\data\\obs-plugins\\win-dshow\\"); L"\\data\\obs-plugins\\win-dshow\\");
StringCbCopy(tmp, sizeof(tmp), L"\"\""); StringCbCopy(tmp, sizeof(tmp), L"\"");
StringCbCat(tmp, sizeof(tmp), regsvr); StringCbCat(tmp, sizeof(tmp), regsvr);
StringCbCat(tmp, sizeof(tmp), L"\" /s \""); StringCbCat(tmp, sizeof(tmp), L"\" /s \"");
StringCbCat(tmp, sizeof(tmp), src); StringCbCat(tmp, sizeof(tmp), src);
StringCbCat(tmp, sizeof(tmp), L"obs-virtualcam-module"); StringCbCat(tmp, sizeof(tmp), L"obs-virtualcam-module");
StringCbCopy(tmp2, sizeof(tmp2), tmp); StringCbCopy(tmp2, sizeof(tmp2), tmp);
StringCbCat(tmp2, sizeof(tmp2), L"32.dll\"\""); StringCbCat(tmp2, sizeof(tmp2), L"32.dll\"");
_wsystem(tmp2); runcommand(tmp2);
if (is_64bit_windows()) { if (is_64bit_windows()) {
StringCbCopy(tmp2, sizeof(tmp2), tmp); StringCbCopy(tmp2, sizeof(tmp2), tmp);
StringCbCat(tmp2, sizeof(tmp2), L"64.dll\"\""); StringCbCat(tmp2, sizeof(tmp2), L"64.dll\"");
_wsystem(tmp2); runcommand(tmp2);
} }
} }

View file

@ -50,8 +50,14 @@ static inline QString MakeQuickTransitionText(QuickTransition *qt)
void OBSBasic::InitDefaultTransitions() void OBSBasic::InitDefaultTransitions()
{ {
struct AddTransitionVal {
QString id;
QString name;
};
ui->transitions->blockSignals(true); ui->transitions->blockSignals(true);
std::vector<OBSSource> transitions; std::vector<OBSSource> transitions;
std::vector<AddTransitionVal> addables;
size_t idx = 0; size_t idx = 0;
const char *id; const char *id;
@ -73,25 +79,57 @@ void OBSBasic::InitDefaultTransitions()
obs_source_release(tr); obs_source_release(tr);
} else { } else {
QString addString = QTStr("Add") + AddTransitionVal val;
QStringLiteral(": ") + val.name = QTStr("Add") + QStringLiteral(": ") +
QT_UTF8(name); QT_UTF8(name);
ui->transitions->addItem( val.id = QT_UTF8(id);
addString, addables.push_back(val);
QVariant::fromValue(QString(QT_UTF8(id))));
} }
} }
if (ui->transitions->count())
ui->transitions->insertSeparator(ui->transitions->count());
for (OBSSource &tr : transitions) { for (OBSSource &tr : transitions) {
ui->transitions->addItem(QT_UTF8(obs_source_get_name(tr)), ui->transitions->addItem(QT_UTF8(obs_source_get_name(tr)),
QVariant::fromValue(OBSSource(tr))); QVariant::fromValue(OBSSource(tr)));
} }
if (addables.size())
ui->transitions->insertSeparator(ui->transitions->count());
for (AddTransitionVal &val : addables) {
ui->transitions->addItem(val.name, QVariant::fromValue(val.id));
}
ui->transitions->blockSignals(false); ui->transitions->blockSignals(false);
} }
int OBSBasic::TransitionCount()
{
int idx = 0;
for (int i = 0; i < ui->transitions->count(); i++) {
QVariant v = ui->transitions->itemData(i);
if (!v.toString().isEmpty()) {
idx = i;
break;
}
}
/* should always have at least fade and cut due to them being
* defaults */
assert(idx != 0);
return idx - 1; /* remove separator from equation */
}
int OBSBasic::AddTransitionBeforeSeparator(const QString &name,
obs_source_t *source)
{
int idx = TransitionCount();
ui->transitions->blockSignals(true);
ui->transitions->insertItem(idx, name,
QVariant::fromValue(OBSSource(source)));
ui->transitions->blockSignals(false);
return idx;
}
void OBSBasic::AddQuickTransitionHotkey(QuickTransition *qt) void OBSBasic::AddQuickTransitionHotkey(QuickTransition *qt)
{ {
DStr hotkeyId; DStr hotkeyId;
@ -506,10 +544,9 @@ void OBSBasic::AddTransition(QString id)
source = obs_source_create_private(QT_TO_UTF8(id), name.c_str(), source = obs_source_create_private(QT_TO_UTF8(id), name.c_str(),
NULL); NULL);
InitTransition(source); InitTransition(source);
ui->transitions->addItem( int idx = AddTransitionBeforeSeparator(QT_UTF8(name.c_str()),
QT_UTF8(name.c_str()), source);
QVariant::fromValue(OBSSource(source))); ui->transitions->setCurrentIndex(idx);
ui->transitions->setCurrentIndex(ui->transitions->count() - 1);
CreatePropertiesWindow(source); CreatePropertiesWindow(source);
obs_source_release(source); obs_source_release(source);
@ -548,7 +585,15 @@ void OBSBasic::on_transitionRemove_clicked()
} }
} }
ui->transitions->blockSignals(true);
ui->transitions->removeItem(idx); ui->transitions->removeItem(idx);
ui->transitions->setCurrentIndex(-1);
ui->transitions->blockSignals(false);
int bottomIdx = TransitionCount() - 1;
if (idx > bottomIdx)
idx = bottomIdx;
ui->transitions->setCurrentIndex(idx);
if (api) if (api)
api->on_event(OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED); api->on_event(OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED);
@ -1540,9 +1585,7 @@ void OBSBasic::LoadTransitions(obs_data_array_t *transitions)
obs_source_create_private(id, name, settings); obs_source_create_private(id, name, settings);
if (!obs_obj_invalid(source)) { if (!obs_obj_invalid(source)) {
InitTransition(source); InitTransition(source);
ui->transitions->addItem( AddTransitionBeforeSeparator(QT_UTF8(name), source);
QT_UTF8(name),
QVariant::fromValue(OBSSource(source)));
} }
obs_data_release(settings); obs_data_release(settings);

View file

@ -326,6 +326,10 @@ OBSBasic::OBSBasic(QWidget *parent)
renameSource->setShortcut({Qt::Key_F2}); renameSource->setShortcut({Qt::Key_F2});
#endif #endif
#ifdef __linux__
ui->actionE_xit->setShortcut(Qt::CTRL + Qt::Key_Q);
#endif
auto addNudge = [this](const QKeySequence &seq, const char *s) { auto addNudge = [this](const QKeySequence &seq, const char *s) {
QAction *nudge = new QAction(ui->preview); QAction *nudge = new QAction(ui->preview);
nudge->setShortcut(seq); nudge->setShortcut(seq);
@ -1554,6 +1558,8 @@ void OBSBasic::AddVCamButton()
vcamButton->setProperty("themeID", "vcamButton"); vcamButton->setProperty("themeID", "vcamButton");
ui->buttonsVLayout->insertWidget(2, vcamButton); ui->buttonsVLayout->insertWidget(2, vcamButton);
setTabOrder(ui->recordButton, vcamButton);
setTabOrder(vcamButton, ui->modeSwitch);
} }
void OBSBasic::ResetOutputs() void OBSBasic::ResetOutputs()
@ -1588,6 +1594,9 @@ void OBSBasic::ResetOutputs()
replayBufferButton->setProperty("themeID", replayBufferButton->setProperty("themeID",
"replayBufferButton"); "replayBufferButton");
ui->buttonsVLayout->insertLayout(2, replayLayout); ui->buttonsVLayout->insertLayout(2, replayLayout);
setTabOrder(ui->recordButton, replayBufferButton);
setTabOrder(replayBufferButton,
ui->buttonsVLayout->itemAt(3)->widget());
} }
if (sysTrayReplayBuffer) if (sysTrayReplayBuffer)
@ -1867,6 +1876,10 @@ void OBSBasic::OBSInit()
SystemTray(true); SystemTray(true);
#endif #endif
#ifdef __APPLE__
disableColorSpaceConversion(this);
#endif
bool has_last_version = config_has_user_value(App()->GlobalConfig(), bool has_last_version = config_has_user_value(App()->GlobalConfig(),
"General", "LastVersion"); "General", "LastVersion");
bool first_run = bool first_run =
@ -7035,15 +7048,6 @@ OBSProjector *OBSBasic::OpenProjector(obs_source_t *source, int monitor,
if (monitor > 9 || monitor > QGuiApplication::screens().size() - 1) if (monitor > 9 || monitor > QGuiApplication::screens().size() - 1)
return nullptr; return nullptr;
if (monitor > -1) {
for (size_t i = 0; i < projectors.size(); i++) {
if (projectors[i]->GetMonitor() == monitor) {
DeleteProjector(projectors[i]);
break;
}
}
}
OBSProjector *projector = OBSProjector *projector =
new OBSProjector(nullptr, source, monitor, type); new OBSProjector(nullptr, source, monitor, type);
@ -8211,6 +8215,10 @@ void OBSBasic::UpdateReplayBuffer(bool activate)
connect(replay.data(), &QAbstractButton::clicked, this, connect(replay.data(), &QAbstractButton::clicked, this,
&OBSBasic::ReplayBufferSave); &OBSBasic::ReplayBufferSave);
replayLayout->addWidget(replay.data()); replayLayout->addWidget(replay.data());
setTabOrder(replayLayout->itemAt(0)->widget(),
replayLayout->itemAt(1)->widget());
setTabOrder(replayLayout->itemAt(1)->widget(),
ui->buttonsVLayout->itemAt(3)->widget());
} }
#define MBYTE (1024ULL * 1024ULL) #define MBYTE (1024ULL * 1024ULL)

View file

@ -401,6 +401,9 @@ private:
void CreateProgramDisplay(); void CreateProgramDisplay();
void CreateProgramOptions(); void CreateProgramOptions();
int TransitionCount();
int AddTransitionBeforeSeparator(const QString &name,
obs_source_t *source);
void AddQuickTransitionId(int id); void AddQuickTransitionId(int id);
void AddQuickTransition(); void AddQuickTransition();
void AddQuickTransitionHotkey(QuickTransition *qt); void AddQuickTransitionHotkey(QuickTransition *qt);

View file

@ -32,7 +32,9 @@ find_path(Libfdk_INCLUDE_DIR
${DepsPath} ${DepsPath}
${_LIBFDK_INCLUDE_DIRS} ${_LIBFDK_INCLUDE_DIRS}
PATHS PATHS
/usr/include /usr/local/include /opt/local/include /sw/include) /usr/include /usr/local/include /opt/local/include /sw/include
PATH_SUFFIXES
include)
find_library(Libfdk_LIB find_library(Libfdk_LIB
NAMES ${_LIBFDK_LIBRARIES} fdk-aac libfdk-aac NAMES ${_LIBFDK_LIBRARIES} fdk-aac libfdk-aac

View file

@ -137,58 +137,6 @@ struct winrt_capture {
BOOL active; BOOL active;
struct winrt_capture *next; struct winrt_capture *next;
void draw_cursor()
{
CURSORINFO ci{};
ci.cbSize = sizeof(CURSORINFO);
if (!GetCursorInfo(&ci))
return;
if (!(ci.flags & CURSOR_SHOWING))
return;
HICON icon = CopyIcon(ci.hCursor);
if (!icon)
return;
ICONINFO ii;
if (GetIconInfo(icon, &ii)) {
POINT win_pos{};
if (window) {
if (client_area) {
ClientToScreen(window, &win_pos);
} else {
RECT window_rect;
if (DwmGetWindowAttribute(
window,
DWMWA_EXTENDED_FRAME_BOUNDS,
&window_rect,
sizeof(window_rect)) ==
S_OK) {
win_pos.x = window_rect.left;
win_pos.y = window_rect.top;
}
}
}
POINT pos;
pos.x = ci.ptScreenPos.x - (int)ii.xHotspot - win_pos.x;
pos.y = ci.ptScreenPos.y - (int)ii.yHotspot - win_pos.y;
HDC hdc = (HDC)gs_texture_get_dc(texture);
DrawIconEx(hdc, pos.x, pos.y, icon, 0, 0, 0, NULL,
DI_NORMAL);
gs_texture_release_dc(texture);
DeleteObject(ii.hbmColor);
DeleteObject(ii.hbmMask);
}
DestroyIcon(icon);
}
void on_closed( void on_closed(
winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &, winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &,
winrt::Windows::Foundation::IInspectable const &) winrt::Windows::Foundation::IInspectable const &)
@ -256,10 +204,6 @@ struct winrt_capture {
frame_surface.get()); frame_surface.get());
} }
if (capture_cursor && cursor_visible) {
draw_cursor();
}
texture_written = true; texture_written = true;
} }
@ -342,9 +286,9 @@ static void winrt_capture_device_loss_rebuild(void *device_void, void *data)
const winrt::Windows::Graphics::Capture::GraphicsCaptureSession session = const winrt::Windows::Graphics::Capture::GraphicsCaptureSession session =
frame_pool.CreateCaptureSession(item); frame_pool.CreateCaptureSession(item);
/* disable cursor capture if possible since ours performs better */
if (winrt_capture_cursor_toggle_supported()) if (winrt_capture_cursor_toggle_supported())
session.IsCursorCaptureEnabled(false); session.IsCursorCaptureEnabled(capture->capture_cursor &&
capture->cursor_visible);
capture->item = item; capture->item = item;
capture->device = device; capture->device = device;
@ -425,12 +369,13 @@ try {
const BOOL cursor_toggle_supported = const BOOL cursor_toggle_supported =
winrt_capture_cursor_toggle_supported(); winrt_capture_cursor_toggle_supported();
if (cursor_toggle_supported) if (cursor_toggle_supported)
session.IsCursorCaptureEnabled(false); session.IsCursorCaptureEnabled(cursor);
struct winrt_capture *capture = new winrt_capture{}; struct winrt_capture *capture = new winrt_capture{};
capture->window = window; capture->window = window;
capture->client_area = client_area; capture->client_area = client_area;
capture->capture_cursor = cursor && cursor_toggle_supported; capture->capture_cursor = cursor && cursor_toggle_supported;
capture->cursor_visible = cursor;
capture->item = item; capture->item = item;
capture->device = device; capture->device = device;
d3d_device->GetImmediateContext(&capture->context); d3d_device->GetImmediateContext(&capture->context);
@ -523,7 +468,12 @@ extern "C" EXPORT BOOL winrt_capture_active(const struct winrt_capture *capture)
extern "C" EXPORT void winrt_capture_show_cursor(struct winrt_capture *capture, extern "C" EXPORT void winrt_capture_show_cursor(struct winrt_capture *capture,
BOOL visible) BOOL visible)
{ {
if (capture->capture_cursor) {
if (capture->cursor_visible != visible) {
capture->session.IsCursorCaptureEnabled(visible);
capture->cursor_visible = visible; capture->cursor_visible = visible;
}
}
} }
extern "C" EXPORT void winrt_capture_render(struct winrt_capture *capture, extern "C" EXPORT void winrt_capture_render(struct winrt_capture *capture,

View file

@ -41,7 +41,7 @@
* *
* Reset to zero each major or minor version * Reset to zero each major or minor version
*/ */
#define LIBOBS_API_PATCH_VER 0 #define LIBOBS_API_PATCH_VER 2
#define MAKE_SEMANTIC_VERSION(major, minor, patch) \ #define MAKE_SEMANTIC_VERSION(major, minor, patch) \
((major << 24) | (minor << 16) | patch) ((major << 24) | (minor << 16) | patch)

View file

@ -361,49 +361,60 @@ static HMODULE audio_toolbox = NULL;
static void release_lib(void) static void release_lib(void)
{ {
#define RELEASE_LIB(x) \ if (audio_toolbox) {
if (x) { \ FreeLibrary(audio_toolbox);
FreeLibrary(x); \ audio_toolbox = NULL;
x = NULL; \ }
}
static bool load_from_shell_path(REFKNOWNFOLDERID rfid, const wchar_t *subpath)
{
wchar_t *sh_path;
if (SHGetKnownFolderPath(rfid, 0, NULL, &sh_path) != S_OK) {
CA_LOG(LOG_WARNING, "Could not retrieve shell path");
return false;
} }
RELEASE_LIB(audio_toolbox); wchar_t path[MAX_PATH];
#undef RELEASE_LIB _snwprintf(path, MAX_PATH, L"%s\\%s", sh_path, subpath);
CoTaskMemFree(sh_path);
SetDllDirectory(path);
audio_toolbox = LoadLibraryW(L"CoreAudioToolbox.dll");
SetDllDirectory(nullptr);
return !!audio_toolbox;
} }
static bool load_lib(void) static bool load_lib(void)
{ {
PWSTR common_path; /* -------------------------------------------- */
if (SHGetKnownFolderPath(FOLDERID_ProgramFilesCommon, 0, NULL, /* attempt to load from path */
&common_path) != S_OK) {
CA_LOG(LOG_WARNING, "Could not retrieve common files path");
return false;
}
struct dstr path = {0}; audio_toolbox = LoadLibraryW(L"CoreAudioToolbox.dll");
dstr_printf(&path, "%S\\Apple\\Apple Application Support", common_path); if (!!audio_toolbox)
CoTaskMemFree(common_path);
wchar_t *w_path = dstr_to_wcs(&path);
dstr_free(&path);
SetDllDirectory(w_path);
bfree(w_path);
#define LOAD_LIB(x, n) \
x = LoadLibrary(TEXT(n)); \
if (!x) \
CA_LOG(LOG_DEBUG, "Failed loading library '" n "'");
LOAD_LIB(audio_toolbox, "CoreAudioToolbox.dll");
#undef LOAD_LIB
SetDllDirectory(NULL);
if (audio_toolbox)
return true; return true;
release_lib(); /* -------------------------------------------- */
/* attempt to load from known install locations */
struct path_list_t {
REFKNOWNFOLDERID rfid;
const wchar_t *subpath;
};
path_list_t path_list[] = {
{FOLDERID_ProgramFilesCommon,
L"Apple\\Apple Application Support"},
{FOLDERID_ProgramFiles, L"iTunes"},
};
for (auto &val : path_list) {
if (load_from_shell_path(val.rfid, val.subpath)) {
return true;
}
}
return false; return false;
} }

View file

@ -18,8 +18,6 @@ typedef struct cocoa_window *cocoa_window_t;
NSArray *enumerate_cocoa_windows(void); NSArray *enumerate_cocoa_windows(void);
NSArray *filter_nonzero_kcgwindowlayer_sources(NSArray *windows_arr);
bool find_window(cocoa_window_t cw, obs_data_t *settings, bool force); bool find_window(cocoa_window_t cw, obs_data_t *settings, bool force);
void init_window(cocoa_window_t cw, obs_data_t *settings); void init_window(cocoa_window_t cw, obs_data_t *settings);

View file

@ -23,25 +23,14 @@ static NSComparator win_info_cmp = ^(NSDictionary *o1, NSDictionary *o2) {
return [o1[WINDOW_NUMBER] compare:o2[WINDOW_NUMBER]]; return [o1[WINDOW_NUMBER] compare:o2[WINDOW_NUMBER]];
}; };
NSArray *filter_nonzero_kcgwindowlayer_sources(NSArray *windows_arr)
{
NSPredicate *pred =
[NSPredicate predicateWithFormat:@"(kCGWindowLayer == 0)"];
NSArray *new_windows_arr =
[windows_arr filteredArrayUsingPredicate:pred];
return new_windows_arr;
}
NSArray *enumerate_windows(void) NSArray *enumerate_windows(void)
{ {
NSArray *arr = (NSArray *)CGWindowListCopyWindowInfo( NSArray *arr = (NSArray *)CGWindowListCopyWindowInfo(
kCGWindowListOptionOnScreenOnly, kCGNullWindowID); kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
NSArray *filtered_arr = filter_nonzero_kcgwindowlayer_sources(arr);
[arr autorelease]; [arr autorelease];
return [filtered_arr sortedArrayUsingComparator:win_info_cmp]; return [arr sortedArrayUsingComparator:win_info_cmp];
} }
#define WAIT_TIME_MS 500 #define WAIT_TIME_MS 500

View file

@ -304,7 +304,7 @@ static bool new_stream(struct ffmpeg_mux *ffm, AVStream **stream,
*codec = avcodec_find_encoder(desc->id); *codec = avcodec_find_encoder(desc->id);
if (!*codec) { if (!*codec) {
fprintf(stderr, "Couldn't create encoder"); fprintf(stderr, "Couldn't create encoder\n");
return false; return false;
} }
@ -520,7 +520,7 @@ static inline int open_output_file(struct ffmpeg_mux *ffm)
ret = avio_open(&ffm->output->pb, ffm->params.file, ret = avio_open(&ffm->output->pb, ffm->params.file,
AVIO_FLAG_WRITE); AVIO_FLAG_WRITE);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Couldn't open '%s', %s", fprintf(stderr, "Couldn't open '%s', %s\n",
ffm->params.file, av_err2str(ret)); ffm->params.file, av_err2str(ret));
return FFM_ERROR; return FFM_ERROR;
} }
@ -529,7 +529,7 @@ static inline int open_output_file(struct ffmpeg_mux *ffm)
AVDictionary *dict = NULL; AVDictionary *dict = NULL;
if ((ret = av_dict_parse_string(&dict, ffm->params.muxer_settings, "=", if ((ret = av_dict_parse_string(&dict, ffm->params.muxer_settings, "=",
" ", 0))) { " ", 0))) {
fprintf(stderr, "Failed to parse muxer settings: %s\n%s", fprintf(stderr, "Failed to parse muxer settings: %s\n%s\n",
av_err2str(ret), ffm->params.muxer_settings); av_err2str(ret), ffm->params.muxer_settings);
av_dict_free(&dict); av_dict_free(&dict);
@ -548,7 +548,7 @@ static inline int open_output_file(struct ffmpeg_mux *ffm)
ret = avformat_write_header(ffm->output, &dict); ret = avformat_write_header(ffm->output, &dict);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error opening '%s': %s", ffm->params.file, fprintf(stderr, "Error opening '%s': %s\n", ffm->params.file,
av_err2str(ret)); av_err2str(ret));
av_dict_free(&dict); av_dict_free(&dict);
@ -723,7 +723,14 @@ static inline bool ffmpeg_mux_packet(struct ffmpeg_mux *ffm, uint8_t *buf,
if (info->keyframe) if (info->keyframe)
packet.flags = AV_PKT_FLAG_KEY; packet.flags = AV_PKT_FLAG_KEY;
return av_interleaved_write_frame(ffm->output, &packet) >= 0; int ret = av_interleaved_write_frame(ffm->output, &packet);
if (ret < 0) {
fprintf(stderr, "av_interleaved_write_frame failed: %s\n",
av_err2str(ret));
}
return ret >= 0;
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@ -772,7 +779,7 @@ int main(int argc, char *argv[])
resize_buf_resize(&rb, info.size); resize_buf_resize(&rb, info.size);
if (safe_read(rb.buf, info.size) == info.size) { if (safe_read(rb.buf, info.size) == info.size) {
ffmpeg_mux_packet(&ffm, rb.buf, &info); fail = !ffmpeg_mux_packet(&ffm, rb.buf, &info);
} else { } else {
fail = true; fail = true;
} }

View file

@ -440,7 +440,11 @@ static void signal_failure(struct ffmpeg_muxer *stream)
code = OBS_OUTPUT_UNSUPPORTED; code = OBS_OUTPUT_UNSUPPORTED;
break; break;
default: default:
code = OBS_OUTPUT_ERROR; if (stream->is_network) {
code = OBS_OUTPUT_DISCONNECTED;
} else {
code = OBS_OUTPUT_ENCODE_ERROR;
}
} }
obs_output_signal_stop(stream->output, code); obs_output_signal_stop(stream->output, code);

View file

@ -1,10 +1,10 @@
{ {
"url": "https://obsproject.com/obs2_update/rtmp-services", "url": "https://obsproject.com/obs2_update/rtmp-services",
"version": 147, "version": 148,
"files": [ "files": [
{ {
"name": "services.json", "name": "services.json",
"version": 147 "version": 148
} }
] ]
} }

View file

@ -759,6 +759,10 @@
"name": "North America : US West", "name": "North America : US West",
"url": "rtmp://rtmp-wsu.afreecatv.com/app" "url": "rtmp://rtmp-wsu.afreecatv.com/app"
}, },
{
"name": "Europe : UK",
"url": "rtmp://rtmp-uk.afreecatv.com/app"
},
{ {
"name": "Asia : Singapore", "name": "Asia : Singapore",
"url": "rtmp://rtmp-sgp.afreecatv.com/app" "url": "rtmp://rtmp-sgp.afreecatv.com/app"
@ -1726,32 +1730,6 @@
"max audio bitrate": 160 "max audio bitrate": 160
} }
}, },
{
"name": "weabook.live",
"servers": [
{
"name": "N.Virgina, US",
"url": "rtmp://us-api.weabook.live/live"
},
{
"name": "Singapore, SG",
"url": "rtmp://sg-api.weabook.live/live"
},
{
"name": "Tokyo, JP",
"url": "rtmp://jp-api.weabook.live/live"
},
{
"name": "Premium Streaming",
"url": "rtmp://premium.rtmp.weabook.live/live"
}
],
"recommended": {
"keyint": 2,
"max audio bitrate": 256,
"max video bitrate": 20480
}
},
{ {
"name": "Taryana - Apachat | تاریانا - آپاچت", "name": "Taryana - Apachat | تاریانا - آپاچت",
"servers": [ "servers": [

View file

@ -515,8 +515,10 @@ static void apply_video_encoder_settings(obs_data_t *settings,
} }
item = json_object_get(recommended, "bframes"); item = json_object_get(recommended, "bframes");
if (json_is_integer(item)) if (json_is_integer(item)) {
obs_data_set_int(settings, "bf", 0); int bframes = json_integer_value(item);
obs_data_set_int(settings, "bf", bframes);
}
item = json_object_get(recommended, "x264opts"); item = json_object_get(recommended, "x264opts");
if (json_is_string(item)) { if (json_is_string(item)) {