├── .github └── workflows │ └── nightly.yml ├── .gitignore ├── CMakeLists.txt ├── COPYING.txt ├── README.md ├── cmake ├── FindLibObs.cmake └── ObsPluginHelpers.cmake ├── data ├── dvd.png └── locale │ └── en-US.ini ├── format.sh ├── package ├── README.txt.in ├── installer-Windows.iss.in ├── installer-macOS.pkgproj.in └── macOS-intro.txt └── src └── dvd.c /.github/workflows/nightly.yml: -------------------------------------------------------------------------------- 1 | name: nightly 2 | on: 3 | pull_request: 4 | paths-ignore: 5 | - '**.md' 6 | - '**.ini' 7 | push: 8 | paths-ignore: 9 | - '**.md' 10 | - '**.ini' 11 | branches: 12 | - "*" 13 | tags: 14 | - "v*" 15 | jobs: 16 | build-linux: 17 | name: 'Linux 64bit' 18 | runs-on: ubuntu-latest 19 | env: 20 | obs-studio-version: 27.2.2 21 | project-name: dvd-screensaver 22 | project-git: dvds3 23 | maintainer: uni@vrsal.xyz 24 | steps: 25 | - name: Checkout 26 | uses: actions/checkout@v2 27 | with: 28 | path: ${{ github.workspace }} 29 | submodules: 'recursive' 30 | - name: 'Get ${{ env.project-git }} git info' 31 | shell: bash 32 | working-directory: ${{ github.workspace }} 33 | run: | 34 | git fetch --prune --unshallow 35 | echo "GIT_BRANCH=${{ github.event.pull_request.head.ref }}" >> $GITHUB_ENV 36 | echo "GIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV 37 | echo "GIT_TAG=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV 38 | - name: Cache Dependencies 39 | id: cache-linux-deps 40 | uses: actions/cache@v1 41 | with: 42 | path: obs-studio 43 | key: obs-deps-${{ env.obs-studio-ref }}-linux 44 | - name: Install dependencies 45 | if: steps.cache-linux-deps.outputs.cache-hit != 'true' 46 | shell: bash 47 | run: | 48 | set -ex 49 | 50 | sudo add-apt-repository -y ppa:obsproject/obs-studio 51 | sudo apt-get -qq update 52 | 53 | sudo apt-get install -y \ 54 | libjansson-dev \ 55 | libc-dev-bin \ 56 | libc6-dev git \ 57 | build-essential \ 58 | checkinstall \ 59 | libcurl4-openssl-dev \ 60 | cmake \ 61 | obs-studio \ 62 | qtbase5-dev \ 63 | qtbase5-private-dev 64 | sudo wget -O /usr/include/obs/obs-frontend-api.h https://raw.githubusercontent.com/obsproject/obs-studio/27.2.2/UI/obs-frontend-api/obs-frontend-api.h 65 | sudo ldconfig 66 | - name: Build plugin 67 | shell: bash 68 | run: | 69 | cmake -S ${{github.workspace}} -B ${{github.workspace}}/build/ \-G "Unix Makefiles" \ 70 | -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/dist -DOBS_FRONTEND_INCLUDE=/usr/include/obs 71 | cmake --build ${{github.workspace}}/build/ --parallel 4 --target install 72 | - name: Compile deb installer 73 | shell: bash 74 | run: | # Now only build deb installer 75 | cmake ${{github.workspace}} -B ${{github.workspace}}/build \ 76 | -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_VERBOSE_MAKEFILE=true \ 77 | -DOBS_FRONTEND_INCLUDE=/usr/include/obs -DGLOBAL_INSTALLATION=ON 78 | sudo cmake --build ${{github.workspace}}/build \ 79 | --parallel 4 \ 80 | --target install 81 | cd ${{github.workspace}} 82 | export GIT_HASH=$(git rev-parse --short HEAD) 83 | export GIT_TAG=$(git describe --tags --abbrev=0) 84 | export PKG_VERSION="1-$GIT_TAG-$GIT_HASH-git" 85 | 86 | [[ "$GITHUB_REF" =~ "^refs/tags/" ]] && export PKG_VERSION="$BRANCH_SHORT_NAME" 87 | cd ${{github.workspace}}/build 88 | echo "Packaging version ${PKG_VERSION}" 89 | PAGER="cat" sudo checkinstall -y --type=debian --fstrans=no --nodoc \ 90 | --backup=no --deldoc=yes --install=no \ 91 | --pkgname=${{ env.project-name }} --pkgversion="$PKG_VERSION" \ 92 | --pkglicense="GPLv2.0" --maintainer="${{ env.maintainer }}" \ 93 | --pkggroup="video" \ 94 | --pkgsource="https://github.com/${{ env.GITHUB_REPOSITORY }}" \ 95 | --requires="obs-studio \(\>= ${{ env.obs-studio-version }}\)" \ 96 | --pakdir="../package" 97 | mv ../package/*.deb ../package/${{ env.project-name }}.${{ env.GIT_TAG }}.linux.x64.deb 98 | - name: Publish Linux binary 99 | uses: actions/upload-artifact@v2 100 | with: 101 | name: ${{ env.project-name }}.${{ env.GIT_TAG }}.bin.linux.x64 102 | path: ${{github.workspace}}/dist/**/* 103 | - name: Publish Linux installer 104 | uses: actions/upload-artifact@v2 105 | with: 106 | name: ${{ env.project-name }}.${{ env.GIT_TAG }}.installer.linux.x64 107 | path: ${{github.workspace}}/package/*.deb 108 | windows: 109 | name: 'Windows 32/64bit' 110 | runs-on: [windows-2019] 111 | env: 112 | QT_VERSION: '5.15.2' 113 | WINDOWS_DEPS_VERSION: '2022-01-31' 114 | CMAKE_GENERATOR: "Visual Studio 16 2019" 115 | CMAKE_SYSTEM_VERSION: "10.0" 116 | obs-studio-version: 5.15.2 117 | project-git: dvds3 118 | project-name: dvd-screensaver 119 | steps: 120 | - name: Add msbuild to PATH 121 | uses: microsoft/setup-msbuild@v1.0.2 122 | - name: Checkout 123 | uses: actions/checkout@v2 124 | with: 125 | path: ${{ github.workspace }}/${{ env.project-git }} 126 | submodules: 'recursive' 127 | - name: 'Checkout OBS' 128 | uses: actions/checkout@v2 129 | with: 130 | repository: obsproject/obs-studio 131 | path: ${{ github.workspace }}/obs-studio 132 | submodules: 'recursive' 133 | - name: 'Get OBS-Studio git info' 134 | shell: bash 135 | working-directory: ${{ github.workspace }}/obs-studio 136 | run: | 137 | git fetch --prune --unshallow 138 | echo "OBS_GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)" >> $GITHUB_ENV 139 | echo "OBS_GIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV 140 | echo "OBS_GIT_TAG=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV 141 | - name: 'Checkout last OBS-Studio release (${{ env.OBS_GIT_TAG }})' 142 | shell: bash 143 | working-directory: ${{ github.workspace }}/obs-studio 144 | run: | 145 | git checkout ${{ env.OBS_GIT_TAG }} 146 | git submodule update 147 | - name: 'Get ${{ env.project-git }} git info' 148 | shell: bash 149 | working-directory: ${{ github.workspace }}/${{ env.project-git }} 150 | run: | 151 | git fetch --prune --unshallow 152 | echo "GIT_BRANCH=${{ github.event.pull_request.head.ref }}" >> $GITHUB_ENV 153 | echo "GIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV 154 | echo "GIT_TAG=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV 155 | - name: 'Install prerequisite: QT' 156 | run: | 157 | curl -kLO https://cdn-fastly.obsproject.com/downloads/Qt_${{ env.QT_VERSION }}.7z -f --retry 5 -C - 158 | 7z x Qt_${{ env.QT_VERSION }}.7z -o"${{ github.workspace }}\cmbuild\QT" 159 | - name: 'Install prerequisite: Pre-built OBS dependencies' 160 | run: | 161 | curl -L -O https://github.com/obsproject/obs-deps/releases/download/win-${{ env.WINDOWS_DEPS_VERSION }}/windows-deps-${{ env.WINDOWS_DEPS_VERSION }}.zip --retry 5 -C - 162 | 7z x windows-deps-${{ env.WINDOWS_DEPS_VERSION }}.zip -o"${{ github.workspace }}/cmbuild/deps" 163 | - name: 'Restore OBS 32-bit build v${{ env.OBS_GIT_TAG }} from cache' 164 | id: build-cache-obs-32 165 | uses: actions/cache@v1 166 | env: 167 | CACHE_NAME: 'build-cache-obs-32' 168 | with: 169 | path: ${{ github.workspace }}/obs-studio/build32 170 | key: ${{ runner.os }}-${{ env.CACHE_NAME }}-${{ env.OBS_GIT_TAG }} 171 | restore-keys: | 172 | ${{ runner.os }}-${{ env.CACHE_NAME }}- 173 | - name: 'Configure OBS 32-bit' 174 | if: steps.build-cache-obs-32.outputs.cache-hit != 'true' 175 | working-directory: ${{ github.workspace }}/obs-studio 176 | shell: powershell 177 | run: | 178 | New-Item -ItemType Directory -Force -Path .\build32 179 | cd .\build32 180 | cmake -G "${{ env.CMAKE_GENERATOR }}" ` 181 | -A Win32 -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" ` 182 | -DQTDIR="${{ github.workspace }}\cmbuild\QT\${{ env.QT_VERSION }}\msvc2019" ` 183 | -DDepsPath="${{ github.workspace }}\cmbuild\deps\win32" -DBUILD_CAPTIONS=YES ` 184 | -DCOPIED_DEPENDENCIES=NO -DCOPY_DEPENDENCIES=YES -DBUILD_BROWSER=OFF .. 185 | - name: 'Build OBS-Studio 32-bit' 186 | if: steps.build-cache-obs-32.outputs.cache-hit != 'true' 187 | working-directory: ${{ github.workspace }}/obs-studio 188 | run: | 189 | msbuild /m /p:Configuration=RelWithDebInfo .\build32\libobs\libobs.vcxproj 190 | msbuild /m /p:Configuration=RelWithDebInfo .\build32\UI\obs-frontend-api\obs-frontend-api.vcxproj 191 | - name: 'Restore OBS 64-bit build v${{ env.OBS_GIT_TAG }} from cache' 192 | id: build-cache-obs-64 193 | uses: actions/cache@v1 194 | env: 195 | CACHE_NAME: 'build-cache-obs-64' 196 | with: 197 | path: ${{ github.workspace }}/obs-studio/build64 198 | key: ${{ runner.os }}-${{ env.CACHE_NAME }}-${{ env.OBS_GIT_TAG }} 199 | restore-keys: | 200 | ${{ runner.os }}-${{ env.CACHE_NAME }}- 201 | - name: 'Configure OBS 64-bit' 202 | if: steps.build-cache-obs-64.outputs.cache-hit != 'true' 203 | working-directory: ${{ github.workspace }}/obs-studio 204 | shell: powershell 205 | run: | 206 | New-Item -ItemType Directory -Force -Path .\build64 207 | cd .\build64 208 | cmake -G "${{ env.CMAKE_GENERATOR }}" -A x64 ` 209 | -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" ` 210 | -DQTDIR="${{ github.workspace }}\cmbuild\QT\${{ env.QT_VERSION }}\msvc2019_64" ` 211 | -DDepsPath="${{ github.workspace }}\cmbuild\deps\win64" -DBUILD_CAPTIONS=YES -DCOPIED_DEPENDENCIES=NO ` 212 | -DCOPY_DEPENDENCIES=YES -DBUILD_BROWSER=OFF .. 213 | - name: 'Build OBS-Studio 64-bit' 214 | if: steps.build-cache-obs-64.outputs.cache-hit != 'true' 215 | working-directory: ${{ github.workspace }}/obs-studio 216 | run: | 217 | msbuild /m /p:Configuration=RelWithDebInfo .\build64\libobs\libobs.vcxproj 218 | msbuild /m /p:Configuration=RelWithDebInfo .\build64\UI\obs-frontend-api\obs-frontend-api.vcxproj 219 | - name: 'Configure ${{ env.project-git }} 64-bit' 220 | working-directory: ${{ github.workspace }}\${{ env.project-git }} 221 | run: | 222 | New-Item -ItemType Directory -Force -Path .\build64 223 | cd .\build64 224 | cmake -G "${{ env.CMAKE_GENERATOR }}" -A x64 -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" ` 225 | -DQTDIR="${{ github.workspace }}\cmbuild\QT\${{ env.QT_VERSION }}\msvc2019_64" ` 226 | -DDepsPath="${{ github.workspace }}\cmbuild\deps\win64" ` 227 | -DLibObs_DIR="${{ github.workspace }}\obs-studio\build64\libobs" ` 228 | -DLIBOBS_INCLUDE_DIR="${{ github.workspace }}\obs-studio\libobs" ` 229 | -DLIBOBS_LIB="${{ github.workspace }}\obs-studio\build64\libobs\RelWithDebInfo\obs.lib" ` 230 | -DOBS_FRONTEND_LIB="${{ github.workspace }}\obs-studio\build64\UI\obs-frontend-api\RelWithDebInfo\obs-frontend-api.lib" ` 231 | -DW32_PTHREADS_LIB="${{ github.workspace }}\obs-studio\build64\deps\w32-pthreads\RelWithDebInfo\w32-pthreads.lib" .. 232 | - name: 'Configure ${{ env.project-git }} 32-bit' 233 | working-directory: ${{ github.workspace }}/${{ env.project-git }} 234 | run: | 235 | New-Item -ItemType Directory -Force -Path .\build32 236 | cd .\build32 237 | cmake -G "${{ env.CMAKE_GENERATOR }}" -A Win32 -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" ` 238 | -DQTDIR="${{ github.workspace }}\cmbuild\QT\${{ env.QT_VERSION }}\msvc2019" ` 239 | -DDepsPath="${{ github.workspace }}\cmbuild\deps\win32" ` 240 | -DLibObs_DIR="${{ github.workspace }}\obs-studio\build32\libobs" ` 241 | -DLIBOBS_INCLUDE_DIR="${{ github.workspace }}\obs-studio\libobs" ` 242 | -DLIBOBS_LIB="${{ github.workspace }}\obs-studio\build32\libobs\RelWithDebInfo\obs.lib" ` 243 | -DOBS_FRONTEND_LIB="${{ github.workspace }}\obs-studio\build32\UI\obs-frontend-api\RelWithDebInfo\obs-frontend-api.lib" ` 244 | -DW32_PTHREADS_LIB="${{ github.workspace }}\obs-studio\build32\deps\w32-pthreads\RelWithDebInfo\w32-pthreads.lib" .. 245 | - name: 'Build ${{ env.project-git }} 64-bit' 246 | working-directory: ${{ github.workspace }}/${{ env.project-git }} 247 | run: msbuild /m /p:Configuration=RelWithDebInfo .\build64\${{ env.project-name }}.sln 248 | - name: 'Build ${{ env.project-git }} 32-bit' 249 | working-directory: ${{ github.workspace }}/${{ env.project-git }} 250 | run: msbuild /m /p:Configuration=RelWithDebInfo .\build32\${{ env.project-name }}.sln 251 | - name: 'Package ${{ env.project-git }}' 252 | working-directory: ${{ github.workspace }}/${{ env.project-git }} 253 | run: | 254 | mkdir release\obs-plugins\64bit 255 | mkdir release\obs-plugins\32bit 256 | mkdir release\data\obs-plugins\${{ env.project-name }}\ 257 | 258 | robocopy .\build64\RelWithDebInfo .\release\obs-plugins\64bit\ ${{ env.project-name }}.dll ${{ env.project-name }}.pdb 259 | robocopy .\build32\RelWithDebInfo .\release\obs-plugins\32bit\ ${{ env.project-name }}.dll ${{ env.project-name }}.pdb 260 | robocopy /E .\data .\release\data\obs-plugins\${{ env.project-name }} 261 | robocopy .\package .\release README.txt 262 | 263 | cd ${{ github.workspace }}/${{ env.project-git }} 264 | iscc .\package\installer-Windows.iss /O. /F"${{ env.project-name }}.${{ env.GIT_TAG }}.installer.windows" 265 | - name: 'Publish Windows binary' 266 | if: success() 267 | uses: actions/upload-artifact@v2-preview 268 | with: 269 | name: '${{ env.project-name }}.${{ env.GIT_TAG }}.bin.windows' 270 | path: ${{ github.workspace }}\${{ env.project-git }}\release\**\* 271 | - name: 'Publish Windows installer' 272 | if: success() 273 | uses: actions/upload-artifact@v2-preview 274 | with: 275 | name: '${{ env.project-name }}.${{ env.GIT_TAG }}.installer.windows' 276 | path: ${{ github.workspace }}/${{ env.project-git }}/*.exe 277 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build**/ 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.17) 2 | project(dvd-screensaver VERSION 1.1.0) 3 | 4 | set(PLUGIN_AUTHOR "univrsal") 5 | set(PLUGIN_GIT dvds3) 6 | set(LINUX_MAINTAINER_EMAIL "uni@vrsal.xyz") 7 | set(MACOS_BUNDLEID "xyz.vrsal.dvds3") 8 | 9 | set(CMAKE_PREFIX_PATH "${QTDIR}") 10 | set(CMAKE_INCLUDE_CURRENT_DIR TRUE) 11 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 12 | #set(CMAKE_AUTOMOC ON) 13 | #set(CMAKE_AUTOUIC ON) 14 | set(CMAKE_CXX_STANDARD 14) 15 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 16 | 17 | option(LOCAL_INSTALLATION "Whether to install for the current user (default: OFF)" OFF) 18 | option(GLOBAL_INSTALLATION "Whether to install for all users (default: OFF)" OFF) 19 | 20 | include(${CMAKE_SOURCE_DIR}/cmake/ObsPluginHelpers.cmake) 21 | if (MSVC OR APPLE) 22 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") 23 | include(${CMAKE_SOURCE_DIR}/cmake/FindLibObs.cmake) 24 | endif() 25 | 26 | configure_file( 27 | package/installer-macOS.pkgproj.in 28 | ../package/installer-macOS.pkgproj 29 | ) 30 | configure_file( 31 | package/installer-Windows.iss.in 32 | ../package/installer-Windows.iss 33 | ) 34 | configure_file( 35 | package/README.txt.in 36 | ../package/README.txt 37 | ) 38 | 39 | if(MSVC) 40 | set(dvd-screensaver_PLATFORM_DEPS 41 | ${W32_PTHREADS_LIB}) 42 | endif() 43 | 44 | if(UNIX AND NOT APPLE) 45 | add_definitions(-DUNIX=1) 46 | set(LIBOBS_LIB "libobs") 47 | set(OBS_FRONTEND_LIB "obs-frontend-api") 48 | endif() 49 | 50 | if(APPLE) 51 | add_definitions(-DMAC_OS=1) 52 | endif() 53 | 54 | find_package(LibObs REQUIRED) 55 | #find_package(Qt5 REQUIRED COMPONENTS Core Widgets) 56 | 57 | set(dvd-screensaver_SOURCES 58 | src/dvd.c) 59 | 60 | add_library(dvd-screensaver MODULE 61 | ${dvd-screensaver_SOURCES}) 62 | 63 | if (OBS_FRONTEND_INCLUDE) 64 | include_directories(${OBS_FRONTEND_INCLUDE}) 65 | endif() 66 | 67 | include_directories( 68 | "${LIBOBS_INCLUDE_DIR}/../UI/obs-frontend-api" 69 | ${LIBOBS_INCLUDE_DIR} 70 | # ${Qt5Core_INCLUDES} 71 | # ${Qt5Widgets_INCLUDES} 72 | ) 73 | 74 | target_link_libraries(dvd-screensaver 75 | ${LIBOBS_LIB} 76 | # ${OBS_FRONTEND_LIB} 77 | # Qt5::Core 78 | # Qt5::Widgets 79 | ${dvd-screensaver_PLATFORM_DEPS}) 80 | 81 | 82 | # --- Windows-specific build settings and tasks --- 83 | if(WIN32) 84 | if(NOT DEFINED OBS_FRONTEND_LIB) 85 | set(OBS_FRONTEND_LIB "OBS_FRONTEND_LIB-NOTFOUND" CACHE FILEPATH "OBS frontend library") 86 | message(FATAL_ERROR "Could not find OBS Frontend API\'s library !") 87 | endif() 88 | 89 | # Enable Multicore Builds and disable FH4 (to not depend on VCRUNTIME140_1.DLL when building with VS2019) 90 | if (MSVC) 91 | add_definitions(/MP /d2FH4-) 92 | endif() 93 | 94 | include_directories( 95 | "${LIBOBS_INCLUDE_DIR}" 96 | ) 97 | 98 | install_external_plugin_with_data(${CMAKE_PROJECT_NAME} "data") 99 | endif() 100 | 101 | if(UNIX AND NOT APPLE) 102 | include(GNUInstallDirs) 103 | 104 | set_target_properties(dvd-screensaver PROPERTIES PREFIX "") 105 | 106 | if (LOCAL_INSTALLATION) 107 | # Installs into home directory 108 | install(TARGETS ${CMAKE_PROJECT_NAME} 109 | LIBRARY DESTINATION "$ENV{HOME}/.config/obs-studio/plugins/${CMAKE_PROJECT_NAME}/bin/${OBS_ARCH_NAME}") 110 | 111 | install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data 112 | DESTINATION "$ENV{HOME}/.config/obs-studio/plugins/${CMAKE_PROJECT_NAME}/") 113 | elseif(GLOBAL_INSTALLATION) 114 | # For *.deb installer 115 | install(TARGETS ${CMAKE_PROJECT_NAME} 116 | LIBRARY DESTINATION "/usr/lib/obs-plugins") # Ubuntu apparently doesn't know the correct path 117 | 118 | file(GLOB locale_files data/locale/*.ini) 119 | file(GLOB other_files data/*.*) 120 | 121 | install(FILES ${locale_files} 122 | DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/obs/obs-plugins/${CMAKE_PROJECT_NAME}/locale") 123 | install(FILES ${other_files} 124 | DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/obs/obs-plugins/${CMAKE_PROJECT_NAME}") 125 | else() 126 | # For *.zip binary 127 | install(TARGETS ${CMAKE_PROJECT_NAME} 128 | LIBRARY DESTINATION "${CMAKE_PROJECT_NAME}/bin/${OBS_ARCH_NAME}") 129 | 130 | install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data 131 | DESTINATION "${CMAKE_PROJECT_NAME}") 132 | 133 | install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/package/README.txt" 134 | DESTINATION "${CMAKE_PROJECT_NAME}") 135 | endif() 136 | elseif(APPLE) 137 | if(NOT DEFINED OBS_FRONTEND_LIB) 138 | set(OBS_FRONTEND_LIB "OBS_FRONTEND_LIB-NOTFOUND" CACHE FILEPATH "OBS frontend library") 139 | message(FATAL_ERROR "Could not find OBS Frontend API\'s library !") 140 | endif() 141 | endif() 142 | -------------------------------------------------------------------------------- /COPYING.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dvds3 2 | ![nightly](https://github.com/univrsal/dvds3/workflows/nightly/badge.svg) 3 | Will it hit the corner? 4 | 5 | obs-studio plugin, which adds a dvd screen saver source type 6 | 7 | Issues have moved to [git.vrsal.xyz/alex/dvds3/issues](https://git.vrsal.xyz/alex/dvds3/issues). You can sign up to submit new ones. 8 | 9 | ![logo](./data/dvd.png) 10 | -------------------------------------------------------------------------------- /cmake/FindLibObs.cmake: -------------------------------------------------------------------------------- 1 | # This module can be copied and used by external plugins for OBS 2 | # 3 | # Once done these will be defined: 4 | # 5 | # LIBOBS_FOUND 6 | # LIBOBS_INCLUDE_DIRS 7 | # LIBOBS_LIBRARIES 8 | 9 | find_package(PkgConfig QUIET) 10 | if (PKG_CONFIG_FOUND) 11 | pkg_check_modules(_OBS QUIET obs libobs) 12 | endif() 13 | 14 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 15 | set(_lib_suffix 64) 16 | else() 17 | set(_lib_suffix 32) 18 | endif() 19 | 20 | if(DEFINED CMAKE_BUILD_TYPE) 21 | if(CMAKE_BUILD_TYPE STREQUAL "Debug") 22 | set(_build_type_base "debug") 23 | else() 24 | set(_build_type_base "release") 25 | endif() 26 | endif() 27 | 28 | find_path(LIBOBS_INCLUDE_DIR 29 | NAMES obs.h 30 | HINTS 31 | ENV obsPath${_lib_suffix} 32 | ENV obsPath 33 | ${obsPath} 34 | PATHS 35 | /usr/include /usr/local/include /opt/local/include /sw/include 36 | PATH_SUFFIXES 37 | libobs 38 | ) 39 | 40 | function(find_obs_lib base_name repo_build_path lib_name) 41 | string(TOUPPER "${base_name}" base_name_u) 42 | 43 | if(DEFINED _build_type_base) 44 | set(_build_type_${repo_build_path} "${_build_type_base}/${repo_build_path}") 45 | set(_build_type_${repo_build_path}${_lib_suffix} "${_build_type_base}${_lib_suffix}/${repo_build_path}") 46 | endif() 47 | 48 | find_library(${base_name_u}_LIB 49 | NAMES ${_${base_name_u}_LIBRARIES} ${lib_name} lib${lib_name} 50 | HINTS 51 | ENV obsPath${_lib_suffix} 52 | ENV obsPath 53 | ${obsPath} 54 | ${_${base_name_u}_LIBRARY_DIRS} 55 | PATHS 56 | /usr/lib /usr/local/lib /opt/local/lib /sw/lib 57 | PATH_SUFFIXES 58 | lib${_lib_suffix} lib 59 | libs${_lib_suffix} libs 60 | bin${_lib_suffix} bin 61 | ../lib${_lib_suffix} ../lib 62 | ../libs${_lib_suffix} ../libs 63 | ../bin${_lib_suffix} ../bin 64 | # base repo non-msvc-specific search paths 65 | ${_build_type_${repo_build_path}} 66 | ${_build_type_${repo_build_path}${_lib_suffix}} 67 | build/${repo_build_path} 68 | build${_lib_suffix}/${repo_build_path} 69 | # base repo msvc-specific search paths on windows 70 | build${_lib_suffix}/${repo_build_path}/Debug 71 | build${_lib_suffix}/${repo_build_path}/RelWithDebInfo 72 | build/${repo_build_path}/Debug 73 | build/${repo_build_path}/RelWithDebInfo 74 | ) 75 | endfunction() 76 | 77 | find_obs_lib(LIBOBS libobs obs) 78 | 79 | if(MSVC) 80 | find_obs_lib(W32_PTHREADS deps/w32-pthreads w32-pthreads) 81 | endif() 82 | 83 | include(FindPackageHandleStandardArgs) 84 | find_package_handle_standard_args(Libobs DEFAULT_MSG LIBOBS_LIB LIBOBS_INCLUDE_DIR) 85 | mark_as_advanced(LIBOBS_INCLUDE_DIR LIBOBS_LIB) 86 | 87 | if(LIBOBS_FOUND) 88 | if(MSVC) 89 | if (NOT DEFINED W32_PTHREADS_LIB) 90 | message(FATAL_ERROR "Could not find the w32-pthreads library" ) 91 | endif() 92 | 93 | set(W32_PTHREADS_INCLUDE_DIR ${LIBOBS_INCLUDE_DIR}/../deps/w32-pthreads) 94 | endif() 95 | 96 | set(LIBOBS_INCLUDE_DIRS ${LIBOBS_INCLUDE_DIR} ${W32_PTHREADS_INCLUDE_DIR}) 97 | set(LIBOBS_LIBRARIES ${LIBOBS_LIB} ${W32_PTHREADS_LIB}) 98 | include(${LIBOBS_INCLUDE_DIR}/../cmake/external/ObsPluginHelpers.cmake) 99 | 100 | # allows external plugins to easily use/share common dependencies that are often included with libobs (such as FFmpeg) 101 | if(NOT DEFINED INCLUDED_LIBOBS_CMAKE_MODULES) 102 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${LIBOBS_INCLUDE_DIR}/../cmake/Modules/") 103 | set(INCLUDED_LIBOBS_CMAKE_MODULES true) 104 | endif() 105 | else() 106 | message(FATAL_ERROR "Could not find the libobs library" ) 107 | endif() 108 | -------------------------------------------------------------------------------- /cmake/ObsPluginHelpers.cmake: -------------------------------------------------------------------------------- 1 | # Functions for generating external plugins 2 | 3 | set(EXTERNAL_PLUGIN_OUTPUT_DIR "${LibObs_DIR}/../rundir") 4 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 5 | set(OBS_ARCH_NAME "64bit") 6 | set(OBS_BUILDDIR_ARCH "build64") 7 | else() 8 | set(OBS_ARCH_NAME "32bit") 9 | set(OBS_BUILDDIR_ARCH "build32") 10 | endif() 11 | 12 | # Fix XCode includes to ignore warnings on system includes 13 | function(target_include_directories_system _target) 14 | if(XCODE) 15 | foreach(_arg ${ARGN}) 16 | if("${_arg}" STREQUAL "PRIVATE" OR "${_arg}" STREQUAL "PUBLIC" OR "${_arg}" STREQUAL "INTERFACE") 17 | set(_scope ${_arg}) 18 | else() 19 | target_compile_options(${_target} ${_scope} -isystem${_arg}) 20 | endif() 21 | endforeach() 22 | else() 23 | target_include_directories(${_target} SYSTEM ${_scope} ${ARGN}) 24 | endif() 25 | endfunction() 26 | 27 | function(install_external_plugin_data_internal target source_dir) 28 | install(DIRECTORY ${source_dir}/ 29 | DESTINATION "data/obs-plugins/${target}" 30 | USE_SOURCE_PERMISSIONS) 31 | add_custom_command(TARGET ${target} POST_BUILD 32 | COMMAND "${CMAKE_COMMAND}" -E copy_directory 33 | "${CMAKE_CURRENT_SOURCE_DIR}/${source_dir}" "${EXTERNAL_PLUGIN_OUTPUT_DIR}/$/data/obs-plugins/${target}" 34 | VERBATIM) 35 | endfunction() 36 | 37 | # Installs data 38 | # 'target' is the destination target project being installed to 39 | # 'data_loc' specifies the directory of the data 40 | function(install_external_plugin_data target data_loc) 41 | install_external_plugin_data_internal(${target} ${data_loc}) 42 | endfunction() 43 | 44 | # Installs an additional binary to a target 45 | # 'target' is the destination target project being installed to 46 | # 'additional_target' specifies the additional binary 47 | function(install_external_plugin_additional target additional_target) 48 | if(APPLE) 49 | set(_bit_suffix "") 50 | elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) 51 | set(_bit_suffix "64bit/") 52 | else() 53 | set(_bit_suffix "32bit/") 54 | endif() 55 | 56 | set_target_properties(${additional_target} PROPERTIES 57 | PREFIX "") 58 | 59 | install(TARGETS ${additional_target} 60 | LIBRARY DESTINATION "bin" 61 | RUNTIME DESTINATION "bin") 62 | install(FILES $ DESTINATION bin OPTIONAL) 63 | 64 | add_custom_command(TARGET ${additional_target} POST_BUILD 65 | COMMAND "${CMAKE_COMMAND}" -E copy 66 | "$" 67 | "${EXTERNAL_PLUGIN_OUTPUT_DIR}/$/${target}/${_bit_suffix}$" 68 | VERBATIM) 69 | add_custom_command(TARGET ${additional_target} POST_BUILD 70 | COMMAND ${CMAKE_COMMAND} -E copy_if_different 71 | $ 72 | "${EXTERNAL_PLUGIN_OUTPUT_DIR}/$/${target}/${_bit_suffix}") 73 | endfunction() 74 | 75 | # Installs the binary of the target 76 | # 'target' is the target project being installed 77 | function(install_external_plugin target) 78 | install_external_plugin_additional(obs-plugins ${target}) 79 | endfunction() 80 | 81 | # Installs the binary and data of the target 82 | # 'target' is the destination target project being installed to 83 | function(install_external_plugin_with_data target data_loc) 84 | install_external_plugin(${target}) 85 | install_external_plugin_data(${target} ${data_loc}) 86 | endfunction() -------------------------------------------------------------------------------- /data/dvd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/univrsal/dvds3/b5237556e7a8e6aa03a01a51d80f0ae4554a4c21/data/dvd.png -------------------------------------------------------------------------------- /data/locale/en-US.ini: -------------------------------------------------------------------------------- 1 | DVDSource.Name="DVD screen saver" 2 | DVDSource.Width="Width" 3 | DVDSource.Height="Height" 4 | DVDSource.Speed="Speed (Pixel per second)" 5 | DVDSource.Scale="Image scale" 6 | DVDSource.Color="Color shift" 7 | DVDSource.Reset="Reset" 8 | DVDSource.Source="Source" 9 | DVDSource.Source.Image="Image" 10 | DVDSource.ExternalSource="[Source]" -------------------------------------------------------------------------------- /format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | grep -rl 'Copyright 2019' ./src | xargs sed -i 's/Copyright 2019/Copyright 2020/g' 3 | find ./src -iname *.h* -o -iname *.c* | xargs clang-format -i -verbose 4 | -------------------------------------------------------------------------------- /package/README.txt.in: -------------------------------------------------------------------------------- 1 | @CMAKE_PROJECT_NAME@ v@CMAKE_PROJECT_VERSION@ 2 | This program is licensed under the GPL v2.0 See COPYING 3 | github.com/univrsal/@PLUGIN_GIT@ 4 | 5 | INSTALLATION 6 | 7 | Linux: 8 | ------ 9 | 1. Create a plugin folder in your home directory: 10 | $ mkdir -p ~/.config/obs-studio/plugins/@CMAKE_PROJECT_NAME@ 11 | 2. Extract the bolder bin and data into the newly created folder 12 | $ mv plugin/* ~/.config/obs-studio/plugins/@CMAKE_PROJECT_NAME@ 13 | 14 | Windows: 15 | -------- 16 | 1. Extract the archive 17 | 2. Move the contents of plugin into your obs installation directory 18 | -------------------------------------------------------------------------------- /package/installer-Windows.iss.in: -------------------------------------------------------------------------------- 1 | #define MyAppName "@CMAKE_PROJECT_NAME@" 2 | #define MyAppVersion "@CMAKE_PROJECT_VERSION@" 3 | #define MyAppPublisher "@PLUGIN_AUTHOR@" 4 | #define MyAppURL "https://github.com/univrsal/@PLUGIN_GIT@" 5 | 6 | [Setup] 7 | ; NOTE: The value of AppId uniquely identifies this application. 8 | ; Do not use the same AppId value in installers for other applications. 9 | ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) 10 | AppId={{44b785ed-eef5-4b73-bef0-42ee3493c021} 11 | AppName={#MyAppName} 12 | AppVersion={#MyAppVersion} 13 | AppPublisher={#MyAppPublisher} 14 | AppPublisherURL={#MyAppURL} 15 | AppSupportURL={#MyAppURL} 16 | AppUpdatesURL={#MyAppURL} 17 | DefaultDirName={code:GetDirName} 18 | DefaultGroupName={#MyAppName} 19 | OutputBaseFilename={#MyAppName}-{#MyAppVersion}-Windows-Installer 20 | Compression=lzma 21 | SolidCompression=yes 22 | 23 | [Languages] 24 | Name: "english"; MessagesFile: "compiler:Default.isl" 25 | 26 | [Files] 27 | Source: "..\release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs 28 | Source: "..\COPYING.txt"; Flags: dontcopy 29 | ; NOTE: Don't use "Flags: ignoreversion" on any shared system files 30 | 31 | [Icons] 32 | Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}" 33 | Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" 34 | 35 | [Code] 36 | procedure InitializeWizard(); 37 | var 38 | GPLText: AnsiString; 39 | Page: TOutputMsgMemoWizardPage; 40 | begin 41 | ExtractTemporaryFile('LICENSE'); 42 | LoadStringFromFile(ExpandConstant('{tmp}\LICENSE'), GPLText); 43 | Page := CreateOutputMsgMemoPage(wpWelcome, 44 | 'License Information', 'Please review the license terms before installing {#MyAppName}', 45 | 'Press Page Down to see the rest of the agreement. Once you are aware of your rights, click Next to continue.', 46 | String(GPLText) 47 | ); 48 | end; 49 | 50 | // credit where it's due : 51 | // following function come from https://github.com/Xaymar/obs-studio_amf-encoder-plugin/blob/master/%23Resources/Installer.in.iss#L45 52 | function GetDirName(Value: string): string; 53 | var 54 | InstallPath: string; 55 | begin 56 | // initialize default path, which will be returned when the following registry 57 | // key queries fail due to missing keys or for some different reason 58 | Result := '{pf}\obs-studio'; 59 | // query the first registry value; if this succeeds, return the obtained value 60 | if RegQueryStringValue(HKLM32, 'SOFTWARE\OBS Studio', '', InstallPath) then 61 | Result := InstallPath 62 | end; 63 | 64 | -------------------------------------------------------------------------------- /package/installer-macOS.pkgproj.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PACKAGES 6 | 7 | 8 | PACKAGE_FILES 9 | 10 | DEFAULT_INSTALL_LOCATION 11 | / 12 | HIERARCHY 13 | 14 | CHILDREN 15 | 16 | 17 | CHILDREN 18 | 19 | GID 20 | 80 21 | PATH 22 | Applications 23 | PATH_TYPE 24 | 0 25 | PERMISSIONS 26 | 509 27 | TYPE 28 | 1 29 | UID 30 | 0 31 | 32 | 33 | CHILDREN 34 | 35 | 36 | CHILDREN 37 | 38 | 39 | CHILDREN 40 | 41 | 42 | CHILDREN 43 | 44 | 45 | CHILDREN 46 | 47 | 48 | CHILDREN 49 | 50 | 51 | CHILDREN 52 | 53 | GID 54 | 80 55 | PATH 56 | ../build/libdvd-screensaver.so 57 | PATH_TYPE 58 | 1 59 | PERMISSIONS 60 | 493 61 | TYPE 62 | 3 63 | UID 64 | 0 65 | 66 | 67 | GID 68 | 80 69 | PATH 70 | bin 71 | PATH_TYPE 72 | 2 73 | PERMISSIONS 74 | 509 75 | TYPE 76 | 2 77 | UID 78 | 0 79 | 80 | 81 | CHILDREN 82 | 83 | GID 84 | 80 85 | PATH 86 | ../data 87 | PATH_TYPE 88 | 1 89 | PERMISSIONS 90 | 493 91 | TYPE 92 | 3 93 | UID 94 | 0 95 | 96 | 97 | GID 98 | 80 99 | PATH 100 | @CMAKE_PROJECT_NAME@ 101 | PATH_TYPE 102 | 2 103 | PERMISSIONS 104 | 509 105 | TYPE 106 | 2 107 | UID 108 | 0 109 | 110 | 111 | GID 112 | 80 113 | PATH 114 | plugins 115 | PATH_TYPE 116 | 2 117 | PERMISSIONS 118 | 509 119 | TYPE 120 | 2 121 | UID 122 | 0 123 | 124 | 125 | GID 126 | 80 127 | PATH 128 | obs-studio 129 | PATH_TYPE 130 | 2 131 | PERMISSIONS 132 | 509 133 | TYPE 134 | 2 135 | UID 136 | 0 137 | 138 | 139 | GID 140 | 80 141 | PATH 142 | Application Support 143 | PATH_TYPE 144 | 0 145 | PERMISSIONS 146 | 493 147 | TYPE 148 | 1 149 | UID 150 | 0 151 | 152 | 153 | CHILDREN 154 | 155 | GID 156 | 0 157 | PATH 158 | Automator 159 | PATH_TYPE 160 | 0 161 | PERMISSIONS 162 | 493 163 | TYPE 164 | 1 165 | UID 166 | 0 167 | 168 | 169 | CHILDREN 170 | 171 | GID 172 | 0 173 | PATH 174 | Documentation 175 | PATH_TYPE 176 | 0 177 | PERMISSIONS 178 | 493 179 | TYPE 180 | 1 181 | UID 182 | 0 183 | 184 | 185 | CHILDREN 186 | 187 | GID 188 | 0 189 | PATH 190 | Extensions 191 | PATH_TYPE 192 | 0 193 | PERMISSIONS 194 | 493 195 | TYPE 196 | 1 197 | UID 198 | 0 199 | 200 | 201 | CHILDREN 202 | 203 | GID 204 | 0 205 | PATH 206 | Filesystems 207 | PATH_TYPE 208 | 0 209 | PERMISSIONS 210 | 493 211 | TYPE 212 | 1 213 | UID 214 | 0 215 | 216 | 217 | CHILDREN 218 | 219 | GID 220 | 0 221 | PATH 222 | Frameworks 223 | PATH_TYPE 224 | 0 225 | PERMISSIONS 226 | 493 227 | TYPE 228 | 1 229 | UID 230 | 0 231 | 232 | 233 | CHILDREN 234 | 235 | GID 236 | 0 237 | PATH 238 | Input Methods 239 | PATH_TYPE 240 | 0 241 | PERMISSIONS 242 | 493 243 | TYPE 244 | 1 245 | UID 246 | 0 247 | 248 | 249 | CHILDREN 250 | 251 | GID 252 | 0 253 | PATH 254 | Internet Plug-Ins 255 | PATH_TYPE 256 | 0 257 | PERMISSIONS 258 | 493 259 | TYPE 260 | 1 261 | UID 262 | 0 263 | 264 | 265 | CHILDREN 266 | 267 | GID 268 | 0 269 | PATH 270 | LaunchAgents 271 | PATH_TYPE 272 | 0 273 | PERMISSIONS 274 | 493 275 | TYPE 276 | 1 277 | UID 278 | 0 279 | 280 | 281 | CHILDREN 282 | 283 | GID 284 | 0 285 | PATH 286 | LaunchDaemons 287 | PATH_TYPE 288 | 0 289 | PERMISSIONS 290 | 493 291 | TYPE 292 | 1 293 | UID 294 | 0 295 | 296 | 297 | CHILDREN 298 | 299 | GID 300 | 0 301 | PATH 302 | PreferencePanes 303 | PATH_TYPE 304 | 0 305 | PERMISSIONS 306 | 493 307 | TYPE 308 | 1 309 | UID 310 | 0 311 | 312 | 313 | CHILDREN 314 | 315 | GID 316 | 0 317 | PATH 318 | Preferences 319 | PATH_TYPE 320 | 0 321 | PERMISSIONS 322 | 493 323 | TYPE 324 | 1 325 | UID 326 | 0 327 | 328 | 329 | CHILDREN 330 | 331 | GID 332 | 80 333 | PATH 334 | Printers 335 | PATH_TYPE 336 | 0 337 | PERMISSIONS 338 | 493 339 | TYPE 340 | 1 341 | UID 342 | 0 343 | 344 | 345 | CHILDREN 346 | 347 | GID 348 | 0 349 | PATH 350 | PrivilegedHelperTools 351 | PATH_TYPE 352 | 0 353 | PERMISSIONS 354 | 493 355 | TYPE 356 | 1 357 | UID 358 | 0 359 | 360 | 361 | CHILDREN 362 | 363 | GID 364 | 0 365 | PATH 366 | QuickLook 367 | PATH_TYPE 368 | 0 369 | PERMISSIONS 370 | 493 371 | TYPE 372 | 1 373 | UID 374 | 0 375 | 376 | 377 | CHILDREN 378 | 379 | GID 380 | 0 381 | PATH 382 | QuickTime 383 | PATH_TYPE 384 | 0 385 | PERMISSIONS 386 | 493 387 | TYPE 388 | 1 389 | UID 390 | 0 391 | 392 | 393 | CHILDREN 394 | 395 | GID 396 | 0 397 | PATH 398 | Screen Savers 399 | PATH_TYPE 400 | 0 401 | PERMISSIONS 402 | 493 403 | TYPE 404 | 1 405 | UID 406 | 0 407 | 408 | 409 | CHILDREN 410 | 411 | GID 412 | 0 413 | PATH 414 | Scripts 415 | PATH_TYPE 416 | 0 417 | PERMISSIONS 418 | 493 419 | TYPE 420 | 1 421 | UID 422 | 0 423 | 424 | 425 | CHILDREN 426 | 427 | GID 428 | 0 429 | PATH 430 | Services 431 | PATH_TYPE 432 | 0 433 | PERMISSIONS 434 | 493 435 | TYPE 436 | 1 437 | UID 438 | 0 439 | 440 | 441 | CHILDREN 442 | 443 | GID 444 | 0 445 | PATH 446 | Widgets 447 | PATH_TYPE 448 | 0 449 | PERMISSIONS 450 | 493 451 | TYPE 452 | 1 453 | UID 454 | 0 455 | 456 | 457 | GID 458 | 0 459 | PATH 460 | Library 461 | PATH_TYPE 462 | 0 463 | PERMISSIONS 464 | 493 465 | TYPE 466 | 1 467 | UID 468 | 0 469 | 470 | 471 | CHILDREN 472 | 473 | 474 | CHILDREN 475 | 476 | GID 477 | 0 478 | PATH 479 | Shared 480 | PATH_TYPE 481 | 0 482 | PERMISSIONS 483 | 1023 484 | TYPE 485 | 1 486 | UID 487 | 0 488 | 489 | 490 | GID 491 | 80 492 | PATH 493 | Users 494 | PATH_TYPE 495 | 0 496 | PERMISSIONS 497 | 493 498 | TYPE 499 | 1 500 | UID 501 | 0 502 | 503 | 504 | GID 505 | 0 506 | PATH 507 | / 508 | PATH_TYPE 509 | 0 510 | PERMISSIONS 511 | 493 512 | TYPE 513 | 1 514 | UID 515 | 0 516 | 517 | PAYLOAD_TYPE 518 | 0 519 | SHOW_INVISIBLE 520 | 521 | SPLIT_FORKS 522 | 523 | TREAT_MISSING_FILES_AS_WARNING 524 | 525 | VERSION 526 | 4 527 | 528 | PACKAGE_SETTINGS 529 | 530 | AUTHENTICATION 531 | 1 532 | CONCLUSION_ACTION 533 | 0 534 | FOLLOW_SYMBOLIC_LINKS 535 | 536 | IDENTIFIER 537 | @MACOS_BUNDLEID@ 538 | LOCATION 539 | 0 540 | NAME 541 | @CMAKE_PROJECT_NAME@ 542 | OVERWRITE_PERMISSIONS 543 | 544 | PAYLOAD_SIZE 545 | -1 546 | RELOCATABLE 547 | 548 | USE_HFS+_COMPRESSION 549 | 550 | VERSION 551 | @CMAKE_PROJECT_VERSION@ 552 | 553 | TYPE 554 | 0 555 | UUID 556 | 1CE75441-F73C-4D15-9650-9741A116DDB8 557 | 558 | 559 | PROJECT 560 | 561 | PROJECT_COMMENTS 562 | 563 | NOTES 564 | 565 | 566 | 567 | PROJECT_PRESENTATION 568 | 569 | BACKGROUND 570 | 571 | INSTALLATION_STEPS 572 | 573 | 574 | ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS 575 | ICPresentationViewIntroductionController 576 | INSTALLER_PLUGIN 577 | Introduction 578 | LIST_TITLE_KEY 579 | InstallerSectionTitle 580 | 581 | 582 | ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS 583 | ICPresentationViewReadMeController 584 | INSTALLER_PLUGIN 585 | ReadMe 586 | LIST_TITLE_KEY 587 | InstallerSectionTitle 588 | 589 | 590 | ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS 591 | ICPresentationViewLicenseController 592 | INSTALLER_PLUGIN 593 | License 594 | LIST_TITLE_KEY 595 | InstallerSectionTitle 596 | 597 | 598 | ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS 599 | ICPresentationViewDestinationSelectController 600 | INSTALLER_PLUGIN 601 | TargetSelect 602 | LIST_TITLE_KEY 603 | InstallerSectionTitle 604 | 605 | 606 | ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS 607 | ICPresentationViewInstallationTypeController 608 | INSTALLER_PLUGIN 609 | PackageSelection 610 | LIST_TITLE_KEY 611 | InstallerSectionTitle 612 | 613 | 614 | ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS 615 | ICPresentationViewInstallationController 616 | INSTALLER_PLUGIN 617 | Install 618 | LIST_TITLE_KEY 619 | InstallerSectionTitle 620 | 621 | 622 | ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS 623 | ICPresentationViewSummaryController 624 | INSTALLER_PLUGIN 625 | Summary 626 | LIST_TITLE_KEY 627 | InstallerSectionTitle 628 | 629 | 630 | INTRODUCTION 631 | 632 | LOCALIZATIONS 633 | 634 | 635 | LANGUAGE 636 | English 637 | VALUE 638 | 639 | PATH 640 | ../package/macOS-intro.txt 641 | PATH_TYPE 642 | 1 643 | 644 | 645 | 646 | 647 | LICENSE 648 | 649 | LOCALIZATIONS 650 | 651 | 652 | LANGUAGE 653 | English 654 | VALUE 655 | 656 | PATH 657 | ../COPYING.txt 658 | PATH_TYPE 659 | 1 660 | 661 | 662 | 663 | MODE 664 | 0 665 | 666 | README 667 | 668 | LOCALIZATIONS 669 | 670 | 671 | TITLE 672 | 673 | LOCALIZATIONS 674 | 675 | 676 | LANGUAGE 677 | English 678 | VALUE 679 | @CMAKE_PROJECT_NAME@ 680 | 681 | 682 | 683 | 684 | PROJECT_REQUIREMENTS 685 | 686 | LIST 687 | 688 | RESOURCES 689 | 690 | ROOT_VOLUME_ONLY 691 | 692 | 693 | PROJECT_SETTINGS 694 | 695 | BUILD_FORMAT 696 | 0 697 | BUILD_PATH 698 | 699 | PATH 700 | build 701 | PATH_TYPE 702 | 1 703 | 704 | EXCLUDED_FILES 705 | 706 | 707 | PATTERNS_ARRAY 708 | 709 | 710 | REGULAR_EXPRESSION 711 | 712 | STRING 713 | .DS_Store 714 | TYPE 715 | 0 716 | 717 | 718 | PROTECTED 719 | 720 | PROXY_NAME 721 | Remove .DS_Store files 722 | PROXY_TOOLTIP 723 | Remove ".DS_Store" files created by the Finder. 724 | STATE 725 | 726 | 727 | 728 | PATTERNS_ARRAY 729 | 730 | 731 | REGULAR_EXPRESSION 732 | 733 | STRING 734 | .pbdevelopment 735 | TYPE 736 | 0 737 | 738 | 739 | PROTECTED 740 | 741 | PROXY_NAME 742 | Remove .pbdevelopment files 743 | PROXY_TOOLTIP 744 | Remove ".pbdevelopment" files created by ProjectBuilder or Xcode. 745 | STATE 746 | 747 | 748 | 749 | PATTERNS_ARRAY 750 | 751 | 752 | REGULAR_EXPRESSION 753 | 754 | STRING 755 | CVS 756 | TYPE 757 | 1 758 | 759 | 760 | REGULAR_EXPRESSION 761 | 762 | STRING 763 | .cvsignore 764 | TYPE 765 | 0 766 | 767 | 768 | REGULAR_EXPRESSION 769 | 770 | STRING 771 | .cvspass 772 | TYPE 773 | 0 774 | 775 | 776 | REGULAR_EXPRESSION 777 | 778 | STRING 779 | .svn 780 | TYPE 781 | 1 782 | 783 | 784 | REGULAR_EXPRESSION 785 | 786 | STRING 787 | .git 788 | TYPE 789 | 1 790 | 791 | 792 | REGULAR_EXPRESSION 793 | 794 | STRING 795 | .gitignore 796 | TYPE 797 | 0 798 | 799 | 800 | PROTECTED 801 | 802 | PROXY_NAME 803 | Remove SCM metadata 804 | PROXY_TOOLTIP 805 | Remove helper files and folders used by the CVS, SVN or Git Source Code Management systems. 806 | STATE 807 | 808 | 809 | 810 | PATTERNS_ARRAY 811 | 812 | 813 | REGULAR_EXPRESSION 814 | 815 | STRING 816 | classes.nib 817 | TYPE 818 | 0 819 | 820 | 821 | REGULAR_EXPRESSION 822 | 823 | STRING 824 | designable.db 825 | TYPE 826 | 0 827 | 828 | 829 | REGULAR_EXPRESSION 830 | 831 | STRING 832 | info.nib 833 | TYPE 834 | 0 835 | 836 | 837 | PROTECTED 838 | 839 | PROXY_NAME 840 | Optimize nib files 841 | PROXY_TOOLTIP 842 | Remove "classes.nib", "info.nib" and "designable.nib" files within .nib bundles. 843 | STATE 844 | 845 | 846 | 847 | PATTERNS_ARRAY 848 | 849 | 850 | REGULAR_EXPRESSION 851 | 852 | STRING 853 | Resources Disabled 854 | TYPE 855 | 1 856 | 857 | 858 | PROTECTED 859 | 860 | PROXY_NAME 861 | Remove Resources Disabled folders 862 | PROXY_TOOLTIP 863 | Remove "Resources Disabled" folders. 864 | STATE 865 | 866 | 867 | 868 | SEPARATOR 869 | 870 | 871 | 872 | NAME 873 | @CMAKE_PROJECT_NAME@ 874 | PAYLOAD_ONLY 875 | 876 | TREAT_MISSING_PRESENTATION_DOCUMENTS_AS_WARNING 877 | 878 | 879 | 880 | TYPE 881 | 0 882 | VERSION 883 | 2 884 | 885 | 886 | -------------------------------------------------------------------------------- /package/macOS-intro.txt: -------------------------------------------------------------------------------- 1 | This will automatically install the plugin to the appropriate directories. 2 | NOTICE: I offer no support for macOS versions. 3 | -------------------------------------------------------------------------------- /src/dvd.c: -------------------------------------------------------------------------------- 1 | /* This file is part of dvds3 2 | * DVD screen saver source 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | * github.com/univrsal/dvds3 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #define blog(log_level, format, ...) \ 21 | blog(log_level, "[dvd_source: '%s'] " format, \ 22 | obs_source_get_name(context->source), ##__VA_ARGS__) 23 | 24 | #define debug(format, ...) blog(LOG_DEBUG, format, ##__VA_ARGS__) 25 | #define info(format, ...) blog(LOG_INFO, format, ##__VA_ARGS__) 26 | #define warn(format, ...) blog(LOG_WARNING, format, ##__VA_ARGS__) 27 | 28 | #define FILTER_NAME "dvd-filter" 29 | #define SOURCE_NAME "dvd-image" 30 | #define DVD_SOURCE_ID "dvds3_source" 31 | 32 | #define S_SOURCE_CX "source_cx" 33 | #define S_SOURCE_CY "source_cy" 34 | #define S_SPEED "speed" 35 | #define S_SCALE "logo_scale" 36 | #define S_COLOR "color_shift" 37 | #define S_RESET "reset" 38 | #define S_SOURCE_ID "source_id" 39 | #define S_SOURCE_IMAGE "image_source" 40 | 41 | #define _T(t) obs_module_text(t) 42 | #define T_SOURCE_CX _T("DVDSource.Width") 43 | #define T_SOURCE_CY _T("DVDSource.Height") 44 | #define T_SOURCE _T("DVDSource.Name") 45 | #define T_SPEED _T("DVDSource.Speed") 46 | #define T_SCALE _T("DVDSource.Scale") 47 | #define T_COLOR _T("DVDSource.Color") 48 | #define T_RESET _T("DVDSource.Reset") 49 | #define T_SOURCE_ID _T("DVDSource.Source") 50 | #define T_SOURCE_IMAGE _T("DVDSource.Source.Image") 51 | #define T_EXTERNAL_SOURCE _T("DVDSource.ExternalSource") 52 | 53 | struct dvd_source { 54 | obs_source_t *source; 55 | obs_source_t *logo_source; 56 | obs_weak_source_t *other_source; 57 | obs_source_t *color_filter; 58 | 59 | bool use_image; /* False for custom src */ 60 | bool use_color; /* Enable color filter */ 61 | uint32_t cx, cy; /* Source size */ 62 | uint32_t img_cx, img_cy; /* Scaled image size */ 63 | struct vec2 pos; /* Image position */ 64 | int8_t d_x, d_y; /* Movement vector */ 65 | struct vec4 color; /* Color */ 66 | double scale, speed; /* Image scale/speed */ 67 | }; 68 | 69 | struct enum_param { 70 | obs_property_t *list; 71 | obs_source_t *this; 72 | }; 73 | 74 | static const char *dvd_source_get_name(void *unused) 75 | { 76 | UNUSED_PARAMETER(unused); 77 | return T_SOURCE; 78 | } 79 | 80 | static int rand_limit(int limit) 81 | { 82 | int divisor = RAND_MAX / (limit + 1); 83 | int retval; 84 | 85 | do { 86 | retval = rand() / divisor; 87 | } while (retval > limit); 88 | 89 | return retval; 90 | } 91 | 92 | static void remove_source(struct dvd_source *context) 93 | { 94 | obs_source_t *target = 95 | obs_weak_source_get_source(context->other_source); 96 | if (target) { 97 | obs_source_filter_remove(target, context->color_filter); 98 | obs_source_remove_active_child(context->source, target); 99 | obs_source_release(target); 100 | } 101 | 102 | if (context->other_source) { 103 | obs_weak_source_release(context->other_source); 104 | context->other_source = NULL; 105 | } 106 | obs_source_add_active_child(context->source, context->logo_source); 107 | } 108 | 109 | static bool add_source(struct dvd_source *context, const char *id) 110 | { 111 | bool result = true; 112 | obs_source_t *target = obs_get_source_by_name(id); 113 | if (target) { 114 | context->other_source = obs_source_get_weak_source(target); 115 | context->img_cx = obs_source_get_width(target) * context->scale; 116 | context->img_cy = 117 | obs_source_get_height(target) * context->scale; 118 | obs_source_filter_add(target, context->color_filter); 119 | obs_source_remove_active_child(context->source, 120 | context->logo_source); 121 | if (!obs_source_add_active_child(context->source, target)) { 122 | result = false; 123 | remove_source(context); 124 | warn("Can't add %s, as it would cause recursion", id); 125 | } 126 | obs_source_release(target); 127 | } 128 | return result; 129 | } 130 | 131 | static void dvd_source_update(void *data, obs_data_t *settings) 132 | { 133 | struct dvd_source *context = data; 134 | 135 | context->cx = obs_data_get_int(settings, S_SOURCE_CX); 136 | context->cy = obs_data_get_int(settings, S_SOURCE_CY); 137 | context->scale = obs_data_get_double(settings, S_SCALE); 138 | context->speed = obs_data_get_double(settings, S_SPEED); 139 | context->use_color = obs_data_get_bool(settings, S_COLOR); 140 | 141 | #ifndef MAC_OS 142 | obs_source_set_enabled(context->color_filter, context->use_color); 143 | #endif 144 | 145 | obs_source_update(context->logo_source, settings); 146 | /* Since obs_source_getwidth reports old values, we 147 | * get the image size here every time a new file is loaded 148 | */ 149 | gs_image_file_t temp; 150 | const char *file = obs_data_get_string(settings, "file"); 151 | const char *id = obs_data_get_string(settings, S_SOURCE_ID); 152 | context->use_image = strcmp(id, S_SOURCE_IMAGE) == 0; 153 | 154 | if (file && strlen(file) > 0) { 155 | gs_image_file_init(&temp, file); 156 | obs_enter_graphics(); 157 | gs_image_file_init_texture(&temp); 158 | context->img_cx = temp.cx * context->scale; 159 | context->img_cy = temp.cy * context->scale; 160 | gs_image_file_free(&temp); 161 | obs_leave_graphics(); 162 | } else { 163 | context->img_cx = obs_source_get_width(context->logo_source) * 164 | context->scale; 165 | context->img_cy = obs_source_get_height(context->logo_source) * 166 | context->scale; 167 | } 168 | 169 | if (context->use_image) { 170 | remove_source(context); 171 | } else { 172 | /* id is still postfixed with 'e' so get rid of that */ 173 | char *cpy = bstrdup(id); 174 | int index = strlen(cpy) - 1; 175 | if (index > 0) 176 | cpy[index] = '\0'; 177 | remove_source(context); 178 | 179 | add_source(context, cpy); 180 | bfree(cpy); 181 | } 182 | } 183 | 184 | static void dvd_source_defaults(obs_data_t *settings) 185 | { 186 | obs_data_set_default_int(settings, S_SOURCE_CX, 640); 187 | obs_data_set_default_int(settings, S_SOURCE_CY, 480); 188 | obs_data_set_default_double(settings, S_SCALE, 1.0); 189 | obs_data_set_default_double(settings, S_SPEED, 50.0); 190 | 191 | obs_data_set_default_bool(settings, S_COLOR, true); 192 | char *path = obs_module_file("dvd.png"); 193 | obs_data_set_default_string(settings, "file", path); 194 | obs_data_set_default_string(settings, S_SOURCE_ID, T_SOURCE_IMAGE); 195 | bfree(path); 196 | } 197 | 198 | static void dvd_source_destroy(void *data) 199 | { 200 | struct dvd_source *context = data; 201 | remove_source(context); 202 | obs_source_remove(context->logo_source); 203 | obs_source_release(context->logo_source); 204 | 205 | #ifndef MAC_OS 206 | obs_source_remove(context->color_filter); 207 | obs_source_release(context->color_filter); 208 | #endif 209 | bfree(data); 210 | } 211 | 212 | static uint32_t dvd_source_getwidth(void *data) 213 | { 214 | struct dvd_source *context = data; 215 | return context->cx; 216 | } 217 | 218 | static uint32_t dvd_source_getheight(void *data) 219 | { 220 | struct dvd_source *context = data; 221 | return context->cy; 222 | } 223 | 224 | static void dvd_source_render(void *data, gs_effect_t *effect) 225 | { 226 | struct dvd_source *context = data; 227 | if (obs_source_showing(context->source)) { 228 | obs_source_t *target = NULL; 229 | bool free = false; 230 | if (context->use_image) { 231 | target = context->logo_source; 232 | } else if (context->other_source) { 233 | target = obs_weak_source_get_source( 234 | context->other_source); 235 | free = true; 236 | } 237 | 238 | if (target) { 239 | gs_matrix_push(); 240 | gs_matrix_translate3f(context->pos.x, context->pos.y, 241 | 0.f); 242 | gs_matrix_scale3f(context->scale, context->scale, 1.f); 243 | obs_source_video_render(target); 244 | gs_matrix_pop(); 245 | } 246 | 247 | if (free) 248 | obs_source_release(target); 249 | } 250 | } 251 | 252 | static void dvd_source_tick(void *data, float seconds) 253 | { 254 | struct dvd_source *context = data; 255 | 256 | if (obs_source_showing(context->source)) { 257 | float d_x = seconds * (context->d_x * context->speed); 258 | float d_y = seconds * (context->d_y * context->speed); 259 | 260 | bool bounce = false; 261 | 262 | if (context->pos.x + d_x + context->img_cx >= context->cx || 263 | context->pos.x + d_x <= 0) { 264 | context->d_x *= -1; 265 | bounce = true; 266 | } else { 267 | context->pos.x += d_x; 268 | } 269 | 270 | if (context->pos.y + d_y + context->img_cy >= context->cy || 271 | context->pos.y + d_y <= 0) { 272 | context->d_y *= -1; 273 | bounce = true; 274 | } else { 275 | context->pos.y += d_y; 276 | } 277 | #ifndef MAC_OS 278 | if (bounce) /* Shift color for each bounce */ { 279 | obs_data_t *settings = 280 | obs_source_get_settings(context->color_filter); 281 | double val = 282 | obs_data_get_double(settings, "hue_shift") + 283 | 45.f; 284 | if (val > 180.f) 285 | val = -180.f + 45.f; 286 | obs_data_set_double(settings, "hue_shift", val); 287 | obs_source_update(context->color_filter, settings); 288 | obs_data_release(settings); 289 | } 290 | #endif 291 | } 292 | } 293 | 294 | bool use_color_shift_changed(obs_properties_t *props, obs_property_t *p, 295 | obs_data_t *data) 296 | { 297 | /* Returning true forces an update */ 298 | return true; 299 | } 300 | 301 | bool image_path_changed(obs_properties_t *props, obs_property_t *p, 302 | obs_data_t *data) 303 | { 304 | uint32_t cx = 0, cy = 0; 305 | 306 | /* Since obs_source_getwidth reports old values, we 307 | * get the image size here every time a new file is loaded 308 | */ 309 | gs_image_file_t temp; 310 | char *file = obs_data_get_string(data, "file"); 311 | gs_image_file_init(&temp, file); 312 | 313 | obs_enter_graphics(); 314 | gs_image_file_init_texture(&temp); 315 | cx = temp.cx; 316 | cy = temp.cy; 317 | gs_image_file_free(&temp); 318 | obs_leave_graphics(); 319 | 320 | obs_property_int_set_limits(obs_properties_get(props, S_SOURCE_CX), 321 | cx + 4, 0xffff, 1); 322 | obs_property_int_set_limits(obs_properties_get(props, S_SOURCE_CY), 323 | cy + 4, 0xffff, 1); 324 | return true; 325 | } 326 | static bool reset_logo_position(obs_properties_t *props, 327 | obs_property_t *property, void *data) 328 | { 329 | struct dvd_source *context = data; 330 | context->pos.x = rand_limit(context->cx - context->img_cx); 331 | context->pos.y = rand_limit(context->cx - context->img_cy); 332 | context->d_x = rand_limit(1) == 0 ? -1 : 1; 333 | context->d_y = rand_limit(1) == 0 ? -1 : 1; 334 | return true; 335 | } 336 | 337 | static bool dvd_enum_global_sources(void *param, obs_source_t *current) 338 | { 339 | struct enum_param *data = param; 340 | uint32_t flags = obs_source_get_output_flags(current); 341 | const char *name = obs_source_get_name(current); 342 | const char *id = obs_source_get_id(current); 343 | if (data->this == current || (flags & OBS_SOURCE_VIDEO) == 0 || 344 | strcmp(name, SOURCE_NAME) == 0 || strcmp(id, DVD_SOURCE_ID) == 0) 345 | return true; 346 | char *tmp = bzalloc(512); 347 | char *tmp2 = bzalloc(512); 348 | 349 | strcat(tmp, T_EXTERNAL_SOURCE); 350 | strcat(tmp, " "); 351 | strcat(tmp, name); 352 | 353 | strcat(tmp2, name); 354 | strcat(tmp2, 355 | "e"); /* Every external source get's a postfix to distinguish it from 356 | the internal 'Image' option, to prevent confusion between a 357 | source named 'Image' and the actual 'Image' option */ 358 | obs_property_list_add_string(data->list, tmp, tmp2); 359 | bfree(tmp); 360 | bfree(tmp2); 361 | return true; 362 | } 363 | 364 | static bool source_changed(obs_properties_t *props, obs_property_t *prop, 365 | obs_data_t *data) 366 | { 367 | char *val = obs_data_get_string(data, S_SOURCE_ID); 368 | bool vis = strcmp(val, S_SOURCE_IMAGE) == 0; 369 | obs_property_t *path = obs_properties_get(props, "file"); 370 | 371 | obs_property_set_visible(path, vis); 372 | return true; 373 | } 374 | 375 | static obs_properties_t *dvd_source_properties(void *data) 376 | { 377 | struct dvd_source *context = data; 378 | if (context) { 379 | obs_properties_t *props = 380 | obs_source_properties(context->logo_source); 381 | if (props) { 382 | obs_property_t *list = obs_properties_add_list( 383 | props, S_SOURCE_ID, T_SOURCE_ID, 384 | OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); 385 | obs_property_list_add_string(list, T_SOURCE_IMAGE, 386 | S_SOURCE_IMAGE); 387 | struct enum_param e; 388 | e.list = list; 389 | e.this = context->source; 390 | 391 | obs_property_set_modified_callback(list, 392 | source_changed); 393 | obs_enum_sources(dvd_enum_global_sources, &e); 394 | 395 | #ifndef MAC_OS 396 | obs_properties_add_bool(props, S_COLOR, T_COLOR); 397 | #endif 398 | obs_properties_add_int(props, S_SOURCE_CX, T_SOURCE_CX, 399 | 25, 0xffff, 1); 400 | obs_properties_add_int(props, S_SOURCE_CY, T_SOURCE_CY, 401 | 25, 0xffff, 1); 402 | obs_properties_add_float_slider(props, S_SPEED, T_SPEED, 403 | 0.10f, 1000.f, 0.25); 404 | obs_properties_add_float_slider(props, S_SCALE, T_SCALE, 405 | 0.10f, 10.f, 0.25); 406 | obs_properties_add_button(props, S_RESET, T_RESET, 407 | reset_logo_position); 408 | obs_property_set_modified_callback( 409 | obs_properties_get(props, "file"), 410 | image_path_changed); 411 | 412 | obs_property_set_modified_callback( 413 | obs_properties_get(props, S_COLOR), 414 | use_color_shift_changed); 415 | 416 | obs_property_set_visible( 417 | obs_properties_get(props, "unload"), false); 418 | 419 | return props; 420 | } 421 | } 422 | return NULL; 423 | } 424 | 425 | static void *dvd_source_create(obs_data_t *settings, obs_source_t *source) 426 | { 427 | struct dvd_source *context = bzalloc(sizeof(struct dvd_source)); 428 | context->source = source; 429 | context->logo_source = obs_source_create_private( 430 | "image_source", SOURCE_NAME, settings); 431 | #ifndef MAC_OS 432 | context->color_filter = obs_source_create_private( 433 | "color_filter", FILTER_NAME, settings); 434 | obs_source_add_active_child(context->source, context->color_filter); 435 | obs_source_filter_add(context->logo_source, context->color_filter); 436 | #endif 437 | 438 | obs_source_add_active_child(context->source, context->logo_source); 439 | 440 | obs_source_update(context->logo_source, settings); 441 | dvd_source_update(context, settings); 442 | 443 | context->pos.x = 0; 444 | context->pos.y = 0; 445 | context->d_x = 1; 446 | context->d_y = 1; 447 | context->use_image = true; 448 | return context; 449 | } 450 | 451 | static void dvd_enum_sources(void *data, obs_source_enum_proc_t cb, void *param) 452 | { 453 | struct dvd_source *context = data; 454 | cb(context->source, context->logo_source, param); 455 | obs_source_t *target = 456 | obs_weak_source_get_source(context->other_source); 457 | if (target) { 458 | cb(context->source, target, param); 459 | obs_source_release(target); 460 | } 461 | } 462 | 463 | static struct obs_source_info dvd_source_info = { 464 | .id = DVD_SOURCE_ID, 465 | .type = OBS_SOURCE_TYPE_INPUT, 466 | .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW, 467 | .get_name = dvd_source_get_name, 468 | .create = dvd_source_create, 469 | .destroy = dvd_source_destroy, 470 | .update = dvd_source_update, 471 | .get_defaults = dvd_source_defaults, 472 | .get_width = dvd_source_getwidth, 473 | .get_height = dvd_source_getheight, 474 | .video_render = dvd_source_render, 475 | .enum_active_sources = dvd_enum_sources, 476 | .video_tick = dvd_source_tick, 477 | .get_properties = dvd_source_properties}; 478 | 479 | OBS_DECLARE_MODULE() 480 | OBS_MODULE_USE_DEFAULT_LOCALE("dvd-screensaver", "en-US") 481 | 482 | bool obs_module_load(void) 483 | { 484 | obs_register_source(&dvd_source_info); 485 | return true; 486 | } 487 | --------------------------------------------------------------------------------