From 7e1df5cec9275e54b2c07b317864fe72c5dfb3bd Mon Sep 17 00:00:00 2001 From: Lukas W Date: Sun, 10 Mar 2019 14:47:05 +0100 Subject: [PATCH 01/81] Add issue templates Add Github issue templates for bug reports and feature requests --- .github/ISSUE_TEMPLATE/bug_report.md | 26 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 14 ++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..3ca71ce76 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,26 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +### Bug Summary + +#### Steps to reproduce + +#### Expected behavior + +#### Actual behavior + +#### Screenshot + +#### Logs +
+ Click to expand +
+# paste here
+
+
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..feacb8fdb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,14 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' + +--- + +### Enhancement Summary + +#### Justification + +#### Mockup From 3ada5b8a126b529c94cbe0c01b60a11ecb08dec8 Mon Sep 17 00:00:00 2001 From: Olivier Humbert Date: Fri, 14 Jun 2019 21:07:14 +0200 Subject: [PATCH 02/81] Update .mailmap (#5037) --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 71b6697c8..896202c5a 100644 --- a/.mailmap +++ b/.mailmap @@ -29,3 +29,4 @@ grejppi Johannes Lorenz Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com> Noah Brecht +Olivier Humbert From bdbea87149ee98e3bbe6bead94c6d5102abdfc50 Mon Sep 17 00:00:00 2001 From: Steffen Baranowsky Date: Fri, 26 Jul 2019 10:04:16 +0200 Subject: [PATCH 03/81] show BBEditor on clicking the TrackLabelButton (#5060) --- src/tracks/BBTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracks/BBTrack.cpp b/src/tracks/BBTrack.cpp index a4217d23d..14b65f336 100644 --- a/src/tracks/BBTrack.cpp +++ b/src/tracks/BBTrack.cpp @@ -664,5 +664,5 @@ bool BBTrackView::close() void BBTrackView::clickedTrackLabel() { Engine::getBBTrackContainer()->setCurrentBB( m_bbTrack->index() ); - gui->getBBEditor()->show(); + gui->getBBEditor()->parentWidget()->show(); } From 0db83c55a0acef82d805abbbf6cd03bd96585797 Mon Sep 17 00:00:00 2001 From: Olivier Humbert Date: Wed, 31 Jul 2019 01:17:55 +0200 Subject: [PATCH 04/81] Better French translations in the menu item file (#4711) in order to stick with the original English meaning --- cmake/linux/lmms.desktop | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/linux/lmms.desktop b/cmake/linux/lmms.desktop index 2ef4c8148..94d171b5e 100644 --- a/cmake/linux/lmms.desktop +++ b/cmake/linux/lmms.desktop @@ -3,10 +3,10 @@ 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 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 Icon=lmms Exec=lmms %f Terminal=false From a631c0c47e73f2e1ae0d91fd2ae1a8ba0428ab7f Mon Sep 17 00:00:00 2001 From: Artur Twardowski <32247490+artur-twardowski@users.noreply.github.com> Date: Mon, 26 Aug 2019 03:05:59 +0200 Subject: [PATCH 05/81] Fix invalid MIDI Program Change decoding (#5154) --- src/core/midi/MidiAlsaSeq.cpp | 10 +++++----- src/core/midi/MidiClient.cpp | 6 +++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/core/midi/MidiAlsaSeq.cpp b/src/core/midi/MidiAlsaSeq.cpp index e420ebc08..56fd956d4 100644 --- a/src/core/midi/MidiAlsaSeq.cpp +++ b/src/core/midi/MidiAlsaSeq.cpp @@ -563,7 +563,7 @@ void MidiAlsaSeq::run() case SND_SEQ_EVENT_CONTROLLER: dest->processInEvent( MidiEvent( - MidiControlChange, + MidiControlChange, ev->data.control.channel, ev->data.control.param, ev->data.control.value, source ), @@ -572,11 +572,11 @@ void MidiAlsaSeq::run() case SND_SEQ_EVENT_PGMCHANGE: dest->processInEvent( MidiEvent( - MidiProgramChange, + MidiProgramChange, ev->data.control.channel, - ev->data.control.param, - ev->data.control.value, source ), - MidiTime() ); + ev->data.control.value, 0, + source ), + MidiTime() ); break; case SND_SEQ_EVENT_CHANPRESS: diff --git a/src/core/midi/MidiClient.cpp b/src/core/midi/MidiClient.cpp index b88c64db1..e22daf235 100644 --- a/src/core/midi/MidiClient.cpp +++ b/src/core/midi/MidiClient.cpp @@ -222,12 +222,16 @@ void MidiClientRaw::parseData( const unsigned char c ) case MidiNoteOff: case MidiNoteOn: case MidiKeyPressure: - case MidiProgramChange: case MidiChannelPressure: m_midiParseData.m_midiEvent.setKey( m_midiParseData.m_buffer[0] - KeysPerOctave ); m_midiParseData.m_midiEvent.setVelocity( m_midiParseData.m_buffer[1] ); break; + case MidiProgramChange: + m_midiParseData.m_midiEvent.setKey( m_midiParseData.m_buffer[0] ); + m_midiParseData.m_midiEvent.setVelocity( m_midiParseData.m_buffer[1] ); + break; + case MidiControlChange: m_midiParseData.m_midiEvent.setControllerNumber( m_midiParseData.m_buffer[0] ); m_midiParseData.m_midiEvent.setControllerValue( m_midiParseData.m_buffer[1] ); From 8568ae4eacdd3bbdae8e8eaeb1536bebce3cfeeb Mon Sep 17 00:00:00 2001 From: Spekular Date: Tue, 27 Aug 2019 15:24:13 +0200 Subject: [PATCH 06/81] Make splash screen text white (#5149) Make splash screen text white Closes #5023 --- data/themes/default/style.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index cd74c349d..a9af1139f 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -81,6 +81,12 @@ TextFloat { } +/* splash screen text */ +QSplashScreen QLabel { + color: white; +} + + QMenu { border-top: 2px solid #08993E; background-color: #15191c; From c2eefe73d049ae92398da288acdc3d71c3592504 Mon Sep 17 00:00:00 2001 From: Lost Robot <34612565+DouglasDGI@users.noreply.github.com> Date: Fri, 30 Aug 2019 16:36:04 -0600 Subject: [PATCH 07/81] Prevent LMMS VisualizationWidget from showing clipping color at exactly 0 db (#5162) --- src/gui/widgets/VisualizationWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/widgets/VisualizationWidget.cpp b/src/gui/widgets/VisualizationWidget.cpp index 7234331df..635f96896 100644 --- a/src/gui/widgets/VisualizationWidget.cpp +++ b/src/gui/widgets/VisualizationWidget.cpp @@ -210,7 +210,7 @@ QColor const & VisualizationWidget::determineLineColor(float level) const { return normalColor(); } - else if( level < 1.0f ) + else if( level <= 1.0f ) { return warningColor(); } From 4fd8e08f3bd02f173e97bb721a30565f17cd1dbc Mon Sep 17 00:00:00 2001 From: Lukas W Date: Wed, 13 Jun 2018 16:32:57 +0200 Subject: [PATCH 08/81] Rewrite CMake dependency installation Replaces the hard-coded library paths by a method based on CMake's GetPrerequisites module which recursively finds a binary file's linked libraries. Advantage: Potentially works on any system without adaption as long as CMake supports it, so it could be used to create portable Linux packages as well. Disadvantage: "Potentially". Co-Authored-By: Hyunjin Song --- CMakeLists.txt | 5 +- cmake/install/CMakeLists.txt | 125 ++++++++++++++ cmake/install/excludelist-win | 23 +++ cmake/modules/BuildPlugin.cmake | 8 +- cmake/modules/InstallDependencies.cmake | 184 ++++++++++++++++++++ cmake/postinstall/CMakeLists.txt | 4 - plugins/zynaddsubfx/CMakeLists.txt | 2 + src/CMakeLists.txt | 220 ++---------------------- 8 files changed, 359 insertions(+), 212 deletions(-) create mode 100644 cmake/install/CMakeLists.txt create mode 100644 cmake/install/excludelist-win create mode 100644 cmake/modules/InstallDependencies.cmake delete mode 100644 cmake/postinstall/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index bd9d376e2..590a20c98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ 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(CheckSubmodules) @@ -565,8 +566,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 diff --git a/cmake/install/CMakeLists.txt b/cmake/install/CMakeLists.txt new file mode 100644 index 000000000..3e37fa00e --- /dev/null +++ b/cmake/install/CMakeLists.txt @@ -0,0 +1,125 @@ + +FUNCTION(GET_COMPILER_SEARCH_DIR VAR) + SET(results "") + IF(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang|AppleClang)") + EXECUTE_PROCESS( + COMMAND ${CMAKE_CXX_COMPILER} --print-search-dirs + OUTPUT_VARIABLE out + ) + STRING(REPLACE "\n" ";" out "${out}") + FOREACH(line ${out}) + IF(line MATCHES "^.+:") + STRING(REPLACE " " ";" line "${line}") + LIST(GET line 1 paths) + # Remove "=" prefix + STRING(REGEX REPLACE "^=" "" paths "${paths}") + STRING(REPLACE ":" ";" paths "${paths}") + FOREACH(path ${paths}) + LIST(APPEND results ${path}) + ENDFOREACH() + ENDIF() + ENDFOREACH() + ENDIF() + + SET(paths "") + FOREACH(result ${results}) + GET_FILENAME_COMPONENT(result ${result} REALPATH) + IF(IS_DIRECTORY "${result}") + LIST(APPEND paths ${result}) + ENDIF() + ENDFOREACH() + LIST(REMOVE_DUPLICATES paths) + + SET(${VAR} ${paths} PARENT_SCOPE) +ENDFUNCTION() + +SET(PLUGIN_FILES "") +IF(LMMS_BUILD_WIN32) + INSTALL(FILES $ DESTINATION platforms) +ENDIF() + +IF(LMMS_BUILD_WIN32 OR LMMS_INSTALL_DEPENDENCIES) + # 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) + + foreach(target lmms ${PLUGINS_BUILT}) + 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 LIB_DIRS ${lib_dir}) + if(lib MATCHES ".(lib|dll.a)$") + if(IS_DIRECTORY ${lib_dir}/../bin) + list(APPEND LIB_DIRS ${lib_dir}/../bin) + endif() + if(IS_DIRECTORY ${lib_dir}/bin) + list(APPEND LIB_DIRS ${lib_dir}/bin) + endif() + endif() + endforeach() + endforeach() + + GET_COMPILER_SEARCH_DIR(COMPILER_SEARCH_DIRS) + LIST(APPEND LIB_DIRS ${COMPILER_SEARCH_DIRS}) + + LIST(REMOVE_DUPLICATES LIB_DIRS) + + # Collect plugin files to inspect + FOREACH(PLUGIN ${PLUGINS_BUILT}) + LIST(APPEND DEPLOY_TARGETS "$") + ENDFOREACH() + # Create the list of files using file(GENERATE) + SET(DEPLOY_LIST_FILE "${CMAKE_CURRENT_BINARY_DIR}/filelist.txt") + FILE(GENERATE OUTPUT "${DEPLOY_LIST_FILE}" CONTENT "${DEPLOY_TARGETS}") + + 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 ${CMAKE_CURRENT_LIST_DIR}/excludelist-win) + IF(CMAKE_CROSSCOMPILING) + SET(additional_args "${additional_args}" GP_TOOL objdump) + ENDIF() + ENDIF() + + 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(CODE " + INCLUDE(\"${CMAKE_SOURCE_DIR}/cmake/modules/InstallDependencies.cmake\") + # Install dependencies of lmms + INSTALL_DEPENDENCIES( + FILES ${BIN_DIR}/lmms${CMAKE_EXECUTABLE_SUFFIX} + DESTINATION ${LMMS_DEP_DESTINATION} + LIB_DIRS ${LIB_DIRS} + ${additional_args} + ) + # Install dependencies of plugins + FILE(READ \"${DEPLOY_LIST_FILE}\" DEPLOY_FILES) + INSTALL_DEPENDENCIES( + FILES \"\${DEPLOY_FILES}\" + DESTINATION \"${PLUGIN_DEP_DESTINATION}\" + LIB_DIRS ${LIB_DIRS} \"${BIN_DIR}\" \"${PLUGIN_DIR}\" + SEARCH_PATHS \"${BIN_DIR}\" \"${PLUGIN_DIR}\" + ${additional_args} + ) + ") +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/modules/BuildPlugin.cmake b/cmake/modules/BuildPlugin.cmake index efa3e5b46..e285e05bb 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") @@ -89,5 +92,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/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/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/plugins/zynaddsubfx/CMakeLists.txt b/plugins/zynaddsubfx/CMakeLists.txt index f1d37fa3e..d6fa9c727 100644 --- a/plugins/zynaddsubfx/CMakeLists.txt +++ b/plugins/zynaddsubfx/CMakeLists.txt @@ -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/CMakeLists.txt b/src/CMakeLists.txt index 4ac6bf133..10ce72ae6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -186,210 +186,20 @@ 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() + INSTALL(FILES "${CMAKE_BINARY_DIR}/lmms.1.gz" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1/" + PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) +ENDIF() - 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(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}") \ No newline at end of file From 8d169fa5290c1b8a8c3e0894060337083a7080ee Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Mon, 26 Nov 2018 12:50:37 +0900 Subject: [PATCH 09/81] CircleCI: create Windows installers --- .circleci/config.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4174ba1ef..99b987f86 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -59,6 +59,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,6 +88,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 linux.gcc: From 7a23ee8ad1b194bc218f3be921ce16b12dcf461a Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Mon, 26 Nov 2018 12:53:34 +0900 Subject: [PATCH 10/81] AppVeyor: create Windows installers --- .appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) 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 From 72bdb23531c22d0f8c6fc22813ece640f3df03e4 Mon Sep 17 00:00:00 2001 From: Shmuel H Date: Wed, 21 Aug 2019 23:27:58 +0300 Subject: [PATCH 11/81] CMake: Provide API for install-time variables with generator expression --- cmake/modules/CreateTempFile.cmake | 18 +++++++++++++++++ cmake/modules/DefineInstallVar.cmake | 30 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 cmake/modules/CreateTempFile.cmake create mode 100644 cmake/modules/DefineInstallVar.cmake diff --git a/cmake/modules/CreateTempFile.cmake b/cmake/modules/CreateTempFile.cmake new file mode 100644 index 000000000..ceefa4928 --- /dev/null +++ b/cmake/modules/CreateTempFile.cmake @@ -0,0 +1,18 @@ +function(CreateTempFilePath) + set(options) + 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}") + + file(GENERATE OUTPUT "${file_name}" + CONTENT "${TEMP_CONTENT}") + + set(${TEMP_OUTPUT_VAR} "${file_name}" PARENT_SCOPE) +endfunction() diff --git a/cmake/modules/DefineInstallVar.cmake b/cmake/modules/DefineInstallVar.cmake new file mode 100644 index 000000000..36f221410 --- /dev/null +++ b/cmake/modules/DefineInstallVar.cmake @@ -0,0 +1,30 @@ +# 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") + if(MSVC) + message(FATAL_ERROR "Installing is not supported with msvc and cmake<3.14") + endif() + + include(CreateTempFile) + CreateTempFilePath(OUTPUT_VAR file_path TAG "${VAR_NAME}" CONTENT "${VAR_CONTENT}") + install(CODE "file(READ \"${file_path}\" \"${VAR_NAME}\")") + else() + if(VAR_GENERATOR_EXPRESSION) + cmake_policy(SET CMP0087 NEW) + endif() + install(CODE "set(\"${VAR_NAME}\" \"${VAR_CONTENT}\")") + endif() +endfunction() From 13da2b957608fd1ae38d59c38280127ddfd007cd Mon Sep 17 00:00:00 2001 From: Shmuel H Date: Mon, 12 Aug 2019 12:17:12 +0300 Subject: [PATCH 12/81] CMake: extract dll installation code into a portable function --- CMakeLists.txt | 2 + cmake/install/CMakeLists.txt | 114 +++--------------- cmake/modules/InstallTargetDependencies.cmake | 89 ++++++++++++++ 3 files changed, 106 insertions(+), 99 deletions(-) create mode 100644 cmake/modules/InstallTargetDependencies.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 590a20c98..36e35bf4c 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) diff --git a/cmake/install/CMakeLists.txt b/cmake/install/CMakeLists.txt index 3e37fa00e..a3a81beeb 100644 --- a/cmake/install/CMakeLists.txt +++ b/cmake/install/CMakeLists.txt @@ -1,95 +1,17 @@ - -FUNCTION(GET_COMPILER_SEARCH_DIR VAR) - SET(results "") - IF(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang|AppleClang)") - EXECUTE_PROCESS( - COMMAND ${CMAKE_CXX_COMPILER} --print-search-dirs - OUTPUT_VARIABLE out - ) - STRING(REPLACE "\n" ";" out "${out}") - FOREACH(line ${out}) - IF(line MATCHES "^.+:") - STRING(REPLACE " " ";" line "${line}") - LIST(GET line 1 paths) - # Remove "=" prefix - STRING(REGEX REPLACE "^=" "" paths "${paths}") - STRING(REPLACE ":" ";" paths "${paths}") - FOREACH(path ${paths}) - LIST(APPEND results ${path}) - ENDFOREACH() - ENDIF() - ENDFOREACH() - ENDIF() - - SET(paths "") - FOREACH(result ${results}) - GET_FILENAME_COMPONENT(result ${result} REALPATH) - IF(IS_DIRECTORY "${result}") - LIST(APPEND paths ${result}) - ENDIF() - ENDFOREACH() - LIST(REMOVE_DUPLICATES paths) - - SET(${VAR} ${paths} PARENT_SCOPE) -ENDFUNCTION() - 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) - foreach(target lmms ${PLUGINS_BUILT}) - 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 LIB_DIRS ${lib_dir}) - if(lib MATCHES ".(lib|dll.a)$") - if(IS_DIRECTORY ${lib_dir}/../bin) - list(APPEND LIB_DIRS ${lib_dir}/../bin) - endif() - if(IS_DIRECTORY ${lib_dir}/bin) - list(APPEND LIB_DIRS ${lib_dir}/bin) - endif() - endif() - endforeach() - endforeach() - - GET_COMPILER_SEARCH_DIR(COMPILER_SEARCH_DIRS) - LIST(APPEND LIB_DIRS ${COMPILER_SEARCH_DIRS}) - - LIST(REMOVE_DUPLICATES LIB_DIRS) - - # Collect plugin files to inspect - FOREACH(PLUGIN ${PLUGINS_BUILT}) - LIST(APPEND DEPLOY_TARGETS "$") - ENDFOREACH() - # Create the list of files using file(GENERATE) - SET(DEPLOY_LIST_FILE "${CMAKE_CURRENT_BINARY_DIR}/filelist.txt") - FILE(GENERATE OUTPUT "${DEPLOY_LIST_FILE}" CONTENT "${DEPLOY_TARGETS}") - - 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 ${CMAKE_CURRENT_LIST_DIR}/excludelist-win) - IF(CMAKE_CROSSCOMPILING) - SET(additional_args "${additional_args}" GP_TOOL objdump) - ENDIF() - ENDIF() - IF(LMMS_BUILD_WIN32) SET(LMMS_DEP_DESTINATION ${BIN_DIR}) SET(PLUGIN_DEP_DESTINATION ${BIN_DIR}) @@ -98,25 +20,19 @@ IF(LMMS_BUILD_WIN32 OR LMMS_INSTALL_DEPENDENCIES) SET(PLUGIN_DEP_DESTINATION ${LIB_DIR}) ENDIF() - INSTALL(CODE " - INCLUDE(\"${CMAKE_SOURCE_DIR}/cmake/modules/InstallDependencies.cmake\") - # Install dependencies of lmms - INSTALL_DEPENDENCIES( - FILES ${BIN_DIR}/lmms${CMAKE_EXECUTABLE_SUFFIX} - DESTINATION ${LMMS_DEP_DESTINATION} - LIB_DIRS ${LIB_DIRS} - ${additional_args} - ) - # Install dependencies of plugins - FILE(READ \"${DEPLOY_LIST_FILE}\" DEPLOY_FILES) - INSTALL_DEPENDENCIES( - FILES \"\${DEPLOY_FILES}\" - DESTINATION \"${PLUGIN_DEP_DESTINATION}\" - LIB_DIRS ${LIB_DIRS} \"${BIN_DIR}\" \"${PLUGIN_DIR}\" - SEARCH_PATHS \"${BIN_DIR}\" \"${PLUGIN_DIR}\" - ${additional_args} - ) - ") + 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) 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() From 84d1091100d60708ba4d3def92c0b9fd17112d74 Mon Sep 17 00:00:00 2001 From: Hussam al-Homsi Date: Thu, 5 Sep 2019 20:32:17 -0400 Subject: [PATCH 13/81] Rewrite the setup dialog (#3820) --- include/ConfigManager.h | 215 +-- include/SetupDialog.h | 218 ++- plugins/MidiImport/MidiImport.cpp | 4 +- plugins/sf2_player/sf2_player.cpp | 2 +- src/core/ConfigManager.cpp | 354 ++--- src/core/audio/AudioJack.cpp | 4 +- src/core/audio/AudioOss.cpp | 4 +- src/core/audio/AudioPortAudio.cpp | 6 +- src/core/audio/AudioPulseAudio.cpp | 4 +- src/core/audio/AudioSdl.cpp | 2 +- src/core/audio/AudioSndio.cpp | 4 +- src/core/audio/AudioSoundIo.cpp | 4 +- src/gui/AudioDeviceSetupWidget.cpp | 6 +- src/gui/GuiApplication.cpp | 4 +- src/gui/MainWindow.cpp | 14 +- src/gui/MidiSetupWidget.cpp | 24 +- src/gui/SetupDialog.cpp | 2180 ++++++++++++++-------------- 17 files changed, 1506 insertions(+), 1543 deletions(-) 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/SetupDialog.h b/include/SetupDialog.h index 272ba7b09..4a2e5c025 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,17 +47,18 @@ 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(); @@ -67,148 +67,136 @@ protected slots: 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/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index e31c24508..1f2ab1f57 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" ), @@ -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 ); } 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/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/audio/AudioJack.cpp b/src/core/audio/AudioJack.cpp index e149f5cbd..aebfe5e1c 100644 --- a/src/core/audio/AudioJack.cpp +++ b/src/core/audio/AudioJack.cpp @@ -454,7 +454,7 @@ AudioJack::setupWidget::setupWidget( QWidget * _parent ) : m_clientName = new QLineEdit( cn, this ); m_clientName->setGeometry( 10, 20, 160, 20 ); - QLabel * cn_lbl = new QLabel( tr( "CLIENT-NAME" ), this ); + QLabel * cn_lbl = new QLabel( tr( "Client name" ), this ); cn_lbl->setFont( pointSize<7>( cn_lbl->font() ) ); cn_lbl->setGeometry( 10, 40, 160, 10 ); @@ -466,7 +466,7 @@ AudioJack::setupWidget::setupWidget( QWidget * _parent ) : m_channels = new LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "CHANNELS" ) ); + m_channels->setLabel( tr( "Channels" ) ); m_channels->move( 180, 20 ); } diff --git a/src/core/audio/AudioOss.cpp b/src/core/audio/AudioOss.cpp index c9ad01801..bbd9a9507 100644 --- a/src/core/audio/AudioOss.cpp +++ b/src/core/audio/AudioOss.cpp @@ -327,7 +327,7 @@ AudioOss::setupWidget::setupWidget( QWidget * _parent ) : m_device = new QLineEdit( probeDevice(), this ); m_device->setGeometry( 10, 20, 160, 20 ); - QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + QLabel * dev_lbl = new QLabel( tr( "Device" ), this ); dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); dev_lbl->setGeometry( 10, 40, 160, 10 ); @@ -339,7 +339,7 @@ AudioOss::setupWidget::setupWidget( QWidget * _parent ) : m_channels = new LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "CHANNELS" ) ); + m_channels->setLabel( tr( "Channels" ) ); m_channels->move( 180, 20 ); } diff --git a/src/core/audio/AudioPortAudio.cpp b/src/core/audio/AudioPortAudio.cpp index 61dca4a22..ad67277ab 100644 --- a/src/core/audio/AudioPortAudio.cpp +++ b/src/core/audio/AudioPortAudio.cpp @@ -412,14 +412,14 @@ AudioPortAudio::setupWidget::setupWidget( QWidget * _parent ) : m_backend = new ComboBox( this, "BACKEND" ); m_backend->setGeometry( 64, 15, 260, 20 ); - QLabel * backend_lbl = new QLabel( tr( "BACKEND" ), this ); + QLabel * backend_lbl = new QLabel( tr( "Backend" ), this ); backend_lbl->setFont( pointSize<7>( backend_lbl->font() ) ); backend_lbl->move( 8, 18 ); m_device = new ComboBox( this, "DEVICE" ); m_device->setGeometry( 64, 35, 260, 20 ); - QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + QLabel * dev_lbl = new QLabel( tr( "Device" ), this ); dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); dev_lbl->move( 8, 38 ); @@ -431,7 +431,7 @@ AudioPortAudio::setupWidget::setupWidget( QWidget * _parent ) : m_channels = new LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "CHANNELS" ) ); + m_channels->setLabel( tr( "Channels" ) ); m_channels->move( 308, 20 );*/ connect( &m_setupUtil.m_backendModel, SIGNAL( dataChanged() ), diff --git a/src/core/audio/AudioPulseAudio.cpp b/src/core/audio/AudioPulseAudio.cpp index 857ef981b..af14960a7 100644 --- a/src/core/audio/AudioPulseAudio.cpp +++ b/src/core/audio/AudioPulseAudio.cpp @@ -314,7 +314,7 @@ AudioPulseAudio::setupWidget::setupWidget( QWidget * _parent ) : m_device = new QLineEdit( AudioPulseAudio::probeDevice(), this ); m_device->setGeometry( 10, 20, 160, 20 ); - QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + QLabel * dev_lbl = new QLabel( tr( "Device" ), this ); dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); dev_lbl->setGeometry( 10, 40, 160, 10 ); @@ -326,7 +326,7 @@ AudioPulseAudio::setupWidget::setupWidget( QWidget * _parent ) : m_channels = new LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "CHANNELS" ) ); + m_channels->setLabel( tr( "Channels" ) ); m_channels->move( 180, 20 ); } diff --git a/src/core/audio/AudioSdl.cpp b/src/core/audio/AudioSdl.cpp index 42adb9b33..b970ba630 100644 --- a/src/core/audio/AudioSdl.cpp +++ b/src/core/audio/AudioSdl.cpp @@ -325,7 +325,7 @@ AudioSdl::setupWidget::setupWidget( QWidget * _parent ) : m_device = new QLineEdit( dev, this ); m_device->setGeometry( 10, 20, 160, 20 ); - QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + QLabel * dev_lbl = new QLabel( tr( "Device" ), this ); dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); dev_lbl->setGeometry( 10, 40, 160, 10 ); diff --git a/src/core/audio/AudioSndio.cpp b/src/core/audio/AudioSndio.cpp index 853d734d5..24bef9246 100644 --- a/src/core/audio/AudioSndio.cpp +++ b/src/core/audio/AudioSndio.cpp @@ -193,7 +193,7 @@ AudioSndio::setupWidget::setupWidget( QWidget * _parent ) : m_device = new QLineEdit( "", this ); m_device->setGeometry( 10, 20, 160, 20 ); - QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + QLabel * dev_lbl = new QLabel( tr( "Device" ), this ); dev_lbl->setFont( pointSize<6>( dev_lbl->font() ) ); dev_lbl->setGeometry( 10, 40, 160, 10 ); @@ -205,7 +205,7 @@ AudioSndio::setupWidget::setupWidget( QWidget * _parent ) : m_channels = new LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "CHANNELS" ) ); + m_channels->setLabel( tr( "Channels" ) ); m_channels->move( 180, 20 ); } diff --git a/src/core/audio/AudioSoundIo.cpp b/src/core/audio/AudioSoundIo.cpp index cde14a1c5..2c3d493a6 100644 --- a/src/core/audio/AudioSoundIo.cpp +++ b/src/core/audio/AudioSoundIo.cpp @@ -426,14 +426,14 @@ AudioSoundIo::setupWidget::setupWidget( QWidget * _parent ) : m_backend = new ComboBox( this, "BACKEND" ); m_backend->setGeometry( 64, 15, 260, 20 ); - QLabel * backend_lbl = new QLabel( tr( "BACKEND" ), this ); + QLabel * backend_lbl = new QLabel( tr( "Backend" ), this ); backend_lbl->setFont( pointSize<7>( backend_lbl->font() ) ); backend_lbl->move( 8, 18 ); m_device = new ComboBox( this, "DEVICE" ); m_device->setGeometry( 64, 35, 260, 20 ); - QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + QLabel * dev_lbl = new QLabel( tr( "Device" ), this ); dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); dev_lbl->move( 8, 38 ); diff --git a/src/gui/AudioDeviceSetupWidget.cpp b/src/gui/AudioDeviceSetupWidget.cpp index 86800643e..fbec38c76 100644 --- a/src/gui/AudioDeviceSetupWidget.cpp +++ b/src/gui/AudioDeviceSetupWidget.cpp @@ -24,9 +24,9 @@ #include "AudioDeviceSetupWidget.h" -AudioDeviceSetupWidget::AudioDeviceSetupWidget( const QString & _caption, QWidget * _parent ) : - TabWidget( TabWidget::tr( "Settings for %1" ).arg(TabWidget::tr( _caption.toLatin1() ) ).toUpper(), - _parent ) + +AudioDeviceSetupWidget::AudioDeviceSetupWidget(const QString & caption, QWidget * parent) : + TabWidget(TabWidget::tr("Settings for %1").arg(TabWidget::tr(caption.toLatin1())), parent) { } diff --git a/src/gui/GuiApplication.cpp b/src/gui/GuiApplication.cpp index a7a3d1baa..fb2e3eae3 100644 --- a/src/gui/GuiApplication.cpp +++ b/src/gui/GuiApplication.cpp @@ -67,8 +67,8 @@ GuiApplication::GuiApplication() ConfigManager::inst()->createWorkingDir(); } // Init style and palette - QDir::addSearchPath("artwork", ConfigManager::inst()->artworkDir()); - QDir::addSearchPath("artwork", ConfigManager::inst()->defaultArtworkDir()); + QDir::addSearchPath("artwork", ConfigManager::inst()->themeDir()); + QDir::addSearchPath("artwork", ConfigManager::inst()->defaultThemeDir()); QDir::addSearchPath("artwork", ":/artwork"); LmmsStyle* lmmsstyle = new LmmsStyle(); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 0914d1685..bdb3a7472 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -174,16 +174,16 @@ MainWindow::MainWindow() : m_workspace = new QMdiArea( splitter ); // Load background - emit initProgress(tr("Loading background artwork")); - QString bgArtwork = ConfigManager::inst()->backgroundArtwork(); - QImage bgImage; - if( !bgArtwork.isEmpty() ) + emit initProgress(tr("Loading background picture")); + QString backgroundPicFile = ConfigManager::inst()->backgroundPicFile(); + QImage backgroundPic; + if( !backgroundPicFile.isEmpty() ) { - bgImage = QImage( bgArtwork ); + backgroundPic = QImage( backgroundPicFile ); } - if( !bgImage.isNull() ) + if( !backgroundPicFile.isNull() ) { - m_workspace->setBackground( bgImage ); + m_workspace->setBackground( backgroundPic ); } else { diff --git a/src/gui/MidiSetupWidget.cpp b/src/gui/MidiSetupWidget.cpp index f3001b3af..0c34544d6 100644 --- a/src/gui/MidiSetupWidget.cpp +++ b/src/gui/MidiSetupWidget.cpp @@ -29,23 +29,22 @@ #include "ConfigManager.h" #include "gui_templates.h" -MidiSetupWidget::MidiSetupWidget( const QString & caption, const QString & configSection, - const QString & devName, QWidget * parent ) : - TabWidget( TabWidget::tr( "Settings for %1" ).arg( - tr( caption.toLatin1() ) ).toUpper(), parent ), +MidiSetupWidget::MidiSetupWidget(const QString & caption, const QString & configSection, + const QString & devName, QWidget * parent) : + TabWidget(TabWidget::tr("Settings for %1").arg(tr(caption.toLatin1())), parent), m_configSection(configSection), m_device(nullptr) { // supply devName=QString() (distinct from QString("")) - // to indicate that there is no editable DEVICE field + // to indicate that there is no editable device field if (!devName.isNull()) { - m_device = new QLineEdit( devName, this ); - m_device->setGeometry( 10, 20, 160, 20 ); + m_device = new QLineEdit(devName, this); + m_device->setGeometry(10, 20, 160, 20); - QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); - dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); - dev_lbl->setGeometry( 10, 40, 160, 10 ); + QLabel * dev_lbl = new QLabel(tr("Device"), this); + dev_lbl->setFont(pointSize<7>(dev_lbl->font())); + dev_lbl->setGeometry(10, 40, 160, 10); } } @@ -53,8 +52,8 @@ void MidiSetupWidget::saveSettings() { if (!m_configSection.isEmpty() && m_device) { - ConfigManager::inst()->setValue( m_configSection, "device", - m_device->text() ); + ConfigManager::inst()->setValue(m_configSection, "device", + m_device->text()); } } @@ -65,4 +64,3 @@ void MidiSetupWidget::show() parentWidget()->setVisible(visible); QWidget::setVisible(visible); } - diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index 5ab9630b2..f23b5b271 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -22,6 +22,7 @@ * */ + #include #include #include @@ -30,291 +31,247 @@ #include #include +#include "debug.h" +#include "embed.h" +#include "Engine.h" +#include "FileDialog.h" +#include "gui_templates.h" +#include "MainWindow.h" +#include "Mixer.h" +#include "ProjectJournal.h" #include "SetupDialog.h" #include "TabBar.h" #include "TabButton.h" -#include "gui_templates.h" -#include "Mixer.h" -#include "MainWindow.h" -#include "ProjectJournal.h" -#include "embed.h" -#include "Engine.h" -#include "debug.h" #include "ToolTip.h" -#include "FileDialog.h" -// platform-specific audio-interface-classes +// Platform-specific audio-interface classes. #include "AudioAlsa.h" #include "AudioAlsaSetupWidget.h" +#include "AudioDummy.h" #include "AudioJack.h" #include "AudioOss.h" -#include "AudioSndio.h" #include "AudioPortAudio.h" -#include "AudioSoundIo.h" #include "AudioPulseAudio.h" #include "AudioSdl.h" -#include "AudioDummy.h" +#include "AudioSndio.h" +#include "AudioSoundIo.h" -// platform-specific midi-interface-classes +// Platform-specific midi-interface classes. #include "MidiAlsaRaw.h" #include "MidiAlsaSeq.h" +#include "MidiApple.h" +#include "MidiDummy.h" #include "MidiJack.h" #include "MidiOss.h" #include "MidiSndio.h" #include "MidiWinMM.h" -#include "MidiApple.h" -#include "MidiDummy.h" + constexpr int BUFFERSIZE_RESOLUTION = 32; -inline void labelWidget( QWidget * _w, const QString & _txt ) +inline void labelWidget(QWidget * w, const QString & txt) { - QLabel * title = new QLabel( _txt, _w ); + QLabel * title = new QLabel(txt, w); QFont f = title->font(); - f.setBold( true ); - title->setFont( pointSize<12>( f ) ); + f.setBold(true); + title->setFont(pointSize<12>(f)); - assert( dynamic_cast( _w->layout() ) != NULL ); + assert(dynamic_cast(w->layout()) != NULL); - dynamic_cast( _w->layout() )->addSpacing( 5 ); - dynamic_cast( _w->layout() )->addWidget( title ); - dynamic_cast( _w->layout() )->addSpacing( 10 ); + dynamic_cast(w->layout())->addSpacing(5); + dynamic_cast(w->layout())->addWidget(title); } -SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : - m_bufferSize( ConfigManager::inst()->value( "mixer", - "framesperaudiobuffer" ).toInt() ), - m_toolTips( !ConfigManager::inst()->value( "tooltips", - "disabled" ).toInt() ), - m_warnAfterSetup( !ConfigManager::inst()->value( "app", - "nomsgaftersetup" ).toInt() ), - m_displaydBFS( ConfigManager::inst()->value( "app", - "displaydbfs" ).toInt() ), - m_MMPZ( !ConfigManager::inst()->value( "app", "nommpz" ).toInt() ), - m_disableBackup( !ConfigManager::inst()->value( "app", - "disablebackup" ).toInt() ), - m_openLastProject( ConfigManager::inst()->value( "app", - "openlastproject" ).toInt() ), - m_NaNHandler( ConfigManager::inst()->value( "app", - "nanhandler", "1" ).toInt() ), - m_hqAudioDev( ConfigManager::inst()->value( "mixer", - "hqaudio" ).toInt() ), - m_lang( ConfigManager::inst()->value( "app", - "language" ) ), - m_workingDir( QDir::toNativeSeparators( ConfigManager::inst()->workingDir() ) ), - m_vstDir( QDir::toNativeSeparators( ConfigManager::inst()->vstDir() ) ), - m_artworkDir( QDir::toNativeSeparators( ConfigManager::inst()->artworkDir() ) ), - m_ladDir( QDir::toNativeSeparators( ConfigManager::inst()->ladspaDir() ) ), - m_gigDir( QDir::toNativeSeparators( ConfigManager::inst()->gigDir() ) ), - m_sf2Dir( QDir::toNativeSeparators( ConfigManager::inst()->sf2Dir() ) ), +SetupDialog::SetupDialog(ConfigTabs tab_to_open) : + m_displaydBFS(ConfigManager::inst()->value( + "app", "displaydbfs").toInt()), + m_tooltips(!ConfigManager::inst()->value( + "tooltips", "disabled").toInt()), + m_displayWaveform(ConfigManager::inst()->value( + "ui", "displaywaveform").toInt()), + m_printNoteLabels(ConfigManager::inst()->value( + "ui", "printnotelabels").toInt()), + m_compactTrackButtons(ConfigManager::inst()->value( + "ui", "compacttrackbuttons").toInt()), + m_oneInstrumentTrackWindow(ConfigManager::inst()->value( + "ui", "oneinstrumenttrackwindow").toInt()), + m_MMPZ(!ConfigManager::inst()->value( + "app", "nommpz").toInt()), + m_disableBackup(!ConfigManager::inst()->value( + "app", "disablebackup").toInt()), + m_openLastProject(ConfigManager::inst()->value( + "app", "openlastproject").toInt()), + m_lang(ConfigManager::inst()->value( + "app", "language")), + m_saveInterval( ConfigManager::inst()->value( + "ui", "saveinterval").toInt() < 1 ? + MainWindow::DEFAULT_SAVE_INTERVAL_MINUTES : + ConfigManager::inst()->value( + "ui", "saveinterval").toInt()), + m_enableAutoSave(ConfigManager::inst()->value( + "ui", "enableautosave", "1").toInt()), + m_enableRunningAutoSave(ConfigManager::inst()->value( + "ui", "enablerunningautosave", "0").toInt()), + m_smoothScroll(ConfigManager::inst()->value( + "ui", "smoothscroll").toInt()), + m_animateAFP(ConfigManager::inst()->value( + "ui", "animateafp", "1").toInt()), + m_vstEmbedMethod(ConfigManager::inst()->vstEmbedMethod()), + m_vstAlwaysOnTop(ConfigManager::inst()->value( + "ui", "vstalwaysontop").toInt()), + m_syncVSTPlugins(ConfigManager::inst()->value( + "ui", "syncvstplugins").toInt()), + m_disableAutoQuit(ConfigManager::inst()->value( + "ui", "disableautoquit").toInt()), + m_NaNHandler(ConfigManager::inst()->value( + "app", "nanhandler", "1").toInt()), + m_hqAudioDev(ConfigManager::inst()->value( + "mixer", "hqaudio").toInt()), + m_bufferSize(ConfigManager::inst()->value( + "mixer", "framesperaudiobuffer").toInt()), + m_workingDir(QDir::toNativeSeparators(ConfigManager::inst()->workingDir())), + m_vstDir(QDir::toNativeSeparators(ConfigManager::inst()->vstDir())), + m_ladspaDir(QDir::toNativeSeparators(ConfigManager::inst()->ladspaDir())), + m_gigDir(QDir::toNativeSeparators(ConfigManager::inst()->gigDir())), + m_sf2Dir(QDir::toNativeSeparators(ConfigManager::inst()->sf2Dir())), #ifdef LMMS_HAVE_FLUIDSYNTH - m_defaultSoundfont( QDir::toNativeSeparators( ConfigManager::inst()->defaultSoundfont() ) ), + m_sf2File(QDir::toNativeSeparators(ConfigManager::inst()->sf2File())), #endif -#ifdef LMMS_HAVE_STK - m_stkDir( QDir::toNativeSeparators( ConfigManager::inst()->stkDir() ) ), -#endif - m_backgroundArtwork( QDir::toNativeSeparators( ConfigManager::inst()->backgroundArtwork() ) ), - m_smoothScroll( ConfigManager::inst()->value( "ui", "smoothscroll" ).toInt() ), - m_enableAutoSave( ConfigManager::inst()->value( "ui", "enableautosave", "1" ).toInt() ), - m_enableRunningAutoSave( ConfigManager::inst()->value( "ui", "enablerunningautosave", "0" ).toInt() ), - m_saveInterval( ConfigManager::inst()->value( "ui", "saveinterval" ).toInt() < 1 ? - MainWindow::DEFAULT_SAVE_INTERVAL_MINUTES : - ConfigManager::inst()->value( "ui", "saveinterval" ).toInt() ), - m_oneInstrumentTrackWindow( ConfigManager::inst()->value( "ui", - "oneinstrumenttrackwindow" ).toInt() ), - m_compactTrackButtons( ConfigManager::inst()->value( "ui", - "compacttrackbuttons" ).toInt() ), - m_syncVSTPlugins( ConfigManager::inst()->value( "ui", - "syncvstplugins", "1" ).toInt() ), - m_animateAFP(ConfigManager::inst()->value( "ui", - "animateafp", "1" ).toInt() ), - m_printNoteLabels(ConfigManager::inst()->value( "ui", - "printnotelabels").toInt() ), - m_displayWaveform(ConfigManager::inst()->value( "ui", - "displaywaveform").toInt() ), - m_disableAutoQuit(ConfigManager::inst()->value( "ui", - "disableautoquit", "1" ).toInt() ), - m_vstEmbedMethod( ConfigManager::inst()->vstEmbedMethod() ), - m_vstAlwaysOnTop( ConfigManager::inst()->value( "ui", - "vstalwaysontop" ).toInt() ) + m_themeDir(QDir::toNativeSeparators(ConfigManager::inst()->themeDir())), + m_backgroundPicFile(QDir::toNativeSeparators(ConfigManager::inst()->backgroundPicFile())) { - setWindowIcon( embed::getIconPixmap( "setup_general" ) ); - setWindowTitle( tr( "Setup LMMS" ) ); - setModal( true ); - setFixedSize( 452, 570 ); + setWindowIcon(embed::getIconPixmap("setup_general")); + setWindowTitle(tr("Settings")); + // TODO: Equivalent to the new setWindowFlag(Qt::WindowContextHelpButtonHint, false) + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + setModal(true); + setFixedSize(454, 400); - Engine::projectJournal()->setJournalling( false ); + Engine::projectJournal()->setJournalling(false); - QVBoxLayout * vlayout = new QVBoxLayout( this ); - vlayout->setSpacing( 0 ); - vlayout->setMargin( 0 ); - QWidget * settings = new QWidget( this ); - QHBoxLayout * hlayout = new QHBoxLayout( settings ); - hlayout->setSpacing( 0 ); - hlayout->setMargin( 0 ); - m_tabBar = new TabBar( settings, QBoxLayout::TopToBottom ); - m_tabBar->setExclusive( true ); - m_tabBar->setFixedWidth( 72 ); - - QWidget * ws = new QWidget( settings ); - int wsHeight = 420; -#ifdef LMMS_HAVE_STK - wsHeight += 50; -#endif -#ifdef LMMS_HAVE_FLUIDSYNTH - wsHeight += 50; -#endif - ws->setFixedSize( 360, wsHeight ); - QWidget * general = new QWidget( ws ); - general->setFixedSize( 360, 290 ); - QVBoxLayout * gen_layout = new QVBoxLayout( general ); - gen_layout->setSpacing( 0 ); - gen_layout->setMargin( 0 ); - labelWidget( general, tr( "General settings" ) ); - - TabWidget * bufsize_tw = new TabWidget( tr( "BUFFER SIZE" ), general ); - bufsize_tw->setFixedHeight( 80 ); - - m_bufSizeSlider = new QSlider( Qt::Horizontal, bufsize_tw ); - m_bufSizeSlider->setRange( 1, 128 ); - m_bufSizeSlider->setTickPosition( QSlider::TicksBelow ); - m_bufSizeSlider->setPageStep( 8 ); - m_bufSizeSlider->setTickInterval( 8 ); - m_bufSizeSlider->setGeometry( 10, 16, 340, 18 ); - m_bufSizeSlider->setValue( m_bufferSize / BUFFERSIZE_RESOLUTION ); - - connect( m_bufSizeSlider, SIGNAL( valueChanged( int ) ), this, - SLOT( setBufferSize( int ) ) ); - - m_bufSizeLbl = new QLabel( bufsize_tw ); - m_bufSizeLbl->setGeometry( 10, 40, 200, 32 ); - setBufferSize( m_bufSizeSlider->value() ); - - QPushButton * bufsize_reset_btn = new QPushButton( - embed::getIconPixmap( "reload" ), "", bufsize_tw ); - bufsize_reset_btn->setGeometry( 320, 40, 28, 28 ); - connect( bufsize_reset_btn, SIGNAL( clicked() ), this, - SLOT( resetBufSize() ) ); - ToolTip::add( bufsize_reset_btn, tr( "Reset to default value" ) ); - - TabWidget * misc_tw = new TabWidget( tr( "MISC" ), general ); + // Constants for positioning LED check boxes. const int XDelta = 10; const int YDelta = 18; - const int HeaderSize = 30; - int labelNumber = 0; - auto addLedCheckBox = [&XDelta, &YDelta, &misc_tw, &labelNumber, this]( + // Main widget. + QWidget * main_w = new QWidget(this); + + + // Vertical layout. + QVBoxLayout * vlayout = new QVBoxLayout(this); + vlayout->setSpacing(0); + vlayout->setMargin(0); + + // Horizontal layout. + QHBoxLayout * hlayout = new QHBoxLayout(main_w); + hlayout->setSpacing(0); + hlayout->setMargin(0); + + // Tab bar for the main tabs. + m_tabBar = new TabBar(main_w, QBoxLayout::TopToBottom); + m_tabBar->setExclusive(true); + m_tabBar->setFixedWidth(72); + + // Settings widget. + QWidget * settings_w = new QWidget(main_w); + settings_w->setFixedSize(360, 360); + + // General widget. + QWidget * general_w = new QWidget(settings_w); + QVBoxLayout * general_layout = new QVBoxLayout(general_w); + general_layout->setSpacing(10); + general_layout->setMargin(0); + labelWidget(general_w, tr("General")); + + + auto addLedCheckBox = [&XDelta, &YDelta, this]( const char* ledText, + TabWidget* tw, + int& counter, bool initialState, - const char* toggledSlot + const char* toggledSlot, + bool showRestartWarning ){ - LedCheckBox * checkBox = new LedCheckBox(tr(ledText), misc_tw); - labelNumber++; - checkBox->move(XDelta, YDelta*labelNumber); + LedCheckBox * checkBox = new LedCheckBox(tr(ledText), tw); + counter++; + checkBox->move(XDelta, YDelta * counter); checkBox->setChecked(initialState); connect(checkBox, SIGNAL(toggled(bool)), this, toggledSlot); + if (showRestartWarning) + { + connect(checkBox, SIGNAL(toggled(bool)), this, SLOT(showRestartWarning())); + } }; - addLedCheckBox("Enable tooltips", - m_toolTips, SLOT(toggleToolTips(bool))); - addLedCheckBox("Show restart warning after changing settings", - m_warnAfterSetup, SLOT(toggleWarnAfterSetup(bool))); - addLedCheckBox("Display volume as dBFS ", - m_displaydBFS, SLOT(toggleDisplaydBFS(bool))); - addLedCheckBox("Compress project files per default", - m_MMPZ, SLOT(toggleMMPZ(bool))); - addLedCheckBox("One instrument track window mode", - m_oneInstrumentTrackWindow, - SLOT(toggleOneInstrumentTrackWindow(bool))); - addLedCheckBox("HQ-mode for output audio-device", - m_hqAudioDev, SLOT(toggleHQAudioDev(bool))); - addLedCheckBox("Compact track buttons", - m_compactTrackButtons, SLOT(toggleCompactTrackButtons(bool))); - addLedCheckBox("Sync VST plugins to host playback", - m_syncVSTPlugins, SLOT(toggleSyncVSTPlugins(bool))); - addLedCheckBox("Enable note labels in piano roll", - m_printNoteLabels, SLOT(toggleNoteLabels(bool))); - addLedCheckBox("Enable waveform display by default", - m_displayWaveform, SLOT(toggleDisplayWaveform(bool))); - addLedCheckBox("Keep effects running even without input", - m_disableAutoQuit, SLOT(toggleDisableAutoquit(bool))); - addLedCheckBox("Create backup file when saving a project", - m_disableBackup, SLOT(toggleDisableBackup(bool))); - addLedCheckBox("Reopen last project on start", - m_openLastProject, SLOT(toggleOpenLastProject(bool))); - misc_tw->setFixedHeight( YDelta*labelNumber + HeaderSize ); + int counter = 0; - // Advanced setting, hidden for now - if( false ) + // GUI tab. + TabWidget * gui_tw = new TabWidget( + tr("Graphical user interface (GUI)"), general_w); + + + addLedCheckBox("Display volume as dBFS ", gui_tw, counter, + m_displaydBFS, SLOT(toggleDisplaydBFS(bool)), true); + addLedCheckBox("Enable tooltips", gui_tw, counter, + m_tooltips, SLOT(toggleTooltips(bool)), true); + addLedCheckBox("Enable master oscilloscope by default", gui_tw, counter, + m_displayWaveform, SLOT(toggleDisplayWaveform(bool)), true); + addLedCheckBox("Enable all note labels in piano roll", gui_tw, counter, + m_printNoteLabels, SLOT(toggleNoteLabels(bool)), false); + addLedCheckBox("Enable compact track buttons", gui_tw, counter, + m_compactTrackButtons, SLOT(toggleCompactTrackButtons(bool)), true); + addLedCheckBox("Enable one instrument-track-window mode", gui_tw, counter, + m_oneInstrumentTrackWindow, SLOT(toggleOneInstrumentTrackWindow(bool)), true); + + gui_tw->setFixedHeight(YDelta + YDelta * counter); + + + counter = 0; + + // Projects tab. + TabWidget * projects_tw = new TabWidget( + tr("Projects"), general_w); + + + addLedCheckBox("Compress project files by default", projects_tw, counter, + m_MMPZ, SLOT(toggleMMPZ(bool)), true); + addLedCheckBox("Create a backup file when saving a project", projects_tw, counter, + m_disableBackup, SLOT(toggleDisableBackup(bool)), false); + addLedCheckBox("Reopen last project on startup", projects_tw, counter, + m_openLastProject, SLOT(toggleOpenLastProject(bool)), false); + + projects_tw->setFixedHeight(YDelta + YDelta * counter); + + // Language tab. + TabWidget * lang_tw = new TabWidget( + tr("Language"), general_w); + lang_tw->setFixedHeight(48); + QComboBox * changeLang = new QComboBox(lang_tw); + changeLang->move(XDelta, 20); + + QDir dir(ConfigManager::inst()->localeDir()); + QStringList fileNames = dir.entryList(QStringList("*.qm")); + for(int i = 0; i < fileNames.size(); ++i) { - LedCheckBox * useNaNHandler = new LedCheckBox( - tr( "Use built-in NaN handler" ), - misc_tw ); - useNaNHandler->setChecked( m_NaNHandler ); + // Get locale extracted by filename. + fileNames[i].truncate(fileNames[i].lastIndexOf('.')); + m_languages.append(fileNames[i]); + QString lang = QLocale(m_languages.last()).nativeLanguageName(); + changeLang->addItem(lang); } - TabWidget* embed_tw = new TabWidget( tr( "PLUGIN EMBEDDING" ), general); - embed_tw->setFixedHeight( 66 ); - m_vstEmbedComboBox = new QComboBox( embed_tw ); - m_vstEmbedComboBox->move( XDelta, YDelta ); - - QStringList embedMethods = ConfigManager::availabeVstEmbedMethods(); - m_vstEmbedComboBox->addItem( tr( "No embedding" ), "none" ); - if( embedMethods.contains("qt") ) + // If language unset, fallback to system language when available. + if(m_lang == "") { - m_vstEmbedComboBox->addItem( tr( "Embed using Qt API" ), "qt" ); - } - if( embedMethods.contains("win32") ) - { - m_vstEmbedComboBox->addItem( tr( "Embed using native Win32 API" ), "win32" ); - } - if( embedMethods.contains("xembed") ) - { - m_vstEmbedComboBox->addItem( tr( "Embed using XEmbed protocol" ), "xembed" ); - } - m_vstEmbedComboBox->setCurrentIndex( m_vstEmbedComboBox->findData( m_vstEmbedMethod ) ); - connect( m_vstEmbedComboBox, SIGNAL( currentIndexChanged( int ) ), - this, SLOT( vstEmbedMethodChanged() ) ); - - m_vstAlwaysOnTopCheckBox = new LedCheckBox( - tr( "Keep plugin windows on top when not embedded" ), - embed_tw ); - m_vstAlwaysOnTopCheckBox->move( 20, 44 ); - m_vstAlwaysOnTopCheckBox->setChecked( m_vstAlwaysOnTop ); - m_vstAlwaysOnTopCheckBox->setVisible( m_vstEmbedMethod == "none" ); - connect( m_vstAlwaysOnTopCheckBox, SIGNAL( toggled( bool ) ), - this, SLOT( toggleVSTAlwaysOnTop( bool ) ) ); - - TabWidget * lang_tw = new TabWidget( tr( "LANGUAGE" ), general ); - lang_tw->setFixedHeight( 48 ); - QComboBox * changeLang = new QComboBox( lang_tw ); - changeLang->move( XDelta, YDelta ); - - QDir dir( ConfigManager::inst()->localeDir() ); - QStringList fileNames = dir.entryList( QStringList( "*.qm" ) ); - for( int i = 0; i < fileNames.size(); ++i ) - { - // get locale extracted by filename - fileNames[i].truncate( fileNames[i].lastIndexOf( '.' ) ); - m_languages.append( fileNames[i] ); - QString lang = QLocale( m_languages.last() ).nativeLanguageName(); - changeLang->addItem( lang ); - } - connect( changeLang, SIGNAL( currentIndexChanged( int ) ), - this, SLOT( setLanguage( int ) ) ); - - //If language unset, fallback to system language when available - if( m_lang == "" ) - { - QString tmp = QLocale::system().name().left( 2 ); - if( m_languages.contains( tmp ) ) + QString tmp = QLocale::system().name().left(2); + if(m_languages.contains(tmp)) { m_lang = tmp; } @@ -324,69 +281,439 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : } } - for( int i = 0; i < changeLang->count(); ++i ) + for(int i = 0; i < changeLang->count(); ++i) { - if( m_lang == m_languages.at( i ) ) + if(m_lang == m_languages.at(i)) { - changeLang->setCurrentIndex( i ); + changeLang->setCurrentIndex(i); break; } } - gen_layout->addWidget( bufsize_tw ); - gen_layout->addSpacing( 10 ); - gen_layout->addWidget( misc_tw ); - gen_layout->addSpacing( 10 ); - gen_layout->addWidget( embed_tw ); - gen_layout->addSpacing( 10 ); - gen_layout->addWidget( lang_tw ); - gen_layout->addStretch(); + connect(changeLang, SIGNAL(currentIndexChanged(int)), + this, SLOT(setLanguage(int))); + connect(changeLang, SIGNAL(currentIndexChanged(int)), + this, SLOT(showRestartWarning())); + + + // General layout ordering. + general_layout->addWidget(gui_tw); + general_layout->addWidget(projects_tw); + general_layout->addWidget(lang_tw); + general_layout->addStretch(); - QWidget * paths = new QWidget( ws ); - int pathsHeight = 420; -#ifdef LMMS_HAVE_STK - pathsHeight += 55; + + // Performance widget. + QWidget * performance_w = new QWidget(settings_w); + QVBoxLayout * performance_layout = new QVBoxLayout(performance_w); + performance_layout->setSpacing(10); + performance_layout->setMargin(0); + labelWidget(performance_w, + tr("Performance")); + + + // Autosave tab. + TabWidget * auto_save_tw = new TabWidget( + tr("Autosave"), performance_w); + auto_save_tw->setFixedHeight(106); + + m_saveIntervalSlider = new QSlider(Qt::Horizontal, auto_save_tw); + m_saveIntervalSlider->setValue(m_saveInterval); + m_saveIntervalSlider->setRange(1, 20); + m_saveIntervalSlider->setTickInterval(1); + m_saveIntervalSlider->setPageStep(1); + m_saveIntervalSlider->setGeometry(10, 18, 340, 18); + m_saveIntervalSlider->setTickPosition(QSlider::TicksBelow); + + connect(m_saveIntervalSlider, SIGNAL(valueChanged(int)), + this, SLOT(setAutoSaveInterval(int))); + + m_saveIntervalLbl = new QLabel(auto_save_tw); + m_saveIntervalLbl->setGeometry(10, 40, 200, 24); + setAutoSaveInterval(m_saveIntervalSlider->value()); + + m_autoSave = new LedCheckBox( + tr("Enable autosave"), auto_save_tw); + m_autoSave->move(10, 70); + m_autoSave->setChecked(m_enableAutoSave); + connect(m_autoSave, SIGNAL(toggled(bool)), + this, SLOT(toggleAutoSave(bool))); + + m_runningAutoSave = new LedCheckBox( + tr("Allow autosave while playing"), auto_save_tw); + m_runningAutoSave->move(20, 88); + m_runningAutoSave->setChecked(m_enableRunningAutoSave); + connect(m_runningAutoSave, SIGNAL(toggled(bool)), + this, SLOT(toggleRunningAutoSave(bool))); + + QPushButton * autoSaveResetBtn = new QPushButton( + embed::getIconPixmap("reload"), "", auto_save_tw); + autoSaveResetBtn->setGeometry(320, 70, 28, 28); + connect(autoSaveResetBtn, SIGNAL(clicked()), + this, SLOT(resetAutoSave())); + + m_saveIntervalSlider->setEnabled(m_enableAutoSave); + m_runningAutoSave->setVisible(m_enableAutoSave); + + + counter = 0; + + // UI effect vs. performance tab. + TabWidget * ui_fx_tw = new TabWidget( + tr("User interface (UI) effects vs. performance"), performance_w); + + addLedCheckBox("Smooth scroll in song editor", ui_fx_tw, counter, + m_smoothScroll, SLOT(toggleSmoothScroll(bool)), false); + addLedCheckBox("Display playback cursor in AudioFileProcessor", ui_fx_tw, counter, + m_animateAFP, SLOT(toggleAnimateAFP(bool)), false); + + ui_fx_tw->setFixedHeight(YDelta + YDelta * counter); + + + counter = 0; + + // Plugins tab. + TabWidget * plugins_tw = new TabWidget( + tr("Plugins"), performance_w); + + m_vstEmbedLbl = new QLabel(plugins_tw); + m_vstEmbedLbl->move(XDelta, YDelta * ++counter); + m_vstEmbedLbl->setText(tr("VST plugins embedding:")); + + m_vstEmbedComboBox = new QComboBox(plugins_tw); + m_vstEmbedComboBox->move(XDelta, YDelta * ++counter); + + QStringList embedMethods = ConfigManager::availabeVstEmbedMethods(); + m_vstEmbedComboBox->addItem(tr("No embedding"), "none"); + if(embedMethods.contains("qt")) + { + m_vstEmbedComboBox->addItem(tr("Embed using Qt API"), "qt"); + } + if(embedMethods.contains("win32")) + { + m_vstEmbedComboBox->addItem(tr("Embed using native Win32 API"), "win32"); + } + if(embedMethods.contains("xembed")) + { + m_vstEmbedComboBox->addItem(tr("Embed using XEmbed protocol"), "xembed"); + } + m_vstEmbedComboBox->setCurrentIndex(m_vstEmbedComboBox->findData(m_vstEmbedMethod)); + connect(m_vstEmbedComboBox, SIGNAL(currentIndexChanged(int)), + this, SLOT(vstEmbedMethodChanged())); + + counter += 2; + + m_vstAlwaysOnTopCheckBox = new LedCheckBox( + tr("Keep plugin windows on top when not embedded"), plugins_tw); + m_vstAlwaysOnTopCheckBox->move(20, 66); + m_vstAlwaysOnTopCheckBox->setChecked(m_vstAlwaysOnTop); + m_vstAlwaysOnTopCheckBox->setVisible(m_vstEmbedMethod == "none"); + connect(m_vstAlwaysOnTopCheckBox, SIGNAL(toggled(bool)), + this, SLOT(toggleVSTAlwaysOnTop(bool))); + + addLedCheckBox("Sync VST plugins to host playback", plugins_tw, counter, + m_syncVSTPlugins, SLOT(toggleSyncVSTPlugins(bool)), false); + + addLedCheckBox("Keep effects running even without input", plugins_tw, counter, + m_disableAutoQuit, SLOT(toggleDisableAutoQuit(bool)), false); + + plugins_tw->setFixedHeight(YDelta + YDelta * counter); + + + // Performance layout ordering. + performance_layout->addWidget(auto_save_tw); + performance_layout->addWidget(ui_fx_tw); + performance_layout->addWidget(plugins_tw); + performance_layout->addStretch(); + + + + // Audio widget. + QWidget * audio_w = new QWidget(settings_w); + QVBoxLayout * audio_layout = new QVBoxLayout(audio_w); + audio_layout->setSpacing(10); + audio_layout->setMargin(0); + labelWidget(audio_w, + tr("Audio")); + + // Audio interface tab. + TabWidget * audioiface_tw = new TabWidget( + tr("Audio interface"), audio_w); + audioiface_tw->setFixedHeight(56); + + m_audioInterfaces = new QComboBox(audioiface_tw); + m_audioInterfaces->setGeometry(10, 20, 240, 28); + + + // Ifaces-settings-widget. + QWidget * as_w = new QWidget(audio_w); + as_w->setFixedHeight(60); + + QHBoxLayout * as_w_layout = new QHBoxLayout(as_w); + as_w_layout->setSpacing(0); + as_w_layout->setMargin(0); + +#ifdef LMMS_HAVE_JACK + m_audioIfaceSetupWidgets[AudioJack::name()] = + new AudioJack::setupWidget(as_w); #endif -#ifdef LMMS_HAVE_FLUIDSYNTH - pathsHeight += 55; + +#ifdef LMMS_HAVE_ALSA + m_audioIfaceSetupWidgets[AudioAlsa::name()] = + new AudioAlsaSetupWidget(as_w); #endif - paths->setFixedSize( 360, pathsHeight ); - QVBoxLayout * dir_layout = new QVBoxLayout( paths ); - dir_layout->setSpacing( 0 ); - dir_layout->setMargin( 0 ); - labelWidget( paths, tr( "Paths" ) ); - QLabel * title = new QLabel( tr( "Directories" ), paths ); - QFont f = title->font(); - f.setBold( true ); - title->setFont( pointSize<12>( f ) ); + +#ifdef LMMS_HAVE_PULSEAUDIO + m_audioIfaceSetupWidgets[AudioPulseAudio::name()] = + new AudioPulseAudio::setupWidget(as_w); +#endif + +#ifdef LMMS_HAVE_PORTAUDIO + m_audioIfaceSetupWidgets[AudioPortAudio::name()] = + new AudioPortAudio::setupWidget(as_w); +#endif + +#ifdef LMMS_HAVE_SOUNDIO + m_audioIfaceSetupWidgets[AudioSoundIo::name()] = + new AudioSoundIo::setupWidget(as_w); +#endif + +#ifdef LMMS_HAVE_SDL + m_audioIfaceSetupWidgets[AudioSdl::name()] = + new AudioSdl::setupWidget(as_w); +#endif + +#ifdef LMMS_HAVE_OSS + m_audioIfaceSetupWidgets[AudioOss::name()] = + new AudioOss::setupWidget(as_w); +#endif + +#ifdef LMMS_HAVE_SNDIO + m_audioIfaceSetupWidgets[AudioSndio::name()] = + new AudioSndio::setupWidget(as_w); +#endif + + m_audioIfaceSetupWidgets[AudioDummy::name()] = + new AudioDummy::setupWidget(as_w); - QScrollArea *pathScroll = new QScrollArea( paths ); + for(AswMap::iterator it = m_audioIfaceSetupWidgets.begin(); + it != m_audioIfaceSetupWidgets.end(); ++it) + { + m_audioIfaceNames[ + tr(it.key().toLatin1())] = it.key(); + } + for(trMap::iterator it = m_audioIfaceNames.begin(); + it != m_audioIfaceNames.end(); ++it) + { + QWidget * audioWidget = m_audioIfaceSetupWidgets[it.value()]; + audioWidget->hide(); + as_w_layout->addWidget(audioWidget); + m_audioInterfaces->addItem(it.key()); + } - QWidget *pathSelectors = new QWidget( ws ); - QVBoxLayout *pathSelectorLayout = new QVBoxLayout; - pathScroll->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn ); - pathScroll->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); - pathScroll->resize( 362, pathsHeight - 50 ); - pathScroll->move( 0, 30 ); - pathSelectors->resize( 360, pathsHeight - 50 ); + // If no preferred audio device is saved, save the current one. + QString audioDevName = ConfigManager::inst()->value("mixer", "audiodev"); + if (m_audioInterfaces->findText(audioDevName) < 0) + { + audioDevName = Engine::mixer()->audioDevName(); + ConfigManager::inst()->setValue("mixer", "audiodev", audioDevName); + } + m_audioInterfaces-> + setCurrentIndex(m_audioInterfaces->findText(audioDevName)); + m_audioIfaceSetupWidgets[audioDevName]->show(); + + connect(m_audioInterfaces, SIGNAL(activated(const QString &)), + this, SLOT(audioInterfaceChanged(const QString &))); + + // Advanced setting, hidden for now + if(false) + { + LedCheckBox * useNaNHandler = new LedCheckBox( + tr("Use built-in NaN handler"), audio_w); + useNaNHandler->setChecked(m_NaNHandler); + } + + // HQ mode LED. + LedCheckBox * hqaudio = new LedCheckBox( + tr("HQ mode for output audio device"), audio_w); + hqaudio->move(10, 0); + hqaudio->setChecked(m_hqAudioDev); + connect(hqaudio, SIGNAL(toggled(bool)), + this, SLOT(toggleHQAudioDev(bool))); + + + // Buffer size tab. + TabWidget * bufferSize_tw = new TabWidget( + tr("Buffer size"), audio_w); + bufferSize_tw->setFixedHeight(76); + + m_bufferSizeSlider = new QSlider(Qt::Horizontal, bufferSize_tw); + m_bufferSizeSlider->setRange(1, 128); + m_bufferSizeSlider->setTickInterval(8); + m_bufferSizeSlider->setPageStep(8); + m_bufferSizeSlider->setValue(m_bufferSize / BUFFERSIZE_RESOLUTION); + m_bufferSizeSlider->setGeometry(10, 18, 340, 18); + m_bufferSizeSlider->setTickPosition(QSlider::TicksBelow); + + connect(m_bufferSizeSlider, SIGNAL(valueChanged(int)), + this, SLOT(setBufferSize(int))); + connect(m_bufferSizeSlider, SIGNAL(valueChanged(int)), + this, SLOT(showRestartWarning())); + + m_bufferSizeLbl = new QLabel(bufferSize_tw); + m_bufferSizeLbl->setGeometry(10, 40, 200, 24); + setBufferSize(m_bufferSizeSlider->value()); + + QPushButton * bufferSize_reset_btn = new QPushButton( + embed::getIconPixmap("reload"), "", bufferSize_tw); + bufferSize_reset_btn->setGeometry(320, 40, 28, 28); + connect(bufferSize_reset_btn, SIGNAL(clicked()), + this, SLOT(resetBufferSize())); + ToolTip::add(bufferSize_reset_btn, + tr("Reset to default value")); + + + // Audio layout ordering. + audio_layout->addWidget(audioiface_tw); + audio_layout->addWidget(as_w); + audio_layout->addWidget(hqaudio); + audio_layout->addWidget(bufferSize_tw); + audio_layout->addStretch(); + + + + // MIDI widget. + QWidget * midi_w = new QWidget(settings_w); + QVBoxLayout * midi_layout = new QVBoxLayout(midi_w); + midi_layout->setSpacing(10); + midi_layout->setMargin(0); + labelWidget(midi_w, + tr("MIDI")); + + // MIDI interface tab. + TabWidget * midiiface_tw = new TabWidget( + tr("MIDI interface"), midi_w); + midiiface_tw->setFixedHeight(56); + + m_midiInterfaces = new QComboBox(midiiface_tw); + m_midiInterfaces->setGeometry(10, 20, 240, 28); + + // Ifaces-settings-widget. + QWidget * ms_w = new QWidget(midi_w); + ms_w->setFixedHeight(60); + + QHBoxLayout * ms_w_layout = new QHBoxLayout(ms_w); + ms_w_layout->setSpacing(0); + ms_w_layout->setMargin(0); + +#ifdef LMMS_HAVE_ALSA + m_midiIfaceSetupWidgets[MidiAlsaSeq::name()] = + MidiSetupWidget::create(ms_w); + m_midiIfaceSetupWidgets[MidiAlsaRaw::name()] = + MidiSetupWidget::create(ms_w); +#endif + +#ifdef LMMS_HAVE_JACK + m_midiIfaceSetupWidgets[MidiJack::name()] = + MidiSetupWidget::create(ms_w); +#endif + +#ifdef LMMS_HAVE_OSS + m_midiIfaceSetupWidgets[MidiOss::name()] = + MidiSetupWidget::create(ms_w); +#endif + +#ifdef LMMS_HAVE_SNDIO + m_midiIfaceSetupWidgets[MidiSndio::name()] = + MidiSetupWidget::create(ms_w); +#endif + +#ifdef LMMS_BUILD_WIN32 + m_midiIfaceSetupWidgets[MidiWinMM::name()] = + MidiSetupWidget::create(ms_w); +#endif + +#ifdef LMMS_BUILD_APPLE + m_midiIfaceSetupWidgets[MidiApple::name()] = + MidiSetupWidget::create(ms_w); +#endif + + m_midiIfaceSetupWidgets[MidiDummy::name()] = + MidiSetupWidget::create(ms_w); + + + for(MswMap::iterator it = m_midiIfaceSetupWidgets.begin(); + it != m_midiIfaceSetupWidgets.end(); ++it) + { + m_midiIfaceNames[ + tr(it.key().toLatin1())] = it.key(); + } + for(trMap::iterator it = m_midiIfaceNames.begin(); + it != m_midiIfaceNames.end(); ++it) + { + QWidget * midiWidget = m_midiIfaceSetupWidgets[it.value()]; + midiWidget->hide(); + ms_w_layout->addWidget(midiWidget); + m_midiInterfaces->addItem(it.key()); + } + + QString midiDevName = ConfigManager::inst()->value("mixer", "mididev"); + if (m_midiInterfaces->findText(midiDevName) < 0) + { + midiDevName = Engine::mixer()->midiClientName(); + ConfigManager::inst()->setValue("mixer", "mididev", midiDevName); + } + m_midiInterfaces->setCurrentIndex(m_midiInterfaces->findText(midiDevName)); + m_midiIfaceSetupWidgets[midiDevName]->show(); + + connect(m_midiInterfaces, SIGNAL(activated(const QString &)), + this, SLOT(midiInterfaceChanged(const QString &))); + + + // MIDI layout ordering. + midi_layout->addWidget(midiiface_tw); + midi_layout->addWidget(ms_w); + midi_layout->addStretch(); + + + + // Paths widget. + QWidget * paths_w = new QWidget(settings_w); + + QVBoxLayout * paths_layout = new QVBoxLayout(paths_w); + paths_layout->setSpacing(10); + paths_layout->setMargin(0); + + labelWidget(paths_w, tr("Paths")); + + + // Paths scroll area. + QScrollArea * pathsScroll = new QScrollArea(paths_w); + pathsScroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + pathsScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + // Path selectors widget. + QWidget * pathSelectors = new QWidget(paths_w); const int txtLength = 284; - const int btnStart = 297; + const int btnStart = 300; + // Path selectors layout. + QVBoxLayout * pathSelectorsLayout = new QVBoxLayout; + pathSelectorsLayout->setSpacing(10); auto addPathEntry = [&](const char* caption, const QString& content, const char* setSlot, const char* openSlot, QLineEdit*& lineEdit, - QWidget* twParent, const char* pixmap = "project_open") { - TabWidget * newTw = new TabWidget(tr(caption).toUpper(), - twParent); + TabWidget * newTw = new TabWidget(tr(caption), + pathSelectors); newTw->setFixedHeight(48); lineEdit = new QLineEdit(content, newTw); @@ -401,397 +728,122 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : selectBtn->move(btnStart, 16); connect(selectBtn, SIGNAL(clicked()), this, openSlot); - pathSelectorLayout->addWidget(newTw); - pathSelectorLayout->addSpacing(10); + pathSelectorsLayout->addWidget(newTw); + pathSelectorsLayout->addSpacing(10); }; addPathEntry("LMMS working directory", m_workingDir, SLOT(setWorkingDir(const QString &)), SLOT(openWorkingDir()), - m_wdLineEdit, pathSelectors); - addPathEntry("GIG directory", m_gigDir, - SLOT(setGIGDir(const QString &)), - SLOT(openGIGDir()), - m_gigLineEdit, pathSelectors); + m_workingDirLineEdit); + addPathEntry("VST plugins directory", m_vstDir, + SLOT(setVSTDir(const QString &)), + SLOT(openVSTDir()), + m_vstDirLineEdit); + addPathEntry("LADSPA plugins directories", m_ladspaDir, + SLOT(setLADSPADir(const QString &)), + SLOT(openLADSPADir()), + m_ladspaDirLineEdit, "add_folder"); addPathEntry("SF2 directory", m_sf2Dir, SLOT(setSF2Dir(const QString &)), SLOT(openSF2Dir()), - m_sf2LineEdit, pathSelectors); - addPathEntry("VST-plugin directory", m_vstDir, - SLOT(setVSTDir(const QString &)), - SLOT(openVSTDir()), - m_vdLineEdit, pathSelectors); - addPathEntry("LADSPA plugin directories", m_ladDir, - SLOT(setLADSPADir(const QString &)), - SLOT(openLADSPADir()), - m_ladLineEdit, paths, - "add_folder"); -#ifdef LMMS_HAVE_STK - addPathEntry("STK rawwave directory", m_stkDir, - SLOT(setSTKDir(const QString &)), - SLOT(openSTKDir()), - m_stkLineEdit, paths); -#endif + m_sf2DirLineEdit); #ifdef LMMS_HAVE_FLUIDSYNTH - addPathEntry("Default Soundfont File", m_defaultSoundfont, - SLOT(setDefaultSoundfont(const QString &)), - SLOT(openDefaultSoundfont()), - m_sfLineEdit, paths); + addPathEntry("Default SF2", m_sf2File, + SLOT(setSF2File(const QString &)), + SLOT(openSF2File()), + m_sf2FileLineEdit); #endif - addPathEntry("Themes directory", m_artworkDir, - SLOT(setArtworkDir(const QString &)), - SLOT(openArtworkDir()), - m_adLineEdit, pathSelectors); - pathSelectorLayout->addStretch(); - addPathEntry("Background artwork", m_backgroundArtwork, - SLOT(setBackgroundArtwork(const QString &)), - SLOT(openBackgroundArtwork()), - m_baLineEdit, paths); - pathSelectors->setLayout(pathSelectorLayout); - - - dir_layout->addWidget(pathSelectors); - - pathScroll->setWidget(pathSelectors); - pathScroll->setWidgetResizable(true); - - - - QWidget * performance = new QWidget( ws ); - performance->setFixedSize( 360, 200 ); - QVBoxLayout * perf_layout = new QVBoxLayout( performance ); - perf_layout->setSpacing( 0 ); - perf_layout->setMargin( 0 ); - labelWidget( performance, tr( "Performance settings" ) ); - - - TabWidget * auto_save_tw = new TabWidget( - tr( "Auto save" ).toUpper(), performance ); - auto_save_tw->setFixedHeight( 110 ); - - m_saveIntervalSlider = new QSlider( Qt::Horizontal, auto_save_tw ); - m_saveIntervalSlider->setRange( 1, 20 ); - m_saveIntervalSlider->setTickPosition( QSlider::TicksBelow ); - m_saveIntervalSlider->setPageStep( 1 ); - m_saveIntervalSlider->setTickInterval( 1 ); - m_saveIntervalSlider->setGeometry( 10, 16, 340, 18 ); - m_saveIntervalSlider->setValue( m_saveInterval ); - - connect( m_saveIntervalSlider, SIGNAL( valueChanged( int ) ), this, - SLOT( setAutoSaveInterval( int ) ) ); - - m_saveIntervalLbl = new QLabel( auto_save_tw ); - m_saveIntervalLbl->setGeometry( 10, 40, 200, 24 ); - setAutoSaveInterval( m_saveIntervalSlider->value() ); - - m_autoSave = new LedCheckBox( - tr( "Enable auto-save" ), auto_save_tw ); - m_autoSave->move( 10, 70 ); - m_autoSave->setChecked( m_enableAutoSave ); - connect( m_autoSave, SIGNAL( toggled( bool ) ), - this, SLOT( toggleAutoSave( bool ) ) ); - - m_runningAutoSave = new LedCheckBox( - tr( "Allow auto-save while playing" ), auto_save_tw ); - m_runningAutoSave->move( 20, 90 ); - m_runningAutoSave->setChecked( m_enableRunningAutoSave ); - connect( m_runningAutoSave, SIGNAL( toggled( bool ) ), - this, SLOT( toggleRunningAutoSave( bool ) ) ); - - QPushButton * autoSaveResetBtn = new QPushButton( - embed::getIconPixmap( "reload" ), "", auto_save_tw ); - autoSaveResetBtn->setGeometry( 320, 70, 28, 28 ); - connect( autoSaveResetBtn, SIGNAL( clicked() ), this, - SLOT( resetAutoSave() ) ); - ToolTip::add( autoSaveResetBtn, tr( "Reset to default value" ) ); - - m_saveIntervalSlider->setEnabled( m_enableAutoSave ); - m_runningAutoSave->setVisible( m_enableAutoSave ); - - - perf_layout->addWidget( auto_save_tw ); - perf_layout->addSpacing( 10 ); - - - TabWidget * ui_fx_tw = new TabWidget( tr( "UI effects vs. " - "performance" ).toUpper(), - performance ); - ui_fx_tw->setFixedHeight( 70 ); - - LedCheckBox * smoothScroll = new LedCheckBox( - tr( "Smooth scroll in Song Editor" ), ui_fx_tw ); - smoothScroll->move( 10, 20 ); - smoothScroll->setChecked( m_smoothScroll ); - connect( smoothScroll, SIGNAL( toggled( bool ) ), - this, SLOT( toggleSmoothScroll( bool ) ) ); - - LedCheckBox * animAFP = new LedCheckBox( - tr( "Show playback cursor in AudioFileProcessor" ), - ui_fx_tw ); - animAFP->move( 10, 40 ); - animAFP->setChecked( m_animateAFP ); - connect( animAFP, SIGNAL( toggled( bool ) ), - this, SLOT( toggleAnimateAFP( bool ) ) ); - - - - perf_layout->addWidget( ui_fx_tw ); - perf_layout->addStretch(); - - - - QWidget * audio = new QWidget( ws ); - audio->setFixedSize( 360, 200 ); - QVBoxLayout * audio_layout = new QVBoxLayout( audio ); - audio_layout->setSpacing( 0 ); - audio_layout->setMargin( 0 ); - labelWidget( audio, tr( "Audio settings" ) ); - - TabWidget * audioiface_tw = new TabWidget( tr( "AUDIO INTERFACE" ), - audio ); - audioiface_tw->setFixedHeight( 60 ); - - m_audioInterfaces = new QComboBox( audioiface_tw ); - m_audioInterfaces->setGeometry( 10, 20, 240, 22 ); - - - // create ifaces-settings-widget - QWidget * asw = new QWidget( audio ); - asw->setFixedHeight( 60 ); - - QHBoxLayout * asw_layout = new QHBoxLayout( asw ); - asw_layout->setSpacing( 0 ); - asw_layout->setMargin( 0 ); - //asw_layout->setAutoAdd( true ); - -#ifdef LMMS_HAVE_JACK - m_audioIfaceSetupWidgets[AudioJack::name()] = - new AudioJack::setupWidget( asw ); -#endif - -#ifdef LMMS_HAVE_ALSA - m_audioIfaceSetupWidgets[AudioAlsa::name()] = - new AudioAlsaSetupWidget( asw ); -#endif - -#ifdef LMMS_HAVE_PULSEAUDIO - m_audioIfaceSetupWidgets[AudioPulseAudio::name()] = - new AudioPulseAudio::setupWidget( asw ); -#endif - -#ifdef LMMS_HAVE_PORTAUDIO - m_audioIfaceSetupWidgets[AudioPortAudio::name()] = - new AudioPortAudio::setupWidget( asw ); -#endif - -#ifdef LMMS_HAVE_SOUNDIO - m_audioIfaceSetupWidgets[AudioSoundIo::name()] = - new AudioSoundIo::setupWidget( asw ); -#endif - -#ifdef LMMS_HAVE_SDL - m_audioIfaceSetupWidgets[AudioSdl::name()] = - new AudioSdl::setupWidget( asw ); -#endif - -#ifdef LMMS_HAVE_OSS - m_audioIfaceSetupWidgets[AudioOss::name()] = - new AudioOss::setupWidget( asw ); -#endif - -#ifdef LMMS_HAVE_SNDIO - m_audioIfaceSetupWidgets[AudioSndio::name()] = - new AudioSndio::setupWidget( asw ); -#endif - m_audioIfaceSetupWidgets[AudioDummy::name()] = - new AudioDummy::setupWidget( asw ); - - - for( AswMap::iterator it = m_audioIfaceSetupWidgets.begin(); - it != m_audioIfaceSetupWidgets.end(); ++it ) - { - m_audioIfaceNames[tr( it.key().toLatin1())] = it.key(); - } - for( trMap::iterator it = m_audioIfaceNames.begin(); - it != m_audioIfaceNames.end(); ++it ) - { - QWidget * audioWidget = m_audioIfaceSetupWidgets[it.value()]; - audioWidget->hide(); - asw_layout->addWidget( audioWidget ); - m_audioInterfaces->addItem( it.key() ); - } - - // If no preferred audio device is saved, save the current one - QString audioDevName = - ConfigManager::inst()->value( "mixer", "audiodev" ); - if( m_audioInterfaces->findText(audioDevName) < 0 ) - { - audioDevName = Engine::mixer()->audioDevName(); - ConfigManager::inst()->setValue( - "mixer", "audiodev", audioDevName ); - } - m_audioInterfaces-> - setCurrentIndex( m_audioInterfaces->findText( audioDevName ) ); - m_audioIfaceSetupWidgets[audioDevName]->show(); - - connect( m_audioInterfaces, SIGNAL( activated( const QString & ) ), - this, SLOT( audioInterfaceChanged( const QString & ) ) ); - - - audio_layout->addWidget( audioiface_tw ); - audio_layout->addSpacing( 20 ); - audio_layout->addWidget( asw ); - audio_layout->addStretch(); - - - - QWidget * midi = new QWidget( ws ); - QVBoxLayout * midi_layout = new QVBoxLayout( midi ); - midi_layout->setSpacing( 0 ); - midi_layout->setMargin( 0 ); - labelWidget( midi, tr( "MIDI settings" ) ); - - TabWidget * midiiface_tw = new TabWidget( tr( "MIDI INTERFACE" ), - midi ); - midiiface_tw->setFixedHeight( 60 ); - - m_midiInterfaces = new QComboBox( midiiface_tw ); - m_midiInterfaces->setGeometry( 10, 20, 240, 22 ); - - - // create ifaces-settings-widget - QWidget * msw = new QWidget( midi ); - msw->setFixedHeight( 60 ); - - QHBoxLayout * msw_layout = new QHBoxLayout( msw ); - msw_layout->setSpacing( 0 ); - msw_layout->setMargin( 0 ); - //msw_layout->setAutoAdd( true ); - -#ifdef LMMS_HAVE_ALSA - m_midiIfaceSetupWidgets[MidiAlsaSeq::name()] = - MidiSetupWidget::create( msw ); - m_midiIfaceSetupWidgets[MidiAlsaRaw::name()] = - MidiSetupWidget::create( msw ); -#endif - -#ifdef LMMS_HAVE_JACK - m_midiIfaceSetupWidgets[MidiJack::name()] = - MidiSetupWidget::create( msw ); -#endif - -#ifdef LMMS_HAVE_OSS - m_midiIfaceSetupWidgets[MidiOss::name()] = - MidiSetupWidget::create( msw ); -#endif - -#ifdef LMMS_HAVE_SNDIO - m_midiIfaceSetupWidgets[MidiSndio::name()] = - MidiSetupWidget::create( msw ); -#endif - -#ifdef LMMS_BUILD_WIN32 - m_midiIfaceSetupWidgets[MidiWinMM::name()] = - MidiSetupWidget::create( msw ); -#endif - -#ifdef LMMS_BUILD_APPLE - m_midiIfaceSetupWidgets[MidiApple::name()] = - MidiSetupWidget::create( msw ); -#endif - - m_midiIfaceSetupWidgets[MidiDummy::name()] = - MidiSetupWidget::create( msw ); - - - for( MswMap::iterator it = m_midiIfaceSetupWidgets.begin(); - it != m_midiIfaceSetupWidgets.end(); ++it ) - { - m_midiIfaceNames[tr( it.key().toLatin1())] = it.key(); - } - for( trMap::iterator it = m_midiIfaceNames.begin(); - it != m_midiIfaceNames.end(); ++it ) - { - QWidget * midiWidget = m_midiIfaceSetupWidgets[it.value()]; - midiWidget->hide(); - msw_layout->addWidget( midiWidget ); - m_midiInterfaces->addItem( it.key() ); - } - - QString midiDevName = - ConfigManager::inst()->value( "mixer", "mididev" ); - if( m_midiInterfaces->findText(midiDevName) < 0 ) - { - midiDevName = Engine::mixer()->midiClientName(); - ConfigManager::inst()->setValue( - "mixer", "mididev", midiDevName ); - } - m_midiInterfaces->setCurrentIndex( - m_midiInterfaces->findText( midiDevName ) ); - m_midiIfaceSetupWidgets[midiDevName]->show(); - - connect( m_midiInterfaces, SIGNAL( activated( const QString & ) ), - this, SLOT( midiInterfaceChanged( const QString & ) ) ); - - - midi_layout->addWidget( midiiface_tw ); - midi_layout->addSpacing( 20 ); - midi_layout->addWidget( msw ); - midi_layout->addStretch(); - - - m_tabBar->addTab( general, tr( "General settings" ), 0, false, true - )->setIcon( embed::getIconPixmap( "setup_general" ) ); - m_tabBar->addTab( paths, tr( "Paths" ), 1, false, true - )->setIcon( embed::getIconPixmap( - "setup_directories" ) ); - m_tabBar->addTab( performance, tr( "Performance settings" ), 2, false, - true )->setIcon( embed::getIconPixmap( - "setup_performance" ) ); - m_tabBar->addTab( audio, tr( "Audio settings" ), 3, false, true - )->setIcon( embed::getIconPixmap( "setup_audio" ) ); - m_tabBar->addTab( midi, tr( "MIDI settings" ), 4, true, true - )->setIcon( embed::getIconPixmap( "setup_midi" ) ); - - - m_tabBar->setActiveTab( _tab_to_open ); - - hlayout->addWidget( m_tabBar ); - hlayout->addSpacing( 10 ); - hlayout->addWidget( ws ); - hlayout->addSpacing( 10 ); - hlayout->addStretch(); - - QWidget * buttons = new QWidget( this ); - QHBoxLayout * btn_layout = new QHBoxLayout( buttons ); - btn_layout->setSpacing( 0 ); - btn_layout->setMargin( 0 ); - QPushButton * ok_btn = new QPushButton( embed::getIconPixmap( "apply" ), - tr( "OK" ), buttons ); - connect( ok_btn, SIGNAL( clicked() ), this, SLOT( accept() ) ); - - QPushButton * cancel_btn = new QPushButton( embed::getIconPixmap( - "cancel" ), - tr( "Cancel" ), - buttons ); - connect( cancel_btn, SIGNAL( clicked() ), this, SLOT( reject() ) ); - - btn_layout->addStretch(); - btn_layout->addSpacing( 10 ); - btn_layout->addWidget( ok_btn ); - btn_layout->addSpacing( 10 ); - btn_layout->addWidget( cancel_btn ); - btn_layout->addSpacing( 10 ); - - vlayout->addWidget( settings ); - vlayout->addSpacing( 10 ); - vlayout->addWidget( buttons ); - vlayout->addSpacing( 10 ); - vlayout->addStretch(); + addPathEntry("GIG directory", m_gigDir, + SLOT(setGIGDir(const QString &)), + SLOT(openGIGDir()), + m_gigDirLineEdit); + addPathEntry("Theme directory", m_themeDir, + SLOT(setThemeDir(const QString &)), + SLOT(openThemeDir()), + m_themeDirLineEdit); + addPathEntry("Background artwork", m_backgroundPicFile, + SLOT(setBackgroundPicFile(const QString &)), + SLOT(openBackgroundPicFile()), + m_backgroundPicFileLineEdit); + + pathSelectorsLayout->addStretch(); + + pathSelectors->setLayout(pathSelectorsLayout); + + pathsScroll->setWidget(pathSelectors); + pathsScroll->setWidgetResizable(true); + + paths_layout->addWidget(pathsScroll); + paths_layout->addStretch(); + + // Major tabs ordering. + m_tabBar->addTab(general_w, + tr("General"), 0, false, true)->setIcon( + embed::getIconPixmap("setup_general")); + m_tabBar->addTab(performance_w, + tr("Performance"), 1, false, true)->setIcon( + embed::getIconPixmap("setup_performance")); + m_tabBar->addTab(audio_w, + tr("Audio"), 2, false, true)->setIcon( + embed::getIconPixmap("setup_audio")); + m_tabBar->addTab(midi_w, + tr("MIDI"), 3, false, true)->setIcon( + embed::getIconPixmap("setup_midi")); + m_tabBar->addTab(paths_w, + tr("Paths"), 4, true, true)->setIcon( + embed::getIconPixmap("setup_directories")); + + m_tabBar->setActiveTab(tab_to_open); + + // Horizontal layout ordering. + hlayout->addSpacing(2); + hlayout->addWidget(m_tabBar); + hlayout->addSpacing(10); + hlayout->addWidget(settings_w); + hlayout->addSpacing(10); + + // Extras widget and layout. + QWidget * extras_w = new QWidget(this); + QHBoxLayout * extras_layout = new QHBoxLayout(extras_w); + extras_layout->setSpacing(0); + extras_layout->setMargin(0); + + // Restart warning label. + restartWarningLbl = new QLabel( + tr("Some changes require restarting."), extras_w); + restartWarningLbl->hide(); + + // OK button. + QPushButton * ok_btn = new QPushButton( + embed::getIconPixmap("apply"), + tr("OK"), extras_w); + connect(ok_btn, SIGNAL(clicked()), + this, SLOT(accept())); + + // Cancel button. + QPushButton * cancel_btn = new QPushButton( + embed::getIconPixmap("cancel"), + tr("Cancel"), extras_w); + connect(cancel_btn, SIGNAL(clicked()), + this, SLOT(reject())); + + // Extras layout ordering. + extras_layout->addSpacing(10); + extras_layout->addWidget(restartWarningLbl); + extras_layout->addStretch(); + extras_layout->addWidget(ok_btn); + extras_layout->addSpacing(10); + extras_layout->addWidget(cancel_btn); + extras_layout->addSpacing(10); + + // Vertical layout ordering. + vlayout->addWidget(main_w); + vlayout->addSpacing(10); + vlayout->addWidget(extras_w); + vlayout->addSpacing(10); show(); - - } @@ -799,7 +851,7 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : SetupDialog::~SetupDialog() { - Engine::projectJournal()->setJournalling( true ); + Engine::projectJournal()->setJournalling(true); } @@ -807,286 +859,146 @@ SetupDialog::~SetupDialog() void SetupDialog::accept() { - if( m_warnAfterSetup ) - { - QMessageBox::information( NULL, tr( "Restart LMMS" ), - tr( "Please note that most changes " - "won't take effect until " - "you restart LMMS!" ), - QMessageBox::Ok ); - } - - // Hide dialog before setting values. This prevents an obscure bug - // where non-embedded VST windows would steal focus and prevent LMMS - // from taking mouse input, rendering the application unusable. + /* Hide dialog before setting values. This prevents an obscure bug + where non-embedded VST windows would steal focus and prevent LMMS + from taking mouse input, rendering the application unusable. */ QDialog::accept(); - ConfigManager::inst()->setValue( "mixer", "framesperaudiobuffer", - QString::number( m_bufferSize ) ); - ConfigManager::inst()->setValue( "mixer", "audiodev", - m_audioIfaceNames[m_audioInterfaces->currentText()] ); - ConfigManager::inst()->setValue( "mixer", "mididev", - m_midiIfaceNames[m_midiInterfaces->currentText()] ); - ConfigManager::inst()->setValue( "tooltips", "disabled", - QString::number( !m_toolTips ) ); - ConfigManager::inst()->setValue( "app", "nomsgaftersetup", - QString::number( !m_warnAfterSetup ) ); - ConfigManager::inst()->setValue( "app", "displaydbfs", - QString::number( m_displaydBFS ) ); - ConfigManager::inst()->setValue( "app", "nommpz", - QString::number( !m_MMPZ ) ); - ConfigManager::inst()->setValue( "app", "disablebackup", - QString::number( !m_disableBackup ) ); - ConfigManager::inst()->setValue( "app", "openlastproject", - QString::number( m_openLastProject ) ); - ConfigManager::inst()->setValue( "app", "nanhandler", - QString::number( m_NaNHandler ) ); - ConfigManager::inst()->setValue( "mixer", "hqaudio", - QString::number( m_hqAudioDev ) ); - ConfigManager::inst()->setValue( "ui", "smoothscroll", - QString::number( m_smoothScroll ) ); - ConfigManager::inst()->setValue( "ui", "enableautosave", - QString::number( m_enableAutoSave ) ); - ConfigManager::inst()->setValue( "ui", "saveinterval", - QString::number( m_saveInterval ) ); - ConfigManager::inst()->setValue( "ui", "enablerunningautosave", - QString::number( m_enableRunningAutoSave ) ); - ConfigManager::inst()->setValue( "ui", "oneinstrumenttrackwindow", - QString::number( m_oneInstrumentTrackWindow ) ); - ConfigManager::inst()->setValue( "ui", "compacttrackbuttons", - QString::number( m_compactTrackButtons ) ); - ConfigManager::inst()->setValue( "ui", "syncvstplugins", - QString::number( m_syncVSTPlugins ) ); - ConfigManager::inst()->setValue( "ui", "animateafp", - QString::number( m_animateAFP ) ); - ConfigManager::inst()->setValue( "ui", "printnotelabels", - QString::number( m_printNoteLabels ) ); - ConfigManager::inst()->setValue( "ui", "displaywaveform", - QString::number( m_displayWaveform ) ); - ConfigManager::inst()->setValue( "ui", "disableautoquit", - QString::number( m_disableAutoQuit ) ); - ConfigManager::inst()->setValue( "app", "language", m_lang ); - ConfigManager::inst()->setValue( "ui", "vstembedmethod", - m_vstEmbedMethod ); - ConfigManager::inst()->setValue( "ui", "vstalwaysontop", - QString::number( m_vstAlwaysOnTop ) ); + ConfigManager::inst()->setValue("app", "displaydbfs", + QString::number(m_displaydBFS)); + ConfigManager::inst()->setValue("tooltips", "disabled", + QString::number(!m_tooltips)); + ConfigManager::inst()->setValue("ui", "displaywaveform", + QString::number(m_displayWaveform)); + ConfigManager::inst()->setValue("ui", "printnotelabels", + QString::number(m_printNoteLabels)); + ConfigManager::inst()->setValue("ui", "compacttrackbuttons", + QString::number(m_compactTrackButtons)); + ConfigManager::inst()->setValue("ui", "oneinstrumenttrackwindow", + QString::number(m_oneInstrumentTrackWindow)); + ConfigManager::inst()->setValue("app", "nommpz", + QString::number(!m_MMPZ)); + ConfigManager::inst()->setValue("app", "disablebackup", + QString::number(!m_disableBackup)); + ConfigManager::inst()->setValue("app", "openlastproject", + QString::number(m_openLastProject)); + ConfigManager::inst()->setValue("app", "language", m_lang); + ConfigManager::inst()->setValue("ui", "saveinterval", + QString::number(m_saveInterval)); + ConfigManager::inst()->setValue("ui", "enableautosave", + QString::number(m_enableAutoSave)); + ConfigManager::inst()->setValue("ui", "enablerunningautosave", + QString::number(m_enableRunningAutoSave)); + ConfigManager::inst()->setValue("ui", "smoothscroll", + QString::number(m_smoothScroll)); + ConfigManager::inst()->setValue("ui", "animateafp", + QString::number(m_animateAFP)); + ConfigManager::inst()->setValue("ui", "vstembedmethod", + m_vstEmbedComboBox->currentData().toString()); + ConfigManager::inst()->setValue("ui", "vstalwaysontop", + QString::number(m_vstAlwaysOnTop)); + ConfigManager::inst()->setValue("ui", "syncvstplugins", + QString::number(m_syncVSTPlugins)); + ConfigManager::inst()->setValue("ui", "disableautoquit", + QString::number(m_disableAutoQuit)); + ConfigManager::inst()->setValue("mixer", "audiodev", + m_audioIfaceNames[m_audioInterfaces->currentText()]); + ConfigManager::inst()->setValue("app", "nanhandler", + QString::number(m_NaNHandler)); + ConfigManager::inst()->setValue("mixer", "hqaudio", + QString::number(m_hqAudioDev)); + ConfigManager::inst()->setValue("mixer", "framesperaudiobuffer", + QString::number(m_bufferSize)); + ConfigManager::inst()->setValue("mixer", "mididev", + m_midiIfaceNames[m_midiInterfaces->currentText()]); ConfigManager::inst()->setWorkingDir(QDir::fromNativeSeparators(m_workingDir)); ConfigManager::inst()->setVSTDir(QDir::fromNativeSeparators(m_vstDir)); - ConfigManager::inst()->setGIGDir(QDir::fromNativeSeparators(m_gigDir)); + ConfigManager::inst()->setLADSPADir(QDir::fromNativeSeparators(m_ladspaDir)); ConfigManager::inst()->setSF2Dir(QDir::fromNativeSeparators(m_sf2Dir)); - ConfigManager::inst()->setArtworkDir(QDir::fromNativeSeparators(m_artworkDir)); - ConfigManager::inst()->setLADSPADir(QDir::fromNativeSeparators(m_ladDir)); #ifdef LMMS_HAVE_FLUIDSYNTH - ConfigManager::inst()->setDefaultSoundfont( m_defaultSoundfont ); + ConfigManager::inst()->setSF2File(m_sf2File); #endif -#ifdef LMMS_HAVE_STK - ConfigManager::inst()->setSTKDir(QDir::fromNativeSeparators(m_stkDir)); -#endif - ConfigManager::inst()->setBackgroundArtwork( m_backgroundArtwork ); + ConfigManager::inst()->setGIGDir(QDir::fromNativeSeparators(m_gigDir)); + ConfigManager::inst()->setThemeDir(QDir::fromNativeSeparators(m_themeDir)); + ConfigManager::inst()->setBackgroundPicFile(m_backgroundPicFile); - // tell all audio-settings-widget to save their settings - for( AswMap::iterator it = m_audioIfaceSetupWidgets.begin(); - it != m_audioIfaceSetupWidgets.end(); ++it ) + // Tell all audio-settings-widgets to save their settings. + for(AswMap::iterator it = m_audioIfaceSetupWidgets.begin(); + it != m_audioIfaceSetupWidgets.end(); ++it) { it.value()->saveSettings(); } - // tell all MIDI-settings-widget to save their settings - for( MswMap::iterator it = m_midiIfaceSetupWidgets.begin(); - it != m_midiIfaceSetupWidgets.end(); ++it ) + // Tell all MIDI-settings-widgets to save their settings. + for(MswMap::iterator it = m_midiIfaceSetupWidgets.begin(); + it != m_midiIfaceSetupWidgets.end(); ++it) { it.value()->saveSettings(); } - ConfigManager::inst()->saveConfigFile(); } -void SetupDialog::setBufferSize( int _value ) +// General settings slots. + +void SetupDialog::toggleDisplaydBFS(bool enabled) { - const int step = DEFAULT_BUFFER_SIZE / BUFFERSIZE_RESOLUTION; - if( _value > step && _value % step ) - { - int mod_value = _value % step; - if( mod_value < step / 2 ) - { - m_bufSizeSlider->setValue( _value - mod_value ); - } - else - { - m_bufSizeSlider->setValue( _value + step - mod_value ); - } - return; - } - - if( m_bufSizeSlider->value() != _value ) - { - m_bufSizeSlider->setValue( _value ); - } - - m_bufferSize = _value * BUFFERSIZE_RESOLUTION; - m_bufSizeLbl->setText( tr( "Frames: %1\nLatency: %2 ms" ).arg( - m_bufferSize ).arg( - 1000.0f * m_bufferSize / - Engine::mixer()->processingSampleRate(), - 0, 'f', 1 ) ); + m_displaydBFS = enabled; } - - -void SetupDialog::resetBufSize() +void SetupDialog::toggleTooltips(bool enabled) { - setBufferSize( DEFAULT_BUFFER_SIZE / BUFFERSIZE_RESOLUTION ); + m_tooltips = enabled; } - - -void SetupDialog::toggleToolTips( bool _enabled ) +void SetupDialog::toggleDisplayWaveform(bool enabled) { - m_toolTips = _enabled; + m_displayWaveform = enabled; } - - -void SetupDialog::toggleWarnAfterSetup( bool _enabled ) +void SetupDialog::toggleNoteLabels(bool enabled) { - m_warnAfterSetup = _enabled; + m_printNoteLabels = enabled; } - - -void SetupDialog::toggleDisplaydBFS( bool _enabled ) +void SetupDialog::toggleCompactTrackButtons(bool enabled) { - m_displaydBFS = _enabled; + m_compactTrackButtons = enabled; } - - -void SetupDialog::toggleMMPZ( bool _enabled ) +void SetupDialog::toggleOneInstrumentTrackWindow(bool enabled) { - m_MMPZ = _enabled; + m_oneInstrumentTrackWindow = enabled; } - - -void SetupDialog::toggleDisableBackup( bool _enabled ) +void SetupDialog::toggleMMPZ(bool enabled) { - m_disableBackup = _enabled; + m_MMPZ = enabled; } - - -void SetupDialog::toggleOpenLastProject( bool _enabled ) +void SetupDialog::toggleDisableBackup(bool enabled) { - m_openLastProject = _enabled; + m_disableBackup = enabled; } - - -void SetupDialog::toggleHQAudioDev( bool _enabled ) +void SetupDialog::toggleOpenLastProject(bool enabled) { - m_hqAudioDev = _enabled; + m_openLastProject = enabled; } - - -void SetupDialog::toggleSmoothScroll( bool _enabled ) -{ - m_smoothScroll = _enabled; -} - - - - -void SetupDialog::toggleAutoSave( bool _enabled ) -{ - m_enableAutoSave = _enabled; - m_saveIntervalSlider->setEnabled( _enabled ); - m_runningAutoSave->setVisible( _enabled ); - setAutoSaveInterval( m_saveIntervalSlider->value() ); -} - - - - -void SetupDialog::toggleRunningAutoSave( bool _enabled ) -{ - m_enableRunningAutoSave = _enabled; -} - - - - -void SetupDialog::toggleCompactTrackButtons( bool _enabled ) -{ - m_compactTrackButtons = _enabled; -} - - - - - -void SetupDialog::toggleSyncVSTPlugins( bool _enabled ) -{ - m_syncVSTPlugins = _enabled; -} - -void SetupDialog::toggleAnimateAFP( bool _enabled ) -{ - m_animateAFP = _enabled; -} - - -void SetupDialog::toggleNoteLabels( bool en ) -{ - m_printNoteLabels = en; -} - - -void SetupDialog::toggleDisplayWaveform( bool en ) -{ - m_displayWaveform = en; -} - - -void SetupDialog::toggleDisableAutoquit( bool en ) -{ - m_disableAutoQuit = en; -} - - -void SetupDialog::toggleOneInstrumentTrackWindow( bool _enabled ) -{ - m_oneInstrumentTrackWindow = _enabled; -} - - -void SetupDialog::vstEmbedMethodChanged() -{ - m_vstEmbedMethod = m_vstEmbedComboBox->currentData().toString(); - m_vstAlwaysOnTopCheckBox->setVisible( m_vstEmbedMethod == "none" ); -} - - -void SetupDialog::toggleVSTAlwaysOnTop( bool en ) -{ - m_vstAlwaysOnTop = en; -} - - -void SetupDialog::setLanguage( int lang ) +void SetupDialog::setLanguage(int lang) { m_lang = m_languages[lang]; } @@ -1094,270 +1006,322 @@ void SetupDialog::setLanguage( int lang ) +// Performance settings slots. -void SetupDialog::openWorkingDir() -{ - QString new_dir = FileDialog::getExistingDirectory( this, - tr( "Choose LMMS working directory" ), m_workingDir ); - if( ! new_dir.isEmpty() ) - { - m_wdLineEdit->setText( new_dir ); - } -} - -void SetupDialog::openGIGDir() -{ - QString new_dir = FileDialog::getExistingDirectory( this, - tr( "Choose your GIG directory" ), - m_gigDir ); - if( ! new_dir.isEmpty() ) - { - m_gigLineEdit->setText( new_dir ); - } -} - -void SetupDialog::openSF2Dir() -{ - QString new_dir = FileDialog::getExistingDirectory( this, - tr( "Choose your SF2 directory" ), - m_sf2Dir ); - if( ! new_dir.isEmpty() ) - { - m_sf2LineEdit->setText( new_dir ); - } -} - - - - -void SetupDialog::setWorkingDir( const QString & _wd ) -{ - m_workingDir = _wd; -} - - - - -void SetupDialog::openVSTDir() -{ - QString new_dir = FileDialog::getExistingDirectory( this, - tr( "Choose your VST-plugin directory" ), - m_vstDir ); - if( ! new_dir.isEmpty() ) - { - m_vdLineEdit->setText( new_dir ); - } -} - - - - -void SetupDialog::setVSTDir( const QString & _vd ) -{ - m_vstDir = _vd; -} - -void SetupDialog::setGIGDir(const QString &_gd) -{ - m_gigDir = _gd; -} - -void SetupDialog::setSF2Dir(const QString &_sfd) -{ - m_sf2Dir = _sfd; -} - - - - -void SetupDialog::openArtworkDir() -{ - QString new_dir = FileDialog::getExistingDirectory( this, - tr( "Choose artwork-theme directory" ), - m_artworkDir ); - if( ! new_dir.isEmpty() ) - { - m_adLineEdit->setText( new_dir ); - } -} - - - - -void SetupDialog::setArtworkDir( const QString & _ad ) -{ - m_artworkDir = _ad; -} - - - - -void SetupDialog::openLADSPADir() -{ - QString new_dir = FileDialog::getExistingDirectory( this, - tr( "Choose LADSPA plugin directory" ), - m_ladDir ); - if( ! new_dir.isEmpty() ) - { - if( m_ladLineEdit->text() == "" ) - { - m_ladLineEdit->setText( new_dir ); - } - else - { - m_ladLineEdit->setText( m_ladLineEdit->text() + "," + - new_dir ); - } - } -} - - - -void SetupDialog::openSTKDir() -{ -#ifdef LMMS_HAVE_STK - QString new_dir = FileDialog::getExistingDirectory( this, - tr( "Choose STK rawwave directory" ), - m_stkDir ); - if( ! new_dir.isEmpty() ) - { - m_stkLineEdit->setText( new_dir ); - } -#endif -} - - - - -void SetupDialog::openDefaultSoundfont() -{ -#ifdef LMMS_HAVE_FLUIDSYNTH - QString new_file = FileDialog::getOpenFileName( this, - tr( "Choose default SoundFont" ), m_defaultSoundfont, - "SoundFont2 Files (*.sf2)" ); - - if( ! new_file.isEmpty() ) - { - m_sfLineEdit->setText( new_file ); - } -#endif -} - - - - -void SetupDialog::openBackgroundArtwork() -{ - QList fileTypesList = QImageReader::supportedImageFormats(); - QString fileTypes; - for( int i = 0; i < fileTypesList.count(); i++ ) - { - if( fileTypesList[i] != fileTypesList[i].toUpper() ) - { - if( !fileTypes.isEmpty() ) - { - fileTypes += " "; - } - fileTypes += "*." + QString( fileTypesList[i] ); - } - } - - QString dir = ( m_backgroundArtwork.isEmpty() ) ? - m_artworkDir : - m_backgroundArtwork; - QString new_file = FileDialog::getOpenFileName( this, - tr( "Choose background artwork" ), dir, - "Image Files (" + fileTypes + ")" ); - - if( ! new_file.isEmpty() ) - { - m_baLineEdit->setText( new_file ); - } -} - - - - -void SetupDialog::setLADSPADir( const QString & _fd ) -{ - m_ladDir = _fd; -} - - - - -void SetupDialog::setSTKDir( const QString & _fd ) -{ -#ifdef LMMS_HAVE_STK - m_stkDir = _fd; -#endif -} - - - - -void SetupDialog::setDefaultSoundfont( const QString & _sf ) -{ -#ifdef LMMS_HAVE_FLUIDSYNTH - m_defaultSoundfont = _sf; -#endif -} - - - - -void SetupDialog::setBackgroundArtwork( const QString & _ba ) -{ - m_backgroundArtwork = _ba; -} - - - - -void SetupDialog::setAutoSaveInterval( int value ) +void SetupDialog::setAutoSaveInterval(int value) { m_saveInterval = value; - m_saveIntervalSlider->setValue( m_saveInterval ); - QString minutes = m_saveInterval > 1 ? tr( "minutes" ) : tr( "minute" ); - minutes = QString( "%1 %2" ).arg( QString::number( m_saveInterval ), minutes ); - minutes = m_enableAutoSave ? minutes : tr( "Disabled" ); - m_saveIntervalLbl->setText( tr( "Auto-save interval: %1" ).arg( minutes ) ); + m_saveIntervalSlider->setValue(m_saveInterval); + QString minutes = m_saveInterval > 1 ? tr("minutes") : tr("minute"); + minutes = QString("%1 %2").arg(QString::number(m_saveInterval), minutes); + minutes = m_enableAutoSave ? minutes : tr("Disabled"); + m_saveIntervalLbl->setText( + tr("Autosave interval: %1").arg(minutes)); } +void SetupDialog::toggleAutoSave(bool enabled) +{ + m_enableAutoSave = enabled; + m_saveIntervalSlider->setEnabled(enabled); + m_runningAutoSave->setVisible(enabled); + setAutoSaveInterval(m_saveIntervalSlider->value()); +} + + +void SetupDialog::toggleRunningAutoSave(bool enabled) +{ + m_enableRunningAutoSave = enabled; +} void SetupDialog::resetAutoSave() { - setAutoSaveInterval( MainWindow::DEFAULT_SAVE_INTERVAL_MINUTES ); - m_autoSave->setChecked( true ); - m_runningAutoSave->setChecked( false ); + setAutoSaveInterval(MainWindow::DEFAULT_SAVE_INTERVAL_MINUTES); + m_autoSave->setChecked(true); + m_runningAutoSave->setChecked(false); +} + + +void SetupDialog::toggleSmoothScroll(bool enabled) +{ + m_smoothScroll = enabled; +} + + +void SetupDialog::toggleAnimateAFP(bool enabled) +{ + m_animateAFP = enabled; +} + + +void SetupDialog::toggleSyncVSTPlugins(bool enabled) +{ + m_syncVSTPlugins = enabled; +} + + +void SetupDialog::vstEmbedMethodChanged() +{ + m_vstEmbedMethod = m_vstEmbedComboBox->currentData().toString(); + m_vstAlwaysOnTopCheckBox->setVisible(m_vstEmbedMethod == "none"); +} + + +void SetupDialog::toggleVSTAlwaysOnTop(bool enabled) +{ + m_vstAlwaysOnTop = enabled; +} + + +void SetupDialog::toggleDisableAutoQuit(bool enabled) +{ + m_disableAutoQuit = enabled; } -void SetupDialog::audioInterfaceChanged( const QString & _iface ) +// Audio settings slots. + +void SetupDialog::toggleHQAudioDev(bool enabled) { - for( AswMap::iterator it = m_audioIfaceSetupWidgets.begin(); - it != m_audioIfaceSetupWidgets.end(); ++it ) + m_hqAudioDev = enabled; +} + + +void SetupDialog::audioInterfaceChanged(const QString & iface) +{ + for(AswMap::iterator it = m_audioIfaceSetupWidgets.begin(); + it != m_audioIfaceSetupWidgets.end(); ++it) { it.value()->hide(); } - m_audioIfaceSetupWidgets[m_audioIfaceNames[_iface]]->show(); + m_audioIfaceSetupWidgets[m_audioIfaceNames[iface]]->show(); } - - -void SetupDialog::midiInterfaceChanged( const QString & _iface ) +void SetupDialog::setBufferSize(int value) { - for( MswMap::iterator it = m_midiIfaceSetupWidgets.begin(); - it != m_midiIfaceSetupWidgets.end(); ++it ) + const int step = DEFAULT_BUFFER_SIZE / BUFFERSIZE_RESOLUTION; + if(value > step && value % step) + { + int mod_value = value % step; + if(mod_value < step / 2) + { + m_bufferSizeSlider->setValue(value - mod_value); + } + else + { + m_bufferSizeSlider->setValue(value + step - mod_value); + } + return; + } + + if(m_bufferSizeSlider->value() != value) + { + m_bufferSizeSlider->setValue(value); + } + + m_bufferSize = value * BUFFERSIZE_RESOLUTION; + m_bufferSizeLbl->setText(tr("Frames: %1\nLatency: %2 ms").arg(m_bufferSize).arg( + 1000.0f * m_bufferSize / Engine::mixer()->processingSampleRate(), 0, 'f', 1)); +} + + +void SetupDialog::resetBufferSize() +{ + setBufferSize(DEFAULT_BUFFER_SIZE / BUFFERSIZE_RESOLUTION); +} + + +// MIDI settings slots. + +void SetupDialog::midiInterfaceChanged(const QString & iface) +{ + for(MswMap::iterator it = m_midiIfaceSetupWidgets.begin(); + it != m_midiIfaceSetupWidgets.end(); ++it) { it.value()->hide(); } - m_midiIfaceSetupWidgets[m_midiIfaceNames[_iface]]->show(); + m_midiIfaceSetupWidgets[m_midiIfaceNames[iface]]->show(); +} + + +// Paths settings slots. + +void SetupDialog::openWorkingDir() +{ + QString new_dir = FileDialog::getExistingDirectory(this, + tr("Choose the LMMS working directory"), m_workingDir); + if (!new_dir.isEmpty()) + { + m_workingDirLineEdit->setText(new_dir); + } +} + + +void SetupDialog::setWorkingDir(const QString & workingDir) +{ + m_workingDir = workingDir; +} + + +void SetupDialog::openVSTDir() +{ + QString new_dir = FileDialog::getExistingDirectory(this, + tr("Choose your VST plugins directory"), m_vstDir); + if (!new_dir.isEmpty()) + { + m_vstDirLineEdit->setText(new_dir); + } +} + + +void SetupDialog::setVSTDir(const QString & vstDir) +{ + m_vstDir = vstDir; +} + + +void SetupDialog::openLADSPADir() +{ + QString new_dir = FileDialog::getExistingDirectory(this, + tr("Choose your LADSPA plugins directory"), m_ladspaDir); + if (!new_dir.isEmpty()) + { + if(m_ladspaDirLineEdit->text() == "") + { + m_ladspaDirLineEdit->setText(new_dir); + } + else + { + m_ladspaDirLineEdit->setText(m_ladspaDirLineEdit->text() + "," + + new_dir); + } + } +} + + +void SetupDialog::setLADSPADir(const QString & ladspaDir) +{ + m_ladspaDir = ladspaDir; +} + + +void SetupDialog::openSF2Dir() +{ + QString new_dir = FileDialog::getExistingDirectory(this, + tr("Choose your SF2 directory"), m_sf2Dir); + if (!new_dir.isEmpty()) + { + m_sf2DirLineEdit->setText(new_dir); + } +} + + +void SetupDialog::setSF2Dir(const QString & sf2Dir) +{ + m_sf2Dir = sf2Dir; +} + + +void SetupDialog::openSF2File() +{ +#ifdef LMMS_HAVE_FLUIDSYNTH + QString new_file = FileDialog::getOpenFileName(this, + tr("Choose your default SF2"), m_sf2File, "SoundFont 2 files (*.sf2)"); + + if (!new_file.isEmpty()) + { + m_sf2FileLineEdit->setText(new_file); + } +#endif +} + + +void SetupDialog::setSF2File(const QString & sf2File) +{ +#ifdef LMMS_HAVE_FLUIDSYNTH + m_sf2File = sf2File; +#endif +} + + +void SetupDialog::openGIGDir() +{ + QString new_dir = FileDialog::getExistingDirectory(this, + tr("Choose your GIG directory"), m_gigDir); + if(new_dir != QString::null) + { + m_gigDirLineEdit->setText(new_dir); + } +} + + +void SetupDialog::setGIGDir(const QString & gigDir) +{ + m_gigDir = gigDir; +} + + +void SetupDialog::openThemeDir() +{ + QString new_dir = FileDialog::getExistingDirectory(this, + tr("Choose your theme directory"), m_themeDir); + if(new_dir != QString::null) + { + m_themeDirLineEdit->setText(new_dir); + } +} + + +void SetupDialog::setThemeDir(const QString & themeDir) +{ + m_themeDir = themeDir; +} + + +void SetupDialog::openBackgroundPicFile() +{ + QList fileTypesList = QImageReader::supportedImageFormats(); + QString fileTypes; + for(int i = 0; i < fileTypesList.count(); i++) + { + if(fileTypesList[i] != fileTypesList[i].toUpper()) + { + if(!fileTypes.isEmpty()) + { + fileTypes += " "; + } + fileTypes += "*." + QString(fileTypesList[i]); + } + } + + QString dir = (m_backgroundPicFile.isEmpty()) ? + m_themeDir : + m_backgroundPicFile; + QString new_file = FileDialog::getOpenFileName(this, + tr("Choose your background picture"), dir, "Picture files (" + fileTypes + ")"); + + if(new_file != QString::null) + { + m_backgroundPicFileLineEdit->setText(new_file); + } +} + + +void SetupDialog::setBackgroundPicFile(const QString & backgroundPicFile) +{ + m_backgroundPicFile = backgroundPicFile; +} + + + + +void SetupDialog::showRestartWarning() +{ + restartWarningLbl->show(); } From e1236f53e2af1569182f01d6ec451c2cd1dd1bbb Mon Sep 17 00:00:00 2001 From: malcops Date: Sat, 7 Sep 2019 22:18:45 -0400 Subject: [PATCH 14/81] Remove maximize from Meter(Metro) menu (#5071) Fixes #4984. --- src/gui/widgets/TempoSyncKnob.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/TempoSyncKnob.cpp b/src/gui/widgets/TempoSyncKnob.cpp index 1e2e249f3..d769fd831 100644 --- a/src/gui/widgets/TempoSyncKnob.cpp +++ b/src/gui/widgets/TempoSyncKnob.cpp @@ -291,7 +291,11 @@ void TempoSyncKnob::showCustom() if( m_custom == NULL ) { m_custom = new MeterDialog( gui->mainWindow()->workspace() ); - gui->mainWindow()->addWindowedWidget( m_custom ); + QMdiSubWindow * subWindow = gui->mainWindow()->addWindowedWidget( m_custom ); + Qt::WindowFlags flags = subWindow->windowFlags(); + flags &= ~Qt::WindowMaximizeButtonHint; + subWindow->setWindowFlags( flags ); + subWindow->setFixedSize( subWindow->size() ); m_custom->setWindowTitle( "Meter" ); m_custom->setModel( &model()->m_custom ); } From 2e84cd3e0ce3b888d4dd9b87a85011af26e29767 Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Sun, 8 Sep 2019 13:43:15 +0100 Subject: [PATCH 15/81] Fix stuck keys when dragging on piano view (#5127) * Fix stuck keys when dragging on piano view * Add comment Co-Authored-By: Shmuel H. --- src/core/NotePlayHandle.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 1e6ce01c9..d62857350 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -199,7 +199,12 @@ void NotePlayHandle::play( sampleFrame * _working_buffer ) lock(); - if( m_totalFramesPlayed == 0 && !m_hasMidiNote + /* It is possible for NotePlayHandle::noteOff to be called before NotePlayHandle::play, + * which results in a note-on message being sent without a subsequent note-off message. + * Therefore, we check here whether the note has already been released before sending + * the note-on message. */ + if( !m_released + && m_totalFramesPlayed == 0 && !m_hasMidiNote && ( hasParent() || ! m_instrumentTrack->isArpeggioEnabled() ) ) { m_hasMidiNote = true; From a0e7a88e67d560264da8cb31576db4fae62c52b6 Mon Sep 17 00:00:00 2001 From: Hussam al-Homsi Date: Mon, 9 Sep 2019 00:22:43 -0400 Subject: [PATCH 16/81] Remove "What's This?" leftovers (#5173) --- data/themes/classic/style.css | 3 --- data/themes/default/style.css | 3 --- include/LmmsPalette.h | 6 ------ src/gui/LmmsPalette.cpp | 8 +------- 4 files changed, 1 insertion(+), 19 deletions(-) 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..ff6d032c2 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -920,7 +920,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/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/src/gui/LmmsPalette.cpp b/src/gui/LmmsPalette.cpp index e58e72cea..e0b356d7a 100644 --- a/src/gui/LmmsPalette.cpp +++ b/src/gui/LmmsPalette.cpp @@ -42,9 +42,7 @@ LmmsPalette::LmmsPalette( QWidget * parent, QStyle * stylearg ) : m_buttonText( 0,0,0 ), m_brightText( 74, 253, 133 ), m_highlight( 100, 100, 100 ), - m_highlightedText( 255, 255, 255 ), - m_toolTipText( 0, 0, 0 ), - m_toolTipBase( 128, 128, 128 ) + m_highlightedText( 255, 255, 255 ) { setStyle( stylearg ); stylearg->polish( this ); @@ -72,8 +70,6 @@ LmmsPalette::~LmmsPalette() ACCESSMET( brightText, setBrightText ) ACCESSMET( highlight, setHighlight ) ACCESSMET( highlightedText, setHighlightedText ) - ACCESSMET( toolTipText, setToolTipText ) - ACCESSMET( toolTipBase, setToolTipBase ) QPalette LmmsPalette::palette() const @@ -90,8 +86,6 @@ QPalette LmmsPalette::palette() const pal.setColor( QPalette::Shadow, shadow() ); pal.setColor( QPalette::Highlight, highlight() ); pal.setColor( QPalette::HighlightedText, highlightedText() ); - pal.setBrush( QPalette::ToolTipText, QBrush( toolTipText() ) ); - pal.setBrush( QPalette::ToolTipBase, QBrush( toolTipBase() ) ); return pal; } From 91cf5bd88d3cb0878fa7af50f75a15a51316542c Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Tue, 10 Sep 2019 15:17:55 +0100 Subject: [PATCH 17/81] Support compilation with MSVC 2019 (#5180) --- plugins/vst_base/RemoteVstPlugin32.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/vst_base/RemoteVstPlugin32.cmake b/plugins/vst_base/RemoteVstPlugin32.cmake index 9a8f04529..ec290ce96 100644 --- a/plugins/vst_base/RemoteVstPlugin32.cmake +++ b/plugins/vst_base/RemoteVstPlugin32.cmake @@ -13,7 +13,10 @@ 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) + IF(MSVC_VER VERSION_GREATER 19.20 OR MSVC_VER VERSION_EQUAL 19.20) + SET(CMAKE_GENERATOR_32 "Visual Studio 16 2019") + SET(MSVC_YEAR 2017) # 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(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) @@ -39,6 +42,7 @@ ELSEIF(LMMS_BUILD_WIN64 AND MSVC) ExternalProject_Add(RemoteVstPlugin32 "${EXTERNALPROJECT_ARGS}" CMAKE_GENERATOR "${CMAKE_GENERATOR_32}" + CMAKE_GENERATOR_PLATFORM Win32 #CMAKE_GENERATOR_TOOLSET "${CMAKE_GENERATOR_TOOLSET}" CMAKE_ARGS "${EXTERNALPROJECT_CMAKE_ARGS}" From c436e5ca578e98f5d9b8eadbb077a283978cd867 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Fri, 13 Sep 2019 07:54:48 +0900 Subject: [PATCH 18/81] Remove MIDI connections from factory .mmpz files (#5163) --- ...apDan-TwilightArea-OriginalByAlf42red.mmpz | Bin 51694 -> 51679 bytes .../CapDan-ZeroSumGame-OriginalByZakarra.mmpz | Bin 43076 -> 43070 bytes data/projects/demos/EsoXLB-CPU.mmpz | Bin 33938 -> 33924 bytes ...- Krem Kaakkuja (Second Flight Remix).mmpz | Bin 46102 -> 46086 bytes data/projects/demos/Impulslogik-Zen.mmpz | Bin 37337 -> 37190 bytes .../projects/demos/Jousboxx-BuzzerBeater.mmpz | Bin 43351 -> 43235 bytes data/projects/demos/Momo64-esp.mmpz | Bin 55497 -> 55428 bytes data/projects/demos/Namitryus-K-Project.mmpz | Bin 63584 -> 63445 bytes data/projects/demos/Oglsdl-Dr8v2.mmpz | Bin 43206 -> 43069 bytes data/projects/demos/Oglsdl-PpTrip.mmpz | Bin 26086 -> 26015 bytes .../demos/Popsip-Electric Dancer.mmpz | Bin 26235 -> 26220 bytes data/projects/demos/Root84-Initialize.mmpz | Bin 17157 -> 17017 bytes data/projects/demos/Saber-FinalStep.mmpz | Bin 45501 -> 45429 bytes .../demos/Settel-InnerRecreation.mmpz | Bin 35882 -> 35811 bytes .../Shovon-ProgressiveHousePluckDemo.mmpz | Bin 16145 -> 16014 bytes data/projects/demos/Skiessi/Skiessi-C64.mmpz | Bin 5033 -> 5029 bytes .../projects/demos/Skiessi/Skiessi-Onion.mmpz | Bin 26929 -> 26919 bytes .../Skiessi-RandomProjectNumber14253.mmpz | Bin 18142 -> 18137 bytes .../demos/Skiessi/Skiessi-TurningPoint.mmpz | Bin 20851 -> 20844 bytes data/projects/demos/Socceroos-Progress.mmpz | Bin 18487 -> 18425 bytes data/projects/demos/TameAnderson-MakeMe.mmpz | Bin 60674 -> 60609 bytes data/projects/demos/Thaledric-Armageddon.mmpz | Bin 53974 -> 53910 bytes .../demos/Thomasso-AxeFromThe80s.mmpz | Bin 15390 -> 15255 bytes data/projects/demos/TobyDox-Psycho.mmpz | Bin 5856 -> 5787 bytes data/projects/demos/unfa-Spoken.mmpz | Bin 212235 -> 212173 bytes data/projects/shorties/DirtyLove.mmpz | Bin 8660 -> 8595 bytes data/projects/shorties/Root84-TrancyLoop.mmpz | Bin 4464 -> 4386 bytes data/projects/shorties/Skiessi-222.mmpz | Bin 4825 -> 4747 bytes data/projects/shorties/Surrender-Main.mmpz | Bin 3176 -> 3110 bytes data/projects/shorties/sv-DnB-Startup.mmpz | Bin 3906 -> 3829 bytes data/projects/shorties/sv-Trance-Startup.mmpz | Bin 3924 -> 3855 bytes 31 files changed, 0 insertions(+), 0 deletions(-) diff --git a/data/projects/demos/CapDan/CapDan-TwilightArea-OriginalByAlf42red.mmpz b/data/projects/demos/CapDan/CapDan-TwilightArea-OriginalByAlf42red.mmpz index 1687e8c343327ead0d969653b68a562567aa0c00..b4a00e1ea86f149a9fa998ff8b062971c1c7079c 100644 GIT binary patch delta 17931 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 KfBU~%OgH~O%@C~s diff --git a/data/projects/demos/CapDan/CapDan-ZeroSumGame-OriginalByZakarra.mmpz b/data/projects/demos/CapDan/CapDan-ZeroSumGame-OriginalByZakarra.mmpz index 95a29daff1d211fd6cbb3162656afec54ceb7998..578c4f926d40ebc42e42664c1b72a5c356f25108 100644 GIT binary patch delta 32433 zcma(2bzD_X)IW*~(k&@nhmw|V>F#a`iGzTENV7%a(A_A94ru{tknRwUbcmF6Bh7E~ zd7kh6z3#pL+<)GCX00`AX3w5k^ImhHX9Br>0=XKE1@MV_BVwA`ZEZ3ZH3+FXId32D z-w^EeenBK|JGJc#DO+$cyb_!ttV-s;v@%H+x%~D*R=u^-Tle51Yp%5sZXfqch#|}2 zNM?-C2lKM>pO%63tH_qy11{Pj_Y^8Eo7B^{mn@f#%*^j4 z;TJS%8$ff8G5v{R>28Fv$tK@%XN<+Ufr>uA`G|Z?hx~%yC|S~<7Bk5_BN5#pbomMk zRiBE;WO@6kU;Jrr2C(i&sg9CZR`_p z5la$8; z7T!fw=GC*11Y2L8e^pOv;+3!PLCL<o)N79wnYVEME2UZ3v)gxWi`t!;wb(hPXhgWSm77FgUB zKe>RXH$A+@z{bq|dMNelmC+00jk(tx*Uic`KUC!%SYtYjLc%65hvgj{PB-13QRv)= z$vG&UH^ff76L}&4JY!~-c|VAOFCUl|eH1?rbYkE~biV_!^p2WAyx`hY(HqLZuZH)O z(yIA&NVx5_8IOz{^Z}JoZd8~fEtnu-euZ8}?(0J-qnsMvFcYI11aAbDQLW&@lBerG zJ5VrDtB}5^rEysNgf{^LW-hH(FmxUnrf{*3WeqU=s+@UQu=fQN&Y!;sOKy`5k1*)4 z=$$z6Lg)RtbBJf1_iN>vH|k=?6;1nBh|(Feq`KR-y1z+aPfzhchirJ%bf83!{BYbW zvx0js^n{=DRYJ#(Vr0k(39*Ck(QAIrk1sVPRAeC@4(LSlHae*~4(KEgcuT_w%tviL zECJM~e-a0j&KU{lIi<)LY-y6@=@d+E&IuU7s}$50fcsdf{pF0+ScT~rTroZIA8NF$mrW74la}8{D5Vcep+XKPEsIBJrFVkjc@2w7CucGY6U*-ovVYXfW`zrmgY3dytDVopRS}jzb+rNNLrCJfV}(7wtA&eq zB1Fp1SF5T+=|s%S`_#QViT~=0SgTLxscBg@$DIWlxIi zw`@NK#3UTKFU1T)j+jC&xrF4r4hR;SWNq!Gg6u)DboidTtRA;S&)KA`+{LF37MeT} zd(_K_Eh#oJB`R^2wQC?R5RhRj|FYeHKk?z)ZmsIzJEqL)x%%o-lP7^QGX zhX+idS*%TN7l7qv*cHd^$RCRN)7+}%mSz@PatZSTJ>qwA6u`wci;KgqyR7csly1TC z?vcCFCrq4zYf|QOr_)*JWiB4C?n}{!L81_t1wkBfnf_ zmxrd}8Ku)hciDW+wKMX`K*FPAf7#l)doQmh7Uz327l%vb&w<_Zn&c1mRGFLE?cf@5 zmt6zu?k$hDB@%B<@kileb(Z6SJts-)|NKjl3hv=wOnykTc{d?YF19<9v?${*k~YUT zbQl|p@g46P5I6=m+?QvJoEP(}+lo4OOJ4$Q;qBrN+k+EnNk^Z!y(-8!*46cwW!6fs zwp7&Vr9;H+q6&-nX&UWS)pNCtIZMYu37dU! zDo-hIYG&8Squ2lAt92s3u;|FT3Y32XnhT5M^a1bVE6crrF-lVht9Ik+;;-wA}sHkZ3H1<6#SSC^Y)ut&TU%juz1%Om@VMzT9n9yWd9A_d1Szjx1+_Z7nh zAXlDBIHLG9#RAqiX|uAs9RV62nL4;E7wrf=9D3rhnK$F-;|QF_)b?^m;loUu?;?2X zegMsqQlmSHCrKmspr|^6*Pi)eqOU{D8t?ekQ;+-iiX*u(mN2ir`1uv;nhnQAV~@@r z3PP8ks~!}@S2p{_BOTbx(-WXy8*tAE)ogu=0LQ_1#}aKMOCfbbg{d0&ye3R8`ZuA6 zC}cW*=P=etHi=dTwFE~pQzdea?9#kZ>ca8~s?u#= zp<3gMFSFDJ@1ha^#u)tg56Y)y=p!^}Go4b~ve(Z$c@x)Lut&8aRsSlK^2FX%>_liB zW+XuS89WvlPeDSVXm_31mya?i);2d>BGbBy(tv>Ew>_z`b;0Z=rc1Nzxy>Z6?so+@bACTZy^bkTd#|(aD#WCd* z*N1`2%7^6hmDL1~#JeEsE4yjUN!oo{@+uLaMa*3zt3&MpRqUHa=EIic%h*fJ0>LgdacGolrpgt6}|tLi3}Pg0lSDqB3)gM`VbZ=W`SNERjyQ%E{VF) z!qj*8&K{*qa>a4zxSmSj-nVJaPn{?sr*1EL1tdzPQFt84&X_?}yby#JPH4%;VmG-? zTmqr0`+s9iWb(foK`~wL%&6)Mm<0-2WEb8-F;6E1)$gfwRMTOVO$Y+eR3TGf!~QK+k`A&cA8ID-KVyKnXz{iv`H2nz`m zia`e*OQ^SszQ0%Dj9{D#pW;!~c;^;w@C(hpl_#`-8LzuXpxbOjkv8FWucb7@%LdLo z;_JpT>*euJ+-f?LhuwNJ@wIPJM)bPq?k01R#>dY$KczNXM3n+FvmzVkAbjSB%#(}!%%jhS z$KUHxG%JHsl9Bb@w4>8!N$$&?R`;k1a+7!x4?h{ev1?~6G~8^=*<|eKIlIB{>Lldu zxx*F}OI1kp`RHIT!S+DnC|Mx#vsYnsrlgqi(e)lbx+bugv`I&QmDQ%bm>ukwm{r%} z@lNv(-3RZa53=ZO*}+S>!3#%?dg|y+-D`p@Zt*Q1Je14pzP$a;4tQ8IoqJ=Qg(6Dh zW1Sm-Xi3G-LQ2sRGxWBi;14e7DZ8(|wsPF5*U1ile^{r>9_id4kgoC|N~ zuV@ft%^y8|S%1%~th;-oZft+8dtO)kH^Tt$R87n^&N}<=>vrogam`L~ji2QF(iFl) zZX@DYLFR?>CVT_SGAH{Pih~JdjShGAG;e-X0$mJ)aZL@@=Sk~^53F6K)zq1{jk9>C ztioXx@z*P>`X-RKYH|D3H{$^tG4DwTPFY3WNys>*PFcNRhHh?E$ob}|z2cFvX1ySV zH4E)+i;UtATr8_=H1y%E!CimBnfYtys1k}odNX4b!UR&I1w%c};JP%z{i&VR3Y_kt(n zR?YWwwsQNy$qOFBBe#RHAMs_aN_UEtCx0xM`rb-8-+#V&!P5iK*Tc7^tgo8(S$a3e z?uN{~s#?F?rHJZ0w6tJFPXmzes)+!Yo-G7|$9D%-d0SbJl3^)*jbr3p_=Xhb)$L*x zg11SY+5%M}YLs!GMWVCoOiIlEO)N-THw8a$y{MV4M9v?CZ$DTW1|{?z{;4E%+JC{r zP+%$DBJe>MUcptOV8Q0Oe zdqxB)vj9vXM&w^gm#;%Aa|a$!g(4{=5LUObn`^A|fM3chP)g$KkY*r7MDa$~v=Koi z!LPb2h3uTTUR69j0iJ>LGL#@k;02G0+`+Ib)BNuf<#rIMw9KhJl_TF1v4TDXP6Zu*$MN>r|C|@&N!}hf$E`|WUQxz>RUcUBrw+ecbOkEwHPlO$)&IuN%On6W z1aac+LU9oy8Sp}+Cg(lyKrz!yWOp8#O4-oCSOi~w$QcE@=fqtR7v~i~J%*D+wlb&bZUzP|HCGKuUMS`i&{aZBd_{ldsOkHzl(Rxt^#k}t z9Ve*;LV>!#gj>iBYJMun5=83@HgEUiGi5R#%%B)k4S}OI@~gb!c=~ zaN(uINnhU~3&pCvZW~7r1>;<>Y-~l)4UE~ zx8SirHZOSuaMTwVI4pxcFQOisD7RdJ{XD7*DsOkRR6p@ZP}herxMnwubwhnJGhw=a ztxRt6Vt@A9nS_g@_AbEpqePahdm&G45O|Y^$J7y^4I?vc;NCg9b_G4uuYewgA4~t2FPPB%)@Bji zA|bO-Z+nUC;Qyth?C|i=1-lTxnj`bv8LGk)Vk$pk8dev{Tu5?L2tv2^Q|1toPfB{H z0HDz?Cd*agC%sh&1Kc3{`BU$7^O7elm)~w#k(j7cCo*`>M`#TF&kl*9k&zYgp@R#G zIgb6Mw@&;^5R$?mdWWX@m72ad{)}k66=Bb!Y=J+PcpX?RG?UaC=v2&U6f!S^A$&FSc0niRm@v|18i2}4j23ZM;+7osJUus!Y%J0B2ox2$;$W$5-uQS?U%bqkS{!qA!wn;8_q zOEc*%=$lxdp%w^Jz?DAnD3wry;;0AuIwTf!%oq2)D`gY789(bFfU0!go}YQ8AxMWV z!9`w;J_U#sfSU-OJug!RSH+bsVFSq?m^D`w7foCPzaJ3EQjdFrNezna_^_s9N&v+w zeZUYXw7U1bAKhI_e1>p3b@&r0lW3>coQAn zd$kA5{QrdYp>+=o2tt$fxa|k3&8h~#3PETW$Ww0&oPYqSpxhiI9z6g1_+&Wh@Q!j3U%{e*zm8w%&S-34Qi>1>{Eja}<@r1_&#hS_a zXRC3y_zmoxEEp*^3pt4g8Gl3M--E+r5Vdt;2~BNk$fiRO=s0BhIbq9i(x21LWoB(u zk(+ES1DRcmCUXt#bf$dDffxe85UCJ~t`S9yVX*ia~y!gmCa+% z;Qaz=rou^52`ab%@>BVTE&1xkn0oktDks~O`K~iR(N=*_TdCLJ#N2_LI6w7WDgC0U zVq-%#e|{fgPihKWE=;2*GgBSU>qAh)-g`S?vDJ;At?)pVYHvZxy;Q-(e?^ZVoxEg3 z5Y9)iX5WQt>nfetFN;oYRIn9H2u?kKZv#5Oso*O;HedFY$@{=_M;i@fcD9{|sB&6O zYkre@48#;&;6Tg)KB%%flz0m0{y)8fGr+mJ+}zdr-#4$w0EeLmz#6i_^;vMdhE|z= zkFTIEGFU;sv}7XFA`rU$@EUyYzj51A<|h>_Bc`ejcQZHK1$UJBVLYy!^mE*Mrn)=* zRR9>$bTkj*igQzyG`nUkE55I{LA(9pwm4k>AWZGAowKhB@Ej3iHw>B!nmdR^D{o!W z)vzOrb!DF(QbM{MDUWZ(KwVQd*1C)@5B=xet~Er*k#B2Olj$ zx`fHTC~RUHf9gT>CRh|aI+AFUD1c4`F}O``=2#tsK&z+VclvcksfBT31Ae4KrYkM+YUuQSFhlFaB{rbd zvwZyny8^yB9qzF*|D(;b3#?O09aKE4Sh?2H4II%`wC|`7!i=d0c4gIzpSoozoqLg) zY=vDk<@y{{;1@S}t}Y@z9=HTJJU4OWtb34?J!Qe$_aXx_i$evQa_^@9t9!_$NjBCd3H}$@o;TQNwEq3e6XZV>3~4t68Pl9nyeo4S|@89 zL_k+8{azE+AW49adV1@15lp8PxLJV@X5s&GF!uZI@Mt0QF_w4vh4n50N`=7tJaqZy zVy~lW6K5Bl^t%ilRfq9|5AvM35+?I6>(>iLh?$%6`JkA}C(d9hHKb;xD<)cy8ZWZ| z(h;Z*cH`sc%m#;)dlfHf(g75p@dlyAH5FC+)+CK32U>bA&*7b{tyESx3 zx1&DK6FOLVS76HBh)DKW@$D@9E^hgl{n492RsSb{Z3KPk>ON+u3=K=#vfw*`8Ko{X zV$0y7sjYt9!Nt!Blf1CDA(g*kY1w4b=;UIW(Bfggf~obmp&_;UeOz08h@x{%L+Y%l zsu6G^B_zSmnQ)tG0^V`Ca$1Q7h&v2|P01fM;2oDMr=tjq7(mWj11XKDUJHt+w#%yYvKX7a~JN6H8~_;V5LNs-)# zuA&e~5=BS*)=jFqtG*qjd!TgEFipeBh4Rv%1 zU;Gr$Dpd9Be@F{QmIF4+5jS>7T}=B=oILKp-n z+6r=GbZ{Z_xCbd>;%&lh!7(_x=MA5F)TOKCb#7YL!s4sh${z}jft^LdkSsvjSBb1s zFyp+oi3#$1Z4s1F%IrvW;jX&trtcSz!aY1x2_8Zb_uwdU2WcIpB23>MkhwMc{R{*7 zYF3ua4&b#&X!7vP1zj0TDqU`rPdXOK+#D7mAz3mtv^BSoD~WS5PXZTow(l#{4I%vZ zMmNg#zT>0n(v3_77mUCn0T(C@1n-`@)g5C@Ws<<7wi{F(w+OqaI4u%VG$0RZip`95 z(^lWwZx&Ts_Rza|q}!LxEvCmdu|<4dNzHQSZ`dd@a>0_8J~>O;DB`!|OU>#^f^QTZ zt=l)TmETRf>v9N%@&%@5SvRq9)at`m+;v&6IE6yDJ$Zqxs*R%RJ?>%knnhxRw@dE2 z;Nn;$wg?W3+sqYXAL}8QsDcO-H0R%p6xGT6k zI^7U@w<4e0`wz}56*S156SJ~$g57xg#KfO;Q1j*IY;LLFh5i2=Pj(N?2|oCPKUPhz zo$mMcXPtKx-M;nzLI(HmJ9bOFZ8~s-riq|0^3kUAQcW(VV}u^|+e*-_q&*|B}|s*0t3^#mc!g`-Uh*Fy2BO9*b^Z*t=_ie(5?spyk`(NFEk%x#`# zmF6#(pYqGVCDVefe4j@7g=s(5C~$IrOzC|(jhs7tclf(wF^%w_f%wVhc-i z2V;t-3rkH?OCm}&EwH_V=&`e>%9fTX9`rf;{X0Yi*Lmpx@h@6-URZyK*f`m%x|z9e z95l7=W@=?!m9h7ALA_NU5^ zVSy>J+eU*4wNzE#|ISd7!*4BNu_O3lr_em{V5b z{usgaGWlByfIwEs-9!aEwVliCDs_tBG4H!sWgF*7$VcTn$cK96DGX-MJUWEx6w;mh zjoa^{@OA2R1BkrB;J?=Tsm_>*`r*_==Y$Nr@=SD=0!@!UGV1mF&G3?)9R&HZBoDod-#jCATLI$G9e34&ck8TfVKO1lwb^v#%OoPUdD#I~o9B^V|nQR4=1SP2uR|B1`l zy-ErJ!d*~QApG0fIdU?=47eW&F>y2bpMa8*$tSD{6FI6+9~Ccgb4Ynvr=CEcfyLa% zBEkQyXqFN7Dgp)V4FxhM;qzoij5?*)T1E5|3_;Qv3a_Fb6-fUnQ0kOEvQJ^KCj7`z zW6Y654t@#5fL-DY@gu81cv$~$nwTKwM+I8uqvE+kBG|+xM;UDL|5r@lyW%8cq~iRI zd-c~$lN*6jf}cRFikYnVJAyn4g4!$#ktam%r6+7QI@fZ;xQi$Vfp+iT80nMSeQOkutC)5|m&i5G2`S@rS}6HQ5Agygo&*)GvKUlaO&& z`y0iBJ`pGQr13 zm?(WhQnveqgnrUm**u5ApEj)wJ2^xtst`pKkSUPc*g+Op^(!$m&taC+(W~UrA|6=Y zYJR19$;D+z1`dW)bq7g*RjkoWqJ)D=t&#>og2!cuUxLjozp;blNuQYKe*UrR$1N1! z0h_xM6s6El<|zja9a)=IN=}e7aHbME;3N>Hl;OV*Bg=I^4;ms+)^56fWl#4#WEXfE zuo~KE7LdayXTr~>MQ-tNSm24MY(cLMatysro;&Wxu_J%IN+d0E2DTS7PyXWcM7@8S z!!3@V=Je!!m{Jro>WgjFXt|g$<+cq;wZJj7~fc&El}Qu`3mk};{xhW z<2Szl6;qnYsf@XaeU23{Z!~ulaI6Uz)E2xQz$cKK*8c9lYDTYARW|$58sdQQO^Nav zg9`JRZGs>sf!VO3Gk=XaLxAqvxK${Pw$1_~e4*!z zXZs=OG@=+U_t-vozVH%qHu<}x>_H7EV|@{;IS-@H8N54|qg{hzu5|4}-N)QHXC0i0JwY}q zhYyrz&-q)_cb;V~G1r4;Nun^&EDN-?`WFP2bWfpgQ$bVbu17ckfgJY{7#~685i}p+ z%_I0dLIMc0MSgZd&=cSwW2up?B6F!RqB3)-WE+3fC0G#&>?0o;gr_JV*r0;YjRpcE z1_;5JAgp15Ad3S+KK1mw-{4@8(Q@XTe^7$(iT4o{AHn<)JV1CA0Rl4o5$Ydd_z_k? z0FeJZ7I8rjT?`<65(Ys|Ll(6~9?96@gAI+03~~;=S9b`7>`7Q@N_@N3j>NiadXUYv zgESt@k@OWQ%<+RX1@aiSZF-2Mw=6GK86}dB6=Iai=-pnf%m@-US2c|3} zV*pd$l7YgcQ)HnqN0`;SD~ z5kDBnos`0fjp};f@sY!N+OrO2BPK|~FFtyuHkK=c!t3(|i==0L40vHikOVKEkXFNM z>_X=izQCgIL3z#^O+ZALJ0YV+0PDi$wPuMYx9+l~Gq%)y|8^oMDVp*UhPR)7nukrGj+%>^Fl0U>T9=! z^!GAd1-f!r{cffl8HxauT+XS+7O51SAip=!iZ^_1f+LlK$rB0ro6*ZO1S&>%UMGgh z2t$Do%w+QaxUo zjv@U&Dlkwpnd+frI!5m-@_#D8e>Fu=^)uB&&UEaVv&jFeGL`C~W;({}EYc5}O{MY; z5eVbyTMz2=LgmzbF!WWhiB6B{^w`u5M{ZzRg>@0UW*9Olld}p|G7cv!jaN9iDyuX( zu_Pfc`g8e^KD`UYSm`maBqD0BN2}rTaBU4-&x!_!lmW zHbY4KL}pkCAx{*?Q*0c9Ive!x@-np0Hz1j=PYRN|9RhL7b*y<B98VTV=Ax;0NFi{f(lnldnZ>#gE~_zET-SGbc3T>d~w`;`UCOkTl!i^G#Cq8o^* zt&qO*cY2MnFy%FrCIeP&GyL4TXD!6d+5tkHBPhMpdpAb>@@|;DmEjctUoSWD7)sFs z$(9yH=ImLRq50Vo#)5Nh)?X}pTwR6qaKa{yDlD|eq zaOIF{uUzJckdf4nssJbp$x7OvrZBTogglFUm=Al-v0hI?ni1IQZ_;Cd9AN zf8;PElr!xSQ0PHQk6_gv@3ayyR%ZIg{z$7QUW8s3Q@ap3GS)<&JLWP!%Wi{x5&Ja5 zAsWyx%asz0QLhB-`t)==p9D&g@ov!@a85>&M^sy_nn!8S*5=STa8_~2MYJD%m0#5o zMsjc0XoK?pFuOJaA3g7?R46NFEp7W7e%)Tg3d*0ObOlCIsERr{x1Qb*OZ`}w!KdMI3So5T38JwxC^bEbN z%0gTs-Y5uUQd}^TKS9Cj}6}e~L^^U)=O?mqn^bf!bKO`0N&`h~mZls}{(612U z4=gI{q0NvznB*qx6^1D!wno*01jE!~WY;PiBcxh(P`57==Uf@W?cPJ@TcX8a6=3ZE z;PzC@|C#O8QV+Kp9*#4I4}8b9u`;#scMP|J5kBqx&1%?&CiU!rcxO>^?zK7xQ8YdPyxE1SfpFBF#RY3VE?k*%Y8 zo<-_P6PQ9Y{9lA~!U=!)yQB8RLbzgj<>Jr$`^0C{V4Ze=kK?5 z-2Ss`*kC0jgZn|IrtBeiY{(F=2WRmxGmY1`I_1yjroQgMH{eq>E83C&{ zX_H`UO()CC>i=5rVbflO0{H*6%wM9UoIE>9_*BQf7L@0t)uwq3|i+epYB zbi-H8VkK1nsm>BIfbKFO7mK_T;=stDDeXD21UVtm>+dBhgS_S_#PWxfd}Ktu`th%n zRh!iNBbM-|uh?D`)+J4l*eC&pu&>xKvc=~u=6T01J^}h;wX5)jxL?IkGAjM7#k_Pd z<=+@5Uwp1OT-63t%~>N|^zRW}r;DqC=btqnrhqnZ+1cfMTv z9r|5xrb&482%7!cQo=v^b>ZiA+QyC>vh;6x)6cb@FRBO-(_iSNbvcLqy)`Rpr_{9F z{>8oA$z6Gi8n~*jOdHwKB5zR{Wd@j}h;e+ol1aTZ+1YA2=7$UaMkl-FvAokNEN#dC z5bCo4->j^o6uOcys&2S0RN1J&_U2HSTW>eQw7csJroG+i&igD8ed69kI((7ef>+_v zQ9_ZYu~`NzHNIHcO42s4YirrpYo+8G9=apb-9GTMF!0!M$yU8lV@+x69A~j^^*!}x z07x(uuim9p3K@?m>~h=Z@BA~As8L%t%Ho^U*`_8KF~_ZK3rBNsxRy;`&x=-RksV8Zo81yLtW#y2HMLOB;FRAUw`4VGv+cigY!z z>z^6$W&L+n#h5qC7|igKQ2!n&iE2zyZOSkhQof?-AHZNhc{zgzkT`NRpVmObImuOU~fgu zv?#rIhIs0z)keAt(CvGbZmh%KWmTEvzhD&nvR!^X9O0@n< zgFz#vsfZ3*o6om$KH5!lvgTy?IB?~J5v3UzHW|@-u>{4jQL(TC?$WC zj`|uwpae7L1D^k!3`&yX`e0~>d=vEfyRwy3{LN3QS^W7H`pPIZwRZ#P>gcg7%>xyq zN7({oP0O?v-!>T<_&Twtt7o`=Z$J+^=Paswegw&pH8oOMeBET&`nnnlbr7xoUW3iQ zDi59Yusk9Z;HNfPt&AH$Eq5amVZ`Lt=$`D%nlf8|!3KCcWkxMFBfF}3BrLf6c6OXK zzdtJC-Y<27f+7INKRj>Ox#G9vGC7Uq@JG|<9wWWh(q`|hLub`zPN{w9+!7P4N+GEW4UHrz@|-A_K&Pye_Kth1CnkUm@XH|X^lD3 z@{3KI7UWi)k^T>;-nr>0JqaHzGu!bXh=v*Fzs5NSxG>vrW*0xWLJ&!BIdARY{i<9jjo6rRv=41CZx;{V zY3>_Nvu8CAW}zD|i4=2MFqW5~_+C4-KtUZA$f>&@)~=?5!{Bti&u=hoW_+XJjV#}3 z=uipw*0k>T4CVEE%=j^X#*D8rF{$+>*==2M~ z!)Lqvg!t2?xVs7JOXa!`qSul%DJS#6J56B`e-|vv@Z)+N{DsC8#XbknGYXvg*QBZX z^AQVdowoSglW}192ewu*2$T2%h9e#JrwKUnI52i{($kko72Fq0y7iX;ps^CIV3}$O z+`(t`Cr+{)h8xq{1F1A;I*G8;A*QMLC%bVO@zzOJp47myG?5(Ra=`8R)E2(0%Synt zx99rSga7G<-O)nUxU1yi;QBmu$&p$@;rv15$3C?csE$%(bCY{92atd1(4 z>HXdeEN-L%^%;Wb@)0dXCMsQ0-mL zJiFq0Z(^6U?0nB^XHoC%S2>gP)%7RQ${AMEfx9d)cysrKH0vO?*jhU^c;hY4i+0U8 zFK^AEvE$a@6!)&ki8?E435b3>^`9H%V}UFjNWYDi+e`lZ`ZTGf^>H+vFbAhCpYP7j zy(kOo$ykPbLX}5@Zkz^v&h@C&JC-q@e=L^Mm+c`d5!t2XdS!)Yl1)m)U@d%O1B~T5vF>oc!pdl2kQ}M9sel?fZ zTAz5(HR09w@DGL_8zsG^qyY9U|E;-=UNhY+-+X(?=7&^?jvr+-$J2~PTV(0Y~Y%Q!?4VNId=KP zWeQcB1-w<4ndFFK(#b?ynr~M&ywv#U9;*^$aZ~;^&lks|HlhvIT{4&aZ?{HoG&`2k zzvY<78$~v0`_b%bR!;@5paHekZ)ZJXNme@~=DhHJ_+W9L)j5zOj_+~k|H+bK9k1c(S(Eg^5`{k>fu+Fsy=v0l zYoeR3vU@(xn{)lU6im`nzmcyYxO$%@i)novU#xH~Roca@6d$r3rEZXoipg{eq@@^j zb**GeAdCcIn|J2CKVp*Ds3AZ+Bw8$+RP|GHn8&=Zw3YR@x%1tvtcUx%&9w!oObT`V zzfeYV99xm>l{sbk>6X{Pr-v zSo+`JaDu)_FAor4j5}iNeS;6-m2_}*>bSf`Zw#Wmp%VMi5cZ^|I?VwCK&0pL@GcQ} z|FbB7I-p*P{k0uetl~Qo_rJ^G#x3sSVL!dGw($G#R(`^EaF1AA(}UkjGNh|fil#<> zf%?Y>{1+|?r!Nnb4PfcZ1;eGipR38H@TZ|!eh^CqPU^9#Ha;{2NTc|ZBw`PMT# zrI6Q7g+qb=g{!#1?zd?@p1jQ|Il}2T`k^0>%)3*crQiz2Y&AJ(3Q_~pdy~7=%NO}n zdjAC6up0f|>h!rZmW`-~*>zz2jHf94tF|BcP0fa4BJ%pW);B3>)xHEi%x!UxBXen_j)*wC{S_sQIiMahNQf<74jY&5}pYUKg-e1mP{DGL6RcB@((A zys6^f8F!iZ-a8U`=*!SnBe3uVtx)NZEPu}CR~MSs+Etz)%D1E`fHf<{hBr>Ia5~P` zH=@0|Q{|bEr*0YcQr(-W{&iYcN#OGAc*&Hpud=}6iz=V5dA}U;WkEqcBbXra`y1bjyaxY2+$MM)XF2P)F{wwg=Cyc4wOKT`-pmM<;|QjC0ZQ&>mIVI(dv+6TJ*1Kfk+ny> zH4toC+VzGb!0k&Ohrd}qF*dE~Wx9EMXdI{iVu2DiZN78$QB4giX!R^2G%o8$|Mv92 z_oJH7IAvTZA%CiymULKXoWL6kWPhq23j#ztp)AR_H?%VxV_p4ZD6}`ElAv)r4>qlC z=Id3P|C}!fK0ao<`bV*9j(96T9asap`bi}#wLgZ&k;|K0HX`|d7T&&Kw#BA(8frzk z6n0<#GW4ITns9q8TJ-;~Uc36aF(tnn((0PL`MEYM9jD7(en-$GA2%*7sX-`YmDhiN zp&z#Ok)}lhz~bbLqCJfCF1mDcIJSwR-NmlGJRo3|uTHh@zds z`rq1Z;?dfB>w-7Co}`4br;#vvJ~A zu{%!(TE>WGoR$Q8(|$77!0%3me-G2rx;_BX#8Q*xy(jGIZS-$OzCA09-YxT@?N|)F zzv~|DU+4tdTBuuF+O9rAq!KehoRgNB|zYId?{rfUjbA z!<)4g6&h_kerg5Y2eNJ{nY|&gdL9j&7)Q{_I`DWkazwR=89W07hVKNjV%y^sH)Ox; zVM1Qw7_7Y-sLX)3yzF^RJmqf^%NIfrYTXqV{9;0dT-ls_R|~f+y4PLX&gM_@B*{zm z&B99?6VjOC&B_q>=-z5#hijz+Xj=-tbs>R$cof;E-JyI@0@Av>B>MP`w|f2nT&3o@ zw7HGnX6P;CeYoQ?4OdQ^^(J}I-xPx4%5VkfYt=9+9C>M(FFdOBUsHD3{jnR{um69I zy>(O_P17$*LU4k6a0n6{f;&Nz;I;|w5?q50mf-GA@Zjzm+}(n^>&Ep=p6C7Ed+xdG ztabm`MOFREW>)vErs-jhhIg`?dTSnDaKm z{;?W{^p!3oSBPlUaT>1GSby#DH6i&L&GD`RYR>lFa@uZsXVTCt@YhD6d~tv4qQ}G5 zm2y=}%n5ZS@Ho$Fk3YI6o3;-LohadJk;?LB$-GA7x_;>vL2wANZY1|uZe{9FmY>&d z*|%>mbZqK{^Owo;_zdv0bUnXO4TbnsiOs4%-#gryyuYh_xI1`mCN(zB%LDJ#^{6=) z5mUVGiC23@X<5(Y_hvJ$jQD};Tk-gbrWlg4OBP0+&N-cBGtKt? zKzS4Yhnh{g{AQVfndJYm&DT<_g?p{=S@OUrBx7>TknM|Vx?rhSh9#Cb1 zv(0(S8+q|ORYAXByYm9z9;iy@dQpHzoU^Bpo%S^Pteu*1KV!DX7lCjff8ledeYAXA z$=3$H-8_uJPrG>pJEqIS2SwAV>aA~taG>M1>4Og~`yW&tFJ})fMFW<&r+F>Sa|+>1 zp&DL*aOr>o99u>|Y@++)ACIOL$1}m9h7!vdeb28&H`Ov()e0W1qaPzJ-lvlxuh|I@ z4Z_9=-o^$DX>BpZZ&_+k3~1hOcN;~k-@2{rY}lt52*e?gR_-|pMo$}O7I~y-YR0h8 z5(BOr=gjI(nump)A04Kxmme{V!}D88yf=?4JQ$D9o0>cz%xHpP2h%L>u;65Bi{G%H zuH3VDKeIv-s+-Fp;X6%dSr;$E^<}71b&tG`ofhrl@!e!&Ku9`qMfX|S`Io0{9zot3 ziAzrwf!c@?rG^8QJsTgB)TY4S+9Vn45~bQuZvgO+z+U$dR}A%pKTUy%vUM zNCo3sm#|iol9}4E^0hoq!_(iuTl%sgt9@xD)oM+ zO9vE0Sg{vgSckX@o>dkv>bzO`blNYc-5|rTX>Rt8MGSxP_DKC9qDUCqUc}B|;rB@_;3?lXtW&8Fz<`QKgfEV-bzxTA2y-MG1Tq(|g9r zlFrku{;CJO6*fx+_-qr_yAa`hiO}ku?wJTTAu3PLT)m9hXEp@sB2cD%rT0*u zLYd+&x$)#xZJsc6sn;lyGJ>MlD4rr$>k`Af7x2fivMj~Xd}T5(ggB9TA}>VnOQX>& z`sm*MA4hZXPdj`~;olMyNg`3Bst(+{{6%4~d+z-8#Xl4HlzxLu2f z!gG^@!QTH=oVh3aTTl4iD{R0mlY@fYTW7W1|1N3cdnN~_n!zi+Z2UTWzf!$Vh38Oi zBy7tg-b@Di${UaJeb2{&8@+ME{`TZ+ZE;p1$VIDH|GnPu{hZNhN7glLahu-s{ao=` zN2L@tyxu&>BDMda(`#E}fF0RiO+3t62zizTF zX;(JL!;4w~!vJ(?K{YJD@OwoVN5J?9qshVsxqDHoV*rMg zcNT!A#rTAw$$|uV_$F3FXaG!*`)EtrHy#iwq@Vs^n zw|u^n865D!{jFR656-`r4tkw__zcA5=&gYX=xGE7Ugb@Vvdz8-5e|(U&_*csio#;R zrt`*_6exv#FB15RboRwNa&b#n1T$|8Wua176_G>(dhG&OR^zos5hQW6?XgA?6!Ann zTkTAERC*uMKrKr~?My_<&zSYhW3PV1iV&{S3ueBi{A^WEs(^qQkGAWFs0nPBBH;K^ zyd6VS49t7=PBce+I{?8^%)gWZo$foL_6O22WJTZH3m>(>F~Sqr5{#c5%Lrd6oX28C z7`mAAT0Amw4bW41g~pKCW*k7?vdz{L{NXqS`$pX`qdXol zSqnyQcj}2l2OsR%61Sio)S)Xy_8*{+RSk{O|79u1;mji0O~I z)6)NQzl*+D)+Y%StwG1t!QHdw?t8QqL_iJu@Pr#+s**Y30&qCWzBCKY9>_4&?grVo zeb;hn_-XVA%ewIk61%0x`=*a}JN!R8T?eys<&;2j3$2Go;0bN_tR;K>8~LrhB75HH z^jnql{FH}zkpT>=BZ1M{l9J*mS-D@foDLhv8N^MqZhd7!9S9N-w+xO(eUtS}fclhwk-eD7Zp@lvm9kAq2A0q)>+{MeoNqbmQB`u-)lF zU3?&u&eZ2Sj`)r85ID;=OHUMe%(sw z(YbuiW&E5g12~rld9JBGC&fSB6+R8T3b_?DQT+}7PA+3IqWS%$R(Ud~S4L}oyJozA z^3T=e!HLHO2c`K^j$!nFG$;vi=cy|dM2A;j3XN*T=vSE3_yp2)J@Rh`)Cxf)BBs0+<>Xh#%`*b9BuY>QYP zMi?|U9eH1#WUtUYer+*56O4>!b}NwNud3-p71_#fZ{*YSL$C*$MLeo!@46aWTgFW% z#K@8tGN{-$vS+orf0f8pTi5h-##WcNB+eTN`{k_R52rD2s5!>WR8vG%$GE%5OJCj36-7i3(@=D_;X7TdnH0FQ}f zkg4SYUXgy`^shU&>c5EUXB|YGBw&P4@K|}Mg zESt1t)eIllFQ0+sxwiA9Kcf|RgtC-*d5jYpx{Rfr0FGC> zSgSGcOvBD7B0DHyS}Fkpmwm9zGQu~>sn>p~#o4==>G|x5<9nW3VuZPlxtw8Ii{UgB zKaoy2Y`=+p4==2gIViBI&tIH3!rer^Zi>iky$Gjjb4=wH!ug=|P_;0YF6gw>^}UU_ zYc@FSGS7oPR%YXqA4yN|8EFN&9;e`cpNvPqa|PxS*1v%4owO&p=c@Ee(KfW#2mujIB!oz0Rom1a z#B&q)1VYO+(6?@k;~NOUq$lVzLMn8sS-n_-Xx6)v5)pM&ca^@q_v@{?pMleF?mt|; zSJ}Spqhkmxzo!{D3?lt>aq~5p^q>>&1+@p`+J-!#kX%-^>L>cOjeJ6(@Xyvt#64>i z{Z@G*zk5Z8Wo~YezDHcs`_;B%3DJNePx)IUvXcj$-@O6v->z-Ieu+A*@Q*lIiu8|o z>*4V^21_W-)M*NebKyS71#Bg7SR>iG^ZL?R;_^9Cc2=lDlNAd;CXwknFnpH}1#=VO2c ze^l1^-HRo3Y`Ko|noJXk?9GJ5bsMryrrA3k4Rc-_#PZ%dm6%jySx(5dg_JMv z!aVfX;;7fn8n8aBtK0IZyt+l(`DL*Mg~KK%Y+jFGqQ~{QSKVg0_31i8x7E%4%tpAi z<>u^YFaya0ov(ekWrgWm0h|5haXy4AA@RLUf%wbse#A*dSF z3%xaEmBjT#^Lrq6Cc5OcqZjMW#OQl``5oSA`H0>Olu&enco!Q)D2h*3kaW2k#3sh^KD z`g%7@8CdUDeuhr#l`}%Z2OGols`2yl?MGR~P?lxfm^Ba92AbJ`=y{=`?QR3bt>T?- zV>aNfB|A;fHIAm!mW|Qm6Bc1s|KecN*2Vt5j_iZ;V%f@Tn$GL&we#)B3{z>Ndb8sX z?W2ODJGEiwCZB1$jd+PL#BjopR&=I!!Dj%9dzilhiMV_Gv@{}Hh?gO0juMK;ab-gzl$$B$%M z?|j>y+*daL(3rlk1UF@2BBb|YS;p=znP&jivM&-p!T3WiZ-Xg=kI7c^Xq`9oDWeT& zak=IxdlFg7F-$v(6!H}6qQAc&nUI^$KN)fw5b~5NP`=tjX-}(^*A+R6^}Ks&lz#|J z;-B&vXDq|a$nZbn#P_|?<1^3C_>JcZD?)p8fmt%1($?yFf4&p`Ar5vwu+=f$ID)6w zIZc1``Fv1*E2@lxxw`IP;?hKrTQ=ZgNQ^fBC`kfeZh-@3J-yZxFG~Yz-pc}rx zfZuKOZG7Bw(o6apLD(F9;ju%0!Ly0wIha|iJY}a%c70pWYZN3V|0UM5plCmYEi&&`w$^3uGLJcS` zUaGI}zWPSQ)Te`|teOBlzg!>#T&FvnEH)Z<4;h9*Im&xS_h8hmUg5Sx~X@^mf<_zowUo=j0i9@Z8fmoI*~! ze%{#Fyk9#VUTPA4YTN1TuwSJdxd)zk2vGwD=b^n@IyXgm$nEEt|Wx3+3188wZ+$&K(x5(m%p*SDQ!)C zeb6R+@H$@BfqU}I7ETlJNYz@F3y|IMTi8C?;IwVN-2)$kZIWOsi}fgz+&Gt#6~>RT zH-UE8^Od2R-A)e|_mu8qt805IC{9(YJ{mzj=hbERZ%ZW%+OgewPJaSSledg-iSjg- zcUU}mR^>n{QPr|KHW1tB>#SjdP!@V zakX~p^ih8G!(!Z=$_d>arS_$K*@6jZ`u-0_Cd@D8A|=T-zAug^8O}4PAT@je171^P8nxv#sZN(yy;{iw3f% zhsn0R73Ds-K?8VeHM}01&o%dTVe)QGT^R{N%km3@G0KF^9`yFnL$(g{@M>(_RyDz%nbW$ybcG46_7GGa)iVMwmWQX?AMYxba z1+r(^ms=0-$`xmXEyI+0rQFYv1RVu-ndE_~itM4{pV=NmA+DL&B>b=kVfiQSHI{T2 zto535HV4=IGgg<^Pv)NHg>`@4%UwEmtHs077#E%tzTl)WSh#m_cPledAX*>3)EHb% zYQ7{A_f|dLCdx-DJ!hQdiF?CR+KBY#wk5~&)t`0C+74s$Xm`7QXVRo$Ll)+x5vobR zb-mko!PV$vUEKf^^U4U-Fmwud%sLYPC>5){d-Qpt>#i)6ec@LQO^sLP(#Ts?JNJke zdd+E{qotl?ij4S^sAV736^$4AsbxN!q}kBM%uN9#PSt6j4Gf-P^Kd^)a%BGKFX#hE zYL?_^MhID#MFa)5q-VS@tT2)shhR;|8B>I0z?UN>f--|J|+hH9L|5{nrqX$!6>!tS+UW5Vu6>KKegcHbaHLNI6 z>%pk(y}j|#gZUT`S&axUlKboVr*u0^f&UE>5&;bE-=xOM&v{9{FBE>f=zyWKdW_IO zh8KzRy!Qe0UJag{c7ZCUw+M4*E`}!^~sgDs~^TDus(nFLsP(~BiWP{a)uiJU6ukp z**DA=$kS6D!zo5f_N@_BF1MS*i7uzl(O2&C&BKrqRSpC(1CsaO=U&ND)aols|IUm2 zAxnXhB1ZcDJ2i5$7*=g+O!-!-KhqAiB`>Z1ATN^Uh|HY5TxYxkQEjR+WMqg+m0og> zjuj1RH#j^8|B~&al#j-$Q6-%%yGCYbDLV&(S+SWAHAF&D%*D zmrv2NM*K!odN->`j)C|0M(nin94ZvpqfRQ5|Jb7+Lz=wrg*2vcVFc>CA$PF~!uh_? zGyO^eM>^w#^X8xAM$O3=q5U-KZN6*7DnEK0 z3I`imaR83%|EULn>i~zpx5TtlD0mg9p_2y$u$MSsp)X^=dlZB`$h-Rr6$ZigUx&b* zJL#(V)$w$yGsn?rcD`;{A*pr3463wK5{Y#gVFMTT?oLqSnn88eHyZVAe@9y2M(VKD z^xKvCp|#1khaG9!uToJ2uU4f)VQr1D1gJs*`0~T75ms`MDBhk|JXoDCiGzHE!mEFB z46rTc&sD`{8?Q=NqY?+ji$?8CiklI>Z%CoBU%$f%iucLQkoAujjR|$$LpAvc8ii(> zQvPG=Lp9D$Aa>6&(7#<(gctj*sbbRbVgbVPlRIN4=JyC6kC4L|ScL_8lMJ{VcP9JL}9#0-z*_0HHq>W3}@ z7So511tL8>IAp)!*rm_2jmZ5Nh2tr zk^C*S)Hw1epNdZ|0DuvR(j(-Vpm<;_thXZoKC)3OJ@H`i0>nW%!jc6XXa^C|o7#WK zj+WLQ71sr^o>9L}>Oal<-%vAG$jZ-~pm*kEhCXqMfC z>#~&m)rneev?GSB=XyiUk8ck{?>bG6RK93OfE6Sf%KJ4E0f3OI&xMY$8}VkFWgGV) zVb77j858$Mwv0rVp6`Yy1RtCJ@oG@-okav0Qv6RxT>>n|4@V+5V9f(Z@pG=5@b=V| zuwh_YFLLA9H%5rba~NO!h&%qI-hw6{{eDO45z-|rlPixI{U~aov;d~tNF2M3;xNNj;xdSOFOBk@rp&O-jcc1bO_9t*|MvV~?g@v58VmWPkTV!a%J$CsZXLAkXHbWoxaf@6YU*}=XaDSnU~yFz{97r0?r{q#|5N1H*=U4kOz~J5q#n3nu$FvR!Iy(QnKJIw+eI^Qn_Dsam3X z01tyrZi~T>K2fU$uO;}{WYkcJzxPlZZt_fgvkaw{BGM0!+LAu-FwEhdU=#@zkV>8n zjM|m1ddJ32VlGE3Sx7aE-QDMuqftoEA5J3O>q>rG4B>5s{b14SlqpRc(ckkcO@O8! zz30!_8?%#LuJS68&>X4cz3`e&TXNSc2*8huFhg@rN?%7UxlUz_+)WdCgF^+4vMV(( z5@P@OC3HwivMc06Qba|khY=IskQB1Gsn1xIAqXbBgP ziFDKj!cl3UDRE%<3phTn7qA9}(J!mo`^k@@QoRhR1(k>yfnXE{NO;t-w4KbVz(l*N zkq@-5bK8enDtJ;KD&kAkJzwrh-Vn7O{a+|YGFTae#Quen{(*8pFW>Db@}MYx039ob z6-#U1KTMjD(aBd5C-9hToKHF}Ssl5n8oLutwIbhK0oOel{y$7G1tmO6p@Do==DVx+ ze;GE$ECmU%+%PD}btr50ZKjTtXIkMYfq2G+bkh)JxasrB7#<0b+k#?%kr5$FobQH$96 zf6?JuVB0zsFtM8a?k}gIkAOoFHHg3N=8LS)vU2k&XQzLQR3u^$PuxQp$wRr{4S^L) z(u2G-;DGmMN+`rPd;uWJZt6b+3r<`AoogzdB{V>HMbWNYa9vYT9rZVYo`aAA!llmO+S49tlM#v7*~5 zNwr(A0fDKy!vg)wmLW-lRJ>m2QPMQG{x1aiV_y3RM#BIhZUz9alMfwDye%cJUq23E zwBzT=FxFQYGi|eV)=KGtK1>%ALRQ98z5aKMCwlaBjK_NHD3CuLR~OU@?C^tpiICTL zPUVN#@s8!2%0vbD-?xZElY+X5aRL^=wP)$*_F81k6%YRanZplNh}{RRiI^^H+0 zq`4zn8`3ChR}Rc+$e|8$5sc9PAvdSbH}YGv%{S#?oYmuDoFSiQ%~$ao#z)~KKpT8d zfTp{O@osPE907DvfE(XpOP%&h35pp!f`cDV?u3&@&rHQA`Yw3HT`y~Q(Kjf|0fi=b zgej4ZuMSikA_Qku(ea(UjOmCW1fXaNIB62&^L{uIJMi?uBSJZJd;#PVHKbtIVb!#^oQ{^l)X zY@_3I2bIlynn76rR0m90CR;+scmG!>1{xxO-XM#DBVnrOxcuTDR~tJ}Lq;1sat|_x zpbqNwpUe60^)Y|ONn2nA6LyG?yGo7omi0?8iSF>Vxyp;0Iv1$v2RK4}KfgeaC-<8# zhxoe~m2Rsa~WA>?);3KfV`_C|$B1zXZ$hLER@fsKkAzwdv*a~jh<25Sf?@CNfz zaxd-QRg2?H78N6pBE?o#GA(MG!(}QXN)BqX9S?q$TcZ>8-HH&?uXv|V8qQmJq(f;NGAvqk3K`PJ`MGb%6rh;&jMS@ymQ9Fp z`{#2FDGI<#_egTULznSlkSFwQ?A6qo5-T~)M}kX|uRH~J!tu6=@1er=kPdzJ-?_an z(LP4Hbfr>BL>Oq2XZP~kkA(7X?DD?Z0DhB*ntoayT&3gV@Qt9_8{&x!&*R7*GhF&1 zD-!~#72W#?sZkWF+f1X~J?6*~oU!b}gf+;E9X|vr45-vLFUcU~qB2*IvJPEE-%BDV zxrqqzw0eJAIug$vp0^M0rB;*L9N-Q(*F$TAe2+t=cFY85Reydb3$n0FZn1(t;KcfX zSRFpZv4z3MH!34GcN0FwVa&?+aa3kx%C|y?>h+A<_Q`7{G$&sQPzswT#5~~KT?o@^ z*#S~dRf)TILhba3hj&8Leh^RZOzfD9qfUhzn7)>}ZKxg)w^!ufSM17nn#ypH-IpYJ z+)2I741eWl9ptxDAhN?Ik>!sAWhP<-`zQ??_VyB3e;9p`2rmChK_AGAs^>`FNBytc27T#~c@*EGj0x z34W3BC_IuqlFVJ{knjsM1;-o-DK~T_$D9w5SyUvxI3#-*IlI!}{FZ7I4GynHrw8~Z z7(fj;AOD46K%op2jy?p3JNkhc$UtXUP|+gxk3HYSYf#}S4JQ8It^Q^Oi@BosZ(zQO zBJ7rb1OIis@B#zdczphE-Qc_quiljgPGBUY{sdr?>^<^;Sj2yrtKZ^Mjd0i`=J+&x z6IO}4(%=^t)sk;exFZUvXqnuXPSBCQd|%_AbHMl@_&vwrL)H{>w&*K_BG&w7)q>q@ z%DhMvLq0jVdAgumgK4@D8iVly$}<@Ok&5;=cz#n0P0wQ4gCo_6z!|DUclRkq_qihk zF?zF$yPFSVK(>QDG6$LNn@_mKtF>-3DY@`5mvVUjbC2>@{=v)oaMGSx(3eq_-Tp5s zo~UZYzhVpuuLq}Wz)|Xk(9;^6A-t_gQqY%Sd@Pp{AADcip15lbeuv=hb~U087S$B5X#2|VNE zBHY69;K)=y8TOWI;D$9w4g0%@)N_JI;G@LYG|G2^kak9enn+0;DZE1(QH-Lk7omqR z_Gj`iu2b`D#M)MFxJSkoA}RZE>RXi4e11LS|EnVzVC95h=fQvNoYJ#OBr1L#oZUn; z_6iS2%B3a)iIFb+*g`0#KvscxY1)mZJd>xf=hGc2~pIw2F}Kd?w}Jro%fgg}%VvjwT7PLdhOA5ssl1iI2ZdBB<@z-xN^4`a&m zxhqYR71PC8pYnL|M^HVumRJYZ5`p}6dZ2>8qTWG`!&7s8#K{+$zCLoOQu14Fui#R$ z0EX_ehX7W;1D>{HJpfKpR)NL0zZtGjqMb6Q5~&@z}LwNT9 zI^OH9#)wpU<$#$$1FyKaHQp#CwYu*M3`{Q^-*uR^Fu;4cj?<^Um3CaDztZcl%b)S< zUPx0y*9phg3d8;qx?v;-*$R%~(f`g+zc=xPK&n5kCh(2Tz?ZI)grL4gTvEn`hy@k~ zak~S4ItHXpJ8H!rz%)s<#c%p!JvcNuD+FU+{mj@GX#;482?qaqlTH+Ay-A{<+&VKA3<&K@~Sk!9P z3TT3O)^oAdi2D_M}sqKb~t-gLS-ZCc& z)Gt!INzsTTxjWPpjvi9`NlFAHB|Frn_C1jDD0>Nuq5LuYTe<-Lj!01MISdVidt=@s z2SCadlfPXdQ>la-P!mX9@EYb*NL@8tG-$jBV7s&DG&-Za@@x|9yE3X$Z>qx|97<)@ z3aDVxILM~Py+@erPKgP31@fe)A`O;vso>M{yLufiGNGaMVd2z{=~Y}MDN0nS3hIP> z2H)dL`5e36F=>C_?TfxXtbaF->42)8yBmlr*=RAYDE2_F&c^pKFk-t<(nW+s^;hf| z5TJdz8>p()h&+MmAV7j^Zjx4E;wMvP*a6=i6bW`4u?cr?N@^yt39C#*nUKf}W(EHo z328S3IK0fW3Ukb8aFT=j<1#0r!I6%LO8#K8rKAR%Ed|(Y5oN%s8x2lfX}9m7 zE&BhU-XMw#3V>MFgidYq6|2ZsgHh(OE<=z4z-%3$!UdgT5Bg*;RR2(OTYqQEo5qNcEyJeksR?L=NTPow-2L~@Xb(I^ zS$JPb_D;CdF7`7lV{=4{8lOG@qhwbh5GnqbGt+Oa_SD-No0zu!wj9wWrft{Anaf+~ z4xXd!!@z|D}` zhaNYGD}3NtER(Td>~gtwZo-;`voYPxq{%zD0hpHLHs9@R9y^SaW;J2(%sv?b>ujwHM8IN;LQDHrY&7=|GA{CiNHGHa}Ax_ zNeH})pzYSasc{vwX`#c2_37r?K5_w%=IbYgM^Xf3Gz70JJFTbUN_*(uw{e>_FD9YJ zTA*g-^QPi97bz-!mFT3~YIAZ%v8l399P~~{CF0WT{Ofekz27-4E{#&lnjWuN`ZI2M z8`&?vC>jEDzbHFab|lHXjy^_$Bm^qe>L2N}j`;14FD&uNk6%)2dsm}G zI=wh&_IB4;7;HQ#jaiatn=~`8-^q5#{RL=g-VAnFR_GL{XWLbnlJmE@-Y(qXSDh_g znpN_bs?9cSZ#TEGw=5hP8_xauC68^gKkcUX%=J>8sc)>Pm+eCS4?$s-07`AZelcHe zpbRQ&5V|S)0soXf*1;QS9Hg6No?7imn~m^FO|qO#v~IGgzj7-vKx2f*G+w!^_Zct{ zNK_motYOM`z$SIJ+2!vva>V%~e{Ut8;P-CBlKK zjoPFZvDPN)*R>xrIqOtBTYO zJn2Lvf8ybDjjr;{Vr8~`)H`MKl3Zt_eEVRJDJiC-Ik6!P92YCfqw_u{gCm-nPhxd} zVHulNhDUF=ZZ(cOyWZFoO@0DA(=#NF&VvJ72jczaySIiNz3S?T&}n8DmZ&e1pj@`U zX;10v*>rV&+`BsFHKH5#S!x5pU}#F3@eLgKB&Ut{)Lm(>`9ZS&4C689=|_IhFO`6 zAjWT_E!Q|TZOz4V>XFVKkszZVER7hKu_#oDy}p}!D1KBjtru%5DRT?cD3iIg7*D+* z%AZNEIbf++xWO6p^l;j>2ecn_hE@c(-adDe`7mI$JtH>%G;M2ecbR)}cKPxS98S4-jn>c!^1@W`9l;L z<&v5C4VOw$WmWBad56*P@Gr*i!YwVrkCc7YuvlR>cjAr1zWUnf6}P84846D-bWm+- z9DG{Bd|Oaj{tAh7yG!8?qq{mW_WsKF#o+4<%e2E!3b-BYg(387h2H`+^R{3uIJRad z&u+|LwcdDh8^0|J0an~uw*BCCic+%_vhT7=Wpq6~#s%Cr44&Ly_5yHm}?D+u?I(%j~Btt;dAHsx^Cvkp0ed!b+O@S@p??O^E%11?k|* z$D!fM8wDa@YJdiJxO3_NP`^_m>+SydI_KpD%RzA3{4+iG+Vb;BOB*3m$W9zRL+jq~ zb~p4I+HttB3_N$bwmogR>^$aGxlFEs&rna3rC*i~2&L=3wwBt6Sb3P#4ZgKyC488y z8=eh0U-!(OvTV3}Xl?ahp;oMhR|)e_7E-A5JF5exQ%zbrzBy`J(1cy;i$)sqm8O zUO^v7dyrzw5CR-r7Vc-ygXS*gGCY^@dC-&Zn<8|F{6CyrtSbK~ZcvqQ@cFK6{}by|(PQRB5dA2HgpGi5 zjaI0fMeh8WWkoT`OyM_kypmX>nWnxilUXaG=rH5D$$lr-v-^#Og>I;-@XBN7GYrG) Huly2z;5!jS~H0(vEw2}hSjUe4EEw!bjySwu)-tRm2 zeCOWt&u`5{9lt&O)$H4>ug!?I4!-)aRk84}-SItOebB z`GVxPOd^VH8To=-?{_ROlW$9nht(P>_I}2D)liZMo&TbJ8!_&YA0B_=hC)2XMTfoF zE>)t}Hj?JSkxebPj}4@pta^o^YQn-of1lyV?_XlEb*Dyjt@kgUdYoJ$WZbp9K(G4v z5GDYK<_B-li_C8eHyiDaN|ozD+&9e}M8#YVJ4Ea>?vb0Yr@HKirSfYs8vsP)Tb9e!6|RcTbcH$~_alU8@6==Pr*z(o9gVzM*@7@xuXx+U2nW2MaWEt7?n# zq725-*)i9a9e7{z5yl|-n)~wSmg!@0$|DFfu>8}{VWaS&kvV{79)Fst(No zTtUG>YJV>?p;T;y5hr$BM85O6x=VR9ykCEtut`eU+^y5_R(rZMpkNl=lhg3#-WbSQ z*S`k*Qc>{nsT)58h0?SszVndVZ!--F?KZ0i5&nRMOQCUJMk~UHOUe-HAH`+FB`N*J zmxF|wrsgpKH~Zu3#6gKLx&1>NYMQ@~a9kRO(Dis+20Y}A09*!*TTT+Q|Hy%aEj?N# z2d08cO}}KhpssQ%290$u87bOZHvo}44mxG~O5@@WNZj`#lp0u|?v^ew`Dt!_-4vK? zeeRCTJ+|X`pDg2jE)ZA9* zPo-T|r=$D#$@P9{44k&!-#nP>n^fKb+;PaqPE4as+;J!`liy2)m2YqZO$X7QPVyge zZ*aq66Eo3q-^BFO;Lw)cdxgb;U2d9d`SV?B1^wHU3t}X7=TjbPm051S{QIsDLGWzc zq+DPl#XV8A54fc`x(CWLQ7iF$-50K^s3#BP{HiZ@srB_?9H2WH~exS<4t?nh)Voi z!tdUc&8tko=JFBMoqNQt)9MQoj%HQcN5oL%`lGvsE_5X%`%aP7yEmQaH+Q_(MxQ(a z;ExBLWMI?5BM=TFqZl)Apu2X$ly&gfC<@g%yS6zwA}a3?m-j#^v~NwVIznjM)tnxqdc`15)pd%n}7VVV7c{f8A+Ox(p|RcLShatk`v z&$v$3`QS~tRiJ-a2>b}>hhuA(<6Yii_an_YYkSKQq#i#91izGku$YD&f~ihhK^_i zny=wq3Dp<>CUp2kY`PLKnv#TIb0A&BtD~Sdd08gj+rBH|=2|w6Qn-0~9#PK{*i<2nKy|$@oygL^0vB$pCNt<(Ctx5oQ zBLdPVaH-c90d1N=OdOXl;SH)>Gw2U&(u<~ z+@2q3W-NG)9|@k`VaBJwvE(59&d9fr@nBY(f~AVB{`(+63co-|GzhL5zt|u}JD+Zx zecskJs#G;0d!BtsE`|-uAALVO!AT6fCNHW=e5Y%_|znrkswLo5jE-DyaxZARN#pO{(jldXPEU|> zhbZo4oiBzBp?aPMoSutFUZj7wsxzu-)0Q#mznVBEYX|Lr! zK7yp_?qnW(Z|l`Xa_&%%AO1o>BkjiM@1I@57T`4>J$=G^P}*Q>j)_{gbtHrtaaVbv zxv_|dZ)*+Ozih@ZXhEM`ij(2hl^m=t|MN`xGujj%O=(?k-!J)sJ12 z$qP%=?Mg5Ke9e`k+Kp2gjF2yOj{B-3*>f?7M&6HYL~CeUN5en2q|LD1s_bF03clO% zwu%!ab=S7dij^+F9_AY~Rz0~{B9T9t58hykpSsni8zZmRK9?@I9FnWCh!Z-9^8^D5 z+Nztr*JY1hBgJM9Mvp0RqWX`*U-sf=f5r@rt%XVhwaFmqLt#_jYxZBcml!rD6S5nU z;~~Q$Z^qW++{Y7tUSi1KL%x*m?=Z?}pJmXO!8YPTu_)0t-%VQI%Zl*C-<`(^>EFwJ z*qe(J9lzQZmC}DakE;o}-i=zEp|zOnqgXkP{f^XaMNQryW5}R!54xfTTJNw$DVN!^ z(@@}6O_=9R(zuT{1>8@1()whV>&-jRQ^{`RSvrUG=_-F{ZR#T}der?8`3APvXSf?z znF?OpzY^cjTF^bBMwW_(_f1PYOwt%sUzd!i8bDM<--KMLZi>Bu#rGMy$8pEs`>!$1 zVC#PP0ta&MH-(&y9q(PQQxR+)sN?v?uYmO1KEVkG~lCP*i5#IqI6A3j{PxGb65=An&d3itN-;fIB>X;&tOe^sF-jRDSr_ zF`d*|AF6l@kH^>4Z1h(4S7guXZ*ztAhZiv?>USnkCZw7d(Gx4OFH_8JXeic));7TL zvL|{2L*C|sXP}0%%z91{aaL)E6pA<0P@=+Yfar>T@I!<1*#tV;j z(KL9Qm)IR=*KLzb&sZ-gT>=f{F;14$zz;QBNj2lx$cd4IUChIWnkrTCKep84?=>}e zXK>jnClhkJ$a9HKD7`zWI^_4oV-y_m4Nx}$+Jm-L5fUgn-}BAe`GVm!ufXjb7b-CW zl$@bR;Bgl6{4=1RjO3Ca&nW)qev9(dh@1{GtSmEU7oSq@j&I{Yny?YJZq>+)IiCwI z$&m8Dvc;ulhwMMF!sUKUDIgq!7?vI31qIu1rV>^%&N^8@FWozfBn`{sp`F&&*-l2`e8k%MMXjZqxUhttY^{Mzk8}_3W}g+7&iUBcPH2oj0naj|DJ7 z5=j_?sLBYPiMuBu3F?*LrIu-*mT~R_t&XSDPdtm-On%^xFCocFTkPz}8D-_&+(m-9 z%O=dSyh&%_&w~Pa(c`=k;=5f4-aq<&%Kj012r+Q`{sMM=Bds=Jd;c#Rt& zNt|}sh^mF_=@By9W6DpwRpWJ;)k&_*&W0nMojYm%UT4kdjoLYaL1k(txeVB^xvv|x zznwKbPO9bzGVa&}f@>D_9U|8AKm8tY)&#qjwL7N<4rugkzdRph8V*_*Zbn|+C#eb_=K>lN;V$BLE-1Rp|jk@ zxRU?<*kJ@;G=gw4=q=@mpuYpR4xlD-{8`c-cPY zW^^0*_^H4uy0PucjgK?`a%w*n@#T(+ohrNuB9+3Ubfafa(3dL7Y~ZtilRRa~yLBJ+ zA911R38_*!zrWuqn2GW#CYXfkAY`VIO3j{}kFpg#hQgCm;b@}OiY1w-QNN1V4WZE# zsd?v={`~SMQ<}D5W+iK%1w?_d3JK`4Mn81jm8lz8YxBfsDh}JY(R+wqlWSN&Lnd*P z!rwy@@E7U%LUW@)9~>9>uyUd=mr1|pBUmuk&&DlaHXmQMNOKO z%pv+z#6GXCS+8pTDRYf#=5UWuh$AW0IbVP=6ST1nF@s}8+{NBiGm6&36DN!4n=TSE zc(pmW)GOxM?Nd2o|crXB`3_=2_{zo+YiBhW!#th9|r|2@5PFNJB` z3In-`v9pWRe8Dp?(wag8XgI#&ZJ&nX(OjbbxL{LWA_*az;tAN+1p#y@rN?z}yu^b_ zI3DO(`W7`5LD%pXP-HjTr~D89we`S%XoRGoobe-jO;BDNTTQoyqTp>zUZO4(RS^by zCv4P(;sm+w-K8JAVg~p75PDt{gDe9^53bIoI6KrRwnS}{*l(gu35+Z$hRQ<&(#dE>)X|kX=2yp zYmn4@2NI28x7k>%ZNBQE@r$5rWZ6GrS2>USI?%$bBWPj$srA2Ykv+P&XyQ1aCZw60 zz`;QHe=(yL8yc8Fa~XGgk#Aksbwbndw6Ee5O8G;OD_iIi)3W;$D)<2;90vuOsZfv{ z415)gzZkQrXI59(;&iM%tw1Zw$C8hGyD!aX`CrH59d=gMcad1tv~*spGaPRD&nTS= zxaqJ!#=p_AnsPVcR>nJ333NY^t>k?n(`mc%#%(ndL~N4w)WNmjA*h3CSR1QGWu2R} z@d*sI?Lxq_vI}vs{k_8&)dsW82l{_XK{3Ng1J^b+0_ETYPiG~QVwR5i=S30U`FjD$ z;Vk=WFYCla6YOFBArn#VmsbrFQ1lj;{S2 zQB7!jI!=$zQcIZu(Q5hPOl9SWfEk>C1K zfD1)sKj}RKuuiA`wQ)gFc_2ypk~zRfu6xQasS?>6pJkP^qA15<8hdrHyJD;wx}v)Y zd?RnkSB?vI6TA8pWx+(-mRiwExpd!++lCWNIT!{8Udnrtup?B)*IF->nq}Ne)l-AF z#OXLu#2W6Wc$&B1^l-_4)g(v`&KaoUKv9@^hg)h8vl3%(V(f;8Po^-+TmVO9Gl#N0 z1C!XY6go&yszf}cB&OL$ObYz#*OgRLaPjzpd~MN_NIUatV;!Qze`v+`_>1SzCA{$e zD1XkA^%u+0etDr$au*_rX_MHtaYYTs*(l@OY;_H0fV@n#OKi)y<9-?$+!W}_U?v4e z05^cTV(R+OSNfZHD?rK=-!Dgdvl~(Jg;dF3l;FZtf!CD3x?(*X=b(%hoOr6b1@t0w z8{97OAFp?}O}^+$29UpP<_jj6wYqU6;mg%~0K@)+NxalM94NZY9k|f@(gY*0?m}j| zYaU1P?UP9Y4ePY+N7E+*wjq-#@GA~SQEGMJ<E=lCYOOPV!Q4C9Ti-G#7~Y!W()uM=95a`G>Y503{>mk1mjmuFLab1k#q9DuT91t zIIw5Ur*@tJT;O}3^`2#NTu?Ib zHN{*;v%R0%1}DZf%PqYwi2_bLWjy!%BR(3TywFYGxPpB~SLgv(Gjrr8DG$z*ToH5h za6$J4Vo#ipXyEtpjSbD^I=hySEWbzgg=*k8dgE;I!eh~4I9u{+QsBy*PU0N|zO6nF z6fenraKEC$*_QY=2~eID**F^>1d4;j>_X${& zfd*`Zu`g~fN%Mvts~}qwU?Or$H6mZgOfI(7l^gP@h?y7K*CV>sHEiN?PczCS40_gRycc|d;JepG0yP?}a z`n?1>=tBBq&5Z9C7(pYX3&%DrhqFLRN)of{RooD7|q zYy9K@6?d-_+_w*u9RX4dJiW+Cp@8NRkJc&b%F^F`0W1m9+L%FDW~=3=7oxe}B&jr3D& z+sFIOe56lBm|l;OlfZo$Cg$nX>$ZbJOkOBL5^0AB!9e~yuA<@1{C7Y_5xLT1L6-q# zSZILfgYc~c4jtrl5*e&ad8-Avt-?aF<70pSd>9+ouM^81hrAsNq?w-(_RuZk7hoQG zP%5IYwsLREP8_9Rw@=Y`*7%5)FgNz9CW!93wuqk5G9NTguAwNGwGW0Od_{_sdMP$){QpLsgMba$zy-crFFD64z zHKg{+u$7>_4USP;vHH&O$f9qXT?6Raz!@>-18$$)cVF5+)Tyuwar3PgE$WZGt@$to z8!sa^gbp+~wk&BFWNg5CA@h3lPWl#wlx?Wf~s1eP{kw&U`WSWJ$wfISCDrR_+OMWt0MYlus|tqbp1Cg z5x9!3##TL}!jdr-aZC^Wd&0|y%{basojZ`yBtlHLK2xZKFA-CL$F7tgu(6Gt;Tg)M z$n>K3r9g@|>+fNzvR6TA5)s2ZmGVLVB*3`FvAdp-?wb2jyA&3Gw{vI@eZXpX1s3)j z$d&AHR~ce&7O4dSyV=KFc%Cv$IjIPMou^V6)Eyk@MiO3g`_w?s>+l@^pL9KW^&LuG zz~DX=m;`Xnelp3;>W>M>bn7oObp~B}*Q{zp6i+%5IQmmsspNp93?m2a#X}}e+v{<8 z>mr2!Fg%ohkb{k1fwTK!AhD89HBD1=Kkp3uFw%jQNt z)f}G2tt74kN)kwgfc3BC{OaFer6_az(QFP6ESMHXdf=tN=rC%xn4J*55NO#S{gU-(m4X z0%@9wM@F`yO*+ZJG*C%B4huNbmwuYk?*4AyGe+!YN^t0(Gl|7g;F)v-KTX7ztT|INvNcl$T)>;9Xzac%E2 z{+rR>2l&-+XZK&tU!ITuP5gEIV6&Rgd~LOwz%K^2{sY5zBj_=z@5^)qf>NGNJeBwhij=q#CVmjjS(P>JEO>8mQ41XpuqMujs=@`?}xQ&|+rh6QW z`V;Ra%LdtYv!Z*e6c6}*1_~z+_Jm2i`wsrNxz{#T&8P1l*tu`!T<;&uZ6CbOot~F+ zbAM-bNq=j+kUWyd%;hd(kEC-tnoBCYu;RC z3Gci-wbCXT$|i_&mVoVv5L_j)KGRBm`>*ZQ<)NS1XI$BpZo>nW+u?yWf!$L{22S$s zHuHUdM}nb6cH<29(ioLuWl8PTl4v(GYRB9l4?Y!Hx?=1w{@d3sUW>QaNTZS}_AiMn zSJ`GTC^AMYV3Px5nT&zmzr|7_i*TAKK#Y*eB~%{097YCqXfbY!D0g&XvA>4Nk(o^l zA?r)$o=b1y%)h)LI@8QbKeO?tz_sZKko|x}5H7dtO+mx+Ltau^0D&Ga^^8f4CQBj? zNjy9VNtyH+Js#nKQU5})FMf~+B~ZXlSm2qPZQ;THc`rzq<|mN2!U@f z{fSU926$iU({V9P;8@4C|4^d+ApDcBGQ>G)n}l*fEbDZ50#6^ zdpSUR)cr*!9$}t3o(9!_1qaor)T>Z1=s{XTvS#_hmyH=tdZU*r9=!bHL@BHF6PIVc zxWN@O%LoAzdK`f~%KKosuznuI)K1kWj%wJ~WD(6D3_dLz^8O)57KRz(5@ES=3RBN- zI%3rP8?i>QY1k9-0BhtpJp7{FXZuT`$x24ZOvrHr_{F==)|YY)NVnemMf`R3i@>p| z%;iwSZH*cHi>M%(+oOR%POXvc?CPI-B>KLbLk*vXnMH?~3GKt7i_s5yAL67EbZ|0} z^yhxXN92a(6z_?!7<90A(2$c#km12e+0N&FjX3h^4PN4AfGMm7xjHy$38W3+*o@_h zTY7MF=umE9#1Sc?@`lKT5Bx=b+ZCzSa3gLRmRo4(`-2C^p!3|n^+?jNTx|3e4SOm< zAqHprI_a}?>Tz>s|KB*w>J3QZRvuz3Q_l)9;t0OkKKqQcBGdSMlsF@Fknh=Bsa%-^ zgm23Y^@dVE03K<5Hu_N#8hVx~oGpwIiFH!RZ^tICR$@#vVnMm`B zfa6SmiARf2n9jmlkw6|G2vgHhN_k!sXiBHn79q4Hebb-Lq$&K_yk$Y1*p6kO*RZD?Q>8?e-2q z`SreUB@;#}$xe15gUkd9JP6)Nfx| zj9@YQQoF0xs{++DCNkI>G78NulR@jJa-7^LExT9Tc)Tz5axr~hMhBt%l1qDuQodfo zpE}JE*UAj=>qAg*1fSFNjVoc`s0pf(V9&Q_1sxZJc#i`LxW-nezXz$SnB>Vlx@ z?YE{he)hA2+=ghn;6LfpUR^lqn^`N|bkw-gL==%^G}d%4<78&3Bu&{-XcP-jHPy0q zR>GqsArn%6d+;MA7wgnqPqLZDFEIo9XzWSpQ3A+-;sx8UG(QB+PJ)IYCkqCNd^*g|Ae#v`>O& zxzy{DpP3H4&Goh>igDD#FlBPhrRC$P+ADI}jU9HV{Hh9`nV3s#-y%tTKrP4R>WVkh69pvzrjD zBIEPC9CDcZsy*y5C#^H=06z=;Sl5x`_pz>D-5-SK0U%U9fmt93xIrLvJb@E9jehD7 z5XP`<1&_eV0?%K7xP%Ep2gwuAJ^{xQ2!ZfJ8U%mUC(wTa%P08s1l~^&0)kl_2om2x zpee`-n9ufO<89)`rlx*A8rx(h8Aa{c1y_(;=Mmx^i8pYr1|6fKV;P zw1zb?nNuOG)AO^MVivkWAQ z&;&m>cdj8o3+oTn^q^wcRHF_^ZdM6KGk3Nk~LGUgN zHC)Y_njuVTIhdppzYl}k>`m+|^KLIHp>7l!2{)AI>BY~zB?7{5RRh^@Y1NQz02+p8 zYSaA#q?71FWisBAJklC2&OZJbrki4yp!T=kiA7vjiYrnskb;hzD6#Buw>G%KXNP!%iL7`ms z&Dh%S|3`;*);Su~$!6aStNs4}>wr4>?3>B8-z`8fo55F>D6d0VDnAsN^JV9Y1hM1= zhhKZ(0L5SPSvT&b3N>cCNjP3+DcIQMa8dJK2HPqh!5v z!aS;U<{0L~8T*!F6WuYg5Xj<$@)5hZdrSyL%c}^rE{c$esOOZhP=oH>sxX>1^RmTv zrQGo!PP#*yo}+^1J5%lB-@2gOD#JQhB|RR^%A%DYJ99+%2qa}$)`hqTx-b5kqEIZV zVFBgAAys$-{WYV{UNT!vN#egNq$q1&wlEPj@JA-{Isc3Zb9nh%(x+>ga2+Sj5nzlQPz>wR^xkETYb zbFaXJjJVY1*k>HRL?-U$%NwC_&t;~iVRzGLaT)2bAkNP4dq#yd%WI}-x1@Dr<48&RdjP>3 zm=%GRI3y=Q+X^Cc4CCgklFxm5YF8{+i94mog+Jkpvvf!Jm~omT*HD?RU0PrZvm&X} zF5h}gd-9=>he!SE`7l+;$(<`8_+%N7fBDx@0f^bD^! zg{sAMcSd)Evr>*f>)DeD>)*k&p+JD`8^sdI4XT3gPQ{K^@xoLsPHqy<4M4$UiGP13 zH7z7qC>M0NYhiW#gF*gQ@_quVF1$KU_xDY;S^~<*Lf0Si4qKx1)>Z1H0f`{}+;fqY zWq!}L%*fvgihM*(%fe51mm#*jM@MB>IYMEug!AIHsAnBKXKGN?jkmaAjQ!NaVi!r1&v3Oc79 z;iTdh!(|leJvFZ$lHX{YcHeYr1yTMyaW)hQ#;EM#_@lXsS(_`gBVm(4r zn|1lReQ?e@C)K=~XRCLD%aSePST4b8+q1lKNoAV7q-U0+l7JQ-S`$9~iKG$Ug%stf z6jcyAUhg#hPqZL*&W&>})t8dfS!>J|${{y&@x(&rIHK>F;wr?rtC7s7X`J@V3mLjA z*4KN>RX_X-sjMjDZsqN+kP7!V|Ma!Q_yze}l9i=mVu@a?Zw{=S$tvoToN%@`;-N+# zu(<8wbcZl7jzWM&8C_oafG{l39`}yF6o!HEO8Sp_UN}c*ez-af=X=i1!fDRdDw|C!{@`#RhOVWu8~ctf2H1QH8PNF^Um( zC#s^FiZvjZ%i<;dHqXZCCJKKs^r$8d4lodshe-M^SD8ywv7;h~1*VYuFQS{GF-si7 zfR1Q2^!dV316mtp7CNH&G^6ig7rM4;0xLrvc4Vlg+HeRN8oiqmIr9F(d~%<)~eNPC|-)Ou8@XalMj)NuMt|402I z82h#})b~ko>>vu$#_LM%^8};V=q^4}5pXToE@HkGIf z7`1e0WXPVipmwc8B7||zaHG-A7$gDtN*Pid)&;u&{%1D?>Xg*+;xV0{Ug#Cm;9yPq zeU6cob!I_W_Wgm0LICfRB6}vGw0C2Ll5M_iI=|&Qj;6o9TI`frADX935T3u4k1x6Q zLcp3v_PMKMHEvwNkGES6c-Lsft1IDJcwC7Zh+=r}+v5U!mTupFWkMGbM|>>-{0$by zbB{)*&B0zD{c;68j+0(HYG_*2;BpuA_8TxJ_Ha*goc* zCsnDR-BNOM9I9wL6U_fzh!%l4bd90^@pWZV_wTpr&MVmZ@2 zp8usj$k%*h%m*opuT=QW@~Y&+Ta7oYN{dgeQjnBSM!zalNvTI~@$HM&8}0tj`5)#Y zLLI>l0QPk0C*tCdS$^j}v2;Nh4B39(yjZqGlO~H8Y2sdrW5SEDHnW)e4!vpGKheS` zv!|c;a7X@)$%^Z-cy>RZi}UDx?c~;tTYzhy`<4|uoL0r48kbf}8c&hsjTXVn)@FnJ zI+BkGJ{2tHG>zYe>prkSM1Lz3j_`RxfzqH5r3A(qxU07*>@KF07b-Nqy_q-;bSp9PJDLkCygiiNIUt8Phqj{EDAzb9Qi4sua31Xs z8nwH6K!W77e_PP<&mXS&Z>4RZRcS z(|m!r?Bs&itLE;O3>B1pHfaPGFB&L^{qKLYkgYWKb-xVt8U4KEksUcVi*cyu61RK5 zOmEBKER5f5is`+NU|haI@qHf=P{epG_c<X@FLA>@(n4a${5rOyLRUsq zU|nuQ-?z%65MBZJ;H!n`4Vp{Njz}4)Cg_qdV z3c)xq#OOKJPjQzx9i63fE8Vvq=P6{nx9C4br6xLDRhkcnWE{|g+|wKS(v6NXc!)iv z5f+>_XozvTZifxm-Z^^Ir9?J+BOLO%;J!dvu-TybjoCahB%_4qk(3f?n1abkaTFW5 zvON4^>mSY00PdPI)Z@}G6xd5TT6m7_8UAcRXbG2cuKmC+a0=6-PgEe>xdlaov)TA% zLks1?noM1 zKsfnQTwhh2t_8qz%!Est%f`&Mrr!K@*cznkq574-sA6F`{H^9Nh*6EeCwSu~{F2Vi zPyl6uv2tBOb60+^!Qnmim8y8Qdc0V;(Nt8<*2~Bu#Bc_}pLx3>P+rfn!RTU-L42+c zTXk<{hR;7IP3Y=n9zzJEIWdWn>L7T!u5zNy5(*#XFW%6`$ zr&>n&fol)1#fK&Wt?CN2R))sd5{&$QuBr<6`)|Ja5Z;5gW^Rk2mAyKe^ntbKkEVy8q}j5y|kq~6{D z1A^jHlnXw%Z6xcQ;m=AMdx{B%`33lA2lSbKb*z~Agnk)WvZemo@pe;nEX{Rt+lQZg z=+sQ?A;09LtEny%G7r1C+PJUGlnMA2@{fS&0XTP`Vs&)*`BS@1?H6WbFErr(e&eSl z|MvVwjQNIEWZkBhXweOk=&|z8*j)|*;A`{ZqD|%Yfd>nbrI79)q@0!8Gmp^A+`ZQ$ z!n(|ir6|f|lVegE>;I@*GYL$p`o*0^kOc=WxmCzK!Ts4T;3-7>8HO=>GuD615G z;&WL=%X~d$ZaJrIFq-x7w-0q_m^46vc3@`=RcEh2lRJ$mrPdrbty{cQSRn)I4Im7B zON?x8=EMAs-G&*0T`kmF2F1svL~*f@An1>qV_m`Xv={fK`?&o>+@NgmEh_^AIeu47 zQ7OTYBnD9^ldMxcVye{S*I^4MYr-$$C9k83 zuy2?-wnt_+HQJMV-$Tb|6tq&4Z)BCGbadPN=a3%HRak|UhsQs6fPV$9p7UL{^8?qW zj)9;iQQYhYxa#f*S`y9Dvc*nP{LVjUYrCccM4#>xw*aM z>o?fd{(aNGMSxrH@$DEror^|NS~DNTNb8H+qTBvs=h{_>fl4U$3+{{SvsRzNnWPpC zy6v(`-r9Yf12^Rq4=6Re{04OzglOXU6BqG<%dy}vab(ARv+f^jnS=b9;a*^&`SI*u z6f=6UR#09tS*8^>>KqrYBlz*~6z7L(e^1aDGaMT0mMN44lq8Coj zcDFwx6=msSy|765VvdB5;Mp1ULNM*ipr!A=TPYXwoTV7~Wa3C|g}PY3?znyVf*YEA zXZ@;8C0(JdU_lf<0RuytQ5&rF`f$-vto1&pXzYD(IsbT%c;f1Hdiwh{RPq;UF3lJ^ z_RpM7C@5FhvsIW(8JmDpeFU*Zyic6{c+Y4W=%lFDNDw#%ai(9bMPc|KeGh5pxGmcA zyV=EKTmS9mM^;}sQu)Hi76k|0J3K@@>J=LP1g5|Hp-gdzwqIMI%7xF_+ZQ8UQ`k4- zpP(33Z`wFFYOH#-Un(aKsdSw3%DQYyF@3pR#Wkp&e{OgAW91_+z`2_7!8L4KnRIdZ zYc1C>x}S|mj754LckkPTq}(?{Ren|(9kme5)6#`sb8HsqqqSeIp3uzjd`(S+$iGx|B z9`OfW&NRrI|Gcd5C!|CGHFX$ojL}O|%-8c)rR$nkyE;k{0(`uTx^RDH9=YyR_Z^F# zxZZ8_*n>NsaNff}M-k5f?i|l&V~}g}uUvXYsV>dDrLpHg4YyRct@8c9SPR>DTV-vf z?fL_4z5&}Zq{z@O@AgJfUJ;FZC<}R`74`2#2ewFhtk$sRUg+*$ZrH+fhEAW$&i&)Y zPyDTR@)v1l%LEvdnNh-i*EmkPRbj6;K4;Cwy!=t?LLuj256RwOsPw9wah%McYTiaI z;ta-}Dyq$H_emgw6Dma|EEM%iPl)K$S`&INm!GtSPF70bq$yC-II3*G@2m81ym1<; zO1ap=XTGPf^S6OFXUbKH&QDcAKlPUW*;`7&hFF#L{B_`EoMD`$v#-pXU!-Fad{yy7 zTW}R(mK*{jn-WQ+m{n%P)X_iwH_r*HwKN#*)eIW*?ASB{3_mwDJwMNz`f_J}Bmi5Z zT{{{vlaRfDE91Vncfv7Zme{h7;Z#rIZRFAw6^owiDevgxMl^kZf_n)igspl~sbqvu z5KSS}DHaf{nL+RloX1F-?0wvMHo-1F!5%ol-Zf$9*N7O_$R69s;QNExf2lYir2nXL zCbsg3Tl;%(OgO!$)RhPEP~BFgOpJkKOiW;ny+jd_Xzdnv!;jOf-X*ZrLJN5SF@1Pq;Wig}>3mrtScs4_Ta22t;7 zy0cd~qWXw?773k_ED{vLjnloVNA>yc5M_r>X>gScKXU2nt!#_*)Vqh- zCH7gl-%}f0I1R6``S?g2RXQ$Ppi}OmR~>QZp%RJJK3Q+DuX=j0`^=T%pi@qu{ddo9 zd6g7V_bOREH#ml@y*E6;!BG;F&mU6si=mZWC;}(^G!u{fBPY}UyHVi(V)ZV5$-?`b zJ5P&9wDt9w;CbgPcAUZ4)$6rYIwyPvuRTW-OAoBA%H7=2@n2WRG@irm|yd*h*Qg?y{6AAd%W8j&NhtJyW`^v zO6g;sCuuKFZ>LuKccqrt#fuog5QY+r~mdv zGl;q+xFEe`w&OqO+2g+ruh|y=m1Y98czQ=p7l($I7?V}^u;g`AIJ_flXnjKro2z6? z%qz0HH%-YIkGN8{hllYFSGk9Df%OsclGZavfS+F>B?M2G>;D zXig#Z9@O>aBE>JvB>q8OA?W>i*K=7!5Qz)ttFG8m}UK#VHRPG>a-JK zor_fap|3-YfDVpYMUbuE(Art&_y08VmO*i}P1`U|a19QNB}gDagG+)t1SbR*4-njf z4i;R4ySqzpcX#*TPH=~Ja^2T^KTo|?U)A?xo9;f2?z7LWneEwTW)F&1SKI^}T(t)w zitGgi6>>mij~oz z4qAIW9FYXj{ptz3U20~SDbpOfDRJGW8(Y`&_B9oTK=j?<@i>dM-bA;#zisH9wjj-0 z`)V^i7X!|+pxmjD4|K~jAsJ|(@Tvm^RTTir_7YJ1IBX~(M(c9;%ub+lP-D#Wb*ADq zPZlm;8i7cs8o9c=pn#uWJa6e;SK{H|aIdbV5a;3>!drU|7L``Uv`_9w2{V?Lzf4GL zT~6O{{O&VO^@uM{aJow@NpKqYuUIGq&Gkav>;#je;w)zV@~R8Kw$gEC&%DNQhT*@$ zvk(02zKGAcM*evwdPt#x}Z}c64jWt;PL%FU#wo zI&DPM32xaPVon|`@)(v=qV2F@iMYWFVvI-vat&ZTS?sCbug?ZWwt z>r%#*sQdBc((m4G|52}y#<=}*+MlbViJSY4z58XWP@a`|*1N&7)~C?}B{gHSpo1dd zIoUXCT>tj+82MrE&W!&{U$F7HX@Ogsf+0gQ-~6dGrcc{5$)VLz6o!gHq zD7CGEVjg;5FSl<+pBVj&foLrCJ(sBNZ`Dt>?+ZPE>A?Y28?0`_YWbQQ9&$l~EY+>~ zjs5HX*S`&u94c=u>ic%iUavNuiW+K7v&RRe4p&vi%OEngxWucP&hFsNsymf7740|sRPYA z5c@fI<&@4?@j@-@_i0<#*BgcCs@UfV{GRo*Wy7`ia)hg$$%_N;iDznSf)tWyrO~=~ z?u!u$#5Zm;uqk@8D)<%WqZFL`hE!MdHAiA|ntoa7$i8-tDZ6$Td|S)#-wCDW7o>)P z+WKD(IY4$h)@0^Tdz>n<*}6k_l5Oqk(02DDziV+zBp1zzt!iy|sa6(;`qB0>meTh3 zg+)}!V~WAv^|!5!gZ^9VW0Q3{kCj}WgOxYtJa5&RlS;)69+%s1RC$$YH9|Wa%@Yi> zx|u%5VA{U1TNhp}V=Hm3+wI5sOt#8Uwq+GI83ibRR$0C7Fu0#%jA@jQq4?_gg~Tf5 zwfMm4tZ8|Jx7-&~q3Jx-*@6fpu{+vX^}=LKk7xF0=WLCP*zJw7LAKR+Sflr(eTXgE zOLCiqNj{CpVTp*GLGg02*Bdm~XS%xN9P(fD&0_Pl%mrecbUOr^lTA8>+7;Nx%iRQz z1cHFvlBtejY&<#?Z_(XxwzU2PNb`P4jXSI6j~aXfato{1goxpJ*JwtWUj`kT7$phf z<<$4px9ycrR2A$+W%W;ESWwjVcM2UHZySg=#%nDDl_m+I3*3xrzv^(OzV2 zAZqKD_)qhX70^k{VqTm>c2#1Hk?-cQstA)1D<8Gj`@8Jy2+loCAOL>U2pW z>n(&{mD*0+7mSvY?(sIGKjxDTBf2D1x)k7jO3}$RHB>*6(fE~$cRv&AfkBI4(HQC|61&_*DSuXxjiPP&*VfH12+*UPIW37_&c*S1|0h( zN(%eo|ELmI!+gTnqM#;4@P<8DczzmvTrk4w32$VmtT*8}K9NXr?AON1MXTOxg2|Ps z-ZOON+WYB|FGqLZAQg8dVA0U$wMT8yFqf4h2*g;^)Xz4;tT%kq3%KFHXfy|3X z4Zn+sDVv|hqw|6nPw$m@I=hRFE9)+5O*W$t5XI6ylM3JPlR9`5xoBlJJP30|jHv5${Sfo&aF+Sy$%m>$|h#9zb72>pp{ri2R?Y9la5AONr_ zY4E(ZAinXYFtGsOS0n@XhNTE2o#M9DOhN1kOfIbNHRhx zuzdon{1VqE2Le5K1-jZ|KcEw|O6HgG!UhX<&B(wJ0K1f`bkI}(ITxw6b*zfZpPt>} zbO^x^g%<=szy&eW<5=gRO8JGzH?chEp1-6s^tZpD8bG0OLsgTi{7>Q8a{t*n7=|X) zr6Pq&&?1?irr(hz3zdE(vm-CR>3mVJtf;YYIDyXx0{iyX)20-7|q0MA?Dw1suT1 zK_yY5VN)mI7brWX{0?9pu=Vyl1p~^Bj$MSQh(5uEV*mImosKIiZRqh`m`-$;KyYzg)&4Qa^NA1_i)1;vp;Ui7)L$4x)}p#9cRqwK!8Q;8^`0xV zS@4gzga8aEd)fX<33?bni^|4Y+h{hcOT-+6QOaA8h2PNPypM$)L%qlU{EB=Gr67FI z7kk$izl6^hn(pJRK-C3LZrJk!8{7UPex7&yT4Z+jEFfj;;Lyb$=4J(15`fX*5}NUK zzV@2Y(Hx@eY3xmo>BXj~`jKDm(qxLbJJ9O5>Dn)-dpg(oJrvLaXP%n%XAh64#ihnZ zR$u&Fya`q6ElIcwt42Q{3tiSIpqJ=SY6LeV4_}WD-fX~pfd~;eQ36h`lGfxatiXH6>$=&r+tL3F@WPK@ zHSW0?e@8pH`+rAv9SivJ{c8~iFP5Qr^M2h1ob68@=d)}{7nbJ|tmlQ@i+0Va zQ~JTFH@WJ44soQ?GeR)zsX=0zn6Xt}Zu-an4(l2{LNVTC&bxN>`riQHUG~GTeHu?y zQd=0~l#db=UI7jLX&Bk)<1-`Y-xe1JNai=AQPtVGO8@j%xR&@o?Blt?M8D1F$SkHv zv7SBg{lsR`P5nO5OT#IefBFg``VBLov$Ht~H^hS!9rD%A?ep|@`GT+pCR(Os*yh{g zV*;K9?Gi!UDtpEBk{KajfajJcVrSJX(Ddi3iP49V9Y1T8*BiYRElIf&j^G24$Gsbg zmoit)*G3jpNOctaO!`KhyCiP$9wjlSgh5GU(!F=?a;_9#l&d(tl(#P#PSNi~vJem5 zI)o3Arhc|6J(xix8$sr8Zb^$F)gSqyenh^V{YEHzW}jNTLK^E^)S3Y)U@#atYs2;b z4C5#)MEFzxnZ{8_I9x|GrG1On4dnV>;;N4?x@@4sd zMa0scM+`%P_r7yuTR!K1Pu>phUh~jlGO4C^nmpXz5VBeU?&Ms5B`jcus^P@yTTZ3+ z-r)g<7i+cc#YCi6$p&KI%L6W((HsV?quKI1L*Csq>I)7@bTp)H&U-Tvg?iF;JP`^7 zZ3pi8SXA`h*PfrPqKhMKImf&1;5|%GI@OVm6@O_uA~s%&xOQ;WwxW=q2~A2j(qN1tZMwD(@!ith)l-qLBc2JRGR z@?;MRDqhrZsjkrK!}SRlWc6u$>T6+q7U`Zo<>2YVh&MBq+>VZFoUz))H&IY0^`XI-c`>@>(VrB9;%2>j!*x zJZIx|WK6*adk<@Q26iZ6nrxrp0ii*ghu>KoM6>q*dyV}PL9e^gBvY8x25;X1J>(?) zzR@H5mF)RTU(@QAaHrV3>(ddH?Bk8p`TKek?yJ#G0lsgVrEwJqU%TEdJ|8F?#32f% zkQ$atT-|LY>FT&Y?~7fd@+5Lsk!wRuc7WThUc%)Q&hwCivCX4~NO-%gdyfWI7^kRl zecpONBjm{=UxMUU;vD}GVX$USnOm_>BZX4RmRo#{2c$U(D|T=s*%ZpYl^&FJGF@2m z@+H&QnKK(oQO&+MrMuH+A6zJgYsiimPip(-SsR0eu9c#jhK?*@TvkNNF zE2qZ|153HaKwC=W>UFzc<^#4wla$2;P7o8oCoAozt^9A1+pXbXh(Pk_NZ5Ply~XxR zrF%Yvioq=#2d?_!x;A7w@@p>Tip=npndR64gQ?~3)0y7qe>t-CfWMpvjI(fgLHDocP;|jvQkmyK#o7XGVILhjFZJGwfLz)dE5&v826>fT{1Z5thiR^kzX=LjK5eLiN) zK_s&FPme#GJSWIJniAt51Qd)|vL^5AeA%S;q|Hg{>&WFke#BcbS^MLQO0H@YHKVj> ztx#Xp&)E0!*a`B%eUDtiV~^X)jovT&#-uhwz;(YN5Dnl7D0@kIAb0zTKB^}U3E&F} z-w@D;wDs*tw>@03j1n8O6pCZHOknPy9%4xM77S>*>y z3t4}^Yk}QIexW3!5^*Pd*A|K3?Lkh0i3xGyW5X3R9+tY{F3)+#;?^X$Epwrf*^7lQ zumUM|&sQuI4S(fAwltO(OkpK)0T>~MUw6B=#;=`Tp`XLF8~mAqP=0SRmCfwM6^PwE zoy8ZJ@kfJ`ywT|BO=ELQ7Bwx3{nXK`!0twtu$0Xm(kb$DQP#^h+$S;W&nX@%u}q~qdXcNCe;c4cRvW2MATl>M@vlKvFD3AMVt!d|{ zB`{&dqRPu(qnDy^!VDY$ug6Xi}@>x+*V9(<=+HL^Ie1_f;CZ5?u@`j8G{?sL@!m=&)w6>K#Cn+!5gtnT!AP2 z%?&2yd4a56<8w8?cT_ILnPdXYfe@>tn~z`*>k5D6acCvG-b*DCar2Mmwpt6IS#JcGCh+_bUt!55H$qirbotfW7SAB$0A`+T)+j?xfZhm;1c7K?T2Gb*_ZQ zE0UyD?JU`$=TG5fD^2c?Cqk`mmsjhn9&WCu8;fy5csCUGo=L8)pZ_QtZ0;{B7=&n3 zZ<~fh&QkG*vYu(rP7={@bUz-a>8VO0iy5xyKI&cV`Z0js_3vU${!}xt=k~`Tf?{7>cE36OF2m za~j;6o^DROIjYlbC6)C%k?7nSrV<*B=(8SQ^7l-0O&zr$-5QRU59+t&p!B6D!E0&G z$19<7nwafjRJAL6Pv8^`Y(epFByUL)TvyApPb9kyMz8uDLVM#~N^Ynm9; zrPuH>ztb$K9sly08{1C1uA_9S`hD@3-N2OcVR__qC~rD%!p~lywh=9VddRH}y*X}^IEZ$?3scNHoFw$*GfHdmTwu7rKDiwkf+zuFol_h&?&!g1f@AEdAeJL2t3ecp;o8=%oO(f(>Rn{zPiVws4! zm+(Vgevv)+ZE}qXK+q*%G0Mc|x{#__cUdh^6}@cgY8+TMc{Ma)o_Cb+YFPf8lwbzV zy}epUZi)QTWnPs5N4NcYDP;aZVb`JmiltJ}+$?Pcq`4FxikoScPOBbfr5=iVPc%Vs_+N3P z^-wHvd{=Z)B}gjKE2L;+Ptj@uimLyLT655>KPc-ONBP5{717L;TljWo>!4QX>8#M_ zV5-MqJO$b?`unlUF0=dmrd0k5!G`QX#C#OfnmUUsE|7GOYOFwZRR+ECAid`tTCv)0 z^_#y>*)G$&^5}h(Nql^37XI0K<@xr0qIs_1CGW{|Z*Tu~=kKIOC*T1X_4nCo6HC5+ zezIXB!X$J$DHU8x8@bQw&%{k+el4?eudn@UqOtI`j;?>vV58C2zL@IE{poxCc{jdy z1Tn9*T>7A8Ru)Yq%txjmqR(PVv+t*t|+dfcjVMM;{WU#96w8}8CG z^G%EH`pe^Gtt6s`!{5ej=%3ve#yyR23=W=g$^unQqq;X7qxZw?CvHy8>?v69cEm34 zbsjS;8=hv*RWmxTk{U1@Z9gshA)jm7xC<06TEFXZQ+o-m+5YuZBXDu%`mmK-b%~`` zShAJJ*+r~(d+Sn;FlEiL+Wew6>vuk5{-J8wS-yw%v!hFG@-p+A>6Tl2{~UzF%0U{Z^}0n7uw3>n-p@Xm}v6E?&W<)@e{x zq-rlS=wrO}sB;CA@pRs%W*KYFmggW{`2zs7jEBDaOd(fF*t})G9Y21)f5%ax>fKV+ zp6y&(l%}rxpcQ={dT!D@G4;N7n)u8N3M;~?lpK+fE9Kaxm^CB0VJ|QxdITvvKPNfn zP}D8Rg*}I{8?F|Z*FMnY68UuvDGV)2Nc);E)lgrk*=AAj`#!DBzwS*%!HUv_<`NLY zuQ1o(QJ&#KFbFF$tz;%&TMBW^XAGk-(iCh{{3WkY%LK8{mp(XTO`W#4fSnjJ7nbK! zdU?=W4hiQNKX2JEOrA}Hj(}fGw4M#@cpDkSXSrnDh=8)ZGa@9^Z z&|dy3eExO$=1p&*&G@=KU%`Mw;W@xJtj+l9L>0~QD+#YQBy%TgzAk^Ymb0{J;VPlx z@mj|LCO?-*l`5jJ@eGpNgm`eGDv*A5zYRGkySy`RZXq4NgP84DA+ z6-M@a^h|?=NLNAiC6x{^cGEruAsC#OV>Vm8Xt~W_3U?VDr{|VdL`It8Wl0}dfW1Fw z3>!oErD7(VL(^JE7DAfvD8x@17ez9ZW?^Wb$su!{EdHwI&nr1)eKg$95px}|6+c8Z zx0%#eB1SRh4hl7P{N*&LG*5t&{y?`%9|__}C5jW?ZD;W^qbB$HOTDaOV2&gwEc|K{ z&t>=f*yq%I1BnDp5sBM)!gFCdUPq)EQiauPvw6i`J?q-!m6;Q#;>G=w$H}`16{}yS z$@@n^B}{0t11hVk@Mf}IHPBVRk7{t&Ig` zbR|+O>F`KJVs&d$WQ*B^#za{X=+A_Vk@pK{EgM~fP_X%g_kt6E6D z(^f@TI+RR6QRuTbsm8M!D{$Kf>H!hD=ScMPNEZ~we!vqH9e>5Q$66L7`1F#qq-GGG zG1Luhhxuyp*oJ`asfPXnNmwHL08|I;T5}}ZVDcwq{=m1xL}OB!;-Gs^dfe%}C z2T>k&8t1HgT)hHmm%+ei!2?1kH@{Ad)t??IkEzxEivpeP`n7xvmKRrg6?T-zS3_Lk z*0p)e9s0A?Vj72JFN#v&_3F)e#WhYCFG%>fGNgpXV5J?f`+6&VeG{`v+&3$sA8|4hNddiZWxee9|_+7;Qxv$h0pPW_8SkK-XIUk=MkwnTltPy zJKUP&sPe63KW1Qu;~P(2d2)h8;ir%ZB`DeUMr=|A27-Qc7+h6bzoF8aVI}z7ixICi zTLMb5tg#544=I<;f-2HrGQ3_!)keqwv_Kh3@q;{Dr8G;JlIiaoG3sSAm!Y^tl$$4v zKB=6JmwO#vVb5hjiQRdDAE4)giU8j>GQ*3?UwlCS2dFNk;V<2Jvi1&ZgHcR}gKzVK z!f<1w!yqTN_0zM!FmY$9;u46BqoTv04Sq#L@`Ptq==J194Sr!7>dcGE;T1Lh-kOaU zGuYA;0|eV)tifXzl>^Md!lIHFikTcz;T6SdvupTstltw>az2q23PV5U4Z8*&YD^r3 zB>-k{h8f!5v{DLQ^0BF~lVknR)YN5SG$cxcSyrU~)`R8^9{w=Fg$G37E{KToKy04@ ztP}Ay_!i;5jI|p>A%ejKxAsr{qnDA!Rqa^<66<@ZuZ--2kln(%*aancfAa-(MR{}` z8wUBihjpC`N&xGTX*8!(qmkeLgwMH;{y8k0TORszGa4yB6GqMYqAijLd99E3yEqXB zbY3h)PuP>%E(FDz)(?>z7v7!BRKz6OpiZH}gh67kE%GZdH!iae^=Mw;7~5A{F1gLF zO9otKcp0Ij7tB7diH|0ThdzQNq7S2@|4`v2GL69B>Ay0Gjv6*mM?rBXm#ju73yf_q zC#K3Pg9nv~`YfY0&>1`Y!ucOG#9A+6K94D>(b3j@CQXoILFx)8H*j3OCY(hQz4Csa zyAl!@OQqLL(;ANZ1s(T6WneoDy%m#I%P(5dE5wFg&=<`xVpF1D7)jHEktSQu2jCEj z8MnzaN|&U)bD$h&+x#Xjd8y2kgk$^28v)k(Wsq`FLBc*66V{Wuoy|I1$ztXzaYt>T;!hBA&_Ze5gV>6^XdZV`ji&>3cj7 z_BKkVmG(JoJ?k6n2~37rd0hzyd{62_3z!f2~I*#ld7Md>M2R=PJcw6nt(W@Ua#n-R0wgfoaQF0F>BzZ zCM}yWlZc73f3I-m8bLt_!<)H^KBH{04TAmxN2`gx_WG{P5RdEHuy35 zr?ocUCkB-0({fFG_ZD-^l9%G35qF^pz3u9=nu?8qqiI(n4YJq&Sxm%@8YBWahd=}F`q#!-etGahNIs&B|Ukt`pgB9TZJ6nP+7rNa7?oG&8m zT=-10!qyEL@S6%d5RR0mhzeEabC&%H3Hi0bHMTNt0X6X=k_zXTBscf}Eqr!Z;Yfs8 zEVn7}$x&NRIN9L42ELL%X}r%`m!}C?Px~fY6@}V&H$jvp`rmtoQi zf*jW%SgcJ6vXS+V;EzZi5!Tbes7>Ju+&O?K^0v=Q9{ndQD}od?E-M=ZqhKWz^bO=} z%$;HpVK2ik{MsPLhOToXXPX-en&B=4f+#f~$mGE$hex%4fJ5q1d4*`~74>0(hUc+I z(j}W);|ZTot(=TzIdc7Hn{&3;c^}+Pr2jCyR2Y6<=e8GuL{OF9xv(uw_bcFkuu%NG zj%_br@qaKj5c4{hgx`ro9H#kzOM?QTmDHoHn?fOt)X>;R2&Knf7Rq#p;N>jC4=|JEHRc<7E$W{^te!Zv)ilY~Sk* z&PQzVyIM7U-3|ZgeQU83Gv+L_RBs%(q`ssX_3$!?kNt;4F`3b+HWQhg z=6iHIJ=tG4Yv=N;Ou0Zl-YcEIWGDd&#`K{`^9ysj8zRo)= z^8gptSU?d)ulR{2B+9EB!olhP3zG8+4bLfe?|t#Z7|+Hib#u~0WaRR2Jd4Ivd%;%U z(fg3a&?!st!rnxzM3c^+SXx7CYHo_DxCCx220-v4TTxKEEtb|-pJ|HffnHwQaHe*@ zMfM`Aj!#&rOLm(Snmw5AmTF9X4isbo9$astIvKH2eMDB1Ud{X*YZ&X&GmMOmq&Xg9 zgKDg`|5VjjY5%0CvD9uzP+skGv?rBrh#u>}QbEGB51prD+JpAzaVWk+9poWm#|!46 z#{_EK{W`y-4R=zR-!Bf56~1r(9Xm=JWz%cIz4WKwt>U}StHyGBpLJ+ORWebm1xvDW z^@oX1^8HAizvV}*HA>s9HHtq}>d6-%CA}jsVrTjM%s)eu|T4<}Opv2%oT$J%QK`c{)9BaAp-UL(mAuC;Sw5NhN#C4?&rBFFpbI zDIyV>yG3Pc{Gj|XF1L3ETf{y!t(fK!xao!q7)mS z_y4C3g1^P+XnH8wUx7|%hZ@J(32b(ZDmyK`kY%nm zj%7Hb!y~O`aQdV4Y>?H%!~rC(A}ecYKKg!?jcoK?e8(}4Ts%4>P1%sBO6nJRg+AL_ ztnvddKFiBV40#gK8FjtQ%cSY=+)Q#9@YEQMj6{XWOZLebsz~%P{#_B@N&j)WR|_+X z?HMmDhfJKE^6XcFnE-*U;vL_NjiMlYtPPP2{ZT<@4pdk+nq{AF#u`w(1ekuam~I2s z72chOzB1v6WYLr-0Xz~x6x}t#;^9u4$;3`Q<96?Ro_+beM`D}e+Li2$5g-y12{x4E zawg&#y$u*iKM5+n`Ao!=n`OCK_VX!>Et`nC7S9LJAa%(yWX&6Nix>AD2$e&9ejZln z__Sss9B}R@XF~#cZ2*+tioACtHqtkyVQuWd4(g0~7qJB%;xcjg$oO~p!jEV|xYO$# zu8Zh1=Cpp;U&#|p2B_@qQ=@##PsuY(2B7xQsZq%Vhz8B#B*m9QtEAav`v@ZXpjE|A zJ!3vrOIq(T%JaL3J7|=6qm4Upl$Z~Lr*Jf9bU2eZpS*hnAPGCOGmQz{%ygW}3Q#!6 z7urdj3gx{UjaRDy|bNS0w8 zL~}lMP&jsH0W@mXd#I8UL#Otl*$EC|DNaH-WNKdQ$-9!Z&`g?UWP09-Oqyk+ps?y) z$rCs+2`&3<@Z6?h=AGaZ9*-m--y=`ol?)EMpvc~p^rsY);6-5IouHB&j|5NfFnb?- za#P4B`)qa40iKTkL195dhe}Lh!5^O-*h2#Of?zN*2)q3Fmrn{hz%!p_8Fc=o{lofa z)l8Zrk^h~T&gDOu|Ay{8f|*xt;{RKBGd!3NbisnG_9vT#6~{260eO@NcT1 zt-W$=+WtVRAP36mByS^1sh5htA2{;q7ahUlVaa3}Cs2$RTenb@7cZMTQ6ug|cMz$K zf>Gf0A0@s8&QQhzT`#$M(L`Gal;ykDv82t|Gdg~1-04LH#F~EdVjW-Z>cCho1ad4ZM##-Ma=8tT}rVs9?iuF!f(dHo}I`xz#Mw}I(+ZL;EEO?qi z<(x2Bfc|lz;Ia=TYmwm+itms&;d8o?@)4`>BqT#wO=K=neSG0=`1pwZWE z7+5LXoX@2A7FC8@gBKT#JD!Co)~ejlkRt!(PJmREhs~hLBT@?=QtyDGAF#CSRQ0gVFZ!xd^iMsLVbOk+RW<7e|=%hb`26&x7~1N=eCh(`P&%9Iqn z4A>jy-`EBiZj6QVR+3;-Y^{*GxJmzBS+?(^W7>;S_Vvpjl=J)15D$k1Eo7+RCTCGA zSbKdc*ZBFtMx#s0x`*MnVed61gDPGwl6l7zR4$&R7)9BKQ_rmYwJgSrUqSl<3#SGt zzJwEJItmkg*s+-qfTy8Iwmj|jS}7@=yP@b(7W%=)UVS5>&3k<}tcl$Rv3p!>$r<_e z`iQG1^)b`>h(&q;UvS;|Tg9%FzX1LE2=y`8zHCfzoWR4pt}1}<#$*jc;4#!7um z=8bQ&gPk3~$0dp51a`kAu>0A7-S1!269D0tpydw2mLUI71Pq1&9qRw`>%nYQSPbi6 z$QH4w;1i$^18TB^*o~8V<(&TQ{FDjuY64$iedOt-+EZbn7GcHq^j> zG@bYWzFH`_e23^#JqDf)c!ALcUSNPVwSx{PeVd(P(#ScumIx5_|5p`<}NN57^ag2)_t03tat1FZEv_-H8EAkSA4iXxs6YHfF>?ew7E z8iOA=`zoTd>}LbYytIx(p2L2SMUQzpkoDloyY5FY5Mi^w3b_vxBlE+#DfjElCdP3W zXLibkhQB0>rV2*{$liatV5&i6^WcxQQanRfv(hklP~ax88jHh*9w8asK==HNXeEo6 z(#c$ymdY7SS+U#`d}t1njh^V1lpKv^U6~fZHfw+J1tkVs=KXHt+j4!M%EOAkt(M$< zhnHbbB2$sfl{g^l4_TgX`nDv0?{wt_O*`t}E;|JC3Yg$w9KHC#5H@7DHy9c9!&c|u zBT;qO82c+6Ug=S(kGnTvQ|vh`yjr7DBby-=P@1ivsd$BqcV|kNPTo|Y9Xd~pgZ6$R zB;~0bn#FN?_)Nou+a2ww z4kZZ~fY(GYKMOYH^ZFVO+nBR#WIk1QlZ*s9uR>t>&hCdDVjEI&sa<{(3oWi3aqf&# zHv2AA<}VJr0jgRJsN<2ZPUdY?GikPo8l=Z@-h|jsXJ+}{D3|KnM`J^VRYQ+Gc?&-= zWMDP!kK+{8*}u%D+5XPUI5EU)FpLzX)9Z~91mIDD-NrZj8b(Y~%Qt&b80RMe)!vu% z7gE6y7nq8^*qwHV0y$=8;g?#eOCjDPDu#SI<0Y4M|C-J`M zyZ>bV8`}&4Gm}D;|68|{Cp9heNAQvW=jYXLQArmec@Wz8S7~Me^R$afF8m0LuqS=} zae_Jig%o(U(=K}l0ulBn6dxyc9=F`AZ_UqbE`QtdYGR5<>9^d~JXI2eQp~W8{pWvc zw>D~G%rm?bt5&>w(?av~Qa)-9kN!`oLWhJEVU7sJMKTK$WgZSrpNEhK_sFt~es_G( zhPo=vy>gED@Te%8TbtFdOggi;?)d(QB%(5$Cp!%}_$&`-Ud`J$6LiGHz}gAtte*es z>^#X+>1k76bhO`jv@61SKCXXZsm(RsNbW|o9QM?rWx55AkY*V)emPuO>im7iRfy!R zm6~)UgfZ@o$IQJ(lwj@P@jiGX1eA@TrzrSyjcsi2sFsZLpz~5)J?Ds_?1y8{M$(CEaCp?<;$C@u@wCJ3k!5u;AdoWk{26d!U3!~f zrgX7Fh;i()HZVOpV7%j0>(dW?I6c{-tYwy+iA}!~z|1AXd^p^wd(br6+MYbkTHd)em9DWo}?>&Ccq*_;nh9E@+y7UEqaZz(X!X1jE@+m7)+ zzkvcmpO9(fSSFBYHlT*MA+kP^nk;Ns;)P!^1d7~5!qgV;H(__*dhWr^y%k z{?3vW%Wn2re&;p+ZUplscpF9^K*B_*VB7};Va%8MKfF7ZDS*4myRlnLYpBWVyT8U& zVm{$LGf?@q|Ix2|3#zTnF`jUG;gU4}{&rs8`GZ|=qUBXmL`qqOviU^5%T9YmO3h~g zyU4zge~Ny2sPxz(M$lhEZvNPW`TL{}m0aB<{xK_Jqs($&=khDNT)s!n=bnWt71=x> zZ(=Xk{+3=xxIFxm!foL97w>XwtDGw|++Mypn-n+m4r8@tbDoQmGRgKM|FWrZW*Gh| zWjmKZ_-+cR*Z$kXQK2t$<^k-xqj2_9BytH;cisZQ`c8`$v*Bli@Xl#yMH7)iUMr?$ zQ2QT!{swa9;M*SqF+3Lx1&Md2%M%K6fQW)~(%okN&nU?BUOg9hp9B|#Zjh8m3@Mq~ zAvY6i@q*~WR^;cd1v#@g zUrQWPq5j351(|{KswMwGt`)VsxI2EK;DxQ1Sm)8q$W_6ENqY~LHk=f)rL~Pxz%Kia z#hS0enzFS)OB4F_`L3)3q~|9y?{wP5AN=U)JKCMRdy|GF*Kr$9Gt2gVEF~tXONZ2~ z)HZ^6*AV%ErR1sCzb3q9hXV(EfX|cJ_2T!Wy3Ai@OkP=jVi0w{mz8ZaCUaRbUEqXm z$%F8`^-zFTt&O_LFz<&%il+n%0-s{PK(eByR0`-%E-P*|?{h}1e>i^Dy(Fp9iQ1pe zXQK#`!KX>S1?%Tn_&Sg}s%5 z)TV*rv^AE?c8>4+QW~j1!5hk10^UVxT1uxx&!qzO;+ezS(f4m^k`FfTgn=`k+o9Aa ze`+DohVh9%7WryMCKjft+o|N_zXnvu=BLOO^AJjCp)h@;%!4Ge2per0UOWdq9=RFb z5`9%OaSb%mieL0laQTMV)>2%uCz|PYI9|X0#Pr?~E{~P7M;xcW zENJq^m!i6~%9&2RCt0jz?Xf4=t#tH49^rz@^6-xpVYk&*1@9;SmDRgAg$FXZLF6gp zfwH`f)5#ZZr?6H7(mI5#*E&PUXd~)8Vj1F>VqcqY%b z`f`otftO{D(^>-OosiU5QaXf12SxPK%W48sT0W5dH(zSXYRZ1Y z3V7;sGcvdRUKU-ktci+Octal6Z?DOO`R-uVF2_u>xiEM_JLP!;Xu0`)U%UFeb1U@p zXE3-Hcsw6mNn3e(P(A@hpP$|dJ>FzqA3C=_1H-`{&;GSS96-5=QtR{Cbk#~#(w6O& zTukb<@?9Rf4UW zY5v&OnD`{4(+rOM7&*p7|AN`)(u*9yu;3UHNyJ^Jkr1dth761G< zl2AZ4?At*bb@}y% zq{a58YKzgh$$5Zl{IIk3VDuz+@XXn!g@jODW+&Kr+4OPvd^L7-H8d}-RS+UKz+Cun zwW#Cp>ODk8(HVKroMm39J#F=3WeI<4^11V-Auq+*_{em@EHN(UHXb-{4a&bO`_`!4 zsCpoAmC?a_8?G#Onu6on3F6TjkK(^_)L!Ou>-HySi1*vX zv#XM2ROjI7h2?igp5~)COl6+Y?tA^32a`J7oyP$U)z~7o*yl^#={V?v`u&F-Jmpl8 zpq1~rX7xlVQ_@u%^ZJ^6#j2+hOj->6#ZHlf!=;O~q=S}uQ3q%1*S)p1!8=7BE%*M< Ku#W}DqyGoJ6ParO diff --git a/data/projects/demos/EsoXLB-CPU.mmpz b/data/projects/demos/EsoXLB-CPU.mmpz index 1c2549027e43a6b8323abaa43ef5fc23be978d68..bc2445e8761f703419afd9d899fd64bfbdff937d 100644 GIT binary patch delta 17243 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 delta 18444 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 diff --git a/data/projects/demos/Impulslogik-Zen.mmpz b/data/projects/demos/Impulslogik-Zen.mmpz index 05fa375c49f21628b86169c557b625083f1315d4..774ce89e3d5c0190db819712eddbcc75945e3349 100644 GIT binary patch delta 9767 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 J`+uM_4)h4qK2ZPw delta 640 zcmV-`0)PF4u>;Am0|WpN`m?bFS=N7hc8vxSkA6>Eo(op77};;=ch`>XqzCE%X8?CC zy8Lq4u~u5giUPNPvZH}o#nC`kJN?oRn0~Uy1hsvj)OqIxy9I5{x@E1-x`#gA+t$vW zb{{_<{M$_C5_GCRYI+Vji#)V!`2nVD}XOC)XCQI)9ioz@6TT@9xnd(?0hg2v!^dv-zxtoM-7gPck{<@2dfo2)=0oShDvCCL>2|+=|NiNF z|C1jqyAOBWyZPsjt7z>Gdfk683LGo?WJfl2+8O)ur`d{{+fTDKiOij6{6WjCBJv!4 z=rAiKUKFdL`_n9pUR<&>Nmih1g&}3M`Tshu)A|29-&amVK8739B7dQAkbL|en47sJ!krf2@Izb1cQhg4sG(X>sp z`}{pt?q4X@-xpv^{zA=ZZMuJDZQ308uFYWScpoEw^OxS{`LFxWkA6fAB=?m|7E$ht zAg(3;=HnmH$4BbpzkhT*o2ue3v}V@y!$(?(b{TE7SKXrP`_BD}P-Fk%E<1XzVUuFJ z2CQ8cjjO?5{+;yL|0rz2qltsHfJS#;!2_ aidOA=ORD^?yIzMMcXj>rZ~qV0SAjd2AZB0y diff --git a/data/projects/demos/Namitryus-K-Project.mmpz b/data/projects/demos/Namitryus-K-Project.mmpz index 6d463cbb95497e8233878585ed60e9f1deced5c1..4d62826c9b4d5c78b7e3e34e4d4e8e6d262c575e 100644 GIT binary patch delta 7393 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 CAW!lD diff --git a/data/projects/demos/Oglsdl-PpTrip.mmpz b/data/projects/demos/Oglsdl-PpTrip.mmpz index d1baceeba51d3dd468e5dc5f008a9ac7ad5f7b04..776aeea2bdd76055b17e10357e4fc5a47852a46e 100644 GIT binary patch delta 24682 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 delta 24756 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 T4ARK8Z>$>t{q``Saj@|}aA{W! diff --git a/data/projects/demos/Popsip-Electric Dancer.mmpz b/data/projects/demos/Popsip-Electric Dancer.mmpz index fc93dd64a23dc693793182e58b473cea3afdc069..1c935dbe1264073b6a6acf4ca61e7041ba64a9e8 100644 GIT binary patch delta 1397 zcmV-*1&aFn%mM7o0R#XAI<>I`4Pk#~VJp7XzwH`%+dtQl8%({yx#!M!=VVfF_O{kr zO|!30P3z4uLYsqKB8G_2e~MxoM*bW(Qw(O*r*+P%X;6V%4cHtAv^qvhsE6p`qG{*3lH3S)!erSp^WHnKSymt69TT7*g!)(f_ROsQT z)LY|GU9XN~FPIJ7MYswwy?_EA`)NV7RSQ~<)Ph-wU9_N~TDFaXui%q8G;5=TUP241 zs-`H8BPyO$gRfW(IxngQov(jV4QksPzAz_7SF0PW0hzD{RLUB#(7x9)Lv;3%Gel=! z~77oAY*S2>}K+Mt+R>lojf*3n*cl4xJ$Br%a) z@~4BJe11NS5Q;bDo3one^lnJ9UiYZi+Oyuqtq)b*v5ZEX3qrOznn} zSgPr0I>I6J1`K-CzrKr0ZM%=HnG)q<0T$`G9-MgL}!R^a#oj{TJVRY&u8h%Y1u|uGE~Pv-BL@;HGDNj;`lZYrOQ` zAmlYQ@Yn4&{yYYiSKw^<^XT#o|2)_LoX<1?Nqsf#&ERpSydHn0wjS_we}kdnj%wW0 zRl3s>a$xg|qEJWP6y4U2ei;9c|NZX$$@R(q9{-Q`m+!8B{d79`@%rQW;M324KR)`+UxA7<~`NMdWRdy53o(Abx ze*?cC>Nvi27ykU|`+xt%i)L=%{`+6EuVd)0?-^Sr>(76WY2SWtD$0g{Gx;8-)WV(r zmA7d*aOeIVSdxfS9&Kw`xDl+u<0M>uuPnd(b@TZqOklzkzM6ZtN#To>Q})gAAIb3z zY+8Ol_5(0&@ahz8`!Fm$APT zY9kkJ=|(Q>te5x4eDQtnEtbjCU!Sq@JG6Fu6LHn??G58Qo+8GZeLwgwH(0sR(?Hd} z8>p~h`gUjT2e4rAJ!-Mpp~YX>JZ{y--^|2rZE1fD&gE=64_C9{G+cmd&2`sE4*HvH z^H)8yQ`R$Y8m19^!S@50*j~hsWvb2ol)3nW53u7KoQKn_#AenXYOM`Q%j#?D?iznp z{eHmrBr$AC=8Hu<^uy6SUXK2!n*!{Ai|@n7|JPkC|C*+QGxUln`8t=>x3hxEEjfOU z|Gs6)C1BTe*X4Zn{kPK^SkJ7>de$A?`o`Duc*L;`4s38N<^TL2{w0Ej)@TvGqr{EO zV7_GOWfsTcw_oPVIN2cP^QDsA)pxdclE?WmXBLMIeHjLK(2r@~AFnI=;ots$tIOQq D8QB6Z delta 1412 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 diff --git a/data/projects/demos/Saber-FinalStep.mmpz b/data/projects/demos/Saber-FinalStep.mmpz index 5e3d1d1ffc6a26e339f864341fb0b0e2434d9b40..05a5022a7d47b5c546f0eb6aaefcb8596077081a 100644 GIT binary patch delta 5720 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 Y?>!R2_UyTvO>~k``too8A7bbrZp;IFp#T5? diff --git a/data/projects/demos/Settel-InnerRecreation.mmpz b/data/projects/demos/Settel-InnerRecreation.mmpz index aaa01e0bcfe9f6df594bd08144199a33a020ac2b..78e1d611de830cc14cb3e86ec455a61f09f00658 100644 GIT binary patch delta 30409 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 delta 30388 zcmagFbwHKPw?DdJ(<##3-KjKEQi^nU3xagB>5|@bcXx<%cY}h2Al)L;{d>Uod){-; zxxah=S+nuso`7)$SBe^!jVJfXj>Sn+4*TytKh$;hlF4Lv~Bw zLR8Nn%QE4DRv30?M$x4rWHR=1PBJS~k#im~<0ik!K^}JBi}s^oehd(KqEADdZq73E z570q(0|Y+aH1ytjPgsi{{}na+=iiN4nO8qz({IlNV(v{8?kfTA+V|ch0%Au)54np< z|FggE@MrEw;w!oE!;J+06|vLC=?Vy9DnxKgIU6u_57X;aeJOE(C~+T5ann`p^X#T8 z`9UJ|ZYO%@n&Rfw#RHPDD8cP(0N#1P>h-C<3^+jianIT7!*Ll+c^*LdU=n&~c#JrY z8T>HiNAL^*Q~|D`KtrAsc!u3A396-x5SgTq4h#|t(8LPHo8$>4G@=5{V?m_Jcb-Xf zi)Tx)Aj@Mog)%;(&(+DrB9KvE;TylvEc0XQP3OS!oux*TJrGAjL4Ad3tfc8M8IX)a z2RoS>$cZ8xs$@jDBT8j1vY#FH+x zaL1Z8)$AY?)JI)ZQlyj0LDJc-Vl`~dn5P()HQnMsZfN|Iyps+=eq!Lh76R{VKRgx| zI6&oOSTlxp4ac*c>|}gY7|XsVSr+~sh`%}u7y;(p(kB=DQ?~!$-jm=8O#&p3?C$`r)doCeK%9?7rKn!}{;$QJ(@xN6P^$75{`Ow|$Ba;1k-i zYw=Z~n9uPcKsJwZt98TrGHa0zamBUxB4r0b$-YksveeGS6~xTgk<8g6fxj9q_N$CA@RK2L0N3XTae2>WF;r6D=FbZ`3VTl4}Ew50n+`pP_NH`10D{=kUk0 zc1ZUE5*ZQiuXB9z@Y>VhZH6-Z7%KV!z=jV98Ha5AS#iGnu_AUOz!6{>csO?GGzg z({;O&6EV!VF%1sg;o{2FsQ3^%YaUv2Aosk4G7EObGfMD%(a+`*^$|l}ezPy&tMxJN z4}wb~tOky>_Vc5P6`&xz%0PcJ-+M~WDS{kwuNPp?!|zdMedYE!^fPrGf-dz730k6Q zQTTQQKSfDiyf$1%jFru%`QfPQe7HD1{pzz+ecn+sLuXGLltP7&9FMGB(fWj4v@`K1 z(_R1Z;ET4?G*H{i4T+_A7FrerC_F3`Pzb6+EwR|Lu z^ffR1HRQbiRPFbDy>z+z=q>7qkYa+;@l|QF;2sXgdT#AS zTG~zSB2a%~xVCOXMO0NFAAh4$jArRQ3^_#>tW)+#Pt8gsm}HdM5#_H>3#=>G!*KnO zkjni!ld{PCe88pYqr&fAw}>(OkQ`0->ymdYBjyud#1uF83{Ccou>8*$__z=<-K5A+ zS}>FC$s3K4ed#gscUn&Air>L0?%X zJ+b)~dDKq$z2@hn3I8OU2OqVl0ko)Wu=vaP!qE3#AESoF`L*NKi<{kpSUtmSZJfKo z*>YErd*d2TRvgbf?Ix!D5}I~JEc52ux19JcdrF8{Nne^@U-&4>b{w>fUtWALy4Vas z@MQN|Z>mbhr6ImSyMpZX5vBS~e(_FUPGS<^)A4Oy#LAY+ZN0_nag*(tm*yOMJ-0Cj zQPnGtwE-)t4wnV|9Q;h~>59<7YChA6%3wuA4DDAEzI3xPV!2NjzE`iIVd#qbfxmH5 zHyTZIaVk*iriolQn^X4b>xOCU7rW*s)H7rW9#fQBKDD~gI?S28-K#zfC+ofPa!|2&Y|pXRQwg`b;B6% zuTPfNc?tuA5japXh3{p%Lo(u6uQGZThp|U@yFYAfZ)1lD46gn;?lv`RmhTL-=`r6h zZU555s_Di>Sutt|IrNM&D<8Aioo`w4zzdTivFzO7c^wd;A)tq%!9Wt|a>DURKKBEm zgFE3Np2ugyTta?f(ka{KWo9IF+-C{DI&#U@GXfR3em9NMK+okGg2u{BPvBQ^i<(w- zVAQ9x=`km-`|MY5ab{7(-8N|)O!7a)$qW=B?tdo@qpv>&LrghZ2xqxh5d=F;+l&_= zA9`e@M@XT=d&QIr^YGtaVfLyAKL#xA4Hzr@M|ynlGV} zt^F4GyV@shWqcTX0AJ3TmpkTWK6ai-h=x1S$|BZhVhVv*+O-HP^-L_@d2{6`_Dxh? zHK0zCS4dtp5BP}4tEL7zRAJA$zjr+p`qtu-d95d?2w#;^6g)?xDx~=H6;5JcR26n& zVB8}~tinoU%h_~S=gF<6srSnG4-uN!(*y()|H?cHZfkw{)EzhZ#~JcOABj+`-IQAU zKSJAK2jTw}KlQ{FFA&50sAvk@juRM zaqrHwGh)q=^&Vr*CK9SC!sW#m=K%778%6-?Q z^Is{M!ih8!zsw+V27DM|?{*OA`T#Ur;nE#8cH_Jl#z5b%~Tq)FF zc&VYaFb!0HNezs%xwsYAfPI62V-8OWb`uZ_U|UvJT-y%T(sU+Z$et8Hfs#6kH3Hcn zHUg}(Q`y@JN=M~JePRkn%|`t!^{rOhHfEy|>Xrs+%zTW)St3!W;AfrvrFcNuFMccK z*RK0Zg){jWN3%_JC9KEr&}Xp4!amn_)!k_tC%W%sVfOX}<9(Zq@|N^x0aEUilh!r?-ttku zW!s8wcE=m@M>^n8!9}-zJGVO^N4i&`aw4CxS8=wb#W>ON)=)VLlF^xedoSQ8+jQp) z3;lDw59dM;<*n`mv?0iPltO}f|Wda1zGm+%P8AQ;$PKauXg-)%VptZ9oaWb z@~46~L1`=Au7a$5l+&Q{!ZyfnXlehQg{t0Gwp|9|5N`^!JwU)yVXN3Ktln0-T?W4FF4ut9eyh8D691;owwhVmbT#}zQ8$X|QcW+{ItZy9G z*>O&RwmFN?XOEB^RGb86vN=~asteOW7ghG($pJlsmHahlS%A0WYs#`fkinkJV{7n0 zfQ1G!eYM|9n{%5?SIANqIcVGy%bO4@6_3jrP15EwXN8Hma^XB+-_YsLb6i9J)@e$->$>V0bmVm z-DXiod(IyCTm!EALfR#d0{F>+TSt)DlB2%!u>n+M3*Kk8ejA` zUag%UyNHwp#^gpX^X-7LELvwuFR|}M#r+c5+}zO60{q$DCzW4R{L+cN@)v)#C3xD8051&@XH+Zv zmVvfgkId+Kb9s|gatv%xu6?dwdTWAW+An{(WaO?dz>cECZu2kK6{EFN%r&O(jCD%j zn(uzxL^L(D5wzXl%w`>{yr8lb8|At12p`O9qcW% zrFFlp9bUwtBr!$ob$@_vY>E(Dqh+>@?$)_fU?#z( zec{RqR6EEB1D5jVvB80SXp2abdRr&9r_)XtIQWu^+MiN1z%4Pr>LDxbMb~P%x(D_< zJSj zd54j`zC0_krvp7tWgR_ISXy3H_OFS{lj1k|*<}0aCz3B(6Pn`^1aI=Ews~OYotUnG zgCj!o?C36L=IyQSVLg+g+nuJFkcGedyA0eLA0Tj?e5 z6vvhcUur^6#@&8xs4b@ix+0_{+-Q{>3*oOPdFK;gRymQ${o&Vyo;U8Z_peRNuiNSJ z(jETSK7Pvd^5QVh{^n&HJL5P*#uCQ6W+m?>t3mE8T~kMw`4W!AZK-s`{y#WjC!Ly^ ztoCFCBiQugU=#QAC3iy>#e6}`h)sUyZND0!wqHUV>gk1|*fB|lR!nc_vycbnt9fyY zjwawXps#eWAs?6aP(H-Qmw&WH?KVuvbmMEI7o#-Aw?{-HsOAyM%A4YO$qlM>z}9~z z(hdl z=}?83tRrIG|CDO~Vp>S^CuHohpHD?N^WzkXA|$~nR36Qh7Hc^{5+4 z_pZ@SsHQC~AjO~1j_T(_gRBHtInR>`c@20&zSI0Usb)E2wKjMc+U1GI#iD>@jZJA5 zqwHs$AltG88*_JqSa_TqLoTPGm1}QKmMO(1nIZIPR@V6s%Ytn&)I!O!_HCwA&47SA z9xH@ve?zN2yc}vV#Z~h*Gibk4JEc8@j%i7!B4O8aC%3z8LOX@8I1&%SMpkrzYh9|F z6W(dDsjO~DsM8Rbam(4!!`wa`V{;zkKd~*^fITggK4Q#v=D>!^_I0F*B}$upyEZ@2 zgFoqm$?QmzO=GS8xLMaO5bn#~-_*r>52@6Gw&p$e6lGOUtx@CNznC#8m{;Siv(<#M z7S^#xJBC)E#aa+A9bjJz9q`juu$`w*y9k_L&XuDM9B$!aLLE+0x67AW>G+vnRLPDH zk69-+IGhlf-%0@6(I zx`?3I!3oepk^yLWT?A;EvI4X?0a{*>kYXsV7b9_h3L_aw5s4Y_W^%}g8c{0{+{92S zKvWb>C`f(rYp=J+*kR1SzTFi6H@Lo?hVKGK+hDC4;ya7K|2=y0+L-qNOWWXp2NF1o zFZfGTWq(&0t3jJWk>_%hpm`io(;vcJ8XPqNGP1fG=?A0pBGUMu!fYf}8u zd+2mS>~&q>zjqzWXHx&1G_;TeRx$Ojurbf=b{c{>JnHX z#2-G#HgE|?JK=A&-1J}McDm}t|E8Sq{bisfL*~Aiun2eWXjr+PdW@;dTI=bRbOeK)&Q^zD}yWb<8_^a{RYA zHa>dXl#%1lZi!cYcB88q|L7^(y#{fAPbPzRMl41$Zsgt=csc3OCKusRRoC-!=cCc+ zH?m*EFA2yrqL3jPs){L?o>XTl=XdLSdT*-Amk*s#R$X7W4PUQ!kqP&;zgV-pv#hVG zBA+|LM7%xNjU`4a)5#*d`elE&YN)Cunpo-IMT}nRStaRGyV@A^y`X5os>j(U3VAM%JZVzAPclOh;7d1osH(W38nOGT^EtwFJDaGjkNolnt_P#_Ytzkr0s0mU28KYWx^!&`v`u1*3dh&#-Y_Fj3@gtSre(kVo zXAs4Q7r5-I;dSAMofmDDhGL*C_RMFekXh-*6^1vO_>S%#*^P6I@I5 zLNEAD=GLq#5VE)Bx~5U4>p{TiK$L@JyhNTqIn!m%6Cp{(+?@1Hhu516`PRZeto3f( zKisFar7k;{oas6z9e$IgHLZ?g&)z1XSDkeiQgn=Akv`h9%bJg8lCSd3oy9y@ESidA zvTT5nbZ5$!s?+2Y1I$aLeAe(bOTr{d?%H?ceSQE(E~1~jwS|XYe`i4hS4B3Wzr0nx zcE}VIIJ%kAVL^khtMr(CW}FT!EIX6_#@Q2*P~@40xsjhCf1KJ2QDS&#xH|?1oa%`} z?j5q|({eoHxn{!+{6kTp2iy*+)Z>}d-@{OeiXX%NG)pZ`3*DXHtzDI)*Zkvq5svq9 z+nUO-yC-P&0nw$E-iulSgKr%##N%L7An9JJCOx`zPpe-!%*`Z)S9fw-s_;IzQ1ygO3h?kTa7@>POe3#U_f{B1>MgJ5 zxO72rUng+t;E2MAekn}}5PQ$N=z+b6(2Y(~m;^0enaC=QX&VFpo z&sg`CR=qqn;^QXE%qpV?&c>y&Gy8YY^4FB5m1Ut(^6k2P!P$u~ASkoYOGwrFsw^?# zV&tpLQvUicm$bPG?A!al^qplrTMd&f(QXwTERscA?xDLx@&nXYi&L}f?j8&(D?Bm- z1hPA_h?3VU z+I93K+Ox?Hfj=08Lx3-w7MoQyG^1v!s%vp*YGb_WxCSk4ymp!G*m?cgT+gP4NH=*! zr_F&@W=@d=N>%T4l_AIGPQ^OMdrQAKOqAhm_-Ccj%VIBdrTazPO*ljgtG1>wrb_>~ z+Jr3UabLOZ#-=4cb%-?C{Z9Wr)Tnjgr%hh+c%JniYmri0uQcq;+;~yMuGkNv=lf`G zMFx;7<0n6E|6TAor$OztxQM8H_v!uOkHhsNgHoXf|H}1KTGaO^i&A_iR3==(Q}d4o zP|OSXw(Zd#S6#@F3c1RV@ItXO3f}VsvD#>2*c+ZgrSH6MSLivPxdIxF_!Ip!jz4#t zzat=;@aytE zOi!Uc|7VOMe~rgf6mg501`cgGDT5FPBgZ~@TK48>snstIzZO-N#1l-Sr@4!MiZXXy z;N9(lcqte>Kn!wq94DO2!Qk87ERS=r{qEo!!W}t* zA`xkl)kMGydXKM-YaOvYn#fu|1=omWq3)ZjekI)UXa=qPYX-d;8=sF^+&6{rTL?|9 zJl{qW;Bwzq0Jj9YAKAd2-74;7obi7-vS9Dzl^@RPW}mt4Aybu_woPHnHcK#27e5fX z<6_Hjd1gUYg|=nz4i$-I&Vgrb7*;)u%Fi!U zX^213evLEXV`sxlbEt>MVlw5&lnkwfaz+-RTrPv9CA@rZJPrYyw^d^n5Pq;C*L>vW zY@G~W^=}92*FhUnMe*6=W|=tpG9UD~L*A4I5&FXw(*4p-i2b%tx%g)8U=p_n`TE#Y z*tND@KY z`vkDW)te`u8!U3f?U$GsYe8^lLl8E@Iw&LH*z1f#q$-6GnTQ`e`4Y$kY!M}(6LEMb z;7uz+d3q%3n1Zp!Nxm1c0h^YJ>OxeqP_E~^3arY!zqvAB35wEe#1mrJHhz(=6=e-W~m)Yj z3CZS+&UuwZ*J|Wo|6*`WbVVWAg$9P#xCs61Cs?V(qCjL#f{Elk65(U5=Q4uQ#0up& zM~THL%Cn4xG!%PCx!lKNyLl-SAv{+s7kW!ToPr43AFjO_RK}C92x`#3z$V=^+HAVHTnjbH& zW*Jo>tThV~Q#J7UmrxKfRU^>-KOm-R7u|h&%*2-uJJx?;YRuB0;+ zrTmFBs2aY3pZ$lR%Sgb_cJ}@YeWkT#s&rA^r;jd+%)#F&E!KvwLCAgYy<1E)(SyaI z5WwBbBZR4-dE)h-9|Pm_f$Hu zEn=GFK6L3>I*Q5F)ZU}>qQC=iUV!fbUxluBCSt#X^JDnizPllb9;p8q-tg-%d62-9 z_o7~&gLi@UJJI3uh)5T{*{v@hjhYl{cIT>Q(gvOzB(RMh2QJYtYOQMGAM9%ABWI#d zz%c}tC%AU{MnhVN*6nS zZ_|k~U;j-^sm4rDjI>a6AgUPC#VfrJ65n^MZ`x7+ z`tqYD2)wDgVWW=Q538fPiZlE@x3utK^oRCpf2l2NA7qe0n?s_G7FBL()FK-5q@`t7 zg0dx|-=50)%sVK?T8MH2L*a=3khIMP9R5emAPj;V7Z?H38gyS(aLK!vKqLM@)gF?$ z%L4xYa782ut3rej7}14@+Cy3ghgui)=_ZCTa)ru_1!bOTNR~4+|LXOP#27j_(ZjVOVr_6<(jFXyZ1jODA5EF*V+EI0 zl8&z|aSOyxVV#pwG~Pot7Y5}&4hdKtz#$Q?@@=Tj@{JDtM6Q%I;H6M606=Y*Spd}2 zqMzu_hEyo5NMPe4Y+9RLlQkD}Sn4y+AT&&^P4umwwi~}mU{=LytR_5d*+oyEE4$Y}a|eph&+9=O;$|CCO-Hfv z#r28#s4|N>BcPzm9(Hf&9lZb&tONDgv^{4&loOp4C+g#5rFO`Xdb{<}mtechhV#Sx zW2ilYI$Vsdm;#j1fQ`rD;r#x7b)$P#uj$QCV5cBZNoe4^?{>LZzf*K~A$#0SE+i_) zo77O_Rx$QK0 zmV;hchF%?beHkD^wE8^EXN=vNE`JQUZF#5k>_vCmbdRzx@1CuY39O0u(CJQpO(|ya z9ucMN9Q|B;FFMovN0ZmqMEP@WBv_g56@TtK7p6s-=A2>|h2~tJV2JP!*`6+>$)Qt% z)wh+ludWy(OR-E-v!`&b_4r>+onho-Tf#LjS4qcMfqz7LG*Z)*XI~ZXw`F;Y@8ywQ zm7C|M#vbudL&MXzsCTVtE4CRbzRD;r@XuL3e~^lH@?uumY4N$;^zlx~@!WXdutuyJ z$GgLPHTkA>yqA+CVjWV@yFg>d`b#d37jzZhJZcZUF6rF5rrc}{NY-K|XSe1SHPYZ# z_=OHk%HBq=`a}`^88|-sTvq0-2vpKa_<7*Q%s^Srca67|oN~zdbEyZd`?_ie-GcIn z^Cc6+aRn;kG&y2Y2vK10za~{}Gexx2VTXO|4-Yw$hc~|ZB!4Jv@KM-0 zq{`>pspa)cEBcP#s&%){EblwsKFp`u?qgLzYS8*;+6s1Ab0@p;?h7}eSAk3n69UG0d45tZeOF%rhfb%`J;D(`4)sUg7$%u_pHi*NTPKETqvM>4h6>`StBqF;VjS zIQo5rdFV0jZcv7Ya>c5h>u<6xx-X{}xg_oM7@HQ#-Oh1DLGh@cwzHbn_LOW8(S(j6 zrPM0}rMPC~hRj|ba+ZL#^<-?lT(%iK*Po)+(j~!cxZC9Nt=(AN%jS>1d8J36S+UfMwUIU&rK<>+9EzQ9{$h2}bEN64 zcr!juZ+u8)zD1to9Geyh2_i);ee&eHd#`%-Ol+kk_lnML`J~P!On6Jv7@uGN9;Y_O zW-G{!{XK_xT7^XgngeUmMS7E9t?}0s$v<?+a==;yThXumD+z7c#w1W?tC6m-`&F8oNFb)JxR-VzR$pRckaq8J9@xF zcJ^6afg1|;7@qwN3J$zbz;UzA2K-ieTF2?;GR4G>nq!-NhULiq`$X)#tj*x(bx&5* zQux$$D4Y)I1fs}fdcv+846ggC<_^SrU3YFvoRzv(1*K;AU^{Tg9A_{O}l1 z8Y0>EE=QJw=o%0?N#o-4Yh2bl5aH-OLd$Pr)7W(0p8AJ{;8NdPUb;W6jQ^si=?PxnO_pTh|jCl z3(d-2j4bFfgL8zo01L?>_Vv3@&haSdNHP``65@TDf@B=o{f($d9KB6}E;g?(JkiDF z-|#_XpQqqze?i%>Y3Qx}tXa09VY(e%YpLaN9K|YhmBZUG`U@C9f2#~ZlJ`T-t3I&WZ)m~s4}zu=g* z?^9(myX%jQ;Ge1lBPQ36R*3ME72^JAg=_g8V!5fkofTZ92%7_UT)Aui! zV(a>9nPm9V8Zb=w7Unh6*1Ll?x%vtXI^Nom$$P0ab4-+p%MPIoXtUfIO;^%oMmpXs zhGv~l8Tz?sJN__$y68|tF1hAyvQveSZvQa@qOuS~>J`~P38=ikaK_G#X$>EFXx-sV zrg?As-LmKEJxp68aO4ANil;h`);#R-L^b|4*ZzS999yM-O2lG~rcC6<*~>PHv9YptVqb2smrE*C-hMV_@=H-VQF9D^LnVqi;KhT1?9;OC-xvQ% z4!%;2?$801!wMSWp3*_0f57@DPSX3se>VKHmXCXThsO;+yc)3KztqWq2z^?!dNc!~ z0hD1GK)Wy1{_gnulivT`@!zZbuN}Wv$^YE(;|*_P9{;x;|KANifi1AXhphuP_@6#M z9zPCL0>_UxAA#_qURjdkd?rL|EOmo4;roqM&9q)ws#Zr98S@XL(iG>OR2$9=Z})Tw z8?#WM#h>O`liNlUj8@Jy+wq@gY6d#Y^heG(92f8;!-L1@DOVl@@y4eTVp&yW_s0H7u6EubZD2GFv$^U;mywN$c}!iMJf>FVRHmqBL%HjRW|@xmEc`Hds- zdISql>X&A)yrt0amrAf?3(y}gBVnE6p*H;NxU)a*3i5_n^I9B$i|iPq&br*~XVcJX zeiGQKSI}{OPH3|MI^>qQJ&Yn^5&?S_K~vKE)+qbz_aq$(Uq@w1j5Ix*v+jmnU`xS^ z?!-Y?S1=Ja#X}m|k1w?g9-(crKc` z?;9eOUXqb0-fpYY5^wCd{QSN!WzC{%yGRUF(3^(VP4CUyKagg<*k!>8VRsn$@H?6O z3k;K${lPH(DrOpwoAINwP06YkanIX)UcWuPZk9PB?QdU6!fv~NC$oPz;4>ME-R2k5 z_0s8HY|zm3J8DWqd|S+r%sgh0O~27W$TR5FoaOnmH2Y!*!3|}vDaZF{3O;JHj-y+w zUeoID5;h0{!o9#%+wakoeCzKXIL=K%hYV{%zN2{@3_OE&8AgjD4=r~s?ukVpV1s&X zszG9-2&ldYoFw%iOQPP7957-Eh^(-w2%MxWAc0;tj$pA60!%tk=#?RiZ}KApV>Bp+ zZ!D$>Y8I!XN${(TK^}sA#znRJ>@+Y!#&({TK2Vqv!W{=sVJf3cxD$XTn}slmm=Y&K z3-*p-G=c#ULPdDtz%i^wAOhbAWH4wju^QwXA)6KFM>&|t0YZD#ADH;aKBCCNaMVwd ze*a1$vx5I(0TBRe0z?Bku|1IbDRjialY$f`;xLmCK?egggE=$fzKIEunm5 z!D5)E3YH+@zqvu#Xu^2lmF7LW;SLa7r6!-2;|xBDz2$VL{=H-=NT5kXM=Gff@; z92Nj?8HRk2r#sXOf3?NDnh&lZ4pC8?g-LH37I>$H2n~Dt9P&yFvCU6+wkxMya~38* zm|>s7j6L4D(-^askjFD-D0@Dj76ap~uNFh|;1yp0k>|TdDVBZTU*3Q`HfYd>1LQl3 z00uGa`{IHALQe0fKqCT%Fd#Ehj$ja=3=YIajs~JQ=>lp^QIF;eCH-->vOu%pu1Z06>4XVQ^9(>NR?+Y)+_62cNz!2mM=mg0iT=;4s zs+uAvJ9mPBtg_8OiO!v{6!=SEb0E627J~p3$QK@1hha(hlmI}UxM~p6Ax;<|Lp54m z4i@M|AAtbne73;&9LV!g_hbti5P=6=MWagnM>h*Cd1yFX7Y;+t9P!DX7rIGl^W23-7HUI(ae=zWWrQiY$3mC#eK&%Ru zKs)@SM&bzsNi|u5vj1rk34|xr;{B43?eMQQps%t1X^}~;NtxNMm&*@ovWOqIn0Ccz zNkeNiWDx<*ZO(v}v^XDJQxl@+ES6R33(yQ}KY-Rf0;CWofbTS9cPf|pT?$SWJ}3q6 zNumN2!Lx>1%22i7?;Q5LrOt(vqiub`TIi1BshMBzbmyDZ$nGVCh*f z%dYQRAwSy3wunH^xPXy=>=ar+weR0)HW@|_2qJ(qr(swhli-13ICDZkiB3QckFvlc z#wQ3E4u7G?f#KBoIM+^}b;e;>f;#iTC?JkqpdC#W7zjahq!6IoaTrf5FgOUYr~c88 z{*;iyR6!C7bgrQ+Vm%rlrwQt<&4K?1;dv|vs_#3#ddq*mU=UCVGT5gWT|OQlD;PkN z*vKOcFUCNu4OI6D!Gw82^mi;Hf#grg5@DW_0sZ>sZ^b7i9;*fOjEgQ;7Lf;JI1NJ! z9@BN^2+fOS+6Rs6nvoWlgE`Nc_QlLdk?d~D%E1ZF6ny7s zN>0fdf9fIfcz)MI{A#^i-GV`I@M=o<{Q)4(LB<{O!&$7O5ToUBnBpv%fIuH`I6<92 z@+?OP5C`JRSev7KqRvZFI@bVqlOt={pdx$^au4e>?P_Wd#@~=0K4{e{=yd zf0v&BzC17=!T^(fPzVNCq+pN=s*xXspH>IR-#N@^%`y10~i>9zW=UgV>-v^pBic-5Df`Tp1s5=ti|{Vl~OW= z^C6K@hE^z%ps=&Z)M&7?ghsbPt(EwNit+J8dQnlY8KQcC@$}L$!8yAYqxbvY0n&O{ zRg0lI>-YVi@TmUNsC$wLjL(K{D$z&-;()}kz?a+dfL?^(W~5F~hTvfVUv3R8L|}MD zv_1W9x)<-C##(6PKj8zl$3(!72!LgfOQFA&@E`%0S2L%%L2>(MOcO`Mtb;(&KwpK4%a*ofyy=FMkum#{ZkM9Lvyme`tR=nYw!)ELu9sT!~8FSc(xzBrehWd}RI4ltGDQ1{~ zQQ+fsl7j{l!9?7;{-8{SiThvQr`~Ir-`NQ0x2|hK1h5(Z!7{{KBC1l!pt5d7cX5(2O66JAZN zmqyIzQgr7@|L4|;Qxj4Q;d9KDPmm+cV*k5*J$^Ch%|85nfj@WV27%LXxk?x=voN(T z|A>@C_TV>|lTkHaScmVCG!X+HshWRgK+7Y?79tBE7hO9+tl3NOGDWGQa}C$ z=Yy}p#k*LBGpDWd@ZK6dHWF+hPBNV+Z<~h8oB!ME#1OfH^(?jjdYvfwzn>@m5&xJ( z^8RMTEYxjv>l6!5x#z-dKuE`Vy~Pf}h2`a`CPw|I%(20Vxs6>WE~d&l7cS^Nm>kP> zuzm!W@(uN|SEY|0#Q~@VN(3hZg90^ygF^6$J1Hgr0hpfBp(m0N5r*AH4l zkgLtw!UJ5hTXhkVy-?StGnVH`zAjv!5C|)rDloB&gmQk+Kt|W% zEOmmHVgrYH_!L#E0xVyk|LOElX?_UzC`Yu`RU$u=N`oHZW(Qx{wo|lT^StmX>yjfn z-SBgEcut*|(k+P6L`j4T2gfX%-;z!X`kM z@J*?+2DADToi@JCi-505Jgdl%NWcw++_(lj-LoeEp6;#xeYzJRd01}szu)bR#lnfo z4qy3EczS(%O$^59;OSN`?JW{5af-btNpWikV>vaa_n4bJWi)`ICIpliSydaxW)*PMaMZqkA%# z?8rjcY3b7)dgy<&V`Ca<*E0Q@+tTD${O1lv4=x_|;-UhKJ=aL!!Pck6T(k(2kL7oW z$##LFs}D70nU#2_KC5pP`H@%QkNm`wI&kNcQ8c38;LTmE{3`5+_;j?lc;8|}YV|4X z8E^zdr{4y%7N3W`^T$e{!KFC!F=DPEy?*(PHm6t7ayr;)Auztp`}R&=jY<(_dj0FO zWcKlnu`zS~`WHf59OhaCIuqK2MmQ8l{Mh^OSw4FTr`R(xw%G+hz*+)fT}* z{>j6=PUi!sw)Yjv`_mry>|dXmLek=n&4NOW{q-dC}a9RW?Y3p2O8w`SabWk{%8Zv zgi&q?)g+njGL^LXGeU7TYq}cq-2kww>dvHrCj(k!kH{QjDDt7wR_Od7ubBtFt)pd- zq(c$u#7Z!QTKuCkd<<{vEz9M0Gh~Kno9`LhT zaOPf2XcYyhbU8*I>E|o%ro(g-ZIl1zFK~5HKPJlz{ZQlC-^i%Fk?Ch)w=BH>=finc zk!Sxd9^~;oDP{@opAlzV1Jer9I&c?kQJraj7CU}HwUV$%mSVQjPf5Rn_@7*8L6K`i zB{~7XFh<>u;I+zF#kxBUo_$lwe#f{P(%;# zX$D2CqjqY>B6`tLuy;+X=9Bz=hOq#lB_KYuDIc?6?RH2po~be@dJ%0VLZz0xO%;}J z8sx~FNFZpXfjv>lfBT_V@y4-;#(nq$J)I8?{Ih1ob6H##j%OKLMP3t%FB)Ld{gvD@e$6tvfysBi z>WnkDlj1=ag&+XzbzotL{4+b;AY$8a=X}B2S*@kIi>MB5z>rc0IkHejeXlx_aE+t_z4C$TWW#}3GL^0r0gtl|`CtSC9+e!UUVQ~gu z#M5=CxK8b=UoY!UO|D8ib}r=v()Y_;%8xxk;bU2%-(Vm6C*nu2yP;xFNc1=&Ywy+W zFz{?{C7>6+i6ggkJCD?Fo18!(L5*YnF%EaPOOhpb8Whh$W^2z3g%$tUo$!^H0sm6w zy|P24&*7?ak6x5dkZmaBCC%~Qr4XdRk~qp6?i1uBA@H{EY;C_3&JK{mg3w~@@{F%!GY~A@M4fr@^cr6z>@RFz zm@72g0ti(9m6H|LxapEmj{$aQCyU`@;W){#+OS|cmk(>{l0UlZ^Nbl{{tO zS`0{m+Lj-M$o^GsWLe)*mpr=(M2b*cc(`e5Ru#HI{B(Zmkc@OSE896SAx>G7rw3zl zX>6^|Qtw%#T$-wm3py_K2@X$uQ+k;-`-SlVC{yI$-tiFCsq8}g4k&G(@*AtGZ*v2< zEcgA<6Yf~8YF=&%J5w8L7Lk4CW4en&%rCE9uqGA~C>^n9E|exg8P(%U_qF+*qT^Q# z6pAV6ox6eKf(vz@JLGCLF;-fvI{WNbPVmm%iRla)x0dS$VYJnrQdbKA{<-z;1@fN& zm8Yt=6IP97-)&8wy3|R?Nom7x)|KsAyncwG#;{$!g(Rvt@k@G?4(hGE!nU-xIf{#C zWEnck7t*oLn0GjcVnT*?=5hy4?(w!mHRqr7ptX@Hg<0v~-JZ7|Ud(RUbYa;fFKr*# zkSiuMxr4E~Jf_NQK`-2qMCCpQG7XG?EJcKMkBIr13)U&tiEq*hE3cB#3BfP%G$1U+ zK27S%y#tBM8YM6tI6Mg8T=_7&aIvS*z40~`tuDgB;$)&br6!yGI=bg9MfHU71bblj zgyjSsh!hCcGxp<0@fxCEv0uO*AFPTy5l5ziqSd-;ZC(ry!ohM!%vLaj?{rOI;n)T6 zr=+)gAiEe-_$NpfXP9vr4rEyg7OoW=Tn0y1@;aHwvRL>#(27;BK>as>5Hm3)`@AA8 zXe6@UIt}6vNP_=l09i|tY}}Wt{N*YHWD@~)vcIoHYp92`3)48P5XesMqOAnw9xujrx z4rAYEyc~YmM0`M3)C%+k#xVs2S6mmrZqn`&Fw85p1`l(oRpmON2*q2wI~?tJ_jWm< zBw4#d&Z9Gi#y3*-V;h}ouj$Hu9Yo6KEc_p6%QX1SX|Cuj zGaO5y!~OHWdtF-43i(S84C;vZhVz7U%h{LQ&WcGgBSR+>m8BC}*o5iQ){N>%6kxr3 zC@KB+YM7=NOI+Xv)cVDKsbtYO@v=`b>WFBdPyMz6iZoq<(3oBI9v1q(4z{du&EYn1 zHrvfE85*E`q%|;y7=MU1GWX$d`&N&OlLomE8-hc@$j~8vPg@HuOX?NxC$Eb&vQ$~$ z1MZ@PHh;Ile!RZ`7bWoa#CZ=MeW0J}%Tv~Qe0lgPmH8nV{|%k!Rt=3f1|rie-tEQi zEpy!ip|kh-%+gcDonwn6+B)yrc>OXEFdvS3kIqAv00D^!5RyD?;Ud_X8|*W!?I`uT|CkLsk(grrpQgVFM-T#8gx+Z|u9}e{HLT)xpsq*#K3~ZGgi5 z1J*-@{6o%EYFTs6%esOI?^{p^Ro|EtjB+ICF1Wa7Y2kek9D%?a1Y`)9w+n(}1^ z4A%~Zx8vG;pcKY&(nrs3Ncg<^w-cv*OSDA`Z(XU`Jn&EFgZfPV;dVjRQ;)&o<$Uen z3*WQ3bz7xmLw_BSb#-!4b7&QSs&ki-tcV4*l?TkCMTfX5nb`0Ip8~h20-N`y#BqdS zA7Chz7Y<7jQR$-0n~^agF8`?~W6I614B<7Ul#X zJKV2CQm1Ym{#U;y#W$CNOGbvpj94c%P$)oaJu++B}mv3Low zHLVAWkx$+}FVR%n`+U~4#*0X2Z{Mr^M_shcn&A@m6CW#U&)hB21hSI#9zS`CM$r&e zw1Ee}aRB1?Ql7eU6u3iDZ4W;^5*)g&zBpeF7aWhF{=7u?siyjC(#N`pcv=-xalF*1 z<$*(ika1J7H`Z&!_@H=qD`K{o`S6^k5jvwbK{aeutSz_2TEQG$J>DXlZo`!MFKxIs zGVZRP6f)pOO+Of!-22S_GWayMF<7Gf2IgbYOtVR^PHc=N{A9{WaW>%ye16Z-kYYns zC+Wo^hS5KR`*#Utudd;(lk6GTpChinFhihIKo!YHlxzq!y1=^fwsT5`+~w-*XfLqX zuMRG@DD*SqLIlHk9LLL-e&Bnr0+)Empb==O@5!q^{uaeK>XB|~iEhT|vUjKe5#Vz4 zR&(xE>57Mq|Jf=q@?kOaVO7G{_mh)#I*|k^>$yfzJM_eP(;#&AC@xQP;fN2-U=n_X z&qQrx<9%jIZoIh&QfVK9(QDR6AYPNjOUA?m1}<6Jj;CBPf{i*oFRN!#1F zHu5u6jNrsNh%w`f5B^)+$IxN3pmud(-g=Tut@;~P&J3MXQe}^BGdIOao72m5y#`eS z2;OxYJGhq1sB9}!~!;~As#Z6vDl+90#HIdc6g4Zr|ujXCrc`38iVxkN(Wv==HxcI#HvutKpg6D*B^qxlKE__^+}uhG+lQ_b(s!SF+ZR0Topr`t>Xd-V zwx1}Wi3Z0~bxn+pULM)=@gmz)q|PtG=ee1rA!4^6&p#&Xv)Zv~@IEA(#Do zU=V6|6fFS{GT`5sDD74z&BbN{|BN;NnbfS2 z6}*yE)zNtL3(j>nXIQ6PL6uzC!}_P?AjoyMQoWcQbMjx4vxOXKGJ#uTI~ZA5aY-X8V@WHHTU|YbRxwy@Nrej>l%fbh>Nf?avn}Ki zO9|Yn;F*Ax;*v}hVO_C+B_)^Lpu|mq?Q97-;m?#NIIjk64|*4M>#naOD@+s;OEUj5g~UNoB;V-dh-mkqiq9 zF3is!WRo3N=O!xNYZ-_M7s{)N;aJhx<`Q5`=XUs6!IyOSfWy;gH8J5`o_qpG2K&s{ zkntMQ31lu(6w@r=OT2r;!Q(U3U^bg+3SH@5EiCwpez+-t9{2)Y!#|e+82=A0ilN99 z|7#T+OzHMctb&wJSyKLYg=C#rkK*HSx`@-VwMsiwBVYoL(AD3ICSBB%jr$0?S&lR4 z`jgEp!da>X;$h!H3FgYXDXeKAqE?x<#UPKq0M|HQ!J%DTRf@G=B5T7gtSDALGK%l} z7=}FgUrN;fD9QYzl=zPl9a!mKLW=(gW&9(=@|RG2w@e<}>l!=N@fOJ7_37@*sR+b8 z0XA-#7lyF@*Tw$3IscziN-%Y)|9ZYlO=-?x@JmR1GR25`-4!(eWQiNU?pSX$2xF;l zg)UcbH0c%4gF)ddU;u;0SHK7ceXoEicgTQwYL-9q(oL2V{Hd0B{b);Y1*yGwg7+b_ zT=MThf4I>*{fQX!@8w4RT5V{ZV``Q%?($X+06&n5O(F|0@jB8caR}!A?-cm#`c^n{ z4MqhpAO80Mzya0d$7vJ>X>^%?Y<7k``X z2)CEL9UtBKvmO0q2(deDCv(-I&NK?4f6+bxfso94sJHiU@gh=+##Ww+!AiHnCB2en z(>O$(c?Yzl*KWGX>`n13LAX$_!uIJj-@nD+V2v3~? z_^tW}8YqhCij*-)uCOZInA+wU*t2vaoT=OHp04@^SPjCE9s9?R`fpbgi){^;%R9S= z3U}@cY!dm*y}Bz=yS6{xS5PG@M=7}@Q;u8&Pn`1=4u5;AlL4!I|9uHqtAJc?%th(N zI?p90ke_k=Kq%;!DO$;^gf4&Bsc)NC>mx7S!5ptNrp(C_!8y1uQ^@#{jw60h2S>b0 zM!aA8#)*n@q;H{B{~ZSDx(|Lqj-M^|N$+jPv9mn8d>C(-R{R@Il);UUw~6tA$>gCL zA$pFe(L`Eq$JH{EPDGM`->&Ubr+LUGq7fo3pB-MjIHf~FCs*YPca!zhi0=uz7LSkh zdIZsgP%x#&*R2XNwX;u2MuXP(XO~;ue?DK_k5zNV+8#fBiIBA9i=*An7_2y1`7vy~ zG1wm+tzT6F%O}B`IlR>DKdG-C3ZXvN|K>4J&O;?Wf}XU5zL(+?fVG4a(T~4%^(`;= zl0xJopd4v^!pvA7T!`6cl zbx!%t>?g}=blB{iCr}p-Y5g2E*R+arF@w(I9V%#|YCKGr2)FNP`4uBLIxvq>vOT5!Kb}RaL&v z-p{_mox5AT`{l3}kJ#i=$=RVO}`Mw4!W z4Q)EfJe5vF(E!&FcmAQHeBG{vCzy`Q0@KT;#bA1F@s*DH?5T^ndciKzM7n<@~*z! zb+eliL;6VZ)VJE9(6F|8YO}1jy0Au5)3Mw$?p~`I-1u>8fV`%6@}g7Su-bONSw#8d zq5te>zo597sA!>{gq;ao`3>7;vkq)v*UTi)Qrj_>RUh`5Q~dXfSrW2FS}2=)rjv}r z5ATWJ6vgQLXPS?oy-zWD3C05*QuOb!mGU_=3psmx{fh%g#ebo(URpNt(W))Y3P~X$ zifTWoO4J;;?_gpRbS}3TB6hju$c0J`fVl z)MN|9_14#3;Q%wyRYz%4;a=jy+TbN2^}8#UViEk*;r;l zN)FY!PUy5%aJ!$4x!a?ytL0ZfIR** zfljhcuS0I=tHMyG!ce-xP^w@H^R84=3U0JXhR3EF&}LahN7 zu|sEz_&OHFk`9PjzNxdpU4w1#JTK#hG&TK=OXNgiGM|91XlFb0*UmuC{D}#D(N4R$ z`V^&gneWuI&EAd(H?5qyqCU}cS8+<6HjIEfh()lo%c@h+v-NJE^VYMzm2a)%@zKWk zqlRkh?$)i>#F9snXUx*)h@Bf`AQA)k zTk3u5o1>BNy~ryl=YRW-44tCBUyVAw_ZsL;1l}mit&wmyMU3R)d_#f|TE0J{vE}Nx zojV9Vz4Jit&TgioIblj1xjJN;4Kbfu+@(lELb0FY7h0%*BCI9hX#!9T#q>-b0F#yT7E9pD1I7gG;CoGF9fxayF-j-m9BX>o7a}fO)Vvm|UUqrGh zzLkcPz{Z8h?$nPQYuOUVZuSOa-+~>VLxsuGb4m&pK;dzckVrmQ7#g&oKw=M<;n*;v zG49LRghgvXv}hR`Dsf35r_QJ6g!;-DEy2a(SnU!QoRt|loePY7w3<*blrr9Sml3nF zq6i`%8(?g@gQ9NG<*djaxznyB%{7PlJq&t8x978dJNmq=vp~3hBU^4-xjPJE{=wr; ztv`tdT!(zkNrQGE%Lv6K#cKV<;!IPFzg2bQ4{nw;8*8-#|X0n6T(_ z%KlVfB>UAWM3ui1T0}a0N_3K*S`_!5)){kX1K2?w)>XqkDd23Ui=Vs9WjXT|92_U`f{ersHXZdE2~mX~Pgj%5u;8io?3 z1v|An6E9z96DP>$>glHWp2h?sFNz{mB8vigYU!H1p#mF%^C78s--~sL`L{xgKJkfR zCt!hYi!IHwuE7s46@V;N?u-CssSbf3ZMWtin$VRNp+Y$cnE(SK5*7M6?gT$Ze%&i_ zP}Jwl=^L%-d5N=i@=fX2ho&eDry^kv8~+yJJdr%!ZqXz>`VH%{S@^R=WDAo7*D{WL z5vVEzwa%T}$crubB|QJNfhJ}DvxtjHK43+Aj_25qys=82SOxc&3tTD-{8hoGMPiGL za03I=UpBO(vp2{((W2hQDm7n7y*Ltaxo)l^wHVPY)No@c?kRFI}1WCzp; zlhrDW6Lm)35vMWu1Q53+n944lGB;Ari)1YM9p{Vh1_?H#zd_A>91x$cuCaELOk=3&TvN2*xEPH9}Aa`Q;XG?vSVLjx^ zgyEJsR^d<<@|lSPZ2&+1%8)yvf`nz3$*~bJ zXCQSZVD-)*g+An(Xxdq7f?Ocv8eELSQ;`;_3TKP*F65R1^Q8aaH@!wi_f`s;uVCIA z+xB<}wbn>|f!wS2E-O%FAD~Ha%NQdsPgT^SkrXOjPEYcONv}b04_Ko1nAh5YYcyIO zWc=plAIlq$#Wu#yxT(mZT|^N9LP^pT%sLAUDz^_U+uw=N&fFaaw&{6EqGYL;tz)Fp zbGoiW3*yK%Nuumb;4!SlH;AJQk@b5%q3xEl35kg8m$M0qe1{z6(NCLY>l$U1%e(5+ zZrQ@PB7~)jF{%|@WZ#k+w$PN|i({mW-&g%)a|NA=AI8tIlD0XH>}J*ia9oLJ;U8X) z%gJKeWThobEbwtKN7cBR6(sO-;2E;}mAb$sY3u2KdHiwo1$vc+hr4(fplBw1zHL%a24pF1vMBBw@JZU<@%$FkB1X?$ehF5#(yUJ1^u2Fr#V@nI z{Kd`JW`o;xP<}OtV%<^oi&)#{S6j~o-@q|ZwR6Y##RF#F@$lh=CwK?oK>2rQbDE}t z-Q{WF;N=OjZ{BZyp3a&wbb$>~|E5PRGHM>NywCDBpdL7TW{GpcNP&;ImexmRGc%EB z*I;m~TxfZXE!KT{jAtOn`J=EljiW=o@?@HYHjUTUQwbt4ItG;%%LggJtfc9Bd-=D= zY5OFa@sS=J+=|Ysx|82?i*jR_a`iOuD85^3b4x~IQs{uG`Q9!=nyZddCHFbDTZhHY zjsfUP`8BkpSeahJvoMYa1Wk2jya}ahz_k8B;AsZ`Nh-MDjo#ZEiusQ{QQWOzRaSYq z)J3x6HTYiNXvvVtU6o;uL{Im)tnT0;h`N9B~equrZD|Wt=9+aOm89 zGw_~#szF+K@fhtC#bh>L2g&4tyr-Mfts{# zYfV!jo-cZkY3zcYexQ-Qva0mN`IaqBb+Zfd@rm6jwDQp=qVQ5GkA~AfRU+i7tR_6Y z!H)mk2l9z3c&_M*mNY2+2}gBv@heUHSW%y?VV28sp#Sp_jIzp(Z-hJnwxMj;4Y)L$ZHK~7pm(@rtkK@x-mrm^Q8)mg@%`@ zZ#b64I6XgEyOzN2b~LE01wo?zd;Ye$m@VP>=hq6_A7f{G4Vt*MAMDKxFz~bv)h&Hq4^(G;# zG0gRKGK6lec7AJ~N7Mbs&FD)SxKfw)w(A9Zr&L+cCVR-8rgyfOCy~cn2@P~pQkAOJ zL&M1S83+?MK04?3?K2``O>W45J-Yr&XaAvwdNuQxTzS#flAYOQS~i)-ksrxi(6Sno@9B zbh-xGf92haIS2i&I(_~g(qPN_gw*9u=!!wmjVSZcjG$YQ*iC6vkr}r!c%bH*9=1se z_%#VquA%uF*@$NqvmY5)T?cCmoNRhxzM=Xv?Kp;La=(p`uJ2^9UL+Cf=@2_4aW8G-(4wP;+bp(PtLgW2X9ywt98fF^^ig#KT1(3$#Af;EiwgUIohHZ! zvOPbGl209Q+(!B;`@vJ+y@Nd63R>yMSBOo6nd}Ic&cc|xopnvx%218C@>cK^&8iD} z8!;*TrZc58aR+5VZCGk&F?-oqTWgdGdlr*|0 zqp-md3WD}L?H6srA;tnn-Ka;W@l)!n=sPO{$~JVu z)pu4^${6;NKVcs>C6*yJ7HTOcGk+|ju%Xw8)3t@H=VA#V7Dp6mfmCsgaW-BJk6U~g z*r>ie-{>~*k-DZQAT&H`D?;Jnj$bghc_X6H6faHFg!fF%(fO60@B6hTfK>SNWwH8g zeJ(D1#6o9Ew&m=Q%!SB#DrN@8 zFl^ZiHI*C&q+J!qBysInSVzj*~pT*(=i`d2Us6y;D5ez zlu4^+GET01$5h8OqH3x=1ZZ`IPwquR&TkQ&US`tFTlL>$WSv7(?@ksE*K4SuUL!Q+ zmC!O;5=pjRR(xZri@ZFd6ocM~3xaQGLKlg-VdW)~VBElI6zOWCIuwQoBHPx*DK{sL zSGJ=Oq!G-4(oWuiq_Tm&imHW(G=}A}c%zIx6;{U7zr3UyWd{Q{2DlcU@vs?q-cG@5 zQq)YrhG(Ro^CZD64DR7PM7vq;Db9h?7W$W}2+u0)`?R<->3NTeejzwrVmJx<3205dPA03gqK_@6e%;dp^*C)ZjPF@p z2aVN&!EvE){Rz14Vm!@^8|N^WqgfXHQUamPVviIjd5)-@bd(#~F;aM)7_OfG@nQ`vQk^Z;(keNZ{^Cw zLTxg@UDo;G3S|w|%d)cj`DDS()+=jD!MkH#+h*a|2FQ6tJD>7UdVBtvr6Oh|z}Q33 zs=N@U@4#9lehYR>wrCo*Va12>gtnOnm5=S`w1T~&@CtHUSXpk8*v20;BEp6VUK>l1 z@N@Q)C0x6lv4D$l2TUFc*@uYiWZ-E(qq(};;E(hDK(oP`?w^MnQFq|^F#p$$J@9Rua>*E`a;b#`XwOFQwr@!8R*wWY(IWBH?( z=388HwMkdbb#X!q`Q(F5#gQyqTVK$bEw4Ie<1^~W3B@BE=VyzDg;G0aUr_K=r*-ji zp0ZybA2NAvZ@1Vs*;BPcvonQPuvyl#3NQ5U6M&@#wL0+6W3SWO`6tU(DT4M3o?FqU z16I~RW*g(C#^2Fie=aA4mcRF3RtR;=kc221vO@5RAD*{swXt$3k0O#$u;wb9GT&k! z%|Oho>Of@r)DH@EV4(@=n|9kj!Iw!L##!6vPY00MQTwt#l8o8u0?)R4?ha{R6b%qc zj)6N`Cg>34&r8;4Q%So)JxRp8%TC1wR>fH0f2X5++3#&b(iJlQ@3X%yyT$Xszy}=(*G$d>Jwx=9tc?-9a4H99` zXMg`H4F@!%L?fMBG8$TF_4nP)?rGWH2-}iM9bIlnAKQibcx0C!4$=Ogh1ch`{2wSQ BQ#Swr diff --git a/data/projects/demos/Shovon-ProgressiveHousePluckDemo.mmpz b/data/projects/demos/Shovon-ProgressiveHousePluckDemo.mmpz index 2d31bd7bdc25008624f6eb0b345c4ab635ba05c1..3ec6a2cffde81abf1a6b130e1ea1b8b4c68966ce 100644 GIT binary patch delta 764 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

6-+Nfxx{V%e{K3PY-yh?{$I% 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 Px=ihN9taMpnC<=_t^GU6 diff --git a/data/projects/demos/Skiessi/Skiessi-RandomProjectNumber14253.mmpz b/data/projects/demos/Skiessi/Skiessi-RandomProjectNumber14253.mmpz index d3c6e0f8d0ed65b18121ef34bc63c9ee9943b67f..bc2810567b911f68adbc8518df9fedabaa556e44 100644 GIT binary patch delta 10958 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 diff --git a/data/projects/demos/Skiessi/Skiessi-TurningPoint.mmpz b/data/projects/demos/Skiessi/Skiessi-TurningPoint.mmpz index ee5be4b553e9f3f9ba5cbc36d314bae47ed2fec4..47a0a3672c696a68fdc1f8fed34f0db45548a535 100644 GIT binary patch delta 8601 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 delta 8608 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 BfbakS diff --git a/data/projects/demos/Socceroos-Progress.mmpz b/data/projects/demos/Socceroos-Progress.mmpz index 74ff5774c94e30fd98d03372ae2690386d3fa967..854663787c30cabf73e38ea3e24820a925eeaaeb 100644 GIT binary patch literal 18425 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 literal 18487 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 Y%_3aUC@hlWvAAy9`S}n3AF{)gARr)h4gdfE diff --git a/data/projects/demos/TameAnderson-MakeMe.mmpz b/data/projects/demos/TameAnderson-MakeMe.mmpz index de0152818816daec384ba000e646b9808fa55129..b69a64e3afef4692accfad724b0263f4aa6d099c 100644 GIT binary patch delta 3116 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 Gzhql&g&KYU delta 3181 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 TCKnCU^m-wm%OCy^uo%{&q}D63 diff --git a/data/projects/demos/Thaledric-Armageddon.mmpz b/data/projects/demos/Thaledric-Armageddon.mmpz index 0e9d5f83fa9aa17ad0e6ece235c573a2357bf710..731ea55f7d52d44c3aab8204c082677dd519043b 100644 GIT binary patch delta 676 zcmV;V0$csor303w0|WpK35c--1JHlg{T<e-GDJZ_w>Tap>Cd2Pbx*HW}#4kH!*M&PQVfVk=X^@374>2G22CxO_PO(!=e} zMT(^I<|EoPM-59(_hnL_laGHYmPocH`tM>o?WONe9k47gY z_7FHPTDDYbb4cU;+*-Nb%U}NUD+nFSxBm05>DLhy*I#sf9cQ1P650M`)a`B?AS8c* zI<>OAzoI^^cX(G;xN!aVaj^bNcm4d=?dOLehAM)6<$-yOeGw*9l5co z=Ktsapf3w5ymd679rb^pMSpiQOS_#5dFJKrwA%3ILH>27 zSGk$d`f0-Gf2CQ7tBn`CYtPM6H={KG^SuL2g?f6YqG)+b@*j^idxJN)3+A0M@tp!l%!R6o|zqWAs)6GmT6V?@qEY6EmXX( zE_foTTN0S9SGR7WZu)RKPV`ORXFMdiQ~yH{E;{$Oo!i;@d+2}4c!O>yibL0qKRB@iC$53M{Aetp%6&9eAhxpE@g25V z#^5#^60VCkB6k77@IE3a#~D zwg2}gqmw{>G&(7{_>w+LFib%^`C!Dzm9*Pxc;K+>p1)T zl*slkqi%QG03rDc)Tx!_{T20Ty~De*!iDR?2d;IY#zaHNU**WB7Zc}QvHLYWW(jd@?+RAhCe0R8GnFc zhipNqui^hAnWF(fWBz~s5Bjp8!dssXE?FM*@icF(r#q8wvN!P7QJm)MqQAS@qPCq2 zxjEY<1{mHvDA?;%uW~b^^;6^gUunYUYU9Q3+H*6r9jyT0yK1`?6A-xaDYET>-s1bp` WfYYSotyaHh;NAve!OkdAl& diff --git a/data/projects/demos/Thomasso-AxeFromThe80s.mmpz b/data/projects/demos/Thomasso-AxeFromThe80s.mmpz index af68b8b8b114b9f7a6623f57d6637f27da47e4db..f7056d38c2217b78503cdc2228b41f319f31aad3 100644 GIT binary patch literal 15255 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 literal 15390 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 b7}hq4GUlki>}sDT|Mb}Wf#~?7mhJxmHE|BW diff --git a/data/projects/demos/TobyDox-Psycho.mmpz b/data/projects/demos/TobyDox-Psycho.mmpz index 09ec6b6a6b4bd4ca305cb54bafb657e3854c0258..c4fe7a1c428e416336a6ec65d2189e5ef8dcfcc8 100644 GIT binary patch literal 5787 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
Click to expand
-# paste here
+
 
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index feacb8fdb..f9a0ae192 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -7,8 +7,12 @@ 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 + + From 35daff9a841b39abea4f30febb4c9d497d87c190 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Tue, 29 Oct 2019 22:42:52 +0100 Subject: [PATCH 61/81] GitHub: Add Discord contact link to template chooser --- .github/ISSUE_TEMPLATE/config.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/config.yml 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! From 200d1c209ce39b1b186a66389b22a9340c51dcdd Mon Sep 17 00:00:00 2001 From: Noah Brecht Date: Sat, 20 Jul 2019 21:03:48 -0400 Subject: [PATCH 62/81] more depricated qt functions --- src/gui/AutomationPatternView.cpp | 2 +- src/gui/widgets/GroupBox.cpp | 2 +- src/tracks/BBTrack.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/AutomationPatternView.cpp b/src/gui/AutomationPatternView.cpp index 6879b5bbd..a9033f37f 100644 --- a/src/gui/AutomationPatternView.cpp +++ b/src/gui/AutomationPatternView.cpp @@ -366,7 +366,7 @@ void AutomationPatternView::paintEvent( QPaintEvent * ) } p.setRenderHints( QPainter::Antialiasing, false ); - p.resetMatrix(); + p.resetTransform(); // bar lines const int lineSize = 3; diff --git a/src/gui/widgets/GroupBox.cpp b/src/gui/widgets/GroupBox.cpp index 158390bb5..06b8e1c5c 100644 --- a/src/gui/widgets/GroupBox.cpp +++ b/src/gui/widgets/GroupBox.cpp @@ -90,7 +90,7 @@ void GroupBox::paintEvent( QPaintEvent * pe ) p.fillRect( 0, 0, width() - 1, height() - 1, p.background() ); // outer rect - p.setPen( p.background().color().dark( 150 ) ); + p.setPen( p.background().color().darker( 150 ) ); p.drawRect( 0, 0, width() - 1, height() - 1 ); // draw line below titlebar diff --git a/src/tracks/BBTrack.cpp b/src/tracks/BBTrack.cpp index 205a22087..779cd3c74 100644 --- a/src/tracks/BBTrack.cpp +++ b/src/tracks/BBTrack.cpp @@ -218,8 +218,8 @@ void BBTCOView::paintEvent( QPaintEvent * ) : ( m_bbTCO->m_useStyleColor ? painter.background().color() : m_bbTCO->colorObj() ) ); - lingrad.setColorAt( 0, c.light( 130 ) ); - lingrad.setColorAt( 1, c.light( 70 ) ); + lingrad.setColorAt( 0, c.lighter( 130 ) ); + lingrad.setColorAt( 1, c.lighter( 70 ) ); // paint a black rectangle under the pattern to prevent glitches with transparent backgrounds p.fillRect( rect(), QColor( 0, 0, 0 ) ); From 38f599b6e71f94fdc743c7f9bd2a95aa339aa0da Mon Sep 17 00:00:00 2001 From: Noah Brecht Date: Sat, 20 Jul 2019 21:08:49 -0400 Subject: [PATCH 63/81] setPath rather than operator= for qDir --- src/gui/dialogs/FileDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/dialogs/FileDialog.cpp b/src/gui/dialogs/FileDialog.cpp index 3ce10760a..54cc9d6e4 100644 --- a/src/gui/dialogs/FileDialog.cpp +++ b/src/gui/dialogs/FileDialog.cpp @@ -47,7 +47,7 @@ FileDialog::FileDialog( QWidget *parent, const QString &caption, // Find downloads directory QDir downloadDir( QDir::homePath() + "/Downloads" ); if ( ! downloadDir.exists() ) - downloadDir = QStandardPaths::writableLocation( QStandardPaths::DownloadLocation ); + downloadDir.setPath(QStandardPaths::writableLocation( QStandardPaths::DownloadLocation )); if ( downloadDir.exists() ) urls << QUrl::fromLocalFile( downloadDir.absolutePath() ); From 2c5bf2b9dd75d21c5a059d58de68a270666d533c Mon Sep 17 00:00:00 2001 From: Noah Brecht Date: Thu, 25 Jul 2019 11:01:29 -0400 Subject: [PATCH 64/81] lambdas instead of QSignalMapper --- src/gui/editors/PianoRoll.cpp | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 065234aa4..5d11088f3 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -36,7 +36,6 @@ #include #include #include -#include #ifndef __USE_XOPEN #define __USE_XOPEN @@ -204,20 +203,15 @@ PianoRoll::PianoRoll() : m_nemStr.push_back( tr( "Note Velocity" ) ); m_nemStr.push_back( tr( "Note Panning" ) ); - QSignalMapper * signalMapper = new QSignalMapper( this ); m_noteEditMenu = new QMenu( this ); m_noteEditMenu->clear(); for( int i = 0; i < m_nemStr.size(); ++i ) { QAction * act = new QAction( m_nemStr.at(i), this ); - connect( act, SIGNAL(triggered()), signalMapper, SLOT(map()) ); - signalMapper->setMapping( act, i ); + connect( act, &QAction::triggered, [this, i](){ changeNoteEditMode(i); } ); m_noteEditMenu->addAction( act ); } - connect( signalMapper, SIGNAL(mapped(int)), - this, SLOT(changeNoteEditMode(int)) ); - signalMapper = new QSignalMapper( this ); m_semiToneMarkerMenu = new QMenu( this ); QAction* markSemitoneAction = new QAction( tr("Mark/unmark current semitone"), this ); @@ -227,19 +221,12 @@ PianoRoll::PianoRoll() : QAction* unmarkAllAction = new QAction( tr("Unmark all"), this ); QAction* copyAllNotesAction = new QAction( tr("Select all notes on this key"), this); - connect( markSemitoneAction, SIGNAL(triggered()), signalMapper, SLOT(map()) ); - connect( markAllOctaveSemitonesAction, SIGNAL(triggered()), signalMapper, SLOT(map()) ); - connect( markScaleAction, SIGNAL(triggered()), signalMapper, SLOT(map()) ); - connect( markChordAction, SIGNAL(triggered()), signalMapper, SLOT(map()) ); - connect( unmarkAllAction, SIGNAL(triggered()), signalMapper, SLOT(map()) ); - connect( copyAllNotesAction, SIGNAL(triggered()), signalMapper, SLOT(map()) ); - - signalMapper->setMapping( markSemitoneAction, static_cast( stmaMarkCurrentSemiTone ) ); - signalMapper->setMapping( markAllOctaveSemitonesAction, static_cast( stmaMarkAllOctaveSemiTones ) ); - signalMapper->setMapping( markScaleAction, static_cast( stmaMarkCurrentScale ) ); - signalMapper->setMapping( markChordAction, static_cast( stmaMarkCurrentChord ) ); - signalMapper->setMapping( unmarkAllAction, static_cast( stmaUnmarkAll ) ); - signalMapper->setMapping( copyAllNotesAction, static_cast( stmaCopyAllNotesOnKey ) ); + connect( markSemitoneAction, &QAction::triggered, [this](){ markSemiTone(stmaMarkCurrentSemiTone); }); + connect( markAllOctaveSemitonesAction, &QAction::triggered, [this](){ markSemiTone(stmaMarkAllOctaveSemiTones); }); + connect( markScaleAction, &QAction::triggered, [this](){ markSemiTone(stmaMarkCurrentScale); }); + connect( markChordAction, &QAction::triggered, [this](){ markSemiTone(stmaMarkCurrentChord); }); + connect( unmarkAllAction, &QAction::triggered, [this](){ markSemiTone(stmaUnmarkAll); }); + connect( copyAllNotesAction, &QAction::triggered, [this](){ markSemiTone(stmaCopyAllNotesOnKey); }); markScaleAction->setEnabled( false ); markChordAction->setEnabled( false ); @@ -247,8 +234,6 @@ PianoRoll::PianoRoll() : connect( this, SIGNAL(semiToneMarkerMenuScaleSetEnabled(bool)), markScaleAction, SLOT(setEnabled(bool)) ); connect( this, SIGNAL(semiToneMarkerMenuChordSetEnabled(bool)), markChordAction, SLOT(setEnabled(bool)) ); - connect( signalMapper, SIGNAL(mapped(int)), this, SLOT(markSemiTone(int)) ); - m_semiToneMarkerMenu->addAction( markSemitoneAction ); m_semiToneMarkerMenu->addAction( markAllOctaveSemitonesAction ); m_semiToneMarkerMenu->addAction( markScaleAction ); From d9f1383ca9d5b1b2af89c415cab57363a4357d49 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Tue, 27 Aug 2019 15:19:42 +0200 Subject: [PATCH 65/81] Remove remaining usages of QSignalMapper --- include/PianoRoll.h | 1 - include/Track.h | 1 - src/tracks/InstrumentTrack.cpp | 11 +++++------ src/tracks/SampleTrack.cpp | 11 +++++------ 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/include/PianoRoll.h b/include/PianoRoll.h index f56d791f4..7c2c53d42 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; diff --git a/include/Track.h b/include/Track.h index 40b32a61a..525699548 100644 --- a/include/Track.h +++ b/include/Track.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 730ab97bd..673996fa2 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -1239,6 +1239,7 @@ void InstrumentTrackView::muteChanged() +//FIXME: This is identical to SampleTrackView::createFxMenu QMenu * InstrumentTrackView::createFxMenu(QString title, QString newFxLabel) { int channelIndex = model()->effectChannelModel()->value(); @@ -1253,8 +1254,6 @@ QMenu * InstrumentTrackView::createFxMenu(QString title, QString newFxLabel) QMenu *fxMenu = new QMenu( title ); - QSignalMapper * fxMenuSignalMapper = new QSignalMapper(fxMenu); - fxMenu->addAction( newFxLabel, this, SLOT( createFxLine() ) ); fxMenu->addSeparator(); @@ -1264,14 +1263,14 @@ QMenu * InstrumentTrackView::createFxMenu(QString title, QString newFxLabel) if ( currentChannel != fxChannel ) { + auto index = currentChannel->m_channelIndex; QString label = tr( "FX %1: %2" ).arg( currentChannel->m_channelIndex ).arg( currentChannel->m_name ); - QAction * action = fxMenu->addAction( label, fxMenuSignalMapper, SLOT( map() ) ); - fxMenuSignalMapper->setMapping(action, currentChannel->m_channelIndex); + fxMenu->addAction(label, [this, index](){ + assignFxLine(index); + }); } } - connect(fxMenuSignalMapper, SIGNAL(mapped(int)), this, SLOT(assignFxLine(int))); - return fxMenu; } diff --git a/src/tracks/SampleTrack.cpp b/src/tracks/SampleTrack.cpp index 4b51ef6ec..ba04f909b 100644 --- a/src/tracks/SampleTrack.cpp +++ b/src/tracks/SampleTrack.cpp @@ -847,6 +847,7 @@ SampleTrackView::~SampleTrackView() +//FIXME: This is identical to InstrumentTrackView::createFxMenu QMenu * SampleTrackView::createFxMenu(QString title, QString newFxLabel) { int channelIndex = model()->effectChannelModel()->value(); @@ -861,8 +862,6 @@ QMenu * SampleTrackView::createFxMenu(QString title, QString newFxLabel) QMenu *fxMenu = new QMenu(title); - QSignalMapper * fxMenuSignalMapper = new QSignalMapper(fxMenu); - fxMenu->addAction(newFxLabel, this, SLOT(createFxLine())); fxMenu->addSeparator(); @@ -872,14 +871,14 @@ QMenu * SampleTrackView::createFxMenu(QString title, QString newFxLabel) if (currentChannel != fxChannel) { + const auto index = currentChannel->m_channelIndex; QString label = tr("FX %1: %2").arg(currentChannel->m_channelIndex).arg(currentChannel->m_name); - QAction * action = fxMenu->addAction(label, fxMenuSignalMapper, SLOT(map())); - fxMenuSignalMapper->setMapping(action, currentChannel->m_channelIndex); + fxMenu->addAction(label, [this, index](){ + assignFxLine(index); + }); } } - connect(fxMenuSignalMapper, SIGNAL(mapped(int)), this, SLOT(assignFxLine(int))); - return fxMenu; } From b5b3b2e6a61d4eb97b6f5016069e56ff820c2b47 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Wed, 30 Oct 2019 11:13:18 +0100 Subject: [PATCH 66/81] CMake: Require Qt 5.6+ --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 22e241c92..2f310d27c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,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( From 400c8d8105b1ed3cb312d45c2c42f7b9b28da1c2 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Wed, 30 Oct 2019 12:12:53 +0100 Subject: [PATCH 67/81] Remove Travis MinGW builds We already run them on CircleCI with a newer Qt version. --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ab2a8ae85..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 From 9cb1f8e784b5000654f49504bae717ce1828f34c Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Thu, 31 Oct 2019 14:37:40 +0900 Subject: [PATCH 68/81] Change the docker tag for CircleCI Linux builds In response to https://github.com/LMMS/lmms-ci-docker/pull/7 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c1a8ea7ff..0dc146486 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -113,7 +113,7 @@ jobs: - *save_cache linux.gcc: docker: - - image: lmmsci/linux.gcc:xenial + - image: lmmsci/linux.gcc:16.04 environment: <<: *common_environment steps: From 488c4ea6034da306ee14932131c4d6536bfbf7af Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Thu, 31 Oct 2019 15:14:52 +0900 Subject: [PATCH 69/81] CircleCI: support Qt from a PPA on /opt --- .circleci/config.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0dc146486..0ab2c51a0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -122,7 +122,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 From 53e6b645c8e550156aa312a1b8b0d4b085bf7eac Mon Sep 17 00:00:00 2001 From: Alexandre Almeida Date: Thu, 31 Oct 2019 15:13:25 +0100 Subject: [PATCH 70/81] Use "bar" instead of "tact" Closes #4865 --- include/AutomationEditor.h | 6 +- include/BBTrackContainer.h | 4 +- include/MidiTime.h | 36 +++--- include/PianoRoll.h | 2 +- include/Song.h | 26 ++--- include/StepRecorderWidget.h | 6 +- include/TimeLineWidget.h | 18 +-- include/Track.h | 8 +- include/TrackContainerView.h | 22 ++-- include/lmms_basics.h | 2 +- plugins/MidiImport/MidiImport.cpp | 14 +-- plugins/carlabase/carla.cpp | 4 +- src/core/AutomationPattern.cpp | 2 +- src/core/BBTrackContainer.cpp | 25 ++-- src/core/Engine.cpp | 8 +- src/core/Mixer.cpp | 8 +- src/core/Song.cpp | 44 +++---- src/core/Track.cpp | 138 +++++++++++----------- src/core/TrackContainer.cpp | 7 +- src/core/midi/MidiTime.cpp | 52 ++++----- src/gui/AutomationPatternView.cpp | 12 +- src/gui/TimeLineWidget.cpp | 30 ++--- src/gui/TrackContainerView.cpp | 6 +- src/gui/editors/AutomationEditor.cpp | 94 +++++++-------- src/gui/editors/PianoRoll.cpp | 142 +++++++++++------------ src/gui/editors/SongEditor.cpp | 42 +++---- src/gui/widgets/StepRecorderWidget.cpp | 10 +- src/gui/widgets/TimeDisplayWidget.cpp | 10 +- src/tracks/AutomationTrack.cpp | 6 +- src/tracks/BBTrack.cpp | 10 +- src/tracks/InstrumentTrack.cpp | 2 +- src/tracks/Pattern.cpp | 64 +++++----- src/tracks/SampleTrack.cpp | 18 +-- tests/src/tracks/AutomationTrackTest.cpp | 4 +- 34 files changed, 439 insertions(+), 443 deletions(-) diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index 968bb34be..e39eaddd7 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -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; diff --git a/include/BBTrackContainer.h b/include/BBTrackContainer.h index 236325157..e4895aa87 100644 --- a/include/BBTrackContainer.h +++ b/include/BBTrackContainer.h @@ -48,8 +48,8 @@ public: 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/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/PianoRoll.h b/include/PianoRoll.h index 7c2c53d42..b600385c8 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -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 diff --git a/include/Song.h b/include/Song.h index 32ead7181..1e047caaa 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,7 +254,7 @@ public: } void updateLength(); - tact_t length() const + bar_t length() const { return m_length; } @@ -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/StepRecorderWidget.h b/include/StepRecorderWidget.h index 0e4512169..cafce2b24 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); @@ -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/TimeLineWidget.h b/include/TimeLineWidget.h index 7629694ca..374a26418 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,18 +135,18 @@ 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(); } @@ -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: @@ -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 525699548..4adf6378e 100644 --- a/include/Track.h +++ b/include/Track.h @@ -266,7 +266,7 @@ protected: selectableObject::resizeEvent( re ); } - float pixelsPerTact(); + float pixelsPerBar(); DataFile createTCODataFiles(const QVector & tcos) const; @@ -547,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 diff --git a/include/TrackContainerView.h b/include/TrackContainerView.h index 094cbfff0..cf79a0a21 100644 --- a/include/TrackContainerView.h +++ b/include/TrackContainerView.h @@ -54,25 +54,25 @@ public: 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(); } @@ -118,7 +118,7 @@ public: virtual QString nodeName() const { - return( "trackcontainerview" ); + return "trackcontainerview"; } @@ -139,7 +139,7 @@ public slots: protected: - static const int DEFAULT_PIXELS_PER_TACT = 16; + static const int DEFAULT_PIXELS_PER_BAR = 16; virtual void resizeEvent( QResizeEvent * ); @@ -176,7 +176,7 @@ private: scrollArea * m_scrollArea; QVBoxLayout * m_scrollLayout; - float m_ppt; + float m_ppb; RubberBand * m_rubberBand; 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/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index b8653fe18..b3d01e790 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -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; } @@ -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 ); } @@ -325,8 +325,8 @@ bool MidiImport::readSMF( TrackContainer* tc ) 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; 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/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/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/Mixer.cpp b/src/core/Mixer.cpp index fd44b0459..3f22a22e1 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -361,12 +361,12 @@ const surroundSampleFrame * Mixer::renderNextBuffer() // Stop crash with metronome if empty project Engine::getSong()->countTracks() ) { - tick_t ticksPerTact = MidiTime::ticksPerTact(); - if ( p.getTicks() % (ticksPerTact / 1 ) == 0 ) + tick_t ticksPerBar = MidiTime::ticksPerBar(); + if ( p.getTicks() % ( ticksPerBar / 1 ) == 0 ) { addPlayHandle( new SamplePlayHandle( "misc/metronome02.ogg" ) ); } - else if ( p.getTicks() % (ticksPerTact / + else if ( p.getTicks() % ( ticksPerBar / song->getTimeSigModel().getNumerator() ) == 0 ) { addPlayHandle( new SamplePlayHandle( "misc/metronome01.ogg" ) ); @@ -1288,5 +1288,3 @@ void Mixer::fifoWriter::write( surroundSampleFrame * buffer ) m_mixer->m_doChangesMutex.unlock(); } - - diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 336aa3df2..78c9f422a 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -55,7 +55,7 @@ #include "PeakController.h" -tick_t MidiTime::s_ticksPerTact = DefaultTicksPerTact; +tick_t MidiTime::s_ticksPerBar = DefaultTicksPerBar; @@ -66,7 +66,7 @@ Song::Song() : this ) ) ), m_tempoModel( DefaultTempo, MinTempo, MaxTempo, this, tr( "Tempo" ) ), m_timeSigModel( this ), - m_oldTicksPerTact( DefaultTicksPerTact ), + m_oldTicksPerBar( DefaultTicksPerBar ), m_masterVolumeModel( 100, 0, 200, this, tr( "Master volume" ) ), m_masterPitchModel( 0, -12, 12, this, tr( "Master pitch" ) ), m_fileName(), @@ -86,7 +86,7 @@ Song::Song() : m_patternToPlay( NULL ), m_loopPattern( false ), m_elapsedTicks( 0 ), - m_elapsedTacts( 0 ), + m_elapsedBars( 0 ), m_loopRenderCount(1), m_loopRenderRemaining(1) { @@ -162,10 +162,10 @@ void Song::setTempo() void Song::setTimeSignature() { - MidiTime::setTicksPerTact( ticksPerTact() ); - emit timeSignatureChanged( m_oldTicksPerTact, ticksPerTact() ); + MidiTime::setTicksPerBar( ticksPerBar() ); + emit timeSignatureChanged( m_oldTicksPerBar, ticksPerBar() ); emit dataChanged(); - m_oldTicksPerTact = ticksPerTact(); + m_oldTicksPerBar = ticksPerBar(); m_vstSyncController.setTimeSignature( getTimeSigModel().getNumerator(), getTimeSigModel().getDenominator() ); @@ -286,20 +286,20 @@ void Song::processNextBuffer() int ticks = m_playPos[m_playMode].getTicks() + ( int )( currentFrame / framesPerTick ); - // did we play a whole tact? - if( ticks >= MidiTime::ticksPerTact() ) + // did we play a whole bar? + if( ticks >= MidiTime::ticksPerBar() ) { // per default we just continue playing even if // there's no more stuff to play // (song-play-mode) - int maxTact = m_playPos[m_playMode].getTact() + int maxBar = m_playPos[m_playMode].getBar() + 2; - // then decide whether to go over to next tact - // or to loop back to first tact + // then decide whether to go over to next bar + // or to loop back to first bar if( m_playMode == Mode_PlayBB ) { - maxTact = Engine::getBBTrackContainer() + maxBar = Engine::getBBTrackContainer() ->lengthOfCurrentBB(); } else if( m_playMode == Mode_PlayPattern && @@ -307,17 +307,17 @@ void Song::processNextBuffer() tl != NULL && tl->loopPointsEnabled() == false ) { - maxTact = m_patternToPlay->length() - .getTact(); + maxBar = m_patternToPlay->length() + .getBar(); } // end of played object reached? - if( m_playPos[m_playMode].getTact() + 1 - >= maxTact ) + if( m_playPos[m_playMode].getBar() + 1 + >= maxBar ) { // then start from beginning and keep // offset - ticks %= ( maxTact * MidiTime::ticksPerTact() ); + ticks %= ( maxBar * MidiTime::ticksPerBar() ); // wrap milli second counter setToTimeByTicks(ticks); @@ -407,8 +407,8 @@ void Song::processNextBuffer() m_playPos[m_playMode].setCurrentFrame( framesToPlay + currentFrame ); m_elapsedMilliSeconds[m_playMode] += MidiTime::ticksToMilliseconds(framesToPlay / framesPerTick, getTempo()); - m_elapsedTacts = m_playPos[Mode_PlaySong].getTact(); - m_elapsedTicks = ( m_playPos[Mode_PlaySong].getTicks() % ticksPerTact() ) / 48; + m_elapsedBars = m_playPos[Mode_PlaySong].getBar(); + m_elapsedTicks = ( m_playPos[Mode_PlaySong].getTicks() % ticksPerBar() ) / 48; } } @@ -619,7 +619,7 @@ void Song::updateLength() continue; } - const tact_t cur = ( *it )->length(); + const bar_t cur = ( *it )->length(); if( cur > m_length ) { m_length = cur; @@ -805,7 +805,7 @@ void Song::insertBar() for( TrackList::const_iterator it = tracks().begin(); it != tracks().end(); ++it ) { - ( *it )->insertTact( m_playPos[Mode_PlaySong] ); + ( *it )->insertBar( m_playPos[Mode_PlaySong] ); } m_tracksMutex.unlock(); } @@ -819,7 +819,7 @@ void Song::removeBar() for( TrackList::const_iterator it = tracks().begin(); it != tracks().end(); ++it ) { - ( *it )->removeTact( m_playPos[Mode_PlaySong] ); + ( *it )->removeBar( m_playPos[Mode_PlaySong] ); } m_tracksMutex.unlock(); } diff --git a/src/core/Track.cpp b/src/core/Track.cpp index fe66ab4a5..dedfcbc27 100644 --- a/src/core/Track.cpp +++ b/src/core/Track.cpp @@ -489,8 +489,8 @@ void TrackContentObjectView::updateLength() else { setFixedWidth( - static_cast( m_tco->length() * pixelsPerTact() / - MidiTime::ticksPerTact() ) + 1 /*+ + static_cast( m_tco->length() * pixelsPerBar() / + MidiTime::ticksPerBar() ) + 1 /*+ TCO_BORDER_WIDTH * 2-1*/ ); } m_trackView->trackContainerView()->update(); @@ -528,6 +528,7 @@ void TrackContentObjectView::dragEnterEvent( QDragEnterEvent * dee ) { TrackContentWidget * tcw = getTrackView()->getTrackContentWidget(); MidiTime tcoPos = MidiTime( m_tco->startPosition() ); + if( tcw->canPasteSelection( tcoPos, dee ) == false ) { dee->ignore(); @@ -567,6 +568,7 @@ void TrackContentObjectView::dropEvent( QDropEvent * de ) { TrackContentWidget * tcw = getTrackView()->getTrackContentWidget(); MidiTime tcoPos = MidiTime( m_tco->startPosition() ); + if( tcw->pasteSelection( tcoPos, de ) == true ) { de->accept(); @@ -656,7 +658,7 @@ DataFile TrackContentObjectView::createTCODataFiles( // initialTrackIndex is the index of the track that was touched metadata.setAttribute( "initialTrackIndex", initialTrackIndex ); metadata.setAttribute( "trackContainerId", tc->id() ); - // grabbedTCOPos is the pos of the tact containing the TCO we grabbed + // grabbedTCOPos is the pos of the bar containing the TCO we grabbed metadata.setAttribute( "grabbedTCOPos", m_tco->startPosition() ); dataFile.content().appendChild( metadata ); @@ -770,23 +772,23 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) { s_textFloat->setTitle( tr( "Current position" ) ); s_textFloat->setText( QString( "%1:%2" ). - arg( m_tco->startPosition().getTact() + 1 ). + arg( m_tco->startPosition().getBar() + 1 ). arg( m_tco->startPosition().getTicks() % - MidiTime::ticksPerTact() ) ); + MidiTime::ticksPerBar() ) ); } else if( m_action == Resize || m_action == ResizeLeft ) { s_textFloat->setTitle( tr( "Current length" ) ); s_textFloat->setText( tr( "%1:%2 (%3:%4 to %5:%6)" ). - arg( m_tco->length().getTact() ). + arg( m_tco->length().getBar() ). arg( m_tco->length().getTicks() % - MidiTime::ticksPerTact() ). - arg( m_tco->startPosition().getTact() + 1 ). + MidiTime::ticksPerBar() ). + arg( m_tco->startPosition().getBar() + 1 ). arg( m_tco->startPosition().getTicks() % - MidiTime::ticksPerTact() ). - arg( m_tco->endPosition().getTact() + 1 ). + MidiTime::ticksPerBar() ). + arg( m_tco->endPosition().getBar() + 1 ). arg( m_tco->endPosition().getTicks() % - MidiTime::ticksPerTact() ) ); + MidiTime::ticksPerBar() ) ); } // s_textFloat->reparent( this ); // setup text-float as if TCO was already moved/resized @@ -893,7 +895,7 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) m_hint = NULL; } - const float ppt = m_trackView->trackContainerView()->pixelsPerTact(); + const float ppb = m_trackView->trackContainerView()->pixelsPerBar(); if( m_action == Move ) { MidiTime newPos = draggedTCOPos( me ); @@ -903,9 +905,9 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) m_tco->movePosition( newPos ); m_trackView->getTrackContentWidget()->changePosition(); s_textFloat->setText( QString( "%1:%2" ). - arg( newPos.getTact() + 1 ). + arg( newPos.getBar() + 1 ). arg( newPos.getTicks() % - MidiTime::ticksPerTact() ) ); + MidiTime::ticksPerBar() ) ); s_textFloat->moveGlobal( this, QPoint( width() + 2, height() + 2 ) ); } else if( m_action == MoveSelection ) @@ -945,12 +947,12 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) const bool unquantized = (me->modifiers() & Qt::ControlModifier) || (me->modifiers() & Qt::AltModifier); const float snapSize = gui->songEditor()->m_editor->getSnapSize(); // Length in ticks of one snap increment - const MidiTime snapLength = MidiTime( (int)(snapSize * MidiTime::ticksPerTact()) ); + const MidiTime snapLength = MidiTime( (int)(snapSize * MidiTime::ticksPerBar()) ); if( m_action == Resize ) { // The clip's new length - MidiTime l = static_cast( me->x() * MidiTime::ticksPerTact() / ppt ); + MidiTime l = static_cast( me->x() * MidiTime::ticksPerBar() / ppb ); if ( unquantized ) { // We want to preserve this adjusted offset, @@ -985,8 +987,8 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) const int x = mapToParent( me->pos() ).x() - m_initialMousePos.x(); MidiTime t = qMax( 0, (int) - m_trackView->trackContainerView()->currentPosition()+ - static_cast( x * MidiTime::ticksPerTact() / ppt ) ); + m_trackView->trackContainerView()->currentPosition() + + static_cast( x * MidiTime::ticksPerBar() / ppb ) ); if( unquantized ) { // We want to preserve this adjusted offset, @@ -1023,15 +1025,15 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) } } s_textFloat->setText( tr( "%1:%2 (%3:%4 to %5:%6)" ). - arg( m_tco->length().getTact() ). + arg( m_tco->length().getBar() ). arg( m_tco->length().getTicks() % - MidiTime::ticksPerTact() ). - arg( m_tco->startPosition().getTact() + 1 ). + MidiTime::ticksPerBar() ). + arg( m_tco->startPosition().getBar() + 1 ). arg( m_tco->startPosition().getTicks() % - MidiTime::ticksPerTact() ). - arg( m_tco->endPosition().getTact() + 1 ). + MidiTime::ticksPerBar() ). + arg( m_tco->endPosition().getBar() + 1 ). arg( m_tco->endPosition().getTicks() % - MidiTime::ticksPerTact() ) ); + MidiTime::ticksPerBar() ) ); s_textFloat->moveGlobal( this, QPoint( width() + 2, height() + 2) ); } else @@ -1127,13 +1129,13 @@ void TrackContentObjectView::contextMenuEvent( QContextMenuEvent * cme ) -/*! \brief How many pixels a tact (bar) takes for this trackContentObjectView. +/*! \brief How many pixels a bar takes for this trackContentObjectView. * - * \return the number of pixels per tact (bar). + * \return the number of pixels per bar. */ -float TrackContentObjectView::pixelsPerTact() +float TrackContentObjectView::pixelsPerBar() { - return m_trackView->trackContainerView()->pixelsPerTact(); + return m_trackView->trackContainerView()->pixelsPerBar(); } @@ -1181,11 +1183,11 @@ bool TrackContentObjectView::mouseMovedDistance( QMouseEvent * me, int distance */ MidiTime TrackContentObjectView::draggedTCOPos( QMouseEvent * me ) { - //Pixels per tact - const float ppt = m_trackView->trackContainerView()->pixelsPerTact(); + //Pixels per bar + const float ppb = m_trackView->trackContainerView()->pixelsPerBar(); // The pixel distance that the mouse has moved const int mouseOff = mapToGlobal(me->pos()).x() - m_initialMouseGlobalPos.x(); - MidiTime newPos = m_initialTCOPos + mouseOff * MidiTime::ticksPerTact() / ppt; + MidiTime newPos = m_initialTCOPos + mouseOff * MidiTime::ticksPerBar() / ppb; MidiTime offset = newPos - m_initialTCOPos; // If the user is holding alt, or pressed ctrl after beginning the drag, don't quantize if ( me->button() != Qt::NoButton @@ -1264,13 +1266,13 @@ TrackContentWidget::~TrackContentWidget() void TrackContentWidget::updateBackground() { - const int tactsPerBar = 4; const TrackContainerView * tcv = m_trackView->trackContainerView(); - // Assume even-pixels-per-tact. Makes sense, should be like this anyways - int ppt = static_cast( tcv->pixelsPerTact() ); + // Assume even-pixels-per-bar. Makes sense, should be like this anyways + int ppb = static_cast( tcv->pixelsPerBar() ); - int w = ppt * tactsPerBar; + // alternate between a darker and a lighter color every 4 bars + int w = ppb * 4; int h = height(); m_background = QPixmap( w * 2, height() ); QPainter pmp( &m_background ); @@ -1281,13 +1283,13 @@ void TrackContentWidget::updateBackground() // draw lines // vertical lines pmp.setPen( QPen( gridColor(), 1 ) ); - for( float x = 0; x < w * 2; x += ppt ) + for( float x = 0; x < w * 2; x += ppb ) { pmp.drawLine( QLineF( x, 0.0, x, h ) ); } pmp.setPen( QPen( embossColor(), 1 ) ); - for( float x = 1.0; x < w * 2; x += ppt ) + for( float x = 1.0; x < w * 2; x += ppb ) { pmp.drawLine( QLineF( x, 0.0, x, h ) ); } @@ -1382,7 +1384,7 @@ void TrackContentWidget::changePosition( const MidiTime & newPos ) it != m_tcoViews.end(); ++it ) { if( ( *it )->getTrackContentObject()-> - startPosition().getTact() == curBB ) + startPosition().getBar() == curBB ) { ( *it )->move( 0, ( *it )->y() ); ( *it )->raise(); @@ -1398,7 +1400,7 @@ void TrackContentWidget::changePosition( const MidiTime & newPos ) it != m_tcoViews.end(); ++it ) { if( ( *it )->getTrackContentObject()-> - startPosition().getTact() != curBB ) + startPosition().getBar() != curBB ) { ( *it )->hide(); } @@ -1415,7 +1417,7 @@ void TrackContentWidget::changePosition( const MidiTime & newPos ) const int begin = pos; const int end = endPosition( pos ); - const float ppt = m_trackView->trackContainerView()->pixelsPerTact(); + const float ppb = m_trackView->trackContainerView()->pixelsPerBar(); setUpdatesEnabled( false ); for( tcoViewVector::iterator it = m_tcoViews.begin(); @@ -1432,8 +1434,8 @@ void TrackContentWidget::changePosition( const MidiTime & newPos ) ( te >= begin && te <= end ) || ( ts <= begin && te >= end ) ) { - tcov->move( static_cast( ( ts - begin ) * ppt / - MidiTime::ticksPerTact() ), + tcov->move( static_cast( ( ts - begin ) * ppb / + MidiTime::ticksPerBar() ), tcov->y() ); if( !tcov->isVisible() ) { @@ -1454,7 +1456,7 @@ void TrackContentWidget::changePosition( const MidiTime & newPos ) -/*! \brief Return the position of the trackContentWidget in Tacts. +/*! \brief Return the position of the trackContentWidget in bars. * * \param mouseX the mouse's current X position in pixels. */ @@ -1463,8 +1465,8 @@ MidiTime TrackContentWidget::getPosition( int mouseX ) TrackContainerView * tv = m_trackView->trackContainerView(); return MidiTime( tv->currentPosition() + mouseX * - MidiTime::ticksPerTact() / - static_cast( tv->pixelsPerTact() ) ); + MidiTime::ticksPerBar() / + static_cast( tv->pixelsPerBar() ) ); } @@ -1477,7 +1479,7 @@ MidiTime TrackContentWidget::getPosition( int mouseX ) void TrackContentWidget::dragEnterEvent( QDragEnterEvent * dee ) { MidiTime tcoPos = getPosition( dee->pos().x() ); - if( canPasteSelection( tcoPos, dee ) == false ) + if( canPasteSelection( tcoPos, dee ) == false ) { dee->ignore(); } @@ -1518,7 +1520,7 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QDropEvent* d QDomElement metadata = dataFile.content().firstChildElement( "copyMetadata" ); QDomAttr tcoPosAttr = metadata.attributeNode( "grabbedTCOPos" ); MidiTime grabbedTCOPos = tcoPosAttr.value().toInt(); - MidiTime grabbedTCOTact = MidiTime( grabbedTCOPos.getTact(), 0 ); + MidiTime grabbedTCOBar = MidiTime( grabbedTCOPos.getBar(), 0 ); // Extract the track index that was originally clicked QDomAttr tiAttr = metadata.attributeNode( "initialTrackIndex" ); @@ -1528,10 +1530,10 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QDropEvent* d const TrackContainer::TrackList tracks = t->trackContainer()->tracks(); const int currentTrackIndex = tracks.indexOf( t ); - // Don't paste if we're on the same tact + // Don't paste if we're on the same bar auto sourceTrackContainerId = metadata.attributeNode( "trackContainerId" ).value().toUInt(); if( de->source() && sourceTrackContainerId == t->trackContainer()->id() && - tcoPos == grabbedTCOTact && currentTrackIndex == initialTrackIndex ) + tcoPos == grabbedTCOBar && currentTrackIndex == initialTrackIndex ) { return false; } @@ -1596,7 +1598,7 @@ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * de ) QDomAttr tcoPosAttr = metadata.attributeNode( "grabbedTCOPos" ); MidiTime grabbedTCOPos = tcoPosAttr.value().toInt(); - // Snap the mouse position to the beginning of the dropped tact, in ticks + // Snap the mouse position to the beginning of the dropped bar, in ticks const TrackContainer::TrackList tracks = getTrack()->trackContainer()->tracks(); const int currentTrackIndex = tracks.indexOf( getTrack() ); @@ -1631,7 +1633,7 @@ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * de ) // The new position is the old position plus the offset. MidiTime pos = tcoElement.attributeNode( "pos" ).value().toInt() + offset; // If we land on ourselves, offset by one snap - MidiTime shift = MidiTime::ticksPerTact() * gui->songEditor()->m_editor->getSnapSize(); + MidiTime shift = MidiTime::ticksPerBar() * gui->songEditor()->m_editor->getSnapSize(); if (offset == 0) { pos += shift; } TrackContentObject * tco = t->createTCO( pos ); @@ -1695,8 +1697,8 @@ void TrackContentWidget::mousePressEvent( QMouseEvent * me ) so.at( i )->setSelected( false); } getTrack()->addJournalCheckPoint(); - const MidiTime pos = getPosition( me->x() ).getTact() * - MidiTime::ticksPerTact(); + const MidiTime pos = getPosition( me->x() ).getBar() * + MidiTime::ticksPerBar(); TrackContentObject * tco = getTrack()->createTCO( pos ); tco->saveJournallingState( false ); @@ -1714,15 +1716,15 @@ void TrackContentWidget::mousePressEvent( QMouseEvent * me ) */ void TrackContentWidget::paintEvent( QPaintEvent * pe ) { - // Assume even-pixels-per-tact. Makes sense, should be like this anyways + // Assume even-pixels-per-bar. Makes sense, should be like this anyways const TrackContainerView * tcv = m_trackView->trackContainerView(); - int ppt = static_cast( tcv->pixelsPerTact() ); + int ppb = static_cast( tcv->pixelsPerBar() ); QPainter p( this ); // Don't draw background on BB-Editor if( m_trackView->trackContainerView() != gui->getBBEditor()->trackContainerView() ) { p.drawTiledPixmap( rect(), m_background, QPoint( - tcv->currentPosition().getTact() * ppt, 0 ) ); + tcv->currentPosition().getBar() * ppb, 0 ) ); } } @@ -1755,15 +1757,15 @@ Track * TrackContentWidget::getTrack() -/*! \brief Return the end position of the trackContentWidget in Tacts. +/*! \brief Return the end position of the trackContentWidget in Bars. * * \param posStart the starting position of the Widget (from getPosition()) */ MidiTime TrackContentWidget::endPosition( const MidiTime & posStart ) { - const float ppt = m_trackView->trackContainerView()->pixelsPerTact(); + const float ppb = m_trackView->trackContainerView()->pixelsPerBar(); const int w = width(); - return posStart + static_cast( w * MidiTime::ticksPerTact() / ppt ); + return posStart + static_cast( w * MidiTime::ticksPerBar() / ppb ); } @@ -2417,7 +2419,7 @@ TrackContentObject * Track::getTCO( int tcoNum ) } printf( "called Track::getTCO( %d ), " "but TCO %d doesn't exist\n", tcoNum, tcoNum ); - return createTCO( tcoNum * MidiTime::ticksPerTact() ); + return createTCO( tcoNum * MidiTime::ticksPerBar() ); } @@ -2525,17 +2527,17 @@ void Track::createTCOsForBB( int bb ) * in ascending order by TCO time, once we hit a TCO that was earlier * than the insert time, we could fall out of the loop early. */ -void Track::insertTact( const MidiTime & pos ) +void Track::insertBar( const MidiTime & pos ) { // we'll increase the position of every TCO, positioned behind pos, by - // one tact + // one bar for( tcoVector::iterator it = m_trackContentObjects.begin(); it != m_trackContentObjects.end(); ++it ) { if( ( *it )->startPosition() >= pos ) { ( *it )->movePosition( (*it)->startPosition() + - MidiTime::ticksPerTact() ); + MidiTime::ticksPerBar() ); } } } @@ -2547,17 +2549,17 @@ void Track::insertTact( const MidiTime & pos ) * * \param pos The time at which we want to remove the bar. */ -void Track::removeTact( const MidiTime & pos ) +void Track::removeBar( const MidiTime & pos ) { // we'll decrease the position of every TCO, positioned behind pos, by - // one tact + // one bar for( tcoVector::iterator it = m_trackContentObjects.begin(); it != m_trackContentObjects.end(); ++it ) { if( ( *it )->startPosition() >= pos ) { ( *it )->movePosition( qMax( ( *it )->startPosition() - - MidiTime::ticksPerTact(), 0 ) ); + MidiTime::ticksPerBar(), 0 ) ); } } } @@ -2571,7 +2573,7 @@ void Track::removeTact( const MidiTime & pos ) * keeping track of the latest time found in ticks. Then we return * that in bars by dividing by the number of ticks per bar. */ -tact_t Track::length() const +bar_t Track::length() const { // find last end-position tick_t last = 0; @@ -2591,7 +2593,7 @@ tact_t Track::length() const } } - return last / MidiTime::ticksPerTact(); + return last / MidiTime::ticksPerBar(); } diff --git a/src/core/TrackContainer.cpp b/src/core/TrackContainer.cpp index edea9aa14..95dd46f29 100644 --- a/src/core/TrackContainer.cpp +++ b/src/core/TrackContainer.cpp @@ -313,7 +313,7 @@ AutomatedValueMap TrackContainer::automatedValuesFromTracks(const TrackList &tra MidiTime bbTime = time - tco->startPosition(); bbTime = std::min(bbTime, tco->length()); - bbTime = bbTime % (bbContainer->lengthOfBB(bbIndex) * MidiTime::ticksPerTact()); + bbTime = bbTime % (bbContainer->lengthOfBB(bbIndex) * MidiTime::ticksPerBar()); auto bbValues = bbContainer->automatedValuesAt(bbTime, bbIndex); for (auto it=bbValues.begin(); it != bbValues.end(); it++) @@ -344,8 +344,3 @@ DummyTrackContainer::DummyTrackContainer() : m_dummyInstrumentTrack->setJournalling( false ); } - - - - - diff --git a/src/core/midi/MidiTime.cpp b/src/core/midi/MidiTime.cpp index 82ed642ba..4e718a1d8 100644 --- a/src/core/midi/MidiTime.cpp +++ b/src/core/midi/MidiTime.cpp @@ -53,8 +53,8 @@ int TimeSig::denominator() const -MidiTime::MidiTime( const tact_t tact, const tick_t ticks ) : - m_ticks( tact * s_ticksPerTact + ticks ) +MidiTime::MidiTime( const bar_t bar, const tick_t ticks ) : + m_ticks( bar * s_ticksPerBar + ticks ) { } @@ -66,7 +66,7 @@ MidiTime::MidiTime( const tick_t ticks ) : MidiTime MidiTime::quantize(float bars) const { //The intervals we should snap to, our new position should be a factor of this - int interval = s_ticksPerTact * bars; + int interval = s_ticksPerBar * bars; //The lower position we could snap to int lowPos = m_ticks / interval; //Offset from the lower position @@ -78,9 +78,9 @@ MidiTime MidiTime::quantize(float bars) const } -MidiTime MidiTime::toAbsoluteTact() const +MidiTime MidiTime::toAbsoluteBar() const { - return getTact() * s_ticksPerTact; + return getBar() * s_ticksPerBar; } @@ -98,15 +98,15 @@ MidiTime& MidiTime::operator-=( const MidiTime& time ) } -tact_t MidiTime::getTact() const +bar_t MidiTime::getBar() const { - return m_ticks / s_ticksPerTact; + return m_ticks / s_ticksPerBar; } -tact_t MidiTime::nextFullTact() const +bar_t MidiTime::nextFullBar() const { - return (m_ticks + (s_ticksPerTact-1)) / s_ticksPerTact; + return ( m_ticks + ( s_ticksPerBar - 1 ) ) / s_ticksPerBar; } @@ -131,23 +131,23 @@ MidiTime::operator int() const tick_t MidiTime::ticksPerBeat( const TimeSig &sig ) const { // (number of ticks per bar) divided by (number of beats per bar) - return ticksPerTact(sig) / sig.numerator(); + return ticksPerBar(sig) / sig.numerator(); } tick_t MidiTime::getTickWithinBar( const TimeSig &sig ) const { - return m_ticks % ticksPerTact(sig); + return m_ticks % ticksPerBar( sig ); } tick_t MidiTime::getBeatWithinBar( const TimeSig &sig ) const { - return getTickWithinBar(sig) / ticksPerBeat(sig); + return getTickWithinBar( sig ) / ticksPerBeat( sig ); } tick_t MidiTime::getTickWithinBeat( const TimeSig &sig ) const { - return getTickWithinBar(sig) % ticksPerBeat(sig); + return getTickWithinBar( sig ) % ticksPerBeat( sig ); } @@ -160,9 +160,9 @@ f_cnt_t MidiTime::frames( const float framesPerTick ) const return 0; } -double MidiTime::getTimeInMilliseconds(bpm_t beatsPerMinute) const +double MidiTime::getTimeInMilliseconds( bpm_t beatsPerMinute ) const { - return ticksToMilliseconds(getTicks(), beatsPerMinute); + return ticksToMilliseconds( getTicks(), beatsPerMinute ); } MidiTime MidiTime::fromFrames( const f_cnt_t frames, const float framesPerTick ) @@ -171,39 +171,39 @@ MidiTime MidiTime::fromFrames( const f_cnt_t frames, const float framesPerTick ) } -tick_t MidiTime::ticksPerTact() +tick_t MidiTime::ticksPerBar() { - return s_ticksPerTact; + return s_ticksPerBar; } -tick_t MidiTime::ticksPerTact( const TimeSig &sig ) +tick_t MidiTime::ticksPerBar( const TimeSig &sig ) { - return DefaultTicksPerTact * sig.numerator() / sig.denominator(); + return DefaultTicksPerBar * sig.numerator() / sig.denominator(); } -int MidiTime::stepsPerTact() +int MidiTime::stepsPerBar() { - int steps = ticksPerTact() / DefaultBeatsPerTact; + int steps = ticksPerBar() / DefaultBeatsPerBar; return qMax( 1, steps ); } -void MidiTime::setTicksPerTact( tick_t tpt ) +void MidiTime::setTicksPerBar( tick_t tpb ) { - s_ticksPerTact = tpt; + s_ticksPerBar = tpb; } MidiTime MidiTime::stepPosition( int step ) { - return step * ticksPerTact() / stepsPerTact(); + return step * ticksPerBar() / stepsPerBar(); } -double MidiTime::ticksToMilliseconds(tick_t ticks, bpm_t beatsPerMinute) +double MidiTime::ticksToMilliseconds( tick_t ticks, bpm_t beatsPerMinute ) { - return MidiTime::ticksToMilliseconds(static_cast(ticks), beatsPerMinute); + return MidiTime::ticksToMilliseconds( static_cast(ticks), beatsPerMinute ); } double MidiTime::ticksToMilliseconds(double ticks, bpm_t beatsPerMinute) diff --git a/src/gui/AutomationPatternView.cpp b/src/gui/AutomationPatternView.cpp index a9033f37f..130d51a0e 100644 --- a/src/gui/AutomationPatternView.cpp +++ b/src/gui/AutomationPatternView.cpp @@ -278,10 +278,10 @@ void AutomationPatternView::paintEvent( QPaintEvent * ) p.fillRect( rect(), c ); } - const float ppt = fixedTCOs() ? + const float ppb = fixedTCOs() ? ( parentWidget()->width() - 2 * TCO_BORDER_WIDTH ) - / (float) m_pat->timeMapLength().getTact() : - pixelsPerTact(); + / (float) m_pat->timeMapLength().getBar() : + pixelsPerBar(); const int x_base = TCO_BORDER_WIDTH; @@ -290,7 +290,7 @@ void AutomationPatternView::paintEvent( QPaintEvent * ) const float y_scale = max - min; const float h = ( height() - 2 * TCO_BORDER_WIDTH ) / y_scale; - const float ppTick = ppt / MidiTime::ticksPerTact(); + const float ppTick = ppb / MidiTime::ticksPerBar(); p.translate( 0.0f, max * height() / y_scale - TCO_BORDER_WIDTH ); p.scale( 1.0f, -h ); @@ -372,9 +372,9 @@ void AutomationPatternView::paintEvent( QPaintEvent * ) const int lineSize = 3; p.setPen( c.darker( 300 ) ); - for( tact_t t = 1; t < width() - TCO_BORDER_WIDTH; ++t ) + for( bar_t t = 1; t < width() - TCO_BORDER_WIDTH; ++t ) { - const int tx = x_base + static_cast( ppt * t ) - 2; + const int tx = x_base + static_cast( ppb * t ) - 2; p.drawLine( tx, TCO_BORDER_WIDTH, tx, TCO_BORDER_WIDTH + lineSize ); p.drawLine( tx, rect().bottom() - ( lineSize + TCO_BORDER_WIDTH ), tx, rect().bottom() - TCO_BORDER_WIDTH ); diff --git a/src/gui/TimeLineWidget.cpp b/src/gui/TimeLineWidget.cpp index dfa7e388f..bd196de7f 100644 --- a/src/gui/TimeLineWidget.cpp +++ b/src/gui/TimeLineWidget.cpp @@ -42,7 +42,7 @@ QPixmap * TimeLineWidget::s_posMarkerPixmap = NULL; -TimeLineWidget::TimeLineWidget( const int xoff, const int yoff, const float ppt, +TimeLineWidget::TimeLineWidget( const int xoff, const int yoff, const float ppb, Song::PlayPos & pos, const MidiTime & begin, Song::PlayModes mode, QWidget * parent ) : QWidget( parent ), @@ -61,7 +61,7 @@ TimeLineWidget::TimeLineWidget( const int xoff, const int yoff, const float ppt, m_changedPosition( true ), m_xOffset( xoff ), m_posMarkerX( 0 ), - m_ppt( ppt ), + m_ppb( ppb ), m_pos( pos ), m_begin( begin ), m_mode( mode ), @@ -71,7 +71,7 @@ TimeLineWidget::TimeLineWidget( const int xoff, const int yoff, const float ppt, m_moveXOff( 0 ) { m_loopPos[0] = 0; - m_loopPos[1] = DefaultTicksPerTact; + m_loopPos[1] = DefaultTicksPerBar; if( s_posMarkerPixmap == NULL ) { @@ -247,18 +247,18 @@ void TimeLineWidget::paintEvent( QPaintEvent * ) QColor const & barLineColor = getBarLineColor(); QColor const & barNumberColor = getBarNumberColor(); - tact_t barNumber = m_begin.getTact(); + bar_t barNumber = m_begin.getBar(); int const x = m_xOffset + s_posMarkerPixmap->width() / 2 - - ( ( static_cast( m_begin * m_ppt ) / MidiTime::ticksPerTact() ) % static_cast( m_ppt ) ); + ( ( static_cast( m_begin * m_ppb ) / MidiTime::ticksPerBar() ) % static_cast( m_ppb ) ); - for( int i = 0; x + i * m_ppt < width(); ++i ) + for( int i = 0; x + i * m_ppb < width(); ++i ) { ++barNumber; if( ( barNumber - 1 ) % qMax( 1, qRound( 1.0f / 3.0f * - MidiTime::ticksPerTact() / m_ppt ) ) == 0 ) + MidiTime::ticksPerBar() / m_ppb ) ) == 0 ) { - const int cx = x + qRound( i * m_ppt ); + const int cx = x + qRound( i * m_ppb ); p.setPen( barLineColor ); p.drawLine( cx, 5, cx, height() - 6 ); @@ -313,7 +313,7 @@ void TimeLineWidget::mousePressEvent( QMouseEvent* event ) else if( event->button() == Qt::RightButton ) { m_moveXOff = s_posMarkerPixmap->width() / 2; - const MidiTime t = m_begin + static_cast( qMax( event->x() - m_xOffset - m_moveXOff, 0 ) * MidiTime::ticksPerTact() / m_ppt ); + const MidiTime t = m_begin + static_cast( qMax( event->x() - m_xOffset - m_moveXOff, 0 ) * MidiTime::ticksPerBar() / m_ppb ); const MidiTime loopMid = ( m_loopPos[0] + m_loopPos[1] ) / 2; if( t < loopMid ) @@ -349,7 +349,7 @@ void TimeLineWidget::mousePressEvent( QMouseEvent* event ) void TimeLineWidget::mouseMoveEvent( QMouseEvent* event ) { parentWidget()->update(); // essential for widgets that this timeline had taken their mouse move event from. - const MidiTime t = m_begin + static_cast( qMax( event->x() - m_xOffset - m_moveXOff, 0 ) * MidiTime::ticksPerTact() / m_ppt ); + const MidiTime t = m_begin + static_cast( qMax( event->x() - m_xOffset - m_moveXOff, 0 ) * MidiTime::ticksPerBar() / m_ppb ); switch( m_action ) { @@ -387,10 +387,14 @@ void TimeLineWidget::mouseMoveEvent( QMouseEvent* event ) { // Note, swap 1 and 0 below and the behavior "skips" the other // marking instead of pushing it. - if( m_action == MoveLoopBegin ) - m_loopPos[0] -= MidiTime::ticksPerTact(); + if( m_action == MoveLoopBegin ) + { + m_loopPos[0] -= MidiTime::ticksPerBar(); + } else - m_loopPos[1] += MidiTime::ticksPerTact(); + { + m_loopPos[1] += MidiTime::ticksPerBar(); + } } update(); break; diff --git a/src/gui/TrackContainerView.cpp b/src/gui/TrackContainerView.cpp index bc3205730..9b51c76f2 100644 --- a/src/gui/TrackContainerView.cpp +++ b/src/gui/TrackContainerView.cpp @@ -54,7 +54,7 @@ TrackContainerView::TrackContainerView( TrackContainer * _tc ) : m_tc( _tc ), m_trackViews(), m_scrollArea( new scrollArea( this ) ), - m_ppt( DEFAULT_PIXELS_PER_TACT ), + m_ppb( DEFAULT_PIXELS_PER_BAR ), m_rubberBand( new RubberBand( m_scrollArea ) ) { m_tc->setHook( this ); @@ -305,9 +305,9 @@ bool TrackContainerView::allowRubberband() const -void TrackContainerView::setPixelsPerTact( int _ppt ) +void TrackContainerView::setPixelsPerBar( int ppb ) { - m_ppt = _ppt; + m_ppb = ppb; // tell all TrackContentWidgets to update their background tile pixmap for( trackViewList::Iterator it = m_trackViews.begin(); diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index bb00a1bd1..bf56e3039 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -92,7 +92,7 @@ AutomationEditor::AutomationEditor() : m_moveStartTick( 0 ), m_drawLastLevel( 0.0f ), m_drawLastTick( 0 ), - m_ppt( DEFAULT_PPT ), + m_ppb( DEFAULT_PPB ), m_y_delta( DEFAULT_Y_DELTA ), m_y_auto( true ), m_editMode( DRAW ), @@ -149,7 +149,7 @@ AutomationEditor::AutomationEditor() : } // add time-line - m_timeLine = new TimeLineWidget( VALUES_WIDTH, 0, m_ppt, + m_timeLine = new TimeLineWidget( VALUES_WIDTH, 0, m_ppb, Engine::getSong()->getPlayPos( Song::Mode_PlayAutomationPattern ), m_currentPosition, @@ -514,7 +514,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) x -= VALUES_WIDTH; // get tick in which the user clicked - int pos_ticks = x * MidiTime::ticksPerTact() / m_ppt + + int pos_ticks = x * MidiTime::ticksPerBar() / m_ppb + m_currentPosition; // get time map of current pattern @@ -531,7 +531,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) if( pos_ticks >= it.key() && ( it+1==time_map.end() || pos_ticks <= (it+1).key() ) && - ( pos_ticks<= it.key() + MidiTime::ticksPerTact() *4 / m_ppt ) && + ( pos_ticks<= it.key() + MidiTime::ticksPerBar() *4 / m_ppb ) && ( level == it.value() || mouseEvent->button() == Qt::RightButton ) ) { break; @@ -583,7 +583,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) int aligned_x = (int)( (float)( ( it.key() - m_currentPosition ) * - m_ppt ) / MidiTime::ticksPerTact() ); + m_ppb ) / MidiTime::ticksPerBar() ); m_moveXOffset = x - aligned_x - 1; // set move-cursor QCursor c( Qt::SizeAllCursor ); @@ -740,7 +740,7 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) x -= m_moveXOffset; } - int pos_ticks = x * MidiTime::ticksPerTact() / m_ppt + + int pos_ticks = x * MidiTime::ticksPerBar() / m_ppb + m_currentPosition; if( mouseEvent->buttons() & Qt::LeftButton && m_editMode == DRAW ) { @@ -872,7 +872,7 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) } // get tick in which the cursor is posated - int pos_ticks = x * MidiTime::ticksPerTact() / m_ppt + + int pos_ticks = x * MidiTime::ticksPerBar() / m_ppb + m_currentPosition; m_selectedTick = pos_ticks - m_selectStartTick; @@ -893,7 +893,7 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) // move selection + selected values // do horizontal move-stuff - int pos_ticks = x * MidiTime::ticksPerTact() / m_ppt + + int pos_ticks = x * MidiTime::ticksPerBar() / m_ppb + m_currentPosition; int ticks_diff = pos_ticks - m_moveStartTick; @@ -918,8 +918,8 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) } m_selectStartTick += ticks_diff; - int tact_diff = ticks_diff / MidiTime::ticksPerTact(); - ticks_diff = ticks_diff % MidiTime::ticksPerTact(); + int bar_diff = ticks_diff / MidiTime::ticksPerBar(); + ticks_diff = ticks_diff % MidiTime::ticksPerBar(); // do vertical move-stuff @@ -967,24 +967,24 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) MidiTime new_value_pos; if( it.key() ) { - int value_tact = + int value_bar = ( it.key() / - MidiTime::ticksPerTact() ) - + tact_diff; + MidiTime::ticksPerBar() ) + + bar_diff; int value_ticks = ( it.key() % - MidiTime::ticksPerTact() ) + MidiTime::ticksPerBar() ) + ticks_diff; // ensure value_ticks range - if( value_ticks / MidiTime::ticksPerTact() ) + if( value_ticks / MidiTime::ticksPerBar() ) { - value_tact += value_ticks - / MidiTime::ticksPerTact(); + value_bar += value_ticks + / MidiTime::ticksPerBar(); value_ticks %= - MidiTime::ticksPerTact(); + MidiTime::ticksPerBar(); } m_pattern->removeValue( it.key() ); - new_value_pos = MidiTime( value_tact, + new_value_pos = MidiTime( value_bar, value_ticks ); } new_selValuesForMove[ @@ -1032,7 +1032,7 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) } // get tick in which the cursor is posated - int pos_ticks = x * MidiTime::ticksPerTact() / m_ppt + + int pos_ticks = x * MidiTime::ticksPerBar() / m_ppb + m_currentPosition; m_selectedTick = pos_ticks - @@ -1116,7 +1116,7 @@ inline void AutomationEditor::drawAutomationPoint( QPainter & p, timeMap::iterat { int x = xCoordOfTick( it.key() ); int y = yCoordOfLevel( it.value() ); - const int outerRadius = qBound( 3, ( m_ppt * AutomationPattern::quantization() ) / 576, 5 ); // man, getting this calculation right took forever + const int outerRadius = qBound( 3, ( m_ppb * AutomationPattern::quantization() ) / 576, 5 ); // man, getting this calculation right took forever p.setPen( QPen( vertexColor().lighter( 200 ) ) ); p.setBrush( QBrush( vertexColor() ) ); p.drawEllipse( x - outerRadius, y - outerRadius, outerRadius * 2, outerRadius * 2 ); @@ -1288,20 +1288,20 @@ void AutomationEditor::paintEvent(QPaintEvent * pe ) / static_cast( Engine::getSong()->getTimeSigModel().getDenominator() ); float zoomFactor = m_zoomXLevels[m_zoomingXModel.value()]; //the bars which disappears at the left side by scrolling - int leftBars = m_currentPosition * zoomFactor / MidiTime::ticksPerTact(); + int leftBars = m_currentPosition * zoomFactor / MidiTime::ticksPerBar(); //iterates the visible bars and draw the shading on uneven bars - for( int x = VALUES_WIDTH, barCount = leftBars; x < width() + m_currentPosition * zoomFactor / timeSignature; x += m_ppt, ++barCount ) + for( int x = VALUES_WIDTH, barCount = leftBars; x < width() + m_currentPosition * zoomFactor / timeSignature; x += m_ppb, ++barCount ) { if( ( barCount + leftBars ) % 2 != 0 ) { - p.fillRect( x - m_currentPosition * zoomFactor / timeSignature, TOP_MARGIN, m_ppt, + p.fillRect( x - m_currentPosition * zoomFactor / timeSignature, TOP_MARGIN, m_ppb, height() - ( SCROLLBAR_SIZE + TOP_MARGIN ), backgroundShade() ); } } // Draw the beat grid - int ticksPerBeat = DefaultTicksPerTact / + int ticksPerBeat = DefaultTicksPerBar / Engine::getSong()->getTimeSigModel().getDenominator(); for( tick = m_currentPosition - m_currentPosition % ticksPerBeat, @@ -1314,10 +1314,10 @@ void AutomationEditor::paintEvent(QPaintEvent * pe ) } // and finally bars - for( tick = m_currentPosition - m_currentPosition % MidiTime::ticksPerTact(), + for( tick = m_currentPosition - m_currentPosition % MidiTime::ticksPerBar(), x = xCoordOfTick( tick ); x<=width(); - tick += MidiTime::ticksPerTact(), x = xCoordOfTick( tick ) ) + tick += MidiTime::ticksPerBar(), x = xCoordOfTick( tick ) ) { p.setPen( barLineColor() ); p.drawLine( x, grid_bottom, x, x_line_end ); @@ -1452,9 +1452,9 @@ void AutomationEditor::paintEvent(QPaintEvent * pe ) } // now draw selection-frame - int x = ( sel_pos_start - m_currentPosition ) * m_ppt / - MidiTime::ticksPerTact(); - int w = ( sel_pos_end - sel_pos_start ) * m_ppt / MidiTime::ticksPerTact(); + int x = ( sel_pos_start - m_currentPosition ) * m_ppb / + MidiTime::ticksPerBar(); + int w = ( sel_pos_end - sel_pos_start ) * m_ppb / MidiTime::ticksPerBar(); int y, h; if( m_y_auto ) { @@ -1526,7 +1526,7 @@ void AutomationEditor::paintEvent(QPaintEvent * pe ) int AutomationEditor::xCoordOfTick(int tick ) { return VALUES_WIDTH + ( ( tick - m_currentPosition ) - * m_ppt / MidiTime::ticksPerTact() ); + * m_ppb / MidiTime::ticksPerBar() ); } @@ -1687,11 +1687,11 @@ void AutomationEditor::wheelEvent(QWheelEvent * we ) } x = qBound( 0, x, m_zoomingXModel.size() - 1 ); - int mouseX = (we->x() - VALUES_WIDTH)* MidiTime::ticksPerTact(); + int mouseX = (we->x() - VALUES_WIDTH)* MidiTime::ticksPerBar(); // ticks based on the mouse x-position where the scroll wheel was used - int ticks = mouseX / m_ppt; + int ticks = mouseX / m_ppb; // what would be the ticks in the new zoom level on the very same mouse x - int newTicks = mouseX / (DEFAULT_PPT * m_zoomXLevels[x]); + int newTicks = mouseX / (DEFAULT_PPB * m_zoomXLevels[x]); // scroll so the tick "selected" by the mouse x doesn't move on the screen m_leftRightScroll->setValue(m_leftRightScroll->value() + ticks - newTicks); @@ -1958,7 +1958,7 @@ void AutomationEditor::getSelectedValues( timeMap & selected_values ) ++it ) { //TODO: Add constant - tick_t len_ticks = MidiTime::ticksPerTact() / 16; + tick_t len_ticks = MidiTime::ticksPerBar() / 16; float level = it.value(); tick_t pos_ticks = it.key(); @@ -2095,17 +2095,17 @@ void AutomationEditor::updatePosition(const MidiTime & t ) m_scrollBack == true ) { const int w = width() - VALUES_WIDTH; - if( t > m_currentPosition + w * MidiTime::ticksPerTact() / m_ppt ) + if( t > m_currentPosition + w * MidiTime::ticksPerBar() / m_ppb ) { - m_leftRightScroll->setValue( t.getTact() * - MidiTime::ticksPerTact() ); + m_leftRightScroll->setValue( t.getBar() * + MidiTime::ticksPerBar() ); } else if( t < m_currentPosition ) { - MidiTime t_ = qMax( t - w * MidiTime::ticksPerTact() * - MidiTime::ticksPerTact() / m_ppt, 0 ); - m_leftRightScroll->setValue( t_.getTact() * - MidiTime::ticksPerTact() ); + MidiTime t_ = qMax( t - w * MidiTime::ticksPerBar() * + MidiTime::ticksPerBar() / m_ppb, 0 ); + m_leftRightScroll->setValue( t_.getBar() * + MidiTime::ticksPerBar() ); } m_scrollBack = false; } @@ -2116,11 +2116,11 @@ void AutomationEditor::updatePosition(const MidiTime & t ) void AutomationEditor::zoomingXChanged() { - m_ppt = m_zoomXLevels[m_zoomingXModel.value()] * DEFAULT_PPT; + m_ppb = m_zoomXLevels[m_zoomingXModel.value()] * DEFAULT_PPB; - assert( m_ppt > 0 ); + assert( m_ppb > 0 ); - m_timeLine->setPixelsPerTact( m_ppt ); + m_timeLine->setPixelsPerBar( m_ppb ); update(); } @@ -2159,9 +2159,9 @@ void AutomationEditor::setQuantization() } else { - quantization = DefaultTicksPerTact; + quantization = DefaultTicksPerBar; } - quantization = DefaultTicksPerTact / quantization; + quantization = DefaultTicksPerBar / quantization; AutomationPattern::setQuantization( quantization ); update(); diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 5d11088f3..183735450 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -139,7 +139,7 @@ PianoRoll::PianoRollKeyTypes PianoRoll::prKeyOrder[] = } ; -const int DEFAULT_PR_PPT = KEY_LINE_HEIGHT * DefaultStepsPerTact; +const int DEFAULT_PR_PPB = KEY_LINE_HEIGHT * DefaultStepsPerBar; const QVector PianoRoll::m_zoomLevels = { 0.125f, 0.25f, 0.5f, 1.0f, 2.0f, 4.0f, 8.0f }; @@ -168,8 +168,8 @@ PianoRoll::PianoRoll() : m_lastMouseY( 0 ), m_oldNotesEditHeight( 100 ), m_notesEditHeight( 100 ), - m_ppt( DEFAULT_PR_PPT ), - m_lenOfNewNotes( MidiTime( 0, DefaultTicksPerTact/4 ) ), + m_ppb( DEFAULT_PR_PPB ), + m_lenOfNewNotes( MidiTime( 0, DefaultTicksPerBar/4 ) ), m_lastNoteVolume( DefaultVolume ), m_lastNotePanning( DefaultPanning ), m_startKey( INITIAL_START_KEY ), @@ -178,7 +178,7 @@ PianoRoll::PianoRoll() : m_ctrlMode( ModeDraw ), m_mouseDownRight( false ), m_scrollBack( false ), - m_stepRecorderWidget(this, DEFAULT_PR_PPT, PR_TOP_MARGIN, PR_BOTTOM_MARGIN + m_notesEditHeight, WHITE_KEY_WIDTH, 0), + m_stepRecorderWidget(this, DEFAULT_PR_PPB, PR_TOP_MARGIN, PR_BOTTOM_MARGIN + m_notesEditHeight, WHITE_KEY_WIDTH, 0), m_stepRecorder(*this, m_stepRecorderWidget), m_barLineColor( 0, 0, 0 ), m_beatLineColor( 0, 0, 0 ), @@ -302,7 +302,7 @@ PianoRoll::PianoRoll() : setAttribute( Qt::WA_OpaquePaintEvent, true ); // add time-line - m_timeLine = new TimeLineWidget( WHITE_KEY_WIDTH, 0, m_ppt, + m_timeLine = new TimeLineWidget( WHITE_KEY_WIDTH, 0, m_ppb, Engine::getSong()->getPlayPos( Song::Mode_PlayPattern ), m_currentPosition, @@ -759,28 +759,28 @@ void PianoRoll::selectRegionFromPixels( int xStart, int xEnd ) xEnd -= WHITE_KEY_WIDTH; // select an area of notes - int pos_ticks = xStart * MidiTime::ticksPerTact() / m_ppt + + int posTicks = xStart * MidiTime::ticksPerBar() / m_ppb + m_currentPosition; - int key_num = 0; - m_selectStartTick = pos_ticks; + int keyNum = 0; + m_selectStartTick = posTicks; m_selectedTick = 0; - m_selectStartKey = key_num; + m_selectStartKey = keyNum; m_selectedKeys = 1; // change size of selection // get tick in which the cursor is posated - pos_ticks = xEnd * MidiTime::ticksPerTact() / m_ppt + + posTicks = xEnd * MidiTime::ticksPerBar() / m_ppb + m_currentPosition; - key_num = 120; + keyNum = 120; - m_selectedTick = pos_ticks - m_selectStartTick; + m_selectedTick = posTicks - m_selectStartTick; if( (int) m_selectStartTick + m_selectedTick < 0 ) { m_selectedTick = -static_cast( m_selectStartTick ); } - m_selectedKeys = key_num - m_selectStartKey; - if( key_num <= m_selectStartKey ) + m_selectedKeys = keyNum - m_selectStartKey; + if( keyNum <= m_selectStartKey ) { --m_selectedKeys; } @@ -1033,7 +1033,7 @@ void PianoRoll::drawDetuningInfo( QPainter & _p, const Note * _n, int _x, for( timeMap::ConstIterator it = map.begin(); it != map.end(); ++it ) { int pos_ticks = it.key(); - int pos_x = _x + pos_ticks * m_ppt / MidiTime::ticksPerTact(); + int pos_x = _x + pos_ticks * m_ppb / MidiTime::ticksPerBar(); const float level = it.value(); @@ -1268,7 +1268,7 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke) // Move selected notes by one bar to the left if (hasValidPattern()) { - shiftPos( direction * MidiTime::ticksPerTact() ); + shiftPos( direction * MidiTime::ticksPerBar() ); } } else if( ke->modifiers() & Qt::ShiftModifier && m_action == ActionNone) @@ -1572,7 +1572,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) x -= WHITE_KEY_WIDTH; // get tick in which the user clicked - int pos_ticks = x * MidiTime::ticksPerTact() / m_ppt + + int pos_ticks = x * MidiTime::ticksPerBar() / m_ppb + m_currentPosition; @@ -1602,7 +1602,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) || ( edit_note && pos_ticks <= note->pos() + - NOTE_EDIT_LINE_WIDTH * MidiTime::ticksPerTact() / m_ppt ) + NOTE_EDIT_LINE_WIDTH * MidiTime::ticksPerBar() / m_ppb ) ) ) { @@ -1746,8 +1746,8 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) // clicked at the "tail" of the note? - if( pos_ticks * m_ppt / MidiTime::ticksPerTact() > - m_currentNote->endPos() * m_ppt / MidiTime::ticksPerTact() - RESIZE_AREA_WIDTH + if( pos_ticks * m_ppb / MidiTime::ticksPerBar() > + m_currentNote->endPos() * m_ppb / MidiTime::ticksPerBar() - RESIZE_AREA_WIDTH && m_currentNote->length() > 0 ) { m_pattern->addJournalCheckPoint(); @@ -1902,10 +1902,10 @@ void PianoRoll::mouseDoubleClickEvent(QMouseEvent * me ) int pixel_range = 4; int x = me->x() - WHITE_KEY_WIDTH; const int ticks_start = ( x-pixel_range/2 ) * - MidiTime::ticksPerTact() / m_ppt + m_currentPosition; + MidiTime::ticksPerBar() / m_ppb + m_currentPosition; const int ticks_end = ( x+pixel_range/2 ) * - MidiTime::ticksPerTact() / m_ppt + m_currentPosition; - const int ticks_middle = x * MidiTime::ticksPerTact() / m_ppt + m_currentPosition; + MidiTime::ticksPerBar() / m_ppb + m_currentPosition; + const int ticks_middle = x * MidiTime::ticksPerBar() / m_ppb + m_currentPosition; // go through notes to figure out which one we want to change bool altPressed = me->modifiers() & Qt::AltModifier; @@ -2300,9 +2300,9 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) // convert to ticks so that we can check which notes // are in the range int ticks_start = ( x-pixel_range/2 ) * - MidiTime::ticksPerTact() / m_ppt + m_currentPosition; + MidiTime::ticksPerBar() / m_ppb + m_currentPosition; int ticks_end = ( x+pixel_range/2 ) * - MidiTime::ticksPerTact() / m_ppt + m_currentPosition; + MidiTime::ticksPerBar() / m_ppb + m_currentPosition; // get note-vector of current pattern const NoteVector & notes = m_pattern->notes(); @@ -2398,8 +2398,8 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) // set move- or resize-cursor // get tick in which the cursor is posated - int pos_ticks = ( x * MidiTime::ticksPerTact() ) / - m_ppt + m_currentPosition; + int pos_ticks = ( x * MidiTime::ticksPerBar() ) / + m_ppb + m_currentPosition; // get note-vector of current pattern const NoteVector & notes = m_pattern->notes(); @@ -2431,7 +2431,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) Note *note = *it; // x coordinate of the right edge of the note int noteRightX = ( note->pos() + note->length() - - m_currentPosition) * m_ppt/MidiTime::ticksPerTact(); + m_currentPosition) * m_ppb/MidiTime::ticksPerBar(); // cursor at the "tail" of the note? bool atTail = note->length() > 0 && x > noteRightX - RESIZE_AREA_WIDTH; @@ -2470,7 +2470,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) // change size of selection // get tick in which the cursor is posated - int pos_ticks = x * MidiTime::ticksPerTact() / m_ppt + + int pos_ticks = x * MidiTime::ticksPerBar() / m_ppb + m_currentPosition; m_selectedTick = pos_ticks - m_selectStartTick; @@ -2492,7 +2492,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) // any key if in erase mode // get tick in which the user clicked - int pos_ticks = x * MidiTime::ticksPerTact() / m_ppt + + int pos_ticks = x * MidiTime::ticksPerBar() / m_ppb + m_currentPosition; @@ -2523,8 +2523,8 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) ( edit_note && pos_ticks <= note->pos() + NOTE_EDIT_LINE_WIDTH * - MidiTime::ticksPerTact() / - m_ppt ) + MidiTime::ticksPerBar() / + m_ppb ) ) ) { @@ -2573,7 +2573,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) } // get tick in which the cursor is posated - int pos_ticks = x * MidiTime::ticksPerTact()/ m_ppt + + int pos_ticks = x * MidiTime::ticksPerBar()/ m_ppb + m_currentPosition; m_selectedTick = pos_ticks - @@ -2634,7 +2634,7 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl ) // convert pixels to ticks and keys int off_x = x - m_moveStartX; - int off_ticks = off_x * MidiTime::ticksPerTact() / m_ppt; + int off_ticks = off_x * MidiTime::ticksPerBar() / m_ppb; int off_key = getKey( y ) - getKey( m_moveStartY ); // handle scroll changes while dragging @@ -2818,10 +2818,10 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl ) Engine::getSong()->setModified(); } -int PianoRoll::xCoordOfTick(int tick ) +int PianoRoll::xCoordOfTick( int tick ) { return WHITE_KEY_WIDTH + ( ( tick - m_currentPosition ) - * m_ppt / MidiTime::ticksPerTact() ); + * m_ppb / MidiTime::ticksPerBar() ); } void PianoRoll::paintEvent(QPaintEvent * pe ) @@ -3118,20 +3118,20 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) / static_cast( Engine::getSong()->getTimeSigModel().getDenominator() ); float zoomFactor = m_zoomLevels[m_zoomingModel.value()]; //the bars which disappears at the left side by scrolling - int leftBars = m_currentPosition * zoomFactor / MidiTime::ticksPerTact(); + int leftBars = m_currentPosition * zoomFactor / MidiTime::ticksPerBar(); //iterates the visible bars and draw the shading on uneven bars - for( int x = WHITE_KEY_WIDTH, barCount = leftBars; x < width() + m_currentPosition * zoomFactor / timeSignature; x += m_ppt, ++barCount ) + for( int x = WHITE_KEY_WIDTH, barCount = leftBars; x < width() + m_currentPosition * zoomFactor / timeSignature; x += m_ppb, ++barCount ) { if( ( barCount + leftBars ) % 2 != 0 ) { - p.fillRect( x - m_currentPosition * zoomFactor / timeSignature, PR_TOP_MARGIN, m_ppt, + p.fillRect( x - m_currentPosition * zoomFactor / timeSignature, PR_TOP_MARGIN, m_ppb, height() - ( PR_BOTTOM_MARGIN + PR_TOP_MARGIN ), backgroundShade() ); } } // Draw the vertical beat lines - int ticksPerBeat = DefaultTicksPerTact / + int ticksPerBeat = DefaultTicksPerBar / Engine::getSong()->getTimeSigModel().getDenominator(); for( tick = m_currentPosition - m_currentPosition % ticksPerBeat, @@ -3143,9 +3143,9 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) } // Draw the vertical bar lines - for( tick = m_currentPosition - m_currentPosition % MidiTime::ticksPerTact(), + for( tick = m_currentPosition - m_currentPosition % MidiTime::ticksPerBar(), x = xCoordOfTick( tick ); x <= width(); - tick += MidiTime::ticksPerTact(), x = xCoordOfTick( tick ) ) + tick += MidiTime::ticksPerBar(), x = xCoordOfTick( tick ) ) { p.setPen( barLineColor() ); p.drawLine( x, PR_TOP_MARGIN, x, height() - PR_BOTTOM_MARGIN ); @@ -3217,9 +3217,9 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) int pos_ticks = note->pos(); - int note_width = len_ticks * m_ppt / MidiTime::ticksPerTact(); + int note_width = len_ticks * m_ppb / MidiTime::ticksPerBar(); const int x = ( pos_ticks - m_currentPosition ) * - m_ppt / MidiTime::ticksPerTact(); + m_ppb / MidiTime::ticksPerBar(); // skip this note if not in visible area at all if( !( x + note_width >= 0 && x <= width() - WHITE_KEY_WIDTH ) ) { @@ -3259,9 +3259,9 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) int pos_ticks = note->pos(); - int note_width = len_ticks * m_ppt / MidiTime::ticksPerTact(); + int note_width = len_ticks * m_ppb / MidiTime::ticksPerBar(); const int x = ( pos_ticks - m_currentPosition ) * - m_ppt / MidiTime::ticksPerTact(); + m_ppb / MidiTime::ticksPerBar(); // skip this note if not in visible area at all if( !( x + note_width >= 0 && x <= width() - WHITE_KEY_WIDTH ) ) { @@ -3347,9 +3347,9 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) int pos_ticks = note->pos(); - int note_width = len_ticks * m_ppt / MidiTime::ticksPerTact(); + int note_width = len_ticks * m_ppb / MidiTime::ticksPerBar(); const int x = ( pos_ticks - m_currentPosition ) * - m_ppt / MidiTime::ticksPerTact(); + m_ppb / MidiTime::ticksPerBar(); // skip this note if not in visible area at all if( !( x + note_width >= 0 && x <= width() - WHITE_KEY_WIDTH ) ) { @@ -3389,10 +3389,10 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) m_notesEditHeight - PR_BOTTOM_MARGIN ); // now draw selection-frame - int x = ( ( sel_pos_start - m_currentPosition ) * m_ppt ) / - MidiTime::ticksPerTact(); - int w = ( ( ( sel_pos_end - m_currentPosition ) * m_ppt ) / - MidiTime::ticksPerTact() ) - x; + int x = ( ( sel_pos_start - m_currentPosition ) * m_ppb ) / + MidiTime::ticksPerBar(); + int w = ( ( ( sel_pos_end - m_currentPosition ) * m_ppb ) / + MidiTime::ticksPerBar() ) - x; int y = (int) y_base - sel_key_start * KEY_LINE_HEIGHT; int h = (int) y_base - sel_key_end * KEY_LINE_HEIGHT - y; p.setPen( selectedNoteColor() ); @@ -3508,9 +3508,9 @@ void PianoRoll::wheelEvent(QWheelEvent * we ) int pixel_range = 8; int x = we->x() - WHITE_KEY_WIDTH; int ticks_start = ( x - pixel_range / 2 ) * - MidiTime::ticksPerTact() / m_ppt + m_currentPosition; + MidiTime::ticksPerBar() / m_ppb + m_currentPosition; int ticks_end = ( x + pixel_range / 2 ) * - MidiTime::ticksPerTact() / m_ppt + m_currentPosition; + MidiTime::ticksPerBar() / m_ppb + m_currentPosition; // When alt is pressed we only edit the note under the cursor bool altPressed = we->modifiers() & Qt::AltModifier; @@ -3611,11 +3611,11 @@ void PianoRoll::wheelEvent(QWheelEvent * we ) } z = qBound( 0, z, m_zoomingModel.size() - 1 ); - int x = (we->x() - WHITE_KEY_WIDTH)* MidiTime::ticksPerTact(); + int x = (we->x() - WHITE_KEY_WIDTH)* MidiTime::ticksPerBar(); // ticks based on the mouse x-position where the scroll wheel was used - int ticks = x / m_ppt; + int ticks = x / m_ppb; // what would be the ticks in the new zoom level on the very same mouse x - int newTicks = x / (DEFAULT_PR_PPT * m_zoomLevels[z]); + int newTicks = x / (DEFAULT_PR_PPB * m_zoomLevels[z]); // scroll so the tick "selected" by the mouse x doesn't move on the screen m_leftRightScroll->setValue(m_leftRightScroll->value() + ticks - newTicks); // update combobox with zooming-factor @@ -4039,7 +4039,7 @@ void PianoRoll::copyToClipboard( const NoteVector & notes ) const QDomElement note_list = dataFile.createElement( "note-list" ); dataFile.content().appendChild( note_list ); - MidiTime start_pos( notes.front()->pos().getTact(), 0 ); + MidiTime start_pos( notes.front()->pos().getBar(), 0 ); for( const Note *note : notes ) { Note clip_note( *note ); @@ -4200,15 +4200,15 @@ void PianoRoll::deleteSelectedNotes() void PianoRoll::autoScroll( const MidiTime & t ) { const int w = width() - WHITE_KEY_WIDTH; - if( t > m_currentPosition + w * MidiTime::ticksPerTact() / m_ppt ) + if( t > m_currentPosition + w * MidiTime::ticksPerBar() / m_ppb ) { - m_leftRightScroll->setValue( t.getTact() * MidiTime::ticksPerTact() ); + m_leftRightScroll->setValue( t.getBar() * MidiTime::ticksPerBar() ); } else if( t < m_currentPosition ) { - MidiTime t2 = qMax( t - w * MidiTime::ticksPerTact() * - MidiTime::ticksPerTact() / m_ppt, (tick_t) 0 ); - m_leftRightScroll->setValue( t2.getTact() * MidiTime::ticksPerTact() ); + MidiTime t2 = qMax( t - w * MidiTime::ticksPerBar() * + MidiTime::ticksPerBar() / m_ppb, (tick_t) 0 ); + m_leftRightScroll->setValue( t2.getBar() * MidiTime::ticksPerBar() ); } m_scrollBack = false; } @@ -4262,12 +4262,12 @@ void PianoRoll::updatePositionStepRecording( const MidiTime & t ) void PianoRoll::zoomingChanged() { - m_ppt = m_zoomLevels[m_zoomingModel.value()] * DEFAULT_PR_PPT; + m_ppb = m_zoomLevels[m_zoomingModel.value()] * DEFAULT_PR_PPB; - assert( m_ppt > 0 ); + assert( m_ppb > 0 ); - m_timeLine->setPixelsPerTact( m_ppt ); - m_stepRecorderWidget.setPixelsPerTact( m_ppt ); + m_timeLine->setPixelsPerBar( m_ppb ); + m_stepRecorderWidget.setPixelsPerBar( m_ppb ); update(); } @@ -4297,12 +4297,12 @@ int PianoRoll::quantization() const } else { - return DefaultTicksPerTact / 16; + return DefaultTicksPerBar / 16; } } QString text = m_quantizeModel.currentText(); - return DefaultTicksPerTact / text.right( text.length() - 2 ).toInt(); + return DefaultTicksPerBar / text.right( text.length() - 2 ).toInt(); } @@ -4370,7 +4370,7 @@ MidiTime PianoRoll::newNoteLen() const } QString text = m_noteLenModel.currentText(); - return DefaultTicksPerTact / text.right( text.length() - 2 ).toInt(); + return DefaultTicksPerBar / text.right( text.length() - 2 ).toInt(); } @@ -4398,7 +4398,7 @@ Note * PianoRoll::noteUnderMouse() int key_num = getKey( pos.y() ); int pos_ticks = ( pos.x() - WHITE_KEY_WIDTH ) * - MidiTime::ticksPerTact() / m_ppt + m_currentPosition; + MidiTime::ticksPerBar() / m_ppb + m_currentPosition; // loop through whole note-vector... for( Note* const& note : m_pattern->notes() ) diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index a077840d0..2c2485d00 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -95,7 +95,7 @@ SongEditor::SongEditor( Song * song ) : m_zoomingModel->setParent(this); m_snappingModel->setParent(this); m_timeLine = new TimeLineWidget( m_trackHeadWidth, 32, - pixelsPerTact(), + pixelsPerBar(), m_song->m_playPos[Song::Mode_PlaySong], m_currentPosition, Song::Mode_PlaySong, this ); @@ -374,7 +374,7 @@ void SongEditor::selectRegionFromPixels(int xStart, int xEnd) //calculate the song position where the mouse was clicked m_rubberbandStartMidipos = MidiTime((xStart - m_trackHeadWidth) - / pixelsPerTact() * MidiTime::ticksPerTact()) + / pixelsPerBar() * MidiTime::ticksPerBar()) + m_currentPosition; m_rubberBandStartTrackview = 0; } @@ -409,7 +409,7 @@ void SongEditor::updateRubberband() } //take care of the scrollbar position - int hs = (m_leftRightScroll->value() - m_scrollPos.x()) * pixelsPerTact(); + int hs = (m_leftRightScroll->value() - m_scrollPos.x()) * pixelsPerBar(); int vs = contentWidget()->verticalScrollBar()->value() - m_scrollPos.y(); //the adjusted origin point @@ -425,7 +425,7 @@ void SongEditor::updateRubberband() //the miditime the mouse is hover MidiTime rubberbandMidipos = MidiTime((qMin(m_mousePos.x(), width()) - m_trackHeadWidth) - / pixelsPerTact() * MidiTime::ticksPerTact()) + / pixelsPerBar() * MidiTime::ticksPerBar()) + m_currentPosition; //are tcos in the rect of selection? @@ -485,7 +485,7 @@ void SongEditor::keyPressEvent( QKeyEvent * ke ) } else if( ke->key() == Qt::Key_Left ) { - tick_t t = m_song->currentTick() - MidiTime::ticksPerTact(); + tick_t t = m_song->currentTick() - MidiTime::ticksPerBar(); if( t >= 0 ) { m_song->setPlayPos( t, Song::Mode_PlaySong ); @@ -493,7 +493,7 @@ void SongEditor::keyPressEvent( QKeyEvent * ke ) } else if( ke->key() == Qt::Key_Right ) { - tick_t t = m_song->currentTick() + MidiTime::ticksPerTact(); + tick_t t = m_song->currentTick() + MidiTime::ticksPerBar(); if( t < MaxSongLength ) { m_song->setPlayPos( t, Song::Mode_PlaySong ); @@ -549,20 +549,20 @@ void SongEditor::wheelEvent( QWheelEvent * we ) z = qBound( 0, z, m_zoomingModel->size() - 1 ); - int x = (we->x() - m_trackHeadWidth); - // tact based on the mouse x-position where the scroll wheel was used - int tact= x / pixelsPerTact(); - // what would be the tact in the new zoom level on the very same mouse x - int newTact = x / DEFAULT_PIXELS_PER_TACT / m_zoomLevels[z]; - // scroll so the tact "selected" by the mouse x doesn't move on the screen - m_leftRightScroll->setValue(m_leftRightScroll->value() + tact - newTact); + int x = we->x() - m_trackHeadWidth; + // bar based on the mouse x-position where the scroll wheel was used + int bar = x / pixelsPerBar(); + // what would be the bar in the new zoom level on the very same mouse x + int newBar = x / DEFAULT_PIXELS_PER_BAR / m_zoomLevels[z]; + // scroll so the bar "selected" by the mouse x doesn't move on the screen + m_leftRightScroll->setValue(m_leftRightScroll->value() + bar - newBar); // update combobox with zooming-factor m_zoomingModel->setValue( z ); // update timeline m_song->m_playPos[Song::Mode_PlaySong].m_timeLine-> - setPixelsPerTact( pixelsPerTact() ); + setPixelsPerBar( pixelsPerBar() ); // and make sure, all TCO's are resized and relocated realignTracks(); } @@ -614,7 +614,7 @@ void SongEditor::mousePressEvent(QMouseEvent *me) //the trackView(index) and the miditime where the mouse was clicked m_rubberBandStartTrackview = trackIndexFromSelectionPoint(me->y()); m_rubberbandStartMidipos = MidiTime((me->x() - m_trackHeadWidth) - / pixelsPerTact() * MidiTime::ticksPerTact()) + / pixelsPerBar() * MidiTime::ticksPerBar()) + m_currentPosition; } QWidget::mousePressEvent(me); @@ -791,14 +791,14 @@ void SongEditor::updatePosition( const MidiTime & t ) const int w = width() - widgetWidth - trackOpWidth - contentWidget()->verticalScrollBar()->width(); // width of right scrollbar - if( t > m_currentPosition + w * MidiTime::ticksPerTact() / - pixelsPerTact() ) + if( t > m_currentPosition + w * MidiTime::ticksPerBar() / + pixelsPerBar() ) { - animateScroll( m_leftRightScroll, t.getTact(), m_smoothScroll ); + animateScroll( m_leftRightScroll, t.getBar(), m_smoothScroll ); } else if( t < m_currentPosition ) { - animateScroll( m_leftRightScroll, t.getTact(), m_smoothScroll ); + animateScroll( m_leftRightScroll, t.getBar(), m_smoothScroll ); } m_scrollBack = false; } @@ -831,10 +831,10 @@ void SongEditor::updatePositionLine() void SongEditor::zoomingChanged() { - setPixelsPerTact( m_zoomLevels[m_zoomingModel->value()] * DEFAULT_PIXELS_PER_TACT ); + setPixelsPerBar( m_zoomLevels[m_zoomingModel->value()] * DEFAULT_PIXELS_PER_BAR ); m_song->m_playPos[Song::Mode_PlaySong].m_timeLine-> - setPixelsPerTact( pixelsPerTact() ); + setPixelsPerBar( pixelsPerBar() ); realignTracks(); updateRubberband(); } diff --git a/src/gui/widgets/StepRecorderWidget.cpp b/src/gui/widgets/StepRecorderWidget.cpp index f59e235fc..a546c2a2c 100644 --- a/src/gui/widgets/StepRecorderWidget.cpp +++ b/src/gui/widgets/StepRecorderWidget.cpp @@ -26,7 +26,7 @@ StepRecorderWidget::StepRecorderWidget( QWidget * parent, - const int ppt, + const int ppb, const int marginTop, const int marginBottom, const int marginLeft, @@ -42,15 +42,15 @@ StepRecorderWidget::StepRecorderWidget( m_colorLineStart = baseColor.darker(120); setAttribute(Qt::WA_NoSystemBackground, true); - setPixelsPerTact(ppt); + setPixelsPerBar(ppb); m_top = m_marginTop; m_left = m_marginLeft; } -void StepRecorderWidget::setPixelsPerTact(int ppt) +void StepRecorderWidget::setPixelsPerBar(int ppb) { - m_ppt = ppt; + m_ppb = ppb; } void StepRecorderWidget::setCurrentPosition(MidiTime currentPosition) @@ -125,7 +125,7 @@ void StepRecorderWidget::paintEvent(QPaintEvent * pe) int StepRecorderWidget::xCoordOfTick(int tick) { - return m_marginLeft + ((tick - m_currentPosition) * m_ppt / MidiTime::ticksPerTact()); + return m_marginLeft + ((tick - m_currentPosition) * m_ppb / MidiTime::ticksPerBar()); } diff --git a/src/gui/widgets/TimeDisplayWidget.cpp b/src/gui/widgets/TimeDisplayWidget.cpp index e9a831193..01604a9dc 100644 --- a/src/gui/widgets/TimeDisplayWidget.cpp +++ b/src/gui/widgets/TimeDisplayWidget.cpp @@ -100,11 +100,11 @@ void TimeDisplayWidget::updateTime() case BarsTicks: int tick; tick = s->getPlayPos().getTicks(); - m_majorLCD.setValue((int)(tick / s->ticksPerTact()) + 1); - m_minorLCD.setValue((tick % s->ticksPerTact()) / - (s->ticksPerTact() / s->getTimeSigModel().getNumerator() ) +1); - m_milliSecondsLCD.setValue((tick % s->ticksPerTact()) % - (s->ticksPerTact() / s->getTimeSigModel().getNumerator())); + m_majorLCD.setValue((int)(tick / s->ticksPerBar()) + 1); + m_minorLCD.setValue((tick % s->ticksPerBar()) / + (s->ticksPerBar() / s->getTimeSigModel().getNumerator() ) +1); + m_milliSecondsLCD.setValue((tick % s->ticksPerBar()) % + (s->ticksPerBar() / s->getTimeSigModel().getNumerator())); break; default: break; diff --git a/src/tracks/AutomationTrack.cpp b/src/tracks/AutomationTrack.cpp index 11c919f0e..430f54a56 100644 --- a/src/tracks/AutomationTrack.cpp +++ b/src/tracks/AutomationTrack.cpp @@ -121,9 +121,9 @@ void AutomationTrackView::dropEvent( QDropEvent * _de ) currentPosition() + ( _de->pos().x() - getTrackContentWidget()->x() ) * - MidiTime::ticksPerTact() / - static_cast( trackContainerView()->pixelsPerTact() ) ) - .toAbsoluteTact(); + MidiTime::ticksPerBar() / + static_cast( trackContainerView()->pixelsPerBar() ) ) + .toAbsoluteBar(); if( pos.getTicks() < 0 ) { diff --git a/src/tracks/BBTrack.cpp b/src/tracks/BBTrack.cpp index 779cd3c74..a779e2ea4 100644 --- a/src/tracks/BBTrack.cpp +++ b/src/tracks/BBTrack.cpp @@ -51,7 +51,7 @@ BBTCO::BBTCO( Track * _track ) : m_color( 128, 128, 128 ), m_useStyleColor( true ) { - tact_t t = Engine::getBBTrackContainer()->lengthOfBB( bbTrackIndex() ); + bar_t t = Engine::getBBTrackContainer()->lengthOfBB( bbTrackIndex() ); if( t > 0 ) { saveJournallingState( false ); @@ -237,12 +237,12 @@ void BBTCOView::paintEvent( QPaintEvent * ) const int lineSize = 3; p.setPen( c.darker( 200 ) ); - tact_t t = Engine::getBBTrackContainer()->lengthOfBB( m_bbTCO->bbTrackIndex() ); - if( m_bbTCO->length() > MidiTime::ticksPerTact() && t > 0 ) + bar_t t = Engine::getBBTrackContainer()->lengthOfBB( m_bbTCO->bbTrackIndex() ); + if( m_bbTCO->length() > MidiTime::ticksPerBar() && t > 0 ) { - for( int x = static_cast( t * pixelsPerTact() ); + for( int x = static_cast( t * pixelsPerBar() ); x < width() - 2; - x += static_cast( t * pixelsPerTact() ) ) + x += static_cast( t * pixelsPerBar() ) ) { p.drawLine( x, TCO_BORDER_WIDTH, x, TCO_BORDER_WIDTH + lineSize ); p.drawLine( x, rect().bottom() - ( TCO_BORDER_WIDTH + lineSize ), diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 673996fa2..b44d1b4fa 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -677,7 +677,7 @@ bool InstrumentTrack::play( const MidiTime & _start, const fpp_t _frames, if( cur_start > 0 ) { - // skip notes which are posated before start-tact + // skip notes which are posated before start-bar while( nit != notes.end() && ( *nit )->pos() < cur_start ) { ++nit; diff --git a/src/tracks/Pattern.cpp b/src/tracks/Pattern.cpp index 32baf0b14..125e84a1f 100644 --- a/src/tracks/Pattern.cpp +++ b/src/tracks/Pattern.cpp @@ -56,7 +56,7 @@ Pattern::Pattern( InstrumentTrack * _instrument_track ) : TrackContentObject( _instrument_track ), m_instrumentTrack( _instrument_track ), m_patternType( BeatPattern ), - m_steps( MidiTime::stepsPerTact() ) + m_steps( MidiTime::stepsPerBar() ) { setName( _instrument_track->name() ); if( _instrument_track->trackContainer() @@ -161,7 +161,7 @@ void Pattern::updateLength() return; } - tick_t max_length = MidiTime::ticksPerTact(); + tick_t max_length = MidiTime::ticksPerBar(); for( NoteVector::ConstIterator it = m_notes.begin(); it != m_notes.end(); ++it ) @@ -172,8 +172,8 @@ void Pattern::updateLength() ( *it )->endPos() ); } } - changeLength( MidiTime( max_length ).nextFullTact() * - MidiTime::ticksPerTact() ); + changeLength( MidiTime( max_length ).nextFullBar() * + MidiTime::ticksPerBar() ); updateBBTrack(); } @@ -182,7 +182,7 @@ void Pattern::updateLength() MidiTime Pattern::beatPatternLength() const { - tick_t max_length = MidiTime::ticksPerTact(); + tick_t max_length = MidiTime::ticksPerBar(); for( NoteVector::ConstIterator it = m_notes.begin(); it != m_notes.end(); ++it ) @@ -194,13 +194,13 @@ MidiTime Pattern::beatPatternLength() const } } - if( m_steps != MidiTime::stepsPerTact() ) + if( m_steps != MidiTime::stepsPerBar() ) { - max_length = m_steps * MidiTime::ticksPerTact() / - MidiTime::stepsPerTact(); + max_length = m_steps * MidiTime::ticksPerBar() / + MidiTime::stepsPerBar(); } - return MidiTime( max_length ).nextFullTact() * MidiTime::ticksPerTact(); + return MidiTime( max_length ).nextFullBar() * MidiTime::ticksPerBar(); } @@ -298,7 +298,7 @@ void Pattern::clearNotes() Note * Pattern::addStepNote( int step ) { - return addNote( Note( MidiTime( -DefaultTicksPerTact ), + return addNote( Note( MidiTime( -DefaultTicksPerBar ), MidiTime::stepPosition( step ) ), false ); } @@ -417,7 +417,7 @@ void Pattern::loadSettings( const QDomElement & _this ) m_steps = _this.attribute( "steps" ).toInt(); if( m_steps == 0 ) { - m_steps = MidiTime::stepsPerTact(); + m_steps = MidiTime::stepsPerBar(); } checkType(); @@ -466,7 +466,7 @@ void Pattern::clear() void Pattern::addSteps() { - m_steps += MidiTime::stepsPerTact(); + m_steps += MidiTime::stepsPerBar(); updateLength(); emit dataChanged(); } @@ -497,7 +497,7 @@ void Pattern::cloneSteps() void Pattern::removeSteps() { - int n = MidiTime::stepsPerTact(); + int n = MidiTime::stepsPerBar(); if( n < m_steps ) { for( int i = m_steps - n; i < m_steps; ++i ) @@ -555,19 +555,19 @@ bool Pattern::empty() void Pattern::changeTimeSignature() { - MidiTime last_pos = MidiTime::ticksPerTact() - 1; + MidiTime last_pos = MidiTime::ticksPerBar() - 1; for( NoteVector::ConstIterator cit = m_notes.begin(); cit != m_notes.end(); ++cit ) { if( ( *cit )->length() < 0 && ( *cit )->pos() > last_pos ) { - last_pos = ( *cit )->pos()+MidiTime::ticksPerTact() / - MidiTime::stepsPerTact(); + last_pos = ( *cit )->pos()+MidiTime::ticksPerBar() / + MidiTime::stepsPerBar(); } } - last_pos = last_pos.nextFullTact() * MidiTime::ticksPerTact(); - m_steps = qMax( MidiTime::stepsPerTact(), - last_pos.getTact() * MidiTime::stepsPerTact() ); + last_pos = last_pos.nextFullBar() * MidiTime::ticksPerBar(); + m_steps = qMax( MidiTime::stepsPerBar(), + last_pos.getBar() * MidiTime::stepsPerBar() ); updateLength(); } @@ -715,7 +715,7 @@ void PatternView::mousePressEvent( QMouseEvent * _me ) { if( _me->button() == Qt::LeftButton && m_pat->m_patternType == Pattern::BeatPattern && - ( fixedTCOs() || pixelsPerTact() >= 96 ) && + ( fixedTCOs() || pixelsPerBar() >= 96 ) && _me->y() > height() - s_stepBtnOff->height() ) // when mouse button is pressed in beat/bassline -mode @@ -785,7 +785,7 @@ void PatternView::mouseDoubleClickEvent(QMouseEvent *_me) void PatternView::wheelEvent( QWheelEvent * _we ) { if( m_pat->m_patternType == Pattern::BeatPattern && - ( fixedTCOs() || pixelsPerTact() >= 96 ) && + ( fixedTCOs() || pixelsPerBar() >= 96 ) && _we->y() > height() - s_stepBtnOff->height() ) { // get the step number that was wheeled on and @@ -902,14 +902,14 @@ void PatternView::paintEvent( QPaintEvent * ) textBoxHeight = fontMetrics.height() + 2 * textTop; } - // Compute pixels per tact + // Compute pixels per bar const int baseWidth = fixedTCOs() ? parentWidget()->width() - 2 * TCO_BORDER_WIDTH : width() - TCO_BORDER_WIDTH; - const float pixelsPerTact = baseWidth / (float) m_pat->length().getTact(); + const float pixelsPerBar = baseWidth / (float) m_pat->length().getBar(); - // Length of one tact/beat in the [0,1] x [0,1] coordinate system - const float tactLength = 1. / m_pat->length().getTact(); - const float tickLength = tactLength / MidiTime::ticksPerTact(); + // Length of one bar/beat in the [0,1] x [0,1] coordinate system + const float barLength = 1. / m_pat->length().getBar(); + const float tickLength = barLength / MidiTime::ticksPerBar(); const int x_base = TCO_BORDER_WIDTH; @@ -1029,7 +1029,7 @@ void PatternView::paintEvent( QPaintEvent * ) } // beat pattern paint event - else if( beatPattern && ( fixedTCOs() || pixelsPerTact >= 96 ) ) + else if( beatPattern && ( fixedTCOs() || pixelsPerBar >= 96 ) ) { QPixmap stepon0; QPixmap stepon200; @@ -1097,14 +1097,14 @@ void PatternView::paintEvent( QPaintEvent * ) const int lineSize = 3; p.setPen( c.darker( 200 ) ); - for( tact_t t = 1; t < m_pat->length().getTact(); ++t ) + for( bar_t t = 1; t < m_pat->length().getBar(); ++t ) { - p.drawLine( x_base + static_cast( pixelsPerTact * t ) - 1, + p.drawLine( x_base + static_cast( pixelsPerBar * t ) - 1, TCO_BORDER_WIDTH, x_base + static_cast( - pixelsPerTact * t ) - 1, TCO_BORDER_WIDTH + lineSize ); - p.drawLine( x_base + static_cast( pixelsPerTact * t ) - 1, + pixelsPerBar * t ) - 1, TCO_BORDER_WIDTH + lineSize ); + p.drawLine( x_base + static_cast( pixelsPerBar * t ) - 1, rect().bottom() - ( lineSize + TCO_BORDER_WIDTH ), - x_base + static_cast( pixelsPerTact * t ) - 1, + x_base + static_cast( pixelsPerBar * t ) - 1, rect().bottom() - TCO_BORDER_WIDTH ); } diff --git a/src/tracks/SampleTrack.cpp b/src/tracks/SampleTrack.cpp index ba04f909b..72f63bb05 100644 --- a/src/tracks/SampleTrack.cpp +++ b/src/tracks/SampleTrack.cpp @@ -157,7 +157,7 @@ void SampleTCO::setSampleFile( const QString & _sf ) { //When creating an empty sample pattern make it a bar long float nom = Engine::getSong()->getTimeSigModel().getNumerator(); float den = Engine::getSong()->getTimeSigModel().getDenominator(); - length = DefaultTicksPerTact * ( nom / den ); + length = DefaultTicksPerBar * ( nom / den ); } else { //Otherwise set it to the sample's length @@ -521,18 +521,18 @@ void SampleTCOView::paintEvent( QPaintEvent * pe ) p.setPen( !muted ? painter.pen().brush().color() : mutedColor() ); const int spacing = TCO_BORDER_WIDTH + 1; - const float ppt = fixedTCOs() ? + const float ppb = fixedTCOs() ? ( parentWidget()->width() - 2 * TCO_BORDER_WIDTH ) - / (float) m_tco->length().getTact() : - pixelsPerTact(); + / (float) m_tco->length().getBar() : + pixelsPerBar(); float nom = Engine::getSong()->getTimeSigModel().getNumerator(); float den = Engine::getSong()->getTimeSigModel().getDenominator(); - float ticksPerTact = DefaultTicksPerTact * nom / den; + float ticksPerBar = DefaultTicksPerBar * nom / den; - float offset = m_tco->startTimeOffset() / ticksPerTact * pixelsPerTact(); + float offset = m_tco->startTimeOffset() / ticksPerBar * pixelsPerBar(); QRect r = QRect( TCO_BORDER_WIDTH + offset, spacing, - qMax( static_cast( m_tco->sampleLength() * ppt / ticksPerTact ), 1 ), rect().bottom() - 2 * spacing ); + qMax( static_cast( m_tco->sampleLength() * ppb / ticksPerBar ), 1 ), rect().bottom() - 2 * spacing ); m_tco->m_sampleBuffer->visualize( p, r, pe->rect() ); QFileInfo fileInfo(m_tco->m_sampleBuffer->audioFile()); @@ -928,8 +928,8 @@ void SampleTrackView::dropEvent(QDropEvent *de) MidiTime tcoPos = trackContainerView()->fixedTCOs() ? MidiTime(0) - : MidiTime(((xPos - trackHeadWidth) / trackContainerView()->pixelsPerTact() - * MidiTime::ticksPerTact()) + trackContainerView()->currentPosition() + : MidiTime(((xPos - trackHeadWidth) / trackContainerView()->pixelsPerBar() + * MidiTime::ticksPerBar()) + trackContainerView()->currentPosition() ).quantize(1.0); SampleTCO * sTco = static_cast(getTrack()->createTCO(tcoPos)); diff --git a/tests/src/tracks/AutomationTrackTest.cpp b/tests/src/tracks/AutomationTrackTest.cpp index f9f77fac4..291ae293e 100644 --- a/tests/src/tracks/AutomationTrackTest.cpp +++ b/tests/src/tracks/AutomationTrackTest.cpp @@ -186,12 +186,12 @@ private slots: QVERIFY(! bbContainer->automatedValuesAt(5, bbTrack2.index()).size()); BBTCO tco(&bbTrack); - tco.changeLength(MidiTime::ticksPerTact() * 2); + tco.changeLength(MidiTime::ticksPerBar() * 2); tco.movePosition(0); QCOMPARE(song->automatedValuesAt(0)[&model], 0.0f); QCOMPARE(song->automatedValuesAt(5)[&model], 0.5f); - QCOMPARE(song->automatedValuesAt(MidiTime::ticksPerTact() + 5)[&model], 0.5f); + QCOMPARE(song->automatedValuesAt(MidiTime::ticksPerBar() + 5)[&model], 0.5f); } void testGlobalAutomation() From 46f5433732654d8090cc75ee21f3a00f93910439 Mon Sep 17 00:00:00 2001 From: Alexandre Almeida Date: Sun, 27 Oct 2019 08:45:58 -0300 Subject: [PATCH 71/81] New BARS_PER_GROUP constant --- src/core/Track.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/core/Track.cpp b/src/core/Track.cpp index dedfcbc27..5c61dc5ab 100644 --- a/src/core/Track.cpp +++ b/src/core/Track.cpp @@ -73,6 +73,10 @@ */ const int RESIZE_GRIP_WIDTH = 4; +/*! Alternate between a darker and a lighter background color every 4 bars + */ +const int BARS_PER_GROUP = 4; + /*! A pointer for that text bubble used when moving segments, etc. * @@ -1271,8 +1275,7 @@ void TrackContentWidget::updateBackground() // Assume even-pixels-per-bar. Makes sense, should be like this anyways int ppb = static_cast( tcv->pixelsPerBar() ); - // alternate between a darker and a lighter color every 4 bars - int w = ppb * 4; + int w = ppb * BARS_PER_GROUP; int h = height(); m_background = QPixmap( w * 2, height() ); QPainter pmp( &m_background ); From dac59a5fa056048ccc4655b06102406ac7c502ac Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Thu, 31 Oct 2019 19:05:33 +0000 Subject: [PATCH 72/81] C++11 inheritance updates Add `override` and remove `virtual` where applicable --- include/AudioAlsa.h | 8 +-- include/AudioAlsaSetupWidget.h | 2 +- include/AudioDummy.h | 10 +-- include/AudioFileMP3.h | 2 +- include/AudioFileOgg.h | 2 +- include/AudioFileWave.h | 2 +- include/AudioOss.h | 10 +-- include/AudioPort.h | 4 +- include/AudioPulseAudio.h | 10 +-- include/AudioSampleRecorder.h | 2 +- include/AudioSdl.h | 10 +-- include/AudioSndio.h | 10 +-- include/AutomatableButton.h | 10 +-- include/AutomatableModel.h | 6 +- include/AutomatableModelView.h | 2 +- include/AutomatableSlider.h | 10 +-- include/AutomationEditor.h | 34 +++++----- include/AutomationPattern.h | 8 +-- include/AutomationPatternView.h | 12 ++-- include/AutomationTrack.h | 16 ++--- include/BBEditor.h | 14 ++-- include/BBTrack.h | 30 ++++---- include/BBTrackContainer.h | 4 +- include/CPULoadWidget.h | 2 +- include/ComboBox.h | 8 +-- include/Controller.h | 6 +- include/ControllerConnection.h | 6 +- include/ControllerDialog.h | 2 +- include/ControllerRackView.h | 8 +-- include/ControllerView.h | 6 +- include/DetuningHelper.h | 6 +- include/DummyEffect.h | 14 ++-- include/DummyInstrument.h | 10 +-- include/DummyPlugin.h | 8 +-- include/Editor.h | 6 +- include/Effect.h | 8 +-- include/EffectChain.h | 6 +- include/EffectControlDialog.h | 2 +- include/EffectRackView.h | 2 +- include/EffectView.h | 6 +- include/EnvelopeAndLfoParameters.h | 6 +- include/EnvelopeAndLfoView.h | 10 +-- include/ExportFilter.h | 6 +- include/ExportProjectDialog.h | 6 +- include/FadeButton.h | 4 +- include/Fader.h | 14 ++-- include/FileBrowser.h | 10 +-- include/FxLine.h | 10 +-- include/FxLineLcdSpinBox.h | 4 +- include/FxMixer.h | 10 +-- include/FxMixerView.h | 8 +-- include/Graph.h | 14 ++-- include/GroupBox.h | 6 +- include/ImportFilter.h | 6 +- include/InlineAutomation.h | 4 +- include/Instrument.h | 2 +- include/InstrumentFunctionViews.h | 4 +- include/InstrumentFunctions.h | 12 ++-- include/InstrumentMidiIOView.h | 2 +- include/InstrumentPlayHandle.h | 6 +- include/InstrumentSoundShaping.h | 6 +- include/InstrumentSoundShapingView.h | 2 +- include/InstrumentTrack.h | 38 +++++------ include/JournallingObject.h | 4 +- include/Knob.h | 22 +++--- include/LadspaControl.h | 6 +- include/LcdSpinBox.h | 14 ++-- include/LcdWidget.h | 2 +- include/LedCheckbox.h | 2 +- include/LfoController.h | 14 ++-- include/LmmsStyle.h | 8 +-- include/MainApplication.h | 2 +- include/MainWindow.h | 10 +-- include/MeterDialog.h | 2 +- include/MidiAlsaRaw.h | 4 +- include/MidiAlsaSeq.h | 24 +++---- include/MidiClient.h | 4 +- include/MidiController.h | 14 ++-- include/MidiDummy.h | 2 +- include/MidiOss.h | 4 +- include/MidiPort.h | 6 +- include/MidiPortMenu.h | 2 +- include/MidiSndio.h | 4 +- include/Mixer.h | 2 +- include/MixerWorkerThread.h | 2 +- include/NStateButton.h | 2 +- include/Note.h | 6 +- include/NotePlayHandle.h | 10 +-- include/Pattern.h | 20 +++--- include/PeakController.h | 16 ++--- include/PianoRoll.h | 42 ++++++------ include/PianoView.h | 20 +++--- include/PixmapButton.h | 10 +-- include/PlayHandle.h | 4 +- include/Plugin.h | 2 +- include/PresetPreviewPlayHandle.h | 8 +-- include/ProjectNotes.h | 8 +-- include/ProjectRenderer.h | 2 +- include/RemotePlugin.h | 4 +- include/RenameDialog.h | 4 +- include/RowTableView.h | 4 +- include/Rubberband.h | 2 +- include/SamplePlayHandle.h | 8 +-- include/SampleRecordHandle.h | 6 +- include/SampleTrack.h | 54 +++++++-------- include/SendButtonIndicator.h | 2 +- include/SetupDialog.h | 2 +- include/SideBarWidget.h | 6 +- include/Song.h | 6 +- include/SongEditor.h | 38 +++++------ include/StepRecorderWidget.h | 2 +- include/SubWindow.h | 8 +-- include/TabWidget.h | 14 ++-- include/TempoSyncKnob.h | 4 +- include/TempoSyncKnobModel.h | 2 +- include/TextFloat.h | 4 +- include/TimeDisplayWidget.h | 2 +- include/TimeLineWidget.h | 14 ++-- include/Track.h | 68 +++++++++---------- include/TrackContainer.h | 6 +- include/TrackContainerView.h | 17 +++-- include/TrackLabelButton.h | 14 ++-- include/TrackRenameLineEdit.h | 2 +- include/VisualizationWidget.h | 4 +- plugins/VstEffect/VstEffectControlDialog.h | 4 +- .../peak_controller_effect.h | 4 +- .../peak_controller_effect_controls.h | 10 +-- plugins/vst_base/VstPlugin.h | 10 +-- src/core/PresetPreviewPlayHandle.cpp | 2 +- src/gui/ControllerConnectionDialog.cpp | 2 +- src/gui/FxMixerView.cpp | 2 +- src/gui/RowTableView.cpp | 4 +- src/gui/widgets/SideBar.cpp | 4 +- 133 files changed, 578 insertions(+), 579 deletions(-) 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 e39eaddd7..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 ); @@ -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(); @@ -298,11 +298,11 @@ signals: void currentPatternChanged(); protected: - virtual void focusInEvent(QFocusEvent * event); + 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 e4895aa87..17d6eb5fe 100644 --- a/include/BBTrackContainer.h +++ b/include/BBTrackContainer.h @@ -41,9 +41,9 @@ 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"; } 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/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/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/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/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 b600385c8..27a15149e 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -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, @@ -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/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/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 4a2e5c025..9f9ae1b3f 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -63,7 +63,7 @@ public: protected slots: - virtual void accept(); + void accept() override; private slots: diff --git a/include/SideBarWidget.h b/include/SideBarWidget.h index 37acc9770..9972daa7c 100644 --- a/include/SideBarWidget.h +++ b/include/SideBarWidget.h @@ -52,9 +52,9 @@ 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 { } diff --git a/include/Song.h b/include/Song.h index 1e047caaa..d398a168c 100644 --- a/include/Song.h +++ b/include/Song.h @@ -261,7 +261,7 @@ public: 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"; } diff --git a/include/SongEditor.h b/include/SongEditor.h index 6f39cc1d9..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; @@ -93,10 +93,10 @@ public slots: void selectAllTcos( bool select ); protected: - virtual void closeEvent( QCloseEvent * ce ); - virtual void mousePressEvent(QMouseEvent * me); - virtual void mouseMoveEvent(QMouseEvent * me); - virtual void mouseReleaseEvent(QMouseEvent * me); + 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 ); @@ -116,10 +116,10 @@ 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); @@ -175,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(); @@ -199,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 cafce2b24..14cfc2eed 100644 --- a/include/StepRecorderWidget.h +++ b/include/StepRecorderWidget.h @@ -55,7 +55,7 @@ public: void showHint(); private: - virtual void paintEvent(QPaintEvent * pe); + void paintEvent(QPaintEvent * pe) override; int xCoordOfTick(int tick); 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 374a26418..bc0881f82 100644 --- a/include/TimeLineWidget.h +++ b/include/TimeLineWidget.h @@ -153,9 +153,9 @@ public: 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"; } @@ -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: diff --git a/include/Track.h b/include/Track.h index 4adf6378e..70e49a1c6 100644 --- a/include/Track.h +++ b/include/Track.h @@ -98,7 +98,7 @@ public: emit dataChanged(); } - virtual QString displayName() const + QString displayName() const override { return name(); } @@ -246,21 +246,21 @@ 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 ); @@ -381,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) } @@ -435,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: @@ -518,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() { @@ -564,7 +564,7 @@ public: return m_name; } - virtual QString displayName() const + QString displayName() const override { return name(); } @@ -692,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 cf79a0a21..6e952189b 100644 --- a/include/TrackContainerView.h +++ b/include/TrackContainerView.h @@ -49,8 +49,8 @@ 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() { @@ -116,7 +116,7 @@ public: void clearAllTracks(); - virtual QString nodeName() const + QString nodeName() const override { return "trackcontainerview"; } @@ -129,8 +129,8 @@ public slots: TrackView * createTrackView( Track * _t ); void deleteTrackView( TrackView * _tv ); - virtual void dropEvent( QDropEvent * _de ); - virtual void dragEnterEvent( QDragEnterEvent * _dee ); + void dropEvent( QDropEvent * _de ) override; + void dragEnterEvent( QDragEnterEvent * _dee ) override; /// /// \brief stopRubberBand @@ -141,8 +141,7 @@ public slots: protected: static const int DEFAULT_PIXELS_PER_BAR = 16; - - virtual void resizeEvent( QResizeEvent * ); + void resizeEvent( QResizeEvent * ) override; MidiTime m_currentPosition; @@ -161,7 +160,7 @@ private: virtual ~scrollArea(); protected: - virtual void wheelEvent( QWheelEvent * _we ); + void wheelEvent( QWheelEvent * _we ) override; private: TrackContainerView* m_trackContainerView; @@ -195,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/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/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/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/src/core/PresetPreviewPlayHandle.cpp b/src/core/PresetPreviewPlayHandle.cpp index ca0e52194..11b145b22 100644 --- a/src/core/PresetPreviewPlayHandle.cpp +++ b/src/core/PresetPreviewPlayHandle.cpp @@ -54,7 +54,7 @@ public: { } - virtual QString nodeName() const + QString nodeName() const override { return "previewtrackcontainer"; } diff --git a/src/gui/ControllerConnectionDialog.cpp b/src/gui/ControllerConnectionDialog.cpp index 02857b034..f0d3d10e9 100644 --- a/src/gui/ControllerConnectionDialog.cpp +++ b/src/gui/ControllerConnectionDialog.cpp @@ -63,7 +63,7 @@ public: } - virtual void processInEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset = 0 ) + void processInEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset = 0 ) override { if( event.type() == MidiControlChange && ( m_midiPort.inputChannel() == 0 || m_midiPort.inputChannel() == event.channel() + 1 ) ) diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index 4ae2a630a..54bbff70f 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -115,7 +115,7 @@ FxMixerView::FxMixerView() : ChannelArea( QWidget * parent, FxMixerView * mv ) : QScrollArea( parent ), m_mv( mv ) {} ~ChannelArea() {} - virtual void keyPressEvent( QKeyEvent * e ) + void keyPressEvent( QKeyEvent * e ) override { m_mv->keyPressEvent( e ); } diff --git a/src/gui/RowTableView.cpp b/src/gui/RowTableView.cpp index a4daeb17f..9830354be 100644 --- a/src/gui/RowTableView.cpp +++ b/src/gui/RowTableView.cpp @@ -39,12 +39,12 @@ public: } virtual void paint( QPainter * painter, const QStyleOptionViewItem & option, - const QModelIndex & index ) const; + const QModelIndex & index ) const override; protected: virtual void initStyleOption( QStyleOptionViewItem * option, - const QModelIndex & index ) const; + const QModelIndex & index ) const override; private: diff --git a/src/gui/widgets/SideBar.cpp b/src/gui/widgets/SideBar.cpp index cc83abae4..36c417b93 100644 --- a/src/gui/widgets/SideBar.cpp +++ b/src/gui/widgets/SideBar.cpp @@ -49,7 +49,7 @@ public: return m_orientation; } - virtual QSize sizeHint() const + QSize sizeHint() const override { QSize s = QToolButton::sizeHint(); s.setWidth( s.width() + 8 ); @@ -62,7 +62,7 @@ public: protected: - virtual void paintEvent( QPaintEvent * ) + void paintEvent( QPaintEvent * ) override { QStylePainter p( this ); QStyleOptionToolButton opt; From ebf71003c7873d02da10ea44c60e69ca773c79f4 Mon Sep 17 00:00:00 2001 From: Kevin Zander Date: Fri, 1 Nov 2019 02:36:54 -0500 Subject: [PATCH 73/81] Fix vertical piano mouse click unresponsiveness `PianoRoll::mouseDoubleClickEvent` wasn't forwarding the event to the base class when not acting on the event. The base class calls `mousePressEvent`. Fixes #3005 --- src/gui/editors/PianoRoll.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 183735450..3b42bd9b2 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -1948,6 +1948,10 @@ void PianoRoll::mouseDoubleClickEvent(QMouseEvent * me ) enterValue( &nv ); } } + else + { + QWidget::mouseDoubleClickEvent(me); + } } From 8a52ddb642d0789fd017fa36e491d187040de594 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Fri, 1 Nov 2019 09:56:39 +0100 Subject: [PATCH 74/81] CricleCI: Test merged pull request --- .circleci/config.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0ab2c51a0..a3be541b5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,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 From a24f1d779d2226104a69ff004e5ad83365cbec9b Mon Sep 17 00:00:00 2001 From: Hussam al-Homsi Date: Wed, 6 Nov 2019 22:03:39 -0500 Subject: [PATCH 75/81] Do not include unused headers --- include/Pitch.h | 3 --- include/panning.h | 1 - include/volume.h | 3 --- 3 files changed, 7 deletions(-) diff --git a/include/Pitch.h b/include/Pitch.h index 5ef1c3d62..8a9b371b4 100644 --- a/include/Pitch.h +++ b/include/Pitch.h @@ -25,9 +25,6 @@ #ifndef PITCH_H #define PITCH_H -#include "lmms_basics.h" -#include "Midi.h" - typedef int16_t pitch_t; const pitch_t CentsPerSemitone = 100; diff --git a/include/panning.h b/include/panning.h index 8668ddf88..8994df9ab 100644 --- a/include/panning.h +++ b/include/panning.h @@ -27,7 +27,6 @@ #define PANNING_H #include "lmms_basics.h" -#include "volume.h" #include "panning_constants.h" #include "Midi.h" 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; From b4459bed9e48f8dddc448da2f8bf6202dc87df5b Mon Sep 17 00:00:00 2001 From: nia <29542929+niacat@users.noreply.github.com> Date: Thu, 7 Nov 2019 04:47:20 +0000 Subject: [PATCH 76/81] Support NetBSD's OSS audio/midi implementation (#5277) --- src/core/audio/AudioOss.cpp | 2 +- src/core/midi/MidiOss.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/audio/AudioOss.cpp b/src/core/audio/AudioOss.cpp index bbd9a9507..cbf9278a7 100644 --- a/src/core/audio/AudioOss.cpp +++ b/src/core/audio/AudioOss.cpp @@ -59,7 +59,7 @@ #ifndef _PATH_DEV_DSP -#ifdef __OpenBSD__ +#if defined(__NetBSD__) || defined(__OpenBSD__) #define _PATH_DEV_DSP "/dev/audio" #else #define _PATH_DEV_DSP "/dev/dsp" diff --git a/src/core/midi/MidiOss.cpp b/src/core/midi/MidiOss.cpp index a8e948efc..c1c990b0b 100644 --- a/src/core/midi/MidiOss.cpp +++ b/src/core/midi/MidiOss.cpp @@ -71,7 +71,11 @@ QString MidiOss::probeDevice() { return getenv( "MIDIDEV" ); } +#ifdef __NetBSD__ + return "/dev/rmidi0"; +#else return "/dev/midi"; +#endif } return dev; } From ffce1d947a633881b78711062653c6eda1a6be86 Mon Sep 17 00:00:00 2001 From: Olivier Humbert Date: Fri, 15 Nov 2019 05:30:49 +0100 Subject: [PATCH 77/81] Debian packaging improvements (#5264) * d/control: http -> https * d/control: rearrange lists (one item per line + alphabetically ordered) * d/copyright: http -> https * Delete contributors.patch (integrated now) * d/series: removes contributors.patch --- debian/control | 38 +++++++++---- debian/copyright | 4 +- debian/patches/contributors.patch | 89 ------------------------------- debian/patches/series | 1 - 4 files changed, 30 insertions(+), 102 deletions(-) delete mode 100644 debian/patches/contributors.patch 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 From 33b36ffc5ea7889066a04d7823fa6d027461ce0f Mon Sep 17 00:00:00 2001 From: Hussam al-Homsi Date: Fri, 15 Nov 2019 17:09:57 -0500 Subject: [PATCH 78/81] Add some missing includes --- include/Pitch.h | 2 ++ include/panning.h | 1 + 2 files changed, 3 insertions(+) diff --git a/include/Pitch.h b/include/Pitch.h index 8a9b371b4..2f866a1c5 100644 --- a/include/Pitch.h +++ b/include/Pitch.h @@ -25,6 +25,8 @@ #ifndef PITCH_H #define PITCH_H +#include + typedef int16_t pitch_t; const pitch_t CentsPerSemitone = 100; diff --git a/include/panning.h b/include/panning.h index 8994df9ab..c043adf5c 100644 --- a/include/panning.h +++ b/include/panning.h @@ -29,6 +29,7 @@ #include "lmms_basics.h" #include "panning_constants.h" #include "Midi.h" +#include "volume.h" inline stereoVolumeVector panningToVolumeVector( panning_t _p, float _scale = 1.0f ) From 256ae6dad6d03cbad2c72a14939faf2aaea20549 Mon Sep 17 00:00:00 2001 From: Kevin Zander Date: Fri, 15 Nov 2019 19:46:09 -0600 Subject: [PATCH 79/81] Fix incorrect m_lastSoloed after moving/deleting an FX channel Original code by @gi0e5b06. --- src/core/FxMixer.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) 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 songTrackList = Engine::getSong()->tracks(); QVector bbTrackList = Engine::getBBTrackContainer()->tracks(); From 2f0010270eaf64efd716d775ddaffbb25818b3ea Mon Sep 17 00:00:00 2001 From: Kapandaria Date: Mon, 18 Nov 2019 22:29:08 +0200 Subject: [PATCH 80/81] Xpressive plugin updates (#5217) * Updated plugin artwork. * Update the formula in the presets to use integrate(f) instead of t*f, as integrate operation is more robust to frequency changes. * rename X-Pressive to Xpressive in help window title. * Xpressive.cpp, spaces to tabs and remove commented code. --- data/presets/X-Pressive/Ambition.xpf | 21 --- data/presets/X-Pressive/Baby Violin.xpf | 21 --- data/presets/X-Pressive/Bad Singer.xpf | 21 --- data/presets/X-Pressive/Cloud Bass.xpf | 21 --- data/presets/X-Pressive/Creature.xpf | 21 --- data/presets/X-Pressive/Electric Shock.xpf | 21 --- data/presets/X-Pressive/Faded Colors.xpf | 21 --- data/presets/X-Pressive/Fat Flute.xpf | 21 --- data/presets/X-Pressive/Horn.xpf | 21 --- data/presets/X-Pressive/Piano-Gong.xpf | 21 --- data/presets/X-Pressive/Rubber Bass.xpf | 21 --- data/presets/X-Pressive/Space Echoes.xpf | 21 --- data/presets/X-Pressive/Speaker Swapper.xpf | 21 --- data/presets/X-Pressive/Toss.xpf | 21 --- data/presets/X-Pressive/Untuned Bell.xpf | 21 --- data/presets/X-Pressive/Vibrato.xpf | 21 --- data/presets/X-Pressive/X-Distorted.xpf | 21 --- .../{X-Pressive => Xpressive}/Accordion.xpf | 0 data/presets/Xpressive/Ambition.xpf | 22 +++ data/presets/Xpressive/Baby Violin.xpf | 22 +++ data/presets/Xpressive/Bad Singer.xpf | 22 +++ data/presets/Xpressive/Cloud Bass.xpf | 22 +++ data/presets/Xpressive/Creature.xpf | 22 +++ .../{X-Pressive => Xpressive}/Dream.xpf | 0 data/presets/Xpressive/Electric Shock.xpf | 22 +++ .../Xpressive/Faded Colors - notes test.xpf | 22 +++ data/presets/Xpressive/Faded Colors.xpf | 22 +++ data/presets/Xpressive/Fat Flute.xpf | 22 +++ .../{X-Pressive => Xpressive}/Frog.xpf | 0 data/presets/Xpressive/Horn.xpf | 22 +++ .../{X-Pressive => Xpressive}/Low Battery.xpf | 23 ++-- data/presets/Xpressive/Piano-Gong.xpf | 22 +++ data/presets/Xpressive/Rubber Bass.xpf | 22 +++ data/presets/Xpressive/Space Echoes.xpf | 22 +++ data/presets/Xpressive/Speaker Swapper.xpf | 22 +++ data/presets/Xpressive/Toss.xpf | 22 +++ data/presets/Xpressive/Untuned Bell.xpf | 22 +++ data/presets/Xpressive/Vibrato.xpf | 22 +++ data/presets/Xpressive/X-Distorted.xpf | 22 +++ plugins/Xpressive/Xpressive.cpp | 90 ++++++------ plugins/Xpressive/Xpressive.svg | 130 ++++++++++++++++++ plugins/Xpressive/Xpressive_logo.svg | 106 ++++++++++++++ plugins/Xpressive/artwork.png | Bin 70956 -> 10950 bytes plugins/Xpressive/help_active.png | Bin 840 -> 546 bytes plugins/Xpressive/help_inactive.png | Bin 806 -> 549 bytes plugins/Xpressive/logo.png | Bin 4497 -> 1884 bytes plugins/Xpressive/o1_active.png | Bin 629 -> 548 bytes plugins/Xpressive/o1_inactive.png | Bin 508 -> 512 bytes plugins/Xpressive/o2_active.png | Bin 723 -> 653 bytes plugins/Xpressive/o2_inactive.png | Bin 602 -> 589 bytes plugins/Xpressive/w1_active.png | Bin 685 -> 590 bytes plugins/Xpressive/w1_inactive.png | Bin 549 -> 554 bytes plugins/Xpressive/w2_active.png | Bin 766 -> 715 bytes plugins/Xpressive/w2_inactive.png | Bin 628 -> 662 bytes plugins/Xpressive/w3_active.png | Bin 771 -> 705 bytes plugins/Xpressive/w3_inactive.png | Bin 626 -> 652 bytes plugins/Xpressive/wavegraph.png | Bin 9029 -> 9006 bytes 57 files changed, 694 insertions(+), 408 deletions(-) delete mode 100644 data/presets/X-Pressive/Ambition.xpf delete mode 100644 data/presets/X-Pressive/Baby Violin.xpf delete mode 100644 data/presets/X-Pressive/Bad Singer.xpf delete mode 100644 data/presets/X-Pressive/Cloud Bass.xpf delete mode 100644 data/presets/X-Pressive/Creature.xpf delete mode 100644 data/presets/X-Pressive/Electric Shock.xpf delete mode 100644 data/presets/X-Pressive/Faded Colors.xpf delete mode 100644 data/presets/X-Pressive/Fat Flute.xpf delete mode 100644 data/presets/X-Pressive/Horn.xpf delete mode 100644 data/presets/X-Pressive/Piano-Gong.xpf delete mode 100644 data/presets/X-Pressive/Rubber Bass.xpf delete mode 100644 data/presets/X-Pressive/Space Echoes.xpf delete mode 100644 data/presets/X-Pressive/Speaker Swapper.xpf delete mode 100644 data/presets/X-Pressive/Toss.xpf delete mode 100644 data/presets/X-Pressive/Untuned Bell.xpf delete mode 100644 data/presets/X-Pressive/Vibrato.xpf delete mode 100644 data/presets/X-Pressive/X-Distorted.xpf rename data/presets/{X-Pressive => Xpressive}/Accordion.xpf (100%) create mode 100644 data/presets/Xpressive/Ambition.xpf create mode 100644 data/presets/Xpressive/Baby Violin.xpf create mode 100644 data/presets/Xpressive/Bad Singer.xpf create mode 100644 data/presets/Xpressive/Cloud Bass.xpf create mode 100644 data/presets/Xpressive/Creature.xpf rename data/presets/{X-Pressive => Xpressive}/Dream.xpf (100%) create mode 100644 data/presets/Xpressive/Electric Shock.xpf create mode 100644 data/presets/Xpressive/Faded Colors - notes test.xpf create mode 100644 data/presets/Xpressive/Faded Colors.xpf create mode 100644 data/presets/Xpressive/Fat Flute.xpf rename data/presets/{X-Pressive => Xpressive}/Frog.xpf (100%) create mode 100644 data/presets/Xpressive/Horn.xpf rename data/presets/{X-Pressive => Xpressive}/Low Battery.xpf (64%) create mode 100644 data/presets/Xpressive/Piano-Gong.xpf create mode 100644 data/presets/Xpressive/Rubber Bass.xpf create mode 100644 data/presets/Xpressive/Space Echoes.xpf create mode 100644 data/presets/Xpressive/Speaker Swapper.xpf create mode 100644 data/presets/Xpressive/Toss.xpf create mode 100644 data/presets/Xpressive/Untuned Bell.xpf create mode 100644 data/presets/Xpressive/Vibrato.xpf create mode 100644 data/presets/Xpressive/X-Distorted.xpf create mode 100644 plugins/Xpressive/Xpressive.svg create mode 100644 plugins/Xpressive/Xpressive_logo.svg 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/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 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/plugins/Xpressive/artwork.png b/plugins/Xpressive/artwork.png index d5b39acee2eb1a99bec7c5581619f7436906b593..1f4e35ad51e06095d738315a49801ca0115195ae 100644 GIT binary patch literal 10950 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 literal 70956 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�F>nWc;KI~6AD!}HbH{Wr z<^A>p|MlB{q*H(nP7dc-x`kRwELMG)cRD#`;tdg9%Yi#3r~($@n$zPG;xNR-B#k0e zSq51q%471h;KTMkqUkFj+p_4omZm5;J~?DG9HHw5s-m)4ZMi(TV(1OYvaH`glb3X& zr^#H`CddP_EN8J=P<0iCp<_B0WnD6|M!Z|SC2tE9S>t|rho)-Ob;B}Ta4?vWMll~A z?~vpU$8phBohB26`;fY+8Q30{VYApTn2+ZS>>*`V^XAnToX*dASl<(65tS%Os{~cm zcw9V^l^L?6pjr~6gAqkrunl|9TalLx2Saq(;{ED9+h9Xlq~uM>e0)rlguH(Fn*Z^S z|4LdUJiEL>X=UoX=Kbm&mxmWDgC*9$rc?WB!`3XCM&M`t1|T6d47>qK)3FFwh^|AE zHI~r^NtSxwp%9!859vPkz7F(3PXrbPn>1iF7?6AfwRF)^mN{jXlT{_6>rj4o^X8Ag zY#+FO_KeANiXZtL9UarOO&=mDa$dc7N!2#I-#l=BbkaZQw6v9=QzeFu$A0fqwKWui zqHAb7iQ#yNND7L&(D!eG|yNk`~QSvPUdr>I>YS@R7GKz z_&j^|2~p8!rA6B#xOtM{rxBlj{yB;yePJvM?nnGDePvUq;xvO_f)qWr|@K)J=lk5M6`*x|Jd{rqQNgCblpIcdi$*HcszUZjBFLN2$ua4M#Df90wEgOrbCq#qAXWb!tpEDDCsn4Q1FHXU4d zz%LKK^by&j#Ifvt8KlvnX*yM25~nd$Q=uyws;Z%(6GZ_sGNxfslqFf75fu@YsJNJ) zGn*a}tU{``BCBI8%jVb5zvbuqpZVm)3*sa~myJG~jzL}2-+%KhMU`V47Ng0K`Qg0BzVj4Y zbyx>0il(6H1jpk;cH2E=nX?afNQ#VR8_dQNcH2E!nKE<7gh|N3c*J78!qH8#G$qVa uPLGawxVuGGB&xDTQB@>KMnhr~2mEjNPV$FS65jd%0000w$$WEky|T&0ftFLK~zY`)s{bN!cY{&e|bKe;9#p? zK*&}olrDm}gbq^7(vRdfs*4VtI=DInDeWdA5?qP~ihuIwbx5jG(pJ&IoavE!b92wT z=e!pUVAbi|0xjSkD3TqtftGIDj+T&k0j|g=F|Sr(#DVBPD1=WTL!5sXGeudlz>_*owy3PV^d2*+d8a0sOm7qwa(^L^BOPB<9A zVv*MBy*!mC(i%PFU4VSGO8)v9f4M}tF6(X=r4*u4A%AlNrb(D=&<_;Fx#&X+0-}$P zczt=f4HyPF(~KvR#8cI?&qwq|!vntqOyz@1uY^X zlbVK5nw%1){CO>gdA*-|r-9n!S-pGCcfNDaJ?EbLNW85ls3k&x3QPT7ZmmN_X{JlkGjq6f<1yZToWiQ04@V;PC@b>vTT51)!m<%UY<8>8 z<5F;NSJ;Fx+IbvC$@)(uQ@B6+8Uw?B&(If-006Gt8pU`rg_g!GxH<9?19zXIx3iU> z2xY4H5;-KuiqlkH>X1O0s;^hLRWxm{$;rWsVfEKE4G&+8BQZIx|6bKPM(I zGy4N;%L;XTPv-#uz^4!IG5viG6{UVI7X<)^tUw|Xmb4`sz|`MFLhQ^{WPMDSuD$vx zG1XqC0DxorcW}8f6;Z^er80`*iYi-67=2VmQM_hT z&U=lC2&xG`|z1xSVV1A2-V?w@jF6gX6rfQCaBEpmz^m(erE0` zo{v2;VXAAwaJs!*d(dBi%BpR;zse|rp^d^34gl-Q0|@v$w!P~2766#jllwF+c0veb z)vd3;ew#)2#d{{q?emrJ2Fkeh=GqN78*a)O!z#lMULjQCM@I)AN8)Wq4O+DQ(C-I_ zNYIuRO+oT`z)X4r$G_wiVXhBe5shD2FkScqfiH5Ny8L+mgdxl2r|}n~M*xs^XF{_8 O0000|W` z)05%g!Dx&Z2t5&=z(?YZs70gdFK2{d%mv{NyOC*YK1VgS@c+=--;AkMv^#N)IQ7nKS^2%P6qz} hFgIzP0BX8v+CPa&s3c`Q-x2@-002ovPDHLkV1gvJ)k6RP delta 698 zcmV;r0!96$1f~X%Q3~M!3KS*_3^Mvtky|T&0*XmQK~zY`-B!Apis&M%`7Yyw<$74j`lce@M`e*Z$5v;mv28Te5G2&(2;ITCF59H%VDFSTeWLOQzNQO zZ5NT(i@5mYRZE=Z12${6YBb|{n{{_$5L6K0_xmAm4xe(hhGe7z zC*x83dqj|A5JF%W26v7HNp6XMiL%SWe=n7h{_v>*b1D{r;JXLUioSK1EMt4MZ(f4S^xk507*qoM6N<$f?7XDOaK4? diff --git a/plugins/Xpressive/logo.png b/plugins/Xpressive/logo.png index 68b613176d684bd586ceb10ad2053fcf8309e7d6..555c3f13e682a44b0ed0ebecbb233f5a47470bd0 100644 GIT binary patch literal 1884 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 diff --git a/plugins/Xpressive/o1_inactive.png b/plugins/Xpressive/o1_inactive.png index 0fd4f8b2989d027df7529e31e3c28a34d7690230..7a6b603e3e79540dc6c86a90980343dcc63c57dc 100644 GIT binary patch delta 471 zcmV;|0Vw|b1AqjO85#xv007MxCy4+600v@9M??Vs0RI60puMM)ks%&`;|dB37y$Q2 zOz{8!03B&mSad^gZEa<4bN~PV002XBWnpw>WFU8GbZ8()Nlj2>E@cM*00Cr4L_t(I z%cYY&io#G7g}+3>pNIrR5V26u`e7w#BXI+>2f+>K00T>R4oKB~|>9RV2<2Wd#Fbo5K%d$wP(^RWf>h(H7 z5U^Y>Bh9J delta 493 zcmVeSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00DMM zL_t(2&z({&%K||Vo?S%^R+GpbDkeejFNjS9llg)MIjhJue}BVS#Bg9T8T1br44W(p zqQzhmlNW^9)!R3$tRL@-;5%WNdEl96cIF|LWx>B93;>Nr;|(Q*NGU(ihQnbP0E7_F zsFacrq7&VMQmS(GKA6YjaWELHRx2SyE|+UIo7rskxufg4%jMGZyvMYhbKmz{t=8po zsZ=VlSZp?%*?+d}x~^duQp){)&lsCdr^#fJbN2x|CkMDLnL?ndt`+WeY*XvSBA;il+RUw4X z+oF^PL2$iZ-|`8Iw4Y1##^_%;|)00000NkvXXu0mjfSBBe- diff --git a/plugins/Xpressive/o2_active.png b/plugins/Xpressive/o2_active.png index 51897412d42493bbe5e5ee71851fe6bee62c6136..4e3b5f214d72036360dec9be83298432cda3d78c 100644 GIT binary patch delta 583 zcmV-N0=WIt1&sxeQGeqK3JW6@rYJ`u0000TX;fHrLvL+uWo~o;00000Lvm$dbY)~9 zcWHEJAV*0}P-HG;2LJ#8@kvBMR5;6}lTS#KVI0Rl&%2D})>sr7jag}EK{~Lo3~|GH zAx4lbg1VTopi4xT==xI8!RSzV5_Yl(>7e0t2Va6h55|Tarhnoe-X`T@y<3}(YI{5E z-QZSY#Aj6W^aeZajkF&3A%_Opcfdm?o#N^Jn*azQaJu&3JL5;bGK9@$1LzkK zRWks_ojv4-&uOHJDfCm4gru_|581d0FtXq05lzJ zt|$ZGX>J7|xw2$|tuB1#Lv#uu1RbaQtguQ9AuL6PVSm*8bUO8w*CUTHN<}UY-KFJN zrxoToe6*~bT%%YlRxj7J<+9Y*oKE01(Z*Etz z|HiWi;XoQdTgNE|?k^R9o%0000PbVXQnLvL+uWo~o;Lvm$dbY)~9cWHEJ zAV*0}P*;Ht7XSbPJ4r-AR5;76lUqnsVHAbGf6n>O@rX!K69y@0I^MFtK#WR^$|$sy z$bw1{B+7>nB7=G>ib%+^z*4$s5|oyLP-f5+g4uBQ!W~)BD+tciKxtSTs55`Gkk91i&*n!Tpv>+Zentzm}bT+5#VN2Zi)V6zFwX!BrfQi4+|;5ol8jQi+X90KnyLLpLP4A?X|JWPDw;q;rv+gomH)e6RfM+isQ&C&W;K%^FZqW3!4nWFU8GbZ8()Nlj2>E@cM*00FT{L_t(I z%cYaQisEn-g}>;^_>VylMZ`kElp&}^L>n=MHp13EfY0G0h!3Hp2s=+8i=9^f&@QA9 zL<@_U0SSV^ZPXo+Ep|MA<-OeRo&)zv073{A=mSmQo&VDZ&{tJeNLSErAi?)_02+a- zqgOy&=legd(Kw&aOs7*;s}+aCfp9oXKA%U|b&|;>uIn-w4DQqMcpODh&~=?)FbL3; zgb){i(P)HaS=4GZ>h(I??H0o@2!%rQdOZ?}zvey9!!%87+osijYEi9L0SEwWHXAI< zA{L9$Y&MBTqZErpN~IE>=P{ej9x_ED5z^^20Q>#^UJn3lw_5;GsnpFf0GUjNul<|W z>oxQF8~{a89%28IBuP&-$8j(W1K;=QbUNho`A1kbo4s51egEFv?RI?apH3&n<1wD+ z(QdaXm&*@}0sy&xTn<^5IUbKpCKEi*!?tY}iv^KL1WnVpTrQZV$$r15QmLS6+H(>i zgbTdiPGh-T;<_$xZ*LR|h5KnZj>B*`d;-X_Ot;$w_>_bYzkr{-u8-RX99{$+fPO$# mRRJ`v5BvEYM?gbWRq+R9i>I-$HFU)Q0000eSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00GoV zL_t(2&z+Lb%P~0rpl%eq>>#tR)sx zGbO80GB(OW%7#ey-ZAqo?i+7!Z%;k%S=>(N-p{@Fd(M~1WHRtyVFZ9&F85cJVHjQ4 zzri}4ju8L|A%9kNU1u2PoxHDLS(fH>{gCJLxz%dPvP=kZyWRPG-syA#!2N!2Hk+%} zO4Bs2*IO!;tbbN30I&dnF}_?b#bQwu#c((rjYbtkDVNLp{T^f7Znx+2c`z7EBocxk zG#U+r(1#q4$Jgt%P$;C+>0~lluh&&o?e%&X(@GTw5 aPvaL|eiog_CX>@2HM@dakWG-a~00059 zNkl+ORA2PcP^nuYnsqFVdGx2+8>E-%nu>qyb)D~yiI`mglHmgJpXwAyCSrEs23IbOnQuR_k^lez07*qoM6N<$0fGfI?ScRR delta 650 zcmV;50(Je)1g!-jiBL{Q4GJ0x0000DNk~Le0000K0000E2nGNE058Nm@R1=ff8Yxh z6C@*tXsTlX000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0006NNkl3!Y+9-q&xUNT52myfWx*MMVjOtndzy>uVV;49xd<<#8IErhd=Qw@kD4)N7 zz&MJ>6E`?@`3TEvxp5Su6F0ed=Oi|$F^>8TsEwjCoMN@ILg`}xr6u#le>4I?{{1Z4 zDDtIQLfcws4(()dX`bhk51DxN6d}BRZK?sSB)RVZ0Qqv7r7tDE{rE~E+DooDO+Z7T zlqC`AL0iey2j_V*eis){s zu3n^+WD99x;Z7PhHPF@?A)R|iDsj+fvVPw~1Y@V!Z24YJ` zL;(K){{a7>y{D6rAs&C@3JMDl3g1gF=Kufz9cffpbVF}#ZDnqB0000007G(RVRU6= zAa`kWXdp*PO;BVmWd{HN0gg#TK~y-)t(3j0;$RSlpCre^1a%dHn#9h2iC3WBfTy*w z*4i8JA_OnN&dnXTy^vsMBNpZp(nL|QkYKhkVb2eoKi_VKnP-3A8TdX4!1KJ{zzApq zdA=_P7}>VHl$cuX9}^m;vX zU1z;s<2VlWdYw+E!*n`jx7($(!C-)@s!7j^E?}lG<*!%WybE z)3o=8^$P?MIRUR8^%^Dsj172*VKH_o-H^SeAtlf+&gz zf`CjWgRbkJ2mim~cDp4A0xZj-R;zJ7pINO|+-^52l?sZYd<~qe=(;XZ6k(cXI&866 zeCZ4TPp=(^VThtAl*?rlMWI+M5{BW6n$LodK)z5Ykjq@3zGCTN;QzuyNqN}lKa0iJoRoaE&l9tb@EBiXj?CD6QoAjh9N1)8>P aFaH63d6FP-C7pf%0000#7ev>NpPhZM_jf zrqd}RerZrj|GxZOtJUg_5F(}g(m+H?X)NMj7-L%NlMzAyU_PG@hr`$F1pu?zY%myv zVF&=O>-PKoFbtJaN-5WMCzA;PD5WA;O4;djlv12?A%ySyl+yivuXQe$OC%DU^YwbY z*=!I|N-2bhJWDBU+a`o?&P~&NKA+ug*YmtyuNMTtXfy(V#bWVzJoLh`%?M5=lc`k7 z^E}fuv)OF3+1%}R=kr-9)oQh*l*{Fk5HcQ*5fK3X@T`=wZToV$oKB}orBW`JgCO9X z8-`J@*YyMKQ%?qf2o^#JAuP+f-|xrcu~aH$G8shNZnup_BYvQLB4Vtg$pBER)fi*9 z+by5ZBVwUYxL&W8Wx=P?aI8OI##pslH4G!2P6I%(SR{n#o&N_@$8p;2cAScDq7r9A n$L4T2{5xSk$hPnMzk}ZaIqgR7(&?4!00000NkvXXu0mjfg1_kQ diff --git a/plugins/Xpressive/w2_active.png b/plugins/Xpressive/w2_active.png index cd4729949e171992a25d089f90a5180649a20d74..17d7b53d935a12a59d14d7b253e0a3ace613f751 100644 GIT binary patch delta 680 zcmV;Z0$2V115123j0013nR9JLFZ*6U5Zgc_CX>@2HM@dakWG-a~0006n zNkl|{}T@(U$L?8{m^2Me+bA#@@_f!KoGC3WM1pzghrcA?dc zP+m%2MBQeaW++|c2VN<`D34(ce?i@_scUVdve~hVoekFRYX6%T{yhBnKhN{NuK+L` z4_*TNKnEc6?+O5ZceN)Z7|I;>2ynVwrlHPEGWC;4EXqn)!)0@!I#jeZjdUhW zc;g$#%T8c3+Y7*2SYvYTe=Pz6t(RL1!2qfwoBGpgh}HG4C=M0noJu^g%iPC#4u2ow zv^sM$1Ym3DJCC0~Lf3Wf-+DmP`KDs9;>gZT z43PSjqSx!Av!%136X|boG#25QREGVm1IZ-OP-i9@i)0sP)abg-e$a~{Hn!HecJ(@4 zZCyooP6CpETwha9O=T^+i5;9aCz46Zr;NrTh@!{^n-hTTAKNS~F99&UFvax36adZ2 z75eY>10;pnc<>EylhP`XdwGcxLKA>rbXR*qK)dmQB>y)l(C)7Gg#G~h+`ll)ZtaQy O0000_CX>@2HM@dakSAh-}0007JNkl1wU|D69<%TcqGgiH}<9H&tkHMImGqAQgx$~J+Liy#oeMbRRnb}bAf zh!kuQghC)j#B{-w!b`=7XkNzge=?3TIDtjjjhy*gj7}N`E&NvJ@O|gwd0$?RQeRPL zu!$uAl6RJD%CdmJFT7A{0!2|Uj4-UCC;%9SvEljeTH6xKTYe+Qh03d3Wf6$&)NHDa_ z!lyZeRGIaAP*CuFoJ48@-@+ux+fwNrdcnJqZVGH=9NmAGL3bYyo;D&iv1XyJlAp5| z0AIkv;?e@&e|{w|yBM$EO_YSWg&FcJMJ#>^kYGxp@>mTg4pb5wy_H$N2dS&;CGXyq z!S=)yy#5JHaVAoe)5xJ1uJF%JbF~!Fb3Ik8x zOA2y}QB{?hISJF#10$xOH4@s3fLw-2ca+McxF>}toHVZ~~;)8l$YcfS)&m+L(Y zlg4AWIv5@sAlqz3N{P*q%lPC6N{hV!Z24YJ` zL;(K){{a7>y{D6rAs&C@3JMDn92u$jGynhq9cffpbVF}#ZDnqB0000007G(RVRU6= zAa`kWXdp*PO;BVmWd{HN0s2WqK~y-)t(479;!qfdpHfVe&^j0zq^%|vNo}7 z+)lgzZ-N`(BHVcq(->Vldtw_|vB3?ei!Q9B5+zN;nZ-~t47-0B-sQ>nJ?DGh^P>QS zVR#PofDWMZ@A843<2WzM0{Rp9#%44DE=!9^Hw9(E>Xm`c)6)|{5a4+puIrLz8Mn8$ zNGZ9wxxp|DMxznF?{j>7jOTgW-Q58orKDP|a(a5o#l;1xsseP%fNoh9K@cE>z;#`s zC_+jJfDi)1Fo=Jm2ms5n&~=?|w+p~*Hsj&pf#>IEG)<%3ZUg8g0Nb_!md#NVv9q(Y z0u(~@w=HTFf>2%6)IAni5pR>QeUu5|E_$L$Y@9&XP za&>jZ;o;#rxUd)m0ePNdS=Ms1e!ssKLzZRuzR%a!7oO+QYPD9Jl>eSMNfK05rO{}h zsw%ZwZJAwBBc+5TPR0+fI2k@QE$}e8tWP{KN&?`BP^8#EhK9KZ( fCj~AY$9ee$YuLwPkeYGq00000NkvXXu0mjf8fzlE literal 628 zcmV-)0*n2LP)C$482~`UdcB^@<*wH& zB0fJqvn+c&9ucwKZfCPuK@ghFCdYC4e7@0WoK7c2QND_0SxzRCilT_3c)Q(}%OxRX zHk+y1ZnwX^y$uF~OeRw(6h@;_tJS*QZja)4JPrV&DDLr^?L2~dOXjwEL$uVpPrr`o)Hld{eC~gFo(mz z;c!q&old7DN#Sr95&Qi<&+~4#+wFEwCX?ZC_~@)EhGBd@-)6J1SS*O>a=CW9ojUV; zJ_i6vlDgfl`r)Zm3IIr@Qi;W4cPjpY%AE}ro5f=Bcf$UI?d5X$v*KUhryjt9k`j*q O0000_CX>@2HM@dakWG-a~0006d zNkl<%?`f4B)gTr%k%Jie!mZ2zQ5;rGysX} z;$nVca0MB1O10eG;!$fp~(4!Fd9^WN88)g6deh2Os0KIINe*wrB^8ge+ zec-Tl*p=(7F1s6mWID-%I}eFHjo~=wWaV9gcw(so)(Zf#vt67k=2S@kiGFNW`w_70 zbOA7admO8IkQOa88VvxaO=na;M1WH#^$eP=lq)4ll`@559+%C9*=S)cyGEngp!j8r zW4hzmtai0|Y;ugfdKG}7e@j;w9vW89gwDq8Xsdp|kzwQWCbGkge8Ek%w#!O-m4n|0 zNarO)tyXQGnVKOsHH*jXA+`RNx%k{su+u1w{k7O_#oyp^r9_{o!+zF*s1;R<09;B+Ww3G=xDMzo zCJQFR0K2tsNHz&kE2=8Xl@fv=aM30KAlW1e+XW_HJYlz9Wx!x!^!hDA*G4_CX>@2HM@dakSAh-}0007ONkl4TBaws{=3R;d##c<4Dz|l{y;uh8GC^ z2%rd=p`aHD3IEqVgsR{V^%1{0fw74oEgcOM<{skUo-%p{-{XE#hfr4=YBG+D-2nJU zy?mbzG52$Z>~t4{!5*Rn1VTQtEqNGCMv4ncDcN66QQiRngb)Z#URjD}6ztrQ%$7}C z84UIk8xu=Hd?MLaCoenOe;FMQu(0?Whs}i}!->P@P$T>8lSX)^$ zsN~r4>GyjW81BKGWW|!2$-rFefX`5A<&F#l_od(HJsPLE?Wn3$QJBExJ))x_F2 zTuK^8mNkbDpSws;vm%7RX0hYx>!u)YFPc%Xudo>Z$N-Pp+|15RlWWhX^3=shLaDm6 zQZG4vA_Ar)Nrc1UHwd)L!2b{6O?T>-5-!JGk-Y8&DGKy3|C~iC-@jeEVV}bvfda_n TSmoI300000NkvXXu0mjfXQo6i diff --git a/plugins/Xpressive/w3_inactive.png b/plugins/Xpressive/w3_inactive.png index e5b0bc7d9e1c94ab1cbaaf9733c12fffc4a46489..d45d8b497ab51e777c96856de43f5b2c8f5930c8 100644 GIT binary patch delta 635 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 From da73ddd242dd699bf32471c42662016b358c6e1e Mon Sep 17 00:00:00 2001 From: Martin Pavelek Date: Thu, 21 Nov 2019 14:44:18 +0100 Subject: [PATCH 81/81] Spectrum analyzer update (#5160) * advanced config: expose hidden constants to user screen * 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 * minor fixes * build the ringbuffer library as part of LMMS core --- .gitmodules | 3 + include/LocklessRingBuffer.h | 132 +++++ include/RingBuffer.h | 2 + include/lmms_constants.h | 43 ++ plugins/SpectrumAnalyzer/Analyzer.cpp | 51 +- plugins/SpectrumAnalyzer/Analyzer.h | 24 +- plugins/SpectrumAnalyzer/CMakeLists.txt | 4 +- plugins/SpectrumAnalyzer/DataprocLauncher.h | 52 ++ plugins/SpectrumAnalyzer/README.md | 34 +- plugins/SpectrumAnalyzer/SaControls.cpp | 46 +- plugins/SpectrumAnalyzer/SaControls.h | 71 +-- plugins/SpectrumAnalyzer/SaControlsDialog.cpp | 133 ++++- plugins/SpectrumAnalyzer/SaProcessor.cpp | 459 +++++++++++------- plugins/SpectrumAnalyzer/SaProcessor.h | 70 ++- plugins/SpectrumAnalyzer/SaSpectrumView.cpp | 127 ++--- plugins/SpectrumAnalyzer/SaSpectrumView.h | 17 +- plugins/SpectrumAnalyzer/SaWaterfallView.cpp | 207 ++++++-- plugins/SpectrumAnalyzer/SaWaterfallView.h | 26 +- plugins/SpectrumAnalyzer/advanced_off.svg | 243 ++++++++++ plugins/SpectrumAnalyzer/advanced_on.svg | 224 +++++++++ plugins/SpectrumAnalyzer/advanced_src.svg | 238 +++++++++ src/3rdparty/CMakeLists.txt | 19 + src/3rdparty/ringbuffer | 1 + src/CMakeLists.txt | 3 + src/core/CMakeLists.txt | 1 + src/core/fft_helpers.cpp | 1 + 26 files changed, 1867 insertions(+), 364 deletions(-) create mode 100644 include/LocklessRingBuffer.h create mode 100644 plugins/SpectrumAnalyzer/DataprocLauncher.h create mode 100644 plugins/SpectrumAnalyzer/advanced_off.svg create mode 100644 plugins/SpectrumAnalyzer/advanced_on.svg create mode 100644 plugins/SpectrumAnalyzer/advanced_src.svg create mode 160000 src/3rdparty/ringbuffer 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/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/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/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/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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + ADV. + + + 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 ed0deefd1..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) 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/fft_helpers.cpp b/src/core/fft_helpers.cpp index bc7d289e3..2cf54b7f2 100644 --- a/src/core/fft_helpers.cpp +++ b/src/core/fft_helpers.cpp @@ -66,6 +66,7 @@ int normalize(const float *abs_spectrum, float *norm_spectrum, unsigned int bin_ if (abs_spectrum == NULL || norm_spectrum == NULL) {return -1;} if (bin_count == 0 || block_size == 0) {return -1;} + block_size /= 2; for (i = 0; i < bin_count; i++) { norm_spectrum[i] = abs_spectrum[i] / block_size;

aCA@j!VGXO8EgAlu;)c1g)$M1Vb*@D&h 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 diff --git a/data/projects/shorties/DirtyLove.mmpz b/data/projects/shorties/DirtyLove.mmpz index 177c05ce5162094d4fa92b51ee6cd1be0755baee..37b766f4d29fd4c1a110ff642c0b3b5014c0de79 100644 GIT binary patch literal 8595 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 z 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 Z#p(RV*qTLUG8W(K_SY*y(nBWnzW~JK7#IKm literal 8660 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 diff --git a/data/projects/shorties/Root84-TrancyLoop.mmpz b/data/projects/shorties/Root84-TrancyLoop.mmpz index 22bd5f2fad7d02e5c3d1ab85514b923889a26b5d..f5eb032acbe4c5b31c57709bb4983443300ea619 100644 GIT binary patch literal 4386 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 C1&MP2 diff --git a/data/projects/shorties/Skiessi-222.mmpz b/data/projects/shorties/Skiessi-222.mmpz index a5683364580a8351c71e27bfb67090dab78786e7..a7076949cf62b5e3a8869ce74a888a735da7f76f 100644 GIT binary patch literal 4747 zcmV;65_IhV0PGETob5f?a@#tx@8>IcbgS+>=t?BGGm$gpcuDNzMYd(J;Jt!%9D?jH?iSf#kI^{C0zs6cA)B6&R*s0{QM?dPM# z)#yXDLwTA3U9I=415L}&%m9_IP!G0&fEiSwp}HP)Y|U%;_bT!8(9-uRic*OyFb4*7 zB6Qks0Cx}nKtDZ4Z9law(^EAQI@C~ewFezh04mf->v(=~K{L)L>Wx1{!!FxTzYb=n!_*f$mi(*V3&dB0|+n*K-gx zrWaH)CEX{QL)__(!xCFH{r?|S7ctO7H49RO8n`gUHPmPSm!q0JpXh08srJIod5&i5 z&~n?Fu49g-zNKp5s`o6Ad`P|F z_9`qAs%Q5*&>MtA#g8EU7+@k{Ik-PvO~-vr7l3R5iwh9r7@u);N|5walBsg2cT`WM zx+CcMyyymMi4>*lKo@nQj+oGG571kQVVJDAp^n<4bl1iTTu1nAPlx7EH9Wuny4`_# zz^mwo{|W*2ExqIaa3^LPaR}xJ#?&Ak3Tko(E*_s@hxE7sw{M3(>`u;5_=Ty#PmPh? z@DUupKXrzyP#xF~x)!uW=V(OaFHd7FCX(4Okr9P;Y{h00iNw7;kxWb@?(t?t31T{D zklCOEZBLc8`JQ4&0(=|j&^ zjld#1niu0>|23@P%2wNFf@Rn)wurJ|s9qh@8Vf zIQSg{LRdT)kgDU+z-9;g6q?OLOTuh$t^iyXI7Oa~!WW?M3Ol-wraa|*DCB)7SYxRJl=mra2pRm#qWk}#1b@!}jHu0%zV3e~uI zBTgsoGcBxi5LW(2|^@Z*{DCzF~isf zNX9mhj@#Izi@7j|ZJ}~Wl#y~nq>7xJ7J36u6e-kOqz!Ty=Mb3?O$5_8hmW1{@d;!B zgvkD6JZO~7U;}O@`m}91#Fm8&wm7?OIoGx#X4__GqKi>{$M3M^dq$;n<06-99I#Bb zb$&KJo5$z*ReH}y=r|CSLYEfvecC!JaO+5&6?2_0A@&5ml|)Lz!G~*?C~7F6MIbT@$T5;0_t=2 zSlM24EMQ&{b4<)}4m+=zK+IXRIlY(i_)1RhC3>GQYG4W36&Xc7$Nky(#2pcLw1e(w z*Ovzh%MgD={Lvh~6MIbT@$T5;jV})xbSjqqhI<5AFn5oj!mYhW@Imu5bEtM;Zg=4H z4P{!6q3YU8;CbRbp#C-<&BSe6y6S0Ra>`W=TZcD&74w6AvU@}Aq}hMr?ymOFtJdk$ zWFXr=9Y>hZEtM9`{&=Wd9e1T_+vZf7?q68L(aqP^L-q3Vx=Ooj>tyH*j!w^n%L#j; z93I}BG>smV4*B!DF+dUkSg=ogee9dRQGvCl9hD-wf!#zxT#N?m$16s@B=d4gI}& zG8yte^)rXQAK(0-N7sxxe6fBWK2-nuKCD)+ubs!Cb#gX#q{*EKtA~?=<6(b%dnxhN zo~$bRKBo^R$0yG(%t5<#UVUy}o;07U*WRNj_Xhjb>eJI<6Fh!DK9tY($rU|3;3rMF zFEv~A&+*YcJ$UY1G!@IeZ7DzQ^dtJf6PisyY_}fev3ASQFJJAm=F7qP^`mmb-|o{# zKW?R_^wPR$q52MZdjH4hsY!q3j$dfz`Km|%?4FIA&hy_sLzd8>JSx^@x zzJLwuZsXhvp_h>PHg4w3ZFpF6Gbbq6%*m0>oW+|t*^-+%w{C08TAMk!?2w;AZ}(=- z*&QdFIbU@%=T>iLi}$h#@m4k*fe!Yv;k|CFZfD!TMkO34FCT^|znUyS2HC}=FcZ5d zAfF4Mp{8AZ>f^o52^SOaBXIK^_(thi} zNNl3q>5)O^ie#=x=8AdnEt@NHiY!an#J&$iCW~aUxFwTCz+qx{-zRS6Y_R}6r`c;x zHs{P1OO1>RdM6B~8n5{XMB zE|Ivzw|9wxA}fkqz!BmSiA&rTm*{Kt?z_aTjJ=Rd-3|v&1W6CdVE{-BClqe@CyOw$2-})P7(;v_@rlGI5})`Rd?L#OzzAel81aeQ z>=PySU3^uyl>rzMncU$B3JU;<*^`m+K1arqhhDj+>cC%W+Zwo@){f3!S^fkp;9o&G z=bB7@?IW<%K}WOj`2c9G(}u2_zbG>g5gvQxx8*>5B34MfZdrC@ExL|he{gZ3o_d1e z6aH4;Y424!s7Eec%rw=oL&>?`0Lui|o)-0z=MwP+H%9Uz`&!2mF}rlpAhq&&M7u{O zxi*qq8~M&p8e&o>4W%5~>zpuBY@>q}Y?SKT~S=_GqCqXa;aSS`y#niSm%9_Tq?Wsu1GEyqSykGmt1Z>Y3-+9ea-G$ z_8MzVX2Duh+Wxg>Vxc)}m07^6*I#0S=@QdF#M)nDa%6@1&dDSzOtQlKKr2kb3Z^SL}>R?u##@5KnS)(m_S_pk!9R}HxmX0PO6$dvwfF?;1O z^M_*gk}>YS)>pk>ZQXKVhv8NYa*N_eh;bM3>a~L0O#Xhi#6Bv(GYkoHzjHE4n45&T z-+7pOORsE`^VXHh-P#sj)&}yBRCqfY6J9&Ui@D)F1&S_26Xw7~_n~oM4iHzOqWB`T z*&xDV5OFbx6oM3gjp&2Oi)&G4*YXxOwt1@k3nIg^;;n5MJ-F%2ucfHZxlX;w?QL&+ zTVbg8g&*CfwAH@^R4M)*F{QEowR|O%w$Ad3JnsfWVG6kem;53B3)ykuhnS`G{DzM%Z^KwGtwY9_NclOOz`%-&Ff@S}2jGa14U%57psexG7*B*pkanZ215 zTCVl-V0fk$zNeZzf0jQMtXDBgJI3t|9X!D<_!tOtaoZE6b%w7b z51!yReeeVqB~0UVsYJ4+@19JOEhX8~cb+W;A0k^iH^~VWCk@#$SyygxJtSAU1G&;S z%z-(Y@hV@&<&Mr*bS!FQj``)*9!{&YyC>~~{nUj3f)wr~>-Vd21 z6GD+p$otQPfTEi#vzZX`-B=!kX- zl|$t_OYo{u=?XxaoK6KO`rBdOfi5m6M^alY$*TvU2|F7rZ+Oyd=&TdzynH}u(t9Q8t4cpo-(VzPfLOedv)OWiC9Cpo* zS-!Cp)8?f+Hqe?KF-3DVe?^WL$6Ckhqjjq&RH#1GdVPF<0=_tV92i<;=XeIaGt{wW zXfL7VL96HKQ``%G@qvQ~c&-id;{gD?)7TUQngQY z9(FVwu3Oj$vwS0H5aWB(vDbG?Hy|+qpBAv`OXJUf9UShr_W#xR^YHSZb>BRqzPHZL zsOIh0vy%g=Qlse~+yPA=whn_Ae4U}`ql*ev>3g32iKa)RQGLYKEvHAfuIcNegIeD+ zbe^HnnqO;s^^Vs;`q{vRUmAU=cD^(W=&7OJKO>mF2ghE;cQ?=sh7J7%De(k(onX#^ z0qC~tqKfSQqjZh>f9#YzSi?aS_zC-_+Q?Du&(weZXwW|9mj)d)_F#1;lwY)0p}MGz zT30nRee&rachKpmruvW1L9vUN@(BRj3!g_mOFxMW69M2#J|T57RQ)ri$&TwaRHvtz zHP5m?G4}X#^!#9XNI_CXI_!F>0>^K~FR49ywFlj5Kh-o7*$Y(qnZl&Uj|d2f3=wS> zQ*@)6E_DMPt(ziB$j{rjx{o=i8XMjQ0u5b?fS@|)DdS< z%ZRZy`it3$d5p#S?|xQmn~7Y9Zi8S!!1m Z2(@aNJ;ZHVHw?EHHuL3={{pKE-FCwDViW)X literal 4825 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 diff --git a/data/projects/shorties/Surrender-Main.mmpz b/data/projects/shorties/Surrender-Main.mmpz index a94df2497ef56987ee7b0a6e93a42bc43edc1a32..5565811708f410837b3146c81294bb11fc6b7dcc 100644 GIT binary patch delta 2325 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 delta 2392 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 literal 3906 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 Rbv-X0i&;)y{U1;NJZl}9VPOCO literal 3924 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 From 9eb6e3fa33346402520576ae815f5cbce5bd53a0 Mon Sep 17 00:00:00 2001 From: Hussam al-Homsi Date: Fri, 13 Sep 2019 14:03:26 -0400 Subject: [PATCH 19/81] Update .mailmap --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 71b6697c8..ce10c7d24 100644 --- a/.mailmap +++ b/.mailmap @@ -29,3 +29,4 @@ grejppi Johannes Lorenz Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com> Noah Brecht +Hussam al-Homsi Hussam Eddin Alhomsi From b07c007a27d660fe576cb5c852e01db7560c9e73 Mon Sep 17 00:00:00 2001 From: Kevin Zander Date: Sat, 14 Sep 2019 11:57:44 -0500 Subject: [PATCH 20/81] Add save/load of PianoRoll marked semitones (#5146) --- include/PianoRoll.h | 1 + src/gui/editors/PianoRoll.cpp | 42 ++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/include/PianoRoll.h b/include/PianoRoll.h index 4451a07c5..f56d791f4 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -95,6 +95,7 @@ public: void setCurrentPattern( Pattern* newPattern ); void setGhostPattern( Pattern* newPattern ); void loadGhostNotes( const QDomElement & de ); + void loadMarkedSemiTones(const QDomElement & de); inline void stopRecording() { diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 5edc5d47c..a1fcdc6d8 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -24,6 +24,8 @@ * */ +#include "PianoRoll.h" + #include #include #include @@ -46,7 +48,6 @@ #include "AutomationEditor.h" #include "ActionGroup.h" #include "ConfigManager.h" -#include "PianoRoll.h" #include "BBTrackContainer.h" #include "Clipboard.h" #include "ComboBox.h" @@ -655,6 +656,32 @@ void PianoRoll::clearGhostPattern() } +void PianoRoll::loadMarkedSemiTones(const QDomElement & de) +{ + // clear marked semitones to prevent leftover marks + m_markedSemiTones.clear(); + if (de.isElement()) + { + QDomNode node = de.firstChild(); + while (!node.isNull()) + { + bool ok; + int key = node.toElement().attribute( + QString("key"), QString("-1")).toInt(&ok, 10); + if (ok && key >= 0) + { + m_markedSemiTones.append(key); + } + node = node.nextSibling(); + } + } + // from markSemiTone, required otherwise marks will not show + std::sort(m_markedSemiTones.begin(), m_markedSemiTones.end(), std::greater()); + QList::iterator new_end = std::unique(m_markedSemiTones.begin(), m_markedSemiTones.end()); + m_markedSemiTones.erase(new_end, m_markedSemiTones.end()); +} + + void PianoRoll::setCurrentPattern( Pattern* newPattern ) { if( hasValidPattern() ) @@ -4697,6 +4724,18 @@ void PianoRollWindow::saveSettings( QDomDocument & doc, QDomElement & de ) de.appendChild( ghostNotesRoot ); } + if (m_editor->m_markedSemiTones.length() > 0) + { + QDomElement markedSemiTonesRoot = doc.createElement("markedSemiTones"); + for (int ix = 0; ix < m_editor->m_markedSemiTones.size(); ++ix) + { + QDomElement semiToneNode = doc.createElement("semiTone"); + semiToneNode.setAttribute("key", m_editor->m_markedSemiTones.at(ix)); + markedSemiTonesRoot.appendChild(semiToneNode); + } + de.appendChild(markedSemiTonesRoot); + } + MainWindow::saveWidgetState( this, de ); } @@ -4706,6 +4745,7 @@ void PianoRollWindow::saveSettings( QDomDocument & doc, QDomElement & de ) void PianoRollWindow::loadSettings( const QDomElement & de ) { m_editor->loadGhostNotes( de.firstChildElement("ghostnotes") ); + m_editor->loadMarkedSemiTones(de.firstChildElement("markedSemiTones")); MainWindow::restoreWidgetState( this, de ); } From 0059c6e71f6431b4ed13d8e444f133642bbe933d Mon Sep 17 00:00:00 2001 From: Shmuel H Date: Sat, 14 Sep 2019 20:35:54 +0300 Subject: [PATCH 21/81] Fix #4188 - Check for failed qFind (#5184) --- src/gui/editors/PianoRoll.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index b65a6b56b..7ba01f983 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -537,7 +537,10 @@ void PianoRoll::markSemiTone( int i ) for (int ix = 0; ix < aok.size(); ++ix) { i = qFind(m_markedSemiTones.begin(), m_markedSemiTones.end(), aok.at(ix)); - m_markedSemiTones.erase(i); + if (i != m_markedSemiTones.end()) + { + m_markedSemiTones.erase(i); + } } } else From 8fdf6c4d120430194ee9c4303b6d8a7bcad99c32 Mon Sep 17 00:00:00 2001 From: Kevin Zander Date: Sat, 14 Sep 2019 12:36:06 -0500 Subject: [PATCH 22/81] Fix #4188 - Check for failed std::find (#5137) --- src/gui/editors/PianoRoll.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index a1fcdc6d8..36505e982 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -550,7 +550,10 @@ void PianoRoll::markSemiTone( int i ) for (int ix = 0; ix < aok.size(); ++ix) { i = std::find(m_markedSemiTones.begin(), m_markedSemiTones.end(), aok.at(ix)); - m_markedSemiTones.erase(i); + if (i != m_markedSemiTones.end()) + { + m_markedSemiTones.erase(i); + } } } else From ffa03df72bae81aa886f444e90204246e854cbb1 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Sun, 15 Sep 2019 10:18:47 -0400 Subject: [PATCH 23/81] Fix $PATH value in AppImage Closes #5187 --- cmake/linux/package_linux.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/linux/package_linux.sh.in b/cmake/linux/package_linux.sh.in index 0dec715f4..b838237b7 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*}" From 419321dd0146d9893f7934ef852cb54994ffd26f Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Mon, 16 Sep 2019 07:09:42 +0200 Subject: [PATCH 24/81] Only MacOS and Windows are case insensitive (#4768) --- src/core/Song.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 943524e6d..6bd94a484 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -1414,7 +1414,12 @@ void Song::exportProject( bool multiExport ) // Get first extension from selected dropdown. // i.e. ".wav" from "WAV-File (*.wav), Dummy-File (*.dum)" suffix = efd.selectedNameFilter().mid( stx + 2, etx - stx - 2 ).split( " " )[0].trimmed(); - exportFileName.remove( "." + suffix, Qt::CaseInsensitive ); + + Qt::CaseSensitivity cs = Qt::CaseSensitive; +#if defined(LMMS_BUILD_APPLE) || defined(LMMS_BUILD_WIN32) + cs = Qt::CaseInsensitive; +#endif + exportFileName.remove( "." + suffix, cs ); if ( efd.selectedFiles()[0].endsWith( suffix ) ) { if( VersionedSaveDialog::fileExistsQuery( exportFileName + suffix, From 90dec52db00b20ec986748da571a72df5145a200 Mon Sep 17 00:00:00 2001 From: Hussam al-Homsi Date: Thu, 19 Sep 2019 12:02:11 -0400 Subject: [PATCH 25/81] Add missing icons of File menu actions (#5183) --- src/gui/MainWindow.cpp | 7 ++++--- src/gui/menus/TemplatesMenu.cpp | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index bdb3a7472..08bc90852 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -291,7 +291,7 @@ void MainWindow::finalize() tr( "&Save" ), this, SLOT( saveProject() ), QKeySequence::Save ); - project_menu->addAction( embed::getIconPixmap( "project_saveas" ), + project_menu->addAction( embed::getIconPixmap( "project_save" ), tr( "Save &As..." ), this, SLOT( saveProjectAs() ), Qt::CTRL + Qt::SHIFT + Qt::Key_S ); @@ -300,8 +300,9 @@ void MainWindow::finalize() this, SLOT( saveProjectAsNewVersion() ), Qt::CTRL + Qt::ALT + Qt::Key_S ); - project_menu->addAction( tr( "Save as default template" ), - this, SLOT( saveProjectAsDefaultTemplate() ) ); + project_menu->addAction( embed::getIconPixmap( "project_save" ), + tr( "Save as default template" ), + this, SLOT( saveProjectAsDefaultTemplate() ) ); project_menu->addSeparator(); project_menu->addAction( embed::getIconPixmap( "project_import" ), diff --git a/src/gui/menus/TemplatesMenu.cpp b/src/gui/menus/TemplatesMenu.cpp index 5fb740203..b944b7cf1 100644 --- a/src/gui/menus/TemplatesMenu.cpp +++ b/src/gui/menus/TemplatesMenu.cpp @@ -11,6 +11,8 @@ TemplatesMenu::TemplatesMenu(QWidget *parent) : QMenu(tr("New from template"), parent) { + setIcon(embed::getIconPixmap("project_new")); + connect( this, SIGNAL( aboutToShow() ), SLOT( fillTemplatesMenu() ) ); connect( this, SIGNAL( triggered( QAction * ) ), SLOT( createNewProjectFromTemplate( QAction * ) ) ); From 1324cf48c16a91898a8cdec8af43f0f0ce41bc82 Mon Sep 17 00:00:00 2001 From: Shmuel H Date: Mon, 12 Aug 2019 12:35:12 +0300 Subject: [PATCH 26/81] Enable automatic dll installation for RemoteVstPlugin32 Co-Authored-By: Hyunjin Song --- plugins/vst_base/CMakeLists.txt | 30 +++++++++----- .../vst_base/RemoteVstPlugin/CMakeLists.txt | 15 +++++++ plugins/vst_base/RemoteVstPlugin32.cmake | 40 +++++++++---------- plugins/vst_base/RemoteVstPlugin64.cmake | 1 - 4 files changed, 54 insertions(+), 32 deletions(-) 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/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..efbd00ee9 100644 --- a/plugins/vst_base/RemoteVstPlugin32.cmake +++ b/plugins/vst_base/RemoteVstPlugin32.cmake @@ -1,14 +1,21 @@ +# 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}) @@ -46,16 +53,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 +80,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) From ae9d619abd0410e642c50f48a2095c4fcb82ee7a Mon Sep 17 00:00:00 2001 From: Shmuel H Date: Wed, 21 Aug 2019 21:32:39 +0300 Subject: [PATCH 27/81] BuildPlugin: Always remove 'lib' suffix from the DLL name --- cmake/modules/BuildPlugin.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/modules/BuildPlugin.cmake b/cmake/modules/BuildPlugin.cmake index e285e05bb..675433e63 100644 --- a/cmake/modules/BuildPlugin.cmake +++ b/cmake/modules/BuildPlugin.cmake @@ -75,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}") From 2f64c461e8dcf4d5ac185a763a500cbdd0aec4bf Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Sat, 24 Aug 2019 11:13:49 +0900 Subject: [PATCH 28/81] Fix missing system libraries in MSVC installations * Install UCRT libraries * Install debug libraries in debug builds --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 36e35bf4c..a08a9c8f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -709,4 +709,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) From 94354e305342d894332b9ac919dd9252b39c9422 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Sat, 31 Aug 2019 09:14:36 +0900 Subject: [PATCH 29/81] Support deploying dependencies in MSVC builds with CMake < 3.14 --- cmake/modules/CreateTempFile.cmake | 7 +++++-- cmake/modules/DefineInstallVar.cmake | 13 +++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/cmake/modules/CreateTempFile.cmake b/cmake/modules/CreateTempFile.cmake index ceefa4928..5210342ac 100644 --- a/cmake/modules/CreateTempFile.cmake +++ b/cmake/modules/CreateTempFile.cmake @@ -1,5 +1,5 @@ function(CreateTempFilePath) - set(options) + set(options CONFIG_SUFFIX) set(oneValueArgs OUTPUT_VAR TAG) set(multiValueArgs CONTENT) cmake_parse_arguments(TEMP "${options}" "${oneValueArgs}" @@ -10,9 +10,12 @@ function(CreateTempFilePath) 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}") - set(${TEMP_OUTPUT_VAR} "${file_name}" PARENT_SCOPE) endfunction() diff --git a/cmake/modules/DefineInstallVar.cmake b/cmake/modules/DefineInstallVar.cmake index 36f221410..b13cb1d52 100644 --- a/cmake/modules/DefineInstallVar.cmake +++ b/cmake/modules/DefineInstallVar.cmake @@ -14,13 +14,14 @@ function(DEFINE_INSTALL_VAR) # install(CODE) does not support generator expression in ver<3.14 if(VAR_GENERATOR_EXPRESSION AND ${CMAKE_VERSION} VERSION_LESS "3.14.0") - if(MSVC) - message(FATAL_ERROR "Installing is not supported with msvc and cmake<3.14") - endif() - include(CreateTempFile) - CreateTempFilePath(OUTPUT_VAR file_path TAG "${VAR_NAME}" CONTENT "${VAR_CONTENT}") - install(CODE "file(READ \"${file_path}\" \"${VAR_NAME}\")") + 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) From 867639929ac882c867e87aa6e06101912638861b Mon Sep 17 00:00:00 2001 From: Kevin Zander Date: Mon, 30 Sep 2019 21:36:45 -0500 Subject: [PATCH 30/81] Add close button to SideBarWidget (#5133) --- include/SideBarWidget.h | 5 +++++ src/gui/widgets/SideBar.cpp | 3 +++ src/gui/widgets/SideBarWidget.cpp | 13 +++++++++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/include/SideBarWidget.h b/include/SideBarWidget.h index 229f07df0..37acc9770 100644 --- a/include/SideBarWidget.h +++ b/include/SideBarWidget.h @@ -28,6 +28,7 @@ #include #include #include +#include class SideBarWidget : public QWidget @@ -47,6 +48,8 @@ public: return m_title; } +signals: + void closeButtonClicked(); protected: virtual void paintEvent( QPaintEvent * _pe ); @@ -75,6 +78,8 @@ private: QVBoxLayout * m_layout; QString m_title; QPixmap m_icon; + QPushButton * m_closeBtn; + const QSize m_buttonSize; } ; diff --git a/src/gui/widgets/SideBar.cpp b/src/gui/widgets/SideBar.cpp index 01ea58919..cc83abae4 100644 --- a/src/gui/widgets/SideBar.cpp +++ b/src/gui/widgets/SideBar.cpp @@ -121,6 +121,9 @@ void SideBar::appendTab( SideBarWidget *widget ) widget->setMinimumWidth( 200 ); ToolTip::add( button, widget->title() ); + + connect(widget, &SideBarWidget::closeButtonClicked, + [=]() { button->click(); }); } diff --git a/src/gui/widgets/SideBarWidget.cpp b/src/gui/widgets/SideBarWidget.cpp index c1b46cfa6..41647a4fd 100644 --- a/src/gui/widgets/SideBarWidget.cpp +++ b/src/gui/widgets/SideBarWidget.cpp @@ -22,23 +22,31 @@ * */ +#include "SideBarWidget.h" + #include #include #include -#include "SideBarWidget.h" +#include "embed.h" SideBarWidget::SideBarWidget( const QString & _title, const QPixmap & _icon, QWidget * _parent ) : QWidget( _parent ), m_title( _title ), - m_icon( _icon ) + m_icon(_icon), + m_buttonSize(17, 17) { m_contents = new QWidget( this ); m_layout = new QVBoxLayout( m_contents ); m_layout->setSpacing( 5 ); m_layout->setMargin( 0 ); + m_closeBtn = new QPushButton(embed::getIconPixmap("close"), QString(), this); + m_closeBtn->resize(m_buttonSize); + m_closeBtn->setToolTip(tr("Close")); + connect(m_closeBtn, &QPushButton::clicked, + [=]() { this->closeButtonClicked(); }); } @@ -80,6 +88,7 @@ void SideBarWidget::resizeEvent( QResizeEvent * ) const int MARGIN = 6; m_contents->setGeometry( MARGIN, 40 + MARGIN, width() - MARGIN * 2, height() - MARGIN * 2 - 40 ); + m_closeBtn->move(m_contents->geometry().width() - MARGIN - 5, 5); } From 5132d91bfc7fa05d2fa559c7a96399efa0ae89b6 Mon Sep 17 00:00:00 2001 From: "https://gitlab.com/users/CYBERDEViLNL" <1148379+CYBERDEViLNL@users.noreply.github.com> Date: Wed, 2 Oct 2019 01:00:11 +0200 Subject: [PATCH 31/81] Give focus to AutomationEditor when the window gets the foucs (#5170) This will make shortcuts work on opening the editor. --- include/AutomationEditor.h | 3 +++ src/gui/editors/AutomationEditor.cpp | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index 9705c5efa..968bb34be 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -297,6 +297,9 @@ public slots: signals: void currentPatternChanged(); +protected: + virtual void focusInEvent(QFocusEvent * event); + protected slots: void play(); void stop(); diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index 94e9d5cc8..7583501c7 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -198,6 +198,8 @@ AutomationEditor::AutomationEditor() : setCurrentPattern( NULL ); setMouseTracking( true ); + setFocusPolicy( Qt::StrongFocus ); + setFocus(); } @@ -2516,6 +2518,11 @@ void AutomationEditorWindow::clearCurrentPattern() setCurrentPattern(nullptr); } +void AutomationEditorWindow::focusInEvent(QFocusEvent * event) +{ + m_editor->setFocus( event->reason() ); +} + void AutomationEditorWindow::play() { m_editor->play(); From ca8871455e97bee0274e1c6c4081a0fe82dfeb72 Mon Sep 17 00:00:00 2001 From: "https://gitlab.com/users/CYBERDEViLNL" <1148379+CYBERDEViLNL@users.noreply.github.com> Date: Wed, 2 Oct 2019 01:00:59 +0200 Subject: [PATCH 32/81] Make undo for PianoRoll cut action possible (#5214) --- src/gui/editors/PianoRoll.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 36505e982..065234aa4 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -4095,6 +4095,8 @@ void PianoRoll::cutSelectedNotes() if( ! selected_notes.empty() ) { + m_pattern->addJournalCheckPoint(); + copyToClipboard( selected_notes ); Engine::getSong()->setModified(); From 9f0baab93ae18f88c07dff76a0563f73200b649f Mon Sep 17 00:00:00 2001 From: Hussam al-Homsi Date: Tue, 1 Oct 2019 21:14:55 -0400 Subject: [PATCH 33/81] Fix regression of some default settings The regression was introduced in #3820. --- src/gui/SetupDialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index f23b5b271..885f43dec 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -125,9 +125,9 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : m_vstAlwaysOnTop(ConfigManager::inst()->value( "ui", "vstalwaysontop").toInt()), m_syncVSTPlugins(ConfigManager::inst()->value( - "ui", "syncvstplugins").toInt()), + "ui", "syncvstplugins", "1").toInt()), m_disableAutoQuit(ConfigManager::inst()->value( - "ui", "disableautoquit").toInt()), + "ui", "disableautoquit", "1").toInt()), m_NaNHandler(ConfigManager::inst()->value( "app", "nanhandler", "1").toInt()), m_hqAudioDev(ConfigManager::inst()->value( From 15fe551b1da9863db6b127665dd390473615513d Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Thu, 3 Oct 2019 11:47:49 -0400 Subject: [PATCH 34/81] Submodules: Only fetch required (#5182, closes #5105) + Non-shallow fallback (hotfix) * Retry updating submodules non-shallow if shallow clone fails (master hotfix) * Add `PLUGIN_LIST` support to CheckSubmodules (#5105) * Remove `SKIP_SUBMODULES` switch (it's redundant to specifying `PLUGIN_LIST`) * Add `NO_SHALLOW_CLONE` switch --- CMakeLists.txt | 1 + cmake/modules/CheckSubmodules.cmake | 129 ++++++++++++++++++---------- cmake/modules/PluginList.cmake | 104 ++++++++++++++++++++++ plugins/CMakeLists.txt | 84 +----------------- 4 files changed, 188 insertions(+), 130 deletions(-) create mode 100644 cmake/modules/PluginList.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index a08a9c8f7..b63900dda 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ IF(COMMAND CMAKE_POLICY) CMAKE_POLICY(SET CMP0057 NEW) ENDIF(COMMAND CMAKE_POLICY) +INCLUDE(PluginList) INCLUDE(CheckSubmodules) INCLUDE(AddFileDependencies) INCLUDE(CheckIncludeFiles) diff --git a/cmake/modules/CheckSubmodules.cmake b/cmake/modules/CheckSubmodules.cmake index 65e5be08b..d2475826b 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,110 @@ 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 ) # Recurse - GIT_SUBMODULE(${SUBMODULE_PATH} false false) + GIT_SUBMODULE(${SUBMODULE_PATH} false false ${FULL_CLONE_FLAG}) 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 +162,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,7 +176,7 @@ 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 "") @@ -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/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/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 4f139f8b3..a4e56921f 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -14,89 +14,7 @@ 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 - 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() From da09b2a941a0067d6b6a59dfd0be043134efa780 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Sun, 6 Oct 2019 01:05:53 -0400 Subject: [PATCH 35/81] CheckSubmodules: Workaround submodules failing (#5222) Workaround git's inability to recover from a shallow clone --- cmake/modules/CheckSubmodules.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/modules/CheckSubmodules.cmake b/cmake/modules/CheckSubmodules.cmake index d2475826b..32a2f9951 100644 --- a/cmake/modules/CheckSubmodules.cmake +++ b/cmake/modules/CheckSubmodules.cmake @@ -123,8 +123,10 @@ MACRO(GIT_SUBMODULE SUBMODULE_PATH FORCE_DEINIT FORCE_REMOTE FULL_CLONE) 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 ${FULL_CLONE_FLAG}) + GIT_SUBMODULE(${SUBMODULE_PATH} false false true) ELSE() # Try to use the depth switch IF(NO_SHALLOW_CLONE OR GIT_VERSION_STRING VERSION_LESS "1.8.4") @@ -179,11 +181,9 @@ FOREACH(_submodule ${SUBMODULE_LIST}) 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}") From 16390f61a51c2134d05e4029ca809cf528ce769f Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Mon, 7 Oct 2019 08:01:48 +0900 Subject: [PATCH 36/81] Work around a winegcc bug of Wine >= 4.14 (#5210) See https://bugs.winehq.org/show_bug.cgi?id=47710 for details --- plugins/vst_base/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/vst_base/CMakeLists.txt b/plugins/vst_base/CMakeLists.txt index 84920d9be..441b961f4 100644 --- a/plugins/vst_base/CMakeLists.txt +++ b/plugins/vst_base/CMakeLists.txt @@ -54,6 +54,8 @@ SET(WINE_CXX_ARGS -I${WINE_INCLUDE_BASE_DIR} -I${WINE_INCLUDE_DIR}/windows -L${WINE_LIBRARY_DIR} + # Work around https://bugs.winehq.org/show_bug.cgi?id=47710 + -D__WIDL_objidl_generated_name_0000000C="" ${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp -std=c++0x -mwindows -lpthread -lole32 ${EXTRA_FLAGS} -fno-omit-frame-pointer From 2df4fff1c0f83f96e64cd8b4c6af30de2aba9016 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Mon, 7 Oct 2019 08:02:03 +0900 Subject: [PATCH 37/81] Work around a winegcc bug of Wine >= 4.14 (#5211) See https://bugs.winehq.org/show_bug.cgi?id=47710 for details --- cmake/modules/winegcc_wrapper.in | 3 +++ 1 file changed, 3 insertions(+) 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 From 770e8cc777406d42aab2fafe079b9104852e369b Mon Sep 17 00:00:00 2001 From: Shmuel H Date: Tue, 1 Oct 2019 12:12:25 +0300 Subject: [PATCH 38/81] CircleCI: Use xenial for linux.gcc builds AppImage will fail otherwise. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 99b987f86..981034ffb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -101,7 +101,7 @@ jobs: - *save_cache linux.gcc: docker: - - image: lmmsci/linux.gcc:18.04 + - image: lmmsci/linux.gcc:xenial environment: <<: *common_environment steps: From 45cb7f21c5246cd2ca9bf895b86653fc1eefaff5 Mon Sep 17 00:00:00 2001 From: Shmuel H Date: Tue, 1 Oct 2019 22:27:36 +0300 Subject: [PATCH 39/81] linuxdeployqt: drop -unsupported-allow-new-glibc --- cmake/linux/package_linux.sh.in | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmake/linux/package_linux.sh.in b/cmake/linux/package_linux.sh.in index b838237b7..9f233d401 100644 --- a/cmake/linux/package_linux.sh.in +++ b/cmake/linux/package_linux.sh.in @@ -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 From 5aa87886c9c098b1e37c1eeb7e9383a1c8e1a069 Mon Sep 17 00:00:00 2001 From: Steffen Baranowsky Date: Mon, 7 Oct 2019 18:13:44 +0200 Subject: [PATCH 40/81] Rubberband fix for selecting large area in Songeditor (#5003) --- include/SongEditor.h | 17 +++ include/Track.h | 12 ++- include/TrackContainerView.h | 14 +-- src/gui/TrackContainerView.cpp | 59 ++-------- src/gui/editors/SongEditor.cpp | 189 +++++++++++++++++++++++++++++++-- src/gui/widgets/Rubberband.cpp | 12 --- 6 files changed, 218 insertions(+), 85 deletions(-) diff --git a/include/SongEditor.h b/include/SongEditor.h index e03c63280..de149e9a4 100644 --- a/include/SongEditor.h +++ b/include/SongEditor.h @@ -75,6 +75,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(); @@ -85,6 +88,9 @@ public slots: protected: virtual void closeEvent( QCloseEvent * ce ); + virtual void mousePressEvent(QMouseEvent * me); + virtual void mouseMoveEvent(QMouseEvent * me); + virtual void mouseReleaseEvent(QMouseEvent * me); private slots: void setHighQuality( bool ); @@ -109,6 +115,9 @@ private: virtual bool allowRubberband() const; + int trackIndexFromSelectionPoint(int yPos); + int indexOfTrackView(const TrackView* tv); + Song * m_song; @@ -135,6 +144,14 @@ private: bool m_smoothScroll; EditMode m_mode; + 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; diff --git a/include/Track.h b/include/Track.h index f548168b7..f3b6c5e4c 100644 --- a/include/Track.h +++ b/include/Track.h @@ -210,6 +210,12 @@ public: { return m_tco; } + + inline TrackView * getTrackView() + { + return m_trackView; + } + // qproperty access func QColor mutedColor() const; QColor mutedBackgroundColor() const; @@ -229,7 +235,7 @@ public: // access needsUpdate member variable bool needsUpdate(); void setNeedsUpdate( bool b ); - + public slots: virtual bool close(); void cut(); @@ -256,10 +262,6 @@ protected: float pixelsPerTact(); - inline TrackView * getTrackView() - { - return m_trackView; - } DataFile createTCODataFiles(const QVector & tcos) const; diff --git a/include/TrackContainerView.h b/include/TrackContainerView.h index bf6ada409..e0c9d11f7 100644 --- a/include/TrackContainerView.h +++ b/include/TrackContainerView.h @@ -133,27 +133,21 @@ public slots: 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); /// /// \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 * ); MidiTime m_currentPosition; + RubberBand *rubberBand() const; private: @@ -187,7 +181,7 @@ private: float m_ppt; RubberBand * m_rubberBand; - QPoint m_origin; + signals: diff --git a/src/gui/TrackContainerView.cpp b/src/gui/TrackContainerView.cpp index 4c7498ab0..255fb1a02 100644 --- a/src/gui/TrackContainerView.cpp +++ b/src/gui/TrackContainerView.cpp @@ -55,8 +55,7 @@ TrackContainerView::TrackContainerView( TrackContainer * _tc ) : m_trackViews(), m_scrollArea( new scrollArea( this ) ), m_ppt( DEFAULT_PIXELS_PER_TACT ), - m_rubberBand( new RubberBand( m_scrollArea ) ), - m_origin() + m_rubberBand( new RubberBand( m_scrollArea ) ) { m_tc->setHook( this ); //keeps the direction of the widget, undepended on the locale @@ -346,12 +345,8 @@ void TrackContainerView::dragEnterEvent( QDragEnterEvent * _dee ) arg( Track::SampleTrack ) ); } -void TrackContainerView::selectRegionFromPixels(int xStart, int xEnd) -{ - m_rubberBand->setEnabled( true ); - m_rubberBand->show(); - m_rubberBand->setGeometry( min( xStart, xEnd ), 0, max( xStart, xEnd ) - min( xStart, xEnd ), std::numeric_limits::max() ); -} + + void TrackContainerView::stopRubberBand() { @@ -427,46 +422,6 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) -void TrackContainerView::mousePressEvent( QMouseEvent * _me ) -{ - if( allowRubberband() == true ) - { - m_origin = m_scrollArea->mapFromParent( _me->pos() ); - m_rubberBand->setEnabled( true ); - m_rubberBand->setGeometry( QRect( m_origin, QSize() ) ); - m_rubberBand->show(); - } - QWidget::mousePressEvent( _me ); -} - - - - -void TrackContainerView::mouseMoveEvent( QMouseEvent * _me ) -{ - if( rubberBandActive() == true ) - { - m_rubberBand->setGeometry( QRect( m_origin, - m_scrollArea->mapFromParent( _me->pos() ) ). - normalized() ); - } - QWidget::mouseMoveEvent( _me ); -} - - - - -void TrackContainerView::mouseReleaseEvent( QMouseEvent * _me ) -{ - m_rubberBand->hide(); - m_rubberBand->setEnabled( false ); - QWidget::mouseReleaseEvent( _me ); -} - - - - - void TrackContainerView::resizeEvent( QResizeEvent * _re ) { realignTracks(); @@ -476,6 +431,14 @@ void TrackContainerView::resizeEvent( QResizeEvent * _re ) +RubberBand *TrackContainerView::rubberBand() const +{ + return m_rubberBand; +} + + + + TrackContainerView::scrollArea::scrollArea( TrackContainerView * _parent ) : QScrollArea( _parent ), m_trackContainerView( _parent ) diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index 286b01f15..31cb142c0 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -51,8 +51,7 @@ #include "TimeDisplayWidget.h" #include "AudioDevice.h" #include "PianoRoll.h" - - +#include "Track.h" positionLine::positionLine( QWidget * parent ) : QWidget( parent ) @@ -80,15 +79,21 @@ SongEditor::SongEditor( Song * song ) : m_zoomingModel(new ComboBoxModel()), m_scrollBack( false ), m_smoothScroll( ConfigManager::inst()->value( "ui", "smoothscroll" ).toInt() ), - m_mode(DrawMode) + m_mode(DrawMode), + m_origin(), + m_scrollPos(), + m_mousePos(), + m_rubberBandStartTrackview(0), + m_rubberbandStartMidipos(0), + m_currentZoomingValue(m_zoomingModel->value()), + m_trackHeadWidth(ConfigManager::inst()->value("ui", "compacttrackbuttons").toInt()==1 + ? DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT + TRACK_OP_WIDTH_COMPACT + : DEFAULT_SETTINGS_WIDGET_WIDTH + TRACK_OP_WIDTH), + m_selectRegion(false) { m_zoomingModel->setParent(this); // create time-line - int widgetTotal = ConfigManager::inst()->value( "ui", - "compacttrackbuttons" ).toInt()==1 ? - DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT + TRACK_OP_WIDTH_COMPACT : - DEFAULT_SETTINGS_WIDGET_WIDTH + TRACK_OP_WIDTH; - m_timeLine = new TimeLineWidget( widgetTotal, 32, + m_timeLine = new TimeLineWidget( m_trackHeadWidth, 32, pixelsPerTact(), m_song->m_playPos[Song::Mode_PlaySong], m_currentPosition, this ); @@ -239,6 +244,10 @@ SongEditor::SongEditor( Song * song ) : this, SLOT( scrolled( int ) ) ); connect( m_song, SIGNAL( lengthChanged( int ) ), this, SLOT( updateScrollBar( int ) ) ); + connect(m_leftRightScroll, SIGNAL(valueChanged(int)),this, SLOT(updateRubberband())); + connect(contentWidget()->verticalScrollBar(), SIGNAL(valueChanged(int)),this, SLOT(updateRubberband())); + connect(m_timeLine, SIGNAL(selectionFinished()), this, SLOT(stopSelectRegion())); + // Set up zooming model for( float const & zoomLevel : m_zoomLevels ) @@ -293,6 +302,99 @@ void SongEditor::scrolled( int new_pos ) +void SongEditor::selectRegionFromPixels(int xStart, int xEnd) +{ + if (!m_selectRegion) + { + m_selectRegion = true; + + //deselect all tcos + for (auto &it : findChildren()) { it->setSelected(false); } + + rubberBand()->setEnabled(true); + rubberBand()->show(); + + //we save the position of scrollbars, mouse position and zooming level + m_origin = QPoint(xStart, 0); + m_scrollPos = QPoint(m_leftRightScroll->value(), contentWidget()->verticalScrollBar()->value()); + m_currentZoomingValue = zoomingModel()->value(); + + //calculate the song position where the mouse was clicked + m_rubberbandStartMidipos = MidiTime((xStart - m_trackHeadWidth) + / pixelsPerTact() * MidiTime::ticksPerTact()) + + m_currentPosition; + m_rubberBandStartTrackview = 0; + } + //the current mouse position within the borders of song editor + m_mousePos = QPoint(qMax(m_trackHeadWidth, qMin(xEnd, width())) + , std::numeric_limits::max()); + updateRubberband(); +} + + + + +void SongEditor::stopSelectRegion() +{ + m_selectRegion = false; +} + + + + +void SongEditor::updateRubberband() +{ + if (rubberBandActive()) + { + int originX = m_origin.x(); + + //take care of the zooming + if (m_currentZoomingValue != m_zoomingModel->value()) + { + originX = m_trackHeadWidth + (originX - m_trackHeadWidth) + * m_zoomLevels[m_zoomingModel->value()] / m_zoomLevels[m_currentZoomingValue]; + } + + //take care of the scrollbar position + int hs = (m_leftRightScroll->value() - m_scrollPos.x()) * pixelsPerTact(); + int vs = contentWidget()->verticalScrollBar()->value() - m_scrollPos.y(); + + //the adjusted origin point + QPoint origin = QPoint(qMax(originX - hs, m_trackHeadWidth), m_origin.y() - vs); + + //paint the rubber band rect + rubberBand()->setGeometry(QRect(origin, + contentWidget()->mapFromParent(QPoint(m_mousePos.x(), m_mousePos.y())) + ).normalized()); + + //the index of the TrackView the mouse is hover + int rubberBandTrackview = trackIndexFromSelectionPoint(m_mousePos.y()); + + //the miditime the mouse is hover + MidiTime rubberbandMidipos = MidiTime((qMin(m_mousePos.x(), width()) - m_trackHeadWidth) + / pixelsPerTact() * MidiTime::ticksPerTact()) + + m_currentPosition; + + //are tcos in the rect of selection? + for (auto &it : findChildren()) + { + TrackContentObjectView * tco = dynamic_cast(it); + if (tco) + { + auto indexOfTrackView = trackViews().indexOf(tco->getTrackView()); + bool isBeetweenRubberbandViews = indexOfTrackView >= qMin(m_rubberBandStartTrackview, rubberBandTrackview) + && indexOfTrackView <= qMax(m_rubberBandStartTrackview, rubberBandTrackview); + bool isBeetweenRubberbandMidiPos = tco->getTrackContentObject()->endPosition() >= qMin(m_rubberbandStartMidipos, rubberbandMidipos) + && tco->getTrackContentObject()->startPosition() <= qMax(m_rubberbandStartMidipos, rubberbandMidipos); + it->setSelected(isBeetweenRubberbandViews && isBeetweenRubberbandMidiPos); + } + } + } +} + + + + void SongEditor::setEditMode( EditMode mode ) { m_mode = mode; @@ -394,7 +496,7 @@ void SongEditor::wheelEvent( QWheelEvent * we ) void SongEditor::closeEvent( QCloseEvent * ce ) - { +{ if( parentWidget() ) { parentWidget()->hide(); @@ -404,7 +506,53 @@ void SongEditor::closeEvent( QCloseEvent * ce ) hide(); } ce->ignore(); - } +} + + + + +void SongEditor::mousePressEvent(QMouseEvent *me) +{ + if (allowRubberband()) + { + //we save the position of scrollbars, mouse position and zooming level + m_scrollPos = QPoint(m_leftRightScroll->value(), contentWidget()->verticalScrollBar()->value()); + m_origin = contentWidget()->mapFromParent(QPoint(me->pos().x(), me->pos().y())); + m_currentZoomingValue = zoomingModel()->value(); + + //paint the rubberband + rubberBand()->setEnabled(true); + rubberBand()->setGeometry(QRect(m_origin, QSize())); + rubberBand()->show(); + + //the trackView(index) and the miditime where the mouse was clicked + m_rubberBandStartTrackview = trackIndexFromSelectionPoint(me->y()); + m_rubberbandStartMidipos = MidiTime((me->x() - m_trackHeadWidth) + / pixelsPerTact() * MidiTime::ticksPerTact()) + + m_currentPosition; + } + QWidget::mousePressEvent(me); +} + + + + +void SongEditor::mouseMoveEvent(QMouseEvent *me) +{ + m_mousePos = me->pos(); + updateRubberband(); + QWidget::mouseMoveEvent(me); +} + + + + +void SongEditor::mouseReleaseEvent(QMouseEvent *me) +{ + rubberBand()->hide(); + rubberBand()->setEnabled(false); + QWidget::mouseReleaseEvent(me); +} @@ -602,6 +750,7 @@ void SongEditor::zoomingChanged() m_song->m_playPos[Song::Mode_PlaySong].m_timeLine-> setPixelsPerTact( pixelsPerTact() ); realignTracks(); + updateRubberband(); } @@ -615,6 +764,26 @@ bool SongEditor::allowRubberband() const +int SongEditor::trackIndexFromSelectionPoint(int yPos) +{ + const TrackView * tv = trackViewAt(yPos - m_timeLine->height()); + return tv ? indexOfTrackView(tv) + : yPos < m_timeLine->height() ? 0 + : trackViews().count(); +} + + + + +int SongEditor::indexOfTrackView(const TrackView *tv) +{ + return static_cast(std::distance(trackViews().begin(), + std::find(trackViews().begin(), trackViews().end(), tv))); +} + + + + ComboBoxModel *SongEditor::zoomingModel() const { return m_zoomingModel; diff --git a/src/gui/widgets/Rubberband.cpp b/src/gui/widgets/Rubberband.cpp index 6bf702edc..0a4e891b5 100644 --- a/src/gui/widgets/Rubberband.cpp +++ b/src/gui/widgets/Rubberband.cpp @@ -66,18 +66,6 @@ QVector RubberBand::selectedObjects() const void RubberBand::resizeEvent( QResizeEvent * _re ) { QRubberBand::resizeEvent( _re ); - if( isEnabled() ) - { - QVector so = selectableObjects(); - for( QVector::iterator it = so.begin(); - it != so.end(); ++it ) - { - ( *it )->setSelected( QRect( pos(), size() ).intersects( - QRect( ( *it )->mapTo( parentWidget(), - QPoint() ), - ( *it )->size() ) ) ); - } - } } From e1d311730b5de201c7b02360d5caa7e22b204af0 Mon Sep 17 00:00:00 2001 From: Kevin Zander Date: Mon, 7 Oct 2019 14:33:11 -0500 Subject: [PATCH 41/81] Fix regression introduced in #5170 (#5224) --- src/gui/editors/AutomationEditor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index 7583501c7..bb00a1bd1 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -1484,7 +1484,7 @@ void AutomationEditor::paintEvent(QPaintEvent * pe ) m_leftRightScroll->setPageStep( l ); } - if( validPattern() && GuiApplication::instance()->automationEditor()->hasFocus() ) + if(validPattern() && GuiApplication::instance()->automationEditor()->m_editor->hasFocus()) { drawCross( p ); From 91a38a922d349e6f0b9beabfe25f1f5b2d0fc0a1 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Thu, 10 Oct 2019 10:06:14 +0900 Subject: [PATCH 42/81] Add back '-Wl,-E' (#5233) --- src/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 10ce72ae6..2fa72a401 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -198,8 +198,12 @@ IF(LMMS_BUILD_WIN32) ) ENDIF() ELSE() + IF(NOT LMMS_BUILD_APPLE) + SET_TARGET_PROPERTIES(lmms PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Wl,-E") + ENDIF(NOT LMMS_BUILD_APPLE) + INSTALL(FILES "${CMAKE_BINARY_DIR}/lmms.1.gz" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1/" PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) ENDIF() -INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") \ No newline at end of file +INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") From d7a78fe1212af26bdbfa38802bc3038eded0814f Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Thu, 10 Oct 2019 14:22:42 +0900 Subject: [PATCH 43/81] Specify timeout for transfer.sh uploads Prevents "No output has been received in the last 10m0s" errors on Travis CI. --- .travis/script.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 From e321dff733061597869821de6c37c1683d6f06c4 Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Thu, 10 Oct 2019 19:01:17 +0200 Subject: [PATCH 44/81] Translation Fixes (Continuation of #4482) (#5185) Fix some formatting issues with some translations. * Russian * Polish * Swedish * Ukrainian --- data/locale/pl.ts | 2 +- data/locale/ru.ts | 4 ++-- data/locale/sv.ts | 4 ++-- data/locale/uk.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/data/locale/pl.ts b/data/locale/pl.ts index 2e8f989ce..4cbc95441 100644 --- a/data/locale/pl.ts +++ b/data/locale/pl.ts @@ -3002,7 +3002,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri VELOCITY - PRĘDKOŚĆ UDERZENIA + PRĘDKOŚĆ ENABLE MIDI OUTPUT diff --git a/data/locale/ru.ts b/data/locale/ru.ts index 9946e5cfd..1d1c2d73e 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 7b2557cfd..6e3e4f9af 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 39403714f..fa0eede63 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 - ЗГАСАННЯ + From 6dee6a4418b7e541b548170fb32d4f15aab8ef9e Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Sat, 12 Oct 2019 17:41:30 +0200 Subject: [PATCH 45/81] Show icon on 'Turn off all notes' button (#5237) Backporting fix from 2815da28057788ba420d8e128958698a8c3d2d6d by @karmux --- plugins/vestige/vestige.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index fc07e46d5..143c9dc37 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -607,7 +607,7 @@ VestigeInstrumentView::VestigeInstrumentView( Instrument * _instrument, QPushButton * note_off_all_btn = new QPushButton( tr( "Turn off all " "notes" ), this ); note_off_all_btn->setGeometry( 20, 160, 200, 24 ); - note_off_all_btn->setIcon( embed::getIconPixmap( "state_stop" ) ); + note_off_all_btn->setIcon( embed::getIconPixmap( "stop" ) ); note_off_all_btn->setFont( pointSize<8>( note_off_all_btn->font() ) ); connect( note_off_all_btn, SIGNAL( clicked() ), this, SLOT( noteOffAll() ) ); From 95c46a805d4673b6ebbaf7a549b278fab478c249 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Tue, 15 Oct 2019 11:18:46 +0900 Subject: [PATCH 46/81] RemoteVstPlugin: fix crashes when failed to open a file (#5235) --- plugins/vst_base/RemoteVstPlugin.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 4a147f7c9..d12ccd88a 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -718,6 +718,7 @@ void RemoteVstPlugin::init( const std::string & _plugin_file ) static void close_check( FILE* fp ) { + if (!fp) {return;} if( fclose( fp ) ) { perror( "close" ); @@ -1115,6 +1116,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, @@ -1280,6 +1287,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 ) { @@ -1332,6 +1345,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" ); @@ -1433,6 +1452,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" ); From 170d28ffbd39b1f0406e437eaeac39a07389f525 Mon Sep 17 00:00:00 2001 From: Kevin Zander Date: Mon, 14 Oct 2019 21:22:41 -0500 Subject: [PATCH 47/81] Remove global automation from MIDI import (#5223) --- plugins/MidiImport/MidiImport.cpp | 35 +++++++++++++++++-------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index 1f2ab1f57..b8653fe18 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -309,10 +309,20 @@ 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; @@ -323,19 +333,12 @@ bool MidiImport::readSMF( TrackContainer* tc ) 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 ); From f1831ffdc614b44f051de6e345af134bdaf8241f Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Thu, 17 Oct 2019 08:50:12 +0900 Subject: [PATCH 48/81] Export TrackContentObject class Fix a build error introduced in #5223. --- include/Track.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Track.h b/include/Track.h index b00c50248..6c98de10e 100644 --- a/include/Track.h +++ b/include/Track.h @@ -73,7 +73,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 From d005eec1aab1d3252c20b426ac43561ec0e75149 Mon Sep 17 00:00:00 2001 From: Shmuel H Date: Thu, 17 Oct 2019 03:03:26 +0300 Subject: [PATCH 49/81] MSVC: Move MSVC year detection to DetectMachine.cmake. --- cmake/modules/DetectMachine.cmake | 19 ++++++++++++++++ plugins/vst_base/RemoteVstPlugin32.cmake | 28 +++++++----------------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/cmake/modules/DetectMachine.cmake b/cmake/modules/DetectMachine.cmake index f3458165b..08e8745cd 100644 --- a/cmake/modules/DetectMachine.cmake +++ b/cmake/modules/DetectMachine.cmake @@ -30,6 +30,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/plugins/vst_base/RemoteVstPlugin32.cmake b/plugins/vst_base/RemoteVstPlugin32.cmake index 1cac65e15..cba9a26c8 100644 --- a/plugins/vst_base/RemoteVstPlugin32.cmake +++ b/plugins/vst_base/RemoteVstPlugin32.cmake @@ -17,27 +17,15 @@ ENDMACRO() IF(LMMS_BUILD_WIN32 AND NOT LMMS_BUILD_WIN64) ADD_SUBDIRECTORY(RemoteVstPlugin) ELSEIF(LMMS_BUILD_WIN64 AND MSVC) - SET(MSVC_VER ${CMAKE_CXX_COMPILER_VERSION}) - - IF(NOT CMAKE_GENERATOR_32) - IF(MSVC_VER VERSION_GREATER 19.20 OR MSVC_VER VERSION_EQUAL 19.20) - SET(CMAKE_GENERATOR_32 "Visual Studio 16 2019") - SET(MSVC_YEAR 2017) # 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(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. @@ -48,7 +36,7 @@ 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 From a22b6d75750800123dd68119a66737fe52078075 Mon Sep 17 00:00:00 2001 From: Shmuel H Date: Thu, 17 Oct 2019 03:04:18 +0300 Subject: [PATCH 50/81] NSIS: Add compiler to installer name --- cmake/nsis/CMakeLists.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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} From 2d17bf07f3e575a1a5a5da00df57a01d0956cf3d Mon Sep 17 00:00:00 2001 From: Lost Robot <34612565+DouglasDGI@users.noreply.github.com> Date: Thu, 17 Oct 2019 01:44:55 -0600 Subject: [PATCH 51/81] Allow mid-note automation of BitInvader sample length (#4705) --- plugins/bit_invader/bit_invader.cpp | 20 ++++++++------------ plugins/bit_invader/bit_invader.h | 5 ++--- 2 files changed, 10 insertions(+), 15 deletions(-) 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; From 732448c3921d9ef2e4297d6670ecfcade42e8572 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 2 Jun 2019 08:18:36 +0100 Subject: [PATCH 52/81] FreeBSD build version --- CMakeLists.txt | 4 ++-- cmake/modules/DetectMachine.cmake | 2 ++ include/versioninfo.h | 4 ++++ plugins/zynaddsubfx/CMakeLists.txt | 2 +- src/core/Mixer.cpp | 2 +- src/core/ProjectRenderer.cpp | 2 +- src/core/main.cpp | 2 +- src/gui/PianoView.cpp | 2 +- src/lmmsconfig.h.in | 1 + 9 files changed, 14 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 057cfa281..5dab2ab13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -431,9 +431,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) IF(WANT_SNDIO) FIND_PACKAGE(Sndio) diff --git a/cmake/modules/DetectMachine.cmake b/cmake/modules/DetectMachine.cmake index 60c4a0953..c764b5507 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() diff --git a/include/versioninfo.h b/include/versioninfo.h index 8477a61c0..664fc80e6 100644 --- a/include/versioninfo.h +++ b/include/versioninfo.h @@ -28,6 +28,10 @@ #define PLATFORM "OpenBSD" #endif +#ifdef LMMS_BUILD_FREEBSD +#define PLATFORM "FreeBSD" +#endif + #ifdef LMMS_BUILD_WIN32 #define PLATFORM "win32" #endif diff --git a/plugins/zynaddsubfx/CMakeLists.txt b/plugins/zynaddsubfx/CMakeLists.txt index 9d90c5e38..4c170a987 100644 --- a/plugins/zynaddsubfx/CMakeLists.txt +++ b/plugins/zynaddsubfx/CMakeLists.txt @@ -2,7 +2,7 @@ INCLUDE(BuildPlugin) # 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) diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index ac1aa2564..38ee5c46d 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -1242,7 +1242,7 @@ void Mixer::fifoWriter::run() disable_denormals(); #if 0 -#ifdef LMMS_BUILD_LINUX +#if defined(LMMS_BUILD_LINUX) || defined(LMMS_BUILD_FREEBSD) #ifdef LMMS_HAVE_SCHED_H cpu_set_t mask; CPU_ZERO( &mask ); diff --git a/src/core/ProjectRenderer.cpp b/src/core/ProjectRenderer.cpp index 95ed1bd8d..edf7a88a3 100644 --- a/src/core/ProjectRenderer.cpp +++ b/src/core/ProjectRenderer.cpp @@ -162,7 +162,7 @@ void ProjectRenderer::run() { MemoryManager::ThreadGuard mmThreadGuard; Q_UNUSED(mmThreadGuard); #if 0 -#ifdef LMMS_BUILD_LINUX +#if defined(LMMS_BUILD_LINUX) || defined(LMMS_BUILD_FREEBSD) #ifdef LMMS_HAVE_SCHED_H cpu_set_t mask; CPU_ZERO( &mask ); diff --git a/src/core/main.cpp b/src/core/main.cpp index cc9cb4f2a..1f400e91a 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -666,7 +666,7 @@ int main( int argc, char * * argv ) // try to set realtime priority -#ifdef LMMS_BUILD_LINUX +#if defined(LMMS_BUILD_LINUX) || defined(LMMS_BUILD_FREEBSD) #ifdef LMMS_HAVE_SCHED_H #ifndef __OpenBSD__ struct sched_param sparam; diff --git a/src/gui/PianoView.cpp b/src/gui/PianoView.cpp index 2a64e72dd..596a2c212 100644 --- a/src/gui/PianoView.cpp +++ b/src/gui/PianoView.cpp @@ -200,7 +200,7 @@ int PianoView::getKeyFromKeyEvent( QKeyEvent * _ke ) case 27: return 31; // ] } #endif -#if defined(LMMS_BUILD_LINUX) || defined(LMMS_BUILD_OPENBSD) +#if defined(LMMS_BUILD_LINUX) || defined(LMMS_BUILD_OPENBSD) || defined(LMMS_BUILD_FREEBSD) switch( k ) { case 52: return 0; // Z = C diff --git a/src/lmmsconfig.h.in b/src/lmmsconfig.h.in index aa4505dbb..7e37be8bd 100644 --- a/src/lmmsconfig.h.in +++ b/src/lmmsconfig.h.in @@ -3,6 +3,7 @@ #cmakedefine LMMS_BUILD_WIN64 #cmakedefine LMMS_BUILD_APPLE #cmakedefine LMMS_BUILD_OPENBSD +#cmakedefine LMMS_BUILD_FREEBSD #cmakedefine LMMS_BUILD_HAIKU #cmakedefine LMMS_HOST_X86 From a9262b9613cc786d797f437184e630c5e2563bab Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Sat, 19 Oct 2019 11:40:06 +0200 Subject: [PATCH 53/81] Fix Organic offset glitch (#5252) --- plugins/organic/organic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/organic/organic.cpp b/plugins/organic/organic.cpp index b062e5b11..d61072aaf 100644 --- a/plugins/organic/organic.cpp +++ b/plugins/organic/organic.cpp @@ -307,7 +307,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; From 4f11cf1b23c6ba8490c23a863b5b94804b017dc9 Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Sat, 19 Oct 2019 22:41:51 +0300 Subject: [PATCH 54/81] Make SampleBuffer adjust its members when resampling Fixes #5218. --- src/core/SampleBuffer.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 7f0980fe9..872b8cfac 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -382,11 +382,14 @@ void SampleBuffer::directFloatWrite ( sample_t * & _fbuf, f_cnt_t _frames, int _ void SampleBuffer::normalizeSampleRate( const sample_rate_t _src_sr, bool _keep_settings ) { + const sample_rate_t old_rate = m_sampleRate; // do samplerate-conversion to our default-samplerate if( _src_sr != mixerSampleRate() ) { SampleBuffer * resampled = resample( _src_sr, mixerSampleRate() ); + + m_sampleRate = mixerSampleRate(); MM_FREE( m_data ); m_frames = resampled->frames(); m_data = MM_ALLOC( sampleFrame, m_frames ); @@ -401,6 +404,16 @@ void SampleBuffer::normalizeSampleRate( const sample_rate_t _src_sr, m_loopStartFrame = m_startFrame = 0; m_loopEndFrame = m_endFrame = m_frames; } + else if( old_rate != mixerSampleRate() ) + { + auto old_rate_to_new_rate_ratio = static_cast(mixerSampleRate()) / old_rate; + + m_startFrame = qBound(0, f_cnt_t(m_startFrame*old_rate_to_new_rate_ratio), m_frames); + m_endFrame = qBound(m_startFrame, f_cnt_t(m_endFrame*old_rate_to_new_rate_ratio), m_frames); + m_loopStartFrame = qBound(0, f_cnt_t(m_loopStartFrame*old_rate_to_new_rate_ratio), m_frames); + m_loopEndFrame = qBound(m_loopStartFrame, f_cnt_t(m_loopEndFrame*old_rate_to_new_rate_ratio), m_frames); + m_sampleRate = mixerSampleRate(); + } } From dbf5f47149fbb7584bf48ce9e767b9e90ee2df7e Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Mon, 21 Oct 2019 09:27:12 +0900 Subject: [PATCH 55/81] Bump version to 1.2.1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5dab2ab13..d82ace4ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,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}") From 13c4f4a99541a75c8ef4e9cc1d1b63064382a11e Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Tue, 22 Oct 2019 11:30:36 +0900 Subject: [PATCH 56/81] Let Travis Mac builds use the Xcode 9.4 image --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b3cb8aa7c..ab2a8ae85 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,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 From 3745bfbd7fb7b90f682eecd7cd9c7c264122f95f Mon Sep 17 00:00:00 2001 From: Mark-Agent003 Date: Fri, 25 Oct 2019 02:20:02 -0500 Subject: [PATCH 57/81] Increase File Browser Spacing (#4252) Increase File Browser Spacing --- data/themes/default/style.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index c5a449128..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 { From eeaaf6d1da6b8b74b5bf28cf633245c47a365ec6 Mon Sep 17 00:00:00 2001 From: nia <29542929+niacat@users.noreply.github.com> Date: Mon, 28 Oct 2019 00:56:34 +0000 Subject: [PATCH 58/81] Support CMAKE_INSTALL_MANDIR (#5276) --- src/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2fa72a401..ed0deefd1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -202,7 +202,13 @@ ELSE() SET_TARGET_PROPERTIES(lmms PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Wl,-E") ENDIF(NOT LMMS_BUILD_APPLE) - INSTALL(FILES "${CMAKE_BINARY_DIR}/lmms.1.gz" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1/" + 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() From 1b45ce5a9856f16afc286b70508fb611b47e080c Mon Sep 17 00:00:00 2001 From: Shmuel H Date: Thu, 17 Oct 2019 15:28:49 +0300 Subject: [PATCH 59/81] CircleCI: Add macOS support. --- .circleci/config.yml | 55 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 981034ffb..c1a8ea7ff 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: @@ -143,10 +155,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 From 4a9e9da78c7fcc5e77546ebebcdcc0736a0c359a Mon Sep 17 00:00:00 2001 From: Lukas W Date: Tue, 29 Oct 2019 22:42:20 +0100 Subject: [PATCH 60/81] Issue templates improvements * Ask users to search the tracker first * Ask for the LMMS version in bug reports --- .github/ISSUE_TEMPLATE/bug_report.md | 6 +++++- .github/ISSUE_TEMPLATE/feature_request.md | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 3ca71ce76..2c22146ae 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,6 +7,8 @@ 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 @@ -17,10 +19,12 @@ assignees: '' #### Screenshot +#### LMMS version used + #### Logs