diff --git a/.mailmap b/.mailmap index 0ff7c15dd..7628795f9 100644 --- a/.mailmap +++ b/.mailmap @@ -1,5 +1,5 @@ Alexandre Almeida -Tobias Doerffel +Tobias Junghans Dave French Paul Giblock Paul Giblock diff --git a/CMakeLists.txt b/CMakeLists.txt index b82076c0b..88aefadae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,7 @@ SET(PROJECT_COPYRIGHT "2008-${PROJECT_YEAR} ${PROJECT_AUTHOR}") SET(VERSION_MAJOR "1") SET(VERSION_MINOR "2") SET(VERSION_RELEASE "0") -SET(VERSION_STAGE "rc6") +SET(VERSION_STAGE "rc7") SET(VERSION_BUILD "0") SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE}") IF(VERSION_STAGE) diff --git a/cmake/apple/CMakeLists.txt b/cmake/apple/CMakeLists.txt index ff1a8ea46..835d886b9 100644 --- a/cmake/apple/CMakeLists.txt +++ b/cmake/apple/CMakeLists.txt @@ -1,4 +1,4 @@ -SET(MACOSX_BUNDLE_ICON_FILE "lmms.icns") +SET(MACOSX_BUNDLE_ICON_FILE "icon.icns") SET(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_NAME_UCASE}") SET(MACOSX_BUNDLE_LONG_VERSION_STRING "${VERSION}") SET(MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME_UCASE}") diff --git a/cmake/apple/icon.icns b/cmake/apple/icon.icns new file mode 100644 index 000000000..3ee7857f4 Binary files /dev/null and b/cmake/apple/icon.icns differ diff --git a/cmake/apple/lmms.icns b/cmake/apple/lmms.icns deleted file mode 100644 index e54187b5c..000000000 Binary files a/cmake/apple/lmms.icns and /dev/null differ diff --git a/cmake/apple/project.icns b/cmake/apple/project.icns index 930afc217..9ae58d7fb 100644 Binary files a/cmake/apple/project.icns and b/cmake/apple/project.icns differ diff --git a/cmake/linux/CMakeLists.txt b/cmake/linux/CMakeLists.txt index 45f0e5e7a..27c6655eb 100644 --- a/cmake/linux/CMakeLists.txt +++ b/cmake/linux/CMakeLists.txt @@ -1,5 +1,4 @@ -INSTALL(FILES lmms.svg DESTINATION "${DATA_DIR}/icons/hicolor/scalable/apps") -INSTALL(FILES project.svg DESTINATION "${DATA_DIR}/icons/hicolor/scalable/mimetypes/" RENAME "application-x-lmms-project.svg") +INSTALL(DIRECTORY icons/ DESTINATION "${DATA_DIR}/icons/hicolor") INSTALL(FILES lmms.desktop DESTINATION "${DATA_DIR}/applications") INSTALL(FILES lmms.xml DESTINATION "${DATA_DIR}/mime/packages") diff --git a/cmake/linux/icons/128x128/apps/lmms.png b/cmake/linux/icons/128x128/apps/lmms.png new file mode 100644 index 000000000..7bad96f98 Binary files /dev/null and b/cmake/linux/icons/128x128/apps/lmms.png differ diff --git a/cmake/linux/icons/128x128/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/128x128/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..7a016d0ed Binary files /dev/null and b/cmake/linux/icons/128x128/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/128x128@2/apps/lmms.png b/cmake/linux/icons/128x128@2/apps/lmms.png new file mode 100644 index 000000000..a75f1b237 Binary files /dev/null and b/cmake/linux/icons/128x128@2/apps/lmms.png differ diff --git a/cmake/linux/icons/128x128@2/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/128x128@2/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..e7dbe591f Binary files /dev/null and b/cmake/linux/icons/128x128@2/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/16x16/apps/lmms.png b/cmake/linux/icons/16x16/apps/lmms.png new file mode 100644 index 000000000..7148c9373 Binary files /dev/null and b/cmake/linux/icons/16x16/apps/lmms.png differ diff --git a/cmake/linux/icons/16x16/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/16x16/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..b3ef2151e Binary files /dev/null and b/cmake/linux/icons/16x16/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/16x16@2/apps/lmms.png b/cmake/linux/icons/16x16@2/apps/lmms.png new file mode 100644 index 000000000..f6ca1cb29 Binary files /dev/null and b/cmake/linux/icons/16x16@2/apps/lmms.png differ diff --git a/cmake/linux/icons/16x16@2/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/16x16@2/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..d4b20ae01 Binary files /dev/null and b/cmake/linux/icons/16x16@2/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/24x24/apps/lmms.png b/cmake/linux/icons/24x24/apps/lmms.png new file mode 100644 index 000000000..988da8872 Binary files /dev/null and b/cmake/linux/icons/24x24/apps/lmms.png differ diff --git a/cmake/linux/icons/24x24/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/24x24/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..548660bb2 Binary files /dev/null and b/cmake/linux/icons/24x24/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/24x24@2/apps/lmms.png b/cmake/linux/icons/24x24@2/apps/lmms.png new file mode 100644 index 000000000..76d9e5b9b Binary files /dev/null and b/cmake/linux/icons/24x24@2/apps/lmms.png differ diff --git a/cmake/linux/icons/24x24@2/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/24x24@2/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..a8bbf9d01 Binary files /dev/null and b/cmake/linux/icons/24x24@2/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/32x32/apps/lmms.png b/cmake/linux/icons/32x32/apps/lmms.png new file mode 100644 index 000000000..5f67ceb1d Binary files /dev/null and b/cmake/linux/icons/32x32/apps/lmms.png differ diff --git a/cmake/linux/icons/32x32/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/32x32/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..9aabbde82 Binary files /dev/null and b/cmake/linux/icons/32x32/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/32x32@2/apps/lmms.png b/cmake/linux/icons/32x32@2/apps/lmms.png new file mode 100644 index 000000000..4504c4a66 Binary files /dev/null and b/cmake/linux/icons/32x32@2/apps/lmms.png differ diff --git a/cmake/linux/icons/32x32@2/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/32x32@2/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..87ca938aa Binary files /dev/null and b/cmake/linux/icons/32x32@2/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/48x48/apps/lmms.png b/cmake/linux/icons/48x48/apps/lmms.png new file mode 100644 index 000000000..4b2c9fc87 Binary files /dev/null and b/cmake/linux/icons/48x48/apps/lmms.png differ diff --git a/cmake/linux/icons/48x48/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/48x48/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..4ea287a9b Binary files /dev/null and b/cmake/linux/icons/48x48/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/48x48@2/apps/lmms.png b/cmake/linux/icons/48x48@2/apps/lmms.png new file mode 100644 index 000000000..af2c5eda2 Binary files /dev/null and b/cmake/linux/icons/48x48@2/apps/lmms.png differ diff --git a/cmake/linux/icons/48x48@2/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/48x48@2/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..c583535d6 Binary files /dev/null and b/cmake/linux/icons/48x48@2/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/64x64/apps/lmms.png b/cmake/linux/icons/64x64/apps/lmms.png new file mode 100644 index 000000000..52b25564f Binary files /dev/null and b/cmake/linux/icons/64x64/apps/lmms.png differ diff --git a/cmake/linux/icons/64x64/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/64x64/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..96bfae222 Binary files /dev/null and b/cmake/linux/icons/64x64/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/64x64@2/apps/lmms.png b/cmake/linux/icons/64x64@2/apps/lmms.png new file mode 100644 index 000000000..9e9403a22 Binary files /dev/null and b/cmake/linux/icons/64x64@2/apps/lmms.png differ diff --git a/cmake/linux/icons/64x64@2/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/64x64@2/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..7a016d0ed Binary files /dev/null and b/cmake/linux/icons/64x64@2/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/scalable/apps/lmms.svg b/cmake/linux/icons/scalable/apps/lmms.svg new file mode 100644 index 000000000..fc0867aa6 --- /dev/null +++ b/cmake/linux/icons/scalable/apps/lmms.svg @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/cmake/linux/icons/scalable/mimetypes/application-x-lmms-project.svg b/cmake/linux/icons/scalable/mimetypes/application-x-lmms-project.svg new file mode 100644 index 000000000..29697ece8 --- /dev/null +++ b/cmake/linux/icons/scalable/mimetypes/application-x-lmms-project.svg @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/cmake/linux/lmms.png b/cmake/linux/lmms.png deleted file mode 100644 index ae9fe6a2a..000000000 Binary files a/cmake/linux/lmms.png and /dev/null differ diff --git a/cmake/linux/lmms.svg b/cmake/linux/lmms.svg deleted file mode 100644 index ffe6976ce..000000000 --- a/cmake/linux/lmms.svg +++ /dev/null @@ -1,1540 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cmake/linux/package_linux.sh.in b/cmake/linux/package_linux.sh.in index 31fa8ad53..7c3a4cf3b 100644 --- a/cmake/linux/package_linux.sh.in +++ b/cmake/linux/package_linux.sh.in @@ -102,7 +102,7 @@ cat >"${APPDIR}usr/bin/lmms" < /dev/null 2>&1; then - CARLAPATH="$(which carla)" + CARLAPATH="\$(which carla)" CARLAPREFIX="\${CARLAPATH%/bin*}" echo "Carla appears to be installed on this system at \$CARLAPREFIX/lib[64]/carla so we'll use it." export LD_LIBRARY_PATH=\$CARLAPREFIX/lib/carla:\$CARLAPREFIX/lib64/carla:\$LD_LIBRARY_PATH diff --git a/cmake/linux/project.svg b/cmake/linux/project.svg deleted file mode 100644 index 62888e277..000000000 --- a/cmake/linux/project.svg +++ /dev/null @@ -1,1912 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mmpz - - - - mmpz - mmpz - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cmake/modules/BashCompletion.cmake b/cmake/modules/BashCompletion.cmake new file mode 100644 index 000000000..0dc016178 --- /dev/null +++ b/cmake/modules/BashCompletion.cmake @@ -0,0 +1,92 @@ +# A wrapper around pkg-config-provided and cmake-provided bash completion that +# will have dynamic behavior at INSTALL() time to allow both root-level +# INSTALL() as well as user-level INSTALL(). +# +# See also https://github.com/scop/bash-completion +# +# Copyright (c) 2018, Tres Finocchiaro, +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# +# Usage: +# INCLUDE(BashCompletion) +# BASHCOMP_INSTALL(foo) +# ... where "foo" is a shell script adjacent to the CMakeLists.txt +# +# How it determines BASHCOMP_PKG_PATH, in order: +# 1. Uses BASHCOMP_PKG_PATH if already set (e.g. -DBASHCOMP_PKG_PATH=...) +# a. If not, uses pkg-config's PKG_CHECK_MODULES to determine path +# b. Fallback to cmake's FIND_PACKAGE(bash-completion) path +# c. Fallback to hard-coded /usr/share/bash-completion/completions +# 2. Final fallback to ${CMAKE_INSTALL_PREFIX}/share/bash-completion/completions if +# detected path is unwritable. + +# - Windows does not support bash completion +# - macOS support should eventually be added for Homebrew (TODO) +IF(WIN32) + MESSAGE(STATUS "Bash competion is not supported on this platform.") +ELSEIF(APPLE) + MESSAGE(STATUS "Bash completion is not yet implemented for this platform.") +ELSE() + INCLUDE(FindUnixCommands) + # Honor manual override if provided + IF(NOT BASHCOMP_PKG_PATH) + # First, use pkg-config, which is the most reliable + FIND_PACKAGE(PkgConfig QUIET) + IF(PKGCONFIG_FOUND) + PKG_CHECK_MODULES(BASH_COMPLETION bash-completion) + PKG_GET_VARIABLE(BASHCOMP_PKG_PATH bash-completion completionsdir) + ELSE() + # Second, use cmake (preferred but less common) + FIND_PACKAGE(bash-completion QUIET) + IF(BASH_COMPLETION_FOUND) + SET(BASHCOMP_PKG_PATH "${BASH_COMPLETION_COMPLETIONSDIR}") + ENDIF() + ENDIF() + + # Third, use a hard-coded fallback value + IF("${BASHCOMP_PKG_PATH}" STREQUAL "") + SET(BASHCOMP_PKG_PATH "/usr/share/bash-completion/completions") + ENDIF() + ENDIF() + + # Always provide a fallback for non-root INSTALL() + SET(BASHCOMP_USER_PATH "${CMAKE_INSTALL_PREFIX}/share/bash-completion/completions") + + # Cmake doesn't allow easy use of conditional logic at INSTALL() time + # this is a problem because ${BASHCOMP_PKG_PATH} may not be writable and we + # need sane fallback behavior for bundled INSTALL() (e.g. .AppImage, etc). + # + # The reason this can't be detected by cmake is that it's fairly common to + # run "cmake" as a one user (i.e. non-root) and "make install" as another user + # (i.e. root). + # + # - Creates a script called "install_${SCRIPT_NAME}_completion.sh" into the + # working binary directory and invokes this script at install. + # - Script handles INSTALL()-time conditional logic for sane ballback behavior + # when ${BASHCOMP_PKG_PATH} is unwritable (i.e. non-root); Something cmake + # can't handle on its own at INSTALL() time) + MACRO(BASHCOMP_INSTALL SCRIPT_NAME) + # A shell script for wrapping conditionl logic + SET(BASHCOMP_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/install_${SCRIPT_NAME}_completion.sh") + + FILE(WRITE ${BASHCOMP_SCRIPT} "\ +#!${BASH}\n\ +set -e\n\ +BASHCOMP_PKG_PATH=\"${BASHCOMP_USER_PATH}\"\n\ +if [ -w \"${BASHCOMP_PKG_PATH}\" ]; then\n\ + BASHCOMP_PKG_PATH=\"${BASHCOMP_PKG_PATH}\"\n\ +fi\n\ +echo -e \"\\nInstalling bash completion...\\n\"\n\ +mkdir -p \"\$BASHCOMP_PKG_PATH\"\n\ +cp \"${CMAKE_CURRENT_SOURCE_DIR}/${SCRIPT_NAME}\" \"\$BASHCOMP_PKG_PATH\"\n\ +chmod a+r \"\$BASHCOMP_PKG_PATH/${SCRIPT_NAME}\"\n\ +echo -e \"Bash completion for ${SCRIPT_NAME} has been installed to \$BASHCOMP_PKG_PATH/${SCRIPT_NAME}\"\n\ +") + INSTALL(CODE "EXECUTE_PROCESS(COMMAND chmod u+x \"install_${SCRIPT_NAME}_completion.sh\" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} )") + INSTALL(CODE "EXECUTE_PROCESS(COMMAND \"./install_${SCRIPT_NAME}_completion.sh\" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} )") + + MESSAGE(STATUS "Bash completion script for ${SCRIPT_NAME} will be installed to ${BASHCOMP_PKG_PATH} or fallback to ${BASHCOMP_USER_PATH} if unwritable.") + ENDMACRO() +ENDIF() + diff --git a/cmake/nsis/CMakeLists.txt b/cmake/nsis/CMakeLists.txt index a19555a19..ac628d549 100644 --- a/cmake/nsis/CMakeLists.txt +++ b/cmake/nsis/CMakeLists.txt @@ -2,7 +2,7 @@ SET(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/cmake/nsis/nsis_bra IF(MSVC) STRING(REPLACE "/" "\\\\" CPACK_PACKAGE_ICON ${CPACK_PACKAGE_ICON}) ENDIF(MSVC) -SET(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/cmake/nsis/lmms.ico") +SET(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/cmake/nsis/icon.ico") SET(CPACK_NSIS_INSTALLED_ICON_NAME "${CMAKE_PROJECT_NAME}.exe" PARENT_SCOPE) SET(CPACK_NSIS_DISPLAY_NAME "${PROJECT_NAME_UCASE} ${VERSION}" PARENT_SCOPE) SET(CPACK_NSIS_HELP_LINK "${PROJECT_URL}" PARENT_SCOPE) @@ -75,3 +75,5 @@ IF(LMMS_HAVE_STK) ENDIF() INSTALL(FILES "lmms.exe.manifest" DESTINATION .) +INSTALL(FILES "lmms.VisualElementsManifest.xml" DESTINATION .) +INSTALL(DIRECTORY "assets" DESTINATION .) diff --git a/cmake/nsis/FileAssociation.nsh b/cmake/nsis/FileAssociation.nsh index 061df6c4f..2ae430504 100644 --- a/cmake/nsis/FileAssociation.nsh +++ b/cmake/nsis/FileAssociation.nsh @@ -129,6 +129,7 @@ NoBackup: WriteRegStr HKCR "$R0" "" "$R0" WriteRegStr HKCR "$R0\shell" "" "open" Skip: + WriteRegStr HKCR "$R0\DefaultIcon" "" "$R2,1" WriteRegStr HKCR "$R0\shell\open\command" "" '"$R2" "%1"' WriteRegStr HKCR "$R0\shell\edit" "" "Edit $R0" WriteRegStr HKCR "$R0\shell\edit\command" "" '"$R2" "%1"' diff --git a/cmake/nsis/assets/Logo.png b/cmake/nsis/assets/Logo.png new file mode 100644 index 000000000..e1566b218 Binary files /dev/null and b/cmake/nsis/assets/Logo.png differ diff --git a/cmake/nsis/assets/SmallLogo.png b/cmake/nsis/assets/SmallLogo.png new file mode 100644 index 000000000..23d44ee28 Binary files /dev/null and b/cmake/nsis/assets/SmallLogo.png differ diff --git a/cmake/nsis/icon.ico b/cmake/nsis/icon.ico new file mode 100644 index 000000000..96125a1bb Binary files /dev/null and b/cmake/nsis/icon.ico differ diff --git a/cmake/nsis/lmms.VisualElementsManifest.xml b/cmake/nsis/lmms.VisualElementsManifest.xml new file mode 100644 index 000000000..6bda439b0 --- /dev/null +++ b/cmake/nsis/lmms.VisualElementsManifest.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/cmake/nsis/lmms.ico b/cmake/nsis/lmms.ico deleted file mode 100644 index 9ee65b86d..000000000 Binary files a/cmake/nsis/lmms.ico and /dev/null differ diff --git a/cmake/nsis/lmms.rc.in b/cmake/nsis/lmms.rc.in index f153ee235..a3723b20d 100644 --- a/cmake/nsis/lmms.rc.in +++ b/cmake/nsis/lmms.rc.in @@ -1,4 +1,5 @@ -lmmsicon ICON cmake/nsis/lmms.ico +lmmsicon ICON cmake/nsis/icon.ico +lmmsprojecticon ICON cmake/nsis/project.ico #include VS_VERSION_INFO VERSIONINFO diff --git a/cmake/nsis/nsis_branding.bmp b/cmake/nsis/nsis_branding.bmp index a7e75e3c1..939f2ebab 100644 Binary files a/cmake/nsis/nsis_branding.bmp and b/cmake/nsis/nsis_branding.bmp differ diff --git a/cmake/nsis/project.ico b/cmake/nsis/project.ico new file mode 100644 index 000000000..4b994f321 Binary files /dev/null and b/cmake/nsis/project.ico differ diff --git a/data/locale/de.ts b/data/locale/de.ts index e6a1dafd5..ce57aa6c4 100644 --- a/data/locale/de.ts +++ b/data/locale/de.ts @@ -515,7 +515,7 @@ Wenn Sie daran interessiert sind LMMS in eine andere Sprache zu übersetzen oder AutomationPattern Drag a control while pressing <%1> - Ein Steuerelement mit <Strg> hier her ziehen + Ein Steuerelement mit <%1> hier her ziehen @@ -6133,7 +6133,7 @@ Grund: »%2« Mute/unmute (<%1> + middle click) - Stumm/Laut schalten (<Strg> + Mittelklick) + Stumm/Laut schalten (<%1> + Mittelklick) @@ -6968,7 +6968,7 @@ Bitte stellen Sie sicher, dass Sie Leserechte auf diese Datei sowie das Verzeich Mute/unmute (<%1> + middle click) - Stumm/Laut schalten (<Strg> + Mittelklick) + Stumm/Laut schalten (<%1> + Mittelklick) diff --git a/data/themes/classic/icon_small.png b/data/themes/classic/icon_small.png new file mode 100644 index 000000000..522290061 Binary files /dev/null and b/data/themes/classic/icon_small.png differ diff --git a/data/themes/default/icon.png b/data/themes/default/icon.png index ae9fe6a2a..ec881aacf 100644 Binary files a/data/themes/default/icon.png and b/data/themes/default/icon.png differ diff --git a/data/themes/default/icon_small.png b/data/themes/default/icon_small.png new file mode 100644 index 000000000..fd74011f9 Binary files /dev/null and b/data/themes/default/icon_small.png differ diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 7aca74d87..859c5f2c6 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -15,3 +15,6 @@ if(DOXYGEN_FOUND) COMMENT "Generating API documentation with Doxygen" SOURCES Doxyfile.in) endif(DOXYGEN_FOUND) + +ADD_SUBDIRECTORY(bash-completion) + diff --git a/doc/bash-completion/CMakeLists.txt b/doc/bash-completion/CMakeLists.txt new file mode 100644 index 000000000..783e13a71 --- /dev/null +++ b/doc/bash-completion/CMakeLists.txt @@ -0,0 +1,4 @@ +INCLUDE(BashCompletion) +IF(COMMAND BASHCOMP_INSTALL) + BASHCOMP_INSTALL(lmms) +ENDIF() diff --git a/doc/bash-completion/lmms b/doc/bash-completion/lmms new file mode 100644 index 000000000..19fbf4723 --- /dev/null +++ b/doc/bash-completion/lmms @@ -0,0 +1,334 @@ +# lmms(1) completion -*- shell-script -*- +# use shellcheck: "shellcheck -e bash " + +_lmms_array_contains () +{ + local e match="$1" + shift + for e; do [[ "$e" == "$match" ]] && return 0; done + return 1 +} + +_lmms_long_param_of() +{ + case "$1" in + -a) + echo "float" + ;; + -b) + echo "bitrate" + ;; + -c) + echo "config" + ;; + -f) + echo "format" + ;; + -i) + echo "interpolation" + ;; + -l) + echo "loop" + ;; + -m) + echo "mode" + ;; + -o) + echo "output" + ;; + -p) + echo "profile" + ;; + -s) + echo "samplerate" + ;; + -x) + echo "oversampling" + ;; + *) + echo "" + ;; + esac +} + +_lmms_conv_old_action () +{ + case "$1" in + -d|--dump) + echo "dump" + ;; + -r|--render) + echo "render" + ;; + --rendertracks) + echo "rendertracks" + ;; + -u|--upgrade) + echo "upgrade" + ;; + *) + echo "" + ;; + esac +} + +_lmms() +{ + local cword=$COMP_CWORD + local cur="${COMP_WORDS[COMP_CWORD]}" + + # call routine provided by bash-completion + _init_completion || return + + local params filemode filetypes + local i # counter variable + local pars_global pars_noaction pars_render actions shortargs + pars_global=(--allowroot --config --help --version) + pars_noaction=(--geometry --import) + pars_render=(--float --bitrate --format --interpolation) + pars_render+=(--loop --mode --output --profile) + pars_render+=(--samplerate --oversampling) + actions=(dump render rendertracks upgrade) + actions_old=(-d --dump -r --render --rendertracks -u --upgrade) + shortargs+=(-a -b -c -f -h -i -l -m -o -p -s -v -x) + + local prev prev2 + if [ "$cword" -gt 1 ] + then + prev=${COMP_WORDS[cword-1]} + fi + if [ "$cword" -gt 2 ] + then + prev2=${COMP_WORDS[cword-2]} + fi + + # don't show shortargs, but complete them when entered + if [[ $cur =~ ^-[^-]$ ]] + then + if _lmms_array_contains "$cur" "${shortargs[@]}" + then + COMPREPLY=( "$cur" ) + fi + return + fi + + # + # please keep those in order like def_pars_args above + # + case $prev in + --bitrate|-b) + params="64 96 128 160 192 256 320" + ;; + --config|-c) + filetypes='xml' + filemode='existing_files' + ;; + --format|-f) + params='wav ogg mp3' + ;; + --geometry) + # we can not name all possibilities, but this helps the user + # by showing them how the format is + params='0x0+0+0' + ;; + --interpolation|-i) + params='linear sincfastest sincmedium sincbest' + ;; + --import) + filetypes='mid|midi|MID|MIDI|rmi|RMI|h2song|H2SONG' + filemode='existing_files' + ;; + --mode|-m) + params='s j m' + ;; + --output|-o) + # default assumption: could be both + local render=1 rendertracks=1 + for i in "${!COMP_WORDS[@]}" + do + if [[ ${COMP_WORDS[i]} =~ ^(render|-r|--render)$ ]] + then + rendertracks= + elif [[ ${COMP_WORDS[i]} =~ ^(rendertracks|--rendertracks)$ ]] + then + render= + fi + done + if [ "$rendertracks" ] + then + filemode='existing_directories' + fi + if [ "$render" ] + then + # filemode files is a superset of "existing directories" + # so it's OK to overwrite the filemode='existing_directories' + # from above + filetypes='wav|ogg|mp3' + filemode='files' + fi + ;; + --profile|-p) + filemode='files' + ;; + --samplerate|-s) + # these are the ones suggested for zyn + # if you think more are required, + # remove this comment and write a justification + params='44100 48000 96000 192000' + ;; + --oversampling|-x) + params='1 2 4 8' + ;; + *) + local action_found + + # Is an action specified? + if [ "$cword" -gt 1 ] + then + local wrd + for wrd in "${COMP_WORDS[@]}" + do + # action named explicitly? + if _lmms_array_contains "$wrd" "${actions[@]}" + then + action_found=$wrd + break + # deprecated action name? + elif _lmms_array_contains "$wrd" "${actions_old[@]}" + then + action_found="$(_lmms_conv_old_action "$wrd")" + break + # no-action params found? + elif _lmms_array_contains "$wrd" "${pars_noaction[@]}" + then + action_found=none + break + fi + done + fi + + if [[ $prev =~ -e|--help|-h|-version|-v ]] + then + # the -e flag (from --import) and help/version + # always mark the end of arguments + return + fi + + if [[ "$action_found" =~ dump|none|^$ ]] && [[ $prev =~ \.mmpz? ]] + then + # mmp(z) mark the end of arguments for those actions + return + fi + + local savefiletypes='mmpz|mmp' + local params_array + + # find parameters/filetypes/dirtypes depending on actions + if ! [ "$action_found" ] + then + params_array=( "${actions[@]}" "${pars_global[@]}" "${pars_noaction[@]}") + filemode="existing_files" + filetypes="$savefiletypes" + elif [ "$action_found" == "none" ] + then + params_array=( "${pars_noaction[@]}" ) + filemode="existing_files" + filetypes="$savefiletypes" + elif [ "$action_found" == "dump" ] + then + filemode="existing_files" + filetypes="mmpz" + elif [ "$action_found" == "upgrade" ] + then + if [ "$prev" == "upgrade" ] + then + filemode="existing_files" + filetypes="$savefiletypes" + elif [ "$prev2" == "upgrade" ] + then + filemode="files" + filetypes="$savefiletypes" + fi + elif [[ "$action_found" =~ render(tracks)? ]] + then + if [[ "$prev" =~ render(tracks)? ]] + then + filemode="existing_files" + filetypes="$savefiletypes" + else + params_array=( "${pars_render[@]}" ) + fi + fi + + # add params_array to params, but also check the history of comp words + local param + for param in "${params_array[@]}" + do + local do_append=1 + for i in "${!COMP_WORDS[@]}" + do + if [ "$i" -ne 0 ] && [ "$i" -ne "$cword" ] + then + # disallow double long parameters + if [ "${COMP_WORDS[$i]}" == "$param" ] + then + do_append= + # disallow double short parameters + elif [ "--$(_lmms_long_param_of "${COMP_WORDS[$i]}")" == "$param" ] + then + do_append= + # --help or --version must be the first parameters + elif [ "$cword" -gt 1 ] && [[ $param =~ --help|--version ]] + then + do_append= + fi + fi + done + if [ "$do_append" ] + then + params+="$param " + fi + done + ;; + esac + + case $filemode in + + # use completion routine provided by bash-completion + # to fill $COMPREPLY + + existing_files) + _filedir "@($filetypes)" + ;; + + existing_directories) + _filedir -d + ;; + + files) + + # non existing files complete like directories... + _filedir -d + + # ...except for non-completing files with the right file type + if [ ${#COMPREPLY[@]} -eq 0 ] + then + if ! [[ "$cur" =~ /$ ]] && [ "$filetypes" ] && [[ "$cur" =~ \.($filetypes)$ ]] + then + # file ending fits, we seem to be done + COMPREPLY=( "$cur" ) + fi + fi + ;; + + esac + + if [ "$params" ] + then + # none of our parameters contain spaces, so deactivate shellcheck's warning + # shellcheck disable=SC2207 + COMPREPLY+=( $(compgen -W "${params}" -- "${cur}") ) + fi +} + +complete -F _lmms lmms diff --git a/include/Mixer.h b/include/Mixer.h index 88ff92e4e..e91cd15c2 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -171,10 +171,11 @@ public: return m_audioDevStartFailed; } - void setAudioDevice( AudioDevice * _dev ); + void setAudioDevice( AudioDevice * _dev , bool startNow ); void setAudioDevice( AudioDevice * _dev, const struct qualitySettings & _qs, - bool _needs_fifo ); + bool _needs_fifo, + bool startNow ); void storeAudioDevice(); void restoreAudioDevice(); inline AudioDevice * audioDev() diff --git a/plugins/VstEffect/VstEffect.cpp b/plugins/VstEffect/VstEffect.cpp index 2d2308675..cbb30e2fe 100644 --- a/plugins/VstEffect/VstEffect.cpp +++ b/plugins/VstEffect/VstEffect.cpp @@ -95,7 +95,7 @@ bool VstEffect::processAudioBuffer( sampleFrame * _buf, const fpp_t _frames ) sampleFrame * buf = new sampleFrame[_frames]; #endif memcpy( buf, _buf, sizeof( sampleFrame ) * _frames ); - if (m_pluginMutex.tryLock()) + if (m_pluginMutex.tryLock(Engine::getSong()->isExporting() ? -1 : 0)) { m_plugin->process( buf, buf ); m_pluginMutex.unlock(); diff --git a/plugins/sf2_player/fluidsynthshims.h b/plugins/sf2_player/fluidsynthshims.h new file mode 100644 index 000000000..4302256ba --- /dev/null +++ b/plugins/sf2_player/fluidsynthshims.h @@ -0,0 +1,88 @@ +/* + * fluidsynthshims.h - a shim header for FluidSynth 2.0 API changes + * + * Copyright (c) 2018 Hyunjin Song + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#ifndef FLUIDSYNTHSHIMS_H +#define FLUIDSYNTHSHIMS_H + +#include + +#if FLUIDSYNTH_VERSION_MAJOR < 2 + +inline const char* fluid_preset_get_name(fluid_preset_t* preset) +{ + return preset->get_name(preset); +} + +inline int fluid_preset_get_banknum(fluid_preset_t* preset) +{ + return preset->get_banknum(preset); +} + +inline int fluid_preset_get_num(fluid_preset_t* preset) +{ + return preset->get_num(preset); +} + +inline fluid_sfont_t* fluid_preset_get_sfont(fluid_preset_t* preset) +{ + return preset->sfont; +} + +inline char* fluid_sfont_get_name(fluid_sfont_t* sfont) +{ + return sfont->get_name(sfont); +} + +inline void fluid_sfont_iteration_start(fluid_sfont_t* sfont) +{ + sfont->iteration_start(sfont); +} + +// Due to the API change, we can't simply shim the 'fluid_sfont_iteration_next' function +inline fluid_preset_t* fluid_sfont_iteration_next_wrapper(fluid_sfont_t* sfont, fluid_preset_t* preset) +{ + return sfont->iteration_next(sfont, preset) ? preset : nullptr; +} + +#else // FLUIDSYNTH_VERSION_MAJOR < 2 + +#define FLUID_REVERB_DEFAULT_ROOMSIZE 0.2f +#define FLUID_REVERB_DEFAULT_DAMP 0.0f +#define FLUID_REVERB_DEFAULT_WIDTH 0.5f +#define FLUID_REVERB_DEFAULT_LEVEL 0.9f + +#define FLUID_CHORUS_DEFAULT_N 3 +#define FLUID_CHORUS_DEFAULT_LEVEL 2.0f +#define FLUID_CHORUS_DEFAULT_SPEED 0.3f +#define FLUID_CHORUS_DEFAULT_DEPTH 8.0f + +inline fluid_preset_t* fluid_sfont_iteration_next_wrapper(fluid_sfont_t* sfont, fluid_preset_t*) +{ + return fluid_sfont_iteration_next(sfont); +} + +#endif // FLUIDSYNTH_VERSION_MAJOR < 2 + +#endif // FLUIDSYNTHSHIMS_H diff --git a/plugins/sf2_player/patches_dialog.cpp b/plugins/sf2_player/patches_dialog.cpp index bb8801f49..fe49ab1b3 100644 --- a/plugins/sf2_player/patches_dialog.cpp +++ b/plugins/sf2_player/patches_dialog.cpp @@ -139,7 +139,6 @@ void patchesDialog::setup ( fluid_synth_t * pSynth, int iChan, m_iChan = iChan; - fluid_preset_t preset; QTreeWidgetItem *pBankItem = NULL; // For all soundfonts (in reversed stack order) fill the available banks... int cSoundFonts = ::fluid_synth_sfcount(m_pSynth); @@ -147,11 +146,17 @@ void patchesDialog::setup ( fluid_synth_t * pSynth, int iChan, fluid_sfont_t *pSoundFont = ::fluid_synth_get_sfont(m_pSynth, i); if (pSoundFont) { #ifdef CONFIG_FLUID_BANK_OFFSET - int iBankOffset = ::fluid_synth_get_bank_offset(m_pSynth, pSoundFont->id); + int iBankOffset = ::fluid_synth_get_bank_offset(m_pSynth, fluid_sfont_get_id(pSoundFont)); #endif - pSoundFont->iteration_start(pSoundFont); - while (pSoundFont->iteration_next(pSoundFont, &preset)) { - int iBank = preset.get_banknum(&preset); + fluid_sfont_iteration_start(pSoundFont); +#if FLUIDSYNTH_VERSION_MAJOR < 2 + fluid_preset_t preset; + fluid_preset_t *pCurPreset = &preset; +#else + fluid_preset_t *pCurPreset; +#endif + while ((pCurPreset = fluid_sfont_iteration_next_wrapper(pSoundFont, pCurPreset))) { + int iBank = fluid_preset_get_banknum(pCurPreset); #ifdef CONFIG_FLUID_BANK_OFFSET iBank += iBankOffset; #endif @@ -169,9 +174,9 @@ void patchesDialog::setup ( fluid_synth_t * pSynth, int iChan, m_iBank = 0; fluid_preset_t *pPreset = ::fluid_synth_get_channel_preset(m_pSynth, m_iChan); if (pPreset) { - m_iBank = pPreset->get_banknum(pPreset); + m_iBank = fluid_preset_get_banknum(pPreset); #ifdef CONFIG_FLUID_BANK_OFFSET - m_iBank += ::fluid_synth_get_bank_offset(m_pSynth, (pPreset->sfont)->id); + m_iBank += ::fluid_synth_get_bank_offset(m_pSynth, fluid_sfont_get_id(fluid_preset_get_sfont(sfont))); #endif } @@ -182,7 +187,7 @@ void patchesDialog::setup ( fluid_synth_t * pSynth, int iChan, // Set the selected program. if (pPreset) - m_iProg = pPreset->get_num(pPreset); + m_iProg = fluid_preset_get_num(pPreset); QTreeWidgetItem *pProgItem = findProgItem(m_iProg); m_progListView->setCurrentItem(pProgItem); m_progListView->scrollToItem(pProgItem); @@ -308,7 +313,6 @@ void patchesDialog::bankChanged (void) // Clear up the program listview. m_progListView->setSortingEnabled(false); m_progListView->clear(); - fluid_preset_t preset; QTreeWidgetItem *pProgItem = NULL; // For all soundfonts (in reversed stack order) fill the available programs... int cSoundFonts = ::fluid_synth_sfcount(m_pSynth); @@ -316,23 +320,29 @@ void patchesDialog::bankChanged (void) fluid_sfont_t *pSoundFont = ::fluid_synth_get_sfont(m_pSynth, i); if (pSoundFont) { #ifdef CONFIG_FLUID_BANK_OFFSET - int iBankOffset = ::fluid_synth_get_bank_offset(m_pSynth, pSoundFont->id); + int iBankOffset = ::fluid_synth_get_bank_offset(m_pSynth, fluid_sfont_get_id(pSoundFont)); #endif - pSoundFont->iteration_start(pSoundFont); - while (pSoundFont->iteration_next(pSoundFont, &preset)) { - int iBank = preset.get_banknum(&preset); + fluid_sfont_iteration_start(pSoundFont); +#if FLUIDSYNTH_VERSION_MAJOR < 2 + fluid_preset_t preset; + fluid_preset_t *pCurPreset = &preset; +#else + fluid_preset_t *pCurPreset; +#endif + while ((pCurPreset = fluid_sfont_iteration_next_wrapper(pSoundFont, pCurPreset))) { + int iBank = fluid_preset_get_banknum(pCurPreset); #ifdef CONFIG_FLUID_BANK_OFFSET iBank += iBankOffset; #endif - int iProg = preset.get_num(&preset); + int iProg = fluid_preset_get_num(pCurPreset); if (iBank == iBankSelected && !findProgItem(iProg)) { pProgItem = new patchItem(m_progListView, pProgItem); if (pProgItem) { pProgItem->setText(0, QString::number(iProg)); - pProgItem->setText(1, preset.get_name(&preset)); - //pProgItem->setText(2, QString::number(pSoundFont->id)); + pProgItem->setText(1, fluid_preset_get_name(pCurPreset)); + //pProgItem->setText(2, QString::number(fluid_sfont_get_id(pSoundFont))); //pProgItem->setText(3, QFileInfo( - // pSoundFont->get_name(pSoundFont)).baseName()); + // fluid_sfont_get_name(pSoundFont).baseName()); } } } diff --git a/plugins/sf2_player/patches_dialog.h b/plugins/sf2_player/patches_dialog.h index f4523ff90..a2c88a79d 100644 --- a/plugins/sf2_player/patches_dialog.h +++ b/plugins/sf2_player/patches_dialog.h @@ -29,7 +29,7 @@ #include "ui_patches_dialog.h" #include "LcdSpinBox.h" -#include +#include "fluidsynthshims.h" #include #include diff --git a/plugins/sf2_player/sf2_player.cpp b/plugins/sf2_player/sf2_player.cpp index 292c5750f..4bf75777c 100644 --- a/plugins/sf2_player/sf2_player.cpp +++ b/plugins/sf2_player/sf2_player.cpp @@ -128,6 +128,29 @@ sf2Instrument::sf2Instrument( InstrumentTrack * _instrument_track ) : // everytime we load a new soundfont. m_synth = new_fluid_synth( m_settings ); +#if FLUIDSYNTH_VERSION_MAJOR >= 2 + // Get the default values from the setting + double settingVal; + + fluid_settings_getnum_default(m_settings, "synth.reverb.room-size", &settingVal); + m_reverbRoomSize.setInitValue(settingVal); + fluid_settings_getnum_default(m_settings, "synth.reverb.damping", &settingVal); + m_reverbDamping.setInitValue(settingVal); + fluid_settings_getnum_default(m_settings, "synth.reverb.width", &settingVal); + m_reverbWidth.setInitValue(settingVal); + fluid_settings_getnum_default(m_settings, "synth.reverb.level", &settingVal); + m_reverbLevel.setInitValue(settingVal); + + fluid_settings_getnum_default(m_settings, "synth.chorus.nr", &settingVal); + m_chorusNum.setInitValue(settingVal); + fluid_settings_getnum_default(m_settings, "synth.chorus.level", &settingVal); + m_chorusLevel.setInitValue(settingVal); + fluid_settings_getnum_default(m_settings, "synth.chorus.speed", &settingVal); + m_chorusSpeed.setInitValue(settingVal); + fluid_settings_getnum_default(m_settings, "synth.chorus.depth", &settingVal); + m_chorusDepth.setInitValue(settingVal); +#endif + loadFile( ConfigManager::inst()->defaultSoundfont() ); updateSampleRate(); @@ -393,7 +416,6 @@ QString sf2Instrument::getCurrentPatchName() int iBankSelected = m_bankNum.value(); int iProgSelected = m_patchNum.value(); - fluid_preset_t preset; // For all soundfonts (in reversed stack order) fill the available programs... int cSoundFonts = ::fluid_synth_sfcount( m_synth ); for( int i = 0; i < cSoundFonts; i++ ) @@ -404,21 +426,26 @@ QString sf2Instrument::getCurrentPatchName() #ifdef CONFIG_FLUID_BANK_OFFSET int iBankOffset = fluid_synth_get_bank_offset( - m_synth, pSoundFont->id ); + m_synth, fluid_sfont_get_id(pSoundFont) ); #endif - pSoundFont->iteration_start( pSoundFont ); - while( pSoundFont->iteration_next( pSoundFont, - &preset ) ) + fluid_sfont_iteration_start( pSoundFont ); +#if FLUIDSYNTH_VERSION_MAJOR < 2 + fluid_preset_t preset; + fluid_preset_t *pCurPreset = &preset; +#else + fluid_preset_t *pCurPreset; +#endif + while ((pCurPreset = fluid_sfont_iteration_next_wrapper(pSoundFont, pCurPreset))) { - int iBank = preset.get_banknum( &preset ); + int iBank = fluid_preset_get_banknum( pCurPreset ); #ifdef CONFIG_FLUID_BANK_OFFSET iBank += iBankOffset; #endif - int iProg = preset.get_num( &preset ); + int iProg = fluid_preset_get_num( pCurPreset ); if( iBank == iBankSelected && iProg == iProgSelected ) { - return preset.get_name( &preset ); + return fluid_preset_get_name( pCurPreset ); } } } diff --git a/plugins/sf2_player/sf2_player.h b/plugins/sf2_player/sf2_player.h index 0d29c27e1..eed7e24ab 100644 --- a/plugins/sf2_player/sf2_player.h +++ b/plugins/sf2_player/sf2_player.h @@ -36,7 +36,7 @@ #include "Knob.h" #include "LcdSpinBox.h" #include "LedCheckbox.h" -#include "fluidsynth.h" +#include "fluidsynthshims.h" #include "MemoryManager.h" class sf2InstrumentView; diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 594e41a64..73ea33a51 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -51,6 +51,7 @@ #include "GuiApplication.h" #include "PixmapButton.h" #include "SampleBuffer.h" +#include "Song.h" #include "StringPairDrag.h" #include "TextFloat.h" #include "ToolTip.h" @@ -365,7 +366,7 @@ void vestigeInstrument::loadFile( const QString & _file ) void vestigeInstrument::play( sampleFrame * _buf ) { - if (!m_pluginMutex.tryLock()) {return;} + if (!m_pluginMutex.tryLock(Engine::getSong()->isExporting() ? -1 : 0)) {return;} const fpp_t frames = Engine::mixer()->framesPerPeriod(); diff --git a/plugins/zynaddsubfx/ZynAddSubFx.cpp b/plugins/zynaddsubfx/ZynAddSubFx.cpp index b7d990935..ad8d9a78c 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/ZynAddSubFx.cpp @@ -40,6 +40,7 @@ #include "InstrumentPlayHandle.h" #include "InstrumentTrack.h" #include "gui_templates.h" +#include "Song.h" #include "StringPairDrag.h" #include "RemoteZynAddSubFx.h" #include "LocalZynAddSubFx.h" @@ -324,7 +325,7 @@ QString ZynAddSubFxInstrument::nodeName() const void ZynAddSubFxInstrument::play( sampleFrame * _buf ) { - if (!m_pluginMutex.tryLock()) {return;} + if (!m_pluginMutex.tryLock(Engine::getSong()->isExporting() ? -1 : 0)) {return;} if( m_remotePlugin ) { m_remotePlugin->process( NULL, _buf ); diff --git a/src/core/BBTrackContainer.cpp b/src/core/BBTrackContainer.cpp index e9af1f621..e349c7b02 100644 --- a/src/core/BBTrackContainer.cpp +++ b/src/core/BBTrackContainer.cpp @@ -95,10 +95,13 @@ tact_t BBTrackContainer::lengthOfBB( int _bb ) const MidiTime max_length = MidiTime::ticksPerTact(); const TrackList & tl = tracks(); - for( TrackList::const_iterator it = tl.begin(); it != tl.end(); ++it ) + for (Track* t : tl) { - max_length = qMax( max_length, - ( *it )->getTCO( _bb )->length() ); + // Don't create TCOs here if not exist + if (_bb < t->numOfTCOs()) + { + max_length = qMax(max_length, t->getTCO( _bb )->length()); + } } return max_length.nextFullTact(); diff --git a/src/core/EffectChain.cpp b/src/core/EffectChain.cpp index 8439fd91e..21b85917b 100644 --- a/src/core/EffectChain.cpp +++ b/src/core/EffectChain.cpp @@ -53,7 +53,7 @@ EffectChain::~EffectChain() void EffectChain::saveSettings( QDomDocument & _doc, QDomElement & _this ) { - _this.setAttribute( "enabled", m_enabledModel.value() ); + m_enabledModel.saveSettings( _doc, _this, "enabled" ); _this.setAttribute( "numofeffects", m_effects.count() ); for( Effect* effect : m_effects) @@ -80,7 +80,7 @@ void EffectChain::loadSettings( const QDomElement & _this ) // TODO This method should probably also lock the mixer - m_enabledModel.setValue( _this.attribute( "enabled" ).toInt() ); + m_enabledModel.loadSettings( _this, "enabled" ); const int plugin_cnt = _this.attribute( "numofeffects" ).toInt(); diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index d749c4343..e0ac414c2 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -577,7 +577,8 @@ void Mixer::changeQuality( const struct qualitySettings & _qs ) -void Mixer::setAudioDevice( AudioDevice * _dev ) +void Mixer::setAudioDevice( AudioDevice * _dev, + bool startNow ) { stopProcessing(); @@ -594,7 +595,7 @@ void Mixer::setAudioDevice( AudioDevice * _dev ) emit sampleRateChanged(); - startProcessing(); + if (startNow) {startProcessing();} } @@ -602,7 +603,8 @@ void Mixer::setAudioDevice( AudioDevice * _dev ) void Mixer::setAudioDevice( AudioDevice * _dev, const struct qualitySettings & _qs, - bool _needs_fifo ) + bool _needs_fifo, + bool startNow ) { // don't delete the audio-device stopProcessing(); @@ -623,7 +625,7 @@ void Mixer::setAudioDevice( AudioDevice * _dev, emit qualitySettingsChanged(); emit sampleRateChanged(); - startProcessing( _needs_fifo ); + if (startNow) {startProcessing( _needs_fifo );} } diff --git a/src/core/ProjectRenderer.cpp b/src/core/ProjectRenderer.cpp index adb715cfd..57975356e 100644 --- a/src/core/ProjectRenderer.cpp +++ b/src/core/ProjectRenderer.cpp @@ -152,7 +152,7 @@ void ProjectRenderer::startProcessing() // Have to do mixer stuff with GUI-thread affinity in order to // make slots connected to sampleRateChanged()-signals being called immediately. Engine::mixer()->setAudioDevice( m_fileDev, - m_qualitySettings, false ); + m_qualitySettings, false, false ); start( #ifndef LMMS_BUILD_WIN32 @@ -193,6 +193,9 @@ void ProjectRenderer::run() tick_t endTick = exportEndpoints.second.getTicks(); tick_t lengthTicks = endTick - startTick; + // Now start processing + Engine::mixer()->startProcessing(false); + // Continually track and emit progress percentage to listeners. while( exportPos.getTicks() < endTick && Engine::getSong()->isExporting() == true diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 140a420fb..0f58e7560 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -285,7 +285,6 @@ void SampleBuffer::update( bool _keep_settings ) else { fprintf( stderr, "%s\n", message.toUtf8().constData() ); - exit( EXIT_FAILURE ); } } } diff --git a/src/core/Song.cpp b/src/core/Song.cpp index e48eb725c..6f060664e 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -346,9 +346,7 @@ void Song::processNextBuffer() m_vstSyncController.setAbsolutePosition( ticks ); m_vstSyncController.setPlaybackJumped( true ); - } - else if( m_playPos[m_playMode] == tl->loopEnd() - 1 ) - { + emit updateSampleTracks(); } } diff --git a/src/core/Track.cpp b/src/core/Track.cpp index 9ceff8f44..aec0e5150 100644 --- a/src/core/Track.cpp +++ b/src/core/Track.cpp @@ -2125,8 +2125,9 @@ void Track::saveSettings( QDomDocument & doc, QDomElement & element ) } element.setAttribute( "type", type() ); element.setAttribute( "name", name() ); - element.setAttribute( "muted", isMuted() ); - element.setAttribute( "solo", isSolo() ); + m_mutedModel.saveSettings( doc, element, "muted" ); + m_soloModel.saveSettings( doc, element, "solo" ); + if( m_height >= MINIMAL_TRACK_HEIGHT ) { element.setAttribute( "trackheight", m_height ); @@ -2178,8 +2179,8 @@ void Track::loadSettings( const QDomElement & element ) setName( element.hasAttribute( "name" ) ? element.attribute( "name" ) : element.firstChild().toElement().attribute( "name" ) ); - setMuted( element.attribute( "muted" ).toInt() ); - setSolo( element.attribute( "solo" ).toInt() ); + m_mutedModel.loadSettings( element, "muted" ); + m_soloModel.loadSettings( element, "solo" ); if( m_simpleSerializingMode ) { @@ -2212,8 +2213,9 @@ void Track::loadSettings( const QDomElement & element ) { loadTrackSpecificSettings( node.toElement() ); } - else if( - !node.toElement().attribute( "metadata" ).toInt() ) + else if( node.nodeName() != "muted" + && node.nodeName() != "solo" + && !node.toElement().attribute( "metadata" ).toInt() ) { TrackContentObject * tco = createTCO( MidiTime( 0 ) ); diff --git a/src/core/main.cpp b/src/core/main.cpp index 255fe7f2b..0289f0c53 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -804,7 +804,7 @@ int main( int argc, char * * argv ) ) ); mb.setIcon( QMessageBox::Warning ); - mb.setWindowIcon( embed::getIconPixmap( "icon" ) ); + mb.setWindowIcon( embed::getIconPixmap( "icon_small" ) ); mb.setWindowFlags( Qt::WindowCloseButtonHint ); QPushButton * recover; diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 07a6dcf9c..424c23d26 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -266,7 +266,7 @@ MainWindow::~MainWindow() void MainWindow::finalize() { resetWindowTitle(); - setWindowIcon( embed::getIconPixmap( "icon" ) ); + setWindowIcon( embed::getIconPixmap( "icon_small" ) ); // project-popup-menu @@ -414,7 +414,7 @@ void MainWindow::finalize() #if !(defined(LMMS_BUILD_APPLE) && (QT_VERSION < 0x050600)) help_menu->addSeparator(); #endif - help_menu->addAction( embed::getIconPixmap( "icon" ), tr( "About" ), + help_menu->addAction( embed::getIconPixmap( "icon_small" ), tr( "About" ), this, SLOT( aboutLMMS() ) ); // create tool-buttons diff --git a/src/gui/editors/BBEditor.cpp b/src/gui/editors/BBEditor.cpp index dde3cf95c..56fe29856 100644 --- a/src/gui/editors/BBEditor.cpp +++ b/src/gui/editors/BBEditor.cpp @@ -250,7 +250,25 @@ void BBTrackContainerView::dropEvent(QDropEvent* de) DataFile dataFile( value.toUtf8() ); Track * t = Track::create( dataFile.content().firstChild().toElement(), model() ); - t->deleteTCOs(); + // Ensure BB TCOs exist + bool hasValidBBTCOs = false; + if (t->getTCOs().size() == m_bbtc->numOfBBs()) + { + hasValidBBTCOs = true; + for (int i = 0; i < t->getTCOs().size(); ++i) + { + if (t->getTCOs()[i]->startPosition() != MidiTime(i, 0)) + { + hasValidBBTCOs = false; + break; + } + } + } + if (!hasValidBBTCOs) + { + t->deleteTCOs(); + t->createTCOsForBB(m_bbtc->numOfBBs() - 1); + } m_bbtc->updateAfterTrackAdd(); de->accept(); diff --git a/src/tracks/Pattern.cpp b/src/tracks/Pattern.cpp index 8218d16f6..05d316f00 100644 --- a/src/tracks/Pattern.cpp +++ b/src/tracks/Pattern.cpp @@ -697,8 +697,7 @@ void PatternView::mousePressEvent( QMouseEvent * _me ) { if( _me->button() == Qt::LeftButton && m_pat->m_patternType == Pattern::BeatPattern && - ( fixedTCOs() || pixelsPerTact() >= 96 || - m_pat->m_steps != MidiTime::stepsPerTact() ) && + ( fixedTCOs() || pixelsPerTact() >= 96 ) && _me->y() > height() - s_stepBtnOff->height() ) // when mouse button is pressed in beat/bassline -mode @@ -768,8 +767,7 @@ void PatternView::mouseDoubleClickEvent(QMouseEvent *_me) void PatternView::wheelEvent( QWheelEvent * _we ) { if( m_pat->m_patternType == Pattern::BeatPattern && - ( fixedTCOs() || pixelsPerTact() >= 96 || - m_pat->m_steps != MidiTime::stepsPerTact() ) && + ( fixedTCOs() || pixelsPerTact() >= 96 ) && _we->y() > height() - s_stepBtnOff->height() ) { // get the step number that was wheeled on and @@ -1013,8 +1011,7 @@ void PatternView::paintEvent( QPaintEvent * ) } // beat pattern paint event - else if( beatPattern && ( fixedTCOs() || pixelsPerTact >= 96 - || m_pat->m_steps != MidiTime::stepsPerTact() ) ) + else if( beatPattern && ( fixedTCOs() || pixelsPerTact >= 96 ) ) { QPixmap stepon0; QPixmap stepon200; diff --git a/src/tracks/SampleTrack.cpp b/src/tracks/SampleTrack.cpp index caa0dbe15..8fa6fd50f 100644 --- a/src/tracks/SampleTrack.cpp +++ b/src/tracks/SampleTrack.cpp @@ -73,13 +73,16 @@ SampleTCO::SampleTCO( Track * _track ) : connect( timeLine, SIGNAL( positionMarkerMoved() ), this, SLOT( playbackPositionChanged() ) ); } //playbutton clicked or space key / on Export Song set isPlaying to false - connect( Engine::getSong(), SIGNAL( playbackStateChanged() ), this, SLOT( playbackPositionChanged() ) ); + connect( Engine::getSong(), SIGNAL( playbackStateChanged() ), + this, SLOT( playbackPositionChanged() ), Qt::DirectConnection ); //care about loops - connect( Engine::getSong(), SIGNAL( updateSampleTracks() ), this, SLOT( playbackPositionChanged() ) ); + connect( Engine::getSong(), SIGNAL( updateSampleTracks() ), + this, SLOT( playbackPositionChanged() ), Qt::DirectConnection ); //care about mute TCOs connect( this, SIGNAL( dataChanged() ), this, SLOT( playbackPositionChanged() ) ); //care about mute track - connect( getTrack()->getMutedModel(), SIGNAL( dataChanged() ),this, SLOT( playbackPositionChanged() ) ); + connect( getTrack()->getMutedModel(), SIGNAL( dataChanged() ), + this, SLOT( playbackPositionChanged() ), Qt::DirectConnection ); //care about TCO position connect( this, SIGNAL( positionChanged() ), this, SLOT( updateTrackTcos() ) );