Update upstream source from tag 'upstream/24.0.5+dfsg1'
Update to upstream version '24.0.5+dfsg1'
with Debian dir 82bd3986cf
This commit is contained in:
commit
f29396f1f6
61 changed files with 710 additions and 130 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -37,6 +37,7 @@ ipch/
|
|||
GeneratedFiles/
|
||||
.moc/
|
||||
/UI/obs.rc
|
||||
.vscode/
|
||||
|
||||
/other/
|
||||
|
||||
|
|
|
@ -8,9 +8,12 @@ hr() {
|
|||
set -e
|
||||
|
||||
# Generate file name variables
|
||||
export GIT_TAG=$(git describe --abbrev=0)
|
||||
export GIT_HASH=$(git rev-parse --short HEAD)
|
||||
export FILE_DATE=$(date +%Y-%m-%d.%H-%M-%S)
|
||||
export FILENAME=$FILE_DATE-$GIT_HASH-$TRAVIS_BRANCH-osx.pkg
|
||||
export FILENAME=$FILE_DATE-$GIT_HASH-$TRAVIS_BRANCH-osx.dmg
|
||||
|
||||
echo "git tag: $GIT_TAG"
|
||||
|
||||
cd ./build
|
||||
|
||||
|
@ -19,9 +22,9 @@ hr "Moving OBS LUA"
|
|||
mv ./rundir/RelWithDebInfo/data/obs-scripting/obslua.so ./rundir/RelWithDebInfo/bin/
|
||||
|
||||
# Move obspython
|
||||
# hr "Moving OBS Python"
|
||||
# mv ./rundir/RelWithDebInfo/data/obs-scripting/_obspython.so ./rundir/RelWithDebInfo/bin/
|
||||
# mv ./rundir/RelWithDebInfo/data/obs-scripting/obspython.py ./rundir/RelWithDebInfo/bin/
|
||||
hr "Moving OBS Python"
|
||||
mv ./rundir/RelWithDebInfo/data/obs-scripting/_obspython.so ./rundir/RelWithDebInfo/bin/
|
||||
mv ./rundir/RelWithDebInfo/data/obs-scripting/obspython.py ./rundir/RelWithDebInfo/bin/
|
||||
|
||||
# Package everything into a nice .app
|
||||
hr "Packaging .app"
|
||||
|
@ -30,32 +33,44 @@ if [ -n "${TRAVIS_TAG}" ]; then
|
|||
STABLE=true
|
||||
fi
|
||||
|
||||
sudo python ../CI/install/osx/build_app.py --public-key ../CI/install/osx/OBSPublicDSAKey.pem --sparkle-framework ../../sparkle/Sparkle.framework --stable=$STABLE
|
||||
#sudo python ../CI/install/osx/build_app.py --public-key ../CI/install/osx/OBSPublicDSAKey.pem --sparkle-framework ../../sparkle/Sparkle.framework --stable=$STABLE
|
||||
|
||||
../CI/install/osx/packageApp.sh
|
||||
|
||||
# fix obs outputs
|
||||
cp /usr/local/opt/mbedtls/lib/libmbedtls.12.dylib ./OBS.app/Contents/Frameworks/
|
||||
cp /usr/local/opt/mbedtls/lib/libmbedcrypto.3.dylib ./OBS.app/Contents/Frameworks/
|
||||
cp /usr/local/opt/mbedtls/lib/libmbedx509.0.dylib ./OBS.app/Contents/Frameworks/
|
||||
install_name_tool -change /usr/local/opt/mbedtls/lib/libmbedtls.12.dylib @executable_path/../Frameworks/libmbedtls.12.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
|
||||
install_name_tool -change /usr/local/opt/mbedtls/lib/libmbedcrypto.3.dylib @executable_path/../Frameworks/libmbedcrypto.3.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
|
||||
install_name_tool -change /usr/local/opt/mbedtls/lib/libmbedx509.0.dylib @executable_path/../Frameworks/libmbedx509.0.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
|
||||
install_name_tool -change /usr/local/opt/curl/lib/libcurl.4.dylib @executable_path/../Frameworks/libcurl.4.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
|
||||
install_name_tool -change @rpath/libobs.0.dylib @executable_path/../Frameworks/libobs.0.dylib ./OBS.app/Contents/Plugins/obs-outputs.so
|
||||
|
||||
# copy sparkle into the app
|
||||
hr "Copying Sparkle.framework"
|
||||
cp -r ../../sparkle/Sparkle.framework ./OBS.app/Contents/Frameworks/
|
||||
install_name_tool -change @rpath/Sparkle.framework/Versions/A/Sparkle @executable_path/../Frameworks/Sparkle.framework/Versions/A/Sparkle ./OBS.app/Contents/MacOS/obs
|
||||
|
||||
# Copy Chromium embedded framework to app Frameworks directory
|
||||
hr "Copying Chromium Embedded Framework.framework"
|
||||
sudo mkdir -p OBS.app/Contents/Frameworks
|
||||
sudo cp -r ../../cef_binary_${CEF_BUILD_VERSION}_macosx64/Release/Chromium\ Embedded\ Framework.framework OBS.app/Contents/Frameworks/
|
||||
sudo install_name_tool -change \
|
||||
@rpath/Frameworks/Chromium\ Embedded\ Framework.framework/Chromium\ Embedded\ Framework \
|
||||
../../Frameworks/Chromium\ Embedded\ Framework.framework/Chromium\ Embedded\ Framework \
|
||||
OBS.app/Contents/Resources/obs-plugins/obs-browser.so
|
||||
sudo install_name_tool -change \
|
||||
@executable_path/../Frameworks/Chromium\ Embedded\ Framework.framework/Chromium\ Embedded\ Framework \
|
||||
../../Frameworks/Chromium\ Embedded\ Framework.framework/Chromium\ Embedded\ Framework \
|
||||
OBS.app/Contents/Resources/obs-plugins/obs-browser.so
|
||||
sudo install_name_tool -change \
|
||||
@rpath/Frameworks/Chromium\ Embedded\ Framework.framework/Chromium\ Embedded\ Framework \
|
||||
../../Frameworks/Chromium\ Embedded\ Framework.framework/Chromium\ Embedded\ Framework \
|
||||
OBS.app/Contents/Resources/obs-plugins/obs-browser-page
|
||||
sudo install_name_tool -change \
|
||||
@executable_path/../Frameworks/Chromium\ Embedded\ Framework.framework/Chromium\ Embedded\ Framework \
|
||||
../../Frameworks/Chromium\ Embedded\ Framework.framework/Chromium\ Embedded\ Framework \
|
||||
OBS.app/Contents/Resources/obs-plugins/obs-browser-page
|
||||
|
||||
# Package app
|
||||
hr "Generating .pkg"
|
||||
packagesbuild ../CI/install/osx/CMakeLists.pkgproj
|
||||
install_name_tool -change /usr/local/opt/qt/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui ./OBS.app/Contents/Plugins/obs-browser.so
|
||||
install_name_tool -change /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ./OBS.app/Contents/Plugins/obs-browser.so
|
||||
install_name_tool -change /usr/local/opt/qt/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets ./OBS.app/Contents/Plugins/obs-browser.so
|
||||
|
||||
cp ../CI/install/osx/OBSPublicDSAKey.pem OBS.app/Contents/Resources
|
||||
|
||||
# edit plist
|
||||
plutil -insert CFBundleVersion -string $GIT_TAG ./OBS.app/Contents/Info.plist
|
||||
plutil -insert CFBundleShortVersionString -string $GIT_TAG ./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 SUPublicDSAKeyFile -string OBSPublicDSAKey.pem ./OBS.app/Contents/Info.plist
|
||||
|
||||
dmgbuild -s ../CI/install/osx/settings.json "OBS" obs.dmg
|
||||
|
||||
if [ -v "$TRAVIS" ]; then
|
||||
# Signing stuff
|
||||
|
@ -70,12 +85,10 @@ if [ -v "$TRAVIS" ]; then
|
|||
security import ./Certificates.p12 -k build.keychain -T /usr/bin/productsign -P ""
|
||||
# macOS 10.12+
|
||||
security set-key-partition-list -S apple-tool:,apple: -s -k mysecretpassword build.keychain
|
||||
hr "Signing Package"
|
||||
productsign --sign 2MMRE5MTB8 ./OBS.pkg ./$FILENAME
|
||||
else
|
||||
cp ./OBS.pkg ./$FILENAME
|
||||
fi
|
||||
|
||||
cp ./OBS.dmg ./$FILENAME
|
||||
|
||||
# Move to the folder that travis uses to upload artifacts from
|
||||
hr "Moving package to nightly folder for distribution"
|
||||
mkdir ../nightly
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#!/bin/sh
|
||||
set -ex
|
||||
|
||||
sudo add-apt-repository ppa:jonathonf/ffmpeg-3 -y
|
||||
curl -L https://packagecloud.io/github/git-lfs/gpgkey | sudo apt-key add -
|
||||
|
||||
# gets us newer clang
|
||||
|
|
|
@ -16,6 +16,8 @@ else
|
|||
/bin/bash -c "sudo xcode-select -s /Applications/Xcode_9.4.1.app/Contents/Developer"
|
||||
fi
|
||||
|
||||
git fetch origin --tags
|
||||
|
||||
# Leave obs-studio folder
|
||||
cd ../
|
||||
|
||||
|
@ -28,10 +30,12 @@ sudo installer -pkg ./Packages.pkg -target /
|
|||
brew update
|
||||
|
||||
#Base OBS Deps and ccache
|
||||
brew install jack speexdsp ccache mbedtls clang-format
|
||||
brew install jack speexdsp ccache mbedtls clang-format freetype fdk-aac
|
||||
brew install https://gist.githubusercontent.com/DDRBoxman/b3956fab6073335a4bf151db0dcbd4ad/raw/ed1342a8a86793ea8c10d8b4d712a654da121ace/qt.rb
|
||||
brew install https://gist.githubusercontent.com/DDRBoxman/4cada55c51803a2f963fa40ce55c9d3e/raw/572c67e908bfbc1bcb8c476ea77ea3935133f5b5/swig.rb
|
||||
|
||||
pip install dmgbuild
|
||||
|
||||
export PATH=/usr/local/opt/ccache/libexec:$PATH
|
||||
ccache -s || echo "CCache is not available."
|
||||
|
||||
|
|
30
CI/install/osx/Info.plist
Normal file
30
CI/install/osx/Info.plist
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>obs.icns</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>OBS</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>OBS - Free and Open Source Streaming/Recording Software</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>OBS</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.obsproject.obs-studio</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.8.5</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
<key>LSAppNapIsDisabled</key>
|
||||
<true/>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>OBS needs to access the camera to enable camera sources to work.</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>OBS needs to access the microphone to enable audio input.</string>
|
||||
</dict>
|
||||
</plist>
|
BIN
CI/install/osx/background.png
Normal file
BIN
CI/install/osx/background.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
CI/install/osx/background.pxd/QuickLook/Icon.tiff
Normal file
BIN
CI/install/osx/background.pxd/QuickLook/Icon.tiff
Normal file
Binary file not shown.
BIN
CI/install/osx/background.pxd/QuickLook/Preview.tiff
Normal file
BIN
CI/install/osx/background.pxd/QuickLook/Preview.tiff
Normal file
Binary file not shown.
BIN
CI/install/osx/background.pxd/QuickLook/Thumbnail.tiff
Normal file
BIN
CI/install/osx/background.pxd/QuickLook/Thumbnail.tiff
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
CI/install/osx/background.pxd/metadata.info
Normal file
BIN
CI/install/osx/background.pxd/metadata.info
Normal file
Binary file not shown.
BIN
CI/install/osx/background.tiff
Normal file
BIN
CI/install/osx/background.tiff
Normal file
Binary file not shown.
BIN
CI/install/osx/background@2x.png
Normal file
BIN
CI/install/osx/background@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
1
CI/install/osx/buildDMG
Executable file
1
CI/install/osx/buildDMG
Executable file
|
@ -0,0 +1 @@
|
|||
dmgbuild -s ./settings.json "OBS" obs.dmg
|
BIN
CI/install/osx/dylibBundler
Executable file
BIN
CI/install/osx/dylibBundler
Executable file
Binary file not shown.
1
CI/install/osx/makeRetinaBG
Executable file
1
CI/install/osx/makeRetinaBG
Executable file
|
@ -0,0 +1 @@
|
|||
tiffutil -cathidpicheck background.png background@2x.png -out background.tiff
|
BIN
CI/install/osx/obs.icns
Normal file
BIN
CI/install/osx/obs.icns
Normal file
Binary file not shown.
67
CI/install/osx/packageApp.sh
Executable file
67
CI/install/osx/packageApp.sh
Executable file
|
@ -0,0 +1,67 @@
|
|||
rm -rf ./OBS.app
|
||||
|
||||
mkdir OBS.app
|
||||
mkdir OBS.app/Contents
|
||||
mkdir OBS.app/Contents/MacOS
|
||||
mkdir OBS.app/Contents/Plugins
|
||||
mkdir OBS.app/Contents/Resources
|
||||
|
||||
cp -r rundir/RelWithDebInfo/bin/ ./OBS.app/Contents/MacOS
|
||||
cp -r rundir/RelWithDebInfo/data ./OBS.app/Contents/Resources
|
||||
cp ../CI/install/osx/obs.icns ./OBS.app/Contents/Resources
|
||||
cp -r rundir/RelWithDebInfo/obs-plugins/ ./OBS.app/Contents/Plugins
|
||||
cp ../CI/install/osx/Info.plist ./OBS.app/Contents
|
||||
|
||||
../CI/install/osx/dylibBundler -b -cd -d ./OBS.app/Contents/Frameworks -p @executable_path/../Frameworks/ \
|
||||
-s ./OBS.app/Contents/MacOS \
|
||||
-s /usr/local/opt/mbedtls/lib/ \
|
||||
-x ./OBS.app/Contents/Plugins/coreaudio-encoder.so \
|
||||
-x ./OBS.app/Contents/Plugins/decklink-ouput-ui.so \
|
||||
-x ./OBS.app/Contents/Plugins/frontend-tools.so \
|
||||
-x ./OBS.app/Contents/Plugins/image-source.so \
|
||||
-x ./OBS.app/Contents/Plugins/linux-jack.so \
|
||||
-x ./OBS.app/Contents/Plugins/mac-avcapture.so \
|
||||
-x ./OBS.app/Contents/Plugins/mac-capture.so \
|
||||
-x ./OBS.app/Contents/Plugins/mac-decklink.so \
|
||||
-x ./OBS.app/Contents/Plugins/mac-syphon.so \
|
||||
-x ./OBS.app/Contents/Plugins/mac-vth264.so \
|
||||
-x ./OBS.app/Contents/Plugins/obs-browser.so \
|
||||
-x ./OBS.app/Contents/Plugins/obs-browser-page \
|
||||
-x ./OBS.app/Contents/Plugins/obs-ffmpeg.so \
|
||||
-x ./OBS.app/Contents/Plugins/obs-filters.so \
|
||||
-x ./OBS.app/Contents/Plugins/obs-transitions.so \
|
||||
-x ./OBS.app/Contents/Plugins/obs-vst.so \
|
||||
-x ./OBS.app/Contents/Plugins/rtmp-services.so \
|
||||
-x ./OBS.app/Contents/MacOS/obs \
|
||||
-x ./OBS.app/Contents/MacOS/obs-ffmpeg-mux \
|
||||
-x ./OBS.app/Contents/MacOS/obslua.so \
|
||||
-x ./OBS.app/Contents/MacOS/_obspython.so \
|
||||
-x ./OBS.app/Contents/Plugins/obs-x264.so \
|
||||
-x ./OBS.app/Contents/Plugins/text-freetype2.so \
|
||||
-x ./OBS.app/Contents/Plugins/obs-libfdk.so
|
||||
# -x ./OBS.app/Contents/Plugins/obs-outputs.so \
|
||||
|
||||
/usr/local/Cellar/qt/5.10.1/bin/macdeployqt ./OBS.app
|
||||
|
||||
mv ./OBS.app/Contents/MacOS/libobs-opengl.so ./OBS.app/Contents/Frameworks
|
||||
|
||||
# put qt network in here becasuse streamdeck uses it
|
||||
cp -r /usr/local/opt/qt/lib/QtNetwork.framework ./OBS.app/Contents/Frameworks
|
||||
chmod +w ./OBS.app/Contents/Frameworks/QtNetwork.framework/Versions/5/QtNetwork
|
||||
install_name_tool -change /usr/local/Cellar/qt/5.10.1/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ./OBS.app/Contents/Frameworks/QtNetwork.framework/Versions/5/QtNetwork
|
||||
|
||||
# decklink ui qt
|
||||
install_name_tool -change /usr/local/opt/qt/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui ./OBS.app/Contents/Plugins/decklink-ouput-ui.so
|
||||
install_name_tool -change /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ./OBS.app/Contents/Plugins/decklink-ouput-ui.so
|
||||
install_name_tool -change /usr/local/opt/qt/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets ./OBS.app/Contents/Plugins/decklink-ouput-ui.so
|
||||
|
||||
# frontend tools qt
|
||||
install_name_tool -change /usr/local/opt/qt/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui ./OBS.app/Contents/Plugins/frontend-tools.so
|
||||
install_name_tool -change /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ./OBS.app/Contents/Plugins/frontend-tools.so
|
||||
install_name_tool -change /usr/local/opt/qt/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets ./OBS.app/Contents/Plugins/frontend-tools.so
|
||||
|
||||
# vst qt
|
||||
install_name_tool -change /usr/local/opt/qt/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui ./OBS.app/Contents/Plugins/obs-vst.so
|
||||
install_name_tool -change /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ./OBS.app/Contents/Plugins/obs-vst.so
|
||||
install_name_tool -change /usr/local/opt/qt/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets ./OBS.app/Contents/Plugins/obs-vst.so
|
||||
install_name_tool -change /usr/local/opt/qt/lib/QtMacExtras.framework/Versions/5/QtMacExtras @executable_path/../Frameworks/QtMacExtras.framework/Versions/5/QtMacExtras ./OBS.app/Contents/Plugins/obs-vst.so
|
13
CI/install/osx/settings.json
Normal file
13
CI/install/osx/settings.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"title": "OBS",
|
||||
"background": "../CI/install/osx/background.tiff",
|
||||
"format": "UDZO",
|
||||
"compression-level": 9,
|
||||
"window": { "position": { "x": 100, "y": 100 },
|
||||
"size": { "width": 540, "height": 380 } },
|
||||
"contents": [
|
||||
{ "x": 120, "y": 180, "type": "file",
|
||||
"path": "./OBS.app" },
|
||||
{ "x": 420, "y": 180, "type": "link", "path": "/Applications" }
|
||||
]
|
||||
}
|
|
@ -373,14 +373,6 @@ if (APPLE)
|
|||
target_link_libraries(obs
|
||||
Qt5::MacExtras)
|
||||
set_target_properties(obs PROPERTIES LINK_FLAGS "-pagezero_size 10000 -image_base 100000000")
|
||||
set_property(
|
||||
TARGET obs
|
||||
APPEND
|
||||
PROPERTY INSTALL_RPATH
|
||||
"/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/"
|
||||
"/Library/Frameworks/Python.framework/Versions/3.6/lib/"
|
||||
"/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/"
|
||||
)
|
||||
endif()
|
||||
|
||||
define_graphic_modules(obs)
|
||||
|
|
|
@ -216,7 +216,8 @@ void TwitchAuth::LoadUI()
|
|||
chat->SetWidget(browser);
|
||||
cef->add_force_popup_url(moderation_tools_url, chat.data());
|
||||
|
||||
script = bttv_script;
|
||||
script = "localStorage.setItem('twilight.theme', 1);";
|
||||
script += bttv_script;
|
||||
script += ffz_script;
|
||||
browser->setStartupScript(script);
|
||||
|
||||
|
|
|
@ -3685,19 +3685,19 @@
|
|||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="sampleRate">
|
||||
<property name="currentText">
|
||||
<string notr="true">44.1khz</string>
|
||||
<string notr="true">44.1 kHz</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>44.1khz</string>
|
||||
<string>44.1 kHz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>48khz</string>
|
||||
<string>48 kHz</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
|
|
|
@ -126,9 +126,16 @@ static std::string GetWindowTitle(size_t i)
|
|||
if (status >= Success && name != nullptr) {
|
||||
std::string str(name);
|
||||
windowTitle = str;
|
||||
}
|
||||
|
||||
XFree(name);
|
||||
} else {
|
||||
XTextProperty xtp_new_name;
|
||||
if (XGetWMName(disp(), w, &xtp_new_name) != 0 &&
|
||||
xtp_new_name.value != nullptr) {
|
||||
std::string str((const char *)xtp_new_name.value);
|
||||
windowTitle = str;
|
||||
XFree(xtp_new_name.value);
|
||||
}
|
||||
}
|
||||
|
||||
return windowTitle;
|
||||
}
|
||||
|
|
|
@ -28,11 +28,29 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
bool isInBundle()
|
||||
{
|
||||
NSRunningApplication *app = [NSRunningApplication currentApplication];
|
||||
return [app bundleIdentifier] != nil;
|
||||
}
|
||||
|
||||
bool GetDataFilePath(const char *data, string &output)
|
||||
{
|
||||
if (isInBundle()) {
|
||||
NSRunningApplication *app =
|
||||
[NSRunningApplication currentApplication];
|
||||
NSURL *bundleURL = [app bundleURL];
|
||||
NSString *path = [NSString
|
||||
stringWithFormat:@"Contents/Resources/data/obs-studio/%@",
|
||||
[NSString stringWithUTF8String:data]];
|
||||
NSURL *dataURL = [bundleURL URLByAppendingPathComponent:path];
|
||||
output = [[dataURL path] UTF8String];
|
||||
} else {
|
||||
stringstream str;
|
||||
str << OBS_DATA_PATH "/obs-studio/" << data;
|
||||
output = str.str();
|
||||
}
|
||||
|
||||
return !access(output.c_str(), R_OK);
|
||||
}
|
||||
|
||||
|
|
|
@ -1820,7 +1820,7 @@ void WidgetInfo::ControlChanged()
|
|||
break;
|
||||
case OBS_PROPERTY_GROUP:
|
||||
GroupChanged(setting);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (view->callback && !view->deferUpdate)
|
||||
|
|
|
@ -417,6 +417,8 @@ void AutoConfigStreamPage::on_connectAccount_clicked()
|
|||
#ifdef BROWSER_AVAILABLE
|
||||
std::string service = QT_TO_UTF8(ui->service->currentText());
|
||||
|
||||
OAuth::DeleteCookies(service);
|
||||
|
||||
auth = OAuthStreamKey::Login(this, service);
|
||||
if (!!auth)
|
||||
OnAuthConnected();
|
||||
|
|
|
@ -59,6 +59,10 @@ OBSBasicInteraction::OBSBasicInteraction(QWidget *parent, OBSSource source_)
|
|||
const char *name = obs_source_get_name(source);
|
||||
setWindowTitle(QTStr("Basic.InteractionWindow").arg(QT_UTF8(name)));
|
||||
|
||||
Qt::WindowFlags flags = windowFlags();
|
||||
Qt::WindowFlags helpFlag = Qt::WindowContextHelpButtonHint;
|
||||
setWindowFlags(flags & (~helpFlag));
|
||||
|
||||
auto addDrawCallback = [this]() {
|
||||
obs_display_add_draw_callback(ui->preview->GetDisplay(),
|
||||
OBSBasicInteraction::DrawPreview,
|
||||
|
|
|
@ -643,6 +643,7 @@ void SimpleOutput::UpdateRecordingSettings()
|
|||
} else if (videoEncoder == SIMPLE_ENCODER_NVENC) {
|
||||
UpdateRecordingSettings_nvenc(crf);
|
||||
}
|
||||
UpdateRecordingAudioSettings();
|
||||
}
|
||||
|
||||
inline void SimpleOutput::SetupOutputs()
|
||||
|
|
|
@ -88,6 +88,38 @@ static bool SceneCollectionExists(const char *findName)
|
|||
return found;
|
||||
}
|
||||
|
||||
static bool GetUnusedSceneCollectionFile(std::string &name, std::string &file)
|
||||
{
|
||||
char path[512];
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
if (!GetFileSafeName(name.c_str(), file)) {
|
||||
blog(LOG_WARNING, "Failed to create safe file name for '%s'",
|
||||
name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = GetConfigPath(path, sizeof(path), "obs-studio/basic/scenes/");
|
||||
if (ret <= 0) {
|
||||
blog(LOG_WARNING, "Failed to get scene collection config path");
|
||||
return false;
|
||||
}
|
||||
|
||||
len = file.size();
|
||||
file.insert(0, path);
|
||||
|
||||
if (!GetClosestUnusedFileName(file, "json")) {
|
||||
blog(LOG_WARNING, "Failed to get closest file name for %s",
|
||||
file.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
file.erase(file.size() - 5, 5);
|
||||
file.erase(0, file.size() - len);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GetSceneCollectionName(QWidget *parent, std::string &name,
|
||||
std::string &file,
|
||||
const char *oldName = nullptr)
|
||||
|
@ -95,9 +127,6 @@ static bool GetSceneCollectionName(QWidget *parent, std::string &name,
|
|||
bool rename = oldName != nullptr;
|
||||
const char *title;
|
||||
const char *text;
|
||||
char path[512];
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
if (rename) {
|
||||
title = Str("Basic.Main.RenameSceneCollection.Title");
|
||||
|
@ -128,29 +157,10 @@ static bool GetSceneCollectionName(QWidget *parent, std::string &name,
|
|||
break;
|
||||
}
|
||||
|
||||
if (!GetFileSafeName(name.c_str(), file)) {
|
||||
blog(LOG_WARNING, "Failed to create safe file name for '%s'",
|
||||
name.c_str());
|
||||
if (!GetUnusedSceneCollectionFile(name, file)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = GetConfigPath(path, sizeof(path), "obs-studio/basic/scenes/");
|
||||
if (ret <= 0) {
|
||||
blog(LOG_WARNING, "Failed to get scene collection config path");
|
||||
return false;
|
||||
}
|
||||
|
||||
len = file.size();
|
||||
file.insert(0, path);
|
||||
|
||||
if (!GetClosestUnusedFileName(file, "json")) {
|
||||
blog(LOG_WARNING, "Failed to get closest file name for %s",
|
||||
file.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
file.erase(file.size() - 5, 5);
|
||||
file.erase(0, file.size() - len);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -166,6 +176,10 @@ bool OBSBasic::AddSceneCollection(bool create_new, const QString &qname)
|
|||
name = QT_TO_UTF8(qname);
|
||||
if (SceneCollectionExists(name.c_str()))
|
||||
return false;
|
||||
|
||||
if (!GetUnusedSceneCollectionFile(name, file)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SaveProjectNow();
|
||||
|
|
|
@ -466,6 +466,8 @@ void OBSBasicSettings::on_connectAccount_clicked()
|
|||
#ifdef BROWSER_AVAILABLE
|
||||
std::string service = QT_TO_UTF8(ui->service->currentText());
|
||||
|
||||
OAuth::DeleteCookies(service);
|
||||
|
||||
auth = OAuthStreamKey::Login(this, service);
|
||||
if (!!auth)
|
||||
OnAuthConnected();
|
||||
|
|
|
@ -2189,9 +2189,9 @@ void OBSBasicSettings::LoadAudioSettings()
|
|||
|
||||
const char *str;
|
||||
if (sampleRate == 48000)
|
||||
str = "48khz";
|
||||
str = "48 kHz";
|
||||
else
|
||||
str = "44.1khz";
|
||||
str = "44.1 kHz";
|
||||
|
||||
int sampleRateIdx = ui->sampleRate->findText(str);
|
||||
if (sampleRateIdx != -1)
|
||||
|
@ -3253,7 +3253,7 @@ void OBSBasicSettings::SaveAudioSettings()
|
|||
}
|
||||
|
||||
int sampleRate = 44100;
|
||||
if (sampleRateStr == "48khz")
|
||||
if (sampleRateStr == "48 kHz")
|
||||
sampleRate = 48000;
|
||||
|
||||
if (WidgetChanged(ui->sampleRate))
|
||||
|
|
|
@ -533,6 +533,24 @@ void OBSBasic::AddExtraBrowserDock(const QString &title, const QString &url,
|
|||
|
||||
dock->SetWidget(browser);
|
||||
|
||||
/* Add support for Twitch Dashboard panels */
|
||||
if (url.contains("twitch.tv/popout") &&
|
||||
url.contains("dashboard/live")) {
|
||||
QRegularExpression re("twitch.tv\/popout\/([^/]+)\/");
|
||||
QRegularExpressionMatch match = re.match(url);
|
||||
QString username = match.captured(1);
|
||||
if (username.length() > 0) {
|
||||
std::string script;
|
||||
script =
|
||||
"Object.defineProperty(document, 'referrer', { get: () => '";
|
||||
script += "https://twitch.tv/";
|
||||
script += QT_TO_UTF8(username);
|
||||
script += "/dashboard/live";
|
||||
script += "'});";
|
||||
browser->setStartupScript(script);
|
||||
}
|
||||
}
|
||||
|
||||
addDockWidget(Qt::RightDockWidgetArea, dock);
|
||||
|
||||
if (firstCreate) {
|
||||
|
|
|
@ -653,6 +653,9 @@ void OBSProjector::OBSRender(void *data, uint32_t cx, uint32_t cy)
|
|||
source = curSource;
|
||||
window->source = source;
|
||||
}
|
||||
} else if (window->type == ProjectorType::Preview &&
|
||||
!main->IsPreviewProgramMode()) {
|
||||
window->source = nullptr;
|
||||
}
|
||||
|
||||
if (source)
|
||||
|
|
|
@ -61,7 +61,7 @@ if(NOT UNIX_STRUCTURE)
|
|||
set(OBS_INSTALL_PREFIX "")
|
||||
set(OBS_RELATIVE_PREFIX "../")
|
||||
|
||||
set(OBS_SCRIPT_PLUGIN_DESTINATION "${OBS_DATA_DESTINATION}/obs-scripting/${_lib_suffix}bit")
|
||||
set(OBS_SCRIPT_PLUGIN_DESTINATION "${OBS_DATA_DESTINATION}/obs-scripting")
|
||||
else()
|
||||
set(OBS_EXECUTABLE_DESTINATION "bin/${_lib_suffix}bit")
|
||||
set(OBS_EXECUTABLE32_DESTINATION "bin/32bit")
|
||||
|
|
6
deps/media-playback/media-playback/media.c
vendored
6
deps/media-playback/media-playback/media.c
vendored
|
@ -139,7 +139,7 @@ static int mp_media_next_packet(mp_media_t *media)
|
|||
|
||||
int ret = av_read_frame(media->fmt, &pkt);
|
||||
if (ret < 0) {
|
||||
if (ret != AVERROR_EOF)
|
||||
if (ret != AVERROR_EOF && ret != AVERROR_EXIT)
|
||||
blog(LOG_WARNING, "MP: av_read_frame failed: %s (%d)",
|
||||
av_err2str(ret), ret);
|
||||
return ret;
|
||||
|
@ -230,7 +230,7 @@ static bool mp_media_prepare_frames(mp_media_t *m)
|
|||
while (!mp_media_ready_to_start(m)) {
|
||||
if (!m->eof) {
|
||||
int ret = mp_media_next_packet(m);
|
||||
if (ret == AVERROR_EOF)
|
||||
if (ret == AVERROR_EOF || ret == AVERROR_EXIT)
|
||||
m->eof = true;
|
||||
else if (ret < 0)
|
||||
return false;
|
||||
|
@ -577,8 +577,10 @@ static bool init_avformat(mp_media_t *m)
|
|||
av_dict_set_int(&opts, "buffer_size", m->buffering, 0);
|
||||
|
||||
m->fmt = avformat_alloc_context();
|
||||
if (!m->is_local_file) {
|
||||
m->fmt->interrupt_callback.callback = interrupt_callback;
|
||||
m->fmt->interrupt_callback.opaque = m;
|
||||
}
|
||||
|
||||
int ret = avformat_open_input(&m->fmt, m->path, format,
|
||||
opts ? &opts : NULL);
|
||||
|
|
5
deps/obs-scripting/CMakeLists.txt
vendored
5
deps/obs-scripting/CMakeLists.txt
vendored
|
@ -12,6 +12,11 @@ if(MSVC)
|
|||
w32-pthreads)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(obs-scripting_PLATFORM_DEPS
|
||||
objc)
|
||||
endif()
|
||||
|
||||
option(DISABLE_LUA "Disable Lua scripting support" OFF)
|
||||
option(DISABLE_PYTHON "Disable Python scripting support" OFF)
|
||||
|
||||
|
|
29
deps/obs-scripting/obs-scripting-lua.c
vendored
29
deps/obs-scripting/obs-scripting-lua.c
vendored
|
@ -43,7 +43,8 @@ static const char *startup_script_template = "\
|
|||
for val in pairs(package.preload) do\n\
|
||||
package.preload[val] = nil\n\
|
||||
end\n\
|
||||
package.cpath = package.cpath .. \";\" .. \"%s\" .. \"/?." SO_EXT "\"\n\
|
||||
package.cpath = package.cpath .. \";\" .. \"%s/Contents/MacOS/?.so\" .. \";\" .. \"%s\" .. \"/?." SO_EXT
|
||||
"\"\n\
|
||||
require \"obslua\"\n";
|
||||
|
||||
static const char *get_script_path_func = "\
|
||||
|
@ -1310,7 +1311,31 @@ void obs_lua_load(void)
|
|||
/* ---------------------------------------------- */
|
||||
/* Initialize Lua startup script */
|
||||
|
||||
dstr_printf(&tmp, startup_script_template, SCRIPT_DIR);
|
||||
char *bundlePath = "./";
|
||||
|
||||
#ifdef __APPLE__
|
||||
Class nsRunningApplication = objc_lookUpClass("NSRunningApplication");
|
||||
SEL currentAppSel = sel_getUid("currentApplication");
|
||||
|
||||
typedef id (*running_app_func)(Class, SEL);
|
||||
running_app_func operatingSystemName = (running_app_func)objc_msgSend;
|
||||
id app = operatingSystemName(nsRunningApplication, currentAppSel);
|
||||
|
||||
typedef id (*bundle_url_func)(id, SEL);
|
||||
bundle_url_func bundleURL = (bundle_url_func)objc_msgSend;
|
||||
id url = bundleURL(app, sel_getUid("bundleURL"));
|
||||
|
||||
typedef id (*url_path_func)(id, SEL);
|
||||
url_path_func urlPath = (url_path_func)objc_msgSend;
|
||||
|
||||
id path = urlPath(url, sel_getUid("path"));
|
||||
|
||||
typedef id (*string_func)(id, SEL);
|
||||
string_func utf8String = (string_func)objc_msgSend;
|
||||
bundlePath = (char *)utf8String(path, sel_registerName("UTF8String"));
|
||||
#endif
|
||||
|
||||
dstr_printf(&tmp, startup_script_template, bundlePath, SCRIPT_DIR);
|
||||
startup_script = tmp.array;
|
||||
|
||||
dstr_free(&dep_paths);
|
||||
|
|
|
@ -32,6 +32,12 @@
|
|||
#define SO_EXT ".dylib"
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define PYTHON_LIB_SUBDIR "lib/"
|
||||
#else
|
||||
#define PYTHON_LIB_SUBDIR ""
|
||||
#endif
|
||||
|
||||
bool import_python(const char *python_path)
|
||||
{
|
||||
struct dstr lib_path;
|
||||
|
@ -44,7 +50,7 @@ bool import_python(const char *python_path)
|
|||
dstr_init_copy(&lib_path, python_path);
|
||||
dstr_replace(&lib_path, "\\", "/");
|
||||
if (!dstr_is_empty(&lib_path)) {
|
||||
dstr_cat(&lib_path, "/");
|
||||
dstr_cat(&lib_path, "/" PYTHON_LIB_SUBDIR);
|
||||
}
|
||||
dstr_cat(&lib_path, PYTHON_LIB SO_EXT);
|
||||
|
||||
|
|
7
deps/obs-scripting/obs-scripting-python.c
vendored
7
deps/obs-scripting/obs-scripting-python.c
vendored
|
@ -1651,6 +1651,13 @@ bool obs_scripting_load_python(const char *python_path)
|
|||
|
||||
add_to_python_path(SCRIPT_DIR);
|
||||
|
||||
#if __APPLE__
|
||||
char *exec_path = os_get_executable_path_ptr("");
|
||||
if (exec_path)
|
||||
add_to_python_path(exec_path);
|
||||
bfree(exec_path);
|
||||
#endif
|
||||
|
||||
py_obspython = PyImport_ImportModule("obspython");
|
||||
bool success = !py_error();
|
||||
if (!success) {
|
||||
|
|
16
deps/obs-scripting/obspython/CMakeLists.txt
vendored
16
deps/obs-scripting/obspython/CMakeLists.txt
vendored
|
@ -42,7 +42,12 @@ if(CMAKE_VERSION VERSION_GREATER 3.7.2)
|
|||
else()
|
||||
SWIG_ADD_MODULE(obspython python obspython.i ../cstrcache.cpp ../cstrcache.h)
|
||||
endif()
|
||||
SWIG_LINK_LIBRARIES(obspython obs-scripting libobs ${PYTHON_LIBRARIES})
|
||||
|
||||
IF(APPLE)
|
||||
SWIG_LINK_LIBRARIES(obspython obs-scripting libobs)
|
||||
ELSE()
|
||||
SWIG_LINK_LIBRARIES(obspython obs-scripting libobs ${PYTHON_LIBRARIES})
|
||||
ENDIF()
|
||||
|
||||
function(install_plugin_bin_swig target additional_target)
|
||||
if(APPLE)
|
||||
|
@ -57,14 +62,7 @@ function(install_plugin_bin_swig target additional_target)
|
|||
PREFIX "")
|
||||
|
||||
if (APPLE)
|
||||
set_property(
|
||||
TARGET ${additional_target}
|
||||
APPEND
|
||||
PROPERTY INSTALL_RPATH
|
||||
"/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/"
|
||||
"/Library/Frameworks/Python.framework/Versions/3.6/lib/"
|
||||
"/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/"
|
||||
)
|
||||
SET_TARGET_PROPERTIES(${additional_target} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
|
||||
endif()
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/obspython.py"
|
||||
|
|
|
@ -27,5 +27,14 @@ else
|
|||
CLANG_FORMAT=clang-format
|
||||
fi
|
||||
|
||||
find . -type d \( -path ./deps -o -path ./cmake -o -path ./plugins/decklink/win -o -path ./plugins/decklink/mac -o -path ./plugins/decklink/linux -o -path ./build \) -prune -type f -o -name '*.h' -or -name '*.hpp' -or -name '*.m' -or -name '*.mm' -or -name '*.c' -or -name '*.cpp' \
|
||||
find . -type d \( -path ./deps \
|
||||
-o -path ./cmake \
|
||||
-o -path ./plugins/decklink/win \
|
||||
-o -path ./plugins/decklink/mac \
|
||||
-o -path ./plugins/decklink/linux \
|
||||
-o -path ./plugins/enc-amf \
|
||||
-o -path ./plugins/mac-syphon/syphon-framework \
|
||||
-o -path ./plugins/obs-outputs/ftl-sdk \
|
||||
-o -path ./plugins/obs-vst \
|
||||
-o -path ./build \) -prune -type f -o -name '*.h' -or -name '*.hpp' -or -name '*.m' -or -name '*.mm' -or -name '*.c' -or -name '*.cpp' \
|
||||
| xargs -I{} -P ${NPROC} ${CLANG_FORMAT} -i -style=file -fallback-style=none {}
|
||||
|
|
|
@ -178,10 +178,13 @@ void gs_vertex_shader::Rebuild(ID3D11Device *dev)
|
|||
if (FAILED(hr))
|
||||
throw HRError("Failed to create vertex shader", hr);
|
||||
|
||||
hr = dev->CreateInputLayout(layoutData.data(), (UINT)layoutData.size(),
|
||||
const UINT layoutSize = (UINT)layoutData.size();
|
||||
if (layoutSize > 0) {
|
||||
hr = dev->CreateInputLayout(layoutData.data(), layoutSize,
|
||||
data.data(), data.size(), &layout);
|
||||
if (FAILED(hr))
|
||||
throw HRError("Failed to create input layout", hr);
|
||||
}
|
||||
|
||||
if (constantSize) {
|
||||
hr = dev->CreateBuffer(&bd, NULL, &constants);
|
||||
|
|
|
@ -796,6 +796,53 @@ bool device_enum_adapters(bool (*callback)(void *param, const char *name,
|
|||
}
|
||||
}
|
||||
|
||||
static bool GetMonitorTarget(const MONITORINFOEX &info,
|
||||
DISPLAYCONFIG_TARGET_DEVICE_NAME &target)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
UINT32 numPath, numMode;
|
||||
if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &numPath,
|
||||
&numMode) == ERROR_SUCCESS) {
|
||||
std::vector<DISPLAYCONFIG_PATH_INFO> paths(numPath);
|
||||
std::vector<DISPLAYCONFIG_MODE_INFO> modes(numMode);
|
||||
if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &numPath,
|
||||
paths.data(), &numMode, modes.data(),
|
||||
nullptr) == ERROR_SUCCESS) {
|
||||
paths.resize(numPath);
|
||||
for (size_t i = 0; i < numPath; ++i) {
|
||||
const DISPLAYCONFIG_PATH_INFO &path = paths[i];
|
||||
|
||||
DISPLAYCONFIG_SOURCE_DEVICE_NAME
|
||||
source;
|
||||
source.header.type =
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
|
||||
source.header.size = sizeof(source);
|
||||
source.header.adapterId =
|
||||
path.sourceInfo.adapterId;
|
||||
source.header.id = path.sourceInfo.id;
|
||||
if (DisplayConfigGetDeviceInfo(
|
||||
&source.header) == ERROR_SUCCESS &&
|
||||
wcscmp(info.szDevice,
|
||||
source.viewGdiDeviceName) == 0) {
|
||||
target.header.type =
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
|
||||
target.header.size = sizeof(target);
|
||||
target.header.adapterId =
|
||||
path.sourceInfo.adapterId;
|
||||
target.header.id = path.targetInfo.id;
|
||||
found = DisplayConfigGetDeviceInfo(
|
||||
&target.header) ==
|
||||
ERROR_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static inline void LogAdapterMonitors(IDXGIAdapter1 *adapter)
|
||||
{
|
||||
UINT i;
|
||||
|
@ -806,15 +853,41 @@ static inline void LogAdapterMonitors(IDXGIAdapter1 *adapter)
|
|||
if (FAILED(output->GetDesc(&desc)))
|
||||
continue;
|
||||
|
||||
RECT rect = desc.DesktopCoordinates;
|
||||
unsigned refresh = 0;
|
||||
|
||||
bool target_found = false;
|
||||
DISPLAYCONFIG_TARGET_DEVICE_NAME target;
|
||||
|
||||
MONITORINFOEX info;
|
||||
info.cbSize = sizeof(info);
|
||||
if (GetMonitorInfo(desc.Monitor, &info)) {
|
||||
target_found = GetMonitorTarget(info, target);
|
||||
|
||||
DEVMODE mode;
|
||||
mode.dmSize = sizeof(mode);
|
||||
mode.dmDriverExtra = 0;
|
||||
if (EnumDisplaySettings(info.szDevice,
|
||||
ENUM_CURRENT_SETTINGS, &mode)) {
|
||||
refresh = mode.dmDisplayFrequency;
|
||||
}
|
||||
}
|
||||
|
||||
if (!target_found) {
|
||||
target.monitorFriendlyDeviceName[0] = 0;
|
||||
}
|
||||
|
||||
const RECT &rect = desc.DesktopCoordinates;
|
||||
blog(LOG_INFO,
|
||||
"\t output %u: "
|
||||
"pos={%d, %d}, "
|
||||
"size={%d, %d}, "
|
||||
"attached=%s",
|
||||
"attached=%s, "
|
||||
"refresh=%u, "
|
||||
"name=%ls",
|
||||
i, rect.left, rect.top, rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
desc.AttachedToDesktop ? "true" : "false");
|
||||
desc.AttachedToDesktop ? "true" : "false", refresh,
|
||||
target.monitorFriendlyDeviceName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -853,6 +926,25 @@ static inline void LogD3DAdapters()
|
|||
blog(LOG_INFO, "\t Shared VRAM: %u",
|
||||
desc.SharedSystemMemory);
|
||||
|
||||
/* driver version */
|
||||
LARGE_INTEGER umd;
|
||||
hr = adapter->CheckInterfaceSupport(__uuidof(IDXGIDevice),
|
||||
&umd);
|
||||
if (SUCCEEDED(hr)) {
|
||||
const uint64_t version = umd.QuadPart;
|
||||
const uint16_t aa = (version >> 48) & 0xffff;
|
||||
const uint16_t bb = (version >> 32) & 0xffff;
|
||||
const uint16_t ccccc = (version >> 16) & 0xffff;
|
||||
const uint16_t ddddd = version & 0xffff;
|
||||
blog(LOG_INFO,
|
||||
"\t Driver Version: %" PRIu16 ".%" PRIu16
|
||||
".%" PRIu16 ".%" PRIu16,
|
||||
aa, bb, ccccc, ddddd);
|
||||
} else {
|
||||
blog(LOG_INFO, "\t Driver Version: Unknown (0x%X)",
|
||||
(unsigned)hr);
|
||||
}
|
||||
|
||||
LogAdapterMonitors(adapter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ if(WIN32)
|
|||
endif()
|
||||
elseif(APPLE)
|
||||
set(libobs_PLATFORM_SOURCES
|
||||
obs-cocoa.c
|
||||
obs-cocoa.m
|
||||
util/threading-posix.c
|
||||
util/pipe-posix.c
|
||||
util/platform-nix.c
|
||||
|
|
|
@ -29,6 +29,14 @@
|
|||
#include <IOKit/hid/IOHIDDevice.h>
|
||||
#include <IOKit/hid/IOHIDManager.h>
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
bool is_in_bundle()
|
||||
{
|
||||
NSRunningApplication *app = [NSRunningApplication currentApplication];
|
||||
return [app bundleIdentifier] != nil;
|
||||
}
|
||||
|
||||
const char *get_module_extension(void)
|
||||
{
|
||||
return ".so";
|
||||
|
@ -51,12 +59,45 @@ void add_default_module_paths(void)
|
|||
{
|
||||
for (int i = 0; i < module_patterns_size; i++)
|
||||
obs_add_module_path(module_bin[i], module_data[i]);
|
||||
|
||||
if (is_in_bundle()) {
|
||||
NSRunningApplication *app =
|
||||
[NSRunningApplication currentApplication];
|
||||
NSURL *bundleURL = [app bundleURL];
|
||||
NSURL *pluginsURL = [bundleURL
|
||||
URLByAppendingPathComponent:@"Contents/Plugins"];
|
||||
NSURL *dataURL = [bundleURL
|
||||
URLByAppendingPathComponent:
|
||||
@"Contents/Resources/data/obs-plugins/%module%"];
|
||||
|
||||
const char *binPath = [[pluginsURL path]
|
||||
cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
const char *dataPath = [[dataURL path]
|
||||
cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
obs_add_module_path(binPath, dataPath);
|
||||
}
|
||||
}
|
||||
|
||||
char *find_libobs_data_file(const char *file)
|
||||
{
|
||||
struct dstr path;
|
||||
|
||||
if (is_in_bundle()) {
|
||||
NSRunningApplication *app =
|
||||
[NSRunningApplication currentApplication];
|
||||
NSURL *bundleURL = [app bundleURL];
|
||||
NSURL *libobsDataURL =
|
||||
[bundleURL URLByAppendingPathComponent:
|
||||
@"Contents/Resources/data/libobs/"];
|
||||
const char *libobsDataPath = [[libobsDataURL path]
|
||||
cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
dstr_init_copy(&path, libobsDataPath);
|
||||
dstr_cat(&path, "/");
|
||||
} else {
|
||||
dstr_init_copy(&path, OBS_INSTALL_DATA_PATH "/libobs/");
|
||||
}
|
||||
|
||||
dstr_cat(&path, file);
|
||||
return path.array;
|
||||
}
|
||||
|
@ -111,13 +152,20 @@ static void log_available_memory(void)
|
|||
memory_available / 1024 / 1024);
|
||||
}
|
||||
|
||||
static void log_os_name(id pi, SEL UTF8String)
|
||||
static void log_os_name(id pi, SEL UTF8StringSel)
|
||||
{
|
||||
unsigned long os_id = (unsigned long)objc_msgSend(
|
||||
typedef int (*os_func)(id, SEL);
|
||||
os_func operatingSystem = (os_func)objc_msgSend;
|
||||
unsigned long os_id = (unsigned long)operatingSystem(
|
||||
pi, sel_registerName("operatingSystem"));
|
||||
|
||||
id os = objc_msgSend(pi, sel_registerName("operatingSystemName"));
|
||||
const char *name = (const char *)objc_msgSend(os, UTF8String);
|
||||
typedef id (*os_name_func)(id, SEL);
|
||||
os_name_func operatingSystemName = (os_name_func)objc_msgSend;
|
||||
id os = operatingSystemName(pi,
|
||||
sel_registerName("operatingSystemName"));
|
||||
typedef const char *(*utf8_func)(id, SEL);
|
||||
utf8_func UTF8String = (utf8_func)objc_msgSend;
|
||||
const char *name = UTF8String(os, UTF8StringSel);
|
||||
|
||||
if (os_id == 5 /*NSMACHOperatingSystem*/) {
|
||||
blog(LOG_INFO, "OS Name: Mac OS X (%s)", name);
|
||||
|
@ -127,11 +175,15 @@ static void log_os_name(id pi, SEL UTF8String)
|
|||
blog(LOG_INFO, "OS Name: %s", name ? name : "Unknown");
|
||||
}
|
||||
|
||||
static void log_os_version(id pi, SEL UTF8String)
|
||||
static void log_os_version(id pi, SEL UTF8StringSel)
|
||||
{
|
||||
id vs = objc_msgSend(pi,
|
||||
sel_registerName("operatingSystemVersionString"));
|
||||
const char *version = (const char *)objc_msgSend(vs, UTF8String);
|
||||
typedef id (*version_func)(id, SEL);
|
||||
version_func operatingSystemVersionString = (version_func)objc_msgSend;
|
||||
id vs = operatingSystemVersionString(
|
||||
pi, sel_registerName("operatingSystemVersionString"));
|
||||
typedef const char *(*utf8_func)(id, SEL);
|
||||
utf8_func UTF8String = (utf8_func)objc_msgSend;
|
||||
const char *version = UTF8String(vs, UTF8StringSel);
|
||||
|
||||
blog(LOG_INFO, "OS Version: %s", version ? version : "Unknown");
|
||||
}
|
||||
|
@ -139,8 +191,9 @@ static void log_os_version(id pi, SEL UTF8String)
|
|||
static void log_os(void)
|
||||
{
|
||||
Class NSProcessInfo = objc_getClass("NSProcessInfo");
|
||||
id pi = objc_msgSend((id)NSProcessInfo,
|
||||
sel_registerName("processInfo"));
|
||||
typedef id (*func)(id, SEL);
|
||||
func processInfo = (func)objc_msgSend;
|
||||
id pi = processInfo((id)NSProcessInfo, sel_registerName("processInfo"));
|
||||
|
||||
SEL UTF8String = sel_registerName("UTF8String");
|
||||
|
||||
|
@ -1673,9 +1726,11 @@ static bool mouse_button_pressed(obs_key_t key, bool *pressed)
|
|||
}
|
||||
|
||||
Class NSEvent = objc_getClass("NSEvent");
|
||||
SEL pressedMouseButtons = sel_registerName("pressedMouseButtons");
|
||||
NSUInteger buttons =
|
||||
(NSUInteger)objc_msgSend((id)NSEvent, pressedMouseButtons);
|
||||
SEL pressedMouseButtonsSel = sel_registerName("pressedMouseButtons");
|
||||
typedef int (*func)(id, SEL);
|
||||
func pressedMouseButtons = (func)objc_msgSend;
|
||||
NSUInteger buttons = (NSUInteger)pressedMouseButtons(
|
||||
(id)NSEvent, pressedMouseButtonsSel);
|
||||
|
||||
*pressed = (buttons & (1 << button)) != 0;
|
||||
return true;
|
|
@ -41,7 +41,7 @@
|
|||
*
|
||||
* Reset to zero each major or minor version
|
||||
*/
|
||||
#define LIBOBS_API_PATCH_VER 3
|
||||
#define LIBOBS_API_PATCH_VER 5
|
||||
|
||||
#define MAKE_SEMANTIC_VERSION(major, minor, patch) \
|
||||
((major << 24) | (minor << 16) | patch)
|
||||
|
|
|
@ -58,9 +58,10 @@ static void *gpu_encode_thread(void *unused)
|
|||
video_output_inc_texture_frames(video->video);
|
||||
|
||||
for (size_t i = 0; i < video->gpu_encoders.num; i++) {
|
||||
obs_encoder_t *encoder = video->gpu_encoders.array[i];
|
||||
obs_encoder_t *encoder = obs_encoder_get_ref(
|
||||
video->gpu_encoders.array[i]);
|
||||
if (encoder)
|
||||
da_push_back(encoders, &encoder);
|
||||
obs_encoder_addref(encoder);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&video->gpu_encoder_mutex);
|
||||
|
|
|
@ -664,7 +664,8 @@ void XCompcapMain::render(gs_effect_t *effect)
|
|||
effect = obs_get_base_effect(OBS_EFFECT_DEFAULT);
|
||||
|
||||
while (gs_effect_loop(effect, "Draw")) {
|
||||
xcursor_render(p->cursor);
|
||||
xcursor_render(p->cursor, -p->cur_cut_left,
|
||||
-p->cur_cut_top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ void xcursor_tick(xcursor_t *data)
|
|||
XFree(xc);
|
||||
}
|
||||
|
||||
void xcursor_render(xcursor_t *data)
|
||||
void xcursor_render(xcursor_t *data, int x_offset, int y_offset)
|
||||
{
|
||||
if (!data->tex)
|
||||
return;
|
||||
|
@ -117,7 +117,8 @@ void xcursor_render(xcursor_t *data)
|
|||
gs_enable_color(true, true, true, false);
|
||||
|
||||
gs_matrix_push();
|
||||
gs_matrix_translate3f(data->render_x, data->render_y, 0.0f);
|
||||
gs_matrix_translate3f(data->render_x + x_offset,
|
||||
data->render_y + y_offset, 0.0f);
|
||||
gs_draw_sprite(data->tex, 0, 0, 0);
|
||||
gs_matrix_pop();
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ void xcursor_tick(xcursor_t *data);
|
|||
*
|
||||
* This needs to be executed within a valid render context
|
||||
*/
|
||||
void xcursor_render(xcursor_t *data);
|
||||
void xcursor_render(xcursor_t *data, int x_offset, int y_offset);
|
||||
|
||||
/**
|
||||
* Specify offset for the cursor
|
||||
|
|
|
@ -108,7 +108,6 @@ int randr_screen_count(xcb_connection_t *xcb)
|
|||
{
|
||||
if (!xcb)
|
||||
return 0;
|
||||
|
||||
xcb_screen_t *screen;
|
||||
screen = xcb_setup_roots_iterator(xcb_get_setup(xcb)).data;
|
||||
|
||||
|
|
|
@ -324,7 +324,9 @@ static bool xshm_server_changed(obs_properties_t *props, obs_property_t *p,
|
|||
")",
|
||||
i, w, h, x, y);
|
||||
|
||||
obs_property_list_add_int(screens, screen_info.array, i);
|
||||
if (h > 0 && w > 0)
|
||||
obs_property_list_add_int(screens, screen_info.array,
|
||||
i);
|
||||
}
|
||||
|
||||
/* handle missing screen */
|
||||
|
|
|
@ -183,7 +183,8 @@ static bool parse_params(AVCodecContext *context, char **opts)
|
|||
*assign = 0;
|
||||
value = assign + 1;
|
||||
|
||||
if (av_opt_set(context->priv_data, name, value, 0)) {
|
||||
if (av_opt_set(context, name, value,
|
||||
AV_OPT_SEARCH_CHILDREN)) {
|
||||
blog(LOG_WARNING, "Failed to set %s=%s", name,
|
||||
value);
|
||||
ret = false;
|
||||
|
|
|
@ -1342,7 +1342,7 @@ static void check_to_drop_frames(struct rtmp_stream *stream, bool pframes)
|
|||
return;
|
||||
}
|
||||
|
||||
if (buffer_duration_usec >= DBR_TRIGGER_USEC) {
|
||||
if ((uint64_t)buffer_duration_usec >= DBR_TRIGGER_USEC) {
|
||||
pthread_mutex_lock(&stream->dbr_mutex);
|
||||
bitrate_changed = dbr_bitrate_lowered(stream);
|
||||
pthread_mutex_unlock(&stream->dbr_mutex);
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
project(rtmp-services)
|
||||
|
||||
find_package(Libcurl REQUIRED)
|
||||
|
||||
include_directories(${LIBCURL_INCLUDE_DIRS})
|
||||
|
||||
include_directories(${OBS_JANSSON_INCLUDE_DIRS})
|
||||
|
||||
set(rtmp-services_SOURCES
|
||||
twitch.c
|
||||
younow.c
|
||||
rtmp-common.c
|
||||
rtmp-custom.c
|
||||
rtmp-services-main.c)
|
||||
|
||||
set(rtmp-services_HEADERS
|
||||
twitch.h
|
||||
younow.h
|
||||
rtmp-format-ver.h)
|
||||
|
||||
set(RTMP_SERVICES_URL
|
||||
|
@ -28,10 +34,12 @@ add_library(rtmp-services MODULE
|
|||
${rtmp-services_SOURCES}
|
||||
${rtmp-services_HEADERS}
|
||||
${rtmp-services_config_HEADERS})
|
||||
|
||||
target_link_libraries(rtmp-services
|
||||
libobs
|
||||
file-updater
|
||||
${OBS_JANSSON_IMPORT})
|
||||
${OBS_JANSSON_IMPORT}
|
||||
${LIBCURL_LIBRARIES})
|
||||
|
||||
target_include_directories(rtmp-services
|
||||
PUBLIC
|
||||
|
|
4
plugins/rtmp-services/data/package.json
Normal file → Executable file
4
plugins/rtmp-services/data/package.json
Normal file → Executable file
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"url": "https://obsproject.com/obs2_update/rtmp-services",
|
||||
"version": 112,
|
||||
"version": 114,
|
||||
"files": [
|
||||
{
|
||||
"name": "services.json",
|
||||
"version": 112
|
||||
"version": 114
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
49
plugins/rtmp-services/data/services.json
Normal file → Executable file
49
plugins/rtmp-services/data/services.json
Normal file → Executable file
|
@ -1465,6 +1465,20 @@
|
|||
"max audio bitrate": 192
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ChathostessModels",
|
||||
"servers": [
|
||||
{
|
||||
"name": "ChathostessModels - Default",
|
||||
"url": "rtmp://wowza01.foobarweb.com/cmschatsys_video"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 2,
|
||||
"max video bitrate": 3000,
|
||||
"max audio bitrate": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Camplace",
|
||||
"servers": [
|
||||
|
@ -1500,6 +1514,24 @@
|
|||
"x264opts": "tune=zerolatency"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "YouNow",
|
||||
"common": false,
|
||||
"servers": [
|
||||
{
|
||||
"name": "younow.com",
|
||||
"url": "https://signaling-api.younow-prod.video.propsproject.com/api/v1/ingest/server/"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 2,
|
||||
"output": "ftl_output",
|
||||
"max audio bitrate": 160,
|
||||
"max video bitrate": 7000,
|
||||
"profile": "main",
|
||||
"bframes": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Steam",
|
||||
"common": false,
|
||||
|
@ -1559,6 +1591,23 @@
|
|||
"max video bitrate": 7000,
|
||||
"max audio bitrate": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Stars.AVN.com",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Default",
|
||||
"url": "rtmp://alpha.gateway.stars.avn.com/live"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 2,
|
||||
"profile": "main",
|
||||
"max video bitrate": 2500,
|
||||
"max audio bitrate": 192,
|
||||
"bframes": 0,
|
||||
"x264opts": "tune=zerolatency"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "rtmp-format-ver.h"
|
||||
#include "twitch.h"
|
||||
#include "younow.h"
|
||||
|
||||
struct rtmp_common {
|
||||
char *service;
|
||||
|
@ -485,7 +486,9 @@ static void apply_video_encoder_settings(obs_data_t *settings,
|
|||
obs_data_set_string(settings, "rate_control", "CBR");
|
||||
|
||||
item = json_object_get(recommended, "profile");
|
||||
if (json_is_string(item)) {
|
||||
obs_data_item_t *enc_item = obs_data_item_byname(settings, "profile");
|
||||
if (json_is_string(item) &&
|
||||
obs_data_item_gettype(enc_item) == OBS_DATA_STRING) {
|
||||
const char *profile = json_string_value(item);
|
||||
obs_data_set_string(settings, "profile", profile);
|
||||
}
|
||||
|
@ -594,6 +597,12 @@ static const char *rtmp_common_url(void *data)
|
|||
}
|
||||
}
|
||||
|
||||
if (service->service && strcmp(service->service, "YouNow") == 0) {
|
||||
if (service->server && service->key) {
|
||||
return younow_get_ingest(service->server, service->key);
|
||||
}
|
||||
}
|
||||
|
||||
return service->server;
|
||||
}
|
||||
|
||||
|
|
113
plugins/rtmp-services/younow.c
Normal file
113
plugins/rtmp-services/younow.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
#include <curl/curl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <util/dstr.h>
|
||||
#include "util/base.h"
|
||||
#include "younow.h"
|
||||
|
||||
struct younow_mem_struct {
|
||||
char *memory;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static char *current_ingest = NULL;
|
||||
|
||||
static size_t younow_write_cb(void *contents, size_t size, size_t nmemb,
|
||||
void *userp)
|
||||
{
|
||||
size_t realsize = size * nmemb;
|
||||
struct younow_mem_struct *mem = (struct younow_mem_struct *)userp;
|
||||
|
||||
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
|
||||
if (mem->memory == NULL) {
|
||||
blog(LOG_WARNING, "yyounow_write_cb: realloc returned NULL");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&(mem->memory[mem->size]), contents, realsize);
|
||||
mem->size += realsize;
|
||||
mem->memory[mem->size] = 0;
|
||||
|
||||
return realsize;
|
||||
}
|
||||
|
||||
const char *younow_get_ingest(const char *server, const char *key)
|
||||
{
|
||||
CURL *curl_handle;
|
||||
CURLcode res;
|
||||
struct younow_mem_struct chunk;
|
||||
struct dstr uri;
|
||||
long response_code;
|
||||
|
||||
// find the delimiter in stream key
|
||||
const char *delim = strchr(key, '_');
|
||||
if (delim == NULL) {
|
||||
blog(LOG_WARNING,
|
||||
"younow_get_ingest: delimiter not found in stream key");
|
||||
return server;
|
||||
}
|
||||
|
||||
curl_handle = curl_easy_init();
|
||||
|
||||
chunk.memory = malloc(1); /* will be grown as needed by realloc */
|
||||
chunk.size = 0; /* no data at this point */
|
||||
|
||||
dstr_init(&uri);
|
||||
dstr_copy(&uri, server);
|
||||
dstr_ncat(&uri, key, delim - key);
|
||||
|
||||
curl_easy_setopt(curl_handle, CURLOPT_URL, uri.array);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, true);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 3L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, younow_write_cb);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
|
||||
|
||||
#if LIBCURL_VERSION_NUM >= 0x072400
|
||||
// A lot of servers don't yet support ALPN
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_ENABLE_ALPN, 0);
|
||||
#endif
|
||||
|
||||
res = curl_easy_perform(curl_handle);
|
||||
dstr_free(&uri);
|
||||
|
||||
if (res != CURLE_OK) {
|
||||
blog(LOG_WARNING,
|
||||
"younow_get_ingest: curl_easy_perform() failed: %s",
|
||||
curl_easy_strerror(res));
|
||||
curl_easy_cleanup(curl_handle);
|
||||
free(chunk.memory);
|
||||
return server;
|
||||
}
|
||||
|
||||
curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &response_code);
|
||||
if (response_code != 200) {
|
||||
blog(LOG_WARNING,
|
||||
"younow_get_ingest: curl_easy_perform() returned code: %ld",
|
||||
response_code);
|
||||
curl_easy_cleanup(curl_handle);
|
||||
free(chunk.memory);
|
||||
return server;
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl_handle);
|
||||
|
||||
if (chunk.size == 0) {
|
||||
blog(LOG_WARNING,
|
||||
"younow_get_ingest: curl_easy_perform() returned empty response");
|
||||
free(chunk.memory);
|
||||
return server;
|
||||
}
|
||||
|
||||
if (current_ingest) {
|
||||
free(current_ingest);
|
||||
current_ingest = NULL;
|
||||
}
|
||||
|
||||
current_ingest = strdup(chunk.memory);
|
||||
free(chunk.memory);
|
||||
blog(LOG_INFO, "younow_get_ingest: returning ingest: %s",
|
||||
current_ingest);
|
||||
return current_ingest;
|
||||
}
|
3
plugins/rtmp-services/younow.h
Normal file
3
plugins/rtmp-services/younow.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
extern const char *younow_get_ingest(const char *server, const char *key);
|
Loading…
Reference in a new issue