diff --git a/.github/workflows/CI Build and release.yml b/.github/workflows/CI Build and release.yml index d5cc5408..1a8a03b5 100644 --- a/.github/workflows/CI Build and release.yml +++ b/.github/workflows/CI Build and release.yml @@ -1,7 +1,10 @@ -name: 'CI Multiplatform Build' +name: 'CI Multiplatform Build and release' on: push: + branches: + - release + - master paths-ignore: - 'docs/**' pull_request: @@ -277,7 +280,7 @@ jobs: - name: 'Set release filename' shell: bash run: | - FILENAME="obs-midi-${{ env.GIT_HASH }}-1_amd64.deb" + FILENAME="obs-midi-0${{ env.GIT_HASH }}-1_amd64.deb" echo "::set-env name=LINUX_FILENAME::$FILENAME" - name: 'Package ${{ env.LINUX_FILENAME }}' if: success() @@ -287,23 +290,40 @@ jobs: VERSION="${{ env.GIT_HASH }}" cd ./build sudo checkinstall -y --type=debian --fstrans=no -nodoc \ - --backup=no --deldoc=yes --install=no --pkgname=obs-midi --pkgversion=$VERSION \ + --backup=no --deldoc=yes --install=no --pkgname=obs-midi --pkgversion=0$VERSION \ --pkglicense="GPLv2.0" --maintainer="${{ github.event.pusher.email }}" --pkggroup="video" \ --pkgsource="${{ github.event.repository.html_url }}" \ --requires="obs-studio,libqt5core5a,libqt5widgets5,qt5-image-formats-plugins" \ --pakdir="../package" sudo chmod ao+r ../package/* cd - + - name: 'Tar ${{ env.LINUX_FILENAME }}' + if: success() + working-directory: ${{ github.workspace }}/obs-midi + shell: bash + run: | + VERSION="${{ env.GIT_HASH }}" + cd ./build + mkdir -p obs-studio/plugins/64bit/ + cp ./obs-midi.so obs-studio/plugins/64bit/ + tar -czvf obs-midi-Linux-${{ env.GIT_HASH }}-x64.tar.gz obs-studio + pwd + - name: 'Publish ${{ env.LINUX_FILENAME }}' if: success() uses: actions/upload-artifact@v2-preview with: name: '${{ env.GIT_HASH }}-linux' path: '${{ github.workspace }}/obs-midi/package/*.deb' + - name: 'Publish ${{ env.LINUX_FILENAME }}' + if: success() + uses: actions/upload-artifact@v2-preview + with: + name: '${{ env.GIT_HASH }}-linux' + path: '${{ github.workspace }}/obs-midi/build/*.tar.gz' macos64: name: "macOS 64-bit" runs-on: [macos-latest] - if: contains(github.event.head_commit.message, '[skip ci]') != true env: MACOS_DEPS_VERSION: '2020-04-18' QT_VERSION: '5.14.1' @@ -340,16 +360,10 @@ jobs: echo ::set-env name=GIT_BRANCH::${{ github.event.pull_request.head.ref }} echo ::set-env name=GIT_HASH::$(git rev-parse --short HEAD) echo ::set-env name=GIT_TAG::$(git describe --tags --abbrev=0) - - name: 'Install Deps' + - name: 'Install prerequisites (Homebrew)' shell: bash - working-directory: ${{ github.workspace }}/obs-midi run: | - ./CI/install-dependencies-macos.sh - echo 'export PATH="/usr/local/opt/qt/bin:$PATH"' >> /Users/runner/.bash_profile - echo ::set-env name=LDFLAGS="-L/usr/local/opt/qt/lib" - echo ::set-env name=CPPFLAGS="-I/usr/local/opt/qt/include" - echo ::set-env name=PKG_CONFIG_PATH="/usr/local/opt/qt/lib/pkgconfig" - echo ::set-env name=PATH="/usr/local/opt/qt/bin:$PATH" + brew bundle --file ${{ github.workspace }}/obs-midi/CI/macos/Brewfile - name: 'Install prerequisite: Pre-built OBS dependencies' shell: bash run: | @@ -397,7 +411,6 @@ jobs: FILENAME="obs-midi-${{ env.GIT_HASH }}-macOS.pkg" echo "::set-env name=MAC_FILENAME_UNSIGNED::$FILENAME_UNSIGNED" echo "::set-env name=MAC_FILENAME::$FILENAME" - - name: 'Fix linked dynamic library paths' if: success() working-directory: ${{ github.workspace }}/obs-midi @@ -408,16 +421,40 @@ jobs: install_name_tool -change /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore ./build/obs-midi.so echo "Dependencies for obs-midi" otool -L ./build/obs-midi.so - - name: 'package file' + - name: 'Install Apple Developer Certificate' + if: success() + uses: apple-actions/import-codesign-certs@253ddeeac23f2bdad1646faac5c8c2832e800071 + with: + p12-file-base64: ${{ secrets.MACOS_CERT_CODESIGN }} + p12-password: ${{ secrets.MACOS_CERT_PASS }} + - name: 'Code signing' if: success() working-directory: ./obs-midi shell: bash run: | set -e + security find-identity -v -p codesigning + codesign --sign "${{ secrets.MACOS_IDENT_CODESIGN }}" ./build/obs-midi.so packagesbuild ./CI/macos/obs-midi.pkgproj mv ./release/obs-midi.pkg ./release/${{ env.MAC_FILENAME_UNSIGNED }} + productsign --sign "${{ secrets.MACOS_IDENT_INSTALLER }}" ./release/${{ env.MAC_FILENAME_UNSIGNED }} ./release/${{ env.MAC_FILENAME }} + rm ./release/${{ env.MAC_FILENAME_UNSIGNED }} + + - name: 'Notarization' + if: success() + working-directory: ./obs-midi + shell: bash + run: | + set -e + echo "store password" + xcrun altool --store-password-in-keychain-item "AC_PASSWORD" -u "${{ secrets.MACOS_IDENT_USER }}" -p "${{ secrets.MACOS_IDENT_PASS }}" + echo "xcnotary precheck" + xcnotary precheck ./release/${{ env.MAC_FILENAME }} + echo "xcnotary notarize Currently Disabled" + #if [ "$?" -eq 0 ]; then xcnotary notarize ./release/${{ env.MAC_FILENAME }} -d "cpyarger@gmail.com" -k "AC_PASSWORD"; fi + - name: 'Publish ${{ env.MAC_FILENAME }} artifact' - if: success() + if: success() uses: actions/upload-artifact@v2-preview with: name: '${{ env.GIT_HASH }}-macOS' @@ -493,8 +530,8 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ${{ github.workspace }}/${{ env.GIT_HASH }}-macOS/obs-midi-${{ env.GIT_HASH }}-macOS-Unsigned.pkg - asset_name: obs-midi-${{ env.GIT_HASH }}-macOS-Unsigned.pkg + asset_path: ${{ github.workspace }}/${{ env.GIT_HASH }}-macOS/obs-midi-${{ env.GIT_HASH }}-macOS.pkg + asset_name: obs-midi-${{ env.GIT_HASH }}-macOS.pkg asset_content_type: application/octet-stream - name: 'Upload Linux artifact to release' uses: actions/upload-release-asset@v1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..beb5e236 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +################################################################################ +# This .gitignore file was automatically created by Microsoft(R) Visual Studio. +################################################################################ + +/.vs/obs-midi/v16 diff --git a/CI/macos/Brewfile b/CI/macos/Brewfile index f3aa898c..018dd0db 100644 --- a/CI/macos/Brewfile +++ b/CI/macos/Brewfile @@ -4,7 +4,7 @@ brew "speexdsp" brew "cmake" brew "freetype" brew "fdk-aac" -brew "./qt.rb" +brew "/Users/runner/work/obs-midi/obs-midi/obs-midi/CI/macos/qt.rb" brew "swig", link: false -brew "./swig.rb" +brew "/Users/runner/work/obs-midi/obs-midi/obs-midi/CI/macos/swig.rb" brew "akeru-inc/tap/xcnotary" diff --git a/CI/macos/obs-midi.pkgproj b/CI/macos/obs-midi.pkgproj index 69d24d1b..53fc025f 100644 --- a/CI/macos/obs-midi.pkgproj +++ b/CI/macos/obs-midi.pkgproj @@ -514,11 +514,11 @@ CONCLUSION_ACTION 0 IDENTIFIER - fr.palakis.obs-midi + en.cpyarger.obs-midi OVERWRITE_PERMISSIONS VERSION - 4.8.0 + 0.9.0 PROJECT_COMMENTS diff --git a/CI/package-macos.sh b/CI/package-macos.sh index 0ebac50a..6f341a52 100755 --- a/CI/package-macos.sh +++ b/CI/package-macos.sh @@ -59,7 +59,7 @@ if [[ "$RELEASE_MODE" == "True" ]]; then zip -r ./release/$FILENAME.zip ./release/$FILENAME UPLOAD_RESULT=$(xcrun altool \ --notarize-app \ - --primary-bundle-id "fr.palakis.obs-midi" \ + --primary-bundle-id "en.cpyarger.obs-midi" \ --username "$AC_USERNAME" \ --password "$AC_PASSWORD" \ --asc-provider "$AC_PROVIDER_SHORTNAME" \ diff --git a/README.md b/README.md index 7ac34751..a39a687a 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,13 @@ Use MIDI devices to trigger events in OBS and visa versa. -# Status -- ![CI Multiplatform Build](https://github.com/cpyarger/obs-midi/workflows/CI%20Multiplatform%20Build/badge.svg) +# Status -- ![CI Multiplatform Build and release](https://github.com/cpyarger/obs-midi/workflows/CI%20Multiplatform%20Build%20and%20release/badge.svg?branch=release) # Installing -1. Grab the zip from the [OBS-Midi Releases Page](https://github.com/Alzy/obs-midi/releases) +1. Grab the installer from the [OBS-Midi Releases Page](https://github.com/cpyarger/obs-midi/releases) -2. Copy the files in the zip to your obs plugins directory. - - * By Default this is C:\Program Files\obs-studio\obs-plugins\64bit +2. Download and run the installer for your OS 3. Launch OBS @@ -23,10 +21,12 @@ Use MIDI devices to trigger events in OBS and visa versa. -Currently runs on Windows and Linux, and is untested on MAC - +Currently runs on Windows and Linux, and is partly tested on MAC # Special thanks to the following projects * [RTMidi17](https://github.com/jcelerier/RtMidi17) An amazing modernized RTMIDI library * [OBSWebsocket](https://github.com/Palakis/obs-websocket/) from which much code was borrowed for interfacing with OBS * [Midi2OBS](https://github.com/lebaston100/MIDItoOBS) Where I got my start playing with this + +# Build Instructions +[Build instructions can be found here](build.md) diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 8bf8ddc8..00000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,169 +0,0 @@ -variables: - isReleaseMode: ${{ startsWith(variables['Build.SourceBranch'], 'refs/tags/') }} - - -trigger: - branches: - include: - - master - - UI - - releases - tags: - include: - - '*' - -jobs: -- job: 'GenerateDocs' - condition: | - or( - eq(variables['Build.SourceBranch'], 'refs/heads/4.x-current'), - eq(variables['Build.SourceBranch'], 'refs/heads/master') - ) - pool: - vmImage: 'ubuntu-18.04' - steps: - - checkout: self - submodules: false - - - script: ./CI/generate-docs.sh - displayName: 'Generate docs' - env: - CHECKOUT_REF: $(Build.SourceBranch) - GH_TOKEN: $(GithubToken) - -- job: 'Build_Windows' - pool: - vmImage: 'windows-2019' - variables: - build_config: RelWithDebInfo - DepsBasePath: 'D:\obsdependencies' - DepsPath32: '$(DepsBasePath)\win32' - DepsPath64: '$(DepsBasePath)\win64' - QtBaseDir: 'D:\QtDep' - QTDIR32: '$(QtBaseDir)\5.10.1\msvc2017' - QTDIR64: '$(QtBaseDir)\5.10.1\msvc2017_64' - OBSPath: 'D:\obs-studio' - isAzure: 'true' - steps: - - checkout: self - submodules: true - - script: ./CI/install-qt-win.cmd - displayName: 'Install Qt' - env: - QtBaseDir: $(QtBaseDir) - - task: Cache@2 - displayName: Restore cached OBS Studio dependencies - inputs: - key: 'obsdeps | "$(Agent.OS)"' - restoreKeys: | - obsdeps | "$(Agent.OS)" - path: $(DepsBasePath) - - script: ./CI/download-obs-deps.cmd - displayName: 'Download OBS Studio dependencies' - - task: Cache@2 - displayName: Restore cached OBS Studio builds - inputs: - key: 'obs | "$(Agent.OS)"' - restoreKeys: | - obs | "$(Agent.OS)" - path: $(OBSPath) - - script: ./CI/prepare-obs-windows.cmd - displayName: 'Checkout & CMake OBS Studio' - env: - build_config: $(build_config) - DepsPath32: $(DepsPath32) - DepsPath64: $(DepsPath64) - QTDIR32: $(QTDIR32) - QTDIR64: $(QTDIR64) - OBSPath: $(OBSPath) - isAzure: $(isAzure) - - task: MSBuild@1 - displayName: 'Build OBS Studio 32-bit' - inputs: - msbuildArguments: '/m /p:Configuration=$(build_config)' - solution: '$(OBSPath)\build32\obs-studio.sln' - - task: MSBuild@1 - displayName: 'Build OBS Studio 64-bit' - inputs: - msbuildArguments: '/m /p:Configuration=$(build_config)' - solution: '$(OBSPath)\build64\obs-studio.sln' - - script: ./CI/prepare-windows.cmd - displayName: 'CMake obs-midi' - env: - build_config: $(build_config) - QTDIR32: $(QTDIR32) - QTDIR64: $(QTDIR64) - OBSPath: $(OBSPath) - isAzure: $(isAzure) - - task: MSBuild@1 - displayName: 'Build obs-midi 32-bit' - inputs: - msbuildArguments: '/m /p:Configuration=$(build_config)' - solution: '.\build32\obs-midi.sln' - - task: MSBuild@1 - displayName: 'Build obs-midi 64-bit' - inputs: - msbuildArguments: '/m /p:Configuration=$(build_config)' - solution: '.\build64\obs-midi.sln' - - - script: ./CI/package-windows.cmd - displayName: 'Package obs-midi' - - task: PublishBuildArtifacts@1 - displayName: 'Upload package artifacts' - inputs: - pathtoPublish: './package' - artifactName: 'windows_build' - -- job: 'Build_Linux' - pool: - vmImage: 'ubuntu-18.04' - variables: - BUILD_REASON: $(Build.Reason) - BRANCH_SHORT_NAME: $(Build.SourceBranchName) - BRANCH_FULL_NAME: $(Build.SourceBranch) - isAzure: true - steps: - - checkout: self - submodules: true - - script: ./CI/install-dependencies-ubuntu.sh - displayName: 'Install dependencies' - - script: ./CI/build-ubuntu.sh - displayName: 'Build obs-midi' - env: - isAzure: $(isAzure) - - script: ./CI/package-ubuntu.sh - displayName: 'Package obs-midi' - - task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: './package' - artifactName: 'deb_build' - -- job: 'Build_macOS' - pool: - vmImage: 'macos-10.14' - variables: - isAzure: true - steps: - - checkout: self - submodules: true - - - script: ./CI/install-dependencies-macos.sh - displayName: 'Install dependencies' - - - script: ./CI/install-build-obs-macos.sh - displayName: 'Build OBS' - - - script: ./CI/build-macos.sh - displayName: 'Build obs-midi' - env: - isAzure: $(isAzure) - - - script: ./CI/package-macos.sh - displayName: 'Package obs-midi' - env: - RELEASE_MODE: false - - - task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: './release' - artifactName: 'macos_build' diff --git a/azure-testing.yml b/azure-testing.yml deleted file mode 100644 index a1ba590b..00000000 --- a/azure-testing.yml +++ /dev/null @@ -1,162 +0,0 @@ -variables: - isReleaseMode: ${{ startsWith(variables['Build.SourceBranch'], 'refs/tags/') }} - - -trigger: - branches: - include: - - testing - tags: - include: - - '*' - -jobs: -- job: 'GenerateDocs' - condition: | - or( - eq(variables['Build.SourceBranch'], 'refs/heads/4.x-current'), - eq(variables['Build.SourceBranch'], 'refs/heads/master') - ) - pool: - vmImage: 'ubuntu-18.04' - steps: - - checkout: self - submodules: false - - - script: ./CI/generate-docs.sh - displayName: 'Generate docs' - env: - CHECKOUT_REF: $(Build.SourceBranch) - GH_TOKEN: $(GithubToken) - -- job: 'Build_Windows' - pool: - vmImage: 'windows-2019' - variables: - build_config: RelWithDebInfo - DepsBasePath: 'D:\obsdependencies' - DepsPath32: '$(DepsBasePath)\win32' - DepsPath64: '$(DepsBasePath)\win64' - QtBaseDir: 'D:\QtDep' - QTDIR32: '$(QtBaseDir)\5.10.1\msvc2017' - QTDIR64: '$(QtBaseDir)\5.10.1\msvc2017_64' - OBSPath: 'D:\obs-studio' - isAzure: 'true' - steps: - - checkout: self - submodules: true - - script: ./CI/install-qt-win.cmd - displayName: 'Install Qt' - env: - QtBaseDir: $(QtBaseDir) - - task: Cache@2 - displayName: Restore cached OBS Studio dependencies - inputs: - key: 'obsdeps | "$(Agent.OS)"' - restoreKeys: | - obsdeps | "$(Agent.OS)" - path: $(DepsBasePath) - - script: ./CI/download-obs-deps.cmd - displayName: 'Download OBS Studio dependencies' - - task: Cache@2 - displayName: Restore cached OBS Studio builds - inputs: - key: 'obs | "$(Agent.OS)"' - restoreKeys: | - obs | "$(Agent.OS)" - path: $(OBSPath) - - script: ./CI/prepare-obs-windows.cmd - displayName: 'Checkout & CMake OBS Studio' - env: - build_config: $(build_config) - DepsPath32: $(DepsPath32) - DepsPath64: $(DepsPath64) - QTDIR32: $(QTDIR32) - QTDIR64: $(QTDIR64) - OBSPath: $(OBSPath) - isAzure: $(isAzure) - - task: MSBuild@1 - displayName: 'Build OBS Studio 32-bit' - inputs: - msbuildArguments: '/m /p:Configuration=$(build_config)' - solution: '$(OBSPath)\build32\obs-studio.sln' - - task: MSBuild@1 - displayName: 'Build OBS Studio 64-bit' - inputs: - msbuildArguments: '/m /p:Configuration=$(build_config)' - solution: '$(OBSPath)\build64\obs-studio.sln' - - script: ./CI/prepare-windows.cmd - displayName: 'CMake obs-midi' - env: - build_config: $(build_config) - QTDIR32: $(QTDIR32) - QTDIR64: $(QTDIR64) - OBSPath: $(OBSPath) - isAzure: $(isAzure) - - task: MSBuild@1 - displayName: 'Build obs-midi 32-bit' - inputs: - msbuildArguments: '/m /p:Configuration=$(build_config)' - solution: '.\build32\obs-midi.sln' - - task: MSBuild@1 - displayName: 'Build obs-midi 64-bit' - inputs: - msbuildArguments: '/m /p:Configuration=$(build_config)' - solution: '.\build64\obs-midi.sln' - - - script: ./CI/package-windows.cmd - displayName: 'Package obs-midi' - - task: PublishBuildArtifacts@1 - displayName: 'Upload package artifacts' - inputs: - pathtoPublish: './package' - artifactName: 'windows_build' - -- job: 'Build_Linux' - pool: - vmImage: 'ubuntu-18.04' - variables: - BUILD_REASON: $(Build.Reason) - BRANCH_SHORT_NAME: $(Build.SourceBranchName) - BRANCH_FULL_NAME: $(Build.SourceBranch) - isAzure: true - steps: - - checkout: self - submodules: true - - script: ./CI/install-dependencies-ubuntu.sh - displayName: 'Install dependencies' - - script: ./CI/build-ubuntu.sh - displayName: 'Build obs-midi' - env: - isAzure: $(isAzure) - - script: ./CI/package-ubuntu.sh - displayName: 'Package obs-midi' - - task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: './package' - artifactName: 'deb_build' - -- job: 'Build_macOS' - pool: - vmImage: 'macos-10.14' - variables: - isAzure: true - steps: - - checkout: self - submodules: true - - script: ./CI/install-dependencies-macos.sh - displayName: 'Install dependencies' - - script: ./CI/install-build-obs-macos.sh - displayName: 'Build OBS' - - script: ./CI/build-macos.sh - displayName: 'Build obs-midi' - env: - isAzure: $(isAzure) - - script: ./CI/package-macos.sh - displayName: 'Package obs-midi' - env: - RELEASE_MODE: false - - task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: './release' - artifactName: 'macos_build' diff --git a/azureremoves.txt b/azureremoves.txt deleted file mode 100644 index 463ee77d..00000000 --- a/azureremoves.txt +++ /dev/null @@ -1,18 +0,0 @@ - - task: InstallAppleCertificate@1 - displayName: 'Install release signing certificates' - condition: eq(variables['isReleaseMode'], true) - inputs: - certSecureFile: 'Certificates.p12' - certPwd: $(secrets.macOS.certificatesImportPassword) - - - -- script: ./CI/package-macos.sh - displayName: 'Package obs-midi' - env: - RELEASE_MODE: $(isReleaseMode) - CODE_SIGNING_IDENTITY: $(secrets.macOS.codeSigningIdentity) - INSTALLER_SIGNING_IDENTITY: $(secrets.macOS.installerSigningIdentity) - AC_USERNAME: $(secrets.macOS.notarization.username) - AC_PASSWORD: $(secrets.macOS.notarization.password) - AC_PROVIDER_SHORTNAME: $(secrets.macOS.notarization.providerShortName) diff --git a/build.md b/build.md new file mode 100644 index 00000000..bf73f2db --- /dev/null +++ b/build.md @@ -0,0 +1,93 @@ +# Compiling obs-midi + +## Prerequisites + +You'll need [Qt 5.15.2](https://download.qt.io/official_releases/qt/5.15/), +[CMake](https://cmake.org/download/) and a working [OBS Studio development environment](https://obsproject.com/wiki/install-instructions) installed on your +computer. + +For Cleanliness and sanity, Do not mix the obs-studio and obs-midi directories. + +For Example My Directory structure looks like this + + +|Directory | Reason| +|-----------|----------| +| Desktop\OBS\Build| (OBS-Studio Build Dir) | +| Desktop\OBS\Deps | (OBS Dependencies from zip file on obs site) | +| Desktop\OBS\midibuild | (Build Directory for obs-midi) | +| Desktop\OBS\obs-studio | (obs studio source code) | +| Desktop\OBS\obs-midi | (obs midi source code) | +| C:\Qt\5.15.2\msvc2019_64 | (QTDIR) | + + +## Windows + +In cmake-gui, you'll have to set the following variables : + +| Variable | info | Example Path | +|----------|-------|-----------| +| **QTDIR** | (path) : location of the Qt environment suited for your compiler and architecture | C:/Qt/5.15.2/msvc2019_64| +| **LIBOBS_INCLUDE_DIR** | (path) : location of the libobs subfolder in the source code of OBS Studio | C:/Users/User/Desktop/OBS/obs-studio/libobs | +| **LIBOBS_LIB** | (filepath) : location of the obs.lib file | C:/Users/User/Desktop/OBS/build/libobs/RelWithDebInfo/obs.lib| +| **OBS_FRONTEND_LIB** | (filepath) : location of the obs-frontend-api.lib file | C:/Users/User/Desktop/OBS/build/UI/obs-frontend-api/RelWithDebInfo/obs-frontend-api.lib| +| **CMAKE_INSTALL_PREFIX** | (path) : Same location as QTDIR | C:/Qt/5.15.2/msvc2019_64| + +![My CMake Gui Looks like ](https://github.com/cpyarger/obs-midi/blob/master/docs/obs-midi-cmake.PNG?raw=true) + +In Visual Studio, Set OBS-Midi as the startup project, + +![set obs-midi as startup project ](https://github.com/cpyarger/obs-midi/blob/master/docs/obs-midi-set-as-startup-project.PNG?raw=true) +Change Output Directory to OBS-Studio projects plugin's folder on the general page +![My CMake Gui Looks like ](https://github.com/cpyarger/obs-midi/blob/master/docs/obs-midi-general-page.PNG?raw=true) +Change Debug to obs-studio's exe and exe dir in the debug page +![My CMake Gui Looks like ](https://github.com/cpyarger/obs-midi/blob/master/docs/obs-midi-debug-page.PNG?raw=true) +## Linux + +On Debian/Ubuntu : + +```shell +sudo apt-get install libboost-all-dev +git clone --recursive https://github.com/Palakis/obs-midi.git +cd obs-midi +mkdir build && cd build +cmake -DLIBOBS_INCLUDE_DIR="" -DCMAKE_INSTALL_PREFIX=/usr -DUSE_UBUNTU_FIX=true .. +make -j4 +sudo make install +``` + +On other linux OS's, use this cmake command instead: + +```shell +cmake -DLIBOBS_INCLUDE_DIR="" -DCMAKE_INSTALL_PREFIX=/usr .. +``` + +## OS X + +As a prerequisite, you will need Xcode for your current OSX version, the Xcode command line tools, and [Homebrew](https://brew.sh/). +Homebrew's setup will guide you in getting your system set up, you should be good to go once Homebrew is successfully up and running. + +Use of the macOS CI scripts is recommended. Please note that these +scripts install new software and can change several settings on your system. An +existing obs-studio development environment is not required, as +`install-build-obs-macos.sh` will install it for you. If you already have a +working obs-studio development environment and have built obs-studio, you can +skip that script. + +Of course, you're encouraged to dig through the contents of these scripts to +look for issues or specificities. + +```shell +git clone --recursive https://github.com/Palakis/obs-midi.git +cd obs-midi +./CI/install-dependencies-macos.sh +./CI/install-build-obs-macos.sh +./CI/build-macos.sh +./CI/package-macos.sh +``` + +This will result in a ready-to-use `obs-midi.pkg` installer in the `release` subfolder. + +## Automated Builds + +![CI Multiplatform Build](https://github.com/cpyarger/obs-midi/workflows/CI%20Multiplatform%20Build/badge.svg) diff --git a/docs/obs-midi-cmake.PNG b/docs/obs-midi-cmake.PNG new file mode 100644 index 00000000..748894a0 Binary files /dev/null and b/docs/obs-midi-cmake.PNG differ diff --git a/docs/obs-midi-debug-page.PNG b/docs/obs-midi-debug-page.PNG new file mode 100644 index 00000000..7bb7cacb Binary files /dev/null and b/docs/obs-midi-debug-page.PNG differ diff --git a/docs/obs-midi-general-page.PNG b/docs/obs-midi-general-page.PNG new file mode 100644 index 00000000..3cc7c3b5 Binary files /dev/null and b/docs/obs-midi-general-page.PNG differ diff --git a/docs/obs-midi-set-as-startup-project.PNG b/docs/obs-midi-set-as-startup-project.PNG new file mode 100644 index 00000000..0daacd8d Binary files /dev/null and b/docs/obs-midi-set-as-startup-project.PNG differ diff --git a/src/forms/settings-dialog.cpp b/src/forms/settings-dialog.cpp index 1c3c0628..a3e8cdd8 100644 --- a/src/forms/settings-dialog.cpp +++ b/src/forms/settings-dialog.cpp @@ -31,7 +31,7 @@ with this program. If not, see #include #include "../version.h" -PluginWindow::PluginWindow(QWidget *parent) +PluginWindow::PluginWindow(QWidget* parent) : QDialog(parent, Qt::Dialog), ui(new Ui::PluginWindow) { ui->setupUi(this); @@ -54,9 +54,9 @@ PluginWindow::PluginWindow(QWidget *parent) SLOT(on_check_enabled_state_changed(int))); connect(ui->bidirectional, SIGNAL(stateChanged(int)), this, SLOT(on_bid_enabled_state_changed(int))); - + //Connections for Configure Tab - + connect(ui->cb_obs_output_scene, SIGNAL(currentTextChanged(QString)), this, SLOT(get_sources(QString))); connect(ui->cb_obs_output_action, SIGNAL(currentTextChanged(QString)), @@ -100,7 +100,8 @@ void PluginWindow::ToggleShowHide() setVisible(true); - } else { + } + else { setVisible(false); ui->btn_Listen_many->setChecked(false); ui->btn_Listen_one->setChecked(false); @@ -128,7 +129,8 @@ void PluginWindow::SetAvailableDevices() ui->check_enabled->setEnabled(false); this->ui->outbox->setEnabled(false); ui->tabWidget->setEnabled(false); - } else if (midiDevices.size() > 0) { + } + else if (midiDevices.size() > 0) { for (int i = 0; i < midiDevices.size(); i++) { this->ui->list_midi_dev->addItem(midiDevices.at(i)); } @@ -150,10 +152,10 @@ void PluginWindow::SetAvailableDevices() this->ui->outbox->setCurrentIndex(1); #elif __linux__ this->ui->outbox->setCurrentIndex(0); -// linux + // linux #elif __unix__ // all unices not caught above this->ui->outbox->setCurrentIndex(0); -// Unix + // Unix #endif if (midiDevices.size() != 0) { desconnect = connect( @@ -199,13 +201,14 @@ int PluginWindow::on_check_enabled_state_changed(int state) selectedOutDeviceName.c_str()); if (device == NULL) { GetDeviceManager()->RegisterMidiDevice(devicePort, - deviceOutPort); + deviceOutPort); device = GetDeviceManager()->GetMidiDeviceByName( selectedDeviceName.c_str()); device->open_midi_input_port(devicePort); device->open_midi_output_port(deviceOutPort); - } else { + } + else { device->open_midi_input_port(devicePort); device->open_midi_output_port(deviceOutPort); @@ -215,10 +218,10 @@ int PluginWindow::on_check_enabled_state_changed(int state) ui->bidirectional->setEnabled(true); ui->bidirectional->setChecked(true); ui->outbox->setEnabled(true); - + } //ui->outbox->setCurrentText(QString::fromStdString(device->GetOutName())); - + GetConfig()->Save(); //on_device_select(ui->list_midi_dev->currentItem()->text()); return state; @@ -228,7 +231,7 @@ void PluginWindow::on_device_select(QString curitem) { auto devicemanager = GetDeviceManager(); auto config = GetConfig(); - MidiAgent *MAdevice = devicemanager->GetMidiDeviceByName(curitem); + MidiAgent* MAdevice = devicemanager->GetMidiDeviceByName(curitem); ui->tabWidget->setTabText(1, QString("Configure - ").append(curitem)); // Pull info on if device is enabled, if so set true if not set false @@ -239,7 +242,8 @@ void PluginWindow::on_device_select(QString curitem) ui->bidirectional->setChecked(MAdevice->isBidirectional()); ui->outbox->setCurrentText(MAdevice->get_midi_output_name()); - } else { + } + else { ui->check_enabled->setChecked(false); ui->outbox->setEnabled(false); ui->bidirectional->setEnabled(false); @@ -256,24 +260,25 @@ void PluginWindow::handle_midi_message(MidiMessage mess) { if (ui->tabWidget->currentIndex() == 1) { if (ui->btn_Listen_one->isChecked() || - ui->btn_Listen_many->isChecked()) { + ui->btn_Listen_many->isChecked()) { blog(1, - "got midi message via gui, \n Device = %s \nMType = %s \n NORC : %i \n Channel: %i \n Value: %i", - mess.device_name.toStdString().c_str(), - mess.message_type.toStdString().c_str(), mess.NORC, - mess.channel, mess.value); + "got midi message via gui, \n Device = %s \nMType = %s \n NORC : %i \n Channel: %i \n Value: %i", + mess.device_name.toStdString().c_str(), + mess.message_type.toStdString().c_str(), mess.NORC, + mess.channel, mess.value); ui->mapping_lbl_device_name->setText(mess.device_name); ui->sb_channel->setValue(mess.channel); ui->sb_norc->setValue(mess.NORC); ui->slider_value->setValue(mess.value); ui->cb_mtype->setCurrentText(mess.message_type); ui->btn_Listen_one->setChecked(false); - } else { + } + else { if (map_location(mess) != -1) { ui->table_mapping->selectRow( map_location(mess)); } - + } } } @@ -285,11 +290,12 @@ int PluginWindow::on_bid_enabled_state_changed(int state) device->setBidirectional(state); return 1; - } else { + } + else { device->setBidirectional(state); return 0; } - + } PluginWindow::~PluginWindow() @@ -316,12 +322,12 @@ void PluginWindow::get_scene_names() void PluginWindow::add_midi_device(QString name) { blog(LOG_DEBUG, "Adding Midi Device %s", name.toStdString().c_str()); - QTableWidgetItem *device_name = new QTableWidgetItem(); - QTableWidgetItem *device_enabled = new QTableWidgetItem(); - QTableWidgetItem *device_status = new QTableWidgetItem(); - QTableWidgetItem *feedback_enabled = new QTableWidgetItem(); - QTableWidgetItem *feedback_name = new QTableWidgetItem(); - QTableWidgetItem *feedback_status = new QTableWidgetItem(); + QTableWidgetItem* device_name = new QTableWidgetItem(); + QTableWidgetItem* device_enabled = new QTableWidgetItem(); + QTableWidgetItem* device_status = new QTableWidgetItem(); + QTableWidgetItem* feedback_enabled = new QTableWidgetItem(); + QTableWidgetItem* feedback_name = new QTableWidgetItem(); + QTableWidgetItem* feedback_status = new QTableWidgetItem(); int rowcount = this->ui->table_mapping->rowCount(); this->ui->table_mapping->insertRow(rowcount); device_name->setText(name); @@ -341,9 +347,9 @@ void PluginWindow::add_midi_device(QString name) void PluginWindow::set_headers() { ui->table_mapping->setHorizontalHeaderLabels( - {"Channel", "Message Type", "Note or Control", "Action", + { "Channel", "Message Type", "Note or Control", "Action", "Scene", "Source", "Filter", "Transition", "Item", - "Audio Source", "Media Source"}); + "Audio Source", "Media Source" }); QColor midicolor("#00aaff"); QColor actioncolor("#aa00ff"); @@ -529,15 +535,15 @@ void PluginWindow::ShowOnly(QList shows) for (int i = 0; i < shows.size(); i++) { ui->cb_obs_output_action->addItem( obs_module_text(ActionsClass::action_to_string(shows.at(i)) - .toStdString() - .c_str())); + .toStdString() + .c_str())); } } void PluginWindow::ShowEntry(ActionsClass::Actions Entry) { if (ui->cb_obs_output_action->findText( - ActionsClass::action_to_string(Entry)) == -1) { + ActionsClass::action_to_string(Entry)) == -1) { ui->cb_obs_output_action->addItem(obs_module_text( ActionsClass::action_to_string(Entry).toStdString().c_str())); } @@ -545,7 +551,7 @@ void PluginWindow::ShowEntry(ActionsClass::Actions Entry) void PluginWindow::HideEntry(ActionsClass::Actions Entry) { if (ui->cb_obs_output_action->findText( - ActionsClass::action_to_string(Entry)) > 0) { + ActionsClass::action_to_string(Entry)) > 0) { ui->cb_obs_output_action->removeItem( ui->cb_obs_output_action->findText( ActionsClass::action_to_string(Entry))); @@ -589,7 +595,7 @@ void PluginWindow::get_sources(QString scene) auto arrayref = Utils::GetSceneArray(scene); int size = obs_data_array_count(arrayref); for (int i = 0; i < size; i++) { - obs_data *item = obs_data_array_item(arrayref, i); + obs_data* item = obs_data_array_item(arrayref, i); ui->cb_obs_output_source->addItem( QString(obs_data_get_string(item, "name"))); @@ -600,7 +606,7 @@ void PluginWindow::get_sources(QString scene) void PluginWindow::get_scenes() { ui->cb_obs_output_scene->clear(); - obs_data_array *x = Utils::GetScenes(); + obs_data_array* x = Utils::GetScenes(); int cnt = obs_data_array_count(x); for (int i = 0; i <= cnt; i++) { auto it = obs_data_array_item(x, i); @@ -745,9 +751,9 @@ bool PluginWindow::map_exists() ui->mapping_lbl_device_name->text()); for (int i = 0; i < hooks.size(); i++) { if ((hooks.at(i)->channel == ui->sb_channel->value()) && - (hooks.at(i)->norc == ui->sb_norc->value()) && - (hooks.at(i)->message_type == - ui->cb_mtype->currentText())) { + (hooks.at(i)->norc == ui->sb_norc->value()) && + (hooks.at(i)->message_type == + ui->cb_mtype->currentText())) { return true; } } @@ -760,9 +766,9 @@ int PluginWindow::map_location(MidiMessage message) ui->mapping_lbl_device_name->text()); for (int i = 0; i < hooks.size(); i++) { if ((hooks.at(i)->channel == message.channel) && - (hooks.at(i)->norc == message.NORC) && - (hooks.at(i)->message_type == - message.message_type)) { + (hooks.at(i)->norc == message.NORC) && + (hooks.at(i)->message_type == + message.message_type)) { return i; } } @@ -772,31 +778,31 @@ void PluginWindow::add_new_mapping() { ui->btn_Listen_many->setChecked(false); ui->btn_Listen_one->setChecked(false); - if (!map_exists()) { + if (!map_exists() && verify_mapping()) { int row = ui->table_mapping->rowCount(); ui->table_mapping->insertRow(row); - QTableWidgetItem *channelitem = new QTableWidgetItem( + QTableWidgetItem* channelitem = new QTableWidgetItem( QString::number(ui->sb_channel->value())); - QTableWidgetItem *mtypeitem = + QTableWidgetItem* mtypeitem = new QTableWidgetItem(ui->cb_mtype->currentText()); - QTableWidgetItem *norcitem = new QTableWidgetItem( + QTableWidgetItem* norcitem = new QTableWidgetItem( QString::number(ui->sb_norc->value())); - QTableWidgetItem *actionitem = new QTableWidgetItem( + QTableWidgetItem* actionitem = new QTableWidgetItem( ui->cb_obs_output_action->currentText()); - QTableWidgetItem *sceneitem = new QTableWidgetItem( + QTableWidgetItem* sceneitem = new QTableWidgetItem( ui->cb_obs_output_scene->currentText()); - QTableWidgetItem *sourceitem = new QTableWidgetItem( + QTableWidgetItem* sourceitem = new QTableWidgetItem( ui->cb_obs_output_source->currentText()); - QTableWidgetItem *filteritem = new QTableWidgetItem( + QTableWidgetItem* filteritem = new QTableWidgetItem( ui->cb_obs_output_filter->currentText()); - QTableWidgetItem *transitionitem = new QTableWidgetItem( + QTableWidgetItem* transitionitem = new QTableWidgetItem( ui->cb_obs_output_transition->currentText()); - QTableWidgetItem *itemitem = new QTableWidgetItem( + QTableWidgetItem* itemitem = new QTableWidgetItem( ui->cb_obs_output_item->currentText()); - QTableWidgetItem *audioitem = new QTableWidgetItem( + QTableWidgetItem* audioitem = new QTableWidgetItem( ui->cb_obs_output_audio_source->currentText()); - QTableWidgetItem *mediaitem = new QTableWidgetItem( + QTableWidgetItem* mediaitem = new QTableWidgetItem( ui->cb_obs_output_media_source->currentText()); ui->table_mapping->setItem(row, 0, channelitem); ui->table_mapping->setItem(row, 1, mtypeitem); @@ -809,7 +815,7 @@ void PluginWindow::add_new_mapping() ui->table_mapping->setItem(row, 8, itemitem); ui->table_mapping->setItem(row, 9, audioitem); ui->table_mapping->setItem(row, 10, mediaitem); - MidiHook *newmh = new MidiHook(); + MidiHook* newmh = new MidiHook(); newmh->channel = ui->sb_channel->value(); newmh->message_type = ui->cb_mtype->currentText(); newmh->norc = ui->sb_norc->value(); @@ -829,22 +835,29 @@ void PluginWindow::add_new_mapping() dev->add_MidiHook(newmh); auto conf = GetConfig(); conf->Save(); - } else { - // TODO: Fix this, and create Utils::message_to_user(QString) - QString Mess; - Mess.append("Mapping already Exists for "); - Mess.append(ui->mapping_lbl_device_name->text()); - Mess.append(" , with channel # "); - Mess.append(QString::number(ui->sb_channel->value())); - Mess.append(" norc # "); - Mess.append(QString::number(ui->sb_norc->value())); - Mess.append(" and Message Type "); - Mess.append(ui->cb_mtype->currentText()); - Utils::alert_popup(Mess); + } + else { + if (!verify_mapping()) { + Utils::alert_popup("Mapping Missing required variable"); + } + if(map_exists()){ + // TODO: Fix this, and create Utils::message_to_user(QString) + QString Mess; + + Mess.append("Mapping already Exists for "); + Mess.append(ui->mapping_lbl_device_name->text()); + Mess.append(" , with channel # "); + Mess.append(QString::number(ui->sb_channel->value())); + Mess.append(" norc # "); + Mess.append(QString::number(ui->sb_norc->value())); + Mess.append(" and Message Type "); + Mess.append(ui->cb_mtype->currentText()); + Utils::alert_popup(Mess); + } } } -void PluginWindow::add_row_from_hook(MidiHook *hook) +void PluginWindow::add_row_from_hook(MidiHook* hook) { int row = ui->table_mapping->rowCount(); ui->table_mapping->insertRow(row); @@ -852,21 +865,21 @@ void PluginWindow::add_row_from_hook(MidiHook *hook) midic.setRgb(0, 170, 255); QColor actc; actc.setRgb(170, 0, 255); - QTableWidgetItem *channelitem = + QTableWidgetItem* channelitem = new QTableWidgetItem(QString::number(hook->channel)); - QTableWidgetItem *mtypeitem = new QTableWidgetItem(hook->message_type); - QTableWidgetItem *norcitem = + QTableWidgetItem* mtypeitem = new QTableWidgetItem(hook->message_type); + QTableWidgetItem* norcitem = new QTableWidgetItem(QString::number(hook->norc)); - QTableWidgetItem *actionitem = new QTableWidgetItem(hook->action); - QTableWidgetItem *sceneitem = new QTableWidgetItem(hook->scene); - QTableWidgetItem *sourceitem = new QTableWidgetItem(hook->source); - QTableWidgetItem *filteritem = new QTableWidgetItem(hook->filter); - QTableWidgetItem *transitionitem = + QTableWidgetItem* actionitem = new QTableWidgetItem(hook->action); + QTableWidgetItem* sceneitem = new QTableWidgetItem(hook->scene); + QTableWidgetItem* sourceitem = new QTableWidgetItem(hook->source); + QTableWidgetItem* filteritem = new QTableWidgetItem(hook->filter); + QTableWidgetItem* transitionitem = new QTableWidgetItem(hook->transition); - QTableWidgetItem *itemitem = new QTableWidgetItem(hook->item); - QTableWidgetItem *audioitem = new QTableWidgetItem(hook->audio_source); - QTableWidgetItem *mediaitem = new QTableWidgetItem(hook->media_source); + QTableWidgetItem* itemitem = new QTableWidgetItem(hook->item); + QTableWidgetItem* audioitem = new QTableWidgetItem(hook->audio_source); + QTableWidgetItem* mediaitem = new QTableWidgetItem(hook->media_source); set_cell_colors(midic, channelitem); set_cell_colors(midic, mtypeitem); @@ -892,7 +905,7 @@ void PluginWindow::add_row_from_hook(MidiHook *hook) ui->table_mapping->setItem(row, 9, audioitem); ui->table_mapping->setItem(row, 10, mediaitem); } -void PluginWindow::set_cell_colors(QColor color, QTableWidgetItem *item) +void PluginWindow::set_cell_colors(QColor color, QTableWidgetItem* item) { QColor txcolor; txcolor.black(); @@ -908,7 +921,7 @@ void PluginWindow::tab_changed(int i) set_headers(); ui->table_mapping->setRowCount(0); auto devicemanager = GetDeviceManager(); - + auto hooks = devicemanager->GetMidiHooksByDeviceName( ui->mapping_lbl_device_name->text()); if (hooks.count() > 0) { @@ -916,7 +929,7 @@ void PluginWindow::tab_changed(int i) add_row_from_hook(hooks.at(i)); } } - + } void PluginWindow::delete_mapping() { auto devicemanager = GetDeviceManager(); @@ -926,18 +939,18 @@ void PluginWindow::delete_mapping() { auto conf = GetConfig(); for (int i = 0; i < hooks.size(); i++) { if ((hooks.at(i)->channel == ui->sb_channel->value()) && - (hooks.at(i)->norc == ui->sb_norc->value()) && - (hooks.at(i)->message_type == - ui->cb_mtype->currentText())) { + (hooks.at(i)->norc == ui->sb_norc->value()) && + (hooks.at(i)->message_type == + ui->cb_mtype->currentText())) { dev->remove_MidiHook(hooks.at(i)); conf->Save(); ui->table_mapping->removeRow( ui->table_mapping->selectedItems().at(0)->row()); } } - - - + + + } void PluginWindow::edit_mapping(int row, int col) { @@ -956,3 +969,34 @@ void PluginWindow::edit_mapping(int row, int col) ui->cb_obs_output_audio_source->setCurrentText(sitems.at(9)->text()); ui->cb_obs_output_media_source->setCurrentText(sitems.at(10)->text()); } +bool PluginWindow::verify_mapping() { + int testresults = 0; + if (ui->cb_obs_output_audio_source->isVisible() && ui->cb_obs_output_audio_source->count() == 0) { + testresults++; + } + if (ui->cb_obs_output_scene->isVisible() && ui->cb_obs_output_scene->count() == 0) { + testresults++; + } + if (ui->cb_obs_output_source->isVisible() && ui->cb_obs_output_source->count() == 0) { + testresults++; + } + if (ui->cb_obs_output_filter->isVisible() && ui->cb_obs_output_filter->count() == 0) { + testresults++; + } + if (ui->cb_obs_output_transition->isVisible() && ui->cb_obs_output_transition->count() == 0) { + testresults++; + } + if (ui->cb_obs_output_item->isVisible() && ui->cb_obs_output_item->count() == 0) { + testresults++; + } + if (ui->cb_obs_output_media_source->isVisible() && ui->cb_obs_output_media_source->count() == 0) { + testresults++; + } + + if (testresults > 0) { + return false; + } + else { + return true; + } +} \ No newline at end of file diff --git a/src/forms/settings-dialog.h b/src/forms/settings-dialog.h index cfdb79ef..31f4c81d 100644 --- a/src/forms/settings-dialog.h +++ b/src/forms/settings-dialog.h @@ -78,7 +78,7 @@ public slots: bool first_run; bool map_exists(); int map_location(MidiMessage message); - + bool verify_mapping(); private: QGridLayout *layout; QStringList *items;