aboutsummaryrefslogtreecommitdiffhomepage
path: root/assets
diff options
context:
space:
mode:
Diffstat (limited to 'assets')
-rw-r--r--assets/MIDIMonster.svg1
-rw-r--r--assets/TODO15
-rw-r--r--assets/ci-config73
-rwxr-xr-xassets/ci.sh313
-rw-r--r--assets/midimonster.142
-rw-r--r--assets/midimonster.icobin0 -> 321510 bytes
-rw-r--r--assets/midimonster.rc22
7 files changed, 466 insertions, 0 deletions
diff --git a/assets/MIDIMonster.svg b/assets/MIDIMonster.svg
new file mode 100644
index 0000000..7e411dc
--- /dev/null
+++ b/assets/MIDIMonster.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 525.82 454.06"><defs><style>.cls-1{fill:#c1282d;}.cls-2{fill:#333132;}.cls-3{fill:#fff;}</style></defs><title>Asset 3</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><g id="Logo"><path class="cls-1" d="M261.45,244c-37.35,0-67.74-31-67.74-69.09A70.34,70.34,0,0,1,199.06,148C217,159.44,239,165.66,262,165.66c22.59,0,44.3-6,62.07-17.11a70.34,70.34,0,0,1,5.13,26.36C329.18,213,298.8,244,261.45,244"/><path class="cls-2" d="M350.86,125.56l-8.44-5.37a75.48,75.48,0,0,1-17,18.67c-16.84,12.1-39,19.48-63.42,19.48-25.48,0-48.59-8.05-65.68-21.13a.16.16,0,0,1,0,.07,74.74,74.74,0,0,1-15.08-17.09l-8.45,5.37a85.44,85.44,0,0,0,19.15,21,77.31,77.31,0,0,0-5.35,28.32c0,42.2,33.54,76.41,74.92,76.41s74.91-34.21,74.91-76.41a77.23,77.23,0,0,0-5.18-27.9A85.73,85.73,0,0,0,350.86,125.56ZM261.45,236.67c-33.39,0-60.56-27.71-60.56-61.76A62.79,62.79,0,0,1,203,158.74a129.21,129.21,0,0,0,117,.49,63,63,0,0,1,2,15.68C322,209,294.84,236.67,261.45,236.67Z"/><path class="cls-2" d="M261.45,215.57a21.3,21.3,0,1,1,20.88-21.3,21.12,21.12,0,0,1-20.88,21.3"/><path class="cls-3" d="M261.45,203.2a8.93,8.93,0,1,1,8.75-8.93,8.86,8.86,0,0,1-8.75,8.93"/><path class="cls-2" d="M513.32,296.36H450.2c-1.83-1.55-3.52-2.83-5.08-4-2.38-1.81-4.32-3.49-6.82-5.66a99.24,99.24,0,0,0-9.89-7.91,358.26,358.26,0,0,0,2-40.38,12.4,12.4,0,0,0,3.87.62h72a12.5,12.5,0,0,0,0-25h-72a12.42,12.42,0,0,0-5.31,1.2,8,8,0,0,0-.22-1l.32-.92,0-1.35a167.76,167.76,0,0,0-3.24-29.64c2-2.13,4-4.76,5.36-6l19.27-18.6h68.86c12.53-11,4.89-25-6-25H440.38l-22.65,21.87A165.62,165.62,0,0,0,397.88,118a176.74,176.74,0,0,0,3.31-57.81A169.18,169.18,0,0,0,383.11,0c.42,31.45-5.81,52.76-11.75,66.57-2.67,6.2-5.53,11.47-6.85,16.77A167.28,167.28,0,0,0,158.44,84c-1.49-4.37-3.81-8.85-6-14-5.94-13.81-12.17-35.11-11.75-66.56A169.39,169.39,0,0,0,122.6,63.7a176.69,176.69,0,0,0,2.73,55.13A166,166,0,0,0,106.67,153l-21.23-20.5H12.5c-10.91,0-18.55,14-6,25H75.34l19.27,18.6c1,.93,2.29,2.59,3.73,4.25A168.8,168.8,0,0,0,94.7,212l0,1.35.23.66c0,.09-.08.19-.11.29a12.4,12.4,0,0,0-3.3-.46H19.54a12.5,12.5,0,1,0,0,25H91.49a12.66,12.66,0,0,0,1.64-.12A359.58,359.58,0,0,0,95.32,280c-3.19,2.37-6.83,5.62-7.8,6.46-2.5,2.17-4.44,3.85-6.81,5.66-1.57,1.19-3.25,2.47-5.09,4H12.5a12.5,12.5,0,0,0,0,25H80.39A12.55,12.55,0,0,0,89,317.69,71.81,71.81,0,0,1,95.85,312c1.13-.86,2.32-1.77,3.58-2.78,2.24,13,5.23,27.25,9.19,42.63,3.43,13.29,15.24,38.77,16.46,41.38a.37.37,0,0,1,0,.11,7,7,0,0,0,12.14,1.07l1.59-1.85c5.62-6.47,11.74-13.74,16.91-20.72,1,11.59,2.43,21.73,4.58,28.29,4.18,12.8,24.92,34.81,32.15,42.22a7.19,7.19,0,0,0,5.83,2.95,7,7,0,0,0,6.45-4.3,6.57,6.57,0,0,0,.41-1.42c2-2.91,7.87-9.87,12.28-15.11s7.66-9.17,10.22-12.35c.23.38.46.77.72,1.14,7.24,10.52,20.42,29.07,25.75,36.56a10,10,0,0,0,8.1,4.21h0a10,10,0,0,0,8.11-4.25c5.19-7.35,17.63-25,25.28-35.77.28-.4.53-.81.79-1.21,2.48,3.06,5.64,6.86,9.68,11.67,4.41,5.25,10.25,12.2,12.28,15.11a6.88,6.88,0,0,0,6.86,5.72,7.19,7.19,0,0,0,5.81-2.93c7.22-7.4,28-29.42,32.17-42.24,2.14-6.56,3.6-16.7,4.57-28.29,5.17,7,11.29,14.25,16.91,20.73.74.84,1.29,1.47,1.6,1.84a7,7,0,0,0,12.13-1.07l.05-.11c1.22-2.6,13-28.09,16.46-41.38,4.11-15.95,7.17-30.66,9.45-44.07,2,1.72,3.86,3.13,5.55,4.41a73.6,73.6,0,0,1,6.82,5.67,12.51,12.51,0,0,0,8.64,3.47h67.89a12.5,12.5,0,0,0,0-25ZM137.54,394a7.11,7.11,0,0,0,.57-1.22A7.21,7.21,0,0,1,137.54,394Zm-4.2-16.49c-3.9-8.87-9.21-21.57-11.16-29.13-12.3-47.78-14.92-84.49-15-106.74a176.24,176.24,0,0,0,36.32,45.81l-.44,58.72a3.4,3.4,0,0,0,3.46,3.38h6.71C151,355.14,144.29,364.51,133.34,377.52ZM222,396.46c-1.95,3.24-9.87,12.67-15.22,19-4.19,5-7.28,8.68-9.55,11.52-10.77-11.57-21.45-24.77-23.55-31.2-2.91-8.91-4.42-26.92-5.14-46.25h5.54a3.47,3.47,0,0,0,3.52-3.38l.38-34.42a177,177,0,0,0,33.82,14l-.28,21.88a2.72,2.72,0,0,0,.86,1.18,4,4,0,0,0,2.62.75h6C221.76,367,222.43,386.89,222,396.46Zm65.51-.85a18,18,0,0,1-3.24,10.33c-6.32,8.91-15.92,22.51-22,31.12-6.28-8.85-16.34-23.05-22.3-31.71a16.65,16.65,0,0,1-2.88-9.39v-46.4h5.63c1.95,0,3.53-.86,3.55-1.93l.28-15.29q7.62.68,15.38.68a176.26,176.26,0,0,0,25.58-1.87Zm62.46.2c-2.19,6.72-13.74,20.6-23.55,31.19-2.27-2.84-5.36-6.53-9.54-11.51-5.35-6.36-13.28-15.79-15.23-19-.09-1.91-.13-4.24-.14-6.87V387.1c.07-17,1.41-44.21,2.22-59.1a177,177,0,0,0,41.09-15.67l.2,33.73a3.49,3.49,0,0,0,3.56,3.38h6.54C354.37,368.82,352.86,386.88,349.94,395.81Zm17.19-116.76a169.09,169.09,0,0,1-198.57,9.27,161.39,161.39,0,0,1-58.83-77.39,152.23,152.23,0,0,1,304.33,0A161.23,161.23,0,0,1,367.13,279.05Zm18.36,113.74a7.11,7.11,0,0,0,.57,1.22A5.94,5.94,0,0,1,385.49,392.79Zm15.92-44.4c-1.94,7.56-7.25,20.26-11.15,29.12-13.21-15.69-18.24-23.84-20-28.07h6a3.44,3.44,0,0,0,3.5-3.38l-1-57.29A176.27,176.27,0,0,0,416.42,242C416.35,264.19,413.69,300.71,401.41,348.39Z"/></g></g></g></svg> \ No newline at end of file
diff --git a/assets/TODO b/assets/TODO
new file mode 100644
index 0000000..9158e24
--- /dev/null
+++ b/assets/TODO
@@ -0,0 +1,15 @@
+keepalive channels per backend?
+Note source in channel value struct
+udp backends may ignore MTU
+make event collectors threadsafe to stop marshalling data...
+collect & check backend API version
+move all connection establishment to _start to be able to hot-stop/start all backends
+event deduplication in core?
+move all typenames to _t
+
+per-channel filters
+ * invert
+ * edge detection
+
+channel discovery / enumeration
+note exit condition/reconnection details for backends
diff --git a/assets/ci-config b/assets/ci-config
new file mode 100644
index 0000000..ac94661
--- /dev/null
+++ b/assets/ci-config
@@ -0,0 +1,73 @@
+#!/usr/bin/env groovy
+
+/*
+ * This Jenkinsfile is intended to run on https://ci.spacecdn.de and may fail anywhere else.
+ * It makes assumptions about plugins being installed, labels mapping to nodes that can build what is needed, etc.
+ */
+
+def buildTypes = ['linux', 'windows']
+def builds = [:]
+
+//if(env.TAG_NAME) {
+// buildTypes.add("debian")
+//}
+
+buildTypes.each{
+ builds["$it"] = {
+ node() {
+ skipDefaultCheckout()
+ stage('Checkout') {
+ checkout scm
+ }
+
+ stage("$it Build"){
+ sh label: "Build", script: "./assets/ci.sh --target=build-$it --deploy"
+ }
+
+ stage('Stash artifacts') {
+ stash includes: "deployment/$it/*", name: "$it", allowEmpty: 'false'
+ }
+ }
+ }
+}
+
+def deploy = {
+ node(){
+ skipDefaultCheckout()
+ stage('Deploy') {
+ buildTypes.each{
+ unstash "$it"
+ }
+ archiveArtifacts artifacts: 'deployment/*/*', onlyIfSuccessful: true, fingerprint: true
+ }
+ }
+}
+
+builds.Test = {
+ node() {
+ skipDefaultCheckout()
+ stage('Checkout') {
+ checkout scm
+ }
+ stage('Test') {
+ catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
+ sh label: "Check Spelling", script: './assets/ci.sh --target=check-spelling'
+ }
+ catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
+ sh label: "Check Codespelling", script: './assets/ci.sh --target=check-codespelling'
+ }
+ catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
+ sh label: "Analyze Complexity", script: './assets/ci.sh --target=analyze-complexity'
+ }
+ catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
+ sh label: "Analyze Shellscripts", script: './assets/ci.sh --target=analyze-shellscript'
+ }
+ catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
+ sh label: "Code Statistics", script: './assets/ci.sh --target=stats'
+ }
+ }
+ }
+}
+
+parallel builds
+deploy.call()
diff --git a/assets/ci.sh b/assets/ci.sh
new file mode 100755
index 0000000..94b8bed
--- /dev/null
+++ b/assets/ci.sh
@@ -0,0 +1,313 @@
+#!/bin/bash
+# shellcheck disable=SC2001,SC2181
+
+################################################ SETUP ################################################
+dep_build_core=(
+ libasound2-dev
+ libevdev-dev
+ liblua5.3-dev
+ libola-dev
+ libjack-jackd2-dev
+ python3-dev
+ libssl-dev
+ build-essential
+ pkg-config
+ git
+)
+
+dep_build_win=(
+ mingw-w64
+)
+
+dep_build_debian=(
+ git-buildpackage
+ debhelper
+)
+
+exitcode="0"
+
+############################################## FUNCTIONS ##############################################
+
+ARGS(){
+ for i in "$@"; do
+ case "$i" in
+ --target=*|-t=*)
+ TARGETS="${i#*=}"
+ ;;
+ --deploy)
+ deploy="1"
+ ;;
+ --deps)
+ install_deps="1"
+ ;;
+ -v|--verbose)
+ verbose="1"
+ ;;
+ -af|--allow-failure)
+ allow_failure="1"
+ ;;
+ -h|--help|*)
+ print_help
+ exit "0"
+ ;;
+ esac
+ shift
+ done
+ [[ -z $TARGETS ]] && print_help && printf "\nNo target specified!\n" && exit "1" # If no target(s) are specified exit.
+}
+
+print_help() {
+ printf "Usage: %s [OPTIONS]\n\n" "$0"
+ printf -- "-t=<argument>, <argument>\t--target=<argument>, <argument>\n\n"
+ printf -- "--deploy\tPackage release/nightly versions to the ./deployment/\$target directory.\n"
+ printf -- "--deps\t\tCheck and install all dependencies needed for the specified target without the need to manualy run the dependency install targets/s.\n"
+ printf -- "-af, --allow-failure\tAlways exit with code 0.\n"
+ printf -- "-v, --verbose\tEnables detailed log output.\n\n"
+ printf "Valid test targets are: \t\"check-spelling\" - \"1\", \"check-codespelling\" - \"2\", \"analyze-complexity\" - \"3\", \"analyze-shellscript\" - \"4\", \"stats\" - \"5\".\n"
+ printf "Valid build targets are: \t\"build-linux\" - \"10\", \"build-windows\" - \"11\", \"build-debian\" - \"12\".\n"
+ printf "Valid dependency install targets are: \t\"deps-linux\", \"deps-windows\", \"deps-debian\", \"deps-osx\" \"deps-tests\", \"deps-all\".\n\n"
+}
+
+install_dependencies(){
+ start_apt update -y -qq > /dev/null || error_handler "There was an error doing apt update."
+ for dependency in "$@"; do
+ if [ "$(dpkg-query -W -f='${Status}' "$dependency" 2>/dev/null | grep -c "ok installed")" -eq 0 ]; then
+ deps+=("$dependency") # Add not installed dependency to the "to be installed array".
+ else
+ [[ -n $verbose ]] && printf "%s already installed!\n" "$dependency" # If the dependency is already installed print it.
+ fi
+ done
+
+if [ ! "${#deps[@]}" -ge "1" ]; then # If nothing needs to get installed don't start apt.
+ [[ -n $verbose ]] && echo "All dependencies are fulfilled." # Dependency array empty! Not running apt!
+else
+ [[ -z $verbose ]] && echo "Starting dependency installation."
+ [[ -n $verbose ]] && echo "Then following dependencies are going to be installed:" # Dependency array contains items. Running apt.
+ [[ -n $verbose ]] && echo "${deps[@]}" | sed 's/ /, /g'
+ start_apt install -y -qq --no-install-suggests --no-install-recommends "${deps[@]}" > /dev/null || error_handler "There was an error doing dependency installation!"
+fi
+ [[ -n $verbose ]] && printf "\n"
+}
+
+start_apt(){
+ i="0"
+ if command -v fuser &> /dev/null; then
+ while fuser /var/lib/dpkg/lock >/dev/null 2>&1 ; do
+ [ "$i" -eq "0" ] && printf "\nWaiting for other software managers to finish"
+ [ "$i" -le "16" ] && printf "." # Print a max of 16 dots if waiting.
+ ((i=i+1))
+ sleep "1s"
+ done
+ [ "$i" -ge "1" ] && printf "ready!\n"
+ fi
+ DEBIAN_FRONTEND=noninteractive apt-get "$@"
+}
+
+# Build targets and corresponding deployment.
+
+build-linux(){
+ [[ -n $install_deps ]] && install_dependencies "${dep_build_core[@]}"
+ make full
+}
+
+build-linux-deploy(){
+ #printf "\nLinux Deployment started..\n"
+ mkdir -p ./deployment/linux/backends
+ mkdir -p ./deployment/linux/docs
+ cp ./midimonster ./deployment/linux/
+ cp ./backends/*.so ./deployment/linux/backends/
+ cp ./monster.cfg ./deployment/linux/monster.cfg
+ cp ./backends/*.md ./deployment/linux/docs/
+ cp -r ./configs ./deployment/linux/
+ cd ./deployment/linux || error_handler "Error doing cd to ./deployment"
+ filename="midimonster-$(git describe)-$OS.tgz"
+ touch "$filename" && tar --exclude=*.tgz -czf "$filename" "./"
+ find . ! -iname "*.zip" ! -iname "*.tgz" -delete
+}
+
+build-windows(){
+ [[ -n $install_deps ]] && install_dependencies "${dep_build_core[@]}" "${dep_build_win[@]}"
+ make windows
+}
+
+build-windows-deploy(){
+ #printf "\nWindows Deployment started..\n"
+ mkdir -p ./deployment/windows/backends
+ mkdir -p ./deployment/windows/docs
+ strip midimonster.exe backends/*.dll # Strip the Windows binaries as they become huge quickly.
+ cp ./midimonster.exe ./deployment/windows/
+ cp ./backends/*.dll ./deployment/windows/backends/
+ cp ./backends/*.dll.disabled ./deployment/windows/backends/
+ cp ./monster.cfg ./deployment/windows/monster.cfg
+ cp ./backends/*.md ./deployment/windows/docs/
+ cp -r ./configs ./deployment/windows/
+ cd ./deployment/windows || error_handler "Error doing cd to ./deployment/windows"
+ zip -r "./midimonster-$(git describe)-windows.zip" "./"
+ find . ! -iname "*.zip" ! -iname "*.tgz" -delete
+}
+
+build-debian(){
+ [[ -n $install_deps ]] && install_dependencies "${dep_build_core[@]}" "${dep_build_debian[@]}"
+ git checkout debian/master
+ gbp buildpackage
+}
+
+build-debian-deploy(){
+ #printf "\nDebian Package Deployment started..\n"
+ mkdir -p ./deployment/debian/
+ cp ./*.deb ./deployment/debian/
+}
+
+# Tests
+
+ckeck-spelling(){ # Check spelling.
+ [[ -n $install_deps ]] && install_dependencies "lintian"
+ spellcheck_files=$(find . -type f | grep -v ".git/") # Create list of files to be spellchecked.
+ sl_results=$(xargs spellintian 2>&1 <<< "$spellcheck_files") # Run spellintian to find spelling errors
+ sl_errors=$(wc -l <<< "$sl_results")
+ sl_errors_dups=$( (grep -c "\(duplicate word\)") <<< "$sl_results")
+ sl_errors_nodups=$( (grep -cv "\(duplicate word\)") <<< "$sl_results")
+
+ if [ "$sl_errors" -gt "1" ]; then
+ printf "Spellintian found %s errors (%s spelling, %s duplicate words):\n\n" "$sl_errors" "$sl_errors_nodups" "$sl_errors_dups"
+ printf "%s\n\n" "$sl_results"
+ exitcode=1
+ else
+ printf "Spellintian reports no errors\n"
+ fi
+}
+
+check-codespelling(){ # Check code for common misspellings.
+ [[ -n $install_deps ]] && install_dependencies "codespell"
+ spellcheck_files=$(find . -type f | grep -v ".git/") # Create list of files to be spellchecked.
+ cs_results=$(xargs codespell --quiet 2 <<< "$spellcheck_files" 2>&1)
+ cs_errors=$(wc -l <<< "$cs_results")
+ if [ "$cs_errors" -gt "1" ]; then
+ printf "Codespell found %s errors:\n\n" "$cs_errors"
+ printf "%s\n\n" "$cs_results"
+ exitcode=1
+ else
+ printf "Codespell reports no errors\n"
+ fi
+}
+
+analyze-complexity(){ # code complexity analyser.
+ [[ -n $install_deps ]] && install_dependencies "python3" "python3-pip"
+ if [ -z "$(which ~/.local/bin/lizard)" ]; then
+ printf "Installing lizard...\n"
+ pip3 install lizard >/dev/null
+ fi
+ printf "Running lizard for code complexity analysis\n"
+ ~/.local/bin/lizard ./
+ if [ "$?" -ne "0" ]; then
+ exitcode=1
+ fi
+}
+
+analyze-shellscript(){ # Shellscript analysis tool.
+ [[ -n $install_deps ]] && install_dependencies "shellcheck"
+ printf "Running shellcheck:\n"
+ shell_files="$(find . -type f -iname \*.sh)"
+ xargs shellcheck -Cnever -s bash <<< "$shell_files"
+ if [ "$?" -ne "0" ]; then
+ exitcode=1
+ fi
+}
+
+stats(){ # Code statistics.
+ [[ -n $install_deps ]] && install_dependencies "cloc"
+ printf "Code statistics:\n"
+ cloc ./
+}
+
+target_queue(){
+ printf "\n"
+ IFS=',|.' read -ra Queue <<< "$TARGETS"
+ for i in "${Queue[@]}"; do
+ case "$i" in
+ check-spelling|1)
+ ckeck-spelling
+ ;;
+ check-codespelling|2)
+ check-codespelling
+ ;;
+ analyze-complexity|3)
+ analyze-complexity
+ ;;
+ analyze-shellscript|4)
+ analyze-shellscript
+ ;;
+ stats|5)
+ stats
+ ;;
+ build-linux|10)
+ OS="linux"
+ build-linux
+ [[ -n $deploy ]] && build-linux-deploy # Deploy build artifacts if the deploy flag is set.
+ ;;
+ build-windows|build-win|11)
+ build-windows
+ [[ -n $deploy ]] && build-windows-deploy # Deploy build artifacts if the deploy flag is set.
+ ;;
+ build-debian|build-deb|12)
+ build-debian
+ [[ -n $deploy ]] && build-debian-deploy # Deploy build artifacts if the deploy flag is set.
+ ;;
+ build-osx|13)
+ OS="osx"
+ printf "\nNot implemented yet!\n"
+ #build-linux
+ #[[ -n $deploy ]] && build-linux-deploy # Deploy build artifacts if the deploy flag is set.
+ ;;
+ deps-linux)
+ # Target to install all needed dependencies for linux builds.
+ install_dependencies "${dep_build_core[@]}"
+ ;;
+ deps-windows|deps-win)
+ # Target to install all needed dependencies for windows builds.
+ install_dependencies "${dep_build_core[@]}" "${dep_build_win[@]}"
+ ;;
+ deps-debian|deps-deb)
+ # Target to install all needed dependencies for debian packaging.
+ install_dependencies "${dep_build_core[@]}" "${dep_build_debian[@]}"
+ ;;
+ deps-osx)
+ # Target to install all needed dependencies for osx.
+ printf "\nNot implemented yet!\n"
+ ;;
+ deps-tests)
+ install_dependencies "lintian" "codespell" "python3" "python3-pip" "shellcheck" "cloc"
+ # Install lizard if not found.
+ if [ -z "$(which ~/.local/bin/lizard)" ]; then
+ pip3 install lizard >/dev/null
+ fi
+ ;;
+ deps-all)
+ # Target to install all needed dependencies for this ci script.
+ install_dependencies "${dep_build_core[@]}" "${dep_build_win[@]}" "${dep_build_debian[@]}" "lintian" "codespell" "python3" "python3-pip" "shellcheck" "cloc"
+ ;;
+ *)
+ printf "Target '%s' not valid!\n" "$i"
+ ;;
+ esac
+ printf "\n"
+ done
+}
+
+error_handler(){
+ [[ -n $1 ]] && printf "\n%s\n" "$1"
+ printf "\nAborting"
+ for i in {1..3}; do sleep 0.3s && printf "." && sleep 0.2s; done
+ printf "\n"
+ exit "1"
+}
+
+################################################ Main #################################################
+trap error_handler SIGINT SIGTERM
+
+ARGS "$@" # Parse arguments.
+target_queue # Start requestet targets.
+
+# Allow failure handler.
+[[ -z $allow_failure ]] && exit "$exitcode"
+exit "0" \ No newline at end of file
diff --git a/assets/midimonster.1 b/assets/midimonster.1
new file mode 100644
index 0000000..44c414e
--- /dev/null
+++ b/assets/midimonster.1
@@ -0,0 +1,42 @@
+.TH MIDIMONSTER 1 "December 2019"
+.SH NAME
+midimonster \- Multi-protocol translation tool
+.SH SYNOPSIS
+.B midimonster
+.I config-file
+.RB [ "-i"
+.IR instance.option=value ]
+.RB [ "-b"
+.IR backend.option=value ]
+
+.B midimonster -v
+.SH DESCRIPTION
+.B MIDIMonster
+allows the user to translate any channel on one supported protocol into channel(s)
+on any other (or the same) supported protocol.
+.SH OPTIONS
+.TP
+.I config-file
+The configuration file to read. If not specified, a default configuration file is read.
+
+.TP
+.BI "-i " instance.option=value
+Supply an additional instance configuration option
+.IR option " for " instance "."
+Command-line overrides are applied when the instance is first mentioned in the configuration file.
+
+.TP
+.BI "-b " backend.option=value
+Supply an additional backend configuration option
+.IR option " to " backend "."
+Command-line overrides are applied when the backend is first mentioned in the configuration file.
+
+.B -v
+Display version information
+.SH "SEE ALSO"
+Online documentation and repository at https://github.com/cbdevnet/midimonster
+
+For more and in-depth information see the homepage at https://midimonster.net/
+as well as the knowledge base at https://kb.midimonster.net/
+.SH AUTHOR
+Fabian "cbdev" Stumpf <fjs at fabianstumpf dot de>
diff --git a/assets/midimonster.ico b/assets/midimonster.ico
new file mode 100644
index 0000000..9391160
--- /dev/null
+++ b/assets/midimonster.ico
Binary files differ
diff --git a/assets/midimonster.rc b/assets/midimonster.rc
new file mode 100644
index 0000000..45a88aa
--- /dev/null
+++ b/assets/midimonster.rc
@@ -0,0 +1,22 @@
+#include "midimonster.h"
+
+0 ICON "midimonster.ico"
+1 VERSIONINFO
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "CompanyName", "control8r"
+ VALUE "FileDescription", "MIDIMonster"
+ VALUE "InternalName", "MIDIMonster Core (Windows Build)"
+ VALUE "FileVersion", MIDIMONSTER_VERSION
+ VALUE "OriginalFilename", "midimonster.exe"
+ VALUE "ProductName", "MIDIMonster"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0409, 1252
+ END
+END