Overview
Request 3709 (accepted)
- Update to version 18.0.0:
* UI: Add more command line options
* obs-browser: Update submodule to latest version
* Revert "Revert "win-capture: Use FindWindowEx to traverse window list""
* CI: Add in inital appveyor config
* CI: Move browser source before building app
* CI: Build VLC plugin for OSX on travis
* rtmp-services: remove shut down services
* CI: Build Windows version and upload artifacts
* obs-browser: Update browser ref
* CI: Update permissions on CEF app plist before packaging
* cmake: Enable COPY_DEPENDENCIES by default on Windows
* rtmp-services: Update Vaughn Live ingests
* libobs: Log correct amount of memory on 32bit (windows)
* UI: Convert to wide before outputting debug text (win)
* UI: Protect debug text static string var with mutex
* libobs: Add ability to get output congestion
* obs-output: Add ability to get congestion to rtmp output
* obs-outputs: Increase default drop threshold
* UI: Add connection status square to status bar
* UI: Add separate timers to status bar
* UI: Add option to always minimize to tray
* UI: Hide/show dialogs when minimizing to tray
* UI: Do not quit program when last windows are projectors
* UI: Add option to save projectors
* UI: Add auto-start replay buf. opt. when stream starts
* UI: Fix scaling in viewport when source flipped
* UI: Fix linux display/resize bug with preview widget
* rtmp-services: Add Restream.io Los Angeles server
* libobs: Add optional ultrawide -> wide scaling techniques
- Created by boombatower about 8 years ago
- In state accepted
-
Package maintainers:
boombatower,
darix, and
frispete
obs-studio.changes
Changed
-------------------------------------------------------------------
+Tue Feb 28 00:38:38 UTC 2017 - jimmy@boombatower.com
+
+- Update to version 18.0.0:
+ * UI: Add more command line options
+ * obs-browser: Update submodule to latest version
+ * Revert "Revert "win-capture: Use FindWindowEx to traverse window list""
+ * CI: Add in inital appveyor config
+ * CI: Move browser source before building app
+ * CI: Build VLC plugin for OSX on travis
+ * rtmp-services: remove shut down services
+ * CI: Build Windows version and upload artifacts
+ * obs-browser: Update browser ref
+ * CI: Update permissions on CEF app plist before packaging
+ * cmake: Enable COPY_DEPENDENCIES by default on Windows
+ * rtmp-services: Update Vaughn Live ingests
+ * libobs: Log correct amount of memory on 32bit (windows)
+ * UI: Convert to wide before outputting debug text (win)
+ * UI: Protect debug text static string var with mutex
+ * libobs: Add ability to get output congestion
+ * obs-output: Add ability to get congestion to rtmp output
+ * obs-outputs: Increase default drop threshold
+ * UI: Add connection status square to status bar
+ * UI: Add separate timers to status bar
+ * UI: Add option to always minimize to tray
+ * UI: Hide/show dialogs when minimizing to tray
+ * UI: Do not quit program when last windows are projectors
+ * UI: Add option to save projectors
+ * UI: Add auto-start replay buf. opt. when stream starts
+ * UI: Fix scaling in viewport when source flipped
+ * UI: Fix linux display/resize bug with preview widget
+ * rtmp-services: Add Restream.io Los Angeles server
+ * libobs: Add optional ultrawide -> wide scaling techniques
+ * obs-filters: Add option to undistort ultrawide -> wide
+ * obs-filters: Add "Color Grading" filter
+ * rtmp-services: Add new beam.pro ingests
+ * CI: Add post install script to OBS installer to fix CEF permissions
+ * rtmp-services: Add Web.TV streaming service
+ * Add VST Plugin
+ * obs-filters: Fix compiler warnings
+ * UI: Remove unused variables
+ * UI: Clarify "Always minimize to tray" option
+ * obs-filters: Rename "Color Grade" filter to "LUT Filter"
+ * obs-filters: Change "LUT Filter" to "Apply LUT"
+ * CI: Fix VLC download
+ * CI: Unzip VLC quietly
+ * rtmp-services: Update twitch/hitbox ingest and youtube recommendations
+ * CI: Fix OSX post-install script
+ * UI: Fix locale text alignment
+ * UI: Make advanced settings pane a bit more compact
+ * libobs: Mark last video ts even when buffering off
+ * libobs: Mark parameter as constant if not modifying
+ * libobs: Use original audio structure for audio signal
+ * libobs: Implement audio monitoring
+ * win-wasapi: Mark audio outputs as unmonitorable
+ * UI: Add audio monitoring to settings/adv audio props.
+ * UI: Prevent thread stalls with fader/volume widgets
+ * obs-transitions: Convert premultiplied alpha to straight
+ * UI: Add 24 NTSC as a common FPS value
+ * obs-ffmpeg: Do not use HW accel by default on mac
+ * rtmp-services: Update twitch ingests
+ * obs-ffmpeg: Fix compiler warnings
+ * UI: Fix compiler warning
+ * UI: Change volume meter update interval to 30fps
+ * UI: Add warning if starting the output fails
+ * obs-ffmpeg: Be more verbose when custom params fail
+ * obs-ffmpeg: Fix custom audio codec parameters
+ * CI: Retry failed downloads
+ * UI: fix ffmpeg output file extension
+ * UI: Clean up general pane of settings dialog
+ * UI: Add function to get remote file
+ * UI: Add front-end auto-updater
+ * UI: Update installer to latest version
+ * UI: Add latest installer fixes from R1CH
+ * obs-ffmpeg: Add 'save' to replay buffer proc handler
+ * win-capture: Fall back to GetWindow if FindWindowEx fails
+ * libobs: Fix audio monitoring delaying perpetually
+ * rtmp-services: Update max video bitrate for beam
+ * libobs/util: Use a mutex with config files
+ * win-capture: Blacklist chrome/firefox from game capture
+ * win-dshow: Add LGP timestamp fix
+ * UI: Trigger frontend api scene change after transition
+ * Add AUTHORS file
+ * mailmap: Disambiguate between a few authors
+ * mailmap: Disambiguate between another author
+ * rtmp-services: Add "Pandora TV Korea"
+ * UI: Trigger scene list change event when scene removed
+ * CI: Speedup msbuild by using all CPU cores
+ * UI: Improve accessibility text on main window
+ * CI: Download VLC repo instead of cloning from git
+ * CI: Disable test discovery on AppVeyor
+ * CI: Cache dependencies downloads on AppVeyor
+ * CI: Disable deps download in AppVeyor and use cache
+ * CI: Download deps if they aren't in build cache
+ * UI: Use blake2b instead of SHA1 for updater
+ * UI: Make installer execute 64bit on 64bit windows
+ * obs-text: Fix issue drawing some chinese characters
+ * obs-filters: Add audio compression filter
+ * obs-outputs: Port windows socket loop from OBS Classic
+ * librtmp: Clean up our extra RTMP fields on close
+ * UI: Add options for new socket loop
+ * UI: Make sure size-specific spacers are fixed
+ * UI: Fix some settings layouts on non-windows systems
+ * win-capture: Add hook exception for theHunter: COTW
+ * obs-ffmpeg/ffmpeg-mux: Fix failing when no video
+ * image-source: Add solid color source
+ * image-source: Add missing locale
+ * Fix various null pointer issues detected by Coverity
+ * obs-ffmpeg: Allow saving with different video codecs
+ * UI: Add support for other codecs
+ * graphics-hook: Account for sizeof(wchar_t) in len
+ * obs-qsv11: Fix various issues detected by Coverity
+ * obs-ffmpeg: Make gop size configurable
+ * UI: Add gop size option for custom ffmpeg output
+ * libff: Add override for codec compatability check
+ * UI: Add codec compatability checkbox to ffmpeg output
+ * UI: Add warning about recording to mp4 format
+ * CI: Fetch git tags on OSX build
+ * CI: Exit on errors when building the OSX package
+ * UI: Fix typo in general settings
+ * enc-amf: Update to version 1.4.3.9
+ * CI: Build on Linux
+ * libobs: Update version to 18.0.0
+ * libobs: Fix bug where scenes would not properly mix audio
+ * UI: If scene/source names exist, start from 2
+ * CI: Don't skip_join for Travis IRC notifications
+ * obs-frontend-api: Use virtual destructor (fix memory leak)
+ * libobs: Add missing mutex unlock in audio monitoring
+ * CI: Get some codesigning and sparkle stuff in place
+ * CI: Use combined cert for signing OSX
+ * CI: Set keychain timeout & allow productsign
+ * CI: Add some logging to the before deploy script on OSX
+ * CI: Possibly fix OSX cert import issue
+ * CI: OSX - Brew install jack
+ * CI: Notify on failure and only for fixed builds
+ * CI: Reformat Travis CI IRC notification
+ * UI: Hide auto update option for linux
+ * obs-filters: Change attack/release ms limit to 300 (from 100)
+ * obs-filters: Increase max compressor release/attack values
+ * Update translations from Crowdin
+ * AUTHORS: Update with data from Git and Crowdin
+ * UI: Update Simple Mode AMD Presets
+ * enc-amf: Update to hotfix 1.4.3.10
+ * CI: OSX Set builds to stable on tagged builds
+ * CI: Update public OSX install key
+
+-------------------------------------------------------------------
Wed Jan 18 14:48:26 UTC 2017 - jimmy@boombatower.com
- Update to version 17.0.2:
obs-studio.spec
Changed
Name: obs-studio
-Version: 17.0.2
+Version: 18.0.0
Release: 0
Summary: A recording/broadcasting program
_service
Changed
<services>
<service name="tar_scm" mode="disabled">
<param name="versionformat">@PARENT_TAG@</param>
- <param name="revision">refs/tags/17.0.2</param>
+ <param name="revision">refs/tags/18.0.0</param>
<param name="url">git://github.com/jp9000/obs-studio.git</param>
<param name="scm">git</param>
<param name="changesgenerate">enable</param>
_servicedata
Changed
<servicedata>
<service name="tar_scm">
<param name="url">git://github.com/jp9000/obs-studio.git</param>
- <param name="changesrevision">841dfade55dff65a4080dbdfd5672f3318de6f08</param>
+ <param name="changesrevision">5312ffa8157c4210cf57026f90eeb09e81a5a461</param>
</service>
</servicedata>
obs-studio-17.0.2.tar.xz/.mailmap -> obs-studio-18.0.0.tar.xz/.mailmap
Changed
Benjamin Klettbach <b.klettbach@gmail.com>
BtbN <btbn@btbn.de>
John Bradley <jrb@turrettech.com>
+HomeWorld <homeworld@gmail.com> hwdro <pdarvaru@yahoo.com>
+Michael Fabian Dirks <info@xaymar.com> <michael.dirks@xaymar.com>
+Martell Malone <martellmalone@gmail.com>
obs-studio-17.0.2.tar.xz/.travis.yml -> obs-studio-18.0.0.tar.xz/.travis.yml
Changed
-os: osx
+language: cpp
+
env:
- matrix:
- - CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake
global:
# AWS S3 creds
# access key
- secure: "MfhOg+84yb4ZHB2tM8PIPFQX2Y+WLN0I0iiAgyLC4KaHPUoNOyloe9yk6OjV7Lj7SZWqTlQUsqHa8S9mOUswGIody1Ydglo4RvyGOKCd8I6b2ri/jE8qHVuD9sO+sNlIxq4YqqG/qReTsbSs2YEgLneZUCYLCk/fihl8L6eVuSc="
# secret
- secure: "JRQVU2zgC3hY6CEY+Crmh/upp93En0BzKaLcsuBT538johNlK7m5hn3m2UOw63seLvBvVaKKWUDj9N986a3DwcXxWPMyF/9ctXgNWy39WzaVWxrbVR5nQB1fdiRp5YEgkoVN+gEm3OVF7sV5AGzh5/8CvEdRCoTLIGgMGHxW9mc="
-language: cpp
-before_install: "./CI/install-dependencies-osx.sh"
-before_script: "./CI/before-script-osx.sh"
+
+matrix:
+ include:
+ - os: osx
+ env: CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake
+ before_install: "./CI/install-dependencies-osx.sh"
+ before_script: "./CI/before-script-osx.sh"
+ before_deploy: "./CI/before-deploy-osx.sh"
+
+ - os: linux
+ dist: trusty
+ sudo: required
+ before_install: "./CI/install-dependencies-linux.sh"
+ before_script: "./CI/before-script-linux.sh"
+
script: cd ./build && make -j4 && cd -
-before_deploy: "./CI/before-deploy-osx.sh"
+
deploy:
provider: s3
access_key_id: $AWS_ACCESS_KEY
acl: public_read
on:
repo: jp9000/obs-studio
+ condition: "$TRAVIS_OS_NAME = osx"
# The channel name "azubu.il.us.quakenet.org#obs-dev" is encrypted against jp9000/obs-studio to prevent IRC spam of forks
notifications:
irc:
- skip_join: true
+ skip_join: false
template:
- - "%{message} %{build_url}"
+ - "[Travis CI|%{result}] %{repository_name}/%{branch} (%{author} - %{commit_subject}) %{build_url}"
channels:
- secure: k9j7+ogVODMlveZdd5pP73AVLCFl1VbzVaVon0ECn3EQcxnLSpiZbc6l+PnIUKgee5pRKtUB4breufgmr4puq3s69YeQiOVKk5gx2yJGZ5jGacbSne0xTspzPxapiEbVUkcJ2L7gKntDG4+SUiW67dtt4G26O7zsErDF/lY/woQ=
+ on_failure: always
+ on_success: change
obs-studio-18.0.0.tar.xz/AUTHORS
Added
+Contributors are sorted by their amount of commits / validated strings.
+
+Contributors:
+Jim
+Palana
+fryshorts
+BtbN
+John Bradley
+Gol-D-Ace
+Zachary Lund
+Richard Stanway
+Colin Edwards
+Michael Fabian Dirks
+Martell Malone
+Christoph Hohmann
+HomeWorld
+dodgepong
+cg2121
+derrod
+Ryan Foster
+Radzaquiel
+Socapex
+Skyler Lipthay
+SuslikV
+Arkkis
+Cephas Reis
+GoaLitiuM
+Danni
+Jess Mayo
+Kris Moore
+Carl Fürstenberg
+juvester
+Anry
+CoDEmanX
+Ján Mlynek
+Manuel Kroeber
+sorayuki
+Alexandre Vicenzi
+Benjamin Klettbach
+bl
+Bl00drav3n
+Blackhive
+Charles Ray Shisler III
+Jeremiah Senkpiel
+John R. Bradley
+Kilian von Pflugk
+Serge Paquet
+shiina424
+shousa
+Timo Gurr
+adray
+Andrei Nistor
+Andrew Surzhynskyi
+Azat Khasanshin
+Ben Torell
+bootkiller
+Brian S. Stephan
+Eric Bataille
+Joseph El-Khouri
+jpk
+Kurt Kartaltepe
+Lexsus
+Lionheart Zhang
+paibox
+Robin Hielscher
+skwerlman
+taesheren
+Take Vos
+Taylor Blau
+Warren Turkal
+yogpstop
+Aarni Koskela
+Aesen Vismea
+Akagi201
+Alexander Uhlmann
+Alexandre Biny
+Andreas Reischuck
+Anthony Catel
+Anthony Super
+Asgeir Mortensen
+Autumin
+Aydin Akan
+Bernd Buschinski
+bla
+boombatower
+Caitlin Potter
+Caleb Anderson
+CallumHoward
+Cam
+CommanderRoot
+Copy Liu
+cryptonaut
+Dan Dascalescu
+David Cooper
+David McMackins II
+dennis
+Derrick Lambert
+Emil Sayahi
+EpicCoder
+Ethan Lee
+Frank Gehann
+Giorgio Pellero
+Grigorii Chirkov
+Guillermo A. Amaral
+Gökberk Yaltıraklı
+Haden F
+Iblis Lin
+Jake Probst
+Jamy Timmermans
+Jimmy Berry
+Jkoan
+Joel Bethke
+Julian Miller
+Kazuki Oishi
+ka’imi
+Kevin
+Kevin Tardif
+Lasse Dalegaard
+lemmi
+Lioncash
+Lucian Poston
+Lukas Monka
+Luke Yelavich
+mape
+Marc Chambers
+Mark Vaughn
+Mathias Panzenböck
+Matthew McNamara
+MedicMomcilo
+michael bishop
+Michael Hoang
+Momcilo Medic
+nd
+Nicolas F
+Night
+Olle Kelderman
+pantonvich
+partouf
+Peter SZTANOJEV
+pipll
+raincomplex
+repeat
+Ricardo Constantino
+Rodrigo Ipince
+rpslack
+Ryan Sullivan
+sam8641
+Seth Murphy
+Seung-Woo Kim
+Simon
+Teemu Kauhanen
+thekrzos
+Thomas McGrew
+TotalCaesar659
+vic
+vividnightmare
+wayne wang
+Weikardzaena
+Will Jamieson
+William Casarin
+Younes SERRAJ
+Ziemas
+
+Translations:
+Arabic
+ Abdullah AL-Qahtani (Za7ef_SA)
+ majdcomp
+ ZILZAL
+ BWU Wheelman (Wheelman)
+ Saleh Luxmaroc (salehoukiki)
+ Gol D. Ace (goldace)
+ معتصم دعنا (rozana-media)
+ chaironeko
+ dodgepong
+ FC Barcelona HD (kurdnews)
+Basque
+ Alexander Gabilondo (alexgabi)
+ Xabier Aramendi (azpidatziak)
+ Osoitz
+ txaro
+ etxondoko
+ Gol D. Ace (goldace)
+ dodgepong
+Bulgarian
+ kalmarin
+ Seyhan Halil (yildirim17)
+ Viktor Kitov (viktorkitov)
+ Stanislav_Evtimov
+ Ivan (SKDown)
+Catalan
+ Jaime Muñoz Martín (jmmartin_5)
+ jmontane
+ Nil Campamà (Soifam)
+ Aleix Vidal i Gaya (leixet)
+ Gol D. Ace (goldace)
+Chinese Simplified
+ Bob Liu (Akagi201)
+ PabloLiu (719018105)
+ Sasasu
+ cai_miao
+ David Kuo (s50407s)
+ Boyuan Yang (073plan)
+ 鲜童 (xiananjyzy)
+ copyliu
+ wwj402_github
+ Bing Feng (fengbing123)
+ dodgepong
+ WaterOtaku
+Chinese Traditional
+ TzeKei Lee (chikei)
+ dodgepong
+ Julian_Lai
+ Chien-Yu Lin (u900011)
+ David Kuo (s50407s)
+ You-Ruei Tzeng (e222et)
+ Inndy.Lin (inndy)
+ Meng Hao Li (GazCore)
+ Gol D. Ace (goldace)
+ Watson Tsai (ashaneba)
+ cai_miao
+ Jimmy Huang (f56112000)
+ chaironeko
+ tomoe-musashi
+Croatian
+ medicmomcilo
+ Gol D. Ace (goldace)
+ dodgepong
+Czech
+ Jirka 'Venty' Michel (VentyCZ)
+ Sawanyo
+ dodgepong
+ Kiznoh
+Danish
+ Jens Hyllegaard (Hyllegaard)
+ Anders G. Jørgensen (spirit55555)
+ MaltahlGaming (maltahlgaming)
+ NCAA
+ Anders Urban (minikaliffen)
+ Christian Henriksen (cnhenriksen)
+ Gol D. Ace (goldace)
+ Johan Keller Jensen (JKeller)
+Dutch
+ Eric Bataille (ThoNohT)
+ Michel Snippe (michelsnippe)
+ Nicole (NIsengo)
+ Jasper J (JassieJ)
+ Gol D. Ace (goldace)
+ JorRy
+Estonian
+ AndresTraks
+Finnish
+ ArkkisN (j)
+ dodgepong
+ Jarska
+ Jarppi (Jarppi01)
+ Gol D. Ace (goldace)
+ chaironeko
+French
+ radzaquiel
+ Yberion
+ Stéphane Lepin (Palakis)
+ Léo (leeo97one)
+ DoK_-
+ BoboopTeam
+ DarkInFire
+ Nunzio Conte (nunzioconte54)
+ steve_fr
+ Grisou2907
+ McGuygnol
+ Gabriel Dugny (Gabigabigo)
+ Gol D. Ace (goldace)
+ dodgepong
+ chaironeko
+Galician
+ Xesús M. Mosquera Carregal (xesusmosquera)
+ Gol D. Ace (goldace)
+ chaironeko
+German
+ Gol D. Ace (goldace)
+ Michael Fabian Dirks (Xaymar)
+ dodgepong
+ Benjamin Klettbach (benklett)
+ Sven Kirschbaum (fallobst22) (fallobst22)
+ random31415
+ Palana
+ Dennis Giebert (Isegrim) (isegrimderwolf)
+ Jonathan (macburgerjunior)
+ Robin Hielscher (Jack0r)
+ BoJustus
+ Jonas Otto (jottosmail)
+ mdod
+ Prince_of_Raop
+ Tiim
+ Tim (robske_110) (robske110)
+ WurstOnAir
+Greek
+ Mepharees
+ Tasos Sahanidis (tatokis)
+ Alex Kalles (alexakis1997)
+ iosifidis
+ chaironeko
+ dodgepong
+Hebrew
+ amirsher
+ Chemi
+ epic_ziver_D
+Hungarian
+ Gige
+ Adam Liszkai (adamos42)
+ dodgepong
+ Gol D. Ace (goldace)
+Italian
+ LordShadow95
+ Marocco2
+ dodgepong
+ Edoardo Macrì (edomacri)
+ smart2128
+ Edoardo “OfficialDJMela” Macrì (agersforum)
+ ScemEnzo
+ Fisherozzo
+ Gol D. Ace (goldace)
+ Sergio Beneduce (sbeneduce)
+ SkyLion
+Japanese
+ shousa
+ Kenta (kenta0644)
+ dodgepong
+ chaironeko
+Korean
+ Wonjoo Noh (ynetwork)
+ Gol D. Ace (goldace)
+ antome
+Lithuanian
+ Justas Vilimas (tyntas)
+Malay
+ amsyar ZeRo (amsyarminer555)
+ dodgepong
+Norwegian Bokmal
+ Taesh (magnusmbratteng)
+ dodgepong
+ mgKaiztra
+ Tommy (nwgat)
+ Oddbjørn Grytdal (Fooshi)
+ Decicus
+ Gol D. Ace (goldace)
+ areedw
+ Legend27
+ chaironeko
+ Mats Andreassen (MatsA)
+Pirate English
+ Matthew Hatcher (MatthewSH)
+ jkcoaster
+ Charlie W. (wallichc)
+ iltrof
+ chaironeko
+ Gol D. Ace (goldace)
+Polish
+ grocal
+ Michał Durak (micechal)
+ Damian Korcz (damikiller)
+ opl
+ Gol D. Ace (goldace)
+ dodgepong
+ Mateusz (Silesianek)
+ Michał Lewczak (michal200507)
+Portuguese
+ André Biscaia (LazP)
+ dodgepong
+ joaoboia
+ Gol D. Ace (goldace)
+Portuguese, Brazilian
+ Ramon Mendes (rbrgameplays)
+ Fabio Madia (Shaolin)
+ Burkes
+ TFSThiagoBR98
+ CaioWzy
+ clr0dr1g
+ aalonsomb
+ André Gama (ToeOficial)
+ Gol D. Ace (goldace)
+ dodgepong
+ ThisGuy
+Romanian
+ Cristian Silaghi (stelistcristi)
+ banrek
+ Hisashi
+ Gol D. Ace (goldace)
+ chaironeko
+ dodgepong
+Russian
+ iltrof
+ Alek Nirov (dectanova)
+ VNGXR
+ dodgepong
+ Pavel (Shevalie)
+ Maxim Gribanov (MaximGribanov)
+ Andy (anry025)
+ fromgate
+ Gol D. Ace (goldace)
+ Andrei Stepanov (adem4ik)
+ Vlad (KoTmaxHo)
+ Bugo
+ Mixaill
+ Sergei Fug1t1v3 (fug)
+ Walt Gee (vovanych)
+ Sigge Stjärnholm (Kladdy)
+ Yuri Mihaqlov (yurijmi)
+Serbian (Cyrillic)
+ medicmomcilo
+ Gol D. Ace (goldace)
+Serbian (Latin)
+ medicmomcilo
+ Gol D. Ace (goldace)
+ dodgepong
+Slovak
+ Ján M (longmoped)
+ Anton Lokaj (anlo)
+ LoLLy Nka (lollynka279)
+Slovenian
+ kristjan.krusic (krusic22)
+ ArcaneWater
+ Gol D. Ace (goldace)
+ dodgepong
+Spanish
+ Roberto Lorenzo (HonzoNebro)
+ Marcos Vidal Martinez (M4RK22)
+ Jaime Martinez Rincon (mrjaime1999)
+ Jaime Muñoz Martín (jmmartin_5)
+ Maximiliano Schtroumpftech Pena-Roig (som2tokmynam)
+ Eleazar Córcoles (MtrElee3)
+ Gol D. Ace (goldace)
+ Sigge Stjärnholm (Kladdy)
+ chaironeko
+ dodgepong
+ Rodrigo Ipince (ipince)
+ Rubén Pérez (RixzZ)
+Swedish
+ Anton R (FirePhoenix)
+ Sigge Stjärnholm (Kladdy)
+ Laccy IEST (Laccy)
+ Olle Dahström (odahlstrom)
+ Gustav Ekner (ekner)
+ Gol D. Ace (goldace)
+ chaironeko
+ Jonas Svensson (jonassanojj99)
+Tamil
+ Kolappan Nathan (kolappannathan)
+Thai
+ sakuhanachan* (sakuhanachanloli)
+ 盛凤阁 (execzero)
+ nongnoobjung (kitcharuk_4)
+ dodgepong
+Turkish
+ omer.karagoz (mrkaragoz)
+ Ali Kömesöğütlü (Mobile46) (byzlo685)
+ Cemal Dursun (cmldrs)
+ Savas Tokmak (Laserist)
+ Murat Karagöz (anemon_1994)
+ gecebekcisi1
+ Gol D. Ace (goldace)
+ Hydroboost
+ mustafaa
+Ukrainian
+ SuslikV
+ Юрій (Devinit)
+ Andy (anry025)
+ Maksym Tymoshyk (maximillian_)
+Vietnamese
+ Johnny “max20091” Utah (boostyourprogram)
+ Hưng Nguyễn (hoyostudio)
+ Hà Phi Hùng (haphihungcom)
+ dodgepong
obs-studio-17.0.2.tar.xz/CI/before-deploy-osx.sh -> obs-studio-18.0.0.tar.xz/CI/before-deploy-osx.sh
Changed
+hr() {
+ echo "───────────────────────────────────────────────────"
+ echo $1
+ echo "───────────────────────────────────────────────────"
+}
+
+# Exit if something fails
+set -e
+
+# Generate file name variables
export GIT_HASH=$(git rev-parse --short HEAD)
export FILE_DATE=$(date +%Y-%m-%d.%H:%M:%S)
export FILENAME=$FILE_DATE-$GIT_HASH-osx.pkg
-mkdir nightly
+
cd ./build
-sudo python ../CI/install/osx/build_app.py
+
+# Move the CEF plugin out before running build_app so that it doesn't get packaged twice
+hr "Moving CEF out to preserve linking"
+mv ./rundir/RelWithDebInfo/obs-plugins/CEF.app ./
+mv ./rundir/RelWithDebInfo/obs-plugins/obs-browser.so ./
+
+# Package everything into a nice .app
+hr "Packaging .app"
+STABLE=False
+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 --base-url "https://obsproject.com/osx_update" --stable $STABLE
+
+# Move the CEF plugin back to where it belongs
+hr "Moving CEF back"
+mv ./CEF.app ./rundir/RelWithDebInfo/obs-plugins/
+mv ./obs-browser.so ./rundir/RelWithDebInfo/obs-plugins/
+
+# Package app
+hr "Generating .pkg"
packagesbuild ../CI/install/osx/CMakeLists.pkgproj
-sudo cp OBS.pkg ./$FILENAME
+# Signing stuff
+hr "Decrypting Cert"
+openssl aes-256-cbc -K $encrypted_dd3c7f5e9db9_key -iv $encrypted_dd3c7f5e9db9_iv -in ../CI/osxcert/Certificates.p12.enc -out Certificates.p12 -d
+hr "Creating Keychain"
+security create-keychain -p mysecretpassword build.keychain
+security default-keychain -s build.keychain
+security unlock-keychain -p mysecretpassword build.keychain
+security set-keychain-settings -t 3600 -u build.keychain
+hr "Importing certs into keychain"
+security import ./Certificates.p12 -k build.keychain -T /usr/bin/productsign -P ""
+hr "Signing Package"
+productsign --sign 'Developer ID Installer: Hugh Bailey (2MMRE5MTB8)' ./OBS.pkg ./$FILENAME
+
+# Move to the folder that travis uses to upload artifacts from
+hr "Moving package to nightly folder for distribution"
+mkdir ../nightly
sudo mv ./$FILENAME ../nightly
obs-studio-18.0.0.tar.xz/CI/before-deploy-win.cmd
Added
+xcopy /e C:\projects\obs-studio\build32\rundir\RelWithDebInfo C:\projects\obs-studio\build\
+robocopy C:\projects\obs-studio\build64\rundir\RelWithDebInfo C:\projects\obs-studio\build\ /E /XC /XN /XO
+7z a build.zip C:\projects\obs-studio\build\*
\ No newline at end of file
obs-studio-18.0.0.tar.xz/CI/before-script-linux.sh
Added
+#!/bin/sh
+set -ex
+
+mkdir build && cd build
+cmake ..
obs-studio-17.0.2.tar.xz/CI/before-script-osx.sh -> obs-studio-18.0.0.tar.xz/CI/before-script-osx.sh
Changed
mkdir build
cd build
-cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9 -DDepsPath=/tmp/obsdeps -DBUILD_BROWSER=ON -DCEF_ROOT_DIR=$PWD/../../cef_binary_3.2883.1540.gedbfb20_macosx64 ..
\ No newline at end of file
+cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9 -DDepsPath=/tmp/obsdeps -DVLCPath=$PWD/../../vlc-master -DBUILD_BROWSER=ON -DCEF_ROOT_DIR=$PWD/../../cef_binary_3.2883.1540.gedbfb20_macosx64 ..
\ No newline at end of file
obs-studio-18.0.0.tar.xz/CI/install-dependencies-linux.sh
Added
+#!/bin/sh
+set -ex
+
+sudo add-apt-repository ppa:kirillshkrogalev/ffmpeg-next -y
+sudo apt-get -qq update
+sudo apt-get install -y \
+ build-essential \
+ checkinstall \
+ cmake \
+ libasound2-dev \
+ libavcodec-ffmpeg-dev \
+ libavdevice-ffmpeg-dev \
+ libavfilter-ffmpeg-dev \
+ libavformat-ffmpeg-dev \
+ libavutil-ffmpeg-dev \
+ libcurl4-openssl-dev \
+ libfontconfig-dev \
+ libfreetype6-dev \
+ libgl1-mesa-dev \
+ libjack-jackd2-dev \
+ libjansson-dev \
+ libpulse-dev \
+ libqt5x11extras5-dev \
+ libspeexdsp-dev \
+ libswresample-ffmpeg-dev \
+ libswscale-ffmpeg-dev \
+ libudev-dev \
+ libv4l-dev \
+ libvlc-dev \
+ libx11-dev \
+ libx264-dev \
+ libxcb-shm0-dev \
+ libxcb-xinerama0-dev \
+ libxcomposite-dev \
+ libxinerama-dev \
+ pkg-config \
+ qtbase5-dev
obs-studio-17.0.2.tar.xz/CI/install-dependencies-osx.sh -> obs-studio-18.0.0.tar.xz/CI/install-dependencies-osx.sh
Changed
-curl -L -O https://s3-us-west-2.amazonaws.com/obs-nightly/Packages.pkg
+# Exit if something fails
+set -e
+
+git fetch --tags
+
+# Leave obs-studio folder
+cd ../
+
+# Install Packages app so we can build a package later
+# http://s.sudre.free.fr/Software/Packages/about.html
+curl -L -O https://s3-us-west-2.amazonaws.com/obs-nightly/Packages.pkg -f --retry 5 -C -
sudo installer -pkg ./Packages.pkg -target /
brew update
#Base OBS Deps
-brew install qt5
+brew install qt5 jack
-curl -L -O https://s3-us-west-2.amazonaws.com/obs-nightly/osx-deps.tar.gz
+# Fetch and untar prebuilt OBS deps that are compatible with older versions of OSX
+curl -L -O https://s3-us-west-2.amazonaws.com/obs-nightly/osx-deps.tar.gz -f --retry 5 -C -
tar -xf ./osx-deps.tar.gz -C /tmp
+# Fetch vlc codebase
+curl -L -o vlc-master.zip https://github.com/videolan/vlc/archive/master.zip -f --retry 5 -C -
+unzip -q ./vlc-master.zip
+
+# Get sparkle
+curl -L -o ./sparkle.tar.bz2 https://github.com/sparkle-project/Sparkle/releases/download/1.16.0/Sparkle-1.16.0.tar.bz2
+mkdir ./sparkle
+tar -xf ./sparkle.tar.bz2 -C ./sparkle
+
# CEF Stuff
-cd ../
-curl -kLO http://opensource.spotify.com/cefbuilds/cef_binary_3.2883.1540.gedbfb20_macosx64.tar.bz2
+curl -kLO http://opensource.spotify.com/cefbuilds/cef_binary_3.2883.1540.gedbfb20_macosx64.tar.bz2 -f --retry 5 -C -
tar -xf ./cef_binary_3.2883.1540.gedbfb20_macosx64.tar.bz2
cd ./cef_binary_3.2883.1540.gedbfb20_macosx64
mkdir build
obs-studio-17.0.2.tar.xz/CI/install/osx/CMakeLists.pkgproj -> obs-studio-18.0.0.tar.xz/CI/install/osx/CMakeLists.pkgproj
Changed
<key>PACKAGE_SCRIPTS</key>
<dict>
<key>POSTINSTALL_PATH</key>
- <dict/>
+ <dict>
+ <key>PATH</key>
+ <string>post-install.sh</string>
+ <key>PATH_TYPE</key>
+ <integer>3</integer>
+ </dict>
<key>PREINSTALL_PATH</key>
<dict/>
<key>RESOURCES</key>
ZW50LVN0eWxlLVR5cGUiIGNvbnRlbnQ9InRleHQvY3NzIj4KPHRp
dGxlPjwvdGl0bGU+CjxtZXRhIG5hbWU9IkdlbmVyYXRvciIgY29u
dGVudD0iQ29jb2EgSFRNTCBXcml0ZXIiPgo8bWV0YSBuYW1lPSJD
- b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjE1MDQuNzYiPgo8c3R5bGUg
+ b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjE1MDQuODEiPgo8c3R5bGUg
dHlwZT0idGV4dC9jc3MiPgo8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5
Pgo8L2JvZHk+CjwvaHRtbD4K
</data>
obs-studio-17.0.2.tar.xz/CI/install/osx/OBSPublicDSAKey.pem -> obs-studio-18.0.0.tar.xz/CI/install/osx/OBSPublicDSAKey.pem
Changed
-----BEGIN PUBLIC KEY-----
-MIIGSDCCBDoGByqGSM44BAEwggQtAoICAQDDTtoCl3zVYY4jq2ZvJhY+jZB23BdR
-k+oTQH0lIUuIBjJR+S8NZqylr4SIGF2S76sCDdpK5P7Waj1y5WyBIJQDCPA7UI1T
-P8UeZgxLazl+oVPnDhUeiEWCNkZIcn746/pPgdoG5KNjb6CUNQ8X+zkUzq6LJ7w9
-Sn02g1FPf0HUlR0D9bx8KweetAZrBGYNP2Mv0RvUSE3TS+t1zJadOp7GsMcoRBxD
-XnJXirBiTjGu3pUZ5bJSLEw+Jm46DdEj0f+SSMpPjgRAG3Pn8ac7U+CVonGHEIRB
-4+yjHTqF9aPtsABIbAeSh63U54yYcmYuF/ioxTNjXXsNGNm5ZAeGq1/o0iT2eesu
-nC6yUYggWSBVZEdTD4uI9iYsYnpjbp+fAUoD53MxTRgKqdOESdtZTJ0HSUqTjngH
-kwzpvxN7WmCpxISzAjs5bknu90DcdP2R4KrJfiJJzAMFp0hmwuy4OaUX0+BWZzvW
-KxCbHsvJL2asHkX4kQpoGVnYmEglH0vOLuK3iJi96jDcGBDGGPO0OXgu6P00iALT
-JF1KylJNnyH0K1a7EbS1QJlF50+zW+okc5Da1iy4vktTP7gPxBHZWeFHPMRZOp1H
-CZeP6Lipf9NpE5dqzMuHLFmxWeKn/7CQ2T9LyeTIajbeGqRsoSII3qEgQd/nDM3k
-NYt6e7dKx6rk6QIhAJ8/wlS8dyJEnvMwVRqn5ER05q7NuHocmGGiX2V/ONLnAoIC
-AQCTFu8RESwHSQ4uR3O0CjlvQKwqEM3Vlv+nyEqYvfqJNAfxrncpV0TF05GvUV7M
-e31solt3eK31qjK1H3AMaD8ToCinSYMLaoyMt0AfGljGK5cNZKXn/xFVM4mq71id
-RzrIfmL2327+kH7wC/8sk7R3FB/mxPV1fRhKuBqG+Y6x9NX7vz57JnIio20OQKCE
-Sn7a18QWHgmt+e+n9R6x7JiVOj+ZTwuPPXpomNB6nPVnQftf3lwB7ug1wJyBxAqy
-NkIhzkAk4RDn4NzhP70ULD80GdS36swCIOg08uTSsYA6FMgrD6JLpmKC4Uha8vPM
-421qxX8Si/Dk3r4one6NUr2WD0sy754MKOCZ5aD8XUB2ylLzfvdSEaGo+G/IyPtC
-o71PMnIStEPXH6GkvzxJv17zvhqQcyKBciqxR7GCQhbwMimp96EPIA3/2UDXQ9UE
-O+/JulJKVEuu4HhWLW8+s+qKhyTyP1dRd0qzLoLj81JA3FcotB1Lncas8mtv+eET
-Z1tKuDy8f4esOh0fuGNrDiMnm3y+cnsa41k4XLDLPrqGbJHxiRTlGwCMLxLEMcFa
-0gjYU3UFFiEvNG0vFWr4h57taLBoyKoyBON+Cmn5hsrKs1J1kTBTc1EvDF5mXjoX
-RhlrPxd/6b5aa12d3xIYofcp70RyPBM1AZ7jfWeSgKhN6AOCAgYAAoICAQClbOeZ
-cnCCsOaZyXp7aiZmDmJ4dtvCRXc+uD+VzRHlg/8X3BYQ01KUMc5/m+fFT7x8w12w
-FEN/txOxTB+NzQBlnRFHWjBOioxHWqAnYLuADP4nZM+1bwaMUBCRUX0MHZbaMMSR
-/dBa45Y9quc4JTV8rpfIzXdw1NZjDmnKYwKQxQ6eD/WymJFNpWKkaniMda0HQVCU
-eBEEpLjW4UE1YUFQgKuIKUdZ1eBxeXHgX6uDpU53reK8gC5ry8xZXryJlcqhKyQ8
-TrDarZgmxhzAvAwPbtCutiOpPaVpCQCdgi4PgA3sAgmdGENXDqTxcSCbCcmCYMzl
-pJLh+giO74OwZMqWvHwHPY5wgZbx9Tnw4JS+gsjl3K3XUeY1+J6cgrFCK/9iaRUx
-7lBroEgQoi+O+yM9ikPeGZYKwgobWslmNuMdYvbZl+hQF+eo7dgnABl+WHLkHogv
-O0wfbENlYECAHXJ/ncyRWoiyd3d/HrZBwMfMFv0hv9JdQ1EjVePXGh9+cDxO0W+Y
-ZJhXsXEmQ82+Pg9cCVywLKdbNWi4qPgwYEKKagq4ack6JHCcwbLMmNTz/PaDZpfP
-wCCxYzVxKksGnV2tb2quAW1/GB+H9FcPSHvE1MMsPhRwAGAm4+aKuL1IvrvLh8fj
-0tZk6dhMjtrBOkZMfnBbSKDKQlcHvXM25yIjgA==
+MIIGPDCCBC4GByqGSM44BAEwggQhAoICAQCZZZ2y7H2GJmMfP4KQihJTJOoiGNUw
+mue6sqMbH+utRykRnSKBZux6R665eRFMpNgrgFO1TLLGbdD2U31KiGtCvFJOmOl3
++QP055BuXjEG36NU7AWEFLAlbDlr/2D3oumq3Ib3iMnnr9RrVztJ2VFOvVio1eWr
+ZxboVwKPK8D6BqsWiv15vbYlJnTC4Fls6ySmdjVBxwoPlTaMu1ysi5DfbIZ93s5u
+aQt1FvXuWtPBWjyVUORcNbcWf49E5R2pV0OSBK95Hw2/wXz4vmj+w92dTePGnVaW
+Me4CoF5PIeZILwp6DCLStX4eW2WG1NChJTC8zeQ/3bMMoGyKM/MadyvrDqMywsKY
+caxkIwHrDKOEdXXGo80dIwZMMLipPA8DKhx5ojphfkeXjIhKSx+49knXT3ED5okE
+Wai7tGUXj/8D8sGh+7b+AVsdujvr4v8WQaZiKUOZ2IIHOg3VLz9T9v0zet1Yt987
+KNymFcp2CHeJ6KnDP/ZGQ6Nl0HsPxUgscsXV+R2FEc8Q1j0Ukkuxnopa0E4/huUu
+gjyRzpXD734qFMDf7LcXca6qNjBor6gVj5sRyRKCpZ+KQfMUlr8jp506ztYSyeJu
+dxJV30tQgztwkbrs02CqOt4Z3Peo6sdht7hWKSPVwmja3tq8/TfUSSoo6wKYN9/w
+Mf3dVeRF8hCzJQIVAJnzuzmzQhCKPiQnl3jh5qGII2XfAoICAQCCVATAff89ceHj
+ROHEbHTQFpVxJ/kRZPfxnU46DSw79Tih7tthV68oakPSOTP3cx/Tga0GwogarZ9N
+F2VVan5w9OQSSewXsr5UDT5bnmJF+h+JB7TMy+sXZBYobUqjlUd5VtKc8RsN86P4
+s7xbK0mA+hfe+27r18JT81/eH3xUfh7UOUGSdMN2Ch9f7RFSMZIgUAZUzu2K3ODp
+hPgtc2QJ8QVAp7GLvQgw8ZUME/ChZslyBIyJvYgUIxfxlgRWYro5pQT7/ngkgdXo
+wlghHKkldwMuY3zaFdhPnFNuEUEtc18ILsbz0+AnagCUd6n+3safskCRqLIHMOY6
+iLBSZPX9hJQhVCqSqz1VNDDww8FNa/fojJ1Lr/TI0I+0Ib2pCiY2LChXUqGY5SLZ
+2KNs5qFsyZP+I0L8YsGwqvUYyFwk7Ok224n0NtaOwqpLCrtXd/i6DaDNiaoJuwJC
+1ELCfaZivorgkC5rhBt2H7qWUAR+EtrFE/gb0k/G5EIhjYql7onGbX+G2re38vQA
+fg1pzguhig2dafP/BxMLZrn1Gg61xzmEYPuS9gclktaf675srv8GVb46VkOxXL+D
+YvTmpJPP7UUOVlmAMCo4j4y09MW3jq9TDp42VTLeZVubyjslGnavlnq1O+ZyXUye
+1FMeby65sIbSHHHwoFnRv3hLSEXI5gOCAgYAAoICAQCUkYnZkPfHfOJZI403xUYP
+CE/bLpkza074Xo6EXElsWRnpQgNTx+JFOvItgj3v0OkIqDin9UredKOwfkiftslV
+jxUVKA6I5kwnGvCpvTpQMLyLjq+VQr+J2D6eId6tV/iajhdu5r4JThU8KllT7Ywb
+NAur34ftLNCVAMRUaDNeEoHfePgderW384e+lbvpmtifmBluammGSxxRtUsdjvJZ
+BFkhaJu86CKxcU7D1lbPVOtV/jaxz6d16VdGcfBdi2LzXZzZtYpT9XGPX3NF+xii
+spAURWsoe11LTRXF+eJhgCm5iIDN3kh1HEQKYKAVpmrcM0aFzk/NpS+tFyU72vaq
+IRSSJw/aa1oELOAakG5oPldc4RcYWl32sbnVwXHO7TZvgTrBSC10o65MAC5CHP/s
+b07heDYAIt7re7szvOYq+c/9zAMAlu3pcO8MqaXYMmybdHBXHQ2b+DdJWHmIUWcX
+CbUzr09vzGkJAvqsXqbmJPr8aixrO75DhT0iDTILLWe/GWK51nf+Tg0pNxVgGyAl
+BqvRqqo7SSDu9FMkwQesFFHhuoHLyEHwVPJ+sMQTNwQcm9c6YuW8EYDRSkeKLWYk
+3fkjG+Pe9uVE8a1taDg3FjSY0UqjUT6XMw+i0Lajyus2L6wFBwrrGM6E4xa6x1CC
+MGjmuSOlPA1umQsToIcO4g==
-----END PUBLIC KEY-----
obs-studio-18.0.0.tar.xz/CI/install/osx/post-install.sh
Added
+#!/usr/bin/env bash
+
+# Fix permissions on CEF
+chmod 744 "/Library/Application Support/obs-studio/plugins/obs-browser/bin/CEF.app/Contents/Info.plist"
+chmod 744 "/Library/Application Support/obs-studio/plugins/obs-browser/bin/CEF.app/Contents/Frameworks/CEF Helper.app/Contents/Info.plist"
obs-studio-18.0.0.tar.xz/CI/osxcert
Added
+(directory)
obs-studio-17.0.2.tar.xz/UI/CMakeLists.txt -> obs-studio-18.0.0.tar.xz/UI/CMakeLists.txt
Changed
project(obs)
+set(ENABLE_WIN_UPDATER FALSE CACHE BOOL "Enable the windows updater")
+
if(DEFINED QTDIR${_lib_suffix})
list(APPEND CMAKE_PREFIX_PATH "${QTDIR${_lib_suffix}}")
elseif(DEFINED QTDIR)
add_definitions(${LIBCURL_DEFINITIONS})
if(WIN32)
+ include_directories(${OBS_JANSSON_INCLUDE_DIRS})
+ include_directories(${BLAKE2_INCLUDE_DIR})
+
set(obs_PLATFORM_SOURCES
platform-windows.cpp
+ win-update/update-window.cpp
+ win-update/win-update.cpp
+ win-update/win-update-helpers.cpp
obs.rc)
+ set(obs_PLATFORM_HEADERS
+ win-update/update-window.hpp
+ win-update/win-update.hpp
+ win-update/win-update-helpers.hpp)
+ set(obs_PLATFORM_LIBRARIES
+ crypt32
+ blake2
+ ${OBS_JANSSON_IMPORT})
+
+ if(ENABLE_WIN_UPDATER)
+ add_definitions(-DENABLE_WIN_UPDATER)
+ endif()
elseif(APPLE)
set(obs_PLATFORM_SOURCES
platform-osx.mm)
qt-wrappers.cpp)
set(obs_HEADERS
+ ${obs_PLATFORM_HEADERS}
obs-app.hpp
platform.hpp
window-main.hpp
forms/OBSBasicSettings.ui
forms/OBSBasicSourceSelect.ui
forms/OBSBasicInteraction.ui
+ forms/OBSUpdate.ui
forms/OBSRemux.ui)
set(obs_QRC
obs-studio-17.0.2.tar.xz/UI/adv-audio-control.cpp -> obs-studio-18.0.0.tar.xz/UI/adv-audio-control.cpp
Changed
#include <QGridLayout>
#include <QLabel>
#include <QSpinBox>
+#include <QComboBox>
#include <QCheckBox>
#include <QSlider>
#include "qt-wrappers.hpp"
+#include "obs-app.hpp"
#include "adv-audio-control.hpp"
#ifndef NSEC_PER_MSEC
volume = new QSpinBox();
forceMono = new QCheckBox();
panning = new QSlider(Qt::Horizontal);
+#if defined(_WIN32) || defined(__APPLE__)
+ monitoringType = new QComboBox();
+#endif
syncOffset = new QSpinBox();
mixer1 = new QCheckBox();
mixer2 = new QCheckBox();
syncOffset->setMaximum(20000);
syncOffset->setValue(int(cur_sync / NSEC_PER_MSEC));
+ int idx;
+#if defined(_WIN32) || defined(__APPLE__)
+ monitoringType->addItem(QTStr("Basic.AdvAudio.Monitoring.None"),
+ (int)OBS_MONITORING_TYPE_NONE);
+ monitoringType->addItem(QTStr("Basic.AdvAudio.Monitoring.MonitorOnly"),
+ (int)OBS_MONITORING_TYPE_MONITOR_ONLY);
+ monitoringType->addItem(QTStr("Basic.AdvAudio.Monitoring.Both"),
+ (int)OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT);
+ int mt = (int)obs_source_get_monitoring_type(source);
+ idx = monitoringType->findData(mt);
+ monitoringType->setCurrentIndex(idx);
+#endif
+
mixer1->setText("1");
mixer1->setChecked(mixers & (1<<0));
mixer2->setText("2");
this, SLOT(panningChanged(int)));
QWidget::connect(syncOffset, SIGNAL(valueChanged(int)),
this, SLOT(syncOffsetChanged(int)));
+#if defined(_WIN32) || defined(__APPLE__)
+ QWidget::connect(monitoringType, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(monitoringTypeChanged(int)));
+#endif
QWidget::connect(mixer1, SIGNAL(clicked(bool)),
this, SLOT(mixer1Changed(bool)));
QWidget::connect(mixer2, SIGNAL(clicked(bool)),
int lastRow = layout->rowCount();
- layout->addWidget(nameLabel, lastRow, 0);
- layout->addWidget(volume, lastRow, 1);
- layout->addWidget(forceMonoContainer, lastRow, 2);
- layout->addWidget(panningContainer, lastRow, 3);
- layout->addWidget(syncOffset, lastRow, 4);
- layout->addWidget(mixerContainer, lastRow, 5);
+ idx = 0;
+ layout->addWidget(nameLabel, lastRow, idx++);
+ layout->addWidget(volume, lastRow, idx++);
+ layout->addWidget(forceMonoContainer, lastRow, idx++);
+ layout->addWidget(panningContainer, lastRow, idx++);
+ layout->addWidget(syncOffset, lastRow, idx++);
+#if defined(_WIN32) || defined(__APPLE__)
+ layout->addWidget(monitoringType, lastRow, idx++);
+#endif
+ layout->addWidget(mixerContainer, lastRow, idx++);
layout->layout()->setAlignment(mixerContainer,
Qt::AlignHCenter | Qt::AlignVCenter);
}
forceMonoContainer->deleteLater();
panningContainer->deleteLater();
syncOffset->deleteLater();
+#if defined(_WIN32) || defined(__APPLE__)
+ monitoringType->deleteLater();
+#endif
mixerContainer->deleteLater();
}
int64_t(milliseconds) * NSEC_PER_MSEC);
}
+void OBSAdvAudioCtrl::monitoringTypeChanged(int index)
+{
+ int mt = monitoringType->itemData(index).toInt();
+ obs_source_set_monitoring_type(source, (obs_monitoring_type)mt);
+}
+
static inline void setMixer(obs_source_t *source, const int mixerIdx,
const bool checked)
{
obs-studio-17.0.2.tar.xz/UI/adv-audio-control.hpp -> obs-studio-18.0.0.tar.xz/UI/adv-audio-control.hpp
Changed
class QSpinBox;
class QCheckBox;
class QSlider;
+class QComboBox;
class OBSAdvAudioCtrl : public QObject {
Q_OBJECT
QPointer<QLabel> labelL;
QPointer<QLabel> labelR;
QPointer<QSpinBox> syncOffset;
+ QPointer<QComboBox> monitoringType;
QPointer<QCheckBox> mixer1;
QPointer<QCheckBox> mixer2;
QPointer<QCheckBox> mixer3;
void downmixMonoChanged(bool checked);
void panningChanged(int val);
void syncOffsetChanged(int milliseconds);
+ void monitoringTypeChanged(int index);
void mixer1Changed(bool checked);
void mixer2Changed(bool checked);
void mixer3Changed(bool checked);
obs-studio-17.0.2.tar.xz/UI/data/locale/ar-SA.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/ar-SA.ini
Changed
Top="أعلى"
Bottom="أسفل"
+
QuickTransitions.SwapScenes="التبديل بين مشهدي المعاينة و الاخراج بعد عملية الانتقال"
QuickTransitions.SwapScenesTT="يقوم بتبديل مشهد المعاينة مع مشهد الاخراج بعد عملية الانتقال بين المشاهد (اذا كان مشهد الاخراج الاصلي لازال موجوداً) \n هذا لن يقوم بالتراجع عن اي تغييرات قمت بها على مشهد الاخراج الأصلي."
QuickTransitions.DuplicateScene="استنساخ المشهد"
ConfirmRemove.Title="تأكيد الإزالة"
ConfirmRemove.Text="هل أنت متأكد من رغبتك في إزالة '$1' ?"
+
Output.ConnectFail.Title="فشل في الاتصال"
Output.ConnectFail.BadPath="مسار أو رابط الاتصال غير صالح. الرجاء التحقق من الإعدادات للتحقق من كونه صالح."
Output.ConnectFail.ConnectFailed="فشل الاتصال بالسيرفر"
Deinterlacing.Discard="تجاهل"
+
Basic.Main.AddSceneDlg.Title="أضف المشهد"
Basic.Main.AddSceneDlg.Text="الرجاء إدخال اسم المشهد"
obs-studio-17.0.2.tar.xz/UI/data/locale/bg-BG.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/bg-BG.ini
Changed
+
TitleBar.Profile="Профил"
TitleBar.Scenes="Сцени"
ConfirmRemove.Title="Потвърди премахване"
ConfirmRemove.Text="Наистина ли искате да премахнете \"$1\"?"
+
Output.ConnectFail.Title="Неуспешно свързване"
Output.ConnectFail.BadPath="Невалиден път или URL. Проверете дали настройките ви са валидни."
Output.ConnectFail.ConnectFailed="Неуспешна връзка със сървъра"
+
Basic.Main.AddSceneDlg.Title="Добави сцена"
Basic.Main.AddSceneDlg.Text="Моля, въведете името на сцената"
obs-studio-17.0.2.tar.xz/UI/data/locale/ca-ES.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/ca-ES.ini
Changed
Import="Importa"
Export="Exporta"
+Updater.Title="Nova actualització disponible"
+Updater.Text="Hi ha una nova actualització disponible:"
+Updater.UpdateNow="Actualitza ara"
+Updater.RemindMeLater="Recordeu-m'ho més tard"
+Updater.Skip="Omet la versió"
+Updater.Running.Title="Programa actualment actiu"
+Updater.Running.Text="Les sortides estan actives actualment, apagueu qualsevol sortida activa abans d'intentar actualitzar"
+Updater.NoUpdatesAvailable.Title="No hi ha actualitzacions disponibles"
+Updater.NoUpdatesAvailable.Text="Actualment no hi ha actualitzacions disponibles"
+Updater.FailedToLaunch="No s'han pogut executar l'actualitzador"
+Updater.GameCaptureActive.Title="Captura de joc activa"
+Updater.GameCaptureActive.Text="La llibreria de captura de jocs està actualment en ús. Tanqueu qualsevol joc/programa que estigui sent capturat (o reinicieu Windows) i proveu-ho de nou."
+
QuickTransitions.SwapScenes="Canvia la vista prèvia i sortida d'escenes després de la transició"
QuickTransitions.SwapScenesTT="Canvia la vista prèvia i sortida d'escenes després de la transició (si encara existeix l'escena original de la sortida). \nAixò no desfarà qualsevol canvi que pugui haver fet a l'escena original de la sortida."
QuickTransitions.DuplicateScene="Duplica l'escena"
-QuickTransitions.DuplicateSceneTT="Al editar la misma escena, permite la edición transformar/visibilidad de fuentes sin modificar las salida.\nPer editar les propietats de les fonts sense modificar la sortida, activi 'Duplicar Fonts'.\nCanviant aquest valor restablirà l'escena actual de sortida (si encara existeix)."
+QuickTransitions.DuplicateSceneTT="En editar la mateixa escena, permet editar la visibilitat i transformació de les fonts sense modificar la sortida.\nPer editar les propietats de les fonts sense modificar la sortida, activeu «Duplicar Fonts».\nSi canvieu aquest valor es restablirà l'escena actual de la sortida (si encara existeix)."
QuickTransitions.EditProperties="Duplica les fonts"
-QuickTransitions.EditPropertiesTT="En editar la mateixa escena, permeti editar propietats de fonts sense modificar la sortida.\n Això només es pot utilitzar si està activat 'Duplicar l'escena'.\nCertes fonts (tals com a fonts de captura o els mitjans de comunicació) no són compatibles amb això i no es poden editar per separat.\nCanviant aquest valor restablirà l'escena actual de sortida (si encara existeix).\n\nAdvertiment: com es duplicaran les fonts, això requerirà un extra de recursos del sistema i de vídeo."
+QuickTransitions.EditPropertiesTT="En editar la mateixa escena, permet editar les propietats de les fonts sense modificar la sortida.\nAixò només es pot utilitzar si s'ha activat «Duplicar l'escena».\nAlgunes fonts (com dispositius de captura o mèdia) no ho permeten i no es poden editar per separat.\nSi canvieu aquest valor es restablirà l'escena actual de la sortida (si encara existeix).\n\nAtenció: com que es duplicaran les fonts, poden ser necessaris més recursos del sistema o de vídeo."
QuickTransitions.HotkeyName="Transició Ràpida: %1"
Basic.AddTransition="Afegir transició configurable"
ConfirmRemove.Text="Esteu segur que voleu suprimir «$1»?"
ConfirmRemove.TextMultiple="¿Segur que vols esborrar %1 elements?"
+Output.StartStreamFailed="No s'ha pogut iniciar la transmissió"
+Output.StartRecordingFailed="No s'ha pogut iniciar la gravació"
+Output.StartReplayFailed="No s'ha pogut iniciar la memòria intermèdia de reproducció"
+Output.StartFailedGeneric="Error en iniciar la sortida. Comproveu el registre per més detalls.\n\nAvís: Si utilitzeu els codificadors NVENC o AMD, assegureu-vos que els controladors de vídeo estan actualitzats."
+
Output.ConnectFail.Title="Error en connectar"
Output.ConnectFail.BadPath="Ruta o adreça URL no vàlida. Si us plau, comproveu la configuració per confirmar que són vàlids."
Output.ConnectFail.ConnectFailed="No ha pogut connectar al servidor"
Deinterlacing.TopFieldFirst="Camp superior primer"
Deinterlacing.BottomFieldFirst="Camp inferior primer"
+VolControl.SliderUnmuted="Control lliscant del volum per '%1': %2"
+VolControl.SliderMuted="Control lliscant del volum per '%1': %2 (silenciat)"
+VolControl.Mute="Silencia '%1'"
+VolControl.Properties="Propietats per '%1'"
+
Basic.Main.AddSceneDlg.Title="Afegeix una escena"
Basic.Main.AddSceneDlg.Text="Introduïu el nom de l'escena"
Basic.Settings.General="General"
Basic.Settings.General.Theme="Tema"
Basic.Settings.General.Language="Llengua"
+Basic.Settings.General.EnableAutoUpdates="Comprova si hi ha actualitzacions automàticament a l'inici"
Basic.Settings.General.WarnBeforeStartingStream="Mostra diàleg de confirmació quan s'iniciï una transmissió"
Basic.Settings.General.WarnBeforeStoppingStream="Mostra diàleg de confirmació quan s'aturi una transmissió"
+Basic.Settings.General.Projectors="Projectors"
Basic.Settings.General.HideProjectorCursor="Amaga el cursor sobre projectors"
Basic.Settings.General.ProjectorAlwaysOnTop="Projectors sempre en la part superior"
Basic.Settings.General.Snapping="Ajustament d'alineació de la font"
Basic.Settings.General.SnapDistance="Ajusta la sensibilitat"
Basic.Settings.General.RecordWhenStreaming="Enregistra automàticament quan es transmet"
Basic.Settings.General.KeepRecordingWhenStreamStops="Mantenir l'enregistrament quan s'atura la transmissió"
-Basic.Settings.General.SysTrayEnabled="Activar icona a la safata del sistema"
+Basic.Settings.General.ReplayBufferWhileStreaming="Inicia la reproducció de la memòria intermèdia automàticament durant la transmissió"
+Basic.Settings.General.KeepReplayBufferStreamStops="Mantén activa la memòria intermèdia de reproducció quan la transmissió s'aturi"
+Basic.Settings.General.SysTray="Safata del sistema"
Basic.Settings.General.SysTrayWhenStarted="Minimitzar a la safata del sistema en iniciar"
+Basic.Settings.General.SystemTrayHideMinimize="Minimitza sempre a la safata del sistema en lloc de la barra de tasques"
+Basic.Settings.General.SaveProjectors="Desa els projectors en sortir"
Basic.Settings.Stream="Directe"
Basic.Settings.Stream.StreamType="Tipus de directe"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="Codificador d'àudio"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="Configuració de codificador d'àudio (si escau)"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="Configuració del convertidor (si escau)"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="Interval de fotogrames clau (fotogrames)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="Mostra tots els codificadors (encara que siguin potencialment incompatibles)"
FilenameFormatting.completer="%CCYY-%MM-%DD %hh-%mm-%ss\n%YY-%MM-%DD %hh-%mm-%ss\n%Y-%m-%d %H-%M-%S\n%y-%m-%d %H-%M-%S\n%a %Y-%m-%d %H-%M-%S\n%A %Y-%m-%d %H-%M-%S\n%Y-%b-%d %H-%M-%S\n%Y-%B-%d %H-%M-%S\n%Y-%m-%d %I-%M-%S-%p\n%Y-%m-%d %H-%M-%S-%z\n%Y-%m-%d %H-%M-%S-%Z"
Basic.Settings.Advanced.Video.ColorRange="Gamma de color YUV"
Basic.Settings.Advanced.Video.ColorRange.Partial="Parcial"
Basic.Settings.Advanced.Video.ColorRange.Full="Màxima"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Dispositiu de monitorització d'àudio"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Per defecte"
Basic.Settings.Advanced.StreamDelay="Retard del directe"
Basic.Settings.Advanced.StreamDelay.Duration="Durada (en segons)"
Basic.Settings.Advanced.StreamDelay.Preserve="Preservar el punt de tall (augmenta retard) quan s'estigui reconnectant"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Ús de memòria estimat: %1 MB"
Basic.Settings.Advanced.Network="Xarxa"
Basic.Settings.Advanced.Network.BindToIP="Enllaçar amb"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="Activa el nou codi de xarxa"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="Mode de baixa latència"
Basic.AdvAudio="&Propietats avançades d'àudio"
Basic.AdvAudio.Name="Nom"
Basic.AdvAudio.Mono="Mescla a Mono"
Basic.AdvAudio.Panning="Balanç"
Basic.AdvAudio.SyncOffset="Correcció de sincronització (ms)"
+Basic.AdvAudio.Monitoring="Monitorització d'àudio"
+Basic.AdvAudio.Monitoring.None="Monitorització desactivada"
+Basic.AdvAudio.Monitoring.MonitorOnly="Només monitorizació (silencia la sortida)"
+Basic.AdvAudio.Monitoring.Both="Monitorització i sortida"
Basic.AdvAudio.AudioTracks="Pistes"
Basic.Settings.Hotkeys="Dreceres de teclat"
Basic.Hotkeys.SelectScene="Canviar a escena"
Basic.SystemTray.Show="Mostra"
-Basic.SystemTray.Hide="Oculta"
+Basic.SystemTray.Hide="Amaga"
Basic.SystemTray.Message.Reconnecting="Desconnectat. Tornant a connectar..."
OutputWarnings.NoTracksSelected="Heu de seleccionar almenys una cançó"
OutputWarnings.MultiTrackRecording="Advertiment: Alguns formats (com FLV) no suporten múltiples cançons per gravació"
+OutputWarnings.MP4Recording="Advertència: Els enregistraments desats en MP4 seran irrecuperables si l'arxiu no va poder finalitzar (p.ex. com a resultat de BSODs, pèrdues de potència, etc.). Si voleu enregistrar diverses pistes d'àudio utilitzi MKV i multiplexeu l'enregistrament a MP4 després que acabi (Fitxer-> Multiplexació d'enregistraments)"
obs-studio-17.0.2.tar.xz/UI/data/locale/cs-CZ.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/cs-CZ.ini
Changed
Import="Importovat"
Export="Exportovat"
+Updater.Title="Aktualizace"
+Updater.Text="K dispozici je nová verze:"
+Updater.UpdateNow="Aktualizovat nyní"
+Updater.RemindMeLater="Upozornit později"
+Updater.Skip="Přeskočit verzi"
+Updater.Running.Title="Program je stále aktivní"
+Updater.Running.Text="Některé výstupy jsou stále aktivní, zastavte je, prosím, před další pokusem o aktualizaci"
+Updater.NoUpdatesAvailable.Title="Žádná aktualizace"
+Updater.NoUpdatesAvailable.Text="Není dostupná žádná novější verze"
+Updater.FailedToLaunch="Nepodařilo se spustit aktualizátor"
+Updater.GameCaptureActive.Title="Snímání hry"
+Updater.GameCaptureActive.Text="Knihovna pro snímání her je aktivní. Ukončete prosím všechny snímané hry/programy (nebo restartujte Windows) a zkuste to znovu."
+
QuickTransitions.SwapScenes="Prohodit scény náhledu a výstupu po přechodu"
QuickTransitions.SwapScenesTT="Prohodí scény náhledu a výstupu po přechodu (pokud originální výstupní scéna stále existuje).\nTato funkce nevrátí provedené změny, které byly provedeny v originální scéně výstupu."
QuickTransitions.DuplicateScene="Duplikovat scénu"
ConfirmRemove.Text="Opravdu si přejete odebrat '$1'?"
ConfirmRemove.TextMultiple="Opravdu si přejete odebrat %1 položky ?"
+Output.StartStreamFailed="Chyba při spouštění vysílání"
+Output.StartRecordingFailed="Chyba při spouštění nahrávání"
+Output.StartReplayFailed="Chyba při spouštění nahrávání do paměti"
+Output.StartFailedGeneric="Nastala chyba při začátku nahrávání. Zkontrolujte, prosím, textový záznam pro další podrobnosti.\n\nPoznámka: Pokud používáte enkodér NVENC či AMD, zkontrolujte zda používáte aktuální verzi grafického ovladače."
+
Output.ConnectFail.Title="Spojení se nezdařilo"
Output.ConnectFail.BadPath="Chybná cesta nebo adresa připojení. Zkontrolujte, prosím, správnost svých nastavení."
Output.ConnectFail.ConnectFailed="K serveru se nepodařilo připojit"
Deinterlacing.TopFieldFirst="Svrchní řádek dříve"
Deinterlacing.BottomFieldFirst="Spodní řádek dříve"
+VolControl.SliderUnmuted="Posuvník hlasitosti pro '%1': %2"
+VolControl.SliderMuted="Posuvník hlasitosti pro '%1': %2 (ztlumeno)"
+VolControl.Mute="Ztlumit '%1'"
+VolControl.Properties="Vlastnosti pro \"%1\""
+
Basic.Main.AddSceneDlg.Title="Přidat scénu"
Basic.Main.AddSceneDlg.Text="Prosím, zadejte jméno scény"
Basic.Settings.General="Hlavní"
Basic.Settings.General.Theme="Vzhled"
Basic.Settings.General.Language="Jazyk"
+Basic.Settings.General.EnableAutoUpdates="Automaticky kontrolovat aktualizace při spuštění"
Basic.Settings.General.WarnBeforeStartingStream="Vyžadovat potvrzení pro spuštění vysílání"
Basic.Settings.General.WarnBeforeStoppingStream="Vyžadovat potvrzení pro ukončení vysílání"
+Basic.Settings.General.Projectors="Projektory"
Basic.Settings.General.HideProjectorCursor="Skrýt kurzor přes projektor"
Basic.Settings.General.ProjectorAlwaysOnTop="Zobrazovat projektor vždy navrchu"
Basic.Settings.General.Snapping="Přichycování zdrojů"
Basic.Settings.General.SnapDistance="Citlivost přichycení"
Basic.Settings.General.RecordWhenStreaming="Automaticky nahrávat při vysílání"
Basic.Settings.General.KeepRecordingWhenStreamStops="Pokračovat v nahrávání i po zastavení vysílání"
-Basic.Settings.General.SysTrayEnabled="Zobrazit ikonu v oznamovací oblasti"
+Basic.Settings.General.ReplayBufferWhileStreaming="Automaticky zapnout záznam do paměti se začátkem vysílání"
+Basic.Settings.General.KeepReplayBufferStreamStops="Ponechat záznam do paměti aktivní i po ukončení vysílání"
+Basic.Settings.General.SysTray="Systémová lišta"
Basic.Settings.General.SysTrayWhenStarted="Minimalizovat do systémové lišty při spuštění"
+Basic.Settings.General.SystemTrayHideMinimize="Vždy minimalizovat do systémové lišty místo hlavního panelu"
+Basic.Settings.General.SaveProjectors="Při ukončení uložit projektory"
Basic.Settings.Stream="Vysílání"
Basic.Settings.Stream.StreamType="Typ vysílání"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="Enkodér zvuku"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="Nastavení enkodéru zvuku (pokud existuje)"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="Nastavení směšovače (pokud existuje)"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="Interval klíčových snímků (snímky)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="Zobrazit všechny kodeky (i když je možné, že nejsou kompatibilní)"
FilenameFormatting.completer="%CCYY-%MM-%DD %hh-%mm-%ss\n%YY-%MM-%DD %hh-%mm-%ss\n%Y-%m-%d %H-%M-%S\n%y-%m-%d %H-%M-%S\n%a %Y-%m-%d %H-%M-%S\n%A %Y-%m-%d %H-%M-%S\n%Y-%b-%d %H-%M-%S\n%Y-%B-%d %H-%M-%S\n%Y-%m-%d %I-%M-%S-%p\n%Y-%m-%d %H-%M-%S-%z\n%Y-%m-%d %H-%M-%S-%Z"
Basic.Settings.Advanced.Video.ColorRange="Oblast barev YUV"
Basic.Settings.Advanced.Video.ColorRange.Partial="Částečné"
Basic.Settings.Advanced.Video.ColorRange.Full="Plné"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Zařízení pro monitorování zvuku"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Výchozí"
Basic.Settings.Advanced.StreamDelay="Zpoždění vysílání"
Basic.Settings.Advanced.StreamDelay.Duration="Délka (vteřiny)"
Basic.Settings.Advanced.StreamDelay.Preserve="Zachovat zpoždění při obnovení spojení (zvýšení zpoždění)"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Přibližné využití paměti: %1 MB"
Basic.Settings.Advanced.Network="Síť"
Basic.Settings.Advanced.Network.BindToIP="Svázat s adresou"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="Použít nový síťový kód"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="Režim nízké odezvy"
Basic.AdvAudio="Rozšířené vlastnosti zvuku"
Basic.AdvAudio.Name="Název"
Basic.AdvAudio.Mono="Převést na Mono"
Basic.AdvAudio.Panning="Pozicování"
Basic.AdvAudio.SyncOffset="Zpoždění synchronizace (ms)"
+Basic.AdvAudio.Monitoring="Monitorování zvuku"
+Basic.AdvAudio.Monitoring.None="Monitorování vypnuto"
+Basic.AdvAudio.Monitoring.MonitorOnly="Pouhé monitorování (ztlumit výstup)"
+Basic.AdvAudio.Monitoring.Both="Monitorovat a odesílat na výstup"
Basic.AdvAudio.AudioTracks="Stopy"
Basic.Settings.Hotkeys="Zkratky"
OutputWarnings.NoTracksSelected="Musíte vybrat alespoň jednu stopu"
OutputWarnings.MultiTrackRecording="Varování: Některé formáty (např. FLV) nepodporují více zvukových stop na nahrávku"
+OutputWarnings.MP4Recording="Varování: Nahrávky uložené v MP4 nebude možné obnovit, pokud soubor nemohl být dokončen (např. po BSOD, výpadku napájení atp.). Pokud chcete nahrávat více zvukových stop, promyslete použití MKV a poté převodení do MP4 (Soubor -> Převést nahrávky)"
obs-studio-17.0.2.tar.xz/UI/data/locale/da-DK.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/da-DK.ini
Changed
Import="Importér"
Export="Eksportér"
+Updater.Title="Ny opdatering tilgængelig"
+Updater.Text="Der er en ny opdatering tilgængelig:"
+Updater.UpdateNow="Opdater nu"
+Updater.RemindMeLater="Påmind mig senere"
+Updater.Skip="Spring versionen over"
+Updater.Running.Title="Program er aktivt i øjeblikket"
+Updater.Running.Text="Outputs er aktive i øjeblikket. Luk venligst alle aktive outputs før forsøg på opdatering"
+Updater.NoUpdatesAvailable.Title="Ingen opdateringer tilgængelige"
+Updater.NoUpdatesAvailable.Text="Ingen opdateringer er tilgængelige i øjeblikket"
+Updater.FailedToLaunch="Kunne ikke starte opdatering"
+Updater.GameCaptureActive.Title="Spil capture aktiv"
+Updater.GameCaptureActive.Text="Spil capture fangstbibliotek er i brug i øjeblikket. Luk venligst alle spil/programmer der bliver captured (eller genstart windows) og prøv igen."
+
QuickTransitions.SwapScenes="Byt om på forhåndsvisning/output scener efter overgang"
QuickTransitions.SwapScenesTT="Ombytter uddrag- og output-scener efter omskiftning (hvis oprindelige output-scene stadig eksisterer).\nDette vil ikke omgøre eventuelle ændringer, der måtte været udført på den oprindelige output-scene."
QuickTransitions.DuplicateScene="Dupliker scene"
ConfirmRemove.Text="Er du sikker på du ønsker at fjerne '$1'?"
ConfirmRemove.TextMultiple="Er du sikker på at du vil fjerne %1 elementer?"
+Output.StartStreamFailed="Kunne ikke starte streaming"
+Output.StartRecordingFailed="Kunne ikke begynde optagelsen"
+Output.StartReplayFailed="Kunne ikke starte replay buffer"
+Output.StartFailedGeneric="Start af output mislykkedes. Kontroller venligst loggen for oplysninger.\n\nBemærk: Hvis du bruger NVENC eller AMD encoder, så sørg for at dine video drivere er opdateret."
+
Output.ConnectFail.Title="Kunne ikke oprette forbindelse"
Output.ConnectFail.BadPath="Ugyldig sti eller forbindelses URL. Kontroller indstillinger for at bekræfte, at de er gyldige."
Output.ConnectFail.ConnectFailed="Kunne ikke forbinde til server"
UpdateAvailable="Ny opdatering tilgængelig"
UpdateAvailable.Text="Version %1.%2.%3 er nu tilgængelig. <a href='%4'>Klik her for at downloade</a>"
-Basic.DesktopDevice1="Desktop lyd"
-Basic.DesktopDevice2="Desktop lyd 2"
+Basic.DesktopDevice1="Skrivebordslyd"
+Basic.DesktopDevice2="Skrivebordslyd 2"
Basic.AuxDevice1="Mic/Aux"
Basic.AuxDevice2="Mic/Aux 2"
Basic.AuxDevice3="Mic/Aux 3"
Deinterlacing.TopFieldFirst="Øverste felt først"
Deinterlacing.BottomFieldFirst="Nederste felt først"
+
Basic.Main.AddSceneDlg.Title="Tilføje scene"
Basic.Main.AddSceneDlg.Text="Angiv navnet på scene"
Basic.MainMenu.Edit.Order="Rækkefølge (&O)"
Basic.MainMenu.Edit.Order.MoveUp="Flyt Op (&U)"
Basic.MainMenu.Edit.Order.MoveDown="Flyt Ned (&D)"
-Basic.MainMenu.Edit.Order.MoveToTop="Flyt til &Toppen"
+Basic.MainMenu.Edit.Order.MoveToTop="Flyt til &toppen"
Basic.MainMenu.Edit.Order.MoveToBottom="Flyt til &Bunden"
Basic.MainMenu.Edit.AdvAudio="&Avancerede lydegenskaber"
Basic.Settings.General="Generelt"
Basic.Settings.General.Theme="Tema"
Basic.Settings.General.Language="Sprog"
+Basic.Settings.General.EnableAutoUpdates="Automatisk søgning efter opdateringer ved opstart"
Basic.Settings.General.WarnBeforeStartingStream="Vis bekræftelses-dialog ved opstart af stream"
Basic.Settings.General.WarnBeforeStoppingStream="Vis bekræftelses-dialog ved afslutning af stream"
+Basic.Settings.General.Projectors="Projektorer"
Basic.Settings.General.HideProjectorCursor="Skjul markør over projektorer"
Basic.Settings.General.ProjectorAlwaysOnTop="Hav altid projektorer øverst"
Basic.Settings.General.Snapping="Kilde justeringsfastgørelse"
Basic.Settings.General.SnapDistance="Fastgørings-følsomhed"
Basic.Settings.General.RecordWhenStreaming="Optag automatisk ved streaming"
Basic.Settings.General.KeepRecordingWhenStreamStops="Bliv ved med at optage når stream stopper"
-Basic.Settings.General.SysTrayEnabled="Aktiver proceslinje-ikon"
+Basic.Settings.General.ReplayBufferWhileStreaming="Start automatisk replay buffer ved streaming"
+Basic.Settings.General.KeepReplayBufferStreamStops="Hold replay buffer aktiv når stream stopper"
+Basic.Settings.General.SysTray="Processlinjen"
Basic.Settings.General.SysTrayWhenStarted="Minimer til proceslinjen ved start"
+Basic.Settings.General.SystemTrayHideMinimize="Minimer altid til processlinjen i stedet for værktøjslinjen"
+Basic.Settings.General.SaveProjectors="Gem projektorer ved afslutning"
Basic.Settings.Stream="Stream"
Basic.Settings.Stream.StreamType="Streamtype"
Basic.Settings.Output.Adv.Audio.Track2="Spor 2"
Basic.Settings.Output.Adv.Audio.Track3="Spor 3"
Basic.Settings.Output.Adv.Audio.Track4="Spor 4"
+Basic.Settings.Output.Adv.Audio.Track5="Sport 5"
+Basic.Settings.Output.Adv.Audio.Track6="Spor 6"
Basic.Settings.Output.Adv.Recording="Optagelse"
Basic.Settings.Output.Adv.Recording.Type="Type"
Basic.Settings.Audio="Lyd"
Basic.Settings.Audio.SampleRate="Sample Rate"
Basic.Settings.Audio.Channels="Kanaler"
-Basic.Settings.Audio.DesktopDevice="Desktop lydenhed"
-Basic.Settings.Audio.DesktopDevice2="Desktop lydenhed 2"
+Basic.Settings.Audio.DesktopDevice="Skrivebord lydenhed"
+Basic.Settings.Audio.DesktopDevice2="Skrivebord lydenhed 2"
Basic.Settings.Audio.AuxDevice="Mic/Auxiliary lydenhed"
Basic.Settings.Audio.AuxDevice2="Mic/Auxiliary lydenhed 2"
Basic.Settings.Audio.AuxDevice3="Mic/Auxiliary lydenhed 3"
Basic.Settings.Advanced.Video.ColorRange="YUV farveområde"
Basic.Settings.Advanced.Video.ColorRange.Partial="Delvis"
Basic.Settings.Advanced.Video.ColorRange.Full="Fuld"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Lyd overvågningsenhed"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Standard"
Basic.Settings.Advanced.StreamDelay="Stream forsinkelse"
Basic.Settings.Advanced.StreamDelay.Duration="Varighed (sekunder)"
Basic.Settings.Advanced.StreamDelay.Preserve="Bevar afskæringspunkt (forøg forsinkelse) ved forbindelsesgendannelse"
Basic.AdvAudio.Mono="Nedmix til Mono"
Basic.AdvAudio.Panning="Panorering"
Basic.AdvAudio.SyncOffset="Synkr-forskydning (ms)"
+Basic.AdvAudio.Monitoring="Lydovervågning"
+Basic.AdvAudio.Monitoring.None="Overvågning fra"
+Basic.AdvAudio.Monitoring.MonitorOnly="Kun overvågning (mute output)"
+Basic.AdvAudio.Monitoring.Both="Overvåg og output"
Basic.AdvAudio.AudioTracks="Spor"
Basic.Settings.Hotkeys="Genvejstaster"
obs-studio-17.0.2.tar.xz/UI/data/locale/de-DE.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/de-DE.ini
Changed
Import="Importieren"
Export="Exportieren"
+Updater.Title="Neues Update verfügbar"
+Updater.Text="Es ist ein neues Update verfügbar:"
+Updater.UpdateNow="Jetzt updaten"
+Updater.RemindMeLater="Später erinnern"
+Updater.Skip="Version überspringen"
+Updater.Running.Title="Programm derzeit aktiv"
+Updater.Running.Text="Ausgänge sind derzeit aktiv. Bitte beenden Sie alle aktiven Ausgänge, bevor Sie versuchen OBS zu aktualisieren."
+Updater.NoUpdatesAvailable.Title="Keine Updates verfügbar"
+Updater.NoUpdatesAvailable.Text="Zurzeit sind keine Updates verfügbar"
+Updater.FailedToLaunch="Konnte den Updater nicht starten"
+Updater.GameCaptureActive.Title="Spielaufnahme aktiv"
+Updater.GameCaptureActive.Text="Spielaufnahme Hook Bibliothek wird zurzeit verwendet. Bitte schließen Sie alle derzeitigen Spiele / Programme die aufgenommen werden (oder starten Sie Windows neu) und versuchen Sie es erneut."
+
QuickTransitions.SwapScenes="Tausche Vorschau/Ausgabe-Szenen nach dem Übergang"
QuickTransitions.SwapScenesTT="Vertauscht die Vorschau- und Ausgabe-Szenen nach dem Übergang (falls die ursprüngliche Ausgabe-Szene noch vorhanden ist).\nEventuelle Änderungen an der original Ausgabe-Szene werden hierbei nicht rückgängig gemacht."
QuickTransitions.DuplicateScene="Dupliziere Szene"
ConfirmRemove.Text="Sind Sie sicher, dass Sie '$1' entfernen möchten?"
ConfirmRemove.TextMultiple="Sind Sie sicher, dass Sie %1 Elemente löschen möchten?"
+Output.StartStreamFailed="Fehler beim Start des Streams"
+Output.StartRecordingFailed="Fehler beim Starten der Aufnahme"
+Output.StartReplayFailed="Fehler beim Starten des Replaypuffers"
+Output.StartFailedGeneric="Start der Ausgabe fehlgeschlagen. Bitte überprüfen Sie die Logdatei für Details.\n\nHinweis: Wenn Sie die NVENC- oder AMD-Encoder verwenden, stellen Sie sicher, dass Ihre Videotreiber aktuell sind."
+
Output.ConnectFail.Title="Verbindung fehlgeschlagen"
Output.ConnectFail.BadPath="Ungültiger Pfad oder Verbindungs-URL. Bitte überprüfen Sie Ihre Einstellungen und stellen Sie sicher, dass diese korrekt sind."
Output.ConnectFail.ConnectFailed="Verbindung zum Server fehlgeschlagen"
Deinterlacing.TopFieldFirst="Oberes Feld zuerst"
Deinterlacing.BottomFieldFirst="Unteres Feld zuerst"
+VolControl.SliderUnmuted="Lautstärke-Schieberegler für '%1': %2"
+VolControl.SliderMuted="Lautstärke-Schieberegler für '%1': %2 (derzeit stumm geschaltet)"
+VolControl.Mute="'%1' stumm schalten"
+VolControl.Properties="Eigenschaften von '%1'"
+
Basic.Main.AddSceneDlg.Title="Szene hinzufügen"
Basic.Main.AddSceneDlg.Text="Bitte geben Sie einen Namen für die Szene ein"
Basic.Settings.General="Allgemein"
Basic.Settings.General.Theme="Motiv"
Basic.Settings.General.Language="Sprache"
+Basic.Settings.General.EnableAutoUpdates="Beim Start nach Updates suchen"
Basic.Settings.General.WarnBeforeStartingStream="Bestätigungsdialog beim Streamstart anzeigen"
Basic.Settings.General.WarnBeforeStoppingStream="Bestätigungsdialog beim Streamstop anzeigen"
+Basic.Settings.General.Projectors="Projektoren"
Basic.Settings.General.HideProjectorCursor="Mauszeiger über Projektoren verstecken"
Basic.Settings.General.ProjectorAlwaysOnTop="Projektoren immer im Vordergrund anzeigen"
Basic.Settings.General.Snapping="Quellenausrichtung"
Basic.Settings.General.CenterSnapping="Quellen zur horizontalen und vertikalen Mitte ausrichten"
Basic.Settings.General.SourceSnapping="Quellen an anderen Quellen ausrichten"
Basic.Settings.General.SnapDistance="Ausrichtungsempfindlichkeit"
-Basic.Settings.General.RecordWhenStreaming="Stream automatisch aufnehmen"
+Basic.Settings.General.RecordWhenStreaming="Livestream automatisch aufnehmen"
Basic.Settings.General.KeepRecordingWhenStreamStops="Weiter aufnehmen, wenn der Livestream stoppt"
-Basic.Settings.General.SysTrayEnabled="Symbol in der Taskleiste aktivieren"
-Basic.Settings.General.SysTrayWhenStarted="Beim Start zur Taskleiste minimieren"
+Basic.Settings.General.ReplayBufferWhileStreaming="Replaypuffer automatisch starten, beim Streamen"
+Basic.Settings.General.KeepReplayBufferStreamStops="Replaypuffer weiter aktiv lassen, wenn der Livestream stoppt"
+Basic.Settings.General.SysTray="Infobereich"
+Basic.Settings.General.SysTrayWhenStarted="Beim Start zum Infobereich minimieren"
+Basic.Settings.General.SystemTrayHideMinimize="Immer zum Infobereich. statt zur Taskleiste minimieren"
+Basic.Settings.General.SaveProjectors="Projektoren beim Beenden speichern"
Basic.Settings.Stream="Stream"
Basic.Settings.Stream.StreamType="Stream Typ"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="Audio-Codierer"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="Audio Codierer-Einstellungen (falls gewünscht)"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="Muxer Einstellungen (falls vorhanden)"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="Keyframeintervall (Frames)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="Zeige alle Codecs (auch wenn möglicherweise nicht kompatibel)"
FilenameFormatting.completer="%DD-%MM-%CCYY %hh-%mm-%ss\n%DD-%MM-%YY %hh-%mm-%ss\n%d-%m-%Y %H-%M-%S\n%d-%m-%y %H-%M-%S\n%a %d-%m-%Y %H-%M-%S\n%A %d-%m-%Y %H-%M-%S\n%d-%b-%Y %H-%M-%S\n%d-%B-%Y %H-%M-%S"
Basic.Settings.Advanced.Video.ColorRange="YUV Farbbereich"
Basic.Settings.Advanced.Video.ColorRange.Partial="Begrenzt"
Basic.Settings.Advanced.Video.ColorRange.Full="Voll"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Audiomonitoringgerät"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Standard"
Basic.Settings.Advanced.StreamDelay="Stream-Verzögerung"
Basic.Settings.Advanced.StreamDelay.Duration="Dauer (Sekunden)"
Basic.Settings.Advanced.StreamDelay.Preserve="Lückenloses Wiederverbinden (erhöht Verzögerung, um Videoverlust zu vermeiden)"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Geschätzte Speichernutzung: %1 MB"
Basic.Settings.Advanced.Network="Netzwerk"
Basic.Settings.Advanced.Network.BindToIP="Interface"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="Neuen Netzwerkcode aktivieren"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="Niedriger Latenzmodus"
Basic.AdvAudio="Erweiterte Audioeigenschaften"
Basic.AdvAudio.Name="Name"
Basic.AdvAudio.Mono="Heruntermischen zu Mono"
Basic.AdvAudio.Panning="Schwenken"
Basic.AdvAudio.SyncOffset="Sync Verschiebung (ms)"
+Basic.AdvAudio.Monitoring="Audiomonitoring"
+Basic.AdvAudio.Monitoring.None="Monitor aus"
+Basic.AdvAudio.Monitoring.MonitorOnly="Nur Monitor (Ausgabe stumm schalten)"
+Basic.AdvAudio.Monitoring.Both="Monitor und Ausgabe"
Basic.AdvAudio.AudioTracks="Spuren"
Basic.Settings.Hotkeys="Hotkeys"
OutputWarnings.NoTracksSelected="Sie müssen mindestens eine Spur auswählen"
OutputWarnings.MultiTrackRecording="Warnung: Bestimmte Formate (z. B. FLV) unterstützen nicht mehrere Spuren pro Aufnahme"
+OutputWarnings.MP4Recording="Warnung: Aufnahmen, die in MP4 gespeichert werden, sind nicht wiederherstellbar, wenn die Datei nicht abgeschlossen werden kann (zum Beispiel als Folge von BSODs, Stromausfälle, etc). Wenn Sie mehrere Audiospuren aufnehmen möchten, sollten Sie MKV verwenden und die Aufnahme zu MP4 remuxen, nachdem sie fertig ist. (Datei-> Remuxe Aufnahmen)"
obs-studio-17.0.2.tar.xz/UI/data/locale/el-GR.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/el-GR.ini
Changed
Seconds="Δευτερόλεπτα"
+
Basic.TransitionDuration="Διάρκεια"
Basic.TogglePreviewProgramMode="Λειτουργία στούντιο"
ConfirmRemove.Title="Επιβεβαίωση Αφαίρεσης"
ConfirmRemove.Text="Είστε βέβαιοι ότι θέλετε να καταργήσετε \"$1\";"
+
Output.ConnectFail.Title="Η σύνδεση απέτυχε"
Output.ConnectFail.BadPath="Μη έγκυρη Διαδρομή ή URL Σύνδεσης. Παρακαλώ ελέγξτε τις ρυθμίσεις σας και επιβεβαιώστε ότι είναι έγκυρες."
Output.ConnectFail.ConnectFailed="Απέτυχε η σύνδεση στον διακομιστή"
+
Basic.Main.AddSceneDlg.Title="Προσθήκη Σκηνής"
Basic.Main.AddSceneDlg.Text="Παρακαλώ εισάγετε το όνομα της σκηνής"
obs-studio-17.0.2.tar.xz/UI/data/locale/en-US.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/en-US.ini
Changed
Import="Import"
Export="Export"
+# updater
+Updater.Title="New update available"
+Updater.Text="There is a new update available:"
+Updater.UpdateNow="Update Now"
+Updater.RemindMeLater="Remind me Later"
+Updater.Skip="Skip Version"
+Updater.Running.Title="Program currently active"
+Updater.Running.Text="Outputs are currently active, please shut down any active outputs before attempting to update"
+Updater.NoUpdatesAvailable.Title="No updates available"
+Updater.NoUpdatesAvailable.Text="No updates are currently available"
+Updater.FailedToLaunch="Failed to launch updater"
+Updater.GameCaptureActive.Title="Game capture active"
+Updater.GameCaptureActive.Text="Game capture hook library is currently in use. Please close any games/programs being captured (or restart windows) and try again."
+
# quick transitions
QuickTransitions.SwapScenes="Swap Preview/Output Scenes After Transitioning"
QuickTransitions.SwapScenesTT="Swaps the preview and output scenes after transitioning (if the output's original scene still exists).\nThis will not undo any changes that may have been made to the output's original scene."
ConfirmRemove.Text="Are you sure you wish to remove '$1'?"
ConfirmRemove.TextMultiple="Are you sure you wish to remove %1 items?"
+# output start messages
+Output.StartStreamFailed="Failed to start streaming"
+Output.StartRecordingFailed="Failed to start recording"
+Output.StartReplayFailed="Failed to start replay buffer"
+Output.StartFailedGeneric="Starting the output failed. Please check the log for details.\n\nNote: If you are using the NVENC or AMD encoders, make sure your video drivers are up to date."
+
# output connect messages
Output.ConnectFail.Title="Failed to connect"
Output.ConnectFail.BadPath="Invalid Path or Connection URL. Please check your settings to confirm that they are valid."
Deinterlacing.TopFieldFirst="Top Field First"
Deinterlacing.BottomFieldFirst="Bottom Field First"
+# volume control accessibility text
+VolControl.SliderUnmuted="Volume slider for '%1': %2"
+VolControl.SliderMuted="Volume slider for '%1': %2 (currently muted)"
+VolControl.Mute="Mute '%1'"
+VolControl.Properties="Properties for '%1'"
+
# add scene dialog
Basic.Main.AddSceneDlg.Title="Add Scene"
Basic.Main.AddSceneDlg.Text="Please enter the name of the scene"
Basic.Settings.General="General"
Basic.Settings.General.Theme="Theme"
Basic.Settings.General.Language="Language"
+Basic.Settings.General.EnableAutoUpdates="Automatically check for updates on startup"
Basic.Settings.General.WarnBeforeStartingStream="Show confirmation dialog when starting streams"
Basic.Settings.General.WarnBeforeStoppingStream="Show confirmation dialog when stopping streams"
+Basic.Settings.General.Projectors="Projectors"
Basic.Settings.General.HideProjectorCursor="Hide cursor over projectors"
Basic.Settings.General.ProjectorAlwaysOnTop="Make projectors always on top"
Basic.Settings.General.Snapping="Source Alignment Snapping"
Basic.Settings.General.SnapDistance="Snap Sensitivity"
Basic.Settings.General.RecordWhenStreaming="Automatically record when streaming"
Basic.Settings.General.KeepRecordingWhenStreamStops="Keep recording when stream stops"
-Basic.Settings.General.SysTrayEnabled="Enable system tray icon"
+Basic.Settings.General.ReplayBufferWhileStreaming="Automatically start replay buffer when streaming"
+Basic.Settings.General.KeepReplayBufferStreamStops="Keep replay buffer active when stream stops"
+Basic.Settings.General.SysTray="System Tray"
Basic.Settings.General.SysTrayWhenStarted="Minimize to system tray when started"
+Basic.Settings.General.SystemTrayHideMinimize="Always minimize to system tray instead of task bar"
+Basic.Settings.General.SaveProjectors="Save projectors on exit"
# basic mode 'stream' settings
Basic.Settings.Stream="Stream"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="Audio Encoder"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="Audio Encoder Settings (if any)"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="Muxer Settings (if any)"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="Keyframe interval (frames)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="Show all codecs (even if potentially incompatible)"
# basic mode 'output' settings - advanced section - recording subsection - completer
FilenameFormatting.completer="%CCYY-%MM-%DD %hh-%mm-%ss\n%YY-%MM-%DD %hh-%mm-%ss\n%Y-%m-%d %H-%M-%S\n%y-%m-%d %H-%M-%S\n%a %Y-%m-%d %H-%M-%S\n%A %Y-%m-%d %H-%M-%S\n%Y-%b-%d %H-%M-%S\n%Y-%B-%d %H-%M-%S\n%Y-%m-%d %I-%M-%S-%p\n%Y-%m-%d %H-%M-%S-%z\n%Y-%m-%d %H-%M-%S-%Z"
# basic mode 'output' settings - advanced section - recording subsection - TT
-FilenameFormatting.TT="%CCYY Year, four digits\n%YY Year, last two digits (00-99)\n%MM Month as a decimal number (01-12)\n%DD Day of the month, zero-padded (01-31)\n%hh Hour in 24h format (00-23)\n%mm Minute (00-59)\n%ss Second (00-61)\n%% A % sign\n%a Abbreviated weekday name\n%A Full weekday name\n%b Abbreviated month name\n%B Full month name\n%d Day of the month, zero-padded (01-31)\n%H Hour in 24h format (00-23)\n%I Hour in 12h format (01-12)\n%m Month as a decimal number (01-12)\n%M Minute (00-59)\n%p AM or PM designation\n%S Second (00-61)\n%y Year, last two digits (00-99)\n%Y Year\n%z ISO 8601 offset from UTC or timezone\n name or abbreviation\n%Z Timezone name or abbreviation\n"
+FilenameFormatting.TT="%CCYY Year, four digits\n%YY Year, last two digits (00-99)\n%MM Month as a decimal number (01-12)\n%DD Day of the month, zero-padded (01-31)\n%hh Hour in 24h format (00-23)\n%mm Minute (00-59)\n%ss Second (00-61)\n%% A % sign\n%a Abbreviated weekday name\n%A Full weekday name\n%b Abbreviated month name\n%B Full month name\n%d Day of the month, zero-padded (01-31)\n%H Hour in 24h format (00-23)\n%I Hour in 12h format (01-12)\n%m Month as a decimal number (01-12)\n%M Minute (00-59)\n%p AM or PM designation\n%S Second (00-61)\n%y Year, last two digits (00-99)\n%Y Year\n%z ISO 8601 offset from UTC or timezone\n name or abbreviation\n%Z Timezone name or abbreviation\n"
# basic mode 'video' settings
Basic.Settings.Video="Video"
Basic.Settings.Advanced.Video.ColorRange="YUV Color Range"
Basic.Settings.Advanced.Video.ColorRange.Partial="Partial"
Basic.Settings.Advanced.Video.ColorRange.Full="Full"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Audio Monitoring Device"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Default"
Basic.Settings.Advanced.StreamDelay="Stream Delay"
Basic.Settings.Advanced.StreamDelay.Duration="Duration (seconds)"
Basic.Settings.Advanced.StreamDelay.Preserve="Preserve cutoff point (increase delay) when reconnecting"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Estimated Memory Usage: %1 MB"
Basic.Settings.Advanced.Network="Network"
Basic.Settings.Advanced.Network.BindToIP="Bind to IP"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="Enable new networking code"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="Low latency mode"
# advanced audio properties
Basic.AdvAudio="Advanced Audio Properties"
Basic.AdvAudio.Mono="Downmix to Mono"
Basic.AdvAudio.Panning="Panning"
Basic.AdvAudio.SyncOffset="Sync Offset (ms)"
+Basic.AdvAudio.Monitoring="Audio Monitoring"
+Basic.AdvAudio.Monitoring.None="Monitor Off"
+Basic.AdvAudio.Monitoring.MonitorOnly="Monitor Only (mute output)"
+Basic.AdvAudio.Monitoring.Both="Monitor and Output"
Basic.AdvAudio.AudioTracks="Tracks"
# basic mode 'hotkeys' settings
# Output warnings
OutputWarnings.NoTracksSelected="You must select at least one track"
OutputWarnings.MultiTrackRecording="Warning: Certain formats (such as FLV) do not support multiple tracks per recording"
+OutputWarnings.MP4Recording="Warning: Recordings saved to MP4 will be unrecoverable if the file cannot be finalized (e.g. as a result of BSODs, power losses, etc.). If you want to record multiple audio tracks consider using MKV and remux the recording to mp4 after it is finished (File->Remux Recordings)"
obs-studio-17.0.2.tar.xz/UI/data/locale/es-ES.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/es-ES.ini
Changed
Import="Importar"
Export="Exportar"
+Updater.Title="Nueva actualización disponible"
+Updater.Text="Hay una nueva versión disponible:"
+Updater.UpdateNow="Actualizar ahora"
+Updater.RemindMeLater="Recordármelo más tarde"
+Updater.Skip="Saltar Versión"
+Updater.Running.Title="Programa actualmente activo"
+Updater.Running.Text="Las salidas están activas actualmente, por favor apague cualquier salida activa antes de intentar actualizar"
+Updater.NoUpdatesAvailable.Title="No hay actualizaciones disponibles"
+Updater.NoUpdatesAvailable.Text="No hay actualizaciones disponibles actualmente"
+Updater.FailedToLaunch="No se pudo iniciar el actualizador"
+Updater.GameCaptureActive.Title="Captura de juego activa"
+Updater.GameCaptureActive.Text="La libreria de captura de juegos esta actualmente en uso. Por favor, cierra cualquier juego/programa que este siendo capturado (o reinicia windows) e intentalo de nuevo."
+
QuickTransitions.SwapScenes="Cambiar vista previa y salida escenas después de la transición"
QuickTransitions.SwapScenesTT="Cambia la vista previa y salida escenas después de la transición (si todavía existe la escena original de la salida). \nEsto no deshará cualquier cambio que pueda haber hecho a la escena original de la salida."
QuickTransitions.DuplicateScene="Duplicar escena"
ConfirmRemove.Text="¿Seguro que desea eliminar '$1'?"
ConfirmRemove.TextMultiple="¿Seguro que quieres eliminar %1 elementos?"
+Output.StartStreamFailed="No se pudo iniciar la emisión"
+Output.StartRecordingFailed="No se pudo iniciar grabación"
+Output.StartReplayFailed="No se pudo iniciar el buffer de replay"
+Output.StartFailedGeneric="No se pudo iniciar la salida. Por favor compruebe los logs para mas detalles. \n\nNota: Si estas usando los codificadores de NVENC o AMD, asegúrate que tus drivers de vídeo están actualizados."
+
Output.ConnectFail.Title="Error al conectarse"
Output.ConnectFail.BadPath="URL ruta de acceso o conexión no válida. Por favor, compruebe su configuración para confirmar que está correcta."
Output.ConnectFail.ConnectFailed="No se pudo conectar al servidor"
Deinterlacing.TopFieldFirst="Campo Superior Primero"
Deinterlacing.BottomFieldFirst="Campo Inferior Primero"
+VolControl.SliderUnmuted="Deslizador de volumen para '%1': %2"
+VolControl.SliderMuted="Deslizador de volumen para '%1': %2 (silenciado)"
+VolControl.Mute="Silenciar '%1'"
+VolControl.Properties="Propiedades para '%1'"
+
Basic.Main.AddSceneDlg.Title="Añadir escena"
Basic.Main.AddSceneDlg.Text="Por favor, introduzca el nombre de la escena"
Basic.Settings.General="General"
Basic.Settings.General.Theme="Tema"
Basic.Settings.General.Language="Idioma"
+Basic.Settings.General.EnableAutoUpdates="Comprobar actualizaciones automáticamente al inicio"
Basic.Settings.General.WarnBeforeStartingStream="Mostrar diálogo de confirmación cuando se inicia una transmisión"
Basic.Settings.General.WarnBeforeStoppingStream="Mostrar diálogo de confirmación cuando se para una transmisión"
+Basic.Settings.General.Projectors="Proyectores"
Basic.Settings.General.HideProjectorCursor="Ocultar el cursor sobre proyectores"
Basic.Settings.General.ProjectorAlwaysOnTop="Proyectores siempre en la parte superior"
Basic.Settings.General.Snapping="Ajuste de alineación de la fuente"
Basic.Settings.General.SnapDistance="Ajustar la sensibilidad"
Basic.Settings.General.RecordWhenStreaming="Grabar automáticamente cuando se transmite"
Basic.Settings.General.KeepRecordingWhenStreamStops="Mantener la grabación cuando se detiene la trasmision"
-Basic.Settings.General.SysTrayEnabled="Activar icono en la bandeja del sistema"
+Basic.Settings.General.ReplayBufferWhileStreaming="Iniciar la reproducción del búfer automáticamente durante la transmisión"
+Basic.Settings.General.KeepReplayBufferStreamStops="Mantener activo el búfer de reproducción cuando la transmisión se detenga"
+Basic.Settings.General.SysTray="Bandeja del sistema"
Basic.Settings.General.SysTrayWhenStarted="Minimizar a la bandeja del sistema al iniciar"
+Basic.Settings.General.SystemTrayHideMinimize="Minimizar siempre en la bandeja del sistema en lugar de la barra de tareas"
+Basic.Settings.General.SaveProjectors="Guardar los proyectores al salir"
Basic.Settings.Stream="Emision"
Basic.Settings.Stream.StreamType="Tipo de Emision"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="Codificador de audio"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="Configuración de codificador de vídeo (si existe)"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="Ajustes de Muxer (en caso de que haya)"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="Intervalo de fotogramas clave (en Fotogramas)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="Mostrar todos los codecs (aunque sean potencialmente incompatibles)"
FilenameFormatting.completer="%CCYY-%MM-%DD %hh-%mm-%ss\n%YY-%MM-%DD %hh-%mm-%ss\n%Y-%m-%d %H-%M-%S\n%y-%m-%d %H-%M-%S\n%a %Y-%m-%d %H-%M-%S\n%A %Y-%m-%d %H-%M-%S\n%Y-%b-%d %H-%M-%S\n%Y-%B-%d %H-%M-%S\n%Y-%m-%d %I-%M-%S-%p\n%Y-%m-%d %H-%M-%S-%z\n%Y-%m-%d %H-%M-%S-%Z"
Basic.Settings.Advanced.Video.ColorRange="Gama de Color YUV"
Basic.Settings.Advanced.Video.ColorRange.Partial="Parcial"
Basic.Settings.Advanced.Video.ColorRange.Full="Completo"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Dispositivo de monitorización de audio"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Por defecto"
Basic.Settings.Advanced.StreamDelay="Retraso de la transmisión"
Basic.Settings.Advanced.StreamDelay.Duration="Duración (segundos)"
Basic.Settings.Advanced.StreamDelay.Preserve="Preservar el punto de corte (aumento de retraso) al volver a conectar"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Uso estimado de memoria: %1 MB"
Basic.Settings.Advanced.Network="Red"
Basic.Settings.Advanced.Network.BindToIP="Enlazar con IP"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="Habilitar el nuevo código de red"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="Modo de baja latencia"
Basic.AdvAudio="Propiedades de Audio avanzadas"
Basic.AdvAudio.Name="Nombre"
Basic.AdvAudio.Mono="Remezclar a Mono"
Basic.AdvAudio.Panning="Panorámica"
Basic.AdvAudio.SyncOffset="Sincronización Offset (ms)"
+Basic.AdvAudio.Monitoring="Monitorización de audio"
+Basic.AdvAudio.Monitoring.None="Monitorización desactivada"
+Basic.AdvAudio.Monitoring.MonitorOnly="Solo monitorización (silenciar la salida)"
+Basic.AdvAudio.Monitoring.Both="Monitorización y salida"
Basic.AdvAudio.AudioTracks="Pistas"
Basic.Settings.Hotkeys="Atajos"
OutputWarnings.NoTracksSelected="Debe seleccionar al menos una pista"
OutputWarnings.MultiTrackRecording="ADVERTENCIA: Ciertos formatos (como FLV) no admiten varias pistas por grabación"
+OutputWarnings.MP4Recording="ADVERTENCIA: Las grabaciones guardadas en MP4 será irrecuperables si el archivo no puede finalizarse (e.g. como resultado de BSODs, pérdidas de potencia, etcetera). Si quieres grabar varias pistas de audio utiliza MKV y reune la grabación a mp4 después de que termine (archivo-> Remux de grabaciones)"
obs-studio-17.0.2.tar.xz/UI/data/locale/et-EE.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/et-EE.ini
Changed
Top="Ülalt"
Bottom="Alt"
+
QuickTransitions.SwapScenes="Vaheta üleminekul eelvaade ja väljund"
QuickTransitions.SwapScenesTT="Vahetab pärast üleminekut eelvaate ja väljundi stseenid (kui väljundi esialgne stseen on veel olemas).\nEsialgsele stseenile tehtud muudatusi ei pöörata tagasi."
QuickTransitions.DuplicateScene="Tee stseenist koopia"
ConfirmRemove.Title="Ümbernimetamise kinnitamine"
ConfirmRemove.Text="Kas soovid kindlasti eemaldada '$1'?"
+
Output.ConnectFail.Title="Ühendamine ei õnnestunud"
Output.ConnectFail.BadPath="Vigane rada või ühenduse URL. Palun veendu, et valitud sätted on õiged."
Output.ConnectFail.ConnectFailed="Serveriga ühendamine ebaõnnestus"
+
Basic.Main.AddSceneDlg.Title="Stseeni lisamine"
Basic.Main.AddSceneDlg.Text="Sisesta stseeni nimi"
obs-studio-17.0.2.tar.xz/UI/data/locale/eu-ES.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/eu-ES.ini
Changed
Import="Inportatu"
Export="Esportatu"
+Updater.Title="Eguneraketa berria eskuragarri"
+Updater.Text="Eguneraketa berri bat eskuragarri dago:"
+Updater.UpdateNow="Eguneratu orain"
+Updater.RemindMeLater="Gogoratu geroago"
+Updater.Skip="Baztertu bertsioa"
+Updater.Running.Title="Uneko programa aktiboa"
+Updater.Running.Text="Une honetan irteerak aktibo daude, itzali aktibo dauden irteerak eguneratzen saiatu aurretik"
+Updater.NoUpdatesAvailable.Title="Ez dago eguneraketarik eskuragarri"
+Updater.NoUpdatesAvailable.Text="Une honetan ez dago eguneraketarik eskuragarri"
+Updater.FailedToLaunch="Huts egin du eguneratzailea abiarazten"
+Updater.GameCaptureActive.Title="Jolasen kaptura aktiboa"
+Updater.GameCaptureActive.Text="Jolasen kapturaren liburutegia erabiltzen ari da. Itxi kapturatzen ari den jolasa/programa (edo berrabiarazi Windows) eta saiatu berriro."
+
QuickTransitions.SwapScenes="Trukatu Aurrebista/Irteera-eszenak trantsizioen ondoren"
QuickTransitions.SwapScenesTT="Trukatu aurrebistak eta irteera-eszenak trantsizioen ondoren (baldin eta irteerakoaren jatorrizkoa eszena badago).\n Honek ez du desegingo irteerakoaren jatorrizko eszenari egindako aldaketak."
QuickTransitions.DuplicateScene="Bikoiztu eszena"
ConfirmRemove.Text="Ziur zaude '$1' kendu nahi duzula?"
ConfirmRemove.TextMultiple="Seguru zaude %1 elementuak ezabatu nahi dituzula?"
+Output.StartStreamFailed="Huts egin du transmisioak"
+Output.StartRecordingFailed="Huts egin du grabazioak"
+Output.StartReplayFailed="Huts egin du erreprodukzio bufferrak"
+Output.StartFailedGeneric="Huts egin du irteeraren abioak. Begiratu erregistroa zehaztasunak ikusteko.\n\nOharra: NVENC edo AMD kodetzaileak erabiltzen ari bazara segurtatu haien kontrolatzaileak eguneratuta daudela."
+
Output.ConnectFail.Title="Huts egin du konektatzean"
Output.ConnectFail.BadPath="Helburu edo konexio-URL okerra. Egiaztatu zure ezarpenak baliozkoak direla baieztatzeko."
Output.ConnectFail.ConnectFailed="Huts egin du zerbitzariarekin konektatzean"
Deinterlacing.TopFieldFirst="Goiko eremua lehenik"
Deinterlacing.BottomFieldFirst="Beheko eremua lehenik"
+VolControl.SliderUnmuted="Bolumen graduatzailea '%1'-rentzat: %2"
+VolControl.SliderMuted="Bolumen graduatzailea '%1'-rentzat: %2 (une honetan mutu)"
+VolControl.Mute="Mututu '%1'"
+VolControl.Properties="'%1'-ren ezaugarriak"
+
Basic.Main.AddSceneDlg.Title="Gehitu eszena"
Basic.Main.AddSceneDlg.Text="Sartu eszenaren izena"
Basic.Settings.General="Orokorra"
Basic.Settings.General.Theme="Gaia"
Basic.Settings.General.Language="Hizkuntza"
+Basic.Settings.General.EnableAutoUpdates="Abiaraztean begiratu automatikoki eguneraketarik ba ote dagoen"
Basic.Settings.General.WarnBeforeStartingStream="Erakutsi baieztapen elkarrizketa transmisioak hasterakoan"
-Basic.Settings.General.WarnBeforeStoppingStream="Erakutsi baieztapen elkarrizketa transmisioak gelditzerakoan"
+Basic.Settings.General.WarnBeforeStoppingStream="Erakutsi baieztapen elkarrizketa transmisioak gelditzean"
+Basic.Settings.General.Projectors="Projektoreak"
Basic.Settings.General.HideProjectorCursor="Ezkutatu kurtsorea proiekzioetan"
Basic.Settings.General.ProjectorAlwaysOnTop="Proiektoreak beti gainean"
Basic.Settings.General.Snapping="Iturburuaren lerrokatzearen doitzea"
Basic.Settings.General.SnapDistance="Doitu sentikortasuna"
Basic.Settings.General.RecordWhenStreaming="Grabatu automatikoki transmisioa egitean"
Basic.Settings.General.KeepRecordingWhenStreamStops="Mantendu grabazioa transmisioa gelditzean"
-Basic.Settings.General.SysTrayEnabled="Gaitu sistemaren erretiluko ikonoa"
+Basic.Settings.General.ReplayBufferWhileStreaming="Hasi erreprodukzio bufferra automatikoki transmititzean"
+Basic.Settings.General.KeepReplayBufferStreamStops="Mantendu erreprodukzio bufferra aktiboa transmisioa gelditzean"
+Basic.Settings.General.SysTray="Sistemaren erretilua"
Basic.Settings.General.SysTrayWhenStarted="Minimizatu sistemaren erretilura hastean"
+Basic.Settings.General.SystemTrayHideMinimize="Minimizatu beti sistemaren erretilura ataza barrara egin ordez"
+Basic.Settings.General.SaveProjectors="Gorde proiekzioak irtetean"
Basic.Settings.Stream="Transmisioa"
Basic.Settings.Stream.StreamType="Transmisio-mota"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="Audio kodetzailea"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="Audio kodetzailearen ezarpenak (egonez gero)"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="Bihurtzailearen ezarpenak (egonez gero)"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="Gako-fotogramen tartea (fotogramak)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="Erakutsi kodek guztiak (bateragarriak ez balira ere)"
FilenameFormatting.completer="%CCYY-%MM-%DD %hh-%mm-%ss\n%YY-%MM-%DD %hh-%mm-%ss\n%Y-%m-%d %H-%M-%S\n%y-%m-%d %H-%M-%S\n%a %Y-%m-%d %H-%M-%S\n%A %Y-%m-%d %H-%M-%S\n%Y-%b-%d %H-%M-%S\n%Y-%B-%d %H-%M-%S\n%Y-%m-%d %I-%M-%S-%p\n%Y-%m-%d %H-%M-%S-%z\n%Y-%m-%d %H-%M-%S-%Z"
Basic.Settings.Advanced.Video.ColorRange="YUV kolore-barrutia"
Basic.Settings.Advanced.Video.ColorRange.Partial="Partziala"
Basic.Settings.Advanced.Video.ColorRange.Full="Osoa"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Audioa kontrolatzeko gailua"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Lehenetsia"
Basic.Settings.Advanced.StreamDelay="Taansmisio-atzerapena"
Basic.Settings.Advanced.StreamDelay.Duration="Iraupena (segundoak)"
Basic.Settings.Advanced.StreamDelay.Preserve="Mantendu ebaketa puntua (handitu atzerapena) birkonektatzean"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Estimatutako memoria erabilpena: %1 MB"
Basic.Settings.Advanced.Network="Sarea"
Basic.Settings.Advanced.Network.BindToIP="IP bidez lotu"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="Gaitu sare kode berria"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="Latentzia txikiko modua"
Basic.AdvAudio="Audio propietate aurreratuak"
Basic.AdvAudio.Name="Izena"
Basic.AdvAudio.Mono="Nahasketa monora murriztu"
Basic.AdvAudio.Panning="Panoramika"
Basic.AdvAudio.SyncOffset="Sinkronizazioaren desplazamendua (ms)"
+Basic.AdvAudio.Monitoring="Adioaren kontrola"
+Basic.AdvAudio.Monitoring.None="Audioa itzalita"
+Basic.AdvAudio.Monitoring.MonitorOnly="Kontrola bakarrik (irteera mututua)"
+Basic.AdvAudio.Monitoring.Both="Kontrola eta irteera"
Basic.AdvAudio.AudioTracks="Pistak"
Basic.Settings.Hotkeys="Laster-teklak"
OutputWarnings.NoTracksSelected="Gutxienez pista bat hautatu behar duzu"
OutputWarnings.MultiTrackRecording="Oharra: Zenbait formatuk (esaterako FLV-k) ez ditu pista anitzak onartzen grabazioan"
+OutputWarnings.MP4Recording="Kontuz: MP4 formatuz gordetako grabazioak izan daitezke berreskuraezinak fitxategia ezin bada bukatu (esate baterako energia etenagatik). Hainbat audio pista grabatu nahi baduzu erabil dezakezu MKV formatua eta mp4 bihurtu grabazioa bukatu ondoren (Fitxategia->Bihurtu grabazioak)"
obs-studio-17.0.2.tar.xz/UI/data/locale/fi-FI.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/fi-FI.ini
Changed
Import="Tuo"
Export="Vie"
+Updater.Title="Uusi päivitys on saatavilla"
+Updater.Text="Uusi päivitys on saatavilla:"
+Updater.UpdateNow="Päivitä nyt"
+Updater.RemindMeLater="Muistuta myöhemmin"
+Updater.Skip="Ohita versio"
+Updater.Running.Title="Ohjelma on käytössä"
+Updater.Running.Text="Tallentaminen/lähetys on aktiivinen. Sulje kaikki ulostulo ennen päivityksen jatkamista"
+Updater.NoUpdatesAvailable.Title="Päivityksiä ei ole saatavilla"
+Updater.NoUpdatesAvailable.Text="Päivityksiä ei ole tällä hetkellä saatavilla"
+Updater.FailedToLaunch="Päivittäjän käynnistäminen epäonnistui"
+Updater.GameCaptureActive.Title="Game capture on aktiivinen"
+Updater.GameCaptureActive.Text="Game capture -kirjasto on yhä käytössä. Sulje kaikki pelit/ohjelmat, joita on kaapattu tai käynnistä tietokone uudelleen."
+
QuickTransitions.SwapScenes="Vaihda esikatselu- ja ulostulo-skenet siirtymän jälkeen"
QuickTransitions.SwapScenesTT="Vaihda esikatselu- ja ulostulo-skenet siirtymän jälkeen (jos ulostulon alkuperäinen skene on yhä olemassa).\nTämä ei peruuta muutoksia joita on tehty alkuperäiseen skeneen."
QuickTransitions.DuplicateScene="Kahdenna skene"
ConfirmRemove.Text="Haluatko varmasti poistaa '$1'?"
ConfirmRemove.TextMultiple="Haluatko varmasti poistaa %1 kohdetta?"
+Output.StartStreamFailed="Lähetyksen aloittaminen epäonnistui"
+Output.StartRecordingFailed="Tallennuksen aloittaminen epäonnistui"
+Output.StartReplayFailed="Toistopuskurin käynnistäminen epäonnistui"
+Output.StartFailedGeneric="Ulostulon käynnistäminen epäonnistui. Tarkista loki lisätietoja varten.\n\nHuomio: Jos käytät NVENC tai AMD -enkoodereita, varmista, että näytönohjaimen ajurit on päivitetty ajantasalle."
+
Output.ConnectFail.Title="Yhdistäminen epäonnistui"
Output.ConnectFail.BadPath="Viallinen polku tai yhteysosoite. Tarkista, että asetuksesi ovat kunnossa."
Output.ConnectFail.ConnectFailed="Palvelimelle yhdistäminen epäonnistui"
Deinterlacing.TopFieldFirst="Ylin kenttä ensin"
Deinterlacing.BottomFieldFirst="Alin kenttä ensin"
+VolControl.SliderUnmuted="Äänenvoimakkuus \"%1\": %2"
+VolControl.SliderMuted="Äänenvoimakkuus \"%1\": %2 (mykistetty)"
+VolControl.Mute="Mykistä %1"
+VolControl.Properties="Ominaisuudet %1:lle"
+
Basic.Main.AddSceneDlg.Title="Lisää skene"
Basic.Main.AddSceneDlg.Text="Aseta skenen nimi"
Basic.Settings.General="Yleiset"
Basic.Settings.General.Theme="Teema"
Basic.Settings.General.Language="Kieli"
+Basic.Settings.General.EnableAutoUpdates="Tarkista päivitykset automaattisesti käynnistäessä"
Basic.Settings.General.WarnBeforeStartingStream="Näytä varmistus-ikkuna kun lähetys aloitetaan"
Basic.Settings.General.WarnBeforeStoppingStream="Näytä varmistus-ikkuna kun lähetys pysäytetään"
+Basic.Settings.General.Projectors="Peilaukset"
Basic.Settings.General.HideProjectorCursor="Piilota osoitin peilattaessa"
Basic.Settings.General.ProjectorAlwaysOnTop="Pidä peilatut esikatselut aina päällimmäisenä"
Basic.Settings.General.Snapping="Lähteiden kiinnitys"
Basic.Settings.General.SnapDistance="Kiinnityksen herkkyys"
Basic.Settings.General.RecordWhenStreaming="Tallenna automaattisesti kun lähetetään"
Basic.Settings.General.KeepRecordingWhenStreamStops="Jatka tallennusta lähetyksen loputtua"
-Basic.Settings.General.SysTrayEnabled="Ota järjestelmäkuvake käyttöön"
+Basic.Settings.General.ReplayBufferWhileStreaming="Käynnistä toistopuskuri automaattisesti lähetettäessä"
+Basic.Settings.General.KeepReplayBufferStreamStops="Pidä toistopuskuri käytössä kun lähetys loppuu"
+Basic.Settings.General.SysTray="Ilmaisinalue"
Basic.Settings.General.SysTrayWhenStarted="Pienennä ilmaisinalueelle käynnistyessä"
+Basic.Settings.General.SystemTrayHideMinimize="Pienennä aina tilapalkkiin tehtäväpalkin sijaan"
+Basic.Settings.General.SaveProjectors="Tallenna peilaus poistuessa"
Basic.Settings.Stream="Lähetys"
Basic.Settings.Stream.StreamType="Lähetystyyppi"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="Äänienkooderi"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="Äänienkooderin asetukset"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="Muunnon asetukset"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="Keyframe-väli (frameina)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="Näytä kaikki koodekit (myös mahdollisesti yhteensopimattomat)"
FilenameFormatting.completer="%CCYY-%MM-%DD %hh-%mm-%ss\n%YY-%MM-%DD %hh-%mm-%ss\n%Y-%m-%d %H-%M-%S\n%y-%m-%d %H-%M-%S\n%a %Y-%m-%d %H-%M-%S\n%A %Y-%m-%d %H-%M-%S\n%Y-%b-%d %H-%M-%S\n%Y-%B-%d %H-%M-%S\n%Y-%m-%d %I-%M-%S-%p\n%Y-%m-%d %H-%M-%S-%z\n%Y-%m-%d %H-%M-%S-%Z"
Basic.Settings.Advanced.Video.ColorRange="YUV värialue"
Basic.Settings.Advanced.Video.ColorRange.Partial="Osittainen"
Basic.Settings.Advanced.Video.ColorRange.Full="Täysi"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Äänen monitorointilaite"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Oletusarvo"
Basic.Settings.Advanced.StreamDelay="Lähetyksen viive"
Basic.Settings.Advanced.StreamDelay.Duration="Kesto (sekunteina)"
Basic.Settings.Advanced.StreamDelay.Preserve="Säilytä katkaisupiste (lisää viivettä) uudelleenyhdistettäessä"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Arvioitu muistinkäyttö: %1 MB"
Basic.Settings.Advanced.Network="Verkko"
Basic.Settings.Advanced.Network.BindToIP="Liitä IP:seen"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="Käytä uutta verkkokoodia"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="Alhaisen latenssin tila"
Basic.AdvAudio="Äänen lisäominaisuudet"
Basic.AdvAudio.Name="Nimi"
Basic.AdvAudio.Mono="Miksaa yksikanavaiseksi"
Basic.AdvAudio.Panning="Balanssi"
Basic.AdvAudio.SyncOffset="Synkronoinnin viivästys (ms)"
+Basic.AdvAudio.Monitoring="Äänen monitorointi"
+Basic.AdvAudio.Monitoring.None="Monitorointi pois"
+Basic.AdvAudio.Monitoring.MonitorOnly="Vain monitorointi (hiljennä ulostulo)"
+Basic.AdvAudio.Monitoring.Both="Monitorointi ja ulostulo"
Basic.AdvAudio.AudioTracks="Raidat"
Basic.Settings.Hotkeys="Pikanäppäimet"
OutputWarnings.NoTracksSelected="Sinun täytyy valita ainakin yksi raita"
OutputWarnings.MultiTrackRecording="Varoitus: Jotkin muodot (kuten FLV), eivät tue useampaa raitaa per tallennus"
+OutputWarnings.MP4Recording="Varoitus: MP4-muotoon tallentaessa tiedostoista tulee lukukelvottomia, mikäli niitä ei voi viimeistellä. (esim. johtuen BSOD:sta, sähkökatkosta jne.) Jos haluat tallentaa useampaa ääniraitaa, kannattaa käyttää MKV-muotoa ja muuntaa jälkikäteen MP4:ksi. (Tiedosto->Muunna tallenne)"
obs-studio-17.0.2.tar.xz/UI/data/locale/fr-FR.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/fr-FR.ini
Changed
Import="Importer"
Export="Exporter"
+Updater.Title="Nouvelle mise à jour disponible"
+Updater.Text="Une nouvelle mise à jour est disponible :"
+Updater.UpdateNow="Mettre à jour maintenant"
+Updater.RemindMeLater="Me le rappeler ultérieurement"
+Updater.Skip="Ignorer la version"
+Updater.Running.Title="Programme actuellement en cours d’exécution"
+Updater.Running.Text="Des sorties sont actuellement actives, veuillez fermer toutes les sorties actives avant d'essayer de mettre à jour"
+Updater.NoUpdatesAvailable.Title="Aucune mise à jour disponible"
+Updater.NoUpdatesAvailable.Text="Aucune mise à jour n’est actuellement disponible"
+Updater.FailedToLaunch="Impossible de démarrer la mise à jour"
+Updater.GameCaptureActive.Title="Capture de jeu active"
+Updater.GameCaptureActive.Text="La bibliothèque « hook » de capture de jeu est actuellement active. Veuillez fermer tous les jeux/programmes en cours de capture (ou redémarrez Windows) et réessayez."
+
QuickTransitions.SwapScenes="Permuter les scènes d'aperçu et de sortie après la transition"
QuickTransitions.SwapScenesTT="Permute les scènes d'aperçu et de sortie après la transition (si la scène d'origine de la sortie existe toujours). \nCela n'annulera pas les modifications qui auront pu être faites sur la scène d'origine de la sortie."
QuickTransitions.DuplicateScene="Dupliquer la scène"
ConfirmRemove.Text="Êtes-vous sûr de vouloir supprimer « $1 » ?"
ConfirmRemove.TextMultiple="Voulez-vous vraiment supprimer %1 éléments ?"
+Output.StartStreamFailed="Impossible de démarrer le streaming"
+Output.StartRecordingFailed="Impossible de démarrer l'enregistrement"
+Output.StartReplayFailed="Impossible de démarrer le tampon de relecture"
+Output.StartFailedGeneric="Le démarrage de la sortie a échoué. Veuillez consulter le journal pour plus de détails.\n\nRemarque : si vous utilisez les encodeurs NVENC ou AMD, assurez-vous que vos pilotes vidéo soient à jour."
+
Output.ConnectFail.Title="Échec de la connexion"
Output.ConnectFail.BadPath="Adresse de connexion ou chemin invalide. Veuillez vérifier vos paramètres afin de confirmer leur validité."
Output.ConnectFail.ConnectFailed="Échec de la connexion au serveur"
Deinterlacing.TopFieldFirst="Champ du haut prioritaire"
Deinterlacing.BottomFieldFirst="Champ du bas prioritaire"
+VolControl.SliderUnmuted="Curseur de volume pour « %1 » : %2"
+VolControl.SliderMuted="Curseur de volume pour « %1 » : %2 (actuellement désactivé)"
+VolControl.Mute="Muet '%1'"
+VolControl.Properties="Propriétés pour '%1'"
+
Basic.Main.AddSceneDlg.Title="Ajouter une scène"
Basic.Main.AddSceneDlg.Text="Veuillez entrer le nom de la scène"
Basic.Settings.General="Général"
Basic.Settings.General.Theme="Thème"
Basic.Settings.General.Language="Langue"
+Basic.Settings.General.EnableAutoUpdates="Vérifier automatiquement les mises à jour au démarrage"
Basic.Settings.General.WarnBeforeStartingStream="Afficher une boîte de dialogue de confirmation au démarrage d'un stream"
Basic.Settings.General.WarnBeforeStoppingStream="Afficher une boîte de dialogue de confirmation à l'arrêt d'un stream"
+Basic.Settings.General.Projectors="Projecteurs"
Basic.Settings.General.HideProjectorCursor="Cacher le curseur sur les projecteurs"
Basic.Settings.General.ProjectorAlwaysOnTop="Projecteurs toujours au premier plan"
Basic.Settings.General.Snapping="Déclenchement d'alignement des sources"
Basic.Settings.General.SnapDistance="Sensibilité du déclenchement"
Basic.Settings.General.RecordWhenStreaming="Enregistrer automatiquement lors d'un stream"
Basic.Settings.General.KeepRecordingWhenStreamStops="Continuer à enregistrer lorsque le stream s’arrête"
-Basic.Settings.General.SysTrayEnabled="Afficher une icône dans la zone de notification"
+Basic.Settings.General.ReplayBufferWhileStreaming="Démarrer automatiquement le tampon de relecture lors d'un stream"
+Basic.Settings.General.KeepReplayBufferStreamStops="Garder le tampon de relecture actif lors de l'arrêt du stream"
+Basic.Settings.General.SysTray="Zone de notifications"
Basic.Settings.General.SysTrayWhenStarted="Réduire dans la zone de notification dès le démarrage"
+Basic.Settings.General.SystemTrayHideMinimize="Toujours réduire dans la zone de notification au lieu de la barre des tâches"
+Basic.Settings.General.SaveProjectors="Enregistrer les projecteurs en quittant"
Basic.Settings.Stream="Flux"
Basic.Settings.Stream.StreamType="Type de diffusion"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="Encodeur audio"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="Paramètres de l'encodeur audio (le cas échéant)"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="Paramètres du muxer (le cas échéant)"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="Intervalle d'images clés (en images)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="Afficher tous les codecs (même si potentiellement incompatibles)"
FilenameFormatting.completer="%CCYY-%MM-%DD %hh-%mm-%ss\n%YY-%MM-%DD %hh-%mm-%ss\n%Y-%m-%d %H-%M-%S\n%y-%m-%d %H-%M-%S\n%a %Y-%m-%d %H-%M-%S\n%A %Y-%m-%d %H-%M-%S\n%Y-%b-%d %H-%M-%S\n%Y-%B-%d %H-%M-%S\n%Y-%m-%d %I-%M-%S-%p\n%Y-%m-%d %H-%M-%S-%z\n%Y-%m-%d %H-%M-%S-%Z"
Basic.Settings.Advanced.Video.ColorRange="Gamme de couleurs YUV"
Basic.Settings.Advanced.Video.ColorRange.Partial="Partielle"
Basic.Settings.Advanced.Video.ColorRange.Full="Complète"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Dispositif de surveillance audio"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Par défaut"
Basic.Settings.Advanced.StreamDelay="Retard du stream"
Basic.Settings.Advanced.StreamDelay.Duration="Durée (en secondes)"
Basic.Settings.Advanced.StreamDelay.Preserve="Préserver le point de coupure (augmente le retard) lors d'une reconnexion"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Utilisation estimée de la mémoire : %1 Mo"
Basic.Settings.Advanced.Network="Carte réseau (adresse IP source du flux)"
Basic.Settings.Advanced.Network.BindToIP="Lier à :"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="Activer le nouveau code réseau"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="Mode faible latence"
Basic.AdvAudio="Propriétés audio avancées"
Basic.AdvAudio.Name="Nom"
Basic.AdvAudio.Mono="Passer en mono"
Basic.AdvAudio.Panning="Panoramique polyphonique"
Basic.AdvAudio.SyncOffset="Décalage de la synchronisation (ms)"
+Basic.AdvAudio.Monitoring="Surveillance audio"
+Basic.AdvAudio.Monitoring.None="Désactivé"
+Basic.AdvAudio.Monitoring.MonitorOnly="Surveillance uniquement (couper la sortie)"
+Basic.AdvAudio.Monitoring.Both="Surveillance et sortie"
Basic.AdvAudio.AudioTracks="Pistes"
Basic.Settings.Hotkeys="Raccourcis clavier"
obs-studio-17.0.2.tar.xz/UI/data/locale/gl-ES.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/gl-ES.ini
Changed
Bottom="Abaixo"
+
Basic.AddTransition="Engadir transición configurable"
Basic.RemoveTransition="Eliminar transición configurable"
Basic.TransitionProperties="Propiedades da transición"
ConfirmRemove.Title="Confirmar a eliminación"
ConfirmRemove.Text="Tes a certeza de querer eliminar '$1'?"
+
Output.ConnectFail.Title="Erro ao se conectar"
Output.ConnectFail.BadPath="Camiño ou URL de conexión non válidos. Por favor, comproba a configuración para confirmar de que son correctos."
Output.ConnectFail.ConnectFailed="Erro ao conectar co servidor"
+
Basic.Main.AddSceneDlg.Title="Engadir escena"
Basic.Main.AddSceneDlg.Text="Por favor, insire un nome para a escena"
obs-studio-17.0.2.tar.xz/UI/data/locale/he-IL.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/he-IL.ini
Changed
Top="עליון"
Bottom="תחתון"
+
QuickTransitions.SwapScenes="החלף סצינות תצוגה מקדימה/פלט לאחר המעבר"
QuickTransitions.SwapScenesTT="החלף הסצינות של התצוגה המקדימה ושל הפלט לאחר המעבר (באם הסצינה המקורית של הפלט עדיין קיימת). \n פעולה זו לא תבטל כל שינוי שייתכן ובוצע לסצינה המקורית של הפלט."
QuickTransitions.DuplicateScene="הכפל סצינה"
ConfirmRemove.Text="האם אתה בטוח שברצונך להסיר את '$1'?"
ConfirmRemove.TextMultiple="האם אתה בטוח שברצונך להסיר %1 פריטים?"
+
Output.ConnectFail.Title="ההתחברות נכשלה"
Output.ConnectFail.BadPath="URL לא חוקי של נתיב או חיבור. נא בדוק את ההגדרות שלך כדי לוודא כי הם נכונים."
Output.ConnectFail.ConnectFailed="ההתחברות לשרת נכשלה"
Deinterlacing.TopFieldFirst="שדה עליון ראשון"
Deinterlacing.BottomFieldFirst="שדה תחתון ראשון"
+
Basic.Main.AddSceneDlg.Title="הוסף סצנה"
Basic.Main.AddSceneDlg.Text="אנא הזן את השם של הסצנה"
obs-studio-17.0.2.tar.xz/UI/data/locale/hr-HR.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/hr-HR.ini
Changed
Seconds="Sekundi"
Deprecated="Prevaziđeno"
+
QuickTransitions.SwapScenes="Zameni scene pregleda/izlaza nakon prelaza"
QuickTransitions.SwapScenesTT="Zamenjuje scene pregleda i izlaza nakon prelaza (ako originalna scena izlaza još uvek postoji).\nOvo neće poništiti promene koje su načinjene nad originalnom scenom izlaza."
QuickTransitions.DuplicateScene="Dupliraj scenu"
ConfirmRemove.Text="Da li ste sigurni da želite izbaciti '$1'?"
ConfirmRemove.TextMultiple="Da li ste sigurni da želite izbaciti %1 stavke?"
+
Output.ConnectFail.Title="Neuspešno povezivanje"
Output.ConnectFail.BadPath="Neispravna putanja ili URL konekcije. Molim proverite vaša podešavanja da potvrdite njihovu ispravnost."
Output.ConnectFail.ConnectFailed="Neuspešno povezivanje na server"
Deinterlacing.TopFieldFirst="Prvo gornje polje"
Deinterlacing.BottomFieldFirst="Prvo donje polje"
+
Basic.Main.AddSceneDlg.Title="Dodaj scenu"
Basic.Main.AddSceneDlg.Text="Molim unesite ime scene"
Basic.Settings.General.SnapDistance="Osetljivost privlačenja"
Basic.Settings.General.RecordWhenStreaming="Automatsko snimanje pri emitovanju"
Basic.Settings.General.KeepRecordingWhenStreamStops="Nastavi snimati kada se emitovanje zaustavi"
-Basic.Settings.General.SysTrayEnabled="Omogući ikonicu u sistemskom panelu"
Basic.Settings.General.SysTrayWhenStarted="Pri pokretanju minimiziraj na ikonicu u sistemskom panelu"
Basic.Settings.Stream="Strim"
obs-studio-17.0.2.tar.xz/UI/data/locale/hu-HU.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/hu-HU.ini
Changed
Import="Importálás"
Export="Exportálás"
+Updater.Title="Új frissítés elérhető"
+Updater.Text="Új frissítés elérhető:"
+Updater.UpdateNow="Frissítés most"
+Updater.RemindMeLater="Emlékeztessen később"
+Updater.Skip="Verzió átugrása"
+Updater.Running.Title="A program jelenleg aktív"
+Updater.Running.Text="Valamely kimenet jelenleg aktív, állítsa le az aktív kimenetet, mielőtt frissíteni próbál"
+Updater.NoUpdatesAvailable.Title="Nincs elérhető frissítés"
+Updater.NoUpdatesAvailable.Text="Jelenleg nincs elérhető frissítés"
+Updater.FailedToLaunch="Frissítő alkalmazás indítása sikertelen"
+Updater.GameCaptureActive.Title="Játék felvétel aktív"
+Updater.GameCaptureActive.Text="Játékfelvétel hook könyvtár jelenleg használatban. Zárjon be minden játékot/programot, amelyet felvesz (vagy indítsa újra a számítógépét) és próbálkozzon újra."
+
QuickTransitions.SwapScenes="Előnézeti/Kimeneti Jelenetek cseréje átmenet után"
QuickTransitions.SwapScenesTT="Az előnézet és a kimeneti jelenet cseréje átmenet után (ha a kimenet eredeti jelenete még létezik).\nEz nincs kihatással a kimenet eredeti jelenetére."
QuickTransitions.DuplicateScene="Jelenet kettőzése"
ConfirmRemove.Text="\"$1\" eltávolítására készül, biztos benne?"
ConfirmRemove.TextMultiple="\"%1\" elem eltávolítására készül, biztos benne?"
+Output.StartStreamFailed="Stream indítása sikertelen"
+Output.StartRecordingFailed="Felvétel indítása sikertelen"
+Output.StartReplayFailed="Visszajátszás puffer indítása sikertelen"
+Output.StartFailedGeneric="Kimenet indítása sikertelen. Kérem ellenőrizze az eseménynaplóban a részleteket.\n\nMegjegyzés: NVENC vagy AMD kódoló használata esetén, győződjön meg róla, hogy az illesztőprogramok naprakészek!"
+
Output.ConnectFail.Title="Csatlakozás sikertelen"
Output.ConnectFail.BadPath="Érvénytelen elérési út vagy kapcsolati URL cím. Kérem, ellenőrizze a beállításokat és győződjön meg az érvényességükről."
Output.ConnectFail.ConnectFailed="Nem sikerült kapcsolódni a szerverhez"
Deinterlacing.TopFieldFirst="Felső mező először"
Deinterlacing.BottomFieldFirst="Alsó mező először"
+VolControl.SliderUnmuted="Hangerő csúszka a '%1'-hez: %2"
+VolControl.SliderMuted="Hangerő csúszka '%1'-hez: %2 (jelenleg némítva)"
+VolControl.Mute="Némítás '%1'"
+VolControl.Properties="Tulajdonságok a '%1'-hez"
+
Basic.Main.AddSceneDlg.Title="Jelenet hozzáadása"
Basic.Main.AddSceneDlg.Text="Kérem adja meg a jelenet nevét"
Basic.Settings.General="Általános"
Basic.Settings.General.Theme="Téma"
Basic.Settings.General.Language="Nyelv"
+Basic.Settings.General.EnableAutoUpdates="Indításkor a frissítések automatikus ellenőrzése"
Basic.Settings.General.WarnBeforeStartingStream="Megerősítő párbeszédpanel megjelenítése stream indításakor"
Basic.Settings.General.WarnBeforeStoppingStream="Megerősítő párbeszédpanel megjelenítése stream leállításakor"
+Basic.Settings.General.Projectors="Projektorok"
Basic.Settings.General.HideProjectorCursor="Projektor nézetben a kurzor elrejtése"
Basic.Settings.General.ProjectorAlwaysOnTop="Projektorok mindig legfelül"
Basic.Settings.General.Snapping="Forrás pozicionálásának igazítása"
Basic.Settings.General.SnapDistance="Igazítás érzékenysége"
Basic.Settings.General.RecordWhenStreaming="Automatikus felvétel stream esetén"
Basic.Settings.General.KeepRecordingWhenStreamStops="Felvétel folytatása a stream leállása esetén"
-Basic.Settings.General.SysTrayEnabled="Tálca ikon elhelyezése"
+Basic.Settings.General.ReplayBufferWhileStreaming="Automatikusan induljon a visszajátszás puffer stream megkezdésekor"
+Basic.Settings.General.KeepReplayBufferStreamStops="Visszajátszás puffer aktívan tartása stream leállása esetén"
+Basic.Settings.General.SysTray="Tálca"
Basic.Settings.General.SysTrayWhenStarted="Indításkor ikonként a tálcán"
+Basic.Settings.General.SystemTrayHideMinimize="Mindig a rendszertálcára minimalizálás tálca helyett"
+Basic.Settings.General.SaveProjectors="Projektorok mentése kilépéskor"
Basic.Settings.Stream="Stream"
Basic.Settings.Stream.StreamType="Stream típusa"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="Audio kódoló"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="Audio kódoló beállítások (ha van)"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="Muxer beállítások (ha van)"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="Kulcsképkocka időköz (képkockák)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="Minden kodek mutatása (még ha inkompatibilisek is)"
FilenameFormatting.completer="%CCYY-%MM-%DD %hh-%mm-%ss\n%YY-%MM-%DD %hh-%mm-%ss\n%Y-%m-%d %H-%M-%S\n%y-%m-%d %H-%M-%S\n%a %Y-%m-%d %H-%M-%S\n%A %Y-%m-%d %H-%M-%S\n%Y-%b-%d %H-%M-%S\n%Y-%B-%d %H-%M-%S\n%Y-%m-%d %I-%M-%S-%p\n%Y-%m-%d %H-%M-%S-%z\n%Y-%m-%d %H-%M-%S-%Z"
Basic.Settings.Advanced.Video.ColorRange="YUV színtartomány"
Basic.Settings.Advanced.Video.ColorRange.Partial="Részleges"
Basic.Settings.Advanced.Video.ColorRange.Full="Teljes"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Hangfigyelő eszköz"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Alapértelmezett"
Basic.Settings.Advanced.StreamDelay="Stream késleltetés"
Basic.Settings.Advanced.StreamDelay.Duration="Időtartam (másodperc)"
Basic.Settings.Advanced.StreamDelay.Preserve="Töréspont megőrzése (Késleltetés növeléssel) újrakapcsolódás esetén"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Becsült memóriahasználat: %1 MB"
Basic.Settings.Advanced.Network="Hálózat"
Basic.Settings.Advanced.Network.BindToIP="IP-hez rendelés"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="Új hálózatkezelő kód engedélyezése"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="Alacsony késleltetésű mód"
Basic.AdvAudio="Speciális hangtulajdonságok"
Basic.AdvAudio.Name="Név"
Basic.AdvAudio.Mono="Monora lekeverés"
Basic.AdvAudio.Panning="Keverő"
Basic.AdvAudio.SyncOffset="Szinkron eltolás (ms)"
+Basic.AdvAudio.Monitoring="Hangfigyelés"
+Basic.AdvAudio.Monitoring.None="Figyelés kikapcsolása"
+Basic.AdvAudio.Monitoring.MonitorOnly="Csak figyelés (kimenet némítása)"
+Basic.AdvAudio.Monitoring.Both="Figyelés és kimenet"
Basic.AdvAudio.AudioTracks="Sávok"
Basic.Settings.Hotkeys="Gyorsbillentyűk"
OutputWarnings.NoTracksSelected="Ki kell jelölnie legalább egy sávot!"
OutputWarnings.MultiTrackRecording="Figyelem: Bizonyos formátumok (mint az FLV) nem támogatják a több sávot felvételenként"
+OutputWarnings.MP4Recording="Figyelem: Az MP4-be mentett állományok javíthatatlanok, ha a fájl nem kerül lezárásra (pl: BSOD vagy áramkimaradás esetén, stb.). Ha mindenképpen több hangsávval kíván felvételt készíteni, akkor használja az MKV állományt és remuxolja a felvételt MP4-be, miután elkészült. (Fájl->Felvételek remuxolása)"
obs-studio-17.0.2.tar.xz/UI/data/locale/it-IT.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/it-IT.ini
Changed
Import="Importa"
Export="Esporta"
+
QuickTransitions.SwapScenes="Scambia scene di anteprima/uscita dopo la transizione"
QuickTransitions.SwapScenesTT="Scambia le scene di uscita con quella in anteprima dopo la transizione (ammesso che la scena in uscita originale ci sia ancora).\nQuesto non modificherà eventuali cambiamenti apportati alla scena di uscita originale."
QuickTransitions.DuplicateScene="Duplica scena"
ConfirmRemove.Text="Sei sicuro di voler rimuovere '$1'?"
ConfirmRemove.TextMultiple="Sei sicuro di volere rimuovere %1 elementi?"
+
Output.ConnectFail.Title="Impossibile connettersi"
Output.ConnectFail.BadPath="Percorso o URL di connessione non valido. Controlla le tue impostazioni per confermare che siano valide."
Output.ConnectFail.ConnectFailed="Connessione al server fallita"
Deinterlacing.TopFieldFirst="Priorità livello superiore"
Deinterlacing.BottomFieldFirst="Priorità livello inferiore"
+
Basic.Main.AddSceneDlg.Title="Aggiungi scena"
Basic.Main.AddSceneDlg.Text="Inserisci il nome della scena"
Basic.Settings.General.SnapDistance="Sensibilità Snap"
Basic.Settings.General.RecordWhenStreaming="Registra automaticamente quando si è in diretta"
Basic.Settings.General.KeepRecordingWhenStreamStops="Continua a registrare quando la diretta s'interrompe"
-Basic.Settings.General.SysTrayEnabled="Abilita icona area di notifica"
Basic.Settings.General.SysTrayWhenStarted="Minimizza all'area di notifica all'avvio"
+Basic.Settings.General.SystemTrayHideMinimize="Minimizza sempre nel vassoio di sistema invece che nella barra delle applicazioni"
Basic.Settings.Stream="Stream"
Basic.Settings.Stream.StreamType="Tipo di stream"
Basic.Settings.Advanced.Video.ColorRange="Gamma di colore YUV"
Basic.Settings.Advanced.Video.ColorRange.Partial="Parziale"
Basic.Settings.Advanced.Video.ColorRange.Full="Intero"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Dispositivo monitor audio"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Predefinito"
Basic.Settings.Advanced.StreamDelay="Ritardo Diretta"
Basic.Settings.Advanced.StreamDelay.Duration="Durata (secondi)"
Basic.Settings.Advanced.StreamDelay.Preserve="Preserva il punto di taglio (aumenta ritardo) durante la riconnessione"
Basic.AdvAudio.Mono="Downmix to Mono"
Basic.AdvAudio.Panning="Panning"
Basic.AdvAudio.SyncOffset="Sync Offset (ms)"
+Basic.AdvAudio.Monitoring="Monitor audio"
+Basic.AdvAudio.Monitoring.None="Monitor spento"
+Basic.AdvAudio.Monitoring.MonitorOnly="Solo monitor (uscita silenziata)"
+Basic.AdvAudio.Monitoring.Both="Monitor e uscita"
Basic.AdvAudio.AudioTracks="Tracce"
Basic.Settings.Hotkeys="Tasti di scelta rapida"
obs-studio-17.0.2.tar.xz/UI/data/locale/ja-JP.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/ja-JP.ini
Changed
Import="インポート"
Export="エクスポート"
+Updater.Title="利用可能な更新"
+Updater.Text="利用可能な更新があります:"
+Updater.UpdateNow="今すぐ更新"
+Updater.RemindMeLater="後で通知"
+Updater.Skip="バージョンをスキップする"
+Updater.Running.Title="現在アクティブなプログラム"
+Updater.Running.Text="出力が現在アクティブです。更新を試みる前にアクティブな出力をシャットダウンしてください。"
+Updater.NoUpdatesAvailable.Title="利用可能な更新はありません"
+Updater.NoUpdatesAvailable.Text="現在利用可能な更新はありません"
+Updater.FailedToLaunch="アップデータの起動に失敗しました"
+Updater.GameCaptureActive.Title="ゲームキャプチャがアクティブ"
+Updater.GameCaptureActive.Text="ゲームキャプチャフックライブラリが現在使用中です。キャプチャされているすべてのゲーム/プログラムを閉じて (またはwindowsを再起動して) からもう一度やり直してください。"
+
QuickTransitions.SwapScenes="トランジション後にプレビュー/出力シーンを入れ替え"
QuickTransitions.SwapScenesTT="(出力のオリジナルシーンがまだ存在する場合)、トランジション後のプレビューと出力シーンを入れ替えます。\nこれは出力のオリジナルシーンに加えられた可能性があるすべての変更を元に戻しません。"
QuickTransitions.DuplicateScene="シーン複製"
ConfirmRemove.Text="'$1' を削除してもよろしいですか?"
ConfirmRemove.TextMultiple="選択した %1 項目を削除してもよろしいですか?"
+Output.StartStreamFailed="配信開始に失敗しました"
+Output.StartRecordingFailed="録画開始に失敗しました"
+Output.StartReplayFailed="リプレイバッファーの開始に失敗しました"
+Output.StartFailedGeneric="出力開始に失敗しました。詳細はログを確認してください。\n\n注: NVENCまたはAMDエンコーダを使用している場合は、ビデオドライバが最新のものであるかを確認してください。"
+
Output.ConnectFail.Title="接続失敗"
Output.ConnectFail.BadPath="パスかURLが無効です。再確認して下さい。"
Output.ConnectFail.ConnectFailed="サーバーへの接続に失敗しました"
Deinterlacing.TopFieldFirst="トップフィールドが先"
Deinterlacing.BottomFieldFirst="ボトムフィールドが先"
+VolControl.SliderUnmuted="'%1' の音量スライダー: %2"
+VolControl.SliderMuted="'%1' の音量スライダー: %2 (現在ミュート)"
+VolControl.Mute="'%1' をミュート"
+VolControl.Properties="'%1' のプロパティ"
+
Basic.Main.AddSceneDlg.Title="シーン追加"
Basic.Main.AddSceneDlg.Text="シーンの名前を入力してください"
Basic.Settings.General="一般"
Basic.Settings.General.Theme="テーマ"
Basic.Settings.General.Language="言語"
+Basic.Settings.General.EnableAutoUpdates="起動時に自動的に更新を確認する"
Basic.Settings.General.WarnBeforeStartingStream="配信を開始するときに確認ダイアログを表示する"
Basic.Settings.General.WarnBeforeStoppingStream="配信を停止するときに確認ダイアログを表示する"
+Basic.Settings.General.Projectors="プロジェクター"
Basic.Settings.General.HideProjectorCursor="プロジェクター上のカーソルを非表示にする"
Basic.Settings.General.ProjectorAlwaysOnTop="プロジェクタを常に手前に表示させる"
Basic.Settings.General.Snapping="ソース配置のスナップ"
Basic.Settings.General.SnapDistance="スナップ感度"
Basic.Settings.General.RecordWhenStreaming="配信時に自動的に録画"
Basic.Settings.General.KeepRecordingWhenStreamStops="配信が停止しても録画を継続"
-Basic.Settings.General.SysTrayEnabled="システムトレイアイコンを有効にする"
+Basic.Settings.General.ReplayBufferWhileStreaming="配信時に自動的にリプレイバッファーを開始"
+Basic.Settings.General.KeepReplayBufferStreamStops="配信停止時にリプレイバッファーをアクティブにしておく"
+Basic.Settings.General.SysTray="システムトレイ"
Basic.Settings.General.SysTrayWhenStarted="起動時にシステムトレイへ最小化"
+Basic.Settings.General.SystemTrayHideMinimize="タスクバーの代わりにシステムトレイに常に最小化する"
+Basic.Settings.General.SaveProjectors="終了時にプロジェクターを保存する"
Basic.Settings.Stream="配信"
Basic.Settings.Stream.StreamType="配信種別"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="音声エンコーダ"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="音声エンコーダ設定 (ある場合)"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="マルチプレクサーの設定 (ある場合)"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="キーフレーム間隔 (フレーム)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="すべてのコーデックを表示 (潜在的に互換性がない場合でも)"
FilenameFormatting.completer="%CCYY-%MM-%DD %hh-%mm-%ss\n%YY-%MM-%DD %hh-%mm-%ss\n%Y-%m-%d %H-%M-%S\n%y-%m-%d %H-%M-%S\n%a %Y-%m-%d %H-%M-%S\n%A %Y-%m-%d %H-%M-%S\n%Y-%b-%d %H-%M-%S\n%Y-%B-%d %H-%M-%S\n%Y-%m-%d %I-%M-%S-%p\n%Y-%m-%d %H-%M-%S-%z\n%Y-%m-%d %H-%M-%S-%Z"
Basic.Settings.Advanced.Video.ColorRange="YUV 色範囲"
Basic.Settings.Advanced.Video.ColorRange.Partial="一部"
Basic.Settings.Advanced.Video.ColorRange.Full="全部"
+Basic.Settings.Advanced.Audio.MonitoringDevice="音声モニタリングデバイス"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="既定"
Basic.Settings.Advanced.StreamDelay="遅延配信"
Basic.Settings.Advanced.StreamDelay.Duration="継続時間 (秒)"
Basic.Settings.Advanced.StreamDelay.Preserve="再接続時にカットオフポイントを保持する (増加遅延)"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="概算メモリ使用量: %1 MB"
Basic.Settings.Advanced.Network="ネットワーク"
Basic.Settings.Advanced.Network.BindToIP="IP選択"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="新しいネットワークコードを有効にする"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="低遅延モード"
Basic.AdvAudio="オーディオの詳細プロパティ"
Basic.AdvAudio.Name="名称"
Basic.AdvAudio.Mono="モノラルにダウンミックス"
Basic.AdvAudio.Panning="パンニング"
Basic.AdvAudio.SyncOffset="同期オフセット (ミリ秒)"
+Basic.AdvAudio.Monitoring="音声モニタリング"
+Basic.AdvAudio.Monitoring.None="モニターオフ"
+Basic.AdvAudio.Monitoring.MonitorOnly="モニターのみ (出力はミュート)"
+Basic.AdvAudio.Monitoring.Both="モニターと出力"
Basic.AdvAudio.AudioTracks="トラック"
Basic.Settings.Hotkeys="ホットキー"
OutputWarnings.NoTracksSelected="少なくとも 1 つのトラックを選択する必要があります"
OutputWarnings.MultiTrackRecording="警告: 特定のフォーマット (FLVなど) は1つの録画で複数のトラックをサポートしていません"
+OutputWarnings.MP4Recording="警告: ファイルをファイナライズ出来ない場合 (例えば、BSOD、電力損失などの結果として) はMP4に保存された録画は回復不能になります。 複数の音声トラックを録画する場合はMKVの利用を検討して録画の終了後にMP4に再多重化してください。(ファイル -> 録画の再多重化)"
obs-studio-17.0.2.tar.xz/UI/data/locale/ko-KR.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/ko-KR.ini
Changed
Import="가져오기"
Export="내보내기"
+Updater.Title="사용가능한 판올림이 있습니다"
+Updater.Text="새 판올림이 준비되었습니다:"
+Updater.UpdateNow="지금 판올림하기"
+Updater.RemindMeLater="나중에 다시 알림"
+Updater.Skip="이번 버전 건너뛰기"
+Updater.Running.Title="현재 활성화된 프로그램"
+Updater.Running.Text="판올림 전에 활성화되어 있는 출력을 먼저 꺼주세요"
+Updater.NoUpdatesAvailable.Title="가능한 판올림이 없습니다"
+Updater.NoUpdatesAvailable.Text="현재 사용가능한 판올림이 없습니다"
+Updater.FailedToLaunch="판올림 도우미를 실행할 수 없습니다"
+Updater.GameCaptureActive.Title="게임 캡쳐 기능이 활성화 중"
+Updater.GameCaptureActive.Text="게임 캡쳐 기능을 현재 사용 중입니다. 캡쳐 중인 게임이나 프로그램을 종료(혹은 윈도우를 재시작) 한 다음 다시 시도하세요."
+
QuickTransitions.SwapScenes="전환 후 미리 보기/출력 장면을 교체"
QuickTransitions.SwapScenesTT="(만약 출력 쪽 원본 장면이 있을 때) 전환 작업 이후 미리 보기와 출력 장면을 교체합니다. \n출력 쪽 원본 장면에서 변경한 내용은 사라지지 않습니다."
QuickTransitions.DuplicateScene="장면 복제"
ConfirmRemove.Text="'$1'을 정말로 제거하시겠습니까?"
ConfirmRemove.TextMultiple="정말로 %1 개의 항목을 제거하겠습니까?"
+Output.StartStreamFailed="방송을 시작하지 못했습니다"
+Output.StartRecordingFailed="녹화를 시작하지 못했습니다"
+Output.StartReplayFailed="리플레이 버퍼를 시작하지 못했습니다"
+Output.StartFailedGeneric="출력을 시작하지 못했습니다. 기록 파일을 확인하십시오.\n\n참고: NVENC 혹은 AMD 인코더를 사용하고 있다면 드라이버를 최신 버전으로 유지하십시오."
+
Output.ConnectFail.Title="연결에 실패했음"
Output.ConnectFail.BadPath="잘못된 경로 혹은 연결 주소입니다. 유효한 값인지 설정을 확인하시기 바랍니다. "
Output.ConnectFail.ConnectFailed="서버에 연결하지 못했습니다"
Deinterlacing.TopFieldFirst="상위 필드 우선"
Deinterlacing.BottomFieldFirst="하단 필드 우선"
+VolControl.SliderUnmuted="'%1'의 음량 조절: %2"
+VolControl.SliderMuted="'%1'의 음량 조절: %2 (현재 음소거)"
+VolControl.Mute="음소거 '%1'"
+
Basic.Main.AddSceneDlg.Title="장면 추가"
Basic.Main.AddSceneDlg.Text="장면의 이름을 입력하십시오"
Basic.Settings.General="일반"
Basic.Settings.General.Theme="테마"
Basic.Settings.General.Language="언어"
+Basic.Settings.General.EnableAutoUpdates="프로그램을 시작할 때 자동으로 판올림이 있나 확인"
Basic.Settings.General.WarnBeforeStartingStream="방송을 시작할 때 확인 대화 상자 표시"
Basic.Settings.General.WarnBeforeStoppingStream="방송을 중단할 때 확인 대화 상자 표시"
+Basic.Settings.General.Projectors="프로젝터"
Basic.Settings.General.HideProjectorCursor="프로젝터 위 커서 숨기기"
Basic.Settings.General.ProjectorAlwaysOnTop="프로젝터를 항상 위로"
Basic.Settings.General.Snapping="소스를 자석처럼 달라붙여서 정렬"
Basic.Settings.General.SnapDistance="자석 감도"
Basic.Settings.General.RecordWhenStreaming="방송 시 자동으로 녹화"
Basic.Settings.General.KeepRecordingWhenStreamStops="방송을 중단하더라도 녹화는 유지"
-Basic.Settings.General.SysTrayEnabled="시스템 트레이 아이콘 활성화"
+Basic.Settings.General.ReplayBufferWhileStreaming="방송 시 리플레이 버퍼를 자동으로 시작"
+Basic.Settings.General.KeepReplayBufferStreamStops="방송 중단에도 리플레이 버퍼를 계속 활성화"
+Basic.Settings.General.SysTray="시스템 트레이"
Basic.Settings.General.SysTrayWhenStarted="시작할 때 시스템 트레이로 최소화"
+Basic.Settings.General.SystemTrayHideMinimize="작업 표시줄 대신 시스템 트레이에 항상 최소화"
+Basic.Settings.General.SaveProjectors="종료 시 프로젝터 저장"
Basic.Settings.Stream="방송"
Basic.Settings.Stream.StreamType="방송 형식"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="오디오 인코더"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="오디오 인코더 설정 (지원되는 경우)"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="다중화 설정 (제공되는 경우)"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="키프레임 간격 (프레임 단위)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="모든 코덱을 표시 (호환이 안되는 것도 포함)"
FilenameFormatting.completer="%CCYY-%MM-%DD %hh-%mm-%ss\n%YY-%MM-%DD %hh-%mm-%ss\n%Y-%m-%d %H-%M-%S\n%y-%m-%d %H-%M-%S\n%a %Y-%m-%d %H-%M-%S\n%A %Y-%m-%d %H-%M-%S\n%Y-%b-%d %H-%M-%S\n%Y-%B-%d %H-%M-%S\n%Y-%m-%d %I-%M-%S-%p\n%Y-%m-%d %H-%M-%S-%z\n%Y-%m-%d %H-%M-%S-%Z"
Basic.Settings.Advanced.Video.ColorRange="YUV 색상 범위"
Basic.Settings.Advanced.Video.ColorRange.Partial="부분"
Basic.Settings.Advanced.Video.ColorRange.Full="전체"
+Basic.Settings.Advanced.Audio.MonitoringDevice="오디오 모니터링 장치"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="기본값"
Basic.Settings.Advanced.StreamDelay="방송 지연"
Basic.Settings.Advanced.StreamDelay.Duration="기간 (초)"
Basic.Settings.Advanced.StreamDelay.Preserve="재접속 시 잘려나간 지점 보관 (지연시간 증가)"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="예상되는 메모리 사용량: %1 MB"
Basic.Settings.Advanced.Network="네트워크"
Basic.Settings.Advanced.Network.BindToIP="IP에 고정"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="새로운 네트워크 코드 활성화"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="짧은 지연시간 모드"
Basic.AdvAudio="오디오 고급 설정"
Basic.AdvAudio.Name="이름"
Basic.AdvAudio.Mono="모노로 강제 송출"
Basic.AdvAudio.Panning="패닝"
Basic.AdvAudio.SyncOffset="싱크 오프셋 (ms)"
+Basic.AdvAudio.Monitoring="오디오 모니터링"
+Basic.AdvAudio.Monitoring.None="모니터링 끔"
+Basic.AdvAudio.Monitoring.MonitorOnly="모니터링만 (출력은 제거)"
+Basic.AdvAudio.Monitoring.Both="모니터링과 출력"
Basic.AdvAudio.AudioTracks="트랙"
Basic.Settings.Hotkeys="단축키"
OutputWarnings.NoTracksSelected="최소 하나의 트랙을 선택해야 합니다"
OutputWarnings.MultiTrackRecording="경고: 일부 형식(예를 들어 FLV)은 녹화 하나에 여러 개의 트랙을 지원하지 않습니다"
+OutputWarnings.MP4Recording="경고: MP4로 녹화를 하면 파일이 마무리가 되지 않았을 때 (예를 들어 컴퓨터가 급작스럽게 꺼지거나 블루 스크린 오류가 일어나는 경우) 복구할 수 없습니다. 여러 개의 오디오 트랙을 녹음하고 싶다면 MKV 확장자로 녹화 한 뒤 재다중화 작업을 통해 mp4로 전환하십시오. (파일->재다중화 녹화)"
obs-studio-17.0.2.tar.xz/UI/data/locale/lt-LT.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/lt-LT.ini
Changed
Top="Iš viršaus"
Bottom="Iš apačios"
+
QuickTransitions.SwapScenes="Sukeisti Peržiūros/Išvesties scenas po Perėjimo"
QuickTransitions.SwapScenesTT="Sukeičia peržiūros ir išvesties scenas po perėjimo įvykdymo (jei originali išvesties scena vis dar egzistuoja).\nTai neatšauks jokių pakeitimų kurie galima buvo atlikti originalioje išvesties scenoje."
QuickTransitions.DuplicateScene="Dubliuoti Sceną"
ConfirmRemove.Title="Pašalinimo patvirtinimas"
ConfirmRemove.Text="Ar tikrai norite pašalinti '$1'?"
+
Output.ConnectFail.Title="Nepavyko prisijungti"
Output.ConnectFail.BadPath="Neteisingas kelias arba jungimosi URL. Prašome patikrinti nustatymus ir įsitikinti, kad jie teisingi."
Output.ConnectFail.ConnectFailed="Nepavyko prisijungti prie serverio"
Deinterlacing.TopFieldFirst="Piršutinis puskadris pirmas"
Deinterlacing.BottomFieldFirst="Apatinis puskadris pirmas"
+
Basic.Main.AddSceneDlg.Title="Pridėti sceną"
Basic.Main.AddSceneDlg.Text="Įveskite pasirinktą scenos pavadinimą"
obs-studio-17.0.2.tar.xz/UI/data/locale/ms-MY.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/ms-MY.ini
Changed
Minutes="Minit"
Seconds="Saat"
+
QuickTransitions.SwapScenes="Tukar Pratonton/Pengeluaran Adegan Selepas Peralihan"
QuickTransitions.SwapScenesTT="Menukarkan pratonton dan pengeluaran adegan-adegan selepas peralihan(jika pengeluaran adegan mash wujud).\nIni tidak akan mengundurkan sebarang perubahan yang mungkin telah dilakukan pada pengeluaran adegan yang asal."
QuickTransitions.DuplicateScene="Klonkan Adegan"
ConfirmRemove.Text="Adakah anda pasti untuk buang '$1'?"
ConfirmRemove.TextMultiple="Adakah anda yakin untuk buang %1 barang?"
+
Output.ConnectFail.Title="Penyambungan gagal"
Output.ConnectFail.BadPath="Sambungan URL atau Laluan yang tidak sah. Sila semak semula tetapan anda to mengesahkan bahawa semuanya sah."
Output.ConnectFail.ConnectFailed="Penyambungan ke pelayan gagal"
Deinterlacing.TopFieldFirst="Bahagian Atas Dahulu"
Deinterlacing.BottomFieldFirst="Bahagian Bawah Dahulu"
+
Basic.Main.AddSceneDlg.Title="Tambah Adegan"
Basic.Main.AddSceneDlg.Text="Sila taip nama adegan"
obs-studio-17.0.2.tar.xz/UI/data/locale/nb-NO.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/nb-NO.ini
Changed
Right="Høyre"
Top="Topp"
Bottom="Bunn"
+Reset="Tilbakestill"
+Hours="Timer"
+Minutes="Minutter"
+Seconds="Sekunder"
+Deprecated="Foreldet"
+ReplayBuffer="Omspill Buffer"
+Import="Importer"
+Export="Eksporter"
+
+Updater.Title="Ny oppdatering tilgjengelig"
+Updater.Text="Det finnes en ny oppdatering:"
+Updater.UpdateNow="Oppdater nå"
+Updater.RemindMeLater="Påminn meg senere"
+Updater.Skip="Hopp over versjon"
+Updater.Running.Title="Programmet er aktiv"
+Updater.NoUpdatesAvailable.Title="Ingen oppdateringer er tilgjengelig"
+Updater.NoUpdatesAvailable.Text="Ingen oppdateringer er tilgjengelig"
QuickTransitions.SwapScenes="Bytt forhåndsvisnings-/utgangsscener etter overgang"
QuickTransitions.SwapScenesTT="Bytter forhåndsvisnings- og utgangsscenen etter overgang, hvis den originale utgangsscenen fortsatt eksisterer.\nDette vil ikke tilbakestille endringer på den originale utgangsscenen."
ConfirmRemove.Title="Bekreft Fjerning"
ConfirmRemove.Text="Er du sikker på at du vil fjerne '$1'?"
+ConfirmRemove.TextMultiple="Er du sikker du ønsker å fjerne %1 filer?"
+
+Output.StartStreamFailed="Kan ikke starte streaming"
+Output.StartRecordingFailed="Kan ikke starte innspillingen"
Output.ConnectFail.Title="Tilkobling misklytes"
Output.ConnectFail.BadPath="Ugyldig filbane eller tilkoblings-URL. Vennligst bekreft at instillingene dine er riktige."
Output.RecordNoSpace.Msg="Det er ikke nok diskplass til å fortsette opptaket."
Output.RecordError.Title="Innspillingsfeil"
Output.RecordError.Msg="Det oppstod en uspesifisert feil under opptaket."
+Output.ReplayBuffer.NoHotkey.Title="Ingen hurtigtast satt!"
+Output.ReplayBuffer.NoHotkey.Msg="Ingen lagrings hurtigtast satt for omspillings buffer. Venligst sett \"Lagre\" hurtigtasten i bruk for å lagre opptak."
Output.BadPath.Title="Ugyldig Filbane"
Output.BadPath.Text="Den oppgitte fillagringsbanen er ugyldig. Vennligst kontrollér instillingene dine og bekreft at filbanen er gyldig."
Basic.Main.PreviewConextMenu.Enable="Aktiver forhåndsvisning"
+ScaleFiltering="Skala Filtrering"
+ScaleFiltering.Point="Punkt"
+ScaleFiltering.Bilinear="Bilineær"
+ScaleFiltering.Bicubic="Bikubisk"
+ScaleFiltering.Lanczos="Lanczos"
Deinterlacing="Avsammenfletting"
Deinterlacing.Discard="Forkast"
Deinterlacing.TopFieldFirst="Øverste felt først"
Deinterlacing.BottomFieldFirst="Nederste felt først"
+
Basic.Main.AddSceneDlg.Title="Ny Scene"
Basic.Main.AddSceneDlg.Text="Vennligst gi et navn til scenen."
Basic.Main.Sources="Kilder"
Basic.Main.Connecting="Kobler til…"
Basic.Main.StartRecording="Start Opptak"
+Basic.Main.StartReplayBuffer="Start Omspill Buffer"
Basic.Main.StartStreaming="Start Strømming"
Basic.Main.StopRecording="Stopp Opptak"
Basic.Main.StoppingRecording="Stanser innspilling…"
+Basic.Main.StopReplayBuffer="Stopp Omspill Buffer"
+Basic.Main.StoppingReplayBuffer="Stopper Omspill Bufferen..."
Basic.Main.StopStreaming="Stopp Strømming"
Basic.Main.StoppingStreaming="Stanser strøm…"
Basic.Main.ForceStopStreaming="Stopp strømming (forkast forsinkelse)"
Basic.MainMenu.Edit.Redo="&Gjør om"
Basic.MainMenu.Edit.UndoAction="&Angre $1"
Basic.MainMenu.Edit.RedoAction="&Gjør om $1"
+Basic.MainMenu.Edit.LockPreview="Lås Forhåndsvisning"
+Basic.MainMenu.Edit.Scale="Forhåndsvisning & Skalering"
+Basic.MainMenu.Edit.Scale.Window="Tilpass til vindu"
Basic.MainMenu.Edit.Transform="&Transformer"
Basic.MainMenu.Edit.Transform.EditTransform="&Redigér transformering..."
+Basic.MainMenu.Edit.Transform.CopyTransform="Kopiere transformering"
Basic.MainMenu.Edit.Transform.ResetTransform="&Angre transformering"
Basic.MainMenu.Edit.Transform.Rotate90CW="Rotér 90 grader med klokka"
Basic.MainMenu.Edit.Transform.Rotate90CCW="Rotér 90 grader mot klokka"
Basic.MainMenu.Edit.Order.MoveToBottom="Legg på &bunnen"
Basic.MainMenu.Edit.AdvAudio="&Avanserte lydinstillinger"
+Basic.MainMenu.View="&Vis"
+Basic.MainMenu.View.Toolbars="%Verktøylinje"
+Basic.MainMenu.View.SceneTransitions="Sceneoverganger"
+Basic.MainMenu.View.StatusBar="Statuslinje"
Basic.MainMenu.SceneCollection="&Scenesamling"
Basic.MainMenu.Profile="&Profil"
+Basic.MainMenu.Profile.Import="Importer Profil"
+Basic.MainMenu.Profile.Export="Eksporter Profil"
+Basic.MainMenu.SceneCollection.Import="Importer Scenesamling"
+Basic.MainMenu.SceneCollection.Export="Eskporter Scenesamling"
+Basic.MainMenu.Profile.Exists="Profilen eksisterer allerede"
+Basic.MainMenu.SceneCollection.Exists="Scenesamlingen eksisterer allerede"
+Basic.MainMenu.Tools="&Verktøy"
Basic.MainMenu.Help="&Hjelp"
Basic.MainMenu.Help.Website="Besøk &nettsted"
Basic.Settings.General.Language="Språk"
Basic.Settings.General.WarnBeforeStartingStream="Vis bekreftelsesdialogboks når du starter strømming"
Basic.Settings.General.WarnBeforeStoppingStream="Vis bekreftelsesdialogboks når stanser strømming"
+Basic.Settings.General.Projectors="Projektorer"
Basic.Settings.General.HideProjectorCursor="Skjul musepekeren over projektorer"
Basic.Settings.General.Snapping="Festing ved kildejustering"
Basic.Settings.General.ScreenSnapping="Fest kilder til kanten av skjermen"
Basic.Settings.General.SnapDistance="Festingfølsomhet"
Basic.Settings.General.RecordWhenStreaming="Spill inn automatisk ved strømming"
Basic.Settings.General.KeepRecordingWhenStreamStops="Fortsett innspilling etter strømming"
+Basic.Settings.General.SysTrayWhenStarted="Minimer til systemstatusfelt ved oppstart"
Basic.Settings.Stream="Strøm"
Basic.Settings.Stream.StreamType="Strømmetype"
Basic.Settings.Output.Mode.Simple="Enkel"
Basic.Settings.Output.Mode.Adv="Avansert"
Basic.Settings.Output.Mode.FFmpeg="FFmpeg-utgang"
+Basic.Settings.Output.UseReplayBuffer="Aktiver Omspill Buffer"
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Maksimal Omspill Tid (sekunder)"
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Maksimalt Minne (Megabytes)"
+Basic.Settings.Output.ReplayBuffer.Estimate="Anslått minne bruk. %1 MB"
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Kan ikke beregne minnebruk. Vennligst sett maksimalt minnebrukgrense."
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Merk: Sørg for å angi en hurtigtast for omspill bufferen i hurtigtast innstillingen)"
+Basic.Settings.Output.ReplayBuffer.Suffix="Suffiks"
Basic.Settings.Output.Simple.SavePath="Opptaksbane"
Basic.Settings.Output.Simple.RecordingQuality="Opptakskvalitet"
Basic.Settings.Output.Simple.RecordingQuality.Stream="Samme som strøm"
Basic.Settings.Output.Simple.Warn.MultipleQSV="Advarsel: du kan ikke bruke flere separate QSV-kodere når du strømmer og tar opp samtidig. Hvis du ønsker gjøre begge på samme tid må du endre strømme- eller opptakskoderen."
Basic.Settings.Output.Simple.Encoder.Software="Programvare (x264)"
Basic.Settings.Output.Simple.Encoder.Hardware.QSV="Maskinvare (QSV)"
+Basic.Settings.Output.Simple.Encoder.Hardware.AMD="Maskinvare (AMD)"
Basic.Settings.Output.Simple.Encoder.Hardware.NVENC="Maskinvare (NVENC)"
Basic.Settings.Output.Simple.Encoder.SoftwareLowCPU="Programvare (x264 forhåndsinstilling for liten prosessorbruk, øker filstørrelsen)"
Basic.Settings.Output.VideoBitrate="Bildeoverføringshastighet"
Basic.Settings.Output.Adv.Audio.Track2="Spor 2"
Basic.Settings.Output.Adv.Audio.Track3="Spor 3"
Basic.Settings.Output.Adv.Audio.Track4="Spor 4"
+Basic.Settings.Output.Adv.Audio.Track5="Spor 5"
+Basic.Settings.Output.Adv.Audio.Track6="Spor 6"
Basic.Settings.Output.Adv.Recording="Opptak"
Basic.Settings.Output.Adv.Recording.Type="Type"
Basic.Settings.Audio.UnknownAudioDevice="[Enhet ikke tilkoblet eller ikke tilgjengelig]"
Basic.Settings.Advanced="Avansert"
+Basic.Settings.Advanced.General.ProcessPriority="Prosessprioritet"
+Basic.Settings.Advanced.General.ProcessPriority.High="Høy"
+Basic.Settings.Advanced.General.ProcessPriority.AboveNormal="Over Normal"
+Basic.Settings.Advanced.General.ProcessPriority.Normal="Normal"
+Basic.Settings.Advanced.General.ProcessPriority.Idle="Inaktiv"
Basic.Settings.Advanced.FormatWarning="Advarsel: Fargeformater andre enn NV12 er ment for opptak. Disse formatene anbefales ikke ved strømming, da det fører til økt prosessorbruk som følge av fargeformatkonvertering."
Basic.Settings.Advanced.Audio.BufferingTime="Lydbuffertid"
Basic.Settings.Advanced.Video.ColorFormat="Fargeformat"
Basic.Settings.Advanced.StreamDelay.Duration="Varighet (sekunder)"
Basic.Settings.Advanced.StreamDelay.Preserve="Bevar avkuttingspunktet (øk forsinkelse) ved tilbakekobling"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Anslått minnebruk: %1 MB"
+Basic.Settings.Advanced.Network="Nettverk"
+Basic.Settings.Advanced.Network.BindToIP="Bind til IP"
Basic.AdvAudio="Avanserte lydinstillinger"
Basic.AdvAudio.Name="Navn"
Basic.Hotkeys.SelectScene="Bytt til scene"
+Basic.SystemTray.Show="Vis"
+Basic.SystemTray.Hide="Skjul"
+Basic.SystemTray.Message.Reconnecting="Frakoblet. Kobler til på nytt..."
Hotkeys.Insert="Insert"
Hotkeys.Delete="Delete"
obs-studio-17.0.2.tar.xz/UI/data/locale/nl-NL.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/nl-NL.ini
Changed
Import="Importeer"
Export="Exporteer"
+Updater.Title="Update beschikbaar"
+Updater.Text="Er is een update beschikbaar:"
+Updater.UpdateNow="Nu updaten"
+Updater.RemindMeLater="Herinner mij later"
+Updater.Skip="Sla deze versie over"
+Updater.Running.Title="Programma actief"
+Updater.Running.Text="Er is momenteel uitvoer actief, stop alle actieve uitvoer voor je probeert te updaten"
+Updater.NoUpdatesAvailable.Title="Geen updates beschikbaar"
+Updater.NoUpdatesAvailable.Text="Er zijn momenteel geen updates beschikbaar"
+Updater.FailedToLaunch="Starten van updater is mislukt"
+Updater.GameCaptureActive.Title="Game capture actief"
+Updater.GameCaptureActive.Text="Er is momenteel een game capture hook in gebruik. Sluit alle games/programma's af die opgenomen worden (of herstart Windows) en probeer het opnieuw."
+
QuickTransitions.SwapScenes="Preview-/uitvoerscenes verwisselen na overgang"
QuickTransitions.SwapScenesTT="Verwisselt de preview- en uitvoercenes na een overgang (als de originele uitvoerscène nog bestaat.)\nDit zal geen veranderingen ongedaan maken die mogelijk zijn gemaakt aan de originele uitvoerscène."
QuickTransitions.DuplicateScene="Scène Dupliceren"
ConfirmRemove.Text="Weet je zeker dat je '$1' wil verwijderen?"
ConfirmRemove.TextMultiple="Weet je zeker dat je %1 elementen wil verwijderen?"
+Output.StartStreamFailed="Het starten van de stream is mislukt"
+Output.StartRecordingFailed="Het starten van de opname is mislukt"
+Output.StartReplayFailed="Het starten van de replay buffer is mislukt"
+Output.StartFailedGeneric="Het starten van de uitvoer is mislukt. Controleer de logbestanden voor meer informatie.\n\nLet op: Als je gebruik maakt van de NVENC of AMD encoders, controleer of de drivers up to date zijn."
+
Output.ConnectFail.Title="Kan geen verbinding maken"
Output.ConnectFail.BadPath="Ongeldig pad of verbindings-url. Controleer a.u.b. of je instellingen geldig zijn."
Output.ConnectFail.ConnectFailed="Kan geen verbinding maken met de server"
Deinterlacing.TopFieldFirst="Bovenste Veld Eerst"
Deinterlacing.BottomFieldFirst="Onderste Veld Eerst"
+VolControl.SliderUnmuted="Volumeregelaar voor '%1': %2"
+VolControl.SliderMuted="Volumeregelaar voor '%1': %2 (momenteel muted)"
+VolControl.Mute="Mute '%1'"
+VolControl.Properties="Eigenschappen van '%1'"
+
Basic.Main.AddSceneDlg.Title="Scène Toevoegen"
Basic.Main.AddSceneDlg.Text="Voer a.u.b. de naam van de scène in"
Basic.Settings.General="Algemeen"
Basic.Settings.General.Theme="Thema"
Basic.Settings.General.Language="Taal"
+Basic.Settings.General.EnableAutoUpdates="Automatisch controleren op updates tijdens het opstarten"
Basic.Settings.General.WarnBeforeStartingStream="Laat bevestigingsvenster zien bij het starten van streams"
Basic.Settings.General.WarnBeforeStoppingStream="Laat bevestiginsvenster zien bij het stoppen van streams"
+Basic.Settings.General.Projectors="Projectoren"
Basic.Settings.General.HideProjectorCursor="Verberg cursor boven projectors"
Basic.Settings.General.ProjectorAlwaysOnTop="Houd projectoren altijd bovenaan"
Basic.Settings.General.Snapping="Bronuitlijning"
Basic.Settings.General.SnapDistance="Gevoeligheid"
Basic.Settings.General.RecordWhenStreaming="Stream automatisch opnemen"
Basic.Settings.General.KeepRecordingWhenStreamStops="Opname voortzetten als de stream stopt"
-Basic.Settings.General.SysTrayEnabled="Systeemvakicoon weergeven"
+Basic.Settings.General.ReplayBufferWhileStreaming="Replay buffer tegelijk starten met stream"
+Basic.Settings.General.KeepReplayBufferStreamStops="Replay buffer actief houden als stream stopt"
+Basic.Settings.General.SysTray="Systeemvak"
Basic.Settings.General.SysTrayWhenStarted="Naar systeemvak minimaliseren bij opstarten"
+Basic.Settings.General.SystemTrayHideMinimize="Altijd minimaliseren naar het systeemvak in plaats van de taakbalk"
+Basic.Settings.General.SaveProjectors="Projectors opslaan bij afsluiten"
Basic.Settings.Stream="Stream"
Basic.Settings.Stream.StreamType="Stream Type"
Basic.Settings.Advanced.Video.ColorRange="YUV-Kleurbereik"
Basic.Settings.Advanced.Video.ColorRange.Partial="Partial"
Basic.Settings.Advanced.Video.ColorRange.Full="Full"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Audio monitoring apparaat"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Standaard"
Basic.Settings.Advanced.StreamDelay="Streamvertraging"
Basic.Settings.Advanced.StreamDelay.Duration="Duur (seconden)"
Basic.Settings.Advanced.StreamDelay.Preserve="Hervat op het eindpunt (verhoog vertraging) bij opnieuw verbinden"
Basic.AdvAudio.Mono="Downmixen naar Mono"
Basic.AdvAudio.Panning="Pannen"
Basic.AdvAudio.SyncOffset="Sync Offset (ms)"
+Basic.AdvAudio.Monitoring="Audio monitoring"
+Basic.AdvAudio.Monitoring.None="Niet monitoren"
+Basic.AdvAudio.Monitoring.MonitorOnly="Alleen monitoren (uitvoer gedempt)"
+Basic.AdvAudio.Monitoring.Both="Monitoren en uitvoeren"
Basic.AdvAudio.AudioTracks="Sporen"
Basic.Settings.Hotkeys="Sneltoetsen"
obs-studio-17.0.2.tar.xz/UI/data/locale/pl-PL.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/pl-PL.ini
Changed
Import="Importuj"
Export="Eksportuj"
+Updater.Title="Dostępna jest nowa aktualizacja"
+Updater.Text="Dostępna jest nowa aktualizacja:"
+Updater.UpdateNow="Uaktualnij teraz"
+Updater.RemindMeLater="Przypomnij mi później"
+Updater.Skip="Pomiń wersję"
+Updater.Running.Title="Aplikacja jest uruchomiona"
+Updater.Running.Text="Wyjścia są aktualnie aktywne, proszę zamknąć wszystkie aktywne wyjścia przed rozpoczęciem procesu aktualizacji"
+Updater.NoUpdatesAvailable.Title="Brak dostępnych aktualizacji"
+Updater.NoUpdatesAvailable.Text="Brak dostępnych aktualizacji"
+Updater.FailedToLaunch="Nie udało się uruchomić aktualizacji"
+Updater.GameCaptureActive.Title="Przechwytywanie gry aktywne"
+Updater.GameCaptureActive.Text="Przechwytywanie gry jest aktywne. Proszę o zamknięcie wszelkich przechwytywanych gier/aplikacji (lub ponowne uruchomienie systemu) i spróbowanie później."
+
QuickTransitions.SwapScenes="Zamień podgląd/wyjście scen po przejściu"
QuickTransitions.SwapScenesTT="Zamienia podgląd i wyjście scen po przejściu (jeżeli wyjście oryginalnej sceny istnieje).\nNie przywraca to zmian jakie zostały dokonane w oryginalnej scenie."
QuickTransitions.DuplicateScene="Duplikuj scenę"
ConfirmRemove.Text="Czy na pewno chcesz usunąć '$1'?"
ConfirmRemove.TextMultiple="Liczba elementów do usunięcia: %1. Czy na pewno chcesz je usunąć?"
+Output.StartStreamFailed="Nie udało się rozpocząć streamowania"
+Output.StartRecordingFailed="Nie udało się rozpocząć nagrywania"
+Output.StartReplayFailed="Nie udało się rozpocząć nagrywania powtórek"
+Output.StartFailedGeneric="Nie udało się uruchomić wyjścia. Sprawdź szczegóły w plikach dziennika.\n\nUwaga: Sprawdź, czy posiadasz aktualne sterowniki karty graficznej, jeżeli używasz enkodera NVENC lub AMD."
+
Output.ConnectFail.Title="Nie udało się połączyć"
Output.ConnectFail.BadPath="Nieprawidłowa ścieżka lub adres URL połączenia. Sprawdź poprawność ustawień."
Output.ConnectFail.ConnectFailed="Nie udało się połączyć z serwerem"
Deinterlacing.TopFieldFirst="Najpierw pole górne"
Deinterlacing.BottomFieldFirst="Najpierw pole dolne"
+VolControl.SliderUnmuted="Suwak głośności dla '%1': %2"
+VolControl.SliderMuted="Suwak głośności dla '%1': %2 (obecnie wyciszony)"
+VolControl.Mute="Wycisz '%1'"
+VolControl.Properties="Właściwości dla '%1'"
+
Basic.Main.AddSceneDlg.Title="Dodaj scenę"
Basic.Main.AddSceneDlg.Text="Podaj nazwę sceny"
Basic.Settings.General="Główne"
Basic.Settings.General.Theme="Motyw"
Basic.Settings.General.Language="Język"
+Basic.Settings.General.EnableAutoUpdates="Automatycznie sprawdzaj dostępność aktualizacji"
Basic.Settings.General.WarnBeforeStartingStream="Pokaż komunikat potwierdzenia uruchomienia streamowania"
Basic.Settings.General.WarnBeforeStoppingStream="Pokaż komunikat potwierdzenia zatrzymania streamowania"
+Basic.Settings.General.Projectors="Projektory"
Basic.Settings.General.HideProjectorCursor="Ukryj kursor podglądu na pełnym ekranie"
Basic.Settings.General.ProjectorAlwaysOnTop="Podgląd na pełnym ekranie zawsze na wierzchu"
Basic.Settings.General.Snapping="Przyciąganie elementów źródłowych"
Basic.Settings.General.SnapDistance="Czułość przyciągania"
Basic.Settings.General.RecordWhenStreaming="Automatyczne nagrywanie streamu"
Basic.Settings.General.KeepRecordingWhenStreamStops="Zachowaj nagranie po zatrzymaniu streamu"
-Basic.Settings.General.SysTrayEnabled="Wyświetlaj ikonę w zasobniku systemowym"
+Basic.Settings.General.ReplayBufferWhileStreaming="Automatycznie rozpocznij nagrywanie powtórek w przypadku streamowania"
+Basic.Settings.General.KeepReplayBufferStreamStops="Kontynuuj nagrywanie powtórek po zatrzymaniu streamowania"
+Basic.Settings.General.SysTray="Zasobnik systemowy"
Basic.Settings.General.SysTrayWhenStarted="Minimalizuj do zasobnika systemowego podczas uruchamiania"
+Basic.Settings.General.SystemTrayHideMinimize="Zawsze minimalizuj do zasobnika systemowego zamiast do paska zadań"
+Basic.Settings.General.SaveProjectors="Zapisz konfigurację podglądów na pełnym ekranie przy zamknięciu aplikacji"
Basic.Settings.Stream="Stream"
Basic.Settings.Stream.StreamType="Typ streamu"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="Enkoder dźwięku"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="Ustawienia enkodera audio (jeśli są)"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="Ustawienia muxera (jeżeli są)"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="Odstęp między klatkami kluczowymi (klatki)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="Pokaż wszystkie kodeki (nawet potencjalnie niezgodne)"
FilenameFormatting.completer="%CCYY-%MM-%DD %hh-%mm-%ss\n%YY-%MM-%DD %hh-%mm-%ss\n%Y-%m-%d %H-%M-%S\n%y-%m-%d %H-%M-%S\n%a %Y-%m-%d %H-%M-%S\n%A %Y-%m-%d %H-%M-%S\n%Y-%b-%d %H-%M-%S\n%Y-%B-%d %H-%M-%S\n%Y-%m-%d %I-%M-%S-%p\n%Y-%m-%d %H-%M-%S-%z\n%Y-%m-%d %H-%M-%S-%Z"
Basic.Settings.Advanced.Video.ColorRange="Zakres kolorów YUV"
Basic.Settings.Advanced.Video.ColorRange.Partial="Częściowy"
Basic.Settings.Advanced.Video.ColorRange.Full="Pełny"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Monitorowane urządzenie audio"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Domyślne"
Basic.Settings.Advanced.StreamDelay="Opóźnienie streamu"
Basic.Settings.Advanced.StreamDelay.Duration="Czas trwania (s)"
Basic.Settings.Advanced.StreamDelay.Preserve="Zachowuj punkt przerwania (zwiększ opóźnienie) podczas ponownego łączenia"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Szacowane zużycie pamięci: %1 MB"
Basic.Settings.Advanced.Network="Sieć"
Basic.Settings.Advanced.Network.BindToIP="Przypisane IP"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="Aktywuj nowy kod sieciowy"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="Tryb niskich opóźnień"
Basic.AdvAudio="Zaawansowane ustawienia dźwięku"
Basic.AdvAudio.Name="Nazwa"
Basic.AdvAudio.Mono="Downmix do Mono"
Basic.AdvAudio.Panning="Rozciągnięcie dźwięku"
Basic.AdvAudio.SyncOffset="Przesunięcie dźwięku (ms)"
+Basic.AdvAudio.Monitoring="Monitorowanie urządzenia audio"
+Basic.AdvAudio.Monitoring.None="Wyłączone"
+Basic.AdvAudio.Monitoring.MonitorOnly="Tylko monitorowanie (wyjście wyłączone)"
+Basic.AdvAudio.Monitoring.Both="Monitorowanie i przekazywanie na wyjście"
Basic.AdvAudio.AudioTracks="Ścieżki"
Basic.Settings.Hotkeys="Skróty klawiszowe"
OutputWarnings.NoTracksSelected="Musisz wybrać przynajmniej jedną ścieżkę"
OutputWarnings.MultiTrackRecording="Ostrzeżenie: Pewne formaty plików (np. FLV) nie obsługują wielu ścieżek dźwiękowych"
+OutputWarnings.MP4Recording="Ostrzeżenie: Nagrania zapisanego w formacie mp4 nie będzie można odzyskać, jeśli plik nie zostanie zakończony poprawnie (np. w wyniku BSOD, braku prądu, itp.). Jeśli chcesz nagrać wiele ścieżek audio należy rozważyć użycie formatu mkv i remux nagrania do mp4 po zakończeniu (Plik -> Przepakuj nagrania)."
obs-studio-17.0.2.tar.xz/UI/data/locale/pt-BR.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/pt-BR.ini
Changed
ReplayBuffer="Buffer do Replay"
Export="Exportar"
+
QuickTransitions.SwapScenes="Trocar Cenas de Prévia/Saída após a Transição"
QuickTransitions.SwapScenesTT="Troca a preview e a saída após transicionar (se a a cena original de saída ainda exisitr).\nIsto não irá desfazer nenhuma mudança que foi feita na cena original da saída."
QuickTransitions.DuplicateScene="Duplicar Cena"
ConfirmRemove.Text="Tem certeza que deseja remover '$1'?"
ConfirmRemove.TextMultiple="Você tem certeza que quer remover esses %1 itens?"
+
Output.ConnectFail.Title="Falha ao conectar"
Output.ConnectFail.BadPath="Caminho inválido ou URL inválida. Por favor verifique se as configurações estão válidas."
Output.ConnectFail.ConnectFailed="Falha ao conectar com o Servidor"
Deinterlacing.TopFieldFirst="Campo Superior Primeiro"
Deinterlacing.BottomFieldFirst="Campo Inferior Primeiro"
+
Basic.Main.AddSceneDlg.Title="Adicionar Cena"
Basic.Main.AddSceneDlg.Text="Por favor, digite o nome da cena"
Basic.Settings.General.SnapDistance="Sensibilidade de Encaixamento"
Basic.Settings.General.RecordWhenStreaming="Gravar automaticamente quando estiver transmitindo"
Basic.Settings.General.KeepRecordingWhenStreamStops="Continuar gravando quando a transmissão parar"
-Basic.Settings.General.SysTrayEnabled="Habilitar o ícone de bandeja do sistema"
Basic.Settings.General.SysTrayWhenStarted="Minimizar para a bandeja do sistema quando iniciar"
+Basic.Settings.General.SaveProjectors="Salvar projetores ao sair"
Basic.Settings.Stream="Stream"
Basic.Settings.Stream.StreamType="Tipo de Stream"
Basic.Settings.Advanced.Video.ColorRange="Gama de cores YUV"
Basic.Settings.Advanced.Video.ColorRange.Partial="Limitado"
Basic.Settings.Advanced.Video.ColorRange.Full="Completo"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Padrão"
Basic.Settings.Advanced.StreamDelay="Atraso da transmissão"
Basic.Settings.Advanced.StreamDelay.Duration="Duração (segundos)"
Basic.Settings.Advanced.StreamDelay.Preserve="Preservar o ponto de corte (aumento de atraso) quando reconectar"
obs-studio-17.0.2.tar.xz/UI/data/locale/pt-PT.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/pt-PT.ini
Changed
Minutes="Minutos"
Seconds="Segundos"
+
QuickTransitions.SwapScenes="Trocar pré-visualização/saída de cenas Depois de uma Transição"
QuickTransitions.DuplicateScene="Duplicar cena"
QuickTransitions.EditProperties="Fontes duplicadas"
ConfirmRemove.Text="Tem a certeza que quer remover '$1'?"
ConfirmRemove.TextMultiple="Tem a certeza de que pretende remover %1 itens?"
+
Output.ConnectFail.Title="Falha ao ligar"
Output.ConnectFail.BadPath="Caminho ou endereço de ligação inválido. Por favor, verifique as suas definições para confirmar que são válidas."
Output.ConnectFail.ConnectFailed="Falhou a ligação ao servidor"
Deinterlacing.TopFieldFirst="Campo Superior Primeiro"
Deinterlacing.BottomFieldFirst="Campo Inferior Primeiro"
+
Basic.Main.AddSceneDlg.Title="Adicionar Cena"
Basic.Main.AddSceneDlg.Text="Por favor introduza o nome da cena"
Basic.Settings.General.SnapDistance="Sensibilidade do Snap"
Basic.Settings.General.RecordWhenStreaming="Gravar automaticamente quando estiver a transmitir"
Basic.Settings.General.KeepRecordingWhenStreamStops="Continuar a gravar quando a transmissão parar"
-Basic.Settings.General.SysTrayEnabled="Ativar ícone da área de notificações"
Basic.Settings.General.SysTrayWhenStarted="Minimizar para a área de notificações quando iniciado"
Basic.Settings.Stream="Transmissão"
obs-studio-17.0.2.tar.xz/UI/data/locale/ro-RO.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/ro-RO.ini
Changed
Right="Dreapta"
Top="Sus"
Bottom="Jos"
+Hours="Ore"
+Minutes="Minute"
+Seconds="Secunde"
+Deprecated="Invechit"
+Import="Importă"
+Export="Exportă"
+
QuickTransitions.SwapScenes="Comută între previzualizare/scenele de ieșire după tranziționare"
QuickTransitions.SwapScenesTT="Schimba previzualizarea si scenele de output dupa tranzitionare (în cazul în care încă există outputul scenei originale). \nAceasta nu va anula nicio modificăre care au fost făcute la outputul scenei originale."
ConfirmRemove.Title="Confirmă eliminarea"
ConfirmRemove.Text="Sigur dorești să elimini „$1”?"
+ConfirmRemove.TextMultiple="Sigur doriți sa eliminați %1 obiecte?"
+
Output.ConnectFail.Title="Eșec la conectare"
Output.ConnectFail.BadPath="URL-ul conexiunii sau calea este invalidă. Te rugăm să verifici setările pentru a confirma că acestea sunt valide."
Remux.SourceFile="Înregistrare OBS"
Remux.TargetFile="Fișier țintă"
Remux.Remux="Remux"
+Remux.OBSRecording="Înregistrare OBS"
Remux.FinishedTitle="Remuxing încheiat"
Remux.Finished="Înregistrare remuxată"
Remux.FinishedError="Înregistrare remuxată, însă fișierul poate fi incomplet"
Basic.Main.PreviewConextMenu.Enable="Activează previzualizarea"
+ScaleFiltering.Bilinear="Biliniar"
+ScaleFiltering.Bicubic="Bicubic"
+ScaleFiltering.Lanczos="Lanczos"
Deinterlacing="Deîntrețesere"
Deinterlacing.Discard="Înlătură"
Deinterlacing.TopFieldFirst="Câmpul de sus prima oară"
Deinterlacing.BottomFieldFirst="Câmpul de jos prima oară"
+
Basic.Main.AddSceneDlg.Title="Adaugă scenă"
Basic.Main.AddSceneDlg.Text="Te rugăm să introduci numele scenei"
Basic.MainMenu.SceneCollection="Colecție de &scene"
Basic.MainMenu.Profile="&Profil"
+Basic.MainMenu.Profile.Import="Importă Profil"
+Basic.MainMenu.Profile.Export="Exportă profil"
+Basic.MainMenu.Profile.Exists="Profilul deja există"
+Basic.MainMenu.Tools="&Unelte"
Basic.MainMenu.Help="&Ajutor"
Basic.MainMenu.Help.Website="Vizitează site-ul &web"
Basic.Settings.Output.Mode.Simple="Simplu"
Basic.Settings.Output.Mode.Adv="Avansat"
Basic.Settings.Output.Mode.FFmpeg="Ieșire FFmpeg"
+Basic.Settings.Output.ReplayBuffer.Estimate="Utilizare estimată a memoriei: %1 MB"
+Basic.Settings.Output.ReplayBuffer.Suffix="Sufix"
Basic.Settings.Output.Simple.SavePath="Cale de înregistrare"
Basic.Settings.Output.Simple.RecordingQuality="Calitatea înregistrării"
Basic.Settings.Output.Simple.RecordingQuality.Stream="La fel cu cea a streamului"
Basic.Settings.Audio.UnknownAudioDevice="[Dispozitivul nu este disponibil sau nu este conectat]"
Basic.Settings.Advanced="Avansate"
+Basic.Settings.Advanced.General.ProcessPriority="Prioritate Proces"
+Basic.Settings.Advanced.General.ProcessPriority.High="Ridicată"
+Basic.Settings.Advanced.General.ProcessPriority.AboveNormal="Peste Normal"
+Basic.Settings.Advanced.General.ProcessPriority.Normal="Normală"
+Basic.Settings.Advanced.General.ProcessPriority.Idle="Inactiv"
Basic.Settings.Advanced.FormatWarning="Atentie: Formatele de culori diferite de NV12 sunt facute pentru inregistrare si nu sunt recomandate in cazul streaming-ului. Streaming-ul e posibil sa ceara mai multe resurse CPU datorita conversiei formatului culorii."
Basic.Settings.Advanced.Audio.BufferingTime="Timp de buffering pentru audio"
Basic.Settings.Advanced.Video.ColorFormat="Format de culoare"
Basic.Settings.Advanced.StreamDelay.Duration="Durată (secunde)"
Basic.Settings.Advanced.StreamDelay.Preserve="Păstrează punctul de tăiere (crește întârzierea) la reconectare"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Utilizare estimată a memoriei: %1 MB"
+Basic.Settings.Advanced.Network="Rețea"
+Basic.Settings.Advanced.Network.BindToIP="Leagă de IP"
Basic.AdvAudio="Proprietăți audio avansate"
Basic.AdvAudio.Name="Nume"
Basic.Hotkeys.SelectScene="Comută la scenă"
+Basic.SystemTray.Show="Afișează"
+Basic.SystemTray.Hide="Ascunde"
+Basic.SystemTray.Message.Reconnecting="Deconectat. Reconectare..."
Hotkeys.Insert="Inserează"
Hotkeys.Delete="Șterge"
obs-studio-17.0.2.tar.xz/UI/data/locale/ru-RU.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/ru-RU.ini
Changed
Import="Импорт"
Export="Экспорт"
+Updater.Title="Доступно обновление"
+Updater.Text="Доступно новое обновление:"
+Updater.UpdateNow="Обновить сейчас"
+Updater.RemindMeLater="Напомнить позже"
+Updater.Skip="Пропустить версию"
+Updater.Running.Title="Программа в настоящее время активна"
+Updater.Running.Text="Обнаружена активная операция вывода. Перед обновлением необходимо отключить все активные операции вывода"
+Updater.NoUpdatesAvailable.Title="Нет доступных обновлений"
+Updater.NoUpdatesAvailable.Text="Обновления не обнаружены"
+Updater.FailedToLaunch="Не удалось проверить обновления"
+Updater.GameCaptureActive.Title="Производится захват игры"
+Updater.GameCaptureActive.Text="Библиотека захвата игр уже используется. Закройте захватываемые игры/программы (или перезапустите Windows) и попробуйте ещё раз."
+
QuickTransitions.SwapScenes="Замена Просмотра/Вывода Сцены После Перехода"
QuickTransitions.SwapScenesTT="Замена просмотра и вывода сцены после перехода (если выходная оригинальная сцена до сих пор существует).\nЭто будет не отмена каких-либо изменений, что, возможно, было сделано в выходной оригинальной сцены."
QuickTransitions.DuplicateScene="Повторяющиеся Сцены"
ConfirmRemove.Text="Вы уверены, что хотите удалить '$1'?"
ConfirmRemove.TextMultiple="Вы уверены, что вы хотите удалить %1 элементов?"
+Output.StartStreamFailed="Не удалось запустить вещание"
+Output.StartRecordingFailed="Не удалось начать запись"
+Output.StartReplayFailed="Не удалось запустить воспроизведение из буфера"
+Output.StartFailedGeneric="Сбой вывода. Подробности отражены в журнале.\n\nПримечание: Если вы используете кодировщики NVENC или AMD, убедитесь что у вас установлена последняя версия видеорайвера."
+
Output.ConnectFail.Title="Не удалось подключиться"
Output.ConnectFail.BadPath="Неверный путь или URL соединения. Пожалуйста, проверьте настройки, чтобы подтвердить, что они являются действительными."
Output.ConnectFail.ConnectFailed="Не удалось подключиться к серверу"
Deinterlacing.TopFieldFirst="Верхнее поле первое"
Deinterlacing.BottomFieldFirst="Нижнее поле первое"
+VolControl.SliderUnmuted="Регулятор громкости '%1': %2"
+VolControl.SliderMuted="Регулятор громкости '%1': %2 (сейчас заглушен)"
+VolControl.Mute="Заглушить '%1'"
+VolControl.Properties="Свойства '%1'"
+
Basic.Main.AddSceneDlg.Title="Добавить сцену"
Basic.Main.AddSceneDlg.Text="Пожалуйста, введите название сцены"
Basic.Settings.General="Общие"
Basic.Settings.General.Theme="Тема"
Basic.Settings.General.Language="Язык"
+Basic.Settings.General.EnableAutoUpdates="Проверять наличие обновлений при запуске"
Basic.Settings.General.WarnBeforeStartingStream="Показывать окно подтверждения при запуске трансляции"
Basic.Settings.General.WarnBeforeStoppingStream="Показывать окно подтверждения при остановке трансляции"
+Basic.Settings.General.Projectors="Проекторы"
Basic.Settings.General.HideProjectorCursor="Скрыть курсор за проекторы"
Basic.Settings.General.ProjectorAlwaysOnTop="Показывать проекторы поверх всего остального"
Basic.Settings.General.Snapping="Привязка расположения источника"
Basic.Settings.General.SnapDistance="Чувствительность привязки"
Basic.Settings.General.RecordWhenStreaming="Автоматическая запись при стриме"
Basic.Settings.General.KeepRecordingWhenStreamStops="Продолжить запись, когда стрим остановится"
-Basic.Settings.General.SysTrayEnabled="Показывать иконку в системном трее"
+Basic.Settings.General.ReplayBufferWhileStreaming="Автоматически запускать буфер повтора во время трансляции"
+Basic.Settings.General.KeepReplayBufferStreamStops="Сохранять буфер повтора активным когда останавливается трансляция"
+Basic.Settings.General.SysTray="Системный трей"
Basic.Settings.General.SysTrayWhenStarted="Скрывать окно в системный трей при запуске"
+Basic.Settings.General.SystemTrayHideMinimize="Всегда сворачивать в трей вместо панели задач"
+Basic.Settings.General.SaveProjectors="Сохранять проекторы при выходе"
Basic.Settings.Stream="Вещание"
Basic.Settings.Stream.StreamType="Тип вещания"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="Кодировщик аудио"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="Настройки кодировщика аудио (если есть)"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="Настройки мультиплексора (если есть)"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="Интервал ключевых кадров (кадры)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="Показать все кодеки (даже потенциально несовместимые)"
FilenameFormatting.completer="%DD-%MM-%CCYY %hh-%mm-%ss\n%DD-%MM-%YY %hh-%mm-%ss\n%d-%m-%Y %H-%M-%S\n%d-%m-%y %H-%M-%S\n%a %d-%m-%Y %H-%M-%S\n%A %d-%m-%Y %H-%M-%S\n%d-%b-%Y %H-%M-%S\n%d-%B-%Y %H-%M-%S"
Basic.Settings.Advanced.Video.ColorRange="Цветовой диапазон YUV"
Basic.Settings.Advanced.Video.ColorRange.Partial="Частичный"
Basic.Settings.Advanced.Video.ColorRange.Full="Полный"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Устройство прослушивания аудио"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="По умолчанию"
Basic.Settings.Advanced.StreamDelay="Задержка потока"
Basic.Settings.Advanced.StreamDelay.Duration="Продолжительность (секунд)"
Basic.Settings.Advanced.StreamDelay.Preserve="Сохранить точку отсечки (увеличить задержку) при переподключении"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Предполагаемое использование памяти: %1 МБ"
Basic.Settings.Advanced.Network="Сеть"
Basic.Settings.Advanced.Network.BindToIP="Привязать к IP"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="Включить новый сетевой код"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="Режим низкой задержки"
Basic.AdvAudio="Расширенные свойства аудио"
Basic.AdvAudio.Name="Название"
Basic.AdvAudio.Mono="Объединение в один канал"
Basic.AdvAudio.Panning="Панорамирование"
Basic.AdvAudio.SyncOffset="Смещение синхронизации (мс)"
+Basic.AdvAudio.Monitoring="Аудио прослушивание"
+Basic.AdvAudio.Monitoring.None="Выключить прослушивание"
+Basic.AdvAudio.Monitoring.MonitorOnly="Только прослушивание (заглушить вывод)"
+Basic.AdvAudio.Monitoring.Both="Прослушивание и вывод"
Basic.AdvAudio.AudioTracks="Дорожки"
Basic.Settings.Hotkeys="Горячие клавиши"
OutputWarnings.NoTracksSelected="Вы должны выбрать хотя бы одну звуковую дорожку"
OutputWarnings.MultiTrackRecording="Предупреждение: Некоторые форматы (такие как FLV) не поддерживают множественные звуковые дорожки"
+OutputWarnings.MP4Recording="Внимание: Записи, сохраненные в MP4 будут нечитаемы, если файл не будет завершен (например, в результате BSOD'а, потери напряжения в сети и т.д.). Если вы хотите записывать несколько аудио дорожек, рассмотрите использование MKV, и последующее ремультиплексирование в MP4 после завершения записи (Файл -> Ремультиплексирование записей)"
obs-studio-17.0.2.tar.xz/UI/data/locale/sk-SK.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/sk-SK.ini
Changed
Minutes="Minúty"
Seconds="Sekundy"
+
QuickTransitions.DuplicateScene="Duplikovať scénu"
Basic.TransitionDuration="Trvanie"
ConfirmRemove.Title="Potvrdenie odobratia"
ConfirmRemove.Text="Naozaj si prajete odobrať '$1'?"
+
Output.ConnectFail.Title="Spojenie sa nepodarilo"
Output.ConnectFail.BadPath="Neplatná cesta alebo URL. Prosím, skontrolujte, či sú vaše nastavenia správne."
Output.ConnectFail.ConnectFailed="Spojenie so serverom sa nepodarilo"
+
Basic.Main.AddSceneDlg.Title="Pridať scénu"
Basic.Main.AddSceneDlg.Text="Prosím, zadajte názov scény"
obs-studio-17.0.2.tar.xz/UI/data/locale/sl-SI.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/sl-SI.ini
Changed
+
NameExists.Title="Ime že obstaja"
NameExists.Text="Ime je že v uporabi."
ConfirmRemove.Title="Potrdite odstranitev"
ConfirmRemove.Text="Ali ste prepričani, da želite odstraniti '$ 1'?"
+
Output.ConnectFail.Title="Povezava ni uspela"
Output.ConnectFail.BadPath="Neveljavna pot ali URL povezava. Prosimo, preverite vaše nastavitve za potrditev, da so veljavne."
Output.ConnectFail.ConnectFailed="Ni uspelo povezati s strežnikom"
+
Basic.Main.AddSceneDlg.Title="Dodaj seceno"
Basic.Main.AddSceneDlg.Text="Prosimo, vnesite ime scene"
obs-studio-17.0.2.tar.xz/UI/data/locale/sr-CS.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/sr-CS.ini
Changed
Seconds="Sekundi"
Deprecated="Prevaziđeno"
+
QuickTransitions.SwapScenes="Zameni scene pregleda/izlaza nakon prelaza"
QuickTransitions.SwapScenesTT="Zamenjuje scene pregleda i izlaza nakon prelaza (ako originalna scena izlaza još uvek postoji).\nOvo neće poništiti promene koje su načinjene nad originalnom scenom izlaza."
QuickTransitions.DuplicateScene="Dupliraj scenu"
ConfirmRemove.Text="Da li ste sigurni da želite izbaciti '$1'?"
ConfirmRemove.TextMultiple="Da li ste sigurni da želite izbaciti %1 stavke?"
+
Output.ConnectFail.Title="Neuspešno povezivanje"
Output.ConnectFail.BadPath="Neispravna putanja ili URL konekcije. Molim proverite vaša podešavanja da potvrdite njihovu ispravnost."
Output.ConnectFail.ConnectFailed="Neuspešno povezivanje na server"
Deinterlacing.TopFieldFirst="Prvo gornje polje"
Deinterlacing.BottomFieldFirst="Prvo donje polje"
+
Basic.Main.AddSceneDlg.Title="Dodaj scenu"
Basic.Main.AddSceneDlg.Text="Molim unesite ime scene"
Basic.Settings.General.SnapDistance="Osetljivost privlačenja"
Basic.Settings.General.RecordWhenStreaming="Automatsko snimanje pri emitovanju"
Basic.Settings.General.KeepRecordingWhenStreamStops="Nastavi snimati kada se emitovanje zaustavi"
-Basic.Settings.General.SysTrayEnabled="Omogući ikonicu u sistemskom panelu"
Basic.Settings.General.SysTrayWhenStarted="Pri pokretanju minimiziraj na ikonicu u sistemskom panelu"
Basic.Settings.Stream="Strim"
obs-studio-17.0.2.tar.xz/UI/data/locale/sr-SP.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/sr-SP.ini
Changed
Seconds="Секунди"
Deprecated="Превазиђено"
+
QuickTransitions.SwapScenes="Замени сцене прегледа/излаза након прелаза"
QuickTransitions.SwapScenesTT="Замењује сцене прегледа и излаза након прелаза (ако оригинална сцена још увек постоји).\nОво неће поништити промене које су начињене над оригиналном сценом излаза."
QuickTransitions.DuplicateScene="Дуплирај сцену"
ConfirmRemove.Text="Да ли сте сигурни да желите избацити '$1'?"
ConfirmRemove.TextMultiple="Да ли сте сигурни да желите избацити %1 ставке?"
+
Output.ConnectFail.Title="Неуспешно повезивање"
Output.ConnectFail.BadPath="Неисправна путања или URL конекције. Молим проверите ваша подешавања да потврдите њихову исправност."
Output.ConnectFail.ConnectFailed="Неуспешно повезивање на сервер"
Deinterlacing.TopFieldFirst="Прво горње поље"
Deinterlacing.BottomFieldFirst="Прво доње поље"
+
Basic.Main.AddSceneDlg.Title="Додај сцену"
Basic.Main.AddSceneDlg.Text="Молим унесите име сцене"
Basic.Settings.General.SnapDistance="Осетљивост привлачења"
Basic.Settings.General.RecordWhenStreaming="Аутоматско снимање при емитовању"
Basic.Settings.General.KeepRecordingWhenStreamStops="Настави снимати када се емитовање заустави"
-Basic.Settings.General.SysTrayEnabled="Омогући иконицу у системском панелу"
Basic.Settings.General.SysTrayWhenStarted="При покретању минимизирај на иконицу у системском панелу"
Basic.Settings.Stream="Стрим"
obs-studio-17.0.2.tar.xz/UI/data/locale/sv-SE.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/sv-SE.ini
Changed
Mono="Mono"
Stereo="Stereo"
DroppedFrames="Tappade bildrutor %1 (%2%)"
-PreviewProjector="Fullskärm projektor (Förhandsvisa)"
-SceneProjector="Fullskärm projektor (scen)"
-SourceProjector="Fullskärm projektor (källa)"
+PreviewProjector="Fullskärmsprojektor (förhandsvisning)"
+SceneProjector="Fullskärmsprojektor (scen)"
+SourceProjector="Fullskärmsprojektor (källa)"
Clear="Rensa"
Revert="Återgå"
Show="Visa"
Import="Importera"
Export="Exportera"
+Updater.Title="Ny uppdatering tillgänglig"
+Updater.Text="Det finns en ny uppdatering tillgänglig:"
+Updater.UpdateNow="Uppdatera nu"
+Updater.RemindMeLater="Påminn mig senare"
+Updater.Skip="Hoppa över version"
+Updater.Running.Title="Programmet körs för tillfället"
+Updater.Running.Text="Utmatningar pågår för tillfället, stäng ned alla aktiva utmatningar innan du uppdaterar"
+Updater.NoUpdatesAvailable.Title="Inga tillgängliga uppdateringar"
+Updater.NoUpdatesAvailable.Text="Inga uppdateringar är tillgängliga för närvarande"
+Updater.FailedToLaunch="Misslyckades att starta uppdateringen"
+Updater.GameCaptureActive.Title="Spelkälla aktiv"
+Updater.GameCaptureActive.Text="Hook-biblioteket för spelkällor används för tillfället. Stäng alla spel/program som spelas in (eller starta om Windows) och försök igen."
+
QuickTransitions.SwapScenes="Byt plats på Förhandsvisnings-/utdatascenerna efter skifte"
QuickTransitions.SwapScenesTT="Byter plats på förhandsvisnings- och utdatascenerna efter övergång (om utdatans originalscen fortfarande finns). \nDet här kommer inte att ångra några förändringar i utdatans originalscen."
QuickTransitions.DuplicateScene="Duplicera scen"
ConfirmRemove.Text="Vill du verkligen ta bort '$1'?"
ConfirmRemove.TextMultiple="Är du säker på att du vill ta bort %1 poster?"
+Output.StartStreamFailed="Misslyckades att starta strömning"
+Output.StartRecordingFailed="Misslyckades att starta inspelning"
+Output.StartReplayFailed="Misslyckades att starta reprisbuffert"
+Output.StartFailedGeneric="Misslyckades att starta utmatningen. Kolla loggen för detaljer.\n\nOBS: Om du använder kodarna NVENC eller AMD, se till att dina grafikdrivrutiner är uppdaterade."
+
Output.ConnectFail.Title="Anslutning misslyckades"
Output.ConnectFail.BadPath="Ogiltig sökväg eller anslutnings-URL. Kontrollera att dina inställningar är korrekta."
Output.ConnectFail.ConnectFailed="Kunde inte ansluta till servern"
Basic.Scene="Scen"
Basic.DisplayCapture="Bildskärmskälla"
-Basic.Main.PreviewConextMenu.Enable="Förhandsvisa"
+Basic.Main.PreviewConextMenu.Enable="Aktivera förhandsvisning"
ScaleFiltering="Skalningsfiltrering"
ScaleFiltering.Point="Punkt"
Deinterlacing.TopFieldFirst="Övre fältet först"
Deinterlacing.BottomFieldFirst="Nedre fältet först"
+VolControl.SliderUnmuted="Volymreglage för \"%1\": %2"
+VolControl.SliderMuted="Volymreglage för \"%1\": %2 (tyst för tillfället)"
+VolControl.Mute="Tysta \"%1\""
+VolControl.Properties="Egenskaper för \"%1\""
+
Basic.Main.AddSceneDlg.Title="Lägg till scen"
Basic.Main.AddSceneDlg.Text="Vänligen ange ett namn för scenen"
Basic.Settings.General="Allmänt"
Basic.Settings.General.Theme=" Tema"
Basic.Settings.General.Language="Språk"
+Basic.Settings.General.EnableAutoUpdates="Sök efter uppdateringar automatiskt vid start"
Basic.Settings.General.WarnBeforeStartingStream="Visa bekräftelsedialog när ström startas"
Basic.Settings.General.WarnBeforeStoppingStream="Visa bekräftelsedialog när ström stoppas"
+Basic.Settings.General.Projectors="Projektorer"
Basic.Settings.General.HideProjectorCursor="Dölj pekaren över projektorer"
Basic.Settings.General.ProjectorAlwaysOnTop="Lägg alltid projektorer överst"
Basic.Settings.General.Snapping="Fäst justerbara källor"
Basic.Settings.General.SnapDistance="Fästkänslighet"
Basic.Settings.General.RecordWhenStreaming="Spela automatiskt in vid strömning"
Basic.Settings.General.KeepRecordingWhenStreamStops="Fortsätt spela in när strömmen stoppas"
-Basic.Settings.General.SysTrayEnabled="Aktivera ikon i meddelandefältet"
+Basic.Settings.General.ReplayBufferWhileStreaming="Starta reprisbufferten automatiskt vid strömning"
+Basic.Settings.General.KeepReplayBufferStreamStops="Håll reprisbufferten aktiv när ström stoppas"
+Basic.Settings.General.SysTray="Systemfält"
Basic.Settings.General.SysTrayWhenStarted="Minimera till meddelandefältet vid start"
+Basic.Settings.General.SystemTrayHideMinimize="Minimera alltid till meddelandefältet i stället för aktivitetsfältet"
+Basic.Settings.General.SaveProjectors="Spara projektorer vid avslut"
Basic.Settings.Stream="Ström"
Basic.Settings.Stream.StreamType="Strömtyp"
Basic.Settings.Advanced.Video.ColorRange="YUV färgområde"
Basic.Settings.Advanced.Video.ColorRange.Partial="Partiell"
Basic.Settings.Advanced.Video.ColorRange.Full="Full"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Ljuduppspelningsenhet"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Standard"
Basic.Settings.Advanced.StreamDelay="Strömfördröjning"
Basic.Settings.Advanced.StreamDelay.Duration="Varaktighet (sekunder)"
+Basic.Settings.Advanced.StreamDelay.Preserve="Behåll stoppunkten (öka fördröjningen) vid återanslutning"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Uppskattad minnesanvändning: %1 MB"
Basic.Settings.Advanced.Network="Nätverk"
Basic.Settings.Advanced.Network.BindToIP="Bind till IP"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="Aktivera ny nätverkskod"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="Låg latens-läge"
Basic.AdvAudio="Avancerade ljudinställningar"
Basic.AdvAudio.Name="Namn"
Basic.AdvAudio.Mono="Nedmixa till mono"
Basic.AdvAudio.Panning="Panorering"
Basic.AdvAudio.SyncOffset="Sync Offset (ms)"
+Basic.AdvAudio.Monitoring="Ljuduppspelning"
Basic.AdvAudio.AudioTracks="Spår"
Basic.Settings.Hotkeys="Kortkommandon"
obs-studio-17.0.2.tar.xz/UI/data/locale/ta-IN.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/ta-IN.ini
Changed
+
+
+
obs-studio-17.0.2.tar.xz/UI/data/locale/th-TH.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/th-TH.ini
Changed
+
ConfirmRemove.Title="ยืนยันการลบ"
ConfirmRemove.Text="คุณแน่ใจแล้วหรือที่จะลบ '$1'?"
+
Output.ConnectFail.Title="ไม่สามารถเชื่อมต่อได้"
Output.ConnectFail.ConnectFailed="ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์"
Output.ConnectFail.Disconnected="ถูกตัดออกจากเซิร์ฟเวอร์"
+
Basic.Main.AddSceneDlg.Title="เพิ่มฉาก"
Basic.Main.DefaultSceneName.Text="ฉาก %1"
obs-studio-17.0.2.tar.xz/UI/data/locale/tr-TR.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/tr-TR.ini
Changed
Import="İçe Aktar"
Export="Dışa Aktar"
+Updater.Title="Yeni güncelleme mevcut"
+Updater.Text="Mevcut yeni bir güncelleme var:"
+Updater.UpdateNow="Şimdi Güncelle"
+Updater.RemindMeLater="Daha sonra hatırlat"
+Updater.Skip="Sürümü Atla"
+Updater.Running.Title="Program şu anda etkin"
+Updater.NoUpdatesAvailable.Title="Güncelleme mevcut değil"
+Updater.NoUpdatesAvailable.Text="Şu anda mevcut hiçbir güncelleme yok"
+Updater.FailedToLaunch="Güncelleyici başlatılamadı"
+Updater.GameCaptureActive.Title="Oyun yakalama etkin"
+
QuickTransitions.DuplicateScene="Sahneyi Çoğalt"
QuickTransitions.EditProperties="Kaynakları Çoğalt"
QuickTransitions.HotkeyName="Hızlı Geçiş: %1"
ConfirmRemove.Text="'$1''i kaldırmak istediğinizden emin misiniz?"
ConfirmRemove.TextMultiple="%1 öğeyi kaldırmak istediğinizden emin misiniz?"
+Output.StartStreamFailed="Yayın işlemi başarısız oldu"
+Output.StartRecordingFailed="Kayıt işlemi başarısız oldu"
+Output.StartReplayFailed="Tekrar oynatma arabelleği başarısız oldu"
+
Output.ConnectFail.Title="Bağlantı kurulamadı"
Output.ConnectFail.BadPath="Bağlantı adresiniz geçersiz. Ayarlarınızı kontrol edin ve geçerli bir adres giriniz."
Output.ConnectFail.ConnectFailed="Sunucuya bağlanılamadı"
Deinterlacing.TopFieldFirst="Önce Üst Alan"
Deinterlacing.BottomFieldFirst="Önce Alt Alan"
+VolControl.SliderUnmuted="'%1' için ses kaydırıcı: %2"
+VolControl.Properties="'%1' için özellikler"
+
Basic.Main.AddSceneDlg.Title="Sahne Ekle"
Basic.Main.AddSceneDlg.Text="Lütfen sahne adını giriniz"
Basic.Settings.General="Genel"
Basic.Settings.General.Theme="Tema"
Basic.Settings.General.Language="Dil"
+Basic.Settings.General.EnableAutoUpdates="Başlangıçta güncellemeleri otomatik olarak kontrol et"
Basic.Settings.General.WarnBeforeStartingStream="Yayın başlatırken onay iletişim kutusunu göster"
Basic.Settings.General.WarnBeforeStoppingStream="Yayın durduğunda onay iletişim kutusunu göster"
+Basic.Settings.General.Projectors="Projektörler"
Basic.Settings.General.HideProjectorCursor="Projektörler üzerinde imleci gizle"
Basic.Settings.General.ProjectorAlwaysOnTop="Projektörleri her zaman üstte tut"
Basic.Settings.General.Snapping="Kaynak Hizalama"
Basic.Settings.General.SnapDistance="Yaslama Hassasiyeti"
Basic.Settings.General.RecordWhenStreaming="Yayın sırasında otomatik olarak kayıt yap"
Basic.Settings.General.KeepRecordingWhenStreamStops="Yayın durduğunda kaydı tut"
-Basic.Settings.General.SysTrayEnabled="Sistem tepsisi simgesini etkinleştir"
+Basic.Settings.General.ReplayBufferWhileStreaming="Yayın sırasında tekrar oynatma arabelleğini otomatik olarak başlat"
+Basic.Settings.General.KeepReplayBufferStreamStops="Yayın durduğunda tekrar oynatma arabelleğini tut"
+Basic.Settings.General.SysTray="Sistem tepsisi"
Basic.Settings.General.SysTrayWhenStarted="Başladığında sistem tepsisine küçült"
+Basic.Settings.General.SystemTrayHideMinimize="Her zaman görev çubuğu yerine sistem tepsisine küçült"
+Basic.Settings.General.SaveProjectors="Çıkışta projektörleri kaydet"
Basic.Settings.Stream="Yayın"
Basic.Settings.Stream.StreamType="Yayın Türü"
Basic.Settings.Advanced.Video.ColorRange="YUV Renk Aralığı"
Basic.Settings.Advanced.Video.ColorRange.Partial="Kısmi"
Basic.Settings.Advanced.Video.ColorRange.Full="Tam"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Ses İzleme Aygıtı"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="Varsayılan"
Basic.Settings.Advanced.StreamDelay="Yayın Gecikmesi"
Basic.Settings.Advanced.StreamDelay.Duration="Süre (saniye)"
Basic.Settings.Advanced.StreamDelay.Preserve="Tatbik ederken kesim noktasını (gecikme artışı) koru"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Tahmini Bellek Kullanımı: %1 MB"
Basic.Settings.Advanced.Network="Ağ"
Basic.Settings.Advanced.Network.BindToIP="IP Bağla"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="Yeni ağ kodunu etkinleştir"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="Düşük gecike modu"
Basic.AdvAudio="Gelişmiş Ses Özellikleri"
Basic.AdvAudio.Name="İsim"
Basic.AdvAudio.Mono="Mono Karıştırmayı Azalt"
Basic.AdvAudio.Panning="Kaydırma"
Basic.AdvAudio.SyncOffset="Eşitleme Uzaklığı (ms)"
+Basic.AdvAudio.Monitoring="Ses İzleme"
+Basic.AdvAudio.Monitoring.None="Ekran Kapalı"
+Basic.AdvAudio.Monitoring.MonitorOnly="Sadece Ekran (sessiz çıkış)"
+Basic.AdvAudio.Monitoring.Both="Ekran ve Çıkış"
Basic.AdvAudio.AudioTracks="Parçalar"
Basic.Settings.Hotkeys="Kısayollar"
obs-studio-17.0.2.tar.xz/UI/data/locale/uk-UA.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/uk-UA.ini
Changed
Import="Імпорт"
Export="Експорт"
+Updater.Title="Доступне оновлення"
+Updater.Text="Існує нове оновлення:"
+Updater.UpdateNow="Оновити зараз"
+Updater.RemindMeLater="Нагадати пізніше"
+Updater.Skip="Пропустити цю версію"
+Updater.Running.Title="Програма зараз активна"
+Updater.Running.Text="Вивід активний в даний час, будь ласка, завершіть роботу будь-якого активного Виводу перед спробою оновлення"
+Updater.NoUpdatesAvailable.Title="Оновлень немає"
+Updater.NoUpdatesAvailable.Text="На даний час оновлень немає"
+Updater.FailedToLaunch="Не вдалося перевірити оновлення"
+Updater.GameCaptureActive.Title="Захват гри активний"
+Updater.GameCaptureActive.Text="Бібліотека для Захвату гри наразі використовується. Будь ласка, закрийте всі ігри/програми для яких використовувався захват (або перезавантажте Windows) та спробуйте знов."
+
QuickTransitions.SwapScenes="Поміняти місцями сцени Перегляд/Вивід після Відео-переходу"
QuickTransitions.SwapScenesTT="Міняє місцями сцени Перегляд та Вивід після закінчення Відео-переходу (якщо сцена Вивід ще існує).\nЗміни внесені до обох сцен залишаються."
QuickTransitions.DuplicateScene="Використовувати копію сцени"
ConfirmRemove.Text="Ви дійсно бажаєте видалити \"$1\"?"
ConfirmRemove.TextMultiple="Ви впевнені, що хочете видалити %1 елементів?"
+Output.StartStreamFailed="Не вдалося розпочати трансляцію"
+Output.StartRecordingFailed="Не вдалося розпочати запис"
+Output.StartReplayFailed="Не вдалося запустити Буфер Повторів"
+Output.StartFailedGeneric="Помилка. Вивід не було розпочато. За додатковою інформацією, будь ласка зверніться до файлу журналу.\n\nПримітка: якщо ви використовуєте NVENC або AMD енкодер, перевірте чи оновлений драйвер відео."
+
Output.ConnectFail.Title="Не вдалося підключитися"
Output.ConnectFail.BadPath="Шлях або URL-адреса недосяжні. Будь ласка, перевірте налаштування програмного забезпечення."
Output.ConnectFail.ConnectFailed="Не вдалося підключитися до сервера"
Deinterlacing.TopFieldFirst="Спочатку непарні рядки"
Deinterlacing.BottomFieldFirst="Спочатку парні рядки"
+VolControl.SliderUnmuted="Повзунок гучності для '%1': %2"
+VolControl.SliderMuted="Повзунок гучності для '%1': %2 (в даний час звук вимкнено)"
+VolControl.Mute="Вимкнути звук '%1'"
+VolControl.Properties="Властивості для '%1'"
+
Basic.Main.AddSceneDlg.Title="Додати Сцену"
Basic.Main.AddSceneDlg.Text="Будь ласка, введіть назву для Сцени"
Basic.Settings.General="Загальні"
Basic.Settings.General.Theme="Тема"
Basic.Settings.General.Language="Мова"
+Basic.Settings.General.EnableAutoUpdates="Автоматично перевіряти наявність оновлень під час запуску"
Basic.Settings.General.WarnBeforeStartingStream="Показувати підтвердження для початку трансляції"
Basic.Settings.General.WarnBeforeStoppingStream="Показувати підтвердження для закінчення трансляції"
+Basic.Settings.General.Projectors="Проектор"
Basic.Settings.General.HideProjectorCursor="Приховати курсор у режимі Проектор"
Basic.Settings.General.ProjectorAlwaysOnTop="Режим Проектор відображати поверх всіх вікон"
Basic.Settings.General.Snapping="Прив'язка та вирівнювання"
Basic.Settings.General.SnapDistance="Чутливість примагничування"
Basic.Settings.General.RecordWhenStreaming="Автоматично почати запис з початком трансляції"
Basic.Settings.General.KeepRecordingWhenStreamStops="Не припиняти запис, якщо трансляцію закінчено"
-Basic.Settings.General.SysTrayEnabled="Відображати іконку системному треї, та згортати в трей"
+Basic.Settings.General.ReplayBufferWhileStreaming="Автоматично запустити Буфер Повторів з початком трансляції"
+Basic.Settings.General.KeepReplayBufferStreamStops="Не припиняти Буфер Повторів, якщо трансляцію закінчено"
+Basic.Settings.General.SysTray="Системний трей"
Basic.Settings.General.SysTrayWhenStarted="Згорнути програму до трею при запуску"
+Basic.Settings.General.SystemTrayHideMinimize="Згортати в трей замість того, щоб мінімізувати до панелі завдань"
+Basic.Settings.General.SaveProjectors="Зберегти налаштування режиму Проектор при виході"
Basic.Settings.Stream="Трансляція"
Basic.Settings.Stream.StreamType="Тип Трансляції"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="Енкодер аудіо"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="Енкодер аудіо, параметри користувача"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="Мультиплексор, параметри користувача"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="Ключові кадри, період (кадрів)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="Показати всі кодеки (навіть якщо потенційно несумісні)"
FilenameFormatting.completer="%CCYY-%MM-%DD %hh-%mm-%ss\n%YY-%MM-%DD %hh-%mm-%ss\n%Y-%m-%d %H-%M-%S\n%y-%m-%d %H-%M-%S\n%a %Y-%m-%d %H-%M-%S\n%A %Y-%m-%d %H-%M-%S\n%Y-%b-%d %H-%M-%S\n%Y-%B-%d %H-%M-%S\n%Y-%m-%d %I-%M-%S-%p\n%Y-%m-%d %H-%M-%S-%z\n%Y-%m-%d %H-%M-%S-%Z"
-FilenameFormatting.TT="%CCYY Рік, чотири цифри\n%YY Рік, останні дві цифри (00-99)\n%MM Місяць за номером (01-12)\n%DD День місяця, ноль попереду (01-31)\n%hh Години у 24-год. форматі (00-23)\n%mm Мінути (00-59)\n%ss Секунди (00-61)\n%% Знак % \n%a Абревіатура дня тижня\n%A День тижня повністю\n%b Абревіатура місяця\n%B Місяць повністю\n%d День місяця, ноль попереду (01-31)\n%H Години у 24-год. форматі (00-23)\n%I Години у 12-год. форматі (01-12)\n%m Місяць за номером (01-12)\n%M Мінути (00-59)\n%p ДП або ПП позначення\n%S Секунди (00-61)\n%y Рік, останні дві цифри (00-99)\n%Y Рік\n%z ISO 8601 поправка від UTC або часовий\n пояс чи абревіатура\n%Z Часовий пояс чи абревіатура\n"
+FilenameFormatting.TT="%CCYY Рік, чотири цифри\n%YY Рік, останні дві цифри (00-99)\n%MM Місяць за номером (01-12)\n%DD День місяця, ноль попереду (01-31)\n%hh Години у 24-год. форматі (00-23)\n%mm Мінути (00-59)\n%ss Секунди (00-61)\n%% Знак % \n%a Абревіатура дня тижня\n%A День тижня повністю\n%b Абревіатура місяця\n%B Місяць повністю\n%d День місяця, ноль попереду (01-31)\n%H Години у 24-год. форматі (00-23)\n%I Години у 12-год. форматі (01-12)\n%m Місяць за номером (01-12)\n%M Мінути (00-59)\n%p ДП або ПП позначення\n%S Секунди (00-61)\n%y Рік, останні дві цифри (00-99)\n%Y Рік\n%z ISO 8601 поправка від UTC або часовий\n пояс чи абревіатура\n%Z Часовий пояс чи абревіатура\n"
Basic.Settings.Video="Відео"
Basic.Settings.Video.Adapter="Відеокарта:"
Basic.Settings.Advanced.Video.ColorRange="YUV, колірний діапазон"
Basic.Settings.Advanced.Video.ColorRange.Partial="Частковий"
Basic.Settings.Advanced.Video.ColorRange.Full="Повний"
+Basic.Settings.Advanced.Audio.MonitoringDevice="Пристрій Тестування Аудіо (на слух)"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="За замовчанням"
Basic.Settings.Advanced.StreamDelay="Затримка трансляції"
Basic.Settings.Advanced.StreamDelay.Duration="Тривалість (секунди)"
Basic.Settings.Advanced.StreamDelay.Preserve="Зберегати точку роз'єднання (збільшує затримку) під час встановлення нового зв'язку"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="Буде використано пам'яті: %1 МБ"
Basic.Settings.Advanced.Network="Мережа"
Basic.Settings.Advanced.Network.BindToIP="Прив'язати до адаптера (IP)"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="Увімкнути новий мережевий код"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="Режим з низькою затримкою"
Basic.AdvAudio="Розширені Налаштування Аудіо"
Basic.AdvAudio.Name="Назва"
Basic.AdvAudio.Mono="Мікшувати до псевдо-Моно"
Basic.AdvAudio.Panning="Баланс"
Basic.AdvAudio.SyncOffset="Зсув синхронізації (мс)"
+Basic.AdvAudio.Monitoring="Тестування Аудіо (на слух)"
+Basic.AdvAudio.Monitoring.None="Тест вимкнено"
+Basic.AdvAudio.Monitoring.MonitorOnly="Слухати, але не Виводити"
+Basic.AdvAudio.Monitoring.Both="Слухати та Виводити"
Basic.AdvAudio.AudioTracks="Доріжки"
Basic.Settings.Hotkeys="Гарячі клавіші"
OutputWarnings.NoTracksSelected="Ви повинні вибрати хоча б одну аудіо-доріжку"
OutputWarnings.MultiTrackRecording="Попередження: Певні формати (наприклад, FLV) не підтримують кілька треків на запис"
+OutputWarnings.MP4Recording="Попередження: Запис в MP4 може стати невиправно пошкодженим, якщо файл не буде завершено (наприклад, в результаті BSOD, втрати живлення і т.п.). Якщо ви хочете, мати запис декількох звукових доріжок спробуйте використати MKV та зробіть ремультиплексацію запису до mp4 після того, як запис буде закінчено (Файл->Ремультиплексація Записів)"
obs-studio-17.0.2.tar.xz/UI/data/locale/vi-VN.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/vi-VN.ini
Changed
Minutes="Phút"
Seconds="Giây"
+
QuickTransitions.SwapScenes="Hoán đổi cảnh Xem trước/Đầu ra sau khi Chuyển cảnh"
QuickTransitions.SwapScenesTT="Hoán đổi cảnh xem trước và cảnh đầu ra sau khi chuyển cảnh (nếu cảnh đầu ra gốc vẫn tồn tại).\nMọi thay đổi với cảnh đầu ra gốc sẽ không hoàn tác."
QuickTransitions.DuplicateScene="Tạo bản sao cảnh"
ConfirmRemove.Text="Bạn có chắc bạn muốn loại bỏ '$1' không?"
ConfirmRemove.TextMultiple="Bạn có chắc bạn muốn xóa %1 nội dung không?"
+
Output.ConnectFail.Title="Không thể kết nối"
Output.ConnectFail.BadPath="URL không hợp lệ của đường dẫn hoặc kết nối. Xin vui lòng kiểm tra cài đặt của bạn để xác nhận rằng họ là hợp lệ."
Output.ConnectFail.ConnectFailed="Không thể kết nối tới hệ phục vụ"
Deinterlacing.Yadif="Yadif"
Deinterlacing.Yadif2x="Yadif 2x"
+
Basic.Main.AddSceneDlg.Title="Thêm cảnh"
Basic.Main.AddSceneDlg.Text="Vui lòng nhập tên của cảnh"
Basic.Settings.General.Language="Ngôn ngữ"
Basic.Settings.General.HideProjectorCursor="Ẩn con trỏ chuột trên màn chiếu"
Basic.Settings.General.ProjectorAlwaysOnTop="Làm cho màn chiếu luôn luôn trên đầu"
-Basic.Settings.General.SysTrayEnabled="Bật khay biểu tượng hệ thống"
Basic.Settings.Stream="Stream"
Basic.Settings.Stream.StreamType="Kiểu Stream"
obs-studio-17.0.2.tar.xz/UI/data/locale/zh-CN.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/zh-CN.ini
Changed
Import="导入"
Export="导出"
+Updater.Title="有可用的更新"
+Updater.Text="有可用的新版本:"
+Updater.UpdateNow="现在更新"
+Updater.RemindMeLater="稍后再提醒我"
+Updater.Skip="跳过版本"
+Updater.Running.Title="程序当前处于活跃状态"
+Updater.Running.Text="输出当前处于活动状态, 请关闭任何活跃的输出, 然后尝试更新"
+Updater.NoUpdatesAvailable.Title="无可用更新"
+Updater.NoUpdatesAvailable.Text="没有更新当前可用"
+Updater.FailedToLaunch="启动更新程序失败"
+Updater.GameCaptureActive.Title="游戏捕获活跃"
+Updater.GameCaptureActive.Text="游戏捕获钩子库正在使用中, 请关闭所有正在被捕获的游戏/程序(或重新启动 windows), 然后重试."
+
QuickTransitions.SwapScenes="在过渡动画后交换预览/输出场景"
QuickTransitions.SwapScenesTT="在过渡后,交换预览和输出场景(如果输出的原始场景仍然存在). \n 这个不会撤消任何可能对输出的原始场景的更改."
QuickTransitions.DuplicateScene="复制场景"
ConfirmRemove.Text="确定要删除 '$1' 吗?"
ConfirmRemove.TextMultiple="您确定要删除 %1 项目吗?"
+Output.StartStreamFailed="启动推流失败"
+Output.StartRecordingFailed="启动录像失败"
+Output.StartReplayFailed="启动回放缓存失败"
+Output.StartFailedGeneric="启动输出失败. 请检查日志来了解细节.\n\n注意: 如果你使用的是 NVENC 或 AMD 编码器, 请确保您的视频驱动程序是最新的."
+
Output.ConnectFail.Title="连接失败"
Output.ConnectFail.BadPath="无效的路径或URL。请检查您的设置以确认它们是有效的。"
Output.ConnectFail.ConnectFailed="无法连接到服务器"
Deinterlacing.TopFieldFirst="上场优先"
Deinterlacing.BottomFieldFirst="下场优先"
+VolControl.SliderUnmuted="音量滑动条 '%1': %2"
+VolControl.SliderMuted="音量滑动条 '%1': %2 (当前静音)"
+VolControl.Mute="静音 '%1'"
+VolControl.Properties="属性 '%1'"
+
Basic.Main.AddSceneDlg.Title="添加场景"
Basic.Main.AddSceneDlg.Text="请输入场景名称"
Basic.Settings.General="通用"
Basic.Settings.General.Theme="主题"
Basic.Settings.General.Language="语言"
+Basic.Settings.General.EnableAutoUpdates="启动时自动检查更新"
Basic.Settings.General.WarnBeforeStartingStream="启动流时显示确认对话框"
Basic.Settings.General.WarnBeforeStoppingStream="停止流时显示确认对话框"
+Basic.Settings.General.Projectors="投影仪"
Basic.Settings.General.HideProjectorCursor="隐藏投影仪上的光标"
Basic.Settings.General.ProjectorAlwaysOnTop="使投影器总是置顶"
Basic.Settings.General.Snapping="源对齐方式"
Basic.Settings.General.SnapDistance="对齐的敏感性"
Basic.Settings.General.RecordWhenStreaming="当推流时自动录像"
Basic.Settings.General.KeepRecordingWhenStreamStops="当推流停止时保持录像"
-Basic.Settings.General.SysTrayEnabled="启用系统托盘图标"
+Basic.Settings.General.ReplayBufferWhileStreaming="推流时自动启动重播缓冲区"
+Basic.Settings.General.KeepReplayBufferStreamStops="推流停止时重播缓冲区保持活动状态"
+Basic.Settings.General.SysTray="系统托盘"
Basic.Settings.General.SysTrayWhenStarted="开始时最小化到系统托盘"
+Basic.Settings.General.SystemTrayHideMinimize="总是最小化到系统托盘, 而不是任务栏"
+Basic.Settings.General.SaveProjectors="退出时保存投影仪"
Basic.Settings.Stream="串流"
Basic.Settings.Stream.StreamType="串流类型"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="音频编码器"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="视频编码器设置 (如果有)"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="Muxer 设置 (如果有)"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="关键帧间隔 (帧)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="显示所有编解码器 (即使可能不兼容)"
FilenameFormatting.completer="%CCYY-%MM-%DD %hh-%mm-%ss\n%YY-%MM-%DD %hh-%mm-%ss\n%Y-%m-%d %H-%M-%S\n%y-%m-%d %H-%M-%S\n%a %Y-%m-%d %H-%M-%S\n%A %Y-%m-%d %H-%M-%S\n%Y-%b-%d %H-%M-%S\n%Y-%B-%d %H-%M-%S\n%Y-%m-%d %I-%M-%S-%p\n%Y-%m-%d %H-%M-%S-%z\n%Y-%m-%d %H-%M-%S-%Z"
Basic.Settings.Advanced.Video.ColorRange="YUV 颜色范围"
Basic.Settings.Advanced.Video.ColorRange.Partial="局部"
Basic.Settings.Advanced.Video.ColorRange.Full="全部"
+Basic.Settings.Advanced.Audio.MonitoringDevice="音频监测设备"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="默认"
Basic.Settings.Advanced.StreamDelay="流延迟"
Basic.Settings.Advanced.StreamDelay.Duration="持续时间 (秒)"
Basic.Settings.Advanced.StreamDelay.Preserve="重新连接时保持截止点 (增加延迟)"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="估计的内存使用率: %1 MB"
Basic.Settings.Advanced.Network="网络"
Basic.Settings.Advanced.Network.BindToIP="绑定 IP"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="启用新的网络代码"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="低延迟模式"
Basic.AdvAudio="高级音频属性"
Basic.AdvAudio.Name="名称"
Basic.AdvAudio.Mono="下降混合为单声道"
Basic.AdvAudio.Panning="平移"
Basic.AdvAudio.SyncOffset="同步偏移 (毫秒)"
+Basic.AdvAudio.Monitoring="音频监测"
+Basic.AdvAudio.Monitoring.None="关闭监视"
+Basic.AdvAudio.Monitoring.MonitorOnly="仅显示器(静音输出)"
+Basic.AdvAudio.Monitoring.Both="监视器和输出"
Basic.AdvAudio.AudioTracks="轨道"
Basic.Settings.Hotkeys="热键"
OutputWarnings.NoTracksSelected="您必须选择至少一个轨道"
OutputWarnings.MultiTrackRecording="警告: 某些格式 (如 FLV) 不支持每个录像多个轨道"
+OutputWarnings.MP4Recording="警告︰ 录制保存到 MP4 将无法恢复,如果该文件不能完成 (例如由于蓝屏死机,掉电等)。如果您想要记录多个音频轨道考虑使用 MKV 然后在它完成后 remux 录制到 mp4 (文件 -> Remux 录制文件)"
obs-studio-17.0.2.tar.xz/UI/data/locale/zh-TW.ini -> obs-studio-18.0.0.tar.xz/UI/data/locale/zh-TW.ini
Changed
Import="匯入"
Export="匯出"
+Updater.Title="有新更新"
+Updater.Text="有新更新︰"
+Updater.UpdateNow="立即更新"
+Updater.RemindMeLater="稍後提醒我"
+Updater.Skip="略過此版本"
+Updater.Running.Title="程式處於活動狀態"
+Updater.Running.Text="輸出處於活動狀態,請關閉活動中的輸出,然後再嘗試更新"
+Updater.NoUpdatesAvailable.Title="沒有更新"
+Updater.NoUpdatesAvailable.Text="沒有更新"
+Updater.FailedToLaunch="啟動更新程式失敗"
+Updater.GameCaptureActive.Title="遊戲擷取使用中"
+Updater.GameCaptureActive.Text="遊戲擷取函式庫正在使用中。 請關閉所有被擷取的遊戲/程式 (或重新開機 windows),然後重試。"
+
QuickTransitions.SwapScenes="轉場後交換預覽/輸出場景"
QuickTransitions.SwapScenesTT="(如果輸出的原始場景仍然存在) 轉場後交換預覽和輸出場景。\n這並不會復原任何對輸出原始場景所作的改動。"
QuickTransitions.DuplicateScene="複製場景"
ConfirmRemove.Text="您確定要刪除「$1」?"
ConfirmRemove.TextMultiple="您確定要移除這%1個項目嘛?"
+Output.StartStreamFailed="無法開始串流"
+Output.StartRecordingFailed="無法開始錄影"
+Output.StartReplayFailed="無法啟動重播緩衝區"
+Output.StartFailedGeneric="啟動輸出失敗。 詳情請看 Log 檔。\n\n注意︰ 如果你使用 NVENC 或 AMD 編碼器,請確保您的視頻驅動程式是最新。"
+
Output.ConnectFail.Title="連線失敗"
Output.ConnectFail.BadPath="無效的路徑或 URL。 請確認您的設定是正確的。"
Output.ConnectFail.ConnectFailed="與伺服器連線失敗。"
Deinterlacing.TopFieldFirst="由偶數場開始"
Deinterlacing.BottomFieldFirst="由奇數場開始"
+VolControl.SliderUnmuted="'%1' 的音量滑桿︰ %2"
+VolControl.SliderMuted="'%1' 的音量滑桿︰ %2 (目前靜音中)"
+VolControl.Mute="靜音 '%1'"
+VolControl.Properties="'%1' 的屬性"
+
Basic.Main.AddSceneDlg.Title="新增場景"
Basic.Main.AddSceneDlg.Text="請輸入場景名稱"
Basic.Settings.General="一般"
Basic.Settings.General.Theme="佈景主題"
Basic.Settings.General.Language="語言"
+Basic.Settings.General.EnableAutoUpdates="啟動時自動檢查更新"
Basic.Settings.General.WarnBeforeStartingStream="啟動串流時顯示確認對話框"
Basic.Settings.General.WarnBeforeStoppingStream="停止串流時顯示確認對話框"
+Basic.Settings.General.Projectors="投影"
Basic.Settings.General.HideProjectorCursor="當游標在投影上時隱藏游標"
Basic.Settings.General.ProjectorAlwaysOnTop="讓投影總是在最上層"
Basic.Settings.General.Snapping="貼齊對準來源"
Basic.Settings.General.SnapDistance="貼齊敏感度"
Basic.Settings.General.RecordWhenStreaming="串流時自動錄製"
Basic.Settings.General.KeepRecordingWhenStreamStops="串流停止時繼續錄製"
-Basic.Settings.General.SysTrayEnabled="啟用系統列圖示"
+Basic.Settings.General.ReplayBufferWhileStreaming="串流時自動啟動重播緩衝"
+Basic.Settings.General.KeepReplayBufferStreamStops="串流停止時依然保持啟用重播緩衝"
+Basic.Settings.General.SysTray="系統工具列"
Basic.Settings.General.SysTrayWhenStarted="開始時最小化至系統列"
+Basic.Settings.General.SystemTrayHideMinimize="總是最小化到系統列,而非工作列"
+Basic.Settings.General.SaveProjectors="退出時保存投影設定"
Basic.Settings.Stream="串流"
Basic.Settings.Stream.StreamType="串流類型"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="音效編碼器"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="音效編碼設定(如果有才啟用)"
Basic.Settings.Output.Adv.FFmpeg.MuxerSettings="Muxer 設定(如果有才啟用)"
+Basic.Settings.Output.Adv.FFmpeg.GOPSize="關鍵訊框間隔 (訊框)"
+Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat="顯示所有編碼解碼器 (即使可能不相容)"
FilenameFormatting.completer="%CCYY-%MM-%DD %hh-%mm-%ss\n%YY-%MM-%DD %hh-%mm-%ss\n%Y-%m-%d %H-%M-%S\n%y-%m-%d %H-%M-%S\n%a %Y-%m-%d %H-%M-%S\n%A %Y-%m-%d %H-%M-%S\n%Y-%b-%d %H-%M-%S\n%Y-%B-%d %H-%M-%S\n%Y-%m-%d %I-%M-%S-%p\n%Y-%m-%d %H-%M-%S-%z\n%Y-%m-%d %H-%M-%S-%Z"
Basic.Settings.Advanced.Video.ColorRange="YUV 顏色範圍"
Basic.Settings.Advanced.Video.ColorRange.Partial="部份"
Basic.Settings.Advanced.Video.ColorRange.Full="完整"
+Basic.Settings.Advanced.Audio.MonitoringDevice="音訊監測設備"
+Basic.Settings.Advanced.Audio.MonitoringDevice.Default="預設裝置"
Basic.Settings.Advanced.StreamDelay="實況延遲"
Basic.Settings.Advanced.StreamDelay.Duration="延遲(秒)"
Basic.Settings.Advanced.StreamDelay.Preserve="重新連線時維持截止點 (增加延遲)"
Basic.Settings.Advanced.StreamDelay.MemoryUsage="預計記憶體使用率: %1 MB"
Basic.Settings.Advanced.Network="網路"
Basic.Settings.Advanced.Network.BindToIP="綁定到 IP"
+Basic.Settings.Advanced.Network.EnableNewSocketLoop="啟用新的網路程式碼"
+Basic.Settings.Advanced.Network.EnableLowLatencyMode="低延遲模式"
Basic.AdvAudio="進階音訊屬性"
Basic.AdvAudio.Name="名稱"
Basic.AdvAudio.Mono="混降為單聲道"
Basic.AdvAudio.Panning="偏移"
Basic.AdvAudio.SyncOffset="同步位移(ms)"
+Basic.AdvAudio.Monitoring="音訊監測"
+Basic.AdvAudio.Monitoring.None="關閉監測"
+Basic.AdvAudio.Monitoring.MonitorOnly="僅監測(輸出為靜音)"
+Basic.AdvAudio.Monitoring.Both="監測和輸出"
Basic.AdvAudio.AudioTracks="音軌"
Basic.Settings.Hotkeys="快捷鍵"
OutputWarnings.NoTracksSelected="您必須至少選擇一個軌道"
OutputWarnings.MultiTrackRecording="警告:某些格式 (例如 FLV) 不支援多個軌道錄製"
+OutputWarnings.MP4Recording="警告︰ 如果檔案無法完成,儲存成 MP4 的紀錄將無法復原 (例如由於 BSOD,斷電等)。如果想要記錄多個音軌請考慮儲存成 MKV 並在完成後重新封裝成 mp4(檔案 -> 重新封裝)"
obs-studio-17.0.2.tar.xz/UI/forms/OBSBasic.ui -> obs-studio-18.0.0.tar.xz/UI/forms/OBSBasic.ui
Changed
<height>0</height>
</size>
</property>
+ <property name="accessibleName">
+ <string>Transition</string>
+ </property>
</widget>
</item>
<item>
<property name="text">
<string>Basic.TransitionDuration</string>
</property>
+ <property name="buddy">
+ <cstring>transitionDuration</cstring>
+ </property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="transitionDuration">
+ <property name="accessibleName">
+ <string>Basic.TransitionDuration</string>
+ </property>
<property name="suffix">
<string>ms</string>
</property>
obs-studio-17.0.2.tar.xz/UI/forms/OBSBasicSettings.ui -> obs-studio-18.0.0.tar.xz/UI/forms/OBSBasicSettings.ui
Changed
<number>0</number>
</property>
<widget class="QWidget" name="generalPage">
- <layout class="QFormLayout" name="formLayout_2">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ <layout class="QVBoxLayout" name="verticalLayout_18">
+ <property name="leftMargin">
+ <number>0</number>
</property>
- <property name="labelAlignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ <property name="topMargin">
+ <number>0</number>
</property>
- <item row="0" column="0">
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label">
- <property name="minimumSize">
- <size>
- <width>170</width>
- <height>0</height>
- </size>
- </property>
- <property name="text">
- <string>Basic.Settings.General.Language</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="buddy">
- <cstring>language</cstring>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QComboBox" name="language"/>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_42">
- <property name="text">
- <string>Basic.Settings.General.Theme</string>
- </property>
- <property name="buddy">
- <cstring>theme</cstring>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QComboBox" name="theme"/>
- </item>
- <item row="3" column="1">
- <widget class="QCheckBox" name="warnBeforeStreamStart">
- <property name="text">
- <string>Basic.Settings.General.WarnBeforeStartingStream</string>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QCheckBox" name="warnBeforeStreamStop">
- <property name="text">
- <string>Basic.Settings.General.WarnBeforeStoppingStream</string>
- </property>
- </widget>
- </item>
- <item row="7" column="1">
- <widget class="QCheckBox" name="recordWhenStreaming">
- <property name="text">
- <string>Basic.Settings.General.RecordWhenStreaming</string>
- </property>
- </widget>
- </item>
- <item row="9" column="1">
- <widget class="QCheckBox" name="systemTrayEnabled">
- <property name="text">
- <string>Basic.Settings.General.SysTrayEnabled</string>
- </property>
- </widget>
- </item>
- <item row="10" column="1">
- <widget class="QCheckBox" name="systemTrayWhenStarted">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Basic.Settings.General.SysTrayWhenStarted</string>
- </property>
- </widget>
- </item>
- <item row="11" column="0" colspan="2">
- <widget class="Line" name="line_4">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item row="12" column="0" colspan="2">
- <widget class="QGroupBox" name="groupBox_10">
- <property name="enabled">
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QScrollArea" name="scrollArea_2">
+ <property name="widgetResizable">
<bool>true</bool>
</property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="title">
- <string>Basic.Settings.General.Snapping</string>
- </property>
- <property name="flat">
- <bool>false</bool>
- </property>
- <layout class="QFormLayout" name="formLayout_21">
- <property name="labelAlignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ <widget class="QWidget" name="scrollAreaWidgetContents_2">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>818</width>
+ <height>697</height>
+ </rect>
</property>
- <item row="0" column="1">
- <widget class="QCheckBox" name="snappingEnabled">
- <property name="text">
- <string>Enable</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QCheckBox" name="screenSnapping">
- <property name="text">
- <string>Basic.Settings.General.ScreenSnapping</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QCheckBox" name="centerSnapping">
- <property name="text">
- <string>Basic.Settings.General.CenterSnapping</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QCheckBox" name="sourceSnapping">
- <property name="text">
- <string>Basic.Settings.General.SourceSnapping</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QDoubleSpinBox" name="snapDistance">
- <property name="decimals">
- <number>1</number>
- </property>
- <property name="singleStep">
- <double>0.500000000000000</double>
- </property>
- <property name="value">
- <double>10.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_9">
- <property name="minimumSize">
- <size>
- <width>170</width>
- <height>0</height>
- </size>
- </property>
- <property name="text">
- <string>Basic.Settings.General.SnapDistance</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="5" column="1">
- <widget class="QCheckBox" name="hideProjectorCursor">
- <property name="text">
- <string>Basic.Settings.General.HideProjectorCursor</string>
- </property>
- </widget>
- </item>
- <item row="8" column="1">
- <widget class="QCheckBox" name="keepRecordStreamStops">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Basic.Settings.General.KeepRecordingWhenStreamStops</string>
- </property>
- </widget>
- </item>
- <item row="6" column="1">
- <widget class="QCheckBox" name="projectorAlwaysOnTop">
- <property name="text">
- <string>Basic.Settings.General.ProjectorAlwaysOnTop</string>
- </property>
+ <layout class="QVBoxLayout" name="verticalLayout_19">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>9</number>
+ </property>
+ <item alignment="Qt::AlignTop">
+ <widget class="QWidget" name="widget_2" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout_20">
+ <item>
+ <widget class="QGroupBox" name="groupBox_15">
+ <property name="title">
+ <string>Basic.Settings.General</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_32">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <property name="labelAlignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Basic.Settings.General.Language</string>
+ </property>
+ <property name="buddy">
+ <cstring>language</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="language"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_42">
+ <property name="text">
+ <string>Basic.Settings.General.Theme</string>
+ </property>
+ <property name="buddy">
+ <cstring>theme</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="theme"/>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="enableAutoUpdates">
+ <property name="text">
+ <string>Basic.Settings.General.EnableAutoUpdates</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>170</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_16">
+ <property name="title">
+ <string>Basic.Settings.Output</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <item row="0" column="0">
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>170</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="1">
+ <widget class="QCheckBox" name="warnBeforeStreamStart">
+ <property name="text">
+ <string>Basic.Settings.General.WarnBeforeStartingStream</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QCheckBox" name="warnBeforeStreamStop">
+ <property name="text">
+ <string>Basic.Settings.General.WarnBeforeStoppingStream</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="recordWhenStreaming">
+ <property name="text">
+ <string>Basic.Settings.General.RecordWhenStreaming</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QCheckBox" name="keepRecordStreamStops">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Basic.Settings.General.KeepRecordingWhenStreamStops</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QCheckBox" name="replayWhileStreaming">
+ <property name="text">
+ <string>Basic.Settings.General.ReplayBufferWhileStreaming</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QCheckBox" name="keepReplayStreamStops">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Basic.Settings.General.KeepReplayBufferStreamStops</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_10">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Basic.Settings.General.Snapping</string>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <layout class="QFormLayout" name="formLayout_21">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <property name="labelAlignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <item row="0" column="1">
+ <widget class="QCheckBox" name="snappingEnabled">
+ <property name="text">
+ <string>Enable</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="screenSnapping">
+ <property name="text">
+ <string>Basic.Settings.General.ScreenSnapping</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QCheckBox" name="centerSnapping">
+ <property name="text">
+ <string>Basic.Settings.General.CenterSnapping</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QCheckBox" name="sourceSnapping">
+ <property name="text">
+ <string>Basic.Settings.General.SourceSnapping</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QDoubleSpinBox" name="snapDistance">
+ <property name="decimals">
+ <number>1</number>
+ </property>
+ <property name="singleStep">
+ <double>0.500000000000000</double>
+ </property>
+ <property name="value">
+ <double>10.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>Basic.Settings.General.SnapDistance</string>
+ </property>
+ <property name="buddy">
+ <cstring>snapDistance</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>170</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_14">
+ <property name="title">
+ <string>Basic.Settings.General.Projectors</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_28">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <item row="0" column="1">
+ <widget class="QCheckBox" name="hideProjectorCursor">
+ <property name="text">
+ <string>Basic.Settings.General.HideProjectorCursor</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QCheckBox" name="projectorAlwaysOnTop">
+ <property name="text">
+ <string>Basic.Settings.General.ProjectorAlwaysOnTop</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="saveProjectors">
+ <property name="text">
+ <string>Basic.Settings.General.SaveProjectors</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>170</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_13">
+ <property name="title">
+ <string>Basic.Settings.General.SysTray</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_29">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <item row="0" column="1">
+ <widget class="QCheckBox" name="systemTrayEnabled">
+ <property name="text">
+ <string>Enabled</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QCheckBox" name="systemTrayWhenStarted">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Basic.Settings.General.SysTrayWhenStarted</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="systemTrayAlways">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Basic.Settings.General.SystemTrayHideMinimize</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>170</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
</layout>
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="7" column="0">
<widget class="QLabel" name="label_40">
<property name="text">
<string>Basic.Settings.Output.VideoBitrate</string>
</property>
</widget>
</item>
- <item row="6" column="1">
+ <item row="7" column="1">
<widget class="QSpinBox" name="advOutFFVBitrate">
<property name="minimum">
<number>0</number>
</property>
</widget>
</item>
- <item row="7" column="0">
+ <item row="8" column="1">
+ <widget class="QSpinBox" name="advOutFFVGOPSize">
+ <property name="maximum">
+ <number>1000000000</number>
+ </property>
+ <property name="value">
+ <number>250</number>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="label_63">
+ <property name="text">
+ <string>Basic.Settings.Output.Adv.FFmpeg.GOPSize</string>
+ </property>
+ <property name="buddy">
+ <cstring>advOutFFVGOPSize</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="0">
<widget class="QCheckBox" name="advOutFFUseRescale">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
</property>
</widget>
</item>
- <item row="7" column="1">
+ <item row="9" column="1">
<widget class="QComboBox" name="advOutFFRescale">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
- <item row="8" column="0">
+ <item row="10" column="1">
+ <widget class="QCheckBox" name="advOutFFIgnoreCompat">
+ <property name="text">
+ <string>Basic.Settings.Output.Adv.FFmpeg.IgnoreCodecCompat</string>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="0">
<widget class="QLabel" name="label_37">
<property name="text">
<string>Basic.Settings.Output.Adv.FFmpeg.VEncoder</string>
</property>
</widget>
</item>
- <item row="8" column="1">
+ <item row="11" column="1">
<widget class="QComboBox" name="advOutFFVEncoder"/>
</item>
- <item row="10" column="0">
+ <item row="13" column="0">
<widget class="QLabel" name="label_38">
<property name="text">
<string>Basic.Settings.Output.Adv.FFmpeg.VEncoderSettings</string>
</property>
</widget>
</item>
- <item row="10" column="1">
+ <item row="13" column="1">
<widget class="QLineEdit" name="advOutFFVCfg"/>
</item>
- <item row="11" column="0">
+ <item row="14" column="0">
<widget class="QLabel" name="label_41">
<property name="text">
<string>Basic.Settings.Output.AudioBitrate</string>
</property>
</widget>
</item>
- <item row="11" column="1">
+ <item row="14" column="1">
<widget class="QSpinBox" name="advOutFFABitrate">
<property name="minimum">
<number>32</number>
</property>
</widget>
</item>
- <item row="12" column="0">
+ <item row="15" column="0">
<widget class="QLabel" name="label_47">
<property name="text">
<string>Basic.Settings.Output.Adv.AudioTrack</string>
</property>
</widget>
</item>
- <item row="12" column="1">
+ <item row="15" column="1">
<widget class="QWidget" name="widget_10" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
</layout>
</widget>
</item>
- <item row="13" column="0">
+ <item row="17" column="0">
<widget class="QLabel" name="label_39">
<property name="text">
<string>Basic.Settings.Output.Adv.FFmpeg.AEncoder</string>
</property>
</widget>
</item>
- <item row="13" column="1">
+ <item row="17" column="1">
<widget class="QComboBox" name="advOutFFAEncoder"/>
</item>
- <item row="14" column="0">
+ <item row="18" column="0">
<widget class="QLabel" name="label_46">
<property name="text">
<string>Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings</string>
</property>
</widget>
</item>
- <item row="14" column="1">
+ <item row="18" column="1">
<widget class="QLineEdit" name="advOutFFACfg"/>
</item>
<item row="0" column="0">
<rect>
<x>0</x>
<y>0</y>
- <width>800</width>
- <height>69</height>
+ <width>98</width>
+ <height>28</height>
</rect>
</property>
</widget>
<item alignment="Qt::AlignTop">
<widget class="QComboBox" name="fpsCommon">
<property name="currentText">
- <string notr="true">30</string>
+ <string notr="true">10</string>
</property>
<property name="currentIndex">
- <number>3</number>
+ <number>0</number>
</property>
<item>
<property name="text">
</item>
<item>
<property name="text">
+ <string>24 NTSC</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
<string notr="true">29.97</string>
</property>
</item>
<rect>
<x>0</x>
<y>0</y>
- <width>593</width>
- <height>709</height>
+ <width>803</width>
+ <height>738</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_16">
<string>Basic.Settings.General</string>
</property>
<layout class="QFormLayout" name="formLayout_22">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
<item row="0" column="0">
<widget class="QLabel" name="processPriorityLabel">
<property name="text">
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="rendererLabel">
+ <property name="text">
+ <string>Basic.Settings.Video.Renderer</string>
+ </property>
+ <property name="buddy">
+ <cstring>renderer</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="renderer">
+ <property name="currentText">
+ <string notr="true"/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="adapterLabel">
+ <property name="text">
+ <string>Basic.Settings.Video.Adapter</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="buddy">
+ <cstring>adapter</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="adapter">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="currentText">
+ <string notr="true"/>
+ </property>
+ </widget>
+ </item>
<item row="2" column="0">
<widget class="QLabel" name="label_30">
<property name="minimumSize">
</item>
</widget>
</item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_34">
- <property name="text">
- <string>Basic.Settings.Advanced.Video.ColorRange</string>
+ <item row="4" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_18">
+ <property name="leftMargin">
+ <number>0</number>
</property>
- <property name="buddy">
- <cstring>colorRange</cstring>
+ <property name="topMargin">
+ <number>0</number>
</property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QComboBox" name="colorRange"/>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_33">
- <property name="text">
- <string>Basic.Settings.Advanced.Video.ColorSpace</string>
+ <property name="rightMargin">
+ <number>0</number>
</property>
- <property name="buddy">
- <cstring>colorSpace</cstring>
+ <property name="bottomMargin">
+ <number>0</number>
</property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QComboBox" name="colorSpace">
<item>
- <property name="text">
- <string notr="true">709</string>
- </property>
+ <widget class="QCheckBox" name="disableOSXVSync">
+ <property name="text">
+ <string>DisableOSXVSync</string>
+ </property>
+ </widget>
</item>
<item>
- <property name="text">
- <string notr="true">601</string>
- </property>
+ <widget class="QCheckBox" name="resetOSXVSync">
+ <property name="text">
+ <string>ResetOSXVSyncOnExit</string>
+ </property>
+ </widget>
</item>
- </widget>
+ </layout>
</item>
- <item row="0" column="0">
- <widget class="QLabel" name="rendererLabel">
- <property name="text">
- <string>Basic.Settings.Video.Renderer</string>
+ <item row="3" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_20">
+ <property name="leftMargin">
+ <number>0</number>
</property>
- <property name="buddy">
- <cstring>renderer</cstring>
+ <property name="topMargin">
+ <number>0</number>
</property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QComboBox" name="renderer">
- <property name="currentText">
- <string notr="true"/>
+ <property name="rightMargin">
+ <number>0</number>
</property>
- </widget>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QComboBox" name="colorSpace">
+ <item>
+ <property name="text">
+ <string notr="true">709</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">601</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_34">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Basic.Settings.Advanced.Video.ColorRange</string>
+ </property>
+ <property name="buddy">
+ <cstring>colorRange</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="colorRange"/>
+ </item>
+ </layout>
</item>
- <item row="1" column="0">
- <widget class="QLabel" name="adapterLabel">
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_33">
<property name="text">
- <string>Basic.Settings.Video.Adapter</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ <string>Basic.Settings.Advanced.Video.ColorSpace</string>
</property>
<property name="buddy">
- <cstring>adapter</cstring>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QComboBox" name="adapter">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="currentText">
- <string notr="true"/>
+ <cstring>colorSpace</cstring>
</property>
</widget>
</item>
- <item row="5" column="1">
- <widget class="QCheckBox" name="disableOSXVSync">
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="advAudioGroupBox">
+ <property name="title">
+ <string>Basic.Settings.Audio</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_27">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="monitoringDeviceLabel">
<property name="text">
- <string>DisableOSXVSync</string>
+ <string>Basic.Settings.Advanced.Audio.MonitoringDevice</string>
</property>
- </widget>
- </item>
- <item row="6" column="1">
- <widget class="QCheckBox" name="resetOSXVSync">
- <property name="text">
- <string>ResetOSXVSyncOnExit</string>
+ <property name="buddy">
+ <cstring>monitoringDevice</cstring>
</property>
</widget>
</item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="monitoringDevice"/>
+ </item>
</layout>
</widget>
</item>
<string>Basic.Settings.Output.Adv.Recording</string>
</property>
<layout class="QFormLayout" name="formLayout_17">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="text">
<string>Basic.Settings.Output.Adv.Recording.Filename</string>
</property>
+ <property name="buddy">
+ <cstring>filenameFormatting</cstring>
+ </property>
</widget>
</item>
<item row="0" column="1">
<property name="text">
<string>Basic.Settings.Output.ReplayBuffer.Suffix</string>
</property>
+ <property name="buddy">
+ <cstring>simpleRBSuffix</cstring>
+ </property>
</widget>
</item>
<item>
<property name="text">
<string>Basic.Settings.Output.ReplayBuffer.Prefix</string>
</property>
+ <property name="buddy">
+ <cstring>simpleRBPrefix</cstring>
+ </property>
</widget>
</item>
</layout>
<string>Basic.Settings.Advanced.StreamDelay</string>
</property>
<layout class="QFormLayout" name="formLayout_18">
- <item row="0" column="1">
- <widget class="QCheckBox" name="streamDelayEnable">
- <property name="text">
- <string>Enable</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <property name="topMargin">
+ <number>2</number>
+ </property>
<item row="1" column="0">
<widget class="QLabel" name="label_56">
<property name="text">
</property>
</widget>
</item>
+ <item row="0" column="1">
+ <widget class="QCheckBox" name="streamDelayEnable">
+ <property name="text">
+ <string>Enable</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
- <item row="1" column="0">
- <widget class="QLabel" name="label_17">
- <property name="text">
- <string>Basic.Settings.Output.RetryDelay</string>
- </property>
- <property name="buddy">
- <cstring>reconnectRetryDelay</cstring>
- </property>
- </widget>
- </item>
<item row="0" column="1">
<widget class="QCheckBox" name="reconnectEnable">
<property name="text">
</widget>
</item>
<item row="1" column="1">
- <widget class="QSpinBox" name="reconnectRetryDelay">
- <property name="maximum">
- <number>30</number>
+ <layout class="QHBoxLayout" name="horizontalLayout_19">
+ <property name="leftMargin">
+ <number>0</number>
</property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_22">
- <property name="text">
- <string>Basic.Settings.Output.MaxRetries</string>
+ <property name="topMargin">
+ <number>0</number>
</property>
- <property name="buddy">
- <cstring>reconnectMaxRetries</cstring>
+ <property name="rightMargin">
+ <number>0</number>
</property>
- </widget>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="reconnectRetryDelay">
+ <property name="maximum">
+ <number>30</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_22">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Basic.Settings.Output.MaxRetries</string>
+ </property>
+ <property name="buddy">
+ <cstring>reconnectMaxRetries</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="reconnectMaxRetries">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>10000</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
</item>
- <item row="2" column="1">
- <widget class="QSpinBox" name="reconnectMaxRetries">
- <property name="minimum">
- <number>1</number>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_17">
+ <property name="text">
+ <string>Basic.Settings.Output.RetryDelay</string>
</property>
- <property name="maximum">
- <number>10000</number>
+ <property name="buddy">
+ <cstring>reconnectRetryDelay</cstring>
</property>
</widget>
</item>
<property name="text">
<string>Basic.Settings.Advanced.Network.BindToIP</string>
</property>
+ <property name="buddy">
+ <cstring>bindToIP</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QCheckBox" name="enableNewSocketLoop">
+ <property name="text">
+ <string>Basic.Settings.Advanced.Network.EnableNewSocketLoop</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="enableLowLatencyMode">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Basic.Settings.Advanced.Network.EnableLowLatencyMode</string>
+ </property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>listWidget</tabstop>
- <tabstop>buttonBox</tabstop>
+ <tabstop>streamType</tabstop>
+ <tabstop>outputMode</tabstop>
+ <tabstop>simpleOutputVBitrate</tabstop>
+ <tabstop>simpleOutputABitrate</tabstop>
+ <tabstop>simpleOutAdvanced</tabstop>
+ <tabstop>simpleOutPreset</tabstop>
+ <tabstop>simpleOutCustom</tabstop>
+ <tabstop>simpleOutEnforce</tabstop>
+ <tabstop>simpleOutStrEncoder</tabstop>
+ <tabstop>simpleOutputPath</tabstop>
+ <tabstop>simpleOutputBrowse</tabstop>
+ <tabstop>simpleNoSpace</tabstop>
+ <tabstop>simpleOutRecQuality</tabstop>
+ <tabstop>simpleOutRecFormat</tabstop>
+ <tabstop>simpleOutRecEncoder</tabstop>
+ <tabstop>simpleOutMuxCustom</tabstop>
+ <tabstop>simpleReplayBuf</tabstop>
+ <tabstop>simpleRBSecMax</tabstop>
+ <tabstop>simpleRBMegsMax</tabstop>
+ <tabstop>advOutTabs</tabstop>
+ <tabstop>advOutTrack1</tabstop>
+ <tabstop>advOutTrack2</tabstop>
+ <tabstop>advOutTrack3</tabstop>
+ <tabstop>advOutTrack4</tabstop>
+ <tabstop>advOutTrack5</tabstop>
+ <tabstop>advOutTrack6</tabstop>
+ <tabstop>advOutEncoder</tabstop>
+ <tabstop>advOutApplyService</tabstop>
+ <tabstop>advOutUseRescale</tabstop>
+ <tabstop>advOutRescale</tabstop>
+ <tabstop>advOutRecType</tabstop>
+ <tabstop>advOutRecPath</tabstop>
+ <tabstop>advOutRecPathBrowse</tabstop>
+ <tabstop>advOutNoSpace</tabstop>
+ <tabstop>advOutRecFormat</tabstop>
+ <tabstop>advOutRecTrack1</tabstop>
+ <tabstop>advOutRecTrack2</tabstop>
+ <tabstop>advOutRecTrack3</tabstop>
+ <tabstop>advOutRecTrack4</tabstop>
+ <tabstop>advOutRecTrack5</tabstop>
+ <tabstop>advOutRecTrack6</tabstop>
+ <tabstop>advOutRecEncoder</tabstop>
+ <tabstop>advOutRecUseRescale</tabstop>
+ <tabstop>advOutRecRescale</tabstop>
+ <tabstop>advOutMuxCustom</tabstop>
+ <tabstop>advOutFFRecPath</tabstop>
+ <tabstop>advOutFFPathBrowse</tabstop>
+ <tabstop>advOutFFURL</tabstop>
+ <tabstop>advOutFFFormat</tabstop>
+ <tabstop>advOutFFVBitrate</tabstop>
+ <tabstop>advOutFFVGOPSize</tabstop>
+ <tabstop>advOutFFUseRescale</tabstop>
+ <tabstop>advOutFFRescale</tabstop>
+ <tabstop>advOutFFIgnoreCompat</tabstop>
+ <tabstop>advOutFFVEncoder</tabstop>
+ <tabstop>advOutFFVCfg</tabstop>
+ <tabstop>advOutFFABitrate</tabstop>
+ <tabstop>advOutFFTrack1</tabstop>
+ <tabstop>advOutFFTrack2</tabstop>
+ <tabstop>advOutFFTrack3</tabstop>
+ <tabstop>advOutFFTrack4</tabstop>
+ <tabstop>advOutFFTrack5</tabstop>
+ <tabstop>advOutFFTrack6</tabstop>
+ <tabstop>advOutFFAEncoder</tabstop>
+ <tabstop>advOutFFACfg</tabstop>
+ <tabstop>advOutFFType</tabstop>
+ <tabstop>advOutFFMCfg</tabstop>
+ <tabstop>advOutFFNoSpace</tabstop>
+ <tabstop>advOutTrack1Bitrate</tabstop>
+ <tabstop>advOutTrack1Name</tabstop>
+ <tabstop>advOutTrack2Bitrate</tabstop>
+ <tabstop>advOutTrack2Name</tabstop>
+ <tabstop>advOutTrack3Bitrate</tabstop>
+ <tabstop>advOutTrack3Name</tabstop>
+ <tabstop>advOutTrack4Bitrate</tabstop>
+ <tabstop>advOutTrack4Name</tabstop>
+ <tabstop>advOutTrack5Bitrate</tabstop>
+ <tabstop>advOutTrack5Name</tabstop>
+ <tabstop>advOutTrack6Bitrate</tabstop>
+ <tabstop>advOutTrack6Name</tabstop>
+ <tabstop>sampleRate</tabstop>
+ <tabstop>channelSetup</tabstop>
+ <tabstop>desktopAudioDevice1</tabstop>
+ <tabstop>desktopAudioDevice2</tabstop>
+ <tabstop>auxAudioDevice1</tabstop>
+ <tabstop>auxAudioDevice2</tabstop>
+ <tabstop>auxAudioDevice3</tabstop>
+ <tabstop>audioSourceScrollArea</tabstop>
+ <tabstop>baseResolution</tabstop>
+ <tabstop>outputResolution</tabstop>
+ <tabstop>downscaleFilter</tabstop>
+ <tabstop>fpsType</tabstop>
+ <tabstop>fpsCommon</tabstop>
+ <tabstop>fpsInteger</tabstop>
+ <tabstop>fpsNumerator</tabstop>
+ <tabstop>fpsDenominator</tabstop>
+ <tabstop>scrollArea</tabstop>
+ <tabstop>processPriority</tabstop>
+ <tabstop>renderer</tabstop>
+ <tabstop>adapter</tabstop>
+ <tabstop>colorFormat</tabstop>
+ <tabstop>colorSpace</tabstop>
+ <tabstop>colorRange</tabstop>
+ <tabstop>disableOSXVSync</tabstop>
+ <tabstop>resetOSXVSync</tabstop>
+ <tabstop>monitoringDevice</tabstop>
+ <tabstop>filenameFormatting</tabstop>
+ <tabstop>overwriteIfExists</tabstop>
+ <tabstop>simpleRBPrefix</tabstop>
+ <tabstop>simpleRBSuffix</tabstop>
+ <tabstop>streamDelayEnable</tabstop>
+ <tabstop>streamDelaySec</tabstop>
+ <tabstop>streamDelayPreserve</tabstop>
+ <tabstop>reconnectEnable</tabstop>
+ <tabstop>reconnectRetryDelay</tabstop>
+ <tabstop>reconnectMaxRetries</tabstop>
+ <tabstop>bindToIP</tabstop>
+ <tabstop>enableNewSocketLoop</tabstop>
+ <tabstop>enableLowLatencyMode</tabstop>
+ <tabstop>warnBeforeStreamStop</tabstop>
+ <tabstop>recordWhenStreaming</tabstop>
+ <tabstop>keepRecordStreamStops</tabstop>
+ <tabstop>replayWhileStreaming</tabstop>
+ <tabstop>keepReplayStreamStops</tabstop>
+ <tabstop>snappingEnabled</tabstop>
+ <tabstop>screenSnapping</tabstop>
+ <tabstop>centerSnapping</tabstop>
+ <tabstop>sourceSnapping</tabstop>
+ <tabstop>snapDistance</tabstop>
+ <tabstop>hideProjectorCursor</tabstop>
+ <tabstop>projectorAlwaysOnTop</tabstop>
+ <tabstop>saveProjectors</tabstop>
+ <tabstop>systemTrayEnabled</tabstop>
+ <tabstop>systemTrayWhenStarted</tabstop>
+ <tabstop>systemTrayAlways</tabstop>
+ <tabstop>enableAutoUpdates</tabstop>
+ <tabstop>warnBeforeStreamStart</tabstop>
+ <tabstop>scrollArea_2</tabstop>
<tabstop>language</tabstop>
+ <tabstop>theme</tabstop>
</tabstops>
<resources>
<include location="obs.qrc"/>
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
- <x>586</x>
- <y>38</y>
+ <x>241</x>
+ <y>16</y>
</hint>
<hint type="destinationlabel">
- <x>401</x>
- <y>102</y>
+ <x>250</x>
+ <y>39</y>
</hint>
</hints>
</connection>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>640</x>
- <y>180</y>
+ <x>240</x>
+ <y>46</y>
</hint>
<hint type="destinationlabel">
- <x>640</x>
- <y>229</y>
+ <x>240</x>
+ <y>44</y>
</hint>
</hints>
</connection>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>640</x>
- <y>180</y>
+ <x>240</x>
+ <y>46</y>
</hint>
<hint type="destinationlabel">
- <x>383</x>
- <y>229</y>
+ <x>160</x>
+ <y>44</y>
</hint>
</hints>
</connection>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>640</x>
- <y>180</y>
+ <x>240</x>
+ <y>46</y>
</hint>
<hint type="destinationlabel">
- <x>640</x>
- <y>255</y>
+ <x>240</x>
+ <y>43</y>
</hint>
</hints>
</connection>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>640</x>
- <y>180</y>
+ <x>240</x>
+ <y>46</y>
</hint>
<hint type="destinationlabel">
- <x>383</x>
- <y>255</y>
+ <x>160</x>
+ <y>43</y>
</hint>
</hints>
</connection>
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
- <x>606</x>
- <y>113</y>
+ <x>232</x>
+ <y>41</y>
</hint>
<hint type="destinationlabel">
- <x>394</x>
- <y>191</y>
+ <x>241</x>
+ <y>53</y>
</hint>
</hints>
</connection>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>397</x>
- <y>323</y>
+ <x>168</x>
+ <y>67</y>
</hint>
<hint type="destinationlabel">
- <x>676</x>
- <y>323</y>
+ <x>250</x>
+ <y>67</y>
</hint>
</hints>
</connection>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>330</x>
- <y>191</y>
+ <x>168</x>
+ <y>52</y>
</hint>
<hint type="destinationlabel">
- <x>591</x>
- <y>191</y>
+ <x>232</x>
+ <y>52</y>
</hint>
</hints>
</connection>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>353</x>
- <y>277</y>
+ <x>168</x>
+ <y>56</y>
</hint>
<hint type="destinationlabel">
- <x>614</x>
- <y>277</y>
+ <x>232</x>
+ <y>56</y>
</hint>
</hints>
</connection>
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
- <x>676</x>
- <y>148</y>
+ <x>250</x>
+ <y>50</y>
</hint>
<hint type="destinationlabel">
- <x>676</x>
- <y>177</y>
+ <x>250</x>
+ <y>52</y>
</hint>
</hints>
</connection>
<connection>
- <sender>streamDelayEnable</sender>
+ <sender>simpleOutAdvanced</sender>
<signal>toggled(bool)</signal>
- <receiver>label_56</receiver>
- <slot>setEnabled(bool)</slot>
+ <receiver>simpleOutEnforce</receiver>
+ <slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>724</x>
- <y>436</y>
+ <x>240</x>
+ <y>46</y>
</hint>
<hint type="destinationlabel">
- <x>397</x>
- <y>462</y>
+ <x>240</x>
+ <y>45</y>
</hint>
</hints>
</connection>
<connection>
- <sender>streamDelayEnable</sender>
+ <sender>systemTrayEnabled</sender>
<signal>toggled(bool)</signal>
- <receiver>streamDelayPreserve</receiver>
+ <receiver>systemTrayWhenStarted</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>724</x>
- <y>436</y>
+ <x>730</x>
+ <y>556</y>
</hint>
<hint type="destinationlabel">
- <x>724</x>
- <y>485</y>
+ <x>746</x>
+ <y>579</y>
</hint>
</hints>
</connection>
<connection>
- <sender>streamDelayEnable</sender>
+ <sender>systemTrayEnabled</sender>
<signal>toggled(bool)</signal>
- <receiver>widget_12</receiver>
+ <receiver>systemTrayAlways</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>724</x>
- <y>436</y>
+ <x>830</x>
+ <y>556</y>
</hint>
<hint type="destinationlabel">
- <x>724</x>
- <y>462</y>
+ <x>826</x>
+ <y>602</y>
</hint>
</hints>
</connection>
<connection>
- <sender>reconnectEnable</sender>
+ <sender>enableNewSocketLoop</sender>
<signal>toggled(bool)</signal>
- <receiver>label_17</receiver>
+ <receiver>enableLowLatencyMode</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>724</x>
- <y>541</y>
+ <x>403</x>
+ <y>642</y>
</hint>
<hint type="destinationlabel">
- <x>332</x>
- <y>567</y>
+ <x>403</x>
+ <y>665</y>
</hint>
</hints>
</connection>
<connection>
- <sender>reconnectEnable</sender>
+ <sender>snappingEnabled</sender>
<signal>toggled(bool)</signal>
- <receiver>reconnectRetryDelay</receiver>
+ <receiver>label_9</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>724</x>
- <y>541</y>
+ <x>733</x>
+ <y>317</y>
</hint>
<hint type="destinationlabel">
- <x>724</x>
- <y>567</y>
+ <x>347</x>
+ <y>343</y>
</hint>
</hints>
</connection>
<connection>
- <sender>reconnectEnable</sender>
+ <sender>snappingEnabled</sender>
<signal>toggled(bool)</signal>
- <receiver>label_22</receiver>
+ <receiver>snapDistance</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>724</x>
- <y>541</y>
+ <x>774</x>
+ <y>317</y>
</hint>
<hint type="destinationlabel">
- <x>332</x>
- <y>593</y>
+ <x>782</x>
+ <y>343</y>
</hint>
</hints>
</connection>
<connection>
- <sender>reconnectEnable</sender>
+ <sender>snappingEnabled</sender>
<signal>toggled(bool)</signal>
- <receiver>reconnectMaxRetries</receiver>
+ <receiver>screenSnapping</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>724</x>
- <y>541</y>
+ <x>820</x>
+ <y>317</y>
</hint>
<hint type="destinationlabel">
- <x>724</x>
- <y>593</y>
+ <x>837</x>
+ <y>366</y>
</hint>
</hints>
</connection>
<connection>
<sender>snappingEnabled</sender>
<signal>toggled(bool)</signal>
- <receiver>label_9</receiver>
+ <receiver>sourceSnapping</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>951</x>
- <y>349</y>
+ <x>881</x>
+ <y>317</y>
</hint>
<hint type="destinationlabel">
- <x>346</x>
- <y>375</y>
+ <x>890</x>
+ <y>389</y>
</hint>
</hints>
</connection>
<connection>
<sender>snappingEnabled</sender>
<signal>toggled(bool)</signal>
- <receiver>snapDistance</receiver>
+ <receiver>centerSnapping</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>951</x>
- <y>349</y>
+ <x>928</x>
+ <y>317</y>
</hint>
<hint type="destinationlabel">
- <x>951</x>
- <y>375</y>
+ <x>915</x>
+ <y>412</y>
</hint>
</hints>
</connection>
<connection>
- <sender>snappingEnabled</sender>
+ <sender>recordWhenStreaming</sender>
<signal>toggled(bool)</signal>
- <receiver>screenSnapping</receiver>
+ <receiver>keepRecordStreamStops</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>951</x>
- <y>349</y>
+ <x>803</x>
+ <y>199</y>
</hint>
<hint type="destinationlabel">
- <x>951</x>
- <y>398</y>
+ <x>820</x>
+ <y>222</y>
</hint>
</hints>
</connection>
<connection>
- <sender>snappingEnabled</sender>
+ <sender>replayWhileStreaming</sender>
<signal>toggled(bool)</signal>
- <receiver>sourceSnapping</receiver>
+ <receiver>keepReplayStreamStops</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>951</x>
- <y>349</y>
+ <x>747</x>
+ <y>245</y>
</hint>
<hint type="destinationlabel">
- <x>951</x>
- <y>421</y>
+ <x>753</x>
+ <y>268</y>
</hint>
</hints>
</connection>
<connection>
- <sender>snappingEnabled</sender>
+ <sender>streamDelayEnable</sender>
<signal>toggled(bool)</signal>
- <receiver>centerSnapping</receiver>
+ <receiver>label_56</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>951</x>
- <y>349</y>
+ <x>431</x>
+ <y>422</y>
</hint>
<hint type="destinationlabel">
- <x>951</x>
- <y>444</y>
+ <x>356</x>
+ <y>443</y>
</hint>
</hints>
</connection>
<connection>
- <sender>simpleOutAdvanced</sender>
+ <sender>streamDelayEnable</sender>
<signal>toggled(bool)</signal>
- <receiver>simpleOutEnforce</receiver>
- <slot>setVisible(bool)</slot>
+ <receiver>streamDelaySec</receiver>
+ <slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>640</x>
- <y>180</y>
+ <x>465</x>
+ <y>420</y>
</hint>
<hint type="destinationlabel">
- <x>640</x>
- <y>203</y>
+ <x>463</x>
+ <y>447</y>
</hint>
</hints>
</connection>
<connection>
- <sender>recordWhenStreaming</sender>
+ <sender>streamDelayEnable</sender>
<signal>toggled(bool)</signal>
- <receiver>keepRecordStreamStops</receiver>
+ <receiver>streamDelayInfo</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>705</x>
- <y>225</y>
+ <x>533</x>
+ <y>420</y>
</hint>
<hint type="destinationlabel">
- <x>705</x>
- <y>248</y>
+ <x>557</x>
+ <y>446</y>
</hint>
</hints>
</connection>
<connection>
- <sender>systemTrayEnabled</sender>
+ <sender>streamDelayEnable</sender>
<signal>toggled(bool)</signal>
- <receiver>systemTrayWhenStarted</receiver>
+ <receiver>streamDelayPreserve</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>705</x>
- <y>271</y>
+ <x>504</x>
+ <y>420</y>
</hint>
<hint type="destinationlabel">
- <x>705</x>
- <y>294</y>
+ <x>494</x>
+ <y>465</y>
</hint>
</hints>
</connection>
obs-studio-18.0.0.tar.xz/UI/forms/OBSUpdate.ui
Added
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>OBSUpdate</class>
+ <widget class="QDialog" name="OBSUpdate">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>611</width>
+ <height>526</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Updater.Title</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Updater.Text</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTextEdit" name="text">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ <property name="html">
+ <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html></string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="yes">
+ <property name="text">
+ <string>Updater.UpdateNow</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="no">
+ <property name="text">
+ <string>Updater.RemindMeLater</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="skip">
+ <property name="text">
+ <string>Updater.Skip</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
obs-studio-17.0.2.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/da-DK.ini -> obs-studio-18.0.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/da-DK.ini
Changed
Start="Start"
Stop="Stop"
+Captions="Undertekster (eksperimentel)"
+Captions.AudioSource="Lydkilde"
+Captions.CurrentSystemLanguage="Aktuelt systemsprog (%1)"
OutputTimer="Output-timer"
OutputTimer.Stream="Stands streaming efter:"
obs-studio-17.0.2.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/nb-NO.ini -> obs-studio-18.0.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/nb-NO.ini
Changed
+SceneSwitcher="Automatisk Scene Skifter"
+SceneSwitcher.OnNoMatch="Når ingen vindu passer overens:"
+SceneSwitcher.OnNoMatch.DontSwitch="Ikke bytt"
SceneSwitcher.OnNoMatch.SwitchTo="Bytt til:"
+SceneSwitcher.CheckInterval="Sjekk aktivt vindu hver:"
+SceneSwitcher.ActiveOrNotActive="Sceneskifter er:"
+InvalidRegex.Title="Ugyldig regulært utrykk"
+InvalidRegex.Text="Det regulære utrykket du har angitt er ugyldig."
Active="Aktiv"
Inactive="Inaktiv"
Start="Start"
Stop="Stopp"
+Captions="Bildetekster (eksperimentell)"
+Captions.AudioSource="Lyd kilde"
+Captions.CurrentSystemLanguage="Någjeldende System Språk"
+OutputTimer="Stoppeklokke"
+OutputTimer.Stream="Stopp streaming etter:"
+OutputTimer.Record="Stopp opptak etter:"
+OutputTimer.Stream.StoppingIn="Streaming stopper om:"
+OutputTimer.Record.StoppingIn="Opptak stopper om:"
+OutputTimer.Stream.EnableEverytime="Aktiver streaming timer hver gang"
+OutputTimer.Record.EnableEverytime="Aktiver opptaks timer hver gang"
obs-studio-17.0.2.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/pt-BR.ini -> obs-studio-18.0.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/pt-BR.ini
Changed
Start="Iniciar"
Stop="Parar"
+Captions="Legendas (Experimental)"
+Captions.AudioSource="Fonte de Áudio"
+Captions.CurrentSystemLanguage="Idioma Atual do Sistema (%1)"
OutputTimer="Temporizador de saída"
OutputTimer.Stream="Parar a transmissão após:"
OutputTimer.Record="Parar a gravação após:"
OutputTimer.Stream.StoppingIn="A transmissão irá parar em:"
OutputTimer.Record.StoppingIn="A gravação irá parar em:"
+OutputTimer.Stream.EnableEverytime="Ativar o timer streaming o tempo todo"
+OutputTimer.Record.EnableEverytime="Ativar o timer de gravação o tempo todo"
obs-studio-18.0.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ro-RO.ini
Added
+SceneSwitcher="Schimbator automat de scenă"
+SceneSwitcher.OnNoMatch="Cand nici o fereastra nu se potriveste:"
+SceneSwitcher.OnNoMatch.SwitchTo="Schimbă la:"
+Active="Activ"
+Inactive="Inactiv"
+Start="Pornire"
+Stop="Oprire"
+
+Captions.AudioSource="Sursa audio"
+Captions.CurrentSystemLanguage="Limba curentă a sistemului (%1)"
+
+OutputTimer.Record="Opriți inregistrarea dupa:"
+
obs-studio-17.0.2.tar.xz/UI/installer/mp-installer.nsi -> obs-studio-18.0.0.tar.xz/UI/installer/mp-installer.nsi
Changed
; Script generated with the Venis Install Wizard
+Unicode true
+
; Define your application name
!define APPNAME "OBS Studio"
-!define APPVERSION "0.16.5"
-!define APPNAMEANDVERSION "OBS Studio ${APPVERSION}"
+
+!ifndef APPVERSION
+!define APPVERSION "17.0.2"
+!define SHORTVERSION "17.0.2"
+!endif
+
+!define APPNAMEANDVERSION "OBS Studio ${SHORTVERSION}"
; !define FULL
-; !define REALSENSE_PLUGIN
+!define REALSENSE_PLUGIN
; Additional script dependencies
!include WinVer.nsh
InstallDir "$PROGRAMFILES32\obs-studio"
InstallDirRegKey HKLM "Software\${APPNAME}" ""
!ifdef FULL
-OutFile "OBS-Studio-${APPVERSION}-Full-Installer.exe"
+OutFile "OBS-Studio-${SHORTVERSION}-Full-Installer.exe"
!else
-OutFile "OBS-Studio-${APPVERSION}-Small-Installer.exe"
+OutFile "OBS-Studio-${SHORTVERSION}-Small-Installer.exe"
!endif
; Use compression
!include "MUI.nsh"
!define MUI_ABORTWARNING
-!define MUI_FINISHPAGE_RUN "$INSTDIR\bin\32bit\obs32.exe"
+!define MUI_FINISHPAGE_RUN
+!define MUI_FINISHPAGE_RUN_TEXT "Launch OBS Studio ${SHORTVERSION}"
+!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchOBS"
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE PreReqCheck
!insertmacro MUI_PAGE_WELCOME
-!insertmacro MUI_PAGE_LICENSE "data\obs-studio\license\gplv2.txt"
+!insertmacro MUI_PAGE_LICENSE "new\core\data\obs-studio\license\gplv2.txt"
!insertmacro MUI_PAGE_DIRECTORY
!ifdef FULL
!insertmacro MUI_PAGE_COMPONENTS
ClearErrors
; Check previous instance
- FindProcDLL::FindProc "obs32.exe"
+
+ OBSInstallerUtils::IsProcessRunning "obs32.exe"
IntCmp $R0 1 0 notRunning1
MessageBox MB_OK|MB_ICONEXCLAMATION "${APPNAME} is already running. Please close it first before installing a new version." /SD IDOK
Quit
notRunning1:
+
${if} ${RunningX64}
- FindProcDLL::FindProc "obs64.exe"
+ OBSInstallerUtils::IsProcessRunning "obs64.exe"
IntCmp $R0 1 0 notRunning2
MessageBox MB_OK|MB_ICONEXCLAMATION "${APPNAME} is already running. Please close it first before installing a new version." /SD IDOK
Quit
+ notRunning2:
${endif}
- notRunning2:
+ OBSInstallerUtils::AddInUseFileCheck "$INSTDIR\data\obs-plugins\win-capture\graphics-hook32.dll"
+ OBSInstallerUtils::AddInUseFileCheck "$INSTDIR\data\obs-plugins\win-capture\graphics-hook64.dll"
+ OBSInstallerUtils::GetAppNameForInUseFiles
+ StrCmp $R0 "" gameCaptureNotRunning
+ MessageBox MB_OK|MB_ICONEXCLAMATION "Game Capture is still in use by the following applications:$\r$\n$\r$\n$R0$\r$\nPlease close these applications before installing a new version of OBS." /SD IDOK
+ Quit
+ gameCaptureNotRunning:
FunctionEnd
Function filesInUse
MessageBox MB_OK|MB_ICONEXCLAMATION "Some files were not able to be installed. If this is the first time you are installing OBS, please disable any anti-virus or other security software and try again. If you are re-installing or updating OBS, close any applications that may be have been hooked, or reboot and try again." /SD IDOK
FunctionEnd
+Function LaunchOBS
+ ${if} ${RunningX64}
+ Exec '"$WINDIR\explorer.exe" "$SMPROGRAMS\OBS Studio\OBS Studio (64bit).lnk"'
+ ${else}
+ Exec '"$WINDIR\explorer.exe" "$SMPROGRAMS\OBS Studio\OBS Studio (32bit).lnk"'
+ ${endif}
+FunctionEnd
+
Var outputErrors
Section "OBS Studio" SecCore
SetOverwrite on
AllowSkipFiles off
- KillProcDLL::KillProc "obs-plugins\32bit\cef-bootstrap.exe"
- KillProcDLL::KillProc "obs-plugins\64bit\cef-bootstrap.exe"
-
SetShellVarContext all
; Set Section Files and Shortcuts
SetOutPath "$INSTDIR"
- File /r "data"
+ OBSInstallerUtils::KillProcess "obs-plugins\32bit\cef-bootstrap.exe"
+ OBSInstallerUtils::KillProcess "obs-plugins\64bit\cef-bootstrap.exe"
+ File /r "new\core\data"
SetOutPath "$INSTDIR\bin"
- File /r "bin\32bit"
+ File /r "new\core\bin\32bit"
SetOutPath "$INSTDIR\obs-plugins"
- File /r "obs-plugins\32bit"
+ File /r "new\core\obs-plugins\32bit"
${if} ${RunningX64}
SetOutPath "$INSTDIR\bin"
- File /r "bin\64bit"
+ File /r "new\core\bin\64bit"
SetOutPath "$INSTDIR\obs-plugins"
- File /r "obs-plugins\64bit"
+ File /r "new\core\obs-plugins\64bit"
${endif}
ClearErrors
Delete "$SMPROGRAMS\OBS Multiplatform\OBS Multiplatform (64bit).lnk"
${endif}
- SetOutPath "$INSTDIR\bin\32bit"
${if} ${RunningX64}
+ SetOutPath "$INSTDIR\bin\64bit"
CreateShortCut "$DESKTOP\OBS Studio.lnk" "$INSTDIR\bin\64bit\obs64.exe"
${else}
+ SetOutPath "$INSTDIR\bin\32bit"
CreateShortCut "$DESKTOP\OBS Studio.lnk" "$INSTDIR\bin\32bit\obs32.exe"
${endif}
+ SetOutPath "$INSTDIR\bin\32bit"
CreateDirectory "$SMPROGRAMS\OBS Studio"
CreateShortCut "$SMPROGRAMS\OBS Studio\OBS Studio (32bit).lnk" "$INSTDIR\bin\32bit\obs32.exe"
CreateShortCut "$SMPROGRAMS\OBS Studio\Uninstall.lnk" "$INSTDIR\uninstall.exe"
SetShellVarContext all
SetOutPath "$INSTDIR\obs-plugins"
- File /r "obs-browser\obs-plugins\32bit"
+ OBSInstallerUtils::KillProcess "32bit\cef-bootstrap.exe"
+ File /r "new\obs-browser\obs-plugins\32bit"
${if} ${RunningX64}
- File /r "obs-browser\obs-plugins\64bit"
+ OBSInstallerUtils::KillProcess "64bit\cef-bootstrap.exe"
+ File /r "new\obs-browser\obs-plugins\64bit"
${endif}
SetOutPath "$INSTDIR\bin\32bit"
SetShellVarContext all
SetOutPath "$INSTDIR\obs-plugins"
- File /r "realsense\32bit"
+ File /r "new\realsense\32bit"
${if} ${RunningX64}
- File /r "realsense\64bit"
+ File /r "new\realsense\64bit"
${endif}
SetOutPath "$INSTDIR\data\obs-plugins"
- File /r "realsense\actual_data\obs-plugins\win-ivcam"
+ File /r "new\realsense\data\obs-plugins\win-ivcam"
ExecWait '"$INSTDIR\data\obs-plugins\win-ivcam\seg_service.exe" /UnregServer'
ExecWait '"$INSTDIR\data\obs-plugins\win-ivcam\seg_service.exe" /RegServer'
!insertmacro MUI_UNFUNCTION_DESCRIPTION_END
; Version information
-VIProductVersion "0.${APPVERSION}"
+VIProductVersion "${APPVERSION}.0"
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "OBS Studio"
VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "obsproject.com"
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "(c) 2012-2016"
obs-studio-17.0.2.tar.xz/UI/obs-app.cpp -> obs-studio-18.0.0.tar.xz/UI/obs-app.cpp
Changed
#include <wchar.h>
#include <chrono>
#include <ratio>
+#include <string>
#include <sstream>
#include <mutex>
#include <util/bmem.h>
#include <signal.h>
#endif
+#include <iostream>
+
using namespace std;
static log_handler_t def_log_handler;
static bool unfiltered_log = false;
bool opt_start_streaming = false;
bool opt_start_recording = false;
+bool opt_studio_mode = false;
+bool opt_start_replaybuffer = false;
+bool opt_minimize_tray = false;
string opt_starting_collection;
string opt_starting_profile;
string opt_starting_scene;
vsnprintf(str, 4095, msg, args);
#ifdef _WIN32
- OutputDebugStringA(str);
- OutputDebugStringA("\n");
+ if (IsDebuggerPresent()) {
+ int wNum = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
+ if (wNum > 1) {
+ static wstring wide_buf;
+ static mutex wide_mutex;
+
+ lock_guard<mutex> lock(wide_mutex);
+ wide_buf.reserve(wNum + 1);
+ wide_buf.resize(wNum - 1);
+ MultiByteToWideChar(CP_UTF8, 0, str, -1, &wide_buf[0],
+ wNum);
+ wide_buf.push_back('\n');
+
+ OutputDebugStringW(wide_buf.c_str());
+ }
+ }
#else
def_log_handler(log_level, msg, args2, nullptr);
#endif
config_set_default_uint(globalConfig, "General", "MaxLogs", 10);
config_set_default_string(globalConfig, "General", "ProcessPriority",
"Normal");
+ config_set_default_bool(globalConfig, "General", "EnableAutoUpdates",
+ true);
#if _WIN32
config_set_default_string(globalConfig, "Video", "Renderer",
config_set_default_bool(globalConfig, "BasicWindow",
"SysTrayWhenStarted", false);
config_set_default_bool(globalConfig, "BasicWindow",
+ "SaveProjectors", false);
+ config_set_default_bool(globalConfig, "BasicWindow",
"ShowTransitions", true);
config_set_default_bool(globalConfig, "BasicWindow",
"ShowListboxToolbars", true);
return false;
if (!do_mkdir(path))
return false;
+
+ if (GetConfigPath(path, sizeof(path), "obs-studio/updates") <= 0)
+ return false;
+ if (!do_mkdir(path))
+ return false;
#endif
+
if (GetConfigPath(path, sizeof(path), "obs-studio/plugin_config") <= 0)
return false;
if (!do_mkdir(path))
profiler_start();
profile_register_root(run_program_init, 0);
- auto PrintInitProfile = [&]()
- {
- auto snap = GetSnapshot();
-
- profiler_snapshot_filter_roots(snap.get(), [](void *data,
- const char *name, bool *remove)
- {
- *remove = (*static_cast<const char**>(data)) != name;
- return true;
- }, static_cast<void*>(&run_program_init));
-
- profiler_print(snap.get());
- };
-
ScopeProfiler prof{run_program_init};
QCoreApplication::addLibraryPath(".");
} else if (arg_is(argv[i], "--startrecording", nullptr)) {
opt_start_recording = true;
+ } else if (arg_is(argv[i], "--startreplaybuffer", nullptr)) {
+ opt_start_replaybuffer = true;
+
} else if (arg_is(argv[i], "--collection", nullptr)) {
if (++i < argc) opt_starting_collection = argv[i];
} else if (arg_is(argv[i], "--scene", nullptr)) {
if (++i < argc) opt_starting_scene = argv[i];
+
+ } else if (arg_is(argv[i], "--minimize-to-tray", nullptr)) {
+ opt_minimize_tray = true;
+
+ } else if (arg_is(argv[i], "--studio-mode", nullptr)) {
+ opt_studio_mode = true;
+
+ } else if (arg_is(argv[i], "--help", "-h")) {
+ std::cout <<
+ "--help, -h: Get list of available commands.\n\n" <<
+ "--startstreaming: Automatically start streaming.\n" <<
+ "--startrecording: Automatically start recording.\n" <<
+ "--startreplaybuffer: Start replay buffer.\n\n" <<
+ "--collection <string>: Use specific scene collection."
+ << "\n" <<
+ "--profile <string>: Use specific profile.\n" <<
+ "--scene <string>: Start with specific scene.\n\n" <<
+ "--studio-mode: Enable studio mode.\n" <<
+ "--minimize-to-tray: Minimize to system tray.\n" <<
+ "--portable, -p: Use portable mode.\n\n" <<
+ "--verbose: Make log more verbose.\n" <<
+ "--unfiltered_log: Make log unfiltered.\n\n" <<
+ "--version, -V: Get current version.\n";
+
+ exit(0);
+
+ } else if (arg_is(argv[i], "--version", "-V")) {
+ std::cout << "OBS Studio - " <<
+ App()->GetVersionString() << "\n";
+ exit(0);
+
+ } else {
+ std::cout <<
+ "Invalid arguments. Use --help or -h to get " <<
+ "a list of available command line arguments.\n";
+ exit(0);
}
}
obs-studio-17.0.2.tar.xz/UI/obs-app.hpp -> obs-studio-18.0.0.tar.xz/UI/obs-app.hpp
Changed
extern bool opt_start_streaming;
extern bool opt_start_recording;
+extern bool opt_start_replaybuffer;
+extern bool opt_minimize_tray;
+extern bool opt_studio_mode;
extern std::string opt_starting_scene;
obs-studio-17.0.2.tar.xz/UI/obs-frontend-api/obs-frontend-internal.hpp -> obs-studio-18.0.0.tar.xz/UI/obs-frontend-api/obs-frontend-internal.hpp
Changed
#include <string>
struct obs_frontend_callbacks {
+ virtual ~obs_frontend_callbacks() {}
virtual void *obs_frontend_get_main_window(void)=0;
virtual void *obs_frontend_get_main_window_handle(void)=0;
obs-studio-17.0.2.tar.xz/UI/remote-text.cpp -> obs-studio-18.0.0.tar.xz/UI/remote-text.cpp
Changed
using namespace std;
+static auto curl_deleter = [] (CURL *curl) {curl_easy_cleanup(curl);};
+using Curl = unique_ptr<CURL, decltype(curl_deleter)>;
+
static size_t string_write(char *ptr, size_t size, size_t nmemb, string &str)
{
size_t total = size * nmemb;
contentTypeString += contentType;
}
- auto curl_deleter = [] (CURL *curl) {curl_easy_cleanup(curl);};
- using Curl = unique_ptr<CURL, decltype(curl_deleter)>;
-
Curl curl{curl_easy_init(), curl_deleter};
if (curl) {
struct curl_slist *header = nullptr;
curl_slist_free_all(header);
}
}
+
+static size_t header_write(char *ptr, size_t size, size_t nmemb,
+ vector<string> &list)
+{
+ string str;
+
+ size_t total = size * nmemb;
+ if (total)
+ str.append(ptr, total);
+
+ if (str.back() == '\n')
+ str.resize(str.size() - 1);
+ if (str.back() == '\r')
+ str.resize(str.size() - 1);
+
+ list.push_back(std::move(str));
+ return total;
+}
+
+bool GetRemoteFile(
+ const char *url,
+ std::string &str,
+ std::string &error,
+ long *responseCode,
+ const char *contentType,
+ const char *postData,
+ std::vector<std::string> extraHeaders,
+ std::string *signature)
+{
+ vector<string> header_in_list;
+ char error_in[CURL_ERROR_SIZE];
+ CURLcode code = CURLE_FAILED_INIT;
+
+ error_in[0] = 0;
+
+ string versionString("User-Agent: obs-basic ");
+ versionString += App()->GetVersionString();
+
+ string contentTypeString;
+ if (contentType) {
+ contentTypeString += "Content-Type: ";
+ contentTypeString += contentType;
+ }
+
+ Curl curl{curl_easy_init(), curl_deleter};
+ if (curl) {
+ struct curl_slist *header = nullptr;
+
+ header = curl_slist_append(header,
+ versionString.c_str());
+
+ if (!contentTypeString.empty()) {
+ header = curl_slist_append(header,
+ contentTypeString.c_str());
+ }
+
+ for (std::string &h : extraHeaders)
+ header = curl_slist_append(header, h.c_str());
+
+ curl_easy_setopt(curl.get(), CURLOPT_URL, url);
+ curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER,
+ header);
+ curl_easy_setopt(curl.get(), CURLOPT_ERRORBUFFER,
+ error_in);
+ curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION,
+ string_write);
+ curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA,
+ &str);
+ if (signature) {
+ curl_easy_setopt(curl.get(), CURLOPT_HEADERFUNCTION,
+ header_write);
+ curl_easy_setopt(curl.get(), CURLOPT_HEADERDATA,
+ &header_in_list);
+ }
+
+#if LIBCURL_VERSION_NUM >= 0x072400
+ // A lot of servers don't yet support ALPN
+ curl_easy_setopt(curl.get(), CURLOPT_SSL_ENABLE_ALPN, 0);
+#endif
+
+ if (postData) {
+ curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS,
+ postData);
+ }
+
+ code = curl_easy_perform(curl.get());
+ if (responseCode)
+ curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE,
+ responseCode);
+
+ if (code != CURLE_OK) {
+ error = error_in;
+ } else if (signature) {
+ for (string &h : header_in_list) {
+ string name = h.substr(0, 13);
+ if (name == "X-Signature: ") {
+ *signature = h.substr(13);
+ break;
+ }
+ }
+ }
+
+ curl_slist_free_all(header);
+ }
+
+ return code == CURLE_OK;
+}
obs-studio-17.0.2.tar.xz/UI/remote-text.hpp -> obs-studio-18.0.0.tar.xz/UI/remote-text.hpp
Changed
#pragma once
#include <QThread>
+#include <vector>
#include <string>
class RemoteTextThread : public QThread {
: url(url_), contentType(contentType_), postData(postData_)
{}
};
+
+bool GetRemoteFile(
+ const char *url,
+ std::string &str,
+ std::string &error,
+ long *responseCode = nullptr,
+ const char *contentType = nullptr,
+ const char *postData = nullptr,
+ std::vector<std::string> extraHeaders = std::vector<std::string>(),
+ std::string *signature = nullptr);
obs-studio-17.0.2.tar.xz/UI/volume-control.cpp -> obs-studio-18.0.0.tar.xz/UI/volume-control.cpp
Changed
#include "volume-control.hpp"
#include "qt-wrappers.hpp"
+#include "obs-app.hpp"
#include "mute-checkbox.hpp"
#include "slider-absoluteset-style.hpp"
#include <util/platform.h>
+#include <util/threading.h>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
using namespace std;
+QWeakPointer<VolumeMeterTimer> VolumeMeter::updateTimer;
+
void VolControl::OBSVolumeChanged(void *data, float db)
{
Q_UNUSED(db);
{
VolControl *volControl = static_cast<VolControl*>(data);
- QMetaObject::invokeMethod(volControl, "VolumeLevel",
- Q_ARG(float, mag),
- Q_ARG(float, level),
- Q_ARG(float, peak),
- Q_ARG(bool, muted));
+ if (muted)
+ level = mag = peak = 0.0f;
+
+ volControl->volMeter->setLevels(mag, level, peak);
}
void VolControl::OBSVolumeMuted(void *data, calldata_t *calldata)
void VolControl::updateText()
{
- volLabel->setText(QString::number(obs_fader_get_db(obs_fader), 'f', 1)
- .append(" dB"));
+ QString db = QString::number(obs_fader_get_db(obs_fader), 'f', 1)
+ .append(" dB");
+ volLabel->setText(db);
+
+ bool muted = obs_source_muted(source);
+ const char *accTextLookup = muted
+ ? "VolControl.SliderMuted"
+ : "VolControl.SliderUnmuted";
+
+ QString sourceName = obs_source_get_name(source);
+ QString accText = QTStr(accTextLookup).arg(sourceName, db);
+
+ slider->setAccessibleName(accText);
}
QString VolControl::GetName() const
QFont font = nameLabel->font();
font.setPointSize(font.pointSize()-1);
- nameLabel->setText(obs_source_get_name(source));
+ QString sourceName = obs_source_get_name(source);
+
+ nameLabel->setText(sourceName);
nameLabel->setFont(font);
volLabel->setFont(font);
slider->setMinimum(0);
textLayout->setAlignment(nameLabel, Qt::AlignLeft);
textLayout->setAlignment(volLabel, Qt::AlignRight);
- mute->setChecked(obs_source_muted(source));
+ bool muted = obs_source_muted(source);
+ mute->setChecked(muted);
+ mute->setAccessibleName(
+ QTStr("VolControl.Mute").arg(sourceName));
volLayout->addWidget(slider);
volLayout->addWidget(mute);
config->setMaximumSize(22, 22);
config->setAutoDefault(false);
+ config->setAccessibleName(QTStr("VolControl.Properties")
+ .arg(sourceName));
+
connect(config, &QAbstractButton::clicked,
this, &VolControl::EmitConfigClicked);
peakColor.setRgb(0x3E, 0xF1, 0x2B);
peakHoldColor.setRgb(0x00, 0x00, 0x00);
- resetTimer = new QTimer(this);
- connect(resetTimer, SIGNAL(timeout()), this, SLOT(resetState()));
+ updateTimerRef = updateTimer.toStrongRef();
+ if (!updateTimerRef) {
+ updateTimerRef = QSharedPointer<VolumeMeterTimer>::create();
+ updateTimerRef->start(34);
+ updateTimer = updateTimerRef;
+ }
- resetState();
+ updateTimerRef->AddVolControl(this);
}
-void VolumeMeter::resetState(void)
+VolumeMeter::~VolumeMeter()
{
- setLevels(0.0f, 0.0f, 0.0f);
- if (resetTimer->isActive())
- resetTimer->stop();
+ updateTimerRef->RemoveVolControl(this);
}
void VolumeMeter::setLevels(float nmag, float npeak, float npeakHold)
{
- mag = nmag;
- peak = npeak;
- peakHold = npeakHold;
+ uint64_t ts = os_gettime_ns();
+ QMutexLocker locker(&dataMutex);
+
+ mag += nmag;
+ peak += npeak;
+ peakHold += npeakHold;
+ multiple += 1.0f;
+ lastUpdateTime = ts;
+}
+
+inline void VolumeMeter::calcLevels()
+{
+ uint64_t ts = os_gettime_ns();
+ QMutexLocker locker(&dataMutex);
+
+ if (lastUpdateTime && ts - lastUpdateTime > 1000000000) {
+ mag = peak = peakHold = 0.0f;
+ multiple = 1.0f;
+ lastUpdateTime = 0;
+ }
- update();
+ if (multiple > 0.0f) {
+ curMag = mag / multiple;
+ curPeak = peak / multiple;
+ curPeakHold = peakHold / multiple;
- if (resetTimer->isActive())
- resetTimer->stop();
- resetTimer->start(1000);
+ mag = peak = peakHold = multiple = 0.0f;
+ }
}
void VolumeMeter::paintEvent(QPaintEvent *event)
int width = size().width();
int height = size().height();
- int scaledMag = int((float)width * mag);
- int scaledPeak = int((float)width * peak);
- int scaledPeakHold = int((float)width * peakHold);
+ calcLevels();
+
+ int scaledMag = int((float)width * curMag);
+ int scaledPeak = int((float)width * curPeak);
+ int scaledPeakHold = int((float)width * curPeakHold);
gradient.setStart(qreal(scaledMag), 0);
gradient.setFinalStop(qreal(scaledPeak), 0);
scaledPeakHold, height);
}
+
+void VolumeMeterTimer::AddVolControl(VolumeMeter *meter)
+{
+ volumeMeters.push_back(meter);
+}
+
+void VolumeMeterTimer::RemoveVolControl(VolumeMeter *meter)
+{
+ volumeMeters.removeOne(meter);
+}
+
+void VolumeMeterTimer::timerEvent(QTimerEvent*)
+{
+ for (VolumeMeter *meter : volumeMeters)
+ meter->update();
+}
obs-studio-17.0.2.tar.xz/UI/volume-control.hpp -> obs-studio-18.0.0.tar.xz/UI/volume-control.hpp
Changed
#include <obs.hpp>
#include <QWidget>
+#include <QSharedPointer>
+#include <QTimer>
+#include <QMutex>
+#include <QList>
class QPushButton;
+class VolumeMeterTimer;
class VolumeMeter : public QWidget
{
Q_PROPERTY(QColor peakHoldColor READ getPeakHoldColor WRITE setPeakHoldColor DESIGNABLE true)
private:
- float mag, peak, peakHold;
+ static QWeakPointer<VolumeMeterTimer> updateTimer;
+ QSharedPointer<VolumeMeterTimer> updateTimerRef;
+ float curMag = 0.0f, curPeak = 0.0f, curPeakHold = 0.0f;
+
+ inline void calcLevels();
+
+ QMutex dataMutex;
+ float mag = 0.0f, peak = 0.0f, peakHold = 0.0f;
+ float multiple = 0.0f;
+ uint64_t lastUpdateTime = 0;
+
QColor bkColor, magColor, peakColor, peakHoldColor;
- QTimer *resetTimer;
public:
explicit VolumeMeter(QWidget *parent = 0);
+ ~VolumeMeter();
+
void setLevels(float nmag, float npeak, float npeakHold);
QColor getBkColor() const;
void setBkColor(QColor c);
protected:
void paintEvent(QPaintEvent *event);
-private slots:
- void resetState();
+};
+
+class VolumeMeterTimer : public QTimer {
+ Q_OBJECT
+
+public:
+ inline VolumeMeterTimer() : QTimer() {}
+
+ void AddVolControl(VolumeMeter *meter);
+ void RemoveVolControl(VolumeMeter *meter);
+
+protected:
+ virtual void timerEvent(QTimerEvent *event) override;
+ QList<VolumeMeter*> volumeMeters;
};
class QLabel;
obs-studio-18.0.0.tar.xz/UI/win-update
Added
+(directory)
obs-studio-18.0.0.tar.xz/UI/win-update/update-window.cpp
Added
+#include "update-window.hpp"
+#include "obs-app.hpp"
+
+OBSUpdate::OBSUpdate(QWidget *parent, bool manualUpdate, const QString &text)
+ : QDialog (parent, Qt::WindowSystemMenuHint |
+ Qt::WindowTitleHint |
+ Qt::WindowCloseButtonHint),
+ ui (new Ui_OBSUpdate)
+{
+ ui->setupUi(this);
+ ui->text->setHtml(text);
+
+ if (manualUpdate) {
+ delete ui->skip;
+ ui->skip = nullptr;
+
+ ui->no->setText(QTStr("Cancel"));
+ }
+}
+
+void OBSUpdate::on_yes_clicked()
+{
+ done(OBSUpdate::Yes);
+}
+
+void OBSUpdate::on_no_clicked()
+{
+ done(OBSUpdate::No);
+}
+
+void OBSUpdate::on_skip_clicked()
+{
+ done(OBSUpdate::Skip);
+}
+
+void OBSUpdate::accept()
+{
+ done(OBSUpdate::Yes);
+}
+
+void OBSUpdate::reject()
+{
+ done(OBSUpdate::No);
+}
obs-studio-18.0.0.tar.xz/UI/win-update/update-window.hpp
Added
+#pragma once
+
+#include <QDialog>
+#include <memory>
+
+#include "ui_OBSUpdate.h"
+
+class OBSUpdate : public QDialog {
+ Q_OBJECT
+
+public:
+ enum ReturnVal {
+ No,
+ Yes,
+ Skip
+ };
+
+ OBSUpdate(QWidget *parent, bool manualUpdate, const QString &text);
+
+public slots:
+ void on_yes_clicked();
+ void on_no_clicked();
+ void on_skip_clicked();
+ virtual void accept() override;
+ virtual void reject() override;
+
+private:
+ std::unique_ptr<Ui_OBSUpdate> ui;
+};
obs-studio-18.0.0.tar.xz/UI/win-update/win-update-helpers.cpp
Added
+#include "win-update-helpers.hpp"
+
+void FreeProvider(HCRYPTPROV prov)
+{
+ CryptReleaseContext(prov, 0);
+}
+
+void FreeHash(HCRYPTHASH hash)
+{
+ CryptDestroyHash(hash);
+}
+
+void FreeKey(HCRYPTKEY key)
+{
+ CryptDestroyKey(key);
+}
+
+std::string vstrprintf(const char *format, va_list args)
+{
+ if (!format)
+ return std::string();
+
+ std::string str;
+ int size = (int)vsnprintf(nullptr, 0, format, args);
+ str.resize(size);
+ vsnprintf(&str[0], size, format, args);
+ return str;
+}
+
+std::string strprintf(const char *format, ...)
+{
+ std::string str;
+ va_list args;
+
+ va_start(args, format);
+ str = vstrprintf(format, args);
+ va_end(args);
+
+ return str;
+}
obs-studio-18.0.0.tar.xz/UI/win-update/win-update-helpers.hpp
Added
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <Wincrypt.h>
+
+#include <jansson.h>
+
+#include <cstdint>
+#include <string>
+
+/* ------------------------------------------------------------------------ */
+
+template<typename T, void freefunc(T)> class CustomHandle {
+ T handle;
+
+public:
+ inline CustomHandle() : handle(0) {}
+ inline CustomHandle(T in) : handle(in) {}
+ inline ~CustomHandle()
+ {
+ if (handle)
+ freefunc(handle);
+ }
+
+ inline T *operator&() {return &handle;}
+ inline operator T() const {return handle;}
+ inline T get() const {return handle;}
+
+ inline CustomHandle<T, freefunc> &operator=(T in)
+ {
+ if (handle)
+ freefunc(handle);
+ handle = in;
+ return *this;
+ }
+
+ inline bool operator!() const {return !handle;}
+};
+
+void FreeProvider(HCRYPTPROV prov);
+void FreeHash(HCRYPTHASH hash);
+void FreeKey(HCRYPTKEY key);
+
+using CryptProvider = CustomHandle<HCRYPTPROV, FreeProvider>;
+using CryptHash = CustomHandle<HCRYPTHASH, FreeHash>;
+using CryptKey = CustomHandle<HCRYPTKEY, FreeKey>;
+
+/* ------------------------------------------------------------------------ */
+
+template<typename T> class LocalPtr {
+ T *ptr = nullptr;
+
+public:
+ inline ~LocalPtr()
+ {
+ if (ptr)
+ LocalFree(ptr);
+ }
+
+ inline T **operator&() {return &ptr;}
+ inline operator T() const {return ptr;}
+ inline T *get() const {return ptr;}
+
+ inline bool operator!() const {return !ptr;}
+
+ inline T *operator->() {return ptr;}
+};
+
+/* ------------------------------------------------------------------------ */
+
+class Json {
+ json_t *json;
+
+public:
+ inline Json() : json(nullptr) {}
+ explicit inline Json(json_t *json_) : json(json_) {}
+ inline Json(const Json &from) : json(json_incref(from.json)) {}
+ inline Json(Json &&from) : json(from.json) {from.json = nullptr;}
+
+ inline ~Json() {
+ if (json)
+ json_decref(json);
+ }
+
+ inline Json &operator=(json_t *json_)
+ {
+ if (json)
+ json_decref(json);
+ json = json_;
+ return *this;
+ }
+ inline Json &operator=(const Json &from)
+ {
+ if (json)
+ json_decref(json);
+ json = json_incref(from.json);
+ return *this;
+ }
+ inline Json &operator=(Json &&from)
+ {
+ if (json)
+ json_decref(json);
+ json = from.json;
+ from.json = nullptr;
+ return *this;
+ }
+
+ inline operator json_t *() const {return json;}
+
+ inline bool operator!() const {return !json;}
+
+ inline const char *GetString(const char *name,
+ const char *def = nullptr) const
+ {
+ json_t *obj(json_object_get(json, name));
+ if (!obj)
+ return def;
+ return json_string_value(obj);
+ }
+ inline int64_t GetInt(const char *name, int def = 0) const
+ {
+ json_t *obj(json_object_get(json, name));
+ if (!obj)
+ return def;
+ return json_integer_value(obj);
+ }
+ inline json_t *GetObject(const char *name) const
+ {
+ return json_object_get(json, name);
+ }
+
+ inline json_t *get() const {return json;}
+};
+
+/* ------------------------------------------------------------------------ */
+
+std::string vstrprintf(const char *format, va_list args);
+std::string strprintf(const char *format, ...);
obs-studio-18.0.0.tar.xz/UI/win-update/win-update.cpp
Added
+#include "win-update-helpers.hpp"
+#include "update-window.hpp"
+#include "remote-text.hpp"
+#include "win-update.hpp"
+#include "obs-app.hpp"
+
+#include <QMessageBox>
+
+#include <string>
+
+#include <util/windows/WinHandle.hpp>
+#include <util/util.hpp>
+#include <jansson.h>
+#include <blake2.h>
+
+#include <time.h>
+#include <strsafe.h>
+#include <winhttp.h>
+#include <shellapi.h>
+
+using namespace std;
+
+/* ------------------------------------------------------------------------ */
+
+#ifndef WIN_MANIFEST_URL
+#define WIN_MANIFEST_URL "https://obsproject.com/update_studio/manifest.json"
+#endif
+
+#ifndef WIN_UPDATER_URL
+#define WIN_UPDATER_URL "https://obsproject.com/update_studio/updater.exe"
+#endif
+
+static HCRYPTPROV provider = 0;
+
+#pragma pack(push, r1, 1)
+
+typedef struct {
+ BLOBHEADER blobheader;
+ RSAPUBKEY rsapubkey;
+} PUBLICKEYHEADER;
+
+#pragma pack(pop, r1)
+
+#define BLAKE2_HASH_LENGTH 20
+#define BLAKE2_HASH_STR_LENGTH ((BLAKE2_HASH_LENGTH * 2) + 1)
+
+#define TEST_BUILD
+
+// Hard coded 4096 bit RSA public key for obsproject.com in PEM format
+static const unsigned char obs_pub[] = {
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50,
+ 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d,
+ 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x49, 0x6a, 0x41, 0x4e, 0x42,
+ 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41,
+ 0x51, 0x45, 0x46, 0x41, 0x41, 0x4f, 0x43, 0x41, 0x67, 0x38, 0x41, 0x4d,
+ 0x49, 0x49, 0x43, 0x43, 0x67, 0x4b, 0x43, 0x41, 0x67, 0x45, 0x41, 0x6c,
+ 0x33, 0x73, 0x76, 0x65, 0x72, 0x77, 0x39, 0x48, 0x51, 0x2b, 0x72, 0x59,
+ 0x51, 0x4e, 0x6e, 0x39, 0x43, 0x61, 0x37, 0x0a, 0x39, 0x4c, 0x55, 0x36,
+ 0x32, 0x6e, 0x47, 0x36, 0x4e, 0x6f, 0x7a, 0x45, 0x2f, 0x46, 0x73, 0x49,
+ 0x56, 0x4e, 0x65, 0x72, 0x2b, 0x57, 0x2f, 0x68, 0x75, 0x65, 0x45, 0x38,
+ 0x57, 0x51, 0x31, 0x6d, 0x72, 0x46, 0x50, 0x2b, 0x32, 0x79, 0x41, 0x2b,
+ 0x69, 0x59, 0x52, 0x75, 0x74, 0x59, 0x50, 0x65, 0x45, 0x67, 0x70, 0x78,
+ 0x74, 0x6f, 0x64, 0x48, 0x68, 0x67, 0x6b, 0x52, 0x34, 0x70, 0x45, 0x4b,
+ 0x0a, 0x56, 0x6e, 0x72, 0x72, 0x31, 0x38, 0x71, 0x34, 0x73, 0x7a, 0x6c,
+ 0x76, 0x38, 0x39, 0x51, 0x49, 0x37, 0x74, 0x38, 0x6c, 0x4d, 0x6f, 0x4c,
+ 0x54, 0x6c, 0x46, 0x2b, 0x74, 0x31, 0x49, 0x52, 0x30, 0x56, 0x34, 0x77,
+ 0x4a, 0x56, 0x33, 0x34, 0x49, 0x33, 0x43, 0x2b, 0x33, 0x35, 0x39, 0x4b,
+ 0x69, 0x78, 0x6e, 0x7a, 0x4c, 0x30, 0x42, 0x6c, 0x39, 0x61, 0x6a, 0x2f,
+ 0x7a, 0x44, 0x63, 0x72, 0x58, 0x0a, 0x57, 0x6c, 0x35, 0x70, 0x48, 0x54,
+ 0x69, 0x6f, 0x4a, 0x77, 0x59, 0x4f, 0x67, 0x4d, 0x69, 0x42, 0x47, 0x4c,
+ 0x79, 0x50, 0x65, 0x69, 0x74, 0x4d, 0x46, 0x64, 0x6a, 0x6a, 0x54, 0x49,
+ 0x70, 0x43, 0x4d, 0x2b, 0x6d, 0x78, 0x54, 0x57, 0x58, 0x43, 0x72, 0x5a,
+ 0x39, 0x64, 0x50, 0x55, 0x4b, 0x76, 0x5a, 0x74, 0x67, 0x7a, 0x6a, 0x64,
+ 0x2b, 0x49, 0x7a, 0x6c, 0x48, 0x69, 0x64, 0x48, 0x74, 0x4f, 0x0a, 0x4f,
+ 0x52, 0x42, 0x4e, 0x35, 0x6d, 0x52, 0x73, 0x38, 0x4c, 0x4e, 0x4f, 0x35,
+ 0x38, 0x6b, 0x37, 0x39, 0x72, 0x37, 0x37, 0x44, 0x63, 0x67, 0x51, 0x59,
+ 0x50, 0x4e, 0x69, 0x69, 0x43, 0x74, 0x57, 0x67, 0x43, 0x2b, 0x59, 0x34,
+ 0x4b, 0x37, 0x75, 0x53, 0x5a, 0x58, 0x33, 0x48, 0x76, 0x65, 0x6f, 0x6d,
+ 0x32, 0x74, 0x48, 0x62, 0x56, 0x58, 0x79, 0x30, 0x4c, 0x2f, 0x43, 0x6c,
+ 0x37, 0x66, 0x4d, 0x0a, 0x48, 0x4b, 0x71, 0x66, 0x63, 0x51, 0x47, 0x75,
+ 0x79, 0x72, 0x76, 0x75, 0x64, 0x34, 0x32, 0x4f, 0x72, 0x57, 0x61, 0x72,
+ 0x41, 0x73, 0x6e, 0x32, 0x70, 0x32, 0x45, 0x69, 0x36, 0x4b, 0x7a, 0x78,
+ 0x62, 0x33, 0x47, 0x36, 0x45, 0x53, 0x43, 0x77, 0x31, 0x35, 0x6e, 0x48,
+ 0x41, 0x67, 0x4c, 0x61, 0x6c, 0x38, 0x7a, 0x53, 0x71, 0x37, 0x2b, 0x72,
+ 0x61, 0x45, 0x2f, 0x78, 0x6b, 0x4c, 0x70, 0x43, 0x0a, 0x62, 0x59, 0x67,
+ 0x35, 0x67, 0x6d, 0x59, 0x36, 0x76, 0x62, 0x6d, 0x57, 0x6e, 0x71, 0x39,
+ 0x64, 0x71, 0x57, 0x72, 0x55, 0x7a, 0x61, 0x71, 0x4f, 0x66, 0x72, 0x5a,
+ 0x50, 0x67, 0x76, 0x67, 0x47, 0x30, 0x57, 0x76, 0x6b, 0x42, 0x53, 0x68,
+ 0x66, 0x61, 0x45, 0x4f, 0x42, 0x61, 0x49, 0x55, 0x78, 0x41, 0x33, 0x51,
+ 0x42, 0x67, 0x7a, 0x41, 0x5a, 0x68, 0x71, 0x65, 0x65, 0x64, 0x46, 0x39,
+ 0x68, 0x0a, 0x61, 0x66, 0x4d, 0x47, 0x4d, 0x4d, 0x39, 0x71, 0x56, 0x62,
+ 0x66, 0x77, 0x75, 0x75, 0x7a, 0x4a, 0x32, 0x75, 0x68, 0x2b, 0x49, 0x6e,
+ 0x61, 0x47, 0x61, 0x65, 0x48, 0x32, 0x63, 0x30, 0x34, 0x6f, 0x56, 0x63,
+ 0x44, 0x46, 0x66, 0x65, 0x4f, 0x61, 0x44, 0x75, 0x78, 0x52, 0x6a, 0x43,
+ 0x43, 0x62, 0x71, 0x72, 0x35, 0x73, 0x4c, 0x53, 0x6f, 0x31, 0x43, 0x57,
+ 0x6f, 0x6b, 0x79, 0x6e, 0x6a, 0x4e, 0x0a, 0x43, 0x42, 0x2b, 0x62, 0x32,
+ 0x72, 0x51, 0x46, 0x37, 0x44, 0x50, 0x50, 0x62, 0x44, 0x34, 0x73, 0x2f,
+ 0x6e, 0x54, 0x39, 0x4e, 0x73, 0x63, 0x6b, 0x2f, 0x4e, 0x46, 0x7a, 0x72,
+ 0x42, 0x58, 0x52, 0x4f, 0x2b, 0x64, 0x71, 0x6b, 0x65, 0x42, 0x77, 0x44,
+ 0x55, 0x43, 0x76, 0x37, 0x62, 0x5a, 0x67, 0x57, 0x37, 0x4f, 0x78, 0x75,
+ 0x4f, 0x58, 0x30, 0x37, 0x4c, 0x54, 0x71, 0x66, 0x70, 0x35, 0x73, 0x0a,
+ 0x4f, 0x65, 0x47, 0x67, 0x75, 0x62, 0x75, 0x62, 0x69, 0x77, 0x59, 0x33,
+ 0x55, 0x64, 0x48, 0x59, 0x71, 0x2b, 0x4c, 0x39, 0x4a, 0x71, 0x49, 0x53,
+ 0x47, 0x31, 0x74, 0x4d, 0x34, 0x48, 0x65, 0x4b, 0x6a, 0x61, 0x48, 0x6a,
+ 0x75, 0x31, 0x4d, 0x44, 0x6a, 0x76, 0x48, 0x5a, 0x32, 0x44, 0x62, 0x6d,
+ 0x4c, 0x77, 0x55, 0x78, 0x75, 0x59, 0x61, 0x36, 0x4a, 0x5a, 0x44, 0x4b,
+ 0x57, 0x73, 0x37, 0x72, 0x0a, 0x49, 0x72, 0x64, 0x44, 0x77, 0x78, 0x33,
+ 0x4a, 0x77, 0x61, 0x63, 0x46, 0x36, 0x36, 0x68, 0x33, 0x59, 0x55, 0x57,
+ 0x36, 0x74, 0x7a, 0x55, 0x5a, 0x68, 0x7a, 0x74, 0x63, 0x6d, 0x51, 0x65,
+ 0x70, 0x50, 0x2f, 0x75, 0x37, 0x42, 0x67, 0x47, 0x72, 0x6b, 0x4f, 0x50,
+ 0x50, 0x70, 0x59, 0x41, 0x30, 0x4e, 0x45, 0x4a, 0x38, 0x30, 0x53, 0x65,
+ 0x41, 0x78, 0x37, 0x68, 0x69, 0x4e, 0x34, 0x76, 0x61, 0x0a, 0x65, 0x45,
+ 0x51, 0x4b, 0x6e, 0x52, 0x6e, 0x2b, 0x45, 0x70, 0x42, 0x4e, 0x36, 0x55,
+ 0x42, 0x61, 0x35, 0x66, 0x37, 0x4c, 0x6f, 0x4b, 0x38, 0x43, 0x41, 0x77,
+ 0x45, 0x41, 0x41, 0x51, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
+ 0x45, 0x4e, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b,
+ 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a
+};
+static const unsigned int obs_pub_len = 800;
+
+/* ------------------------------------------------------------------------ */
+
+static bool QuickWriteFile(const char *file, const void *data, size_t size)
+try {
+ BPtr<wchar_t> w_file;
+ if (os_utf8_to_wcs_ptr(file, 0, &w_file) == 0)
+ return false;
+
+ WinHandle handle = CreateFileW(
+ w_file,
+ GENERIC_WRITE,
+ 0,
+ nullptr,
+ CREATE_ALWAYS,
+ FILE_FLAG_WRITE_THROUGH,
+ nullptr);
+
+ if (handle == INVALID_HANDLE_VALUE)
+ throw strprintf("Failed to open file '%s': %lu",
+ file, GetLastError());
+
+ DWORD written;
+ if (!WriteFile(handle, data, (DWORD)size, &written, nullptr))
+ throw strprintf("Failed to write file '%s': %lu",
+ file, GetLastError());
+
+ return true;
+
+} catch (string text) {
+ blog(LOG_WARNING, "%s: %s", __FUNCTION__, text.c_str());
+ return false;
+}
+
+static bool QuickReadFile(const char *file, string &data)
+try {
+ BPtr<wchar_t> w_file;
+ if (os_utf8_to_wcs_ptr(file, 0, &w_file) == 0)
+ return false;
+
+ WinHandle handle = CreateFileW(
+ w_file,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ nullptr,
+ OPEN_EXISTING,
+ 0,
+ nullptr);
+
+ if (handle == INVALID_HANDLE_VALUE)
+ throw strprintf("Failed to open file '%s': %lu",
+ file, GetLastError());
+
+ DWORD size = GetFileSize(handle, nullptr);
+ data.resize(size);
+
+ DWORD read;
+ if (!ReadFile(handle, &data[0], size, &read, nullptr))
+ throw strprintf("Failed to write file '%s': %lu",
+ file, GetLastError());
+
+ return true;
+
+} catch (string text) {
+ blog(LOG_WARNING, "%s: %s", __FUNCTION__, text.c_str());
+ return false;
+}
+
+static void HashToString(const uint8_t *in, char *out)
+{
+ const char alphabet[] = "0123456789abcdef";
+
+ for (int i = 0; i != BLAKE2_HASH_LENGTH; ++i) {
+ out[2 * i] = alphabet[in[i] / 16];
+ out[2 * i + 1] = alphabet[in[i] % 16];
+ }
+
+ out[BLAKE2_HASH_LENGTH * 2] = 0;
+}
+
+static bool CalculateFileHash(const char *path, uint8_t *hash)
+try {
+ blake2b_state blake2;
+ if (blake2b_init(&blake2, BLAKE2_HASH_LENGTH) != 0)
+ return false;
+
+ BPtr<wchar_t> w_path;
+ if (os_utf8_to_wcs_ptr(path, 0, &w_path) == 0)
+ return false;
+
+ WinHandle handle = CreateFileW(w_path, GENERIC_READ, FILE_SHARE_READ,
+ nullptr, OPEN_EXISTING, 0, nullptr);
+ if (handle == INVALID_HANDLE_VALUE)
+ throw strprintf("Failed to open file '%s': %lu",
+ path, GetLastError());
+
+ vector<BYTE> buf;
+ buf.resize(65536);
+
+ for (;;) {
+ DWORD read = 0;
+ if (!ReadFile(handle, buf.data(), (DWORD)buf.size(), &read,
+ nullptr))
+ throw strprintf("Failed to read file '%s': %lu",
+ path, GetLastError());
+
+ if (!read)
+ break;
+
+ if (blake2b_update(&blake2, buf.data(), read) != 0)
+ return false;
+ }
+
+ if (blake2b_final(&blake2, hash, BLAKE2_HASH_LENGTH) != 0)
+ return false;
+
+ return true;
+
+} catch (string text) {
+ blog(LOG_WARNING, "%s: %s", __FUNCTION__, text.c_str());
+ return false;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static bool VerifyDigitalSignature(uint8_t *buf, size_t len, uint8_t *sig,
+ size_t sigLen)
+{
+ /* ASN of PEM public key */
+ BYTE binaryKey[1024];
+ DWORD binaryKeyLen = sizeof(binaryKey);
+
+ /* Windows X509 public key info from ASN */
+ LocalPtr<CERT_PUBLIC_KEY_INFO> publicPBLOB;
+ DWORD iPBLOBSize;
+
+ /* RSA BLOB info from X509 public key */
+ LocalPtr<PUBLICKEYHEADER> rsaPublicBLOB;
+ DWORD rsaPublicBLOBSize;
+
+ /* Handle to public key */
+ CryptKey keyOut;
+
+ /* Handle to hash context */
+ CryptHash hash;
+
+ /* Signature in little-endian format */
+ vector<BYTE> reversedSig;
+
+ if (!CryptStringToBinaryA((LPCSTR)obs_pub,
+ obs_pub_len,
+ CRYPT_STRING_BASE64HEADER,
+ binaryKey,
+ &binaryKeyLen,
+ nullptr,
+ nullptr))
+ return false;
+
+ if (!CryptDecodeObjectEx(X509_ASN_ENCODING,
+ X509_PUBLIC_KEY_INFO,
+ binaryKey,
+ binaryKeyLen,
+ CRYPT_ENCODE_ALLOC_FLAG,
+ nullptr,
+ &publicPBLOB,
+ &iPBLOBSize))
+ return false;
+
+ if (!CryptDecodeObjectEx(X509_ASN_ENCODING,
+ RSA_CSP_PUBLICKEYBLOB,
+ publicPBLOB->PublicKey.pbData,
+ publicPBLOB->PublicKey.cbData,
+ CRYPT_ENCODE_ALLOC_FLAG,
+ nullptr,
+ &rsaPublicBLOB,
+ &rsaPublicBLOBSize))
+ return false;
+
+ if (!CryptImportKey(provider,
+ (const BYTE *)rsaPublicBLOB.get(),
+ rsaPublicBLOBSize,
+ 0,
+ 0,
+ &keyOut))
+ return false;
+
+ if (!CryptCreateHash(provider, CALG_SHA_512, 0, 0, &hash))
+ return false;
+
+ if (!CryptHashData(hash, buf, (DWORD)len, 0))
+ return false;
+
+ /* Windows requires signature in little-endian. Every other crypto
+ * provider is big-endian of course. */
+ reversedSig.resize(sigLen);
+ for (size_t i = 0; i < sigLen; i++)
+ reversedSig[i] = sig[sigLen - i - 1];
+
+ if (!CryptVerifySignature(hash,
+ reversedSig.data(),
+ (DWORD)sigLen,
+ keyOut,
+ nullptr,
+ 0))
+ return false;
+
+ return true;
+}
+
+static inline void HexToByteArray(const char *hexStr, size_t hexLen,
+ vector<uint8_t> &out)
+{
+ char ptr[3];
+
+ ptr[2] = 0;
+
+ for (size_t i = 0; i < hexLen; i += 2) {
+ ptr[0] = hexStr[i];
+ ptr[1] = hexStr[i + 1];
+ out.push_back((uint8_t)strtoul(ptr, nullptr, 16));
+ }
+}
+
+static bool CheckDataSignature(const string &data, const char *name,
+ const char *hexSig, size_t sigLen)
+try {
+ if (sigLen == 0 || sigLen > 0xFFFF || (sigLen & 1) != 0)
+ throw strprintf("Missing or invalid signature for %s", name);
+
+ /* Convert TCHAR signature to byte array */
+ vector<uint8_t> signature;
+ signature.reserve(sigLen);
+ HexToByteArray(hexSig, sigLen, signature);
+
+ if (!VerifyDigitalSignature((uint8_t*)data.data(),
+ data.size(),
+ signature.data(),
+ signature.size()))
+ throw strprintf("Signature check failed for %s", name);
+
+ return true;
+
+} catch (string text) {
+ blog(LOG_WARNING, "%s: %s", __FUNCTION__, text.c_str());
+ return false;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static bool FetchUpdaterModule(const char *url)
+try {
+ long responseCode;
+ uint8_t updateFileHash[BLAKE2_HASH_LENGTH];
+ vector<string> extraHeaders;
+
+ BPtr<char> updateFilePath = GetConfigPathPtr(
+ "obs-studio\\updates\\updater.exe");
+
+ if (CalculateFileHash(updateFilePath, updateFileHash)) {
+ char hashString[BLAKE2_HASH_STR_LENGTH];
+ HashToString(updateFileHash, hashString);
+
+ string header = "If-None-Match: ";
+ header += hashString;
+ extraHeaders.push_back(move(header));
+ }
+
+ string signature;
+ string error;
+ string data;
+
+ bool success = GetRemoteFile(url, data, error, &responseCode,
+ nullptr, nullptr, extraHeaders, &signature);
+
+ if (!success || (responseCode != 200 && responseCode != 304)) {
+ if (responseCode == 404)
+ return false;
+
+ throw strprintf("Could not fetch '%s': %s", url, error.c_str());
+ }
+
+ /* A new file must be digitally signed */
+ if (responseCode == 200) {
+ bool valid = CheckDataSignature(data, url, signature.data(),
+ signature.size());
+ if (!valid)
+ throw string("Invalid updater module signature");
+
+ if (!QuickWriteFile(updateFilePath, data.data(), data.size()))
+ return false;
+ }
+
+ return true;
+
+} catch (string text) {
+ blog(LOG_WARNING, "%s: %s", __FUNCTION__, text.c_str());
+ return false;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static bool ParseUpdateManifest(const char *manifest, bool *updatesAvailable,
+ string ¬es_str, int &updateVer)
+try {
+
+ json_error_t error;
+ Json root(json_loads(manifest, 0, &error));
+ if (!root)
+ throw strprintf("Failed reading json string (%d): %s",
+ error.line, error.text);
+
+ if (!json_is_object(root.get()))
+ throw string("Root of manifest is not an object");
+
+ int major = root.GetInt("version_major");
+ int minor = root.GetInt("version_minor");
+ int patch = root.GetInt("version_patch");
+
+ if (major == 0)
+ throw strprintf("Invalid version number: %d.%d.%d",
+ major,
+ minor,
+ patch);
+
+ json_t *notes = json_object_get(root, "notes");
+ if (!json_is_string(notes))
+ throw string("'notes' value invalid");
+
+ notes_str = json_string_value(notes);
+
+ json_t *packages = json_object_get(root, "packages");
+ if (!json_is_array(packages))
+ throw string("'packages' value invalid");
+
+ int cur_ver = LIBOBS_API_VER;
+ int new_ver = MAKE_SEMANTIC_VERSION(major, minor, patch);
+
+ updateVer = new_ver;
+ *updatesAvailable = new_ver > cur_ver;
+
+ return true;
+
+} catch (string text) {
+ blog(LOG_WARNING, "%s: %s", __FUNCTION__, text.c_str());
+ return false;
+}
+
+/* ------------------------------------------------------------------------ */
+
+void GenerateGUID(string &guid)
+{
+ BYTE junk[20];
+
+ if (!CryptGenRandom(provider, sizeof(junk), junk))
+ return;
+
+ guid.resize(41);
+ HashToString(junk, &guid[0]);
+}
+
+void AutoUpdateThread::infoMsg(const QString &title, const QString &text)
+{
+ QMessageBox::information(App()->GetMainWindow(), title, text);
+}
+
+void AutoUpdateThread::info(const QString &title, const QString &text)
+{
+ QMetaObject::invokeMethod(this, "infoMsg",
+ Qt::BlockingQueuedConnection,
+ Q_ARG(QString, title),
+ Q_ARG(QString, text));
+}
+
+int AutoUpdateThread::queryUpdateSlot(bool manualUpdate, const QString &text)
+{
+ OBSUpdate updateDlg(App()->GetMainWindow(), manualUpdate, text);
+ return updateDlg.exec();
+}
+
+int AutoUpdateThread::queryUpdate(bool manualUpdate, const char *text_utf8)
+{
+ int ret = OBSUpdate::No;
+ QString text = text_utf8;
+ QMetaObject::invokeMethod(this, "queryUpdateSlot",
+ Qt::BlockingQueuedConnection,
+ Q_RETURN_ARG(int, ret),
+ Q_ARG(bool, manualUpdate),
+ Q_ARG(QString, text));
+ return ret;
+}
+
+static bool IsFileInUse(const wstring &file)
+{
+ WinHandle f = CreateFile(file.c_str(), GENERIC_READ, 0, nullptr,
+ OPEN_EXISTING, 0, nullptr);
+ if (!f.Valid()) {
+ int err = GetLastError();
+ if (err == ERROR_SHARING_VIOLATION ||
+ err == ERROR_LOCK_VIOLATION)
+ return true;
+ }
+
+ return false;
+}
+
+static bool IsGameCaptureInUse()
+{
+ wstring path = L"..\\..\\data\\obs-plugins\\win-capture\\graphics-hook";
+ return IsFileInUse(path + L"32.dll") ||
+ IsFileInUse(path + L"64.dll");
+}
+
+void AutoUpdateThread::run()
+try {
+ long responseCode;
+ vector<string> extraHeaders;
+ string text;
+ string error;
+ string signature;
+ CryptProvider provider;
+ BYTE manifestHash[BLAKE2_HASH_LENGTH];
+ bool updatesAvailable = false;
+ bool success;
+
+ struct FinishedTrigger {
+ inline ~FinishedTrigger()
+ {
+ QMetaObject::invokeMethod(App()->GetMainWindow(),
+ "updateCheckFinished");
+ }
+ } finishedTrigger;
+
+ BPtr<char> manifestPath = GetConfigPathPtr(
+ "obs-studio\\updates\\manifest.json");
+
+ auto ActiveOrGameCaptureLocked = [this] ()
+ {
+ if (video_output_active(obs_get_video())) {
+ if (manualUpdate)
+ info(QTStr("Updater.Running.Title"),
+ QTStr("Updater.Running.Text"));
+ return true;
+ }
+ if (IsGameCaptureInUse()) {
+ if (manualUpdate)
+ info(QTStr("Updater.GameCaptureActive.Title"),
+ QTStr("Updater.GameCaptureActive.Text"));
+ return true;
+ }
+
+ return false;
+ };
+
+ /* ----------------------------------- *
+ * warn if running or gc locked */
+
+ if (ActiveOrGameCaptureLocked())
+ return;
+
+ /* ----------------------------------- *
+ * create signature provider */
+
+ if (!CryptAcquireContext(&provider,
+ nullptr,
+ MS_ENH_RSA_AES_PROV,
+ PROV_RSA_AES,
+ CRYPT_VERIFYCONTEXT))
+ throw strprintf("CryptAcquireContext failed: %lu",
+ GetLastError());
+
+ ::provider = provider;
+
+ /* ----------------------------------- *
+ * avoid downloading manifest again */
+
+ if (CalculateFileHash(manifestPath, manifestHash)) {
+ char hashString[BLAKE2_HASH_STR_LENGTH];
+ HashToString(manifestHash, hashString);
+
+ string header = "If-None-Match: ";
+ header += hashString;
+ extraHeaders.push_back(move(header));
+ }
+
+ /* ----------------------------------- *
+ * get current install GUID */
+
+ /* NOTE: this is an arbitrary random number that we use to count the
+ * number of unique OBS installations and is not associated with any
+ * kind of identifiable information */
+ const char *pguid = config_get_string(GetGlobalConfig(),
+ "General", "InstallGUID");
+ string guid;
+ if (pguid)
+ guid = pguid;
+
+ if (guid.empty()) {
+ GenerateGUID(guid);
+
+ if (!guid.empty())
+ config_set_string(GetGlobalConfig(),
+ "General", "InstallGUID",
+ guid.c_str());
+ }
+
+ if (!guid.empty()) {
+ string header = "X-OBS2-GUID: ";
+ header += guid;
+ extraHeaders.push_back(move(header));
+ }
+
+ /* ----------------------------------- *
+ * get manifest from server */
+
+ success = GetRemoteFile(WIN_MANIFEST_URL, text, error, &responseCode,
+ nullptr, nullptr, extraHeaders, &signature);
+
+ if (!success || (responseCode != 200 && responseCode != 304)) {
+ if (responseCode == 404)
+ return;
+
+ throw strprintf("Failed to fetch manifest file: %s", error);
+ }
+
+ /* ----------------------------------- *
+ * verify file signature */
+
+ /* a new file must be digitally signed */
+ if (responseCode == 200) {
+ success = CheckDataSignature(text, "manifest",
+ signature.data(), signature.size());
+ if (!success)
+ throw string("Invalid manifest signature");
+ }
+
+ /* ----------------------------------- *
+ * write or load manifest */
+
+ if (responseCode == 200) {
+ if (!QuickWriteFile(manifestPath, text.data(), text.size()))
+ throw strprintf("Could not write file '%s'",
+ manifestPath);
+ } else {
+ if (!QuickReadFile(manifestPath, text))
+ throw strprintf("Could not read file '%s'",
+ manifestPath);
+ }
+
+ /* ----------------------------------- *
+ * check manifest for update */
+
+ string notes;
+ int updateVer = 0;
+
+ success = ParseUpdateManifest(text.c_str(), &updatesAvailable, notes,
+ updateVer);
+ if (!success)
+ throw string("Failed to parse manifest");
+
+ if (!updatesAvailable) {
+ if (manualUpdate)
+ info(QTStr("Updater.NoUpdatesAvailable.Title"),
+ QTStr("Updater.NoUpdatesAvailable.Text"));
+ return;
+ }
+
+ /* ----------------------------------- *
+ * skip this version if set to skip */
+
+ int skipUpdateVer = config_get_int(GetGlobalConfig(), "General",
+ "SkipUpdateVersion");
+ if (!manualUpdate && updateVer == skipUpdateVer)
+ return;
+
+ /* ----------------------------------- *
+ * warn again if running or gc locked */
+
+ if (ActiveOrGameCaptureLocked())
+ return;
+
+ /* ----------------------------------- *
+ * fetch updater module */
+
+ if (!FetchUpdaterModule(WIN_UPDATER_URL))
+ return;
+
+ /* ----------------------------------- *
+ * query user for update */
+
+ int queryResult = queryUpdate(manualUpdate, notes.c_str());
+
+ if (queryResult == OBSUpdate::No) {
+ if (!manualUpdate) {
+ long long t = (long long)time(nullptr);
+ config_set_int(GetGlobalConfig(), "General",
+ "LastUpdateCheck", t);
+ }
+ return;
+
+ } else if (queryResult == OBSUpdate::Skip) {
+ config_set_int(GetGlobalConfig(), "General",
+ "SkipUpdateVersion", updateVer);
+ return;
+ }
+
+ /* ----------------------------------- *
+ * get working dir */
+
+ wchar_t cwd[MAX_PATH];
+ GetModuleFileNameW(nullptr, cwd, _countof(cwd) - 1);
+ wchar_t *p = wcsrchr(cwd, '\\');
+ if (p)
+ *p = 0;
+
+ /* ----------------------------------- *
+ * execute updater */
+
+ BPtr<char> updateFilePath = GetConfigPathPtr(
+ "obs-studio\\updates\\updater.exe");
+ BPtr<wchar_t> wUpdateFilePath;
+
+ size_t size = os_utf8_to_wcs_ptr(updateFilePath, 0, &wUpdateFilePath);
+ if (!size)
+ throw string("Could not convert updateFilePath to wide");
+
+ /* note, can't use CreateProcess to launch as admin. */
+ SHELLEXECUTEINFO execInfo = {};
+
+ execInfo.cbSize = sizeof(execInfo);
+ execInfo.lpFile = wUpdateFilePath;
+#ifndef UPDATE_CHANNEL
+#define UPDATE_ARG_SUFFIX L""
+#else
+#define UPDATE_ARG_SUFFIX UPDATE_CHANNEL
+#endif
+ if (App()->IsPortableMode())
+ execInfo.lpParameters = UPDATE_ARG_SUFFIX L" Portable";
+ else
+ execInfo.lpParameters = UPDATE_ARG_SUFFIX;
+
+ execInfo.lpDirectory = cwd;
+ execInfo.nShow = SW_SHOWNORMAL;
+
+ if (!ShellExecuteEx(&execInfo)) {
+ QString msg = QTStr("Updater.FailedToLaunch");
+ info(msg, msg);
+ throw strprintf("Can't launch updater '%s': %d",
+ updateFilePath, GetLastError());
+ }
+
+ /* force OBS to perform another update check immediately after updating
+ * in case of issues with the new version */
+ config_set_int(GetGlobalConfig(), "General", "LastUpdateCheck", 0);
+ config_set_int(GetGlobalConfig(), "General", "SkipUpdateVersion", 0);
+ config_set_string(GetGlobalConfig(), "General", "InstallGUID",
+ guid.c_str());
+
+ QMetaObject::invokeMethod(App()->GetMainWindow(), "close");
+
+} catch (string text) {
+ blog(LOG_WARNING, "%s: %s", __FUNCTION__, text.c_str());
+}
obs-studio-18.0.0.tar.xz/UI/win-update/win-update.hpp
Added
+#pragma once
+
+#include <QThread>
+#include <QString>
+
+class AutoUpdateThread : public QThread {
+ Q_OBJECT
+
+ bool manualUpdate;
+ bool user_confirmed = false;
+
+ virtual void run() override;
+
+ void info(const QString &title, const QString &text);
+ int queryUpdate(bool manualUpdate, const char *text_utf8);
+
+private slots:
+ void infoMsg(const QString &title, const QString &text);
+ int queryUpdateSlot(bool manualUpdate, const QString &text);
+
+public:
+ AutoUpdateThread(bool manualUpdate_) : manualUpdate(manualUpdate_) {}
+};
obs-studio-17.0.2.tar.xz/UI/window-basic-adv-audio.cpp -> obs-studio-18.0.0.tar.xz/UI/window-basic-adv-audio.cpp
Changed
QWidget *widget;
QLabel *label;
+ int idx = 0;
mainLayout = new QGridLayout;
mainLayout->setContentsMargins(0, 0, 0, 0);
label = new QLabel(QTStr("Basic.AdvAudio.Name"));
label->setAlignment(Qt::AlignHCenter);
- mainLayout->addWidget(label, 0, 0);
+ mainLayout->addWidget(label, 0, idx++);
label = new QLabel(QTStr("Basic.AdvAudio.Volume"));
label->setAlignment(Qt::AlignHCenter);
- mainLayout->addWidget(label, 0, 1);
+ mainLayout->addWidget(label, 0, idx++);
label = new QLabel(QTStr("Basic.AdvAudio.Mono"));
label->setAlignment(Qt::AlignHCenter);
- mainLayout->addWidget(label, 0, 2);
+ mainLayout->addWidget(label, 0, idx++);
label = new QLabel(QTStr("Basic.AdvAudio.Panning"));
label->setAlignment(Qt::AlignHCenter);
- mainLayout->addWidget(label, 0, 3);
+ mainLayout->addWidget(label, 0, idx++);
label = new QLabel(QTStr("Basic.AdvAudio.SyncOffset"));
label->setAlignment(Qt::AlignHCenter);
- mainLayout->addWidget(label, 0, 4);
+ mainLayout->addWidget(label, 0, idx++);
+#if defined(_WIN32) || defined(__APPLE__)
+ label = new QLabel(QTStr("Basic.AdvAudio.Monitoring"));
+ label->setAlignment(Qt::AlignHCenter);
+ mainLayout->addWidget(label, 0, idx++);
+#endif
label = new QLabel(QTStr("Basic.AdvAudio.AudioTracks"));
label->setAlignment(Qt::AlignHCenter);
- mainLayout->addWidget(label, 0, 5);
+ mainLayout->addWidget(label, 0, idx++);
controlArea = new QWidget;
controlArea->setLayout(mainLayout);
obs-studio-17.0.2.tar.xz/UI/window-basic-main-outputs.cpp -> obs-studio-18.0.0.tar.xz/UI/window-basic-main-outputs.cpp
Changed
obs_data_set_int(settings, "AMF.H264.Bitrate.Target", bitrate);
obs_data_set_int(settings, "bitrate", bitrate);
obs_data_set_int(settings, "AMF.H264.FillerData", 1);
+ obs_data_set_int(settings, "AMF.H264.VBVBuffer", 1);
+ obs_data_set_int(settings, "AMF.H264.VBVBuffer.Size", bitrate);
// Picture Control Properties
obs_data_set_double(settings, "AMF.H264.KeyframeInterval", 2.0);
obs_data_set_int(settings, "AMF.H264.QP.IFrame", cqp);
obs_data_set_int(settings, "AMF.H264.QP.PFrame", cqp);
obs_data_set_int(settings, "AMF.H264.QP.BFrame", cqp);
+ obs_data_set_int(settings, "AMF.H264.VBVBuffer", 1);
+ obs_data_set_int(settings, "AMF.H264.VBVBuffer.Size", 50000);
// Picture Control Properties
obs_data_set_double(settings, "AMF.H264.KeyframeInterval", 2.0);
"DelayPreserve");
const char *bindIP = config_get_string(main->Config(), "Output",
"BindIP");
+ bool enableNewSocketLoop = config_get_bool(main->Config(), "Output",
+ "NewSocketLoopEnable");
+ bool enableLowLatencyMode = config_get_bool(main->Config(), "Output",
+ "LowLatencyEnable");
obs_data_t *settings = obs_data_create();
obs_data_set_string(settings, "bind_ip", bindIP);
+ obs_data_set_bool(settings, "new_socket_loop_enabled",
+ enableNewSocketLoop);
+ obs_data_set_bool(settings, "low_latency_mode_enabled",
+ enableLowLatencyMode);
obs_output_update(streamOutput, settings);
obs_data_release(settings);
UpdateRecording();
if (!ConfigureRecording(false))
return false;
- if (!obs_output_start(fileOutput))
+ if (!obs_output_start(fileOutput)) {
+ QMessageBox::critical(main,
+ QTStr("Output.StartRecordingFailed"),
+ QTStr("Output.StartFailedGeneric"));
return false;
+ }
+
return true;
}
UpdateRecording();
if (!ConfigureRecording(true))
return false;
- if (!obs_output_start(replayBuffer))
+ if (!obs_output_start(replayBuffer)) {
+ QMessageBox::critical(main,
+ QTStr("Output.StartReplayFailed"),
+ QTStr("Output.StartFailedGeneric"));
return false;
+ }
+
return true;
}
const char *url = config_get_string(main->Config(), "AdvOut", "FFURL");
int vBitrate = config_get_int(main->Config(), "AdvOut",
"FFVBitrate");
+ int gopSize = config_get_int(main->Config(), "AdvOut",
+ "FFVGOPSize");
bool rescale = config_get_bool(main->Config(), "AdvOut",
"FFRescale");
const char *rescaleRes = config_get_string(main->Config(), "AdvOut",
obs_data_set_string(settings, "format_name", formatName);
obs_data_set_string(settings, "format_mime_type", mimeType);
obs_data_set_string(settings, "muxer_settings", muxCustom);
+ obs_data_set_int(settings, "gop_size", gopSize);
obs_data_set_int(settings, "video_bitrate", vBitrate);
obs_data_set_string(settings, "video_encoder", vEncoder);
obs_data_set_int(settings, "video_encoder_id", vEncoderId);
"DelayPreserve");
const char *bindIP = config_get_string(main->Config(), "Output",
"BindIP");
+ bool enableNewSocketLoop = config_get_bool(main->Config(), "Output",
+ "NewSocketLoopEnable");
+ bool enableLowLatencyMode = config_get_bool(main->Config(), "Output",
+ "LowLatencyEnable");
obs_data_t *settings = obs_data_create();
obs_data_set_string(settings, "bind_ip", bindIP);
+ obs_data_set_bool(settings, "new_socket_loop_enabled",
+ enableNewSocketLoop);
+ obs_data_set_bool(settings, "low_latency_mode_enabled",
+ enableLowLatencyMode);
obs_output_update(streamOutput, settings);
obs_data_release(settings);
obs_data_release(settings);
}
- if (obs_output_start(fileOutput)) {
- return true;
+ if (!obs_output_start(fileOutput)) {
+ QMessageBox::critical(main,
+ QTStr("Output.StartRecordingFailed"),
+ QTStr("Output.StartFailedGeneric"));
+ return false;
}
- return false;
+ return true;
}
void AdvancedOutput::StopStreaming(bool force)
obs-studio-17.0.2.tar.xz/UI/window-basic-main-scene-collections.cpp -> obs-studio-18.0.0.tar.xz/UI/window-basic-main-scene-collections.cpp
Changed
EnumSceneCollections(addCollection);
ui->actionRemoveSceneCollection->setEnabled(count > 1);
+
+ OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow());
+ main->OpenSavedProjectors();
}
void OBSBasic::on_actionNewSceneCollection_triggered()
obs-studio-17.0.2.tar.xz/UI/window-basic-main-transitions.cpp -> obs-studio-18.0.0.tar.xz/UI/window-basic-main-transitions.cpp
Changed
SetCurrentScene(scene);
}
- if (api)
+ if (api) {
api->on_event(OBS_FRONTEND_EVENT_TRANSITION_STOPPED);
+ api->on_event(OBS_FRONTEND_EVENT_SCENE_CHANGED);
+ }
swapScene = nullptr;
}
obs_source_t *transition = obs_get_output_source(0);
- if (force)
+ if (force) {
obs_transition_set(transition, source);
- else
+ if (api)
+ api->on_event(OBS_FRONTEND_EVENT_SCENE_CHANGED);
+ } else {
obs_transition_start(transition, OBS_TRANSITION_MODE_AUTO,
ui->transitionDuration->value(), source);
+ }
if (usingPreviewProgram && sceneDuplicationMode)
obs_scene_release(scene);
obs_source_release(transition);
-
- if (api)
- api->on_event(OBS_FRONTEND_EVENT_SCENE_CHANGED);
}
static inline void SetComboTransition(QComboBox *combo, obs_source_t *tr)
obs-studio-17.0.2.tar.xz/UI/window-basic-main.cpp -> obs-studio-18.0.0.tar.xz/UI/window-basic-main.cpp
Changed
#include "volume-control.hpp"
#include "remote-text.hpp"
+#if defined(_WIN32) && defined(ENABLE_WIN_UPDATER)
+#include "win-update/win-update.hpp"
+#endif
+
#include "ui_OBSBasic.h"
#include <fstream>
: OBSMainWindow (parent),
ui (new Ui::OBSBasic)
{
+ setAttribute(Qt::WA_NativeWindow);
+
+ projectorArray.resize(10, "");
+ previewProjectorArray.resize(10, 0);
+
setAcceptDrops(true);
ui->setupUi(this);
static obs_data_t *GenerateSaveData(obs_data_array_t *sceneOrder,
obs_data_array_t *quickTransitionData, int transitionDuration,
obs_data_array_t *transitions,
- OBSScene &scene, OBSSource &curProgramScene)
+ OBSScene &scene, OBSSource &curProgramScene,
+ obs_data_array_t *savedProjectorList,
+ obs_data_array_t *savedPreviewProjectorList)
{
obs_data_t *saveData = obs_data_create();
obs_data_set_array(saveData, "sources", sourcesArray);
obs_data_set_array(saveData, "quick_transitions", quickTransitionData);
obs_data_set_array(saveData, "transitions", transitions);
+ obs_data_set_array(saveData, "saved_projectors", savedProjectorList);
+ obs_data_set_array(saveData, "saved_preview_projectors",
+ savedPreviewProjectorList);
obs_data_array_release(sourcesArray);
obs_data_set_string(saveData, "current_transition",
return sceneOrder;
}
+obs_data_array_t *OBSBasic::SaveProjectors()
+{
+ obs_data_array_t *saveProjector = obs_data_array_create();
+
+ for (size_t i = 0; i < projectorArray.size(); i++) {
+ obs_data_t *data = obs_data_create();
+ obs_data_set_string(data, "saved_projectors",
+ projectorArray.at(i).c_str());
+ obs_data_array_push_back(saveProjector, data);
+ obs_data_release(data);
+ }
+
+ return saveProjector;
+}
+
+obs_data_array_t *OBSBasic::SavePreviewProjectors()
+{
+ obs_data_array_t *saveProjector = obs_data_array_create();
+
+ for (size_t i = 0; i < previewProjectorArray.size(); i++) {
+ obs_data_t *data = obs_data_create();
+ obs_data_set_int(data, "saved_preview_projectors",
+ previewProjectorArray.at(i));
+ obs_data_array_push_back(saveProjector, data);
+ obs_data_release(data);
+ }
+
+ return saveProjector;
+}
+
void OBSBasic::Save(const char *file)
{
OBSScene scene = GetCurrentScene();
obs_data_array_t *sceneOrder = SaveSceneListOrder();
obs_data_array_t *transitions = SaveTransitions();
obs_data_array_t *quickTrData = SaveQuickTransitions();
+ obs_data_array_t *savedProjectorList = SaveProjectors();
+ obs_data_array_t *savedPreviewProjectorList = SavePreviewProjectors();
obs_data_t *saveData = GenerateSaveData(sceneOrder, quickTrData,
ui->transitionDuration->value(), transitions,
- scene, curProgramScene);
+ scene, curProgramScene, savedProjectorList,
+ savedPreviewProjectorList);
obs_data_set_bool(saveData, "preview_locked", ui->preview->Locked());
obs_data_set_int(saveData, "scaling_mode",
obs_data_array_release(sceneOrder);
obs_data_array_release(quickTrData);
obs_data_array_release(transitions);
+ obs_data_array_release(savedProjectorList);
+ obs_data_array_release(savedPreviewProjectorList);
}
static void LoadAudioDevice(const char *name, int channel, obs_data_t *parent)
}
}
+void OBSBasic::LoadSavedProjectors(obs_data_array_t *array)
+{
+ size_t num = obs_data_array_count(array);
+
+ for (size_t i = 0; i < num; i++) {
+ obs_data_t *data = obs_data_array_item(array, i);
+ projectorArray.at(i) = obs_data_get_string(data,
+ "saved_projectors");
+
+ obs_data_release(data);
+ }
+}
+
+void OBSBasic::LoadSavedPreviewProjectors(obs_data_array_t *array)
+{
+ size_t num = obs_data_array_count(array);
+
+ for (size_t i = 0; i < num; i++) {
+ obs_data_t *data = obs_data_array_item(array, i);
+ previewProjectorArray.at(i) = obs_data_get_int(data,
+ "saved_preview_projectors");
+
+ obs_data_release(data);
+ }
+}
+
static void LogFilter(obs_source_t*, obs_source_t *filter, void *v_val)
{
const char *name = obs_source_get_name(filter);
ui->transitionDuration->setValue(newDuration);
SetTransition(curTransition);
+ obs_data_array_t *savedProjectors = obs_data_get_array(data,
+ "saved_projectors");
+
+ if (savedProjectors)
+ LoadSavedProjectors(savedProjectors);
+
+ obs_data_array_release(savedProjectors);
+
+ obs_data_array_t *savedPreviewProjectors = obs_data_get_array(data,
+ "saved_preview_projectors");
+
+ if (savedPreviewProjectors)
+ LoadSavedPreviewProjectors(savedPreviewProjectors);
+
+ obs_data_array_release(savedPreviewProjectors);
+
+
retryScene:
curScene = obs_get_source_by_name(sceneName);
curProgramScene = obs_get_source_by_name(programSceneName);
opt_start_recording = false;
}
+ if (opt_start_replaybuffer) {
+ QMetaObject::invokeMethod(this, "StartReplayBuffer",
+ Qt::QueuedConnection);
+ opt_start_replaybuffer = false;
+ }
+
LogScenes();
disableSaving--;
GetDefaultVideoSavePath().c_str());
config_set_default_string(basicConfig, "AdvOut", "FFExtension", "mp4");
config_set_default_uint (basicConfig, "AdvOut", "FFVBitrate", 2500);
+ config_set_default_uint (basicConfig, "AdvOut", "FFVGOPSize", 250);
config_set_default_bool (basicConfig, "AdvOut", "FFUseRescale",
false);
+ config_set_default_bool (basicConfig, "AdvOut", "FFIgnoreCompat",
+ false);
config_set_default_uint (basicConfig, "AdvOut", "FFABitrate", 160);
config_set_default_uint (basicConfig, "AdvOut", "FFAudioTrack", 1);
config_set_default_uint (basicConfig, "Output", "MaxRetries", 20);
config_set_default_string(basicConfig, "Output", "BindIP", "default");
+ config_set_default_bool (basicConfig, "Output", "NewSocketLoopEnable",
+ false);
+ config_set_default_bool (basicConfig, "Output", "LowLatencyEnable",
+ false);
int i = 0;
uint32_t scale_cx = cx;
config_set_default_string(basicConfig, "Video", "ColorRange",
"Partial");
+ config_set_default_string(basicConfig, "Audio", "MonitoringDeviceId",
+ "default");
+ config_set_default_string(basicConfig, "Audio", "MonitoringDeviceName",
+ Str("Basic.Settings.Advanced.Audio.MonitoringDevice"
+ ".Default"));
config_set_default_uint (basicConfig, "Audio", "SampleRate", 44100);
config_set_default_string(basicConfig, "Audio", "ChannelSetup",
"Stereo");
"BasicWindow", "SwapScenesMode");
editPropertiesMode = config_get_bool(App()->GlobalConfig(),
"BasicWindow", "EditPropertiesMode");
- SetPreviewProgramMode(config_get_bool(App()->GlobalConfig(),
- "BasicWindow", "PreviewProgramMode"));
+
+ if (!opt_studio_mode) {
+ SetPreviewProgramMode(config_get_bool(App()->GlobalConfig(),
+ "BasicWindow", "PreviewProgramMode"));
+ } else {
+ SetPreviewProgramMode(true);
+ opt_studio_mode = false;
+ }
#define SET_VISIBILITY(name, control) \
do { \
ui->mainSplitter->setSizes(defSizes);
SystemTray(true);
+
+ OpenSavedProjectors();
}
void OBSBasic::InitHotkeys()
OBSBasic::~OBSBasic()
{
+ if (updateCheckThread && updateCheckThread->isRunning())
+ updateCheckThread->wait();
+
delete programOptions;
delete program;
config_set_int(App()->GlobalConfig(), "General", "LastVersion",
LIBOBS_API_VER);
- QRect lastGeom = normalGeometry();
QList<int> splitterSizes = ui->mainSplitter->sizes();
bool alwaysOnTop = IsAlwaysOnTop(this);
blog(LOG_INFO, "User Removed scene '%s'",
obs_source_get_name(source));
}
+
+ if (api)
+ api->on_event(OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED);
}
void OBSBasic::AddSceneItem(OBSSceneItem item)
volumes[i]->SetName(newName);
}
+ std::string newText = newName.toUtf8().constData();
+ std::string prevText = prevName.toUtf8().constData();
+
+ for (size_t j = 0; j < projectorArray.size(); j++) {
+ if (projectorArray.at(j) == prevText)
+ projectorArray.at(j) = newText;
+ }
+
SaveProject();
}
void OBSBasic::TimedCheckForUpdates()
{
+ if (!config_get_bool(App()->GlobalConfig(), "General",
+ "EnableAutoUpdates"))
+ return;
+
#ifdef UPDATE_SPARKLE
init_sparkle_updater(config_get_bool(App()->GlobalConfig(), "General",
"UpdateToUndeployed"));
-#else
+#elif ENABLE_WIN_UPDATER
long long lastUpdate = config_get_int(App()->GlobalConfig(), "General",
"LastUpdateCheck");
uint32_t lastVersion = config_get_int(App()->GlobalConfig(), "General",
long long secs = t - lastUpdate;
if (secs > UPDATE_CHECK_INTERVAL)
- CheckForUpdates();
+ CheckForUpdates(false);
#endif
}
-void OBSBasic::CheckForUpdates()
+void OBSBasic::CheckForUpdates(bool manualUpdate)
{
#ifdef UPDATE_SPARKLE
trigger_sparkle_update();
-#else
+#elif ENABLE_WIN_UPDATER
ui->actionCheckForUpdates->setEnabled(false);
- if (updateCheckThread) {
- updateCheckThread->wait();
- delete updateCheckThread;
- }
+ if (updateCheckThread && updateCheckThread->isRunning())
+ return;
- RemoteTextThread *thread = new RemoteTextThread(
- "https://obsproject.com/obs2_update/basic.json");
- updateCheckThread = thread;
- connect(thread, &RemoteTextThread::Result,
- this, &OBSBasic::updateFileFinished);
+ updateCheckThread = new AutoUpdateThread(manualUpdate);
updateCheckThread->start();
#endif
}
#define VERSION_ENTRY "other"
#endif
-void OBSBasic::updateFileFinished(const QString &text, const QString &error)
+void OBSBasic::updateCheckFinished()
{
ui->actionCheckForUpdates->setEnabled(true);
-
- if (text.isEmpty()) {
- blog(LOG_WARNING, "Update check failed: %s", QT_TO_UTF8(error));
- return;
- }
-
- obs_data_t *returnData = obs_data_create_from_json(QT_TO_UTF8(text));
- obs_data_t *versionData = obs_data_get_obj(returnData, VERSION_ENTRY);
- const char *description = obs_data_get_string(returnData,
- "description");
- const char *download = obs_data_get_string(versionData, "download");
-
- if (returnData && versionData && description && download) {
- long major = obs_data_get_int(versionData, "major");
- long minor = obs_data_get_int(versionData, "minor");
- long patch = obs_data_get_int(versionData, "patch");
- long version = MAKE_SEMANTIC_VERSION(major, minor, patch);
-
- blog(LOG_INFO, "Update check: last known remote version "
- "is %ld.%ld.%ld",
- major, minor, patch);
-
- if (version > LIBOBS_API_VER) {
- QString str = QTStr("UpdateAvailable.Text");
- QMessageBox messageBox(this);
-
- str = str.arg(QString::number(major),
- QString::number(minor),
- QString::number(patch),
- download);
-
- messageBox.setWindowTitle(QTStr("UpdateAvailable"));
- messageBox.setTextFormat(Qt::RichText);
- messageBox.setText(str);
- messageBox.setInformativeText(QT_UTF8(description));
- messageBox.exec();
-
- long long t = (long long)time(nullptr);
- config_set_int(App()->GlobalConfig(), "General",
- "LastUpdateCheck", t);
- config_save_safe(App()->GlobalConfig(), "tmp", nullptr);
- }
- } else {
- blog(LOG_WARNING, "Bad JSON file received from server");
- }
-
- obs_data_release(versionData);
- obs_data_release(returnData);
}
void OBSBasic::DuplicateSelectedScene()
}
}
+void OBSBasic::EnumDialogs()
+{
+ visDialogs.clear();
+ modalDialogs.clear();
+ visMsgBoxes.clear();
+
+ /* fill list of Visible dialogs and Modal dialogs */
+ QList<QDialog*> dialogs = findChildren<QDialog*>();
+ for (QDialog *dialog : dialogs) {
+ if (dialog->isVisible())
+ visDialogs.append(dialog);
+ if (dialog->isModal())
+ modalDialogs.append(dialog);
+ }
+
+ /* fill list of Visible message boxes */
+ QList<QMessageBox*> msgBoxes = findChildren<QMessageBox*>();
+ for (QMessageBox *msgbox : msgBoxes) {
+ if (msgbox->isVisible())
+ visMsgBoxes.append(msgbox);
+ }
+}
+
void OBSBasic::ClearSceneData()
{
disableSaving++;
void OBSBasic::changeEvent(QEvent *event)
{
- /* TODO */
- UNUSED_PARAMETER(event);
+ if (event->type() == QEvent::WindowStateChange &&
+ isMinimized() &&
+ trayIcon->isVisible() &&
+ sysTrayMinimizeToTray()) {
+
+ ToggleShowHide();
+ }
}
void OBSBasic::on_actionShow_Recordings_triggered()
void OBSBasic::on_action_Settings_triggered()
{
- disableHiding = true;
OBSBasicSettings settings(this);
settings.exec();
SystemTray(false);
- disableHiding = false;
}
void OBSBasic::on_actionAdvAudioProperties_triggered()
string name;
QString format{QTStr("Basic.Main.DefaultSceneName.Text")};
- int i = 1;
+ int i = 2;
QString placeHolderText = format.arg(i);
obs_source_t *source = nullptr;
while ((source = obs_get_source_by_name(QT_TO_UTF8(placeHolderText)))) {
void OBSBasic::on_actionCheckForUpdates_triggered()
{
- CheckForUpdates();
+ CheckForUpdates(true);
}
void OBSBasic::logUploadFinished(const QString &text, const QString &error)
sysTrayStream->setText(ui->streamButton->text());
sysTrayStream->setEnabled(true);
}
+
+ QMessageBox::critical(this,
+ QTStr("Output.StartStreamFailed"),
+ QTStr("Output.StartFailedGeneric"));
+ return;
}
bool recordWhenStreaming = config_get_bool(GetGlobalConfig(),
"BasicWindow", "RecordWhenStreaming");
if (recordWhenStreaming)
StartRecording();
+
+ bool replayBufferWhileStreaming = config_get_bool(GetGlobalConfig(),
+ "BasicWindow", "ReplayBufferWhileStreaming");
+ if (replayBufferWhileStreaming)
+ StartReplayBuffer();
}
#ifdef _WIN32
"BasicWindow", "KeepRecordingWhenStreamStops");
if (recordWhenStreaming && !keepRecordingWhenStreamStops)
StopRecording();
+
+ bool replayBufferWhileStreaming = config_get_bool(GetGlobalConfig(),
+ "BasicWindow", "ReplayBufferWhileStreaming");
+ bool keepReplayBufferStreamStops = config_get_bool(GetGlobalConfig(),
+ "BasicWindow", "KeepReplayBufferStreamStops");
+ if (replayBufferWhileStreaming && !keepReplayBufferStreamStops)
+ StopReplayBuffer();
}
void OBSBasic::ForceStopStreaming()
"BasicWindow", "KeepRecordingWhenStreamStops");
if (recordWhenStreaming && !keepRecordingWhenStreamStops)
StopRecording();
+
+ bool replayBufferWhileStreaming = config_get_bool(GetGlobalConfig(),
+ "BasicWindow", "ReplayBufferWhileStreaming");
+ bool keepReplayBufferStreamStops = config_get_bool(GetGlobalConfig(),
+ "BasicWindow", "KeepReplayBufferStreamStops");
+ if (replayBufferWhileStreaming && !keepReplayBufferStreamStops)
+ StopReplayBuffer();
}
void OBSBasic::StreamDelayStarting(int sec)
} else if (strcmp(val, "20") == 0) {
num = 20;
den = 1;
+ } else if (strcmp(val, "24 NTSC") == 0) {
+ num = 24000;
+ den = 1001;
} else if (strcmp(val, "25") == 0) {
num = 25;
den = 1;
void OBSBasic::OpenProjector(obs_source_t *source, int monitor)
{
/* seriously? 10 monitors? */
- if (monitor > 9)
+ if (monitor > 9 || monitor > QGuiApplication::screens().size() - 1)
return;
+ bool isPreview = false;
+
+ if (source == nullptr)
+ isPreview = true;
+
delete projectors[monitor];
projectors[monitor].clear();
+ RemoveSavedProjectors(monitor);
+
OBSProjector *projector = new OBSProjector(nullptr, source);
- projector->Init(monitor);
+ const char *name = obs_source_get_name(source);
+
+ if (isPreview) {
+ previewProjectorArray.at((size_t)monitor) = 1;
+ } else {
+ projectorArray.at((size_t)monitor) = name;
+ }
+
+ projector->Init(monitor);
projectors[monitor] = projector;
}
OpenProjector(obs_scene_get_source(scene), monitor);
}
+void OBSBasic::OpenSavedProjectors()
+{
+ bool projectorSave = config_get_bool(GetGlobalConfig(),
+ "BasicWindow", "SaveProjectors");
+
+ if (projectorSave) {
+ for (size_t i = 0; i < projectorArray.size(); i++) {
+ if (projectorArray.at(i).empty() == false) {
+ OBSSource source = obs_get_source_by_name(
+ projectorArray.at(i).c_str());
+
+ if (!source) {
+ RemoveSavedProjectors((int)i);
+ obs_source_release(source);
+ continue;
+ }
+
+ OpenProjector(source, (int)i);
+ obs_source_release(source);
+ }
+ }
+
+ for (size_t i = 0; i < previewProjectorArray.size(); i++) {
+ if (previewProjectorArray.at(i) == 1) {
+ OpenProjector(nullptr, (int)i);
+ }
+ }
+ }
+}
+
+void OBSBasic::RemoveSavedProjectors(int monitor)
+{
+ previewProjectorArray.at((size_t)monitor) = 0;
+ projectorArray.at((size_t)monitor) = "";
+}
+
void OBSBasic::UpdateTitleBar()
{
stringstream name;
"BasicWindow", "geometry",
saveGeometry().toBase64().constData());
+ /* hide all visible child dialogs */
+ visDlgPositions.clear();
+ if (!visDialogs.isEmpty()) {
+ for (QDialog *dlg : visDialogs) {
+ visDlgPositions.append(dlg->pos());
+ dlg->hide();
+ }
+ }
+
if (showHide)
showHide->setText(QTStr("Basic.SystemTray.Show"));
QTimer::singleShot(250, this, SLOT(hide()));
EnablePreviewDisplay(true);
setVisible(true);
+
+ /* show all child dialogs that was visible earlier */
+ if (!visDialogs.isEmpty()) {
+ for (int i = 0; i < visDialogs.size(); ++i) {
+ QDialog *dlg = visDialogs[i];
+ dlg->move(visDlgPositions[i]);
+ dlg->show();
+ }
+ }
+
+ /* Unminimize window if it was hidden to tray instead of task
+ * bar. */
+ if (sysTrayMinimizeToTray()) {
+ Qt::WindowStates state;
+ state = windowState() & ~Qt::WindowMinimized;
+ state |= Qt::WindowActive;
+ setWindowState(state);
+ }
}
}
+void OBSBasic::ToggleShowHide()
+{
+ bool showing = isVisible();
+ if (showing) {
+ /* check for modal dialogs */
+ EnumDialogs();
+ if (!modalDialogs.isEmpty() || !visMsgBoxes.isEmpty())
+ return;
+ }
+ SetShowing(!showing);
+}
+
void OBSBasic::SystemTrayInit()
{
trayIcon = new QSystemTrayIcon(QIcon(":/res/images/obs.png"),
if (!sysTrayWhenStarted && !sysTrayEnabled) {
trayIcon->hide();
- } else if (sysTrayWhenStarted && sysTrayEnabled) {
+ } else if ((sysTrayWhenStarted && sysTrayEnabled)
+ || opt_minimize_tray) {
trayIcon->show();
if (firstStarted) {
QTimer::singleShot(50, this, SLOT(hide()));
EnablePreviewDisplay(false);
setVisible(false);
+ opt_minimize_tray = false;
}
} else if (sysTrayEnabled) {
trayIcon->show();
else
showHide->setText(QTStr("Basic.SystemTray.Show"));
}
+
+bool OBSBasic::sysTrayMinimizeToTray()
+{
+ return config_get_bool(GetGlobalConfig(),
+ "BasicWindow", "SysTrayMinimizeToTray");
+}
obs-studio-17.0.2.tar.xz/UI/window-basic-main.hpp -> obs-studio-18.0.0.tar.xz/UI/window-basic-main.hpp
Changed
#include <QPointer>
+class QMessageBox;
class QListWidgetItem;
class VolControl;
class QNetworkReply;
std::vector<OBSSignal> signalHandlers;
+ std::vector<std::string> projectorArray;
+ std::vector<int> previewProjectorArray;
+
bool loaded = false;
long disableSaving = 1;
bool projectChanged = false;
QPointer<QAction> showHide;
QPointer<QAction> exit;
QPointer<QMenu> trayMenu;
- bool disableHiding = false;
void DrawBackdrop(float cx, float cy);
bool QueryRemoveSource(obs_source_t *source);
void TimedCheckForUpdates();
- void CheckForUpdates();
+ void CheckForUpdates(bool manualUpdate);
void GetFPSCommon(uint32_t &num, uint32_t &den) const;
void GetFPSInteger(uint32_t &num, uint32_t &den) const;
void ReplayBufferClicked();
+ bool sysTrayMinimizeToTray();
+
+ void EnumDialogs();
+
+ QList<QDialog*> visDialogs;
+ QList<QDialog*> modalDialogs;
+ QList<QMessageBox*> visMsgBoxes;
+
+ QList<QPoint> visDlgPositions;
+
+ obs_data_array_t *SaveProjectors();
+ void LoadSavedProjectors(obs_data_array_t *savedProjectors);
+
+ obs_data_array_t *SavePreviewProjectors();
+ void LoadSavedPreviewProjectors(
+ obs_data_array_t *savedPreviewProjectors);
+
public slots:
void StartStreaming();
void StopStreaming();
void IconActivated(QSystemTrayIcon::ActivationReason reason);
void SetShowing(bool showing);
- inline void ToggleShowHide()
- {
- bool showing = isVisible();
- if (disableHiding && showing)
- return;
- if (showing)
- CloseDialogs();
- SetShowing(!showing);
- }
+ void ToggleShowHide();
private:
/* OBS Callbacks */
void SystemTrayInit();
void SystemTray(bool firstStarted);
+ void OpenSavedProjectors();
+ void RemoveSavedProjectors(int monitor);
+
protected:
virtual void closeEvent(QCloseEvent *event) override;
virtual void changeEvent(QEvent *event) override;
void logUploadFinished(const QString &text, const QString &error);
- void updateFileFinished(const QString &text, const QString &error);
+ void updateCheckFinished();
void AddSourceFromAction();
obs-studio-17.0.2.tar.xz/UI/window-basic-preview.cpp -> obs-studio-18.0.0.tar.xz/UI/window-basic-preview.cpp
Changed
stretchHandle == ItemHandle::TopRight ||
stretchHandle == ItemHandle::BottomLeft ||
stretchHandle == ItemHandle::BottomRight) {
- if (aspect < baseAspect)
- size.x = size.y * baseAspect;
- else
- size.y = size.x / baseAspect;
+ if (aspect < baseAspect) {
+ if ((size.y >= 0.0f && size.x >= 0.0f) ||
+ (size.y <= 0.0f && size.x <= 0.0f))
+ size.x = size.y * baseAspect;
+ else
+ size.x = size.y * baseAspect * -1.0f;
+ } else {
+ if ((size.y >= 0.0f && size.x >= 0.0f) ||
+ (size.y <= 0.0f && size.x <= 0.0f))
+ size.y = size.x / baseAspect;
+ else
+ size.y = size.x / baseAspect * -1.0f;
+ }
} else if (stretchHandle == ItemHandle::TopCenter ||
stretchHandle == ItemHandle::BottomCenter) {
- size.x = size.y * baseAspect;
+ if ((size.y >= 0.0f && size.x >= 0.0f) ||
+ (size.y <= 0.0f && size.x <= 0.0f))
+ size.x = size.y * baseAspect;
+ else
+ size.x = size.y * baseAspect * -1.0f;
} else if (stretchHandle == ItemHandle::CenterLeft ||
stretchHandle == ItemHandle::CenterRight) {
- size.y = size.x / baseAspect;
+ if ((size.y >= 0.0f && size.x >= 0.0f) ||
+ (size.y <= 0.0f && size.x <= 0.0f))
+ size.y = size.x / baseAspect;
+ else
+ size.y = size.x / baseAspect * -1.0f;
}
size.x = std::round(size.x);
obs-studio-17.0.2.tar.xz/UI/window-basic-settings.cpp -> obs-studio-18.0.0.tar.xz/UI/window-basic-settings.cpp
Changed
HookWidget(ui->language, COMBO_CHANGED, GENERAL_CHANGED);
HookWidget(ui->theme, COMBO_CHANGED, GENERAL_CHANGED);
+ HookWidget(ui->enableAutoUpdates, CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->warnBeforeStreamStart,CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->warnBeforeStreamStop, CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->hideProjectorCursor, CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->projectorAlwaysOnTop, CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->recordWhenStreaming, CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->keepRecordStreamStops,CHECK_CHANGED, GENERAL_CHANGED);
+ HookWidget(ui->replayWhileStreaming, CHECK_CHANGED, GENERAL_CHANGED);
+ HookWidget(ui->keepReplayStreamStops,CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->systemTrayEnabled, CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->systemTrayWhenStarted,CHECK_CHANGED, GENERAL_CHANGED);
+ HookWidget(ui->systemTrayAlways, CHECK_CHANGED, GENERAL_CHANGED);
+ HookWidget(ui->saveProjectors, CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->snappingEnabled, CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->screenSnapping, CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->centerSnapping, CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->advOutFFFormat, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFMCfg, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFVBitrate, SCROLL_CHANGED, OUTPUTS_CHANGED);
+ HookWidget(ui->advOutFFVGOPSize, SCROLL_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFUseRescale, CHECK_CHANGED, OUTPUTS_CHANGED);
+ HookWidget(ui->advOutFFIgnoreCompat, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFRescale, CBEDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFVEncoder, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFVCfg, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFTrack4, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFTrack5, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFTrack6, CHECK_CHANGED, OUTPUTS_CHANGED);
- HookWidget(ui->advOutFFAEncoder, COMBO_CHANGED, OUTPUTS_CHANGED);
+ HookWidget(ui->advOutFFAEncoder, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFACfg, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutTrack1Bitrate, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutTrack1Name, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->colorRange, COMBO_CHANGED, ADV_CHANGED);
HookWidget(ui->disableOSXVSync, CHECK_CHANGED, ADV_CHANGED);
HookWidget(ui->resetOSXVSync, CHECK_CHANGED, ADV_CHANGED);
+#if defined(_WIN32) || defined(__APPLE__)
+ HookWidget(ui->monitoringDevice, COMBO_CHANGED, ADV_CHANGED);
+#endif
HookWidget(ui->filenameFormatting, EDIT_CHANGED, ADV_CHANGED);
HookWidget(ui->overwriteIfExists, CHECK_CHANGED, ADV_CHANGED);
HookWidget(ui->simpleRBPrefix, EDIT_CHANGED, ADV_CHANGED);
HookWidget(ui->reconnectMaxRetries, SCROLL_CHANGED, ADV_CHANGED);
HookWidget(ui->processPriority, COMBO_CHANGED, ADV_CHANGED);
HookWidget(ui->bindToIP, COMBO_CHANGED, ADV_CHANGED);
+ HookWidget(ui->enableNewSocketLoop, CHECK_CHANGED, ADV_CHANGED);
+ HookWidget(ui->enableLowLatencyMode, CHECK_CHANGED, ADV_CHANGED);
+
+#if !defined(_WIN32) && !defined(__APPLE__)
+ delete ui->monitoringDevice;
+ delete ui->monitoringDeviceLabel;
+ delete ui->advAudioGroupBox;
+ delete ui->enableAutoUpdates;
+ ui->monitoringDevice = nullptr;
+ ui->monitoringDeviceLabel = nullptr;
+ ui->advAudioGroupBox = nullptr;
+ ui->enableAutoUpdates = nullptr;
+#endif
#ifdef _WIN32
uint32_t winVer = GetWindowsVersion();
delete ui->processPriorityLabel;
delete ui->processPriority;
delete ui->advancedGeneralGroupBox;
+ delete ui->enableNewSocketLoop;
+ delete ui->enableLowLatencyMode;
ui->rendererLabel = nullptr;
ui->renderer = nullptr;
ui->adapterLabel = nullptr;
ui->processPriorityLabel = nullptr;
ui->processPriority = nullptr;
ui->advancedGeneralGroupBox = nullptr;
+ ui->enableNewSocketLoop = nullptr;
+ ui->enableLowLatencyMode = nullptr;
#endif
#ifndef __APPLE__
FillSimpleRecordingValues();
FillSimpleStreamingValues();
+#if defined(_WIN32) || defined(__APPLE__)
+ FillAudioMonitoringDevices();
+#endif
connect(ui->simpleOutRecQuality, SIGNAL(currentIndexChanged(int)),
this, SLOT(SimpleRecordingQualityChanged()));
connect(ui->simpleOutRecQuality, SIGNAL(currentIndexChanged(int)),
this, SLOT(SimpleRecordingQualityLosslessWarning(int)));
+ connect(ui->simpleOutRecFormat, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(SimpleRecordingEncoderChanged()));
connect(ui->simpleOutStrEncoder, SIGNAL(currentIndexChanged(int)),
this, SLOT(SimpleStreamingEncoderChanged()));
connect(ui->simpleOutStrEncoder, SIGNAL(currentIndexChanged(int)),
this, SLOT(AdvOutRecCheckWarnings()));
connect(ui->advOutRecTrack6, SIGNAL(clicked()),
this, SLOT(AdvOutRecCheckWarnings()));
+ connect(ui->advOutRecFormat, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(AdvOutRecCheckWarnings()));
AdvOutRecCheckWarnings();
SimpleRecordingQualityChanged();
+
+ UpdateAutomaticReplayBufferCheckboxes();
}
void OBSBasicSettings::SaveCombo(QComboBox *widget, const char *section,
const char *codec = obs_get_encoder_codec(type);
uint32_t caps = obs_get_encoder_caps(type);
- if (strcmp(codec, "h264") != 0)
+ if (obs_get_encoder_type(type) != OBS_ENCODER_VIDEO)
continue;
+
+ const char* streaming_codecs[] = {
+ "h264",
+ //"hevc",
+ };
+ bool is_streaming_codec = false;
+ for (const char* test_codec : streaming_codecs) {
+ if (strcmp(codec, test_codec) == 0) {
+ is_streaming_codec = true;
+ break;
+ }
+ }
if ((caps & OBS_ENCODER_CAP_DEPRECATED) != 0)
continue;
QString qName = QT_UTF8(name);
QString qType = QT_UTF8(type);
- ui->advOutEncoder->addItem(qName, qType);
+ if (is_streaming_codec)
+ ui->advOutEncoder->addItem(qName, qType);
ui->advOutRecEncoder->addItem(qName, qType);
}
}
if (formatDesc == nullptr)
return;
- OBSFFCodecDesc codecDescs(ff_codec_supported(formatDesc));
+ bool ignore_compatability = ui->advOutFFIgnoreCompat->isChecked();
+ OBSFFCodecDesc codecDescs(ff_codec_supported(formatDesc,
+ ignore_compatability));
const ff_codec_desc *codec = codecDescs.get();
LoadLanguageList();
LoadThemeList();
+#if defined(_WIN32) || defined(__APPLE__)
+ bool enableAutoUpdates = config_get_bool(GetGlobalConfig(),
+ "General", "EnableAutoUpdates");
+ ui->enableAutoUpdates->setChecked(enableAutoUpdates);
+#endif
+
bool recordWhenStreaming = config_get_bool(GetGlobalConfig(),
"BasicWindow", "RecordWhenStreaming");
ui->recordWhenStreaming->setChecked(recordWhenStreaming);
"BasicWindow", "KeepRecordingWhenStreamStops");
ui->keepRecordStreamStops->setChecked(keepRecordStreamStops);
+ bool replayWhileStreaming = config_get_bool(GetGlobalConfig(),
+ "BasicWindow", "ReplayBufferWhileStreaming");
+ ui->replayWhileStreaming->setChecked(replayWhileStreaming);
+
+ bool keepReplayStreamStops = config_get_bool(GetGlobalConfig(),
+ "BasicWindow", "KeepReplayBufferStreamStops");
+ ui->keepReplayStreamStops->setChecked(keepReplayStreamStops);
+
bool systemTrayEnabled = config_get_bool(GetGlobalConfig(),
"BasicWindow", "SysTrayEnabled");
ui->systemTrayEnabled->setChecked(systemTrayEnabled);
"BasicWindow", "SysTrayWhenStarted");
ui->systemTrayWhenStarted->setChecked(systemTrayWhenStarted);
+ bool systemTrayAlways = config_get_bool(GetGlobalConfig(),
+ "BasicWindow", "SysTrayMinimizeToTray");
+ ui->systemTrayAlways->setChecked(systemTrayAlways);
+
+ bool saveProjectors = config_get_bool(GetGlobalConfig(),
+ "BasicWindow", "SaveProjectors");
+ ui->saveProjectors->setChecked(saveProjectors);
+
bool snappingEnabled = config_get_bool(GetGlobalConfig(),
"BasicWindow", "SnappingEnabled");
ui->snappingEnabled->setChecked(snappingEnabled);
"FPSCommon");
int idx = ui->fpsCommon->findText(val);
- if (idx == -1) idx = 3;
+ if (idx == -1) idx = 4;
ui->fpsCommon->setCurrentIndex(idx);
}
"FFMCustom");
int videoBitrate = config_get_int(main->Config(), "AdvOut",
"FFVBitrate");
+ int gopSize = config_get_int(main->Config(), "AdvOut",
+ "FFVGOPSize");
bool rescale = config_get_bool(main->Config(), "AdvOut",
"FFRescale");
+ bool codecCompat = config_get_bool(main->Config(), "AdvOut",
+ "FFIgnoreCompat");
const char *rescaleRes = config_get_string(main->Config(), "AdvOut",
"FFRescaleRes");
const char *vEncoder = config_get_string(main->Config(), "AdvOut",
SelectFormat(ui->advOutFFFormat, format, mimeType);
ui->advOutFFMCfg->setText(muxCustom);
ui->advOutFFVBitrate->setValue(videoBitrate);
+ ui->advOutFFVGOPSize->setValue(gopSize);
ui->advOutFFUseRescale->setChecked(rescale);
+ ui->advOutFFIgnoreCompat->setChecked(codecCompat);
ui->advOutFFRescale->setEnabled(rescale);
ui->advOutFFRescale->setCurrentText(rescaleRes);
SelectEncoder(ui->advOutFFVEncoder, vEncoder, vEncoderId);
switch (encoderType) {
case FF_CODEC_VIDEO:
ui->advOutFFVBitrate->setEnabled(enabled);
+ ui->advOutFFVGOPSize->setEnabled(enabled);
ui->advOutFFUseRescale->setEnabled(enabled);
ui->advOutFFRescale->setEnabled(enabled && rescale);
ui->advOutFFVEncoder->setEnabled(enabled || enableEncoder);
"Video", "ColorSpace");
const char *videoColorRange = config_get_string(main->Config(),
"Video", "ColorRange");
+#if defined(_WIN32) || defined(__APPLE__)
+ const char *monDevName = config_get_string(main->Config(), "Audio",
+ "MonitoringDeviceName");
+ const char *monDevId = config_get_string(main->Config(), "Audio",
+ "MonitoringDeviceId");
+#endif
bool enableDelay = config_get_bool(main->Config(), "Output",
"DelayEnable");
int delaySec = config_get_int(main->Config(), "Output",
"RecRBPrefix");
const char *rbSuffix = config_get_string(main->Config(), "SimpleOutput",
"RecRBSuffix");
+ int idx;
loading = true;
LoadRendererList();
+#if defined(_WIN32) || defined(__APPLE__)
+ QComboBox *cb = ui->monitoringDevice;
+ idx = cb->findData(monDevId);
+ if (idx == -1) {
+ cb->insertItem(0, monDevName, monDevId);
+
+ QStandardItemModel *model =
+ dynamic_cast<QStandardItemModel*>(cb->model());
+ if (!model)
+ return;
+
+ QStandardItem *item = model->item(0);
+ item->setFlags(Qt::NoItemFlags);
+
+ idx = 0;
+ }
+ cb->setCurrentIndex(idx);
+#endif
+
ui->filenameFormatting->setText(filename);
ui->overwriteIfExists->setChecked(overwriteIfExists);
ui->simpleRBPrefix->setText(rbPrefix);
ui->streamDelayPreserve->setChecked(preserveDelay);
ui->streamDelayEnable->setChecked(enableDelay);
+
SetComboByName(ui->colorFormat, videoColorFormat);
SetComboByName(ui->colorSpace, videoColorSpace);
SetComboByValue(ui->colorRange, videoColorRange);
#elif _WIN32
const char *processPriority = config_get_string(App()->GlobalConfig(),
"General", "ProcessPriority");
- int idx = ui->processPriority->findData(processPriority);
+ bool enableNewSocketLoop = config_get_bool(main->Config(), "Output",
+ "NewSocketLoopEnable");
+ bool enableLowLatencyMode = config_get_bool(main->Config(), "Output",
+ "LowLatencyEnable");
+
+ idx = ui->processPriority->findData(processPriority);
if (idx == -1)
idx = ui->processPriority->findData("Normal");
ui->processPriority->setCurrentIndex(idx);
+
+ ui->enableNewSocketLoop->setChecked(enableNewSocketLoop);
+ ui->enableLowLatencyMode->setChecked(enableLowLatencyMode);
#endif
loading = false;
App()->SetTheme(theme);
}
+#if defined(_WIN32) || defined(__APPLE__)
+ if (WidgetChanged(ui->enableAutoUpdates))
+ config_set_bool(GetGlobalConfig(), "General",
+ "EnableAutoUpdates",
+ ui->enableAutoUpdates->isChecked());
+#endif
if (WidgetChanged(ui->snappingEnabled))
config_set_bool(GetGlobalConfig(), "BasicWindow",
"SnappingEnabled",
"KeepRecordingWhenStreamStops",
ui->keepRecordStreamStops->isChecked());
+ if (WidgetChanged(ui->replayWhileStreaming))
+ config_set_bool(GetGlobalConfig(), "BasicWindow",
+ "ReplayBufferWhileStreaming",
+ ui->replayWhileStreaming->isChecked());
+ if (WidgetChanged(ui->keepReplayStreamStops))
+ config_set_bool(GetGlobalConfig(), "BasicWindow",
+ "KeepReplayBufferStreamStops",
+ ui->keepReplayStreamStops->isChecked());
+
if (WidgetChanged(ui->systemTrayEnabled))
config_set_bool(GetGlobalConfig(), "BasicWindow",
"SysTrayEnabled",
config_set_bool(GetGlobalConfig(), "BasicWindow",
"SysTrayWhenStarted",
ui->systemTrayWhenStarted->isChecked());
+
+ if (WidgetChanged(ui->systemTrayAlways))
+ config_set_bool(GetGlobalConfig(),
+ "BasicWindow", "SysTrayMinimizeToTray",
+ ui->systemTrayAlways->isChecked());
+
+ if (WidgetChanged(ui->saveProjectors))
+ config_set_bool(GetGlobalConfig(), "BasicWindow",
+ "SaveProjectors",
+ ui->saveProjectors->isChecked());
}
void OBSBasicSettings::SaveStream1Settings()
priority.c_str());
if (main->Active())
SetProcessPriority(priority.c_str());
+
+ SaveCheckBox(ui->enableNewSocketLoop, "Output", "NewSocketLoopEnable");
+ SaveCheckBox(ui->enableLowLatencyMode, "Output", "LowLatencyEnable");
#endif
#ifdef __APPLE__
SaveCombo(ui->colorFormat, "Video", "ColorFormat");
SaveCombo(ui->colorSpace, "Video", "ColorSpace");
SaveComboData(ui->colorRange, "Video", "ColorRange");
+#if defined(_WIN32) || defined(__APPLE__)
+ SaveCombo(ui->monitoringDevice, "Audio", "MonitoringDeviceName");
+ SaveComboData(ui->monitoringDevice, "Audio", "MonitoringDeviceId");
+#endif
SaveEdit(ui->filenameFormatting, "Output", "FilenameFormatting");
SaveEdit(ui->simpleRBPrefix, "SimpleOutput", "RecRBPrefix");
SaveEdit(ui->simpleRBSuffix, "SimpleOutput", "RecRBSuffix");
SaveSpinBox(ui->reconnectRetryDelay, "Output", "RetryDelay");
SaveSpinBox(ui->reconnectMaxRetries, "Output", "MaxRetries");
SaveComboData(ui->bindToIP, "Output", "BindIP");
+
+#if defined(_WIN32) || defined(__APPLE__)
+ obs_set_audio_monitoring_device(
+ QT_TO_UTF8(ui->monitoringDevice->currentText()),
+ QT_TO_UTF8(ui->monitoringDevice->currentData()
+ .toString()));
+#endif
}
static inline const char *OutputModeFromIdx(int idx)
char *comma = strchr(&extStr[0], ',');
if (comma)
- comma = 0;
+ *comma = 0;
config_set_string(main->Config(), "AdvOut", "FFExtension",
extStr.c_str());
SaveFormat(ui->advOutFFFormat);
SaveEdit(ui->advOutFFMCfg, "AdvOut", "FFMCustom");
SaveSpinBox(ui->advOutFFVBitrate, "AdvOut", "FFVBitrate");
+ SaveSpinBox(ui->advOutFFVGOPSize, "AdvOut", "FFVGOPSize");
SaveCheckBox(ui->advOutFFUseRescale, "AdvOut", "FFRescale");
+ SaveCheckBox(ui->advOutFFIgnoreCompat, "AdvOut", "FFIgnoreCompat");
SaveCombo(ui->advOutFFRescale, "AdvOut", "FFRescaleRes");
SaveEncoder(ui->advOutFFVEncoder, "AdvOut", "FFVEncoder");
SaveEdit(ui->advOutFFVCfg, "AdvOut", "FFVCustom");
}
}
+void OBSBasicSettings::on_advOutFFIgnoreCompat_stateChanged(int)
+{
+ /* Little hack to reload codecs when checked */
+ on_advOutFFFormat_currentIndexChanged(
+ ui->advOutFFFormat->currentIndex());
+}
+
#define DEFAULT_CONTAINER_STR \
QTStr("Basic.Settings.Output.Adv.FFmpeg.FormatDescDef")
text.toStdString().find_first_of("<>:\"|?*");
#else
size_t invalidLocation = string::npos;
+ UNUSED_PARAMETER(text);
#endif
if (invalidLocation != string::npos)
return box->isChecked() ? 1 : 0;
};
- QString msg;
+ QString errorMsg;
+ QString warningMsg;
uint32_t tracks =
Checked(ui->advOutRecTrack1) +
Checked(ui->advOutRecTrack2) +
Checked(ui->advOutRecTrack4) +
Checked(ui->advOutRecTrack5) +
Checked(ui->advOutRecTrack6);
- const char *objectName = nullptr;
if (tracks == 0) {
- msg = QTStr("OutputWarnings.NoTracksSelected");
- objectName = "errorLabel";
+ errorMsg = QTStr("OutputWarnings.NoTracksSelected");
} else if (tracks > 1) {
- msg = QTStr("OutputWarnings.MultiTrackRecording");
- objectName = "warningLabel";
+ warningMsg = QTStr("OutputWarnings.MultiTrackRecording");
+ }
+
+ if (ui->advOutRecFormat->currentText().compare("mp4") == 0) {
+ if (!warningMsg.isEmpty())
+ warningMsg += "\n\n";
+ warningMsg += QTStr("OutputWarnings.MP4Recording");
}
delete advOutRecWarning;
- if (!msg.isEmpty()) {
- advOutRecWarning = new QLabel(msg, this);
- advOutRecWarning->setObjectName(objectName);
+ if (!errorMsg.isEmpty() || !warningMsg.isEmpty()) {
+ advOutRecWarning = new QLabel(
+ errorMsg.isEmpty() ? warningMsg : errorMsg,
+ this);
+ advOutRecWarning->setObjectName(
+ errorMsg.isEmpty() ? "warningLabel" :
+ "errorLabel");
+ advOutRecWarning->setWordWrap(true);
QFormLayout *formLayout = reinterpret_cast<QFormLayout*>(
ui->advOutRecTopContainer->layout());
UpdateSimpleOutStreamDelayEstimate();
else
UpdateAdvOutStreamDelayEstimate();
+
+ UpdateAutomaticReplayBufferCheckboxes();
}
static bool EncoderAvailable(const char *encoder)
#undef ENCODER_STR
}
+void OBSBasicSettings::FillAudioMonitoringDevices()
+{
+ QComboBox *cb = ui->monitoringDevice;
+
+ auto enum_devices = [] (void *param, const char *name, const char *id)
+ {
+ QComboBox *cb = (QComboBox*)param;
+ cb->addItem(name, id);
+ return true;
+ };
+
+ cb->addItem(QTStr("Basic.Settings.Advanced.Audio.MonitoringDevice"
+ ".Default"), "default");
+
+ obs_enum_audio_monitoring_devices(enum_devices, cb);
+}
+
void OBSBasicSettings::SimpleRecordingQualityChanged()
{
QString qual = ui->simpleOutRecQuality->currentData().toString();
#define ESTIMATE_UNKNOWN_STR \
"Basic.Settings.Output.ReplayBuffer.EstimateUnknown"
+void OBSBasicSettings::UpdateAutomaticReplayBufferCheckboxes()
+{
+ bool state = ui->simpleReplayBuf->isChecked() &&
+ ui->outputMode->currentIndex() == 0;
+ ui->replayWhileStreaming->setEnabled(state);
+ ui->keepReplayStreamStops->setEnabled(state &&
+ ui->replayWhileStreaming->isChecked());
+}
+
void OBSBasicSettings::SimpleReplayBufferChanged()
{
QString qual = ui->simpleOutRecQuality->currentData().toString();
ui->replayBufferGroupBox->setVisible(!lossless && replayBufferEnabled);
ui->simpleReplayBuf->setVisible(!lossless);
+
+ UpdateAutomaticReplayBufferCheckboxes();
+
}
#define SIMPLE_OUTPUT_WARNING(str) \
}
}
+ if (ui->simpleOutRecFormat->currentText().compare("mp4") == 0) {
+ if (!warning.isEmpty())
+ warning += "\n\n";
+ warning += QTStr("OutputWarnings.MP4Recording");
+ }
+
if (warning.isEmpty())
return;
obs-studio-17.0.2.tar.xz/UI/window-basic-settings.hpp -> obs-studio-18.0.0.tar.xz/UI/window-basic-settings.hpp
Changed
void FillSimpleRecordingValues();
void FillSimpleStreamingValues();
+ void FillAudioMonitoringDevices();
void RecalcOutputResPixels(const char *resText);
void on_advOutFFPathBrowse_clicked();
void on_advOutEncoder_currentIndexChanged(int idx);
void on_advOutRecEncoder_currentIndexChanged(int idx);
+ void on_advOutFFIgnoreCompat_stateChanged(int state);
void on_advOutFFFormat_currentIndexChanged(int idx);
void on_advOutFFAEncoder_currentIndexChanged(int idx);
void on_advOutFFVEncoder_currentIndexChanged(int idx);
void UpdateStreamDelayEstimate();
+ void UpdateAutomaticReplayBufferCheckboxes();
+
void AdvOutRecCheckWarnings();
void SimpleRecordingQualityChanged();
obs-studio-17.0.2.tar.xz/UI/window-basic-source-select.cpp -> obs-studio-18.0.0.tar.xz/UI/window-basic-source-select.cpp
Changed
QString placeHolderText{QT_UTF8(GetSourceDisplayName(id))};
QString text{placeHolderText};
- int i = 1;
+ int i = 2;
obs_source_t *source = nullptr;
while ((source = obs_get_source_by_name(QT_TO_UTF8(text)))) {
obs_source_release(source);
obs-studio-17.0.2.tar.xz/UI/window-basic-status-bar.cpp -> obs-studio-18.0.0.tar.xz/UI/window-basic-status-bar.cpp
Changed
#include <QLabel>
+#include <QHBoxLayout>
+#include <QPainter>
+#include <QPixmap>
#include "obs-app.hpp"
#include "window-basic-main.hpp"
#include "window-basic-status-bar.hpp"
: QStatusBar (parent),
delayInfo (new QLabel),
droppedFrames (new QLabel),
- sessionTime (new QLabel),
+ streamTime (new QLabel),
+ recordTime (new QLabel),
cpuUsage (new QLabel),
- kbps (new QLabel)
+ transparentPixmap (20, 20),
+ greenPixmap (20, 20),
+ grayPixmap (20, 20),
+ redPixmap (20, 20)
{
- sessionTime->setText(QString("00:00:00"));
- cpuUsage->setText(QString("CPU: 0.0%"));
+ streamTime->setText(QString("LIVE: 00:00:00"));
+ recordTime->setText(QString("REC: 00:00:00"));
+ cpuUsage->setText(QString("CPU: 0.0%, 0.00 fps"));
+
+ QWidget *brWidget = new QWidget(this);
+ QHBoxLayout *brLayout = new QHBoxLayout(brWidget);
+ brLayout->setContentsMargins(0, 0, 0, 0);
+
+ statusSquare = new QLabel(brWidget);
+ brLayout->addWidget(statusSquare);
+
+ kbps = new QLabel(brWidget);
+ brLayout->addWidget(kbps);
+
+ brWidget->setLayout(brLayout);
delayInfo->setAlignment(Qt::AlignRight);
+ delayInfo->setAlignment(Qt::AlignVCenter);
droppedFrames->setAlignment(Qt::AlignRight);
- sessionTime->setAlignment(Qt::AlignRight);
+ droppedFrames->setAlignment(Qt::AlignVCenter);
+ streamTime->setAlignment(Qt::AlignRight);
+ streamTime->setAlignment(Qt::AlignVCenter);
+ recordTime->setAlignment(Qt::AlignRight);
+ recordTime->setAlignment(Qt::AlignVCenter);
cpuUsage->setAlignment(Qt::AlignRight);
+ cpuUsage->setAlignment(Qt::AlignVCenter);
kbps->setAlignment(Qt::AlignRight);
+ kbps->setAlignment(Qt::AlignVCenter);
delayInfo->setIndent(20);
droppedFrames->setIndent(20);
- sessionTime->setIndent(20);
+ streamTime->setIndent(20);
+ recordTime->setIndent(20);
cpuUsage->setIndent(20);
kbps->setIndent(10);
addPermanentWidget(droppedFrames);
- addPermanentWidget(sessionTime);
+ addPermanentWidget(streamTime);
+ addPermanentWidget(recordTime);
addPermanentWidget(cpuUsage);
addPermanentWidget(delayInfo);
- addPermanentWidget(kbps);
+ addPermanentWidget(brWidget);
+
+ transparentPixmap.fill(QColor(0, 0, 0, 0));
+ greenPixmap.fill(QColor(0, 255, 0));
+ grayPixmap.fill(QColor(72, 72, 72));
+ redPixmap.fill(QColor(255, 0, 0));
+
+ statusSquare->setPixmap(transparentPixmap);
}
void OBSBasicStatusBar::Activate()
int skipped = video_output_get_skipped_frames(obs_get_video());
int total = video_output_get_total_frames(obs_get_video());
- totalSeconds = 0;
+ totalStreamSeconds = 0;
+ totalRecordSeconds = 0;
lastSkippedFrameCount = 0;
startSkippedFrameCount = skipped;
startTotalFrameCount = total;
refreshTimer->start(1000);
active = true;
+
+ if (streamOutput) {
+ statusSquare->setPixmap(grayPixmap);
+ }
}
}
if (!main)
return;
+ if (!streamOutput) {
+ streamTime->setText(QString("LIVE: 00:00:00"));
+ totalStreamSeconds = 0;
+ }
+
+ if (!recordOutput) {
+ recordTime->setText(QString("REC: 00:00:00"));
+ totalRecordSeconds = 0;
+ }
+
if (!main->outputHandler->Active()) {
delete refreshTimer;
- sessionTime->setText(QString("00:00:00"));
+
delayInfo->setText("");
droppedFrames->setText("");
kbps->setText("");
reconnectTimeout = 0;
active = false;
overloadedNotify = true;
+
+ statusSquare->setPixmap(transparentPixmap);
}
}
QString text;
text += QString("kb/s: ") +
QString::number(kbitsPerSec, 'f', 0);
+
kbps->setText(text);
kbps->setMinimumWidth(kbps->width());
cpuUsage->setMinimumWidth(cpuUsage->width());
}
-void OBSBasicStatusBar::UpdateSessionTime()
+void OBSBasicStatusBar::UpdateStreamTime()
{
- totalSeconds++;
+ totalStreamSeconds++;
- int seconds = totalSeconds % 60;
- int totalMinutes = totalSeconds / 60;
+ int seconds = totalStreamSeconds % 60;
+ int totalMinutes = totalStreamSeconds / 60;
int minutes = totalMinutes % 60;
int hours = totalMinutes / 60;
QString text;
- text.sprintf("%02d:%02d:%02d", hours, minutes, seconds);
- sessionTime->setText(text);
- sessionTime->setMinimumWidth(sessionTime->width());
+ text.sprintf("LIVE: %02d:%02d:%02d", hours, minutes, seconds);
+ streamTime->setText(text);
+ streamTime->setMinimumWidth(streamTime->width());
if (reconnectTimeout > 0) {
QString msg = QTStr("Basic.StatusBar.Reconnecting")
}
}
+void OBSBasicStatusBar::UpdateRecordTime()
+{
+ totalRecordSeconds++;
+
+ int seconds = totalRecordSeconds % 60;
+ int totalMinutes = totalRecordSeconds / 60;
+ int minutes = totalMinutes % 60;
+ int hours = totalMinutes / 60;
+
+ QString text;
+ text.sprintf("REC: %02d:%02d:%02d", hours, minutes, seconds);
+ recordTime->setText(text);
+ recordTime->setMinimumWidth(recordTime->width());
+}
+
void OBSBasicStatusBar::UpdateDroppedFrames()
{
if (!streamOutput)
QString::number(percent, 'f', 1));
droppedFrames->setText(text);
droppedFrames->setMinimumWidth(droppedFrames->width());
+
+ /* ----------------------------------- *
+ * calculate congestion color */
+
+ float congestion = obs_output_get_congestion(streamOutput);
+ float avgCongestion = (congestion + lastCongestion) * 0.5f;
+ if (avgCongestion < congestion)
+ avgCongestion = congestion;
+ if (avgCongestion > 1.0f)
+ avgCongestion = 1.0f;
+
+ if (avgCongestion < EPSILON) {
+ statusSquare->setPixmap(greenPixmap);
+ } else if (fabsf(avgCongestion - 1.0f) < EPSILON) {
+ statusSquare->setPixmap(redPixmap);
+ } else {
+ QPixmap pixmap(20, 20);
+
+ float red = avgCongestion * 2.0f;
+ if (red > 1.0f) red = 1.0f;
+ red *= 255.0;
+
+ float green = (1.0f - avgCongestion) * 2.0f;
+ if (green > 1.0f) green = 1.0f;
+ green *= 255.0;
+
+ pixmap.fill(QColor(int(red), int(green), 0));
+ statusSquare->setPixmap(pixmap);
+ }
+
+ lastCongestion = congestion;
}
void OBSBasicStatusBar::OBSOutputReconnect(void *data, calldata_t *params)
OBSBasic *main = qobject_cast<OBSBasic*>(parent());
UpdateBandwidth();
- UpdateSessionTime();
+
+ if (streamOutput)
+ UpdateStreamTime();
+
+ if (recordOutput)
+ UpdateRecordTime();
+
UpdateDroppedFrames();
int skipped = video_output_get_skipped_frames(obs_get_video());
obs-studio-17.0.2.tar.xz/UI/window-basic-status-bar.hpp -> obs-studio-18.0.0.tar.xz/UI/window-basic-status-bar.hpp
Changed
private:
QLabel *delayInfo;
QLabel *droppedFrames;
- QLabel *sessionTime;
+ QLabel *streamTime;
+ QLabel *recordTime;
QLabel *cpuUsage;
QLabel *kbps;
+ QLabel *statusSquare;
obs_output_t *streamOutput = nullptr;
obs_output_t *recordOutput = nullptr;
bool overloadedNotify = true;
int retries = 0;
- int totalSeconds = 0;
+ int totalStreamSeconds = 0;
+ int totalRecordSeconds = 0;
int reconnectTimeout = 0;
uint64_t lastBytesSent = 0;
uint64_t lastBytesSentTime = 0;
+ QPixmap transparentPixmap;
+ QPixmap greenPixmap;
+ QPixmap grayPixmap;
+ QPixmap redPixmap;
+
+ float lastCongestion = 0.0f;
+
QPointer<QTimer> refreshTimer;
obs_output_t *GetOutput();
void UpdateDelayMsg();
void UpdateBandwidth();
- void UpdateSessionTime();
+ void UpdateStreamTime();
+ void UpdateRecordTime();
void UpdateDroppedFrames();
static void OBSOutputReconnect(void *data, calldata_t *params);
obs-studio-17.0.2.tar.xz/UI/window-projector.cpp -> obs-studio-18.0.0.tar.xz/UI/window-projector.cpp
Changed
{
setAttribute(Qt::WA_DeleteOnClose, true);
+ //disable application quit when last window closed
+ setAttribute(Qt::WA_QuitOnClose, false);
+
installEventFilter(CreateShortcutFilter());
auto addDrawCallback = [this] ()
void OBSProjector::Init(int monitor)
{
QScreen *screen = QGuiApplication::screens()[monitor];
+
setGeometry(screen->geometry());
bool alwaysOnTop = config_get_bool(GetGlobalConfig(),
addAction(action);
connect(action, SIGNAL(triggered()), this, SLOT(EscapeTriggered()));
+
+ savedMonitor = monitor;
}
void OBSProjector::OBSRender(void *data, uint32_t cx, uint32_t cy)
void OBSProjector::OBSSourceRemoved(void *data, calldata_t *params)
{
OBSProjector *window = reinterpret_cast<OBSProjector*>(data);
+
window->deleteLater();
UNUSED_PARAMETER(params);
void OBSProjector::EscapeTriggered()
{
+ OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow());
+ main->RemoveSavedProjectors(savedMonitor);
+
deleteLater();
}
obs-studio-17.0.2.tar.xz/UI/window-projector.hpp -> obs-studio-18.0.0.tar.xz/UI/window-projector.hpp
Changed
#include <obs.hpp>
#include "qt-display.hpp"
+#include "window-basic-main.hpp"
class QMouseEvent;
void mousePressEvent(QMouseEvent *event) override;
+ int savedMonitor = 0;
+
private slots:
void EscapeTriggered();
obs-studio-18.0.0.tar.xz/appveyor.yml
Added
+environment:
+ CURL_VERSION: 7.39.0
+
+install:
+ - git submodule update --init --recursive
+ - if not exist dependencies2015.zip curl -kLO https://obsproject.com/downloads/dependencies2015.zip -f --retry 5 -C -
+ - if not exist vlc.zip curl -kLO https://obsproject.com/downloads/vlc.zip -f --retry 5 -C -
+ - 7z x dependencies2015.zip -odependencies2015
+ - 7z x vlc.zip -ovlc
+ - set DepsPath32=%CD%\dependencies2015\win32
+ - set DepsPath64=%CD%\dependencies2015\win64
+ - set VLCPath=%CD%\vlc
+ - set QTDIR32=C:\Qt\5.7\msvc2015
+ - set QTDIR64=C:\Qt\5.7\msvc2015_64
+ - set build_config=RelWithDebInfo
+ - move "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\um\d3d11on12*" "C:\Program Files (x86)\Windows Kits\8.1\Include\um"
+ - move "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\um\d3d12*" "C:\Program Files (x86)\Windows Kits\8.1\Include\um"
+ - move "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\shared\dxgi*" "C:\Program Files (x86)\Windows Kits\8.1\Include\shared"
+ - mkdir build
+ - mkdir build32
+ - mkdir build64
+ - cd ./build32
+ - cmake -G "Visual Studio 14 2015" -DCOPIED_DEPENDENCIES=false -DCOPY_DEPENDENCIES=true -DBUILD_CAPTIONS=true -DCOMPILE_D3D12_HOOK=true ..
+ - cd ../build64
+ - cmake -G "Visual Studio 14 2015 Win64" -DCOPIED_DEPENDENCIES=false -DCOPY_DEPENDENCIES=true -DBUILD_CAPTIONS=true -DCOMPILE_D3D12_HOOK=true ..
+
+build_script:
+ - call msbuild /m /p:Configuration=%build_config% C:\projects\obs-studio\build32\obs-studio.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
+ - call msbuild /m /p:Configuration=%build_config% C:\projects\obs-studio\build64\obs-studio.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
+
+before_deploy:
+ - C:\projects\obs-studio\CI\before-deploy-win.cmd
+
+deploy_script:
+ - ps: Push-AppveyorArtifact "build.zip" -FileName "$(git describe).zip"
+
+test: off
+
+cache:
+ - dependencies2015.zip
+ - vlc.zip
obs-studio-17.0.2.tar.xz/cmake/Modules/CopyMSVCBins.cmake -> obs-studio-18.0.0.tar.xz/cmake/Modules/CopyMSVCBins.cmake
Changed
return()
endif()
-option(COPY_DEPENDENCIES "Automaticaly try copying all dependencies" OFF)
+option(COPY_DEPENDENCIES "Automaticaly try copying all dependencies" ON)
if(NOT COPY_DEPENDENCIES)
return()
endif()
obs-studio-17.0.2.tar.xz/deps/CMakeLists.txt -> obs-studio-18.0.0.tar.xz/deps/CMakeLists.txt
Changed
add_subdirectory(libff)
add_subdirectory(file-updater)
+if(WIN32)
+ add_subdirectory(blake2)
+endif()
+
if(BUILD_CAPTIONS)
add_subdirectory(libcaption)
endif()
obs-studio-18.0.0.tar.xz/deps/blake2
Added
+(directory)
obs-studio-18.0.0.tar.xz/deps/blake2/CMakeLists.txt
Added
+cmake_minimum_required(VERSION 3.2)
+
+project(blake2)
+
+set(BLAKE2_INCLUDE_DIR
+ "${CMAKE_CURRENT_SOURCE_DIR}/src"
+ CACHE PATH "blake2 include path")
+
+include_directories(
+ ${LIBblake2_INCLUDE_DIRS}
+ src
+)
+
+if(WIN32)
+ if(MSVC)
+ add_compile_options("$<$<CONFIG:RelWithDebInfo>:/MT>")
+ endif()
+ add_definitions(
+ -Dinline=_inline
+ -Drestrict=__restrict)
+endif()
+
+set(blake2_SOURCES
+ src/blake2b-ref.c)
+
+set(blake2_HEADERS
+ src/blake2.h
+ src/blake2-impl.h)
+
+add_library(blake2 STATIC
+ ${blake2_SOURCES}
+ ${blake2_HEADERS})
obs-studio-18.0.0.tar.xz/deps/blake2/src
Added
+(directory)
obs-studio-18.0.0.tar.xz/deps/blake2/src/blake2-impl.h
Added
+/*
+ BLAKE2 reference source code package - reference C implementations
+
+ Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
+ terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
+ your option. The terms of these licenses can be found at:
+
+ - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ - OpenSSL license : https://www.openssl.org/source/license.html
+ - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
+
+ More information about the BLAKE2 hash function can be found at
+ https://blake2.net.
+*/
+#ifndef BLAKE2_IMPL_H
+#define BLAKE2_IMPL_H
+
+#include <stdint.h>
+#include <string.h>
+
+#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
+ #if defined(_MSC_VER)
+ #define BLAKE2_INLINE __inline
+ #elif defined(__GNUC__)
+ #define BLAKE2_INLINE __inline__
+ #else
+ #define BLAKE2_INLINE
+ #endif
+#else
+ #define BLAKE2_INLINE inline
+#endif
+
+static BLAKE2_INLINE uint32_t load32( const void *src )
+{
+#if defined(NATIVE_LITTLE_ENDIAN)
+ uint32_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ const uint8_t *p = ( const uint8_t * )src;
+ return (( uint32_t )( p[0] ) << 0) |
+ (( uint32_t )( p[1] ) << 8) |
+ (( uint32_t )( p[2] ) << 16) |
+ (( uint32_t )( p[3] ) << 24) ;
+#endif
+}
+
+static BLAKE2_INLINE uint64_t load64( const void *src )
+{
+#if defined(NATIVE_LITTLE_ENDIAN)
+ uint64_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ const uint8_t *p = ( const uint8_t * )src;
+ return (( uint64_t )( p[0] ) << 0) |
+ (( uint64_t )( p[1] ) << 8) |
+ (( uint64_t )( p[2] ) << 16) |
+ (( uint64_t )( p[3] ) << 24) |
+ (( uint64_t )( p[4] ) << 32) |
+ (( uint64_t )( p[5] ) << 40) |
+ (( uint64_t )( p[6] ) << 48) |
+ (( uint64_t )( p[7] ) << 56) ;
+#endif
+}
+
+static BLAKE2_INLINE uint16_t load16( const void *src )
+{
+#if defined(NATIVE_LITTLE_ENDIAN)
+ uint16_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ const uint8_t *p = ( const uint8_t * )src;
+ return (( uint16_t )( p[0] ) << 0) |
+ (( uint16_t )( p[1] ) << 8) ;
+#endif
+}
+
+static BLAKE2_INLINE void store16( void *dst, uint16_t w )
+{
+#if defined(NATIVE_LITTLE_ENDIAN)
+ memcpy(dst, &w, sizeof w);
+#else
+ uint8_t *p = ( uint8_t * )dst;
+ *p++ = ( uint8_t )w; w >>= 8;
+ *p++ = ( uint8_t )w;
+#endif
+}
+
+static BLAKE2_INLINE void store32( void *dst, uint32_t w )
+{
+#if defined(NATIVE_LITTLE_ENDIAN)
+ memcpy(dst, &w, sizeof w);
+#else
+ uint8_t *p = ( uint8_t * )dst;
+ p[0] = (uint8_t)(w >> 0);
+ p[1] = (uint8_t)(w >> 8);
+ p[2] = (uint8_t)(w >> 16);
+ p[3] = (uint8_t)(w >> 24);
+#endif
+}
+
+static BLAKE2_INLINE void store64( void *dst, uint64_t w )
+{
+#if defined(NATIVE_LITTLE_ENDIAN)
+ memcpy(dst, &w, sizeof w);
+#else
+ uint8_t *p = ( uint8_t * )dst;
+ p[0] = (uint8_t)(w >> 0);
+ p[1] = (uint8_t)(w >> 8);
+ p[2] = (uint8_t)(w >> 16);
+ p[3] = (uint8_t)(w >> 24);
+ p[4] = (uint8_t)(w >> 32);
+ p[5] = (uint8_t)(w >> 40);
+ p[6] = (uint8_t)(w >> 48);
+ p[7] = (uint8_t)(w >> 56);
+#endif
+}
+
+static BLAKE2_INLINE uint64_t load48( const void *src )
+{
+ const uint8_t *p = ( const uint8_t * )src;
+ return (( uint64_t )( p[0] ) << 0) |
+ (( uint64_t )( p[1] ) << 8) |
+ (( uint64_t )( p[2] ) << 16) |
+ (( uint64_t )( p[3] ) << 24) |
+ (( uint64_t )( p[4] ) << 32) |
+ (( uint64_t )( p[5] ) << 40) ;
+}
+
+static BLAKE2_INLINE void store48( void *dst, uint64_t w )
+{
+ uint8_t *p = ( uint8_t * )dst;
+ p[0] = (uint8_t)(w >> 0);
+ p[1] = (uint8_t)(w >> 8);
+ p[2] = (uint8_t)(w >> 16);
+ p[3] = (uint8_t)(w >> 24);
+ p[4] = (uint8_t)(w >> 32);
+ p[5] = (uint8_t)(w >> 40);
+}
+
+static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c )
+{
+ return ( w >> c ) | ( w << ( 32 - c ) );
+}
+
+static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )
+{
+ return ( w >> c ) | ( w << ( 64 - c ) );
+}
+
+/* prevents compiler optimizing out memset() */
+static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
+{
+ static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
+ memset_v(v, 0, n);
+}
+
+#endif
obs-studio-18.0.0.tar.xz/deps/blake2/src/blake2.h
Added
+/*
+ BLAKE2 reference source code package - reference C implementations
+
+ Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
+ terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
+ your option. The terms of these licenses can be found at:
+
+ - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ - OpenSSL license : https://www.openssl.org/source/license.html
+ - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
+
+ More information about the BLAKE2 hash function can be found at
+ https://blake2.net.
+*/
+#ifndef BLAKE2_H
+#define BLAKE2_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#if defined(_MSC_VER)
+#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
+#else
+#define BLAKE2_PACKED(x) x __attribute__((packed))
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+ enum blake2s_constant
+ {
+ BLAKE2S_BLOCKBYTES = 64,
+ BLAKE2S_OUTBYTES = 32,
+ BLAKE2S_KEYBYTES = 32,
+ BLAKE2S_SALTBYTES = 8,
+ BLAKE2S_PERSONALBYTES = 8
+ };
+
+ enum blake2b_constant
+ {
+ BLAKE2B_BLOCKBYTES = 128,
+ BLAKE2B_OUTBYTES = 64,
+ BLAKE2B_KEYBYTES = 64,
+ BLAKE2B_SALTBYTES = 16,
+ BLAKE2B_PERSONALBYTES = 16
+ };
+
+ typedef struct blake2s_state__
+ {
+ uint32_t h[8];
+ uint32_t t[2];
+ uint32_t f[2];
+ uint8_t buf[BLAKE2S_BLOCKBYTES];
+ size_t buflen;
+ size_t outlen;
+ uint8_t last_node;
+ } blake2s_state;
+
+ typedef struct blake2b_state__
+ {
+ uint64_t h[8];
+ uint64_t t[2];
+ uint64_t f[2];
+ uint8_t buf[BLAKE2B_BLOCKBYTES];
+ size_t buflen;
+ size_t outlen;
+ uint8_t last_node;
+ } blake2b_state;
+
+ typedef struct blake2sp_state__
+ {
+ blake2s_state S[8][1];
+ blake2s_state R[1];
+ uint8_t buf[8 * BLAKE2S_BLOCKBYTES];
+ size_t buflen;
+ size_t outlen;
+ } blake2sp_state;
+
+ typedef struct blake2bp_state__
+ {
+ blake2b_state S[4][1];
+ blake2b_state R[1];
+ uint8_t buf[4 * BLAKE2B_BLOCKBYTES];
+ size_t buflen;
+ size_t outlen;
+ } blake2bp_state;
+
+
+ BLAKE2_PACKED(struct blake2s_param__
+ {
+ uint8_t digest_length; /* 1 */
+ uint8_t key_length; /* 2 */
+ uint8_t fanout; /* 3 */
+ uint8_t depth; /* 4 */
+ uint32_t leaf_length; /* 8 */
+ uint32_t node_offset; /* 12 */
+ uint16_t xof_length; /* 14 */
+ uint8_t node_depth; /* 15 */
+ uint8_t inner_length; /* 16 */
+ /* uint8_t reserved[0]; */
+ uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
+ uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
+ });
+
+ typedef struct blake2s_param__ blake2s_param;
+
+ BLAKE2_PACKED(struct blake2b_param__
+ {
+ uint8_t digest_length; /* 1 */
+ uint8_t key_length; /* 2 */
+ uint8_t fanout; /* 3 */
+ uint8_t depth; /* 4 */
+ uint32_t leaf_length; /* 8 */
+ uint32_t node_offset; /* 12 */
+ uint32_t xof_length; /* 16 */
+ uint8_t node_depth; /* 17 */
+ uint8_t inner_length; /* 18 */
+ uint8_t reserved[14]; /* 32 */
+ uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
+ uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
+ });
+
+ typedef struct blake2b_param__ blake2b_param;
+
+ typedef struct blake2xs_state__
+ {
+ blake2s_state S[1];
+ blake2s_param P[1];
+ } blake2xs_state;
+
+ typedef struct blake2xb_state__
+ {
+ blake2b_state S[1];
+ blake2b_param P[1];
+ } blake2xb_state;
+
+ /* Padded structs result in a compile-time error */
+ enum {
+ BLAKE2_DUMMY_1 = 1/(sizeof(blake2s_param) == BLAKE2S_OUTBYTES),
+ BLAKE2_DUMMY_2 = 1/(sizeof(blake2b_param) == BLAKE2B_OUTBYTES)
+ };
+
+ /* Streaming API */
+ int blake2s_init( blake2s_state *S, size_t outlen );
+ int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
+ int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
+ int blake2s_update( blake2s_state *S, const void *in, size_t inlen );
+ int blake2s_final( blake2s_state *S, void *out, size_t outlen );
+
+ int blake2b_init( blake2b_state *S, size_t outlen );
+ int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
+ int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
+ int blake2b_update( blake2b_state *S, const void *in, size_t inlen );
+ int blake2b_final( blake2b_state *S, void *out, size_t outlen );
+
+ int blake2sp_init( blake2sp_state *S, size_t outlen );
+ int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
+ int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
+ int blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
+
+ int blake2bp_init( blake2bp_state *S, size_t outlen );
+ int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
+ int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
+ int blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
+
+ /* Variable output length API */
+ int blake2xs_init( blake2xs_state *S, const size_t outlen );
+ int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
+ int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
+ int blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
+
+ int blake2xb_init( blake2xb_state *S, const size_t outlen );
+ int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
+ int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
+ int blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
+
+ /* Simple API */
+ int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
+ int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
+
+ int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
+ int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
+
+ int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
+ int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
+
+ /* This is simply an alias for blake2b */
+ int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
obs-studio-18.0.0.tar.xz/deps/blake2/src/blake2b-ref.c
Added
+/*
+ BLAKE2 reference source code package - reference C implementations
+
+ Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
+ terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
+ your option. The terms of these licenses can be found at:
+
+ - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ - OpenSSL license : https://www.openssl.org/source/license.html
+ - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
+
+ More information about the BLAKE2 hash function can be found at
+ https://blake2.net.
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "blake2.h"
+#include "blake2-impl.h"
+
+static const uint64_t blake2b_IV[8] =
+{
+ 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+static const uint8_t blake2b_sigma[12][16] =
+{
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
+ { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
+ { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
+ { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
+ { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
+ { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
+ { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
+ { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
+ { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
+};
+
+
+static void blake2b_set_lastnode( blake2b_state *S )
+{
+ S->f[1] = (uint64_t)-1;
+}
+
+/* Some helper functions, not necessarily useful */
+static int blake2b_is_lastblock( const blake2b_state *S )
+{
+ return S->f[0] != 0;
+}
+
+static void blake2b_set_lastblock( blake2b_state *S )
+{
+ if( S->last_node ) blake2b_set_lastnode( S );
+
+ S->f[0] = (uint64_t)-1;
+}
+
+static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
+{
+ S->t[0] += inc;
+ S->t[1] += ( S->t[0] < inc );
+}
+
+static void blake2b_init0( blake2b_state *S )
+{
+ size_t i;
+ memset( S, 0, sizeof( blake2b_state ) );
+
+ for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
+}
+
+/* init xors IV with input parameter block */
+int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
+{
+ const uint8_t *p = ( const uint8_t * )( P );
+ size_t i;
+
+ blake2b_init0( S );
+
+ /* IV XOR ParamBlock */
+ for( i = 0; i < 8; ++i )
+ S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
+
+ S->outlen = P->digest_length;
+ return 0;
+}
+
+
+
+int blake2b_init( blake2b_state *S, size_t outlen )
+{
+ blake2b_param P[1];
+
+ if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
+
+ P->digest_length = (uint8_t)outlen;
+ P->key_length = 0;
+ P->fanout = 1;
+ P->depth = 1;
+ store32( &P->leaf_length, 0 );
+ store32( &P->node_offset, 0 );
+ store32( &P->xof_length, 0 );
+ P->node_depth = 0;
+ P->inner_length = 0;
+ memset( P->reserved, 0, sizeof( P->reserved ) );
+ memset( P->salt, 0, sizeof( P->salt ) );
+ memset( P->personal, 0, sizeof( P->personal ) );
+ return blake2b_init_param( S, P );
+}
+
+
+int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )
+{
+ blake2b_param P[1];
+
+ if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
+
+ if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
+
+ P->digest_length = (uint8_t)outlen;
+ P->key_length = (uint8_t)keylen;
+ P->fanout = 1;
+ P->depth = 1;
+ store32( &P->leaf_length, 0 );
+ store32( &P->node_offset, 0 );
+ store32( &P->xof_length, 0 );
+ P->node_depth = 0;
+ P->inner_length = 0;
+ memset( P->reserved, 0, sizeof( P->reserved ) );
+ memset( P->salt, 0, sizeof( P->salt ) );
+ memset( P->personal, 0, sizeof( P->personal ) );
+
+ if( blake2b_init_param( S, P ) < 0 ) return -1;
+
+ {
+ uint8_t block[BLAKE2B_BLOCKBYTES];
+ memset( block, 0, BLAKE2B_BLOCKBYTES );
+ memcpy( block, key, keylen );
+ blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
+ secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
+ }
+ return 0;
+}
+
+#define G(r,i,a,b,c,d) \
+ do { \
+ a = a + b + m[blake2b_sigma[r][2*i+0]]; \
+ d = rotr64(d ^ a, 32); \
+ c = c + d; \
+ b = rotr64(b ^ c, 24); \
+ a = a + b + m[blake2b_sigma[r][2*i+1]]; \
+ d = rotr64(d ^ a, 16); \
+ c = c + d; \
+ b = rotr64(b ^ c, 63); \
+ } while(0)
+
+#define ROUND(r) \
+ do { \
+ G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
+ G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
+ G(r,2,v[ 2],v[ 6],v[10],v[14]); \
+ G(r,3,v[ 3],v[ 7],v[11],v[15]); \
+ G(r,4,v[ 0],v[ 5],v[10],v[15]); \
+ G(r,5,v[ 1],v[ 6],v[11],v[12]); \
+ G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
+ G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
+ } while(0)
+
+static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
+{
+ uint64_t m[16];
+ uint64_t v[16];
+ size_t i;
+
+ for( i = 0; i < 16; ++i ) {
+ m[i] = load64( block + i * sizeof( m[i] ) );
+ }
+
+ for( i = 0; i < 8; ++i ) {
+ v[i] = S->h[i];
+ }
+
+ v[ 8] = blake2b_IV[0];
+ v[ 9] = blake2b_IV[1];
+ v[10] = blake2b_IV[2];
+ v[11] = blake2b_IV[3];
+ v[12] = blake2b_IV[4] ^ S->t[0];
+ v[13] = blake2b_IV[5] ^ S->t[1];
+ v[14] = blake2b_IV[6] ^ S->f[0];
+ v[15] = blake2b_IV[7] ^ S->f[1];
+
+ ROUND( 0 );
+ ROUND( 1 );
+ ROUND( 2 );
+ ROUND( 3 );
+ ROUND( 4 );
+ ROUND( 5 );
+ ROUND( 6 );
+ ROUND( 7 );
+ ROUND( 8 );
+ ROUND( 9 );
+ ROUND( 10 );
+ ROUND( 11 );
+
+ for( i = 0; i < 8; ++i ) {
+ S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
+ }
+}
+
+#undef G
+#undef ROUND
+
+int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
+{
+ const unsigned char * in = (const unsigned char *)pin;
+ if( inlen > 0 )
+ {
+ size_t left = S->buflen;
+ size_t fill = BLAKE2B_BLOCKBYTES - left;
+ if( inlen > fill )
+ {
+ S->buflen = 0;
+ memcpy( S->buf + left, in, fill ); /* Fill buffer */
+ blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
+ blake2b_compress( S, S->buf ); /* Compress */
+ in += fill; inlen -= fill;
+ while(inlen > BLAKE2B_BLOCKBYTES) {
+ blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
+ blake2b_compress( S, in );
+ in += BLAKE2B_BLOCKBYTES;
+ inlen -= BLAKE2B_BLOCKBYTES;
+ }
+ }
+ memcpy( S->buf + S->buflen, in, inlen );
+ S->buflen += inlen;
+ }
+ return 0;
+}
+
+int blake2b_final( blake2b_state *S, void *out, size_t outlen )
+{
+ uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
+ size_t i;
+
+ if( out == NULL || outlen < S->outlen )
+ return -1;
+
+ if( blake2b_is_lastblock( S ) )
+ return -1;
+
+ blake2b_increment_counter( S, S->buflen );
+ blake2b_set_lastblock( S );
+ memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
+ blake2b_compress( S, S->buf );
+
+ for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
+ store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
+
+ memcpy( out, buffer, S->outlen );
+ secure_zero_memory(buffer, sizeof(buffer));
+ return 0;
+}
+
+/* inlen, at least, should be uint64_t. Others can be size_t. */
+int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
+{
+ blake2b_state S[1];
+
+ /* Verify parameters */
+ if ( NULL == in && inlen > 0 ) return -1;
+
+ if ( NULL == out ) return -1;
+
+ if( NULL == key && keylen > 0 ) return -1;
+
+ if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
+
+ if( keylen > BLAKE2B_KEYBYTES ) return -1;
+
+ if( keylen > 0 )
+ {
+ if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
+ }
+ else
+ {
+ if( blake2b_init( S, outlen ) < 0 ) return -1;
+ }
+
+ blake2b_update( S, ( const uint8_t * )in, inlen );
+ blake2b_final( S, out, outlen );
+ return 0;
+}
+
+int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
+ return blake2b(out, outlen, in, inlen, key, keylen);
+}
+
+#if defined(SUPERCOP)
+int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
+{
+ return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );
+}
+#endif
+
+#if defined(BLAKE2B_SELFTEST)
+#include <string.h>
+#include "blake2-kat.h"
+int main( void )
+{
+ uint8_t key[BLAKE2B_KEYBYTES];
+ uint8_t buf[BLAKE2_KAT_LENGTH];
+ size_t i, step;
+
+ for( i = 0; i < BLAKE2B_KEYBYTES; ++i )
+ key[i] = ( uint8_t )i;
+
+ for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
+ buf[i] = ( uint8_t )i;
+
+ /* Test simple API */
+ for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
+ {
+ uint8_t hash[BLAKE2B_OUTBYTES];
+ blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
+
+ if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
+ {
+ goto fail;
+ }
+ }
+
+ /* Test streaming API */
+ for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
+ for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
+ uint8_t hash[BLAKE2B_OUTBYTES];
+ blake2b_state S;
+ uint8_t * p = buf;
+ size_t mlen = i;
+ int err = 0;
+
+ if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
+ goto fail;
+ }
+
+ while (mlen >= step) {
+ if ( (err = blake2b_update(&S, p, step)) < 0 ) {
+ goto fail;
+ }
+ mlen -= step;
+ p += step;
+ }
+ if ( (err = blake2b_update(&S, p, mlen)) < 0) {
+ goto fail;
+ }
+ if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
+ goto fail;
+ }
+
+ if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {
+ goto fail;
+ }
+ }
+ }
+
+ puts( "ok" );
+ return 0;
+fail:
+ puts("error");
+ return -1;
+}
+#endif
obs-studio-17.0.2.tar.xz/deps/libff/libff/ff-decoder.c -> obs-studio-18.0.0.tar.xz/deps/libff/libff/ff-decoder.c
Changed
struct ff_frame *frame;
- if (decoder && decoder->stream) {
+ if (decoder->stream) {
if (decoder->frame_queue.size == 0) {
if (!decoder->eof || !decoder->finished) {
// We expected a frame, but there were none
obs-studio-17.0.2.tar.xz/deps/libff/libff/ff-util.c -> obs-studio-18.0.0.tar.xz/deps/libff/libff/ff-util.c
Changed
static void add_codec_to_list(const struct ff_format_desc *format_desc,
struct ff_codec_desc **first, struct ff_codec_desc **current,
- enum AVCodecID id, const AVCodec *codec)
+ enum AVCodecID id, const AVCodec *codec,
+ bool ignore_compatability)
{
if (codec == NULL)
codec = avcodec_find_encoder(id);
if (!av_codec_is_encoder(codec))
return;
- // Format doesn't support this codec
- unsigned int tag = av_codec_get_tag(format_desc->codec_tags,
- codec->id);
- if (tag == 0)
- return;
+ if (!ignore_compatability) {
+ // Format doesn't support this codec
+ unsigned int tag = av_codec_get_tag(format_desc->codec_tags,
+ codec->id);
+ if (tag == 0)
+ return;
+ }
struct ff_codec_desc *d = av_mallocz(sizeof(struct ff_codec_desc));
static void get_codecs_for_id(const struct ff_format_desc *format_desc,
struct ff_codec_desc **first, struct ff_codec_desc **current,
- enum AVCodecID id)
+ enum AVCodecID id, bool ignore_compatability)
{
const AVCodec *codec = NULL;
while ((codec = next_codec_for_id(id, codec)))
add_codec_to_list(format_desc, first, current, codec->id,
- codec);
+ codec, ignore_compatability);
}
const struct ff_codec_desc *ff_codec_supported(
- const struct ff_format_desc *format_desc)
+ const struct ff_format_desc *format_desc,
+ bool ignore_compatability)
{
const AVCodecDescriptor **codecs;
unsigned int size;
for(i = 0; i < size; i++) {
const AVCodecDescriptor *codec = codecs[i];
- get_codecs_for_id(format_desc, &first, ¤t, codec->id);
+ get_codecs_for_id(format_desc, &first, ¤t, codec->id,
+ ignore_compatability);
}
av_free((void *)codecs);
obs-studio-17.0.2.tar.xz/deps/libff/libff/ff-util.h -> obs-studio-18.0.0.tar.xz/deps/libff/libff/ff-util.h
Changed
// Codec Description
const struct ff_codec_desc *ff_codec_supported(
- const struct ff_format_desc *format_desc);
+ const struct ff_format_desc *format_desc,
+ bool ignore_compatability);
void ff_codec_desc_free(const struct ff_codec_desc *codec_desc);
const char *ff_codec_desc_name(const struct ff_codec_desc *codec_desc);
const char *ff_codec_desc_long_name(const struct ff_codec_desc *codec_desc);
obs-studio-17.0.2.tar.xz/libobs-opengl/gl-subsystem.c -> obs-studio-18.0.0.tar.xz/libobs-opengl/gl-subsystem.c
Changed
/* need a pixel shader to properly bind textures */
if (!device->cur_pixel_shader)
- tex = NULL;
+ goto fail;
if (cur_tex == tex)
return;
obs-studio-17.0.2.tar.xz/libobs/CMakeLists.txt -> obs-studio-18.0.0.tar.xz/libobs/CMakeLists.txt
Changed
util/windows/CoTaskMemPtr.hpp
util/windows/HRError.hpp
util/windows/WinHandle.hpp)
+ set(libobs_audio_monitoring_SOURCES
+ audio-monitoring/win32/wasapi-output.c
+ audio-monitoring/win32/wasapi-enum-devices.c
+ )
+ set(libobs_audio_monitoring_HEADERS
+ audio-monitoring/win32/wasapi-output.h
+ )
set(libobs_PLATFORM_DEPS winmm)
if(MSVC)
set(libobs_PLATFORM_DEPS
util/platform-cocoa.m)
set(libobs_PLATFORM_HEADERS
util/threading-posix.h)
+ set(libobs_audio_monitoring_SOURCES
+ audio-monitoring/osx/coreaudio-enum-devices.c
+ audio-monitoring/osx/coreaudio-output.c
+ )
+ set(libobs_audio_monitoring_HEADERS
+ audio-monitoring/osx/mac-helpers.h
+ )
set_source_files_properties(${libobs_PLATFORM_SOURCES}
PROPERTIES
mark_as_advanced(COCOA)
include_directories(${COCOA})
+ find_library(COREAUDIO CoreAudio)
+ mark_as_advanced(COREAUDIO)
+ include_directories(${COREAUDIO})
+
+ find_library(AUDIOTOOLBOX AudioToolbox)
+ mark_as_advanced(AUDIOTOOLBOX)
+ include_directories(${AUDIOTOOLBOX})
+
+ find_library(AUDIOUNIT AudioUnit)
+ mark_as_advanced(AUDIOUNIT)
+ include_directories(${AUDIOUNIT})
+
find_library(APPKIT AppKit)
mark_as_advanced(APPKIT)
include_directories(${APPKIT})
set(libobs_PLATFORM_DEPS
${COCOA}
+ ${COREAUDIO}
+ ${AUDIOUNIT}
+ ${AUDIOTOOLBOX}
${APPKIT}
${IOKIT}
${CARBON})
util/platform-nix.c)
set(libobs_PLATFORM_HEADERS
util/threading-posix.h)
+ set(libobs_audio_monitoring_SOURCES
+ audio-monitoring/null/null-audio-monitoring.c
+ )
if(DBUS_FOUND)
set(libobs_PLATFORM_SOURCES ${libobs_PLATFORM_SOURCES}
${libobs_graphics_HEADERS}
${libobs_mediaio_HEADERS}
${libobs_util_HEADERS}
- ${libobs_libobs_HEADERS})
+ ${libobs_libobs_HEADERS}
+ ${libobs_audio_monitoring_SOURCES}
+ ${libobs_audio_monitoring_HEADERS}
+ )
source_group("callback\\Source Files" FILES ${libobs_callback_SOURCES})
source_group("callback\\Header Files" FILES ${libobs_callback_HEADERS})
source_group("media-io\\Header Files" FILES ${libobs_mediaio_HEADERS})
source_group("util\\Source Files" FILES ${libobs_util_SOURCES})
source_group("util\\Header Files" FILES ${libobs_util_HEADERS})
+source_group("audio-monitoring\\Source Files" FILES ${libobs_audio_monitoring_SOURCES})
+source_group("audio-monitoring\\Header Files" FILES ${libobs_audio_monitoring_HEADERS})
if(BUILD_CAPTIONS)
include_directories(${CMAKE_SOURCE_DIR}/deps/libcaption)
obs-studio-18.0.0.tar.xz/libobs/audio-monitoring
Added
+(directory)
obs-studio-18.0.0.tar.xz/libobs/audio-monitoring/null
Added
+(directory)
obs-studio-18.0.0.tar.xz/libobs/audio-monitoring/null/null-audio-monitoring.c
Added
+#include "../../obs-internal.h"
+
+void obs_enum_audio_monitoring_devices(obs_enum_audio_device_cb cb, void *data)
+{
+ UNUSED_PARAMETER(cb);
+ UNUSED_PARAMETER(data);
+}
+
+struct audio_monitor *audio_monitor_create(obs_source_t *source)
+{
+ UNUSED_PARAMETER(source);
+ return NULL;
+}
+
+void audio_monitor_reset(struct audio_monitor *monitor)
+{
+ UNUSED_PARAMETER(monitor);
+}
+
+void audio_monitor_destroy(struct audio_monitor *monitor)
+{
+ UNUSED_PARAMETER(monitor);
+}
obs-studio-18.0.0.tar.xz/libobs/audio-monitoring/osx
Added
+(directory)
obs-studio-18.0.0.tar.xz/libobs/audio-monitoring/osx/coreaudio-enum-devices.c
Added
+#include <CoreFoundation/CFString.h>
+#include <CoreAudio/CoreAudio.h>
+
+#include "../../obs-internal.h"
+#include "../../util/dstr.h"
+
+#include "mac-helpers.h"
+
+static inline bool cf_to_cstr(CFStringRef ref, char *buf, size_t size)
+{
+ if (!ref) return false;
+ return (bool)CFStringGetCString(ref, buf, size, kCFStringEncodingUTF8);
+}
+
+static void obs_enum_audio_monitoring_device(obs_enum_audio_device_cb cb,
+ void *data, AudioDeviceID id)
+{
+ UInt32 size = 0;
+ CFStringRef cf_name = NULL;
+ CFStringRef cf_uid = NULL;
+ char name[1024];
+ char uid[1024];
+ OSStatus stat;
+
+ AudioObjectPropertyAddress addr = {
+ kAudioDevicePropertyStreams,
+ kAudioDevicePropertyScopeInput,
+ kAudioObjectPropertyElementMaster
+ };
+
+ /* check to see if it's a mac input device */
+ AudioObjectGetPropertyDataSize(id, &addr, 0, NULL, &size);
+ if (!size)
+ return;
+
+ size = sizeof(CFStringRef);
+
+ addr.mSelector = kAudioDevicePropertyDeviceUID;
+ stat = AudioObjectGetPropertyData(id, &addr, 0, NULL, &size, &cf_uid);
+ if (!success(stat, "get audio device UID"))
+ return;
+
+ addr.mSelector = kAudioDevicePropertyDeviceNameCFString;
+ stat = AudioObjectGetPropertyData(id, &addr, 0, NULL, &size, &cf_name);
+ if (!success(stat, "get audio device name"))
+ goto fail;
+
+ if (!cf_to_cstr(cf_name, name, sizeof(name))) {
+ blog(LOG_WARNING, "%s: failed to convert name", __FUNCTION__);
+ goto fail;
+ }
+
+ if (!cf_to_cstr(cf_uid, uid, sizeof(uid))) {
+ blog(LOG_WARNING, "%s: failed to convert uid", __FUNCTION__);
+ goto fail;
+ }
+
+ cb(data, name, uid);
+
+fail:
+ if (cf_name)
+ CFRelease(cf_name);
+ if (cf_uid)
+ CFRelease(cf_uid);
+}
+
+void obs_enum_audio_monitoring_devices(obs_enum_audio_device_cb cb, void *data)
+{
+ AudioObjectPropertyAddress addr = {
+ kAudioHardwarePropertyDevices,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster
+ };
+
+ UInt32 size = 0;
+ UInt32 count;
+ OSStatus stat;
+ AudioDeviceID *ids;
+
+ stat = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr,
+ 0, NULL, &size);
+ if (!success(stat, "get data size"))
+ return;
+
+ ids = malloc(size);
+ count = size / sizeof(AudioDeviceID);
+
+ stat = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
+ 0, NULL, &size, ids);
+ if (success(stat, "get data")) {
+ for (UInt32 i = 0; i < count; i++)
+ obs_enum_audio_monitoring_device(cb, data, ids[i]);
+ }
+
+ free(ids);
+}
obs-studio-18.0.0.tar.xz/libobs/audio-monitoring/osx/coreaudio-output.c
Added
+#include <AudioUnit/AudioUnit.h>
+#include <AudioToolBox/AudioQueue.h>
+#include <CoreFoundation/CFString.h>
+#include <CoreAudio/CoreAudio.h>
+
+#include "../../media-io/audio-resampler.h"
+#include "../../util/circlebuf.h"
+#include "../../util/threading.h"
+#include "../../util/platform.h"
+#include "../../obs-internal.h"
+#include "../../util/darray.h"
+
+#include "mac-helpers.h"
+
+struct audio_monitor {
+ obs_source_t *source;
+ AudioQueueRef queue;
+ AudioQueueBufferRef buffers[3];
+
+ pthread_mutex_t mutex;
+ struct circlebuf empty_buffers;
+ struct circlebuf new_data;
+ audio_resampler_t *resampler;
+ size_t buffer_size;
+ size_t wait_size;
+ uint32_t channels;
+
+ volatile bool active;
+ bool paused;
+};
+
+static inline bool fill_buffer(struct audio_monitor *monitor)
+{
+ AudioQueueBufferRef buf;
+ OSStatus stat;
+
+ if (monitor->new_data.size < monitor->buffer_size) {
+ return false;
+ }
+
+ circlebuf_pop_front(&monitor->empty_buffers, &buf, sizeof(buf));
+ circlebuf_pop_front(&monitor->new_data, buf->mAudioData,
+ monitor->buffer_size);
+
+ buf->mAudioDataByteSize = monitor->buffer_size;
+
+ stat = AudioQueueEnqueueBuffer(monitor->queue, buf, 0, NULL);
+ if (!success(stat, "AudioQueueEnqueueBuffer")) {
+ blog(LOG_WARNING, "%s: %s", __FUNCTION__,
+ "Failed to enqueue buffer");
+ AudioQueueStop(monitor->queue, false);
+ }
+ return true;
+}
+
+static void on_audio_playback(void *param, obs_source_t *source,
+ const struct audio_data *audio_data, bool muted)
+{
+ struct audio_monitor *monitor = param;
+ float vol = source->user_volume;
+ uint32_t bytes;
+
+ UNUSED_PARAMETER(source);
+
+ if (!os_atomic_load_bool(&monitor->active)) {
+ return;
+ }
+
+ uint8_t *resample_data[MAX_AV_PLANES];
+ uint32_t resample_frames;
+ uint64_t ts_offset;
+ bool success;
+
+ success = audio_resampler_resample(monitor->resampler, resample_data,
+ &resample_frames, &ts_offset,
+ (const uint8_t *const *)audio_data->data,
+ (uint32_t)audio_data->frames);
+ if (!success) {
+ return;
+ }
+
+ bytes = sizeof(float) * monitor->channels * resample_frames;
+
+ if (muted) {
+ memset(resample_data[0], 0, bytes);
+ } else {
+ /* apply volume */
+ if (!close_float(vol, 1.0f, EPSILON)) {
+ register float *cur = (float*)resample_data[0];
+ register float *end = cur +
+ resample_frames * monitor->channels;
+
+ while (cur < end)
+ *(cur++) *= vol;
+ }
+ }
+
+ pthread_mutex_lock(&monitor->mutex);
+ circlebuf_push_back(&monitor->new_data, resample_data[0], bytes);
+
+ if (monitor->new_data.size >= monitor->wait_size) {
+ monitor->wait_size = 0;
+
+ while (monitor->empty_buffers.size > 0) {
+ if (!fill_buffer(monitor)) {
+ break;
+ }
+ }
+
+ if (monitor->paused) {
+ AudioQueueStart(monitor->queue, NULL);
+ monitor->paused = false;
+ }
+ }
+
+ pthread_mutex_unlock(&monitor->mutex);
+}
+
+static void buffer_audio(void *data, AudioQueueRef aq, AudioQueueBufferRef buf)
+{
+ struct audio_monitor *monitor = data;
+
+ pthread_mutex_lock(&monitor->mutex);
+ circlebuf_push_back(&monitor->empty_buffers, &buf, sizeof(buf));
+ while (monitor->empty_buffers.size > 0) {
+ if (!fill_buffer(monitor)) {
+ break;
+ }
+ }
+ if (monitor->empty_buffers.size == sizeof(buf) * 3) {
+ monitor->paused = true;
+ monitor->wait_size = monitor->buffer_size * 3;
+ AudioQueuePause(monitor->queue);
+ }
+ pthread_mutex_unlock(&monitor->mutex);
+
+ UNUSED_PARAMETER(aq);
+}
+
+static bool audio_monitor_init(struct audio_monitor *monitor)
+{
+ const struct audio_output_info *info = audio_output_get_info(
+ obs->audio.audio);
+ uint32_t channels = get_audio_channels(info->speakers);
+ OSStatus stat;
+
+ AudioStreamBasicDescription desc = {
+ .mSampleRate = (Float64)info->samples_per_sec,
+ .mFormatID = kAudioFormatLinearPCM,
+ .mFormatFlags = kAudioFormatFlagIsFloat |
+ kAudioFormatFlagIsPacked,
+ .mBytesPerPacket = sizeof(float) * channels,
+ .mFramesPerPacket = 1,
+ .mBytesPerFrame = sizeof(float) * channels,
+ .mChannelsPerFrame = channels,
+ .mBitsPerChannel = sizeof(float) * 8
+ };
+
+ monitor->channels = channels;
+ monitor->buffer_size =
+ channels * sizeof(float) * info->samples_per_sec / 100 * 3;
+ monitor->wait_size = monitor->buffer_size * 3;
+
+ pthread_mutex_init_value(&monitor->mutex);
+
+ stat = AudioQueueNewOutput(&desc, buffer_audio, monitor, NULL, NULL, 0,
+ &monitor->queue);
+ if (!success(stat, "AudioStreamBasicDescription")) {
+ return false;
+ }
+
+ const char *uid = obs->audio.monitoring_device_id;
+ if (!uid || !*uid) {
+ return false;
+ }
+
+ if (strcmp(uid, "default") != 0) {
+ CFStringRef cf_uid = CFStringCreateWithBytesNoCopy(NULL,
+ (const UInt8*)uid, strlen(uid),
+ kCFStringEncodingUTF8,
+ false, NULL);
+
+ stat = AudioQueueSetProperty(monitor->queue,
+ kAudioQueueProperty_CurrentDevice,
+ cf_uid, sizeof(cf_uid));
+ CFRelease(cf_uid);
+
+ if (!success(stat, "set current device")) {
+ return false;
+ }
+ }
+
+ stat = AudioQueueSetParameter(monitor->queue,
+ kAudioQueueParam_Volume, 1.0);
+ if (!success(stat, "set volume")) {
+ return false;
+ }
+
+ for (size_t i = 0; i < 3; i++) {
+ stat = AudioQueueAllocateBuffer(monitor->queue,
+ monitor->buffer_size, &monitor->buffers[i]);
+ if (!success(stat, "allocation of buffer")) {
+ return false;
+ }
+
+ circlebuf_push_back(&monitor->empty_buffers,
+ &monitor->buffers[i],
+ sizeof(monitor->buffers[i]));
+ }
+
+ if (pthread_mutex_init(&monitor->mutex, NULL) != 0) {
+ blog(LOG_WARNING, "%s: %s", __FUNCTION__,
+ "Failed to init mutex");
+ return false;
+ }
+
+ struct resample_info from = {
+ .samples_per_sec = info->samples_per_sec,
+ .speakers = info->speakers,
+ .format = AUDIO_FORMAT_FLOAT_PLANAR
+ };
+ struct resample_info to = {
+ .samples_per_sec = info->samples_per_sec,
+ .speakers = info->speakers,
+ .format = AUDIO_FORMAT_FLOAT
+ };
+
+ monitor->resampler = audio_resampler_create(&to, &from);
+ if (!monitor->resampler) {
+ blog(LOG_WARNING, "%s: %s", __FUNCTION__,
+ "Failed to create resampler");
+ return false;
+ }
+
+ stat = AudioQueueStart(monitor->queue, NULL);
+ if (!success(stat, "start")) {
+ return false;
+ }
+
+ monitor->active = true;
+ return true;
+}
+
+static void audio_monitor_free(struct audio_monitor *monitor)
+{
+ if (monitor->source) {
+ obs_source_remove_audio_capture_callback(
+ monitor->source, on_audio_playback, monitor);
+ }
+ if (monitor->active) {
+ AudioQueueStop(monitor->queue, true);
+ }
+ for (size_t i = 0; i < 3; i++) {
+ if (monitor->buffers[i]) {
+ AudioQueueFreeBuffer(monitor->queue,
+ monitor->buffers[i]);
+ }
+ }
+ if (monitor->queue) {
+ AudioQueueDispose(monitor->queue, true);
+ }
+
+ audio_resampler_destroy(monitor->resampler);
+ circlebuf_free(&monitor->empty_buffers);
+ circlebuf_free(&monitor->new_data);
+ pthread_mutex_destroy(&monitor->mutex);
+}
+
+static void audio_monitor_init_final(struct audio_monitor *monitor,
+ obs_source_t *source)
+{
+ monitor->source = source;
+ obs_source_add_audio_capture_callback(source, on_audio_playback,
+ monitor);
+}
+
+struct audio_monitor *audio_monitor_create(obs_source_t *source)
+{
+ struct audio_monitor *monitor = bzalloc(sizeof(*monitor));
+
+ if (!audio_monitor_init(monitor)) {
+ goto fail;
+ }
+
+ pthread_mutex_lock(&obs->audio.monitoring_mutex);
+ da_push_back(obs->audio.monitors, &monitor);
+ pthread_mutex_unlock(&obs->audio.monitoring_mutex);
+
+ audio_monitor_init_final(monitor, source);
+ return monitor;
+
+fail:
+ audio_monitor_free(monitor);
+ bfree(monitor);
+ return NULL;
+}
+
+void audio_monitor_reset(struct audio_monitor *monitor)
+{
+ bool success;
+
+ obs_source_t *source = monitor->source;
+ audio_monitor_free(monitor);
+ memset(monitor, 0, sizeof(*monitor));
+
+ success = audio_monitor_init(monitor);
+ if (success)
+ audio_monitor_init_final(monitor, source);
+}
+
+void audio_monitor_destroy(struct audio_monitor *monitor)
+{
+ if (monitor) {
+ audio_monitor_free(monitor);
+
+ pthread_mutex_lock(&obs->audio.monitoring_mutex);
+ da_erase_item(obs->audio.monitors, &monitor);
+ pthread_mutex_unlock(&obs->audio.monitoring_mutex);
+
+ bfree(monitor);
+ }
+}
obs-studio-18.0.0.tar.xz/libobs/audio-monitoring/osx/mac-helpers.h
Added
+#pragma once
+
+static bool success_(OSStatus stat, const char *func, const char *call)
+{
+ if (stat != noErr) {
+ blog(LOG_WARNING, "%s: %s failed: %d",
+ func, call, (int)stat);
+ return false;
+ }
+
+ return true;
+}
+
+#define success(stat, call) \
+ success_(stat, __FUNCTION__, call)
obs-studio-18.0.0.tar.xz/libobs/audio-monitoring/win32
Added
+(directory)
obs-studio-18.0.0.tar.xz/libobs/audio-monitoring/win32/wasapi-enum-devices.c
Added
+#include "../../obs-internal.h"
+
+#include "wasapi-output.h"
+
+#include <propsys.h>
+
+#ifdef __MINGW32__
+
+#ifdef DEFINE_PROPERTYKEY
+#undef DEFINE_PROPERTYKEY
+#endif
+#define DEFINE_PROPERTYKEY(id, a, b, c, d, e, f, g, h, i, j, k, l) \
+ const PROPERTYKEY id = { { a,b,c, { d,e,f,g,h,i,j,k, } }, l };
+DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, \
+ 0xa45c254e, 0xdf1c, 0x4efd, 0x80, \
+ 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);
+
+#else
+
+#include <functiondiscoverykeys_devpkey.h>
+
+#endif
+
+static bool get_device_info(obs_enum_audio_device_cb cb, void *data,
+ IMMDeviceCollection *collection, UINT idx)
+{
+ IPropertyStore *store = NULL;
+ IMMDevice *device = NULL;
+ PROPVARIANT name_var;
+ char utf8_name[512];
+ WCHAR *w_id = NULL;
+ char utf8_id[512];
+ bool cont = true;
+ HRESULT hr;
+
+ hr = collection->lpVtbl->Item(collection, idx, &device);
+ if (FAILED(hr)) {
+ goto fail;
+ }
+
+ hr = device->lpVtbl->GetId(device, &w_id);
+ if (FAILED(hr)) {
+ goto fail;
+ }
+
+ hr = device->lpVtbl->OpenPropertyStore(device, STGM_READ, &store);
+ if (FAILED(hr)) {
+ goto fail;
+ }
+
+ PropVariantInit(&name_var);
+ hr = store->lpVtbl->GetValue(store, &PKEY_Device_FriendlyName,
+ &name_var);
+ if (FAILED(hr)) {
+ goto fail;
+ }
+
+ os_wcs_to_utf8(w_id, 0, utf8_id, 512);
+ os_wcs_to_utf8(name_var.pwszVal, 0, utf8_name, 512);
+
+ cont = cb(data, utf8_name, utf8_id);
+
+fail:
+ safe_release(store);
+ safe_release(device);
+ if (w_id)
+ CoTaskMemFree(w_id);
+ return cont;
+}
+
+void obs_enum_audio_monitoring_devices(obs_enum_audio_device_cb cb,
+ void *data)
+{
+ IMMDeviceEnumerator *enumerator = NULL;
+ IMMDeviceCollection *collection = NULL;
+ UINT count;
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL,
+ &IID_IMMDeviceEnumerator, &enumerator);
+ if (FAILED(hr)) {
+ goto fail;
+ }
+
+ hr = enumerator->lpVtbl->EnumAudioEndpoints(enumerator, eRender,
+ DEVICE_STATE_ACTIVE, &collection);
+ if (FAILED(hr)) {
+ goto fail;
+ }
+
+ hr = collection->lpVtbl->GetCount(collection, &count);
+ if (FAILED(hr)) {
+ goto fail;
+ }
+
+ for (UINT i = 0; i < count; i++) {
+ if (!get_device_info(cb, data, collection, i)) {
+ break;
+ }
+ }
+
+fail:
+ safe_release(enumerator);
+ safe_release(collection);
+}
obs-studio-18.0.0.tar.xz/libobs/audio-monitoring/win32/wasapi-output.c
Added
+#include "../../media-io/audio-resampler.h"
+#include "../../util/circlebuf.h"
+#include "../../util/platform.h"
+#include "../../util/darray.h"
+#include "../../obs-internal.h"
+
+#include "wasapi-output.h"
+
+#define ACTUALLY_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID DECLSPEC_SELECTANY name \
+ = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
+
+ACTUALLY_DEFINE_GUID(CLSID_MMDeviceEnumerator,
+ 0xBCDE0395, 0xE52F, 0x467C,
+ 0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E);
+ACTUALLY_DEFINE_GUID(IID_IMMDeviceEnumerator,
+ 0xA95664D2, 0x9614, 0x4F35,
+ 0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6);
+ACTUALLY_DEFINE_GUID(IID_IAudioClient,
+ 0x1CB9AD4C, 0xDBFA, 0x4C32,
+ 0xB1, 0x78, 0xC2, 0xF5, 0x68, 0xA7, 0x03, 0xB2);
+ACTUALLY_DEFINE_GUID(IID_IAudioRenderClient,
+ 0xF294ACFC, 0x3146, 0x4483,
+ 0xA7, 0xBF, 0xAD, 0xDC, 0xA7, 0xC2, 0x60, 0xE2);
+
+struct audio_monitor {
+ obs_source_t *source;
+ IMMDevice *device;
+ IAudioClient *client;
+ IAudioRenderClient *render;
+
+ uint64_t last_recv_time;
+ uint64_t prev_video_ts;
+ uint64_t time_since_prev;
+ audio_resampler_t *resampler;
+ uint32_t sample_rate;
+ uint32_t channels;
+ bool source_has_video : 1;
+
+ int64_t lowest_audio_offset;
+ struct circlebuf delay_buffer;
+ uint32_t delay_size;
+
+ DARRAY(float) buf;
+ pthread_mutex_t playback_mutex;
+};
+
+/* #define DEBUG_AUDIO */
+
+static bool process_audio_delay(struct audio_monitor *monitor,
+ float **data, uint32_t *frames, uint64_t ts, uint32_t pad)
+{
+ obs_source_t *s = monitor->source;
+ uint64_t last_frame_ts = s->last_frame_ts;
+ uint64_t cur_time = os_gettime_ns();
+ uint64_t front_ts;
+ uint64_t cur_ts;
+ int64_t diff;
+ uint32_t blocksize = monitor->channels * sizeof(float);
+
+ /* cut off audio if long-since leftover audio in delay buffer */
+ if (cur_time - monitor->last_recv_time > 1000000000)
+ circlebuf_free(&monitor->delay_buffer);
+ monitor->last_recv_time = cur_time;
+
+ circlebuf_push_back(&monitor->delay_buffer, &ts, sizeof(ts));
+ circlebuf_push_back(&monitor->delay_buffer, frames, sizeof(*frames));
+ circlebuf_push_back(&monitor->delay_buffer, *data,
+ *frames * blocksize);
+
+ if (!monitor->prev_video_ts) {
+ monitor->prev_video_ts = last_frame_ts;
+
+ } else if (monitor->prev_video_ts == last_frame_ts) {
+ monitor->time_since_prev += (uint64_t)*frames *
+ 1000000000ULL / (uint64_t)monitor->sample_rate;
+ } else {
+ monitor->time_since_prev = 0;
+ }
+
+ while (monitor->delay_buffer.size != 0) {
+ size_t size;
+ bool bad_diff;
+
+ circlebuf_peek_front(&monitor->delay_buffer, &cur_ts,
+ sizeof(ts));
+ front_ts = cur_ts -
+ ((uint64_t)pad * 1000000000ULL /
+ (uint64_t)monitor->sample_rate);
+ diff = (int64_t)front_ts - (int64_t)last_frame_ts;
+ bad_diff = !last_frame_ts ||
+ llabs(diff) > 5000000000 ||
+ monitor->time_since_prev > 100000000ULL;
+
+ /* delay audio if rushing */
+ if (!bad_diff && diff > 75000000) {
+#ifdef DEBUG_AUDIO
+ blog(LOG_INFO, "audio rushing, cutting audio, "
+ "diff: %lld, delay buffer size: %lu, "
+ "v: %llu: a: %llu",
+ diff, (int)monitor->delay_buffer.size,
+ last_frame_ts, front_ts);
+#endif
+ return false;
+ }
+
+ circlebuf_pop_front(&monitor->delay_buffer, NULL, sizeof(ts));
+ circlebuf_pop_front(&monitor->delay_buffer, frames,
+ sizeof(*frames));
+
+ size = *frames * blocksize;
+ da_resize(monitor->buf, size);
+ circlebuf_pop_front(&monitor->delay_buffer,
+ monitor->buf.array, size);
+
+ /* cut audio if dragging */
+ if (!bad_diff && diff < -75000000 && monitor->delay_buffer.size > 0) {
+#ifdef DEBUG_AUDIO
+ blog(LOG_INFO, "audio dragging, cutting audio, "
+ "diff: %lld, delay buffer size: %lu, "
+ "v: %llu: a: %llu",
+ diff, (int)monitor->delay_buffer.size,
+ last_frame_ts, front_ts);
+#endif
+ continue;
+ }
+
+ *data = monitor->buf.array;
+ return true;
+ }
+
+ return false;
+}
+
+static void on_audio_playback(void *param, obs_source_t *source,
+ const struct audio_data *audio_data, bool muted)
+{
+ struct audio_monitor *monitor = param;
+ IAudioRenderClient *render = monitor->render;
+ uint8_t *resample_data[MAX_AV_PLANES];
+ float vol = source->user_volume;
+ uint32_t resample_frames;
+ uint64_t ts_offset;
+ bool success;
+ BYTE *output;
+
+ if (pthread_mutex_trylock(&monitor->playback_mutex) != 0) {
+ return;
+ }
+ if (os_atomic_load_long(&source->activate_refs) == 0) {
+ goto unlock;
+ }
+
+ success = audio_resampler_resample(monitor->resampler, resample_data,
+ &resample_frames, &ts_offset,
+ (const uint8_t *const *)audio_data->data,
+ (uint32_t)audio_data->frames);
+ if (!success) {
+ goto unlock;
+ }
+
+ UINT32 pad = 0;
+ monitor->client->lpVtbl->GetCurrentPadding(monitor->client, &pad);
+
+ if (monitor->source_has_video) {
+ uint64_t ts = audio_data->timestamp - ts_offset;
+
+ if (!process_audio_delay(monitor, (float**)(&resample_data[0]),
+ &resample_frames, ts, pad)) {
+ goto unlock;
+ }
+ }
+
+ HRESULT hr = render->lpVtbl->GetBuffer(render, resample_frames,
+ &output);
+ if (FAILED(hr)) {
+ goto unlock;
+ }
+
+ if (!muted) {
+ /* apply volume */
+ if (!close_float(vol, 1.0f, EPSILON)) {
+ register float *cur = (float*)resample_data[0];
+ register float *end = cur +
+ resample_frames * monitor->channels;
+
+ while (cur < end)
+ *(cur++) *= vol;
+ }
+ memcpy(output, resample_data[0],
+ resample_frames * monitor->channels *
+ sizeof(float));
+ }
+
+ render->lpVtbl->ReleaseBuffer(render, resample_frames,
+ muted ? AUDCLNT_BUFFERFLAGS_SILENT : 0);
+
+unlock:
+ pthread_mutex_unlock(&monitor->playback_mutex);
+}
+
+static inline void audio_monitor_free(struct audio_monitor *monitor)
+{
+ if (monitor->source) {
+ obs_source_remove_audio_capture_callback(
+ monitor->source, on_audio_playback, monitor);
+ }
+
+ if (monitor->client)
+ monitor->client->lpVtbl->Stop(monitor->client);
+
+ safe_release(monitor->device);
+ safe_release(monitor->client);
+ safe_release(monitor->render);
+ audio_resampler_destroy(monitor->resampler);
+ circlebuf_free(&monitor->delay_buffer);
+ da_free(monitor->buf);
+}
+
+static enum speaker_layout convert_speaker_layout(DWORD layout, WORD channels)
+{
+ switch (layout) {
+ case KSAUDIO_SPEAKER_QUAD: return SPEAKERS_QUAD;
+ case KSAUDIO_SPEAKER_2POINT1: return SPEAKERS_2POINT1;
+ case KSAUDIO_SPEAKER_4POINT1: return SPEAKERS_4POINT1;
+ case KSAUDIO_SPEAKER_SURROUND: return SPEAKERS_SURROUND;
+ case KSAUDIO_SPEAKER_5POINT1: return SPEAKERS_5POINT1;
+ case KSAUDIO_SPEAKER_5POINT1_SURROUND: return SPEAKERS_5POINT1_SURROUND;
+ case KSAUDIO_SPEAKER_7POINT1: return SPEAKERS_7POINT1;
+ case KSAUDIO_SPEAKER_7POINT1_SURROUND: return SPEAKERS_7POINT1_SURROUND;
+ }
+
+ return (enum speaker_layout)channels;
+}
+
+static bool audio_monitor_init(struct audio_monitor *monitor)
+{
+ IMMDeviceEnumerator *immde = NULL;
+ WAVEFORMATEX *wfex = NULL;
+ bool success = false;
+ UINT32 frames;
+ HRESULT hr;
+
+ const char *id = obs->audio.monitoring_device_id;
+ if (!id) {
+ return false;
+ }
+
+ pthread_mutex_init_value(&monitor->playback_mutex);
+
+ /* ------------------------------------------ *
+ * Init device */
+
+ hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL,
+ &IID_IMMDeviceEnumerator, (void**)&immde);
+ if (FAILED(hr)) {
+ return false;
+ }
+
+ if (strcmp(id, "default") == 0) {
+ hr = immde->lpVtbl->GetDefaultAudioEndpoint(immde,
+ eRender, eConsole, &monitor->device);
+ } else {
+ wchar_t w_id[512];
+ os_utf8_to_wcs(id, 0, w_id, 512);
+
+ hr = immde->lpVtbl->GetDevice(immde, w_id, &monitor->device);
+ }
+
+ if (FAILED(hr)) {
+ goto fail;
+ }
+
+ /* ------------------------------------------ *
+ * Init client */
+
+ hr = monitor->device->lpVtbl->Activate(monitor->device,
+ &IID_IAudioClient, CLSCTX_ALL, NULL,
+ (void**)&monitor->client);
+ if (FAILED(hr)) {
+ goto fail;
+ }
+
+ hr = monitor->client->lpVtbl->GetMixFormat(monitor->client, &wfex);
+ if (FAILED(hr)) {
+ goto fail;
+ }
+
+ hr = monitor->client->lpVtbl->Initialize(monitor->client,
+ AUDCLNT_SHAREMODE_SHARED, 0,
+ 10000000, 0, wfex, NULL);
+ if (FAILED(hr)) {
+ goto fail;
+ }
+
+ /* ------------------------------------------ *
+ * Init resampler */
+
+ const struct audio_output_info *info = audio_output_get_info(
+ obs->audio.audio);
+ WAVEFORMATEXTENSIBLE *ext = (WAVEFORMATEXTENSIBLE*)wfex;
+ struct resample_info from;
+ struct resample_info to;
+
+ from.samples_per_sec = info->samples_per_sec;
+ from.speakers = info->speakers;
+ from.format = AUDIO_FORMAT_FLOAT_PLANAR;
+
+ to.samples_per_sec = (uint32_t)wfex->nSamplesPerSec;
+ to.speakers = convert_speaker_layout(ext->dwChannelMask,
+ wfex->nChannels);
+ to.format = AUDIO_FORMAT_FLOAT;
+
+ monitor->sample_rate = (uint32_t)wfex->nSamplesPerSec;
+ monitor->channels = wfex->nChannels;
+ monitor->resampler = audio_resampler_create(&to, &from);
+ if (!monitor->resampler) {
+ goto fail;
+ }
+
+ /* ------------------------------------------ *
+ * Init client */
+
+ hr = monitor->client->lpVtbl->GetBufferSize(monitor->client, &frames);
+ if (FAILED(hr)) {
+ goto fail;
+ }
+
+ hr = monitor->client->lpVtbl->GetService(monitor->client,
+ &IID_IAudioRenderClient, (void**)&monitor->render);
+ if (FAILED(hr)) {
+ goto fail;
+ }
+
+ if (pthread_mutex_init(&monitor->playback_mutex, NULL) != 0) {
+ goto fail;
+ }
+
+ hr = monitor->client->lpVtbl->Start(monitor->client);
+ if (FAILED(hr)) {
+ goto fail;
+ }
+
+ success = true;
+
+fail:
+ safe_release(immde);
+ if (wfex)
+ CoTaskMemFree(wfex);
+ return success;
+}
+
+static void audio_monitor_init_final(struct audio_monitor *monitor,
+ obs_source_t *source)
+{
+ monitor->source = source;
+ monitor->source_has_video =
+ (source->info.output_flags & OBS_SOURCE_VIDEO) != 0;
+ obs_source_add_audio_capture_callback(source, on_audio_playback,
+ monitor);
+}
+
+struct audio_monitor *audio_monitor_create(obs_source_t *source)
+{
+ struct audio_monitor monitor = {0};
+ struct audio_monitor *out;
+
+ if (!audio_monitor_init(&monitor)) {
+ goto fail;
+ }
+
+ out = bmemdup(&monitor, sizeof(monitor));
+
+ pthread_mutex_lock(&obs->audio.monitoring_mutex);
+ da_push_back(obs->audio.monitors, &out);
+ pthread_mutex_unlock(&obs->audio.monitoring_mutex);
+
+ audio_monitor_init_final(out, source);
+ return out;
+
+fail:
+ audio_monitor_free(&monitor);
+ return NULL;
+}
+
+void audio_monitor_reset(struct audio_monitor *monitor)
+{
+ struct audio_monitor new_monitor = {0};
+ bool success;
+
+ pthread_mutex_lock(&monitor->playback_mutex);
+ success = audio_monitor_init(&new_monitor);
+ pthread_mutex_unlock(&monitor->playback_mutex);
+
+ if (success) {
+ obs_source_t *source = monitor->source;
+ audio_monitor_free(monitor);
+ *monitor = new_monitor;
+ audio_monitor_init_final(monitor, source);
+ } else {
+ audio_monitor_free(&new_monitor);
+ }
+}
+
+void audio_monitor_destroy(struct audio_monitor *monitor)
+{
+ if (monitor) {
+ audio_monitor_free(monitor);
+
+ pthread_mutex_lock(&obs->audio.monitoring_mutex);
+ da_erase_item(obs->audio.monitors, &monitor);
+ pthread_mutex_unlock(&obs->audio.monitoring_mutex);
+
+ bfree(monitor);
+ }
+}
obs-studio-18.0.0.tar.xz/libobs/audio-monitoring/win32/wasapi-output.h
Added
+#include <windows.h>
+#include <mmdeviceapi.h>
+#include <audioclient.h>
+
+#define KSAUDIO_SPEAKER_4POINT1 (KSAUDIO_SPEAKER_QUAD|SPEAKER_LOW_FREQUENCY)
+#define KSAUDIO_SPEAKER_2POINT1 (KSAUDIO_SPEAKER_STEREO|SPEAKER_LOW_FREQUENCY)
+
+#define safe_release(ptr) \
+ do { \
+ if (ptr) { \
+ ptr->lpVtbl->Release(ptr); \
+ } \
+ } while (false)
obs-studio-17.0.2.tar.xz/libobs/callback/decl.h -> obs-studio-18.0.0.tar.xz/libobs/callback/decl.h
Changed
static inline void decl_param_free(struct decl_param *param)
{
- if (param)
+ if (param->name)
bfree(param->name);
memset(param, 0, sizeof(struct decl_param));
}
obs-studio-17.0.2.tar.xz/libobs/data/bicubic_scale.effect -> obs-studio-18.0.0.tar.xz/libobs/data/bicubic_scale.effect
Changed
uniform float3 color_range_min = {0.0, 0.0, 0.0};
uniform float3 color_range_max = {1.0, 1.0, 1.0};
uniform float2 base_dimension_i;
+uniform float undistort_factor = 1.0;
sampler_state textureSampler {
Filter = Linear;
weight(x + 1.0));
}
-float4 pixel(float xpos, float ypos)
+float AspectUndistortX(float x, float a)
{
- return image.Sample(textureSampler, float2(xpos, ypos));
+ // The higher the power, the longer the linear part will be.
+ return (1.0 - a) * (x * x * x * x * x) + a * x;
}
-float4 get_line(float ypos, float4 xpos, float4 linetaps)
+float AspectUndistortU(float u)
+{
+ // Normalize texture coord to -1.0 to 1.0 range, and back.
+ return AspectUndistortX((u - 0.5) * 2.0, undistort_factor) * 0.5 + 0.5;
+}
+
+float2 pixel_coord(float xpos, float ypos)
+{
+ return float2(AspectUndistortU(xpos), ypos);
+}
+
+float4 pixel(float xpos, float ypos, bool undistort)
+{
+ if (undistort)
+ return image.Sample(textureSampler, pixel_coord(xpos, ypos));
+ else
+ return image.Sample(textureSampler, float2(xpos, ypos));
+}
+
+float4 get_line(float ypos, float4 xpos, float4 linetaps, bool undistort)
{
return
- pixel(xpos.r, ypos) * linetaps.r +
- pixel(xpos.g, ypos) * linetaps.g +
- pixel(xpos.b, ypos) * linetaps.b +
- pixel(xpos.a, ypos) * linetaps.a;
+ pixel(xpos.r, ypos, undistort) * linetaps.r +
+ pixel(xpos.g, ypos, undistort) * linetaps.g +
+ pixel(xpos.b, ypos, undistort) * linetaps.b +
+ pixel(xpos.a, ypos, undistort) * linetaps.a;
}
-float4 DrawBicubic(VertData v_in)
+float4 DrawBicubic(VertData v_in, bool undistort)
{
float2 stepxy = base_dimension_i;
float2 pos = v_in.uv + stepxy * 0.5;
);
return
- get_line(xystart.y , xpos, rowtaps) * coltaps.r +
- get_line(xystart.y + stepxy.y , xpos, rowtaps) * coltaps.g +
- get_line(xystart.y + stepxy.y * 2.0, xpos, rowtaps) * coltaps.b +
- get_line(xystart.y + stepxy.y * 3.0, xpos, rowtaps) * coltaps.a;
+ get_line(xystart.y , xpos, rowtaps, undistort) * coltaps.r +
+ get_line(xystart.y + stepxy.y , xpos, rowtaps, undistort) * coltaps.g +
+ get_line(xystart.y + stepxy.y * 2.0, xpos, rowtaps, undistort) * coltaps.b +
+ get_line(xystart.y + stepxy.y * 3.0, xpos, rowtaps, undistort) * coltaps.a;
}
-float4 PSDrawBicubicRGBA(VertData v_in) : TARGET
+float4 PSDrawBicubicRGBA(VertData v_in, bool undistort) : TARGET
{
- return DrawBicubic(v_in);
+ return DrawBicubic(v_in, undistort);
}
float4 PSDrawBicubicMatrix(VertData v_in) : TARGET
{
- float4 rgba = DrawBicubic(v_in);
+ float4 rgba = DrawBicubic(v_in, false);
float4 yuv;
yuv.xyz = clamp(rgba.xyz, color_range_min, color_range_max);
pass
{
vertex_shader = VSDefault(v_in);
- pixel_shader = PSDrawBicubicRGBA(v_in);
+ pixel_shader = PSDrawBicubicRGBA(v_in, false);
+ }
+}
+
+technique DrawUndistort
+{
+ pass
+ {
+ vertex_shader = VSDefault(v_in);
+ pixel_shader = PSDrawBicubicRGBA(v_in, true);
}
}
obs-studio-17.0.2.tar.xz/libobs/data/lanczos_scale.effect -> obs-studio-18.0.0.tar.xz/libobs/data/lanczos_scale.effect
Changed
uniform float3 color_range_min = {0.0, 0.0, 0.0};
uniform float3 color_range_max = {1.0, 1.0, 1.0};
uniform float2 base_dimension_i;
+uniform float undistort_factor = 1.0;
sampler_state textureSampler
{
weight((x * 2.0 + 2.0 * 2.0 - 3.0) * scale, 3.0));
}
-float4 pixel(float xpos, float ypos)
+float AspectUndistortX(float x, float a)
{
- return image.Sample(textureSampler, float2(xpos, ypos));
+ // The higher the power, the longer the linear part will be.
+ return (1.0 - a) * (x * x * x * x * x) + a * x;
+}
+
+float AspectUndistortU(float u)
+{
+ // Normalize texture coord to -1.0 to 1.0 range, and back.
+ return AspectUndistortX((u - 0.5) * 2.0, undistort_factor) * 0.5 + 0.5;
+}
+
+float2 pixel_coord(float xpos, float ypos)
+{
+ return float2(AspectUndistortU(xpos), ypos);
+}
+
+float4 pixel(float xpos, float ypos, bool undistort)
+{
+ if (undistort)
+ return image.Sample(textureSampler, pixel_coord(xpos, ypos));
+ else
+ return image.Sample(textureSampler, float2(xpos, ypos));
}
float4 get_line(float ypos, float3 xpos1, float3 xpos2, float3 rowtap1,
- float3 rowtap2)
+ float3 rowtap2, bool undistort)
{
return
- pixel(xpos1.r, ypos) * rowtap1.r +
- pixel(xpos1.g, ypos) * rowtap2.r +
- pixel(xpos1.b, ypos) * rowtap1.g +
- pixel(xpos2.r, ypos) * rowtap2.g +
- pixel(xpos2.g, ypos) * rowtap1.b +
- pixel(xpos2.b, ypos) * rowtap2.b;
+ pixel(xpos1.r, ypos, undistort) * rowtap1.r +
+ pixel(xpos1.g, ypos, undistort) * rowtap2.r +
+ pixel(xpos1.b, ypos, undistort) * rowtap1.g +
+ pixel(xpos2.r, ypos, undistort) * rowtap2.g +
+ pixel(xpos2.g, ypos, undistort) * rowtap1.b +
+ pixel(xpos2.b, ypos, undistort) * rowtap2.b;
}
-float4 DrawLanczos(FragData v_in)
+float4 DrawLanczos(FragData v_in, bool undistort)
{
float2 stepxy = base_dimension_i;
float2 pos = v_in.uv + stepxy * 0.5;
float3 xpos2 = float3(xystart.x + stepxy.x * 3.0, xystart.x + stepxy.x * 4.0, xystart.x + stepxy.x * 5.0);
return
- get_line(xystart.y , xpos1, xpos2, rowtap1, rowtap2) * coltap1.r +
- get_line(xystart.y + stepxy.y , xpos1, xpos2, rowtap1, rowtap2) * coltap2.r +
- get_line(xystart.y + stepxy.y * 2.0, xpos1, xpos2, rowtap1, rowtap2) * coltap1.g +
- get_line(xystart.y + stepxy.y * 3.0, xpos1, xpos2, rowtap1, rowtap2) * coltap2.g +
- get_line(xystart.y + stepxy.y * 4.0, xpos1, xpos2, rowtap1, rowtap2) * coltap1.b +
- get_line(xystart.y + stepxy.y * 5.0, xpos1, xpos2, rowtap1, rowtap2) * coltap2.b;
+ get_line(xystart.y , xpos1, xpos2, rowtap1, rowtap2, undistort) * coltap1.r +
+ get_line(xystart.y + stepxy.y , xpos1, xpos2, rowtap1, rowtap2, undistort) * coltap2.r +
+ get_line(xystart.y + stepxy.y * 2.0, xpos1, xpos2, rowtap1, rowtap2, undistort) * coltap1.g +
+ get_line(xystart.y + stepxy.y * 3.0, xpos1, xpos2, rowtap1, rowtap2, undistort) * coltap2.g +
+ get_line(xystart.y + stepxy.y * 4.0, xpos1, xpos2, rowtap1, rowtap2, undistort) * coltap1.b +
+ get_line(xystart.y + stepxy.y * 5.0, xpos1, xpos2, rowtap1, rowtap2, undistort) * coltap2.b;
}
-float4 PSDrawLanczosRGBA(FragData v_in) : TARGET
+float4 PSDrawLanczosRGBA(FragData v_in, bool undistort) : TARGET
{
- return DrawLanczos(v_in);
+ return DrawLanczos(v_in, undistort);
}
float4 PSDrawLanczosMatrix(FragData v_in) : TARGET
{
- float4 rgba = DrawLanczos(v_in);
+ float4 rgba = DrawLanczos(v_in, false);
float4 yuv;
yuv.xyz = clamp(rgba.xyz, color_range_min, color_range_max);
pass
{
vertex_shader = VSDefault(v_in);
- pixel_shader = PSDrawLanczosRGBA(v_in);
+ pixel_shader = PSDrawLanczosRGBA(v_in, false);
+ }
+}
+
+technique DrawUndistort
+{
+ pass
+ {
+ vertex_shader = VSDefault(v_in);
+ pixel_shader = PSDrawLanczosRGBA(v_in, true);
}
}
obs-studio-17.0.2.tar.xz/libobs/obs-config.h -> obs-studio-18.0.0.tar.xz/libobs/obs-config.h
Changed
/*
* Increment if major breaking API changes
*/
-#define LIBOBS_API_MAJOR_VER 17
+#define LIBOBS_API_MAJOR_VER 18
/*
* Increment if backward-compatible additions
*
* Reset to zero each major or minor version
*/
-#define LIBOBS_API_PATCH_VER 2
+#define LIBOBS_API_PATCH_VER 0
#define MAKE_SEMANTIC_VERSION(major, minor, patch) \
((major << 24) | \
obs-studio-17.0.2.tar.xz/libobs/obs-display.c -> obs-studio-18.0.0.tar.xz/libobs/obs-display.c
Changed
{
struct vec4 clear_color;
- gs_load_swapchain(display ? display->swap : NULL);
+ gs_load_swapchain(display->swap);
if (size_changed)
gs_resize(cx, cy);
obs-studio-17.0.2.tar.xz/libobs/obs-internal.h -> obs-studio-18.0.0.tar.xz/libobs/obs-internal.h
Changed
gs_effect_t *deinterlace_yadif_2x_effect;
};
+struct audio_monitor;
+
struct obs_core_audio {
- /* TODO: sound output subsystem */
audio_t *audio;
DARRAY(struct obs_source*) render_order;
int total_buffering_ticks;
float user_volume;
+
+ pthread_mutex_t monitoring_mutex;
+ DARRAY(struct audio_monitor*) monitors;
+ char *monitoring_device_name;
+ char *monitoring_device_id;
};
/* user sources, output channels, and displays */
volatile bool timing_set;
volatile uint64_t timing_adjust;
uint64_t resample_offset;
+ uint64_t last_audio_ts;
uint64_t next_audio_ts_min;
uint64_t next_audio_sys_ts_min;
uint64_t last_frame_ts;
enum obs_transition_mode transition_mode;
enum obs_transition_scale_type transition_scale_type;
struct matrix4 transition_matrices[2];
+
+ struct audio_monitor *monitor;
+ enum obs_monitoring_type monitoring_type;
};
extern const struct obs_source_info *get_source_info(const char *id);
extern void obs_transition_save(obs_source_t *source, obs_data_t *data);
extern void obs_transition_load(obs_source_t *source, obs_data_t *data);
+struct audio_monitor *audio_monitor_create(obs_source_t *source);
+void audio_monitor_reset(struct audio_monitor *monitor);
+extern void audio_monitor_destroy(struct audio_monitor *monitor);
+
extern void obs_source_destroy(struct obs_source *source);
enum view_type {
obs-studio-17.0.2.tar.xz/libobs/obs-output.c -> obs-studio-18.0.0.tar.xz/libobs/obs-output.c
Changed
pthread_mutex_unlock(&output->caption_mutex);
}
#endif
+
+float obs_output_get_congestion(obs_output_t *output)
+{
+ if (!obs_output_valid(output, "obs_output_get_congestion"))
+ return 0;
+
+ if (output->info.get_congestion) {
+ float val = output->info.get_congestion(output->context.data);
+ if (val < 0.0f) val = 0.0f;
+ else if (val > 1.0f) val = 1.0f;
+ return val;
+ }
+ return 0;
+}
obs-studio-17.0.2.tar.xz/libobs/obs-output.h -> obs-studio-18.0.0.tar.xz/libobs/obs-output.h
Changed
void *type_data;
void (*free_type_data)(void *type_data);
+
+ float (*get_congestion)(void *data);
};
EXPORT void obs_register_output_s(const struct obs_output_info *info,
obs-studio-17.0.2.tar.xz/libobs/obs-properties.c -> obs-studio-18.0.0.tar.xz/libobs/obs-properties.c
Changed
enum obs_combo_format format)
{
struct list_data *data = get_list_data(p);
- return (data->format == format) ? data : NULL;
+ return (data && data->format == format) ? data : NULL;
}
/* ------------------------------------------------------------------------- */
obs-studio-17.0.2.tar.xz/libobs/obs-scene.c -> obs-studio-18.0.0.tar.xz/libobs/obs-scene.c
Changed
uint64_t source_ts =
obs_source_get_audio_timestamp(item->source);
- if (!timestamp || source_ts < timestamp)
+ if (source_ts && (!timestamp || source_ts < timestamp))
timestamp = source_ts;
}
}
source_ts = obs_source_get_audio_timestamp(item->source);
+ if (!source_ts) {
+ item = item->next;
+ continue;
+ }
+
pos = (size_t)ns_to_audio_frames(sample_rate,
source_ts - timestamp);
count = AUDIO_OUTPUT_FRAMES - pos;
scene = item->parent;
- if (scene)
- full_lock(scene);
+ full_lock(scene);
if (item->removed) {
if (scene)
obs-studio-17.0.2.tar.xz/libobs/obs-source-deinterlace.c -> obs-studio-18.0.0.tar.xz/libobs/obs-source-deinterlace.c
Changed
if (source->async_frames.num == 2)
source->async_frames.array[0]->prev_frame = true;
source->deinterlace_offset = 0;
+ source->last_frame_ts = next_frame->timestamp;
return true;
}
obs-studio-17.0.2.tar.xz/libobs/obs-source.c -> obs-studio-18.0.0.tar.xz/libobs/obs-source.c
Changed
source->context.data = NULL;
}
+ audio_monitor_destroy(source->monitor);
+
obs_hotkey_unregister(source->push_to_talk_key);
obs_hotkey_unregister(source->push_to_mute_key);
obs_hotkey_pair_unregister(source->mute_unmute_key);
}
static void source_signal_audio_data(obs_source_t *source,
- struct audio_data *in, bool muted)
+ const struct audio_data *in, bool muted)
{
pthread_mutex_lock(&source->audio_cb_mutex);
in.timestamp = source->next_audio_ts_min;
}
+ source->last_audio_ts = in.timestamp;
source->next_audio_ts_min = in.timestamp +
conv_frames_to_time(sample_rate, in.frames);
source->last_sync_offset = sync_offset;
}
- if (push_back && source->audio_ts)
- source_output_audio_push_back(source, &in);
- else
- source_output_audio_place(source, &in);
+ if (source->monitoring_type != OBS_MONITORING_TYPE_MONITOR_ONLY) {
+ if (push_back && source->audio_ts)
+ source_output_audio_push_back(source, &in);
+ else
+ source_output_audio_place(source, &in);
+ }
pthread_mutex_unlock(&source->audio_buf_mutex);
- source_signal_audio_data(source, &in, source_muted(source, os_time));
+ source_signal_audio_data(source, data, source_muted(source, os_time));
}
enum convert_type {
signal_handler_signal(source->context.signals, "filter_add", &cd);
- if (source && filter)
- blog(LOG_DEBUG, "- filter '%s' (%s) added to source '%s'",
- filter->context.name, filter->info.id,
- source->context.name);
+ blog(LOG_DEBUG, "- filter '%s' (%s) added to source '%s'",
+ filter->context.name, filter->info.id,
+ source->context.name);
}
static bool obs_source_filter_remove_refless(obs_source_t *source,
signal_handler_signal(source->context.signals, "filter_remove", &cd);
- if (source && filter)
- blog(LOG_DEBUG, "- filter '%s' (%s) removed from source '%s'",
- filter->context.name, filter->info.id,
- source->context.name);
+ blog(LOG_DEBUG, "- filter '%s' (%s) removed from source '%s'",
+ filter->context.name, filter->info.id,
+ source->context.name);
if (filter->info.filter_remove)
filter->info.filter_remove(filter->context.data,
next_frame = source->async_frames.array[0];
}
+ source->last_frame_ts = next_frame->timestamp;
return true;
}
da_erase_item(source->audio_cb_list, &info);
pthread_mutex_unlock(&source->audio_cb_mutex);
}
+
+void obs_source_set_monitoring_type(obs_source_t *source,
+ enum obs_monitoring_type type)
+{
+ bool was_on;
+ bool now_on;
+
+ if (!obs_source_valid(source, "obs_source_set_monitoring_type"))
+ return;
+ if (source->info.output_flags & OBS_SOURCE_DO_NOT_MONITOR)
+ return;
+ if (source->monitoring_type == type)
+ return;
+
+ was_on = source->monitoring_type != OBS_MONITORING_TYPE_NONE;
+ now_on = type != OBS_MONITORING_TYPE_NONE;
+
+ if (was_on != now_on) {
+ if (!was_on) {
+ source->monitor = audio_monitor_create(source);
+ } else {
+ audio_monitor_destroy(source->monitor);
+ source->monitor = NULL;
+ }
+ }
+
+ source->monitoring_type = type;
+}
+
+enum obs_monitoring_type obs_source_get_monitoring_type(
+ const obs_source_t *source)
+{
+ return obs_source_valid(source, "obs_source_get_monitoring_type") ?
+ source->monitoring_type : OBS_MONITORING_TYPE_NONE;
+}
obs-studio-17.0.2.tar.xz/libobs/obs-source.h -> obs-studio-18.0.0.tar.xz/libobs/obs-source.h
Changed
*/
#define OBS_SOURCE_DEPRECATED (1<<8)
+/**
+ * Source cannot have its audio monitored
+ *
+ * Specifies that this source may cause a feedback loop if audio is monitored.
+ * This is used primarily with desktop audio capture sources.
+ */
+#define OBS_SOURCE_DO_NOT_MONITOR (1<<9)
+
/** @} */
typedef void (*obs_source_enum_proc_t)(obs_source_t *parent,
obs-studio-17.0.2.tar.xz/libobs/obs-windows.c -> obs-studio-18.0.0.tar.xz/libobs/obs-windows.c
Changed
static void log_available_memory(void)
{
- MEMORYSTATUS ms;
- GlobalMemoryStatus(&ms);
+ MEMORYSTATUSEX ms;
+ ms.dwLength = sizeof(ms);
+
+ GlobalMemoryStatusEx(&ms);
#ifdef _WIN64
const char *note = "";
#else
- const char *note = " (NOTE: 2 or 4 gigs max is normal for 32bit programs)";
+ const char *note = " (NOTE: 32bit programs cannot use more than 3gb)";
#endif
blog(LOG_INFO, "Physical Memory: %luMB Total, %luMB Free%s",
- (DWORD)(ms.dwTotalPhys / 1048576),
- (DWORD)(ms.dwAvailPhys / 1048576),
+ (DWORD)(ms.ullTotalPhys / 1048576),
+ (DWORD)(ms.ullAvailPhys / 1048576),
note);
}
obs-studio-17.0.2.tar.xz/libobs/obs.c -> obs-studio-18.0.0.tar.xz/libobs/obs.c
Changed
struct obs_core_audio *audio = &obs->audio;
int errorcode;
- /* TODO: sound subsystem */
+ pthread_mutexattr_t attr;
+
+ pthread_mutex_init_value(&audio->monitoring_mutex);
+
+ if (pthread_mutexattr_init(&attr) != 0)
+ return false;
+ if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0)
+ return false;
+ if (pthread_mutex_init(&audio->monitoring_mutex, &attr) != 0)
+ return false;
audio->user_volume = 1.0f;
+ audio->monitoring_device_name = bstrdup("Default");
+ audio->monitoring_device_id = bstrdup("default");
+
errorcode = audio_output_open(&audio->audio, ai);
if (errorcode == AUDIO_OUTPUT_SUCCESS)
return true;
da_free(audio->render_order);
da_free(audio->root_nodes);
+ da_free(audio->monitors);
+ bfree(audio->monitoring_device_name);
+ bfree(audio->monitoring_device_id);
+ pthread_mutex_destroy(&audio->monitoring_mutex);
+
memset(audio, 0, sizeof(struct obs_core_audio));
}
{
obs = bzalloc(sizeof(struct obs_core));
+ pthread_mutex_init_value(&obs->audio.monitoring_mutex);
+
obs->name_store_owned = !store;
obs->name_store = store ? store : profiler_name_store_create();
if (!obs->name_store) {
stop_video();
obs_free_video();
- if (!ovi) {
- obs_free_graphics();
- return OBS_VIDEO_SUCCESS;
- }
-
/* align to multiple-of-two and SSE alignment sizes */
ovi->output_width &= 0xFFFFFFFC;
ovi->output_height &= 0xFFFFFFFE;
uint32_t mixers;
int di_order;
int di_mode;
+ int monitoring_type;
source = obs_source_create(id, name, settings, hotkeys);
obs_source_set_deinterlace_field_order(source,
(enum obs_deinterlace_field_order)di_order);
+ monitoring_type = (int)obs_data_get_int(source_data, "monitoring_type");
+ obs_source_set_monitoring_type(source,
+ (enum obs_monitoring_type)monitoring_type);
+
if (filters) {
size_t count = obs_data_array_count(filters);
uint64_t ptm_delay = obs_source_get_push_to_mute_delay(source);
bool push_to_talk= obs_source_push_to_talk_enabled(source);
uint64_t ptt_delay = obs_source_get_push_to_talk_delay(source);
+ int m_type = (int)obs_source_get_monitoring_type(source);
int di_mode = (int)obs_source_get_deinterlace_mode(source);
int di_order =
(int)obs_source_get_deinterlace_field_order(source);
obs_data_set_obj (source_data, "hotkeys", hotkey_data);
obs_data_set_int (source_data, "deinterlace_mode", di_mode);
obs_data_set_int (source_data, "deinterlace_field_order", di_order);
+ obs_data_set_int (source_data, "monitoring_type", m_type);
if (source->info.type == OBS_SOURCE_TYPE_TRANSITION)
obs_transition_save(source, source_data);
return !context->data;
}
+
+bool obs_set_audio_monitoring_device(const char *name, const char *id)
+{
+ if (!obs || !name || !id || !*name || !*id)
+ return false;
+
+#ifdef _WIN32
+ pthread_mutex_lock(&obs->audio.monitoring_mutex);
+
+ if (strcmp(id, obs->audio.monitoring_device_id) == 0) {
+ pthread_mutex_unlock(&obs->audio.monitoring_mutex);
+ return true;
+ }
+
+ if (obs->audio.monitoring_device_name)
+ bfree(obs->audio.monitoring_device_name);
+ if (obs->audio.monitoring_device_id)
+ bfree(obs->audio.monitoring_device_id);
+
+ obs->audio.monitoring_device_name = bstrdup(name);
+ obs->audio.monitoring_device_id = bstrdup(id);
+
+ for (size_t i = 0; i < obs->audio.monitors.num; i++) {
+ struct audio_monitor *monitor = obs->audio.monitors.array[i];
+ audio_monitor_reset(monitor);
+ }
+
+ pthread_mutex_unlock(&obs->audio.monitoring_mutex);
+ return true;
+#else
+ return false;
+#endif
+}
+
+void obs_get_audio_monitoring_device(const char **name, const char **id)
+{
+ if (!obs)
+ return;
+
+ if (name)
+ *name = obs->audio.monitoring_device_name;
+ if (id)
+ *id = obs->audio.monitoring_device_id;
+}
obs-studio-17.0.2.tar.xz/libobs/obs.h -> obs-studio-18.0.0.tar.xz/libobs/obs.h
Changed
EXPORT const char *obs_obj_get_id(void *obj);
EXPORT bool obs_obj_invalid(void *obj);
+typedef bool (*obs_enum_audio_device_cb)(void *data, const char *name,
+ const char *id);
+
+EXPORT void obs_enum_audio_monitoring_devices(obs_enum_audio_device_cb cb,
+ void *data);
+
+EXPORT bool obs_set_audio_monitoring_device(const char *name, const char *id);
+EXPORT void obs_get_audio_monitoring_device(const char **name, const char **id);
+
/* ------------------------------------------------------------------------- */
/* View context */
EXPORT enum obs_deinterlace_field_order obs_source_get_deinterlace_field_order(
const obs_source_t *source);
+enum obs_monitoring_type {
+ OBS_MONITORING_TYPE_NONE,
+ OBS_MONITORING_TYPE_MONITOR_ONLY,
+ OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT
+};
+
+EXPORT void obs_source_set_monitoring_type(obs_source_t *source,
+ enum obs_monitoring_type type);
+EXPORT enum obs_monitoring_type obs_source_get_monitoring_type(
+ const obs_source_t *source);
+
/* ------------------------------------------------------------------------- */
/* Functions used by sources */
const char *text);
#endif
+EXPORT float obs_output_get_congestion(obs_output_t *output);
+
/* ------------------------------------------------------------------------- */
/* Functions used by outputs */
obs-studio-17.0.2.tar.xz/libobs/util/config-file.c -> obs-studio-18.0.0.tar.xz/libobs/util/config-file.c
Changed
#include <stdio.h>
#include <wchar.h>
#include "config-file.h"
+#include "threading.h"
#include "platform.h"
#include "base.h"
#include "bmem.h"
char *file;
struct darray sections; /* struct config_section */
struct darray defaults; /* struct config_section */
+ pthread_mutex_t mutex;
};
+static inline bool init_mutex(config_t *config)
+{
+ pthread_mutexattr_t attr;
+ if (pthread_mutexattr_init(&attr) != 0)
+ return false;
+ if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0)
+ return false;
+ return pthread_mutex_init(&config->mutex, &attr) == 0;
+}
+
config_t *config_create(const char *file)
{
struct config_data *config;
fclose(f);
config = bzalloc(sizeof(struct config_data));
+
+ if (!init_mutex(config)) {
+ bfree(config);
+ return NULL;
+ }
+
config->file = bstrdup(file);
return config;
}
if (!*config)
return CONFIG_ERROR;
+ if (!init_mutex(*config)) {
+ bfree(*config);
+ return CONFIG_ERROR;
+ }
+
(*config)->file = bstrdup(file);
errorcode = config_parse_file(&(*config)->sections, file, always_open);
if (!*config)
return CONFIG_ERROR;
+ if (!init_mutex(*config)) {
+ bfree(*config);
+ return CONFIG_ERROR;
+ }
+
(*config)->file = NULL;
lexer_init(&lex);
dstr_init(&str);
dstr_init(&tmp);
+ pthread_mutex_lock(&config->mutex);
+
f = os_fopen(config->file, "wb");
- if (!f)
+ if (!f) {
+ pthread_mutex_unlock(&config->mutex);
return CONFIG_FILENOTFOUND;
+ }
for (i = 0; i < config->sections.num; i++) {
struct config_section *section = darray_item(
fwrite(str.array, 1, str.len, f);
fclose(f);
+ pthread_mutex_unlock(&config->mutex);
+
dstr_free(&tmp);
dstr_free(&str);
return CONFIG_ERROR;
}
+ pthread_mutex_lock(&config->mutex);
+
dstr_copy(&temp_file, config->file);
if (*temp_ext != '.')
dstr_cat(&temp_file, ".");
os_rename(temp_file.array, file);
cleanup:
+ pthread_mutex_unlock(&config->mutex);
dstr_free(&temp_file);
dstr_free(&backup_file);
return ret;
darray_free(&config->defaults);
darray_free(&config->sections);
bfree(config->file);
+ pthread_mutex_destroy(&config->mutex);
bfree(config);
}
const char *config_get_section(config_t *config, size_t idx)
{
struct config_section *section;
+ const char *name = NULL;
+
+ pthread_mutex_lock(&config->mutex);
if (idx >= config->sections.num)
- return NULL;
+ goto unlock;
section = darray_item(sizeof(struct config_section), &config->sections,
idx);
+ name = section->name;
- return section->name;
+unlock:
+ pthread_mutex_unlock(&config->mutex);
+ return name;
}
static const struct config_item *config_find_item(const struct darray *sections,
return NULL;
}
-static void config_set_item(struct darray *sections, const char *section,
- const char *name, char *value)
+static void config_set_item(config_t *config, struct darray *sections,
+ const char *section, const char *name, char *value)
{
struct config_section *sec = NULL;
struct config_section *array = sections->array;
struct config_item *item;
size_t i, j;
+ pthread_mutex_lock(&config->mutex);
+
for (i = 0; i < sections->num; i++) {
struct config_section *cur_sec = array+i;
struct config_item *items = cur_sec->items.array;
if (astrcmpi(item->name, name) == 0) {
bfree(item->value);
item->value = value;
- return;
+ goto unlock;
}
}
item = darray_push_back_new(sizeof(struct config_item), &sec->items);
item->name = bstrdup(name);
item->value = value;
+
+unlock:
+ pthread_mutex_unlock(&config->mutex);
}
void config_set_string(config_t *config, const char *section,
{
if (!value)
value = "";
- config_set_item(&config->sections, section, name, bstrdup(value));
+ config_set_item(config, &config->sections, section, name,
+ bstrdup(value));
}
void config_set_int(config_t *config, const char *section,
struct dstr str;
dstr_init(&str);
dstr_printf(&str, "%"PRId64, value);
- config_set_item(&config->sections, section, name, str.array);
+ config_set_item(config, &config->sections, section, name, str.array);
}
void config_set_uint(config_t *config, const char *section,
struct dstr str;
dstr_init(&str);
dstr_printf(&str, "%"PRIu64, value);
- config_set_item(&config->sections, section, name, str.array);
+ config_set_item(config, &config->sections, section, name, str.array);
}
void config_set_bool(config_t *config, const char *section,
const char *name, bool value)
{
char *str = bstrdup(value ? "true" : "false");
- config_set_item(&config->sections, section, name, str);
+ config_set_item(config, &config->sections, section, name, str);
}
void config_set_double(config_t *config, const char *section,
{
char *str = bzalloc(64);
os_dtostr(value, str, 64);
- config_set_item(&config->sections, section, name, str);
+ config_set_item(config, &config->sections, section, name, str);
}
void config_set_default_string(config_t *config, const char *section,
{
if (!value)
value = "";
- config_set_item(&config->defaults, section, name, bstrdup(value));
+ config_set_item(config, &config->defaults, section, name,
+ bstrdup(value));
}
void config_set_default_int(config_t *config, const char *section,
struct dstr str;
dstr_init(&str);
dstr_printf(&str, "%"PRId64, value);
- config_set_item(&config->defaults, section, name, str.array);
+ config_set_item(config, &config->defaults, section, name, str.array);
}
void config_set_default_uint(config_t *config, const char *section,
struct dstr str;
dstr_init(&str);
dstr_printf(&str, "%"PRIu64, value);
- config_set_item(&config->defaults, section, name, str.array);
+ config_set_item(config, &config->defaults, section, name, str.array);
}
void config_set_default_bool(config_t *config, const char *section,
const char *name, bool value)
{
char *str = bstrdup(value ? "true" : "false");
- config_set_item(&config->defaults, section, name, str);
+ config_set_item(config, &config->defaults, section, name, str);
}
void config_set_default_double(config_t *config, const char *section,
struct dstr str;
dstr_init(&str);
dstr_printf(&str, "%g", value);
- config_set_item(&config->defaults, section, name, str.array);
+ config_set_item(config, &config->defaults, section, name, str.array);
}
-const char *config_get_string(const config_t *config, const char *section,
+const char *config_get_string(config_t *config, const char *section,
const char *name)
{
- const struct config_item *item = config_find_item(&config->sections,
- section, name);
+ const struct config_item *item;
+ const char *value = NULL;
+
+ pthread_mutex_lock(&config->mutex);
+
+ item = config_find_item(&config->sections, section, name);
if (!item)
item = config_find_item(&config->defaults, section, name);
- if (!item)
- return NULL;
+ if (item)
+ value = item->value;
- return item->value;
+ pthread_mutex_unlock(&config->mutex);
+ return value;
}
static inline int64_t str_to_int64(const char *str)
return strtoull(str, NULL, 10);
}
-int64_t config_get_int(const config_t *config, const char *section,
+int64_t config_get_int(config_t *config, const char *section,
const char *name)
{
const char *value = config_get_string(config, section, name);
return 0;
}
-uint64_t config_get_uint(const config_t *config, const char *section,
+uint64_t config_get_uint(config_t *config, const char *section,
const char *name)
{
const char *value = config_get_string(config, section, name);
return 0;
}
-bool config_get_bool(const config_t *config, const char *section,
+bool config_get_bool(config_t *config, const char *section,
const char *name)
{
const char *value = config_get_string(config, section, name);
return false;
}
-double config_get_double(const config_t *config, const char *section,
+double config_get_double(config_t *config, const char *section,
const char *name)
{
const char *value = config_get_string(config, section, name);
const char *name)
{
struct darray *sections = &config->sections;
+ bool success = false;
+
+ pthread_mutex_lock(&config->mutex);
for (size_t i = 0; i < sections->num; i++) {
struct config_section *sec = darray_item(
config_item_free(item);
darray_erase(sizeof(struct config_item),
&sec->items, j);
- return true;
+ success = true;
+ goto unlock;
}
}
}
- return false;
+unlock:
+ pthread_mutex_unlock(&config->mutex);
+ return success;
}
-const char *config_get_default_string(const config_t *config,
+const char *config_get_default_string(config_t *config,
const char *section, const char *name)
{
const struct config_item *item;
+ const char *value = NULL;
+
+ pthread_mutex_lock(&config->mutex);
item = config_find_item(&config->defaults, section, name);
- if (!item)
- return NULL;
+ if (item)
+ value = item->value;
- return item->value;
+ pthread_mutex_unlock(&config->mutex);
+ return value;
}
-int64_t config_get_default_int(const config_t *config, const char *section,
+int64_t config_get_default_int(config_t *config, const char *section,
const char *name)
{
const char *value = config_get_default_string(config, section, name);
return 0;
}
-uint64_t config_get_default_uint(const config_t *config, const char *section,
+uint64_t config_get_default_uint(config_t *config, const char *section,
const char *name)
{
const char *value = config_get_default_string(config, section, name);
return 0;
}
-bool config_get_default_bool(const config_t *config, const char *section,
+bool config_get_default_bool(config_t *config, const char *section,
const char *name)
{
const char *value = config_get_default_string(config, section, name);
return false;
}
-double config_get_default_double(const config_t *config, const char *section,
+double config_get_default_double(config_t *config, const char *section,
const char *name)
{
const char *value = config_get_default_string(config, section, name);
return 0.0;
}
-bool config_has_user_value(const config_t *config, const char *section,
+bool config_has_user_value(config_t *config, const char *section,
const char *name)
{
- return config_find_item(&config->sections, section, name) != NULL;
+ bool success;
+ pthread_mutex_lock(&config->mutex);
+ success = config_find_item(&config->sections, section, name) != NULL;
+ pthread_mutex_unlock(&config->mutex);
+ return success;
}
-bool config_has_default_value(const config_t *config, const char *section,
+bool config_has_default_value(config_t *config, const char *section,
const char *name)
{
- return config_find_item(&config->defaults, section, name) != NULL;
+ bool success;
+ pthread_mutex_lock(&config->mutex);
+ success = config_find_item(&config->defaults, section, name) != NULL;
+ pthread_mutex_unlock(&config->mutex);
+ return success;
}
obs-studio-17.0.2.tar.xz/libobs/util/config-file.h -> obs-studio-18.0.0.tar.xz/libobs/util/config-file.h
Changed
EXPORT void config_set_double(config_t *config, const char *section,
const char *name, double value);
-EXPORT const char *config_get_string(const config_t *config,
+EXPORT const char *config_get_string(config_t *config,
const char *section, const char *name);
-EXPORT int64_t config_get_int(const config_t *config, const char *section,
+EXPORT int64_t config_get_int(config_t *config, const char *section,
const char *name);
-EXPORT uint64_t config_get_uint(const config_t *config, const char *section,
+EXPORT uint64_t config_get_uint(config_t *config, const char *section,
const char *name);
-EXPORT bool config_get_bool(const config_t *config, const char *section,
+EXPORT bool config_get_bool(config_t *config, const char *section,
const char *name);
-EXPORT double config_get_double(const config_t *config, const char *section,
+EXPORT double config_get_double(config_t *config, const char *section,
const char *name);
EXPORT bool config_remove_value(config_t *config, const char *section,
/* These functions allow you to get the current default values rather than get
* the actual values. Probably almost never really needed */
-EXPORT const char *config_get_default_string(const config_t *config,
+EXPORT const char *config_get_default_string(config_t *config,
const char *section, const char *name);
-EXPORT int64_t config_get_default_int(const config_t *config,
+EXPORT int64_t config_get_default_int(config_t *config,
const char *section, const char *name);
-EXPORT uint64_t config_get_default_uint(const config_t *config,
+EXPORT uint64_t config_get_default_uint(config_t *config,
const char *section, const char *name);
-EXPORT bool config_get_default_bool(const config_t *config,
+EXPORT bool config_get_default_bool(config_t *config,
const char *section, const char *name);
-EXPORT double config_get_default_double(const config_t *config,
+EXPORT double config_get_default_double(config_t *config,
const char *section, const char *name);
-EXPORT bool config_has_user_value(const config_t *config,
+EXPORT bool config_has_user_value(config_t *config,
const char *section, const char *name);
-EXPORT bool config_has_default_value(const config_t *config,
+EXPORT bool config_has_default_value(config_t *config,
const char *section, const char *name);
#ifdef __cplusplus
obs-studio-17.0.2.tar.xz/plugins/CMakeLists.txt -> obs-studio-18.0.0.tar.xz/plugins/CMakeLists.txt
Changed
message(STATUS "obs-browser submodule not found! Please fetch submodules. obs-browser plugin disabled.")
endif()
endif()
+
+ if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/obs-vst/CMakeLists.txt")
+ add_subdirectory(obs-vst)
+ else()
+ message(STATUS "obs-vst submodule not found! Please fetch/update submodules. obs-vst plugin disabled.")
+ endif()
endif()
add_subdirectory(image-source)
obs-studio-17.0.2.tar.xz/plugins/enc-amf/CMakeLists.txt -> obs-studio-18.0.0.tar.xz/plugins/enc-amf/CMakeLists.txt
Changed
SET(enc-amf_VERSION_MAJOR 1)
SET(enc-amf_VERSION_MINOR 4)
SET(enc-amf_VERSION_PATCH 3)
-SET(enc-amf_VERSION_BUILD 8)
+SET(enc-amf_VERSION_BUILD 10)
configure_file(
"${PROJECT_SOURCE_DIR}/#Resources/package.in.bat"
"${PROJECT_SOURCE_DIR}/#Resources/package.bat"
obs-studio-17.0.2.tar.xz/plugins/enc-amf/Include/plugin.h -> obs-studio-18.0.0.tar.xz/plugins/enc-amf/Include/plugin.h
Changed
#define clamp(val,low,high) (val > high ? high : (val < low ? low : val))
#include "Version.h"
-#define PLUGIN_VERSION_FULL (((uint64_t)PLUGIN_VERSION_MAJOR << 48ull) | ((uint64_t)PLUGIN_VERSION_MINOR << 32ull) | ((uint64_t)PLUGIN_VERSION_PATCH) | ((uint64_t)PLUGIN_VERSION_BUILD))
+#define PLUGIN_VERSION_FULL (((uint64_t)PLUGIN_VERSION_MAJOR << 48ull) | ((uint64_t)PLUGIN_VERSION_MINOR << 32ull) | ((uint64_t)PLUGIN_VERSION_PATCH) << 16ul | ((uint64_t)PLUGIN_VERSION_BUILD))
#define PLUGIN_VERSION_TEXT vstr(PLUGIN_VERSION_MAJOR) "." vstr(PLUGIN_VERSION_MINOR) "." vstr(PLUGIN_VERSION_PATCH) "." vstr(PLUGIN_VERSION_BUILD)
#define AMF_LOG(level, format, ...) blog(level, "[AMF Encoder] " format, ##__VA_ARGS__);
#define AMF_LOG_CONFIG(format, ...) AMF_LOG(350, format, ##__VA_ARGS__)
#define AMF_LOG_DEBUG(format, ...) AMF_LOG(LOG_DEBUG, format, ##__VA_ARGS__)
+#define ThrowException(format, ...) {\
+ std::vector<char> _throwexceptionwithamferror_buf(8192);\
+ sprintf_s(_throwexceptionwithamferror_buf.data(), _throwexceptionwithamferror_buf.size(), format, ##__VA_ARGS__);\
+ AMF_LOG_WARNING("%s", _throwexceptionwithamferror_buf.data()); \
+ throw std::exception(_throwexceptionwithamferror_buf.data()); \
+}
#define ThrowExceptionWithAMFError(format, res, ...) {\
std::vector<char> _throwexceptionwithamferror_buf(8192);\
sprintf_s(_throwexceptionwithamferror_buf.data(), _throwexceptionwithamferror_buf.size(), format, ##__VA_ARGS__, Plugin::AMD::AMF::GetInstance()->GetTrace()->GetResultText(res), res);\
obs-studio-17.0.2.tar.xz/plugins/enc-amf/Source/amf.cpp -> obs-studio-18.0.0.tar.xz/plugins/enc-amf/Source/amf.cpp
Changed
m_AMFVersion_Compiler = AMF_FULL_VERSION;
res = AMFQueryVersion(&m_AMFVersion_Runtime);
if (res != AMF_OK)
- ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Querying Version failed with error %ls (code %ld).", res);
+ ThrowException("<" __FUNCTION_NAME__ "> Querying Version failed with error code %ld.", res);
#pragma endregion Query AMF Runtime Version
/// Find Function for Initializing AMF.
} else {
res = AMFInit(m_AMFVersion_Runtime, &m_AMFFactory);
if (res != AMF_OK)
- ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Initializing AMF Library failed with error %ls (code %ld).", res);
+ ThrowException("<" __FUNCTION_NAME__ "> Initializing AMF Library failed with error code %ld.", res);
}
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> AMF Library initialized.");
/// Retrieve Trace Object.
res = m_AMFFactory->GetTrace(&m_AMFTrace);
if (res != AMF_OK) {
- ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Retrieving Trace object failed with error %ls (code %ld).", res);
+ ThrowException("<" __FUNCTION_NAME__ "> Retrieving Trace object failed with error code %ld.", res);
}
/// Retrieve Debug Object.
res = m_AMFFactory->GetDebug(&m_AMFDebug);
if (res != AMF_OK) {
- AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Retrieving Debug object failed with error code %ls (code %ld).", res);
- throw std::exception("", res);
+ ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Retrieving Debug object failed with error code %ls (code %ld).", res);
}
/// Register Trace Writer and disable Debug Tracing.
obs-studio-17.0.2.tar.xz/plugins/enc-amf/Source/enc-h264.cpp -> obs-studio-18.0.0.tar.xz/plugins/enc-amf/Source/enc-h264.cpp
Changed
obs_data_set_int(data, "last" vstr(AMF_H264_VIEW), -1);
obs_data_set_default_int(data, AMF_H264_VIEW, static_cast<int32_t>(ViewMode::Basic));
obs_data_set_default_bool(data, AMF_H264_DEBUG, false);
- obs_data_set_default_int(data, AMF_H264_VERSION, 0x0001000400030005ull);
+ obs_data_set_default_int(data, AMF_H264_VERSION, PLUGIN_VERSION_FULL);
}
static void fill_api_list(obs_property_t* p) {
obs-studio-17.0.2.tar.xz/plugins/image-source/CMakeLists.txt -> obs-studio-18.0.0.tar.xz/plugins/image-source/CMakeLists.txt
Changed
set(image-source_SOURCES
image-source.c
+ color-source.c
obs-slideshow.c)
add_library(image-source MODULE
obs-studio-18.0.0.tar.xz/plugins/image-source/color-source.c
Added
+#include <obs-module.h>
+
+struct color_source {
+ uint32_t color;
+
+ uint32_t width;
+ uint32_t height;
+
+ obs_source_t *src;
+};
+
+static const char *color_source_get_name(void *unused)
+{
+ UNUSED_PARAMETER(unused);
+ return obs_module_text("ColorSource");
+}
+
+static void color_source_update(void *data, obs_data_t *settings)
+{
+ struct color_source *context = data;
+ uint32_t color = (uint32_t)obs_data_get_int(settings, "color");
+ uint32_t width = (uint32_t)obs_data_get_int(settings, "width");
+ uint32_t height = (uint32_t)obs_data_get_int(settings, "height");
+
+ context->color = color;
+ context->width = width;
+ context->height = height;
+}
+
+static void *color_source_create(obs_data_t *settings, obs_source_t *source)
+{
+ UNUSED_PARAMETER(source);
+
+ struct color_source *context = bzalloc(sizeof(struct color_source));
+ context->src = source;
+
+ color_source_update(context, settings);
+
+ return context;
+}
+
+static void color_source_destroy(void *data)
+{
+ bfree(data);
+}
+
+static obs_properties_t *color_source_properties(void *unused)
+{
+ UNUSED_PARAMETER(unused);
+
+ obs_properties_t *props = obs_properties_create();
+
+ obs_properties_add_color(props, "color",
+ obs_module_text("ColorSource.Color"));
+
+ obs_properties_add_int(props, "width",
+ obs_module_text("ColorSource.Width"), 0, 4096, 1);
+
+ obs_properties_add_int(props, "height",
+ obs_module_text("ColorSource.Height"), 0, 4096, 1);
+
+ return props;
+}
+
+static void color_source_render(void *data, gs_effect_t *effect)
+{
+ UNUSED_PARAMETER(effect);
+
+ struct color_source *context = data;
+
+ gs_effect_t *solid = obs_get_base_effect(OBS_EFFECT_SOLID);
+ gs_eparam_t *color = gs_effect_get_param_by_name(solid, "color");
+ gs_technique_t *tech = gs_effect_get_technique(solid, "Solid");
+
+ struct vec4 colorVal;
+ vec4_from_rgba(&colorVal, context->color);
+ gs_effect_set_vec4(color, &colorVal);
+
+ gs_technique_begin(tech);
+ gs_technique_begin_pass(tech, 0);
+
+ gs_draw_sprite(0, 0, context->width, context->height);
+
+ gs_technique_end_pass(tech);
+ gs_technique_end(tech);
+}
+
+static uint32_t color_source_getwidth(void *data)
+{
+ struct color_source *context = data;
+ return context->width;
+}
+
+static uint32_t color_source_getheight(void *data)
+{
+ struct color_source *context = data;
+ return context->height;
+}
+
+static void color_source_defaults(obs_data_t *settings)
+{
+ obs_data_set_default_int(settings, "color", 0xFFFFFFFF);
+ obs_data_set_default_int(settings, "width", 400);
+ obs_data_set_default_int(settings, "height", 400);
+}
+
+struct obs_source_info color_source_info = {
+ .id = "color_source",
+ .type = OBS_SOURCE_TYPE_INPUT,
+ .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW,
+ .create = color_source_create,
+ .destroy = color_source_destroy,
+ .update = color_source_update,
+ .get_name = color_source_get_name,
+ .get_defaults = color_source_defaults,
+ .get_width = color_source_getwidth,
+ .get_height = color_source_getheight,
+ .video_render = color_source_render,
+ .get_properties = color_source_properties
+};
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/ar-SA.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/ar-SA.ini
Changed
UnloadWhenNotShowing="إلغاء تحميل الصورة إذا لم تظهر"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/bg-BG.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/bg-BG.ini
Changed
File="Файл с изображение"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/ca-ES.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/ca-ES.ini
Changed
SlideShow.Transition.Swipe="De cop"
SlideShow.Transition.Slide="Diapositiva"
+ColorSource="Origen del color"
+ColorSource.Color="Color"
+ColorSource.Width="Amplada"
+ColorSource.Height="Alçada"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/cs-CZ.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/cs-CZ.ini
Changed
SlideShow.Transition.Swipe="Tažení"
SlideShow.Transition.Slide="Sklouznutí"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/da-DK.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/da-DK.ini
Changed
SlideShow.Transition.Swipe="Stryg"
SlideShow.Transition.Slide="Glide"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/de-DE.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/de-DE.ini
Changed
SlideShow.Transition.Swipe="Swipe"
SlideShow.Transition.Slide="Slide"
+ColorSource="Farbquelle"
+ColorSource.Color="Farbe"
+ColorSource.Width="Breite"
+ColorSource.Height="Höhe"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/el-GR.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/el-GR.ini
Changed
SlideShow.Files="Αρχεία φωτογραφίας"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/en-US.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/en-US.ini
Changed
SlideShow.Transition.Fade="Fade"
SlideShow.Transition.Swipe="Swipe"
SlideShow.Transition.Slide="Slide"
+
+ColorSource="Color Source"
+ColorSource.Color="Color"
+ColorSource.Width="Width"
+ColorSource.Height="Height"
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/es-ES.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/es-ES.ini
Changed
SlideShow.Transition.Swipe="Deslizar Rapido"
SlideShow.Transition.Slide="Deslizar"
+ColorSource="Origen de color"
+ColorSource.Color="Color"
+ColorSource.Width="Ancho"
+ColorSource.Height="Alto"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/eu-ES.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/eu-ES.ini
Changed
SlideShow.Transition.Swipe="Korritu"
SlideShow.Transition.Slide="Irristatu"
+ColorSource="Kolorearen iturburua"
+ColorSource.Color="Kolorea"
+ColorSource.Width="Zabalera"
+ColorSource.Height="Altuera"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/fi-FI.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/fi-FI.ini
Changed
SlideShow.Transition.Swipe="Pyyhkäise"
SlideShow.Transition.Slide="Liu'uta"
+ColorSource="Värilähde"
+ColorSource.Color="Väri"
+ColorSource.Width="Leveys"
+ColorSource.Height="Korkeus"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/fr-FR.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/fr-FR.ini
Changed
SlideShow.Transition.Swipe="Balayage"
SlideShow.Transition.Slide="Glissement"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/gl-ES.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/gl-ES.ini
Changed
UnloadWhenNotShowing="Non descargar a imaxe cando non se mostre"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/he-IL.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/he-IL.ini
Changed
SlideShow.Transition.Swipe="החלקה"
SlideShow.Transition.Slide="הסט"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/hr-HR.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/hr-HR.ini
Changed
SlideShow.Transition.Swipe="Prevlačenje"
SlideShow.Transition.Slide="Klizanje"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/hu-HU.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/hu-HU.ini
Changed
SlideShow.Transition.Swipe="Lapozás"
SlideShow.Transition.Slide="Csúsztatás"
+ColorSource="Színforrás"
+ColorSource.Color="Szín"
+ColorSource.Width="Szélesség"
+ColorSource.Height="Magasság"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/it-IT.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/it-IT.ini
Changed
SlideShow.Transition.Swipe="Scorri"
SlideShow.Transition.Slide="Scivola"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/ja-JP.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/ja-JP.ini
Changed
SlideShow.Transition.Swipe="スワイプ"
SlideShow.Transition.Slide="スライド"
+ColorSource="色ソース"
+ColorSource.Color="色"
+ColorSource.Width="幅"
+ColorSource.Height="高さ"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/ko-KR.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/ko-KR.ini
Changed
SlideShow.Transition.Swipe="밀어내기"
SlideShow.Transition.Slide="슬라이드"
+ColorSource="색상 소스"
+ColorSource.Color="색상"
+ColorSource.Width="너비"
+ColorSource.Height="높이"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/ms-MY.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/ms-MY.ini
Changed
SlideShow.Transition.Swipe="Sapu"
SlideShow.Transition.Slide="Slaid"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/nb-NO.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/nb-NO.ini
Changed
SlideShow.Transition.Swipe="Sveip"
SlideShow.Transition.Slide="Skyv"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/nl-NL.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/nl-NL.ini
Changed
SlideShow.Transition.Swipe="Vegen"
SlideShow.Transition.Slide="Slide"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/pl-PL.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/pl-PL.ini
Changed
SlideShow.Transition.Swipe="Przeciągnięcie"
SlideShow.Transition.Slide="Przesunięcie"
+ColorSource="Kolor"
+ColorSource.Color="Kolor"
+ColorSource.Width="Szerokość"
+ColorSource.Height="Wysokość"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/pt-BR.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/pt-BR.ini
Changed
SlideShow.Transition.Swipe="Arrastar"
SlideShow.Transition.Slide="Deslizar"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/pt-PT.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/pt-PT.ini
Changed
SlideShow.Transition.Swipe="Deslizar"
SlideShow.Transition.Slide="Deslize"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/ro-RO.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/ro-RO.ini
Changed
File="Fișier imagine"
UnloadWhenNotShowing="Eliberează din memorie imaginea când nu este afișată"
+SlideShow="Slide Show de imagini"
+SlideShow.TransitionSpeed="Viteza de tranziție (milisecunde)"
+SlideShow.SlideTime="Timpul dintre diapozitive (milisecunde)"
+SlideShow.Transition="Tranziție"
+SlideShow.Transition.Cut="Decupare"
+SlideShow.Transition.Slide="Diapozitiv"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/ru-RU.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/ru-RU.ini
Changed
SlideShow.Transition.Swipe="Перемещение"
SlideShow.Transition.Slide="Сдвиг"
+ColorSource="Фоновый цвет"
+ColorSource.Color="Цвет"
+ColorSource.Width="Ширина"
+ColorSource.Height="Высота"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/sk-SK.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/sk-SK.ini
Changed
SlideShow.Transition.Swipe="Potiahnite"
SlideShow.Transition.Slide="Posunutie"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/sl-SI.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/sl-SI.ini
Changed
UnloadWhenNotShowing="Ne naloži slike, ko ni prikazana"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/sr-CS.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/sr-CS.ini
Changed
SlideShow.Transition.Swipe="Prevlačenje"
SlideShow.Transition.Slide="Klizanje"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/sr-SP.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/sr-SP.ini
Changed
SlideShow.Transition.Swipe="Превлачење"
SlideShow.Transition.Slide="Клизање"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/sv-SE.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/sv-SE.ini
Changed
SlideShow.Transition.Swipe="Svep"
SlideShow.Transition.Slide="Glid"
+ColorSource="Färgkälla"
+ColorSource.Color="Färg"
+ColorSource.Width="Bredd"
+ColorSource.Height="Höjd"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/th-TH.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/th-TH.ini
Changed
File="ไฟล์รูปภาพ"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/tr-TR.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/tr-TR.ini
Changed
SlideShow.Transition.Swipe="Swipe"
SlideShow.Transition.Slide="Slide"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/uk-UA.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/uk-UA.ini
Changed
SlideShow.Transition.Swipe="Swipe"
SlideShow.Transition.Slide="Slide"
+ColorSource="Щільний колір"
+ColorSource.Color="Колір"
+ColorSource.Width="Ширина"
+ColorSource.Height="Висота"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/zh-CN.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/zh-CN.ini
Changed
SlideShow.Transition.Swipe="滑动"
SlideShow.Transition.Slide="幻灯片"
+ColorSource="色源"
+ColorSource.Color="色彩"
+ColorSource.Width="宽度"
+ColorSource.Height="高度"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/data/locale/zh-TW.ini -> obs-studio-18.0.0.tar.xz/plugins/image-source/data/locale/zh-TW.ini
Changed
SlideShow.Transition.Swipe="滑出"
SlideShow.Transition.Slide="推出"
+ColorSource="色彩來源"
+ColorSource.Color="色彩"
+ColorSource.Width="寬度"
+ColorSource.Height="高度"
+
obs-studio-17.0.2.tar.xz/plugins/image-source/image-source.c -> obs-studio-18.0.0.tar.xz/plugins/image-source/image-source.c
Changed
OBS_MODULE_USE_DEFAULT_LOCALE("image-source", "en-US")
extern struct obs_source_info slideshow_info;
+extern struct obs_source_info color_source_info;
bool obs_module_load(void)
{
obs_register_source(&image_source_info);
+ obs_register_source(&color_source_info);
obs_register_source(&slideshow_info);
return true;
}
obs-studio-17.0.2.tar.xz/plugins/linux-pulseaudio/pulse-input.c -> obs-studio-18.0.0.tar.xz/plugins/linux-pulseaudio/pulse-input.c
Changed
.id = "pulse_output_capture",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_AUDIO |
- OBS_SOURCE_DO_NOT_DUPLICATE,
+ OBS_SOURCE_DO_NOT_DUPLICATE |
+ OBS_SOURCE_DO_NOT_MONITOR,
.get_name = pulse_output_getname,
.create = pulse_create,
.destroy = pulse_destroy,
obs-studio-17.0.2.tar.xz/plugins/mac-capture/mac-audio.c -> obs-studio-18.0.0.tar.xz/plugins/mac-capture/mac-audio.c
Changed
.id = "coreaudio_output_capture",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_AUDIO |
- OBS_SOURCE_DO_NOT_DUPLICATE,
+ OBS_SOURCE_DO_NOT_DUPLICATE |
+ OBS_SOURCE_DO_NOT_MONITOR,
.get_name = coreaudio_output_getname,
.create = coreaudio_create_output_capture,
.destroy = coreaudio_destroy,
obs-studio-17.0.2.tar.xz/plugins/mac-vth264/data/locale/da-DK.ini -> obs-studio-18.0.0.tar.xz/plugins/mac-vth264/data/locale/da-DK.ini
Changed
MaxBitrateWindow="Maks. bit-hastighedsvindue (sekunder)"
KeyframeIntervalSec="Keyframe interval (sekunder, 0= auto)"
Profile="Profil"
+None="(ingen)"
DefaultEncoder="(Standard Encoder)"
UseBFrames="Benyt B-frames"
obs-studio-17.0.2.tar.xz/plugins/obs-browser/CMakeLists.txt -> obs-studio-18.0.0.tar.xz/plugins/obs-browser/CMakeLists.txt
Changed
add_custom_command(TARGET cef-isolation
# Disable taskbar visibility
- COMMAND defaults write "$<TARGET_FILE_DIR:cef-isolation>/../Info.plist" "LSUIElement" true
+ COMMAND defaults write "$<TARGET_FILE_DIR:cef-isolation>/../Info.plist" "LSUIElement" 1
)
add_custom_command(TARGET cef-bootstrap POST_BUILD
COMMAND install_name_tool -change "@executable_path/Chromium Embedded Framework" "@rpath/Chromium Embedded Framework.framework/Chromium Embedded Framework" "$<TARGET_FILE:cef-bootstrap>"
# Disable taskbar visibility
- COMMAND defaults write "$<TARGET_FILE_DIR:cef-bootstrap>/../Info.plist" "LSUIElement" true
+ COMMAND defaults write "$<TARGET_FILE_DIR:cef-bootstrap>/../Info.plist" "LSUIElement" 1
)
add_custom_command(TARGET cef-isolation POST_BUILD
obs-studio-17.0.2.tar.xz/plugins/obs-browser/obs-browser/browser-manager-base.cpp -> obs-studio-18.0.0.tar.xz/plugins/obs-browser/obs-browser/browser-manager-base.cpp
Changed
BrowserManager::Impl::Impl()
{
os_event_init(&dispatchEvent, OS_EVENT_TYPE_AUTO);
+ os_event_init(&startupEvent, OS_EVENT_TYPE_MANUAL);
pthread_mutex_init(&dispatchLock, nullptr);
}
BrowserManager::Impl::~Impl()
{
- os_event_init(&dispatchEvent, OS_EVENT_TYPE_AUTO);
- pthread_mutex_init(&dispatchLock, nullptr);
+ pthread_mutex_destroy(&dispatchLock);
+ os_event_destroy(startupEvent);
+ os_event_destroy(dispatchEvent);
}
int BrowserManager::Impl::CreateBrowser(
os_event_t *createdEvent;
os_event_init(&createdEvent, OS_EVENT_TYPE_AUTO);
+ os_event_wait(startupEvent);
+
BrowserOBSBridge *browserOBSBridge = new BrowserOBSBridgeBase();
CefPostTask(TID_UI, BrowserTask::newTask(
void
BrowserManager::Impl::Startup()
{
+ pthread_mutex_lock(&dispatchLock);
int ret = pthread_create(&managerThread, nullptr,
browserManagerEntry, this);
else {
threadAlive = true;
}
+ pthread_mutex_unlock(&dispatchLock);
return;
}
{
std::string bootstrapPath = getBootstrap();
bool thread_exit = false;
- PushEvent([] {
+ PushEvent([this] {
CefMainArgs mainArgs;
CefSettings settings;
settings.log_severity = LOGSEVERITY_VERBOSE;
CefExecuteProcess(mainArgs, app, nullptr);
CefInitialize(mainArgs, settings, app, nullptr);
CefRegisterSchemeHandlerFactory("http", "absolute", new BrowserSchemeHandlerFactory());
+ os_event_signal(startupEvent);
CefRunMessageLoop();
CefShutdown();
});
obs-studio-17.0.2.tar.xz/plugins/obs-browser/obs-browser/browser-manager-base.hpp -> obs-studio-18.0.0.tar.xz/plugins/obs-browser/obs-browser/browser-manager-base.hpp
Changed
private:
bool threadAlive;
os_event_t *dispatchEvent;
+ os_event_t *startupEvent;
pthread_t managerThread;
pthread_mutex_t dispatchLock;
std::map<int, std::shared_ptr<BrowserListener>> listenerMap;
std::map<int, CefRefPtr<CefBrowser> > browserMap;
std::vector<std::function<void()>> queue;
-};
\ No newline at end of file
+};
obs-studio-17.0.2.tar.xz/plugins/obs-browser/shared/browser-version.h -> obs-studio-18.0.0.tar.xz/plugins/obs-browser/shared/browser-version.h
Changed
#pragma once
-#define OBS_BROWSER_VERSION "1.27.0"
\ No newline at end of file
+#define OBS_BROWSER_VERSION "1.28.0"
\ No newline at end of file
obs-studio-17.0.2.tar.xz/plugins/obs-ffmpeg/data/locale/pt-BR.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-ffmpeg/data/locale/pt-BR.ini
Changed
KeyframeIntervalSec="Intervalo de Keyframe (segundos, 0=auto)"
Lossless="Sem perdas"
+BFrames="B-frames"
NVENC.Use2Pass="Utilizar a codificação em dois passos"
NVENC.Preset.default="Padrão"
MediaFileFilter.AudioFiles="Arquivos de Áudio"
MediaFileFilter.AllFiles="Todos os Arquivos"
+ReplayBuffer="Buffer do Replay"
+ReplayBuffer.Save="Salvar Replay"
obs-studio-17.0.2.tar.xz/plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c -> obs-studio-18.0.0.tar.xz/plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c
Changed
static bool init_streams(struct ffmpeg_mux *ffm)
{
- create_video_stream(ffm);
+ if (ffm->params.has_video)
+ create_video_stream(ffm);
if (ffm->params.tracks) {
ffm->audio_streams =
obs-studio-17.0.2.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-mux.c -> obs-studio-18.0.0.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-mux.c
Changed
obs_data_release(settings);
dstr_catf(cmd, "%s %d %d %d %d %d ",
- "h264",
+ obs_encoder_get_codec(vencoder),
bitrate,
obs_output_get_width(stream->output),
obs_output_get_height(stream->output),
static bool replay_buffer_hotkey(void *data, obs_hotkey_id id,
obs_hotkey_t *hotkey, bool pressed)
{
+ UNUSED_PARAMETER(id);
+ UNUSED_PARAMETER(hotkey);
+ UNUSED_PARAMETER(pressed);
+
struct ffmpeg_muxer *stream = data;
if (os_atomic_load_bool(&stream->active))
stream->save_ts = os_gettime_ns() / 1000LL;
return true;
}
+static void save_replay_proc(void *data, calldata_t *cd)
+{
+ replay_buffer_hotkey(data, 0, NULL, true);
+ UNUSED_PARAMETER(cd);
+}
+
static void *replay_buffer_create(obs_data_t *settings, obs_output_t *output)
{
struct ffmpeg_muxer *stream = bzalloc(sizeof(*stream));
obs_module_text("ReplayBuffer.Save"),
replay_buffer_hotkey, stream);
+ proc_handler_t *ph = obs_output_get_proc_handler(output);
+ proc_handler_add(ph, "void save()", save_replay_proc, stream);
+
UNUSED_PARAMETER(settings);
return stream;
}
obs-studio-17.0.2.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-output.c -> obs-studio-18.0.0.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-output.c
Changed
const char *format_name;
const char *format_mime_type;
const char *muxer_settings;
+ int gop_size;
int video_bitrate;
int audio_bitrate;
const char *video_encoder;
return true;
}
-static void parse_params(AVCodecContext *context, char **opts)
+static bool parse_params(AVCodecContext *context, char **opts)
{
+ bool ret = true;
+
if (!context || !context->priv_data)
- return;
+ return true;
while (*opts) {
char *opt = *opts;
*assign = 0;
value = assign+1;
- av_opt_set(context->priv_data, name, value, 0);
+ if (av_opt_set(context->priv_data, name, value, 0)) {
+ blog(LOG_WARNING, "Failed to set %s=%s", name, value);
+ ret = false;
+ }
}
opts++;
}
+
+ return ret;
}
static bool open_video_codec(struct ffmpeg_data *data)
av_opt_set(context->priv_data, "preset", "veryfast", 0);
if (opts) {
- parse_params(context, opts);
+ // libav requires x264 parameters in a special format which may be non-obvious
+ if (!parse_params(context, opts) && strcmp(data->vcodec->name, "libx264") == 0)
+ blog(LOG_WARNING, "If you're trying to set x264 parameters, use x264-params=name=value:name=value");
strlist_free(opts);
}
context->width = data->config.scale_width;
context->height = data->config.scale_height;
context->time_base = (AVRational){ ovi.fps_den, ovi.fps_num };
- context->gop_size = 120;
+ context->gop_size = data->config.gop_size;
context->pix_fmt = closest_format;
context->colorspace = data->config.color_space;
context->color_range = data->config.color_range;
static bool open_audio_codec(struct ffmpeg_data *data)
{
AVCodecContext *context = data->audio->codec;
- char **opts = strlist_split(data->config.video_settings, ' ', false);
+ char **opts = strlist_split(data->config.audio_settings, ' ', false);
int ret;
if (opts) {
int ret;
settings = obs_output_get_settings(output->output);
+
+ obs_data_set_default_int(settings, "gop_size", 120);
+
config.url = obs_data_get_string(settings, "url");
config.format_name = get_string_or_null(settings, "format_name");
config.format_mime_type = get_string_or_null(settings,
config.muxer_settings = obs_data_get_string(settings, "muxer_settings");
config.video_bitrate = (int)obs_data_get_int(settings, "video_bitrate");
config.audio_bitrate = (int)obs_data_get_int(settings, "audio_bitrate");
+ config.gop_size = (int)obs_data_get_int(settings, "gop_size");
config.video_encoder = get_string_or_null(settings, "video_encoder");
config.video_encoder_id = (int)obs_data_get_int(settings,
"video_encoder_id");
obs-studio-17.0.2.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-source.c -> obs-studio-18.0.0.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-source.c
Changed
obs_data_set_default_bool(settings, "clear_on_media_end", true);
obs_data_set_default_bool(settings, "restart_on_activate", true);
obs_data_set_default_bool(settings, "force_scale", true);
-#if defined(_WIN32) || defined(__APPLE__)
+#if defined(_WIN32)
obs_data_set_default_bool(settings, "hw_decode", true);
#endif
}
obs-studio-17.0.2.tar.xz/plugins/obs-filters/CMakeLists.txt -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/CMakeLists.txt
Changed
scroll-filter.c
chroma-key-filter.c
color-key-filter.c
+ color-grade-filter.c
sharpness-filter.c
gain-filter.c
noise-gate-filter.c
- mask-filter.c)
+ mask-filter.c
+ compressor-filter.c)
add_library(obs-filters MODULE
${obs-filters_SOURCES}
obs-studio-17.0.2.tar.xz/plugins/obs-filters/color-correction-filter.c -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/color-correction-filter.c
Changed
struct vec3 half_unit;
};
-const static float root3 = 0.57735f;
-const static float red_weight = 0.299f;
-const static float green_weight = 0.587f;
-const static float blue_weight = 0.114f;
-
+static const float root3 = 0.57735f;
+static const float red_weight = 0.299f;
+static const float green_weight = 0.587f;
+static const float blue_weight = 0.114f;
/*
* As the functions' namesake, this provides the internal name of your Filter,
obs-studio-18.0.0.tar.xz/plugins/obs-filters/color-grade-filter.c
Added
+#include <obs-module.h>
+#include <graphics/image-file.h>
+#include <util/dstr.h>
+
+#define SETTING_IMAGE_PATH "image_path"
+#define SETTING_CLUT_AMOUNT "clut_amount"
+
+#define TEXT_IMAGE_PATH obs_module_text("Path")
+#define TEXT_AMOUNT obs_module_text("Amount")
+
+struct lut_filter_data {
+ obs_source_t *context;
+ gs_effect_t *effect;
+ gs_texture_t *target;
+ gs_image_file_t image;
+
+ char *file;
+ float clut_amount;
+};
+
+static const char *color_grade_filter_get_name(void *unused)
+{
+ UNUSED_PARAMETER(unused);
+ return obs_module_text("ColorGradeFilter");
+}
+
+static void color_grade_filter_update(void *data, obs_data_t *settings)
+{
+ struct lut_filter_data *filter = data;
+
+ const char *path = obs_data_get_string(settings, SETTING_IMAGE_PATH);
+ double clut_amount = obs_data_get_double(settings, SETTING_CLUT_AMOUNT);
+
+ bfree(filter->file);
+ if (path)
+ filter->file = bstrdup(path);
+
+ obs_enter_graphics();
+ gs_image_file_free(&filter->image);
+ obs_leave_graphics();
+
+ gs_image_file_init(&filter->image, path);
+
+ obs_enter_graphics();
+
+ gs_image_file_init_texture(&filter->image);
+
+ filter->target = filter->image.texture;
+ filter->clut_amount = (float)clut_amount;
+
+ char *effect_path = obs_module_file("color_grade_filter.effect");
+ gs_effect_destroy(filter->effect);
+ filter->effect = gs_effect_create_from_file(effect_path, NULL);
+ bfree(effect_path);
+
+ obs_leave_graphics();
+}
+
+static void color_grade_filter_defaults(obs_data_t *settings)
+{
+ obs_data_set_default_double(settings, SETTING_CLUT_AMOUNT, 1);
+}
+
+static obs_properties_t *color_grade_filter_properties(void *data)
+{
+ struct lut_filter_data *s = data;
+ struct dstr path = {0};
+ const char *slash;
+
+ obs_properties_t *props = obs_properties_create();
+ struct dstr filter_str = {0};
+
+ dstr_cat(&filter_str, "(*.png)");
+
+ if (s && s->file && *s->file) {
+ dstr_copy(&path, s->file);
+ } else {
+ dstr_copy(&path, obs_module_file("LUTs"));
+ dstr_cat_ch(&path, '/');
+ }
+
+ dstr_replace(&path, "\\", "/");
+ slash = strrchr(path.array, '/');
+ if (slash)
+ dstr_resize(&path, slash - path.array + 1);
+
+ obs_properties_add_path(props, SETTING_IMAGE_PATH, TEXT_IMAGE_PATH,
+ OBS_PATH_FILE, filter_str.array, path.array);
+ obs_properties_add_float_slider(props, SETTING_CLUT_AMOUNT,
+ TEXT_AMOUNT, 0, 1, 0.01);
+
+ dstr_free(&filter_str);
+
+ UNUSED_PARAMETER(data);
+ return props;
+}
+
+static void *color_grade_filter_create(
+ obs_data_t *settings, obs_source_t *context)
+{
+ struct lut_filter_data *filter =
+ bzalloc(sizeof(struct lut_filter_data));
+ filter->context = context;
+
+ obs_source_update(context, settings);
+ return filter;
+}
+
+static void color_grade_filter_destroy(void *data)
+{
+ struct lut_filter_data *filter = data;
+
+ obs_enter_graphics();
+ gs_effect_destroy(filter->effect);
+ gs_image_file_free(&filter->image);
+ obs_leave_graphics();
+
+ bfree(filter->file);
+ bfree(filter);
+}
+
+static void color_grade_filter_render(void *data, gs_effect_t *effect)
+{
+ struct lut_filter_data *filter = data;
+ obs_source_t *target = obs_filter_get_target(filter->context);
+ gs_eparam_t *param;
+
+ if (!target || !filter->target || !filter->effect) {
+ obs_source_skip_video_filter(filter->context);
+ return;
+ }
+
+ if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
+ OBS_ALLOW_DIRECT_RENDERING))
+ return;
+
+ param = gs_effect_get_param_by_name(filter->effect, "clut");
+ gs_effect_set_texture(param, filter->target);
+
+ param = gs_effect_get_param_by_name(filter->effect, "clut_amount");
+ gs_effect_set_float(param, filter->clut_amount);
+
+ obs_source_process_filter_end(filter->context, filter->effect, 0, 0);
+
+ UNUSED_PARAMETER(effect);
+}
+
+struct obs_source_info color_grade_filter = {
+ .id = "clut_filter",
+ .type = OBS_SOURCE_TYPE_FILTER,
+ .output_flags = OBS_SOURCE_VIDEO,
+ .get_name = color_grade_filter_get_name,
+ .create = color_grade_filter_create,
+ .destroy = color_grade_filter_destroy,
+ .update = color_grade_filter_update,
+ .get_defaults = color_grade_filter_defaults,
+ .get_properties = color_grade_filter_properties,
+ .video_render = color_grade_filter_render
+};
obs-studio-18.0.0.tar.xz/plugins/obs-filters/compressor-filter.c
Added
+#include <stdint.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include <obs-module.h>
+#include <media-io/audio-math.h>
+
+/* -------------------------------------------------------- */
+
+#define do_log(level, format, ...) \
+ blog(level, "[compressor: '%s'] " format, \
+ obs_source_get_name(cd->context), ##__VA_ARGS__)
+
+#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
+#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
+
+#ifdef _DEBUG
+#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
+#else
+#define debug(format, ...)
+#endif
+
+/* -------------------------------------------------------- */
+
+#define S_RATIO "ratio"
+#define S_THRESHOLD "threshold"
+#define S_ATTACK_TIME "attack_time"
+#define S_RELEASE_TIME "release_time"
+#define S_OUTPUT_GAIN "output_gain"
+
+#define MT_ obs_module_text
+#define TEXT_RATIO MT_("Compressor.Ratio")
+#define TEXT_THRESHOLD MT_("Compressor.Threshold")
+#define TEXT_ATTACK_TIME MT_("Compressor.AttackTime")
+#define TEXT_RELEASE_TIME MT_("Compressor.ReleaseTime")
+#define TEXT_OUTPUT_GAIN MT_("Compressor.OutputGain")
+
+#define MIN_RATIO 1.0f
+#define MAX_RATIO 32.0f
+#define MIN_THRESHOLD_DB -60.0f
+#define MAX_THRESHOLD_DB 0.0f
+#define MIN_OUTPUT_GAIN_DB -32.0f
+#define MAX_OUTPUT_GAIN_DB 32.0f
+#define MIN_ATK_RLS_MS 1
+#define MAX_RLS_MS 1000
+#define MAX_ATK_MS 500
+#define DEFAULT_AUDIO_BUF_MS 10
+
+#define MS_IN_S 1000
+#define MS_IN_S_F ((float)MS_IN_S)
+
+/* -------------------------------------------------------- */
+
+struct compressor_data {
+ obs_source_t *context;
+ float *envelope_buf;
+ size_t envelope_buf_len;
+
+ float ratio;
+ float threshold;
+ float attack_gain;
+ float release_gain;
+ float output_gain;
+
+ size_t num_channels;
+ float envelope;
+ float slope;
+};
+
+/* -------------------------------------------------------- */
+
+static inline void resize_env_buffer(struct compressor_data *cd, size_t len)
+{
+ cd->envelope_buf_len = len;
+ cd->envelope_buf = brealloc(cd->envelope_buf, len * sizeof(float));
+}
+
+static inline float gain_coefficient(uint32_t sample_rate, float time)
+{
+ return (float)exp(-1.0f / (sample_rate * time));
+}
+
+static const char *compressor_name(void *unused)
+{
+ UNUSED_PARAMETER(unused);
+ return obs_module_text("Compressor");
+}
+
+static void compressor_update(void *data, obs_data_t *s)
+{
+ struct compressor_data *cd = data;
+
+ const uint32_t sample_rate =
+ audio_output_get_sample_rate(obs_get_audio());
+ const size_t num_channels =
+ audio_output_get_channels(obs_get_audio());
+ const float attack_time_ms =
+ (float)obs_data_get_int(s, S_ATTACK_TIME);
+ const float release_time_ms =
+ (float)obs_data_get_int(s, S_RELEASE_TIME);
+ const float output_gain_db =
+ (float)obs_data_get_double(s, S_OUTPUT_GAIN);
+
+ if (cd->envelope_buf_len <= 0) {
+ resize_env_buffer(cd,
+ sample_rate * DEFAULT_AUDIO_BUF_MS / MS_IN_S);
+ }
+
+ cd->ratio = (float)obs_data_get_double(s, S_RATIO);
+ cd->threshold = (float)obs_data_get_double(s, S_THRESHOLD);
+ cd->attack_gain = gain_coefficient(sample_rate,
+ attack_time_ms / MS_IN_S_F);
+ cd->release_gain = gain_coefficient(sample_rate,
+ release_time_ms / MS_IN_S_F);
+ cd->output_gain = db_to_mul(output_gain_db);
+ cd->num_channels = num_channels;
+ cd->slope = 1.0f - (1.0f / cd->ratio);
+}
+
+static void *compressor_create(obs_data_t *settings, obs_source_t *filter)
+{
+ struct compressor_data *cd = bzalloc(sizeof(struct compressor_data));
+ cd->context = filter;
+ compressor_update(cd, settings);
+ return cd;
+}
+
+static void compressor_destroy(void *data)
+{
+ struct compressor_data *cd = data;
+ bfree(cd->envelope_buf);
+ bfree(cd);
+}
+
+static inline void analyze_envelope(struct compressor_data *cd,
+ const float **samples, const uint32_t num_samples)
+{
+ if (cd->envelope_buf_len < num_samples) {
+ resize_env_buffer(cd, num_samples);
+ }
+
+ memset(cd->envelope_buf, 0, num_samples * sizeof(cd->envelope_buf[0]));
+ for (size_t chan = 0; chan < cd->num_channels; ++chan) {
+ if (samples[chan]) {
+ float env = cd->envelope;
+ for (uint32_t i = 0; i < num_samples; ++i) {
+ const float env_in = fabsf(samples[chan][i]);
+ if (env < env_in) {
+ env = env_in + cd->attack_gain *
+ (env - env_in);
+ } else {
+ env = env_in + cd->release_gain *
+ (env - env_in);
+ }
+ cd->envelope_buf[i] = fmaxf(
+ cd->envelope_buf[i], env);
+ }
+ }
+ }
+ cd->envelope = cd->envelope_buf[num_samples - 1];
+}
+
+static inline void process_compression(const struct compressor_data *cd,
+ float **samples, uint32_t num_samples)
+{
+ for (size_t i = 0; i < num_samples; ++i) {
+ const float env_db = mul_to_db(cd->envelope_buf[i]);
+ float gain = cd->slope * (cd->threshold - env_db);
+ gain = db_to_mul(fminf(0, gain));
+
+ for (size_t c = 0; c < cd->num_channels; ++c) {
+ if (samples[c]) {
+ samples[c][i] *= gain * cd->output_gain;
+ }
+ }
+ }
+}
+
+static struct obs_audio_data *compressor_filter_audio(void *data,
+ struct obs_audio_data *audio)
+{
+ struct compressor_data *cd = data;
+ const uint32_t num_samples = audio->frames;
+ float **samples = (float**)audio->data;
+
+ analyze_envelope(cd, samples, num_samples);
+ process_compression(cd, samples, num_samples);
+
+ return audio;
+}
+
+static void compressor_defaults(obs_data_t *s)
+{
+ obs_data_set_default_double(s, S_RATIO, 10.0f);
+ obs_data_set_default_double(s, S_THRESHOLD, -18.0f);
+ obs_data_set_default_int(s, S_ATTACK_TIME, 6);
+ obs_data_set_default_int(s, S_RELEASE_TIME, 60);
+ obs_data_set_default_double(s, S_OUTPUT_GAIN, 0.0f);
+}
+
+static obs_properties_t *compressor_properties(void *data)
+{
+ obs_properties_t *props = obs_properties_create();
+
+ obs_properties_add_float_slider(props, S_RATIO,
+ TEXT_RATIO, MIN_RATIO, MAX_RATIO, 0.5f);
+ obs_properties_add_float_slider(props, S_THRESHOLD,
+ TEXT_THRESHOLD, MIN_THRESHOLD_DB, MAX_THRESHOLD_DB, 0.1f);
+ obs_properties_add_int_slider(props, S_ATTACK_TIME,
+ TEXT_ATTACK_TIME, MIN_ATK_RLS_MS, MAX_ATK_MS, 1);
+ obs_properties_add_int_slider(props, S_RELEASE_TIME,
+ TEXT_RELEASE_TIME, MIN_ATK_RLS_MS, MAX_RLS_MS, 1);
+ obs_properties_add_float_slider(props, S_OUTPUT_GAIN,
+ TEXT_OUTPUT_GAIN, MIN_OUTPUT_GAIN_DB, MAX_OUTPUT_GAIN_DB, 0.1f);
+
+ UNUSED_PARAMETER(data);
+ return props;
+}
+
+struct obs_source_info compressor_filter = {
+ .id = "compressor_filter",
+ .type = OBS_SOURCE_TYPE_FILTER,
+ .output_flags = OBS_SOURCE_AUDIO,
+ .get_name = compressor_name,
+ .create = compressor_create,
+ .destroy = compressor_destroy,
+ .update = compressor_update,
+ .filter_audio = compressor_filter_audio,
+ .get_defaults = compressor_defaults,
+ .get_properties = compressor_properties,
+};
obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/LUTs
Added
+(directory)
obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/color_grade_filter.effect
Added
+uniform float4x4 ViewProj;
+uniform texture2d image;
+
+uniform texture2d clut;
+uniform float clut_amount;
+
+sampler_state textureSampler {
+ Filter = Linear;
+ AddressU = Clamp;
+ AddressV = Clamp;
+};
+
+struct VertDataIn {
+ float4 pos : POSITION;
+ float2 uv : TEXCOORD0;
+};
+
+struct VertDataOut {
+ float4 pos : POSITION;
+ float2 uv : TEXCOORD0;
+};
+
+VertDataOut VSDefault(VertDataIn v_in)
+{
+ VertDataOut vert_out;
+ vert_out.uv = v_in.uv;
+ vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
+ return vert_out;
+}
+
+float4 LUT(VertDataOut v_in) : TARGET
+{
+ float4 textureColor = image.Sample(textureSampler, v_in.uv);
+ float blueColor = textureColor.b * 63.0;
+
+ float2 quad1;
+ quad1.y = floor(floor(blueColor) / 8.0);
+ quad1.x = floor(blueColor) - (quad1.y * 8.0);
+
+ float2 quad2;
+ quad2.y = floor(ceil(blueColor) / 8.0);
+ quad2.x = ceil(blueColor) - (quad2.y * 8.0);
+
+ float2 texPos1;
+ texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
+ texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);
+
+ float2 texPos2;
+ texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
+ texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);
+
+ float4 newColor1 = clut.Sample(textureSampler, texPos1);
+ float4 newColor2 = clut.Sample(textureSampler, texPos2);
+ float4 luttedColor = lerp(newColor1, newColor2, frac(blueColor));
+
+ return lerp(textureColor, luttedColor, clut_amount);
+}
+
+technique Draw
+{
+ pass
+ {
+ vertex_shader = VSDefault(v_in);
+ pixel_shader = LUT(v_in);
+ }
+}
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/ca-ES.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/ca-ES.ini
Changed
ColorFilter="Correcció de color"
+ColorGradeFilter="Aplica LUT"
MaskFilter="Màscara d'imatge o barreja"
AsyncDelayFilter="Retard del vídeo (asíncron)"
CropFilter="Escapça/Encoixinar"
ColorKeyFilter="Clau de color"
SharpnessFilter="Agudesa"
ScaleFilter="Escala/Relació d'Aspecte"
+UndistortCenter="No distorsionis el centre de la imatge en escalar des d'una ultrapanoràmica"
NoiseGate="Porta de soroll"
NoiseSuppress="Supressió de soroll"
Gain="Guany"
NoiseSuppress.SuppressLevel="Nivell de supressió (dB)"
Saturation="Saturació"
HueShift="Cavi de tonalitat"
+Amount="Quantitat"
+Compressor="Compressor"
+Compressor.Ratio="Proporció (X:1)"
+Compressor.Threshold="Llindar (dB)"
+Compressor.AttackTime="Atac (ms)"
+Compressor.ReleaseTime="Llançament (ms)"
+Compressor.OutputGain="Guany de sortida (dB)"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/cs-CZ.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/cs-CZ.ini
Changed
ColorFilter="Korekce barev"
+ColorGradeFilter="Použít LUT"
MaskFilter="Maska obrazu/prolnutí"
AsyncDelayFilter="Zpoždění obrazu"
CropFilter="Oříznutí/odsazení"
ColorKeyFilter="Klíč barvy"
SharpnessFilter="Ostření"
ScaleFilter="Škálování/poměr stran"
+UndistortCenter="Zlepší střed obrázku při škálování z ultra-širokého obrazu"
NoiseGate="Šumová brána"
NoiseSuppress="Potlačení šumu"
Gain="Zisk"
NoiseSuppress.SuppressLevel="Úroveň potlačení (dB)"
Saturation="Saturace"
HueShift="Posun odstínu"
+Amount="Množství"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/da-DK.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/da-DK.ini
Changed
ColorFilter="Farvekorrektion"
+ColorGradeFilter="Anvend LUT"
MaskFilter="Billede maske/blanding"
AsyncDelayFilter="Video forsinkelse (asynkron)"
CropFilter="Beskæring/Polstring"
ColorKeyFilter="Farvenøgle"
SharpnessFilter="Skarphed"
ScaleFilter="Skalering/Formatforhold"
+UndistortCenter="Fjern forvrængning af billedets midte ved skalering fra ultrabred"
NoiseGate="Noise Gate"
NoiseSuppress="Støjundertrykkelse"
Gain="Forstærkning"
NoiseSuppress.SuppressLevel="Undertrykkelsesniveau (dB)"
Saturation="Mætning"
HueShift="Nuanceskift"
+Amount="Værdi"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/de-DE.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/de-DE.ini
Changed
ColorFilter="Farbkorrektur"
+ColorGradeFilter="LUT anwenden"
MaskFilter="Bild Maske/Blend"
AsyncDelayFilter="Videoverzögerung (Asynchron)"
CropFilter="Zuschneiden/Pad"
ColorKeyFilter="Color Key"
SharpnessFilter="Schärfen"
ScaleFilter="Skalierung/Seitenverhältnis"
+UndistortCenter="Entzerre Mitte des Bildes bei der Skalierung von Ultraweitwinkel"
NoiseGate="Noise Gate"
NoiseSuppress="Rauschunterdrückung"
Gain="Gain"
NoiseSuppress.SuppressLevel="Unterdrückungspegel (dB)"
Saturation="Sättigung"
HueShift="Farbtonverschiebung"
+Amount="Betrag"
+Compressor="Kompressor"
+Compressor.Ratio="Verhältnis (X:1)"
+Compressor.Threshold="Schwelle (dB)"
+Compressor.AttackTime="Angriff (ms)"
+Compressor.ReleaseTime="Freigabe (ms)"
+Compressor.OutputGain="Ausgangspegel (dB)"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/en-US.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/en-US.ini
Changed
ColorFilter="Color Correction"
+ColorGradeFilter="Apply LUT"
MaskFilter="Image Mask/Blend"
AsyncDelayFilter="Video Delay (Async)"
CropFilter="Crop/Pad"
ColorKeyFilter="Color Key"
SharpnessFilter="Sharpen"
ScaleFilter="Scaling/Aspect Ratio"
+UndistortCenter="Undistort center of image when scaling from ultrawide"
NoiseGate="Noise Gate"
NoiseSuppress="Noise Suppression"
Gain="Gain"
NoiseSuppress.SuppressLevel="Suppression Level (dB)"
Saturation="Saturation"
HueShift="Hue Shift"
+Amount="Amount"
+Compressor="Compressor"
+Compressor.Ratio="Ratio (X:1)"
+Compressor.Threshold="Threshold (dB)"
+Compressor.AttackTime="Attack (ms)"
+Compressor.ReleaseTime="Release (ms)"
+Compressor.OutputGain="Output Gain (dB)"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/es-ES.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/es-ES.ini
Changed
ColorFilter="Corrección de color"
+ColorGradeFilter="Aplicar LUT"
MaskFilter="Imagen máscara/mezcla"
AsyncDelayFilter="Demora de Video (asincróno)"
CropFilter="Recortar/Acolchar"
ColorKeyFilter="Filtro de color"
SharpnessFilter="Filtro de enfoque"
ScaleFilter="Escala/Relación de Aspecto"
+UndistortCenter="No distorsionar el centro de la imagen en escalar des de una ultrapanorámica"
NoiseGate="Puerta anti-ruidos"
NoiseSuppress="Eliminación de ruido"
Gain="Ganancia"
NoiseSuppress.SuppressLevel="Nivel de eliminación de ruido (dB)"
Saturation="Saturación"
HueShift="Cambio de tonalidad"
+Amount="Cantidad"
+Compressor="Compresor"
+Compressor.Ratio="Relación (X:1)"
+Compressor.Threshold="Umbral (dB)"
+Compressor.AttackTime="Ataque (ms)"
+Compressor.ReleaseTime="Liberación (ms)"
+Compressor.OutputGain="Ganancia de salida (dB)"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/eu-ES.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/eu-ES.ini
Changed
ColorFilter="Kolore-zuzenketa"
+ColorGradeFilter="Aplikatu LUT"
MaskFilter="Irudi maskara/nahasketa"
AsyncDelayFilter="Bideo atzerapena (Async)"
CropFilter="Moztu/Bete"
ColorKeyFilter="Kolore gakoa"
SharpnessFilter="Enfokea"
ScaleFilter="Eskala/Aspektu-erlazioa"
+UndistortCenter="Ez distortsionatu irudiaren erdigunea ultra zabala eskalatzean"
NoiseGate="Zarata atalasea"
NoiseSuppress="Zarata kendu"
Gain="Irabazia"
NoiseSuppress.SuppressLevel="Kenketaren maila (dB)"
Saturation="Margoasetasuna"
HueShift="Nabardura Aldaketa"
+Amount="Zenbatekoa"
+Compressor="Konprimitzailea"
+Compressor.Ratio="Erlazioa (X:1)"
+Compressor.Threshold="Atalasea (dB)"
+Compressor.AttackTime="Erasoa (ms)"
+Compressor.ReleaseTime="Askapena (ms)"
+Compressor.OutputGain="Irteerako irabazia (dB)"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/fi-FI.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/fi-FI.ini
Changed
ColorFilter="Värinkorjaus"
+ColorGradeFilter="Käytä LUT"
MaskFilter="Kuvamaski/Sekoitus"
AsyncDelayFilter="Kuvan viive (Async)"
CropFilter="Rajaa"
ColorKeyFilter="Väriavain"
SharpnessFilter="Terävöitä"
ScaleFilter="Skaalaus/Kuvasuhde"
+UndistortCenter="Poista vääristymä keskeltä kuvaa skaalattaessa ultra-leveästä"
NoiseGate="Noise Gate"
NoiseSuppress="Melunvaimennus"
Gain="Vahvistus"
NoiseSuppress.SuppressLevel="Vaimennustaso (dB)"
Saturation="Värikylläisyys"
HueShift="Värisävy"
+Amount="Määrä"
+Compressor="Kompressori"
+Compressor.Ratio="Suhde (X:1)"
+Compressor.Threshold="Kynnysarvo (dB)"
+Compressor.AttackTime="Attack-aika (ms)"
+Compressor.ReleaseTime="Vapautumisaika (ms)"
+Compressor.OutputGain="Signaalin vahvistus (dB)"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/fr-FR.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/fr-FR.ini
Changed
ColorFilter="Corrections colorimétrique"
+ColorGradeFilter="Appliquer LUT"
MaskFilter="Masque d'image/mélange"
AsyncDelayFilter="Retard vidéo (async.)"
CropFilter="Rogner / Encadrer"
ColorKeyFilter="Couleur d'incrustation"
SharpnessFilter="Accentuer"
ScaleFilter="Mise à l’échelle / Ratio d'affichage"
+UndistortCenter="Ne pas déformer le centre de l'image lors d'une mise à l'échelle ultra large"
NoiseGate="Noise Gate"
NoiseSuppress="Suppression du bruit"
Gain="Gain"
NoiseSuppress.SuppressLevel="Seuil de suppression (en dB)"
Saturation="Saturation"
HueShift="Décalage de teinte"
+Amount="Quantité"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/hu-HU.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/hu-HU.ini
Changed
ColorFilter="Színkorrekció"
+ColorGradeFilter="LUT alkalmazása"
MaskFilter="Képmaszk/Keverés"
AsyncDelayFilter="Videó késleltetés (Async)"
CropFilter="Vágás/Margó"
ColorKeyFilter="Színkulcs"
SharpnessFilter="Élesítés"
ScaleFilter="Méretezés/Képarány"
+UndistortCenter="Kép közepének zavarosságának a csökkentése ultraszélesről való skálázás esetén"
NoiseGate="Zajgát"
NoiseSuppress="Zajcsökkentés"
Gain="Erősítés"
NoiseSuppress.SuppressLevel="Csökkentési szint (dB)"
Saturation="Telítettség"
HueShift="Színezet váltása"
+Amount="Mennyiség"
+Compressor="Kompresszor"
+Compressor.Ratio="Arány (X:1)"
+Compressor.Threshold="Küszöb (dB)"
+Compressor.AttackTime="Aktiválás (ms)"
+Compressor.ReleaseTime="Felengedés (ms)"
+Compressor.OutputGain="Kimeneti erősítés (dB)"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/ja-JP.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/ja-JP.ini
Changed
ColorFilter="色補正"
+ColorGradeFilter="LUT を適用"
MaskFilter="イメージ マスク/ブレンド"
AsyncDelayFilter="映像の遅延 (非同期)"
CropFilter="クロップ/パッド"
ColorKeyFilter="カラーキー"
SharpnessFilter="シャープ"
ScaleFilter="スケーリング/アスペクト比"
+UndistortCenter="超広角からスケーリングするときに画像の中心を歪めない"
NoiseGate="ノイズゲート"
NoiseSuppress="ノイズ抑制"
Gain="ゲイン"
NoiseSuppress.SuppressLevel="抑制レベル (dB)"
Saturation="彩度"
HueShift="色相シフト"
+Amount="量"
+Compressor="コンプレッサー"
+Compressor.Ratio="比率 (X:1)"
+Compressor.Threshold="閾値 (dB)"
+Compressor.AttackTime="アタックタイム (ms)"
+Compressor.ReleaseTime="リリースタイム (ms)"
+Compressor.OutputGain="出力ゲイン (dB)"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/ko-KR.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/ko-KR.ini
Changed
ColorFilter="색상 보정"
+ColorGradeFilter="LUT 적용"
MaskFilter="이미지 마스크/혼합"
AsyncDelayFilter="비디오 지연 (비동기)"
CropFilter="자르기/덧대기"
ColorKeyFilter="색상 키"
SharpnessFilter="선명하게"
ScaleFilter="비례축소/가로세로 비율"
+UndistortCenter="울트라와이드에서 크기조정 시 이미지 중앙의 왜곡을 수정"
NoiseGate="노이즈 게이트"
NoiseSuppress="소음 억제"
Gain="증폭"
NoiseSuppress.SuppressLevel="억제 세기 (dB)"
Saturation="채도"
HueShift="색조 변화"
+Amount="양"
+Compressor="압축방식"
+Compressor.Ratio="비율 (X:1)"
+Compressor.Threshold="임계값 (dB)"
+Compressor.AttackTime="신호 감지 후 반응까지 걸리는 시간 (ms)"
+Compressor.ReleaseTime="신호 세기가 감퇴 이후 증폭이 회복하는 시간 (ms)"
+Compressor.OutputGain="출력 증폭 (dB)"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/nb-NO.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/nb-NO.ini
Changed
ChromaKeyFilter="Chromafilter"
ColorKeyFilter="Fargefilter"
SharpnessFilter="Skjerpe"
+ScaleFilter="Skalering/Aspekt Forhold"
NoiseGate="Støyterskel"
+NoiseSuppress="Lyddemping"
Gain="Forsterkning"
DelayMs="Forsinkelse (millisekunder)"
Type="Type"
StretchImage="Strekk bilde (ignorer bildets sideforhold)"
Resolution="Oppløsning"
None="Ingen"
+ScaleFiltering="Skala Filtrering"
+ScaleFiltering.Point="Punkt"
+NoiseSuppress.SuppressLevel="Dempelse Nivå (dB)"
+Saturation="Metning"
+HueShift="Fargetone Skifte"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/nl-NL.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/nl-NL.ini
Changed
ColorFilter="Kleurcorrectie"
+ColorGradeFilter="LUT Toepassen"
MaskFilter="Afbeeldingsmasker/Mengen"
AsyncDelayFilter="Videovertraging (Async)"
CropFilter="Bijsnijden/Aanvullen"
ColorKeyFilter="Color Key"
SharpnessFilter="Verscherpen"
ScaleFilter="Schalen/Aspect Ratio"
+UndistortCenter="Verbeter beeldverhouding in het midden van bij schalen vanaf ultrawide"
NoiseGate="Noise Gate"
NoiseSuppress="Ruisonderdrukking"
Gain="Gain"
NoiseSuppress.SuppressLevel="Onderdrukkingsniveau (dB)"
Saturation="Verzadiging"
HueShift="Tintverschuiving"
+Amount="Hoeveelheid"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/pl-PL.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/pl-PL.ini
Changed
ColorFilter="Korekcja Kolorów"
+ColorGradeFilter="Look-Up Tables (LUT)"
MaskFilter="Maskowanie/nakładanie obrazu"
AsyncDelayFilter="Opóźnienie wideo (asynchronicznie)"
CropFilter="Przytnij/Uzupełnij"
ColorKeyFilter="Kluczowanie koloru (kolor)"
SharpnessFilter="Wyostrzanie"
ScaleFilter="Skalowanie/proporcje"
+UndistortCenter="Usuń przekłamania przy skalowaniu źródeł o dużej szerokości"
NoiseGate="Bramka szumów"
NoiseSuppress="Tłumienie hałasu"
Gain="Poziom"
NoiseSuppress.SuppressLevel="Poziom tłumienia (dB)"
Saturation="Nasycenie"
HueShift="Przesunięcie barwy"
+Amount="Pozion"
+Compressor="Kompresor"
+Compressor.Ratio="Stosunek (X:1)"
+Compressor.Threshold="Próg (dB)"
+Compressor.AttackTime="Atak (ms)"
+Compressor.ReleaseTime="Odpuszczenie (ms)"
+Compressor.OutputGain="Zysk na wyjściu (dB)"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/ro-RO.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/ro-RO.ini
Changed
ChromaKeyFilter="Cheie chroma"
ColorKeyFilter="Culoare cheie"
SharpnessFilter="Accentuare"
+ScaleFilter="Scalare/Rație Aspect"
NoiseGate="Poartă de zgomot"
Gain="Amplificare"
DelayMs="Întârziere (milisecunde)"
NoiseGate.ReleaseTime="Timp de eliberare (milisecunde)"
Gain.GainDB="Amplificare (dB)"
StretchImage="Întinde imaginea (renunță la raportul de aspect al imaginii)"
+Resolution="Rezoluție"
+None="Fără"
+ScaleFiltering.Bilinear="Biliniar"
+ScaleFiltering.Bicubic="Bicubic"
+ScaleFiltering.Lanczos="Lanczos"
+Saturation="Saturație"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/ru-RU.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/ru-RU.ini
Changed
ColorFilter="Коррекция цвета"
+ColorGradeFilter="Применить LUT"
MaskFilter="Маска изображения/Смешивание"
AsyncDelayFilter="Задержка видео (асинхронность)"
CropFilter="Кадрировать"
ColorKeyFilter="Цветовой ключ"
SharpnessFilter="Увеличить резкость"
ScaleFilter="Коэффициент Масштабирования/Аспект"
+UndistortCenter="Не искривлять центр изображения при масштабировании Ultrawide разрешения"
NoiseGate="Подавление шума"
NoiseSuppress="Шумоподавление"
Gain="Усиление"
NoiseSuppress.SuppressLevel="Уровень подавления (дБ)"
Saturation="Насыщенность"
HueShift="Сдвиг оттенка"
+Amount="Количество"
+Compressor="Компрессор"
+Compressor.Ratio="Степень сжатия (X:1)"
+Compressor.Threshold="Порог срабатывания (дБ)"
+Compressor.AttackTime="Атака (мс)"
+Compressor.ReleaseTime="Спад (мс)"
+Compressor.OutputGain="Выходное усиление (дБ)"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/sv-SE.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/sv-SE.ini
Changed
ColorFilter="Färgkorrigering"
+ColorGradeFilter="Tillämpa LUT"
MaskFilter="Bild Mask/Blandning"
AsyncDelayFilter="Videofördröjning (Async)"
CropFilter="Beskär/Fyll ut"
ScaleFiltering.Lanczos="Lanczos"
NoiseSuppress.SuppressLevel="Brusreduceringsnivå (dB)"
Saturation="Mättnad"
+HueShift="Nyansväxling"
+Amount="Mängd"
+Compressor="Kompressor"
+Compressor.Ratio="Förhållande (X:1)"
+Compressor.Threshold="Tröskel (dB)"
+Compressor.AttackTime="Attack (ms)"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/uk-UA.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/uk-UA.ini
Changed
ColorFilter="Коригування кольору"
+ColorGradeFilter="Таблиці підстановки кольору"
MaskFilter="Маска до зображення"
AsyncDelayFilter="Затримка відео (асинхронна)"
CropFilter="Кадрування"
ColorKeyFilter="Фільтрування за кольором"
SharpnessFilter="Різкість"
ScaleFilter="Масштабування/пропорції"
+UndistortCenter="Зменшити викривлення у центрі, якщо масштабувати з надширокоформатного"
NoiseGate="Пороговий шумопонижувач"
NoiseSuppress="Подавлення шуму"
Gain="Підсилення"
NoiseGate.OpenThreshold="Поріг відкриття (дБ)"
NoiseGate.CloseThreshold="Поріг закриття (дБ)"
NoiseGate.AttackTime="Тривалість фронту сигналу (мілісекунд)"
-NoiseGate.HoldTime="Тривалість сигналу (мілісекунд)"
+NoiseGate.HoldTime="Тривалість втримання сигналу (мілісекунд)"
NoiseGate.ReleaseTime="Тривалість спаду сигналу (мілісекунд)"
Gain.GainDB="Підсилення (дБ)"
StretchImage="Розтягнути зображення (ігнорувати пропорції зображення)"
NoiseSuppress.SuppressLevel="Рівень подавлення (дБ)"
Saturation="Насиченість"
HueShift="Відтінок"
+Amount="Обсяг впливу"
+Compressor="Компресор"
+Compressor.Ratio="Відношення (X:1)"
+Compressor.Threshold="Поріг (дБ)"
+Compressor.AttackTime="Атака (мс)"
+Compressor.ReleaseTime="Затухання (мс)"
+Compressor.OutputGain="Підсилення виводу (dB)"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/zh-CN.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/zh-CN.ini
Changed
ColorFilter="色彩校正"
+ColorGradeFilter="应用 LUT"
MaskFilter="图像掩码/混合"
AsyncDelayFilter="视频延迟(异步)"
CropFilter="裁剪/填充"
ColorKeyFilter="色值"
SharpnessFilter="锐化"
ScaleFilter="缩放比例"
+UndistortCenter="当从超宽扩展时, 让图片中心不失真"
NoiseGate="噪音阈值"
NoiseSuppress="噪声抑制"
Gain="增益"
NoiseSuppress.SuppressLevel="抑制程度 (dB)"
Saturation="饱和度"
HueShift="色调偏移"
+Amount="数值"
+Compressor="压缩器"
+Compressor.Ratio="比率 (X:1)"
+Compressor.Threshold="阈值 (dB)"
+Compressor.AttackTime="攻击 (ms)"
+Compressor.ReleaseTime="释放 (ms)"
+Compressor.OutputGain="输出增益 (dB)"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/data/locale/zh-TW.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/data/locale/zh-TW.ini
Changed
ColorFilter="色彩校正"
+ColorGradeFilter="使用色彩對照表"
MaskFilter="影像遮罩/混合"
AsyncDelayFilter="視頻延遲 (非同步)"
CropFilter="剪裁/填充"
ColorKeyFilter="色彩鍵"
SharpnessFilter="銳化"
ScaleFilter="縮放/長寬比"
+UndistortCenter="從超寬影像縮放時彌補影像中心的畸變"
NoiseGate="噪音閾"
NoiseSuppress="雜訊抑制"
Gain="增益"
NoiseSuppress.SuppressLevel="抑制標準 (dB)"
Saturation="飽合度"
HueShift="色調偏移"
+Amount="影響總量"
obs-studio-17.0.2.tar.xz/plugins/obs-filters/obs-filters.c -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/obs-filters.c
Changed
extern struct obs_source_info scale_filter;
extern struct obs_source_info scroll_filter;
extern struct obs_source_info color_key_filter;
+extern struct obs_source_info color_grade_filter;
extern struct obs_source_info sharpness_filter;
extern struct obs_source_info chroma_key_filter;
extern struct obs_source_info async_delay_filter;
extern struct obs_source_info noise_suppress_filter;
#endif
extern struct obs_source_info noise_gate_filter;
+extern struct obs_source_info compressor_filter;
bool obs_module_load(void)
{
obs_register_source(&scale_filter);
obs_register_source(&scroll_filter);
obs_register_source(&color_key_filter);
+ obs_register_source(&color_grade_filter);
obs_register_source(&sharpness_filter);
obs_register_source(&chroma_key_filter);
obs_register_source(&async_delay_filter);
obs_register_source(&noise_suppress_filter);
#endif
obs_register_source(&noise_gate_filter);
+ obs_register_source(&compressor_filter);
return true;
}
obs-studio-17.0.2.tar.xz/plugins/obs-filters/scale-filter.c -> obs-studio-18.0.0.tar.xz/plugins/obs-filters/scale-filter.c
Changed
#define S_RESOLUTION "resolution"
#define S_SAMPLING "sampling"
+#define S_UNDISTORT "undistort"
#define T_RESOLUTION obs_module_text("Resolution")
#define T_NONE obs_module_text("None")
#define T_SAMPLING_BILINEAR obs_module_text("ScaleFiltering.Bilinear")
#define T_SAMPLING_BICUBIC obs_module_text("ScaleFiltering.Bicubic")
#define T_SAMPLING_LANCZOS obs_module_text("ScaleFiltering.Lanczos")
+#define T_UNDISTORT obs_module_text("UndistortCenter")
#define S_SAMPLING_POINT "point"
#define S_SAMPLING_BILINEAR "bilinear"
gs_effect_t *effect;
gs_eparam_t *image_param;
gs_eparam_t *dimension_param;
+ gs_eparam_t *undistort_factor_param;
struct vec2 dimension_i;
+ double undistort_factor;
int cx_in;
int cy_in;
int cx_out;
bool aspect_ratio_only : 1;
bool target_valid : 1;
bool valid : 1;
+ bool undistort : 1;
};
static const char *scale_filter_name(void *unused)
} else { /* S_SAMPLING_BICUBIC */
filter->sampling = OBS_SCALE_BICUBIC;
}
+
+ filter->undistort = obs_data_get_bool(settings, S_UNDISTORT);
}
static void scale_filter_destroy(void *data)
cx_f = (double)cx;
cy_f = (double)cy;
- if (filter->aspect_ratio_only) {
- double old_aspect = cx_f / cy_f;
- double new_aspect =
- (double)filter->cx_in / (double)filter->cy_in;
+ double old_aspect = cx_f / cy_f;
+ double new_aspect =
+ (double)filter->cx_in / (double)filter->cy_in;
+ if (filter->aspect_ratio_only) {
if (fabs(old_aspect - new_aspect) <= EPSILON) {
filter->target_valid = false;
return;
1.0f / (float)cx,
1.0f / (float)cy);
+ if (filter->undistort) {
+ filter->undistort_factor = new_aspect / old_aspect;
+ } else {
+ filter->undistort_factor = 1.0;
+ }
+
/* ------------------------- */
lower_than_2x = filter->cx_out < cx / 2 || filter->cy_out < cy / 2;
filter->dimension_param = NULL;
}
+ if (type == OBS_EFFECT_BICUBIC || type == OBS_EFFECT_LANCZOS) {
+ filter->undistort_factor_param = gs_effect_get_param_by_name(
+ filter->effect, "undistort_factor");
+ }
+ else {
+ filter->undistort_factor_param = NULL;
+ }
+
UNUSED_PARAMETER(seconds);
}
static void scale_filter_render(void *data, gs_effect_t *effect)
{
struct scale_filter_data *filter = data;
+ const char *technique = filter->undistort ?
+ "DrawUndistort" : "Draw";
if (!filter->valid || !filter->target_valid) {
obs_source_skip_video_filter(filter->context);
gs_effect_set_vec2(filter->dimension_param,
&filter->dimension_i);
+ if (filter->undistort_factor_param)
+ gs_effect_set_float(filter->undistort_factor_param,
+ (float)filter->undistort_factor);
+
if (filter->sampling == OBS_SCALE_POINT)
gs_effect_set_next_sampler(filter->image_param,
filter->point_sampler);
- obs_source_process_filter_end(filter->context, filter->effect,
- filter->cx_out, filter->cy_out);
+ obs_source_process_filter_tech_end(filter->context, filter->effect,
+ filter->cx_out, filter->cy_out, technique);
UNUSED_PARAMETER(effect);
}
#define NUM_ASPECTS (sizeof(aspects) / sizeof(const char *))
+static bool sampling_modified(obs_properties_t *props, obs_property_t *p,
+ obs_data_t *settings)
+{
+ const char *sampling = obs_data_get_string(settings, S_SAMPLING);
+
+ bool has_undistort;
+ if (astrcmpi(sampling, S_SAMPLING_POINT) == 0) {
+ has_undistort = false;
+
+ }
+ else if (astrcmpi(sampling, S_SAMPLING_BILINEAR) == 0) {
+ has_undistort = false;
+
+ }
+ else if (astrcmpi(sampling, S_SAMPLING_LANCZOS) == 0) {
+ has_undistort = true;
+
+ }
+ else { /* S_SAMPLING_BICUBIC */
+ has_undistort = true;
+ }
+
+ obs_property_set_visible(obs_properties_get(props, S_UNDISTORT), has_undistort);
+
+ UNUSED_PARAMETER(p);
+ return true;
+}
+
static obs_properties_t *scale_filter_properties(void *data)
{
obs_properties_t *props = obs_properties_create();
p = obs_properties_add_list(props, S_SAMPLING, T_SAMPLING,
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
+ obs_property_set_modified_callback(p, sampling_modified);
obs_property_list_add_string(p, T_SAMPLING_POINT, S_SAMPLING_POINT);
obs_property_list_add_string(p, T_SAMPLING_BILINEAR, S_SAMPLING_BILINEAR);
obs_property_list_add_string(p, T_SAMPLING_BICUBIC, S_SAMPLING_BICUBIC);
obs_property_list_add_string(p, str, str);
}
+ obs_properties_add_bool(props, S_UNDISTORT, T_UNDISTORT);
+
/* ----------------- */
UNUSED_PARAMETER(data);
{
obs_data_set_default_string(settings, S_SAMPLING, S_SAMPLING_BICUBIC);
obs_data_set_default_string(settings, S_RESOLUTION, T_NONE);
+ obs_data_set_default_bool(settings, S_UNDISTORT, 0);
}
static uint32_t scale_filter_width(void *data)
obs-studio-17.0.2.tar.xz/plugins/obs-outputs/CMakeLists.txt -> obs-studio-18.0.0.tar.xz/plugins/obs-outputs/CMakeLists.txt
Changed
set(obs-outputs_HEADERS
obs-output-ver.h
rtmp-helpers.h
+ rtmp-stream.h
net-if.h
flv-mux.h
flv-output.h
set(obs-outputs_SOURCES
obs-outputs.c
rtmp-stream.c
+ rtmp-windows.c
flv-output.c
flv-mux.c
net-if.c)
obs-studio-17.0.2.tar.xz/plugins/obs-outputs/flv-output.c -> obs-studio-18.0.0.tar.xz/plugins/obs-outputs/flv-output.c
Changed
struct flv_output *stream = data;
if (stream->active) {
- if (stream->file)
+ if (stream->file) {
write_file_info(stream->file, stream->last_packet_ts,
os_ftelli64(stream->file));
- fclose(stream->file);
+ fclose(stream->file);
+ }
obs_output_end_data_capture(stream->output);
stream->active = false;
stream->sent_headers = false;
obs-studio-17.0.2.tar.xz/plugins/obs-outputs/librtmp/rtmp.c -> obs-studio-18.0.0.tar.xz/plugins/obs-outputs/librtmp/rtmp.c
Changed
r->Link.lFlags ^= RTMP_LF_FTCU;
}
+ memset (&r->m_bindIP, 0, sizeof(r->m_bindIP));
+ r->m_bCustomSend = 0;
+ r->m_customSendFunc = NULL;
+ r->m_customSendParam = NULL;
+
#if defined(CRYPTO) || defined(USE_ONLY_MD5)
if (!(r->Link.protocol & RTMP_FEATURE_WRITE) || (r->Link.pFlags & RTMP_PUB_CLEAN))
{
obs-studio-17.0.2.tar.xz/plugins/obs-outputs/rtmp-stream.c -> obs-studio-18.0.0.tar.xz/plugins/obs-outputs/rtmp-stream.c
Changed
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
-#include <obs-module.h>
-#include <obs-avc.h>
-#include <util/platform.h>
-#include <util/circlebuf.h>
-#include <util/dstr.h>
-#include <util/threading.h>
-#include <inttypes.h>
-#include "librtmp/rtmp.h"
-#include "librtmp/log.h"
-#include "flv-mux.h"
-#include "net-if.h"
-
-#ifdef _WIN32
-#include <Iphlpapi.h>
-#else
-#include <sys/ioctl.h>
-#endif
-
-#define do_log(level, format, ...) \
- blog(level, "[rtmp stream: '%s'] " format, \
- obs_output_get_name(stream->output), ##__VA_ARGS__)
-
-#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
-#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
-#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
-
-#define OPT_DROP_THRESHOLD "drop_threshold_ms"
-#define OPT_PFRAME_DROP_THRESHOLD "pframe_drop_threshold_ms"
-#define OPT_MAX_SHUTDOWN_TIME_SEC "max_shutdown_time_sec"
-#define OPT_BIND_IP "bind_ip"
-
-//#define TEST_FRAMEDROPS
-
-#ifdef TEST_FRAMEDROPS
-
-#define DROPTEST_MAX_KBPS 3000
-#define DROPTEST_MAX_BYTES (DROPTEST_MAX_KBPS * 1000 / 8)
-
-struct droptest_info {
- uint64_t ts;
- size_t size;
-};
-#endif
-
-struct rtmp_stream {
- obs_output_t *output;
-
- pthread_mutex_t packets_mutex;
- struct circlebuf packets;
- bool sent_headers;
-
- volatile bool connecting;
- pthread_t connect_thread;
-
- volatile bool active;
- volatile bool disconnected;
- pthread_t send_thread;
-
- int max_shutdown_time_sec;
-
- os_sem_t *send_sem;
- os_event_t *stop_event;
- uint64_t stop_ts;
- uint64_t shutdown_timeout_ts;
-
- struct dstr path, key;
- struct dstr username, password;
- struct dstr encoder_name;
- struct dstr bind_ip;
-
- /* frame drop variables */
- int64_t drop_threshold_usec;
- int64_t min_drop_dts_usec;
- int64_t pframe_drop_threshold_usec;
- int64_t pframe_min_drop_dts_usec;
- int min_priority;
-
- int64_t last_dts_usec;
-
- uint64_t total_bytes_sent;
- int dropped_frames;
-
-#ifdef TEST_FRAMEDROPS
- struct circlebuf droptest_info;
- size_t droptest_size;
-#endif
-
- RTMP rtmp;
-};
+#include "rtmp-stream.h"
static const char *rtmp_stream_getname(void *unused)
{
}
}
- if (stream) {
- free_packets(stream);
- dstr_free(&stream->path);
- dstr_free(&stream->key);
- dstr_free(&stream->username);
- dstr_free(&stream->password);
- dstr_free(&stream->encoder_name);
- dstr_free(&stream->bind_ip);
- os_event_destroy(stream->stop_event);
- os_sem_destroy(stream->send_sem);
- pthread_mutex_destroy(&stream->packets_mutex);
- circlebuf_free(&stream->packets);
+ if (stream->socket_thread_active)
+ pthread_join(stream->socket_thread, NULL);
+
+ free_packets(stream);
+ dstr_free(&stream->path);
+ dstr_free(&stream->key);
+ dstr_free(&stream->username);
+ dstr_free(&stream->password);
+ dstr_free(&stream->encoder_name);
+ dstr_free(&stream->bind_ip);
+ os_event_destroy(stream->stop_event);
+ os_sem_destroy(stream->send_sem);
+ pthread_mutex_destroy(&stream->packets_mutex);
+ circlebuf_free(&stream->packets);
#ifdef TEST_FRAMEDROPS
- circlebuf_free(&stream->droptest_info);
+ circlebuf_free(&stream->droptest_info);
#endif
- bfree(stream);
- }
+ if (stream->write_buf)
+ bfree(stream->write_buf);
+ bfree(stream);
}
static void *rtmp_stream_create(obs_data_t *settings, obs_output_t *output)
}
#endif
+static int socket_queue_data(RTMPSockBuf *sb, const char *data, int len, void *arg)
+{
+ struct rtmp_stream *stream = arg;
+
+retry_send:
+
+ if (!RTMP_IsConnected(&stream->rtmp))
+ return 0;
+
+ pthread_mutex_lock(&stream->write_buf_mutex);
+
+ if (stream->write_buf_len + len > stream->write_buf_size) {
+
+ pthread_mutex_unlock(&stream->write_buf_mutex);
+
+ if (os_event_wait(stream->buffer_space_available_event)) {
+ return 0;
+ }
+
+ goto retry_send;
+ }
+
+ memcpy(stream->write_buf + stream->write_buf_len, data, len);
+ stream->write_buf_len += len;
+
+ pthread_mutex_unlock(&stream->write_buf_mutex);
+
+ os_event_signal (stream->buffer_has_data_event);
+
+ return len;
+}
+
static int send_packet(struct rtmp_stream *stream,
struct encoder_packet *packet, bool is_header, size_t idx)
{
int recv_size = 0;
int ret = 0;
+ if (!stream->new_socket_loop) {
#ifdef _WIN32
- ret = ioctlsocket(stream->rtmp.m_sb.sb_socket, FIONREAD,
- (u_long*)&recv_size);
+ ret = ioctlsocket(stream->rtmp.m_sb.sb_socket, FIONREAD,
+ (u_long*)&recv_size);
#else
- ret = ioctl(stream->rtmp.m_sb.sb_socket, FIONREAD, &recv_size);
+ ret = ioctl(stream->rtmp.m_sb.sb_socket, FIONREAD, &recv_size);
#endif
- if (ret >= 0 && recv_size > 0) {
- if (!discard_recv_data(stream, (size_t)recv_size))
- return -1;
+ if (ret >= 0 && recv_size > 0) {
+ if (!discard_recv_data(stream, (size_t)recv_size))
+ return -1;
+ }
}
flv_packet_mux(packet, &data, &size, is_header);
return OBS_OUTPUT_ERROR;
}
+ if (stream->new_socket_loop) {
+ int one = 1;
+#ifdef _WIN32
+ if (ioctlsocket(stream->rtmp.m_sb.sb_socket, FIONBIO, &one)) {
+#else
+ if (ioctl(stream->rtmp.m_sb.sb_socket, FIONBIO, &one)) {
+#endif
+ warn("Failed to set non-blocking socket");
+ return OBS_OUTPUT_ERROR;
+ }
+
+ if (pthread_mutex_init(&stream->write_buf_mutex, NULL) != 0) {
+ warn("Failed to initialize write buffer mutex");
+ return OBS_OUTPUT_ERROR;
+ }
+
+ if (os_event_init(&stream->buffer_space_available_event,
+ OS_EVENT_TYPE_MANUAL) != 0) {
+ warn("Failed to initialize write buffer event");
+ return OBS_OUTPUT_ERROR;
+ }
+ if (os_event_init(&stream->buffer_has_data_event,
+ OS_EVENT_TYPE_MANUAL) != 0) {
+ warn("Failed to initialize data buffer event");
+ return OBS_OUTPUT_ERROR;
+ }
+ if (os_event_init(&stream->socket_available_event,
+ OS_EVENT_TYPE_MANUAL) != 0) {
+ warn("Failed to initialize socket buffer event");
+ return OBS_OUTPUT_ERROR;
+ }
+
+ info("New socket loop enabled by user");
+ if (stream->low_latency_mode)
+ info("Low latency mode enabled by user");
+
+ if (stream->write_buf)
+ bfree(stream->write_buf);
+
+ stream->write_buf_size = STREAM_WRITE_BUFFER_SIZE;
+ stream->write_buf = bmalloc(STREAM_WRITE_BUFFER_SIZE);
+
+#ifdef _WIN32
+ ret = pthread_create(&stream->socket_thread, NULL,
+ socket_thread_windows, stream);
+#else
+ warn("New socket loop not supported on this platform");
+ return OBS_OUTPUT_ERROR;
+#endif
+
+ if (ret != 0) {
+ RTMP_Close(&stream->rtmp);
+ warn("Failed to create socket thread");
+ return OBS_OUTPUT_ERROR;
+ }
+
+ stream->socket_thread_active = true;
+ stream->rtmp.m_bCustomSend = true;
+ stream->rtmp.m_customSendFunc = socket_queue_data;
+ stream->rtmp.m_customSendParam = stream;
+ }
+
os_atomic_set_bool(&stream->active, true);
while (next) {
if (!send_meta_data(stream, idx++, &next)) {
&stream->rtmp.m_bindIP.addrLen,
stream->bind_ip.array);
if (success) {
- info("Binding to IPv%d", (stream->rtmp.m_bindIP.addrLen ==
- sizeof(struct sockaddr_in6) ? 6 : 4));
+ int len = stream->rtmp.m_bindIP.addrLen;
+ bool ipv6 = len == sizeof(struct sockaddr_in6);
+ info("Binding to IPv%d", ipv6 ? 6 : 4);
}
}
int64_t drop_p;
int64_t drop_b;
- if (stopping(stream))
+ if (stopping(stream)) {
pthread_join(stream->send_thread, NULL);
+ }
+
+ if (stream->socket_thread_active) {
+ pthread_join(stream->socket_thread, NULL);
+ stream->socket_thread_active = false;
+ }
free_packets(stream);
bind_ip = obs_data_get_string(settings, OPT_BIND_IP);
dstr_copy(&stream->bind_ip, bind_ip);
+ stream->new_socket_loop = obs_data_get_bool(settings,
+ OPT_NEWSOCKETLOOP_ENABLED);
+ stream->low_latency_mode = obs_data_get_bool(settings,
+ OPT_LOWLATENCY_ENABLED);
+
obs_data_release(settings);
return true;
}
stream->pframe_drop_threshold_usec :
stream->drop_threshold_usec;
- if (num_packets < 5)
+ if (num_packets < 5) {
+ if (!pframes)
+ stream->congestion = 0.0f;
return;
+ }
circlebuf_peek_front(&stream->packets, &first, sizeof(first));
* sent is higher than threshold, drop frames */
buffer_duration_usec = stream->last_dts_usec - first.dts_usec;
+ if (!pframes) {
+ stream->congestion = (float)buffer_duration_usec /
+ (float)drop_threshold;
+ }
+
if (buffer_duration_usec > drop_threshold) {
debug("buffer_duration_usec: %" PRId64, buffer_duration_usec);
drop_frames(stream, name, priority, p_min_dts_usec);
static void rtmp_stream_defaults(obs_data_t *defaults)
{
- obs_data_set_default_int(defaults, OPT_DROP_THRESHOLD, 500);
- obs_data_set_default_int(defaults, OPT_PFRAME_DROP_THRESHOLD, 800);
+ obs_data_set_default_int(defaults, OPT_DROP_THRESHOLD, 700);
+ obs_data_set_default_int(defaults, OPT_PFRAME_DROP_THRESHOLD, 900);
obs_data_set_default_int(defaults, OPT_MAX_SHUTDOWN_TIME_SEC, 30);
obs_data_set_default_string(defaults, OPT_BIND_IP, "default");
+ obs_data_set_default_bool(defaults, OPT_NEWSOCKETLOOP_ENABLED, false);
+ obs_data_set_default_bool(defaults, OPT_LOWLATENCY_ENABLED, false);
}
static obs_properties_t *rtmp_stream_properties(void *unused)
}
netif_saddr_data_free(&addrs);
+ obs_properties_add_bool(props, OPT_NEWSOCKETLOOP_ENABLED,
+ obs_module_text("RTMPStream.NewSocketLoop"));
+ obs_properties_add_bool(props, OPT_LOWLATENCY_ENABLED,
+ obs_module_text("RTMPStream.LowLatencyMode"));
+
return props;
}
return stream->dropped_frames;
}
+static float rtmp_stream_congestion(void *data)
+{
+ struct rtmp_stream *stream = data;
+
+ if (stream->new_socket_loop)
+ return (float)stream->write_buf_len /
+ (float)stream->write_buf_size;
+ else
+ return stream->min_priority > 0 ? 1.0f : stream->congestion;
+}
+
struct obs_output_info rtmp_output_info = {
.id = "rtmp_output",
.flags = OBS_OUTPUT_AV |
.get_defaults = rtmp_stream_defaults,
.get_properties = rtmp_stream_properties,
.get_total_bytes = rtmp_stream_total_bytes_sent,
+ .get_congestion = rtmp_stream_congestion,
.get_dropped_frames = rtmp_stream_dropped_frames
};
obs-studio-18.0.0.tar.xz/plugins/obs-outputs/rtmp-stream.h
Added
+#include <obs-module.h>
+#include <obs-avc.h>
+#include <util/platform.h>
+#include <util/circlebuf.h>
+#include <util/dstr.h>
+#include <util/threading.h>
+#include <inttypes.h>
+#include "librtmp/rtmp.h"
+#include "librtmp/log.h"
+#include "flv-mux.h"
+#include "net-if.h"
+
+#ifdef _WIN32
+#include <Iphlpapi.h>
+#else
+#include <sys/ioctl.h>
+#endif
+
+#define do_log(level, format, ...) \
+ blog(level, "[rtmp stream: '%s'] " format, \
+ obs_output_get_name(stream->output), ##__VA_ARGS__)
+
+#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
+#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
+#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
+
+#define OPT_DROP_THRESHOLD "drop_threshold_ms"
+#define OPT_PFRAME_DROP_THRESHOLD "pframe_drop_threshold_ms"
+#define OPT_MAX_SHUTDOWN_TIME_SEC "max_shutdown_time_sec"
+#define OPT_BIND_IP "bind_ip"
+#define OPT_NEWSOCKETLOOP_ENABLED "new_socket_loop_enabled"
+#define OPT_LOWLATENCY_ENABLED "low_latency_mode_enabled"
+
+#define STREAM_WRITE_BUFFER_SIZE 524288
+
+//#define TEST_FRAMEDROPS
+
+#ifdef TEST_FRAMEDROPS
+
+#define DROPTEST_MAX_KBPS 3000
+#define DROPTEST_MAX_BYTES (DROPTEST_MAX_KBPS * 1000 / 8)
+
+struct droptest_info {
+ uint64_t ts;
+ size_t size;
+};
+#endif
+
+struct rtmp_stream {
+ obs_output_t *output;
+
+ pthread_mutex_t packets_mutex;
+ struct circlebuf packets;
+ bool sent_headers;
+
+ volatile bool connecting;
+ pthread_t connect_thread;
+
+ volatile bool active;
+ volatile bool disconnected;
+ pthread_t send_thread;
+
+ int max_shutdown_time_sec;
+
+ os_sem_t *send_sem;
+ os_event_t *stop_event;
+ uint64_t stop_ts;
+ uint64_t shutdown_timeout_ts;
+
+ struct dstr path, key;
+ struct dstr username, password;
+ struct dstr encoder_name;
+ struct dstr bind_ip;
+
+ /* frame drop variables */
+ int64_t drop_threshold_usec;
+ int64_t min_drop_dts_usec;
+ int64_t pframe_drop_threshold_usec;
+ int64_t pframe_min_drop_dts_usec;
+ int min_priority;
+ float congestion;
+
+ int64_t last_dts_usec;
+
+ uint64_t total_bytes_sent;
+ int dropped_frames;
+
+#ifdef TEST_FRAMEDROPS
+ struct circlebuf droptest_info;
+ size_t droptest_size;
+#endif
+
+ RTMP rtmp;
+
+ bool new_socket_loop;
+ bool low_latency_mode;
+ bool disable_send_window_optimization;
+ bool socket_thread_active;
+ pthread_t socket_thread;
+ uint8_t *write_buf;
+ size_t write_buf_len;
+ size_t write_buf_size;
+ pthread_mutex_t write_buf_mutex;
+ os_event_t *buffer_space_available_event;
+ os_event_t *buffer_has_data_event;
+ os_event_t *socket_available_event;
+};
+
+#ifdef _WIN32
+void *socket_thread_windows(void *data);
+#endif
obs-studio-18.0.0.tar.xz/plugins/obs-outputs/rtmp-windows.c
Added
+#ifdef _WIN32
+#include "rtmp-stream.h"
+#include <winsock2.h>
+
+static void fatal_sock_shutdown(struct rtmp_stream *stream)
+{
+ closesocket(stream->rtmp.m_sb.sb_socket);
+ stream->rtmp.m_sb.sb_socket = -1;
+ stream->write_buf_len = 0;
+}
+
+static bool socket_event(struct rtmp_stream *stream, bool *can_write,
+ uint64_t last_send_time)
+{
+ WSANETWORKEVENTS net_events;
+ bool success;
+
+ success = !!WSAEnumNetworkEvents(stream->rtmp.m_sb.sb_socket, NULL,
+ &net_events);
+ if (success) {
+ blog(LOG_ERROR, "socket_thread_windows: Aborting due to "
+ "WSAEnumNetworkEvents failure, %d",
+ WSAGetLastError());
+ fatal_sock_shutdown(stream);
+ return false;
+ }
+
+ if (net_events.lNetworkEvents & FD_WRITE)
+ *can_write = true;
+
+ if (net_events.lNetworkEvents & FD_CLOSE) {
+ if (last_send_time) {
+ uint32_t diff =
+ (os_gettime_ns() / 1000000) - last_send_time;
+
+ blog(LOG_ERROR, "socket_thread_windows: Received "
+ "FD_CLOSE, %u ms since last send "
+ "(buffer: %d / %d)",
+ diff,
+ stream->write_buf_len,
+ stream->write_buf_size);
+ }
+
+ if (os_event_try(stream->stop_event) != EAGAIN)
+ blog(LOG_ERROR, "socket_thread_windows: Aborting due "
+ "to FD_CLOSE during shutdown, "
+ "%d bytes lost, error %d",
+ stream->write_buf_len,
+ net_events.iErrorCode[FD_CLOSE_BIT]);
+ else
+ blog(LOG_ERROR, "socket_thread_windows: Aborting due "
+ "to FD_CLOSE, error %d",
+ net_events.iErrorCode[FD_CLOSE_BIT]);
+
+ fatal_sock_shutdown(stream);
+ return false;
+ }
+
+ if (net_events.lNetworkEvents & FD_READ) {
+ char discard[16384];
+ int err_code;
+ bool fatal = false;
+
+ for (;;) {
+ int ret = recv(stream->rtmp.m_sb.sb_socket,
+ discard, sizeof(discard), 0);
+ if (ret == -1) {
+ err_code = WSAGetLastError();
+ if (err_code == WSAEWOULDBLOCK)
+ break;
+
+ fatal = true;
+ } else if (ret == 0) {
+ err_code = 0;
+ fatal = true;
+ }
+
+ if (fatal) {
+ blog(LOG_ERROR, "socket_thread_windows: "
+ "Socket error, recv() returned "
+ "%d, GetLastError() %d",
+ ret, err_code);
+ fatal_sock_shutdown(stream);
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+static void ideal_send_backlog_event(struct rtmp_stream *stream,
+ bool *can_write)
+{
+ ULONG ideal_send_backlog;
+ int ret;
+
+ ret = idealsendbacklogquery(
+ stream->rtmp.m_sb.sb_socket,
+ &ideal_send_backlog);
+ if (ret == 0) {
+ int cur_tcp_bufsize;
+ int size = sizeof(cur_tcp_bufsize);
+
+ ret = getsockopt(stream->rtmp.m_sb.sb_socket,
+ SOL_SOCKET,
+ SO_SNDBUF,
+ (char *)&cur_tcp_bufsize,
+ &size);
+ if (ret == 0) {
+ if (cur_tcp_bufsize < (int)ideal_send_backlog) {
+ int bufsize = (int)ideal_send_backlog;
+ setsockopt(stream->rtmp.m_sb.sb_socket,
+ SOL_SOCKET,
+ SO_SNDBUF,
+ (const char *)&bufsize,
+ sizeof(bufsize));
+
+ blog(LOG_INFO, "socket_thread_windows: "
+ "Increasing send buffer to "
+ "ISB %d (buffer: %d / %d)",
+ ideal_send_backlog,
+ stream->write_buf_len,
+ stream->write_buf_size);
+ }
+ } else {
+ blog(LOG_ERROR, "socket_thread_windows: Got "
+ "send_backlog_event but "
+ "getsockopt() returned %d",
+ WSAGetLastError());
+ }
+ } else {
+ blog(LOG_ERROR, "socket_thread_windows: Got "
+ "send_backlog_event but WSAIoctl() "
+ "returned %d",
+ WSAGetLastError());
+ }
+}
+
+enum data_ret {
+ RET_BREAK,
+ RET_FATAL,
+ RET_CONTINUE
+};
+
+static enum data_ret write_data(struct rtmp_stream *stream, bool *can_write,
+ uint64_t *last_send_time, size_t latency_packet_size,
+ int delay_time)
+{
+ bool exit_loop = false;
+
+ pthread_mutex_lock(&stream->write_buf_mutex);
+
+ if (!stream->write_buf_len) {
+ /* this is now an expected occasional condition due to use of
+ * auto-reset events, we could end up emptying the buffer as
+ * it's filled in a previous loop cycle, especially if using
+ * low latency mode. */
+ pthread_mutex_unlock(&stream->write_buf_mutex);
+ /* blog(LOG_DEBUG, "socket_thread_windows: Trying to send, "
+ "but no data available"); */
+ return RET_BREAK;
+ }
+
+ int ret;
+ if (stream->low_latency_mode) {
+ size_t send_len =
+ min(latency_packet_size, stream->write_buf_len);
+
+ ret = send(stream->rtmp.m_sb.sb_socket,
+ (const char *)stream->write_buf,
+ (int)send_len, 0);
+ } else {
+ ret = send(stream->rtmp.m_sb.sb_socket,
+ (const char *)stream->write_buf,
+ (int)stream->write_buf_len, 0);
+ }
+
+ if (ret > 0) {
+ if (stream->write_buf_len - ret)
+ memmove(stream->write_buf,
+ stream->write_buf + ret,
+ stream->write_buf_len - ret);
+ stream->write_buf_len -= ret;
+
+ *last_send_time = os_gettime_ns() / 1000000;
+
+ os_event_signal(stream->buffer_space_available_event);
+ } else {
+ int err_code;
+ bool fatal_err = false;
+
+ if (ret == -1) {
+ err_code = WSAGetLastError();
+
+ if (err_code == WSAEWOULDBLOCK) {
+ *can_write = false;
+ pthread_mutex_unlock(&stream->write_buf_mutex);
+ return RET_BREAK;
+ }
+
+ fatal_err = true;
+ } else if (ret == 0) {
+ err_code = 0;
+ fatal_err = true;
+ }
+
+ if (fatal_err) {
+ /* connection closed, or connection was aborted /
+ * socket closed / etc, that's a fatal error. */
+ blog(LOG_ERROR, "socket_thread_windows: "
+ "Socket error, send() returned %d, "
+ "GetLastError() %d",
+ ret, err_code);
+
+ pthread_mutex_unlock(&stream->write_buf_mutex);
+ fatal_sock_shutdown(stream);
+ return RET_FATAL;
+ }
+ }
+
+ /* finish writing for now */
+ if (stream->write_buf_len <= 1000)
+ exit_loop = true;
+
+ pthread_mutex_unlock(&stream->write_buf_mutex);
+
+ if (delay_time)
+ os_sleep_ms(delay_time);
+
+ return exit_loop ? RET_BREAK : RET_CONTINUE;
+}
+
+static inline void socket_thread_windows_internal(struct rtmp_stream *stream)
+{
+ bool can_write = false;
+
+ int delay_time;
+ size_t latency_packet_size;
+ uint64_t last_send_time = 0;
+
+ HANDLE send_backlog_event;
+ OVERLAPPED send_backlog_overlapped;
+
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
+
+ WSAEventSelect(stream->rtmp.m_sb.sb_socket,
+ stream->socket_available_event,
+ FD_READ|FD_WRITE|FD_CLOSE);
+
+ send_backlog_event = CreateEvent(NULL, true, false, NULL);
+
+ if (stream->low_latency_mode) {
+ delay_time = 1400.0f / (stream->write_buf_size / 1000.0f);
+ latency_packet_size = 1460;
+ } else {
+ latency_packet_size = stream->write_buf_size;
+ delay_time = 0;
+ }
+
+ if (!stream->disable_send_window_optimization) {
+ memset(&send_backlog_overlapped, 0,
+ sizeof(send_backlog_overlapped));
+ send_backlog_overlapped.hEvent = send_backlog_event;
+ idealsendbacklognotify(stream->rtmp.m_sb.sb_socket,
+ &send_backlog_overlapped, NULL);
+ } else {
+ blog(LOG_INFO, "socket_thread_windows: Send window "
+ "optimization disabled by user.");
+ }
+
+ HANDLE objs[3];
+
+ objs[0] = stream->socket_available_event;
+ objs[1] = stream->buffer_has_data_event;
+ objs[2] = send_backlog_event;
+
+ for (;;) {
+ if (os_event_try(stream->stop_event) != EAGAIN) {
+ pthread_mutex_lock(&stream->write_buf_mutex);
+ if (stream->write_buf_len == 0) {
+ //blog(LOG_DEBUG, "Exiting on empty buffer");
+ pthread_mutex_unlock(&stream->write_buf_mutex);
+ break;
+ }
+
+ pthread_mutex_unlock(&stream->write_buf_mutex);
+ }
+
+ int status = WaitForMultipleObjects(3, objs, false, INFINITE);
+ if (status == WAIT_ABANDONED || status == WAIT_FAILED) {
+ blog(LOG_ERROR, "socket_thread_windows: Aborting due "
+ "to WaitForMultipleObjects failure");
+ fatal_sock_shutdown(stream);
+ return;
+ }
+
+ if (status == WAIT_OBJECT_0) {
+ /* Socket event */
+ if (!socket_event(stream, &can_write, last_send_time))
+ return;
+
+ } else if (status == WAIT_OBJECT_0 + 2) {
+ /* Ideal send backlog event */
+ ideal_send_backlog_event(stream, &can_write);
+
+ ResetEvent(send_backlog_event);
+ idealsendbacklognotify(stream->rtmp.m_sb.sb_socket,
+ &send_backlog_overlapped, NULL);
+ continue;
+ }
+
+ if (can_write) {
+ for (;;) {
+ enum data_ret ret = write_data(
+ stream,
+ &can_write,
+ &last_send_time,
+ latency_packet_size,
+ delay_time);
+
+ switch (ret) {
+ case RET_BREAK:
+ break;
+ case RET_FATAL:
+ return;
+ case RET_CONTINUE:;
+ }
+ }
+ }
+ }
+
+ blog(LOG_INFO, "socket_thread_windows: Normal exit");
+}
+
+void *socket_thread_windows(void *data)
+{
+ struct rtmp_stream *stream = data;
+ socket_thread_windows_internal(stream);
+ return NULL;
+}
+#endif
obs-studio-17.0.2.tar.xz/plugins/obs-qsv11/QSV_Encoder_Internal.cpp -> obs-studio-18.0.0.tar.xz/plugins/obs-qsv11/QSV_Encoder_Internal.cpp
Changed
}
mfxFrameSurface1 *pSurface = m_pmfxSurfaces[nSurfIdx];
- if (m_bUseD3D11 || m_bD3D9HACK)
+ if (m_bUseD3D11 || m_bD3D9HACK) {
sts = m_mfxAllocator.Lock(m_mfxAllocator.pthis,
pSurface->Data.MemId, &(pSurface->Data));
+ MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
+ }
sts = LoadNV12(pSurface, pDataY, pDataUV, strideY, strideUV);
+ MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
pSurface->Data.TimeStamp = ts;
- if (m_bUseD3D11 || m_bD3D9HACK)
+ if (m_bUseD3D11 || m_bD3D9HACK) {
sts = m_mfxAllocator.Unlock(m_mfxAllocator.pthis,
pSurface->Data.MemId, &(pSurface->Data));
-
- MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
+ MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
+ }
for (;;) {
// Encode a frame asychronously (returns immediately)
delete m_outBitstream.Data;
- if (m_pmfxENC != NULL) {
- delete m_pmfxENC;
- m_pmfxENC = NULL;
- }
+ delete m_pmfxENC;
+ m_pmfxENC = NULL;
if (m_bUseD3D11 || m_bD3D9HACK)
Release();
obs-studio-17.0.2.tar.xz/plugins/obs-qsv11/common_utils.cpp -> obs-studio-18.0.0.tar.xz/plugins/obs-qsv11/common_utils.cpp
Changed
if (MFX_ERR_NONE != sts)
return sts;
// load V
- ReadPlaneData(w, h, buf, ptr, pitch, 1, fSource);
+ sts = ReadPlaneData(w, h, buf, ptr, pitch, 1, fSource);
if (MFX_ERR_NONE != sts)
return sts;
obs-studio-17.0.2.tar.xz/plugins/obs-qsv11/data/locale/sv-SE.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-qsv11/data/locale/sv-SE.ini
Changed
Accuracy="Noggrannhet"
Convergence="Konvergens"
ICQQuality="ICQ-kvalitet"
+LookAheadDepth="Lookahead-djup"
obs-studio-17.0.2.tar.xz/plugins/obs-qsv11/obs-qsv11.c -> obs-studio-18.0.0.tar.xz/plugins/obs-qsv11/obs-qsv11.c
Changed
mfxU64 qsvPTS = frame->pts * 90000 / voi->fps_num;
+ // FIXME: remove null check from the top of this function
+ // if we actually do expect null frames to complete output.
if (frame)
ret = qsv_encoder_encode(
obsqsv->context,
if (ret < 0) {
warn("encode failed");
+ LeaveCriticalSection(&g_QsvCs);
return false;
}
obs-studio-18.0.0.tar.xz/plugins/obs-text/data/locale/da-DK.ini
Added
+TextGDIPlus="Tekst (GDI+)"
+Font="Skrifttype"
+Text="Tekst"
+ReadFromFile="Indlæs fra fil"
+TextFile="Tekstfil (UTF-8)"
+Filter.TextFiles="Tekstfiler"
+Filter.AllFiles="Alle filer"
+Color="Farve"
+Opacity="Gennemsigtighed"
+Gradient="Gradient"
+Gradient.Color="Gradient farve"
+Gradient.Opacity="Gradient gennemsigtighed"
+Gradient.Direction="Gradient retning"
+BkColor="Baggrundsfarve"
+BkOpacity="Baggrunds gennemsigtighed"
+Alignment="Justering"
+Alignment.Left="Venstre"
+Alignment.Center="Centreret"
+Alignment.Right="Højre"
+Vertical="Vertikal"
+VerticalAlignment="Vertikal justering"
+VerticalAlignment.Top="Top"
+VerticalAlignment.Bottom="Bund"
+Outline="Kontur"
+Outline.Size="Kontur størrelse"
+Outline.Color="Kontur farve"
+Outline.Opacity="Kontur gennemsigtighed"
+ChatlogMode="Chatlog tilstand"
+ChatlogMode.Lines="Chatlog linebegrænsning"
+UseCustomExtents="Brug tilpasset tekstomfang"
+UseCustomExtents.Wrap="Ombryd"
+Width="Bredde"
+Height="Højde"
+
obs-studio-18.0.0.tar.xz/plugins/obs-text/data/locale/pt-BR.ini
Added
+TextGDIPlus="Texto (GDI+)"
+Font="Fonte"
+Text="Texto"
+ReadFromFile="Carregar do Arquivo"
+TextFile="Arquivo de Texto (UTF-8)"
+Filter.TextFiles="Arquivos de Texto"
+Filter.AllFiles="Todos os Arquivos"
+Color="Cor"
+Opacity="Opacidade"
+Gradient="Gradiente"
+Gradient.Color="Cor do Gradiente"
+Gradient.Opacity="Opacidade do Gradiente"
+Gradient.Direction="Direção do Gradiente"
+BkColor="Cor de Fundo"
+BkOpacity="Opacidade de Fundo"
+Alignment="Alinhamento"
+Alignment.Left="Esquerda"
+Alignment.Center="Centralizado"
+Alignment.Right="Direita"
+Vertical="Vertical"
+VerticalAlignment="Alinhamento Vertical"
+VerticalAlignment.Top="Em cima"
+VerticalAlignment.Bottom="Em baixo"
+Outline="Contorno"
+Outline.Size="Tamanho do Contorno"
+Outline.Color="Cor do Contorno"
+Outline.Opacity="Opacidade do Contorno"
+ChatlogMode="Modo de Chat"
+ChatlogMode.Lines="Limite de Linhas do Chat"
+UseCustomExtents="Usar extensões de texto personalizadas"
+UseCustomExtents.Wrap="Ajustar"
+Width="Largura"
+Height="Altura"
+
obs-studio-18.0.0.tar.xz/plugins/obs-text/data/locale/ro-RO.ini
Added
+TextGDIPlus="Text (GDI+)"
+Font="Font"
+Text="Text"
+ReadFromFile="Citește din fișier"
+TextFile="Fișier text (UTF-8)"
+Filter.TextFiles="Fișiere Text"
+Filter.AllFiles="Toate fișierele"
+Color="Culoare"
+Opacity="Opacitate"
+BkColor="Culoare Fundal"
+BkOpacity="Opacitate Fundal"
+Alignment="Aliniere"
+Alignment.Left="Stânga"
+Alignment.Center="Centru"
+Alignment.Right="Dreapta"
+Vertical="Vertical"
+Outline="Contur"
+Outline.Size="Dimensiune Contur"
+Outline.Color="Culoare Contur"
+Outline.Opacity="Opacitate Contur"
+Width="Lățime"
+Height="Înălțime"
+
obs-studio-17.0.2.tar.xz/plugins/obs-text/gdiplus/obs-text.cpp -> obs-studio-18.0.0.tar.xz/plugins/obs-text/gdiplus/obs-text.cpp
Changed
lf.lfUnderline = underline;
lf.lfStrikeOut = strikeout;
lf.lfQuality = ANTIALIASED_QUALITY;
+ lf.lfCharSet = DEFAULT_CHARSET;
if (!face.empty()) {
wcscpy(lf.lfFaceName, face.c_str());
obs-studio-17.0.2.tar.xz/plugins/obs-transitions/data/fade_to_color_transition.effect -> obs-studio-18.0.0.tar.xz/plugins/obs-transitions/data/fade_to_color_transition.effect
Changed
float2 uv : TEXCOORD0;
};
+#include "premultiplied.inc"
+
VertData VSDefault(VertData v_in)
{
VertData vert_out;
float4 PSFadeToColor(VertData v_in) : TARGET
{
- return lerp(tex.Sample(textureSampler, v_in.uv), color, swp);
+ return lerp(convert_pmalpha(tex.Sample(textureSampler, v_in.uv)), color, swp);
}
technique FadeToColor
obs-studio-17.0.2.tar.xz/plugins/obs-transitions/data/fade_transition.effect -> obs-studio-18.0.0.tar.xz/plugins/obs-transitions/data/fade_transition.effect
Changed
float2 uv : TEXCOORD0;
};
+#include "premultiplied.inc"
+
VertData VSDefault(VertData v_in)
{
VertData vert_out;
float4 PSFade(VertData v_in) : TARGET
{
- float4 a_val = tex_a.Sample(textureSampler, v_in.uv);
- float4 b_val = tex_b.Sample(textureSampler, v_in.uv);
+ float4 a_val = convert_pmalpha(tex_a.Sample(textureSampler, v_in.uv));
+ float4 b_val = convert_pmalpha(tex_b.Sample(textureSampler, v_in.uv));
return lerp(a_val, b_val, fade_val);
}
obs-studio-17.0.2.tar.xz/plugins/obs-transitions/data/locale/da-DK.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-transitions/data/locale/da-DK.ini
Changed
SwipeIn="Swipe ind"
Color="Farve"
SwitchPoint="Farvepeakpunkt (procent)"
+LumaWipeTransition="Luma overgang"
+LumaWipe.Image="Billede"
+LumaWipe.Invert="Inverter"
+LumaWipe.Softness="Blødhed"
+LumaWipe.Type.BarndoorBottomLeft="Stalddør nederst til venstre"
+LumaWipe.Type.BarndoorHorizontal="Stalddør horisontal"
+LumaWipe.Type.BarndoorTopLeft="Stalddør øverst til venstre"
+LumaWipe.Type.BarndoorVertical="Stalddør vertikal"
+LumaWipe.Type.BlindsHorizontal="Persienne horisontal"
+LumaWipe.Type.BoxBottomLeft="Boks nederst til venstre"
+LumaWipe.Type.BoxBottomRight="Boks nederst til højre"
+LumaWipe.Type.BoxTopLeft="Boks øverst til venstre"
+LumaWipe.Type.BoxTopRight="Boks øverst til højre"
+LumaWipe.Type.Burst="Sprængning"
+LumaWipe.Type.CheckerboardSmall="Små skaktern"
+LumaWipe.Type.Circles="Cirkler"
+LumaWipe.Type.Clock="Ur"
+LumaWipe.Type.Cloud="Sky"
+LumaWipe.Type.Curtain="Gardin"
+LumaWipe.Type.Fan="Vifte"
+LumaWipe.Type.Fractal="Fraktal"
+LumaWipe.Type.Iris="Iris"
+LumaWipe.Type.LinearHorizontal="Lineær horisontal"
+LumaWipe.Type.LinearTopLeft="Lineær øverst til venstre"
+LumaWipe.Type.LinearTopRight="Lineær øverst til højre"
+LumaWipe.Type.LinearVertical="Lineær vertikal"
+LumaWipe.Type.ParallelZigzagHorizontal="Parallel zigzag horisontal"
+LumaWipe.Type.ParallelZigzagVertical="Parallel zigzag vertikal"
+LumaWipe.Type.Sinus9="Sinus 9"
+LumaWipe.Type.Spiral="Spiral"
+LumaWipe.Type.Square="Firkant"
+LumaWipe.Type.Squares="Firkanter"
+LumaWipe.Type.Stripes="Striber"
+LumaWipe.Type.StripsHorizontal="Strimmel horisontal"
+LumaWipe.Type.StripsVertical="Strimmel vertikal"
+LumaWipe.Type.Watercolor="Vandfarve"
+LumaWipe.Type.ZigzagHorizontal="Zigzag horisontal"
+LumaWipe.Type.ZigzagVertical="Zigzag vertical"
obs-studio-17.0.2.tar.xz/plugins/obs-transitions/data/locale/nb-NO.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-transitions/data/locale/nb-NO.ini
Changed
SwipeIn="Sveip inn"
Color="Farge"
SwitchPoint="Farge ved høydepunkt (prosent)"
+LumaWipe.Image="Bilde"
+LumaWipe.Invert="Inverter"
+LumaWipe.Softness="Mykhet"
obs-studio-17.0.2.tar.xz/plugins/obs-transitions/data/locale/pt-BR.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-transitions/data/locale/pt-BR.ini
Changed
LumaWipe.Type.BarndoorTopLeft="Barndoor inferior esquerdo"
LumaWipe.Type.BarndoorVertical="Barndoor Vertical"
LumaWipe.Type.BlindsHorizontal="Persianas horizontais"
+LumaWipe.Type.Circles="Círculos"
+LumaWipe.Type.Clock="Relógio"
+LumaWipe.Type.Cloud="Nuvem"
+LumaWipe.Type.Curtain="Cortina"
+LumaWipe.Type.Fan="Ventilar"
+LumaWipe.Type.Fractal="Fractal"
+LumaWipe.Type.Iris="Iris"
+LumaWipe.Type.LinearHorizontal="Linear Horizontal"
+LumaWipe.Type.LinearTopLeft="Linear superior esquerdo"
+LumaWipe.Type.LinearTopRight="Linear superior direito"
+LumaWipe.Type.LinearVertical="Linear Vertical"
+LumaWipe.Type.Spiral="Espiral"
+LumaWipe.Type.Square="Quadrado"
+LumaWipe.Type.Squares="Quadrados"
+LumaWipe.Type.Stripes="Listras"
+LumaWipe.Type.StripsHorizontal="Listras horizontais"
+LumaWipe.Type.StripsVertical="Listras Verticais"
+LumaWipe.Type.Watercolor="Aquarela"
+LumaWipe.Type.ZigzagHorizontal="Zigue-zague Horizontal"
+LumaWipe.Type.ZigzagVertical="Zigue-zague Vertical"
obs-studio-17.0.2.tar.xz/plugins/obs-transitions/data/locale/ro-RO.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-transitions/data/locale/ro-RO.ini
Changed
SwipeIn="Glisați înauntru"
Color="Culoare"
SwitchPoint="Punctul de vârf al culorii (procent)"
+LumaWipe.Image="Imagine"
+LumaWipe.Type.Cloud="Cloud"
+LumaWipe.Type.ZigzagHorizontal="Zigzag orizontal"
+LumaWipe.Type.ZigzagVertical="Zigzag Vertical"
obs-studio-17.0.2.tar.xz/plugins/obs-transitions/data/luma_wipe_transition.effect -> obs-studio-18.0.0.tar.xz/plugins/obs-transitions/data/luma_wipe_transition.effect
Changed
float2 uv : TEXCOORD0;
};
+#include "premultiplied.inc"
+
VertData VSDefault(VertData v_in)
{
VertData vert_out;
float4 PSLumaWipe(VertData v_in) : TARGET
{
float2 uv = v_in.uv;
- float4 a_color = a_tex.Sample(textureSampler, uv);
- float4 b_color = b_tex.Sample(textureSampler, uv);
+ float4 a_color = convert_pmalpha(a_tex.Sample(textureSampler, uv));
+ float4 b_color = convert_pmalpha(b_tex.Sample(textureSampler, uv));
float luma = l_tex.Sample(textureSampler, uv).x;
if (invert)
obs-studio-18.0.0.tar.xz/plugins/obs-transitions/data/premultiplied.inc
Added
+float4 convert_pmalpha(float4 color)
+{
+ float4 ret = color;
+ if (color.a >= 0.001)
+ ret.xyz /= color.a;
+ else
+ ret = float4(0.0, 0.0, 0.0, 0.0);
+ return ret;
+}
obs-studio-17.0.2.tar.xz/plugins/obs-transitions/data/slide_transition.effect -> obs-studio-18.0.0.tar.xz/plugins/obs-transitions/data/slide_transition.effect
Changed
float2 uv : TEXCOORD0;
};
+#include "premultiplied.inc"
+
VertData VSDefault(VertData v_in)
{
VertData vert_out;
{
float2 tex_a_uv = v_in.uv + tex_a_dir;
float2 tex_b_uv = v_in.uv - tex_b_dir;
+ float4 outc;
- return (tex_a_uv.x - saturate(tex_a_uv.x) != 0.0) ||
+ outc = (tex_a_uv.x - saturate(tex_a_uv.x) != 0.0) ||
(tex_a_uv.y - saturate(tex_a_uv.y) != 0.0)
? tex_b.Sample(textureSampler, tex_b_uv)
: tex_a.Sample(textureSampler, tex_a_uv);
+
+ return convert_pmalpha(outc);
}
technique Slide
obs-studio-17.0.2.tar.xz/plugins/obs-transitions/data/swipe_transition.effect -> obs-studio-18.0.0.tar.xz/plugins/obs-transitions/data/swipe_transition.effect
Changed
float2 uv : TEXCOORD0;
};
+#include "premultiplied.inc"
+
VertData VSDefault(VertData v_in)
{
VertData vert_out;
float4 PSSwipe(VertData v_in) : TARGET
{
float2 swipe_uv = v_in.uv + swipe_val;
+ float4 outc;
- return (swipe_uv.x - saturate(swipe_uv.x) != 0.0) ||
+ outc = (swipe_uv.x - saturate(swipe_uv.x) != 0.0) ||
(swipe_uv.y - saturate(swipe_uv.y) != 0.0)
? tex_b.Sample(textureSampler, v_in.uv)
: tex_a.Sample(textureSampler, swipe_uv);
+
+ return convert_pmalpha(outc);
}
technique Swipe
obs-studio-18.0.0.tar.xz/plugins/obs-vst
Added
+(directory)
obs-studio-18.0.0.tar.xz/plugins/obs-vst/CMakeLists.txt
Added
+project(obs-vst)
+
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}")
+
+find_package(Qt5Widgets REQUIRED)
+
+option(VST_USE_BUNDLED_HEADERS "Build with Bundled Headers" ON)
+
+if(VST_USE_BUNDLED_HEADERS)
+ message(STATUS "Using the bundled VST header.")
+ include_directories(vst_header)
+ set(vst_HEADER
+ vst_header/aeffectx.h)
+else()
+ set(VST_INCLUDE_DIR "" CACHE PATH
+ "Path to Steinburg headers (e.g. C:/VST3 SDK/pluginterfaces/vst2.x)")
+
+ message(WARNING "You should only use the Steinburg headers for debugging or local
+ builds. It is illegal to distribute the Steinburg headers with anything, and
+ possibly against the GPL to distribute the binaries from the resultant compile.")
+ include_directories(${VST_INCLUDE_DIR})
+ set(vst_HEADER
+ ${VST_INCLUDE_DIR}/aeffectx.h)
+endif()
+
+if(APPLE)
+ find_library(FOUNDATION_FRAMEWORK Foundation)
+ find_library(COCOA_FRAMEWORK Cocoa)
+endif(APPLE)
+
+set(obs-vst_SOURCES
+ obs-vst.cpp
+ VSTPlugin.cpp
+ EditorWidget.cpp)
+
+if(APPLE)
+ list(APPEND obs-vst_SOURCES
+ mac/VSTPlugin-osx.mm
+ mac/EditorWidget-osx.mm)
+
+elseif(WIN32)
+ list(APPEND obs-vst_SOURCES
+ win/VSTPlugin-win.cpp
+ win/EditorWidget-win.cpp)
+
+elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
+ list (APPEND obs-vst_SOURCES
+ linux/VSTPlugin-linux.cpp
+ linux/EditorWidget-linux.cpp)
+endif()
+
+list(APPEND obs-vst_HEADERS
+ headers/vst-plugin-callbacks.hpp
+ headers/EditorWidget.h
+ headers/VSTPlugin.h)
+
+add_library(obs-vst MODULE
+ ${obs-vst_SOURCES}
+ ${obs-vst_HEADERS}
+ ${vst-HEADER})
+
+target_link_libraries(obs-vst
+ libobs
+ Qt5::Widgets)
+
+if(APPLE)
+ target_link_libraries(obs-vst
+ ${COCOA_FRAMEWORK}
+ ${FOUNDATION_FRAMEWORK})
+endif(APPLE)
+
+install_obs_plugin_with_data(obs-vst data)
\ No newline at end of file
obs-studio-18.0.0.tar.xz/plugins/obs-vst/EditorWidget.cpp
Added
+/*****************************************************************************
+Copyright (C) 2016-2017 by Colin Edwards.
+Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#include "headers/EditorWidget.h"
+
+EditorWidget::EditorWidget(QWidget *parent, VSTPlugin *plugin) :
+ QWidget(parent), plugin(plugin) {
+ setWindowFlags(this->windowFlags() |=
+ Qt::MSWindowsFixedSizeDialogHint);
+}
+
+void EditorWidget::closeEvent(QCloseEvent *event) {
+ plugin->closeEditor();
+ UNUSED_PARAMETER(event);
+}
\ No newline at end of file
obs-studio-18.0.0.tar.xz/plugins/obs-vst/LICENSE
Added
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ {description}
+ Copyright (C) {year} {fullname}
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ {signature of Ty Coon}, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
obs-studio-18.0.0.tar.xz/plugins/obs-vst/README.md
Added
+# OBS-VST
+Use VST 2.x plugins as audio filters in OBS.
+
+
+
+## Research
+### Sites
+* http://teragonaudio.com/article/How-to-make-your-own-VST-host.html
+* http://www.reaper.fm/sdk/vst/vst_ext.php
+* https://forum.juce.com/t/mac-64-bit/6295/5
+* https://gist.github.com/t-mat/206e3e7dfc3f89421bc1
+* https://github.com/audacity/audacity/blob/17afc51644b2b327e173a23d6066dde598838c03/src/effects/VST/aeffectx.h
+
+### Info
+> In general VST 2.4 is platform independent. There are only three platform
+ dependent opcodes :
+ effEditOpen
+ audioMasterGetDirectory
+ audioMasterOpenFileSelector
+>
+> Here are the required API changes for 64 bit Mac OS X:
+>
+> effEditOpen:
+ the [ptr] argument is a WindowRef on 32 bit Mac.
+ On 64 bit this is a NSView pointer. The plug-in needs to add its own NSView as
+ subview of it.
+>
+> audioMasterGetDirectory:
+ the [return value] is a FSSpec on 32 bit Mac.
+ On 64 bit this is a char pointer pointing to an UTF-8 encoded string.
+>
+> audioMasterOpenFileSelector:
+ the VstFileSelect struct uses FSSpec's on 32 bit Mac.
+ On 64 bit Mac these are char pointers pointing to UTF-8 encoded strings.
obs-studio-18.0.0.tar.xz/plugins/obs-vst/VSTPlugin.cpp
Added
+/*****************************************************************************
+Copyright (C) 2016-2017 by Colin Edwards.
+Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#include "headers/VSTPlugin.h"
+
+VSTPlugin::VSTPlugin(obs_source_t *sourceContext) :
+ sourceContext{sourceContext} {
+
+ int numChannels = VST_MAX_CHANNELS;
+ int blocksize = 512;
+
+ inputs = (float **) malloc(sizeof(float **) * numChannels);
+ outputs = (float **) malloc(sizeof(float **) * numChannels);
+ for (int channel = 0; channel < numChannels; channel++)
+ {
+ inputs[channel] = (float *) malloc(sizeof(float *)
+ * blocksize);
+ outputs[channel] = (float *) malloc(sizeof(float *)
+ * blocksize);
+ }
+}
+
+void VSTPlugin::loadEffectFromPath(std::string path) {
+ if (this->pluginPath.compare(path) != 0)
+ {
+ closeEditor();
+ unloadEffect();
+ }
+
+ if (!effect)
+ {
+ pluginPath = path;
+ effect = loadEffect();
+
+ if (!effect)
+ {
+ //TODO: alert user of error
+ return;
+ }
+
+ // Check plug-in's magic number
+ // If incorrect, then the file either was not loaded properly, is not a
+ // real VST plug-in, or is otherwise corrupt.
+ if (effect->magic != kEffectMagic)
+ {
+ blog(LOG_WARNING, "VST Plug-in's magic number is bad");
+ return;
+ }
+
+ effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
+
+ // Set some default properties
+ size_t sampleRate = audio_output_get_sample_rate(
+ obs_get_audio());
+ effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr,
+ sampleRate);
+ int blocksize = 512;
+ effect->dispatcher(effect, effSetBlockSize, 0, blocksize,
+ nullptr, 0.0f);
+
+ effect->dispatcher(effect, effMainsChanged, 0, 1, nullptr, 0);
+
+ effectReady = true;
+ }
+}
+
+void silenceChannel(float **channelData, int numChannels, long numFrames) {
+ for (int channel = 0; channel < numChannels; ++channel) {
+ for (long frame = 0; frame < numFrames; ++frame) {
+ channelData[channel][frame] = 0.0f;
+ }
+ }
+}
+
+obs_audio_data *VSTPlugin::process(struct obs_audio_data *audio) {
+
+ if (effect && effectReady)
+ {
+ silenceChannel(outputs, VST_MAX_CHANNELS, audio->frames);
+
+ float *adata[VST_MAX_CHANNELS];
+ for (size_t d = 0; d < VST_MAX_CHANNELS; d++) {
+ adata[d] = (float *) audio->data[d];
+ };
+
+ effect->processReplacing(effect, adata, outputs, audio->frames);
+
+ for (size_t c = 0; c < VST_MAX_CHANNELS; c++) {
+ if (audio->data[c]) {
+ for (size_t i = 0; i < audio->frames; i++) {
+ adata[c][i] = outputs[c][i];
+ }
+ }
+ }
+ }
+
+ return audio;
+}
+
+void VSTPlugin::unloadEffect() {
+ effectReady = false;
+
+ if (effect)
+ {
+ effect->dispatcher(effect, effMainsChanged, 0, 0, nullptr, 0);
+ effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
+ }
+
+ effect = nullptr;
+
+ unloadLibrary();
+}
+
+void VSTPlugin::openEditor() {
+ if (effect && !editorWidget)
+ {
+ editorWidget = new EditorWidget(nullptr, this);
+ editorWidget->buildEffectContainer(effect);
+ editorWidget->show();
+ }
+}
+
+void VSTPlugin::closeEditor() {
+ if (effect)
+ {
+ effect->dispatcher(effect, effEditClose, 0, 0, nullptr, 0);
+ }
+
+ if (editorWidget)
+ {
+ editorWidget->close();
+ delete editorWidget;
+ editorWidget = nullptr;
+ }
+}
+
+intptr_t VSTPlugin::hostCallback(AEffect *effect, int32_t opcode,
+ int32_t index, intptr_t value, void *ptr, float opt) {
+ UNUSED_PARAMETER(effect);
+ UNUSED_PARAMETER(ptr);
+ UNUSED_PARAMETER(opt);
+
+ intptr_t result = 0;
+
+ // Filter idle calls...
+ bool filtered = false;
+ if (opcode == audioMasterIdle)
+ {
+ static bool wasIdle = false;
+ if (wasIdle)
+ filtered = true;
+ else
+ {
+ blog(LOG_WARNING, "VST Plug-in: Future idle calls will not be displayed!");
+ wasIdle = true;
+ }
+ }
+
+ switch (opcode) {
+ case audioMasterSizeWindow:
+ // index: width, value: height
+ if (editorWidget)
+ {
+ editorWidget->handleResizeRequest(index,
+ value);
+ }
+ return 0;
+ }
+
+ return result;
+}
+
+std::string VSTPlugin::getChunk() {
+ if (!effect)
+ {
+ return "";
+ }
+
+ if (effect->flags & effFlagsProgramChunks)
+ {
+ void *buf = nullptr;
+
+ intptr_t chunkSize = effect->dispatcher(effect, effGetChunk, 1, 0, &buf, 0.0);
+
+ QByteArray data = QByteArray((char *) buf, chunkSize);
+ return QString(data.toBase64()).toStdString();
+ } else {
+ std::vector<float> params;
+ for (int i = 0; i < effect->numParams; i++) {
+ float parameter = effect->getParameter(effect, i);
+ params.push_back(parameter);
+ }
+
+ const char *bytes = reinterpret_cast<const char *>(¶ms[0]);
+ QByteArray data = QByteArray(bytes, sizeof(float) * params.size());
+ std::string encoded = QString(data.toBase64()).toStdString();
+ return encoded;
+ }
+}
+
+void VSTPlugin::setChunk(std::string data) {
+ if (!effect)
+ {
+ return;
+ }
+
+ if (effect->flags & effFlagsProgramChunks)
+ {
+ QByteArray base64Data = QByteArray(data.c_str(),
+ data.length());
+ QByteArray chunkData = QByteArray::fromBase64(base64Data);
+ void *buf = nullptr;
+ buf = chunkData.data();
+ effect->dispatcher(effect, effSetChunk, 0, chunkData.length(), buf, 0);
+ } else {
+ QByteArray base64Data = QByteArray(data.c_str(),
+ data.length());
+ QByteArray paramData = QByteArray::fromBase64(base64Data);
+
+ const char *p_chars = paramData.data();
+ const float *p_floats = reinterpret_cast<const float *>
+ (p_chars);
+
+ int size = paramData.length() / sizeof(float);
+
+ std::vector<float> params(p_floats, p_floats + size);
+
+ if (params.size() != effect->numParams)
+ {
+ return;
+ }
+
+ for (int i = 0; i < effect->numParams; i++) {
+ effect->setParameter(effect, i, params[i]);
+ }
+ }
+}
obs-studio-18.0.0.tar.xz/plugins/obs-vst/data
Added
+(directory)
obs-studio-18.0.0.tar.xz/plugins/obs-vst/data/locale
Added
+(directory)
obs-studio-18.0.0.tar.xz/plugins/obs-vst/data/locale/en-US.ini
Added
+OpenPluginInterface="Open Plug-in Interface"
+ClosePluginInterface="Close Plug-in Interface"
+VstPlugin="VST 2.x Plug-in"
obs-studio-18.0.0.tar.xz/plugins/obs-vst/headers
Added
+(directory)
obs-studio-18.0.0.tar.xz/plugins/obs-vst/headers/EditorWidget.h
Added
+/*****************************************************************************
+Copyright (C) 2016-2017 by Colin Edwards.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#ifndef OBS_STUDIO_EDITORDIALOG_H
+#define OBS_STUDIO_EDITORDIALOG_H
+
+#include <QWidget>
+#ifdef __APPLE__
+ #include <QMacCocoaViewContainer>
+#endif
+
+#include "aeffectx.h"
+#include "VSTPlugin.h"
+
+class VSTPlugin;
+
+class VstRect
+{
+ public:
+ short top;
+ short left;
+ short bottom;
+ short right;
+};
+
+class EditorWidget : public QWidget {
+
+ VSTPlugin *plugin;
+
+ #ifdef __APPLE__
+ QMacCocoaViewContainer *cocoaViewContainer = NULL;
+ #elif WIN32
+
+ #elif __linux__
+
+ #endif
+
+ public:
+ EditorWidget(QWidget *parent, VSTPlugin *plugin);
+ void buildEffectContainer(AEffect *effect);
+ void closeEvent(QCloseEvent *event) override;
+ void handleResizeRequest(int width, int height);
+};
+
+#endif //OBS_STUDIO_EDITORDIALOG_H
\ No newline at end of file
obs-studio-18.0.0.tar.xz/plugins/obs-vst/headers/VSTPlugin.h
Added
+/*****************************************************************************
+Copyright (C) 2016-2017 by Colin Edwards.
+Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#ifndef OBS_STUDIO_VSTPLUGIN_H
+#define OBS_STUDIO_VSTPLUGIN_H
+
+#define VST_MAX_CHANNELS 8
+
+#include <string>
+#include "aeffectx.h"
+#include <obs-module.h>
+#include "vst-plugin-callbacks.hpp"
+#include "EditorWidget.h"
+
+#ifdef __APPLE__
+ #include <CoreFoundation/CoreFoundation.h>
+#endif
+
+class EditorWidget;
+
+class VSTPlugin {
+ AEffect *effect = nullptr;
+ obs_source_t *sourceContext;
+ std::string pluginPath;
+
+ float **inputs;
+ float **outputs;
+
+ EditorWidget *editorWidget = nullptr;
+
+ AEffect* loadEffect();
+
+ bool effectReady = false;
+
+ #ifdef __APPLE__
+ CFBundleRef bundle = NULL;
+ #elif WIN32
+ HINSTANCE dllHandle = nullptr;
+ #elif __linux__
+ void *soHandle = nullptr;
+ #endif
+
+ void unloadLibrary();
+
+ static intptr_t hostCallback_static( AEffect *effect, int32_t opcode,
+ int32_t index, intptr_t value, void *ptr, float opt)
+ {
+ if (effect && effect->user)
+ {
+ auto* plugin = static_cast<VSTPlugin*>(effect->user);
+ return plugin->hostCallback(effect, opcode, index, value,
+ ptr, opt);
+ }
+
+ switch (opcode)
+ {
+ case audioMasterVersion:
+ return (intptr_t) 2400;
+
+ default:
+ return 0;
+ }
+ }
+
+ intptr_t hostCallback( AEffect *effect, int32_t opcode, int32_t index,
+ intptr_t value, void *ptr, float opt);
+
+ public:
+ VSTPlugin(obs_source_t *sourceContext);
+ void loadEffectFromPath(std::string path);
+ void unloadEffect();
+ void openEditor();
+ void closeEditor();
+ std::string getChunk();
+ void setChunk(std::string data);
+ obs_audio_data* process(struct obs_audio_data *audio);
+};
+
+#endif //OBS_STUDIO_VSTPLUGIN_H
obs-studio-18.0.0.tar.xz/plugins/obs-vst/headers/vst-plugin-callbacks.hpp
Added
+/*****************************************************************************
+Copyright (C) 2016-2017 by Colin Edwards.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+#pragma once
+
+#include "aeffectx.h"
+
+typedef AEffect *(*vstPluginMain)(audioMasterCallback audioMaster);
\ No newline at end of file
obs-studio-18.0.0.tar.xz/plugins/obs-vst/linux
Added
+(directory)
obs-studio-18.0.0.tar.xz/plugins/obs-vst/linux/EditorWidget-linux.cpp
Added
+/*****************************************************************************
+Copyright (C) 2016-2017 by Colin Edwards.
+Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
+
+Special thanks to Nik Reiman for sharing his awesome code with the world.
+Some of the original code can be found here:
+https://github.com/teragonaudio/MrsWatson/blob/master/source/plugin/PluginVst2xLinux.cpp
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#include "../headers/EditorWidget.h"
+
+#include <X11/Xlib.h>
+#include <QWindow>
+
+
+void EditorWidget::buildEffectContainer(AEffect *effect) {
+ Display *display;
+ Window window;
+ XEvent event;
+
+ int screenNumber;
+
+ blog(LOG_WARNING, "Opening X display");
+ display = XOpenDisplay(NULL);
+ if (display == NULL)
+ {
+ blog(LOG_WARNING, "Can't open default display");
+ return;
+ }
+
+ blog(LOG_WARNING, "Acquiring default screen for X display");
+ screenNumber = DefaultScreen(display);
+ Screen *screen = DefaultScreenOfDisplay(display);
+
+ int screenWidth = WidthOfScreen(screen);
+ int screenHeight = HeightOfScreen(screen);
+ blog(LOG_WARNING, "Screen dimensions: %dx%d", screenWidth, screenHeight);
+
+ // Default size is 300x300 pixels
+ int windowX = (screenWidth - 300) / 2;
+ int windowY = (screenHeight - 300) / 2;
+
+ blog(LOG_WARNING, "Creating window at %dx%d", windowX, windowY);
+ window = XCreateSimpleWindow(display, RootWindow(display, screenNumber),
+ 0, 0, 300, 300, 1, BlackPixel(display, screenNumber),
+ BlackPixel(display, screenNumber));
+
+ //XStoreName(display, window, pluginName->data);
+/*
+ XSelectInput(display, window, ExposureMask | KeyPressMask);
+ XMapWindow(display, window);
+ XMoveWindow(display, window, windowX, windowY);
+
+
+ blog(LOG_WARNING, "Opening plugin editor window");
+ effect->dispatcher(effect, effEditOpen, 0, 0, (void *) window, 0);
+
+ while (true) {
+ XNextEvent(display, &event);
+
+ if (event.type == Expose) {
+ }
+
+ if (event.type == KeyPress) {
+ break;
+ }
+ }
+
+ blog(LOG_WARNING, "Closing plugin editor window");
+ effect->dispatcher(effect, effEditClose, 0, 0, 0, 0);
+ XDestroyWindow(display, window);
+ XCloseDisplay(display);
+*/
+ /*
+ QWidget *widget = QWidget::createWindowContainer(QWindow::window);
+ widget->move(0, 0);
+ widget->resize(300, 300);
+
+ effect->dispatcher(effect, effEditOpen, 0, 0, window, 0);
+
+ VstRect* vstRect = nullptr;
+ effect->dispatcher(effect, effEditGetRect, 0, 0, &vstRect, 0);
+ if (vstRect)
+ {
+ widget->resize(vstRect->right - vstRect->left,
+ vstRect->bottom - vstRect->top);
+ }
+ */
+}
+
+void EditorWidget::handleResizeRequest(int width, int height) {
+ // We don't have to do anything here as far as I can tell.
+ // The widget will resize the HWIND itself and then
+ // this widget will automatically size depending on that.
+}
\ No newline at end of file
obs-studio-18.0.0.tar.xz/plugins/obs-vst/linux/VSTPlugin-linux.cpp
Added
+/*****************************************************************************
+Copyright (C) 2016-2017 by Colin Edwards.
+Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+#include "../headers/VSTPlugin.h"
+
+#include <util/platform.h>
+#include <X11/Xlib.h>
+
+AEffect* VSTPlugin::loadEffect() {
+ AEffect *plugin = nullptr;
+
+ soHandle = dlopen(pluginPath.c_str(), RTLD_LAZY);
+ bfree(wpath);
+ bfree(charPath);
+ if(soHandle == nullptr)
+ {
+ blog(LOG_WARNING, "Failed trying to load VST from '%s', error %d\n",
+ pluginPath.c_str(), errno);
+ return nullptr;
+ }
+
+ vstPluginMain mainEntryPoint =
+ (vstPluginMain)(soHandle, "VSTPluginMain");
+
+ if (mainEntryPoint == nullptr) {
+ mainEntryPoint =
+ (vstPluginMain)os_dlsym(soHandle,
+ "VstPluginMain()");
+ }
+
+ if (mainEntryPoint == nullptr) {
+ mainEntryPoint = (vstPluginMain)os_dlsym(soHandle, "main");
+ }
+
+ if (mainEntryPoint == nullptr) {
+ blog(LOG_WARNING, "Couldn't get a pointer to plug-in's main()");
+ return nullptr;
+ }
+
+ // Instantiate the plug-in
+ plugin = mainEntryPoint(hostCallback_static);
+ plugin->user = this;
+ return plugin;
+}
+
+void VSTPlugin::unloadLibrary() {
+ if (soHandle) {
+ os_dlclose(soHandle);
+ soHandle = nullptr;
+ }
+}
\ No newline at end of file
obs-studio-18.0.0.tar.xz/plugins/obs-vst/mac
Added
+(directory)
obs-studio-18.0.0.tar.xz/plugins/obs-vst/mac/EditorWidget-osx.mm
Added
+/*****************************************************************************
+Copyright (C) 2016-2017 by Colin Edwards.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+#import "../headers/EditorWidget.h"
+#import <Cocoa/Cocoa.h>
+
+#import "../headers/VSTPlugin.h"
+
+void EditorWidget::buildEffectContainer(AEffect *effect) {
+ cocoaViewContainer = new QMacCocoaViewContainer(0, this);
+ cocoaViewContainer->move(0, 0);
+ cocoaViewContainer->resize(300, 300);
+ NSView *view = [[NSView alloc] initWithFrame: NSMakeRect(0, 0,
+ 300, 300)];
+ cocoaViewContainer->setCocoaView(view);
+
+ VstRect* vstRect = 0;
+ effect->dispatcher (effect, effEditGetRect, 0, 0, &vstRect, 0);
+ if (vstRect)
+ {
+ NSRect frame = NSMakeRect(vstRect->left, vstRect->top,
+ vstRect->right, vstRect->bottom);
+
+ [view setFrame:frame];
+
+ cocoaViewContainer->resize(vstRect->right - vstRect->left,
+ vstRect->bottom- vstRect->top);
+ }
+
+ effect->dispatcher (effect, effEditOpen, 0, 0, view, 0);
+}
+
+void EditorWidget::handleResizeRequest(int width, int height) {
+ resize(width, height);
+ cocoaViewContainer->resize(width, height);
+ NSView *view = cocoaViewContainer->cocoaView();
+ NSRect frame = NSMakeRect(0, 0, width, height);
+
+ [view setFrame:frame];
+}
\ No newline at end of file
obs-studio-18.0.0.tar.xz/plugins/obs-vst/mac/VSTPlugin-osx.mm
Added
+/*****************************************************************************
+Copyright (C) 2016-2017 by Colin Edwards.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#include "../headers/VSTPlugin.h"
+
+AEffect* VSTPlugin::loadEffect() {
+ AEffect* newEffect = NULL;
+
+ // Create a path to the bundle
+ CFStringRef pluginPathStringRef = CFStringCreateWithCString(NULL,
+ pluginPath.c_str(), kCFStringEncodingUTF8);
+ CFURLRef bundleUrl = CFURLCreateWithFileSystemPath
+ (kCFAllocatorDefault, pluginPathStringRef,
+ kCFURLPOSIXPathStyle, true);
+
+ if (bundleUrl == NULL)
+ {
+ blog(LOG_WARNING, "Couldn't make URL reference for VST plug-in");
+ return NULL;
+ }
+
+ // Open the bundle
+ bundle = CFBundleCreate(kCFAllocatorDefault, bundleUrl);
+ if (bundle == NULL)
+ {
+ blog(LOG_WARNING, "Couldn't create VST bundle reference.");
+ CFRelease(pluginPathStringRef);
+ CFRelease(bundleUrl);
+ return NULL;
+ }
+
+ vstPluginMain mainEntryPoint = NULL;
+ mainEntryPoint = (vstPluginMain) CFBundleGetFunctionPointerForName
+ (bundle, CFSTR("VSTPluginMain"));
+
+ // VST plugins previous to the 2.4 SDK used main_macho for the
+ // entry point name.
+ if (mainEntryPoint == NULL)
+ {
+ mainEntryPoint = (vstPluginMain)
+ CFBundleGetFunctionPointerForName(bundle,
+ CFSTR("main_macho"));
+ }
+
+ if (mainEntryPoint == NULL)
+ {
+ blog(LOG_WARNING, "Couldn't get a pointer to plug-in's main()");
+ CFBundleUnloadExecutable(bundle);
+ CFRelease(bundle);
+ return NULL;
+ }
+
+ newEffect = mainEntryPoint(hostCallback_static);
+ if (newEffect == NULL)
+ {
+ blog(LOG_WARNING, "VST Plug-in's main() returns null.");
+ CFBundleUnloadExecutable(bundle);
+ CFRelease(bundle);
+ return NULL;
+ }
+
+ newEffect->user = this;
+
+ // Clean up
+ CFRelease(pluginPathStringRef);
+ CFRelease(bundleUrl);
+
+ return newEffect;
+}
+
+void VSTPlugin::unloadLibrary() {
+ if (bundle)
+ {
+ CFBundleUnloadExecutable(bundle);
+ CFRelease(bundle);
+ }
+}
\ No newline at end of file
obs-studio-18.0.0.tar.xz/plugins/obs-vst/obs-vst.cpp
Added
+/*****************************************************************************
+Copyright (C) 2016-2017 by Colin Edwards.
+Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#include "headers/VSTPlugin.h"
+#include <QDir>
+#include <QDirIterator>
+
+#define OPEN_VST_SETTINGS "open_vst_settings"
+#define CLOSE_VST_SETTINGS "close_vst_settings"
+
+#define PLUG_IN_NAME obs_module_text("VstPlugin")
+#define OPEN_VST_TEXT obs_module_text("OpenPluginInterface")
+#define CLOSE_VST_TEXT obs_module_text("ClosePluginInterface")
+
+OBS_DECLARE_MODULE()
+OBS_MODULE_USE_DEFAULT_LOCALE("obs-vst", "en-US")
+
+static bool open_editor_button_clicked(obs_properties_t *props,
+ obs_property_t *property, void *data)
+{
+ VSTPlugin *vstPlugin = (VSTPlugin *)data;
+
+ vstPlugin->openEditor();
+
+ obs_property_set_visible(obs_properties_get(props,
+ OPEN_VST_SETTINGS), false);
+ obs_property_set_visible(obs_properties_get(props,
+ CLOSE_VST_SETTINGS), true);
+
+ UNUSED_PARAMETER(props);
+ UNUSED_PARAMETER(property);
+ UNUSED_PARAMETER(data);
+
+ return true;
+}
+
+static bool close_editor_button_clicked(obs_properties_t *props,
+ obs_property_t *property, void *data)
+{
+ VSTPlugin *vstPlugin = (VSTPlugin *)data;
+
+ vstPlugin->closeEditor();
+
+ obs_property_set_visible(obs_properties_get(props,
+ OPEN_VST_SETTINGS), true);
+ obs_property_set_visible(obs_properties_get(props,
+ CLOSE_VST_SETTINGS), false);
+
+ UNUSED_PARAMETER(property);
+
+ return true;
+}
+
+static const char *vst_name(void *unused)
+{
+ UNUSED_PARAMETER(unused);
+ return PLUG_IN_NAME;
+}
+
+static void vst_destroy(void *data)
+{
+ VSTPlugin *vstPlugin = (VSTPlugin *)data;
+ vstPlugin->closeEditor();
+ delete vstPlugin;
+}
+
+static void vst_update(void *data, obs_data_t *settings)
+{
+ VSTPlugin *vstPlugin = (VSTPlugin *)data;
+
+ const char *path = obs_data_get_string(settings, "plugin_path");
+
+ if (strcmp(path, "") == 0)
+ {
+ return;
+ }
+ vstPlugin->loadEffectFromPath(std::string(path));
+
+ const char *chunkData = obs_data_get_string(settings, "chunk_data");
+ if (chunkData && strlen(chunkData) > 0) {
+ vstPlugin->setChunk(std::string(chunkData));
+ obs_data_set_string(settings, "chunk_data",
+ vstPlugin->getChunk().c_str());
+ }
+}
+
+static void *vst_create(obs_data_t *settings, obs_source_t *filter)
+{
+ VSTPlugin *vstPlugin = new VSTPlugin(filter);
+ vst_update(vstPlugin, settings);
+
+ return vstPlugin;
+}
+
+static void vst_save(void *data, obs_data_t *settings)
+{
+ VSTPlugin *vstPlugin = (VSTPlugin *)data;
+
+ obs_data_set_string(settings, "chunk_data",
+ vstPlugin->getChunk().c_str());
+}
+
+static struct obs_audio_data *vst_filter_audio(void *data,
+ struct obs_audio_data *audio)
+{
+ VSTPlugin *vstPlugin = (VSTPlugin *)data;
+ vstPlugin->process(audio);
+
+ return audio;
+}
+
+static void fill_out_plugins(obs_property_t *list)
+{
+ QStringList dir_list;
+
+ #ifdef __APPLE__
+ dir_list << "/Library/Audio/Plug-Ins/VST/"
+ << "~/Library/Audio/Plug-ins/VST/";
+ #elif WIN32
+ dir_list << "C:/Program Files/Steinberg/VstPlugins/"
+ << "C:/Program Files/Common Files/Steinberg/Shared Components/"
+ << "C:/Program Files/Common Files/VST2"
+ << "C:/Program Files/Common Files/VSTPlugins/"
+ << "C:/Program Files/VSTPlugins/";
+ #elif __linux__
+ // If the user has set the VST_PATH environmental
+ // variable, then use it. Else default to a list
+ // of common locations.
+ char *vstPathEnv;
+ vstPathEnv = getenv("VST_PATH");
+ if (vstPathEnv != nullptr)
+ {
+ dir_list << vstPathEnv;
+ } else {
+ // Choose the most common locations
+ dir_list << "/usr/lib/vst/"
+ << "/usr/lib/lxvst/"
+ << "/usr/lib/linux_vst/"
+ << "/usr/lib64/vst/"
+ << "/usr/lib64/lxvst/"
+ << "/usr/lib64/linux_vst/"
+ << "/usr/local/lib/vst/"
+ << "/usr/local/lib/lxvst/"
+ << "/usr/local/lib/linux_vst/"
+ << "/usr/local/lib64/vst/"
+ << "/usr/local/lib64/lxvst/"
+ << "/usr/local/lib64/linux_vst/"
+ << "~/.vst/"
+ << "~/.lxvst/";
+ }
+ #endif
+
+ QStringList filters;
+
+ #ifdef __APPLE__
+ filters << "*.vst";
+ #elif WIN32
+ filters << "*.dll";
+ #elif __linux__
+ filters << "*.so" << "*.o";
+ #endif
+
+ QStringList vst_list;
+
+ // Read all plugins into a list...
+ for (int a = 0; a < dir_list.size(); ++a)
+ {
+ QDir search_dir(dir_list[a]);
+ search_dir.setNameFilters(filters);
+ QDirIterator it(search_dir, QDirIterator::Subdirectories);
+ while (it.hasNext()) {
+ QString path = it.next();
+ QString name = it.fileName();
+
+ #ifdef __APPLE__
+ name.remove(QRegExp("(\\.vst)"));
+ #elif WIN32
+ name.remove(QRegExp("(\\.dll)"));
+ #elif __linux__
+ name.remove(QRegExp("(\\.so|\\.o)"));
+ #endif
+
+ name.append("=").append(path);
+ vst_list << name;
+ }
+ }
+
+ // Now sort list alphabetically (still case-sensitive though).
+ std::stable_sort(vst_list.begin(), vst_list.end(),
+ std::less<QString>());
+
+ // Now add said list to the plug-in list of OBS
+ obs_property_list_add_string(list, "{Please select a plug-in}",
+ nullptr);
+ for (int b = 0; b < vst_list.size(); ++b)
+ {
+ QString vst_sorted = vst_list[b];
+ obs_property_list_add_string(list,
+ vst_sorted.left(vst_sorted.indexOf
+ ('=')).toStdString().c_str(),
+ vst_sorted.mid(vst_sorted.indexOf('=') +
+ 1).toStdString().c_str());
+ }
+}
+
+static obs_properties_t *vst_properties(void *data)
+{
+ obs_properties_t *props = obs_properties_create();
+ obs_property_t *list = obs_properties_add_list(props, "plugin_path",
+ PLUG_IN_NAME, OBS_COMBO_TYPE_LIST,
+ OBS_COMBO_FORMAT_STRING);
+
+ fill_out_plugins(list);
+
+ obs_properties_add_button(props, OPEN_VST_SETTINGS, OPEN_VST_TEXT,
+ open_editor_button_clicked);
+
+ obs_properties_add_button(props, CLOSE_VST_SETTINGS, CLOSE_VST_TEXT,
+ close_editor_button_clicked);
+ obs_property_set_visible(obs_properties_get(props,
+ CLOSE_VST_SETTINGS), false);
+
+ UNUSED_PARAMETER(data);
+
+ return props;
+}
+
+bool obs_module_load(void)
+{
+ struct obs_source_info vst_filter = {};
+ vst_filter.id = "vst_filter";
+ vst_filter.type = OBS_SOURCE_TYPE_FILTER;
+ vst_filter.output_flags = OBS_SOURCE_AUDIO;
+ vst_filter.get_name = vst_name;
+ vst_filter.create = vst_create;
+ vst_filter.destroy = vst_destroy;
+ vst_filter.update = vst_update;
+ vst_filter.filter_audio = vst_filter_audio;
+ vst_filter.get_properties = vst_properties;
+ vst_filter.save = vst_save;
+
+ obs_register_source(&vst_filter);
+ return true;
+}
\ No newline at end of file
obs-studio-18.0.0.tar.xz/plugins/obs-vst/vst_header
Added
+(directory)
obs-studio-18.0.0.tar.xz/plugins/obs-vst/vst_header/aeffectx.h
Added
+/*
+ * aeffectx.h - simple header to allow VeSTige compilation and eventually work
+ *
+ * Copyright (c) 2006 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
+ *
+ * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program (see COPYING); if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdint.h>
+
+#ifndef _AEFFECTX_H
+#define _AEFFECTX_H
+
+#define CCONST(a, b, c, d)( ( ( (int) a ) << 24 ) | \
+ ( ( (int) b ) << 16 ) | \
+ ( ( (int) c ) << 8 ) | \
+ ( ( (int) d ) << 0 ) )
+
+
+const int audioMasterAutomate = 0;
+const int audioMasterVersion = 1;
+const int audioMasterCurrentId = 2;
+const int audioMasterIdle = 3;
+const int audioMasterPinConnected = 4;
+// unsupported? 5
+const int audioMasterWantMidi = 6;
+const int audioMasterGetTime = 7;
+const int audioMasterProcessEvents = 8;
+const int audioMasterSetTime = 9;
+const int audioMasterTempoAt = 10;
+const int audioMasterGetNumAutomatableParameters = 11;
+const int audioMasterGetParameterQuantization = 12;
+const int audioMasterIOChanged = 13;
+const int audioMasterNeedIdle = 14;
+const int audioMasterSizeWindow = 15;
+const int audioMasterGetSampleRate = 16;
+const int audioMasterGetBlockSize = 17;
+const int audioMasterGetInputLatency = 18;
+const int audioMasterGetOutputLatency = 19;
+const int audioMasterGetPreviousPlug = 20;
+const int audioMasterGetNextPlug = 21;
+const int audioMasterWillReplaceOrAccumulate = 22;
+const int audioMasterGetCurrentProcessLevel = 23;
+const int audioMasterGetAutomationState = 24;
+const int audioMasterOfflineStart = 25;
+const int audioMasterOfflineRead = 26;
+const int audioMasterOfflineWrite = 27;
+const int audioMasterOfflineGetCurrentPass = 28;
+const int audioMasterOfflineGetCurrentMetaPass = 29;
+const int audioMasterSetOutputSampleRate = 30;
+// unsupported? 31
+const int audioMasterGetSpeakerArrangement = 31; // deprecated in 2.4?
+const int audioMasterGetVendorString = 32;
+const int audioMasterGetProductString = 33;
+const int audioMasterGetVendorVersion = 34;
+const int audioMasterVendorSpecific = 35;
+const int audioMasterSetIcon = 36;
+const int audioMasterCanDo = 37;
+const int audioMasterGetLanguage = 38;
+const int audioMasterOpenWindow = 39;
+const int audioMasterCloseWindow = 40;
+const int audioMasterGetDirectory = 41;
+const int audioMasterUpdateDisplay = 42;
+const int audioMasterBeginEdit = 43;
+const int audioMasterEndEdit = 44;
+const int audioMasterOpenFileSelector = 45;
+const int audioMasterCloseFileSelector = 46; // currently unused
+const int audioMasterEditFile = 47; // currently unused
+const int audioMasterGetChunkFile = 48; // currently unused
+const int audioMasterGetInputSpeakerArrangement = 49; // currently unused
+
+const int effFlagsHasEditor = 1;
+const int effFlagsCanReplacing = 1 << 4; // very likely
+const int effFlagsProgramChunks = 1 << 5; // from Ardour
+const int effFlagsIsSynth = 1 << 8; // currently unused
+
+const int effOpen = 0;
+const int effClose = 1; // currently unused
+const int effSetProgram = 2; // currently unused
+const int effGetProgram = 3; // currently unused
+// The next one was gleaned from http://www.kvraudio.com/forum/viewtopic.php?p=1905347
+const int effSetProgramName = 4;
+const int effGetProgramName = 5; // currently unused
+// The next two were gleaned from http://www.kvraudio.com/forum/viewtopic.php?p=1905347
+const int effGetParamLabel = 6;
+const int effGetParamDisplay = 7;
+const int effGetParamName = 8; // currently unused
+const int effSetSampleRate = 10;
+const int effSetBlockSize = 11;
+const int effMainsChanged = 12;
+const int effEditGetRect = 13;
+const int effEditOpen = 14;
+const int effEditClose = 15;
+const int effEditIdle = 19;
+const int effEditTop = 20;
+const int effIdentify = 22; // from http://www.asseca.org/vst-24-specs/efIdentify.html
+const int effGetChunk = 23; // from Ardour
+const int effSetChunk = 24; // from Ardour
+const int effProcessEvents = 25;
+// The next one was gleaned from http://www.asseca.org/vst-24-specs/efCanBeAutomated.html
+const int effCanBeAutomated = 26;
+// The next one was gleaned from http://www.kvraudio.com/forum/viewtopic.php?p=1905347
+const int effGetProgramNameIndexed = 29;
+// The next one was gleaned from http://www.asseca.org/vst-24-specs/efGetPlugCategory.html
+const int effGetPlugCategory = 35;
+const int effGetEffectName = 45;
+const int effGetParameterProperties = 56; // missing
+const int effGetVendorString = 47;
+const int effGetProductString = 48;
+const int effGetVendorVersion = 49;
+const int effCanDo = 51; // currently unused
+// The next one was gleaned from http://www.asseca.org/vst-24-specs/efIdle.html
+const int effIdle = 53;
+const int effGetVstVersion = 58; // currently unused
+// The next one was gleaned from http://www.asseca.org/vst-24-specs/efBeginSetProgram.html
+const int effBeginSetProgram = 67;
+// The next one was gleaned from http://www.asseca.org/vst-24-specs/efEndSetProgram.html
+const int effEndSetProgram = 68;
+// The next one was gleaned from http://www.asseca.org/vst-24-specs/efShellGetNextPlugin.html
+const int effShellGetNextPlugin = 70;
+// The next one was gleaned from http://www.asseca.org/vst-24-specs/efBeginLoadBank.html
+const int effBeginLoadBank = 75;
+// The next one was gleaned from http://www.asseca.org/vst-24-specs/efBeginLoadProgram.html
+const int effBeginLoadProgram = 76;
+
+// The next two were gleaned from http://www.kvraudio.com/forum/printview.php?t=143587&start=0
+const int effStartProcess = 71;
+const int effStopProcess = 72;
+
+const int kEffectMagic = CCONST( 'V', 's', 't', 'P' );
+const int kVstLangEnglish = 1;
+const int kVstMidiType = 1;
+
+const int kVstNanosValid = 1 << 8;
+const int kVstPpqPosValid = 1 << 9;
+const int kVstTempoValid = 1 << 10;
+const int kVstBarsValid = 1 << 11;
+const int kVstCyclePosValid = 1 << 12;
+const int kVstTimeSigValid = 1 << 13;
+// from Ardour
+const int kVstSmpteValid = 1 << 14;
+// from Ardour
+const int kVstClockValid = 1 << 15;
+
+const int kVstTransportPlaying = 1 << 1;
+const int kVstTransportCycleActive = 1 << 2;
+const int kVstTransportChanged = 1;
+
+
+class RemoteVstPlugin;
+
+
+class VstMidiEvent
+{
+ public:
+ // 00
+ int type;
+ // 04
+ int byteSize;
+ // 08
+ int deltaFrames;
+ // 0c?
+ int flags;
+ // 10?
+ int noteLength;
+ // 14?
+ int noteOffset;
+ // 18
+ char midiData[4];
+ // 1c?
+ char detune;
+ // 1d?
+ char noteOffVelocity;
+ // 1e?
+ char reserved1;
+ // 1f?
+ char reserved2;
+};
+
+
+class VstEvent
+{
+ char dump[sizeof( VstMidiEvent )];
+};
+
+
+class VstEvents
+{
+ public:
+ // 00
+ int numEvents;
+ // 04
+ void *reserved;
+ // 08
+ VstEvent* events[1];
+};
+
+
+// Not finished, neither really used
+class VstParameterProperties
+{
+ public:
+ /*
+ float stepFloat;
+ char label[64];
+ int flags;
+ int minInteger;
+ int maxInteger;
+ int stepInteger;
+ char shortLabel[8];
+ int category;
+ char categoryLabel[24];
+ char empty[128];
+ */
+
+ float stepFloat;
+ float smallStepFloat;
+ float largeStepFloat;
+ char label[64];
+ unsigned int flags;
+ unsigned int minInteger;
+ unsigned int maxInteger;
+ unsigned int stepInteger;
+ unsigned int largeStepInteger;
+ char shortLabel[8];
+ unsigned short displayIndex;
+ unsigned short category;
+ unsigned short numParametersInCategory;
+ unsigned short reserved;
+ char categoryLabel[24];
+ char future[16];
+};
+
+
+class AEffect
+{
+ public:
+ // Never use virtual functions!!!
+ // 00-03
+ int magic;
+ // dispatcher 04-07
+ intptr_t (* dispatcher)( AEffect * , int , int , intptr_t, void * , float );
+ // process, quite sure 08-0b
+ void (* process)( AEffect * , float * * , float * * , int );
+ // setParameter 0c-0f
+ void (* setParameter)( AEffect * , int , float );
+ // getParameter 10-13
+ float (* getParameter)( AEffect * , int );
+ // programs 14-17
+ int numPrograms;
+ // Params 18-1b
+ int numParams;
+ // Input 1c-1f
+ int numInputs;
+ // Output 20-23
+ int numOutputs;
+ // flags 24-27
+ int flags;
+ // Fill somewhere 28-2b
+ void * ptr1;
+ void * ptr2;
+ int initialDelay;
+ // Zeroes 34-37 38-3b
+ int empty3a;
+ int empty3b;
+ // 1.0f 3c-3f
+ float unkown_float;
+ // An object? pointer 40-43
+ void *ptr3;
+ // Zeroes 44-47
+ void *user;
+ // Id 48-4b
+ int32_t uniqueID;
+ int32_t version;
+ // processReplacing 50-53
+ void (* processReplacing)( AEffect * , float * * , float * * , int );
+};
+
+typedef intptr_t (* audioMasterCallback)( AEffect * , int32_t, int32_t,
+ intptr_t, void * , float );
+
+class VstTimeInfo
+{
+ public:
+ // 00
+ double samplePos;
+ // 08
+ double sampleRate;
+ // 10
+ double nanoSeconds;
+ // 18
+ double ppqPos;
+ // 20?
+ double tempo;
+ // 28
+ double barStartPos;
+ // 30?
+ double cycleStartPos;
+ // 38?
+ double cycleEndPos;
+ // 40?
+ int timeSigNumerator;
+ // 44?
+ int timeSigDenominator;
+ // unconfirmed 48 4c 50
+ char empty3[4 + 4 + 4];
+ // 54
+ int flags;
+};
+
+// from http://www.asseca.org/vst-24-specs/efGetParameterProperties.html
+enum VstParameterFlags
+{
+ // parameter is a switch (on/off)
+ kVstParameterIsSwitch = 1 << 0,
+
+ // minInteger, maxInteger valid
+ kVstParameterUsesIntegerMinMax = 1 << 1,
+
+ // stepFloat, smallStepFloat, largeStepFloat valid
+ kVstParameterUsesFloatStep = 1 << 2,
+
+ // stepInteger, largeStepInteger valid
+ kVstParameterUsesIntStep = 1 << 3,
+
+ // displayIndex valid
+ kVstParameterSupportsDisplayIndex = 1 << 4,
+
+ // category, etc. valid
+ kVstParameterSupportsDisplayCategory = 1 << 5,
+
+ // set if parameter value can ramp up/down
+ kVstParameterCanRamp = 1 << 6
+};
+
+// from http://www.asseca.org/vst-24-specs/efBeginLoadProgram.html
+struct VstPatchChunkInfo
+{
+ int32_t version; // Format Version (should be 1)
+ int32_t pluginUniqueID; // UniqueID of the plug-in
+ int32_t pluginVersion; // Plug-in Version
+ int32_t numElements; // Number of Programs (Bank) or
+ // Parameters (Program)
+ char future[48]; // Reserved for future use
+};
+
+// from http://www.asseca.org/vst-24-specs/efGetPlugCategory.html
+enum VstPlugCategory
+{
+ kPlugCategUnknown = 0, // 0=Unknown, category not implemented
+ kPlugCategEffect, // 1=Simple Effect
+ kPlugCategSynth, // 2=VST Instrument (Synths, samplers,...)
+ kPlugCategAnalysis, // 3=Scope, Tuner, ...
+ kPlugCategMastering, // 4=Dynamics, ...
+ kPlugCategSpacializer, // 5=Panners, ...
+ kPlugCategRoomFx, // 6=Delays and Reverbs
+ kPlugSurroundFx, // 7=Dedicated surround processor
+ kPlugCategRestoration, // 8=Denoiser, ...
+ kPlugCategOfflineProcess, // 9=Offline Process
+ kPlugCategShell, // 10=Plug-in is container of other
+ // plug-ins @see effShellGetNextPlugin()
+ kPlugCategGenerator, // 11=ToneGenerator, ...
+ kPlugCategMaxCount // 12=Marker to count the categories
+};
+
+#endif
\ No newline at end of file
obs-studio-18.0.0.tar.xz/plugins/obs-vst/win
Added
+(directory)
obs-studio-18.0.0.tar.xz/plugins/obs-vst/win/EditorWidget-win.cpp
Added
+/*****************************************************************************
+Copyright (C) 2016-2017 by Colin Edwards.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#include "../headers/EditorWidget.h"
+
+#include <QWindow>
+#include <Windows.h>
+
+void EditorWidget::buildEffectContainer(AEffect *effect) {
+ WNDCLASSEX wcex{ sizeof(wcex)
+ };
+
+ wcex.lpfnWndProc = DefWindowProc;
+ wcex.hInstance = GetModuleHandle(0);
+ wcex.lpszClassName = L"Minimal VST host - Guest VST Window Frame";
+ RegisterClassEx(&wcex);
+
+ const auto style = WS_CAPTION | WS_THICKFRAME | WS_OVERLAPPEDWINDOW;
+ HWND hwnd = CreateWindow(
+ wcex.lpszClassName, TEXT(""), style
+ , 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr
+ );
+
+ QWidget *widget = QWidget::createWindowContainer(
+ QWindow::fromWinId((WId)hwnd), this);
+ widget->move(0, 0);
+ widget->resize(300, 300);
+
+ effect->dispatcher(effect, effEditOpen, 0, 0, hwnd, 0);
+
+ VstRect* vstRect = nullptr;
+ effect->dispatcher(effect, effEditGetRect, 0, 0, &vstRect, 0);
+ if (vstRect)
+ {
+ widget->resize(vstRect->right - vstRect->left,
+ vstRect->bottom - vstRect->top);
+ }
+}
+
+void EditorWidget::handleResizeRequest(int width, int height) {
+ // We don't have to do anything here as far as I can tell. The widget will resize the HWIND itself and then this widget will automatically size depending on that.
+}
\ No newline at end of file
obs-studio-18.0.0.tar.xz/plugins/obs-vst/win/VSTPlugin-win.cpp
Added
+/*****************************************************************************
+Copyright (C) 2016-2017 by Colin Edwards.
+Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+#include "../headers/VSTPlugin.h"
+#include "../headers/vst-plugin-callbacks.hpp"
+
+#include <util/platform.h>
+#include <windows.h>
+
+AEffect* VSTPlugin::loadEffect() {
+ AEffect *plugin = nullptr;
+
+ wchar_t *wpath;
+ os_utf8_to_wcs_ptr(pluginPath.c_str(), 0, &wpath);
+ dllHandle = LoadLibraryW(wpath);
+ bfree(wpath);
+ if(dllHandle == nullptr) {
+
+ DWORD errorCode = GetLastError();
+
+ // Display the error message and exit the process
+ if (errorCode == ERROR_BAD_EXE_FORMAT) {
+ blog(LOG_WARNING, "Could not open library, wrong architecture.");
+ } else {
+ blog(LOG_WARNING, "Failed trying to load VST from '%s', error %d\n",
+ pluginPath, GetLastError());
+ }
+ return nullptr;
+ }
+
+ vstPluginMain mainEntryPoint =
+ (vstPluginMain)GetProcAddress(dllHandle, "VSTPluginMain");
+
+ if (mainEntryPoint == nullptr) {
+ mainEntryPoint =
+ (vstPluginMain)GetProcAddress(dllHandle,
+ "VstPluginMain()");
+ }
+
+ if (mainEntryPoint == nullptr) {
+ mainEntryPoint = (vstPluginMain)GetProcAddress(dllHandle,
+ "main");
+ }
+
+ if (mainEntryPoint == nullptr) {
+ blog(LOG_WARNING, "Couldn't get a pointer to plug-in's main()");
+ return nullptr;
+ }
+
+ // Instantiate the plug-in
+ plugin = mainEntryPoint(hostCallback_static);
+ plugin->user = this;
+ return plugin;
+}
+
+void VSTPlugin::unloadLibrary() {
+ if (dllHandle) {
+ FreeLibrary(dllHandle);
+ dllHandle = nullptr;
+ }
+}
\ No newline at end of file
obs-studio-17.0.2.tar.xz/plugins/obs-x264/data/locale/da-DK.ini -> obs-studio-18.0.0.tar.xz/plugins/obs-x264/data/locale/da-DK.ini
Changed
Bitrate="Bitrate"
CustomBufsize="Brug brugerdefineret bufferstørrelse"
BufferSize="Bufferstørrelsen"
+RateControl="Rate kontrol"
CRF="CRF"
KeyframeIntervalSec="Keyframe interval (sekunder, 0 = auto)"
CPUPreset="CPU forbrug indstilling (højere = mindre CPU)"
obs-studio-17.0.2.tar.xz/plugins/rtmp-services/data/package.json -> obs-studio-18.0.0.tar.xz/plugins/rtmp-services/data/package.json
Changed
{
"url": "https://obsproject.com/obs2_update/rtmp-services",
- "version": 44,
+ "version": 52,
"files": [
{
"name": "services.json",
- "version": 44
+ "version": 52
}
]
}
obs-studio-17.0.2.tar.xz/plugins/rtmp-services/data/services.json -> obs-studio-18.0.0.tar.xz/plugins/rtmp-services/data/services.json
Changed
"url": "rtmp://live-fra.twitch.tv/app"
},
{
+ "name": "EU: Lisbon, Portugal",
+ "url": "rtmp://live-lis.twitch.tv/app"
+ },
+ {
"name": "EU: London, UK",
"url": "rtmp://live-lhr.twitch.tv/app"
},
{
+ "name": "EU: Milan, Italy",
+ "url": "rtmp://live-mil.twitch.tv/app"
+ },
+ {
"name": "EU: Paris, FR",
"url": "rtmp://live-cdg.twitch.tv/app"
},
"url": "rtmp://live-waw.twitch.tv/app"
},
{
+ "name": "NA: Mexico City",
+ "url": "rtmp://live-qro.twitch.tv/app"
+ },
+ {
+ "name": "NA: Toronto, Canada",
+ "url": "rtmp://live-yto.twitch.tv/app"
+ },
+ {
"name": "South America: Argentina",
"url": "rtmp://live-eze.twitch.tv/app"
},
"url": "rtmp://live-scl.twitch.tv/app"
},
{
+ "name": "South America: Lima, Peru",
+ "url": "rtmp://live-lim.twitch.tv/app"
+ },
+ {
+ "name": "South America: Medellin, Columbia",
+ "url": "rtmp://live-mde.twitch.tv/app"
+ },
+ {
"name": "South America: Rio de Janeiro, Brazil",
"url": "rtmp://live-gig.twitch.tv/app"
},
],
"recommended": {
"keyint": 2,
- "profile": "main",
"max video bitrate": 51000,
"max audio bitrate": 160
}
"url": "rtmp://live.dme.hitbox.tv/push"
},
{
- "name": "US-East: Washington",
- "url": "rtmp://live.vgn.hitbox.tv/push"
- },
- {
"name": "US-East: New York - 1",
"url": "rtmp://live.jfk.hitbox.tv/push"
},
"url": "rtmp://ingest-fra.beam.pro:1935/beam"
},
{
+ "name": "EU: Oslo",
+ "url": "rtmp://ingest-osl.beam.pro:1935/beam"
+ },
+ {
"name": "Brazil: Sao Paulo",
"url": "rtmp://ingest-sao.beam.pro:1935/beam"
},
{
"name": "Asia: Tokyo",
"url": "rtmp://ingest-tok.beam.pro:1935/beam"
+ },
+ {
+ "name": "South Korea: Seoul",
+ "url": "rtmp://ingest-seo.beam.pro:1935/beam"
+ },
+ {
+ "name": "India: Chennai",
+ "url": "rtmp://ingest-che.beam.pro:1935/beam"
}
],
"recommended": {
"keyint": 1,
"max audio bitrate": 160,
- "max video bitrate": 3500,
+ "max video bitrate": 10000,
"profile": "main"
}
},
]
},
{
+ "name": "Web.TV",
+ "servers": [
+ {
+ "name": "Primary",
+ "url": "rtmp://live3.origins.web.tv/liveext"
+ }
+ ],
+ "recommended": {
+ "keyint": 2,
+ "profile": "main",
+ "max video bitrate": 3500,
+ "max audio bitrate": 160
+ }
+ },
+ {
"name": "Switchboard Live (Joicaster)",
"servers": [
{
]
},
{
- "name": "Vaughn Live / iNSTAGIB.tv",
+ "name": "Vaughn Live / iNSTAGIB",
"servers": [
{
"name": "US: Primary",
- "url": "rtmp://live.vaughnsoft.net:443/live"
+ "url": "rtmp://live.vaughnsoft.net/live"
},
{
- "name": "US: San Jose, CA",
- "url": "rtmp://live-sjc.vaughnsoft.net:443/live"
+ "name": "US: Chicago, IL",
+ "url": "rtmp://live-ord.vaughnsoft.net/live"
},
{
- "name": "US: New York, NY",
- "url": "rtmp://live-nyc.vaughnsoft.net:443/live"
+ "name": "US: Denver, CO",
+ "url": "rtmp://live-den.vaughnsoft.net/live"
},
{
- "name": "US: New York 2, NY",
- "url": "rtmp://live-nyc2.vaughnsoft.net:443/live"
- }
- ]
- },
- {
- "name": "connectcast.tv",
- "servers": [
+ "name": "US: Los Angeles, CA",
+ "url": "rtmp://live-lax.vaughnsoft.net/live"
+ },
{
- "name": "Default",
- "url": "rtmp://stream.connectcast.tv/live"
+ "name": "EU: Amsterdam, NL",
+ "url": "rtmp://live-ams.vaughnsoft.net/live"
}
- ]
+ ],
+ "recommended": {
+ "keyint": 2,
+ "max video bitrate": 3500,
+ "max audio bitrate": 160
+ }
},
{
- "name": "Kamcord",
+ "name": "Breakers.TV",
"servers": [
{
- "name": "US East (N. Virginia)",
- "url": "rtmp://us-east-1.stream.kamcord.com/live"
- },
- {
- "name": "Asia Pacific (Seoul)",
- "url": "rtmp://ap-northeast-2.stream.kamcord.com/live"
- },
- {
- "name": "Asia Pacific (Sydney)",
- "url": "rtmp://ap-southeast-2.stream.kamcord.com/live"
+ "name": "US: Primary",
+ "url": "rtmp://live.vaughnsoft.net/live"
},
{
- "name": "Asia Pacific (Tokyo)",
- "url": "rtmp://ap-northeast-1.stream.kamcord.com/live"
+ "name": "US: Chicago, IL",
+ "url": "rtmp://live-ord.vaughnsoft.net/live"
},
{
- "name": "EU (Frankfurt)",
- "url": "rtmp://eu-central-1.stream.kamcord.com/live"
+ "name": "US: Denver, CO",
+ "url": "rtmp://live-den.vaughnsoft.net/live"
},
{
- "name": "South America (Sao Paulo)",
- "url": "rtmp://sa-east-1.stream.kamcord.com/live"
+ "name": "US: Los Angeles, CA",
+ "url": "rtmp://live-lax.vaughnsoft.net/live"
},
{
- "name": "US West (N. California)",
- "url": "rtmp://us-west-1.stream.kamcord.com/live"
+ "name": "EU: Amsterdam, NL",
+ "url": "rtmp://live-ams.vaughnsoft.net/live"
}
],
"recommended": {
"keyint": 2,
- "profile": "main",
- "max video bitrate": 4000,
- "max audio bitrate": 192
+ "max video bitrate": 3500,
+ "max audio bitrate": 160
}
},
{
+ "name": "connectcast.tv",
+ "servers": [
+ {
+ "name": "Default",
+ "url": "rtmp://stream.connectcast.tv/live"
+ }
+ ]
+ },
+ {
"name": "CyberGame.TV",
"servers": [
{
"url": "rtmp://us-west.restream.io/live"
},
{
+ "name": "US-West (Los Angeles, CA)",
+ "url": "rtmp://us-la.restream.io/live"
+ },
+ {
"name": "US-Central (Dallas, TX)",
"url": "rtmp://us-central.restream.io/live"
},
]
},
{
- "name": "Interactive LifeStream",
- "servers": [
- {
- "name": "Default",
- "url": "rtmp://lifestreamcdn.com/live/_definst_/doPublish=wls36"
- }
- ]
- },
- {
"name": "Stre.am",
"servers": [
{
"max video bitrate": 2000,
"max audio bitrate": 160
}
+ },
+ {
+ "name": "Pandora TV Korea",
+ "servers": [
+ {
+ "name": "Default",
+ "url": "rtmp://plive.pandora.tv:80/mediaHub"
+ }
+ ]
}
]
}
obs-studio-18.0.0.tar.xz/plugins/vlc-video/data/locale/da-DK.ini
Added
+VLCSource="VLC videokilde"
+Playlist="Afspilningsliste"
+LoopPlaylist="Loop afspilningsliste"
+PlaybackBehavior="Synligheds opførsel"
+PlaybackBehavior.StopRestart="Stop når ikke synlig, genstart når synlig"
+PlaybackBehavior.PauseUnpause="Paus når ikke synlig, genoptag når synlig"
+PlaybackBehavior.AlwaysPlay="Afspil altid også når usynlig"
+
obs-studio-17.0.2.tar.xz/plugins/win-capture/data/locale/da-DK.ini -> obs-studio-18.0.0.tar.xz/plugins/win-capture/data/locale/da-DK.ini
Changed
PrimaryMonitor="Primære skærm"
GameCapture="Spil optager"
GameCapture.AnyFullscreen="Optag ethvert fuldskærms program"
+GameCapture.CaptureWindow="Optag specifikt vindue"
+GameCapture.UseHotkey="Optag forreste vindue med hotkey"
GameCapture.ForceScaling="Tving skalering"
GameCapture.ScaleRes="Skalere opløsning"
GameCapture.LimitFramerate="Begræns optagelses framerate"
GameCapture.CaptureOverlays="Optag fra tredjepart overlays (såsom Steam)"
GameCapture.AntiCheatHook="Brug anti-cheat kompatibilitet hook"
+GameCapture.HotkeyStart="Optag forreste vindue"
+GameCapture.HotkeyStop="Deaktiver optagelse"
+Mode="Tilstand"
obs-studio-17.0.2.tar.xz/plugins/win-capture/data/locale/ro-RO.ini -> obs-studio-18.0.0.tar.xz/plugins/win-capture/data/locale/ro-RO.ini
Changed
GameCapture.LimitFramerate="Limitează frecvența de cadre a capturii"
GameCapture.CaptureOverlays="Capturează overlay-uri terțe (precum Steam)"
GameCapture.AntiCheatHook="Folosește hook pentru compatibilitate anticheat"
+GameCapture.HotkeyStop="Dezactivare captură"
+Mode="Tip"
obs-studio-17.0.2.tar.xz/plugins/win-capture/game-capture.c -> obs-studio-18.0.0.tar.xz/plugins/win-capture/game-capture.c
Changed
"origin",
"devenv",
"taskmgr",
+ "chrome",
+ "firefox",
"systemsettings",
"applicationframehost",
"cmd",
obs-studio-17.0.2.tar.xz/plugins/win-capture/graphics-hook/dxgi-capture.cpp -> obs-studio-18.0.0.tar.xz/plugins/win-capture/graphics-hook/dxgi-capture.cpp
Changed
* quite know. */
if (_strcmpi(process_name, "iw6sp64_ship.exe") == 0 ||
_strcmpi(process_name, "iw6mp64_ship.exe") == 0 ||
- _strcmpi(process_name, "justcause3.exe") == 0) {
+ _strcmpi(process_name, "justcause3.exe") == 0 ||
+ _strcmpi(process_name, "theHunterCotW_F.exe") == 0) {
ignore_d3d10 = true;
}
obs-studio-17.0.2.tar.xz/plugins/win-capture/graphics-hook/graphics-hook.c -> obs-studio-18.0.0.tar.xz/plugins/win-capture/graphics-hook/graphics-hook.c
Changed
{
wait_for_dll_main_finish(thread_handle);
- _snwprintf(keepalive_name, sizeof(keepalive_name), L"%s%lu",
- WINDOW_HOOK_KEEPALIVE, GetCurrentProcessId());
+ _snwprintf(keepalive_name, sizeof(keepalive_name) / sizeof(wchar_t),
+ L"%s%lu", WINDOW_HOOK_KEEPALIVE, GetCurrentProcessId());
init_pipe();
obs-studio-17.0.2.tar.xz/plugins/win-capture/window-helpers.c -> obs-studio-18.0.0.tar.xz/plugins/win-capture/window-helpers.c
Changed
HWND child;
GetWindowThreadProcessId(parent, &parent_id);
- child = GetWindow(parent, GW_CHILD);
+ child = FindWindowEx(parent, NULL, NULL, NULL);
while (child) {
DWORD child_id = 0;
if (child_id != parent_id)
return child;
- child = GetNextWindow(child, GW_HWNDNEXT);
+ child = FindWindowEx(parent, child, NULL, NULL);
}
return NULL;
}
-static inline HWND next_window(HWND window, enum window_search_mode mode,
- HWND *parent)
+static HWND next_window(HWND window, enum window_search_mode mode,
+ HWND *parent, bool use_findwindowex)
{
if (*parent) {
window = *parent;
}
while (true) {
- window = GetNextWindow(window, GW_HWNDNEXT);
+ if (use_findwindowex)
+ window = FindWindowEx(GetDesktopWindow(), window, NULL,
+ NULL);
+ else
+ window = GetNextWindow(window, GW_HWNDNEXT);
+
if (!window || check_window_valid(window, mode))
break;
}
return window;
}
-static inline HWND first_window(enum window_search_mode mode, HWND *parent)
+static HWND first_window(enum window_search_mode mode, HWND *parent,
+ bool *use_findwindowex)
{
- HWND window = GetWindow(GetDesktopWindow(), GW_CHILD);
+ HWND window = FindWindowEx(GetDesktopWindow(), NULL, NULL, NULL);
+
+ if (!window) {
+ *use_findwindowex = false;
+ window = GetWindow(GetDesktopWindow(), GW_CHILD);
+ } else {
+ *use_findwindowex = true;
+ }
*parent = NULL;
- if (!check_window_valid(window, mode))
- window = next_window(window, mode, parent);
+ if (!check_window_valid(window, mode)) {
+ window = next_window(window, mode, parent, *use_findwindowex);
+
+ if (!window && *use_findwindowex) {
+ *use_findwindowex = false;
+
+ window = GetWindow(GetDesktopWindow(), GW_CHILD);
+ if (!check_window_valid(window, mode))
+ window = next_window(window, mode, parent,
+ *use_findwindowex);
+ }
+ }
if (is_uwp_window(window)) {
HWND child = get_uwp_actual_window(window);
add_window_cb callback)
{
HWND parent;
- HWND window = first_window(mode, &parent);
+ bool use_findwindowex = false;
+
+ HWND window = first_window(mode, &parent, &use_findwindowex);
while (window) {
add_window(p, window, callback);
- window = next_window(window, mode, &parent);
+ window = next_window(window, mode, &parent, use_findwindowex);
}
}
const char *exe)
{
HWND parent;
- HWND window = first_window(mode, &parent);
+ bool use_findwindowex = false;
+
+ HWND window = first_window(mode, &parent, &use_findwindowex);
HWND best_window = NULL;
int best_rating = 0;
best_window = window;
}
- window = next_window(window, mode, &parent);
+ window = next_window(window, mode, &parent, use_findwindowex);
}
return best_window;
obs-studio-17.0.2.tar.xz/plugins/win-dshow/data/locale/da-DK.ini -> obs-studio-18.0.0.tar.xz/plugins/win-dshow/data/locale/da-DK.ini
Changed
VideoFormat="Video Format"
VideoFormat.Any="Enhver"
VideoFormat.Unknown="Ukendt (%1)"
+AudioOutputMode="Tilstand for lydoutput"
+AudioOutputMode.Capture="Optag kun lyd"
+AudioOutputMode.DirectSound="Output skrivebordslyd (DirectSound)"
+AudioOutputMode.WaveOut="Output skrivebordslyd (WaveOut)"
UseCustomAudioDevice="Brug brugerdefinerede lydenhed"
AudioDevice="Lydenhed"
Buffering="Buffering"
+Buffering.ToolTip="Når aktiveret, vil video/audio data blive bufferet for at sikre den glatteste og mest\nkorrekt afspilning, men på bekostning af øget svartid. Når \nbuffering bruges med et video-capturekort, anbefales det at indstille kort og \nprogrammet til samme framerate for bedste resultat.\n\nNår deaktiveret, sikrer laveste svartids afspilning, men på bekostning af frame\nafspilnings-nøjagtighed. Dette er ideelt til ansigtskameraer, eller når du vil bruge the\nprogrammets eksempelvindue til at spille en konsol.\n\nAutogenkend (standard) indstiller den til aktiveret, hvis enheden har forsinkelse og disabled\nhvis det ikke har nogen forsinkelse."
+Buffering.AutoDetect="Autogenkend"
+Buffering.Enable="Aktiver"
+Buffering.Disable="Deaktiver"
Activate="Aktivér"
Deactivate="Deaktivér"
+FlipVertically="Spejlvend vertikalt"
+DeactivateWhenNotShowing="Deaktiver når ikke vist"
Bitrate="Bitrate"
+Encoder.C985="AVerMedia H.264 Encoder (c985)"
+Encoder.C353="AVerMedia H.264 Encoder"
obs-studio-17.0.2.tar.xz/plugins/win-dshow/ffmpeg-decode.c -> obs-studio-18.0.0.tar.xz/plugins/win-dshow/ffmpeg-decode.c
Changed
******************************************************************************/
#include "ffmpeg-decode.h"
+#include <util/util_uint128.h>
+#include <util/base.h>
#include <obs-avc.h>
int ffmpeg_decode_init(struct ffmpeg_decode *decode, enum AVCodecID id)
memcpy(decode->packet_buffer, data, size);
}
+static void do_idiotic_lgp_audio_packet_realignment(
+ struct ffmpeg_decode *decode, long long *ts)
+{
+ uint64_t new_ts = (uint64_t)*ts;
+ util_uint128_t u128;
+
+ if (!decode->lgp_started) {
+ decode->lgp_start_ts = new_ts;
+ decode->lgp_next_expected_ts = new_ts;
+ decode->lgp_started = true;
+ }
+
+ if (llabs(decode->lgp_next_expected_ts - new_ts) < 3000000ULL) {
+ *ts = (long long)decode->lgp_next_expected_ts;
+ } else {
+ decode->lgp_start_ts = new_ts;
+ decode->lgp_frames_since_start = 0;
+ }
+
+ decode->lgp_frames_since_start += (uint64_t)decode->frame->nb_samples;
+ u128 = util_mul64_64(decode->lgp_frames_since_start, 10000000ULL);
+ decode->lgp_next_expected_ts = decode->lgp_start_ts +
+ util_div128_32(u128, (uint32_t)decode->frame->sample_rate).low;
+}
+
int ffmpeg_decode_audio(struct ffmpeg_decode *decode,
- uint8_t *data, size_t size,
+ uint8_t *data, size_t size, long long *ts,
struct obs_source_audio *audio,
bool *got_output)
{
if (audio->format == AUDIO_FORMAT_UNKNOWN)
return 0;
+ if (decode->fix_braindead_lgp_audio_packet_stupidity)
+ do_idiotic_lgp_audio_packet_realignment(decode, ts);
+
*got_output = true;
return len;
}
obs-studio-17.0.2.tar.xz/plugins/win-dshow/ffmpeg-decode.h -> obs-studio-18.0.0.tar.xz/plugins/win-dshow/ffmpeg-decode.h
Changed
uint8_t *packet_buffer;
size_t packet_size;
+
+ uint64_t lgp_start_ts;
+ uint64_t lgp_frames_since_start;
+ uint64_t lgp_next_expected_ts;
+ bool lgp_started;
+ bool fix_braindead_lgp_audio_packet_stupidity;
};
extern int ffmpeg_decode_init(struct ffmpeg_decode *decode, enum AVCodecID id);
extern void ffmpeg_decode_free(struct ffmpeg_decode *decode);
extern int ffmpeg_decode_audio(struct ffmpeg_decode *decode,
- uint8_t *data, size_t size,
+ uint8_t *data, size_t size, long long *ts,
struct obs_source_audio *audio,
bool *got_output);
obs-studio-17.0.2.tar.xz/plugins/win-dshow/win-dshow.cpp -> obs-studio-18.0.0.tar.xz/plugins/win-dshow/win-dshow.cpp
Changed
inline ~Decoder() {ffmpeg_decode_free(&decode);}
inline operator ffmpeg_decode*() {return &decode;}
+ inline ffmpeg_decode *operator->() {return &decode;}
};
class CriticalSection {
blog(LOG_WARNING, "Could not initialize audio decoder");
return;
}
+
+ if (videoConfig.name.find(L"C875") != std::string::npos ||
+ videoConfig.name.find(L"C835") != std::string::npos) {
+ audio_decoder->fix_braindead_lgp_audio_packet_stupidity
+ = true;
+ blog(LOG_INFO, "Oh great, an LGP was detected. "
+ "How wonderful. I'm just ecstatic.");
+ }
}
bool got_output;
- int len = ffmpeg_decode_audio(audio_decoder, data, size,
+ int len = ffmpeg_decode_audio(audio_decoder, data, size, &ts,
&audio, &got_output);
if (len < 0) {
blog(LOG_WARNING, "Error decoding audio");
obs-studio-17.0.2.tar.xz/plugins/win-mf/data/locale/ca-ES.ini -> obs-studio-18.0.0.tar.xz/plugins/win-mf/data/locale/ca-ES.ini
Changed
MF.H264.EncoderName="Codificador H264 de Media Foundation"
MF.H264.Encoder="Nom del codificador"
MF.H264.LowLatency="Baixa latència (desactiva la reorganització de fotogrames)"
-MF.H264.BFrames="Número de B-Frame consecutives"
+MF.H264.BFrames="Número de B-Frame consecutius"
MF.H264.CustomBufsize="Utilitza grandària de memòria cau personalitzada"
MF.H264.BufferSize="Mida de la memòria intermèdia"
MF.H264.CustomMaxBitrate="Utilitza grandària màxima de taxa de bits personalitzada"
obs-studio-17.0.2.tar.xz/plugins/win-mf/data/locale/da-DK.ini -> obs-studio-18.0.0.tar.xz/plugins/win-mf/data/locale/da-DK.ini
Changed
Bitrate="Bitrate"
MF.H264.EncoderName="Media Foundation H264 Encoder"
+MF.H264.Encoder="Encoder navn"
+MF.H264.LowLatency="Lav svartid (deaktiver frame re-ordering)"
+MF.H264.CustomBufsize="Brug tilpasset bufferstørrelse"
+MF.H264.BufferSize="Bufferstørrelse"
+MF.H264.CustomMaxBitrate="Brug tilpasset max bitrate"
+MF.H264.Bitrate="Bitrate"
+MF.H264.MaxBitrate="Maks bitrate"
+MF.H264.KeyframeIntervalSec="Keyframe interval (sekunder, 0=auto)"
+MF.H264.RateControl="Rate kontrol"
+MF.H264.CBR="CBR (Konstant bitrate)"
+MF.H264.VBR="VBR (Variabel bitrate)"
+MF.H264.CQP="CQP (konstant kvalitet)"
MF.H264.MinQP="Minimum QP"
MF.H264.MaxQP="Maximum QP"
+MF.H264.QPI="QP I-frame"
+MF.H264.QPP="QP P-frame"
+MF.H264.QPB="QP B-frame"
MF.H264.Profile="Profil"
MF.H264.Advanced="Advancerede"
+MF.H264.EncoderSWMicrosoft="Microsoft software H.264 encoder"
+MF.H264.EncoderHWAMD="AMD Video Coding Engine H.264 Encoder (Media Foundation)"
+MF.H264.EncoderHWIntel="Intel Quick Sync H.264 Encoder (Media Foundation)"
+MF.H264.EncoderHWNVIDIA="NVIDIA NVENC H.264 Encoder (Media Foundation)"
obs-studio-17.0.2.tar.xz/plugins/win-wasapi/win-wasapi.cpp -> obs-studio-18.0.0.tar.xz/plugins/win-wasapi/win-wasapi.cpp
Changed
info.id = "wasapi_output_capture";
info.type = OBS_SOURCE_TYPE_INPUT;
info.output_flags = OBS_SOURCE_AUDIO |
- OBS_SOURCE_DO_NOT_DUPLICATE;
+ OBS_SOURCE_DO_NOT_DUPLICATE |
+ OBS_SOURCE_DO_NOT_MONITOR;
info.get_name = GetWASAPIOutputName;
info.create = CreateWASAPIOutput;
info.destroy = DestroyWASAPISource;
No build results available
No rpmlint results available
Request History
boombatower created request about 8 years ago
- Update to version 18.0.0:
* UI: Add more command line options
* obs-browser: Update submodule to latest version
* Revert "Revert "win-capture: Use FindWindowEx to traverse window list""
* CI: Add in inital appveyor config
* CI: Move browser source before building app
* CI: Build VLC plugin for OSX on travis
* rtmp-services: remove shut down services
* CI: Build Windows version and upload artifacts
* obs-browser: Update browser ref
* CI: Update permissions on CEF app plist before packaging
* cmake: Enable COPY_DEPENDENCIES by default on Windows
* rtmp-services: Update Vaughn Live ingests
* libobs: Log correct amount of memory on 32bit (windows)
* UI: Convert to wide before outputting debug text (win)
* UI: Protect debug text static string var with mutex
* libobs: Add ability to get output congestion
* obs-output: Add ability to get congestion to rtmp output
* obs-outputs: Increase default drop threshold
* UI: Add connection status square to status bar
* UI: Add separate timers to status bar
* UI: Add option to always minimize to tray
* UI: Hide/show dialogs when minimizing to tray
* UI: Do not quit program when last windows are projectors
* UI: Add option to save projectors
* UI: Add auto-start replay buf. opt. when stream starts
* UI: Fix scaling in viewport when source flipped
* UI: Fix linux display/resize bug with preview widget
* rtmp-services: Add Restream.io Los Angeles server
* libobs: Add optional ultrawide -> wide scaling techniques
boombatower accepted request about 8 years ago
ok