diff --git a/.appveyor.yml b/.appveyor.yml
index 3b632d1f3..7ca7d58c4 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -19,5 +19,9 @@ build_script:
- cmake -DUSE_COMPILE_CACHE=ON -DCACHE_TOOL=%APPVEYOR_BUILD_FOLDER%/clcache.4.1.0/clcache-4.1.0/clcache.exe -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_PREFIX_PATH=c:/Qt/5.12/msvc2017%QT_SUFFIX%;c:/tools/vcpkg/installed/%PLATFORM%-windows -DCMAKE_GENERATOR_PLATFORM="%CMAKE_PLATFORM%" ..
- cmake --build . -- /maxcpucount:4
- cmake --build . --target tests
+ - cmake --build . --target package
+artifacts:
+ - path: 'build\lmms-*.exe'
+ name: Installer
cache:
- c:/tools/vcpkg/installed
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 4174ba1ef..a3be541b5 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -12,6 +12,18 @@ shared:
key: ccache-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }}-{{ .BuildNum }}
paths:
- ~/.ccache
+ restore_homebrew_cache: &restore_homebrew_cache
+ restore_cache:
+ keys:
+ - homebrew-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }}
+ - homebrew-{{ arch }}-{{ .Environment.CIRCLE_JOB }}
+ - homebrew-{{ arch }}
+ save_homebrew_cache: &save_homebrew_cache
+ save_cache:
+ key: homebrew-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }}-{{ .BuildNum }}
+ paths:
+ - ~/Library/Caches/Homebrew
+ - /usr/local/Homebrew
ccache_stats: &ccache_stats
run:
@@ -30,6 +42,14 @@ shared:
mkdir -p /tmp/artifacts
# Workaround for failing submodule fetching
git config --global --unset url."ssh://git@github.com".insteadOf || true
+ if [[ -n "${CIRCLE_PR_NUMBER}" ]]
+ then
+ echo "Fetching out merged pull request"
+ git fetch -u origin refs/pull/${CIRCLE_PR_NUMBER}/merge:pr/merge
+ git checkout pr/merge
+ else
+ echo "Not a pull request"
+ fi
# Commmon environment variables
common_environment: &common_environment
@@ -59,6 +79,15 @@ jobs:
- run:
name: Build tests
command: cd build && make tests
+ - run:
+ name: Build installer
+ command: |
+ cd build
+ make package
+ cp ./lmms-*.exe /tmp/artifacts/
+ - store_artifacts:
+ path: /tmp/artifacts/
+ destination: /
- *ccache_stats
- *save_cache
mingw64:
@@ -79,11 +108,20 @@ jobs:
- run:
name: Build tests
command: cd build && make tests
+ - run:
+ name: Build installer
+ command: |
+ cd build
+ make package
+ cp ./lmms-*.exe /tmp/artifacts/
+ - store_artifacts:
+ path: /tmp/artifacts/
+ destination: /
- *ccache_stats
- *save_cache
linux.gcc:
docker:
- - image: lmmsci/linux.gcc:18.04
+ - image: lmmsci/linux.gcc:16.04
environment:
<<: *common_environment
steps:
@@ -92,7 +130,10 @@ jobs:
- *restore_cache
- run:
name: Configure
- command: mkdir build && cd build && cmake .. $CMAKE_OPTS -DCMAKE_INSTALL_PREFIX=./install
+ command: |
+ source /opt/qt5*/bin/qt5*-env.sh || true
+ mkdir build && cd build
+ cmake .. $CMAKE_OPTS -DCMAKE_INSTALL_PREFIX=./install
- run:
name: Build
command: cd build && make
@@ -125,10 +166,53 @@ jobs:
- run:
name: Shellcheck
command: shellcheck $(find "./cmake/" -type f -name '*.sh' -o -name "*.sh.in")
+ macos:
+ environment:
+ <<: *common_environment
+ macos:
+ xcode: "9.3.1"
+ steps:
+ - checkout
+ - *init
+ - *restore_homebrew_cache
+ - *restore_cache
+ - run:
+ name: Install Homebrew dependencies
+ command: brew update && brew install ccache fftw cmake pkg-config libogg libvorbis lame libsndfile libsamplerate jack sdl libgig libsoundio stk fluid-synth portaudio fltk qt5 carla
+ - run:
+ name: Install nodejs dependencies
+ command: npm install -g appdmg
+ - run:
+ name: Building
+ command: |
+ mkdir build && cd build
+ cmake .. -DCMAKE_INSTALL_PREFIX="../target" -DCMAKE_PREFIX_PATH="$(brew --prefix qt5)" $CMAKE_OPTS -DUSE_WERROR=OFF
+ make
+ - run:
+ name: Build tests
+ command: cd build && make tests
+ - run:
+ name: Run tests
+ command: build/tests/tests
+ - run:
+ name: Build DMG
+ command: |
+ cd build
+ make install
+ make dmg
+ cp ./lmms-*.dmg /tmp/artifacts/
+ - store_artifacts:
+ path: /tmp/artifacts/
+ destination: /
+ - *save_cache
+ - *save_homebrew_cache
+
+
workflows:
version: 2
build-and-test:
jobs:
+ - macos
- mingw32
- mingw64
- linux.gcc
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 000000000..2c22146ae
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,30 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: bug
+assignees: ''
+
+---
+
+# Please search the issue tracker for existing bug reports before submitting your own. Delete this line to confirm no similar report has been posted yet.
+
+### Bug Summary
+
+#### Steps to reproduce
+
+#### Expected behavior
+
+#### Actual behavior
+
+#### Screenshot
+
+#### LMMS version used
+
+#### Logs
+
+ Click to expand
+
+
+
+
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 000000000..2c51f276e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,4 @@
+contact_links:
+- name: Get help on Discord
+ url: https://lmms.io/chat/
+ about: Need help? Have a question? Reach out to other LMMS users on our Discord server!
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 000000000..f9a0ae192
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,18 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: enhancement
+assignees: ''
+
+---
+
+# Please search the issue tracker for existing feature requests before submitting your own. Delete this line to confirm no similar request has been posted yet.
+
+### Enhancement Summary
+
+#### Justification
+
+#### Mockup
+
+
diff --git a/.gitmodules b/.gitmodules
index 28d6c5d46..56b7f3eab 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -34,3 +34,6 @@
[submodule "doc/wiki"]
path = doc/wiki
url = https://github.com/lmms/lmms.wiki.git
+[submodule "src/3rdparty/ringbuffer"]
+ path = src/3rdparty/ringbuffer
+ url = https://github.com/JohannesLorenz/ringbuffer.git
diff --git a/.mailmap b/.mailmap
index 71b6697c8..14d4754ce 100644
--- a/.mailmap
+++ b/.mailmap
@@ -29,3 +29,5 @@ grejppi
Johannes Lorenz
Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com>
Noah Brecht
+Olivier Humbert
+Hussam al-Homsi Hussam Eddin Alhomsi
diff --git a/.travis.yml b/.travis.yml
index b3cb8aa7c..f94aa0846 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,8 +11,6 @@ matrix:
include:
- env: TYPE=style
- os: linux
- - env: TARGET_OS=win32
- - env: TARGET_OS=win64
- env: TARGET_OS=debian-sid TARGET_DEPLOY=True
git:
depth: false
@@ -24,7 +22,7 @@ matrix:
git:
depth: false
- os: osx
- osx_image: xcode8.3
+ osx_image: xcode9.4
before_install:
# appdmg doesn't work with old Node.js
- if [ "$TRAVIS_OS_NAME" = osx ]; then nvm install 10; fi
diff --git a/.travis/script.sh b/.travis/script.sh
index 70391a762..b723f5dd0 100755
--- a/.travis/script.sh
+++ b/.travis/script.sh
@@ -42,5 +42,7 @@ else
fi
echo "Uploading $PACKAGE to transfer.sh..."
- curl --upload-file "$PACKAGE" "https://transfer.sh/$PACKAGE" || true
+ # Limit the connection time to 3 minutes and total upload time to 5 minutes
+ # Otherwise the build may hang
+ curl --connect-timeout 180 --max-time 300 --upload-file "$PACKAGE" "https://transfer.sh/$PACKAGE" || true
fi
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bd9d376e2..2f310d27c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,6 +3,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.3)
PROJECT(lmms)
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules" ${CMAKE_MODULE_PATH})
+SET(LMMS_BINARY_DIR ${CMAKE_BINARY_DIR})
+SET(LMMS_SOURCE_DIR ${CMAKE_SOURCE_DIR})
IF(COMMAND CMAKE_POLICY)
CMAKE_POLICY(SET CMP0005 NEW)
@@ -13,8 +15,10 @@ IF(COMMAND CMAKE_POLICY)
CMAKE_POLICY(SET CMP0050 OLD)
ENDIF()
CMAKE_POLICY(SET CMP0020 NEW)
+ CMAKE_POLICY(SET CMP0057 NEW)
ENDIF(COMMAND CMAKE_POLICY)
+INCLUDE(PluginList)
INCLUDE(CheckSubmodules)
INCLUDE(AddFileDependencies)
INCLUDE(CheckIncludeFiles)
@@ -32,7 +36,7 @@ SET(PROJECT_DESCRIPTION "${PROJECT_NAME_UCASE} - Free music production software"
SET(PROJECT_COPYRIGHT "2008-${PROJECT_YEAR} ${PROJECT_AUTHOR}")
SET(VERSION_MAJOR "1")
SET(VERSION_MINOR "2")
-SET(VERSION_RELEASE "0")
+SET(VERSION_RELEASE "1")
SET(VERSION_STAGE "")
SET(VERSION_BUILD "0")
SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE}")
@@ -140,7 +144,7 @@ CHECK_INCLUDE_FILES(locale.h LMMS_HAVE_LOCALE_H)
LIST(APPEND CMAKE_PREFIX_PATH "${CMAKE_INSTALL_PREFIX}")
-FIND_PACKAGE(Qt5 COMPONENTS Core Gui Widgets Xml REQUIRED)
+FIND_PACKAGE(Qt5 5.6.0 COMPONENTS Core Gui Widgets Xml REQUIRED)
FIND_PACKAGE(Qt5 COMPONENTS LinguistTools QUIET)
INCLUDE_DIRECTORIES(
@@ -434,9 +438,9 @@ If(WANT_GIG)
ENDIF(WANT_GIG)
# check for pthreads
-IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD)
+IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD OR LMMS_BUILD_FREEBSD)
FIND_PACKAGE(Threads)
-ENDIF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD)
+ENDIF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD OR LMMS_BUILD_FREEBSD)
# check for sndio (roaraudio won't work yet)
IF(WANT_SNDIO)
@@ -565,8 +569,8 @@ ADD_SUBDIRECTORY(tests)
ADD_SUBDIRECTORY(data)
ADD_SUBDIRECTORY(doc)
-# post-install tasks
-ADD_SUBDIRECTORY(cmake/postinstall)
+# install tasks
+ADD_SUBDIRECTORY(cmake/install)
ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_BINARY_DIR}/lmms.1.gz"
COMMAND gzip -c ${CMAKE_SOURCE_DIR}/doc/lmms.1 > ${CMAKE_BINARY_DIR}/lmms.1.gz
@@ -706,4 +710,9 @@ MESSAGE(
"\n\n")
SET(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION "${BIN_DIR}")
+if(MSVC)
+ # We can't set this on the install time according to the configuration
+ SET(CMAKE_INSTALL_DEBUG_LIBRARIES TRUE)
+ SET(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)
+endif()
INCLUDE(InstallRequiredSystemLibraries)
diff --git a/cmake/install/CMakeLists.txt b/cmake/install/CMakeLists.txt
new file mode 100644
index 000000000..a3a81beeb
--- /dev/null
+++ b/cmake/install/CMakeLists.txt
@@ -0,0 +1,41 @@
+SET(PLUGIN_FILES "")
+IF(LMMS_BUILD_WIN32)
+ INSTALL(FILES $ DESTINATION platforms)
+ENDIF()
+
+IF(LMMS_BUILD_WIN32 OR LMMS_INSTALL_DEPENDENCIES)
+ include(InstallTargetDependencies)
+
+ # Collect directories to search for DLLs
+ GET_FILENAME_COMPONENT(QTBIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH)
+ set(LIB_DIRS "${QTBIN_DIR}")
+
+ GET_PROPERTY(PLUGINS_BUILT GLOBAL PROPERTY PLUGINS_BUILT)
+
+ IF(LMMS_BUILD_WIN32)
+ SET(LMMS_DEP_DESTINATION ${BIN_DIR})
+ SET(PLUGIN_DEP_DESTINATION ${BIN_DIR})
+ ELSE()
+ SET(LMMS_DEP_DESTINATION ${LIB_DIR})
+ SET(PLUGIN_DEP_DESTINATION ${LIB_DIR})
+ ENDIF()
+
+ INSTALL_TARGET_DEPENDENCIES(
+ NAME "main_binary"
+ TARGETS lmms
+ DESTINATION "${LMMS_DEP_DESTINATION}"
+ LIB_DIRS ${LIB_DIRS}
+ )
+
+ INSTALL_TARGET_DEPENDENCIES(
+ NAME "plugins"
+ TARGETS ${PLUGINS_BUILT}
+ DESTINATION ${PLUGIN_DEP_DESTINATION}
+ LIB_DIRS ${LIB_DIRS} "${PLUGIN_DIR}"
+ )
+ENDIF()
+
+IF(LMMS_BUILD_APPLE)
+ INSTALL(CODE "EXECUTE_PROCESS(COMMAND chmod u+x ${CMAKE_BINARY_DIR}/install_apple.sh)")
+ INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_BINARY_DIR}/install_apple.sh)")
+ENDIF()
diff --git a/cmake/install/excludelist-win b/cmake/install/excludelist-win
new file mode 100644
index 000000000..17793a113
--- /dev/null
+++ b/cmake/install/excludelist-win
@@ -0,0 +1,23 @@
+# List of DLLs considered to be system libraries.
+# This is needed when cross-compiling for Windows.
+ADVAPI32.dll
+COMCTL32.dll
+comdlg32.dll
+dwmapi.dll
+GDI32.dll
+IMM32.dll
+KERNEL32.dll
+MPR.DLL
+msvcrt.dll
+ole32.dll
+OLEAUT32.dll
+OPENGL32.DLL
+SHELL32.dll
+USER32.dll
+UxTheme.dll
+VERSION.dll
+WINMM.DLL
+WS2_32.dll
+RPCRT4.dll
+dsound.dll
+SETUPAPI.dll
diff --git a/cmake/linux/lmms.desktop b/cmake/linux/lmms.desktop
index 72a82da17..d6a05d15f 100644
--- a/cmake/linux/lmms.desktop
+++ b/cmake/linux/lmms.desktop
@@ -3,11 +3,11 @@ Name=LMMS
GenericName=Music production suite
GenericName[ca]=Programari de producció musical
GenericName[de]=Software zur Musik-Produktion
-GenericName[fr]=Ensemble pour la production musicale
+GenericName[fr]=Suite de production musicale
GenericName[pl]=Narzędzia do produkcji muzyki
Comment=Music sequencer and synthesizer
Comment[ca]=Producció fàcil de música per a tothom!
-Comment[fr]=Production facile de musique pour tout le monde !
+Comment[fr]=Séquenceur et synthétiseur de musique
Comment[pl]=Prosta produkcja muzyki dla każdego!
Icon=lmms
Exec=lmms %f
diff --git a/cmake/linux/package_linux.sh.in b/cmake/linux/package_linux.sh.in
index 0dec715f4..9f233d401 100644
--- a/cmake/linux/package_linux.sh.in
+++ b/cmake/linux/package_linux.sh.in
@@ -103,7 +103,7 @@ mv "${APPDIR}usr/bin/lmms" "${APPDIR}usr/bin/lmms.real"
cat >"${APPDIR}usr/bin/lmms" < /dev/null 2>&1; then
CARLAPATH="\$(which carla)"
CARLAPREFIX="\${CARLAPATH%/bin*}"
@@ -175,10 +175,9 @@ executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/pitch_scale
# Bundle both qt and non-qt dependencies into appimage format
echo -e "\nBundling and relinking system dependencies..."
echo -e ">>>>> linuxdeployqt" > "$LOGFILE"
-# FIXME: -unsupported-allow-new-glibc may result in an AppImage which is unusable on old systems.
# shellcheck disable=SC2086
-"$LINUXDEPLOYQT" "$DESKTOPFILE" $executables -unsupported-allow-new-glibc -bundle-non-qt-libs -verbose=$VERBOSITY $STRIP >> "$LOGFILE" 2>&1
+"$LINUXDEPLOYQT" "$DESKTOPFILE" $executables -bundle-non-qt-libs -verbose=$VERBOSITY $STRIP >> "$LOGFILE" 2>&1
success "Bundled and relinked dependencies"
# Link to original location so lmms can find them
diff --git a/cmake/modules/BuildPlugin.cmake b/cmake/modules/BuildPlugin.cmake
index efa3e5b46..675433e63 100644
--- a/cmake/modules/BuildPlugin.cmake
+++ b/cmake/modules/BuildPlugin.cmake
@@ -62,7 +62,10 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME)
TARGET_LINK_LIBRARIES(${PLUGIN_NAME} lmms)
ENDIF(LMMS_BUILD_WIN32)
- INSTALL(TARGETS ${PLUGIN_NAME} DESTINATION "${PLUGIN_DIR}")
+ INSTALL(TARGETS ${PLUGIN_NAME}
+ LIBRARY DESTINATION "${PLUGIN_DIR}"
+ RUNTIME DESTINATION "${PLUGIN_DIR}"
+ )
IF(LMMS_BUILD_APPLE)
IF ("${PLUGIN_LINK}" STREQUAL "SHARED")
@@ -72,9 +75,11 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME)
ENDIF()
ADD_DEPENDENCIES(${PLUGIN_NAME} lmms)
ENDIF(LMMS_BUILD_APPLE)
- IF(LMMS_BUILD_WIN32 AND STRIP)
+ IF(LMMS_BUILD_WIN32)
+ IF(STRIP)
+ ADD_CUSTOM_COMMAND(TARGET ${PLUGIN_NAME} POST_BUILD COMMAND ${STRIP} "$")
+ ENDIF()
SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES PREFIX "")
- ADD_CUSTOM_COMMAND(TARGET ${PLUGIN_NAME} POST_BUILD COMMAND ${STRIP} "$")
ENDIF()
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${RCC_OUT} ${plugin_MOC_out}")
@@ -89,5 +94,8 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME)
TARGET_INCLUDE_DIRECTORIES(${PLUGIN_NAME}
PUBLIC $
)
+
+ SET_PROPERTY(GLOBAL APPEND PROPERTY PLUGINS_BUILT ${PLUGIN_NAME})
+ GET_PROPERTY(PLUGINS_BUILT GLOBAL PROPERTY PLUGINS_BUILT)
ENDMACRO(BUILD_PLUGIN)
diff --git a/cmake/modules/CheckSubmodules.cmake b/cmake/modules/CheckSubmodules.cmake
index 65e5be08b..32a2f9951 100644
--- a/cmake/modules/CheckSubmodules.cmake
+++ b/cmake/modules/CheckSubmodules.cmake
@@ -7,12 +7,12 @@
# INCLUDE(CheckSubmodules)
#
# Options:
-# SET(SKIP_SUBMODULES "foo;bar")
+# SET(PLUGIN_LIST "zynaddsubfx;...") # skips submodules for plugins not explicitely listed
#
# Or via command line:
-# cmake -DSKIP_SUBMODULES=foo;bar
+# cmake -PLUGIN_LIST=foo;bar
#
-# Copyright (c) 2017, Tres Finocchiaro,
+# Copyright (c) 2019, Tres Finocchiaro,
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
@@ -20,13 +20,15 @@
# Files which confirm a successful clone
SET(VALID_CRUMBS "CMakeLists.txt;Makefile;Makefile.in;Makefile.am;configure.ac;configure.py;autogen.sh;.gitignore;LICENSE;Home.md")
+OPTION(NO_SHALLOW_CLONE "Disable shallow cloning of submodules" OFF)
+
# Try and use the specified shallow clone on submodules, if supported
SET(DEPTH_VALUE 100)
# Number of times git commands will retry before failing
SET(MAX_ATTEMPTS 2)
-MESSAGE("\nValidating submodules...")
+MESSAGE("\nChecking submodules...")
IF(NOT EXISTS "${CMAKE_SOURCE_DIR}/.gitmodules")
MESSAGE("Skipping the check because .gitmodules not detected."
"Please make sure you have all submodules in the source tree!"
@@ -41,74 +43,112 @@ SET(LANG_BACKUP "$ENV{LANG}")
SET(ENV{LC_ALL} "C")
SET(ENV{LANG} "en_US")
-# Assume alpha-numeric paths
-STRING(REGEX MATCHALL "path = [-0-9A-Za-z/]+" SUBMODULE_LIST ${SUBMODULE_DATA})
-STRING(REGEX MATCHALL "url = [.:%-0-9A-Za-z/]+" SUBMODULE_URL_LIST ${SUBMODULE_DATA})
+# Submodule list pairs, unparsed (WARNING: Assumes alpha-numeric paths)
+STRING(REGEX MATCHALL "path = [-0-9A-Za-z/]+" SUBMODULE_LIST_RAW ${SUBMODULE_DATA})
+STRING(REGEX MATCHALL "url = [.:%-0-9A-Za-z/]+" SUBMODULE_URL_RAW ${SUBMODULE_DATA})
-FOREACH(_part ${SUBMODULE_LIST})
- STRING(REPLACE "path = " "" SUBMODULE_PATH ${_part})
+# Submodule list pairs, parsed
+SET(SUBMODULE_LIST "")
+SET(SUBMODULE_URL "")
- LIST(FIND SUBMODULE_LIST ${_part} SUBMODULE_INDEX)
- LIST(GET SUBMODULE_URL_LIST ${SUBMODULE_INDEX} _url)
- STRING(REPLACE "url = " "" SUBMODULE_URL ${_url})
+FOREACH(_path ${SUBMODULE_LIST_RAW})
+ # Parse SUBMODULE_PATH
+ STRING(REPLACE "path = " "" SUBMODULE_PATH "${_path}")
+
+ # Grab index for matching SUBMODULE_URL
+ LIST(FIND SUBMODULE_LIST_RAW "${_path}" SUBMODULE_INDEX)
+ LIST(GET SUBMODULE_URL_RAW ${SUBMODULE_INDEX} _url)
+
+ # Parse SUBMODULE_URL
+ STRING(REPLACE "url = " "" SUBMODULE_URL "${_url}")
- # Remove submodules from validation as specified in -DSKIP_SUBMODULES=foo;bar
SET(SKIP false)
+
+ # Loop over skipped plugins, add to SKIP_SUBMODULES (e.g. -DPLUGIN_LIST=foo;bar)
+ IF(${SUBMODULE_PATH} MATCHES "^plugins/")
+ SET(REMOVE_PLUGIN true)
+ FOREACH(_plugin ${PLUGIN_LIST})
+ IF(_plugin STREQUAL "")
+ CONTINUE()
+ ENDIF()
+ IF(${SUBMODULE_PATH} MATCHES "${_plugin}")
+ SET(REMOVE_PLUGIN false)
+ ENDIF()
+ ENDFOREACH()
+
+ IF(REMOVE_PLUGIN)
+ LIST(APPEND SKIP_SUBMODULES "${SUBMODULE_PATH}")
+ ENDIF()
+ ENDIF()
+
+ # Finally, loop and mark "SKIP" on match
IF(SKIP_SUBMODULES)
FOREACH(_skip ${SKIP_SUBMODULES})
- IF(${SUBMODULE_PATH} MATCHES ${_skip})
- MESSAGE("-- Skipping ${SUBMODULE_PATH} matches \"${_skip}\"")
+ IF("${SUBMODULE_PATH}" MATCHES "${_skip}")
+ MESSAGE("-- Skipping ${SUBMODULE_PATH} matches \"${_skip}\" (absent in PLUGIN_LIST)")
SET(SKIP true)
+ BREAK()
ENDIF()
ENDFOREACH()
ENDIF()
- IF(NOT SKIP)
- LIST(INSERT SUBMODULE_LIST ${SUBMODULE_INDEX} ${SUBMODULE_PATH})
- LIST(INSERT SUBMODULE_URL_LIST ${SUBMODULE_INDEX} ${SUBMODULE_URL})
- ENDIF()
- LIST(REMOVE_ITEM SUBMODULE_LIST ${_part})
- LIST(REMOVE_ITEM SUBMODULE_URL_LIST ${_url})
-ENDFOREACH()
+ IF(NOT SKIP)
+ LIST(APPEND SUBMODULE_LIST "${SUBMODULE_PATH}")
+ LIST(APPEND SUBMODULE_URL "${SUBMODULE_URL}")
+ ENDIF()
+ENDFOREACH()
# Once called, status is stored in GIT_RESULT respectively.
# Note: Git likes to write to stderr. Don't assume stderr is error; Check GIT_RESULT instead.
-MACRO(GIT_SUBMODULE SUBMODULE_PATH FORCE_DEINIT FORCE_REMOTE)
+MACRO(GIT_SUBMODULE SUBMODULE_PATH FORCE_DEINIT FORCE_REMOTE FULL_CLONE)
FIND_PACKAGE(Git REQUIRED)
# Handle missing commits
SET(FORCE_REMOTE_FLAG "${FORCE_REMOTE}")
+ SET(FULL_CLONE_FLAG "${FULL_CLONE}")
IF(FORCE_REMOTE_FLAG)
MESSAGE("-- Adding remote submodulefix to ${SUBMODULE_PATH}")
EXECUTE_PROCESS(
- COMMAND ${GIT_EXECUTABLE} remote rm submodulefix
- COMMAND ${GIT_EXECUTABLE} remote add submodulefix ${FORCE_REMOTE}
- COMMAND ${GIT_EXECUTABLE} fetch submodulefix
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}
+ COMMAND "${GIT_EXECUTABLE}" remote rm submodulefix
+ COMMAND "${GIT_EXECUTABLE}" remote add submodulefix ${FORCE_REMOTE}
+ COMMAND "${GIT_EXECUTABLE}" fetch submodulefix
+ WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}"
OUTPUT_QUIET ERROR_QUIET
)
# Recurse
- GIT_SUBMODULE(${SUBMODULE_PATH} false false)
+ GIT_SUBMODULE(${SUBMODULE_PATH} false false ${FULL_CLONE_FLAG})
ELSEIF(${FORCE_DEINIT})
MESSAGE("-- Resetting ${SUBMODULE_PATH}")
EXECUTE_PROCESS(
- COMMAND ${GIT_EXECUTABLE} submodule deinit -f ${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMAND "${GIT_EXECUTABLE}" submodule deinit -f "${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}"
+ WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_QUIET
)
+ MESSAGE("-- Deleting ${CMAKE_SOURCE_DIR}/.git/${SUBMODULE_PATH}")
+ FILE(REMOVE_RECURSE "${CMAKE_SOURCE_DIR}/.git/modules/${SUBMODULE_PATH}")
# Recurse
- GIT_SUBMODULE(${SUBMODULE_PATH} false false)
+ GIT_SUBMODULE(${SUBMODULE_PATH} false false true)
ELSE()
# Try to use the depth switch
- SET(DEPTH_CMD "")
+ IF(NO_SHALLOW_CLONE OR GIT_VERSION_STRING VERSION_LESS "1.8.4")
+ # Shallow submodules were introduced in 1.8.4
MESSAGE("-- Fetching ${SUBMODULE_PATH}")
- IF(DEPTH_VALUE)
- SET(DEPTH_CMD "--depth" )
+ SET(DEPTH_CMD "")
+ SET(DEPTH_VAL "")
+ ELSEIF(FULL_CLONE_FLAG)
+ # Depth doesn't revert easily... It should be "--no-recommend-shallow"
+ # but it's ignored by nested submodules, use the highest value instead.
+ MESSAGE("-- Fetching ${SUBMODULE_PATH}")
+ SET(DEPTH_CMD "--depth")
+ SET(DEPTH_VAL "2147483647")
+ ELSE()
MESSAGE("-- Fetching ${SUBMODULE_PATH} @ --depth ${DEPTH_VALUE}")
+ SET(DEPTH_CMD "--depth")
+ SET(DEPTH_VAL "${DEPTH_VALUE}")
ENDIF()
EXECUTE_PROCESS(
- COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive ${DEPTH_CMD} ${DEPTH_VALUE} ${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMAND "${GIT_EXECUTABLE}" submodule update --init --recursive ${DEPTH_CMD} ${DEPTH_VAL} "${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}"
+ WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE GIT_RESULT
OUTPUT_VARIABLE GIT_STDOUT
ERROR_VARIABLE GIT_STDERR
@@ -124,7 +164,7 @@ SET(RETRY_PHRASES "Failed to recurse;cannot create directory;already exists;${MI
# Attempt to do lazy clone
FOREACH(_submodule ${SUBMODULE_LIST})
- STRING(REPLACE "/" ";" PATH_PARTS ${_submodule})
+ STRING(REPLACE "/" ";" PATH_PARTS "${_submodule}")
LIST(REVERSE PATH_PARTS)
LIST(GET PATH_PARTS 0 SUBMODULE_NAME)
@@ -138,14 +178,12 @@ FOREACH(_submodule ${SUBMODULE_LIST})
ENDIF()
ENDFOREACH()
IF(NOT CRUMB_FOUND)
- GIT_SUBMODULE(${_submodule} false false)
+ GIT_SUBMODULE("${_submodule}" false false false)
SET(COUNTED 0)
- SET(COUNTING "")
# Handle edge-cases where submodule didn't clone properly or re-uses a non-empty directory
WHILE(NOT GIT_RESULT EQUAL 0 AND COUNTED LESS MAX_ATTEMPTS)
- LIST(APPEND COUNTING "x")
- LIST(LENGTH COUNTING COUNTED)
+ MATH(EXPR COUNTED "${COUNTED}+1")
SET(MISSING_COMMIT false)
FOREACH(_phrase ${MISSING_COMMIT_PHRASES})
IF("${GIT_MESSAGE}" MATCHES "${_phrase}")
@@ -154,25 +192,22 @@ FOREACH(_submodule ${SUBMODULE_LIST})
ENDIF()
ENDFOREACH()
FOREACH(_phrase ${RETRY_PHRASES})
- IF(${MISSING_COMMIT})
+ IF(${MISSING_COMMIT} AND COUNTED LESS 2)
LIST(FIND SUBMODULE_LIST ${_submodule} SUBMODULE_INDEX)
LIST(GET SUBMODULE_URL_LIST ${SUBMODULE_INDEX} SUBMODULE_URL)
MESSAGE("-- Retrying ${_submodule} using 'remote add submodulefix' (attempt ${COUNTED} of ${MAX_ATTEMPTS})...")
- GIT_SUBMODULE(${_submodule} false "${SUBMODULE_URL}")
+ GIT_SUBMODULE("${_submodule}" false "${SUBMODULE_URL}" false)
BREAK()
ELSEIF("${GIT_MESSAGE}" MATCHES "${_phrase}")
MESSAGE("-- Retrying ${_submodule} using 'deinit' (attempt ${COUNTED} of ${MAX_ATTEMPTS})...")
-
- # Shallow submodules were introduced in 1.8.4
- # Shallow commits can fail to clone from non-default branches, only try once
- IF(GIT_VERSION_STRING VERSION_GREATER "1.8.3" AND COUNTED LESS 2)
- # Try a shallow submodule clone
+ IF(COUNTED LESS 2)
+ SET(FULL_CLONE false)
ELSE()
- UNSET(DEPTH_VALUE)
+ SET(FULL_CLONE true)
ENDIF()
- GIT_SUBMODULE(${_submodule} true false)
+ GIT_SUBMODULE("${_submodule}" true false ${FULL_CLONE})
BREAK()
ENDIF()
ENDFOREACH()
diff --git a/cmake/modules/CreateTempFile.cmake b/cmake/modules/CreateTempFile.cmake
new file mode 100644
index 000000000..5210342ac
--- /dev/null
+++ b/cmake/modules/CreateTempFile.cmake
@@ -0,0 +1,21 @@
+function(CreateTempFilePath)
+ set(options CONFIG_SUFFIX)
+ set(oneValueArgs OUTPUT_VAR TAG)
+ set(multiValueArgs CONTENT)
+ cmake_parse_arguments(TEMP "${options}" "${oneValueArgs}"
+ "${multiValueArgs}" ${ARGN} )
+
+ # Use hash to create a unique identifier
+ # for this file.
+ string(SHA1 hashed_content "${TEMP_CONTENT}")
+
+ set(file_name "${CMAKE_BINARY_DIR}/${TEMP_TAG}_${hashed_content}")
+ set(${TEMP_OUTPUT_VAR} "${file_name}" PARENT_SCOPE)
+ if(CONFIG_SUFFIX)
+ set(file_name "${file_name}_$")
+ endif()
+
+ file(GENERATE OUTPUT "${file_name}"
+ CONTENT "${TEMP_CONTENT}")
+
+endfunction()
diff --git a/cmake/modules/DefineInstallVar.cmake b/cmake/modules/DefineInstallVar.cmake
new file mode 100644
index 000000000..b13cb1d52
--- /dev/null
+++ b/cmake/modules/DefineInstallVar.cmake
@@ -0,0 +1,31 @@
+# This functions forwards a variable to
+# the install stage.
+# Parameters:
+# CONTENT: Variable content.
+# NAME: Variable name.
+# Options:
+# GENERATOR_EXPRESSION: Support generator expression for CONTENT.
+function(DEFINE_INSTALL_VAR)
+ set(options GENERATOR_EXPRESSION)
+ set(oneValueArgs NAME )
+ set(multiValueArgs CONTENT)
+ cmake_parse_arguments(VAR "${options}" "${oneValueArgs}"
+ "${multiValueArgs}" ${ARGN} )
+
+ # install(CODE) does not support generator expression in ver<3.14
+ if(VAR_GENERATOR_EXPRESSION AND ${CMAKE_VERSION} VERSION_LESS "3.14.0")
+ include(CreateTempFile)
+ if(CMAKE_CONFIGURATION_TYPES) # in case of multi-config generators like MSVC generators
+ CreateTempFilePath(OUTPUT_VAR file_path TAG "${VAR_NAME}" CONTENT "${VAR_CONTENT}" CONFIG_SUFFIX)
+ install(CODE "file(READ \"${file_path}_\${CMAKE_INSTALL_CONFIG_NAME}\" \"${VAR_NAME}\")")
+ else()
+ CreateTempFilePath(OUTPUT_VAR file_path TAG "${VAR_NAME}" CONTENT "${VAR_CONTENT}")
+ install(CODE "file(READ \"${file_path}\" \"${VAR_NAME}\")")
+ endif()
+ else()
+ if(VAR_GENERATOR_EXPRESSION)
+ cmake_policy(SET CMP0087 NEW)
+ endif()
+ install(CODE "set(\"${VAR_NAME}\" \"${VAR_CONTENT}\")")
+ endif()
+endfunction()
diff --git a/cmake/modules/DetectMachine.cmake b/cmake/modules/DetectMachine.cmake
index f3458165b..86807b757 100644
--- a/cmake/modules/DetectMachine.cmake
+++ b/cmake/modules/DetectMachine.cmake
@@ -4,6 +4,8 @@ ELSEIF(APPLE)
SET(LMMS_BUILD_APPLE 1)
ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
SET(LMMS_BUILD_OPENBSD 1)
+ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
+ SET(LMMS_BUILD_FREEBSD 1)
ELSEIF(HAIKU)
SET(LMMS_BUILD_HAIKU 1)
ELSE()
@@ -30,6 +32,25 @@ IF(WIN32)
ELSE(WIN64)
SET(IS_X86 TRUE)
ENDIF(WIN64)
+
+ if(MSVC)
+ SET(MSVC_VER ${CMAKE_CXX_COMPILER_VERSION})
+
+ IF(MSVC_VER VERSION_GREATER 19.20 OR MSVC_VER VERSION_EQUAL 19.20)
+ SET(LMMS_MSVC_GENERATOR "Visual Studio 16 2019")
+ SET(LMMS_MSVC_YEAR 2019) # Qt only provides binaries for MSVC 2017, but 2019 is binary compatible
+ ELSEIF(MSVC_VER VERSION_GREATER 19.10 OR MSVC_VER VERSION_EQUAL 19.10)
+ SET(LMMS_MSVC_GENERATOR "Visual Studio 15 2017")
+ SET(LMMS_MSVC_YEAR 2017)
+ ELSEIF(MSVC_VER VERSION_GREATER 19.0 OR MSVC_VER VERSION_EQUAL 19.0)
+ SET(LMMS_MSVC_GENERATOR "Visual Studio 14 2015")
+ SET(LMMS_MSVC_YEAR 2015)
+ ELSE()
+ MESSAGE(SEND_WARNING "Can't detect MSVC version: ${MSVC_VER}")
+ ENDIF()
+
+ unset(MSVC_VER)
+ endif()
ELSE(WIN32)
EXEC_PROGRAM( ${CMAKE_C_COMPILER} ARGS "-dumpmachine ${CMAKE_C_FLAGS}" OUTPUT_VARIABLE Machine )
MESSAGE("Machine: ${Machine}")
diff --git a/cmake/modules/InstallDependencies.cmake b/cmake/modules/InstallDependencies.cmake
new file mode 100644
index 000000000..791041bb2
--- /dev/null
+++ b/cmake/modules/InstallDependencies.cmake
@@ -0,0 +1,184 @@
+include(GetPrerequisites)
+include(CMakeParseArguments)
+
+CMAKE_POLICY(SET CMP0011 NEW)
+CMAKE_POLICY(SET CMP0057 NEW)
+
+function(make_absolute var)
+ get_filename_component(abs "${${var}}" ABSOLUTE BASE_DIR "${CMAKE_INSTALL_PREFIX}")
+ set(${var} ${abs} PARENT_SCOPE)
+endfunction()
+
+# Reads lines of a file into a list, skipping '#' comment lines
+function(READ_LIST_FILE FILE VAR)
+ file(STRINGS "${FILE}" list)
+
+ set(result "")
+ foreach(item ${list})
+ string(STRIP "${item}" item)
+ if(item STREQUAL "" OR item MATCHES "^\#")
+ continue()
+ endif()
+ list(APPEND result "${item}")
+ endforeach()
+
+ set(${VAR} ${result} PARENT_SCOPE)
+endfunction()
+
+function(make_all_absolute list_var)
+ set(result "")
+ foreach(file ${${list_var}})
+ make_absolute(file)
+ list(APPEND result ${file})
+ endforeach()
+ set(${list_var} ${result} PARENT_SCOPE)
+endfunction()
+
+if(CMAKE_BINARY_DIR)
+ set(tmp_lib_dir "${CMAKE_BINARY_DIR}/bundled-libraries")
+elseif(CMAKE_HOST_UNIX)
+ set(tmp_lib_dir "/tmp/bundled-libraries")
+elseif(DEFINED ENV{TEMP})
+ set(tmp_lib_dir "$ENV{TMP}/bundled-libraries")
+else()
+ message(FATAL_ERROR "Can't find a temp dir for libraries")
+endif()
+
+# Like file(INSTALL), but resolves symlinks
+function(install_file_resolved file destination)
+
+ get_filename_component(file_name "${file}" NAME)
+ if(IS_SYMLINK "${file}")
+ get_filename_component(real_path "${file}" REALPATH)
+ get_filename_component(real_name "${real_path}" NAME)
+ file(COPY "${real_path}" DESTINATION "${tmp_lib_dir}")
+ file(RENAME "${tmp_lib_dir}/${real_name}" "${tmp_lib_dir}/${file_name}")
+ set(file_path "${tmp_lib_dir}/${file_name}")
+ else()
+ set(file_path "${file}")
+ endif()
+
+ file(INSTALL "${file_path}" DESTINATION "${destination}")
+endfunction()
+
+function(install_resolved)
+ cmake_parse_arguments("" "" "DESTINATION" "FILES" ${ARGN})
+ foreach(file ${_FILES})
+ install_file_resolved("${file}" "${_DESTINATION}")
+ endforeach()
+endfunction()
+
+if(CMAKE_CROSSCOMPILING)
+ # If we're cross-compiling, GetPrerequisites may not be able to find system libraries such as kernel32.dll because
+ # they're supplied by the toolchain. To suppress thousands of lines of warnings being printed to the console, we
+ # override gp_resolved_file_type to return "system" for any library in ${IGNORE_LIBS} without trying to resolve the
+ # file first.
+ # GetPrerequisites supports using an override function called gp_resolved_file_type_override, but it's not suited
+ # for our purpose because it's only called by gp_resolved_file_type *after* trying to resolve the file.
+ function(gp_resolved_file_type original_file file exepath dirs type_var)
+ set(file_find "${file}")
+ if(_IGNORE_CASE)
+ # On case-insensitive systems, convert to upper characters to respect it
+ string(TOUPPER "${file_find}" file_find)
+ endif()
+ SET(IGNORE_LIBS ${_IGNORE_LIBS} CACHE INTERNAL "Ignored library names" FORCE)
+ if(IGNORE_LIBS AND ${file_find} IN_LIST IGNORE_LIBS)
+ set(${type_var} system PARENT_SCOPE)
+ else()
+ #_gp_resolved_file_type(${ARGV})
+ _gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "${dirs}" "${type_var}" ${ARGN})
+ endif()
+ endfunction()
+endif()
+
+function(INSTALL_DEPENDENCIES)
+ cmake_parse_arguments("" "INCLUDE_SYSTEM;IGNORE_CASE" "GP_TOOL;DESTINATION;IGNORE_LIBS_FILE" "FILES;LIB_DIRS;SEARCH_PATHS;IGNORE_LIBS" ${ARGN})
+
+ # Make paths absolute
+ make_absolute(_DESTINATION)
+ make_all_absolute(_FILES)
+ make_all_absolute(_LIB_DIRS)
+ make_all_absolute(_SEARCH_PATHS)
+
+ if(_INCLUDE_SYSTEM)
+ set(EXCLUDE_SYSTEM 0)
+ else()
+ set(EXCLUDE_SYSTEM 1)
+ endif()
+
+ if(_IGNORE_LIBS_FILE)
+ READ_LIST_FILE("${_IGNORE_LIBS_FILE}" _IGNORE_LIBS)
+ if(_IGNORE_CASE)
+ # On case-insensitive systems, convert to upper characters to respect it
+ string(TOUPPER "${_IGNORE_LIBS}" _IGNORE_LIBS)
+ endif()
+ SET(IGNORE_LIBS ${_IGNORE_LIBS} CACHE INTERNAL "Ignored library names" FORCE)
+ endif()
+
+ if(_GP_TOOL)
+ set(gp_tool "${_GP_TOOL}")
+ endif()
+
+ set(prereqs "")
+ foreach(file ${_FILES})
+ get_filename_component(file_name "${file}" NAME)
+ message("-- Finding prerequisites of ${file_name}")
+ find_prerequisites("${file}" _prereqs
+ ${EXCLUDE_SYSTEM} # exclude system files
+ 1 # recurse
+ ""
+ "${_LIB_DIRS}"
+ "${_SEARCH_PATHS}"
+ "${_IGNORE_LIBS}"
+ )
+
+ list(APPEND prereqs ${_prereqs})
+ endforeach()
+
+ list(REMOVE_DUPLICATES prereqs)
+
+ foreach(prereq ${prereqs})
+ get_filename_component(prereq_name "${prereq}" NAME)
+
+ foreach(rpath ${_SEARCH_PATHS})
+ if(EXISTS "${rpath}/${prereq_name}")
+ list(REMOVE_ITEM prereqs "${prereq}")
+ break()
+ endif()
+ endforeach()
+ endforeach()
+
+ #file(INSTALL ${prereqs} DESTINATION ${_DESTINATION})
+ install_resolved(FILES ${prereqs} DESTINATION "${_DESTINATION}")
+endfunction()
+
+# Like get_prerequisites, but returns full paths
+function(FIND_PREREQUISITES target RESULT_VAR exclude_system recurse
+ exepath dirs rpaths)
+ set(RESULTS)
+
+ get_prerequisites("${target}" _prereqs ${exclude_system} ${recurse}
+ "" "${dirs}" "${rpaths}")
+
+ foreach(prereq ${_prereqs})
+ get_filename_component(prereq_name "${prereq}" NAME)
+ if(_IGNORE_CASE)
+ # Windows is case insensitive.
+ # Use upper characters to respect it.
+ string(TOUPPER "${prereq_name}" prereq_name)
+ endif()
+ if("${prereq_name}" IN_LIST IGNORE_LIBS)
+ continue()
+ endif()
+
+ gp_resolve_item("${LIB_DLL}" "${prereq}" "" "${dirs}" RESOLVED_PREREQ "${rpaths}")
+
+ if(RESOLVED_PREREQ AND IS_ABSOLUTE ${RESOLVED_PREREQ} AND EXISTS ${RESOLVED_PREREQ})
+ list(APPEND RESULTS ${RESOLVED_PREREQ})
+ else()
+ message(FATAL_ERROR "Can't resolve dependency ${prereq}.")
+ endif()
+ endforeach()
+
+ set(${RESULT_VAR} ${RESULTS} PARENT_SCOPE)
+endfunction()
diff --git a/cmake/modules/InstallTargetDependencies.cmake b/cmake/modules/InstallTargetDependencies.cmake
new file mode 100644
index 000000000..9665a0b87
--- /dev/null
+++ b/cmake/modules/InstallTargetDependencies.cmake
@@ -0,0 +1,89 @@
+include(DefineInstallVar)
+
+SET(DEFAULT_SEARCH_DIRECTORIES "${BIN_DIR}" "${LIB_DIR}" "${CMAKE_FIND_ROOT_PATH}" "${CMAKE_PREFIX_PATH}")
+SET(DEFAULT_SEARCH_SUFFIXES "bin" "lib" "../bin")
+
+# Like INSTALL_DEPENDENCIES but can be called from regular cmake code
+# (instead of install(CODE)), takes targets instead of files,
+# takes care of configuring search paths, and other platform-specific tweaks.
+# Arguments:
+# TARGETS: list of cmake targets to install.
+# NAME: unique string for this install.
+# DESTINATION: directory path to install the binaries to.
+# LIB_DIRS: list of paths for looking up dependencies.
+# LIB_DIRS_SUFFIXES: list of possible suffixes for LIB_DIRS entries.
+# NO_DEFAULT_PATHS: supply this value to avoid adding DEFAULT_SEARCH_DIRECTORIES
+# to LIB_DIRS and DEFAULT_SEARCH_SUFFIXES to LIB_DIRS_SUFFIXES.
+FUNCTION(INSTALL_TARGET_DEPENDENCIES)
+ set(options NO_DEFAULT_PATHS)
+ set(oneValueArgs NAME)
+ set(multiValueArgs TARGETS DESTINATION LIB_DIRS_SUFFIXES LIB_DIRS)
+ cmake_parse_arguments(DEPS "${options}" "${oneValueArgs}"
+ "${multiValueArgs}" ${ARGN} )
+
+ if(NOT DEPS_LIB_DIRS)
+ set(DEPS_LIB_DIRS "")
+ endif()
+
+ # Set default values.
+ if(NOT DEPS_NO_DEFAULT_PATHS)
+ list(APPEND DEPS_LIB_DIRS ${DEFAULT_SEARCH_DIRECTORIES})
+ set(DEPS_LIB_DIRS_SUFFIXES "${DEPS_LIB_DIRS_SUFFIXES}" ${DEFAULT_SEARCH_SUFFIXES})
+ endif()
+
+ FOREACH(TARGET ${DEPS_TARGETS})
+ IF(NOT TARGET ${TARGET})
+ message(FATAL_ERROR "Not a target: ${TARGET}")
+ ENDIF()
+
+ # Collect target output files.
+ LIST(APPEND DEPLOY_TARGETS "$")
+
+ # Collect target link directories
+ get_target_property(target_libs ${TARGET} LINK_LIBRARIES)
+
+ foreach(lib ${target_libs})
+ if(TARGET ${lib} OR NOT IS_ABSOLUTE ${lib})
+ continue()
+ endif()
+
+ get_filename_component(lib_dir ${lib} PATH)
+ list(APPEND DEPS_LIB_DIRS ${lib_dir})
+ endforeach()
+ ENDFOREACH()
+
+ LIST(APPEND DEPS_LIB_DIRS ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES})
+
+ FOREACH(LIB_PATH ${DEPS_LIB_DIRS})
+ FOREACH(suffix ${DEPS_LIB_DIRS_SUFFIXES})
+ list(APPEND DEPS_LIB_DIRS "${LIB_PATH}/${suffix}")
+ ENDFOREACH()
+ ENDFOREACH()
+
+ DEFINE_INSTALL_VAR(NAME "DEPLOY_FILES" CONTENT "${DEPLOY_TARGETS}" GENERATOR_EXPRESSION)
+
+ LIST(REMOVE_DUPLICATES DEPS_LIB_DIRS)
+
+ IF(LMMS_BUILD_LINUX)
+ FILE(DOWNLOAD "https://raw.githubusercontent.com/AppImage/AppImages/master/excludelist"
+ "${CMAKE_BINARY_DIR}/excludelist")
+ SET(additional_args INCLUDE_SYSTEM IGNORE_LIBS_FILE ${CMAKE_BINARY_DIR}/excludelist)
+ ELSEIF(LMMS_BUILD_WIN32)
+ SET(additional_args IGNORE_CASE IGNORE_LIBS_FILE "${LMMS_SOURCE_DIR}/cmake/install/excludelist-win")
+ IF(CMAKE_CROSSCOMPILING)
+ SET(additional_args "${additional_args}" GP_TOOL objdump)
+ ENDIF()
+ ENDIF()
+
+ INSTALL(CODE "
+ INCLUDE(\"${LMMS_SOURCE_DIR}/cmake/modules/InstallDependencies.cmake\")
+
+ INSTALL_DEPENDENCIES(
+ FILES \"\${DEPLOY_FILES}\"
+ DESTINATION \"${DEPS_DESTINATION}\"
+ LIB_DIRS \"${DEPS_LIB_DIRS}\"
+ SEARCH_PATHS \"${DEPS_SEARCH_PATHS}\"
+ ${additional_args}
+ )
+ ")
+ENDFUNCTION()
diff --git a/cmake/modules/PluginList.cmake b/cmake/modules/PluginList.cmake
new file mode 100644
index 000000000..c82bba329
--- /dev/null
+++ b/cmake/modules/PluginList.cmake
@@ -0,0 +1,104 @@
+# Provides a fast mechanism for filtering the plugins used at build-time
+SET(PLUGIN_LIST "" CACHE STRING "List of plug-ins to build")
+STRING(REPLACE " " ";" PLUGIN_LIST "${PLUGIN_LIST}")
+OPTION(LMMS_MINIMAL "Build a minimal list of plug-ins" OFF)
+OPTION(LIST_PLUGINS "Lists the available plugins for building" OFF)
+
+SET(MINIMAL_LIST
+ audio_file_processor
+ kicker
+ triple_oscillator
+)
+
+IF(LMMS_MINIMAL)
+ IF("${PLUGIN_LIST}" STREQUAL "")
+ STRING(REPLACE ";" " " MINIMAL_LIST_STRING "${MINIMAL_LIST}")
+ MESSAGE(
+"-- Using minimal plug-ins: ${MINIMAL_LIST_STRING}\n"
+" Note: You can specify specific plug-ins using -DPLUGIN_LIST=\"foo bar\""
+ )
+ ENDIF()
+ SET(PLUGIN_LIST ${MINIMAL_LIST} ${PLUGIN_LIST})
+ENDIF()
+
+SET(LMMS_PLUGIN_LIST
+ ${MINIMAL_LIST}
+ Amplifier
+ BassBooster
+ bit_invader
+ Bitcrush
+ carlabase
+ carlapatchbay
+ carlarack
+ CrossoverEQ
+ Delay
+ DualFilter
+ dynamics_processor
+ Eq
+ Flanger
+ HydrogenImport
+ ladspa_browser
+ LadspaEffect
+ lb302
+ MidiImport
+ MidiExport
+ MultitapEcho
+ monstro
+ nes
+ OpulenZ
+ organic
+ FreeBoy
+ patman
+ peak_controller_effect
+ GigPlayer
+ ReverbSC
+ sf2_player
+ sfxr
+ sid
+ SpectrumAnalyzer
+ stereo_enhancer
+ stereo_matrix
+ stk
+ vst_base
+ vestige
+ VstEffect
+ watsyn
+ waveshaper
+ vibed
+ Xpressive
+ zynaddsubfx
+)
+
+IF("${PLUGIN_LIST}" STREQUAL "")
+ SET(PLUGIN_LIST ${LMMS_PLUGIN_LIST})
+ENDIF()
+
+MACRO(LIST_ALL_PLUGINS)
+ MESSAGE("\n\nAll possible -DPLUGIN_LIST values")
+ MESSAGE("\n KEYWORD:")
+ MESSAGE(" -DLMMS_MINIMAL=True")
+ FOREACH(item IN LISTS MINIMAL_LIST)
+ MESSAGE(" ${item}")
+ ENDFOREACH()
+ MESSAGE("\n NAME:")
+ FOREACH(item IN LISTS LMMS_PLUGIN_LIST)
+ MESSAGE(" ${item}")
+ ENDFOREACH()
+ MESSAGE("\nNote: This value also impacts the fetching of git submodules.\n")
+ MESSAGE(FATAL_ERROR "Information was requested, aborting build!")
+ENDMACRO()
+
+IF(LIST_PLUGINS)
+ UNSET(LIST_PLUGINS CACHE)
+ LIST_ALL_PLUGINS()
+ENDIF()
+
+IF(MSVC)
+ SET(MSVC_INCOMPATIBLE_PLUGINS
+ LadspaEffect
+ zynaddsubfx
+ )
+ message(WARNING "Compiling with MSVC. The following plugins are not available: ${MSVC_INCOMPATIBLE_PLUGINS}")
+ LIST(REMOVE_ITEM PLUGIN_LIST ${MSVC_INCOMPATIBLE_PLUGINS})
+ENDIF()
+
diff --git a/cmake/modules/winegcc_wrapper.in b/cmake/modules/winegcc_wrapper.in
index d32aec664..7677e4c37 100755
--- a/cmake/modules/winegcc_wrapper.in
+++ b/cmake/modules/winegcc_wrapper.in
@@ -58,6 +58,9 @@ if [ "$win64" = true ] && [ "$no_link" != true ]; then
extra_args="$extra_args @WINE_64_FLAGS@"
fi
+# Work around https://bugs.winehq.org/show_bug.cgi?id=47710
+extra_args="$extra_args -D__WIDL_objidl_generated_name_0000000C="
+
# Run winegcc
export WINEBUILD=@WINE_BUILD@
@WINE_CXX@ $extra_args $args
diff --git a/cmake/nsis/CMakeLists.txt b/cmake/nsis/CMakeLists.txt
index ac628d549..3fcb4b2f3 100644
--- a/cmake/nsis/CMakeLists.txt
+++ b/cmake/nsis/CMakeLists.txt
@@ -1,3 +1,8 @@
+SET(WIN_PLATFORM mingw)
+if(LMMS_MSVC_YEAR)
+ SET(WIN_PLATFORM "msvc${LMMS_MSVC_YEAR}")
+endif()
+
SET(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/cmake/nsis/nsis_branding.bmp")
IF(MSVC)
STRING(REPLACE "/" "\\\\" CPACK_PACKAGE_ICON ${CPACK_PACKAGE_ICON})
@@ -15,7 +20,7 @@ SET(CPACK_NSIS_DEFINES "
!include FileAssociation.nsh
!include LogicLib.nsh
!include WinVer.nsh")
-SET(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}-win32")
+SET(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}-${WIN_PLATFORM}-win32")
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
\\\${registerExtension} \\\"$INSTDIR\\\\${CMAKE_PROJECT_NAME}.exe\\\" \\\".mmp\\\" \\\"${PROJECT_NAME_UCASE} Project\\\"
\\\${registerExtension} \\\"$INSTDIR\\\\${CMAKE_PROJECT_NAME}.exe\\\" \\\".mmpz\\\" \\\"${PROJECT_NAME_UCASE} Project (compressed)\\\"
@@ -31,7 +36,7 @@ SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "
" PARENT_SCOPE)
IF(WIN64)
- SET(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}-win64")
+ SET(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}-${WIN_PLATFORM}-win64")
SET(CPACK_INSTALL_FIX "$PROGRAMFILES64\\\\${CPACK_PACKAGE_INSTALL_DIRECTORY}\\\\")
SET(CPACK_NSIS_DEFINES "
${CPACK_NSIS_DEFINES}
diff --git a/cmake/postinstall/CMakeLists.txt b/cmake/postinstall/CMakeLists.txt
deleted file mode 100644
index 434d1c54e..000000000
--- a/cmake/postinstall/CMakeLists.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-IF(LMMS_BUILD_APPLE)
- INSTALL(CODE "EXECUTE_PROCESS(COMMAND chmod u+x ${CMAKE_BINARY_DIR}/install_apple.sh)")
- INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_BINARY_DIR}/install_apple.sh)")
-ENDIF()
\ No newline at end of file
diff --git a/data/locale/pl.ts b/data/locale/pl.ts
index 5d9cc51cd..4214718af 100644
--- a/data/locale/pl.ts
+++ b/data/locale/pl.ts
@@ -3108,7 +3108,7 @@ Możesz usunąć i przenieść kanały FX w menu kontekstowym, które jest dost
VELOCITY
- GŁOŚNOŚĆ UDERZENIA
+ PRĘDKOŚĆ
ENABLE MIDI OUTPUT
@@ -10321,4 +10321,4 @@ Kontrolka LED w prawym dolnym rogu edytora kształtu fali pokazuje, czy wybrana
Wzmocnienie wyścia
-
\ No newline at end of file
+
diff --git a/data/locale/ru.ts b/data/locale/ru.ts
index c7ec3a328..f717d598d 100644
--- a/data/locale/ru.ts
+++ b/data/locale/ru.ts
@@ -1664,7 +1664,7 @@ Oe Ai <oeai/at/symbiants/dot/com>
W/D
- НАСЫЩ
+
@@ -1679,7 +1679,7 @@ Oe Ai <oeai/at/symbiants/dot/com>
DECAY
- ЗАТУХАНИЕ
+
diff --git a/data/locale/sv.ts b/data/locale/sv.ts
index eb51c9082..56cf1a0af 100644
--- a/data/locale/sv.ts
+++ b/data/locale/sv.ts
@@ -1658,7 +1658,7 @@ If you're interested in translating LMMS in another language or want to imp
W/D
- B/T
+
@@ -1673,7 +1673,7 @@ If you're interested in translating LMMS in another language or want to imp
DECAY
- FÖRFALL
+
diff --git a/data/locale/uk.ts b/data/locale/uk.ts
index 7271c4946..c088f401c 100644
--- a/data/locale/uk.ts
+++ b/data/locale/uk.ts
@@ -1678,7 +1678,7 @@ If you're interested in translating LMMS in another language or want to imp
DECAY
- ЗГАСАННЯ
+
diff --git a/data/presets/X-Pressive/Ambition.xpf b/data/presets/X-Pressive/Ambition.xpf
deleted file mode 100644
index 2d93f7c05..000000000
--- a/data/presets/X-Pressive/Ambition.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Baby Violin.xpf b/data/presets/X-Pressive/Baby Violin.xpf
deleted file mode 100644
index 2e887d3d2..000000000
--- a/data/presets/X-Pressive/Baby Violin.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Bad Singer.xpf b/data/presets/X-Pressive/Bad Singer.xpf
deleted file mode 100644
index ca9cfd5a3..000000000
--- a/data/presets/X-Pressive/Bad Singer.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Cloud Bass.xpf b/data/presets/X-Pressive/Cloud Bass.xpf
deleted file mode 100644
index 4e444f22a..000000000
--- a/data/presets/X-Pressive/Cloud Bass.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Creature.xpf b/data/presets/X-Pressive/Creature.xpf
deleted file mode 100644
index b667a9c7f..000000000
--- a/data/presets/X-Pressive/Creature.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Electric Shock.xpf b/data/presets/X-Pressive/Electric Shock.xpf
deleted file mode 100644
index 7dea6fe4a..000000000
--- a/data/presets/X-Pressive/Electric Shock.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Faded Colors.xpf b/data/presets/X-Pressive/Faded Colors.xpf
deleted file mode 100644
index 84a37826a..000000000
--- a/data/presets/X-Pressive/Faded Colors.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Fat Flute.xpf b/data/presets/X-Pressive/Fat Flute.xpf
deleted file mode 100644
index 92242114e..000000000
--- a/data/presets/X-Pressive/Fat Flute.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Horn.xpf b/data/presets/X-Pressive/Horn.xpf
deleted file mode 100644
index 099480569..000000000
--- a/data/presets/X-Pressive/Horn.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Piano-Gong.xpf b/data/presets/X-Pressive/Piano-Gong.xpf
deleted file mode 100644
index 241f61a55..000000000
--- a/data/presets/X-Pressive/Piano-Gong.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Rubber Bass.xpf b/data/presets/X-Pressive/Rubber Bass.xpf
deleted file mode 100644
index 73c3648ba..000000000
--- a/data/presets/X-Pressive/Rubber Bass.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Space Echoes.xpf b/data/presets/X-Pressive/Space Echoes.xpf
deleted file mode 100644
index 1d4d2b543..000000000
--- a/data/presets/X-Pressive/Space Echoes.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Speaker Swapper.xpf b/data/presets/X-Pressive/Speaker Swapper.xpf
deleted file mode 100644
index cf80b9304..000000000
--- a/data/presets/X-Pressive/Speaker Swapper.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Toss.xpf b/data/presets/X-Pressive/Toss.xpf
deleted file mode 100644
index 27a0b3f96..000000000
--- a/data/presets/X-Pressive/Toss.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Untuned Bell.xpf b/data/presets/X-Pressive/Untuned Bell.xpf
deleted file mode 100644
index 744927063..000000000
--- a/data/presets/X-Pressive/Untuned Bell.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Vibrato.xpf b/data/presets/X-Pressive/Vibrato.xpf
deleted file mode 100644
index 34795de11..000000000
--- a/data/presets/X-Pressive/Vibrato.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/X-Distorted.xpf b/data/presets/X-Pressive/X-Distorted.xpf
deleted file mode 100644
index cbe3742a5..000000000
--- a/data/presets/X-Pressive/X-Distorted.xpf
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/presets/X-Pressive/Accordion.xpf b/data/presets/Xpressive/Accordion.xpf
similarity index 100%
rename from data/presets/X-Pressive/Accordion.xpf
rename to data/presets/Xpressive/Accordion.xpf
diff --git a/data/presets/Xpressive/Ambition.xpf b/data/presets/Xpressive/Ambition.xpf
new file mode 100644
index 000000000..dd6448977
--- /dev/null
+++ b/data/presets/Xpressive/Ambition.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/Xpressive/Baby Violin.xpf b/data/presets/Xpressive/Baby Violin.xpf
new file mode 100644
index 000000000..45e407fc8
--- /dev/null
+++ b/data/presets/Xpressive/Baby Violin.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/Xpressive/Bad Singer.xpf b/data/presets/Xpressive/Bad Singer.xpf
new file mode 100644
index 000000000..10fe3b308
--- /dev/null
+++ b/data/presets/Xpressive/Bad Singer.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/Xpressive/Cloud Bass.xpf b/data/presets/Xpressive/Cloud Bass.xpf
new file mode 100644
index 000000000..15bf4188d
--- /dev/null
+++ b/data/presets/Xpressive/Cloud Bass.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/Xpressive/Creature.xpf b/data/presets/Xpressive/Creature.xpf
new file mode 100644
index 000000000..bee39f224
--- /dev/null
+++ b/data/presets/Xpressive/Creature.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/X-Pressive/Dream.xpf b/data/presets/Xpressive/Dream.xpf
similarity index 100%
rename from data/presets/X-Pressive/Dream.xpf
rename to data/presets/Xpressive/Dream.xpf
diff --git a/data/presets/Xpressive/Electric Shock.xpf b/data/presets/Xpressive/Electric Shock.xpf
new file mode 100644
index 000000000..3f9aef104
--- /dev/null
+++ b/data/presets/Xpressive/Electric Shock.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/Xpressive/Faded Colors - notes test.xpf b/data/presets/Xpressive/Faded Colors - notes test.xpf
new file mode 100644
index 000000000..de4938f4d
--- /dev/null
+++ b/data/presets/Xpressive/Faded Colors - notes test.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/Xpressive/Faded Colors.xpf b/data/presets/Xpressive/Faded Colors.xpf
new file mode 100644
index 000000000..a514ee438
--- /dev/null
+++ b/data/presets/Xpressive/Faded Colors.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/Xpressive/Fat Flute.xpf b/data/presets/Xpressive/Fat Flute.xpf
new file mode 100644
index 000000000..76d9e2f84
--- /dev/null
+++ b/data/presets/Xpressive/Fat Flute.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/X-Pressive/Frog.xpf b/data/presets/Xpressive/Frog.xpf
similarity index 100%
rename from data/presets/X-Pressive/Frog.xpf
rename to data/presets/Xpressive/Frog.xpf
diff --git a/data/presets/Xpressive/Horn.xpf b/data/presets/Xpressive/Horn.xpf
new file mode 100644
index 000000000..d44b332b2
--- /dev/null
+++ b/data/presets/Xpressive/Horn.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/X-Pressive/Low Battery.xpf b/data/presets/Xpressive/Low Battery.xpf
similarity index 64%
rename from data/presets/X-Pressive/Low Battery.xpf
rename to data/presets/Xpressive/Low Battery.xpf
index c0e648ac9..78f1fc78f 100644
--- a/data/presets/X-Pressive/Low Battery.xpf
+++ b/data/presets/Xpressive/Low Battery.xpf
@@ -1,20 +1,21 @@
-
+
-
-
+
+
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
diff --git a/data/presets/Xpressive/Piano-Gong.xpf b/data/presets/Xpressive/Piano-Gong.xpf
new file mode 100644
index 000000000..a8244b799
--- /dev/null
+++ b/data/presets/Xpressive/Piano-Gong.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/Xpressive/Rubber Bass.xpf b/data/presets/Xpressive/Rubber Bass.xpf
new file mode 100644
index 000000000..4b1409e22
--- /dev/null
+++ b/data/presets/Xpressive/Rubber Bass.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/Xpressive/Space Echoes.xpf b/data/presets/Xpressive/Space Echoes.xpf
new file mode 100644
index 000000000..be6de3653
--- /dev/null
+++ b/data/presets/Xpressive/Space Echoes.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/Xpressive/Speaker Swapper.xpf b/data/presets/Xpressive/Speaker Swapper.xpf
new file mode 100644
index 000000000..d4da5aa2f
--- /dev/null
+++ b/data/presets/Xpressive/Speaker Swapper.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/Xpressive/Toss.xpf b/data/presets/Xpressive/Toss.xpf
new file mode 100644
index 000000000..387e78fd9
--- /dev/null
+++ b/data/presets/Xpressive/Toss.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/Xpressive/Untuned Bell.xpf b/data/presets/Xpressive/Untuned Bell.xpf
new file mode 100644
index 000000000..5dd61ec18
--- /dev/null
+++ b/data/presets/Xpressive/Untuned Bell.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/Xpressive/Vibrato.xpf b/data/presets/Xpressive/Vibrato.xpf
new file mode 100644
index 000000000..a7dda25e9
--- /dev/null
+++ b/data/presets/Xpressive/Vibrato.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/presets/Xpressive/X-Distorted.xpf b/data/presets/Xpressive/X-Distorted.xpf
new file mode 100644
index 000000000..b42495d75
--- /dev/null
+++ b/data/presets/Xpressive/X-Distorted.xpf
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/projects/demos/CapDan/CapDan-TwilightArea-OriginalByAlf42red.mmpz b/data/projects/demos/CapDan/CapDan-TwilightArea-OriginalByAlf42red.mmpz
index 1687e8c34..b4a00e1ea 100644
Binary files a/data/projects/demos/CapDan/CapDan-TwilightArea-OriginalByAlf42red.mmpz and b/data/projects/demos/CapDan/CapDan-TwilightArea-OriginalByAlf42red.mmpz differ
diff --git a/data/projects/demos/CapDan/CapDan-ZeroSumGame-OriginalByZakarra.mmpz b/data/projects/demos/CapDan/CapDan-ZeroSumGame-OriginalByZakarra.mmpz
index 95a29daff..578c4f926 100644
Binary files a/data/projects/demos/CapDan/CapDan-ZeroSumGame-OriginalByZakarra.mmpz and b/data/projects/demos/CapDan/CapDan-ZeroSumGame-OriginalByZakarra.mmpz differ
diff --git a/data/projects/demos/EsoXLB-CPU.mmpz b/data/projects/demos/EsoXLB-CPU.mmpz
index 1c2549027..bc2445e87 100644
Binary files a/data/projects/demos/EsoXLB-CPU.mmpz and b/data/projects/demos/EsoXLB-CPU.mmpz differ
diff --git a/data/projects/demos/Greippi - Krem Kaakkuja (Second Flight Remix).mmpz b/data/projects/demos/Greippi - Krem Kaakkuja (Second Flight Remix).mmpz
index 2f862dd51..6c9f34369 100644
Binary files a/data/projects/demos/Greippi - Krem Kaakkuja (Second Flight Remix).mmpz and b/data/projects/demos/Greippi - Krem Kaakkuja (Second Flight Remix).mmpz differ
diff --git a/data/projects/demos/Impulslogik-Zen.mmpz b/data/projects/demos/Impulslogik-Zen.mmpz
index 05fa375c4..774ce89e3 100644
Binary files a/data/projects/demos/Impulslogik-Zen.mmpz and b/data/projects/demos/Impulslogik-Zen.mmpz differ
diff --git a/data/projects/demos/Jousboxx-BuzzerBeater.mmpz b/data/projects/demos/Jousboxx-BuzzerBeater.mmpz
index 60795608c..59f0d63f6 100644
Binary files a/data/projects/demos/Jousboxx-BuzzerBeater.mmpz and b/data/projects/demos/Jousboxx-BuzzerBeater.mmpz differ
diff --git a/data/projects/demos/Momo64-esp.mmpz b/data/projects/demos/Momo64-esp.mmpz
index 68ae6822c..37d1a52b5 100644
Binary files a/data/projects/demos/Momo64-esp.mmpz and b/data/projects/demos/Momo64-esp.mmpz differ
diff --git a/data/projects/demos/Namitryus-K-Project.mmpz b/data/projects/demos/Namitryus-K-Project.mmpz
index 6d463cbb9..4d62826c9 100644
Binary files a/data/projects/demos/Namitryus-K-Project.mmpz and b/data/projects/demos/Namitryus-K-Project.mmpz differ
diff --git a/data/projects/demos/Oglsdl-Dr8v2.mmpz b/data/projects/demos/Oglsdl-Dr8v2.mmpz
index eb9d7559a..14b1b0e85 100644
Binary files a/data/projects/demos/Oglsdl-Dr8v2.mmpz and b/data/projects/demos/Oglsdl-Dr8v2.mmpz differ
diff --git a/data/projects/demos/Oglsdl-PpTrip.mmpz b/data/projects/demos/Oglsdl-PpTrip.mmpz
index d1baceeba..776aeea2b 100644
Binary files a/data/projects/demos/Oglsdl-PpTrip.mmpz and b/data/projects/demos/Oglsdl-PpTrip.mmpz differ
diff --git a/data/projects/demos/Popsip-Electric Dancer.mmpz b/data/projects/demos/Popsip-Electric Dancer.mmpz
index fc93dd64a..1c935dbe1 100644
Binary files a/data/projects/demos/Popsip-Electric Dancer.mmpz and b/data/projects/demos/Popsip-Electric Dancer.mmpz differ
diff --git a/data/projects/demos/Root84-Initialize.mmpz b/data/projects/demos/Root84-Initialize.mmpz
index 349fcb88f..05200823a 100644
Binary files a/data/projects/demos/Root84-Initialize.mmpz and b/data/projects/demos/Root84-Initialize.mmpz differ
diff --git a/data/projects/demos/Saber-FinalStep.mmpz b/data/projects/demos/Saber-FinalStep.mmpz
index 5e3d1d1ff..05a5022a7 100644
Binary files a/data/projects/demos/Saber-FinalStep.mmpz and b/data/projects/demos/Saber-FinalStep.mmpz differ
diff --git a/data/projects/demos/Settel-InnerRecreation.mmpz b/data/projects/demos/Settel-InnerRecreation.mmpz
index aaa01e0bc..78e1d611d 100644
Binary files a/data/projects/demos/Settel-InnerRecreation.mmpz and b/data/projects/demos/Settel-InnerRecreation.mmpz differ
diff --git a/data/projects/demos/Shovon-ProgressiveHousePluckDemo.mmpz b/data/projects/demos/Shovon-ProgressiveHousePluckDemo.mmpz
index 2d31bd7bd..3ec6a2cff 100644
Binary files a/data/projects/demos/Shovon-ProgressiveHousePluckDemo.mmpz and b/data/projects/demos/Shovon-ProgressiveHousePluckDemo.mmpz differ
diff --git a/data/projects/demos/Skiessi/Skiessi-C64.mmpz b/data/projects/demos/Skiessi/Skiessi-C64.mmpz
index f0b3f5cdb..a9756453b 100644
Binary files a/data/projects/demos/Skiessi/Skiessi-C64.mmpz and b/data/projects/demos/Skiessi/Skiessi-C64.mmpz differ
diff --git a/data/projects/demos/Skiessi/Skiessi-Onion.mmpz b/data/projects/demos/Skiessi/Skiessi-Onion.mmpz
index 0c40fb60a..23a1ddc48 100644
Binary files a/data/projects/demos/Skiessi/Skiessi-Onion.mmpz and b/data/projects/demos/Skiessi/Skiessi-Onion.mmpz differ
diff --git a/data/projects/demos/Skiessi/Skiessi-RandomProjectNumber14253.mmpz b/data/projects/demos/Skiessi/Skiessi-RandomProjectNumber14253.mmpz
index d3c6e0f8d..bc2810567 100644
Binary files a/data/projects/demos/Skiessi/Skiessi-RandomProjectNumber14253.mmpz and b/data/projects/demos/Skiessi/Skiessi-RandomProjectNumber14253.mmpz differ
diff --git a/data/projects/demos/Skiessi/Skiessi-TurningPoint.mmpz b/data/projects/demos/Skiessi/Skiessi-TurningPoint.mmpz
index ee5be4b55..47a0a3672 100644
Binary files a/data/projects/demos/Skiessi/Skiessi-TurningPoint.mmpz and b/data/projects/demos/Skiessi/Skiessi-TurningPoint.mmpz differ
diff --git a/data/projects/demos/Socceroos-Progress.mmpz b/data/projects/demos/Socceroos-Progress.mmpz
index 74ff5774c..854663787 100644
Binary files a/data/projects/demos/Socceroos-Progress.mmpz and b/data/projects/demos/Socceroos-Progress.mmpz differ
diff --git a/data/projects/demos/TameAnderson-MakeMe.mmpz b/data/projects/demos/TameAnderson-MakeMe.mmpz
index de0152818..b69a64e3a 100644
Binary files a/data/projects/demos/TameAnderson-MakeMe.mmpz and b/data/projects/demos/TameAnderson-MakeMe.mmpz differ
diff --git a/data/projects/demos/Thaledric-Armageddon.mmpz b/data/projects/demos/Thaledric-Armageddon.mmpz
index 0e9d5f83f..731ea55f7 100644
Binary files a/data/projects/demos/Thaledric-Armageddon.mmpz and b/data/projects/demos/Thaledric-Armageddon.mmpz differ
diff --git a/data/projects/demos/Thomasso-AxeFromThe80s.mmpz b/data/projects/demos/Thomasso-AxeFromThe80s.mmpz
index af68b8b8b..f7056d38c 100644
Binary files a/data/projects/demos/Thomasso-AxeFromThe80s.mmpz and b/data/projects/demos/Thomasso-AxeFromThe80s.mmpz differ
diff --git a/data/projects/demos/TobyDox-Psycho.mmpz b/data/projects/demos/TobyDox-Psycho.mmpz
index 09ec6b6a6..c4fe7a1c4 100644
Binary files a/data/projects/demos/TobyDox-Psycho.mmpz and b/data/projects/demos/TobyDox-Psycho.mmpz differ
diff --git a/data/projects/demos/unfa-Spoken.mmpz b/data/projects/demos/unfa-Spoken.mmpz
index 659afa03a..66b7589d1 100644
Binary files a/data/projects/demos/unfa-Spoken.mmpz and b/data/projects/demos/unfa-Spoken.mmpz differ
diff --git a/data/projects/shorties/DirtyLove.mmpz b/data/projects/shorties/DirtyLove.mmpz
index 177c05ce5..37b766f4d 100644
Binary files a/data/projects/shorties/DirtyLove.mmpz and b/data/projects/shorties/DirtyLove.mmpz differ
diff --git a/data/projects/shorties/Root84-TrancyLoop.mmpz b/data/projects/shorties/Root84-TrancyLoop.mmpz
index 22bd5f2fa..f5eb032ac 100644
Binary files a/data/projects/shorties/Root84-TrancyLoop.mmpz and b/data/projects/shorties/Root84-TrancyLoop.mmpz differ
diff --git a/data/projects/shorties/Skiessi-222.mmpz b/data/projects/shorties/Skiessi-222.mmpz
index a56833645..a7076949c 100644
Binary files a/data/projects/shorties/Skiessi-222.mmpz and b/data/projects/shorties/Skiessi-222.mmpz differ
diff --git a/data/projects/shorties/Surrender-Main.mmpz b/data/projects/shorties/Surrender-Main.mmpz
index a94df2497..556581170 100644
Binary files a/data/projects/shorties/Surrender-Main.mmpz and b/data/projects/shorties/Surrender-Main.mmpz differ
diff --git a/data/projects/shorties/sv-DnB-Startup.mmpz b/data/projects/shorties/sv-DnB-Startup.mmpz
index c9d8d5970..db32d3452 100644
Binary files a/data/projects/shorties/sv-DnB-Startup.mmpz and b/data/projects/shorties/sv-DnB-Startup.mmpz differ
diff --git a/data/projects/shorties/sv-Trance-Startup.mmpz b/data/projects/shorties/sv-Trance-Startup.mmpz
index c508b1500..bea731461 100644
Binary files a/data/projects/shorties/sv-Trance-Startup.mmpz and b/data/projects/shorties/sv-Trance-Startup.mmpz differ
diff --git a/data/themes/classic/style.css b/data/themes/classic/style.css
index 12d90981d..97d68f6e3 100644
--- a/data/themes/classic/style.css
+++ b/data/themes/classic/style.css
@@ -897,7 +897,4 @@ LmmsPalette {
qproperty-brightText: #4afd85;
qproperty-highlight: #202020;
qproperty-highlightedText: #ffffff;
- /* the next two are used for whatsthis dialogs */
- qproperty-toolTipText: #000;
- qproperty-toolTipBase: #c9c9c9;
}
diff --git a/data/themes/default/style.css b/data/themes/default/style.css
index 5d889295c..f95469201 100644
--- a/data/themes/default/style.css
+++ b/data/themes/default/style.css
@@ -9,16 +9,23 @@ QLabel, QTreeWidget, QListWidget, QGroupBox, QMenuBar {
QTreeView {
outline: none;
+ font-size: 12px;
+}
+
+QTreeWidget::item {
+ padding: 1px;
}
QTreeWidget::item:hover,
QTreeWidget::branch:hover {
background-color: #3C444E;
+ padding-left: 0px;
}
QTreeWidget::item:selected,
QTreeWidget::branch:selected {
background-color: #17793b;
+ padding-left: 0px;
}
QTreeView::branch:has-children:open {
@@ -81,6 +88,12 @@ TextFloat {
}
+/* splash screen text */
+QSplashScreen QLabel {
+ color: white;
+}
+
+
QMenu {
border-top: 2px solid #08993E;
background-color: #15191c;
@@ -920,7 +933,4 @@ LmmsPalette {
qproperty-brightText: #d1d8e4;
qproperty-highlight: #262b30;
qproperty-highlightedText: #d1d8e4;
- /* the next two are used for whatsthis dialogs */
- qproperty-toolTipText: #d1d8e4;
- qproperty-toolTipBase: #101213;
}
diff --git a/debian/control b/debian/control
index 463353df0..880e0d89a 100644
--- a/debian/control
+++ b/debian/control
@@ -37,18 +37,28 @@ Build-Depends:
qttools5-dev,
wine64-tools [amd64] | wine32-tools [i386]
Standards-Version: 4.2.1.4
-Homepage: http://lmms.io/
+Homepage: https://lmms.io/
Vcs-Browser: https://salsa.debian.org/debian-edu-pkg-team/lmms.git
Package: lmms-bin
Architecture: any
-Depends: lmms-common (>= ${source:Version}), ${shlibs:Depends}, ${misc:Depends},
- stk
-Recommends: tap-plugins, caps,
+Depends:
+ lmms-common (>= ${source:Version}),
+ ${shlibs:Depends},
+ ${misc:Depends},
+ stk,
+Recommends:
+ caps,
lmms-vst-server:i386 (>= ${source:Version}),
- lmms-vst-server:amd64 (>= ${source:Version})
-Suggests: fil-plugins, mcp-plugins, omins, freepats, fluid-soundfont-gm,
- ladspa-plugin
+ lmms-vst-server:amd64 (>= ${source:Version}),
+ tap-plugins,
+Suggests:
+ fil-plugins,
+ fluid-soundfont-gm,
+ freepats,
+ ladspa-plugin,
+ mcp-plugins,
+ omins,
Replaces: lmms-common (<< 1.0.0-1)
Breaks: lmms-common (<< 1.0.0-1)
Multi-Arch: allowed
@@ -67,7 +77,9 @@ Description: Linux Multimedia Studio - minimal installation
Package: lmms
Architecture: any
-Depends: lmms-bin, ${misc:Depends}
+Depends:
+ lmms-bin,
+ ${misc:Depends},
Description: Linux Multimedia Studio
LMMS aims to be a free alternative to popular (but commercial and closed-
source) programs like FruityLoops, Cubase and Logic giving you the ability of
@@ -83,7 +95,10 @@ Description: Linux Multimedia Studio
Package: lmms-common
Architecture: all
-Depends: zynaddsubfx-data, ${shlibs:Depends}, ${misc:Depends}
+Depends:
+ ${shlibs:Depends},
+ ${misc:Depends},
+ zynaddsubfx-data,
Pre-Depends: ${misc:Pre-Depends}
Description: Linux Multimedia Studio - common files
LMMS aims to be a free alternative to popular (but commercial and closed-
@@ -101,7 +116,10 @@ Description: Linux Multimedia Studio - common files
Package: lmms-vst-server
Architecture: amd64 i386
-Depends: wine64 [amd64] | wine64-development [amd64] | wine32 [i386] | wine32-development [i386], ${shlibs:Depends}, ${misc:Depends}
+Depends:
+ wine64 [amd64] | wine64-development [amd64] | wine32 [i386] | wine32-development [i386],
+ ${shlibs:Depends},
+ ${misc:Depends},
Recommends: lmms-bin:any
Description: Linux Multimedia Studio - VST server
This package contains a helper application that loads VST plugins.
diff --git a/debian/copyright b/debian/copyright
index 3fbf0917e..01b30459e 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -1,4 +1,4 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: LMMS
Upstream-Contact: https://github.com/LMMS/lmms
Source: https://github.com/LMMS/lmms/tags
@@ -1367,7 +1367,7 @@ License: WOL
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice and this license appear in all source copies.
THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF
- ANY KIND. See http://www.dspguru.com/wol.htm for more information.
+ ANY KIND. See https://www.dspguru.com/wol.htm for more information.
License: non-free
This license does not comply with Debian Free Software Guidelines.
diff --git a/debian/patches/contributors.patch b/debian/patches/contributors.patch
deleted file mode 100644
index d2b55fd9a..000000000
--- a/debian/patches/contributors.patch
+++ /dev/null
@@ -1,89 +0,0 @@
-Description: Add contributors
- The list of contributors is missing from the source tarball. This list is
- generated from upstream repository, running:
- git shortlog -sne v1.1.3 | cut -c8-
- See https://github.com/LMMS/lmms/issues/2914 for more information.
-Author: Javier Serrano Polo
-
-Index: lmms-1.1.3/doc/CONTRIBUTORS
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ lmms-1.1.3/doc/CONTRIBUTORS 2016-07-12 00:41:47.000000000 +0200
-@@ -0,0 +1,77 @@
-+Tobias Doerffel
-+Vesa
-+Javier Serrano Polo
-+Paul Giblock
-+Tres Finocchiaro
-+Lukas W
-+Raine M. Ekman
-+Wong Cho Ching
-+Hannu Haahti
-+Danny McRae
-+Dave French
-+Daniel Winzen
-+Andreas Brandmaier
-+Andrew Kelley
-+Oskar Wallgren
-+Mike Choi
-+Alexandre Almeida
-+NoiseByNorthwest
-+Johannes Lorenz
-+Stian Jørgensrud
-+falkTX
-+Csaba Hruska
-+StakeoutPunch
-+ma2moto
-+mikobuntu
-+8tab <8tab@wp.pl>
-+Matthew Krafczyk
-+Spekular
-+Umcaruje
-+DeRobyJ
-+Jonathan Aquilina
-+ra
-+wongcc966422
-+Gurjot Singh
-+Janne Sinisalo
-+Krzysztof Foltman
-+Lou Herard
-+Paul Wayper
-+Rüdiger Ranft
-+Yann Collette
-+grindhold
-+midi-pascal
-+unfa
-+Ian Sannar
-+Jaroslav Petrnoušek
-+LYF610400210
-+Rafael Ruggiero
-+psyomn
-+quadro
-+sarahkeefe
-+Achim Settelmeier
-+André Hentschel
-+Armin Kazmi
-+Attila Herman
-+Christopher A. Oliver
-+Devin Venable
-+Fastigium
-+Frank Mather
-+Frederik
-+Hexasoft
-+Jens Lang
-+Jesse Dubay
-+Joel Muzzerall
-+Kristi
-+Markus Elfring
-+Nikos Chantziaras
-+Paul Nasca
-+Peter Nelson
-+Ra
-+Steffen Baranowsky
-+Thorsten Müller
-+TonyChyi
-+devin
-+dnl-music
-+fundamental
-+groboclown
-+zm1990s
diff --git a/debian/patches/series b/debian/patches/series
index aba1af044..94ae11454 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,3 +1,2 @@
-contributors.patch
clang.patch
build-amd64-20181013.patch
diff --git a/include/AudioAlsa.h b/include/AudioAlsa.h
index 77938e164..b1aa9647a 100644
--- a/include/AudioAlsa.h
+++ b/include/AudioAlsa.h
@@ -80,10 +80,10 @@ public:
static DeviceInfoCollection getAvailableDevices();
private:
- virtual void startProcessing();
- virtual void stopProcessing();
- virtual void applyQualitySettings();
- virtual void run();
+ void startProcessing() override;
+ void stopProcessing() override;
+ void applyQualitySettings() override;
+ void run() override;
int setHWParams( const ch_cnt_t _channels, snd_pcm_access_t _access );
int setSWParams();
diff --git a/include/AudioAlsaSetupWidget.h b/include/AudioAlsaSetupWidget.h
index f087d2fd7..db88558a7 100644
--- a/include/AudioAlsaSetupWidget.h
+++ b/include/AudioAlsaSetupWidget.h
@@ -46,7 +46,7 @@ public:
AudioAlsaSetupWidget( QWidget * _parent );
virtual ~AudioAlsaSetupWidget();
- virtual void saveSettings();
+ void saveSettings() override;
public slots:
void onCurrentIndexChanged(int index);
diff --git a/include/AudioDummy.h b/include/AudioDummy.h
index 5094caddc..0772c69eb 100644
--- a/include/AudioDummy.h
+++ b/include/AudioDummy.h
@@ -64,11 +64,11 @@ public:
{
}
- virtual void saveSettings()
+ void saveSettings() override
{
}
- virtual void show()
+ void show() override
{
parentWidget()->hide();
QWidget::show();
@@ -78,17 +78,17 @@ public:
private:
- virtual void startProcessing()
+ void startProcessing() override
{
start();
}
- virtual void stopProcessing()
+ void stopProcessing() override
{
stopProcessingThread( this );
}
- virtual void run()
+ void run() override
{
MicroTimer timer;
while( true )
diff --git a/include/AudioFileMP3.h b/include/AudioFileMP3.h
index 497208e20..057fd13a4 100644
--- a/include/AudioFileMP3.h
+++ b/include/AudioFileMP3.h
@@ -58,7 +58,7 @@ public:
protected:
virtual void writeBuffer( const surroundSampleFrame * /* _buf*/,
const fpp_t /*_frames*/,
- const float /*_master_gain*/ );
+ const float /*_master_gain*/ ) override;
private:
void flushRemainingBuffers();
diff --git a/include/AudioFileOgg.h b/include/AudioFileOgg.h
index 656a7174e..8082f3767 100644
--- a/include/AudioFileOgg.h
+++ b/include/AudioFileOgg.h
@@ -59,7 +59,7 @@ public:
private:
virtual void writeBuffer( const surroundSampleFrame * _ab,
const fpp_t _frames,
- const float _master_gain );
+ const float _master_gain ) override;
bool startEncoding();
void finishEncoding();
diff --git a/include/AudioFileWave.h b/include/AudioFileWave.h
index 4d2778bad..7c8d54964 100644
--- a/include/AudioFileWave.h
+++ b/include/AudioFileWave.h
@@ -56,7 +56,7 @@ public:
private:
virtual void writeBuffer( const surroundSampleFrame * _ab,
const fpp_t _frames,
- float _master_gain );
+ float _master_gain ) override;
bool startEncoding();
void finishEncoding();
diff --git a/include/AudioOss.h b/include/AudioOss.h
index bacfd9597..9e4787ff2 100644
--- a/include/AudioOss.h
+++ b/include/AudioOss.h
@@ -60,7 +60,7 @@ public:
setupWidget( QWidget * _parent );
virtual ~setupWidget();
- virtual void saveSettings();
+ void saveSettings() override;
private:
QLineEdit * m_device;
@@ -70,10 +70,10 @@ public:
private:
- virtual void startProcessing();
- virtual void stopProcessing();
- virtual void applyQualitySettings();
- virtual void run();
+ void startProcessing() override;
+ void stopProcessing() override;
+ void applyQualitySettings() override;
+ void run() override;
int m_audioFD;
diff --git a/include/AudioPort.h b/include/AudioPort.h
index 2842c6a17..146bbd192 100644
--- a/include/AudioPort.h
+++ b/include/AudioPort.h
@@ -100,8 +100,8 @@ public:
bool processEffects();
// ThreadableJob stuff
- virtual void doProcessing();
- virtual bool requiresProcessing() const
+ void doProcessing() override;
+ bool requiresProcessing() const override
{
return true;
}
diff --git a/include/AudioPulseAudio.h b/include/AudioPulseAudio.h
index 496746691..e65180a74 100644
--- a/include/AudioPulseAudio.h
+++ b/include/AudioPulseAudio.h
@@ -62,7 +62,7 @@ public:
setupWidget( QWidget * _parent );
virtual ~setupWidget();
- virtual void saveSettings();
+ void saveSettings() override;
private:
QLineEdit * m_device;
@@ -80,10 +80,10 @@ public:
private:
- virtual void startProcessing();
- virtual void stopProcessing();
- virtual void applyQualitySettings();
- virtual void run();
+ void startProcessing() override;
+ void stopProcessing() override;
+ void applyQualitySettings() override;
+ void run() override;
volatile bool m_quit;
diff --git a/include/AudioSampleRecorder.h b/include/AudioSampleRecorder.h
index 69ac19490..0a82d2d96 100644
--- a/include/AudioSampleRecorder.h
+++ b/include/AudioSampleRecorder.h
@@ -48,7 +48,7 @@ public:
private:
virtual void writeBuffer( const surroundSampleFrame * _ab,
const fpp_t _frames,
- const float _master_gain );
+ const float _master_gain ) override;
typedef QList > BufferList;
BufferList m_buffers;
diff --git a/include/AudioSdl.h b/include/AudioSdl.h
index fd8c544c2..93f23abed 100644
--- a/include/AudioSdl.h
+++ b/include/AudioSdl.h
@@ -60,9 +60,9 @@ public:
{
public:
setupWidget( QWidget * _parent );
- virtual ~setupWidget();
+ ~setupWidget() override;
- virtual void saveSettings();
+ void saveSettings() override;
private:
QLineEdit * m_device;
@@ -71,9 +71,9 @@ public:
private:
- virtual void startProcessing();
- virtual void stopProcessing();
- virtual void applyQualitySettings();
+ void startProcessing() override;
+ void stopProcessing() override;
+ void applyQualitySettings() override;
static void sdlAudioCallback( void * _udata, Uint8 * _buf, int _len );
void sdlAudioCallback( Uint8 * _buf, int _len );
diff --git a/include/AudioSndio.h b/include/AudioSndio.h
index d2bc5c074..f8cf56848 100644
--- a/include/AudioSndio.h
+++ b/include/AudioSndio.h
@@ -58,7 +58,7 @@ public:
setupWidget( QWidget * _parent );
virtual ~setupWidget();
- virtual void saveSettings( void );
+ void saveSettings( void ) override;
private:
QLineEdit * m_device;
@@ -66,10 +66,10 @@ public:
} ;
private:
- virtual void startProcessing( void );
- virtual void stopProcessing( void );
- virtual void applyQualitySettings( void );
- virtual void run( void );
+ void startProcessing( void ) override;
+ void stopProcessing( void ) override;
+ void applyQualitySettings( void ) override;
+ void run( void ) override;
struct sio_hdl *m_hdl;
struct sio_par m_par;
diff --git a/include/AutomatableButton.h b/include/AutomatableButton.h
index 4b5065542..d7859a10c 100644
--- a/include/AutomatableButton.h
+++ b/include/AutomatableButton.h
@@ -48,7 +48,7 @@ public:
model()->setJournalling( _on );
}
- virtual void modelChanged();
+ void modelChanged() override;
public slots:
@@ -62,9 +62,9 @@ public slots:
protected:
- virtual void contextMenuEvent( QContextMenuEvent * _me );
- virtual void mousePressEvent( QMouseEvent * _me );
- virtual void mouseReleaseEvent( QMouseEvent * _me );
+ void contextMenuEvent( QContextMenuEvent * _me ) override;
+ void mousePressEvent( QMouseEvent * _me ) override;
+ void mouseReleaseEvent( QMouseEvent * _me ) override;
private:
@@ -92,7 +92,7 @@ public:
void activateButton( AutomatableButton * _btn );
- virtual void modelChanged();
+ void modelChanged() override;
private slots:
diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h
index 3e0b6143d..6d8000804 100644
--- a/include/AutomatableModel.h
+++ b/include/AutomatableModel.h
@@ -255,7 +255,7 @@ public:
specified DOM element using as attribute/node name */
virtual void loadSettings( const QDomElement& element, const QString& name );
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "automatablemodel";
}
@@ -337,12 +337,12 @@ private:
static bool mustQuoteName(const QString &name);
- virtual void saveSettings( QDomDocument& doc, QDomElement& element )
+ void saveSettings( QDomDocument& doc, QDomElement& element ) override
{
saveSettings( doc, element, "value" );
}
- virtual void loadSettings( const QDomElement& element )
+ void loadSettings( const QDomElement& element ) override
{
loadSettings( element, "value" );
}
diff --git a/include/AutomatableModelView.h b/include/AutomatableModelView.h
index 964ffdc5d..1bcbd97d6 100644
--- a/include/AutomatableModelView.h
+++ b/include/AutomatableModelView.h
@@ -49,7 +49,7 @@ public:
return castModel();
}
- virtual void setModel( Model* model, bool isOldModelValid = true );
+ void setModel( Model* model, bool isOldModelValid = true ) override;
template
inline T value() const
diff --git a/include/AutomatableSlider.h b/include/AutomatableSlider.h
index f58d4a059..b51ef1e3f 100644
--- a/include/AutomatableSlider.h
+++ b/include/AutomatableSlider.h
@@ -51,12 +51,12 @@ signals:
protected:
- virtual void contextMenuEvent( QContextMenuEvent * _me );
- virtual void mousePressEvent( QMouseEvent * _me );
- virtual void mouseReleaseEvent( QMouseEvent * _me );
- virtual void wheelEvent( QWheelEvent * _me );
+ void contextMenuEvent( QContextMenuEvent * _me ) override;
+ void mousePressEvent( QMouseEvent * _me ) override;
+ void mouseReleaseEvent( QMouseEvent * _me ) override;
+ void wheelEvent( QWheelEvent * _me ) override;
- virtual void modelChanged();
+ void modelChanged() override;
private:
diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h
index 9705c5efa..60b894f1f 100644
--- a/include/AutomationEditor.h
+++ b/include/AutomationEditor.h
@@ -73,9 +73,9 @@ public:
return m_pattern != nullptr;
}
- virtual void saveSettings(QDomDocument & doc, QDomElement & parent);
- virtual void loadSettings(const QDomElement & parent);
- QString nodeName() const
+ void saveSettings(QDomDocument & doc, QDomElement & parent) override;
+ void loadSettings(const QDomElement & parent) override;
+ QString nodeName() const override
{
return "automationeditor";
}
@@ -114,14 +114,14 @@ public slots:
protected:
typedef AutomationPattern::timeMap timeMap;
- virtual void keyPressEvent(QKeyEvent * ke);
- virtual void leaveEvent(QEvent * e);
- virtual void mousePressEvent(QMouseEvent * mouseEvent);
- virtual void mouseReleaseEvent(QMouseEvent * mouseEvent);
- virtual void mouseMoveEvent(QMouseEvent * mouseEvent);
- virtual void paintEvent(QPaintEvent * pe);
- virtual void resizeEvent(QResizeEvent * re);
- virtual void wheelEvent(QWheelEvent * we);
+ void keyPressEvent(QKeyEvent * ke) override;
+ void leaveEvent(QEvent * e) override;
+ void mousePressEvent(QMouseEvent * mouseEvent) override;
+ void mouseReleaseEvent(QMouseEvent * mouseEvent) override;
+ void mouseMoveEvent(QMouseEvent * mouseEvent) override;
+ void paintEvent(QPaintEvent * pe) override;
+ void resizeEvent(QResizeEvent * re) override;
+ void wheelEvent(QWheelEvent * we) override;
float getLevel( int y );
int xCoordOfTick( int tick );
@@ -176,8 +176,8 @@ private:
static const int TOP_MARGIN = 16;
static const int DEFAULT_Y_DELTA = 6;
- static const int DEFAULT_STEPS_PER_TACT = 16;
- static const int DEFAULT_PPT = 12 * DEFAULT_STEPS_PER_TACT;
+ static const int DEFAULT_STEPS_PER_BAR = 16;
+ static const int DEFAULT_PPB = 12 * DEFAULT_STEPS_PER_BAR;
static const int VALUES_WIDTH = 64;
@@ -230,7 +230,7 @@ private:
float m_drawLastLevel;
tick_t m_drawLastTick;
- int m_ppt;
+ int m_ppb;
int m_y_delta;
bool m_y_auto;
@@ -282,14 +282,14 @@ public:
void setCurrentPattern(AutomationPattern* pattern);
const AutomationPattern* currentPattern();
- virtual void dropEvent( QDropEvent * _de );
- virtual void dragEnterEvent( QDragEnterEvent * _dee );
+ void dropEvent( QDropEvent * _de ) override;
+ void dragEnterEvent( QDragEnterEvent * _dee ) override;
void open(AutomationPattern* pattern);
AutomationEditor* m_editor;
- QSize sizeHint() const;
+ QSize sizeHint() const override;
public slots:
void clearCurrentPattern();
@@ -297,9 +297,12 @@ public slots:
signals:
void currentPatternChanged();
+protected:
+ void focusInEvent(QFocusEvent * event) override;
+
protected slots:
- void play();
- void stop();
+ void play() override;
+ void stop() override;
private slots:
void updateWindowTitle();
diff --git a/include/AutomationPattern.h b/include/AutomationPattern.h
index 070b6c669..cad9d0a1d 100644
--- a/include/AutomationPattern.h
+++ b/include/AutomationPattern.h
@@ -140,13 +140,13 @@ public:
const QString name() const;
// settings-management
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
static const QString classNodeName() { return "automationpattern"; }
- QString nodeName() const { return classNodeName(); }
+ QString nodeName() const override { return classNodeName(); }
- virtual TrackContentObjectView * createView( TrackView * _tv );
+ TrackContentObjectView * createView( TrackView * _tv ) override;
static bool isAutomated( const AutomatableModel * _m );
diff --git a/include/AutomationPatternView.h b/include/AutomationPatternView.h
index 45aa9ef2a..3f019483a 100644
--- a/include/AutomationPatternView.h
+++ b/include/AutomationPatternView.h
@@ -44,7 +44,7 @@ public:
public slots:
/// Opens this view's pattern in the global automation editor
void openInAutomationEditor();
- virtual void update();
+ void update() override;
protected slots:
@@ -56,11 +56,11 @@ protected slots:
void flipX();
protected:
- virtual void constructContextMenu( QMenu * );
- virtual void mouseDoubleClickEvent(QMouseEvent * me );
- virtual void paintEvent( QPaintEvent * pe );
- virtual void dragEnterEvent( QDragEnterEvent * _dee );
- virtual void dropEvent( QDropEvent * _de );
+ void constructContextMenu( QMenu * ) override;
+ void mouseDoubleClickEvent(QMouseEvent * me ) override;
+ void paintEvent( QPaintEvent * pe ) override;
+ void dragEnterEvent( QDragEnterEvent * _dee ) override;
+ void dropEvent( QDropEvent * _de ) override;
private:
diff --git a/include/AutomationTrack.h b/include/AutomationTrack.h
index 195c21e9d..92a50dd04 100644
--- a/include/AutomationTrack.h
+++ b/include/AutomationTrack.h
@@ -38,19 +38,19 @@ public:
virtual ~AutomationTrack() = default;
virtual bool play( const MidiTime & _start, const fpp_t _frames,
- const f_cnt_t _frame_base, int _tco_num = -1 );
+ const f_cnt_t _frame_base, int _tco_num = -1 ) override;
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "automationtrack";
}
- virtual TrackView * createView( TrackContainerView* );
- virtual TrackContentObject * createTCO( const MidiTime & _pos );
+ TrackView * createView( TrackContainerView* ) override;
+ TrackContentObject * createTCO( const MidiTime & _pos ) override;
virtual void saveTrackSpecificSettings( QDomDocument & _doc,
- QDomElement & _parent );
- virtual void loadTrackSpecificSettings( const QDomElement & _this );
+ QDomElement & _parent ) override;
+ void loadTrackSpecificSettings( const QDomElement & _this ) override;
private:
friend class AutomationTrackView;
@@ -65,8 +65,8 @@ public:
AutomationTrackView( AutomationTrack* at, TrackContainerView* tcv );
virtual ~AutomationTrackView() = default;
- virtual void dragEnterEvent( QDragEnterEvent * _dee );
- virtual void dropEvent( QDropEvent * _de );
+ void dragEnterEvent( QDragEnterEvent * _dee ) override;
+ void dropEvent( QDropEvent * _de ) override;
} ;
diff --git a/include/BBEditor.h b/include/BBEditor.h
index 59b7142f4..ed54beaf1 100644
--- a/include/BBEditor.h
+++ b/include/BBEditor.h
@@ -42,7 +42,7 @@ public:
BBEditor( BBTrackContainer * _tc );
~BBEditor();
- QSize sizeHint() const;
+ QSize sizeHint() const override;
const BBTrackContainerView* trackContainerView() const {
return m_trackContainerView;
@@ -54,8 +54,8 @@ public:
void removeBBView( int bb );
public slots:
- void play();
- void stop();
+ void play() override;
+ void stop() override;
private:
BBTrackContainerView* m_trackContainerView;
@@ -70,15 +70,15 @@ class BBTrackContainerView : public TrackContainerView
public:
BBTrackContainerView(BBTrackContainer* tc);
- bool fixedTCOs() const
+ bool fixedTCOs() const override
{
return true;
}
void removeBBView(int bb);
- void saveSettings(QDomDocument& doc, QDomElement& element);
- void loadSettings(const QDomElement& element);
+ void saveSettings(QDomDocument& doc, QDomElement& element) override;
+ void loadSettings(const QDomElement& element) override;
public slots:
void addSteps();
@@ -88,7 +88,7 @@ public slots:
void addAutomationTrack();
protected slots:
- void dropEvent(QDropEvent * de );
+ void dropEvent(QDropEvent * de ) override;
void updatePosition();
private:
diff --git a/include/BBTrack.h b/include/BBTrack.h
index a906b54d2..70195f28d 100644
--- a/include/BBTrack.h
+++ b/include/BBTrack.h
@@ -43,9 +43,9 @@ public:
BBTCO( Track * _track );
virtual ~BBTCO() = default;
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
- inline virtual QString nodeName() const
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
+ inline QString nodeName() const override
{
return( "bbtco" );
}
@@ -72,7 +72,7 @@ public:
int bbTrackIndex();
- virtual TrackContentObjectView * createView( TrackView * _tv );
+ TrackContentObjectView * createView( TrackView * _tv ) override;
private:
QColor m_color;
@@ -99,7 +99,7 @@ public:
void setColor( QColor _new_color );
public slots:
- virtual void update();
+ void update() override;
protected slots:
void openInBBEditor();
@@ -110,9 +110,9 @@ protected slots:
protected:
- virtual void paintEvent( QPaintEvent * pe );
- virtual void mouseDoubleClickEvent( QMouseEvent * _me );
- virtual void constructContextMenu( QMenu * );
+ void paintEvent( QPaintEvent * pe ) override;
+ void mouseDoubleClickEvent( QMouseEvent * _me ) override;
+ void constructContextMenu( QMenu * ) override;
private:
@@ -133,13 +133,13 @@ public:
virtual ~BBTrack();
virtual bool play( const MidiTime & _start, const fpp_t _frames,
- const f_cnt_t _frame_base, int _tco_num = -1 );
- virtual TrackView * createView( TrackContainerView* tcv );
- virtual TrackContentObject * createTCO( const MidiTime & _pos );
+ const f_cnt_t _frame_base, int _tco_num = -1 ) override;
+ TrackView * createView( TrackContainerView* tcv ) override;
+ TrackContentObject * createTCO( const MidiTime & _pos ) override;
virtual void saveTrackSpecificSettings( QDomDocument & _doc,
- QDomElement & _parent );
- virtual void loadTrackSpecificSettings( const QDomElement & _this );
+ QDomElement & _parent ) override;
+ void loadTrackSpecificSettings( const QDomElement & _this ) override;
static BBTrack * findBBTrack( int _bb_num );
static void swapBBTracks( Track * _track1, Track * _track2 );
@@ -184,7 +184,7 @@ public:
}
protected:
- inline virtual QString nodeName() const
+ inline QString nodeName() const override
{
return( "bbtrack" );
}
@@ -211,7 +211,7 @@ public:
BBTrackView( BBTrack* bbt, TrackContainerView* tcv );
virtual ~BBTrackView();
- virtual bool close();
+ bool close() override;
const BBTrack * getBBTrack() const
{
diff --git a/include/BBTrackContainer.h b/include/BBTrackContainer.h
index 236325157..17d6eb5fe 100644
--- a/include/BBTrackContainer.h
+++ b/include/BBTrackContainer.h
@@ -41,15 +41,15 @@ public:
virtual bool play( MidiTime _start, const fpp_t _frames,
const f_cnt_t _frame_base, int _tco_num = -1 );
- virtual void updateAfterTrackAdd() override;
+ void updateAfterTrackAdd() override;
- inline virtual QString nodeName() const override
+ inline QString nodeName() const override
{
return "bbtrackcontainer";
}
- tact_t lengthOfBB( int _bb ) const;
- inline tact_t lengthOfCurrentBB()
+ bar_t lengthOfBB( int _bb ) const;
+ inline bar_t lengthOfCurrentBB()
{
return lengthOfBB( currentBB() );
}
diff --git a/include/CPULoadWidget.h b/include/CPULoadWidget.h
index 610403f57..2bc41283b 100644
--- a/include/CPULoadWidget.h
+++ b/include/CPULoadWidget.h
@@ -43,7 +43,7 @@ public:
protected:
- virtual void paintEvent( QPaintEvent * _ev );
+ void paintEvent( QPaintEvent * _ev ) override;
protected slots:
diff --git a/include/ComboBox.h b/include/ComboBox.h
index 927c87620..d530c9d92 100644
--- a/include/ComboBox.h
+++ b/include/ComboBox.h
@@ -57,10 +57,10 @@ public slots:
protected:
- virtual void contextMenuEvent( QContextMenuEvent* event );
- virtual void mousePressEvent( QMouseEvent* event );
- virtual void paintEvent( QPaintEvent* event );
- virtual void wheelEvent( QWheelEvent* event );
+ void contextMenuEvent( QContextMenuEvent* event ) override;
+ void mousePressEvent( QMouseEvent* event ) override;
+ void paintEvent( QPaintEvent* event ) override;
+ void wheelEvent( QWheelEvent* event ) override;
private:
diff --git a/include/ConfigManager.h b/include/ConfigManager.h
index dc5b9f485..556c455a0 100644
--- a/include/ConfigManager.h
+++ b/include/ConfigManager.h
@@ -36,6 +36,7 @@
#include "lmms_export.h"
+
class LmmsCore;
@@ -57,61 +58,22 @@ class LMMS_EXPORT ConfigManager : public QObject
public:
static inline ConfigManager * inst()
{
- if( s_instanceOfMe == NULL )
+ if(s_instanceOfMe == NULL )
{
s_instanceOfMe = new ConfigManager();
}
return s_instanceOfMe;
}
- const QString & dataDir() const
- {
- return m_dataDir;
- }
const QString & workingDir() const
{
return m_workingDir;
}
- QString userProjectsDir() const
+ const QString & dataDir() const
{
- return workingDir() + PROJECTS_PATH;
- }
-
- QString userTemplateDir() const
- {
- return workingDir() + TEMPLATE_PATH;
- }
-
- QString userPresetsDir() const
- {
- return workingDir() + PRESETS_PATH;
- }
-
- QString userSamplesDir() const
- {
- return workingDir() + SAMPLES_PATH;
- }
-
- QString userGigDir() const
- {
- return workingDir() + GIG_PATH;
- }
-
- QString userSf2Dir() const
- {
- return workingDir() + SF2_PATH;
- }
-
- QString userLadspaDir() const
- {
- return workingDir() + LADSPA_PATH;
- }
-
- QString userVstDir() const
- {
- return m_vstDir;
+ return m_dataDir;
}
QString factoryProjectsDir() const
@@ -134,37 +96,27 @@ public:
return dataDir() + SAMPLES_PATH;
}
- QString defaultVersion() const;
- QString defaultArtworkDir() const
+ QString userProjectsDir() const
{
- return m_dataDir + DEFAULT_THEME_PATH;
+ return workingDir() + PROJECTS_PATH;
}
- QString artworkDir() const
+ QString userTemplateDir() const
{
- return m_artworkDir;
+ return workingDir() + TEMPLATE_PATH;
}
- QString trackIconsDir() const
+ QString userPresetsDir() const
{
- return m_dataDir + TRACK_ICON_PATH;
+ return workingDir() + PRESETS_PATH;
}
- QString localeDir() const
+ QString userSamplesDir() const
{
- return m_dataDir + LOCALE_PATH;
+ return workingDir() + SAMPLES_PATH;
}
- const QString & gigDir() const
- {
- return m_gigDir;
- }
-
- const QString & sf2Dir() const
- {
- return m_sf2Dir;
- }
const QString & vstDir() const
{
@@ -173,18 +125,20 @@ public:
const QString & ladspaDir() const
{
- return m_ladDir;
+ return m_ladspaDir;
}
- const QString recoveryFile() const
+ const QString & sf2Dir() const
{
- return m_workingDir + "recover.mmp";
+ return m_sf2Dir;
}
-
- const QString & version() const
+
+#ifdef LMMS_HAVE_FLUIDSYNTH
+ const QString & sf2File() const
{
- return m_version;
+ return m_sf2File;
}
+#endif
#ifdef LMMS_HAVE_STK
const QString & stkDir() const
@@ -193,16 +147,55 @@ public:
}
#endif
-#ifdef LMMS_HAVE_FLUIDSYNTH
- const QString & defaultSoundfont() const
+ const QString & gigDir() const
{
- return m_defaultSoundfont;
+ return m_gigDir;
}
-#endif
- const QString & backgroundArtwork() const
+
+ QString userVstDir() const
{
- return m_backgroundArtwork;
+ return m_vstDir;
+ }
+
+ QString userLadspaDir() const
+ {
+ return workingDir() + LADSPA_PATH;
+ }
+
+ QString userSf2Dir() const
+ {
+ return workingDir() + SF2_PATH;
+ }
+
+ QString userGigDir() const
+ {
+ return workingDir() + GIG_PATH;
+ }
+
+ QString defaultThemeDir() const
+ {
+ return m_dataDir + DEFAULT_THEME_PATH;
+ }
+
+ QString themeDir() const
+ {
+ return m_themeDir;
+ }
+
+ const QString & backgroundPicFile() const
+ {
+ return m_backgroundPicFile;
+ }
+
+ QString trackIconsDir() const
+ {
+ return m_dataDir + TRACK_ICON_PATH;
+ }
+
+ const QString recoveryFile() const
+ {
+ return m_workingDir + "recover.mmp";
}
inline const QStringList & recentlyOpenedProjects() const
@@ -210,39 +203,51 @@ public:
return m_recentlyOpenedProjects;
}
+ QString localeDir() const
+ {
+ return m_dataDir + LOCALE_PATH;
+ }
+
+ const QString & version() const
+ {
+ return m_version;
+ }
+
+ QString defaultVersion() const;
+
+
static QStringList availabeVstEmbedMethods();
QString vstEmbedMethod() const;
- // returns true if the working dir (e.g. ~/lmms) exists on disk
+ // Returns true if the working dir (e.g. ~/lmms) exists on disk.
bool hasWorkingDir() const;
- void addRecentlyOpenedProject( const QString & _file );
+ void addRecentlyOpenedProject(const QString & _file);
- const QString & value( const QString & cls,
- const QString & attribute ) const;
- const QString & value( const QString & cls,
+ const QString & value(const QString & cls,
+ const QString & attribute) const;
+ const QString & value(const QString & cls,
const QString & attribute,
- const QString & defaultVal ) const;
- void setValue( const QString & cls, const QString & attribute,
- const QString & value );
- void deleteValue( const QString & cls, const QString & attribute);
+ const QString & defaultVal) const;
+ void setValue(const QString & cls, const QString & attribute,
+ const QString & value);
+ void deleteValue(const QString & cls, const QString & attribute);
- void loadConfigFile( const QString & configFile = "" );
+ void loadConfigFile(const QString & configFile = "");
void saveConfigFile();
- void setWorkingDir( const QString & _wd );
- void setVSTDir( const QString & _vd );
- void setArtworkDir( const QString & _ad );
- void setLADSPADir( const QString & _fd );
- void setVersion( const QString & _cv );
- void setSTKDir( const QString & _fd );
- void setDefaultSoundfont( const QString & _sf );
- void setBackgroundArtwork( const QString & _ba );
- void setGIGDir( const QString & gd );
- void setSF2Dir( const QString & sfd );
+ void setWorkingDir(const QString & workingDir);
+ void setVSTDir(const QString & vstDir);
+ void setLADSPADir(const QString & ladspaDir);
+ void setSF2Dir(const QString & sf2Dir);
+ void setSF2File(const QString & sf2File);
+ void setSTKDir(const QString & stkDir);
+ void setGIGDir(const QString & gigDir);
+ void setThemeDir(const QString & themeDir);
+ void setBackgroundPicFile(const QString & backgroundPicFile);
- // creates the working directory & subdirectories on disk.
+ // Creates the working directory & subdirectories on disk.
void createWorkingDir();
signals:
@@ -252,29 +257,29 @@ private:
static ConfigManager * s_instanceOfMe;
ConfigManager();
- ConfigManager( const ConfigManager & _c );
+ ConfigManager(const ConfigManager & _c);
~ConfigManager();
void upgrade_1_1_90();
void upgrade_1_1_91();
void upgrade();
- QString m_lmmsRcFile;
QString m_workingDir;
QString m_dataDir;
- QString m_artworkDir;
QString m_vstDir;
- QString m_ladDir;
- QString m_gigDir;
+ QString m_ladspaDir;
QString m_sf2Dir;
- QString m_version;
+#ifdef LMMS_HAVE_FLUIDSYNTH
+ QString m_sf2File;
+#endif
#ifdef LMMS_HAVE_STK
QString m_stkDir;
#endif
-#ifdef LMMS_HAVE_FLUIDSYNTH
- QString m_defaultSoundfont;
-#endif
- QString m_backgroundArtwork;
+ QString m_gigDir;
+ QString m_themeDir;
+ QString m_backgroundPicFile;
+ QString m_lmmsRcFile;
+ QString m_version;
QStringList m_recentlyOpenedProjects;
typedef QVector > stringPairVector;
@@ -283,7 +288,5 @@ private:
friend class LmmsCore;
-
-} ;
-
+};
#endif
diff --git a/include/Controller.h b/include/Controller.h
index f1e71ad8f..b60349463 100644
--- a/include/Controller.h
+++ b/include/Controller.h
@@ -101,9 +101,9 @@ public:
}
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
- virtual void loadSettings( const QDomElement & _this );
- virtual QString nodeName() const;
+ void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
+ void loadSettings( const QDomElement & _this ) override;
+ QString nodeName() const override;
static Controller * create( ControllerTypes _tt, Model * _parent );
static Controller * create( const QDomElement & _this,
diff --git a/include/ControllerConnection.h b/include/ControllerConnection.h
index 5c4d5f20e..e57cd4db2 100644
--- a/include/ControllerConnection.h
+++ b/include/ControllerConnection.h
@@ -85,15 +85,15 @@ public:
static void finalizeConnections();
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
- virtual void loadSettings( const QDomElement & _this );
+ void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
+ void loadSettings( const QDomElement & _this ) override;
static inline const QString classNodeName()
{
return "connection";
}
- virtual QString nodeName() const
+ QString nodeName() const override
{
return classNodeName();
}
diff --git a/include/ControllerDialog.h b/include/ControllerDialog.h
index 58a0a94b2..05e8f3bfe 100644
--- a/include/ControllerDialog.h
+++ b/include/ControllerDialog.h
@@ -47,7 +47,7 @@ signals:
protected:
- virtual void closeEvent( QCloseEvent * _ce );
+ void closeEvent( QCloseEvent * _ce ) override;
} ;
diff --git a/include/ControllerRackView.h b/include/ControllerRackView.h
index cb393f5ca..9ef2d9b7f 100644
--- a/include/ControllerRackView.h
+++ b/include/ControllerRackView.h
@@ -47,10 +47,10 @@ public:
ControllerRackView();
virtual ~ControllerRackView();
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
- inline virtual QString nodeName() const
+ inline QString nodeName() const override
{
return "ControllerRackView";
}
@@ -62,7 +62,7 @@ public slots:
void onControllerRemoved( Controller * );
protected:
- virtual void closeEvent( QCloseEvent * _ce );
+ void closeEvent( QCloseEvent * _ce ) override;
private slots:
void addController();
diff --git a/include/ControllerView.h b/include/ControllerView.h
index 4b215feca..d1284845e 100644
--- a/include/ControllerView.h
+++ b/include/ControllerView.h
@@ -68,9 +68,9 @@ signals:
protected:
- virtual void contextMenuEvent( QContextMenuEvent * _me );
- virtual void modelChanged();
- virtual void mouseDoubleClickEvent( QMouseEvent * event );
+ void contextMenuEvent( QContextMenuEvent * _me ) override;
+ void modelChanged() override;
+ void mouseDoubleClickEvent( QMouseEvent * event ) override;
private:
diff --git a/include/DetuningHelper.h b/include/DetuningHelper.h
index de0acc826..2157b6ba8 100644
--- a/include/DetuningHelper.h
+++ b/include/DetuningHelper.h
@@ -43,17 +43,17 @@ public:
{
}
- virtual float defaultValue() const
+ float defaultValue() const override
{
return 0;
}
- virtual QString displayName() const
+ QString displayName() const override
{
return tr( "Note detuning" );
}
- inline virtual QString nodeName() const
+ inline QString nodeName() const override
{
return "detuning";
}
diff --git a/include/DummyEffect.h b/include/DummyEffect.h
index 4f770af3c..5509131be 100644
--- a/include/DummyEffect.h
+++ b/include/DummyEffect.h
@@ -53,25 +53,25 @@ public:
{
}
- virtual int controlCount()
+ int controlCount() override
{
return 0;
}
- virtual void saveSettings( QDomDocument &, QDomElement & )
+ void saveSettings( QDomDocument &, QDomElement & ) override
{
}
- virtual void loadSettings( const QDomElement & )
+ void loadSettings( const QDomElement & ) override
{
}
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "DummyControls";
}
- virtual EffectControlDialog * createView()
+ EffectControlDialog * createView() override
{
return new DummyEffectControlDialog( this );
}
@@ -95,12 +95,12 @@ public:
{
}
- virtual EffectControls * controls()
+ EffectControls * controls() override
{
return &m_controls;
}
- bool processAudioBuffer( sampleFrame *, const fpp_t )
+ bool processAudioBuffer( sampleFrame *, const fpp_t ) override
{
return false;
}
diff --git a/include/DummyInstrument.h b/include/DummyInstrument.h
index 87083f262..a37b089ae 100644
--- a/include/DummyInstrument.h
+++ b/include/DummyInstrument.h
@@ -47,26 +47,26 @@ public:
{
}
- virtual void playNote( NotePlayHandle *, sampleFrame * buffer )
+ void playNote( NotePlayHandle *, sampleFrame * buffer ) override
{
memset( buffer, 0, sizeof( sampleFrame ) *
Engine::mixer()->framesPerPeriod() );
}
- virtual void saveSettings( QDomDocument &, QDomElement & )
+ void saveSettings( QDomDocument &, QDomElement & ) override
{
}
- virtual void loadSettings( const QDomElement & )
+ void loadSettings( const QDomElement & ) override
{
}
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "dummyinstrument";
}
- virtual PluginView * instantiateView( QWidget * _parent )
+ PluginView * instantiateView( QWidget * _parent ) override
{
return new InstrumentViewFixedSize( this, _parent );
}
diff --git a/include/DummyPlugin.h b/include/DummyPlugin.h
index 49475a2ac..ec26da0a3 100644
--- a/include/DummyPlugin.h
+++ b/include/DummyPlugin.h
@@ -42,22 +42,22 @@ public:
{
}
- virtual void saveSettings( QDomDocument &, QDomElement & )
+ void saveSettings( QDomDocument &, QDomElement & ) override
{
}
- virtual void loadSettings( const QDomElement & )
+ void loadSettings( const QDomElement & ) override
{
}
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "DummyPlugin";
}
protected:
- virtual PluginView * instantiateView( QWidget * _parent )
+ PluginView * instantiateView( QWidget * _parent ) override
{
return new PluginView( this, _parent );
}
diff --git a/include/Editor.h b/include/Editor.h
index 26b70ec87..1c80e9f2f 100644
--- a/include/Editor.h
+++ b/include/Editor.h
@@ -47,7 +47,7 @@ protected:
DropToolBar * addDropToolBar(Qt::ToolBarArea whereToAdd, QString const & windowTitle);
DropToolBar * addDropToolBar(QWidget * parent, Qt::ToolBarArea whereToAdd, QString const & windowTitle);
- virtual void closeEvent( QCloseEvent * _ce );
+ void closeEvent( QCloseEvent * _ce ) override;
protected slots:
virtual void play() {}
virtual void record() {}
@@ -92,8 +92,8 @@ signals:
void dropped(QDropEvent* event);
protected:
- void dragEnterEvent(QDragEnterEvent* event);
- void dropEvent(QDropEvent* event);
+ void dragEnterEvent(QDragEnterEvent* event) override;
+ void dropEvent(QDropEvent* event) override;
};
diff --git a/include/Effect.h b/include/Effect.h
index 4dc50e8a4..3874aa602 100644
--- a/include/Effect.h
+++ b/include/Effect.h
@@ -47,10 +47,10 @@ public:
const Descriptor::SubPluginFeatures::Key * _key );
virtual ~Effect();
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
- inline virtual QString nodeName() const
+ inline QString nodeName() const override
{
return "effect";
}
@@ -170,7 +170,7 @@ protected:
*/
void checkGate( double _out_sum );
- virtual PluginView * instantiateView( QWidget * );
+ PluginView * instantiateView( QWidget * ) override;
// some effects might not be capable of higher sample-rates so they can
// sample it down before processing and back after processing
diff --git a/include/EffectChain.h b/include/EffectChain.h
index bc1e7df8c..9ebc4d534 100644
--- a/include/EffectChain.h
+++ b/include/EffectChain.h
@@ -40,10 +40,10 @@ public:
EffectChain( Model * _parent );
virtual ~EffectChain();
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
- inline virtual QString nodeName() const
+ inline QString nodeName() const override
{
return "fxchain";
}
diff --git a/include/EffectControlDialog.h b/include/EffectControlDialog.h
index c0a60cfa6..4a59489da 100644
--- a/include/EffectControlDialog.h
+++ b/include/EffectControlDialog.h
@@ -48,7 +48,7 @@ signals:
protected:
- virtual void closeEvent( QCloseEvent * _ce );
+ void closeEvent( QCloseEvent * _ce ) override;
EffectControls * m_effectControls;
diff --git a/include/EffectRackView.h b/include/EffectRackView.h
index 0cfc04e15..698bad7fb 100644
--- a/include/EffectRackView.h
+++ b/include/EffectRackView.h
@@ -60,7 +60,7 @@ private slots:
private:
- virtual void modelChanged();
+ void modelChanged() override;
inline EffectChain* fxChain()
{
diff --git a/include/EffectView.h b/include/EffectView.h
index 71a0e7128..6e994dd7e 100644
--- a/include/EffectView.h
+++ b/include/EffectView.h
@@ -73,9 +73,9 @@ signals:
protected:
- virtual void contextMenuEvent( QContextMenuEvent * _me );
- virtual void paintEvent( QPaintEvent * _pe );
- virtual void modelChanged();
+ void contextMenuEvent( QContextMenuEvent * _me ) override;
+ void paintEvent( QPaintEvent * _pe ) override;
+ void modelChanged() override;
private:
diff --git a/include/EnvelopeAndLfoParameters.h b/include/EnvelopeAndLfoParameters.h
index 4824062f3..0f691adb0 100644
--- a/include/EnvelopeAndLfoParameters.h
+++ b/include/EnvelopeAndLfoParameters.h
@@ -91,9 +91,9 @@ public:
}
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
- virtual QString nodeName() const
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
+ QString nodeName() const override
{
return "el";
}
diff --git a/include/EnvelopeAndLfoView.h b/include/EnvelopeAndLfoView.h
index 817b0a6ee..f6d4fd0a8 100644
--- a/include/EnvelopeAndLfoView.h
+++ b/include/EnvelopeAndLfoView.h
@@ -52,12 +52,12 @@ public:
protected:
- virtual void modelChanged();
+ void modelChanged() override;
- virtual void dragEnterEvent( QDragEnterEvent * _dee );
- virtual void dropEvent( QDropEvent * _de );
- virtual void mousePressEvent( QMouseEvent * _me );
- virtual void paintEvent( QPaintEvent * _pe );
+ void dragEnterEvent( QDragEnterEvent * _dee ) override;
+ void dropEvent( QDropEvent * _de ) override;
+ void mousePressEvent( QMouseEvent * _me ) override;
+ void paintEvent( QPaintEvent * _pe ) override;
protected slots:
diff --git a/include/ExportFilter.h b/include/ExportFilter.h
index 950bacbcd..3124b477b 100644
--- a/include/ExportFilter.h
+++ b/include/ExportFilter.h
@@ -44,15 +44,15 @@ public:
int tempo, int masterPitch, const QString &filename ) = 0;
protected:
- virtual void saveSettings( QDomDocument &, QDomElement & )
+ void saveSettings( QDomDocument &, QDomElement & ) override
{
}
- virtual void loadSettings( const QDomElement & )
+ void loadSettings( const QDomElement & ) override
{
}
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "import_filter";
}
diff --git a/include/ExportProjectDialog.h b/include/ExportProjectDialog.h
index 0eedb9722..06c1e3011 100644
--- a/include/ExportProjectDialog.h
+++ b/include/ExportProjectDialog.h
@@ -41,14 +41,14 @@ public:
ExportProjectDialog( const QString & _file_name, QWidget * _parent, bool multi_export );
protected:
- virtual void reject( void );
- virtual void closeEvent( QCloseEvent * _ce );
+ void reject( void ) override;
+ void closeEvent( QCloseEvent * _ce ) override;
private slots:
void startBtnClicked( void );
void updateTitleBar( int );
- void accept();
+ void accept() override;
void startExport();
void onFileFormatChanged(int);
diff --git a/include/FadeButton.h b/include/FadeButton.h
index 8f56a77b2..09a4c6457 100644
--- a/include/FadeButton.h
+++ b/include/FadeButton.h
@@ -50,8 +50,8 @@ public slots:
protected:
- virtual void customEvent( QEvent * );
- virtual void paintEvent( QPaintEvent * _pe );
+ void customEvent( QEvent * ) override;
+ void paintEvent( QPaintEvent * _pe ) override;
private:
diff --git a/include/Fader.h b/include/Fader.h
index 018f66e0c..207215445 100644
--- a/include/Fader.h
+++ b/include/Fader.h
@@ -109,13 +109,13 @@ public:
}
private:
- virtual void contextMenuEvent( QContextMenuEvent * _me );
- virtual void mousePressEvent( QMouseEvent *ev );
- virtual void mouseDoubleClickEvent( QMouseEvent* mouseEvent );
- virtual void mouseMoveEvent( QMouseEvent *ev );
- virtual void mouseReleaseEvent( QMouseEvent * _me );
- virtual void wheelEvent( QWheelEvent *ev );
- virtual void paintEvent( QPaintEvent *ev );
+ void contextMenuEvent( QContextMenuEvent * _me ) override;
+ void mousePressEvent( QMouseEvent *ev ) override;
+ void mouseDoubleClickEvent( QMouseEvent* mouseEvent ) override;
+ void mouseMoveEvent( QMouseEvent *ev ) override;
+ void mouseReleaseEvent( QMouseEvent * _me ) override;
+ void wheelEvent( QWheelEvent *ev ) override;
+ void paintEvent( QPaintEvent *ev ) override;
inline bool clips(float const & value) const { return value >= 1.0f; }
diff --git a/include/FileBrowser.h b/include/FileBrowser.h
index 4b92dd549..9b56a8dbd 100644
--- a/include/FileBrowser.h
+++ b/include/FileBrowser.h
@@ -61,7 +61,7 @@ private slots:
void giveFocusToFilter();
private:
- virtual void keyPressEvent( QKeyEvent * ke );
+ void keyPressEvent( QKeyEvent * ke ) override;
void addItems( const QString & path );
@@ -93,10 +93,10 @@ public:
protected:
- virtual void contextMenuEvent( QContextMenuEvent * e );
- virtual void mousePressEvent( QMouseEvent * me );
- virtual void mouseMoveEvent( QMouseEvent * me );
- virtual void mouseReleaseEvent( QMouseEvent * me );
+ void contextMenuEvent( QContextMenuEvent * e ) override;
+ void mousePressEvent( QMouseEvent * me ) override;
+ void mouseMoveEvent( QMouseEvent * me ) override;
+ void mouseReleaseEvent( QMouseEvent * me ) override;
private:
diff --git a/include/FxLine.h b/include/FxLine.h
index ef8313e74..c16dcd5f5 100644
--- a/include/FxLine.h
+++ b/include/FxLine.h
@@ -51,10 +51,10 @@ public:
FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex);
~FxLine();
- virtual void paintEvent( QPaintEvent * );
- virtual void mousePressEvent( QMouseEvent * );
- virtual void mouseDoubleClickEvent( QMouseEvent * );
- virtual void contextMenuEvent( QContextMenuEvent * );
+ void paintEvent( QPaintEvent * ) override;
+ void mousePressEvent( QMouseEvent * ) override;
+ void mouseDoubleClickEvent( QMouseEvent * ) override;
+ void contextMenuEvent( QContextMenuEvent * ) override;
inline int channelIndex() { return m_channelIndex; }
void setChannelIndex(int index);
@@ -79,7 +79,7 @@ public:
static const int FxLineHeight;
- bool eventFilter (QObject *dist, QEvent *event);
+ bool eventFilter (QObject *dist, QEvent *event) override;
private:
void drawFxLine( QPainter* p, const FxLine *fxLine, bool isActive, bool sendToThis, bool receiveFromThis );
diff --git a/include/FxLineLcdSpinBox.h b/include/FxLineLcdSpinBox.h
index fa001b2bb..eeb104c5c 100644
--- a/include/FxLineLcdSpinBox.h
+++ b/include/FxLineLcdSpinBox.h
@@ -42,8 +42,8 @@ public:
void setTrackView(TrackView * tv);
protected:
- virtual void mouseDoubleClickEvent(QMouseEvent* event);
- virtual void contextMenuEvent(QContextMenuEvent* event);
+ void mouseDoubleClickEvent(QMouseEvent* event) override;
+ void contextMenuEvent(QContextMenuEvent* event) override;
private:
TrackView * m_tv;
diff --git a/include/FxMixer.h b/include/FxMixer.h
index 2c7ef3c5a..68b69d9bc 100644
--- a/include/FxMixer.h
+++ b/include/FxMixer.h
@@ -67,7 +67,7 @@ class FxChannel : public ThreadableJob
// pointers to other channels that send to this one
FxRouteVector m_receives;
- virtual bool requiresProcessing() const { return true; }
+ bool requiresProcessing() const override { return true; }
void unmuteForSolo();
@@ -76,7 +76,7 @@ class FxChannel : public ThreadableJob
void processed();
private:
- virtual void doProcessing();
+ void doProcessing() override;
};
@@ -133,10 +133,10 @@ public:
void prepareMasterMix();
void masterMix( sampleFrame * _buf );
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "fxmixer";
}
diff --git a/include/FxMixerView.h b/include/FxMixerView.h
index 9b07637ed..a7662321a 100644
--- a/include/FxMixerView.h
+++ b/include/FxMixerView.h
@@ -64,10 +64,10 @@ public:
FxMixerView();
virtual ~FxMixerView();
- virtual void keyPressEvent(QKeyEvent * e);
+ void keyPressEvent(QKeyEvent * e) override;
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
- virtual void loadSettings( const QDomElement & _this );
+ void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
+ void loadSettings( const QDomElement & _this ) override;
inline FxLine * currentFxLine()
{
@@ -110,7 +110,7 @@ public slots:
int addNewChannel();
protected:
- virtual void closeEvent( QCloseEvent * _ce );
+ void closeEvent( QCloseEvent * _ce ) override;
private slots:
void updateFaders();
diff --git a/include/Graph.h b/include/Graph.h
index 1bee05c41..2a6fc4f8a 100644
--- a/include/Graph.h
+++ b/include/Graph.h
@@ -87,19 +87,19 @@ public:
signals:
void drawn();
protected:
- virtual void paintEvent( QPaintEvent * _pe );
- virtual void dropEvent( QDropEvent * _de );
- virtual void dragEnterEvent( QDragEnterEvent * _dee );
- virtual void mousePressEvent( QMouseEvent * _me );
- virtual void mouseMoveEvent( QMouseEvent * _me );
- virtual void mouseReleaseEvent( QMouseEvent * _me );
+ void paintEvent( QPaintEvent * _pe ) override;
+ void dropEvent( QDropEvent * _de ) override;
+ void dragEnterEvent( QDragEnterEvent * _dee ) override;
+ void mousePressEvent( QMouseEvent * _me ) override;
+ void mouseMoveEvent( QMouseEvent * _me ) override;
+ void mouseReleaseEvent( QMouseEvent * _me ) override;
protected slots:
void updateGraph( int _startPos, int _endPos );
void updateGraph();
private:
- virtual void modelChanged();
+ void modelChanged() override;
void changeSampleAt( int _x, int _y );
void drawLineAt( int _x, int _y, int _lastx );
diff --git a/include/GroupBox.h b/include/GroupBox.h
index 8a857199f..88428b1aa 100644
--- a/include/GroupBox.h
+++ b/include/GroupBox.h
@@ -42,7 +42,7 @@ public:
GroupBox( const QString & _caption, QWidget * _parent = NULL );
virtual ~GroupBox();
- virtual void modelChanged();
+ void modelChanged() override;
PixmapButton * ledButton()
{
@@ -56,8 +56,8 @@ public:
protected:
- virtual void mousePressEvent( QMouseEvent * _me );
- virtual void paintEvent( QPaintEvent * _pe );
+ void mousePressEvent( QMouseEvent * _me ) override;
+ void paintEvent( QPaintEvent * _pe ) override;
private:
diff --git a/include/ImportFilter.h b/include/ImportFilter.h
index 166c1bfda..ccefd3db2 100644
--- a/include/ImportFilter.h
+++ b/include/ImportFilter.h
@@ -89,15 +89,15 @@ protected:
m_file.ungetChar( _ch );
}
- virtual void saveSettings( QDomDocument &, QDomElement & )
+ void saveSettings( QDomDocument &, QDomElement & ) override
{
}
- virtual void loadSettings( const QDomElement & )
+ void loadSettings( const QDomElement & ) override
{
}
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "import_filter";
}
diff --git a/include/InlineAutomation.h b/include/InlineAutomation.h
index d70121a45..431ecbc81 100644
--- a/include/InlineAutomation.h
+++ b/include/InlineAutomation.h
@@ -79,8 +79,8 @@ public:
return m_autoPattern;
}
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
private:
diff --git a/include/Instrument.h b/include/Instrument.h
index 2179a1f72..438197cd8 100644
--- a/include/Instrument.h
+++ b/include/Instrument.h
@@ -110,7 +110,7 @@ public:
return true;
}
- virtual QString fullDisplayName() const;
+ QString fullDisplayName() const override;
// --------------------------------------------------------------------
// provided functions:
diff --git a/include/InstrumentFunctionViews.h b/include/InstrumentFunctionViews.h
index 8ac13e1b9..58f915b15 100644
--- a/include/InstrumentFunctionViews.h
+++ b/include/InstrumentFunctionViews.h
@@ -49,7 +49,7 @@ public:
private:
- virtual void modelChanged();
+ void modelChanged() override;
InstrumentFunctionNoteStacking * m_cc;
@@ -72,7 +72,7 @@ public:
private:
- virtual void modelChanged();
+ void modelChanged() override;
InstrumentFunctionArpeggio * m_a;
GroupBox * m_arpGroupBox;
diff --git a/include/InstrumentFunctions.h b/include/InstrumentFunctions.h
index 0055c6c97..b45484e71 100644
--- a/include/InstrumentFunctions.h
+++ b/include/InstrumentFunctions.h
@@ -54,10 +54,10 @@ public:
void processNote( NotePlayHandle* n );
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
- inline virtual QString nodeName() const
+ inline QString nodeName() const override
{
return "chordcreator";
}
@@ -176,10 +176,10 @@ public:
void processNote( NotePlayHandle* n );
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
- inline virtual QString nodeName() const
+ inline QString nodeName() const override
{
return "arpeggiator";
}
diff --git a/include/InstrumentMidiIOView.h b/include/InstrumentMidiIOView.h
index 38f441942..e63b48425 100644
--- a/include/InstrumentMidiIOView.h
+++ b/include/InstrumentMidiIOView.h
@@ -47,7 +47,7 @@ public:
private:
- virtual void modelChanged();
+ void modelChanged() override;
GroupBox * m_midiInputGroupBox;
LcdSpinBox * m_inputChannelSpinBox;
diff --git a/include/InstrumentPlayHandle.h b/include/InstrumentPlayHandle.h
index 426b413ce..ac5fc3222 100644
--- a/include/InstrumentPlayHandle.h
+++ b/include/InstrumentPlayHandle.h
@@ -40,7 +40,7 @@ public:
}
- virtual void play( sampleFrame * _working_buffer )
+ void play( sampleFrame * _working_buffer ) override
{
// ensure that all our nph's have been processed first
ConstNotePlayHandleList nphv = NotePlayHandle::nphsOfInstrumentTrack( m_instrument->instrumentTrack(), true );
@@ -65,12 +65,12 @@ public:
m_instrument->play( _working_buffer );
}
- virtual bool isFinished() const
+ bool isFinished() const override
{
return false;
}
- virtual bool isFromTrack( const Track* _track ) const
+ bool isFromTrack( const Track* _track ) const override
{
return m_instrument->isFromTrack( _track );
}
diff --git a/include/InstrumentSoundShaping.h b/include/InstrumentSoundShaping.h
index a159f8380..1b8df38d3 100644
--- a/include/InstrumentSoundShaping.h
+++ b/include/InstrumentSoundShaping.h
@@ -57,9 +57,9 @@ public:
float volumeLevel( NotePlayHandle * _n, const f_cnt_t _frame );
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
- inline virtual QString nodeName() const
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
+ inline QString nodeName() const override
{
return "eldata";
}
diff --git a/include/InstrumentSoundShapingView.h b/include/InstrumentSoundShapingView.h
index a409e8446..06d53232c 100644
--- a/include/InstrumentSoundShapingView.h
+++ b/include/InstrumentSoundShapingView.h
@@ -50,7 +50,7 @@ public:
private:
- virtual void modelChanged();
+ void modelChanged() override;
InstrumentSoundShaping * m_ss;
diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h
index 72e0d04cc..d72331e52 100644
--- a/include/InstrumentTrack.h
+++ b/include/InstrumentTrack.h
@@ -80,8 +80,8 @@ public:
MidiEvent applyMasterKey( const MidiEvent& event );
- virtual void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 );
- virtual void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 );
+ void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ) override;
+ void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ) override;
// silence all running notes played by this track
void silenceAllNotes( bool removeIPH = false );
@@ -111,7 +111,7 @@ public:
void deleteNotePluginData( NotePlayHandle * _n );
// name-stuff
- virtual void setName( const QString & _new_name );
+ void setName( const QString & _new_name ) override;
// translate given key of a note-event to absolute key (i.e.
// add global master-pitch and base-note of this instrument track)
@@ -131,18 +131,18 @@ public:
// play everything in given frame-range - creates note-play-handles
virtual bool play( const MidiTime & _start, const fpp_t _frames,
- const f_cnt_t _frame_base, int _tco_num = -1 );
+ const f_cnt_t _frame_base, int _tco_num = -1 ) override;
// create new view for me
- virtual TrackView * createView( TrackContainerView* tcv );
+ TrackView * createView( TrackContainerView* tcv ) override;
// create new track-content-object = pattern
- virtual TrackContentObject * createTCO( const MidiTime & _pos );
+ TrackContentObject * createTCO( const MidiTime & _pos ) override;
// called by track
virtual void saveTrackSpecificSettings( QDomDocument & _doc,
- QDomElement & _parent );
- virtual void loadTrackSpecificSettings( const QDomElement & _this );
+ QDomElement & _parent ) override;
+ void loadTrackSpecificSettings( const QDomElement & _this ) override;
using Track::setJournalling;
@@ -225,7 +225,7 @@ signals:
protected:
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "instrumenttrack";
}
@@ -317,12 +317,12 @@ public:
static void cleanupWindowCache();
// Create a menu for assigning/creating channels for this track
- QMenu * createFxMenu( QString title, QString newFxLabel );
+ QMenu * createFxMenu( QString title, QString newFxLabel ) override;
protected:
- virtual void dragEnterEvent( QDragEnterEvent * _dee );
- virtual void dropEvent( QDropEvent * _de );
+ void dragEnterEvent( QDragEnterEvent * _dee ) override;
+ void dropEvent( QDropEvent * _de ) override;
private slots:
@@ -404,8 +404,8 @@ public:
static void dragEnterEventGeneric( QDragEnterEvent * _dee );
- virtual void dragEnterEvent( QDragEnterEvent * _dee );
- virtual void dropEvent( QDropEvent * _de );
+ void dragEnterEvent( QDragEnterEvent * _dee ) override;
+ void dropEvent( QDropEvent * _de ) override;
public slots:
@@ -417,11 +417,11 @@ public slots:
protected:
// capture close-events for toggling instrument-track-button
- virtual void closeEvent( QCloseEvent * _ce );
- virtual void focusInEvent( QFocusEvent * _fe );
+ void closeEvent( QCloseEvent * _ce ) override;
+ void focusInEvent( QFocusEvent * _fe ) override;
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
- virtual void loadSettings( const QDomElement & _this );
+ void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
+ void loadSettings( const QDomElement & _this ) override;
protected slots:
@@ -430,7 +430,7 @@ protected slots:
void viewPrevInstrument();
private:
- virtual void modelChanged();
+ void modelChanged() override;
void viewInstrumentInDirection(int d);
//! adjust size of any child widget of the main tab
//! required to keep the old look when using a variable sized tab widget
diff --git a/include/JournallingObject.h b/include/JournallingObject.h
index 6974bef84..f4755994b 100644
--- a/include/JournallingObject.h
+++ b/include/JournallingObject.h
@@ -59,9 +59,9 @@ public:
void addJournalCheckPoint();
virtual QDomElement saveState( QDomDocument & _doc,
- QDomElement & _parent );
+ QDomElement & _parent ) override;
- virtual void restoreState( const QDomElement & _this );
+ void restoreState( const QDomElement & _this ) override;
inline bool isJournalling() const
{
diff --git a/include/Knob.h b/include/Knob.h
index b8d460f45..4f8064731 100644
--- a/include/Knob.h
+++ b/include/Knob.h
@@ -124,16 +124,16 @@ signals:
protected:
- virtual void contextMenuEvent( QContextMenuEvent * _me );
- virtual void dragEnterEvent( QDragEnterEvent * _dee );
- virtual void dropEvent( QDropEvent * _de );
- virtual void focusOutEvent( QFocusEvent * _fe );
- virtual void mousePressEvent( QMouseEvent * _me );
- virtual void mouseReleaseEvent( QMouseEvent * _me );
- virtual void mouseMoveEvent( QMouseEvent * _me );
- virtual void mouseDoubleClickEvent( QMouseEvent * _me );
- virtual void paintEvent( QPaintEvent * _me );
- virtual void wheelEvent( QWheelEvent * _me );
+ void contextMenuEvent( QContextMenuEvent * _me ) override;
+ void dragEnterEvent( QDragEnterEvent * _dee ) override;
+ void dropEvent( QDropEvent * _de ) override;
+ void focusOutEvent( QFocusEvent * _fe ) override;
+ void mousePressEvent( QMouseEvent * _me ) override;
+ void mouseReleaseEvent( QMouseEvent * _me ) override;
+ void mouseMoveEvent( QMouseEvent * _me ) override;
+ void mouseDoubleClickEvent( QMouseEvent * _me ) override;
+ void paintEvent( QPaintEvent * _me ) override;
+ void wheelEvent( QWheelEvent * _me ) override;
virtual float getValue( const QPoint & _p );
@@ -145,7 +145,7 @@ private slots:
private:
QString displayValue() const;
- virtual void doConnections();
+ void doConnections() override;
QLineF calculateLine( const QPointF & _mid, float _radius,
float _innerRadius = 1) const;
diff --git a/include/LadspaControl.h b/include/LadspaControl.h
index 2ad895b3f..34f6c9ae2 100644
--- a/include/LadspaControl.h
+++ b/include/LadspaControl.h
@@ -74,7 +74,7 @@ public:
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent, const QString & _name );
virtual void loadSettings( const QDomElement & _this, const QString & _name );
- inline virtual QString nodeName() const
+ inline QString nodeName() const override
{
return "port";
}
@@ -92,13 +92,13 @@ protected slots:
void linkStateChanged();
protected:
- virtual void saveSettings( QDomDocument& doc, QDomElement& element )
+ void saveSettings( QDomDocument& doc, QDomElement& element ) override
{
Q_UNUSED(doc)
Q_UNUSED(element)
}
- virtual void loadSettings( const QDomElement& element )
+ void loadSettings( const QDomElement& element ) override
{
Q_UNUSED(element)
}
diff --git a/include/LcdSpinBox.h b/include/LcdSpinBox.h
index b63dfaa40..379b743ac 100644
--- a/include/LcdSpinBox.h
+++ b/include/LcdSpinBox.h
@@ -40,7 +40,7 @@ public:
virtual ~LcdSpinBox() = default;
- virtual void modelChanged()
+ void modelChanged() override
{
ModelView::modelChanged();
update();
@@ -65,12 +65,12 @@ public slots:
protected:
- virtual void contextMenuEvent( QContextMenuEvent * _me );
- virtual void mousePressEvent( QMouseEvent * _me );
- virtual void mouseMoveEvent( QMouseEvent * _me );
- virtual void mouseReleaseEvent( QMouseEvent * _me );
- virtual void wheelEvent( QWheelEvent * _we );
- virtual void mouseDoubleClickEvent( QMouseEvent * _me );
+ void contextMenuEvent( QContextMenuEvent * _me ) override;
+ void mousePressEvent( QMouseEvent * _me ) override;
+ void mouseMoveEvent( QMouseEvent * _me ) override;
+ void mouseReleaseEvent( QMouseEvent * _me ) override;
+ void wheelEvent( QWheelEvent * _we ) override;
+ void mouseDoubleClickEvent( QMouseEvent * _me ) override;
private:
bool m_mouseMoving;
diff --git a/include/LcdWidget.h b/include/LcdWidget.h
index db969dd33..f4c7d1579 100644
--- a/include/LcdWidget.h
+++ b/include/LcdWidget.h
@@ -71,7 +71,7 @@ public slots:
protected:
- virtual void paintEvent( QPaintEvent * pe );
+ void paintEvent( QPaintEvent * pe ) override;
virtual void updateSize();
diff --git a/include/LedCheckbox.h b/include/LedCheckbox.h
index 723bae6a9..66d7ce07e 100644
--- a/include/LedCheckbox.h
+++ b/include/LedCheckbox.h
@@ -64,7 +64,7 @@ public:
Q_PROPERTY( QString text READ text WRITE setText )
protected:
- virtual void paintEvent( QPaintEvent * _pe );
+ void paintEvent( QPaintEvent * _pe ) override;
private:
diff --git a/include/LfoController.h b/include/LfoController.h
index 9dfbba671..8fc35fd09 100644
--- a/include/LfoController.h
+++ b/include/LfoController.h
@@ -49,18 +49,18 @@ public:
virtual ~LfoController();
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
- virtual void loadSettings( const QDomElement & _this );
- virtual QString nodeName() const;
+ void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
+ void loadSettings( const QDomElement & _this ) override;
+ QString nodeName() const override;
public slots:
- virtual ControllerDialog * createDialog( QWidget * _parent );
+ ControllerDialog * createDialog( QWidget * _parent ) override;
protected:
// The internal per-controller value updating function
- virtual void updateValueBuffer();
+ void updateValueBuffer() override;
FloatModel m_baseModel;
TempoSyncKnobModel m_speedModel;
@@ -98,8 +98,8 @@ public:
protected:
- virtual void contextMenuEvent( QContextMenuEvent * _me );
- virtual void modelChanged();
+ void contextMenuEvent( QContextMenuEvent * _me ) override;
+ void modelChanged() override;
LfoController * m_lfo;
diff --git a/include/LmmsPalette.h b/include/LmmsPalette.h
index 49b831346..a8ee5d1c8 100644
--- a/include/LmmsPalette.h
+++ b/include/LmmsPalette.h
@@ -43,8 +43,6 @@ class LMMS_EXPORT LmmsPalette : public QWidget
Q_PROPERTY( QColor brightText READ brightText WRITE setBrightText )
Q_PROPERTY( QColor highlight READ highlight WRITE setHighlight )
Q_PROPERTY( QColor highlightedText READ highlightedText WRITE setHighlightedText )
- Q_PROPERTY( QColor toolTipText READ toolTipText WRITE setToolTipText )
- Q_PROPERTY( QColor toolTipBase READ toolTipBase WRITE setToolTipBase )
public:
LmmsPalette( QWidget * parent, QStyle * stylearg );
@@ -65,8 +63,6 @@ public:
ACCESSMET( brightText, setBrightText )
ACCESSMET( highlight, setHighlight )
ACCESSMET( highlightedText, setHighlightedText )
- ACCESSMET( toolTipText, setToolTipText )
- ACCESSMET( toolTipBase, setToolTipBase )
#undef ACCESSMET
@@ -83,8 +79,6 @@ private:
QColor m_brightText;
QColor m_highlight;
QColor m_highlightedText;
- QColor m_toolTipText;
- QColor m_toolTipBase;
};
diff --git a/include/LmmsStyle.h b/include/LmmsStyle.h
index 88b8a2112..ccf14396c 100644
--- a/include/LmmsStyle.h
+++ b/include/LmmsStyle.h
@@ -67,21 +67,21 @@ public:
{
}
- virtual QPalette standardPalette( void ) const;
+ QPalette standardPalette( void ) const override;
virtual void drawComplexControl(
ComplexControl control,
const QStyleOptionComplex * option,
QPainter *painter,
- const QWidget *widget ) const;
+ const QWidget *widget ) const override;
virtual void drawPrimitive( PrimitiveElement element,
const QStyleOption *option,
QPainter *painter,
- const QWidget *widget = 0 ) const;
+ const QWidget *widget = 0 ) const override;
virtual int pixelMetric( PixelMetric metric,
const QStyleOption * option = 0,
- const QWidget * widget = 0 ) const;
+ const QWidget * widget = 0 ) const override;
static QPalette * s_palette;
diff --git a/include/LocklessRingBuffer.h b/include/LocklessRingBuffer.h
new file mode 100644
index 000000000..3b18dd475
--- /dev/null
+++ b/include/LocklessRingBuffer.h
@@ -0,0 +1,132 @@
+/*
+ * LocklessRingBuffer.h - LMMS wrapper for a lockless ringbuffer library
+ *
+ * Copyright (c) 2019 Martin Pavelek
+ *
+ * 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 LOCKLESSRINGBUFFER_H
+#define LOCKLESSRINGBUFFER_H
+
+#include
+#include
+
+#include "lmms_basics.h"
+#include "lmms_export.h"
+#include "../src/3rdparty/ringbuffer/include/ringbuffer/ringbuffer.h"
+
+
+//! A convenience layer for a realtime-safe and thread-safe multi-reader ring buffer library.
+template
+class LocklessRingBufferBase
+{
+ template
+ friend class LocklessRingBufferReader;
+public:
+ LocklessRingBufferBase(std::size_t sz) : m_buffer(sz)
+ {
+ m_buffer.touch(); // reserve storage space before realtime operation starts
+ }
+ ~LocklessRingBufferBase() {};
+
+ std::size_t capacity() const {return m_buffer.maximum_eventual_write_space();}
+ std::size_t free() const {return m_buffer.write_space();}
+ void wakeAll() {m_notifier.wakeAll();}
+
+protected:
+ ringbuffer_t m_buffer;
+ QWaitCondition m_notifier;
+};
+
+
+// The SampleFrameCopier is required because sampleFrame is just a two-element
+// array and therefore does not have a copy constructor needed by std::copy.
+class SampleFrameCopier
+{
+ const sampleFrame* m_src;
+public:
+ SampleFrameCopier(const sampleFrame* src) : m_src(src) {}
+ void operator()(std::size_t src_offset, std::size_t count, sampleFrame* dest)
+ {
+ for (std::size_t i = src_offset; i < src_offset + count; i++, dest++)
+ {
+ (*dest)[0] = m_src[i][0];
+ (*dest)[1] = m_src[i][1];
+ }
+ }
+};
+
+
+//! Standard ring buffer template for data types with copy constructor.
+template
+class LocklessRingBuffer : public LocklessRingBufferBase
+{
+public:
+ LocklessRingBuffer(std::size_t sz) : LocklessRingBufferBase(sz) {};
+
+ std::size_t write(const sampleFrame *src, std::size_t cnt, bool notify = false)
+ {
+ std::size_t written = LocklessRingBufferBase::m_buffer.write(src, cnt);
+ // Let all waiting readers know new data are available.
+ if (notify) {LocklessRingBufferBase::m_notifier.wakeAll();}
+ return written;
+ }
+};
+
+
+//! Specialized ring buffer template with write function modified to support sampleFrame.
+template <>
+class LocklessRingBuffer : public LocklessRingBufferBase
+{
+public:
+ LocklessRingBuffer(std::size_t sz) : LocklessRingBufferBase(sz) {};
+
+ std::size_t write(const sampleFrame *src, std::size_t cnt, bool notify = false)
+ {
+ SampleFrameCopier copier(src);
+ std::size_t written = LocklessRingBufferBase::m_buffer.write_func(copier, cnt);
+ // Let all waiting readers know new data are available.
+ if (notify) {LocklessRingBufferBase::m_notifier.wakeAll();}
+ return written;
+ }
+};
+
+
+//! Wrapper for lockless ringbuffer reader
+template
+class LocklessRingBufferReader : public ringbuffer_reader_t
+{
+public:
+ LocklessRingBufferReader(LocklessRingBuffer &rb) :
+ ringbuffer_reader_t(rb.m_buffer),
+ m_notifier(&rb.m_notifier) {};
+
+ bool empty() const {return !this->read_space();}
+ void waitForData()
+ {
+ QMutex useless_lock;
+ m_notifier->wait(&useless_lock);
+ useless_lock.unlock();
+ }
+private:
+ QWaitCondition *m_notifier;
+};
+
+#endif //LOCKLESSRINGBUFFER_H
diff --git a/include/MainApplication.h b/include/MainApplication.h
index 41d670419..d28900213 100644
--- a/include/MainApplication.h
+++ b/include/MainApplication.h
@@ -42,7 +42,7 @@ class MainApplication : public QApplication
{
public:
MainApplication(int& argc, char** argv);
- bool event(QEvent* event);
+ bool event(QEvent* event) override;
#ifdef LMMS_BUILD_WIN32
bool winEventFilter(MSG* msg, long* result);
bool nativeEventFilter(const QByteArray& eventType, void* message,
diff --git a/include/MainWindow.h b/include/MainWindow.h
index 74e569653..5dc102321 100644
--- a/include/MainWindow.h
+++ b/include/MainWindow.h
@@ -176,11 +176,11 @@ private slots:
void onExportProjectMidi();
protected:
- virtual void closeEvent( QCloseEvent * _ce );
- virtual void focusOutEvent( QFocusEvent * _fe );
- virtual void keyPressEvent( QKeyEvent * _ke );
- virtual void keyReleaseEvent( QKeyEvent * _ke );
- virtual void timerEvent( QTimerEvent * _ev );
+ void closeEvent( QCloseEvent * _ce ) override;
+ void focusOutEvent( QFocusEvent * _fe ) override;
+ void keyPressEvent( QKeyEvent * _ke ) override;
+ void keyReleaseEvent( QKeyEvent * _ke ) override;
+ void timerEvent( QTimerEvent * _ev ) override;
private:
diff --git a/include/MeterDialog.h b/include/MeterDialog.h
index 5399c4a9a..da254c7c7 100644
--- a/include/MeterDialog.h
+++ b/include/MeterDialog.h
@@ -40,7 +40,7 @@ public:
MeterDialog( QWidget * _parent, bool _simple = false );
virtual ~MeterDialog();
- virtual void modelChanged();
+ void modelChanged() override;
private:
diff --git a/include/MidiAlsaRaw.h b/include/MidiAlsaRaw.h
index 81f288c22..69f9366f1 100644
--- a/include/MidiAlsaRaw.h
+++ b/include/MidiAlsaRaw.h
@@ -62,8 +62,8 @@ public:
protected:
- virtual void sendByte( const unsigned char c );
- virtual void run();
+ void sendByte( const unsigned char c ) override;
+ void run() override;
private:
diff --git a/include/MidiAlsaSeq.h b/include/MidiAlsaSeq.h
index 0406b42b9..b6e498721 100644
--- a/include/MidiAlsaSeq.h
+++ b/include/MidiAlsaSeq.h
@@ -67,44 +67,44 @@ public:
virtual void processOutEvent( const MidiEvent & _me,
const MidiTime & _time,
- const MidiPort * _port );
+ const MidiPort * _port ) override;
- virtual void applyPortMode( MidiPort * _port );
- virtual void applyPortName( MidiPort * _port );
+ void applyPortMode( MidiPort * _port ) override;
+ void applyPortName( MidiPort * _port ) override;
- virtual void removePort( MidiPort * _port );
+ void removePort( MidiPort * _port ) override;
// list seq-ports from ALSA
- virtual QStringList readablePorts() const
+ QStringList readablePorts() const override
{
return m_readablePorts;
}
- virtual QStringList writablePorts() const
+ QStringList writablePorts() const override
{
return m_writablePorts;
}
// return name of port which specified MIDI event came from
- virtual QString sourcePortName( const MidiEvent & ) const;
+ QString sourcePortName( const MidiEvent & ) const override;
// (un)subscribe given MidiPort to/from destination-port
virtual void subscribeReadablePort( MidiPort * _port,
const QString & _dest,
- bool _subscribe = true );
+ bool _subscribe = true ) override;
virtual void subscribeWritablePort( MidiPort * _port,
const QString & _dest,
- bool _subscribe = true );
+ bool _subscribe = true ) override;
virtual void connectRPChanged( QObject * _receiver,
- const char * _member )
+ const char * _member ) override
{
connect( this, SIGNAL( readablePortsChanged() ),
_receiver, _member );
}
virtual void connectWPChanged( QObject * _receiver,
- const char * _member )
+ const char * _member ) override
{
connect( this, SIGNAL( writablePortsChanged() ),
_receiver, _member );
@@ -117,7 +117,7 @@ private slots:
private:
- virtual void run();
+ void run() override;
#ifdef LMMS_HAVE_ALSA
QMutex m_seqMutex;
diff --git a/include/MidiClient.h b/include/MidiClient.h
index 293f2b3da..f06cac893 100644
--- a/include/MidiClient.h
+++ b/include/MidiClient.h
@@ -124,7 +124,7 @@ public:
virtual ~MidiClientRaw();
// we are raw-clients for sure!
- virtual bool isRaw() const
+ bool isRaw() const override
{
return true;
}
@@ -141,7 +141,7 @@ protected:
private:
// this does MIDI-event-process
void processParsedEvent();
- virtual void processOutEvent( const MidiEvent& event, const MidiTime& time, const MidiPort* port );
+ void processOutEvent( const MidiEvent& event, const MidiTime& time, const MidiPort* port ) override;
// small helper function returning length of a certain event - this
// is necessary for parsing raw-MIDI-data
diff --git a/include/MidiController.h b/include/MidiController.h
index d661b8d0f..43f928a25 100644
--- a/include/MidiController.h
+++ b/include/MidiController.h
@@ -44,30 +44,30 @@ public:
virtual ~MidiController();
virtual void processInEvent( const MidiEvent & _me,
- const MidiTime & _time, f_cnt_t offset = 0 );
+ const MidiTime & _time, f_cnt_t offset = 0 ) override;
virtual void processOutEvent( const MidiEvent& _me,
- const MidiTime & _time, f_cnt_t offset = 0 )
+ const MidiTime & _time, f_cnt_t offset = 0 ) override
{
// No output yet
}
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
- virtual void loadSettings( const QDomElement & _this );
- virtual QString nodeName() const;
+ void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
+ void loadSettings( const QDomElement & _this ) override;
+ QString nodeName() const override;
// Used by controllerConnectionDialog to copy
void subscribeReadablePorts( const MidiPort::Map & _map );
public slots:
- virtual ControllerDialog * createDialog( QWidget * _parent );
+ ControllerDialog * createDialog( QWidget * _parent ) override;
void updateName();
protected:
// The internal per-controller get-value function
- virtual void updateValueBuffer();
+ void updateValueBuffer() override;
MidiPort m_midiPort;
diff --git a/include/MidiDummy.h b/include/MidiDummy.h
index dffd1ce51..f809d3c36 100644
--- a/include/MidiDummy.h
+++ b/include/MidiDummy.h
@@ -56,7 +56,7 @@ public:
protected:
- virtual void sendByte( const unsigned char )
+ void sendByte( const unsigned char ) override
{
}
diff --git a/include/MidiOss.h b/include/MidiOss.h
index 27ebf0771..7e1f179ef 100644
--- a/include/MidiOss.h
+++ b/include/MidiOss.h
@@ -58,8 +58,8 @@ public:
}
protected:
- virtual void sendByte( const unsigned char c );
- virtual void run();
+ void sendByte( const unsigned char c ) override;
+ void run() override;
private:
diff --git a/include/MidiPort.h b/include/MidiPort.h
index 07c61d788..e9cba39ed 100644
--- a/include/MidiPort.h
+++ b/include/MidiPort.h
@@ -103,10 +103,10 @@ public:
void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime() );
- virtual void saveSettings( QDomDocument& doc, QDomElement& thisElement );
- virtual void loadSettings( const QDomElement& thisElement );
+ void saveSettings( QDomDocument& doc, QDomElement& thisElement ) override;
+ void loadSettings( const QDomElement& thisElement ) override;
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "midiport";
}
diff --git a/include/MidiPortMenu.h b/include/MidiPortMenu.h
index b963a7bd9..ce39c4aac 100644
--- a/include/MidiPortMenu.h
+++ b/include/MidiPortMenu.h
@@ -51,7 +51,7 @@ protected slots:
private:
- virtual void modelChanged();
+ void modelChanged() override;
MidiPort::Modes m_mode;
diff --git a/include/MidiSndio.h b/include/MidiSndio.h
index d115993fe..14ecfa0e9 100644
--- a/include/MidiSndio.h
+++ b/include/MidiSndio.h
@@ -59,8 +59,8 @@ public:
protected:
- virtual void sendByte(const unsigned char c);
- virtual void run(void);
+ void sendByte(const unsigned char c) override;
+ void run(void) override;
private:
struct mio_hdl *m_hdl;
diff --git a/include/MidiTime.h b/include/MidiTime.h
index 0e8015e04..952b4b6d5 100644
--- a/include/MidiTime.h
+++ b/include/MidiTime.h
@@ -32,10 +32,10 @@
#include "lmms_export.h"
#include "lmms_basics.h"
-// note: 1 "Tact" = 1 Measure
-const int DefaultTicksPerTact = 192;
-const int DefaultStepsPerTact = 16;
-const int DefaultBeatsPerTact = DefaultTicksPerTact / DefaultStepsPerTact;
+// note: a bar was erroneously called "tact" in older versions of LMMS
+const int DefaultTicksPerBar = 192;
+const int DefaultStepsPerBar = 16;
+const int DefaultBeatsPerBar = DefaultTicksPerBar / DefaultStepsPerBar;
class MeterModel;
@@ -60,19 +60,19 @@ private:
class LMMS_EXPORT MidiTime
{
public:
- MidiTime( const tact_t tact, const tick_t ticks );
+ MidiTime( const bar_t bar, const tick_t ticks );
MidiTime( const tick_t ticks = 0 );
MidiTime quantize(float) const;
- MidiTime toAbsoluteTact() const;
+ MidiTime toAbsoluteBar() const;
MidiTime& operator+=( const MidiTime& time );
MidiTime& operator-=( const MidiTime& time );
- // return the tact, rounded down and 0-based
- tact_t getTact() const;
- // return the tact, rounded up and 0-based
- tact_t nextFullTact() const;
+ // return the bar, rounded down and 0-based
+ bar_t getBar() const;
+ // return the bar, rounded up and 0-based
+ bar_t nextFullBar() const;
void setTicks( tick_t ticks );
tick_t getTicks() const;
@@ -90,21 +90,21 @@ public:
// calculate number of frame that are needed this time
f_cnt_t frames( const float framesPerTick ) const;
- double getTimeInMilliseconds(bpm_t beatsPerMinute) const;
+ double getTimeInMilliseconds( bpm_t beatsPerMinute ) const;
static MidiTime fromFrames( const f_cnt_t frames, const float framesPerTick );
- static tick_t ticksPerTact();
- static tick_t ticksPerTact( const TimeSig &sig );
- static int stepsPerTact();
- static void setTicksPerTact( tick_t tpt );
+ static tick_t ticksPerBar();
+ static tick_t ticksPerBar( const TimeSig &sig );
+ static int stepsPerBar();
+ static void setTicksPerBar( tick_t tpt );
static MidiTime stepPosition( int step );
- static double ticksToMilliseconds(tick_t ticks, bpm_t beatsPerMinute);
- static double ticksToMilliseconds(double ticks, bpm_t beatsPerMinute);
+ static double ticksToMilliseconds( tick_t ticks, bpm_t beatsPerMinute );
+ static double ticksToMilliseconds( double ticks, bpm_t beatsPerMinute );
private:
tick_t m_ticks;
- static tick_t s_ticksPerTact;
+ static tick_t s_ticksPerBar;
} ;
diff --git a/include/Mixer.h b/include/Mixer.h
index 69ea0d12d..32eeb8977 100644
--- a/include/Mixer.h
+++ b/include/Mixer.h
@@ -345,7 +345,7 @@ private:
fifo * m_fifo;
volatile bool m_writing;
- virtual void run();
+ void run() override;
void write( surroundSampleFrame * buffer );
diff --git a/include/MixerWorkerThread.h b/include/MixerWorkerThread.h
index 7c3792392..2d49dce09 100644
--- a/include/MixerWorkerThread.h
+++ b/include/MixerWorkerThread.h
@@ -106,7 +106,7 @@ public:
private:
- virtual void run();
+ void run() override;
static JobQueue globalJobQueue;
static QWaitCondition * queueReadyWaitCond;
diff --git a/include/NStateButton.h b/include/NStateButton.h
index d9e56b892..95d36c253 100644
--- a/include/NStateButton.h
+++ b/include/NStateButton.h
@@ -61,7 +61,7 @@ signals:
protected:
- virtual void mousePressEvent( QMouseEvent * _me );
+ void mousePressEvent( QMouseEvent * _me ) override;
private:
diff --git a/include/Note.h b/include/Note.h
index 0eae8f6b0..30969b4c8 100644
--- a/include/Note.h
+++ b/include/Note.h
@@ -200,7 +200,7 @@ public:
return "note";
}
- inline virtual QString nodeName() const
+ inline QString nodeName() const override
{
return classNodeName();
}
@@ -218,8 +218,8 @@ public:
protected:
- virtual void saveSettings( QDomDocument & doc, QDomElement & parent );
- virtual void loadSettings( const QDomElement & _this );
+ void saveSettings( QDomDocument & doc, QDomElement & parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
private:
diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h
index ae55c9ebb..3dba0f277 100644
--- a/include/NotePlayHandle.h
+++ b/include/NotePlayHandle.h
@@ -74,8 +74,8 @@ public:
return p;
}
- virtual void setVolume( volume_t volume );
- virtual void setPanning( panning_t panning );
+ void setVolume( volume_t volume ) override;
+ void setPanning( panning_t panning ) override;
int midiKey() const;
int midiChannel() const
@@ -105,10 +105,10 @@ public:
}
/*! Renders one chunk using the attached instrument into the buffer */
- virtual void play( sampleFrame* buffer );
+ void play( sampleFrame* buffer ) override;
/*! Returns whether playback of note is finished and thus handle can be deleted */
- virtual bool isFinished() const
+ bool isFinished() const override
{
return m_released && framesLeft() <= 0;
}
@@ -120,7 +120,7 @@ public:
fpp_t framesLeftForCurrentPeriod() const;
/*! Returns whether the play handle plays on a certain track */
- virtual bool isFromTrack( const Track* _track ) const;
+ bool isFromTrack( const Track* _track ) const override;
/*! Releases the note (and plays release frames */
void noteOff( const f_cnt_t offset = 0 );
diff --git a/include/Pattern.h b/include/Pattern.h
index 3a1cc941c..5192da9fa 100644
--- a/include/Pattern.h
+++ b/include/Pattern.h
@@ -94,9 +94,9 @@ public:
Pattern * nextPattern() const;
// settings-management
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
- inline virtual QString nodeName() const
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
+ inline QString nodeName() const override
{
return "pattern";
}
@@ -109,7 +109,7 @@ public:
bool empty();
- virtual TrackContentObjectView * createView( TrackView * _tv );
+ TrackContentObjectView * createView( TrackView * _tv ) override;
using Model::dataChanged;
@@ -182,7 +182,7 @@ public:
void setMutedNoteBorderColor(QColor const & color) { m_mutedNoteBorderColor = color; }
public slots:
- virtual void update();
+ void update() override;
protected slots:
@@ -194,11 +194,11 @@ protected slots:
protected:
- virtual void constructContextMenu( QMenu * );
- virtual void mousePressEvent( QMouseEvent * _me );
- virtual void mouseDoubleClickEvent( QMouseEvent * _me );
- virtual void paintEvent( QPaintEvent * pe );
- virtual void wheelEvent( QWheelEvent * _we );
+ void constructContextMenu( QMenu * ) override;
+ void mousePressEvent( QMouseEvent * _me ) override;
+ void mouseDoubleClickEvent( QMouseEvent * _me ) override;
+ void paintEvent( QPaintEvent * pe ) override;
+ void wheelEvent( QWheelEvent * _we ) override;
private:
diff --git a/include/PeakController.h b/include/PeakController.h
index b2824f0ac..74a3aab59 100644
--- a/include/PeakController.h
+++ b/include/PeakController.h
@@ -46,9 +46,9 @@ public:
virtual ~PeakController();
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
- virtual void loadSettings( const QDomElement & _this );
- virtual QString nodeName() const;
+ void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
+ void loadSettings( const QDomElement & _this ) override;
+ QString nodeName() const override;
static void initGetControllerBySetting();
static PeakController * getControllerBySetting( const QDomElement & _this );
@@ -57,13 +57,13 @@ public:
public slots:
- virtual ControllerDialog * createDialog( QWidget * _parent );
+ ControllerDialog * createDialog( QWidget * _parent ) override;
void handleDestroyedEffect( );
void updateCoeffs();
protected:
// The internal per-controller get-value function
- virtual void updateValueBuffer();
+ void updateValueBuffer() override;
PeakControllerEffect * m_peakEffect;
@@ -91,9 +91,9 @@ public:
virtual ~PeakControllerDialog();
protected:
- virtual void contextMenuEvent( QContextMenuEvent * _me );
- virtual void paintEvent( QPaintEvent * _pe );
- virtual void modelChanged();
+ void contextMenuEvent( QContextMenuEvent * _me ) override;
+ void paintEvent( QPaintEvent * _pe ) override;
+ void modelChanged() override;
PeakController * m_peakController;
diff --git a/include/PianoRoll.h b/include/PianoRoll.h
index 4451a07c5..27a15149e 100644
--- a/include/PianoRoll.h
+++ b/include/PianoRoll.h
@@ -46,7 +46,6 @@ class QPixmap;
class QScrollBar;
class QString;
class QMenu;
-class QSignalMapper;
class ComboBox;
class NotePlayHandle;
@@ -95,6 +94,7 @@ public:
void setCurrentPattern( Pattern* newPattern );
void setGhostPattern( Pattern* newPattern );
void loadGhostNotes( const QDomElement & de );
+ void loadMarkedSemiTones(const QDomElement & de);
inline void stopRecording()
{
@@ -167,17 +167,17 @@ public:
protected:
- virtual void keyPressEvent( QKeyEvent * ke );
- virtual void keyReleaseEvent( QKeyEvent * ke );
- virtual void leaveEvent( QEvent * e );
- virtual void mousePressEvent( QMouseEvent * me );
- virtual void mouseDoubleClickEvent( QMouseEvent * me );
- virtual void mouseReleaseEvent( QMouseEvent * me );
- virtual void mouseMoveEvent( QMouseEvent * me );
- virtual void paintEvent( QPaintEvent * pe );
- virtual void resizeEvent( QResizeEvent * re );
- virtual void wheelEvent( QWheelEvent * we );
- virtual void focusOutEvent( QFocusEvent * );
+ void keyPressEvent( QKeyEvent * ke ) override;
+ void keyReleaseEvent( QKeyEvent * ke ) override;
+ void leaveEvent( QEvent * e ) override;
+ void mousePressEvent( QMouseEvent * me ) override;
+ void mouseDoubleClickEvent( QMouseEvent * me ) override;
+ void mouseReleaseEvent( QMouseEvent * me ) override;
+ void mouseMoveEvent( QMouseEvent * me ) override;
+ void paintEvent( QPaintEvent * pe ) override;
+ void resizeEvent( QResizeEvent * re ) override;
+ void wheelEvent( QWheelEvent * we ) override;
+ void focusOutEvent( QFocusEvent * ) override;
int getKey( int y ) const;
static void drawNoteRect( QPainter & p, int x, int y,
@@ -382,7 +382,7 @@ private:
int m_oldNotesEditHeight;
int m_notesEditHeight;
- int m_ppt; // pixels per tact
+ int m_ppb; // pixels per bar
int m_totalKeysToScroll;
// remember these values to use them
@@ -460,11 +460,11 @@ public:
int quantization() const;
- void play();
- void stop();
- void record();
- void recordAccompany();
- void toggleStepRecording();
+ void play() override;
+ void stop() override;
+ void record() override;
+ void recordAccompany() override;
+ void toggleStepRecording() override;
void stopRecording();
bool isRecording() const;
@@ -474,15 +474,15 @@ public:
using SerializingObject::saveState;
using SerializingObject::restoreState;
- virtual void saveSettings(QDomDocument & doc, QDomElement & de );
- virtual void loadSettings( const QDomElement & de );
+ void saveSettings(QDomDocument & doc, QDomElement & de ) override;
+ void loadSettings( const QDomElement & de ) override;
- inline virtual QString nodeName() const
+ inline QString nodeName() const override
{
return "pianoroll";
}
- QSize sizeHint() const;
+ QSize sizeHint() const override;
signals:
void currentPatternChanged();
@@ -494,7 +494,7 @@ private slots:
private:
void patternRenamed();
- void focusInEvent(QFocusEvent * event);
+ void focusInEvent(QFocusEvent * event) override;
void stopStepRecording();
void updateStepRecordingIcon();
diff --git a/include/PianoView.h b/include/PianoView.h
index 2a362c584..b793ee768 100644
--- a/include/PianoView.h
+++ b/include/PianoView.h
@@ -44,19 +44,19 @@ public:
public:
- virtual void keyPressEvent( QKeyEvent * ke );
- virtual void keyReleaseEvent( QKeyEvent * ke );
+ void keyPressEvent( QKeyEvent * ke ) override;
+ void keyReleaseEvent( QKeyEvent * ke ) override;
protected:
- virtual void modelChanged();
- virtual void contextMenuEvent( QContextMenuEvent * _me );
- virtual void paintEvent( QPaintEvent * );
- virtual void mousePressEvent( QMouseEvent * me );
- virtual void mouseReleaseEvent( QMouseEvent * me );
- virtual void mouseMoveEvent( QMouseEvent * me );
- virtual void focusOutEvent( QFocusEvent * _fe );
- virtual void resizeEvent( QResizeEvent * _event );
+ void modelChanged() override;
+ void contextMenuEvent( QContextMenuEvent * _me ) override;
+ void paintEvent( QPaintEvent * ) override;
+ void mousePressEvent( QMouseEvent * me ) override;
+ void mouseReleaseEvent( QMouseEvent * me ) override;
+ void mouseMoveEvent( QMouseEvent * me ) override;
+ void focusOutEvent( QFocusEvent * _fe ) override;
+ void resizeEvent( QResizeEvent * _event ) override;
private:
diff --git a/include/Pitch.h b/include/Pitch.h
index 5ef1c3d62..2f866a1c5 100644
--- a/include/Pitch.h
+++ b/include/Pitch.h
@@ -25,8 +25,7 @@
#ifndef PITCH_H
#define PITCH_H
-#include "lmms_basics.h"
-#include "Midi.h"
+#include
typedef int16_t pitch_t;
diff --git a/include/PixmapButton.h b/include/PixmapButton.h
index 6ee7bcdc8..e2fb58885 100644
--- a/include/PixmapButton.h
+++ b/include/PixmapButton.h
@@ -42,17 +42,17 @@ public:
void setActiveGraphic( const QPixmap & _pm );
void setInactiveGraphic( const QPixmap & _pm, bool _update = true );
- QSize sizeHint() const;
+ QSize sizeHint() const override;
signals:
void doubleClicked();
protected:
- virtual void paintEvent( QPaintEvent * _pe );
- virtual void mousePressEvent( QMouseEvent * _me );
- virtual void mouseReleaseEvent( QMouseEvent * _me );
- virtual void mouseDoubleClickEvent( QMouseEvent * _me );
+ void paintEvent( QPaintEvent * _pe ) override;
+ void mousePressEvent( QMouseEvent * _me ) override;
+ void mouseReleaseEvent( QMouseEvent * _me ) override;
+ void mouseDoubleClickEvent( QMouseEvent * _me ) override;
private:
diff --git a/include/PlayHandle.h b/include/PlayHandle.h
index 1760e1ec7..1ddd632d1 100644
--- a/include/PlayHandle.h
+++ b/include/PlayHandle.h
@@ -87,9 +87,9 @@ public:
}
// required for ThreadableJob
- virtual void doProcessing();
+ void doProcessing() override;
- virtual bool requiresProcessing() const
+ bool requiresProcessing() const override
{
return !isFinished();
}
diff --git a/include/Plugin.h b/include/Plugin.h
index af42b0f10..cb8995bf2 100644
--- a/include/Plugin.h
+++ b/include/Plugin.h
@@ -239,7 +239,7 @@ public:
virtual ~Plugin();
//! Return display-name out of sub plugin or descriptor
- virtual QString displayName() const;
+ QString displayName() const override;
//! Return logo out of sub plugin or descriptor
const PixmapLoader *logo() const;
diff --git a/include/PresetPreviewPlayHandle.h b/include/PresetPreviewPlayHandle.h
index 57996fa17..a95b680ab 100644
--- a/include/PresetPreviewPlayHandle.h
+++ b/include/PresetPreviewPlayHandle.h
@@ -38,15 +38,15 @@ public:
PresetPreviewPlayHandle( const QString& presetFile, bool loadByPlugin = false, DataFile *dataFile = 0 );
virtual ~PresetPreviewPlayHandle();
- virtual inline bool affinityMatters() const
+ inline bool affinityMatters() const override
{
return true;
}
- virtual void play( sampleFrame* buffer );
- virtual bool isFinished() const;
+ void play( sampleFrame* buffer ) override;
+ bool isFinished() const override;
- virtual bool isFromTrack( const Track * _track ) const;
+ bool isFromTrack( const Track * _track ) const override;
static void init();
static void cleanup();
diff --git a/include/ProjectNotes.h b/include/ProjectNotes.h
index ab82e4eeb..fc97a8844 100644
--- a/include/ProjectNotes.h
+++ b/include/ProjectNotes.h
@@ -47,17 +47,17 @@ public:
void clear();
void setText( const QString & _text );
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
- inline virtual QString nodeName() const
+ inline QString nodeName() const override
{
return "projectnotes";
}
protected:
- virtual void closeEvent( QCloseEvent * _ce );
+ void closeEvent( QCloseEvent * _ce ) override;
void setupActions();
diff --git a/include/ProjectRenderer.h b/include/ProjectRenderer.h
index 4f932ad34..1af9d422d 100644
--- a/include/ProjectRenderer.h
+++ b/include/ProjectRenderer.h
@@ -86,7 +86,7 @@ signals:
private:
- virtual void run();
+ void run() override;
AudioFileDevice * m_fileDev;
Mixer::qualitySettings m_qualitySettings;
diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h
index 27c658a3d..862370d1f 100644
--- a/include/RemotePlugin.h
+++ b/include/RemotePlugin.h
@@ -766,7 +766,7 @@ public:
}
private:
- virtual void run();
+ void run() override;
RemotePlugin * m_plugin;
volatile bool m_quit;
@@ -803,7 +803,7 @@ public:
m_failed = waitForMessage( IdInitDone, _busyWaiting ).id != IdInitDone;
}
- virtual bool processMessage( const message & _m );
+ bool processMessage( const message & _m ) override;
bool process( const sampleFrame * _in_buf, sampleFrame * _out_buf );
diff --git a/include/RenameDialog.h b/include/RenameDialog.h
index c1d24a8a9..8f526badd 100644
--- a/include/RenameDialog.h
+++ b/include/RenameDialog.h
@@ -42,8 +42,8 @@ public:
protected:
- void keyPressEvent( QKeyEvent * _ke );
- virtual void resizeEvent(QResizeEvent * event);
+ void keyPressEvent( QKeyEvent * _ke ) override;
+ void resizeEvent(QResizeEvent * event) override;
protected slots:
diff --git a/include/RingBuffer.h b/include/RingBuffer.h
index c761616bd..c7e91bd33 100644
--- a/include/RingBuffer.h
+++ b/include/RingBuffer.h
@@ -32,6 +32,8 @@
#include "lmms_math.h"
#include "MemoryManager.h"
+/** \brief A basic LMMS ring buffer for single-thread use. For thread and realtime safe alternative see LocklessRingBuffer.
+*/
class LMMS_EXPORT RingBuffer : public QObject
{
Q_OBJECT
diff --git a/include/RowTableView.h b/include/RowTableView.h
index 537792a05..a7b07c2c8 100644
--- a/include/RowTableView.h
+++ b/include/RowTableView.h
@@ -38,11 +38,11 @@ public:
RowTableView( QWidget * parent = 0 );
virtual ~RowTableView();
- virtual void setModel( QAbstractItemModel * model );
+ void setModel( QAbstractItemModel * model ) override;
protected:
- virtual void keyPressEvent( QKeyEvent * event );
+ void keyPressEvent( QKeyEvent * event ) override;
private:
diff --git a/include/Rubberband.h b/include/Rubberband.h
index bc9f3c6a2..eeb3c7e5b 100644
--- a/include/Rubberband.h
+++ b/include/Rubberband.h
@@ -83,7 +83,7 @@ public:
protected:
- virtual void resizeEvent( QResizeEvent * _re );
+ void resizeEvent( QResizeEvent * _re ) override;
private:
diff --git a/include/SamplePlayHandle.h b/include/SamplePlayHandle.h
index d10c44837..33f5ebe52 100644
--- a/include/SamplePlayHandle.h
+++ b/include/SamplePlayHandle.h
@@ -44,16 +44,16 @@ public:
SamplePlayHandle( SampleTCO* tco );
virtual ~SamplePlayHandle();
- virtual inline bool affinityMatters() const
+ inline bool affinityMatters() const override
{
return true;
}
- virtual void play( sampleFrame * buffer );
- virtual bool isFinished() const;
+ void play( sampleFrame * buffer ) override;
+ bool isFinished() const override;
- virtual bool isFromTrack( const Track * _track ) const;
+ bool isFromTrack( const Track * _track ) const override;
f_cnt_t totalFrames() const;
inline f_cnt_t framesDone() const
diff --git a/include/SampleRecordHandle.h b/include/SampleRecordHandle.h
index 22d9bf315..fc40d0622 100644
--- a/include/SampleRecordHandle.h
+++ b/include/SampleRecordHandle.h
@@ -44,10 +44,10 @@ public:
SampleRecordHandle( SampleTCO* tco );
virtual ~SampleRecordHandle();
- virtual void play( sampleFrame * _working_buffer );
- virtual bool isFinished() const;
+ void play( sampleFrame * _working_buffer ) override;
+ bool isFinished() const override;
- virtual bool isFromTrack( const Track * _track ) const;
+ bool isFromTrack( const Track * _track ) const override;
f_cnt_t framesRecorded() const;
void createSampleBuffer( SampleBuffer * * _sample_buf );
diff --git a/include/SampleTrack.h b/include/SampleTrack.h
index 9469669a1..2bad4d910 100644
--- a/include/SampleTrack.h
+++ b/include/SampleTrack.h
@@ -49,12 +49,12 @@ public:
SampleTCO( Track * _track );
virtual ~SampleTCO();
- virtual void changeLength( const MidiTime & _length );
+ void changeLength( const MidiTime & _length ) override;
const QString & sampleFile() const;
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
- inline virtual QString nodeName() const
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
+ inline QString nodeName() const override
{
return "sampletco";
}
@@ -67,7 +67,7 @@ public:
MidiTime sampleLength() const;
void setSampleStartFrame( f_cnt_t startFrame );
void setSamplePlayLength( f_cnt_t length );
- virtual TrackContentObjectView * createView( TrackView * _tv );
+ TrackContentObjectView * createView( TrackView * _tv ) override;
bool isPlaying() const;
@@ -112,13 +112,13 @@ public slots:
protected:
- virtual void contextMenuEvent( QContextMenuEvent * _cme );
- virtual void mousePressEvent( QMouseEvent * _me );
- virtual void mouseReleaseEvent( QMouseEvent * _me );
- virtual void dragEnterEvent( QDragEnterEvent * _dee );
- virtual void dropEvent( QDropEvent * _de );
- virtual void mouseDoubleClickEvent( QMouseEvent * );
- virtual void paintEvent( QPaintEvent * );
+ void contextMenuEvent( QContextMenuEvent * _cme ) override;
+ void mousePressEvent( QMouseEvent * _me ) override;
+ void mouseReleaseEvent( QMouseEvent * _me ) override;
+ void dragEnterEvent( QDragEnterEvent * _dee ) override;
+ void dropEvent( QDropEvent * _de ) override;
+ void mouseDoubleClickEvent( QMouseEvent * ) override;
+ void paintEvent( QPaintEvent * ) override;
private:
@@ -137,14 +137,14 @@ public:
virtual ~SampleTrack();
virtual bool play( const MidiTime & _start, const fpp_t _frames,
- const f_cnt_t _frame_base, int _tco_num = -1 );
- virtual TrackView * createView( TrackContainerView* tcv );
- virtual TrackContentObject * createTCO(const MidiTime & pos);
+ const f_cnt_t _frame_base, int _tco_num = -1 ) override;
+ TrackView * createView( TrackContainerView* tcv ) override;
+ TrackContentObject * createTCO( const MidiTime & _pos ) override;
virtual void saveTrackSpecificSettings( QDomDocument & _doc,
- QDomElement & _parent );
- virtual void loadTrackSpecificSettings( const QDomElement & _this );
+ QDomElement & _parent ) override;
+ void loadTrackSpecificSettings( const QDomElement & _this ) override;
inline IntModel * effectChannelModel()
{
@@ -156,7 +156,7 @@ public:
return &m_audioPort;
}
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "sampletrack";
}
@@ -204,7 +204,7 @@ public:
}
- virtual QMenu * createFxMenu( QString title, QString newFxLabel );
+ QMenu * createFxMenu( QString title, QString newFxLabel ) override;
public slots:
@@ -212,14 +212,14 @@ public slots:
protected:
- void modelChanged();
- virtual QString nodeName() const
+ void modelChanged() override;
+ QString nodeName() const override
{
return "SampleTrackView";
}
- void dragEnterEvent(QDragEnterEvent *dee);
- void dropEvent(QDropEvent *de);
+ void dragEnterEvent(QDragEnterEvent *dee) override;
+ void dropEvent(QDropEvent *de) override;
private slots:
void assignFxLine( int channelIndex );
@@ -273,13 +273,13 @@ public slots:
protected:
// capture close-events for toggling sample-track-button
- virtual void closeEvent(QCloseEvent * ce);
+ void closeEvent(QCloseEvent * ce) override;
- virtual void saveSettings(QDomDocument & doc, QDomElement & element);
- virtual void loadSettings(const QDomElement & element);
+ void saveSettings(QDomDocument & doc, QDomElement & element) override;
+ void loadSettings(const QDomElement & element) override;
private:
- virtual void modelChanged();
+ void modelChanged() override;
SampleTrack * m_track;
SampleTrackView * m_stv;
diff --git a/include/SendButtonIndicator.h b/include/SendButtonIndicator.h
index 97acde1ba..b60113758 100644
--- a/include/SendButtonIndicator.h
+++ b/include/SendButtonIndicator.h
@@ -17,7 +17,7 @@ public:
SendButtonIndicator( QWidget * _parent, FxLine * _owner,
FxMixerView * _mv);
- virtual void mousePressEvent( QMouseEvent * e );
+ void mousePressEvent( QMouseEvent * e ) override;
void updateLightStatus();
private:
diff --git a/include/SetupDialog.h b/include/SetupDialog.h
index 272ba7b09..9f9ae1b3f 100644
--- a/include/SetupDialog.h
+++ b/include/SetupDialog.h
@@ -1,4 +1,3 @@
-
/*
* SetupDialog.h - dialog for setting up LMMS
*
@@ -23,20 +22,20 @@
*
*/
+
#ifndef SETUP_DIALOG_H
#define SETUP_DIALOG_H
#include
#include
+#include "AudioDevice.h"
+#include "AudioDeviceSetupWidget.h"
#include "LedCheckbox.h"
#include "lmmsconfig.h"
-#include "AudioDevice.h"
#include "MidiClient.h"
#include "MidiSetupWidget.h"
-#include "AudioDeviceSetupWidget.h"
-
class QComboBox;
class QLabel;
@@ -48,167 +47,156 @@ class TabBar;
class SetupDialog : public QDialog
{
Q_OBJECT
+
public:
enum ConfigTabs
{
GeneralSettings,
- PathSettings,
PerformanceSettings,
AudioSettings,
- MidiSettings
- } ;
+ MidiSettings,
+ PathsSettings
+ };
- SetupDialog( ConfigTabs _tab_to_open = GeneralSettings );
+ SetupDialog(ConfigTabs tab_to_open = GeneralSettings);
virtual ~SetupDialog();
protected slots:
- virtual void accept();
+ void accept() override;
private slots:
- // general settings widget
- void setBufferSize( int _value );
- void resetBufSize();
+ // General settings widget.
+ void toggleDisplaydBFS(bool enabled);
+ void toggleTooltips(bool enabled);
+ void toggleDisplayWaveform(bool enabled);
+ void toggleNoteLabels(bool enabled);
+ void toggleCompactTrackButtons(bool enabled);
+ void toggleOneInstrumentTrackWindow(bool enabled);
+ void toggleMMPZ(bool enabled);
+ void toggleDisableBackup(bool enabled);
+ void toggleOpenLastProject(bool enabled);
+ void setLanguage(int lang);
- // path settings widget
- void setWorkingDir( const QString & _wd );
- void setVSTDir( const QString & _vd );
- void setGIGDir( const QString & _gd );
- void setSF2Dir( const QString & _sfd );
- void setArtworkDir( const QString & _ad );
- void setLADSPADir( const QString & _ld );
- void setSTKDir( const QString & _sd );
- void setDefaultSoundfont( const QString & _sf );
- void setBackgroundArtwork( const QString & _ba );
-
- // performance settings widget
- void setAutoSaveInterval( int time );
+ // Performance settings widget.
+ void setAutoSaveInterval(int time);
void resetAutoSave();
-
- // audio settings widget
- void audioInterfaceChanged( const QString & _driver );
-
- // MIDI settings widget
- void midiInterfaceChanged( const QString & _driver );
-
-
- void toggleToolTips( bool _enabled );
- void toggleWarnAfterSetup( bool _enabled );
- void toggleDisplaydBFS( bool _enabled );
- void toggleMMPZ( bool _enabled );
- void toggleDisableBackup( bool _enabled );
- void toggleOpenLastProject( bool _enabled );
- void toggleHQAudioDev( bool _enabled );
-
- void openWorkingDir();
- void openVSTDir();
- void openGIGDir();
- void openSF2Dir();
- void openArtworkDir();
- void openLADSPADir();
- void openSTKDir();
- void openDefaultSoundfont();
- void openBackgroundArtwork();
-
- void toggleSmoothScroll( bool _enabled );
- void toggleAutoSave( bool _enabled );
- void toggleRunningAutoSave( bool _enabled );
- void toggleOneInstrumentTrackWindow( bool _enabled );
- void toggleCompactTrackButtons( bool _enabled );
- void toggleSyncVSTPlugins( bool _enabled );
- void toggleAnimateAFP( bool _enabled );
- void toggleNoteLabels( bool en );
- void toggleDisplayWaveform( bool en );
- void toggleDisableAutoquit( bool en );
-
+ void toggleAutoSave(bool enabled);
+ void toggleRunningAutoSave(bool enabled);
+ void toggleSmoothScroll(bool enabled);
+ void toggleAnimateAFP(bool enabled);
+ void toggleSyncVSTPlugins(bool enabled);
void vstEmbedMethodChanged();
- void toggleVSTAlwaysOnTop( bool en );
+ void toggleVSTAlwaysOnTop(bool en);
+ void toggleDisableAutoQuit(bool enabled);
- void setLanguage( int lang );
+ // Audio settings widget.
+ void audioInterfaceChanged(const QString & driver);
+ void toggleHQAudioDev(bool enabled);
+ void setBufferSize(int value);
+ void resetBufferSize();
+ // MIDI settings widget.
+ void midiInterfaceChanged(const QString & driver);
+
+ // Paths settings widget.
+ void openWorkingDir();
+ void setWorkingDir(const QString & workingDir);
+ void openVSTDir();
+ void setVSTDir(const QString & vstDir);
+ void openLADSPADir();
+ void setLADSPADir(const QString & ladspaDir);
+ void openSF2Dir();
+ void setSF2Dir(const QString & sf2Dir);
+ void openSF2File();
+ void setSF2File(const QString & sf2File);
+ void openGIGDir();
+ void setGIGDir(const QString & gigDir);
+ void openThemeDir();
+ void setThemeDir(const QString & themeDir);
+ void openBackgroundPicFile();
+ void setBackgroundPicFile(const QString & backgroundPicFile);
+
+ void showRestartWarning();
private:
TabBar * m_tabBar;
- QSlider * m_bufSizeSlider;
- QLabel * m_bufSizeLbl;
- int m_bufferSize;
-
- bool m_toolTips;
- bool m_warnAfterSetup;
+ // General settings widgets.
bool m_displaydBFS;
+ bool m_tooltips;
+ bool m_displayWaveform;
+ bool m_printNoteLabels;
+ bool m_compactTrackButtons;
+ bool m_oneInstrumentTrackWindow;
bool m_MMPZ;
bool m_disableBackup;
bool m_openLastProject;
- bool m_NaNHandler;
- bool m_hqAudioDev;
QString m_lang;
QStringList m_languages;
-
- QLineEdit * m_wdLineEdit;
- QLineEdit * m_vdLineEdit;
- QLineEdit * m_adLineEdit;
- QLineEdit * m_ladLineEdit;
- QLineEdit * m_gigLineEdit;
- QLineEdit * m_sf2LineEdit;
-#ifdef LMMS_HAVE_FLUIDSYNTH
- QLineEdit * m_sfLineEdit;
-#endif
-#ifdef LMMS_HAVE_STK
- QLineEdit * m_stkLineEdit;
-#endif
- QLineEdit * m_baLineEdit;
-
- QString m_workingDir;
- QString m_vstDir;
- QString m_artworkDir;
- QString m_ladDir;
- QString m_gigDir;
- QString m_sf2Dir;
-#ifdef LMMS_HAVE_FLUIDSYNTH
- QString m_defaultSoundfont;
-#endif
-#ifdef LMMS_HAVE_STK
- QString m_stkDir;
-#endif
- QString m_backgroundArtwork;
-
- bool m_smoothScroll;
+ // Performance settings widgets.
+ int m_saveInterval;
bool m_enableAutoSave;
bool m_enableRunningAutoSave;
- int m_saveInterval;
QSlider * m_saveIntervalSlider;
QLabel * m_saveIntervalLbl;
LedCheckBox * m_autoSave;
LedCheckBox * m_runningAutoSave;
-
- bool m_oneInstrumentTrackWindow;
- bool m_compactTrackButtons;
- bool m_syncVSTPlugins;
+ bool m_smoothScroll;
bool m_animateAFP;
- bool m_printNoteLabels;
- bool m_displayWaveform;
+ QLabel * m_vstEmbedLbl;
+ QComboBox* m_vstEmbedComboBox;
+ QString m_vstEmbedMethod;
+ LedCheckBox * m_vstAlwaysOnTopCheckBox;
+ bool m_vstAlwaysOnTop;
+ bool m_syncVSTPlugins;
bool m_disableAutoQuit;
+
typedef QMap AswMap;
typedef QMap MswMap;
typedef QMap trMap;
+ // Audio settings widgets.
QComboBox * m_audioInterfaces;
AswMap m_audioIfaceSetupWidgets;
trMap m_audioIfaceNames;
+ bool m_NaNHandler;
+ bool m_hqAudioDev;
+ int m_bufferSize;
+ QSlider * m_bufferSizeSlider;
+ QLabel * m_bufferSizeLbl;
+ // MIDI settings widgets.
QComboBox * m_midiInterfaces;
MswMap m_midiIfaceSetupWidgets;
trMap m_midiIfaceNames;
- QComboBox* m_vstEmbedComboBox;
- QString m_vstEmbedMethod;
- LedCheckBox * m_vstAlwaysOnTopCheckBox;
- bool m_vstAlwaysOnTop;
-} ;
-
-
+ // Paths settings widgets.
+ QString m_workingDir;
+ QString m_vstDir;
+ QString m_ladspaDir;
+ QString m_gigDir;
+ QString m_sf2Dir;
+#ifdef LMMS_HAVE_FLUIDSYNTH
+ QString m_sf2File;
+#endif
+ QString m_themeDir;
+ QString m_backgroundPicFile;
+
+ QLineEdit * m_workingDirLineEdit;
+ QLineEdit * m_vstDirLineEdit;
+ QLineEdit * m_themeDirLineEdit;
+ QLineEdit * m_ladspaDirLineEdit;
+ QLineEdit * m_gigDirLineEdit;
+ QLineEdit * m_sf2DirLineEdit;
+#ifdef LMMS_HAVE_FLUIDSYNTH
+ QLineEdit * m_sf2FileLineEdit;
+#endif
+ QLineEdit * m_backgroundPicFileLineEdit;
+
+ QLabel * restartWarningLbl;
+};
#endif
diff --git a/include/SideBarWidget.h b/include/SideBarWidget.h
index 229f07df0..9972daa7c 100644
--- a/include/SideBarWidget.h
+++ b/include/SideBarWidget.h
@@ -28,6 +28,7 @@
#include
#include
#include
+#include
class SideBarWidget : public QWidget
@@ -47,11 +48,13 @@ public:
return m_title;
}
+signals:
+ void closeButtonClicked();
protected:
- virtual void paintEvent( QPaintEvent * _pe );
- virtual void resizeEvent( QResizeEvent * _re );
- virtual void contextMenuEvent( QContextMenuEvent * )
+ void paintEvent( QPaintEvent * _pe ) override;
+ void resizeEvent( QResizeEvent * _re ) override;
+ void contextMenuEvent( QContextMenuEvent * ) override
{
}
@@ -75,6 +78,8 @@ private:
QVBoxLayout * m_layout;
QString m_title;
QPixmap m_icon;
+ QPushButton * m_closeBtn;
+ const QSize m_buttonSize;
} ;
diff --git a/include/Song.h b/include/Song.h
index 32ead7181..d398a168c 100644
--- a/include/Song.h
+++ b/include/Song.h
@@ -45,7 +45,7 @@ class TimeLineWidget;
const bpm_t MinTempo = 10;
const bpm_t DefaultTempo = 140;
const bpm_t MaxTempo = 999;
-const tick_t MaxSongLength = 9999 * DefaultTicksPerTact;
+const tick_t MaxSongLength = 9999 * DefaultTicksPerBar;
class LMMS_EXPORT Song : public TrackContainer
@@ -155,14 +155,14 @@ public:
m_playPos[playMode].setTicks(ticks);
}
- inline int getTacts() const
+ inline int getBars() const
{
- return currentTact();
+ return currentBar();
}
- inline int ticksPerTact() const
+ inline int ticksPerBar() const
{
- return MidiTime::ticksPerTact(m_timeSigModel);
+ return MidiTime::ticksPerBar(m_timeSigModel);
}
// Returns the beat position inside the bar, 0-based
@@ -254,14 +254,14 @@ public:
}
void updateLength();
- tact_t length() const
+ bar_t length() const
{
return m_length;
}
bpm_t getTempo();
- virtual AutomationPattern * tempoAutomationPattern();
+ AutomationPattern * tempoAutomationPattern() override;
AutomationTrack * globalAutomationTrack()
{
@@ -269,7 +269,7 @@ public:
}
//TODO: Add Q_DECL_OVERRIDE when Qt4 is dropped
- AutomatedValueMap automatedValuesAt(MidiTime time, int tcoNum = -1) const;
+ AutomatedValueMap automatedValuesAt(MidiTime time, int tcoNum = -1) const override;
// file management
void createNewProject();
@@ -305,7 +305,7 @@ public:
return m_modified;
}
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "song";
}
@@ -382,9 +382,9 @@ private:
virtual ~Song();
- inline tact_t currentTact() const
+ inline bar_t currentBar() const
{
- return m_playPos[m_playMode].getTact();
+ return m_playPos[m_playMode].getBar();
}
inline tick_t currentTick() const
@@ -415,7 +415,7 @@ private:
IntModel m_tempoModel;
MeterModel m_timeSigModel;
- int m_oldTicksPerTact;
+ int m_oldTicksPerBar;
IntModel m_masterVolumeModel;
IntModel m_masterPitchModel;
@@ -445,14 +445,14 @@ private:
PlayModes m_playMode;
PlayPos m_playPos[Mode_Count];
- tact_t m_length;
+ bar_t m_length;
const Pattern* m_patternToPlay;
bool m_loopPattern;
double m_elapsedMilliSeconds[Mode_Count];
tick_t m_elapsedTicks;
- tact_t m_elapsedTacts;
+ bar_t m_elapsedBars;
VstSyncController m_vstSyncController;
@@ -473,9 +473,9 @@ signals:
void projectLoaded();
void playbackStateChanged();
void playbackPositionChanged();
- void lengthChanged( int tacts );
+ void lengthChanged( int bars );
void tempoChanged( bpm_t newBPM );
- void timeSignatureChanged( int oldTicksPerTact, int ticksPerTact );
+ void timeSignatureChanged( int oldTicksPerBar, int ticksPerBar );
void controllerAdded( Controller * );
void controllerRemoved( Controller * );
void updateSampleTracks();
diff --git a/include/SongEditor.h b/include/SongEditor.h
index 8a02d5691..9621bcc23 100644
--- a/include/SongEditor.h
+++ b/include/SongEditor.h
@@ -51,7 +51,7 @@ public:
positionLine( QWidget * parent );
private:
- virtual void paintEvent( QPaintEvent * pe );
+ void paintEvent( QPaintEvent * pe ) override;
} ;
@@ -69,8 +69,8 @@ public:
SongEditor( Song * song );
~SongEditor();
- void saveSettings( QDomDocument& doc, QDomElement& element );
- void loadSettings( const QDomElement& element );
+ void saveSettings( QDomDocument& doc, QDomElement& element ) override;
+ void loadSettings( const QDomElement& element ) override;
ComboBoxModel *zoomingModel() const;
ComboBoxModel *snappingModel() const;
@@ -79,6 +79,9 @@ public:
public slots:
void scrolled( int new_pos );
+ void selectRegionFromPixels(int xStart, int xEnd);
+ void stopSelectRegion();
+ void updateRubberband();
void setEditMode( EditMode mode );
void setEditModeDraw();
@@ -90,7 +93,10 @@ public slots:
void selectAllTcos( bool select );
protected:
- virtual void closeEvent( QCloseEvent * ce );
+ void closeEvent( QCloseEvent * ce ) override;
+ void mousePressEvent(QMouseEvent * me) override;
+ void mouseMoveEvent(QMouseEvent * me) override;
+ void mouseReleaseEvent(QMouseEvent * me) override;
private slots:
void setHighQuality( bool );
@@ -110,10 +116,13 @@ private slots:
void zoomingChanged();
private:
- virtual void keyPressEvent( QKeyEvent * ke );
- virtual void wheelEvent( QWheelEvent * we );
+ void keyPressEvent( QKeyEvent * ke ) override;
+ void wheelEvent( QWheelEvent * we ) override;
- virtual bool allowRubberband() const;
+ bool allowRubberband() const override;
+
+ int trackIndexFromSelectionPoint(int yPos);
+ int indexOfTrackView(const TrackView* tv);
Song * m_song;
@@ -141,11 +150,19 @@ private:
bool m_scrollBack;
bool m_smoothScroll;
- int m_widgetWidthTotal;
EditMode m_mode;
EditMode m_ctrlMode; // mode they were in before they hit ctrl
+ QPoint m_origin;
+ QPoint m_scrollPos;
+ QPoint m_mousePos;
+ int m_rubberBandStartTrackview;
+ MidiTime m_rubberbandStartMidipos;
+ int m_currentZoomingValue;
+ int m_trackHeadWidth;
+ bool m_selectRegion;
+
friend class SongEditorWindow;
} ;
@@ -158,19 +175,19 @@ class SongEditorWindow : public Editor
public:
SongEditorWindow( Song* song );
- QSize sizeHint() const;
+ QSize sizeHint() const override;
SongEditor* m_editor;
protected:
- virtual void resizeEvent( QResizeEvent * event );
- virtual void changeEvent( QEvent * );
+ void resizeEvent( QResizeEvent * event ) override;
+ void changeEvent( QEvent * ) override;
protected slots:
- void play();
- void record();
- void recordAccompany();
- void stop();
+ void play() override;
+ void record() override;
+ void recordAccompany() override;
+ void stop() override;
void lostFocus();
void adjustUiAfterProjectLoad();
@@ -182,8 +199,8 @@ signals:
void resized();
private:
- virtual void keyPressEvent( QKeyEvent * ke );
- virtual void keyReleaseEvent( QKeyEvent * ke );
+ void keyPressEvent( QKeyEvent * ke ) override;
+ void keyReleaseEvent( QKeyEvent * ke ) override;
QAction* m_addBBTrackAction;
QAction* m_addSampleTrackAction;
diff --git a/include/StepRecorderWidget.h b/include/StepRecorderWidget.h
index 0e4512169..14cfc2eed 100644
--- a/include/StepRecorderWidget.h
+++ b/include/StepRecorderWidget.h
@@ -36,14 +36,14 @@ class StepRecorderWidget : public QWidget
public:
StepRecorderWidget(
QWidget * parent,
- const int ppt,
+ const int ppb,
const int marginTop,
const int marginBottom,
const int marginLeft,
const int marginRight);
//API used by PianoRoll
- void setPixelsPerTact(int ppt);
+ void setPixelsPerBar(int ppb);
void setCurrentPosition(MidiTime currentPosition);
void setBottomMargin(const int marginBottom);
@@ -55,7 +55,7 @@ public:
void showHint();
private:
- virtual void paintEvent(QPaintEvent * pe);
+ void paintEvent(QPaintEvent * pe) override;
int xCoordOfTick(int tick);
@@ -68,7 +68,7 @@ private:
MidiTime m_curStepStartPos;
MidiTime m_curStepEndPos;
- int m_ppt; // pixels per tact
+ int m_ppb; // pixels per bar
MidiTime m_currentPosition; // current position showed by on PianoRoll
QColor m_colorLineStart;
diff --git a/include/SubWindow.h b/include/SubWindow.h
index 5d7a810c2..148cf2c99 100644
--- a/include/SubWindow.h
+++ b/include/SubWindow.h
@@ -67,10 +67,10 @@ public:
protected:
// hook the QWidget move/resize events to update the tracked geometry
- virtual void moveEvent( QMoveEvent * event );
- virtual void resizeEvent( QResizeEvent * event );
- virtual void paintEvent( QPaintEvent * pe );
- virtual void changeEvent( QEvent * event );
+ void moveEvent( QMoveEvent * event ) override;
+ void resizeEvent( QResizeEvent * event ) override;
+ void paintEvent( QPaintEvent * pe ) override;
+ void changeEvent( QEvent * event ) override;
signals:
void focusLost();
diff --git a/include/TabWidget.h b/include/TabWidget.h
index 88ecf9034..0cf15155b 100644
--- a/include/TabWidget.h
+++ b/include/TabWidget.h
@@ -72,13 +72,13 @@ public:
void setTabBorder( const QColor & c );
protected:
- virtual bool event( QEvent * event );
- virtual void mousePressEvent( QMouseEvent * _me );
- virtual void paintEvent( QPaintEvent * _pe );
- virtual void resizeEvent( QResizeEvent * _re );
- virtual void wheelEvent( QWheelEvent * _we );
- virtual QSize minimumSizeHint() const;
- virtual QSize sizeHint() const;
+ bool event( QEvent * event ) override;
+ void mousePressEvent( QMouseEvent * _me ) override;
+ void paintEvent( QPaintEvent * _pe ) override;
+ void resizeEvent( QResizeEvent * _re ) override;
+ void wheelEvent( QWheelEvent * _we ) override;
+ QSize minimumSizeHint() const override;
+ QSize sizeHint() const override;
private:
struct widgetDesc
diff --git a/include/TempoSyncKnob.h b/include/TempoSyncKnob.h
index 034e2b8f4..416abe1fc 100644
--- a/include/TempoSyncKnob.h
+++ b/include/TempoSyncKnob.h
@@ -52,7 +52,7 @@ public:
return castModel();
}
- virtual void modelChanged();
+ void modelChanged() override;
signals:
@@ -61,7 +61,7 @@ signals:
protected:
- virtual void contextMenuEvent( QContextMenuEvent * _me );
+ void contextMenuEvent( QContextMenuEvent * _me ) override;
protected slots:
diff --git a/include/TempoSyncKnobModel.h b/include/TempoSyncKnobModel.h
index 9aaf48fea..b9512aa1a 100644
--- a/include/TempoSyncKnobModel.h
+++ b/include/TempoSyncKnobModel.h
@@ -52,7 +52,7 @@ public:
const float _max, const float _step,
const float _scale, Model * _parent,
const QString & _display_name = QString() );
- virtual ~TempoSyncKnobModel() override;
+ ~TempoSyncKnobModel() override;
void saveSettings( QDomDocument & _doc, QDomElement & _this, const QString& name ) override;
void loadSettings( const QDomElement & _this, const QString& name ) override;
diff --git a/include/TextFloat.h b/include/TextFloat.h
index ed10516b5..8f940c591 100644
--- a/include/TextFloat.h
+++ b/include/TextFloat.h
@@ -66,8 +66,8 @@ public:
protected:
- virtual void paintEvent( QPaintEvent * _me );
- virtual void mousePressEvent( QMouseEvent * _me );
+ void paintEvent( QPaintEvent * _me ) override;
+ void mousePressEvent( QMouseEvent * _me ) override;
private:
diff --git a/include/TimeDisplayWidget.h b/include/TimeDisplayWidget.h
index 175f159c9..e7e5cb210 100644
--- a/include/TimeDisplayWidget.h
+++ b/include/TimeDisplayWidget.h
@@ -41,7 +41,7 @@ public:
protected:
- virtual void mousePressEvent( QMouseEvent* mouseEvent );
+ void mousePressEvent( QMouseEvent* mouseEvent ) override;
private slots:
diff --git a/include/TimeLineWidget.h b/include/TimeLineWidget.h
index 7629694ca..bc0881f82 100644
--- a/include/TimeLineWidget.h
+++ b/include/TimeLineWidget.h
@@ -72,15 +72,15 @@ public:
} ;
- TimeLineWidget(int xoff, int yoff, float ppt, Song::PlayPos & pos,
+ TimeLineWidget(int xoff, int yoff, float ppb, Song::PlayPos & pos,
const MidiTime & begin, Song::PlayModes mode, QWidget * parent);
virtual ~TimeLineWidget();
inline QColor const & getBarLineColor() const { return m_barLineColor; }
- inline void setBarLineColor(QColor const & tactLineColor) { m_barLineColor = tactLineColor; }
+ inline void setBarLineColor(QColor const & barLineColor) { m_barLineColor = barLineColor; }
inline QColor const & getBarNumberColor() const { return m_barNumberColor; }
- inline void setBarNumberColor(QColor const & tactNumberColor) { m_barNumberColor = tactNumberColor; }
+ inline void setBarNumberColor(QColor const & barNumberColor) { m_barNumberColor = barNumberColor; }
inline QColor const & getInactiveLoopColor() const { return m_inactiveLoopColor; }
inline void setInactiveLoopColor(QColor const & inactiveLoopColor) { m_inactiveLoopColor = inactiveLoopColor; }
@@ -135,27 +135,27 @@ public:
m_loopPos[0] : m_loopPos[1];
}
- inline void savePos( const MidiTime & _pos )
+ inline void savePos( const MidiTime & pos )
{
- m_savedPos = _pos;
+ m_savedPos = pos;
}
inline const MidiTime & savedPos() const
{
return m_savedPos;
}
- inline void setPixelsPerTact( float _ppt )
+ inline void setPixelsPerBar( float ppb )
{
- m_ppt = _ppt;
+ m_ppb = ppb;
update();
}
void addToolButtons(QToolBar* _tool_bar );
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
- inline virtual QString nodeName() const
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
+ inline QString nodeName() const override
{
return "timeline";
}
@@ -163,7 +163,7 @@ public:
inline int markerX( const MidiTime & _t ) const
{
return m_xOffset + static_cast( ( _t - m_begin ) *
- m_ppt / MidiTime::ticksPerTact() );
+ m_ppb / MidiTime::ticksPerBar() );
}
signals:
@@ -184,10 +184,10 @@ public slots:
protected:
- virtual void paintEvent( QPaintEvent * _pe );
- virtual void mousePressEvent( QMouseEvent * _me );
- virtual void mouseMoveEvent( QMouseEvent * _me );
- virtual void mouseReleaseEvent( QMouseEvent * _me );
+ void paintEvent( QPaintEvent * _pe ) override;
+ void mousePressEvent( QMouseEvent * _me ) override;
+ void mouseMoveEvent( QMouseEvent * _me ) override;
+ void mouseReleaseEvent( QMouseEvent * _me ) override;
private:
@@ -214,7 +214,7 @@ private:
int m_xOffset;
int m_posMarkerX;
- float m_ppt;
+ float m_ppb;
Song::PlayPos & m_pos;
const MidiTime & m_begin;
const Song::PlayModes m_mode;
diff --git a/include/Track.h b/include/Track.h
index b00c50248..70e49a1c6 100644
--- a/include/Track.h
+++ b/include/Track.h
@@ -29,7 +29,6 @@
#include
#include
#include
-#include
#include
#include
@@ -73,7 +72,7 @@ const int DEFAULT_TRACK_HEIGHT = 32;
const int TCO_BORDER_WIDTH = 2;
-class TrackContentObject : public Model, public JournallingObject
+class LMMS_EXPORT TrackContentObject : public Model, public JournallingObject
{
Q_OBJECT
MM_OPERATORS
@@ -99,7 +98,7 @@ public:
emit dataChanged();
}
- virtual QString displayName() const
+ QString displayName() const override
{
return name();
}
@@ -215,6 +214,12 @@ public:
{
return m_tco;
}
+
+ inline TrackView * getTrackView()
+ {
+ return m_trackView;
+ }
+
// qproperty access func
QColor mutedColor() const;
QColor mutedBackgroundColor() const;
@@ -241,32 +246,28 @@ public slots:
virtual bool close();
void cut();
void remove();
- virtual void update();
+ void update() override;
protected:
virtual void constructContextMenu( QMenu * )
{
}
- virtual void contextMenuEvent( QContextMenuEvent * cme );
- virtual void dragEnterEvent( QDragEnterEvent * dee );
- virtual void dropEvent( QDropEvent * de );
- virtual void leaveEvent( QEvent * e );
- virtual void mousePressEvent( QMouseEvent * me );
- virtual void mouseMoveEvent( QMouseEvent * me );
- virtual void mouseReleaseEvent( QMouseEvent * me );
- virtual void resizeEvent( QResizeEvent * re )
+ void contextMenuEvent( QContextMenuEvent * cme ) override;
+ void dragEnterEvent( QDragEnterEvent * dee ) override;
+ void dropEvent( QDropEvent * de ) override;
+ void leaveEvent( QEvent * e ) override;
+ void mousePressEvent( QMouseEvent * me ) override;
+ void mouseMoveEvent( QMouseEvent * me ) override;
+ void mouseReleaseEvent( QMouseEvent * me ) override;
+ void resizeEvent( QResizeEvent * re ) override
{
m_needsUpdate = true;
selectableObject::resizeEvent( re );
}
- float pixelsPerTact();
+ float pixelsPerBar();
- inline TrackView * getTrackView()
- {
- return m_trackView;
- }
DataFile createTCODataFiles(const QVector & tcos) const;
@@ -380,24 +381,24 @@ public slots:
void changePosition( const MidiTime & newPos = MidiTime( -1 ) );
protected:
- virtual void dragEnterEvent( QDragEnterEvent * dee );
- virtual void dropEvent( QDropEvent * de );
- virtual void mousePressEvent( QMouseEvent * me );
- virtual void paintEvent( QPaintEvent * pe );
- virtual void resizeEvent( QResizeEvent * re );
+ void dragEnterEvent( QDragEnterEvent * dee ) override;
+ void dropEvent( QDropEvent * de ) override;
+ void mousePressEvent( QMouseEvent * me ) override;
+ void paintEvent( QPaintEvent * pe ) override;
+ void resizeEvent( QResizeEvent * re ) override;
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "trackcontentwidget";
}
- virtual void saveSettings( QDomDocument& doc, QDomElement& element )
+ void saveSettings( QDomDocument& doc, QDomElement& element ) override
{
Q_UNUSED(doc)
Q_UNUSED(element)
}
- virtual void loadSettings( const QDomElement& element )
+ void loadSettings( const QDomElement& element ) override
{
Q_UNUSED(element)
}
@@ -434,8 +435,8 @@ public:
protected:
- virtual void mousePressEvent( QMouseEvent * me );
- virtual void paintEvent( QPaintEvent * pe );
+ void mousePressEvent( QMouseEvent * me ) override;
+ void paintEvent( QPaintEvent * pe ) override;
private slots:
@@ -517,8 +518,8 @@ public:
virtual void loadTrackSpecificSettings( const QDomElement & element ) = 0;
- virtual void saveSettings( QDomDocument & doc, QDomElement & element );
- virtual void loadSettings( const QDomElement & element );
+ void saveSettings( QDomDocument & doc, QDomElement & element ) override;
+ void loadSettings( const QDomElement & element ) override;
void setSimpleSerializing()
{
@@ -546,10 +547,10 @@ public:
void createTCOsForBB( int bb );
- void insertTact( const MidiTime & pos );
- void removeTact( const MidiTime & pos );
+ void insertBar( const MidiTime & pos );
+ void removeBar( const MidiTime & pos );
- tact_t length() const;
+ bar_t length() const;
inline TrackContainer* trackContainer() const
@@ -563,7 +564,7 @@ public:
return m_name;
}
- virtual QString displayName() const
+ QString displayName() const override
{
return name();
}
@@ -691,32 +692,32 @@ public slots:
protected:
- virtual void modelChanged();
+ void modelChanged() override;
- virtual void saveSettings( QDomDocument& doc, QDomElement& element )
+ void saveSettings( QDomDocument& doc, QDomElement& element ) override
{
Q_UNUSED(doc)
Q_UNUSED(element)
}
- virtual void loadSettings( const QDomElement& element )
+ void loadSettings( const QDomElement& element ) override
{
Q_UNUSED(element)
}
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "trackview";
}
- virtual void dragEnterEvent( QDragEnterEvent * dee );
- virtual void dropEvent( QDropEvent * de );
- virtual void mousePressEvent( QMouseEvent * me );
- virtual void mouseMoveEvent( QMouseEvent * me );
- virtual void mouseReleaseEvent( QMouseEvent * me );
- virtual void paintEvent( QPaintEvent * pe );
- virtual void resizeEvent( QResizeEvent * re );
+ void dragEnterEvent( QDragEnterEvent * dee ) override;
+ void dropEvent( QDropEvent * de ) override;
+ void mousePressEvent( QMouseEvent * me ) override;
+ void mouseMoveEvent( QMouseEvent * me ) override;
+ void mouseReleaseEvent( QMouseEvent * me ) override;
+ void paintEvent( QPaintEvent * pe ) override;
+ void resizeEvent( QResizeEvent * re ) override;
private:
diff --git a/include/TrackContainer.h b/include/TrackContainer.h
index 1caca922e..fd853a73c 100644
--- a/include/TrackContainer.h
+++ b/include/TrackContainer.h
@@ -51,9 +51,9 @@ public:
TrackContainer();
virtual ~TrackContainer();
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
- virtual void loadSettings( const QDomElement & _this );
+ void loadSettings( const QDomElement & _this ) override;
virtual AutomationPattern * tempoAutomationPattern()
@@ -124,7 +124,7 @@ public:
{
}
- virtual QString nodeName() const
+ QString nodeName() const override
{
return "DummyTrackContainer";
}
diff --git a/include/TrackContainerView.h b/include/TrackContainerView.h
index 67575583b..6e952189b 100644
--- a/include/TrackContainerView.h
+++ b/include/TrackContainerView.h
@@ -49,30 +49,30 @@ public:
TrackContainerView( TrackContainer* tc );
virtual ~TrackContainerView();
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
- virtual void loadSettings( const QDomElement & _this );
+ void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
+ void loadSettings( const QDomElement & _this ) override;
QScrollArea * contentWidget()
{
- return( m_scrollArea );
+ return m_scrollArea;
}
inline const MidiTime & currentPosition() const
{
- return( m_currentPosition );
+ return m_currentPosition;
}
virtual bool fixedTCOs() const
{
- return( false );
+ return false;
}
- inline float pixelsPerTact() const
+ inline float pixelsPerBar() const
{
- return( m_ppt );
+ return m_ppb;
}
- void setPixelsPerTact( int _ppt );
+ void setPixelsPerBar( int ppb );
const TrackView * trackViewAt( const int _y ) const;
@@ -80,12 +80,12 @@ public:
inline bool rubberBandActive() const
{
- return( m_rubberBand->isEnabled() && m_rubberBand->isVisible() );
+ return m_rubberBand->isEnabled() && m_rubberBand->isVisible();
}
inline QVector selectedObjects()
{
- return( m_rubberBand->selectedObjects() );
+ return m_rubberBand->selectedObjects();
}
@@ -116,9 +116,9 @@ public:
void clearAllTracks();
- virtual QString nodeName() const
+ QString nodeName() const override
{
- return( "trackcontainerview" );
+ return "trackcontainerview";
}
@@ -129,27 +129,19 @@ public slots:
TrackView * createTrackView( Track * _t );
void deleteTrackView( TrackView * _tv );
- virtual void dropEvent( QDropEvent * _de );
- virtual void dragEnterEvent( QDragEnterEvent * _dee );
- ///
- /// \brief selectRegionFromPixels
- /// \param x
- /// \param y
- /// Use the rubber band to select TCO from all tracks using x, y pixels
- void selectRegionFromPixels(int xStart, int xEnd);
+ void dropEvent( QDropEvent * _de ) override;
+ void dragEnterEvent( QDragEnterEvent * _dee ) override;
///
/// \brief stopRubberBand
/// Removes the rubber band from display when finished with.
void stopRubberBand();
-protected:
- static const int DEFAULT_PIXELS_PER_TACT = 16;
- virtual void mousePressEvent( QMouseEvent * _me );
- virtual void mouseMoveEvent( QMouseEvent * _me );
- virtual void mouseReleaseEvent( QMouseEvent * _me );
- virtual void resizeEvent( QResizeEvent * );
+protected:
+ static const int DEFAULT_PIXELS_PER_BAR = 16;
+
+ void resizeEvent( QResizeEvent * ) override;
MidiTime m_currentPosition;
@@ -168,7 +160,7 @@ private:
virtual ~scrollArea();
protected:
- virtual void wheelEvent( QWheelEvent * _we );
+ void wheelEvent( QWheelEvent * _we ) override;
private:
TrackContainerView* m_trackContainerView;
@@ -183,10 +175,10 @@ private:
scrollArea * m_scrollArea;
QVBoxLayout * m_scrollLayout;
- float m_ppt;
+ float m_ppb;
RubberBand * m_rubberBand;
- QPoint m_origin;
+
signals:
@@ -202,7 +194,7 @@ public:
InstrumentLoaderThread( QObject *parent = 0, InstrumentTrack *it = 0,
QString name = "" );
- void run();
+ void run() override;
private:
InstrumentTrack *m_it;
diff --git a/include/TrackLabelButton.h b/include/TrackLabelButton.h
index f1059bdbf..7d9726feb 100644
--- a/include/TrackLabelButton.h
+++ b/include/TrackLabelButton.h
@@ -49,13 +49,13 @@ public slots:
protected:
- virtual void dragEnterEvent( QDragEnterEvent * _dee );
- virtual void dropEvent( QDropEvent * _de );
- virtual void mousePressEvent( QMouseEvent * _me );
- virtual void mouseDoubleClickEvent( QMouseEvent * _me );
- virtual void mouseReleaseEvent( QMouseEvent * _me );
- virtual void paintEvent( QPaintEvent * _pe );
- virtual void resizeEvent( QResizeEvent * _re );
+ void dragEnterEvent( QDragEnterEvent * _dee ) override;
+ void dropEvent( QDropEvent * _de ) override;
+ void mousePressEvent( QMouseEvent * _me ) override;
+ void mouseDoubleClickEvent( QMouseEvent * _me ) override;
+ void mouseReleaseEvent( QMouseEvent * _me ) override;
+ void paintEvent( QPaintEvent * _pe ) override;
+ void resizeEvent( QResizeEvent * _re ) override;
private:
diff --git a/include/TrackRenameLineEdit.h b/include/TrackRenameLineEdit.h
index 6883b9b05..e681a2d21 100644
--- a/include/TrackRenameLineEdit.h
+++ b/include/TrackRenameLineEdit.h
@@ -37,7 +37,7 @@ public:
void show();
protected:
- virtual void keyPressEvent( QKeyEvent * ke );
+ void keyPressEvent( QKeyEvent * ke ) override;
private:
QString m_oldName;
diff --git a/include/VisualizationWidget.h b/include/VisualizationWidget.h
index a178b1ad8..85825975a 100644
--- a/include/VisualizationWidget.h
+++ b/include/VisualizationWidget.h
@@ -61,8 +61,8 @@ public:
protected:
- virtual void paintEvent( QPaintEvent * _pe );
- virtual void mousePressEvent( QMouseEvent * _me );
+ void paintEvent( QPaintEvent * _pe ) override;
+ void mousePressEvent( QMouseEvent * _me ) override;
protected slots:
diff --git a/include/lmms_basics.h b/include/lmms_basics.h
index cca04e97d..961810856 100644
--- a/include/lmms_basics.h
+++ b/include/lmms_basics.h
@@ -35,7 +35,7 @@
#endif
-typedef int32_t tact_t;
+typedef int32_t bar_t;
typedef int32_t tick_t;
typedef uint8_t volume_t;
typedef int8_t panning_t;
diff --git a/include/lmms_constants.h b/include/lmms_constants.h
index befa789dd..ae6d3d277 100644
--- a/include/lmms_constants.h
+++ b/include/lmms_constants.h
@@ -49,4 +49,47 @@ const float F_PI_SQR = (float) LD_PI_SQR;
const float F_E = (float) LD_E;
const float F_E_R = (float) LD_E_R;
+// Frequency ranges (in Hz).
+// Arbitrary low limit for logarithmic frequency scale; >1 Hz.
+const int LOWEST_LOG_FREQ = 10;
+
+// Full range is defined by LOWEST_LOG_FREQ and current sample rate.
+enum FREQUENCY_RANGES
+{
+ FRANGE_FULL = 0,
+ FRANGE_AUDIBLE,
+ FRANGE_BASS,
+ FRANGE_MIDS,
+ FRANGE_HIGH
+};
+
+const int FRANGE_AUDIBLE_START = 20;
+const int FRANGE_AUDIBLE_END = 20000;
+const int FRANGE_BASS_START = 20;
+const int FRANGE_BASS_END = 300;
+const int FRANGE_MIDS_START = 200;
+const int FRANGE_MIDS_END = 5000;
+const int FRANGE_HIGH_START = 4000;
+const int FRANGE_HIGH_END = 20000;
+
+// Amplitude ranges (in dBFS).
+// Reference: full scale sine wave (-1.0 to 1.0) is 0 dB.
+// Doubling or halving the amplitude produces 3 dB difference.
+enum AMPLITUDE_RANGES
+{
+ ARANGE_EXTENDED = 0,
+ ARANGE_AUDIBLE,
+ ARANGE_LOUD,
+ ARANGE_SILENT
+};
+
+const int ARANGE_EXTENDED_START = -80;
+const int ARANGE_EXTENDED_END = 20;
+const int ARANGE_AUDIBLE_START = -50;
+const int ARANGE_AUDIBLE_END = 0;
+const int ARANGE_LOUD_START = -30;
+const int ARANGE_LOUD_END = 0;
+const int ARANGE_SILENT_START = -60;
+const int ARANGE_SILENT_END = -10;
+
#endif
diff --git a/include/panning.h b/include/panning.h
index 8668ddf88..c043adf5c 100644
--- a/include/panning.h
+++ b/include/panning.h
@@ -27,9 +27,9 @@
#define PANNING_H
#include "lmms_basics.h"
-#include "volume.h"
#include "panning_constants.h"
#include "Midi.h"
+#include "volume.h"
inline stereoVolumeVector panningToVolumeVector( panning_t _p,
float _scale = 1.0f )
diff --git a/include/versioninfo.h b/include/versioninfo.h
index b34936d57..a5d3d64c6 100644
--- a/include/versioninfo.h
+++ b/include/versioninfo.h
@@ -32,6 +32,10 @@
#define PLATFORM "OpenBSD"
#endif
+#ifdef LMMS_BUILD_FREEBSD
+#define PLATFORM "FreeBSD"
+#endif
+
#ifdef LMMS_BUILD_WIN32
#define PLATFORM "win32"
#endif
diff --git a/include/volume.h b/include/volume.h
index f0f7708ad..9172395d6 100644
--- a/include/volume.h
+++ b/include/volume.h
@@ -26,10 +26,7 @@
#ifndef VOLUME_H
#define VOLUME_H
-#include "lmmsconfig.h"
-
#include "lmms_basics.h"
-#include "Midi.h"
const volume_t MinVolume = 0;
const volume_t MaxVolume = 200;
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index e12783bab..77f7aa223 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -14,90 +14,8 @@ INCLUDE_DIRECTORIES(
"${CMAKE_BINARY_DIR}/src"
)
-SET(PLUGIN_LIST "" CACHE STRING "List of plug-ins to build")
-
-STRING(REPLACE " " ";" PLUGIN_LIST "${PLUGIN_LIST}")
-
-OPTION(LMMS_MINIMAL "Build a minimal list of plug-ins" OFF)
-
-SET(MINIMAL_LIST
- audio_file_processor
- kicker
- triple_oscillator
-)
-
-IF(LMMS_MINIMAL)
- IF("${PLUGIN_LIST}" STREQUAL "")
- STRING(REPLACE ";" " " MINIMAL_LIST_STRING "${MINIMAL_LIST}")
- MESSAGE(
-"-- Using minimal plug-ins: ${MINIMAL_LIST_STRING}\n"
-" Note: You can specify specific plug-ins using -DPLUGIN_LIST=\"foo bar\""
- )
- ENDIF()
- SET(PLUGIN_LIST ${MINIMAL_LIST} ${PLUGIN_LIST})
-ENDIF()
-
-IF("${PLUGIN_LIST}" STREQUAL "")
- SET(PLUGIN_LIST
- ${MINIMAL_LIST}
- Amplifier
- BassBooster
- bit_invader
- Bitcrush
- carlabase
- carlapatchbay
- carlarack
- CrossoverEQ
- Delay
- Disintegrator
- DualFilter
- dynamics_processor
- Eq
- Flanger
- HydrogenImport
- ladspa_browser
- LadspaEffect
- lb302
- MidiImport
- MidiExport
- MultitapEcho
- monstro
- nes
- OpulenZ
- organic
- FreeBoy
- patman
- peak_controller_effect
- GigPlayer
- ReverbSC
- sf2_player
- sfxr
- sid
- SpectrumAnalyzer
- stereo_enhancer
- stereo_matrix
- stk
- vst_base
- vestige
- VstEffect
- watsyn
- waveshaper
- vibed
- Xpressive
- zynaddsubfx
- )
-
-ENDIF("${PLUGIN_LIST}" STREQUAL "")
-
-IF(MSVC)
- SET(MSVC_INCOMPATIBLE_PLUGINS
- LadspaEffect
- zynaddsubfx
- )
- message(WARNING "Compiling with MSVC. The following plugins are not available: ${MSVC_INCOMPATIBLE_PLUGINS}")
- LIST(REMOVE_ITEM PLUGIN_LIST ${MSVC_INCOMPATIBLE_PLUGINS})
-ENDIF()
+# See cmake/modules/PluginList.cmake
FOREACH(PLUGIN ${PLUGIN_LIST})
ADD_SUBDIRECTORY(${PLUGIN})
ENDFOREACH()
diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp
index e31c24508..b3d01e790 100644
--- a/plugins/MidiImport/MidiImport.cpp
+++ b/plugins/MidiImport/MidiImport.cpp
@@ -103,7 +103,7 @@ bool MidiImport::tryImport( TrackContainer* tc )
#ifdef LMMS_HAVE_FLUIDSYNTH
if( gui != NULL &&
- ConfigManager::inst()->defaultSoundfont().isEmpty() )
+ ConfigManager::inst()->sf2File().isEmpty() )
{
QMessageBox::information( gui->mainWindow(),
tr( "Setup incomplete" ),
@@ -188,9 +188,9 @@ public:
smfMidiCC & putValue( MidiTime time, AutomatableModel * objModel, float value )
{
- if( !ap || time > lastPos + DefaultTicksPerTact )
+ if( !ap || time > lastPos + DefaultTicksPerBar )
{
- MidiTime pPos = MidiTime( time.getTact(), 0 );
+ MidiTime pPos = MidiTime( time.getBar(), 0 );
ap = dynamic_cast(
at->createTCO(0) );
ap->movePosition( pPos );
@@ -200,7 +200,7 @@ public:
lastPos = time;
time = time - ap->startPosition();
ap->putValue( time, value, false );
- ap->changeLength( MidiTime( time.getTact() + 1, 0 ) );
+ ap->changeLength( MidiTime( time.getBar() + 1, 0 ) );
return *this;
}
@@ -242,7 +242,7 @@ public:
if( it_inst )
{
isSF2 = true;
- it_inst->loadFile( ConfigManager::inst()->defaultSoundfont() );
+ it_inst->loadFile( ConfigManager::inst()->sf2File() );
it_inst->childModel( "bank" )->setValue( 0 );
it_inst->childModel( "patch" )->setValue( 0 );
}
@@ -267,9 +267,9 @@ public:
void addNote( Note & n )
{
- if( !p || n.pos() > lastEnd + DefaultTicksPerTact )
+ if( !p || n.pos() > lastEnd + DefaultTicksPerBar )
{
- MidiTime pPos = MidiTime( n.pos().getTact(), 0 );
+ MidiTime pPos = MidiTime( n.pos().getBar(), 0 );
p = dynamic_cast( it->createTCO( 0 ) );
p->movePosition( pPos );
}
@@ -309,33 +309,36 @@ bool MidiImport::readSMF( TrackContainer* tc )
smfMidiChannel chs[256];
MeterModel & timeSigMM = Engine::getSong()->getTimeSigModel();
- AutomationPattern * timeSigNumeratorPat =
- AutomationPattern::globalAutomationPattern( &timeSigMM.numeratorModel() );
- AutomationPattern * timeSigDenominatorPat =
- AutomationPattern::globalAutomationPattern( &timeSigMM.denominatorModel() );
+ AutomationTrack * nt = dynamic_cast(
+ Track::create(Track::AutomationTrack, Engine::getSong()));
+ nt->setName(tr("MIDI Time Signature Numerator"));
+ AutomationTrack * dt = dynamic_cast(
+ Track::create(Track::AutomationTrack, Engine::getSong()));
+ dt->setName(tr("MIDI Time Signature Denominator"));
+ AutomationPattern * timeSigNumeratorPat =
+ new AutomationPattern(nt);
+ timeSigNumeratorPat->setDisplayName(tr("Numerator"));
+ timeSigNumeratorPat->addObject(&timeSigMM.numeratorModel());
+ AutomationPattern * timeSigDenominatorPat =
+ new AutomationPattern(dt);
+ timeSigDenominatorPat->setDisplayName(tr("Denominator"));
+ timeSigDenominatorPat->addObject(&timeSigMM.denominatorModel());
// TODO: adjust these to Time.Sig changes
- double beatsPerTact = 4;
- double ticksPerBeat = DefaultTicksPerTact / beatsPerTact;
+ double beatsPerBar = 4;
+ double ticksPerBeat = DefaultTicksPerBar / beatsPerBar;
// Time-sig changes
Alg_time_sigs * timeSigs = &seq->time_sig;
for( int s = 0; s < timeSigs->length(); ++s )
{
Alg_time_sig timeSig = (*timeSigs)[s];
- // Initial timeSig, set song-default value
- if(/* timeSig.beat == 0*/ true )
- {
- // TODO set song-global default value
- printf("Another timesig at %f\n", timeSig.beat);
- timeSigNumeratorPat->putValue( timeSig.beat*ticksPerBeat, timeSig.num );
- timeSigDenominatorPat->putValue( timeSig.beat*ticksPerBeat, timeSig.den );
- }
- else
- {
- }
-
+ timeSigNumeratorPat->putValue(timeSig.beat * ticksPerBeat, timeSig.num);
+ timeSigDenominatorPat->putValue(timeSig.beat * ticksPerBeat, timeSig.den);
}
+ // manually call otherwise the pattern shows being 1 bar
+ timeSigNumeratorPat->updateLength();
+ timeSigDenominatorPat->updateLength();
pd.setValue( 2 );
diff --git a/plugins/SpectrumAnalyzer/Analyzer.cpp b/plugins/SpectrumAnalyzer/Analyzer.cpp
index 9c3fe0814..656d18bd4 100644
--- a/plugins/SpectrumAnalyzer/Analyzer.cpp
+++ b/plugins/SpectrumAnalyzer/Analyzer.cpp
@@ -27,7 +27,13 @@
#include "Analyzer.h"
+#ifdef SA_DEBUG
+ #include
+ #include
+#endif
+
#include "embed.h"
+#include "lmms_basics.h"
#include "plugin_export.h"
@@ -38,7 +44,7 @@ extern "C" {
"Spectrum Analyzer",
QT_TRANSLATE_NOOP("pluginBrowser", "A graphical spectrum analyzer."),
"Martin Pavelek ",
- 0x0100,
+ 0x0112,
Plugin::Effect,
new PluginPixmapLoader("logo"),
NULL,
@@ -50,17 +56,54 @@ extern "C" {
Analyzer::Analyzer(Model *parent, const Plugin::Descriptor::SubPluginFeatures::Key *key) :
Effect(&analyzer_plugin_descriptor, parent, key),
m_processor(&m_controls),
- m_controls(this)
+ m_controls(this),
+ m_processorThread(m_processor, m_inputBuffer),
+ // Buffer is sized to cover 4* the current maximum LMMS audio buffer size,
+ // so that it has some reserve space in case data processor is busy.
+ m_inputBuffer(4 * m_maxBufferSize)
{
+ m_processorThread.start();
}
+Analyzer::~Analyzer()
+{
+ m_processor.terminate();
+ m_inputBuffer.wakeAll();
+ m_processorThread.wait();
+}
+
// Take audio data and pass them to the spectrum processor.
-// Skip processing if the controls dialog isn't visible, it would only waste CPU cycles.
bool Analyzer::processAudioBuffer(sampleFrame *buffer, const fpp_t frame_count)
{
+ // Measure time spent in audio thread; both average and peak should be well under 1 ms.
+ #ifdef SA_DEBUG
+ unsigned int audio_time = std::chrono::high_resolution_clock::now().time_since_epoch().count();
+ if (audio_time - m_last_dump_time > 5000000000) // print every 5 seconds
+ {
+ std::cout << "Analyzer audio thread: " << m_sum_execution / m_dump_count << " ms avg / "
+ << m_max_execution << " ms peak." << std::endl;
+ m_last_dump_time = audio_time;
+ m_sum_execution = m_max_execution = m_dump_count = 0;
+ }
+ #endif
+
if (!isEnabled() || !isRunning ()) {return false;}
- if (m_controls.isViewVisible()) {m_processor.analyse(buffer, frame_count);}
+
+ // Skip processing if the controls dialog isn't visible, it would only waste CPU cycles.
+ if (m_controls.isViewVisible())
+ {
+ // To avoid processing spikes on audio thread, data are stored in
+ // a lockless ringbuffer and processed in a separate thread.
+ m_inputBuffer.write(buffer, frame_count, true);
+ }
+ #ifdef SA_DEBUG
+ audio_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - audio_time;
+ m_dump_count++;
+ m_sum_execution += audio_time / 1000000.0;
+ if (audio_time / 1000000.0 > m_max_execution) {m_max_execution = audio_time / 1000000.0;}
+ #endif
+
return isRunning();
}
diff --git a/plugins/SpectrumAnalyzer/Analyzer.h b/plugins/SpectrumAnalyzer/Analyzer.h
index 157cc1eae..304777c9a 100644
--- a/plugins/SpectrumAnalyzer/Analyzer.h
+++ b/plugins/SpectrumAnalyzer/Analyzer.h
@@ -27,7 +27,11 @@
#ifndef ANALYZER_H
#define ANALYZER_H
+#include
+
+#include "DataprocLauncher.h"
#include "Effect.h"
+#include "LocklessRingBuffer.h"
#include "SaControls.h"
#include "SaProcessor.h"
@@ -37,7 +41,7 @@ class Analyzer : public Effect
{
public:
Analyzer(Model *parent, const Descriptor::SubPluginFeatures::Key *key);
- virtual ~Analyzer() {};
+ virtual ~Analyzer();
bool processAudioBuffer(sampleFrame *buffer, const fpp_t frame_count) override;
EffectControls *controls() override {return &m_controls;}
@@ -47,6 +51,24 @@ public:
private:
SaProcessor m_processor;
SaControls m_controls;
+
+ // Maximum LMMS buffer size (hard coded, the actual constant is hard to get)
+ const unsigned int m_maxBufferSize = 4096;
+
+ // QThread::create() workaround
+ // Replace DataprocLauncher by QThread and replace initializer in constructor
+ // with the following commented line when LMMS CI starts using Qt > 5.9
+ //m_processorThread = QThread::create([=]{m_processor.analyze(m_inputBuffer);});
+ DataprocLauncher m_processorThread;
+
+ LocklessRingBuffer m_inputBuffer;
+
+ #ifdef SA_DEBUG
+ int m_last_dump_time;
+ int m_dump_count;
+ float m_sum_execution;
+ float m_max_execution;
+ #endif
};
#endif // ANALYZER_H
diff --git a/plugins/SpectrumAnalyzer/CMakeLists.txt b/plugins/SpectrumAnalyzer/CMakeLists.txt
index 630fbf1be..488495a9e 100644
--- a/plugins/SpectrumAnalyzer/CMakeLists.txt
+++ b/plugins/SpectrumAnalyzer/CMakeLists.txt
@@ -1,5 +1,7 @@
INCLUDE(BuildPlugin)
INCLUDE_DIRECTORIES(${FFTW3F_INCLUDE_DIRS})
+
LINK_LIBRARIES(${FFTW3F_LIBRARIES})
+
BUILD_PLUGIN(analyzer Analyzer.cpp SaProcessor.cpp SaControls.cpp SaControlsDialog.cpp SaSpectrumView.cpp SaWaterfallView.cpp
-MOCFILES SaProcessor.h SaControls.h SaControlsDialog.h SaSpectrumView.h SaWaterfallView.h EMBEDDED_RESOURCES *.svg logo.png)
+MOCFILES SaProcessor.h SaControls.h SaControlsDialog.h SaSpectrumView.h SaWaterfallView.h DataprocLauncher.h EMBEDDED_RESOURCES *.svg logo.png)
diff --git a/plugins/SpectrumAnalyzer/DataprocLauncher.h b/plugins/SpectrumAnalyzer/DataprocLauncher.h
new file mode 100644
index 000000000..d91e0bedf
--- /dev/null
+++ b/plugins/SpectrumAnalyzer/DataprocLauncher.h
@@ -0,0 +1,52 @@
+/*
+ * DataprocLauncher.h - QThread::create workaround for older Qt version
+ *
+ * Copyright (c) 2019 Martin Pavelek
+ *
+ * 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 DATAPROCLAUNCHER_H
+#define DATAPROCLAUNCHER_H
+
+#include
+
+#include "SaProcessor.h"
+#include "LocklessRingBuffer.h"
+
+class DataprocLauncher : public QThread
+{
+public:
+ explicit DataprocLauncher(SaProcessor &proc, LocklessRingBuffer &buffer)
+ : m_processor(&proc),
+ m_inputBuffer(&buffer)
+ {
+ }
+
+private:
+ void run() override
+ {
+ m_processor->analyze(*m_inputBuffer);
+ }
+
+ SaProcessor *m_processor;
+ LocklessRingBuffer *m_inputBuffer;
+};
+
+#endif // DATAPROCLAUNCHER_H
diff --git a/plugins/SpectrumAnalyzer/README.md b/plugins/SpectrumAnalyzer/README.md
index 3d3506d65..473083da8 100644
--- a/plugins/SpectrumAnalyzer/README.md
+++ b/plugins/SpectrumAnalyzer/README.md
@@ -4,13 +4,41 @@
This plugin consists of three widgets and back-end code to provide them with required data.
-The top-level widget is SaControlDialog. It populates a configuration widget (created dynamically) and instantiates spectrum display widgets. Its main back-end class is SaControls, which holds all configuration values and globally valid constants (e.g. range definitions).
+The top-level widget is `SaControlDialog`. It populates configuration widgets (created dynamically) and instantiates spectrum display widgets. Its main back-end class is `SaControls`, which holds all configuration values.
-SaSpectrumDisplay and SaWaterfallDisplay show the result of spectrum analysis. Their main back-end class is SaProcessor, which performs FFT analysis on data received from the Analyzer class, which in turn handles the interface with LMMS.
+`SaSpectrumView` and `SaWaterfallView` widgets show the result of spectrum analysis. Their main back-end class is `SaProcessor`, which performs FFT analysis on data received from the `Analyzer` class, which in turn handles the interface with LMMS.
+
+## Threads
+
+The Spectrum Analyzer is involved in three different threads:
+ - **Effect mixer thread**: periodically calls `Analyzer::processAudioBuffer()` to provide the plugin with more data. This thread is real-time sensitive -- any latency spikes can potentially cause interruptions in the audio stream. For this reason, `Analyzer::processAudioBuffer()` must finish as fast as possible and must not call any functions that could cause it to be delayed for unpredictable amount of time. A lock-less ring buffer is used to safely feed data to the FFT analysis thread without risking any latency spikes due to a shared mutex being unavailable at the time of writing.
+ - **FFT analysis thread**: a standalone thread formed by the `SaProcessor::analyze()` function. Takes in data from the ring buffer, performs FFT analysis and prepares results for display. This thread is not real-time sensitive but excessive locking is discouraged to maintain good performance.
+ - **GUI thread**: periodically triggers `paintEvent()` of all Qt widgets, including `SaSpectrumView` and `SaWaterfallView`. While it is not as sensitive to latency spikes as the effect mixer thread, the `paintEvent()`s appear to be called sequentially and the execution time of each widget therefore adds to the total time needed to complete one full refresh cycle. This means the maximum frame rate of the Qt GUI will be limited to `1 / total_execution_time`. Good performance of the `paintEvent()` functions should be therefore kept in mind.
## Changelog
-
+ 1.1.2 2019-11-18
+ - waterfall is no longer cut short when width limit is reached
+ - various small tweaks based on final review
+ 1.1.1 2019-10-13
+ - improved interface for accessing SaProcessor private data
+ - readme file update
+ - other small improvements based on reviews
+ 1.1.0 2019-08-29
+ - advanced config: expose hidden constants to user
+ - advanced config: add support for FFT window overlapping
+ - waterfall: display at native resolution on high-DPI screens
+ - waterfall: add cursor and improve label density
+ - FFT: fix normalization so that 0 dBFS matches full-scale sinewave
+ - FFT: decouple data acquisition from processing and display
+ - FFT: separate lock for reallocation (to avoid some needless waiting)
+ - moved ranges and other constants to a separate file
+ - debug: better performance measurements
+ - various performance optimizations
+ 1.0.3 2019-07-25
+ - rename and tweak amplitude ranges based on feedback
+ 1.0.2 2019-07-12
+ - variety of small changes based on code review
1.0.1 2019-06-02
- code style changes
- added tool-tips
diff --git a/plugins/SpectrumAnalyzer/SaControls.cpp b/plugins/SpectrumAnalyzer/SaControls.cpp
index 5691c0ae4..6be298e27 100644
--- a/plugins/SpectrumAnalyzer/SaControls.cpp
+++ b/plugins/SpectrumAnalyzer/SaControls.cpp
@@ -50,7 +50,17 @@ SaControls::SaControls(Analyzer *effect) :
m_freqRangeModel(this, tr("Frequency range")),
m_ampRangeModel(this, tr("Amplitude range")),
m_blockSizeModel(this, tr("FFT block size")),
- m_windowModel(this, tr("FFT window type"))
+ m_windowModel(this, tr("FFT window type")),
+
+ // Advanced settings knobs
+ m_envelopeResolutionModel(0.25f, 0.1f, 3.0f, 0.05f, this, tr("Peak envelope resolution")),
+ m_spectrumResolutionModel(1.5f, 0.1f, 3.0f, 0.05f, this, tr("Spectrum display resolution")),
+ m_peakDecayFactorModel(0.992f, 0.95f, 0.999f, 0.001f, this, tr("Peak decay multiplier")),
+ m_averagingWeightModel(0.15f, 0.01f, 0.5f, 0.01f, this, tr("Averaging weight")),
+ m_waterfallHeightModel(300.0f, 50.0f, 1000.0f, 50.0f, this, tr("Waterfall history size")),
+ m_waterfallGammaModel(0.30f, 0.10f, 1.00f, 0.05f, this, tr("Waterfall gamma correction")),
+ m_windowOverlapModel(2.0f, 1.0f, 4.0f, 1.0f, this, tr("FFT window overlap")),
+ m_zeroPaddingModel(2.0f, 0.0f, 4.0f, 1.0f, this, tr("FFT zero padding"))
{
// Frequency and amplitude ranges; order must match
// FREQUENCY_RANGES and AMPLITUDE_RANGES defined in SaControls.h
@@ -62,10 +72,10 @@ SaControls::SaControls(Analyzer *effect) :
m_freqRangeModel.setValue(m_freqRangeModel.findText(tr("Full (auto)")));
m_ampRangeModel.addItem(tr("Extended"));
- m_ampRangeModel.addItem(tr("Default"));
m_ampRangeModel.addItem(tr("Audible"));
- m_ampRangeModel.addItem(tr("Noise"));
- m_ampRangeModel.setValue(m_ampRangeModel.findText(tr("Default")));
+ m_ampRangeModel.addItem(tr("Loud"));
+ m_ampRangeModel.addItem(tr("Silent"));
+ m_ampRangeModel.setValue(m_ampRangeModel.findText(tr("Audible")));
// FFT block size labels are generated automatically, based on
// FFT_BLOCK_SIZES vector defined in fft_helpers.h
@@ -95,12 +105,15 @@ SaControls::SaControls(Analyzer *effect) :
// Colors
// Background color is defined by Qt / theme.
- // Make sure the sum of colors for L and R channel stays lower or equal
- // to 255. Otherwise the Waterfall pixels may overflow back to 0 even when
- // the input signal isn't clipping (over 1.0).
+ // Make sure the sum of colors for L and R channel results into a neutral
+ // color that has at least one component equal to 255 (i.e. ideally white).
+ // This means the color overflows to zero exactly when signal reaches
+ // clipping threshold, indicating the problematic frequency to user.
+ // Mono waterfall color should have similarly at least one component at 255.
m_colorL = QColor(51, 148, 204, 135);
m_colorR = QColor(204, 107, 51, 135);
m_colorMono = QColor(51, 148, 204, 204);
+ m_colorMonoW = QColor(64, 185, 255, 255);
m_colorBG = QColor(7, 7, 7, 255); // ~20 % gray (after gamma correction)
m_colorGrid = QColor(30, 34, 38, 255); // ~40 % gray (slightly cold / blue)
m_colorLabels = QColor(192, 202, 212, 255); // ~90 % gray (slightly cold / blue)
@@ -126,6 +139,15 @@ void SaControls::loadSettings(const QDomElement &_this)
m_ampRangeModel.loadSettings(_this, "RangeY");
m_blockSizeModel.loadSettings(_this, "BlockSize");
m_windowModel.loadSettings(_this, "WindowType");
+
+ m_envelopeResolutionModel.loadSettings(_this, "EnvelopeRes");
+ m_spectrumResolutionModel.loadSettings(_this, "SpectrumRes");
+ m_peakDecayFactorModel.loadSettings(_this, "PeakDecayFactor");
+ m_averagingWeightModel.loadSettings(_this, "AverageWeight");
+ m_waterfallHeightModel.loadSettings(_this, "WaterfallHeight");
+ m_waterfallGammaModel.loadSettings(_this, "WaterfallGamma");
+ m_windowOverlapModel.loadSettings(_this, "WindowOverlap");
+ m_zeroPaddingModel.loadSettings(_this, "ZeroPadding");
}
@@ -141,4 +163,14 @@ void SaControls::saveSettings(QDomDocument &doc, QDomElement &parent)
m_ampRangeModel.saveSettings(doc, parent, "RangeY");
m_blockSizeModel.saveSettings(doc, parent, "BlockSize");
m_windowModel.saveSettings(doc, parent, "WindowType");
+
+ m_envelopeResolutionModel.saveSettings(doc, parent, "EnvelopeRes");
+ m_spectrumResolutionModel.saveSettings(doc, parent, "SpectrumRes");
+ m_peakDecayFactorModel.saveSettings(doc, parent, "PeakDecayFactor");
+ m_averagingWeightModel.saveSettings(doc, parent, "AverageWeight");
+ m_waterfallHeightModel.saveSettings(doc, parent, "WaterfallHeight");
+ m_waterfallGammaModel.saveSettings(doc, parent, "WaterfallGamma");
+ m_windowOverlapModel.saveSettings(doc, parent, "WindowOverlap");
+ m_zeroPaddingModel.saveSettings(doc, parent, "ZeroPadding");
+
}
diff --git a/plugins/SpectrumAnalyzer/SaControls.h b/plugins/SpectrumAnalyzer/SaControls.h
index e0b54e6a2..4673416bc 100644
--- a/plugins/SpectrumAnalyzer/SaControls.h
+++ b/plugins/SpectrumAnalyzer/SaControls.h
@@ -27,52 +27,10 @@
#include "ComboBoxModel.h"
#include "EffectControls.h"
+#include "lmms_constants.h"
//#define SA_DEBUG 1 // define SA_DEBUG to enable performance measurements
-// Frequency ranges (in Hz).
-// Full range is defined by LOWEST_LOG_FREQ and current sample rate.
-const int LOWEST_LOG_FREQ = 10; // arbitrary low limit for log. scale, >1
-
-enum FREQUENCY_RANGES
-{
- FRANGE_FULL = 0,
- FRANGE_AUDIBLE,
- FRANGE_BASS,
- FRANGE_MIDS,
- FRANGE_HIGH
-};
-
-const int FRANGE_AUDIBLE_START = 20;
-const int FRANGE_AUDIBLE_END = 20000;
-const int FRANGE_BASS_START = 20;
-const int FRANGE_BASS_END = 300;
-const int FRANGE_MIDS_START = 200;
-const int FRANGE_MIDS_END = 5000;
-const int FRANGE_HIGH_START = 4000;
-const int FRANGE_HIGH_END = 20000;
-
-// Amplitude ranges.
-// Reference: sine wave from -1.0 to 1.0 = 0 dB.
-// I.e. if master volume is 100 %, positive values signify clipping.
-// Doubling or halving the amplitude produces 3 dB difference.
-enum AMPLITUDE_RANGES
-{
- ARANGE_EXTENDED = 0,
- ARANGE_DEFAULT,
- ARANGE_AUDIBLE,
- ARANGE_NOISE
-};
-
-const int ARANGE_EXTENDED_START = -80;
-const int ARANGE_EXTENDED_END = 20;
-const int ARANGE_DEFAULT_START = -30;
-const int ARANGE_DEFAULT_END = 0;
-const int ARANGE_AUDIBLE_START = -50;
-const int ARANGE_AUDIBLE_END = 10;
-const int ARANGE_NOISE_START = -60;
-const int ARANGE_NOISE_END = -20;
-
class Analyzer;
@@ -90,11 +48,12 @@ public:
void loadSettings (const QDomElement &_this) override;
QString nodeName() const override {return "Analyzer";}
- int controlCount() override {return 12;}
+ int controlCount() override {return 20;}
private:
Analyzer *m_effect;
+ // basic settings
BoolModel m_pauseModel;
BoolModel m_refFreezeModel;
@@ -111,12 +70,24 @@ private:
ComboBoxModel m_blockSizeModel;
ComboBoxModel m_windowModel;
- QColor m_colorL;
- QColor m_colorR;
- QColor m_colorMono;
- QColor m_colorBG;
- QColor m_colorGrid;
- QColor m_colorLabels;
+ // advanced settings
+ FloatModel m_envelopeResolutionModel;
+ FloatModel m_spectrumResolutionModel;
+ FloatModel m_peakDecayFactorModel;
+ FloatModel m_averagingWeightModel;
+ FloatModel m_waterfallHeightModel;
+ FloatModel m_waterfallGammaModel;
+ FloatModel m_windowOverlapModel;
+ FloatModel m_zeroPaddingModel;
+
+ // colors (hard-coded, values must add up to specific numbers)
+ QColor m_colorL; //!< color of the left channel
+ QColor m_colorR; //!< color of the right channel
+ QColor m_colorMono; //!< mono color for spectrum display
+ QColor m_colorMonoW; //!< mono color for waterfall display
+ QColor m_colorBG; //!< spectrum display background color
+ QColor m_colorGrid; //!< color of grid lines
+ QColor m_colorLabels; //!< color of axis labels
friend class SaControlsDialog;
friend class SaSpectrumView;
diff --git a/plugins/SpectrumAnalyzer/SaControlsDialog.cpp b/plugins/SpectrumAnalyzer/SaControlsDialog.cpp
index 4ba307a4d..d89cc1093 100644
--- a/plugins/SpectrumAnalyzer/SaControlsDialog.cpp
+++ b/plugins/SpectrumAnalyzer/SaControlsDialog.cpp
@@ -34,6 +34,7 @@
#include "ComboBoxModel.h"
#include "embed.h"
#include "Engine.h"
+#include "Knob.h"
#include "LedCheckbox.h"
#include "PixmapButton.h"
#include "SaControls.h"
@@ -53,13 +54,24 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor)
master_layout->setContentsMargins(2, 6, 2, 8);
setLayout(master_layout);
- // QSplitter top: configuration section
+ // Display splitter top: controls section
+ QWidget *controls_widget = new QWidget;
+ QHBoxLayout *controls_layout = new QHBoxLayout;
+ controls_layout->setContentsMargins(0, 0, 0, 0);
+ controls_widget->setLayout(controls_layout);
+ controls_widget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
+ controls_widget->setMaximumHeight(m_configHeight);
+ display_splitter->addWidget(controls_widget);
+
+
+ // Basic configuration
QWidget *config_widget = new QWidget;
QGridLayout *config_layout = new QGridLayout;
config_widget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
config_widget->setMaximumHeight(m_configHeight);
config_widget->setLayout(config_layout);
- display_splitter->addWidget(config_widget);
+ controls_layout->addWidget(config_widget);
+ controls_layout->setStretchFactor(config_widget, 10);
// Pre-compute target pixmap size based on monitor DPI.
// Using setDevicePixelRatio() on pixmap allows the SVG image to be razor
@@ -67,6 +79,8 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor)
// enlarged. No idea how to make Qt do it in a more reasonable way.
QSize iconSize = QSize(22.0 * devicePixelRatio(), 22.0 * devicePixelRatio());
QSize buttonSize = 1.2 * iconSize;
+ QSize advButtonSize = QSize((m_configHeight * devicePixelRatio()) / 3, m_configHeight * devicePixelRatio());
+
// pause and freeze buttons
PixmapButton *pauseButton = new PixmapButton(this, tr("Pause"));
@@ -79,7 +93,7 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor)
pauseButton->setInactiveGraphic(*pauseOffPixmap);
pauseButton->setCheckable(true);
pauseButton->setModel(&controls->m_pauseModel);
- config_layout->addWidget(pauseButton, 0, 0, 2, 1);
+ config_layout->addWidget(pauseButton, 0, 0, 2, 1, Qt::AlignHCenter);
PixmapButton *refFreezeButton = new PixmapButton(this, tr("Reference freeze"));
refFreezeButton->setToolTip(tr("Freeze current input as a reference / disable falloff in peak-hold mode."));
@@ -91,7 +105,7 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor)
refFreezeButton->setInactiveGraphic(*freezeOffPixmap);
refFreezeButton->setCheckable(true);
refFreezeButton->setModel(&controls->m_refFreezeModel);
- config_layout->addWidget(refFreezeButton, 2, 0, 2, 1);
+ config_layout->addWidget(refFreezeButton, 2, 0, 2, 1, Qt::AlignHCenter);
// misc configuration switches
LedCheckBox *waterfallButton = new LedCheckBox(tr("Waterfall"), this);
@@ -194,6 +208,117 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor)
processor->rebuildWindow();
connect(&controls->m_windowModel, &ComboBoxModel::dataChanged, [=] {processor->rebuildWindow();});
+ // set stretch factors so that combo boxes expand first
+ config_layout->setColumnStretch(3, 2);
+ config_layout->setColumnStretch(5, 3);
+
+
+ // Advanced configuration
+ QWidget *advanced_widget = new QWidget;
+ QGridLayout *advanced_layout = new QGridLayout;
+ advanced_widget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+ advanced_widget->setMaximumHeight(m_configHeight);
+ advanced_widget->setLayout(advanced_layout);
+ advanced_widget->hide();
+ controls_layout->addWidget(advanced_widget);
+ controls_layout->setStretchFactor(advanced_widget, 10);
+
+ // Peak envelope resolution
+ Knob *envelopeResolutionKnob = new Knob(knobSmall_17, this);
+ envelopeResolutionKnob->setModel(&controls->m_envelopeResolutionModel);
+ envelopeResolutionKnob->setLabel(tr("Envelope res."));
+ envelopeResolutionKnob->setToolTip(tr("Increase envelope resolution for better details, decrease for better GUI performance."));
+ envelopeResolutionKnob->setHintText(tr("Draw at most"), tr(" envelope points per pixel"));
+ advanced_layout->addWidget(envelopeResolutionKnob, 0, 0, 1, 1, Qt::AlignCenter);
+
+ // Spectrum graph resolution
+ Knob *spectrumResolutionKnob = new Knob(knobSmall_17, this);
+ spectrumResolutionKnob->setModel(&controls->m_spectrumResolutionModel);
+ spectrumResolutionKnob->setLabel(tr("Spectrum res."));
+ spectrumResolutionKnob->setToolTip(tr("Increase spectrum resolution for better details, decrease for better GUI performance."));
+ spectrumResolutionKnob->setHintText(tr("Draw at most"), tr(" spectrum points per pixel"));
+ advanced_layout->addWidget(spectrumResolutionKnob, 1, 0, 1, 1, Qt::AlignCenter);
+
+ // Peak falloff speed
+ Knob *peakDecayFactorKnob = new Knob(knobSmall_17, this);
+ peakDecayFactorKnob->setModel(&controls->m_peakDecayFactorModel);
+ peakDecayFactorKnob->setLabel(tr("Falloff factor"));
+ peakDecayFactorKnob->setToolTip(tr("Decrease to make peaks fall faster."));
+ peakDecayFactorKnob->setHintText(tr("Multiply buffered value by"), "");
+ advanced_layout->addWidget(peakDecayFactorKnob, 0, 1, 1, 1, Qt::AlignCenter);
+
+ // Averaging weight
+ Knob *averagingWeightKnob = new Knob(knobSmall_17, this);
+ averagingWeightKnob->setModel(&controls->m_averagingWeightModel);
+ averagingWeightKnob->setLabel(tr("Averaging weight"));
+ averagingWeightKnob->setToolTip(tr("Decrease to make averaging slower and smoother."));
+ averagingWeightKnob->setHintText(tr("New sample contributes"), "");
+ advanced_layout->addWidget(averagingWeightKnob, 1, 1, 1, 1, Qt::AlignCenter);
+
+ // Waterfall history size
+ Knob *waterfallHeightKnob = new Knob(knobSmall_17, this);
+ waterfallHeightKnob->setModel(&controls->m_waterfallHeightModel);
+ waterfallHeightKnob->setLabel(tr("Waterfall height"));
+ waterfallHeightKnob->setToolTip(tr("Increase to get slower scrolling, decrease to see fast transitions better. Warning: medium CPU usage."));
+ waterfallHeightKnob->setHintText(tr("Keep"), tr(" lines"));
+ advanced_layout->addWidget(waterfallHeightKnob, 0, 2, 1, 1, Qt::AlignCenter);
+ processor->reallocateBuffers();
+ connect(&controls->m_waterfallHeightModel, &FloatModel::dataChanged, [=] {processor->reallocateBuffers();});
+
+ // Waterfall gamma correction
+ Knob *waterfallGammaKnob = new Knob(knobSmall_17, this);
+ waterfallGammaKnob->setModel(&controls->m_waterfallGammaModel);
+ waterfallGammaKnob->setLabel(tr("Waterfall gamma"));
+ waterfallGammaKnob->setToolTip(tr("Decrease to see very weak signals, increase to get better contrast."));
+ waterfallGammaKnob->setHintText(tr("Gamma value:"), "");
+ advanced_layout->addWidget(waterfallGammaKnob, 1, 2, 1, 1, Qt::AlignCenter);
+
+ // FFT window overlap
+ Knob *windowOverlapKnob = new Knob(knobSmall_17, this);
+ windowOverlapKnob->setModel(&controls->m_windowOverlapModel);
+ windowOverlapKnob->setLabel(tr("Window overlap"));
+ windowOverlapKnob->setToolTip(tr("Increase to prevent missing fast transitions arriving near FFT window edges. Warning: high CPU usage."));
+ windowOverlapKnob->setHintText(tr("Each sample processed"), tr(" times"));
+ advanced_layout->addWidget(windowOverlapKnob, 0, 3, 1, 1, Qt::AlignCenter);
+
+ // FFT zero padding
+ Knob *zeroPaddingKnob = new Knob(knobSmall_17, this);
+ zeroPaddingKnob->setModel(&controls->m_zeroPaddingModel);
+ zeroPaddingKnob->setLabel(tr("Zero padding"));
+ zeroPaddingKnob->setToolTip(tr("Increase to get smoother-looking spectrum. Warning: high CPU usage."));
+ zeroPaddingKnob->setHintText(tr("Processing buffer is"), tr(" steps larger than input block"));
+ advanced_layout->addWidget(zeroPaddingKnob, 1, 3, 1, 1, Qt::AlignCenter);
+ processor->reallocateBuffers();
+ connect(&controls->m_zeroPaddingModel, &FloatModel::dataChanged, [=] {processor->reallocateBuffers();});
+
+
+ // Advanced settings button
+ PixmapButton *advancedButton = new PixmapButton(this, tr("Advanced settings"));
+ advancedButton->setToolTip(tr("Access advanced settings"));
+ QPixmap *advancedOnPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("advanced_on").scaled(advButtonSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+ QPixmap *advancedOffPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("advanced_off").scaled(advButtonSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+ advancedOnPixmap->setDevicePixelRatio(devicePixelRatio());
+ advancedOffPixmap->setDevicePixelRatio(devicePixelRatio());
+ advancedButton->setActiveGraphic(*advancedOnPixmap);
+ advancedButton->setInactiveGraphic(*advancedOffPixmap);
+ advancedButton->setCheckable(true);
+ controls_layout->addStretch(0);
+ controls_layout->addWidget(advancedButton);
+
+ connect(advancedButton, &PixmapButton::toggled, [=](bool checked)
+ {
+ if (checked)
+ {
+ config_widget->hide();
+ advanced_widget->show();
+ }
+ else
+ {
+ config_widget->show();
+ advanced_widget->hide();
+ }
+ }
+ );
// QSplitter middle and bottom: spectrum display widgets
m_spectrum = new SaSpectrumView(controls, processor, this);
diff --git a/plugins/SpectrumAnalyzer/SaProcessor.cpp b/plugins/SpectrumAnalyzer/SaProcessor.cpp
index 9261658aa..9d83f2916 100644
--- a/plugins/SpectrumAnalyzer/SaProcessor.cpp
+++ b/plugins/SpectrumAnalyzer/SaProcessor.cpp
@@ -26,15 +26,23 @@
#include "SaProcessor.h"
#include
+#ifdef SA_DEBUG
+ #include
+#endif
#include
-#include
+#ifdef SA_DEBUG
+ #include
+ #include
+#endif
#include
#include "lmms_math.h"
+#include "LocklessRingBuffer.h"
-SaProcessor::SaProcessor(SaControls *controls) :
+SaProcessor::SaProcessor(const SaControls *controls) :
m_controls(controls),
+ m_terminate(false),
m_inBlockSize(FFT_BLOCK_SIZES[0]),
m_fftBlockSize(FFT_BLOCK_SIZES[0]),
m_sampleRate(Engine::mixer()->processingSampleRate()),
@@ -47,21 +55,23 @@ SaProcessor::SaProcessor(SaControls *controls) :
m_fftWindow.resize(m_inBlockSize, 1.0);
precomputeWindow(m_fftWindow.data(), m_inBlockSize, BLACKMAN_HARRIS);
- m_bufferL.resize(m_fftBlockSize, 0);
- m_bufferR.resize(m_fftBlockSize, 0);
+ m_bufferL.resize(m_inBlockSize, 0);
+ m_bufferR.resize(m_inBlockSize, 0);
+ m_filteredBufferL.resize(m_fftBlockSize, 0);
+ m_filteredBufferR.resize(m_fftBlockSize, 0);
m_spectrumL = (fftwf_complex *) fftwf_malloc(binCount() * sizeof (fftwf_complex));
m_spectrumR = (fftwf_complex *) fftwf_malloc(binCount() * sizeof (fftwf_complex));
- m_fftPlanL = fftwf_plan_dft_r2c_1d(m_fftBlockSize, m_bufferL.data(), m_spectrumL, FFTW_MEASURE);
- m_fftPlanR = fftwf_plan_dft_r2c_1d(m_fftBlockSize, m_bufferR.data(), m_spectrumR, FFTW_MEASURE);
+ m_fftPlanL = fftwf_plan_dft_r2c_1d(m_fftBlockSize, m_filteredBufferL.data(), m_spectrumL, FFTW_MEASURE);
+ m_fftPlanR = fftwf_plan_dft_r2c_1d(m_fftBlockSize, m_filteredBufferR.data(), m_spectrumR, FFTW_MEASURE);
m_absSpectrumL.resize(binCount(), 0);
m_absSpectrumR.resize(binCount(), 0);
m_normSpectrumL.resize(binCount(), 0);
m_normSpectrumR.resize(binCount(), 0);
- m_history.resize(binCount() * m_waterfallHeight * sizeof qRgb(0,0,0), 0);
-
- clear();
+ m_waterfallHeight = 100; // a small safe value
+ m_history_work.resize(waterfallWidth() * m_waterfallHeight * sizeof qRgb(0,0,0), 0);
+ m_history.resize(waterfallWidth() * m_waterfallHeight * sizeof qRgb(0,0,0), 0);
}
@@ -79,169 +89,229 @@ SaProcessor::~SaProcessor()
}
-// Load a batch of data from LMMS; run FFT analysis if buffer is full enough.
-void SaProcessor::analyse(sampleFrame *in_buffer, const fpp_t frame_count)
+// Load data from audio thread ringbuffer and run FFT analysis if buffer is full enough.
+void SaProcessor::analyze(LocklessRingBuffer &ring_buffer)
{
- #ifdef SA_DEBUG
- int start_time = std::chrono::high_resolution_clock::now().time_since_epoch().count();
- #endif
- // only take in data if any view is visible and not paused
- if ((m_spectrumActive || m_waterfallActive) && !m_controls->m_pauseModel.value())
+ LocklessRingBufferReader reader(ring_buffer);
+
+ // Processing thread loop
+ while (!m_terminate)
{
- const bool stereo = m_controls->m_stereoModel.value();
- fpp_t in_frame = 0;
- while (in_frame < frame_count)
+ // If there is nothing to read, wait for notification from the writing side.
+ if (reader.empty()) {reader.waitForData();}
+
+ // skip waterfall render if processing can't keep up with input
+ bool overload = ring_buffer.free() < ring_buffer.capacity() / 2;
+
+ auto in_buffer = reader.read_max(ring_buffer.capacity() / 4);
+ std::size_t frame_count = in_buffer.size();
+
+ // Process received data only if any view is visible and not paused.
+ // Also, to prevent a momentary GUI freeze under high load (due to lock
+ // starvation), skip analysis when buffer reallocation is requested.
+ if ((m_spectrumActive || m_waterfallActive) && !m_controls->m_pauseModel.value() && !m_reallocating)
{
- // fill sample buffers and check for zero input
- bool block_empty = true;
- for (; in_frame < frame_count && m_framesFilledUp < m_inBlockSize; in_frame++, m_framesFilledUp++)
+ const bool stereo = m_controls->m_stereoModel.value();
+ fpp_t in_frame = 0;
+ while (in_frame < frame_count)
{
+ // Lock data access to prevent reallocation from changing
+ // buffers and control variables.
+ QMutexLocker data_lock(&m_dataAccess);
+
+ // Fill sample buffers and check for zero input.
+ bool block_empty = true;
+ for (; in_frame < frame_count && m_framesFilledUp < m_inBlockSize; in_frame++, m_framesFilledUp++)
+ {
+ if (stereo)
+ {
+ m_bufferL[m_framesFilledUp] = in_buffer[in_frame][0];
+ m_bufferR[m_framesFilledUp] = in_buffer[in_frame][1];
+ }
+ else
+ {
+ m_bufferL[m_framesFilledUp] =
+ m_bufferR[m_framesFilledUp] = (in_buffer[in_frame][0] + in_buffer[in_frame][1]) * 0.5f;
+ }
+ if (in_buffer[in_frame][0] != 0.f || in_buffer[in_frame][1] != 0.f)
+ {
+ block_empty = false;
+ }
+ }
+
+ // Run analysis only if buffers contain enough data.
+ if (m_framesFilledUp < m_inBlockSize) {break;}
+
+ // Print performance analysis once per 2 seconds if debug is enabled
+ #ifdef SA_DEBUG
+ unsigned int total_time = std::chrono::high_resolution_clock::now().time_since_epoch().count();
+ if (total_time - m_last_dump_time > 2000000000)
+ {
+ std::cout << "FFT analysis: " << std::fixed << std::setprecision(2)
+ << m_sum_execution / m_dump_count << " ms avg / "
+ << m_max_execution << " ms peak, executing "
+ << m_dump_count << " times per second ("
+ << m_sum_execution / 20.0 << " % CPU usage)." << std::endl;
+ m_last_dump_time = total_time;
+ m_sum_execution = m_max_execution = m_dump_count = 0;
+ }
+ #endif
+
+ // update sample rate
+ m_sampleRate = Engine::mixer()->processingSampleRate();
+
+ // apply FFT window
+ for (unsigned int i = 0; i < m_inBlockSize; i++)
+ {
+ m_filteredBufferL[i] = m_bufferL[i] * m_fftWindow[i];
+ m_filteredBufferR[i] = m_bufferR[i] * m_fftWindow[i];
+ }
+
+ // Run FFT on left channel, convert the result to absolute magnitude
+ // spectrum and normalize it.
+ fftwf_execute(m_fftPlanL);
+ absspec(m_spectrumL, m_absSpectrumL.data(), binCount());
+ normalize(m_absSpectrumL, m_normSpectrumL, m_inBlockSize);
+
+ // repeat analysis for right channel if stereo processing is enabled
if (stereo)
{
- m_bufferL[m_framesFilledUp] = in_buffer[in_frame][0];
- m_bufferR[m_framesFilledUp] = in_buffer[in_frame][1];
+ fftwf_execute(m_fftPlanR);
+ absspec(m_spectrumR, m_absSpectrumR.data(), binCount());
+ normalize(m_absSpectrumR, m_normSpectrumR, m_inBlockSize);
}
- else
+
+ // count empty lines so that empty history does not have to update
+ if (block_empty && m_waterfallNotEmpty)
{
- m_bufferL[m_framesFilledUp] =
- m_bufferR[m_framesFilledUp] = (in_buffer[in_frame][0] + in_buffer[in_frame][1]) * 0.5f;
+ m_waterfallNotEmpty -= 1;
}
- if (in_buffer[in_frame][0] != 0.f || in_buffer[in_frame][1] != 0.f)
+ else if (!block_empty)
{
- block_empty = false;
+ m_waterfallNotEmpty = m_waterfallHeight + 2;
}
- }
-
- // Run analysis only if buffers contain enough data.
- // Also, to prevent audio interruption and a momentary GUI freeze,
- // skip analysis if buffers are being reallocated.
- if (m_framesFilledUp < m_inBlockSize || m_reallocating) {return;}
- // update sample rate
- m_sampleRate = Engine::mixer()->processingSampleRate();
-
- // apply FFT window
- for (unsigned int i = 0; i < m_inBlockSize; i++)
- {
- m_bufferL[i] = m_bufferL[i] * m_fftWindow[i];
- m_bufferR[i] = m_bufferR[i] * m_fftWindow[i];
- }
-
- // lock data shared with SaSpectrumView and SaWaterfallView
- QMutexLocker lock(&m_dataAccess);
-
- // Run FFT on left channel, convert the result to absolute magnitude
- // spectrum and normalize it.
- fftwf_execute(m_fftPlanL);
- absspec(m_spectrumL, m_absSpectrumL.data(), binCount());
- normalize(m_absSpectrumL, m_normSpectrumL, m_inBlockSize);
-
- // repeat analysis for right channel if stereo processing is enabled
- if (stereo)
- {
- fftwf_execute(m_fftPlanR);
- absspec(m_spectrumR, m_absSpectrumR.data(), binCount());
- normalize(m_absSpectrumR, m_normSpectrumR, m_inBlockSize);
- }
-
- // count empty lines so that empty history does not have to update
- if (block_empty && m_waterfallNotEmpty)
- {
- m_waterfallNotEmpty -= 1;
- }
- else if (!block_empty)
- {
- m_waterfallNotEmpty = m_waterfallHeight + 2;
- }
-
- if (m_waterfallActive && m_waterfallNotEmpty)
- {
- // move waterfall history one line down and clear the top line
- QRgb *pixel = (QRgb *)m_history.data();
- std::copy(pixel,
- pixel + binCount() * m_waterfallHeight - binCount(),
- pixel + binCount());
- memset(pixel, 0, binCount() * sizeof (QRgb));
-
- // add newest result on top
- int target; // pixel being constructed
- float accL = 0; // accumulators for merging multiple bins
- float accR = 0;
-
- for (unsigned int i = 0; i < binCount(); i++)
+ if (m_waterfallActive && m_waterfallNotEmpty)
{
- // Every frequency bin spans a frequency range that must be
- // partially or fully mapped to a pixel. Any inconsistency
- // may be seen in the spectrogram as dark or white lines --
- // play white noise to confirm your change did not break it.
- float band_start = freqToXPixel(binToFreq(i) - binBandwidth() / 2.0, binCount());
- float band_end = freqToXPixel(binToFreq(i + 1) - binBandwidth() / 2.0, binCount());
- if (m_controls->m_logXModel.value())
+ // move waterfall history one line down and clear the top line
+ QRgb *pixel = (QRgb *)m_history_work.data();
+ std::copy(pixel,
+ pixel + waterfallWidth() * m_waterfallHeight - waterfallWidth(),
+ pixel + waterfallWidth());
+ memset(pixel, 0, waterfallWidth() * sizeof (QRgb));
+
+ // add newest result on top
+ int target; // pixel being constructed
+ float accL = 0; // accumulators for merging multiple bins
+ float accR = 0;
+ for (unsigned int i = 0; i < binCount(); i++)
{
- // Logarithmic scale
- if (band_end - band_start > 1.0)
+ // fill line with red color to indicate lost data if CPU cannot keep up
+ if (overload && i < waterfallWidth())
{
- // band spans multiple pixels: draw all pixels it covers
- for (target = (int)band_start; target < (int)band_end; target++)
+ pixel[i] = qRgb(42, 0, 0);
+ continue;
+ }
+
+ // Every frequency bin spans a frequency range that must be
+ // partially or fully mapped to a pixel. Any inconsistency
+ // may be seen in the spectrogram as dark or white lines --
+ // play white noise to confirm your change did not break it.
+ float band_start = freqToXPixel(binToFreq(i) - binBandwidth() / 2.0, waterfallWidth());
+ float band_end = freqToXPixel(binToFreq(i + 1) - binBandwidth() / 2.0, waterfallWidth());
+ if (m_controls->m_logXModel.value())
+ {
+ // Logarithmic scale
+ if (band_end - band_start > 1.0)
{
- if (target >= 0 && target < binCount())
+ // band spans multiple pixels: draw all pixels it covers
+ for (target = (int)band_start; target < (int)band_end; target++)
+ {
+ if (target >= 0 && target < waterfallWidth())
+ {
+ pixel[target] = makePixel(m_normSpectrumL[i], m_normSpectrumR[i]);
+ }
+ }
+ // save remaining portion of the band for the following band / pixel
+ // (in case the next band uses sub-pixel drawing)
+ accL = (band_end - (int)band_end) * m_normSpectrumL[i];
+ accR = (band_end - (int)band_end) * m_normSpectrumR[i];
+ }
+ else
+ {
+ // sub-pixel drawing; add contribution of current band
+ target = (int)band_start;
+ if ((int)band_start == (int)band_end)
+ {
+ // band ends within current target pixel, accumulate
+ accL += (band_end - band_start) * m_normSpectrumL[i];
+ accR += (band_end - band_start) * m_normSpectrumR[i];
+ }
+ else
+ {
+ // Band ends in the next pixel -- finalize the current pixel.
+ // Make sure contribution is split correctly on pixel boundary.
+ accL += ((int)band_end - band_start) * m_normSpectrumL[i];
+ accR += ((int)band_end - band_start) * m_normSpectrumR[i];
+
+ if (target >= 0 && target < waterfallWidth()) {pixel[target] = makePixel(accL, accR);}
+
+ // save remaining portion of the band for the following band / pixel
+ accL = (band_end - (int)band_end) * m_normSpectrumL[i];
+ accR = (band_end - (int)band_end) * m_normSpectrumR[i];
+ }
+ }
+ }
+ else
+ {
+ // Linear: always draws one or more pixels per band
+ for (target = (int)band_start; target < band_end; target++)
+ {
+ if (target >= 0 && target < waterfallWidth())
{
pixel[target] = makePixel(m_normSpectrumL[i], m_normSpectrumR[i]);
}
}
- // save remaining portion of the band for the following band / pixel
- // (in case the next band uses sub-pixel drawing)
- accL = (band_end - (int)band_end) * m_normSpectrumL[i];
- accR = (band_end - (int)band_end) * m_normSpectrumR[i];
- }
- else
- {
- // sub-pixel drawing; add contribution of current band
- target = (int)band_start;
- if ((int)band_start == (int)band_end)
- {
- // band ends within current target pixel, accumulate
- accL += (band_end - band_start) * m_normSpectrumL[i];
- accR += (band_end - band_start) * m_normSpectrumR[i];
- }
- else
- {
- // Band ends in the next pixel -- finalize the current pixel.
- // Make sure contribution is split correctly on pixel boundary.
- accL += ((int)band_end - band_start) * m_normSpectrumL[i];
- accR += ((int)band_end - band_start) * m_normSpectrumR[i];
-
- if (target >= 0 && target < binCount()) {pixel[target] = makePixel(accL, accR);}
-
- // save remaining portion of the band for the following band / pixel
- accL = (band_end - (int)band_end) * m_normSpectrumL[i];
- accR = (band_end - (int)band_end) * m_normSpectrumR[i];
- }
}
}
- else
+
+ // Copy work buffer to result buffer. Done only if requested, so
+ // that time isn't wasted on updating faster than display FPS.
+ // (The copy is about as expensive as the movement.)
+ if (m_flipRequest)
{
- // Linear: always draws one or more pixels per band
- for (target = (int)band_start; target < band_end; target++)
- {
- if (target >= 0 && target < binCount())
- {
- pixel[target] = makePixel(m_normSpectrumL[i], m_normSpectrumR[i]);
- }
- }
+ m_history = m_history_work;
+ m_flipRequest = false;
}
}
- }
- #ifdef SA_DEBUG
- // report FFT processing speed
- start_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - start_time;
- std::cout << "Processed " << m_framesFilledUp << " samples in " << start_time / 1000000.0 << " ms" << std::endl;
- #endif
+ // clean up before checking for more data from input buffer
+ const unsigned int overlaps = m_controls->m_windowOverlapModel.value();
+ if (overlaps == 1) // Discard buffer, each sample used only once
+ {
+ m_framesFilledUp = 0;
+ }
+ else
+ {
+ // Drop only a part of the buffer from the beginning, so that new
+ // data can be added to the end. This means the older samples will
+ // be analyzed again, but in a different position in the window,
+ // making short transient signals show up better in the waterfall.
+ const unsigned int drop = m_inBlockSize / overlaps;
+ std::move(m_bufferL.begin() + drop, m_bufferL.end(), m_bufferL.begin());
+ std::move(m_bufferR.begin() + drop, m_bufferR.end(), m_bufferR.begin());
+ m_framesFilledUp -= drop;
+ }
- // clean up before checking for more data from input buffer
- m_framesFilledUp = 0;
- }
- }
+ #ifdef SA_DEBUG
+ // measure overall FFT processing speed
+ total_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - total_time;
+ m_dump_count++;
+ m_sum_execution += total_time / 1000000.0;
+ if (total_time / 1000000.0 > m_max_execution) {m_max_execution = total_time / 1000000.0;}
+ #endif
+ } // frame filler and processing
+ } // process if active
+ } // thread loop end
}
@@ -251,8 +321,9 @@ void SaProcessor::analyse(sampleFrame *in_buffer, const fpp_t frame_count)
// Gamma correction is applied to make small values more visible and to make
// a linear gradient actually appear roughly linear. The correction should be
// around 0.42 to 0.45 for sRGB displays (or lower for bigger visibility boost).
-QRgb SaProcessor::makePixel(float left, float right, float gamma_correction) const
+QRgb SaProcessor::makePixel(float left, float right) const
{
+ const float gamma_correction = m_controls->m_waterfallGammaModel.value();
if (m_controls->m_stereoModel.value())
{
float ampL = pow(left, gamma_correction);
@@ -265,9 +336,9 @@ QRgb SaProcessor::makePixel(float left, float right, float gamma_correction) con
{
float ampL = pow(left, gamma_correction);
// make mono color brighter to compensate for the fact it is not summed
- return qRgb(m_controls->m_colorMono.lighter().red() * ampL,
- m_controls->m_colorMono.lighter().green() * ampL,
- m_controls->m_colorMono.lighter().blue() * ampL);
+ return qRgb(m_controls->m_colorMonoW.red() * ampL,
+ m_controls->m_colorMonoW.green() * ampL,
+ m_controls->m_colorMonoW.blue() * ampL);
}
}
@@ -301,6 +372,7 @@ void SaProcessor::reallocateBuffers()
{
new_in_size = FFT_BLOCK_SIZES.back();
}
+ m_zeroPadFactor = m_controls->m_zeroPaddingModel.value();
if (new_size_index + m_zeroPadFactor < FFT_BLOCK_SIZES.size())
{
new_fft_size = FFT_BLOCK_SIZES[new_size_index + m_zeroPadFactor];
@@ -312,12 +384,16 @@ void SaProcessor::reallocateBuffers()
new_bins = new_fft_size / 2 +1;
- // Lock data shared with SaSpectrumView and SaWaterfallView.
- // The m_reallocating is here to tell analyse() to avoid asking for the
- // lock, since fftw3 can take a while to find the fastest FFT algorithm
- // for given machine, which would produce interruption in the audio stream.
+ // Use m_reallocating to tell analyze() to avoid asking for the lock. This
+ // is needed because under heavy load the FFT thread requests data lock so
+ // often that this routine could end up waiting even for several seconds.
m_reallocating = true;
- QMutexLocker lock(&m_dataAccess);
+
+ // Lock data shared with SaSpectrumView and SaWaterfallView.
+ // Reallocation lock must be acquired first to avoid deadlock (a view class
+ // may already have it and request the "stronger" data lock on top of that).
+ QMutexLocker reloc_lock(&m_reallocationAccess);
+ QMutexLocker data_lock(&m_dataAccess);
// destroy old FFT plan and free the result buffer
if (m_fftPlanL != NULL) {fftwf_destroy_plan(m_fftPlanL);}
@@ -328,30 +404,42 @@ void SaProcessor::reallocateBuffers()
// allocate new space, create new plan and resize containers
m_fftWindow.resize(new_in_size, 1.0);
precomputeWindow(m_fftWindow.data(), new_in_size, (FFT_WINDOWS) m_controls->m_windowModel.value());
- m_bufferL.resize(new_fft_size, 0);
- m_bufferR.resize(new_fft_size, 0);
+ m_bufferL.resize(new_in_size, 0);
+ m_bufferR.resize(new_in_size, 0);
+ m_filteredBufferL.resize(new_fft_size, 0);
+ m_filteredBufferR.resize(new_fft_size, 0);
m_spectrumL = (fftwf_complex *) fftwf_malloc(new_bins * sizeof (fftwf_complex));
m_spectrumR = (fftwf_complex *) fftwf_malloc(new_bins * sizeof (fftwf_complex));
- m_fftPlanL = fftwf_plan_dft_r2c_1d(new_fft_size, m_bufferL.data(), m_spectrumL, FFTW_MEASURE);
- m_fftPlanR = fftwf_plan_dft_r2c_1d(new_fft_size, m_bufferR.data(), m_spectrumR, FFTW_MEASURE);
+ m_fftPlanL = fftwf_plan_dft_r2c_1d(new_fft_size, m_filteredBufferL.data(), m_spectrumL, FFTW_MEASURE);
+ m_fftPlanR = fftwf_plan_dft_r2c_1d(new_fft_size, m_filteredBufferR.data(), m_spectrumR, FFTW_MEASURE);
if (m_fftPlanL == NULL || m_fftPlanR == NULL)
{
- std::cerr << "Failed to create new FFT plan!" << std::endl;
+ #ifdef SA_DEBUG
+ std::cerr << "Analyzer: failed to create new FFT plan!" << std::endl;
+ #endif
}
m_absSpectrumL.resize(new_bins, 0);
m_absSpectrumR.resize(new_bins, 0);
m_normSpectrumL.resize(new_bins, 0);
m_normSpectrumR.resize(new_bins, 0);
- m_history.resize(new_bins * m_waterfallHeight * sizeof qRgb(0,0,0), 0);
+ m_waterfallHeight = m_controls->m_waterfallHeightModel.value();
+ m_history_work.resize((new_bins < m_waterfallMaxWidth ? new_bins : m_waterfallMaxWidth)
+ * m_waterfallHeight
+ * sizeof qRgb(0,0,0), 0);
+ m_history.resize((new_bins < m_waterfallMaxWidth ? new_bins : m_waterfallMaxWidth)
+ * m_waterfallHeight
+ * sizeof qRgb(0,0,0), 0);
// done; publish new sizes and clean up
m_inBlockSize = new_in_size;
m_fftBlockSize = new_fft_size;
- lock.unlock();
+ data_lock.unlock();
+ reloc_lock.unlock();
m_reallocating = false;
+
clear();
}
@@ -369,17 +457,39 @@ void SaProcessor::rebuildWindow()
// Note: may take a few milliseconds, do not call in a loop!
void SaProcessor::clear()
{
+ const unsigned int overlaps = m_controls->m_windowOverlapModel.value();
QMutexLocker lock(&m_dataAccess);
- m_framesFilledUp = 0;
+ // If there is any window overlap, leave space only for the new samples
+ // and treat the rest at initialized with zeros. Prevents missing
+ // transients at the start of the very first block.
+ m_framesFilledUp = m_inBlockSize - m_inBlockSize / overlaps;
std::fill(m_bufferL.begin(), m_bufferL.end(), 0);
std::fill(m_bufferR.begin(), m_bufferR.end(), 0);
+ std::fill(m_filteredBufferL.begin(), m_filteredBufferL.end(), 0);
+ std::fill(m_filteredBufferR.begin(), m_filteredBufferR.end(), 0);
std::fill(m_absSpectrumL.begin(), m_absSpectrumL.end(), 0);
std::fill(m_absSpectrumR.begin(), m_absSpectrumR.end(), 0);
std::fill(m_normSpectrumL.begin(), m_normSpectrumL.end(), 0);
std::fill(m_normSpectrumR.begin(), m_normSpectrumR.end(), 0);
+ std::fill(m_history_work.begin(), m_history_work.end(), 0);
std::fill(m_history.begin(), m_history.end(), 0);
}
+// Clear only history work buffer. Used to flush old data when waterfall
+// is shown after a period of inactivity.
+void SaProcessor::clearHistory()
+{
+ QMutexLocker lock(&m_dataAccess);
+ std::fill(m_history_work.begin(), m_history_work.end(), 0);
+}
+
+// Check if result buffers contain any non-zero values
+bool SaProcessor::spectrumNotEmpty()
+{
+ QMutexLocker lock(&m_reallocationAccess);
+ return notEmpty(m_normSpectrumL) || notEmpty(m_normSpectrumR);
+}
+
// --------------------------------------
// Frequency conversion helpers
@@ -407,6 +517,17 @@ unsigned int SaProcessor::binCount() const
}
+// Return the final width of waterfall display buffer.
+// Normally the waterfall width equals the number of frequency bins, but the
+// FFT transform can easily produce more bins than can be reasonably useful for
+// currently used display resolutions. This function limits width of the final
+// image to a given size, which is then used during waterfall render and display.
+unsigned int SaProcessor::waterfallWidth() const
+{
+ return binCount() < m_waterfallMaxWidth ? binCount() : m_waterfallMaxWidth;
+}
+
+
// Return the center frequency of given frequency bin.
float SaProcessor::binToFreq(unsigned int bin_index) const
{
@@ -499,10 +620,10 @@ float SaProcessor::getAmpRangeMin(bool linear) const
switch (m_controls->m_ampRangeModel.value())
{
case ARANGE_EXTENDED: return ARANGE_EXTENDED_START;
- case ARANGE_AUDIBLE: return ARANGE_AUDIBLE_START;
- case ARANGE_NOISE: return ARANGE_NOISE_START;
+ case ARANGE_SILENT: return ARANGE_SILENT_START;
+ case ARANGE_LOUD: return ARANGE_LOUD_START;
default:
- case ARANGE_DEFAULT: return ARANGE_DEFAULT_START;
+ case ARANGE_AUDIBLE: return ARANGE_AUDIBLE_START;
}
}
@@ -512,10 +633,10 @@ float SaProcessor::getAmpRangeMax() const
switch (m_controls->m_ampRangeModel.value())
{
case ARANGE_EXTENDED: return ARANGE_EXTENDED_END;
- case ARANGE_AUDIBLE: return ARANGE_AUDIBLE_END;
- case ARANGE_NOISE: return ARANGE_NOISE_END;
+ case ARANGE_SILENT: return ARANGE_SILENT_END;
+ case ARANGE_LOUD: return ARANGE_LOUD_END;
default:
- case ARANGE_DEFAULT: return ARANGE_DEFAULT_END;
+ case ARANGE_AUDIBLE: return ARANGE_AUDIBLE_END;
}
}
diff --git a/plugins/SpectrumAnalyzer/SaProcessor.h b/plugins/SpectrumAnalyzer/SaProcessor.h
index ae2df16f8..0c396b3c0 100644
--- a/plugins/SpectrumAnalyzer/SaProcessor.h
+++ b/plugins/SpectrumAnalyzer/SaProcessor.h
@@ -27,6 +27,7 @@
#ifndef SAPROCESSOR_H
#define SAPROCESSOR_H
+#include
#include
#include
#include
@@ -34,27 +35,45 @@
#include "fft_helpers.h"
#include "SaControls.h"
+template
+class LocklessRingBuffer;
//! Receives audio data, runs FFT analysis and stores the result.
class SaProcessor
{
public:
- explicit SaProcessor(SaControls *controls);
+ explicit SaProcessor(const SaControls *controls);
virtual ~SaProcessor();
- void analyse(sampleFrame *in_buffer, const fpp_t frame_count);
+ // analysis thread and a method to terminate it
+ void analyze(LocklessRingBuffer &ring_buffer);
+ void terminate() {m_terminate = true;}
// inform processor if any processing is actually required
void setSpectrumActive(bool active);
void setWaterfallActive(bool active);
+ void flipRequest() {m_flipRequest = true;} // request refresh of history buffer
// configuration is taken from models in SaControls; some changes require
// an exlicit update request (reallocation and window rebuild)
void reallocateBuffers();
void rebuildWindow();
void clear();
+ void clearHistory();
+
+ const float *getSpectrumL() const {return m_normSpectrumL.data();}
+ const float *getSpectrumR() const {return m_normSpectrumR.data();}
+ const uchar *getHistory() const {return m_history.data();}
// information about results and unit conversion helpers
+ unsigned int inBlockSize() const {return m_inBlockSize;}
+ unsigned int binCount() const; //!< size of output (frequency domain) data block
+ bool spectrumNotEmpty(); //!< check if result buffers contain any non-zero values
+
+ unsigned int waterfallWidth() const; //!< binCount value capped at 3840 (for display)
+ unsigned int waterfallHeight() const {return m_waterfallHeight;}
+ bool waterfallNotEmpty() const {return m_waterfallNotEmpty;}
+
float binToFreq(unsigned int bin_index) const;
float binBandwidth() const;
@@ -72,26 +91,38 @@ public:
float getAmpRangeMin(bool linear = false) const;
float getAmpRangeMax() const;
- // data access lock must be acquired by any friendly class that touches
- // the results, mainly to prevent unexpected mid-way reallocation
+ // Reallocation lock prevents the processor from changing size of its buffers.
+ // It is used to keep consistent bin-to-frequency mapping while drawing the
+ // spectrum and to make sure reading side does not find itself out of bounds.
+ // The processor is meanwhile free to work on another block.
+ QMutex m_reallocationAccess;
+ // Data access lock prevents the processor from changing both size and content
+ // of its buffers. It is used when writing to a result buffer, or when a friendly
+ // class reads them and needs guaranteed data consistency.
+ // It causes FFT analysis to be paused, so this lock should be used sparingly.
+ // If using both locks at the same time, reallocation lock MUST be acquired first.
QMutex m_dataAccess;
+
private:
- SaControls *m_controls;
+ const SaControls *m_controls;
+
+ // thread communication and control
+ bool m_terminate;
// currently valid configuration
- const unsigned int m_zeroPadFactor = 2; //!< use n-steps bigger FFT for given block size
- unsigned int m_inBlockSize; //!< size of input (time domain) data block
+ unsigned int m_zeroPadFactor = 2; //!< use n-steps bigger FFT for given block size
+ std::atomic m_inBlockSize;//!< size of input (time domain) data block
unsigned int m_fftBlockSize; //!< size of padded block for FFT processing
unsigned int m_sampleRate;
- unsigned int binCount() const; //!< size of output (frequency domain) data block
-
// data buffers (roughly in the order of processing, from input to output)
unsigned int m_framesFilledUp;
std::vector m_bufferL; //!< time domain samples (left)
std::vector m_bufferR; //!< time domain samples (right)
std::vector m_fftWindow; //!< precomputed window function coefficients
+ std::vector m_filteredBufferL; //!< time domain samples with window function applied (left)
+ std::vector m_filteredBufferR; //!< time domain samples with window function applied (right)
fftwf_plan m_fftPlanL;
fftwf_plan m_fftPlanR;
fftwf_complex *m_spectrumL; //!< frequency domain samples (complex) (left)
@@ -102,21 +133,28 @@ private:
std::vector m_normSpectrumR; //!< frequency domain samples (normalized) (right)
// spectrum history for waterfall: new normSpectrum lines are added on top
- std::vector m_history;
- const unsigned int m_waterfallHeight = 200; // Number of stored lines.
- // Note: high values may make it harder to see transients.
+ std::vector m_history_work; //!< local history buffer for render
+ std::vector m_history; //!< public buffer for reading
+ bool m_flipRequest; //!< update public buffer only when requested
+ std::atomic m_waterfallHeight; //!< number of stored lines in history buffer
+ // Note: high values may make it harder to see transients.
+ const unsigned int m_waterfallMaxWidth = 3840;
// book keeping
bool m_spectrumActive;
bool m_waterfallActive;
- unsigned int m_waterfallNotEmpty;
+ std::atomic m_waterfallNotEmpty; //!< number of lines remaining visible on display
bool m_reallocating;
// merge L and R channels and apply gamma correction to make a spectrogram pixel
- QRgb makePixel(float left, float right, float gamma_correction = 0.30) const;
+ QRgb makePixel(float left, float right) const;
- friend class SaSpectrumView;
- friend class SaWaterfallView;
+ #ifdef SA_DEBUG
+ unsigned int m_last_dump_time;
+ unsigned int m_dump_count;
+ float m_sum_execution;
+ float m_max_execution;
+ #endif
};
#endif // SAPROCESSOR_H
diff --git a/plugins/SpectrumAnalyzer/SaSpectrumView.cpp b/plugins/SpectrumAnalyzer/SaSpectrumView.cpp
index 746d52cfd..13aaeb724 100644
--- a/plugins/SpectrumAnalyzer/SaSpectrumView.cpp
+++ b/plugins/SpectrumAnalyzer/SaSpectrumView.cpp
@@ -39,7 +39,6 @@
#ifdef SA_DEBUG
#include
- #include
#endif
@@ -68,7 +67,11 @@ SaSpectrumView::SaSpectrumView(SaControls *controls, SaProcessor *processor, QWi
m_logAmpTics = makeLogAmpTics(m_processor->getAmpRangeMin(), m_processor->getAmpRangeMax());
m_linearAmpTics = makeLinearAmpTics(m_processor->getAmpRangeMin(), m_processor->getAmpRangeMax());
- m_cursor = QPoint(0, 0);
+ m_cursor = QPointF(0, 0);
+
+ #ifdef SA_DEBUG
+ m_execution_avg = m_path_avg = m_draw_avg = 0;
+ #endif
}
@@ -134,12 +137,20 @@ void SaSpectrumView::paintEvent(QPaintEvent *event)
2.0, 2.0);
#ifdef SA_DEBUG
- // display what FPS would be achieved if spectrum display ran in a loop
+ // display performance measurements if enabled
total_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - total_time;
+ m_execution_avg = 0.95 * m_execution_avg + 0.05 * total_time / 1000000.0;
painter.setPen(QPen(m_controls->m_colorLabels, 1,
Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin));
- painter.drawText(m_displayRight -100, 70, 100, 16, Qt::AlignLeft,
- QString(std::string("Max FPS: " + std::to_string(1000000000.0 / total_time)).c_str()));
+ painter.drawText(m_displayRight -150, 10, 130, 16, Qt::AlignLeft,
+ QString("Exec avg.: ").append(std::to_string(m_execution_avg).substr(0, 5).c_str()).append(" ms"));
+ painter.drawText(m_displayRight -150, 30, 130, 16, Qt::AlignLeft,
+ QString("Buff. upd. avg: ").append(std::to_string(m_refresh_avg).substr(0, 5).c_str()).append(" ms"));
+ painter.drawText(m_displayRight -150, 50, 130, 16, Qt::AlignLeft,
+ QString("Path build avg: ").append(std::to_string(m_path_avg).substr(0, 5).c_str()).append(" ms"));
+ painter.drawText(m_displayRight -150, 70, 130, 16, Qt::AlignLeft,
+ QString("Path draw avg: ").append(std::to_string(m_draw_avg).substr(0, 5).c_str()).append(" ms"));
+
#endif
}
@@ -148,22 +159,14 @@ void SaSpectrumView::paintEvent(QPaintEvent *event)
void SaSpectrumView::drawSpectrum(QPainter &painter)
{
#ifdef SA_DEBUG
- int path_time = 0, draw_time = 0;
+ int draw_time = 0;
#endif
// draw the graph only if there is any input, averaging residue or peaks
- QMutexLocker lock(&m_processor->m_dataAccess);
- if (m_decaySum > 0 || notEmpty(m_processor->m_normSpectrumL) || notEmpty(m_processor->m_normSpectrumR))
+ if (m_decaySum > 0 || m_processor->spectrumNotEmpty())
{
- lock.unlock();
- #ifdef SA_DEBUG
- path_time = std::chrono::high_resolution_clock::now().time_since_epoch().count();
- #endif
// update data buffers and reconstruct paths
refreshPaths();
- #ifdef SA_DEBUG
- path_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - path_time;
- #endif
// draw stored paths
#ifdef SA_DEBUG
@@ -199,17 +202,10 @@ void SaSpectrumView::drawSpectrum(QPainter &painter)
draw_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - draw_time;
#endif
}
- else
- {
- lock.unlock();
- }
#ifdef SA_DEBUG
- // display measurement results
- painter.drawText(m_displayRight -100, 90, 100, 16, Qt::AlignLeft,
- QString(std::string("Path ms: " + std::to_string(path_time / 1000000.0)).c_str()));
- painter.drawText(m_displayRight -100, 110, 100, 16, Qt::AlignLeft,
- QString(std::string("Draw ms: " + std::to_string(draw_time / 1000000.0)).c_str()));
+ // save performance measurement result
+ m_draw_avg = 0.95 * m_draw_avg + 0.05 * draw_time / 1000000.0;
#endif
}
@@ -218,9 +214,9 @@ void SaSpectrumView::drawSpectrum(QPainter &painter)
// and build QPainter paths.
void SaSpectrumView::refreshPaths()
{
- // Lock is required for the entire function, mainly to prevent block size
- // changes from causing reallocation of data structures mid-way.
- QMutexLocker lock(&m_processor->m_dataAccess);
+ // Reallocation lock is required for the entire function, to keep display
+ // buffer size consistent with block size.
+ QMutexLocker reloc_lock(&m_processor->m_reallocationAccess);
// check if bin count changed and reallocate display buffers accordingly
if (m_processor->binCount() != m_displayBufferL.size())
@@ -240,8 +236,8 @@ void SaSpectrumView::refreshPaths()
int refresh_time = std::chrono::high_resolution_clock::now().time_since_epoch().count();
#endif
m_decaySum = 0;
- updateBuffers(m_processor->m_normSpectrumL.data(), m_displayBufferL.data(), m_peakBufferL.data());
- updateBuffers(m_processor->m_normSpectrumR.data(), m_displayBufferR.data(), m_peakBufferR.data());
+ updateBuffers(m_processor->getSpectrumL(), m_displayBufferL.data(), m_peakBufferL.data());
+ updateBuffers(m_processor->getSpectrumR(), m_displayBufferR.data(), m_peakBufferR.data());
#ifdef SA_DEBUG
refresh_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - refresh_time;
#endif
@@ -254,41 +250,43 @@ void SaSpectrumView::refreshPaths()
}
#ifdef SA_DEBUG
- int make_time = std::chrono::high_resolution_clock::now().time_since_epoch().count();
+ int path_time = std::chrono::high_resolution_clock::now().time_since_epoch().count();
#endif
// Use updated display buffers to prepare new paths for QPainter.
// This is the second slowest action (first is the subsequent drawing); use
// the resolution parameter to balance display quality and performance.
- m_pathL = makePath(m_displayBufferL, 1.5);
+ m_pathL = makePath(m_displayBufferL, m_controls->m_spectrumResolutionModel.value());
if (m_controls->m_stereoModel.value())
{
- m_pathR = makePath(m_displayBufferR, 1.5);
+ m_pathR = makePath(m_displayBufferR, m_controls->m_spectrumResolutionModel.value());
}
if (m_controls->m_peakHoldModel.value() || m_controls->m_refFreezeModel.value())
{
- m_pathPeakL = makePath(m_peakBufferL, 0.25);
+ m_pathPeakL = makePath(m_peakBufferL, m_controls->m_envelopeResolutionModel.value());
if (m_controls->m_stereoModel.value())
{
- m_pathPeakR = makePath(m_peakBufferR, 0.25);
+ m_pathPeakR = makePath(m_peakBufferR, m_controls->m_envelopeResolutionModel.value());
}
}
#ifdef SA_DEBUG
- make_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - make_time;
+ path_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - path_time;
#endif
#ifdef SA_DEBUG
- // print measurement results
- std::cout << "Buffer update ms: " << std::to_string(refresh_time / 1000000.0) << ", ";
- std::cout << "Path-make ms: " << std::to_string(make_time / 1000000.0) << std::endl;
+ // save performance measurement results
+ m_refresh_avg = 0.95 * m_refresh_avg + 0.05 * refresh_time / 1000000.0;
+ m_path_avg = .95f * m_path_avg + .05f * path_time / 1000000.f;
#endif
}
// Update display buffers: add new data, update average and peaks / reference.
// Output the sum of all displayed values -- draw only if it is non-zero.
-// NOTE: The calling function is responsible for acquiring SaProcessor data
-// access lock!
-void SaSpectrumView::updateBuffers(float *spectrum, float *displayBuffer, float *peakBuffer)
+// NOTE: The calling function is responsible for acquiring SaProcessor
+// reallocation access lock! Data access lock is not needed: the final result
+// buffer is updated very quickly and the worst case is that one frame will be
+// part new, part old. At reasonable frame rate, such difference is invisible..
+void SaSpectrumView::updateBuffers(const float *spectrum, float *displayBuffer, float *peakBuffer)
{
for (int n = 0; n < m_processor->binCount(); n++)
{
@@ -297,7 +295,8 @@ void SaSpectrumView::updateBuffers(float *spectrum, float *displayBuffer, float
{
if (m_controls->m_smoothModel.value())
{
- displayBuffer[n] = spectrum[n] * m_smoothFactor + displayBuffer[n] * (1 - m_smoothFactor);
+ const float smoothFactor = m_controls->m_averagingWeightModel.value();
+ displayBuffer[n] = spectrum[n] * smoothFactor + displayBuffer[n] * (1 - smoothFactor);
}
else
{
@@ -319,7 +318,7 @@ void SaSpectrumView::updateBuffers(float *spectrum, float *displayBuffer, float
}
else if (!m_controls->m_refFreezeModel.value())
{
- peakBuffer[n] = peakBuffer[n] * m_peakDecayFactor;
+ peakBuffer[n] = peakBuffer[n] * m_controls->m_peakDecayFactorModel.value();
}
}
else if (!m_controls->m_refFreezeModel.value() && !m_controls->m_peakHoldModel.value())
@@ -539,38 +538,52 @@ void SaSpectrumView::drawGrid(QPainter &painter)
// Draw cursor and its coordinates if it is within display bounds.
void SaSpectrumView::drawCursor(QPainter &painter)
{
- if( m_cursor.x() >= m_displayLeft
+ if ( m_cursor.x() >= m_displayLeft
&& m_cursor.x() <= m_displayRight
&& m_cursor.y() >= m_displayTop
&& m_cursor.y() <= m_displayBottom)
{
// cursor lines
painter.setPen(QPen(m_controls->m_colorGrid.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin));
- painter.drawLine(m_cursor.x(), m_displayTop, m_cursor.x(), m_displayBottom);
- painter.drawLine(m_displayLeft, m_cursor.y(), m_displayRight, m_cursor.y());
+ painter.drawLine(QPointF(m_cursor.x(), m_displayTop), QPointF(m_cursor.x(), m_displayBottom));
+ painter.drawLine(QPointF(m_displayLeft, m_cursor.y()), QPointF(m_displayRight, m_cursor.y()));
- // coordinates
+ // coordinates: background box
+ QFontMetrics fontMetrics = painter.fontMetrics();
+ unsigned int const box_left = 5;
+ unsigned int const box_top = 5;
+ unsigned int const box_margin = 3;
+ unsigned int const box_height = 2*(fontMetrics.size(Qt::TextSingleLine, "0 HzdBFS").height() + box_margin);
+ unsigned int const box_width = fontMetrics.size(Qt::TextSingleLine, "-99.9 dBFS").width() + 2*box_margin;
painter.setPen(QPen(m_controls->m_colorLabels.darker(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin));
- painter.drawText(m_displayRight -60, 5, 100, 16, Qt::AlignLeft, "Cursor");
+ painter.fillRect(m_displayLeft + box_left, m_displayTop + box_top,
+ box_width, box_height, QColor(0, 0, 0, 64));
+ // coordinates: text
+ painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin));
QString tmps;
+
// frequency
int xFreq = (int)m_processor->xPixelToFreq(m_cursor.x() - m_displayLeft, m_displayWidth);
- tmps = QString(std::string(std::to_string(xFreq) + " Hz").c_str());
- painter.drawText(m_displayRight -60, 18, 100, 16, Qt::AlignLeft, tmps);
+ tmps = QString("%1 Hz").arg(xFreq);
+ painter.drawText(m_displayLeft + box_left + box_margin,
+ m_displayTop + box_top + box_margin,
+ box_width, box_height / 2, Qt::AlignLeft, tmps);
// amplitude
float yAmp = m_processor->yPixelToAmp(m_cursor.y(), m_displayBottom);
if (m_controls->m_logYModel.value())
{
- tmps = QString(std::string(std::to_string(yAmp).substr(0, 5) + " dB").c_str());
+ tmps = QString(std::to_string(yAmp).substr(0, 5).c_str()).append(" dBFS");
}
else
{
// add 0.0005 to get proper rounding to 3 decimal places
- tmps = QString(std::string(std::to_string(0.0005f + yAmp)).substr(0, 5).c_str());
+ tmps = QString(std::to_string(0.0005f + yAmp).substr(0, 5).c_str());
}
- painter.drawText(m_displayRight -60, 30, 100, 16, Qt::AlignLeft, tmps);
+ painter.drawText(m_displayLeft + box_left + box_margin,
+ m_displayTop + box_top + box_height / 2,
+ box_width, box_height / 2, Qt::AlignLeft, tmps);
}
}
@@ -774,14 +787,18 @@ void SaSpectrumView::periodicUpdate()
// Handle mouse input: set new cursor position.
+// For some reason (a bug?), localPos() only returns integers. As a workaround
+// the fractional part is taken from windowPos() (which works correctly).
void SaSpectrumView::mouseMoveEvent(QMouseEvent *event)
{
- m_cursor = event->pos();
+ m_cursor = QPointF( event->localPos().x() - (event->windowPos().x() - (long)event->windowPos().x()),
+ event->localPos().y() - (event->windowPos().y() - (long)event->windowPos().y()));
}
void SaSpectrumView::mousePressEvent(QMouseEvent *event)
{
- m_cursor = event->pos();
+ m_cursor = QPointF( event->localPos().x() - (event->windowPos().x() - (long)event->windowPos().x()),
+ event->localPos().y() - (event->windowPos().y() - (long)event->windowPos().y()));
}
diff --git a/plugins/SpectrumAnalyzer/SaSpectrumView.h b/plugins/SpectrumAnalyzer/SaSpectrumView.h
index 0db5852e1..b59264d9c 100644
--- a/plugins/SpectrumAnalyzer/SaSpectrumView.h
+++ b/plugins/SpectrumAnalyzer/SaSpectrumView.h
@@ -27,6 +27,8 @@
#ifndef SASPECTRUMVIEW_H
#define SASPECTRUMVIEW_H
+#include "SaControls.h"
+
#include
#include
#include
@@ -34,7 +36,6 @@
class QMouseEvent;
class QPainter;
-class SaControls;
class SaProcessor;
//! Widget that displays a spectrum curve and frequency / amplitude grid
@@ -84,7 +85,7 @@ private:
std::vector m_displayBufferR;
std::vector m_peakBufferL;
std::vector m_peakBufferR;
- void updateBuffers(float *spectrum, float *displayBuffer, float *peakBuffer);
+ void updateBuffers(const float *spectrum, float *displayBuffer, float *peakBuffer);
// final paths to be drawn by QPainter and methods to build them
QPainterPath m_pathL;
@@ -99,14 +100,11 @@ private:
bool m_freezeRequest; // new reference should be acquired
bool m_frozen; // a reference is currently stored in the peakBuffer
- const float m_smoothFactor = 0.15; // alpha for exponential smoothing
- const float m_peakDecayFactor = 0.992; // multiplier for gradual peak decay
-
// top level: refresh buffers, make paths and draw the spectrum
void drawSpectrum(QPainter &painter);
// current cursor location and a method to draw it
- QPoint m_cursor;
+ QPointF m_cursor;
void drawCursor(QPainter &painter);
// wrappers for most used SaProcessor conversion helpers
@@ -121,6 +119,13 @@ private:
unsigned int m_displayLeft;
unsigned int m_displayRight;
unsigned int m_displayWidth;
+
+ #ifdef SA_DEBUG
+ float m_execution_avg;
+ float m_refresh_avg;
+ float m_path_avg;
+ float m_draw_avg;
+ #endif
};
#endif // SASPECTRUMVIEW_H
diff --git a/plugins/SpectrumAnalyzer/SaWaterfallView.cpp b/plugins/SpectrumAnalyzer/SaWaterfallView.cpp
index 617e80b2c..e015d31ef 100644
--- a/plugins/SpectrumAnalyzer/SaWaterfallView.cpp
+++ b/plugins/SpectrumAnalyzer/SaWaterfallView.cpp
@@ -23,8 +23,12 @@
#include "SaWaterfallView.h"
#include
+#ifdef SA_DEBUG
+ #include
+#endif
#include
#include
+#include
#include
#include
#include
@@ -47,8 +51,22 @@ SaWaterfallView::SaWaterfallView(SaControls *controls, SaProcessor *processor, Q
connect(gui->mainWindow(), SIGNAL(periodicUpdate()), this, SLOT(periodicUpdate()));
+ m_displayTop = 1;
+ m_displayBottom = height() -2;
+ m_displayLeft = 26;
+ m_displayRight = width() -26;
+ m_displayWidth = m_displayRight - m_displayLeft;
+ m_displayHeight = m_displayBottom - m_displayTop;
+
m_timeTics = makeTimeTics();
- m_oldTimePerLine = (float)m_processor->m_inBlockSize / m_processor->getSampleRate();
+ m_oldSecondsPerLine = 0;
+ m_oldHeight = 0;
+
+ m_cursor = QPointF(0, 0);
+
+ #ifdef SA_DEBUG
+ m_execution_avg = 0;
+ #endif
}
@@ -58,15 +76,14 @@ SaWaterfallView::SaWaterfallView(SaControls *controls, SaProcessor *processor, Q
void SaWaterfallView::paintEvent(QPaintEvent *event)
{
#ifdef SA_DEBUG
- int start_time = std::chrono::high_resolution_clock::now().time_since_epoch().count();
+ unsigned int draw_time = std::chrono::high_resolution_clock::now().time_since_epoch().count();
#endif
- // all drawing done here, local variables are sufficient for the boundary
- const int displayTop = 1;
- const int displayBottom = height() -2;
- const int displayLeft = 26;
- const int displayRight = width() -26;
- const int displayWidth = displayRight - displayLeft;
+ // update boundary
+ m_displayBottom = height() -2;
+ m_displayRight = width() -26;
+ m_displayWidth = m_displayRight - m_displayLeft;
+ m_displayHeight = m_displayBottom - m_displayTop;
float label_width = 20;
float label_height = 16;
float margin = 2;
@@ -75,10 +92,11 @@ void SaWaterfallView::paintEvent(QPaintEvent *event)
painter.setRenderHint(QPainter::Antialiasing, true);
// check if time labels need to be rebuilt
- if ((float)m_processor->m_inBlockSize / m_processor->getSampleRate() != m_oldTimePerLine)
+ if (secondsPerLine() != m_oldSecondsPerLine || m_processor->waterfallHeight() != m_oldHeight)
{
m_timeTics = makeTimeTics();
- m_oldTimePerLine = (float)m_processor->m_inBlockSize / m_processor->getSampleRate();
+ m_oldSecondsPerLine = secondsPerLine();
+ m_oldHeight = m_processor->waterfallHeight();
}
// print time labels
@@ -86,78 +104,104 @@ void SaWaterfallView::paintEvent(QPaintEvent *event)
painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin));
for (auto & line: m_timeTics)
{
- pos = timeToYPixel(line.first, displayBottom);
+ pos = timeToYPixel(line.first, m_displayHeight);
// align first and last label to the edge if needed, otherwise center them
if (line == m_timeTics.front() && pos < label_height / 2)
{
- painter.drawText(displayLeft - label_width - margin, displayTop - 1,
+ painter.drawText(m_displayLeft - label_width - margin, m_displayTop - 1,
label_width, label_height, Qt::AlignRight | Qt::AlignTop | Qt::TextDontClip,
QString(line.second.c_str()));
- painter.drawText(displayRight + margin, displayTop - 1,
+ painter.drawText(m_displayRight + margin, m_displayTop - 1,
label_width, label_height, Qt::AlignLeft | Qt::AlignTop | Qt::TextDontClip,
QString(line.second.c_str()));
}
- else if (line == m_timeTics.back() && pos > displayBottom - label_height + 2)
+ else if (line == m_timeTics.back() && pos > m_displayBottom - label_height + 2)
{
- painter.drawText(displayLeft - label_width - margin, displayBottom - label_height,
+ painter.drawText(m_displayLeft - label_width - margin, m_displayBottom - label_height,
label_width, label_height, Qt::AlignRight | Qt::AlignBottom | Qt::TextDontClip,
QString(line.second.c_str()));
- painter.drawText(displayRight + margin, displayBottom - label_height + 2,
+ painter.drawText(m_displayRight + margin, m_displayBottom - label_height + 2,
label_width, label_height, Qt::AlignLeft | Qt::AlignBottom | Qt::TextDontClip,
QString(line.second.c_str()));
}
else
{
- painter.drawText(displayLeft - label_width - margin, pos - label_height / 2,
+ painter.drawText(m_displayLeft - label_width - margin, pos - label_height / 2,
label_width, label_height, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip,
QString(line.second.c_str()));
- painter.drawText(displayRight + margin, pos - label_height / 2,
+ painter.drawText(m_displayRight + margin, pos - label_height / 2,
label_width, label_height, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip,
QString(line.second.c_str()));
}
}
// draw the spectrogram precomputed in SaProcessor
- if (m_processor->m_waterfallNotEmpty)
+ if (m_processor->waterfallNotEmpty())
{
- QMutexLocker lock(&m_processor->m_dataAccess);
- painter.drawImage(displayLeft, displayTop, // top left corner coordinates
- QImage(m_processor->m_history.data(), // raw pixel data to display
- m_processor->binCount(), // width = number of frequency bins
- m_processor->m_waterfallHeight, // height = number of history lines
- QImage::Format_RGB32
- ).scaled(displayWidth, // scale to fit view..
- displayBottom,
- Qt::IgnoreAspectRatio,
- Qt::SmoothTransformation));
+ QMutexLocker lock(&m_processor->m_reallocationAccess);
+ QImage temp = QImage(m_processor->getHistory(), // raw pixel data to display
+ m_processor->waterfallWidth(), // width = number of frequency bins
+ m_processor->waterfallHeight(), // height = number of history lines
+ QImage::Format_RGB32);
lock.unlock();
+ temp.setDevicePixelRatio(devicePixelRatio()); // display at native resolution
+ painter.drawImage(m_displayLeft, m_displayTop,
+ temp.scaled(m_displayWidth * devicePixelRatio(),
+ m_displayHeight * devicePixelRatio(),
+ Qt::IgnoreAspectRatio,
+ Qt::SmoothTransformation));
+ m_processor->flipRequest();
}
else
{
- painter.fillRect(displayLeft, displayTop, displayWidth, displayBottom, QColor(0,0,0));
+ painter.fillRect(m_displayLeft, m_displayTop, m_displayWidth, m_displayHeight, QColor(0,0,0));
}
+ // draw cursor (if it is within bounds)
+ drawCursor(painter);
+
// always draw the outline
painter.setPen(QPen(m_controls->m_colorGrid, 2, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin));
- painter.drawRoundedRect(displayLeft, displayTop, displayWidth, displayBottom, 2.0, 2.0);
+ painter.drawRoundedRect(m_displayLeft, m_displayTop, m_displayWidth, m_displayHeight, 2.0, 2.0);
#ifdef SA_DEBUG
- // display what FPS would be achieved if waterfall ran in a loop
- start_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - start_time;
+ draw_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - draw_time;
+ m_execution_avg = 0.95 * m_execution_avg + 0.05 * draw_time / 1000000.0;
painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin));
- painter.drawText(displayRight -100, 10, 100, 16, Qt::AlignLeft,
- QString(std::string("Max FPS: " + std::to_string(1000000000.0 / start_time)).c_str()));
+ painter.drawText(m_displayRight -150, 10, 100, 16, Qt::AlignLeft,
+ QString("Exec avg.: ").append(std::to_string(m_execution_avg).substr(0, 5).c_str()).append(" ms"));
#endif
}
+// Helper functions for time conversion
+float SaWaterfallView::samplesPerLine()
+{
+ return (float)m_processor->inBlockSize() / m_controls->m_windowOverlapModel.value();
+}
+
+float SaWaterfallView::secondsPerLine()
+{
+ return samplesPerLine() / m_processor->getSampleRate();
+}
+
+
// Convert time value to Y coordinate for display of given height.
float SaWaterfallView::timeToYPixel(float time, int height)
{
- float pixels_per_line = (float)height / m_processor->m_waterfallHeight;
- float seconds_per_line = ((float)m_processor->m_inBlockSize / m_processor->getSampleRate());
+ float pixels_per_line = (float)height / m_processor->waterfallHeight();
- return pixels_per_line * time / seconds_per_line;
+ return pixels_per_line * time / secondsPerLine();
+}
+
+
+// Convert Y coordinate on display of given height back to time value.
+float SaWaterfallView::yPixelToTime(float position, int height)
+{
+ if (height == 0) {height = 1;}
+ float pixels_per_line = (float)height / m_processor->waterfallHeight();
+
+ return (position / pixels_per_line) * secondsPerLine();
}
@@ -167,16 +211,21 @@ std::vector> SaWaterfallView::makeTimeTics()
std::vector> result;
float i;
- // upper limit defined by number of lines * time per line
- float limit = m_processor->m_waterfallHeight * ((float)m_processor->m_inBlockSize / m_processor->getSampleRate());
+ // get time value of the last line
+ float limit = yPixelToTime(m_displayBottom, m_displayHeight);
- // set increment so that about 8 tics are generated
- float increment = std::round(10 * limit / 7) / 10;
+ // set increment to about 30 pixels (but min. 0.1 s)
+ float increment = std::round(10 * limit / (m_displayHeight / 30)) / 10;
+ if (increment < 0.1) {increment = 0.1;}
// NOTE: labels positions are rounded to match the (rounded) label value
for (i = 0; i <= limit; i += increment)
{
- if (i < 10)
+ if (i > 99)
+ {
+ result.emplace_back(std::round(i), std::to_string(std::round(i)).substr(0, 3));
+ }
+ else if (i < 10)
{
result.emplace_back(std::round(i * 10) / 10, std::to_string(std::round(i * 10) / 10).substr(0, 3));
}
@@ -208,10 +257,7 @@ void SaWaterfallView::updateVisibility()
if (m_controls->m_waterfallModel.value())
{
// clear old data before showing the waterfall
- QMutexLocker lock(&m_processor->m_dataAccess);
- std::fill(m_processor->m_history.begin(), m_processor->m_history.end(), 0);
- lock.unlock();
-
+ m_processor->clearHistory();
setVisible(true);
// increase window size if it is too small
@@ -228,3 +274,70 @@ void SaWaterfallView::updateVisibility()
}
}
+
+// Draw cursor and its coordinates if it is within display bounds.
+void SaWaterfallView::drawCursor(QPainter &painter)
+{
+ if ( m_cursor.x() >= m_displayLeft
+ && m_cursor.x() <= m_displayRight
+ && m_cursor.y() >= m_displayTop
+ && m_cursor.y() <= m_displayBottom)
+ {
+ // cursor lines
+ painter.setPen(QPen(m_controls->m_colorGrid.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin));
+ painter.drawLine(QPointF(m_cursor.x(), m_displayTop), QPointF(m_cursor.x(), m_displayBottom));
+ painter.drawLine(QPointF(m_displayLeft, m_cursor.y()), QPointF(m_displayRight, m_cursor.y()));
+
+ // coordinates: background box
+ QFontMetrics fontMetrics = painter.fontMetrics();
+ unsigned int const box_left = 5;
+ unsigned int const box_top = 5;
+ unsigned int const box_margin = 3;
+ unsigned int const box_height = 2*(fontMetrics.size(Qt::TextSingleLine, "0 Hz").height() + box_margin);
+ unsigned int const box_width = fontMetrics.size(Qt::TextSingleLine, "20000 Hz ").width() + 2*box_margin;
+ painter.setPen(QPen(m_controls->m_colorLabels.darker(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin));
+ painter.fillRect(m_displayLeft + box_left, m_displayTop + box_top,
+ box_width, box_height, QColor(0, 0, 0, 64));
+
+ // coordinates: text
+ painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin));
+ QString tmps;
+
+ // frequency
+ int freq = (int)m_processor->xPixelToFreq(m_cursor.x() - m_displayLeft, m_displayWidth);
+ tmps = QString("%1 Hz").arg(freq);
+ painter.drawText(m_displayLeft + box_left + box_margin,
+ m_displayTop + box_top + box_margin,
+ box_width, box_height / 2, Qt::AlignLeft, tmps);
+
+ // time
+ float time = yPixelToTime(m_cursor.y(), m_displayBottom);
+ tmps = QString(std::to_string(time).substr(0, 5).c_str()).append(" s");
+ painter.drawText(m_displayLeft + box_left + box_margin,
+ m_displayTop + box_top + box_height / 2,
+ box_width, box_height / 2, Qt::AlignLeft, tmps);
+ }
+}
+
+
+// Handle mouse input: set new cursor position.
+// For some reason (a bug?), localPos() only returns integers. As a workaround
+// the fractional part is taken from windowPos() (which works correctly).
+void SaWaterfallView::mouseMoveEvent(QMouseEvent *event)
+{
+ m_cursor = QPointF( event->localPos().x() - (event->windowPos().x() - (long)event->windowPos().x()),
+ event->localPos().y() - (event->windowPos().y() - (long)event->windowPos().y()));
+}
+
+void SaWaterfallView::mousePressEvent(QMouseEvent *event)
+{
+ m_cursor = QPointF( event->localPos().x() - (event->windowPos().x() - (long)event->windowPos().x()),
+ event->localPos().y() - (event->windowPos().y() - (long)event->windowPos().y()));
+}
+
+
+// Handle resize event: rebuild time labels
+void SaWaterfallView::resizeEvent(QResizeEvent *event)
+{
+ m_timeTics = makeTimeTics();
+}
diff --git a/plugins/SpectrumAnalyzer/SaWaterfallView.h b/plugins/SpectrumAnalyzer/SaWaterfallView.h
index 0e104c0a1..bd91d6d16 100644
--- a/plugins/SpectrumAnalyzer/SaWaterfallView.h
+++ b/plugins/SpectrumAnalyzer/SaWaterfallView.h
@@ -32,6 +32,7 @@
#include "SaControls.h"
#include "SaProcessor.h"
+class QMouseEvent;
// Widget that displays a spectrum waterfall (spectrogram) and time labels.
class SaWaterfallView : public QWidget
@@ -48,6 +49,9 @@ public:
protected:
void paintEvent(QPaintEvent *event) override;
+ void mouseMoveEvent(QMouseEvent *event) override;
+ void mousePressEvent(QMouseEvent *event) override;
+ void resizeEvent(QResizeEvent *event) override;
private slots:
void periodicUpdate();
@@ -58,9 +62,29 @@ private:
const EffectControlDialog *m_controlDialog;
// Methods and data used to make time labels
- float m_oldTimePerLine;
+ float m_oldSecondsPerLine;
+ float m_oldHeight;
+ float samplesPerLine();
+ float secondsPerLine();
float timeToYPixel(float time, int height);
+ float yPixelToTime(float position, int height);
std::vector> makeTimeTics();
std::vector> m_timeTics; // 0..n (s)
+
+ // current cursor location and a method to draw it
+ QPointF m_cursor;
+ void drawCursor(QPainter &painter);
+
+ // current boundaries for drawing
+ unsigned int m_displayTop;
+ unsigned int m_displayBottom;
+ unsigned int m_displayLeft;
+ unsigned int m_displayRight;
+ unsigned int m_displayWidth;
+ unsigned int m_displayHeight;
+
+ #ifdef SA_DEBUG
+ float m_execution_avg;
+ #endif
};
#endif // SAWATERFALLVIEW_H
diff --git a/plugins/SpectrumAnalyzer/advanced_off.svg b/plugins/SpectrumAnalyzer/advanced_off.svg
new file mode 100644
index 000000000..6d3ed82b1
--- /dev/null
+++ b/plugins/SpectrumAnalyzer/advanced_off.svg
@@ -0,0 +1,243 @@
+
+
+
+
diff --git a/plugins/SpectrumAnalyzer/advanced_on.svg b/plugins/SpectrumAnalyzer/advanced_on.svg
new file mode 100644
index 000000000..9e6b1ca3f
--- /dev/null
+++ b/plugins/SpectrumAnalyzer/advanced_on.svg
@@ -0,0 +1,224 @@
+
+
+
+
diff --git a/plugins/SpectrumAnalyzer/advanced_src.svg b/plugins/SpectrumAnalyzer/advanced_src.svg
new file mode 100644
index 000000000..ae201aad0
--- /dev/null
+++ b/plugins/SpectrumAnalyzer/advanced_src.svg
@@ -0,0 +1,238 @@
+
+
+
+
diff --git a/plugins/VstEffect/VstEffectControlDialog.h b/plugins/VstEffect/VstEffectControlDialog.h
index 3cd9af360..930f514c9 100644
--- a/plugins/VstEffect/VstEffectControlDialog.h
+++ b/plugins/VstEffect/VstEffectControlDialog.h
@@ -49,8 +49,8 @@ public:
virtual ~VstEffectControlDialog();
protected:
- virtual void paintEvent( QPaintEvent * _pe );
- virtual void showEvent( QShowEvent* _se ) override;
+ void paintEvent( QPaintEvent * _pe ) override;
+ void showEvent( QShowEvent* _se ) override;
private:
QWidget * m_pluginWidget;
diff --git a/plugins/Xpressive/Xpressive.cpp b/plugins/Xpressive/Xpressive.cpp
index 018319c82..a80a0ae41 100644
--- a/plugins/Xpressive/Xpressive.cpp
+++ b/plugins/Xpressive/Xpressive.cpp
@@ -53,9 +53,9 @@
extern "C" {
Plugin::Descriptor PLUGIN_EXPORT xpressive_plugin_descriptor = { STRINGIFY(
- PLUGIN_NAME), "X-Pressive", QT_TRANSLATE_NOOP("pluginBrowser",
- "Mathematical expression parser"), "Orr Dvori", 0x0100,
- Plugin::Instrument, new PluginPixmapLoader("logo"), NULL, NULL };
+ PLUGIN_NAME), "Xpressive", QT_TRANSLATE_NOOP("pluginBrowser",
+ "Mathematical expression parser"), "Orr Dvori", 0x0100,
+ Plugin::Instrument, new PluginPixmapLoader("logo"), NULL, NULL };
}
@@ -257,7 +257,6 @@ public:
setCenterPointY(14.5);
setInnerRadius(4);
setOuterRadius(9);
- setOuterColor(QColor(0x519fff));
setTotalAngle(300.0);
setLineWidth(3);
}
@@ -277,14 +276,18 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) :
InstrumentViewFixedSize(_instrument, _parent)
{
- const int COL_KNOBS = 194;
- const int ROW_KNOBSA1 = 26;
- const int ROW_KNOBSA2 = 26 + 32;
- const int ROW_KNOBSA3 = 26 + 64;
- const int ROW_KNOBSP1 = 126;
- const int ROW_KNOBSP2 = 126 + 32;
- const int ROW_KNOBREL = 126 + 64;
- const int ROW_WAVEBTN = 234;
+ const int COL_KNOBS = 191;
+ const int BASE_START = 2;
+ const int ROW_KNOBSA1 = BASE_START;
+ const int ROW_KNOBSA2 = BASE_START + 32;
+ const int ROW_KNOBSA3 = BASE_START + 64;
+ const int ROW_KNOBSP1 = BASE_START + 100;
+ const int ROW_KNOBSP2 = BASE_START + 100 + 32;
+ const int ROW_KNOBREL = BASE_START + 100 + 64;
+ const int ROW_BTN = BASE_START + 85;
+ const int ROW_WAVEBTN = BASE_START + 233 - 26;
+ const int EXPR_TEXT_Y = BASE_START + 102;
+ const int EXPR_TEXT_H = 90;
setAutoFillBackground(true);
QPalette pal;
@@ -293,7 +296,7 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) :
setPalette(pal);
m_graph = new Graph(this, Graph::LinearStyle, 180, 81);
- m_graph->move(9, 27);
+ m_graph->move(3, BASE_START + 1);
m_graph->setAutoFillBackground(true);
m_graph->setGraphColor(QColor(255, 255, 255));
m_graph->setEnabled(false);
@@ -313,37 +316,37 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) :
PixmapButton * m_helpBtn;
m_w1Btn = new PixmapButton(this, NULL);
- m_w1Btn->move(9, 111);
+ m_w1Btn->move(3, ROW_BTN);
m_w1Btn->setActiveGraphic(PLUGIN_NAME::getIconPixmap("w1_active"));
m_w1Btn->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("w1_inactive"));
ToolTip::add(m_w1Btn, tr("Select oscillator W1"));
m_w2Btn = new PixmapButton(this, NULL);
- m_w2Btn->move(32, 111);
+ m_w2Btn->move(26, ROW_BTN);
m_w2Btn->setActiveGraphic(PLUGIN_NAME::getIconPixmap("w2_active"));
m_w2Btn->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("w2_inactive"));
ToolTip::add(m_w2Btn, tr("Select oscillator W2"));
m_w3Btn = new PixmapButton(this, NULL);
- m_w3Btn->move(55, 111);
+ m_w3Btn->move(49, ROW_BTN);
m_w3Btn->setActiveGraphic(PLUGIN_NAME::getIconPixmap("w3_active"));
m_w3Btn->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("w3_inactive"));
ToolTip::add(m_w3Btn, tr("Select oscillator W3"));
m_o1Btn = new PixmapButton(this, NULL);
- m_o1Btn->move(85, 111);
+ m_o1Btn->move(79, ROW_BTN);
m_o1Btn->setActiveGraphic(PLUGIN_NAME::getIconPixmap("o1_active"));
m_o1Btn->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("o1_inactive"));
ToolTip::add(m_o1Btn, tr("Select output O1"));
m_o2Btn = new PixmapButton(this, NULL);
- m_o2Btn->move(107, 111);
+ m_o2Btn->move(101, ROW_BTN);
m_o2Btn->setActiveGraphic(PLUGIN_NAME::getIconPixmap("o2_active"));
m_o2Btn->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("o2_inactive"));
ToolTip::add(m_o2Btn, tr("Select output O2"));
m_helpBtn = new PixmapButton(this, NULL);
- m_helpBtn->move(139, 111);
+ m_helpBtn->move(133, ROW_BTN);
m_helpBtn->setActiveGraphic(PLUGIN_NAME::getIconPixmap("help_active"));
m_helpBtn->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("help_inactive"));
ToolTip::add(m_helpBtn, tr("Open help window"));
@@ -359,38 +362,38 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) :
m_selectedGraphGroup->setModel(&e->selectedGraph());
m_sinWaveBtn = new PixmapButton(this, tr("Sine wave"));
- m_sinWaveBtn->move(10, ROW_WAVEBTN);
+ m_sinWaveBtn->move(4, ROW_WAVEBTN);
m_sinWaveBtn->setActiveGraphic(embed::getIconPixmap("sin_wave_active"));
m_sinWaveBtn->setInactiveGraphic(embed::getIconPixmap("sin_wave_inactive"));
ToolTip::add(m_sinWaveBtn, tr("Sine wave"));
m_moogWaveBtn = new PixmapButton(this, tr("Moog-saw wave"));
- m_moogWaveBtn->move(10, ROW_WAVEBTN-14);
+ m_moogWaveBtn->move(4, ROW_WAVEBTN-14);
m_moogWaveBtn->setActiveGraphic(
embed::getIconPixmap( "moog_saw_wave_active" ) );
m_moogWaveBtn->setInactiveGraphic(embed::getIconPixmap("moog_saw_wave_inactive"));
ToolTip::add(m_moogWaveBtn, tr("Moog-saw wave"));
m_expWaveBtn = new PixmapButton(this, tr("Exponential wave"));
- m_expWaveBtn->move(10 +14, ROW_WAVEBTN-14);
+ m_expWaveBtn->move(4 +14, ROW_WAVEBTN-14);
m_expWaveBtn->setActiveGraphic(embed::getIconPixmap( "exp_wave_active" ) );
m_expWaveBtn->setInactiveGraphic(embed::getIconPixmap( "exp_wave_inactive" ) );
ToolTip::add(m_expWaveBtn, tr("Exponential wave"));
m_sawWaveBtn = new PixmapButton(this, tr("Saw wave"));
- m_sawWaveBtn->move(10 + 14 * 2, ROW_WAVEBTN-14);
+ m_sawWaveBtn->move(4 + 14 * 2, ROW_WAVEBTN-14);
m_sawWaveBtn->setActiveGraphic(embed::getIconPixmap("saw_wave_active"));
m_sawWaveBtn->setInactiveGraphic(embed::getIconPixmap("saw_wave_inactive"));
ToolTip::add(m_sawWaveBtn, tr("Saw wave"));
m_usrWaveBtn = new PixmapButton(this, tr("User-defined wave"));
- m_usrWaveBtn->move(10 + 14 * 3, ROW_WAVEBTN-14);
+ m_usrWaveBtn->move(4 + 14 * 3, ROW_WAVEBTN-14);
m_usrWaveBtn->setActiveGraphic(embed::getIconPixmap("usr_wave_active"));
m_usrWaveBtn->setInactiveGraphic(embed::getIconPixmap("usr_wave_inactive"));
ToolTip::add(m_usrWaveBtn, tr("User-defined wave"));
m_triangleWaveBtn = new PixmapButton(this, tr("Triangle wave"));
- m_triangleWaveBtn->move(10 + 14, ROW_WAVEBTN);
+ m_triangleWaveBtn->move(4 + 14, ROW_WAVEBTN);
m_triangleWaveBtn->setActiveGraphic(
embed::getIconPixmap("triangle_wave_active"));
m_triangleWaveBtn->setInactiveGraphic(
@@ -398,14 +401,14 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) :
ToolTip::add(m_triangleWaveBtn, tr("Triangle wave"));
m_sqrWaveBtn = new PixmapButton(this, tr("Square wave"));
- m_sqrWaveBtn->move(10 + 14 * 2, ROW_WAVEBTN);
+ m_sqrWaveBtn->move(4 + 14 * 2, ROW_WAVEBTN);
m_sqrWaveBtn->setActiveGraphic(embed::getIconPixmap("square_wave_active"));
m_sqrWaveBtn->setInactiveGraphic(
embed::getIconPixmap("square_wave_inactive"));
ToolTip::add(m_sqrWaveBtn, tr("Square wave"));
m_whiteNoiseWaveBtn = new PixmapButton(this, tr("White noise"));
- m_whiteNoiseWaveBtn->move(10 + 14 * 3, ROW_WAVEBTN);
+ m_whiteNoiseWaveBtn->move(4 + 14 * 3, ROW_WAVEBTN);
m_whiteNoiseWaveBtn->setActiveGraphic(
embed::getIconPixmap("white_noise_wave_active"));
m_whiteNoiseWaveBtn->setInactiveGraphic(
@@ -415,16 +418,16 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) :
m_waveInterpolate = new LedCheckBox("Interpolate", this, tr("WaveInterpolate"),
LedCheckBox::Green);
- m_waveInterpolate->move(120, 230);
+ m_waveInterpolate->move(2, 230);
m_expressionValidToggle = new LedCheckBox("", this, tr("ExpressionValid"),
LedCheckBox::Red);
- m_expressionValidToggle->move(174, 216);
+ m_expressionValidToggle->move(168, EXPR_TEXT_Y+EXPR_TEXT_H-2);
m_expressionValidToggle->setEnabled( false );
m_expressionEditor = new QPlainTextEdit(this);
- m_expressionEditor->move(9, 128);
- m_expressionEditor->resize(180, 90);
+ m_expressionEditor->move(3, EXPR_TEXT_Y);
+ m_expressionEditor->resize(180, EXPR_TEXT_H);
m_generalPurposeKnob[0] = new XpressiveKnob(this,"A1");
m_generalPurposeKnob[0]->setHintText(tr("General purpose 1:"), "");
@@ -452,9 +455,16 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) :
- m_smoothKnob=new Knob(this,"Smoothness");
+ m_smoothKnob=new Knob(knobStyled, this, "Smoothness");
+ m_smoothKnob->setFixedSize(25, 25);
+ m_smoothKnob->setCenterPointX(12.5);
+ m_smoothKnob->setCenterPointY(12.5);
+ m_smoothKnob->setInnerRadius(4);
+ m_smoothKnob->setOuterRadius(9);
+ m_smoothKnob->setTotalAngle(280.0);
+ m_smoothKnob->setLineWidth(3);
m_smoothKnob->setHintText(tr("Smoothness"), "");
- m_smoothKnob->move(80, 220);
+ m_smoothKnob->move(66, EXPR_TEXT_Y + EXPR_TEXT_H + 4);
connect(m_generalPurposeKnob[0], SIGNAL(sliderMoved(float)), this,
SLOT(expressionChanged()));
@@ -748,7 +758,7 @@ void XpressiveView::updateLayout() {
void XpressiveView::sinWaveClicked() {
if (m_output_expr)
- m_expressionEditor->appendPlainText("sinew(t*f)");
+ m_expressionEditor->appendPlainText("sinew(integrate(f))");
else
m_expressionEditor->appendPlainText("sinew(t)");
Engine::getSong()->setModified();
@@ -756,7 +766,7 @@ void XpressiveView::sinWaveClicked() {
void XpressiveView::triangleWaveClicked() {
if (m_output_expr)
- m_expressionEditor->appendPlainText("trianglew(t*f)");
+ m_expressionEditor->appendPlainText("trianglew(integrate(f))");
else
m_expressionEditor->appendPlainText("trianglew(t)");
Engine::getSong()->setModified();
@@ -764,7 +774,7 @@ void XpressiveView::triangleWaveClicked() {
void XpressiveView::sawWaveClicked() {
if (m_output_expr)
- m_expressionEditor->appendPlainText("saww(t*f)");
+ m_expressionEditor->appendPlainText("saww(integrate(f))");
else
m_expressionEditor->appendPlainText("saww(t)");
Engine::getSong()->setModified();
@@ -772,7 +782,7 @@ void XpressiveView::sawWaveClicked() {
void XpressiveView::sqrWaveClicked() {
if (m_output_expr)
- m_expressionEditor->appendPlainText("squarew(t*f)");
+ m_expressionEditor->appendPlainText("squarew(integrate(f))");
else
m_expressionEditor->appendPlainText("squarew(t)");
Engine::getSong()->setModified();
@@ -786,7 +796,7 @@ void XpressiveView::noiseWaveClicked() {
void XpressiveView::moogSawWaveClicked()
{
if (m_output_expr)
- m_expressionEditor->appendPlainText("moogsaww(t*f)");
+ m_expressionEditor->appendPlainText("moogsaww(integrate(f))");
else
m_expressionEditor->appendPlainText("moogsaww(t)");
Engine::getSong()->setModified();
@@ -794,7 +804,7 @@ void XpressiveView::moogSawWaveClicked()
void XpressiveView::expWaveClicked()
{
if (m_output_expr)
- m_expressionEditor->appendPlainText("expw(t*f)");
+ m_expressionEditor->appendPlainText("expw(integrate(f))");
else
m_expressionEditor->appendPlainText("expw(t)");
Engine::getSong()->setModified();
@@ -861,7 +871,7 @@ QString XpressiveHelpView::s_helpText=
XpressiveHelpView::XpressiveHelpView():QTextEdit(s_helpText)
{
- setWindowTitle ( "X-Pressive Help" );
+ setWindowTitle ( "Xpressive Help" );
setTextInteractionFlags ( Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse );
gui->mainWindow()->addWindowedWidget( this );
parentWidget()->setAttribute( Qt::WA_DeleteOnClose, false );
diff --git a/plugins/Xpressive/Xpressive.svg b/plugins/Xpressive/Xpressive.svg
new file mode 100644
index 000000000..ef3029c0d
--- /dev/null
+++ b/plugins/Xpressive/Xpressive.svg
@@ -0,0 +1,130 @@
+
+
+
+
diff --git a/plugins/Xpressive/Xpressive_logo.svg b/plugins/Xpressive/Xpressive_logo.svg
new file mode 100644
index 000000000..fca1f0d98
--- /dev/null
+++ b/plugins/Xpressive/Xpressive_logo.svg
@@ -0,0 +1,106 @@
+
+
+
+
diff --git a/plugins/Xpressive/artwork.png b/plugins/Xpressive/artwork.png
index d5b39acee..1f4e35ad5 100644
Binary files a/plugins/Xpressive/artwork.png and b/plugins/Xpressive/artwork.png differ
diff --git a/plugins/Xpressive/help_active.png b/plugins/Xpressive/help_active.png
index 4e991ad54..8d8b49d43 100644
Binary files a/plugins/Xpressive/help_active.png and b/plugins/Xpressive/help_active.png differ
diff --git a/plugins/Xpressive/help_inactive.png b/plugins/Xpressive/help_inactive.png
index 4b77af24f..d08f6d9a7 100644
Binary files a/plugins/Xpressive/help_inactive.png and b/plugins/Xpressive/help_inactive.png differ
diff --git a/plugins/Xpressive/logo.png b/plugins/Xpressive/logo.png
index 68b613176..555c3f13e 100644
Binary files a/plugins/Xpressive/logo.png and b/plugins/Xpressive/logo.png differ
diff --git a/plugins/Xpressive/o1_active.png b/plugins/Xpressive/o1_active.png
index 6370769dd..8e31a8322 100644
Binary files a/plugins/Xpressive/o1_active.png and b/plugins/Xpressive/o1_active.png differ
diff --git a/plugins/Xpressive/o1_inactive.png b/plugins/Xpressive/o1_inactive.png
index 0fd4f8b29..7a6b603e3 100644
Binary files a/plugins/Xpressive/o1_inactive.png and b/plugins/Xpressive/o1_inactive.png differ
diff --git a/plugins/Xpressive/o2_active.png b/plugins/Xpressive/o2_active.png
index 51897412d..4e3b5f214 100644
Binary files a/plugins/Xpressive/o2_active.png and b/plugins/Xpressive/o2_active.png differ
diff --git a/plugins/Xpressive/o2_inactive.png b/plugins/Xpressive/o2_inactive.png
index 20158d725..35851d553 100644
Binary files a/plugins/Xpressive/o2_inactive.png and b/plugins/Xpressive/o2_inactive.png differ
diff --git a/plugins/Xpressive/w1_active.png b/plugins/Xpressive/w1_active.png
index 49a3a2b6e..68d8e9ae0 100644
Binary files a/plugins/Xpressive/w1_active.png and b/plugins/Xpressive/w1_active.png differ
diff --git a/plugins/Xpressive/w1_inactive.png b/plugins/Xpressive/w1_inactive.png
index 266e4206f..7159b4979 100644
Binary files a/plugins/Xpressive/w1_inactive.png and b/plugins/Xpressive/w1_inactive.png differ
diff --git a/plugins/Xpressive/w2_active.png b/plugins/Xpressive/w2_active.png
index cd4729949..17d7b53d9 100644
Binary files a/plugins/Xpressive/w2_active.png and b/plugins/Xpressive/w2_active.png differ
diff --git a/plugins/Xpressive/w2_inactive.png b/plugins/Xpressive/w2_inactive.png
index 8d54929da..412482bb0 100644
Binary files a/plugins/Xpressive/w2_inactive.png and b/plugins/Xpressive/w2_inactive.png differ
diff --git a/plugins/Xpressive/w3_active.png b/plugins/Xpressive/w3_active.png
index 9e4facb2c..579b997dd 100644
Binary files a/plugins/Xpressive/w3_active.png and b/plugins/Xpressive/w3_active.png differ
diff --git a/plugins/Xpressive/w3_inactive.png b/plugins/Xpressive/w3_inactive.png
index e5b0bc7d9..d45d8b497 100644
Binary files a/plugins/Xpressive/w3_inactive.png and b/plugins/Xpressive/w3_inactive.png differ
diff --git a/plugins/Xpressive/wavegraph.png b/plugins/Xpressive/wavegraph.png
index 9d58e8fe7..ea7bc3761 100644
Binary files a/plugins/Xpressive/wavegraph.png and b/plugins/Xpressive/wavegraph.png differ
diff --git a/plugins/bit_invader/bit_invader.cpp b/plugins/bit_invader/bit_invader.cpp
index f8a8423ad..caa272fa7 100644
--- a/plugins/bit_invader/bit_invader.cpp
+++ b/plugins/bit_invader/bit_invader.cpp
@@ -64,17 +64,16 @@ Plugin::Descriptor PLUGIN_EXPORT bitinvader_plugin_descriptor =
}
-bSynth::bSynth( float * _shape, int _length, NotePlayHandle * _nph, bool _interpolation,
+bSynth::bSynth( float * _shape, NotePlayHandle * _nph, bool _interpolation,
float _factor, const sample_rate_t _sample_rate ) :
sample_index( 0 ),
sample_realindex( 0 ),
nph( _nph ),
- sample_length( _length ),
sample_rate( _sample_rate ),
interpolation( _interpolation)
{
- sample_shape = new float[sample_length];
- for (int i=0; i < _length; ++i)
+ sample_shape = new float[200];
+ for (int i=0; i < 200; ++i)
{
sample_shape[i] = _shape[i] * _factor;
}
@@ -87,7 +86,7 @@ bSynth::~bSynth()
}
-sample_t bSynth::nextStringSample()
+sample_t bSynth::nextStringSample( float sample_length )
{
float sample_step =
static_cast( sample_length / ( sample_rate / nph->frequency() ) );
@@ -140,10 +139,12 @@ sample_t bSynth::nextStringSample()
bitInvader::bitInvader( InstrumentTrack * _instrument_track ) :
Instrument( _instrument_track, &bitinvader_plugin_descriptor ),
m_sampleLength( 128, 4, 200, 1, this, tr( "Sample length" ) ),
- m_graph( -1.0f, 1.0f, 128, this ),
+ m_graph( -1.0f, 1.0f, 200, this ),
m_interpolation( false, this ),
m_normalize( false, this )
{
+
+ lengthChanged();
m_graph.setWaveToSine();
@@ -278,7 +279,6 @@ void bitInvader::playNote( NotePlayHandle * _n,
_n->m_pluginData = new bSynth(
const_cast( m_graph.samples() ),
- m_graph.length(),
_n,
m_interpolation.value(), factor,
Engine::mixer()->processingSampleRate() );
@@ -290,7 +290,7 @@ void bitInvader::playNote( NotePlayHandle * _n,
bSynth * ps = static_cast( _n->m_pluginData );
for( fpp_t frame = offset; frame < frames + offset; ++frame )
{
- const sample_t cur = ps->nextStringSample();
+ const sample_t cur = ps->nextStringSample( m_graph.length() );
for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
{
_working_buffer[frame][chnl] = cur;
@@ -572,7 +572,3 @@ PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
}
-
-
-
-
diff --git a/plugins/bit_invader/bit_invader.h b/plugins/bit_invader/bit_invader.h
index 793831e4a..ae9c92cb2 100644
--- a/plugins/bit_invader/bit_invader.h
+++ b/plugins/bit_invader/bit_invader.h
@@ -42,12 +42,12 @@ class bSynth
{
MM_OPERATORS
public:
- bSynth( float * sample, int length, NotePlayHandle * _nph,
+ bSynth( float * sample, NotePlayHandle * _nph,
bool _interpolation, float factor,
const sample_rate_t _sample_rate );
virtual ~bSynth();
- sample_t nextStringSample();
+ sample_t nextStringSample( float sample_length );
private:
@@ -55,7 +55,6 @@ private:
float sample_realindex;
float* sample_shape;
NotePlayHandle* nph;
- const int sample_length;
const sample_rate_t sample_rate;
bool interpolation;
diff --git a/plugins/carlabase/carla.cpp b/plugins/carlabase/carla.cpp
index 3df97ce40..ba2dd085c 100644
--- a/plugins/carlabase/carla.cpp
+++ b/plugins/carlabase/carla.cpp
@@ -324,10 +324,10 @@ void CarlaInstrument::play(sampleFrame* workingBuffer)
fTimeInfo.playing = s->isPlaying();
fTimeInfo.frame = s->getPlayPos(s->playMode()).frames(Engine::framesPerTick());
fTimeInfo.usecs = s->getMilliseconds()*1000;
- fTimeInfo.bbt.bar = s->getTacts() + 1;
+ fTimeInfo.bbt.bar = s->getBars() + 1;
fTimeInfo.bbt.beat = s->getBeat() + 1;
fTimeInfo.bbt.tick = s->getBeatTicks();
- fTimeInfo.bbt.barStartTick = ticksPerBeat*s->getTimeSigModel().getNumerator()*s->getTacts();
+ fTimeInfo.bbt.barStartTick = ticksPerBeat*s->getTimeSigModel().getNumerator()*s->getBars();
fTimeInfo.bbt.beatsPerBar = s->getTimeSigModel().getNumerator();
fTimeInfo.bbt.beatType = s->getTimeSigModel().getDenominator();
fTimeInfo.bbt.ticksPerBeat = ticksPerBeat;
diff --git a/plugins/organic/organic.cpp b/plugins/organic/organic.cpp
index 7da4fc6f7..6eb933afa 100644
--- a/plugins/organic/organic.cpp
+++ b/plugins/organic/organic.cpp
@@ -306,7 +306,7 @@ void organicInstrument::playNote( NotePlayHandle * _n,
// fxKnob is [0;1]
float t = m_fx1Model.value();
- for (int i=0 ; i < frames ; i++)
+ for (int i=0 ; i < frames + offset ; i++)
{
_working_buffer[i][0] = waveshape( _working_buffer[i][0], t ) *
m_volModel.value() / 100.0f;
diff --git a/plugins/peak_controller_effect/peak_controller_effect.h b/plugins/peak_controller_effect/peak_controller_effect.h
index 093b56437..a872e2b8b 100644
--- a/plugins/peak_controller_effect/peak_controller_effect.h
+++ b/plugins/peak_controller_effect/peak_controller_effect.h
@@ -36,9 +36,9 @@ public:
const Descriptor::SubPluginFeatures::Key * _key );
virtual ~PeakControllerEffect();
virtual bool processAudioBuffer( sampleFrame * _buf,
- const fpp_t _frames );
+ const fpp_t _frames ) override;
- virtual EffectControls * controls()
+ EffectControls * controls() override
{
return &m_peakControls;
}
diff --git a/plugins/peak_controller_effect/peak_controller_effect_controls.h b/plugins/peak_controller_effect/peak_controller_effect_controls.h
index 784df4d8d..fe90eddca 100644
--- a/plugins/peak_controller_effect/peak_controller_effect_controls.h
+++ b/plugins/peak_controller_effect/peak_controller_effect_controls.h
@@ -41,18 +41,18 @@ public:
{
}
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
- virtual void loadSettings( const QDomElement & _this );
- inline virtual QString nodeName() const
+ void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
+ void loadSettings( const QDomElement & _this ) override;
+ inline QString nodeName() const override
{
return "peakcontrollereffectcontrols";
}
- virtual int controlCount()
+ int controlCount() override
{
return 1;
}
- virtual EffectControlDialog * createView()
+ EffectControlDialog * createView() override
{
return new PeakControllerEffectControlDialog( this );
}
diff --git a/plugins/sf2_player/sf2_player.cpp b/plugins/sf2_player/sf2_player.cpp
index cc2575d2b..99af22781 100644
--- a/plugins/sf2_player/sf2_player.cpp
+++ b/plugins/sf2_player/sf2_player.cpp
@@ -151,7 +151,7 @@ sf2Instrument::sf2Instrument( InstrumentTrack * _instrument_track ) :
m_chorusDepth.setInitValue(settingVal);
#endif
- loadFile( ConfigManager::inst()->defaultSoundfont() );
+ loadFile( ConfigManager::inst()->sf2File() );
updateSampleRate();
updateReverbOn();
diff --git a/plugins/vst_base/CMakeLists.txt b/plugins/vst_base/CMakeLists.txt
index 44ed0dcb3..873ed5f8e 100644
--- a/plugins/vst_base/CMakeLists.txt
+++ b/plugins/vst_base/CMakeLists.txt
@@ -11,23 +11,35 @@ SET(REMOTE_VST_PLUGIN_FILEPATH_64 "RemoteVstPlugin64" CACHE STRING "Relative fil
ADD_SUBDIRECTORY(vstbase)
-SET(LMMS_BINARY_DIR ${CMAKE_BINARY_DIR})
-SET(LMMS_SOURCE_DIR ${CMAKE_SOURCE_DIR})
-
SET(EXTERNALPROJECT_ARGS
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/RemoteVstPlugin"
- INSTALL_COMMAND ""
+ #INSTALL_COMMAND ""
BUILD_ALWAYS ON
+ # Skip the install step.
+ INSTALL_COMMAND ""
)
+set(export_variables
+ "LMMS_SOURCE_DIR"
+ "LMMS_BINARY_DIR"
+ "CMAKE_MODULE_PATH"
+ "CMAKE_RUNTIME_OUTPUT_DIRECTORY"
+ "CMAKE_BUILD_TYPE"
+ "LMMS_BUILD_LINUX"
+ "LMMS_BUILD_WIN32"
+ "PLUGIN_DIR")
+
SET(EXTERNALPROJECT_CMAKE_ARGS
- "-DLMMS_SOURCE_DIR=${CMAKE_SOURCE_DIR}"
- "-DLMMS_BINARY_DIR=${CMAKE_BINARY_DIR}"
- "-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
- "-DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}"
- "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
+ "-DBUILD_WITH_EXTERNALPROJECT=ON"
)
+macro(_export_var_to_external var_name)
+ list(APPEND EXTERNALPROJECT_CMAKE_ARGS "-D${var_name}=${${var_name}}")
+endmacro()
+foreach(var ${export_variables})
+ _export_var_to_external(${var})
+endforeach()
+
# build 32 bit version of RemoteVstPlugin
IF(WANT_VST_32)
INCLUDE("${CMAKE_CURRENT_LIST_DIR}/RemoteVstPlugin32.cmake")
diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp
index 48ab13743..5b4bbbd9b 100644
--- a/plugins/vst_base/RemoteVstPlugin.cpp
+++ b/plugins/vst_base/RemoteVstPlugin.cpp
@@ -734,6 +734,7 @@ void RemoteVstPlugin::init( const std::string & _plugin_file )
static void close_check( FILE* fp )
{
+ if (!fp) {return;}
if( fclose( fp ) )
{
perror( "fclose" );
@@ -1128,6 +1129,12 @@ void RemoteVstPlugin::saveChunkToFile( const std::string & _file )
if( len > 0 )
{
FILE* fp = F_OPEN_UTF8( _file, "wb" );
+ if (!fp)
+ {
+ fprintf( stderr,
+ "Error opening file for saving chunk.\n" );
+ return;
+ }
if ( fwrite( chunk, 1, len, fp ) != len )
{
fprintf( stderr,
@@ -1293,6 +1300,12 @@ void RemoteVstPlugin::savePreset( const std::string & _file )
pBank->numPrograms = endian_swap( uIntToFile );
FILE * stream = F_OPEN_UTF8( _file, "w" );
+ if (!stream)
+ {
+ fprintf( stderr,
+ "Error opening file for saving preset.\n" );
+ return;
+ }
fwrite ( pBank, 1, 28, stream );
fwrite ( progName, 1, isPreset ? 28 : 128, stream );
if ( chunky ) {
@@ -1345,6 +1358,12 @@ void RemoteVstPlugin::loadPresetFile( const std::string & _file )
unsigned int len = 0;
sBank * pBank = (sBank*) new char[ sizeof( sBank ) ];
FILE * stream = F_OPEN_UTF8( _file, "r" );
+ if (!stream)
+ {
+ fprintf( stderr,
+ "Error opening file for loading preset.\n" );
+ return;
+ }
if ( fread ( pBank, 1, 56, stream ) != 56 )
{
fprintf( stderr, "Error loading preset file.\n" );
@@ -1446,6 +1465,12 @@ void RemoteVstPlugin::loadChunkFromFile( const std::string & _file, int _len )
char * chunk = new char[_len];
FILE* fp = F_OPEN_UTF8( _file, "rb" );
+ if (!fp)
+ {
+ fprintf( stderr,
+ "Error opening file for loading chunk.\n" );
+ return;
+ }
if ( fread( chunk, 1, _len, fp ) != _len )
{
fprintf( stderr, "Error loading chunk from file.\n" );
diff --git a/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt b/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt
index 59dd19a0a..f4023fd42 100644
--- a/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt
+++ b/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt
@@ -76,3 +76,18 @@ endif()
IF(STRIP)
ADD_CUSTOM_COMMAND(TARGET ${EXE_NAME} POST_BUILD COMMAND "${STRIP}" "$")
ENDIF()
+
+if(BITNESS EQUAL 32)
+ INSTALL(TARGETS ${EXE_NAME} RUNTIME DESTINATION "${PLUGIN_DIR}/32")
+else()
+ INSTALL(TARGETS ${EXE_NAME} RUNTIME DESTINATION "${PLUGIN_DIR}")
+endif()
+
+if(BUILD_WITH_EXTERNALPROJECT)
+ include(InstallTargetDependencies)
+ INSTALL_TARGET_DEPENDENCIES(TARGETS ${EXE_NAME}
+ DESTINATION "${PLUGIN_DIR}/32")
+else()
+ # Needed to deploy dependencies of RemoteVstPlugin
+ SET_PROPERTY(GLOBAL APPEND PROPERTY PLUGINS_BUILT "${EXE_NAME}")
+endif()
diff --git a/plugins/vst_base/RemoteVstPlugin32.cmake b/plugins/vst_base/RemoteVstPlugin32.cmake
index 9a8f04529..cba9a26c8 100644
--- a/plugins/vst_base/RemoteVstPlugin32.cmake
+++ b/plugins/vst_base/RemoteVstPlugin32.cmake
@@ -1,33 +1,31 @@
+# INSTALL_EXTERNAL_PROJECT: install a project created with ExternalProject_Add in the
+# parent project's install time.
+#
+# Description:
+# In a regular scenario, cmake will install external projects
+# BEFORE actually building the parent project. Since the building
+# process may use installed components from the project.
+# We want to give the external project the ability to install
+# files directly to the parent's install. Therefore, we have to
+# manually trigger the install stage with the parent's INSTALL_PREFIX.
+MACRO(INSTALL_EXTERNAL_PROJECT name)
+ ExternalProject_Get_Property(${name} BINARY_DIR)
+
+ install(CODE "include(\"${BINARY_DIR}/cmake_install.cmake\")")
+ENDMACRO()
+
IF(LMMS_BUILD_WIN32 AND NOT LMMS_BUILD_WIN64)
ADD_SUBDIRECTORY(RemoteVstPlugin)
- IF(MSVC)
- SET(VCPKG_ROOT "${CMAKE_FIND_ROOT_PATH}")
- INSTALL(FILES "${VCPKG_ROOT}/bin/Qt5Core.dll" DESTINATION "${PLUGIN_DIR}/32")
- INSTALL(FILES "${VCPKG_ROOT}/bin/zlib1.dll" DESTINATION "${PLUGIN_DIR}/32")
- ELSE(MSVC)
- INSTALL(FILES "${MINGW_PREFIX}/bin/Qt5Core.dll" DESTINATION "${PLUGIN_DIR}/32")
- INSTALL(FILES "${MINGW_PREFIX}/bin/zlib1.dll" DESTINATION "${PLUGIN_DIR}/32")
- ENDIF(MSVC)
- INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../32/RemoteVstPlugin32.exe" DESTINATION "${PLUGIN_DIR}/32")
ELSEIF(LMMS_BUILD_WIN64 AND MSVC)
- SET(MSVC_VER ${CMAKE_CXX_COMPILER_VERSION})
-
- IF(NOT CMAKE_GENERATOR_32)
- IF(MSVC_VER VERSION_GREATER 19.10 OR MSVC_VER VERSION_EQUAL 19.10)
- SET(CMAKE_GENERATOR_32 "Visual Studio 15 2017")
- SET(MSVC_YEAR 2017)
- ELSEIF(MSVC_VER VERSION_GREATER 19.0 OR MSVC_VER VERSION_EQUAL 19.0)
- SET(CMAKE_GENERATOR_32 "Visual Studio 14 2015")
- SET(MSVC_YEAR 2015)
- ELSE()
- MESSAGE(SEND_WARNING "Can't build RemoteVstPlugin32, unknown MSVC version ${MSVC_VER} and no CMAKE_GENERATOR_32 set")
- RETURN()
- ENDIF()
- ENDIF()
-
IF(NOT QT_32_PREFIX)
+ SET(LMMS_MSVC_YEAR_FOR_QT ${LMMS_MSVC_YEAR})
+
+ if(LMMS_MSVC_YEAR_FOR_QT EQUAL 2019)
+ SET(LMMS_MSVC_YEAR_FOR_QT 2017) # Qt only provides binaries for MSVC 2017, but 2019 is binary compatible
+ endif()
+
GET_FILENAME_COMPONENT(QT_BIN_DIR ${QT_QMAKE_EXECUTABLE} DIRECTORY)
- SET(QT_32_PREFIX "${QT_BIN_DIR}/../../msvc${MSVC_YEAR}")
+ SET(QT_32_PREFIX "${QT_BIN_DIR}/../../msvc${LMMS_MSVC_YEAR_FOR_QT}")
ENDIF()
#TODO: qt5 installed using vcpkg: I don't know how to detect if the user built the x86 version of qt5 from here. At least not cleanly.
@@ -38,7 +36,8 @@ ELSEIF(LMMS_BUILD_WIN64 AND MSVC)
ExternalProject_Add(RemoteVstPlugin32
"${EXTERNALPROJECT_ARGS}"
- CMAKE_GENERATOR "${CMAKE_GENERATOR_32}"
+ CMAKE_GENERATOR "${LMMS_MSVC_GENERATOR}"
+ CMAKE_GENERATOR_PLATFORM Win32
#CMAKE_GENERATOR_TOOLSET "${CMAKE_GENERATOR_TOOLSET}"
CMAKE_ARGS
"${EXTERNALPROJECT_CMAKE_ARGS}"
@@ -46,16 +45,7 @@ ELSEIF(LMMS_BUILD_WIN64 AND MSVC)
"-DCMAKE_PREFIX_PATH=${QT_32_PREFIX}"
)
- INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../32/RemoteVstPlugin32.exe" DESTINATION "${PLUGIN_DIR}/32")
-
- #TODO: find a solution when not using vcpkg for qt
- SET(VCPKG_ROOT_32 "${CMAKE_FIND_ROOT_PATH}/../x86-windows")
-
- INSTALL(FILES "${VCPKG_ROOT_32}/bin/zlib1.dll" DESTINATION "${PLUGIN_DIR}/32")
- INSTALL(FILES "${VCPKG_ROOT_32}/bin/pcre2-16.dll" DESTINATION "${PLUGIN_DIR}/32")
- INSTALL(FILES "${VCPKG_ROOT_32}/bin/double-conversion.dll" DESTINATION "${PLUGIN_DIR}/32")
- INSTALL(FILES "${VCPKG_ROOT_32}/bin/qt5core.dll" DESTINATION "${PLUGIN_DIR}/32")
-
+ INSTALL_EXTERNAL_PROJECT(RemoteVstPlugin32)
ELSEIF(LMMS_BUILD_LINUX)
# Use winegcc
INCLUDE(CheckWineGcc)
@@ -82,9 +72,7 @@ ELSEIF(CMAKE_TOOLCHAIN_FILE_32)
"-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH_32}"
"-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE_32}"
)
- INSTALL(FILES "${CMAKE_PREFIX_PATH_32}/bin/Qt5Core.dll" DESTINATION "${PLUGIN_DIR}/32")
- INSTALL(FILES "${CMAKE_PREFIX_PATH_32}/bin/zlib1.dll" DESTINATION "${PLUGIN_DIR}/32")
- INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../32/RemoteVstPlugin32.exe" DESTINATION "${PLUGIN_DIR}/32")
+ INSTALL_EXTERNAL_PROJECT(RemoteVstPlugin32)
ELSE()
MESSAGE(WARNING "Can't build RemoteVstPlugin32, unknown environment. Please supply CMAKE_TOOLCHAIN_FILE_32 and optionally CMAKE_PREFIX_PATH_32")
RETURN()
diff --git a/plugins/vst_base/RemoteVstPlugin64.cmake b/plugins/vst_base/RemoteVstPlugin64.cmake
index 4b02bf8ab..65b33a162 100644
--- a/plugins/vst_base/RemoteVstPlugin64.cmake
+++ b/plugins/vst_base/RemoteVstPlugin64.cmake
@@ -1,6 +1,5 @@
IF(LMMS_BUILD_WIN64)
ADD_SUBDIRECTORY(RemoteVstPlugin)
- INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../RemoteVstPlugin64.exe" DESTINATION "${PLUGIN_DIR}")
ELSEIF(LMMS_BUILD_LINUX)
INCLUDE(CheckWineGcc)
CheckWineGcc(64 "${WINEGCC}" WINEGCC_WORKING)
diff --git a/plugins/vst_base/VstPlugin.h b/plugins/vst_base/VstPlugin.h
index 5b459d40d..26e7fec36 100644
--- a/plugins/vst_base/VstPlugin.h
+++ b/plugins/vst_base/VstPlugin.h
@@ -49,7 +49,7 @@ public:
void tryLoad( const QString &remoteVstPluginExecutable );
- virtual bool processMessage( const message & _m );
+ bool processMessage( const message & _m ) override;
inline bool hasEditor() const
{
@@ -99,17 +99,17 @@ public:
QWidget * pluginWidget();
- virtual void loadSettings( const QDomElement & _this );
- virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
+ void loadSettings( const QDomElement & _this ) override;
+ void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
- inline virtual QString nodeName() const
+ virtual QString nodeName() const override
{
return "vstplugin";
}
virtual void createUI(QWidget *parent);
- bool eventFilter(QObject *obj, QEvent *event);
+ bool eventFilter(QObject *obj, QEvent *event) override;
QString embedMethod() const;
diff --git a/plugins/zynaddsubfx/CMakeLists.txt b/plugins/zynaddsubfx/CMakeLists.txt
index f1d37fa3e..f9cc4efd3 100644
--- a/plugins/zynaddsubfx/CMakeLists.txt
+++ b/plugins/zynaddsubfx/CMakeLists.txt
@@ -3,7 +3,7 @@ INCLUDE(BuildPlugin)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# definitions for ZynAddSubFX
-IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD)
+IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD OR LMMS_BUILD_FREEBSD)
FIND_PACKAGE(X11)
INCLUDE_DIRECTORIES(${X11_INCLUDE_DIR})
ADD_DEFINITIONS(-DOS_LINUX)
@@ -162,6 +162,8 @@ SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
ADD_EXECUTABLE(RemoteZynAddSubFx RemoteZynAddSubFx.cpp "${WINRC}")
INSTALL(TARGETS RemoteZynAddSubFx RUNTIME DESTINATION "${PLUGIN_DIR}")
+# Needed to deploy dependencies of RemoteZynAddSubFx
+SET_PROPERTY(GLOBAL APPEND PROPERTY PLUGINS_BUILT "RemoteZynAddSubFx")
IF(LMMS_BUILD_WIN32)
SET_TARGET_PROPERTIES(RemoteZynAddSubFx PROPERTIES LINK_FLAGS "${LINK_FLAGS} -mwindows")
diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt
index 473e7702f..bdc4a4d86 100644
--- a/src/3rdparty/CMakeLists.txt
+++ b/src/3rdparty/CMakeLists.txt
@@ -10,3 +10,22 @@ ENDIF()
ADD_SUBDIRECTORY(rpmalloc)
ADD_SUBDIRECTORY(weakjack)
+
+# The lockless ring buffer library is compiled as part of the core
+SET(RINGBUFFER_DIR "${CMAKE_SOURCE_DIR}/src/3rdparty/ringbuffer/")
+SET(RINGBUFFER_DIR ${RINGBUFFER_DIR} PARENT_SCOPE)
+# Create a dummy ringbuffer_export.h, since ringbuffer is not compiled as a library
+FILE(WRITE ${CMAKE_BINARY_DIR}/src/ringbuffer_export.h
+ "#include \"${CMAKE_BINARY_DIR}/src/lmms_export.h\"\n
+ #define RINGBUFFER_EXPORT LMMS_EXPORT")
+# Enable MLOCK support for ringbuffer if available
+INCLUDE(CheckIncludeFiles)
+CHECK_INCLUDE_FILES(sys/mman.h HAVE_SYS_MMAN)
+IF(HAVE_SYS_MMAN)
+ SET(USE_MLOCK ON)
+ELSE()
+ SET(USE_MLOCK OFF)
+ENDIF()
+# Generate ringbuffer configuration headers
+CONFIGURE_FILE(${RINGBUFFER_DIR}/src/ringbuffer-config.h.in ${CMAKE_BINARY_DIR}/src/ringbuffer-config.h)
+CONFIGURE_FILE(${RINGBUFFER_DIR}/src/ringbuffer-version.h.in ${CMAKE_BINARY_DIR}/src/ringbuffer-version.h)
diff --git a/src/3rdparty/ringbuffer b/src/3rdparty/ringbuffer
new file mode 160000
index 000000000..82ed7cfb9
--- /dev/null
+++ b/src/3rdparty/ringbuffer
@@ -0,0 +1 @@
+Subproject commit 82ed7cfb9ad40467421d8b14ca1af0350e92613c
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4ac6bf133..59710926d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -27,6 +27,7 @@ INCLUDE_DIRECTORIES(
"${CMAKE_BINARY_DIR}/include"
"${CMAKE_SOURCE_DIR}"
"${CMAKE_SOURCE_DIR}/include"
+ "${RINGBUFFER_DIR}/include"
)
IF(WIN32 AND MSVC)
@@ -89,6 +90,8 @@ IF(NOT ("${LAME_INCLUDE_DIRS}" STREQUAL ""))
INCLUDE_DIRECTORIES("${LAME_INCLUDE_DIRS}")
ENDIF()
+LIST(APPEND LMMS_SRCS "${RINGBUFFER_DIR}/src/lib/ringbuffer.cpp")
+
# Use libraries in non-standard directories (e.g., another version of Qt)
IF(LMMS_BUILD_LINUX)
LINK_LIBRARIES(-Wl,--enable-new-dtags)
@@ -186,210 +189,30 @@ FOREACH(LIB ${LMMS_REQUIRED_LIBS})
ENDIF()
ENDFOREACH()
-
-# Install
-IF(NOT MSVC)
- IF(LMMS_BUILD_WIN32)
- SET_TARGET_PROPERTIES(lmms PROPERTIES
- LINK_FLAGS "${LINK_FLAGS} -mwindows"
- ENABLE_EXPORTS ON
+IF(LMMS_BUILD_WIN32)
+ SET_TARGET_PROPERTIES(lmms PROPERTIES
+ ENABLE_EXPORTS ON
+ )
+ IF(LMMS_BUILD_MSYS)
+ # ENABLE_EXPORTS property has no effect in some MSYS2 configurations.
+ # Add the linker flag manually to create liblmms.dll.a import library
+ SET_PROPERTY(TARGET lmms
+ APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--out-implib,liblmms.dll.a"
)
+ ENDIF()
+ELSE()
+ IF(NOT LMMS_BUILD_APPLE)
+ SET_TARGET_PROPERTIES(lmms PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Wl,-E")
+ ENDIF(NOT LMMS_BUILD_APPLE)
- IF(LMMS_BUILD_MSYS)
- # ENABLE_EXPORTS property has no effect in some MSYS2 configurations.
- # Add the linker flag manually to create liblmms.dll.a import library
- SET_PROPERTY(TARGET lmms
- APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--out-implib,liblmms.dll.a"
- )
- ENDIF()
+ if(CMAKE_INSTALL_MANDIR)
+ SET(INSTALL_MANDIR ${CMAKE_INSTALL_MANDIR})
+ ELSE(CMAKE_INSTALL_MANDIR)
+ SET(INSTALL_MANDIR ${CMAKE_INSTALL_PREFIX}/share/man)
+ ENDIF(CMAKE_INSTALL_MANDIR)
+ INSTALL(FILES "${CMAKE_BINARY_DIR}/lmms.1.gz"
+ DESTINATION "${INSTALL_MANDIR}/man1/"
+ PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
+ENDIF()
- IF(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
- ADD_CUSTOM_COMMAND(TARGET lmms POST_BUILD COMMAND "${STRIP}" "$")
- ENDIF()
-
- INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}")
- INSTALL(FILES
- "${MINGW_PREFIX}/bin/Qt5Core.dll"
- "${MINGW_PREFIX}/bin/Qt5Gui.dll"
- "${MINGW_PREFIX}/bin/Qt5Widgets.dll"
- "${MINGW_PREFIX}/bin/Qt5Xml.dll"
- DESTINATION .)
- INSTALL(FILES
- "${MINGW_PREFIX}/lib/qt5/plugins/platforms/qwindows.dll"
- DESTINATION ./platforms)
- INSTALL(FILES
- "${MINGW_PREFIX}/bin/libsamplerate-0.dll"
- "${MINGW_PREFIX}/bin/libsndfile-1.dll"
- "${MINGW_PREFIX}/bin/libvorbis-0.dll"
- "${MINGW_PREFIX}/bin/libvorbisenc-2.dll"
- "${MINGW_PREFIX}/bin/libvorbisfile-3.dll"
- "${MINGW_PREFIX}/bin/libjpeg-9.dll"
- "${MINGW_PREFIX}/bin/libogg-0.dll"
- "${MINGW_PREFIX}/bin/libmp3lame-0.dll"
- "${MINGW_PREFIX}/bin/libfftw3f-3.dll"
- "${MINGW_PREFIX}/bin/libFLAC-8.dll"
- "${MINGW_PREFIX}/bin/libpng16-16.dll"
- "${MINGW_PREFIX}/bin/SDL.dll"
- "${MINGW_PREFIX}/bin/libglib-2.0-0.dll"
- "${MINGW_PREFIX}/bin/libgthread-2.0-0.dll"
- "${MINGW_PREFIX}/bin/zlib1.dll"
- "${MINGW_PREFIX}/${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32/bin/libwinpthread-1.dll"
- DESTINATION .)
- IF(LMMS_BUILD_MSYS)
- INSTALL(FILES
- "${MINGW_PREFIX}/bin/libwinpthread-1.dll"
- "${MINGW_PREFIX}/bin/libgcc_s_seh-1.dll"
- "${MINGW_PREFIX}/bin/libstdc++-6.dll"
- DESTINATION .)
- ELSE()
- INSTALL(FILES
- "${MINGW_PREFIX}/${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32/bin/libwinpthread-1.dll"
- DESTINATION .)
- ENDIF()
- IF(FLTK_FOUND)
- INSTALL(FILES
- "${MINGW_PREFIX}/bin/libfltk.dll"
- DESTINATION .)
- ENDIF()
- IF(FLUIDSYNTH_FOUND)
- INSTALL(FILES
- "${MINGW_PREFIX}/bin/libfluidsynth.dll"
- DESTINATION .)
- ENDIF()
- IF(GIG_FOUND)
- # Handle libgig-*.dll
- FILE(GLOB GIG_LIBRARY "${MINGW_PREFIX}/bin/libgig-*.dll")
- INSTALL(FILES
- ${GIG_LIBRARY}
- DESTINATION .)
- ENDIF()
- IF(PORTAUDIO_FOUND)
- INSTALL(FILES
- "${MINGW_PREFIX}/bin/libportaudio-2.dll"
- DESTINATION .)
- ENDIF()
- IF(SOUNDIO_FOUND)
- INSTALL(FILES
- "${MINGW_PREFIX}/lib/libsoundio.dll"
- DESTINATION .)
- ENDIF()
-
- ELSE(LMMS_BUILD_WIN32)
- IF(NOT LMMS_BUILD_APPLE)
- SET_TARGET_PROPERTIES(lmms PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Wl,-E")
- ENDIF(NOT LMMS_BUILD_APPLE)
-
- INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}")
- INSTALL(FILES "${CMAKE_BINARY_DIR}/lmms.1.gz" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1/" PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
-
- ENDIF(LMMS_BUILD_WIN32)
-ELSE(NOT MSVC)
- SET_TARGET_PROPERTIES(lmms PROPERTIES
- ENABLE_EXPORTS ON
- )
- INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}")
-
- SET_TARGET_PROPERTIES(lmms PROPERTIES
- LINK_FLAGS "${LINK_FLAGS} -mwindows"
- ENABLE_EXPORTS ON
- )
-
- #CMAKE_FIND_ROOT_PATH
- SET(VCPKG_ROOT ${CMAKE_FIND_ROOT_PATH})
-
- INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}")
-
- INSTALL(FILES
- "${VCPKG_ROOT}/bin/Qt5Core.dll"
- "${VCPKG_ROOT}/bin/Qt5Gui.dll"
- "${VCPKG_ROOT}/bin/Qt5Widgets.dll"
- "${VCPKG_ROOT}/bin/Qt5Xml.dll"
-
- "${VCPKG_ROOT}/bin/zlib1.dll"
- "${VCPKG_ROOT}/bin/jpeg62.dll"
- "${VCPKG_ROOT}/bin/libpng16.dll"
- "${VCPKG_ROOT}/bin/gthread-2.dll"
- "${VCPKG_ROOT}/bin/glib-2.dll"
- "${VCPKG_ROOT}/bin/harfbuzz.dll"
- "${VCPKG_ROOT}/bin/pcre2-16.dll"
- "${VCPKG_ROOT}/bin/double-conversion.dll"
- "${VCPKG_ROOT}/bin/freetype.dll"
- "${VCPKG_ROOT}/bin/libbz2.dll"
- "${VCPKG_ROOT}/bin/pcre.dll"
- "${VCPKG_ROOT}/bin/libiconv.dll"
- "${VCPKG_ROOT}/bin/libcharset.dll"
- "${VCPKG_ROOT}/bin/libintl.dll"
- DESTINATION .)
-
- INSTALL(FILES
- "${VCPKG_ROOT}/plugins/platforms/qwindows.dll"
- DESTINATION ./platforms)
-
- INSTALL(FILES
- "${VCPKG_ROOT}/bin/libsndfile-1.dll"
- "${VCPKG_ROOT}/bin/ogg.dll"
- "${VCPKG_ROOT}/bin/vorbis.dll"
- "${VCPKG_ROOT}/bin/vorbisenc.dll"
- "${VCPKG_ROOT}/bin/FLAC.dll"
- "${VCPKG_ROOT}/bin/vorbisfile.dll"
-
- "${VCPKG_ROOT}/bin/libsamplerate-0.dll"
- "${VCPKG_ROOT}/bin/SDL2.dll"
- "${VCPKG_ROOT}/bin/fftw3f.dll"
- DESTINATION .)
-
- #not yet in vcpkg
- #IF(LAME_FOUND)
- # INSTALL(FILES
- # "${VCPKG_ROOT}/bin/libmp3lame-0.dll"
- # DESTINATION .)
- #ENDIF(LAME_FOUND)
-
- IF(FLTK_FOUND)
- INSTALL(FILES
- "${VCPKG_ROOT}/bin/libfltk_SHARED.dll"
-
- "${VCPKG_ROOT}/bin/zlib1.dll"
- "${VCPKG_ROOT}/bin/jpeg62.dll"
- DESTINATION .)
- ENDIF()
-
- IF(FLUIDSYNTH_FOUND)
- INSTALL(FILES
- "${VCPKG_ROOT}/bin/libfluidsynth-1.dll"
- "${VCPKG_ROOT}/bin/glib-2.dll"
- "${VCPKG_ROOT}/bin/pcre.dll"
- "${VCPKG_ROOT}/bin/libiconv.dll"
- "${VCPKG_ROOT}/bin/libcharset.dll"
- "${VCPKG_ROOT}/bin/libintl.dll"
- DESTINATION .)
- ENDIF()
-
- #not yet included in vcpkg
- #IF(GIG_FOUND)
- # # Handle libgig-*.dll
- # FILE(GLOB GIG_LIBRARY "${VCPKG_ROOT}/bin/libgig-*.dll")
- # INSTALL(FILES
- # ${GIG_LIBRARY}
- # DESTINATION .)
- #ENDIF()
-
- IF(PORTAUDIO_FOUND)
- IF(LMMS_BUILD_WIN64)
- INSTALL(FILES
- "${VCPKG_ROOT}/bin/portaudio-x64.dll"
- DESTINATION .)
- ELSE(LMMS_BUILD_WIN64)
- INSTALL(FILES
- "${VCPKG_ROOT}/bin/portaudio-x86.dll"
- DESTINATION .)
- ENDIF(LMMS_BUILD_WIN64)
- ENDIF()
-
- #not yet in vcpkg
- #IF(SOUNDIO_FOUND)
- # INSTALL(FILES
- # "${VCPKG_ROOT}/bin/libsoundio.dll"
- # DESTINATION .)
- #ENDIF()
-ENDIF(NOT MSVC)
+INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}")
diff --git a/src/core/AutomationPattern.cpp b/src/core/AutomationPattern.cpp
index e36838d80..b38c704ef 100644
--- a/src/core/AutomationPattern.cpp
+++ b/src/core/AutomationPattern.cpp
@@ -180,7 +180,7 @@ MidiTime AutomationPattern::timeMapLength() const
{
if( m_timeMap.isEmpty() ) return 0;
timeMap::const_iterator it = m_timeMap.end();
- return MidiTime( MidiTime( (it-1).key() ).nextFullTact(), 0 );
+ return MidiTime( MidiTime( (it-1).key() ).nextFullBar(), 0 );
}
diff --git a/src/core/BBTrackContainer.cpp b/src/core/BBTrackContainer.cpp
index e349c7b02..ac4b6cb1a 100644
--- a/src/core/BBTrackContainer.cpp
+++ b/src/core/BBTrackContainer.cpp
@@ -62,7 +62,7 @@ bool BBTrackContainer::play( MidiTime _start, fpp_t _frames,
return false;
}
- _start = _start % ( lengthOfBB( _tco_num ) * MidiTime::ticksPerTact() );
+ _start = _start % ( lengthOfBB( _tco_num ) * MidiTime::ticksPerBar() );
TrackList tl = tracks();
for( TrackList::iterator it = tl.begin(); it != tl.end(); ++it )
@@ -90,9 +90,9 @@ void BBTrackContainer::updateAfterTrackAdd()
-tact_t BBTrackContainer::lengthOfBB( int _bb ) const
+bar_t BBTrackContainer::lengthOfBB( int _bb ) const
{
- MidiTime max_length = MidiTime::ticksPerTact();
+ MidiTime max_length = MidiTime::ticksPerBar();
const TrackList & tl = tracks();
for (Track* t : tl)
@@ -104,7 +104,7 @@ tact_t BBTrackContainer::lengthOfBB( int _bb ) const
}
}
- return max_length.nextFullTact();
+ return max_length.nextFullBar();
}
@@ -124,7 +124,7 @@ void BBTrackContainer::removeBB( int _bb )
for( TrackList::iterator it = tl.begin(); it != tl.end(); ++it )
{
delete ( *it )->getTCO( _bb );
- ( *it )->removeTact( _bb * DefaultTicksPerTact );
+ ( *it )->removeBar( _bb * DefaultTicksPerBar );
}
if( _bb <= currentBB() )
{
@@ -151,7 +151,7 @@ void BBTrackContainer::swapBB( int _bb1, int _bb2 )
void BBTrackContainer::updateBBTrack( TrackContentObject * _tco )
{
BBTrack * t = BBTrack::findBBTrack( _tco->startPosition() /
- DefaultTicksPerTact );
+ DefaultTicksPerBar );
if( t != NULL )
{
t->dataChanged();
@@ -247,16 +247,13 @@ AutomatedValueMap BBTrackContainer::automatedValuesAt(MidiTime time, int tcoNum)
Q_ASSERT(tcoNum >= 0);
Q_ASSERT(time.getTicks() >= 0);
- auto length_tacts = lengthOfBB(tcoNum);
- auto length_ticks = length_tacts * MidiTime::ticksPerTact();
- if (time > length_ticks) {
+ auto length_bars = lengthOfBB(tcoNum);
+ auto length_ticks = length_bars * MidiTime::ticksPerBar();
+ if (time > length_ticks)
+ {
time = length_ticks;
}
- return TrackContainer::automatedValuesAt(time + (MidiTime::ticksPerTact() * tcoNum), tcoNum);
+ return TrackContainer::automatedValuesAt(time + (MidiTime::ticksPerBar() * tcoNum), tcoNum);
}
-
-
-
-
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index ba41e089c..a50b32a0f 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,5 +1,6 @@
set(LMMS_SRCS
${LMMS_SRCS}
+
core/AutomatableModel.cpp
core/AutomationPattern.cpp
core/BandLimitedWave.cpp
diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp
index d8c783dd2..b8e8cd4ae 100644
--- a/src/core/ConfigManager.cpp
+++ b/src/core/ConfigManager.cpp
@@ -22,6 +22,7 @@
*
*/
+
#include
#include
#include
@@ -36,9 +37,10 @@
#include "lmmsversion.h"
-static inline QString ensureTrailingSlash( const QString & s )
+
+static inline QString ensureTrailingSlash(const QString & s )
{
- if( ! s.isEmpty() && !s.endsWith('/') && !s.endsWith('\\') )
+ if(! s.isEmpty() && !s.endsWith('/') && !s.endsWith('\\'))
{
return s + '/';
}
@@ -50,14 +52,14 @@ ConfigManager * ConfigManager::s_instanceOfMe = NULL;
ConfigManager::ConfigManager() :
- m_lmmsRcFile( QDir::home().absolutePath() +"/.lmmsrc.xml" ),
- m_workingDir( QStandardPaths::writableLocation( QStandardPaths::DocumentsLocation ) + "/lmms/"),
- m_dataDir( "data:/" ),
- m_artworkDir( defaultArtworkDir() ),
- m_vstDir( m_workingDir + "vst/" ),
- m_gigDir( m_workingDir + GIG_PATH ),
- m_sf2Dir( m_workingDir + SF2_PATH ),
- m_version( defaultVersion() )
+ m_workingDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/lmms/"),
+ m_dataDir("data:/"),
+ m_vstDir(m_workingDir + "vst/"),
+ m_sf2Dir(m_workingDir + SF2_PATH),
+ m_gigDir(m_workingDir + GIG_PATH),
+ m_themeDir(defaultThemeDir()),
+ m_lmmsRcFile(QDir::home().absolutePath() +"/.lmmsrc.xml"),
+ m_version(defaultVersion())
{
// Detect < 1.2.0 working directory as a courtesy
if ( QFileInfo( QDir::home().absolutePath() + "/lmms/projects/" ).exists() )
@@ -125,19 +127,19 @@ ConfigManager::~ConfigManager()
void ConfigManager::upgrade_1_1_90()
{
// Remove trailing " (bad latency!)" string which was once saved with PulseAudio
- if( value( "mixer", "audiodev" ).startsWith( "PulseAudio (" ) )
+ if(value("mixer", "audiodev").startsWith("PulseAudio ("))
{
setValue("mixer", "audiodev", "PulseAudio");
}
// MidiAlsaRaw used to store the device info as "Device" instead of "device"
- if ( value( "MidiAlsaRaw", "device" ).isNull() )
+ if (value("MidiAlsaRaw", "device").isNull())
{
// copy "device" = "Device" and then delete the old "Device" (further down)
- QString oldDevice = value( "MidiAlsaRaw", "Device" );
+ QString oldDevice = value("MidiAlsaRaw", "Device");
setValue("MidiAlsaRaw", "device", oldDevice);
}
- if ( !value( "MidiAlsaRaw", "device" ).isNull() )
+ if (!value("MidiAlsaRaw", "device").isNull())
{
// delete the old "Device" in the case that we just copied it to "device"
// or if the user somehow set both the "Device" and "device" fields
@@ -149,9 +151,9 @@ void ConfigManager::upgrade_1_1_90()
void ConfigManager::upgrade_1_1_91()
{
// rename displaydbv to displaydbfs
- if ( !value( "app", "displaydbv" ).isNull() ) {
- setValue( "app", "displaydbfs", value( "app", "displaydbv" ) );
- deleteValue( "app", "displaydbv" );
+ if (!value("app", "displaydbv").isNull()) {
+ setValue("app", "displaydbfs", value("app", "displaydbv"));
+ deleteValue("app", "displaydbv");
}
}
@@ -159,27 +161,27 @@ void ConfigManager::upgrade_1_1_91()
void ConfigManager::upgrade()
{
// Skip the upgrade if versions match
- if ( m_version == LMMS_VERSION )
+ if (m_version == LMMS_VERSION)
{
return;
}
ProjectVersion createdWith = m_version;
- if ( createdWith.setCompareType(ProjectVersion::Build) < "1.1.90" )
+ if (createdWith.setCompareType(ProjectVersion::Build) < "1.1.90")
{
upgrade_1_1_90();
}
- if ( createdWith.setCompareType(ProjectVersion::Build) < "1.1.91" )
+ if (createdWith.setCompareType(ProjectVersion::Build) < "1.1.91")
{
upgrade_1_1_91();
}
// Don't use old themes as they break the UI (i.e. 0.4 != 1.0, etc)
- if ( createdWith.setCompareType(ProjectVersion::Minor) != LMMS_VERSION )
+ if (createdWith.setCompareType(ProjectVersion::Minor) != LMMS_VERSION)
{
- m_artworkDir = defaultArtworkDir();
+ m_themeDir = defaultThemeDir();
}
// Bump the version, now that we are upgraded
@@ -221,107 +223,115 @@ QString ConfigManager::vstEmbedMethod() const
bool ConfigManager::hasWorkingDir() const
{
- return QDir( m_workingDir ).exists();
+ return QDir(m_workingDir).exists();
}
-void ConfigManager::setWorkingDir( const QString & wd )
+void ConfigManager::setWorkingDir(const QString & workingDir)
{
- m_workingDir = ensureTrailingSlash( QDir::cleanPath( wd ) );
+ m_workingDir = ensureTrailingSlash(QDir::cleanPath(workingDir));
}
-void ConfigManager::setVSTDir( const QString & _vd )
+void ConfigManager::setVSTDir(const QString & vstDir)
{
- m_vstDir = ensureTrailingSlash( _vd );
+ m_vstDir = ensureTrailingSlash(vstDir);
}
-void ConfigManager::setArtworkDir( const QString & _ad )
+void ConfigManager::setLADSPADir(const QString & ladspaDir)
{
- m_artworkDir = ensureTrailingSlash( _ad );
+ m_ladspaDir = ladspaDir;
}
-void ConfigManager::setLADSPADir( const QString & _fd )
-{
- m_ladDir = _fd;
-}
-
-
-
-
-void ConfigManager::setSTKDir( const QString & _fd )
+void ConfigManager::setSTKDir(const QString & stkDir)
{
#ifdef LMMS_HAVE_STK
- m_stkDir = ensureTrailingSlash( _fd );
+ m_stkDir = ensureTrailingSlash(stkDir);
#endif
}
-void ConfigManager::setDefaultSoundfont( const QString & _sf )
+void ConfigManager::setSF2Dir(const QString & sf2Dir)
+{
+ m_sf2Dir = sf2Dir;
+}
+
+
+
+
+void ConfigManager::setSF2File(const QString & sf2File)
{
#ifdef LMMS_HAVE_FLUIDSYNTH
- m_defaultSoundfont = _sf;
+ m_sf2File = sf2File;
#endif
}
-void ConfigManager::setBackgroundArtwork( const QString & _ba )
+void ConfigManager::setGIGDir(const QString & gigDir)
{
- m_backgroundArtwork = _ba;
+ m_gigDir = gigDir;
}
-void ConfigManager::setGIGDir(const QString &gd)
+
+
+
+void ConfigManager::setThemeDir(const QString & themeDir)
{
- m_gigDir = gd;
+ m_themeDir = ensureTrailingSlash(themeDir);
}
-void ConfigManager::setSF2Dir(const QString &sfd)
+
+
+
+void ConfigManager::setBackgroundPicFile(const QString & backgroundPicFile)
{
- m_sf2Dir = sfd;
+ m_backgroundPicFile = backgroundPicFile;
}
+
+
void ConfigManager::createWorkingDir()
{
- QDir().mkpath( m_workingDir );
+ QDir().mkpath(m_workingDir);
- QDir().mkpath( userProjectsDir() );
- QDir().mkpath( userTemplateDir() );
- QDir().mkpath( userSamplesDir() );
- QDir().mkpath( userPresetsDir() );
- QDir().mkpath( userGigDir() );
- QDir().mkpath( userSf2Dir() );
- QDir().mkpath( userVstDir() );
- QDir().mkpath( userLadspaDir() );
+ QDir().mkpath(userProjectsDir());
+ QDir().mkpath(userTemplateDir());
+ QDir().mkpath(userSamplesDir());
+ QDir().mkpath(userPresetsDir());
+ QDir().mkpath(userGigDir());
+ QDir().mkpath(userSf2Dir());
+ QDir().mkpath(userVstDir());
+ QDir().mkpath(userLadspaDir());
}
-void ConfigManager::addRecentlyOpenedProject( const QString & file )
+void ConfigManager::addRecentlyOpenedProject(const QString & file)
{
- QFileInfo recentFile( file );
- if( recentFile.suffix().toLower() == "mmp" ||
+ QFileInfo recentFile(file);
+ if(recentFile.suffix().toLower() == "mmp" ||
recentFile.suffix().toLower() == "mmpz" ||
- recentFile.suffix().toLower() == "mpt" )
+ recentFile.suffix().toLower() == "mpt")
{
- m_recentlyOpenedProjects.removeAll( file );
- if( m_recentlyOpenedProjects.size() > 50 )
+ m_recentlyOpenedProjects.removeAll(file);
+ if(m_recentlyOpenedProjects.size() > 50)
{
m_recentlyOpenedProjects.removeLast();
}
- m_recentlyOpenedProjects.push_front( file );
+ m_recentlyOpenedProjects.push_front(file);
ConfigManager::inst()->saveConfigFile();
}
}
@@ -329,18 +339,18 @@ void ConfigManager::addRecentlyOpenedProject( const QString & file )
-const QString & ConfigManager::value( const QString & cls,
- const QString & attribute ) const
+const QString & ConfigManager::value(const QString & cls,
+ const QString & attribute) const
{
- if( m_settings.contains( cls ) )
+ if(m_settings.contains(cls))
{
- for( stringPairVector::const_iterator it =
+ for(stringPairVector::const_iterator it =
m_settings[cls].begin();
- it != m_settings[cls].end(); ++it )
+ it != m_settings[cls].end(); ++it)
{
- if( ( *it ).first == attribute )
+ if((*it).first == attribute)
{
- return ( *it ).second ;
+ return (*it).second ;
}
}
}
@@ -350,49 +360,49 @@ const QString & ConfigManager::value( const QString & cls,
-const QString & ConfigManager::value( const QString & cls,
+const QString & ConfigManager::value(const QString & cls,
const QString & attribute,
- const QString & defaultVal ) const
+ const QString & defaultVal) const
{
- const QString & val = value( cls, attribute );
+ const QString & val = value(cls, attribute);
return val.isEmpty() ? defaultVal : val;
}
-void ConfigManager::setValue( const QString & cls,
+void ConfigManager::setValue(const QString & cls,
const QString & attribute,
- const QString & value )
+ const QString & value)
{
- if( m_settings.contains( cls ) )
+ if(m_settings.contains(cls))
{
- for( QPair& pair : m_settings[cls])
+ for(QPair& pair : m_settings[cls])
{
- if( pair.first == attribute )
+ if(pair.first == attribute)
{
- if ( pair.second != value )
+ if (pair.second != value)
{
pair.second = value;
- emit valueChanged( cls, attribute, value );
+ emit valueChanged(cls, attribute, value);
}
return;
}
}
}
// not in map yet, so we have to add it...
- m_settings[cls].push_back( qMakePair( attribute, value ) );
+ m_settings[cls].push_back(qMakePair(attribute, value));
}
-void ConfigManager::deleteValue( const QString & cls, const QString & attribute)
+void ConfigManager::deleteValue(const QString & cls, const QString & attribute)
{
- if( m_settings.contains( cls ) )
+ if(m_settings.contains(cls))
{
- for( stringPairVector::iterator it = m_settings[cls].begin();
- it != m_settings[cls].end(); ++it )
+ for(stringPairVector::iterator it = m_settings[cls].begin();
+ it != m_settings[cls].end(); ++it)
{
- if( ( *it ).first == attribute )
+ if((*it).first == attribute)
{
m_settings[cls].erase(it);
return;
@@ -402,23 +412,23 @@ void ConfigManager::deleteValue( const QString & cls, const QString & attribute)
}
-void ConfigManager::loadConfigFile( const QString & configFile )
+void ConfigManager::loadConfigFile(const QString & configFile)
{
// read the XML file and create DOM tree
// Allow configuration file override through --config commandline option
- if ( !configFile.isEmpty() )
+ if (!configFile.isEmpty())
{
m_lmmsRcFile = configFile;
}
- QFile cfg_file( m_lmmsRcFile );
+ QFile cfg_file(m_lmmsRcFile);
QDomDocument dom_tree;
- if( cfg_file.open( QIODevice::ReadOnly ) )
+ if(cfg_file.open(QIODevice::ReadOnly))
{
QString errorString;
int errorLine, errorCol;
- if( dom_tree.setContent( &cfg_file, false, &errorString, &errorLine, &errorCol ) )
+ if(dom_tree.setContent(&cfg_file, false, &errorString, &errorLine, &errorCol))
{
// get the head information from the DOM
QDomElement root = dom_tree.documentElement();
@@ -426,41 +436,41 @@ void ConfigManager::loadConfigFile( const QString & configFile )
QDomNode node = root.firstChild();
// Cache the config version for upgrade()
- if ( !root.attribute( "version" ).isNull() ) {
- m_version = root.attribute( "version" );
+ if (!root.attribute("version").isNull()) {
+ m_version = root.attribute("version");
}
// create the settings-map out of the DOM
- while( !node.isNull() )
+ while(!node.isNull())
{
- if( node.isElement() &&
- node.toElement().hasAttributes () )
+ if(node.isElement() &&
+ node.toElement().hasAttributes ())
{
stringPairVector attr;
QDomNamedNodeMap node_attr =
node.toElement().attributes();
- for( int i = 0; i < node_attr.count();
- ++i )
+ for(int i = 0; i < node_attr.count();
+ ++i)
{
- QDomNode n = node_attr.item( i );
- if( n.isAttr() )
+ QDomNode n = node_attr.item(i);
+ if(n.isAttr())
{
- attr.push_back( qMakePair( n.toAttr().name(),
- n.toAttr().value() ) );
+ attr.push_back(qMakePair(n.toAttr().name(),
+ n.toAttr().value()));
}
}
m_settings[node.nodeName()] = attr;
}
- else if( node.nodeName() == "recentfiles" )
+ else if(node.nodeName() == "recentfiles")
{
m_recentlyOpenedProjects.clear();
QDomNode n = node.firstChild();
- while( !n.isNull() )
+ while(!n.isNull())
{
- if( n.isElement() && n.toElement().hasAttributes() )
+ if(n.isElement() && n.toElement().hasAttributes())
{
m_recentlyOpenedProjects <<
- n.toElement().attribute( "path" );
+ n.toElement().attribute("path");
}
n = n.nextSibling();
}
@@ -468,45 +478,45 @@ void ConfigManager::loadConfigFile( const QString & configFile )
node = node.nextSibling();
}
- if( value( "paths", "artwork" ) != "" )
+ if(value("paths", "theme") != "")
{
- m_artworkDir = value( "paths", "artwork" );
+ m_themeDir = value("paths", "theme");
#ifdef LMMS_BUILD_WIN32
// Detect a QDir/QFile hang on Windows
// see issue #3417 on github
- bool badPath = ( m_artworkDir == "/" || m_artworkDir == "\\" );
+ bool badPath = (m_themeDir == "/" || m_themeDir == "\\");
#else
bool badPath = false;
#endif
- if( badPath || !QDir( m_artworkDir ).exists() ||
- !QFile( m_artworkDir + "/style.css" ).exists() )
+ if(badPath || !QDir(m_themeDir).exists() ||
+ !QFile(m_themeDir + "/style.css").exists())
{
- m_artworkDir = defaultArtworkDir();
+ m_themeDir = defaultThemeDir();
}
- m_artworkDir = ensureTrailingSlash(m_artworkDir);
+ m_themeDir = ensureTrailingSlash(m_themeDir);
}
- setWorkingDir( value( "paths", "workingdir" ) );
+ setWorkingDir(value("paths", "workingdir"));
- setGIGDir( value( "paths", "gigdir" ) == "" ? gigDir() : value( "paths", "gigdir" ) );
- setSF2Dir( value( "paths", "sf2dir" ) == "" ? sf2Dir() : value( "paths", "sf2dir" ) );
- setVSTDir( value( "paths", "vstdir" ) );
- setLADSPADir( value( "paths", "laddir" ) );
+ setGIGDir(value("paths", "gigdir") == "" ? gigDir() : value("paths", "gigdir"));
+ setSF2Dir(value("paths", "sf2dir") == "" ? sf2Dir() : value("paths", "sf2dir"));
+ setVSTDir(value("paths", "vstdir"));
+ setLADSPADir(value("paths", "ladspadir"));
#ifdef LMMS_HAVE_STK
- setSTKDir( value( "paths", "stkdir" ) );
+ setSTKDir(value("paths", "stkdir"));
#endif
#ifdef LMMS_HAVE_FLUIDSYNTH
- setDefaultSoundfont( value( "paths", "defaultsf2" ) );
+ setSF2File(value("paths", "defaultsf2"));
#endif
- setBackgroundArtwork( value( "paths", "backgroundartwork" ) );
+ setBackgroundPicFile(value("paths", "backgroundtheme"));
}
- else if( gui )
+ else if(gui)
{
- QMessageBox::warning( NULL, MainWindow::tr( "Configuration file" ),
- MainWindow::tr( "Error while parsing configuration file at line %1:%2: %3" ).
- arg( errorLine ).
- arg( errorCol ).
- arg( errorString ) );
+ QMessageBox::warning(NULL, MainWindow::tr("Configuration file"),
+ MainWindow::tr("Error while parsing configuration file at line %1:%2: %3").
+ arg(errorLine).
+ arg(errorCol).
+ arg(errorString));
}
cfg_file.close();
}
@@ -517,21 +527,21 @@ void ConfigManager::loadConfigFile( const QString & configFile )
!QDir( m_vstDir ).exists() )
{
#ifdef LMMS_BUILD_WIN32
- QString programFiles = QString::fromLocal8Bit( getenv( "ProgramFiles" ) );
+ QString programFiles = QString::fromLocal8Bit(getenv("ProgramFiles"));
m_vstDir = programFiles + "/VstPlugins/";
#else
m_vstDir = m_workingDir + "plugins/vst/";
#endif
}
- if( m_ladDir.isEmpty() )
+ if(m_ladspaDir.isEmpty() )
{
- m_ladDir = userLadspaDir();
+ m_ladspaDir = userLadspaDir();
}
#ifdef LMMS_HAVE_STK
- if( m_stkDir.isEmpty() || m_stkDir == QDir::separator() || m_stkDir == "/" ||
- !QDir( m_stkDir ).exists() )
+ if(m_stkDir.isEmpty() || m_stkDir == QDir::separator() || m_stkDir == "/" ||
+ !QDir(m_stkDir).exists())
{
#if defined(LMMS_BUILD_WIN32)
m_stkDir = m_dataDir + "stk/rawwaves/";
@@ -557,11 +567,11 @@ void ConfigManager::loadConfigFile( const QString & configFile )
QStringList searchPaths;
if(! qgetenv("LMMS_THEME_PATH").isNull())
searchPaths << qgetenv("LMMS_THEME_PATH");
- searchPaths << artworkDir() << defaultArtworkDir();
- QDir::setSearchPaths( "resources", searchPaths);
+ searchPaths << themeDir() << defaultThemeDir();
+ QDir::setSearchPaths("resources", searchPaths);
// Create any missing subdirectories in the working dir, but only if the working dir exists
- if( hasWorkingDir() )
+ if(hasWorkingDir())
{
createWorkingDir();
}
@@ -572,72 +582,72 @@ void ConfigManager::loadConfigFile( const QString & configFile )
void ConfigManager::saveConfigFile()
{
- setValue( "paths", "artwork", m_artworkDir );
- setValue( "paths", "workingdir", m_workingDir );
- setValue( "paths", "vstdir", m_vstDir );
- setValue( "paths", "gigdir", m_gigDir );
- setValue( "paths", "sf2dir", m_sf2Dir );
- setValue( "paths", "laddir", m_ladDir );
+ setValue("paths", "theme", m_themeDir);
+ setValue("paths", "workingdir", m_workingDir);
+ setValue("paths", "vstdir", m_vstDir);
+ setValue("paths", "gigdir", m_gigDir);
+ setValue("paths", "sf2dir", m_sf2Dir);
+ setValue("paths", "ladspadir", m_ladspaDir);
#ifdef LMMS_HAVE_STK
- setValue( "paths", "stkdir", m_stkDir );
+ setValue("paths", "stkdir", m_stkDir);
#endif
#ifdef LMMS_HAVE_FLUIDSYNTH
- setValue( "paths", "defaultsf2", m_defaultSoundfont );
+ setValue("paths", "defaultsf2", m_sf2File);
#endif
- setValue( "paths", "backgroundartwork", m_backgroundArtwork );
+ setValue("paths", "backgroundtheme", m_backgroundPicFile);
- QDomDocument doc( "lmms-config-file" );
+ QDomDocument doc("lmms-config-file");
- QDomElement lmms_config = doc.createElement( "lmms" );
- lmms_config.setAttribute( "version", m_version );
- doc.appendChild( lmms_config );
+ QDomElement lmms_config = doc.createElement("lmms");
+ lmms_config.setAttribute("version", m_version);
+ doc.appendChild(lmms_config);
- for( settingsMap::iterator it = m_settings.begin();
- it != m_settings.end(); ++it )
+ for(settingsMap::iterator it = m_settings.begin();
+ it != m_settings.end(); ++it)
{
- QDomElement n = doc.createElement( it.key() );
- for( stringPairVector::iterator it2 = ( *it ).begin();
- it2 != ( *it ).end(); ++it2 )
+ QDomElement n = doc.createElement(it.key());
+ for(stringPairVector::iterator it2 = (*it).begin();
+ it2 != (*it).end(); ++it2)
{
- n.setAttribute( ( *it2 ).first, ( *it2 ).second );
+ n.setAttribute((*it2).first, (*it2).second);
}
- lmms_config.appendChild( n );
+ lmms_config.appendChild(n);
}
- QDomElement recent_files = doc.createElement( "recentfiles" );
+ QDomElement recent_files = doc.createElement("recentfiles");
- for( QStringList::iterator it = m_recentlyOpenedProjects.begin();
- it != m_recentlyOpenedProjects.end(); ++it )
+ for(QStringList::iterator it = m_recentlyOpenedProjects.begin();
+ it != m_recentlyOpenedProjects.end(); ++it)
{
- QDomElement n = doc.createElement( "file" );
- n.setAttribute( "path", *it );
- recent_files.appendChild( n );
+ QDomElement n = doc.createElement("file");
+ n.setAttribute("path", *it);
+ recent_files.appendChild(n);
}
- lmms_config.appendChild( recent_files );
+ lmms_config.appendChild(recent_files);
- QString xml = "\n" + doc.toString( 2 );
+ QString xml = "\n" + doc.toString(2);
- QFile outfile( m_lmmsRcFile );
- if( !outfile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
+ QFile outfile(m_lmmsRcFile);
+ if(!outfile.open(QIODevice::WriteOnly | QIODevice::Truncate))
{
QString title, message;
- title = MainWindow::tr( "Could not open file" );
- message = MainWindow::tr( "Could not open file %1 "
+ title = MainWindow::tr("Could not open file");
+ message = MainWindow::tr("Could not open file %1 "
"for writing.\nPlease make "
"sure you have write "
"permission to the file and "
"the directory containing the "
"file and try again!"
- ).arg( m_lmmsRcFile );
- if( gui )
+ ).arg(m_lmmsRcFile);
+ if(gui)
{
- QMessageBox::critical( NULL, title, message,
+ QMessageBox::critical(NULL, title, message,
QMessageBox::Ok,
- QMessageBox::NoButton );
+ QMessageBox::NoButton);
}
return;
}
- outfile.write( xml.toUtf8() );
+ outfile.write(xml.toUtf8());
outfile.close();
}
diff --git a/src/core/Engine.cpp b/src/core/Engine.cpp
index d2b4a9cc2..ce82310fa 100644
--- a/src/core/Engine.cpp
+++ b/src/core/Engine.cpp
@@ -105,10 +105,10 @@ void LmmsCore::destroy()
delete ConfigManager::inst();
}
-float LmmsCore::framesPerTick(sample_rate_t sample_rate)
+float LmmsCore::framesPerTick(sample_rate_t sampleRate)
{
- return sample_rate * 60.0f * 4 /
- DefaultTicksPerTact / s_song->getTempo();
+ return sampleRate * 60.0f * 4 /
+ DefaultTicksPerBar / s_song->getTempo();
}
@@ -117,7 +117,7 @@ float LmmsCore::framesPerTick(sample_rate_t sample_rate)
void LmmsCore::updateFramesPerTick()
{
s_framesPerTick = s_mixer->processingSampleRate() * 60.0f * 4 /
- DefaultTicksPerTact / s_song->getTempo();
+ DefaultTicksPerBar / s_song->getTempo();
}
diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp
index 032090bf1..f04435e05 100644
--- a/src/core/FxMixer.cpp
+++ b/src/core/FxMixer.cpp
@@ -336,6 +336,11 @@ void FxMixer::deleteChannel( int index )
deleteChannelSend( ch->m_receives.first() );
}
+ // if m_lastSoloed was our index, reset it
+ if (m_lastSoloed == index) { m_lastSoloed = -1; }
+ // if m_lastSoloed is > delete index, it will move left
+ else if (m_lastSoloed > index) { --m_lastSoloed; }
+
// actually delete the channel
m_fxChannels.remove(index);
delete ch;
@@ -373,6 +378,10 @@ void FxMixer::moveChannelLeft( int index )
// channels to swap
int a = index - 1, b = index;
+ // check if m_lastSoloed is one of our swaps
+ if (m_lastSoloed == a) { m_lastSoloed = b; }
+ else if (m_lastSoloed == b) { m_lastSoloed = a; }
+
// go through every instrument and adjust for the channel index change
QVector